Cabal 3.4.1.0 → 3.6.0.0
raw patch · 820 files changed
+61177/−100411 lines, 820 filesdep −Cabaldep −Diffdep −QuickCheckdep ~arraydep ~basedep ~binaryPVP ok
version bump matches the API change (PVP)
Dependencies removed: Cabal, Diff, QuickCheck, async, base-compat, base-orphans, clock, integer-logarithms, optparse-applicative, rere, stm, tar, tasty, tasty-golden, tasty-hunit, tasty-quickcheck, temporary, tree-diff
Dependency ranges changed: array, base, binary, bytestring, containers, deepseq, directory, filepath, pretty, process, semigroups, tagged, text, time, transformers, void
API changes (from Hackage documentation)
- Distribution.Simple: [doctestHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> DoctestFlags -> IO ()
- Distribution.Simple: [postDoctest] :: UserHooks -> Args -> DoctestFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Distribution.Simple: [preDoctest] :: UserHooks -> Args -> DoctestFlags -> IO HookedBuildInfo
- Distribution.Simple.Doctest: doctest :: PackageDescription -> LocalBuildInfo -> [PPSuffixHandler] -> DoctestFlags -> IO ()
- Distribution.Simple.Doctest: instance GHC.Base.Monoid Distribution.Simple.Doctest.DoctestArgs
- Distribution.Simple.Doctest: instance GHC.Base.Semigroup Distribution.Simple.Doctest.DoctestArgs
- Distribution.Simple.Doctest: instance GHC.Generics.Generic Distribution.Simple.Doctest.DoctestArgs
- Distribution.Simple.Doctest: instance GHC.Show.Show Distribution.Simple.Doctest.DoctestArgs
- Distribution.Simple.Setup: DoctestFlags :: [(String, FilePath)] -> [(String, [String])] -> Flag FilePath -> Flag Verbosity -> DoctestFlags
- Distribution.Simple.Setup: [doctestDistPref] :: DoctestFlags -> Flag FilePath
- Distribution.Simple.Setup: [doctestProgramArgs] :: DoctestFlags -> [(String, [String])]
- Distribution.Simple.Setup: [doctestProgramPaths] :: DoctestFlags -> [(String, FilePath)]
- Distribution.Simple.Setup: [doctestVerbosity] :: DoctestFlags -> Flag Verbosity
- Distribution.Simple.Setup: data DoctestFlags
- Distribution.Simple.Setup: defaultDoctestFlags :: DoctestFlags
- Distribution.Simple.Setup: doctestCommand :: CommandUI DoctestFlags
- Distribution.Simple.Setup: emptyDoctestFlags :: DoctestFlags
- Distribution.Simple.Setup: instance GHC.Base.Monoid Distribution.Simple.Setup.DoctestFlags
- Distribution.Simple.Setup: instance GHC.Base.Semigroup Distribution.Simple.Setup.DoctestFlags
- Distribution.Simple.Setup: instance GHC.Generics.Generic Distribution.Simple.Setup.DoctestFlags
- Distribution.Simple.Setup: instance GHC.Show.Show Distribution.Simple.Setup.DoctestFlags
- Distribution.Simple.UserHooks: [doctestHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> DoctestFlags -> IO ()
- Distribution.Simple.UserHooks: [postDoctest] :: UserHooks -> Args -> DoctestFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Distribution.Simple.UserHooks: [preDoctest] :: UserHooks -> Args -> DoctestFlags -> IO HookedBuildInfo
- Distribution.Types.VersionInterval: instance GHC.Classes.Ord Distribution.Types.VersionInterval.LowerBound
- Distribution.Types.VersionInterval: instance GHC.Classes.Ord Distribution.Types.VersionInterval.UpperBound
- Distribution.Types.VersionInterval: intersectVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
- Distribution.Types.VersionInterval: invertVersionIntervals :: VersionIntervals -> VersionIntervals
- Distribution.Types.VersionInterval: mkVersionIntervals :: [VersionInterval] -> VersionIntervals
- Distribution.Types.VersionInterval: type VersionInterval = (LowerBound, UpperBound)
- Distribution.Types.VersionInterval: unionVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
- Distribution.Types.VersionInterval: versionIntervals :: VersionIntervals -> [VersionInterval]
- Distribution.Types.VersionInterval: withinIntervals :: Version -> VersionIntervals -> Bool
- Distribution.Version: differenceVersionRanges :: VersionRange -> VersionRange -> VersionRange
- Distribution.Version: intersectVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
- Distribution.Version: invertVersionIntervals :: VersionIntervals -> VersionIntervals
- Distribution.Version: invertVersionRange :: VersionRange -> VersionRange
- Distribution.Version: mkVersionIntervals :: [VersionInterval] -> VersionIntervals
- Distribution.Version: type VersionInterval = (LowerBound, UpperBound)
- Distribution.Version: unionVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
- Distribution.Version: versionIntervals :: VersionIntervals -> [VersionInterval]
- Distribution.Version: withinIntervals :: Version -> VersionIntervals -> Bool
+ Distribution.CabalSpecVersion: CabalSpecV3_6 :: CabalSpecVersion
+ Distribution.Compat.Prelude.Internal: nonEmpty :: [a] -> Maybe (NonEmpty a)
+ Distribution.FieldGrammar.Newtypes: alaNonEmpty :: sep -> NonEmpty a -> NonEmpty' sep (Identity a) a
+ Distribution.FieldGrammar.Newtypes: alaNonEmpty' :: sep -> (a -> b) -> NonEmpty a -> NonEmpty' sep b a
+ Distribution.FieldGrammar.Newtypes: data NonEmpty' sep b a
+ Distribution.FieldGrammar.Newtypes: instance (Distribution.Compat.Newtype.Newtype a b, Distribution.FieldGrammar.Newtypes.Sep sep, Distribution.Parsec.Parsec b) => Distribution.Parsec.Parsec (Distribution.FieldGrammar.Newtypes.NonEmpty' sep b a)
+ Distribution.FieldGrammar.Newtypes: instance (Distribution.Compat.Newtype.Newtype a b, Distribution.FieldGrammar.Newtypes.Sep sep, Distribution.Pretty.Pretty b) => Distribution.Pretty.Pretty (Distribution.FieldGrammar.Newtypes.NonEmpty' sep b a)
+ Distribution.FieldGrammar.Newtypes: instance Distribution.Compat.Newtype.Newtype (GHC.Base.NonEmpty a) (Distribution.FieldGrammar.Newtypes.NonEmpty' sep wrapper a)
+ Distribution.FieldGrammar.Newtypes: parseSepNE :: (Sep sep, CabalParsing m) => Proxy sep -> m a -> m (NonEmpty a)
+ Distribution.Fields: PWTEmptyFilePath :: PWarnType
+ Distribution.Fields.Field: fieldLinesToString :: [FieldLine ann] -> String
+ Distribution.Fields.Field: sectionArgsToString :: [SectionArg ann] -> String
+ Distribution.PackageDescription.FieldGrammar: instance Distribution.Compat.Newtype.Newtype GHC.Base.String Distribution.PackageDescription.FieldGrammar.CompatFilePath
+ Distribution.PackageDescription.FieldGrammar: instance Distribution.Compat.Newtype.Newtype [Distribution.Utils.Path.SymbolicPath Distribution.Utils.Path.PackageDir Distribution.Utils.Path.LicenseFile] Distribution.PackageDescription.FieldGrammar.CompatLicenseFile
+ Distribution.PackageDescription.FieldGrammar: instance Distribution.Parsec.Parsec Distribution.PackageDescription.FieldGrammar.CompatFilePath
+ Distribution.PackageDescription.FieldGrammar: instance Distribution.Parsec.Parsec Distribution.PackageDescription.FieldGrammar.CompatLicenseFile
+ Distribution.PackageDescription.FieldGrammar: instance Distribution.Pretty.Pretty Distribution.PackageDescription.FieldGrammar.CompatFilePath
+ Distribution.PackageDescription.FieldGrammar: instance Distribution.Pretty.Pretty Distribution.PackageDescription.FieldGrammar.CompatLicenseFile
+ Distribution.Parsec: PWTEmptyFilePath :: PWarnType
+ Distribution.Parsec.Warning: PWTEmptyFilePath :: PWarnType
+ Distribution.Pretty: showTokenStr :: String -> String
+ Distribution.SPDX: BSD_2_Clause_Views :: LicenseId
+ Distribution.SPDX: CC_BY_3_0_AT :: LicenseId
+ Distribution.SPDX: CC_BY_NC_ND_3_0_IGO :: LicenseId
+ Distribution.SPDX: CC_BY_SA_3_0_AT :: LicenseId
+ Distribution.SPDX: EPICS :: LicenseId
+ Distribution.SPDX: GFDL_1_1_invariants_only :: LicenseId
+ Distribution.SPDX: GFDL_1_1_invariants_or_later :: LicenseId
+ Distribution.SPDX: GFDL_1_1_no_invariants_only :: LicenseId
+ Distribution.SPDX: GFDL_1_1_no_invariants_or_later :: LicenseId
+ Distribution.SPDX: GFDL_1_2_invariants_only :: LicenseId
+ Distribution.SPDX: GFDL_1_2_invariants_or_later :: LicenseId
+ Distribution.SPDX: GFDL_1_2_no_invariants_only :: LicenseId
+ Distribution.SPDX: GFDL_1_2_no_invariants_or_later :: LicenseId
+ Distribution.SPDX: GFDL_1_3_invariants_only :: LicenseId
+ Distribution.SPDX: GFDL_1_3_invariants_or_later :: LicenseId
+ Distribution.SPDX: GFDL_1_3_no_invariants_only :: LicenseId
+ Distribution.SPDX: GFDL_1_3_no_invariants_or_later :: LicenseId
+ Distribution.SPDX: GLWTPL :: LicenseId
+ Distribution.SPDX: LicenseListVersion_3_10 :: LicenseListVersion
+ Distribution.SPDX: NIST_PD :: LicenseId
+ Distribution.SPDX: NIST_PD_fallback :: LicenseId
+ Distribution.SPDX.LicenseId: BSD_2_Clause_Views :: LicenseId
+ Distribution.SPDX.LicenseId: CC_BY_3_0_AT :: LicenseId
+ Distribution.SPDX.LicenseId: CC_BY_NC_ND_3_0_IGO :: LicenseId
+ Distribution.SPDX.LicenseId: CC_BY_SA_3_0_AT :: LicenseId
+ Distribution.SPDX.LicenseId: EPICS :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_1_invariants_only :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_1_invariants_or_later :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_1_no_invariants_only :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_1_no_invariants_or_later :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_2_invariants_only :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_2_invariants_or_later :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_2_no_invariants_only :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_2_no_invariants_or_later :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_3_invariants_only :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_3_invariants_or_later :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_3_no_invariants_only :: LicenseId
+ Distribution.SPDX.LicenseId: GFDL_1_3_no_invariants_or_later :: LicenseId
+ Distribution.SPDX.LicenseId: GLWTPL :: LicenseId
+ Distribution.SPDX.LicenseId: NIST_PD :: LicenseId
+ Distribution.SPDX.LicenseId: NIST_PD_fallback :: LicenseId
+ Distribution.SPDX.LicenseListVersion: LicenseListVersion_3_10 :: LicenseListVersion
+ Distribution.Simple.GHC: [supportsGHC2021] :: GhcImplInfo -> Bool
+ Distribution.Simple.GHCJS: [supportsGHC2021] :: GhcImplInfo -> Bool
+ Distribution.Simple.Glob: matchDirFileGlobWithDie :: Verbosity -> (Verbosity -> String -> IO [FilePath]) -> CabalSpecVersion -> FilePath -> FilePath -> IO [FilePath]
+ Distribution.Types.BuildInfo: [hsc2hsOptions] :: BuildInfo -> [String]
+ Distribution.Types.BuildInfo.Lens: hsc2hsOptions :: HasBuildInfo a => Lens' a [String]
+ Distribution.Types.VersionInterval: VersionInterval :: !LowerBound -> !UpperBound -> VersionInterval
+ Distribution.Types.VersionInterval: data VersionInterval
+ Distribution.Types.VersionInterval: instance GHC.Classes.Eq Distribution.Types.VersionInterval.VersionInterval
+ Distribution.Types.VersionInterval: instance GHC.Show.Show Distribution.Types.VersionInterval.VersionInterval
+ Distribution.Types.VersionInterval: invariantVersionIntervals :: VersionIntervals -> Bool
+ Distribution.Types.VersionInterval: normaliseVersionRange2 :: VersionRange -> VersionRange
+ Distribution.Types.VersionInterval: unVersionIntervals :: VersionIntervals -> [VersionInterval]
+ Distribution.Types.VersionInterval.Legacy: ExclusiveBound :: Bound
+ Distribution.Types.VersionInterval.Legacy: InclusiveBound :: Bound
+ Distribution.Types.VersionInterval.Legacy: LowerBound :: Version -> !Bound -> LowerBound
+ Distribution.Types.VersionInterval.Legacy: NoUpperBound :: UpperBound
+ Distribution.Types.VersionInterval.Legacy: UpperBound :: Version -> !Bound -> UpperBound
+ Distribution.Types.VersionInterval.Legacy: asVersionIntervals :: VersionRange -> [VersionInterval]
+ Distribution.Types.VersionInterval.Legacy: data Bound
+ Distribution.Types.VersionInterval.Legacy: data LowerBound
+ Distribution.Types.VersionInterval.Legacy: data UpperBound
+ Distribution.Types.VersionInterval.Legacy: data VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: fromVersionIntervals :: VersionIntervals -> VersionRange
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Classes.Eq Distribution.Types.VersionInterval.Legacy.Bound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Classes.Eq Distribution.Types.VersionInterval.Legacy.LowerBound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Classes.Eq Distribution.Types.VersionInterval.Legacy.UpperBound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Classes.Eq Distribution.Types.VersionInterval.Legacy.VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Classes.Ord Distribution.Types.VersionInterval.Legacy.LowerBound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Classes.Ord Distribution.Types.VersionInterval.Legacy.UpperBound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Show.Show Distribution.Types.VersionInterval.Legacy.Bound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Show.Show Distribution.Types.VersionInterval.Legacy.LowerBound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Show.Show Distribution.Types.VersionInterval.Legacy.UpperBound
+ Distribution.Types.VersionInterval.Legacy: instance GHC.Show.Show Distribution.Types.VersionInterval.Legacy.VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: intersectVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: invertVersionIntervals :: VersionIntervals -> VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: mkVersionIntervals :: [VersionInterval] -> VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: relaxHeadInterval :: VersionIntervals -> VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: relaxLastInterval :: VersionIntervals -> VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: toVersionIntervals :: VersionRange -> VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: type VersionInterval = (LowerBound, UpperBound)
+ Distribution.Types.VersionInterval.Legacy: unionVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
+ Distribution.Types.VersionInterval.Legacy: versionIntervals :: VersionIntervals -> [VersionInterval]
+ Distribution.Types.VersionInterval.Legacy: withinIntervals :: Version -> VersionIntervals -> Bool
+ Distribution.Utils.Path: class IsDir dir
+ Distribution.Utils.Path: data LicenseFile
+ Distribution.Utils.Path: data PackageDir
+ Distribution.Utils.Path: data SourceDir
+ Distribution.Utils.Path: data SymbolicPath from to
+ Distribution.Utils.Path: getSymbolicPath :: SymbolicPath from to -> FilePath
+ Distribution.Utils.Path: instance (Data.Data.Data from, Data.Data.Data to) => Data.Data.Data (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance (Data.Typeable.Internal.Typeable from, Data.Typeable.Internal.Typeable to) => Distribution.Utils.Structured.Structured (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance Control.DeepSeq.NFData (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance Data.Binary.Class.Binary (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance Data.Data.Data Distribution.Utils.Path.LicenseFile
+ Distribution.Utils.Path: instance Data.Data.Data Distribution.Utils.Path.PackageDir
+ Distribution.Utils.Path: instance Data.Data.Data Distribution.Utils.Path.SourceDir
+ Distribution.Utils.Path: instance Distribution.Parsec.Parsec (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance Distribution.Pretty.Pretty (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance Distribution.Utils.Path.IsDir Distribution.Utils.Path.PackageDir
+ Distribution.Utils.Path: instance Distribution.Utils.Path.IsDir Distribution.Utils.Path.SourceDir
+ Distribution.Utils.Path: instance GHC.Classes.Eq (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance GHC.Generics.Generic (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance GHC.Read.Read (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: instance GHC.Show.Show (Distribution.Utils.Path.SymbolicPath from to)
+ Distribution.Utils.Path: sameDirectory :: (IsDir from, IsDir to) => SymbolicPath from to
+ Distribution.Utils.Path: unsafeMakeSymbolicPath :: FilePath -> SymbolicPath from to
+ Distribution.Version: VersionInterval :: !LowerBound -> !UpperBound -> VersionInterval
+ Distribution.Version: data VersionInterval
+ Distribution.Version: transformCaret :: VersionRange -> VersionRange
+ Distribution.Version: transformCaretLower :: VersionRange -> VersionRange
+ Distribution.Version: transformCaretUpper :: VersionRange -> VersionRange
+ Distribution.Version: unVersionIntervals :: VersionIntervals -> [VersionInterval]
+ Language.Haskell.Extension: FieldSelectors :: KnownExtension
+ Language.Haskell.Extension: GHC2021 :: Language
+ Language.Haskell.Extension: OverloadedRecordDot :: KnownExtension
+ Language.Haskell.Extension: UnliftedDatatypes :: KnownExtension
- Distribution.PackageDescription.FieldGrammar: benchmarkFieldGrammar :: (FieldGrammar c g, Applicative (g BenchmarkStanza), Applicative (g BuildInfo), c (Identity BenchmarkType), c (Identity ModuleName), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => g BenchmarkStanza BenchmarkStanza
+ Distribution.PackageDescription.FieldGrammar: benchmarkFieldGrammar :: (FieldGrammar c g, Applicative (g BenchmarkStanza), Applicative (g BuildInfo), c (Identity BenchmarkType), c (Identity ModuleName), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)), c (List VCat Token String), c (MQuoted Language)) => g BenchmarkStanza BenchmarkStanza
- Distribution.PackageDescription.FieldGrammar: buildInfoFieldGrammar :: (FieldGrammar c g, Applicative (g BuildInfo), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => g BuildInfo BuildInfo
+ Distribution.PackageDescription.FieldGrammar: buildInfoFieldGrammar :: (FieldGrammar c g, Applicative (g BuildInfo), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)), c (List VCat Token String), c (MQuoted Language)) => g BuildInfo BuildInfo
- Distribution.PackageDescription.FieldGrammar: executableFieldGrammar :: (FieldGrammar c g, Applicative (g Executable), Applicative (g BuildInfo), c (Identity ExecutableScope), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => UnqualComponentName -> g Executable Executable
+ Distribution.PackageDescription.FieldGrammar: executableFieldGrammar :: (FieldGrammar c g, Applicative (g Executable), Applicative (g BuildInfo), c (Identity ExecutableScope), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => UnqualComponentName -> g Executable Executable
- Distribution.PackageDescription.FieldGrammar: foreignLibFieldGrammar :: (FieldGrammar c g, Applicative (g ForeignLib), Applicative (g BuildInfo), c (Identity ForeignLibType), c (Identity LibVersionInfo), c (Identity Version), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (Identity ForeignLibOption) ForeignLibOption), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => UnqualComponentName -> g ForeignLib ForeignLib
+ Distribution.PackageDescription.FieldGrammar: foreignLibFieldGrammar :: (FieldGrammar c g, Applicative (g ForeignLib), Applicative (g BuildInfo), c (Identity ForeignLibType), c (Identity LibVersionInfo), c (Identity Version), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (Identity ForeignLibOption) ForeignLibOption), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => UnqualComponentName -> g ForeignLib ForeignLib
- Distribution.PackageDescription.FieldGrammar: formatHsSourceDirs :: [FilePath] -> List FSep FilePathNT FilePath
+ Distribution.PackageDescription.FieldGrammar: formatHsSourceDirs :: [SymbolicPath PackageDir SourceDir] -> List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)
- Distribution.PackageDescription.FieldGrammar: libraryFieldGrammar :: (FieldGrammar c g, Applicative (g Library), Applicative (g BuildInfo), c (Identity LibraryVisibility), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List CommaVCat (Identity ModuleReexport) ModuleReexport), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => LibraryName -> g Library Library
+ Distribution.PackageDescription.FieldGrammar: libraryFieldGrammar :: (FieldGrammar c g, Applicative (g Library), Applicative (g BuildInfo), c (Identity LibraryVisibility), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List CommaVCat (Identity ModuleReexport) ModuleReexport), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)), c (List VCat Token String), c (MQuoted Language)) => LibraryName -> g Library Library
- Distribution.PackageDescription.FieldGrammar: packageDescriptionFieldGrammar :: (FieldGrammar c g, Applicative (g PackageDescription), Applicative (g PackageIdentifier), c (Identity BuildType), c (Identity PackageName), c (Identity Version), c (List FSep FilePathNT String), c (List FSep TestedWith (CompilerFlavor, VersionRange)), c (List VCat FilePathNT String), c FilePathNT, c SpecLicense, c SpecVersion) => g PackageDescription PackageDescription
+ Distribution.PackageDescription.FieldGrammar: packageDescriptionFieldGrammar :: (FieldGrammar c g, Applicative (g PackageDescription), Applicative (g PackageIdentifier), c (Identity BuildType), c (Identity PackageName), c (Identity Version), c (List FSep FilePathNT String), c (List FSep CompatFilePath String), c (List FSep (Identity (SymbolicPath PackageDir LicenseFile)) (SymbolicPath PackageDir LicenseFile)), c (List FSep TestedWith (CompilerFlavor, VersionRange)), c (List VCat FilePathNT String), c FilePathNT, c CompatLicenseFile, c CompatFilePath, c SpecLicense, c SpecVersion) => g PackageDescription PackageDescription
- Distribution.PackageDescription.FieldGrammar: testSuiteFieldGrammar :: (FieldGrammar c g, Applicative (g TestSuiteStanza), Applicative (g BuildInfo), c (Identity ModuleName), c (Identity TestType), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List VCat Token String), c (MQuoted Language)) => g TestSuiteStanza TestSuiteStanza
+ Distribution.PackageDescription.FieldGrammar: testSuiteFieldGrammar :: (FieldGrammar c g, Applicative (g TestSuiteStanza), Applicative (g BuildInfo), c (Identity ModuleName), c (Identity TestType), c (List CommaFSep (Identity ExeDependency) ExeDependency), c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency), c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency), c (List CommaVCat (Identity Dependency) Dependency), c (List CommaVCat (Identity Mixin) Mixin), c (List FSep (MQuoted Extension) Extension), c (List FSep (MQuoted Language) Language), c (List FSep FilePathNT String), c (List FSep Token String), c (List NoCommaFSep Token' String), c (List VCat (MQuoted ModuleName) ModuleName), c (List VCat FilePathNT String), c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)), c (List VCat Token String), c (MQuoted Language)) => g TestSuiteStanza TestSuiteStanza
- Distribution.Simple: UserHooks :: IO (Maybe GenericPackageDescription) -> [PPSuffixHandler] -> [Program] -> (Args -> ConfigFlags -> IO HookedBuildInfo) -> ((GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo) -> (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BuildFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()) -> (Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> ReplFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()) -> (Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> CleanFlags -> IO HookedBuildInfo) -> (PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()) -> (Args -> CleanFlags -> PackageDescription -> () -> IO ()) -> (Args -> CopyFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()) -> (Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> InstallFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()) -> (Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HscolourFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO ()) -> (Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> DoctestFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> DoctestFlags -> IO ()) -> (Args -> DoctestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HaddockFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO ()) -> (Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> TestFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) -> (Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BenchmarkFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO ()) -> (Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> UserHooks
+ Distribution.Simple: UserHooks :: IO (Maybe GenericPackageDescription) -> [PPSuffixHandler] -> [Program] -> (Args -> ConfigFlags -> IO HookedBuildInfo) -> ((GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo) -> (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BuildFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()) -> (Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> ReplFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()) -> (Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> CleanFlags -> IO HookedBuildInfo) -> (PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()) -> (Args -> CleanFlags -> PackageDescription -> () -> IO ()) -> (Args -> CopyFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()) -> (Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> InstallFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()) -> (Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HscolourFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO ()) -> (Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HaddockFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO ()) -> (Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> TestFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) -> (Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BenchmarkFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO ()) -> (Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> UserHooks
- Distribution.Simple.GHC: GhcImplInfo :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GhcImplInfo
+ Distribution.Simple.GHC: GhcImplInfo :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GhcImplInfo
- Distribution.Simple.GHCJS: GhcImplInfo :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GhcImplInfo
+ Distribution.Simple.GHCJS: GhcImplInfo :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GhcImplInfo
- Distribution.Simple.Hpc: markupPackage :: Verbosity -> LocalBuildInfo -> FilePath -> String -> [TestSuite] -> IO ()
+ Distribution.Simple.Hpc: markupPackage :: Verbosity -> LocalBuildInfo -> FilePath -> PackageDescription -> [TestSuite] -> IO ()
- Distribution.Simple.Hpc: markupTest :: Verbosity -> LocalBuildInfo -> FilePath -> String -> TestSuite -> IO ()
+ Distribution.Simple.Hpc: markupTest :: Verbosity -> LocalBuildInfo -> FilePath -> String -> TestSuite -> Library -> IO ()
- Distribution.Simple.UserHooks: UserHooks :: IO (Maybe GenericPackageDescription) -> [PPSuffixHandler] -> [Program] -> (Args -> ConfigFlags -> IO HookedBuildInfo) -> ((GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo) -> (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BuildFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()) -> (Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> ReplFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()) -> (Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> CleanFlags -> IO HookedBuildInfo) -> (PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()) -> (Args -> CleanFlags -> PackageDescription -> () -> IO ()) -> (Args -> CopyFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()) -> (Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> InstallFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()) -> (Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HscolourFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO ()) -> (Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> DoctestFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> DoctestFlags -> IO ()) -> (Args -> DoctestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HaddockFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO ()) -> (Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> TestFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) -> (Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BenchmarkFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO ()) -> (Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> UserHooks
+ Distribution.Simple.UserHooks: UserHooks :: IO (Maybe GenericPackageDescription) -> [PPSuffixHandler] -> [Program] -> (Args -> ConfigFlags -> IO HookedBuildInfo) -> ((GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo) -> (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BuildFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()) -> (Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> ReplFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()) -> (Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> CleanFlags -> IO HookedBuildInfo) -> (PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()) -> (Args -> CleanFlags -> PackageDescription -> () -> IO ()) -> (Args -> CopyFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()) -> (Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> InstallFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()) -> (Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HscolourFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO ()) -> (Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HaddockFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO ()) -> (Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> TestFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) -> (Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BenchmarkFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO ()) -> (Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> UserHooks
- Distribution.Types.BuildInfo: BuildInfo :: Bool -> [LegacyExeDependency] -> [ExeDependency] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [PkgconfigDependency] -> [String] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> [ModuleName] -> [ModuleName] -> [ModuleName] -> Maybe Language -> [Language] -> [Extension] -> [Extension] -> [Extension] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> PerCompilerFlavor [String] -> PerCompilerFlavor [String] -> PerCompilerFlavor [String] -> PerCompilerFlavor [String] -> [(String, String)] -> [Dependency] -> [Mixin] -> BuildInfo
+ Distribution.Types.BuildInfo: BuildInfo :: Bool -> [LegacyExeDependency] -> [ExeDependency] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [PkgconfigDependency] -> [String] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> [SymbolicPath PackageDir SourceDir] -> [ModuleName] -> [ModuleName] -> [ModuleName] -> Maybe Language -> [Language] -> [Extension] -> [Extension] -> [Extension] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> PerCompilerFlavor [String] -> PerCompilerFlavor [String] -> PerCompilerFlavor [String] -> PerCompilerFlavor [String] -> [(String, String)] -> [Dependency] -> [Mixin] -> BuildInfo
- Distribution.Types.BuildInfo: [hsSourceDirs] :: BuildInfo -> [FilePath]
+ Distribution.Types.BuildInfo: [hsSourceDirs] :: BuildInfo -> [SymbolicPath PackageDir SourceDir]
- Distribution.Types.BuildInfo.Lens: hsSourceDirs :: HasBuildInfo a => Lens' a [FilePath]
+ Distribution.Types.BuildInfo.Lens: hsSourceDirs :: HasBuildInfo a => Lens' a [SymbolicPath PackageDir SourceDir]
- Distribution.Types.PackageDescription: PackageDescription :: CabalSpecVersion -> PackageIdentifier -> Either License License -> [FilePath] -> !ShortText -> !ShortText -> !ShortText -> !ShortText -> [(CompilerFlavor, VersionRange)] -> !ShortText -> !ShortText -> !ShortText -> [SourceRepo] -> !ShortText -> !ShortText -> !ShortText -> [(String, String)] -> Maybe BuildType -> Maybe SetupBuildInfo -> Maybe Library -> [Library] -> [Executable] -> [ForeignLib] -> [TestSuite] -> [Benchmark] -> [FilePath] -> FilePath -> [FilePath] -> [FilePath] -> [FilePath] -> PackageDescription
+ Distribution.Types.PackageDescription: PackageDescription :: CabalSpecVersion -> PackageIdentifier -> Either License License -> [SymbolicPath PackageDir LicenseFile] -> !ShortText -> !ShortText -> !ShortText -> !ShortText -> [(CompilerFlavor, VersionRange)] -> !ShortText -> !ShortText -> !ShortText -> [SourceRepo] -> !ShortText -> !ShortText -> !ShortText -> [(String, String)] -> Maybe BuildType -> Maybe SetupBuildInfo -> Maybe Library -> [Library] -> [Executable] -> [ForeignLib] -> [TestSuite] -> [Benchmark] -> [FilePath] -> FilePath -> [FilePath] -> [FilePath] -> [FilePath] -> PackageDescription
- Distribution.Types.PackageDescription: [licenseFiles] :: PackageDescription -> [FilePath]
+ Distribution.Types.PackageDescription: [licenseFiles] :: PackageDescription -> [SymbolicPath PackageDir LicenseFile]
- Distribution.Types.PackageDescription.Lens: licenseFiles :: Lens' PackageDescription [FilePath]
+ Distribution.Types.PackageDescription.Lens: licenseFiles :: Lens' PackageDescription [SymbolicPath PackageDir LicenseFile]
- Distribution.Types.VersionInterval: LowerBound :: Version -> !Bound -> LowerBound
+ Distribution.Types.VersionInterval: LowerBound :: !Version -> !Bound -> LowerBound
- Distribution.Types.VersionInterval: UpperBound :: Version -> !Bound -> UpperBound
+ Distribution.Types.VersionInterval: UpperBound :: !Version -> !Bound -> UpperBound
- Distribution.Version: LowerBound :: Version -> !Bound -> LowerBound
+ Distribution.Version: LowerBound :: !Version -> !Bound -> LowerBound
- Distribution.Version: UpperBound :: Version -> !Bound -> UpperBound
+ Distribution.Version: UpperBound :: !Version -> !Bound -> UpperBound
Files
- Cabal-QuickCheck/src/Test/QuickCheck/GenericArbitrary.hs +0/−49
- Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs +0/−548
- Cabal-described/src/Distribution/Described.hs +0/−577
- Cabal-described/src/Distribution/Utils/CharSet.hs +0/−242
- Cabal-described/src/Distribution/Utils/GrammarRegex.hs +0/−215
- Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs +0/−135
- Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalLanguage.hs +0/−17
- Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalSPDX.hs +0/−28
- Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalVersion.hs +0/−14
- Cabal.cabal +14/−491
- ChangeLog.md +10/−25
- Distribution/Backpack.hs +0/−269
- Distribution/Backpack/ComponentsGraph.hs +0/−97
- Distribution/Backpack/Configure.hs +0/−359
- Distribution/Backpack/ConfiguredComponent.hs +0/−308
- Distribution/Backpack/DescribeUnitId.hs +0/−61
- Distribution/Backpack/FullUnitId.hs +0/−26
- Distribution/Backpack/Id.hs +0/−145
- Distribution/Backpack/LinkedComponent.hs +0/−396
- Distribution/Backpack/MixLink.hs +0/−185
- Distribution/Backpack/ModSubst.hs +0/−52
- Distribution/Backpack/ModuleScope.hs +0/−132
- Distribution/Backpack/ModuleShape.hs +0/−84
- Distribution/Backpack/PreExistingComponent.hs +0/−67
- Distribution/Backpack/PreModuleShape.hs +0/−44
- Distribution/Backpack/ReadyComponent.hs +0/−376
- Distribution/Backpack/UnifyM.hs +0/−627
- Distribution/CabalSpecVersion.hs +0/−146
- Distribution/Compat/Async.hs +0/−148
- Distribution/Compat/Binary.hs +0/−71
- Distribution/Compat/Binary/Class.hs +0/−519
- Distribution/Compat/Binary/Generic.hs +0/−128
- Distribution/Compat/CharParsing.hs +0/−357
- Distribution/Compat/CopyFile.hs +0/−250
- Distribution/Compat/CreatePipe.hs +0/−81
- Distribution/Compat/DList.hs +0/−53
- Distribution/Compat/Directory.hs +0/−49
- Distribution/Compat/Environment.hs +0/−134
- Distribution/Compat/Exception.hs +0/−37
- Distribution/Compat/FilePath.hs +0/−27
- Distribution/Compat/GetShortPathName.hs +0/−59
- Distribution/Compat/Graph.hs +0/−408
- Distribution/Compat/Internal/TempFile.hs +0/−137
- Distribution/Compat/Lens.hs +0/−262
- Distribution/Compat/MonadFail.hs +0/−5
- Distribution/Compat/Newtype.hs +0/−91
- Distribution/Compat/NonEmptySet.hs +0/−155
- Distribution/Compat/Parsing.hs +0/−362
- Distribution/Compat/Prelude.hs +0/−316
- Distribution/Compat/Prelude/Internal.hs +0/−14
- Distribution/Compat/Process.hs +0/−82
- Distribution/Compat/ResponseFile.hs +0/−67
- Distribution/Compat/Semigroup.hs +0/−119
- Distribution/Compat/SnocList.hs +0/−33
- Distribution/Compat/Stack.hs +0/−113
- Distribution/Compat/Time.hs +0/−194
- Distribution/Compat/Typeable.hs +0/−18
- Distribution/Compiler.hs +0/−223
- Distribution/FieldGrammar.hs +0/−88
- Distribution/FieldGrammar/Class.hs +0/−205
- Distribution/FieldGrammar/FieldDescrs.hs +0/−121
- Distribution/FieldGrammar/Newtypes.hs +0/−339
- Distribution/FieldGrammar/Parsec.hs +0/−439
- Distribution/FieldGrammar/Pretty.hs +0/−104
- Distribution/Fields.hs +0/−42
- Distribution/Fields/ConfVar.hs +0/−126
- Distribution/Fields/Field.hs +0/−108
- Distribution/Fields/Lexer.hs +0/−496
- Distribution/Fields/LexerMonad.hs +0/−155
- Distribution/Fields/ParseResult.hs +0/−196
- Distribution/Fields/Parser.hs +0/−377
- Distribution/Fields/Pretty.hs +0/−176
- Distribution/GetOpt.hs +0/−209
- Distribution/InstalledPackageInfo.hs +0/−145
- Distribution/Lex.hs +0/−40
- Distribution/License.hs +0/−252
- Distribution/Make.hs +0/−182
- Distribution/ModuleName.hs +0/−131
- Distribution/Package.hs +0/−96
- Distribution/PackageDescription.hs +0/−97
- Distribution/PackageDescription/Check.hs +0/−2389
- Distribution/PackageDescription/Configuration.hs +0/−599
- Distribution/PackageDescription/FieldGrammar.hs +0/−692
- Distribution/PackageDescription/Parsec.hs +0/−975
- Distribution/PackageDescription/PrettyPrint.hs +0/−283
- Distribution/PackageDescription/Quirks.hs +0/−319
- Distribution/PackageDescription/Utils.hs +0/−23
- Distribution/Parsec.hs +0/−524
- Distribution/Parsec/Error.hs +0/−21
- Distribution/Parsec/FieldLineStream.hs +0/−91
- Distribution/Parsec/Position.hs +0/−44
- Distribution/Parsec/Warning.hs +0/−59
- Distribution/Pretty.hs +0/−106
- Distribution/ReadE.hs +0/−49
- Distribution/SPDX.hs +0/−40
- Distribution/SPDX/License.hs +0/−65
- Distribution/SPDX/LicenseExceptionId.hs +0/−294
- Distribution/SPDX/LicenseExpression.hs +0/−162
- Distribution/SPDX/LicenseId.hs +0/−2025
- Distribution/SPDX/LicenseListVersion.hs +0/−20
- Distribution/SPDX/LicenseReference.hs +0/−80
- Distribution/Simple.hs +0/−855
- Distribution/Simple/Bench.hs +0/−125
- Distribution/Simple/Build.hs +0/−733
- Distribution/Simple/Build/Macros.hs +0/−110
- Distribution/Simple/Build/Macros/Z.hs +0/−140
- Distribution/Simple/Build/PathsModule.hs +0/−356
- Distribution/Simple/BuildPaths.hs +0/−256
- Distribution/Simple/BuildTarget.hs +0/−1063
- Distribution/Simple/BuildToolDepends.hs +0/−93
- Distribution/Simple/CCompiler.hs +0/−123
- Distribution/Simple/Command.hs +0/−555
- Distribution/Simple/Compiler.hs +0/−453
- Distribution/Simple/Configure.hs +0/−2092
- Distribution/Simple/Doctest.hs +0/−187
- Distribution/Simple/Flag.hs +0/−132
- Distribution/Simple/GHC.hs +0/−2084
- Distribution/Simple/GHC/EnvironmentParser.hs +0/−49
- Distribution/Simple/GHC/ImplInfo.hs +0/−93
- Distribution/Simple/GHC/Internal.hs +0/−681
- Distribution/Simple/GHCJS.hs +0/−1830
- Distribution/Simple/Glob.hs +0/−306
- Distribution/Simple/Haddock.hs +0/−926
- Distribution/Simple/HaskellSuite.hs +0/−227
- Distribution/Simple/Hpc.hs +0/−149
- Distribution/Simple/Install.hs +0/−258
- Distribution/Simple/InstallDirs.hs +0/−506
- Distribution/Simple/InstallDirs/Internal.hs +0/−127
- Distribution/Simple/LocalBuildInfo.hs +0/−365
- Distribution/Simple/PackageIndex.hs +0/−716
- Distribution/Simple/PreProcess.hs +0/−751
- Distribution/Simple/PreProcess/Unlit.hs +0/−167
- Distribution/Simple/Program.hs +0/−183
- Distribution/Simple/Program/Ar.hs +0/−191
- Distribution/Simple/Program/Builtin.hs +0/−348
- Distribution/Simple/Program/Db.hs +0/−505
- Distribution/Simple/Program/Find.hs +0/−198
- Distribution/Simple/Program/GHC.hs +0/−851
- Distribution/Simple/Program/HcPkg.hs +0/−516
- Distribution/Simple/Program/Hpc.hs +0/−110
- Distribution/Simple/Program/Internal.hs +0/−47
- Distribution/Simple/Program/Ld.hs +0/−92
- Distribution/Simple/Program/ResponseFile.hs +0/−60
- Distribution/Simple/Program/Run.hs +0/−297
- Distribution/Simple/Program/Script.hs +0/−114
- Distribution/Simple/Program/Strip.hs +0/−75
- Distribution/Simple/Program/Types.hs +0/−190
- Distribution/Simple/Register.hs +0/−595
- Distribution/Simple/Setup.hs +0/−2411
- Distribution/Simple/ShowBuildInfo.hs +0/−161
- Distribution/Simple/SrcDist.hs +0/−517
- Distribution/Simple/Test.hs +0/−136
- Distribution/Simple/Test/ExeV10.hs +0/−188
- Distribution/Simple/Test/LibV09.hs +0/−287
- Distribution/Simple/Test/Log.hs +0/−166
- Distribution/Simple/UHC.hs +0/−295
- Distribution/Simple/UserHooks.hs +0/−207
- Distribution/Simple/Utils.hs +0/−1609
- Distribution/Simple/Utils/Json.hs +0/−46
- Distribution/System.hs +0/−275
- Distribution/TestSuite.hs +0/−102
- Distribution/Text.hs +0/−12
- Distribution/Types/AbiDependency.hs +0/−44
- Distribution/Types/AbiHash.hs +0/−61
- Distribution/Types/AnnotatedId.hs +0/−34
- Distribution/Types/Benchmark.hs +0/−77
- Distribution/Types/Benchmark/Lens.hs +0/−27
- Distribution/Types/BenchmarkInterface.hs +0/−46
- Distribution/Types/BenchmarkType.hs +0/−40
- Distribution/Types/BuildInfo.hs +0/−262
- Distribution/Types/BuildInfo/Lens.hs +0/−334
- Distribution/Types/BuildType.hs +0/−55
- Distribution/Types/Component.hs +0/−91
- Distribution/Types/ComponentId.hs +0/−69
- Distribution/Types/ComponentInclude.hs +0/−32
- Distribution/Types/ComponentLocalBuildInfo.hs +0/−129
- Distribution/Types/ComponentName.hs +0/−78
- Distribution/Types/ComponentRequestedSpec.hs +0/−127
- Distribution/Types/CondTree.hs +0/−181
- Distribution/Types/Condition.hs +0/−135
- Distribution/Types/ConfVar.hs +0/−25
- Distribution/Types/Dependency.hs +0/−179
- Distribution/Types/DependencyMap.hs +0/−57
- Distribution/Types/ExeDependency.hs +0/−71
- Distribution/Types/Executable.hs +0/−65
- Distribution/Types/Executable/Lens.hs +0/−31
- Distribution/Types/ExecutableScope.hs +0/−43
- Distribution/Types/ExposedModule.hs +0/−45
- Distribution/Types/Flag.hs +0/−346
- Distribution/Types/ForeignLib.hs +0/−199
- Distribution/Types/ForeignLib/Lens.hs +0/−45
- Distribution/Types/ForeignLibOption.hs +0/−39
- Distribution/Types/ForeignLibType.hs +0/−69
- Distribution/Types/GenericPackageDescription.hs +0/−105
- Distribution/Types/GenericPackageDescription/Lens.hs +0/−131
- Distribution/Types/GivenComponent.hs +0/−28
- Distribution/Types/HookedBuildInfo.hs +0/−66
- Distribution/Types/IncludeRenaming.hs +0/−68
- Distribution/Types/InstalledPackageInfo.hs +0/−173
- Distribution/Types/InstalledPackageInfo/FieldGrammar.hs +0/−317
- Distribution/Types/InstalledPackageInfo/Lens.hs +0/−190
- Distribution/Types/LegacyExeDependency.hs +0/−47
- Distribution/Types/Lens.hs +0/−25
- Distribution/Types/Library.hs +0/−96
- Distribution/Types/Library/Lens.hs +0/−45
- Distribution/Types/LibraryName.hs +0/−73
- Distribution/Types/LibraryVisibility.hs +0/−52
- Distribution/Types/LocalBuildInfo.hs +0/−304
- Distribution/Types/Mixin.hs +0/−93
- Distribution/Types/Module.hs +0/−46
- Distribution/Types/ModuleReexport.hs +0/−50
- Distribution/Types/ModuleRenaming.hs +0/−134
- Distribution/Types/MungedPackageId.hs +0/−83
- Distribution/Types/MungedPackageName.hs +0/−157
- Distribution/Types/PackageDescription.hs +0/−456
- Distribution/Types/PackageDescription/Lens.hs +0/−220
- Distribution/Types/PackageId.hs +0/−74
- Distribution/Types/PackageId/Lens.hs +0/−22
- Distribution/Types/PackageName.hs +0/−73
- Distribution/Types/PackageName/Magic.hs +0/−20
- Distribution/Types/PackageVersionConstraint.hs +0/−74
- Distribution/Types/PkgconfigDependency.hs +0/−39
- Distribution/Types/PkgconfigName.hs +0/−68
- Distribution/Types/PkgconfigVersion.hs +0/−119
- Distribution/Types/PkgconfigVersionRange.hs +0/−161
- Distribution/Types/SetupBuildInfo.hs +0/−41
- Distribution/Types/SetupBuildInfo/Lens.hs +0/−21
- Distribution/Types/SourceRepo.hs +0/−201
- Distribution/Types/SourceRepo/Lens.hs +0/−39
- Distribution/Types/TargetInfo.hs +0/−33
- Distribution/Types/TestSuite.hs +0/−83
- Distribution/Types/TestSuite/Lens.hs +0/−27
- Distribution/Types/TestSuiteInterface.hs +0/−52
- Distribution/Types/TestType.hs +0/−43
- Distribution/Types/UnitId.hs +0/−134
- Distribution/Types/UnqualComponentName.hs +0/−93
- Distribution/Types/Version.hs +0/−242
- Distribution/Types/VersionInterval.hs +0/−364
- Distribution/Types/VersionRange.hs +0/−180
- Distribution/Types/VersionRange/Internal.hs +0/−526
- Distribution/Utils/Base62.hs +0/−22
- Distribution/Utils/Generic.hs +0/−576
- Distribution/Utils/IOData.hs +0/−92
- Distribution/Utils/LogProgress.hs +0/−89
- Distribution/Utils/MD5.hs +0/−79
- Distribution/Utils/MapAccum.hs +0/−34
- Distribution/Utils/NubList.hs +0/−108
- Distribution/Utils/Progress.hs +0/−67
- Distribution/Utils/ShortText.hs +0/−159
- Distribution/Utils/String.hs +0/−93
- Distribution/Utils/Structured.hs +0/−476
- Distribution/Utils/UnionFind.hs +0/−102
- Distribution/Verbosity.hs +0/−345
- Distribution/Verbosity/Internal.hs +0/−27
- Distribution/Version.hs +0/−178
- Distribution/ZinzaPrelude.hs +0/−43
- Language/Haskell/Extension.hs +0/−919
- README.md +0/−102
- doc/README.md +0/−121
- doc/bugs-and-stability.rst +0/−6
- doc/concepts-and-development.rst +0/−7
- doc/conf.py +0/−223
- doc/config-and-install.rst +0/−5
- doc/developing-packages.rst +0/−488
- doc/file-format-changelog.rst +0/−236
- doc/images/Cabal-dark.png binary
- doc/index.rst +0/−21
- doc/installing-packages.rst +0/−247
- doc/intro.rst +0/−200
- doc/misc.rst +0/−103
- doc/nix-local-build-overview.rst +0/−45
- doc/nix-local-build.rst +0/−264
- doc/references.inc +0/−26
- src/Distribution/Backpack.hs +269/−0
- src/Distribution/Backpack/ComponentsGraph.hs +97/−0
- src/Distribution/Backpack/Configure.hs +359/−0
- src/Distribution/Backpack/ConfiguredComponent.hs +308/−0
- src/Distribution/Backpack/DescribeUnitId.hs +61/−0
- src/Distribution/Backpack/FullUnitId.hs +26/−0
- src/Distribution/Backpack/Id.hs +145/−0
- src/Distribution/Backpack/LinkedComponent.hs +396/−0
- src/Distribution/Backpack/MixLink.hs +185/−0
- src/Distribution/Backpack/ModSubst.hs +52/−0
- src/Distribution/Backpack/ModuleScope.hs +132/−0
- src/Distribution/Backpack/ModuleShape.hs +84/−0
- src/Distribution/Backpack/PreExistingComponent.hs +67/−0
- src/Distribution/Backpack/PreModuleShape.hs +44/−0
- src/Distribution/Backpack/ReadyComponent.hs +376/−0
- src/Distribution/Backpack/UnifyM.hs +625/−0
- src/Distribution/CabalSpecVersion.hs +150/−0
- src/Distribution/Compat/Async.hs +148/−0
- src/Distribution/Compat/Binary.hs +71/−0
- src/Distribution/Compat/Binary/Class.hs +519/−0
- src/Distribution/Compat/Binary/Generic.hs +128/−0
- src/Distribution/Compat/CharParsing.hs +357/−0
- src/Distribution/Compat/CopyFile.hs +250/−0
- src/Distribution/Compat/CreatePipe.hs +81/−0
- src/Distribution/Compat/DList.hs +53/−0
- src/Distribution/Compat/Directory.hs +49/−0
- src/Distribution/Compat/Environment.hs +134/−0
- src/Distribution/Compat/Exception.hs +37/−0
- src/Distribution/Compat/FilePath.hs +27/−0
- src/Distribution/Compat/GetShortPathName.hs +59/−0
- src/Distribution/Compat/Graph.hs +408/−0
- src/Distribution/Compat/Internal/TempFile.hs +137/−0
- src/Distribution/Compat/Lens.hs +262/−0
- src/Distribution/Compat/MonadFail.hs +5/−0
- src/Distribution/Compat/Newtype.hs +91/−0
- src/Distribution/Compat/NonEmptySet.hs +155/−0
- src/Distribution/Compat/Parsing.hs +362/−0
- src/Distribution/Compat/Prelude.hs +316/−0
- src/Distribution/Compat/Prelude/Internal.hs +14/−0
- src/Distribution/Compat/Process.hs +82/−0
- src/Distribution/Compat/ResponseFile.hs +67/−0
- src/Distribution/Compat/Semigroup.hs +119/−0
- src/Distribution/Compat/SnocList.hs +33/−0
- src/Distribution/Compat/Stack.hs +113/−0
- src/Distribution/Compat/Time.hs +194/−0
- src/Distribution/Compat/Typeable.hs +18/−0
- src/Distribution/Compiler.hs +223/−0
- src/Distribution/FieldGrammar.hs +88/−0
- src/Distribution/FieldGrammar/Class.hs +205/−0
- src/Distribution/FieldGrammar/FieldDescrs.hs +121/−0
- src/Distribution/FieldGrammar/Newtypes.hs +392/−0
- src/Distribution/FieldGrammar/Parsec.hs +439/−0
- src/Distribution/FieldGrammar/Pretty.hs +104/−0
- src/Distribution/Fields.hs +42/−0
- src/Distribution/Fields/ConfVar.hs +126/−0
- src/Distribution/Fields/Field.hs +141/−0
- src/Distribution/Fields/Lexer.hs +496/−0
- src/Distribution/Fields/LexerMonad.hs +155/−0
- src/Distribution/Fields/ParseResult.hs +196/−0
- src/Distribution/Fields/Parser.hs +377/−0
- src/Distribution/Fields/Pretty.hs +176/−0
- src/Distribution/GetOpt.hs +231/−0
- src/Distribution/InstalledPackageInfo.hs +145/−0
- src/Distribution/Lex.hs +40/−0
- src/Distribution/License.hs +252/−0
- src/Distribution/Make.hs +182/−0
- src/Distribution/ModuleName.hs +131/−0
- src/Distribution/Package.hs +96/−0
- src/Distribution/PackageDescription.hs +113/−0
- src/Distribution/PackageDescription/Check.hs +2392/−0
- src/Distribution/PackageDescription/Configuration.hs +600/−0
- src/Distribution/PackageDescription/FieldGrammar.hs +802/−0
- src/Distribution/PackageDescription/Parsec.hs +980/−0
- src/Distribution/PackageDescription/PrettyPrint.hs +282/−0
- src/Distribution/PackageDescription/Quirks.hs +340/−0
- src/Distribution/PackageDescription/Utils.hs +23/−0
- src/Distribution/Parsec.hs +524/−0
- src/Distribution/Parsec/Error.hs +21/−0
- src/Distribution/Parsec/FieldLineStream.hs +91/−0
- src/Distribution/Parsec/Position.hs +44/−0
- src/Distribution/Parsec/Warning.hs +61/−0
- src/Distribution/Pretty.hs +110/−0
- src/Distribution/ReadE.hs +49/−0
- src/Distribution/SPDX.hs +40/−0
- src/Distribution/SPDX/License.hs +65/−0
- src/Distribution/SPDX/LicenseExceptionId.hs +316/−0
- src/Distribution/SPDX/LicenseExpression.hs +162/−0
- src/Distribution/SPDX/LicenseId.hs +2152/−0
- src/Distribution/SPDX/LicenseListVersion.hs +22/−0
- src/Distribution/SPDX/LicenseReference.hs +80/−0
- src/Distribution/Simple.hs +818/−0
- src/Distribution/Simple/Bench.hs +125/−0
- src/Distribution/Simple/Build.hs +734/−0
- src/Distribution/Simple/Build/Macros.hs +110/−0
- src/Distribution/Simple/Build/Macros/Z.hs +140/−0
- src/Distribution/Simple/Build/PathsModule.hs +165/−0
- src/Distribution/Simple/Build/PathsModule/Z.hs +323/−0
- src/Distribution/Simple/BuildPaths.hs +257/−0
- src/Distribution/Simple/BuildTarget.hs +1064/−0
- src/Distribution/Simple/BuildToolDepends.hs +93/−0
- src/Distribution/Simple/CCompiler.hs +123/−0
- src/Distribution/Simple/Command.hs +594/−0
- src/Distribution/Simple/Compiler.hs +453/−0
- src/Distribution/Simple/Configure.hs +2088/−0
- src/Distribution/Simple/Flag.hs +132/−0
- src/Distribution/Simple/GHC.hs +2087/−0
- src/Distribution/Simple/GHC/EnvironmentParser.hs +49/−0
- src/Distribution/Simple/GHC/ImplInfo.hs +96/−0
- src/Distribution/Simple/GHC/Internal.hs +686/−0
- src/Distribution/Simple/GHCJS.hs +1831/−0
- src/Distribution/Simple/Glob.hs +320/−0
- src/Distribution/Simple/Haddock.hs +926/−0
- src/Distribution/Simple/HaskellSuite.hs +228/−0
- src/Distribution/Simple/Hpc.hs +155/−0
- src/Distribution/Simple/Install.hs +260/−0
- src/Distribution/Simple/InstallDirs.hs +506/−0
- src/Distribution/Simple/InstallDirs/Internal.hs +127/−0
- src/Distribution/Simple/LocalBuildInfo.hs +365/−0
- src/Distribution/Simple/PackageIndex.hs +716/−0
- src/Distribution/Simple/PreProcess.hs +779/−0
- src/Distribution/Simple/PreProcess/Unlit.hs +167/−0
- src/Distribution/Simple/Program.hs +183/−0
- src/Distribution/Simple/Program/Ar.hs +191/−0
- src/Distribution/Simple/Program/Builtin.hs +348/−0
- src/Distribution/Simple/Program/Db.hs +505/−0
- src/Distribution/Simple/Program/Find.hs +198/−0
- src/Distribution/Simple/Program/GHC.hs +850/−0
- src/Distribution/Simple/Program/HcPkg.hs +516/−0
- src/Distribution/Simple/Program/Hpc.hs +109/−0
- src/Distribution/Simple/Program/Internal.hs +47/−0
- src/Distribution/Simple/Program/Ld.hs +92/−0
- src/Distribution/Simple/Program/ResponseFile.hs +60/−0
- src/Distribution/Simple/Program/Run.hs +297/−0
- src/Distribution/Simple/Program/Script.hs +114/−0
- src/Distribution/Simple/Program/Strip.hs +75/−0
- src/Distribution/Simple/Program/Types.hs +190/−0
- src/Distribution/Simple/Register.hs +595/−0
- src/Distribution/Simple/Setup.hs +2348/−0
- src/Distribution/Simple/ShowBuildInfo.hs +162/−0
- src/Distribution/Simple/SrcDist.hs +520/−0
- src/Distribution/Simple/Test.hs +136/−0
- src/Distribution/Simple/Test/ExeV10.hs +193/−0
- src/Distribution/Simple/Test/LibV09.hs +292/−0
- src/Distribution/Simple/Test/Log.hs +166/−0
- src/Distribution/Simple/UHC.hs +296/−0
- src/Distribution/Simple/UserHooks.hs +197/−0
- src/Distribution/Simple/Utils.hs +1609/−0
- src/Distribution/Simple/Utils/Json.hs +46/−0
- src/Distribution/System.hs +275/−0
- src/Distribution/TestSuite.hs +102/−0
- src/Distribution/Text.hs +12/−0
- src/Distribution/Types/AbiDependency.hs +44/−0
- src/Distribution/Types/AbiHash.hs +61/−0
- src/Distribution/Types/AnnotatedId.hs +34/−0
- src/Distribution/Types/Benchmark.hs +77/−0
- src/Distribution/Types/Benchmark/Lens.hs +27/−0
- src/Distribution/Types/BenchmarkInterface.hs +46/−0
- src/Distribution/Types/BenchmarkType.hs +40/−0
- src/Distribution/Types/BuildInfo.hs +266/−0
- src/Distribution/Types/BuildInfo/Lens.hs +342/−0
- src/Distribution/Types/BuildType.hs +55/−0
- src/Distribution/Types/Component.hs +91/−0
- src/Distribution/Types/ComponentId.hs +69/−0
- src/Distribution/Types/ComponentInclude.hs +32/−0
- src/Distribution/Types/ComponentLocalBuildInfo.hs +129/−0
- src/Distribution/Types/ComponentName.hs +78/−0
- src/Distribution/Types/ComponentRequestedSpec.hs +127/−0
- src/Distribution/Types/CondTree.hs +181/−0
- src/Distribution/Types/Condition.hs +135/−0
- src/Distribution/Types/ConfVar.hs +25/−0
- src/Distribution/Types/Dependency.hs +179/−0
- src/Distribution/Types/DependencyMap.hs +57/−0
- src/Distribution/Types/ExeDependency.hs +71/−0
- src/Distribution/Types/Executable.hs +65/−0
- src/Distribution/Types/Executable/Lens.hs +31/−0
- src/Distribution/Types/ExecutableScope.hs +43/−0
- src/Distribution/Types/ExposedModule.hs +45/−0
- src/Distribution/Types/Flag.hs +346/−0
- src/Distribution/Types/ForeignLib.hs +199/−0
- src/Distribution/Types/ForeignLib/Lens.hs +45/−0
- src/Distribution/Types/ForeignLibOption.hs +39/−0
- src/Distribution/Types/ForeignLibType.hs +69/−0
- src/Distribution/Types/GenericPackageDescription.hs +105/−0
- src/Distribution/Types/GenericPackageDescription/Lens.hs +131/−0
- src/Distribution/Types/GivenComponent.hs +28/−0
- src/Distribution/Types/HookedBuildInfo.hs +66/−0
- src/Distribution/Types/IncludeRenaming.hs +68/−0
- src/Distribution/Types/InstalledPackageInfo.hs +173/−0
- src/Distribution/Types/InstalledPackageInfo/FieldGrammar.hs +317/−0
- src/Distribution/Types/InstalledPackageInfo/Lens.hs +190/−0
- src/Distribution/Types/LegacyExeDependency.hs +47/−0
- src/Distribution/Types/Lens.hs +25/−0
- src/Distribution/Types/Library.hs +96/−0
- src/Distribution/Types/Library/Lens.hs +45/−0
- src/Distribution/Types/LibraryName.hs +73/−0
- src/Distribution/Types/LibraryVisibility.hs +52/−0
- src/Distribution/Types/LocalBuildInfo.hs +304/−0
- src/Distribution/Types/Mixin.hs +93/−0
- src/Distribution/Types/Module.hs +46/−0
- src/Distribution/Types/ModuleReexport.hs +50/−0
- src/Distribution/Types/ModuleRenaming.hs +134/−0
- src/Distribution/Types/MungedPackageId.hs +83/−0
- src/Distribution/Types/MungedPackageName.hs +157/−0
- src/Distribution/Types/PackageDescription.hs +457/−0
- src/Distribution/Types/PackageDescription/Lens.hs +221/−0
- src/Distribution/Types/PackageId.hs +74/−0
- src/Distribution/Types/PackageId/Lens.hs +22/−0
- src/Distribution/Types/PackageName.hs +73/−0
- src/Distribution/Types/PackageName/Magic.hs +20/−0
- src/Distribution/Types/PackageVersionConstraint.hs +74/−0
- src/Distribution/Types/PkgconfigDependency.hs +39/−0
- src/Distribution/Types/PkgconfigName.hs +68/−0
- src/Distribution/Types/PkgconfigVersion.hs +119/−0
- src/Distribution/Types/PkgconfigVersionRange.hs +161/−0
- src/Distribution/Types/SetupBuildInfo.hs +41/−0
- src/Distribution/Types/SetupBuildInfo/Lens.hs +21/−0
- src/Distribution/Types/SourceRepo.hs +201/−0
- src/Distribution/Types/SourceRepo/Lens.hs +39/−0
- src/Distribution/Types/TargetInfo.hs +33/−0
- src/Distribution/Types/TestSuite.hs +83/−0
- src/Distribution/Types/TestSuite/Lens.hs +27/−0
- src/Distribution/Types/TestSuiteInterface.hs +52/−0
- src/Distribution/Types/TestType.hs +43/−0
- src/Distribution/Types/UnitId.hs +134/−0
- src/Distribution/Types/UnqualComponentName.hs +93/−0
- src/Distribution/Types/Version.hs +242/−0
- src/Distribution/Types/VersionInterval.hs +345/−0
- src/Distribution/Types/VersionInterval/Legacy.hs +368/−0
- src/Distribution/Types/VersionRange.hs +180/−0
- src/Distribution/Types/VersionRange/Internal.hs +526/−0
- src/Distribution/Utils/Base62.hs +22/−0
- src/Distribution/Utils/Generic.hs +576/−0
- src/Distribution/Utils/IOData.hs +92/−0
- src/Distribution/Utils/LogProgress.hs +89/−0
- src/Distribution/Utils/MD5.hs +79/−0
- src/Distribution/Utils/MapAccum.hs +34/−0
- src/Distribution/Utils/NubList.hs +108/−0
- src/Distribution/Utils/Path.hs +103/−0
- src/Distribution/Utils/Progress.hs +67/−0
- src/Distribution/Utils/ShortText.hs +159/−0
- src/Distribution/Utils/String.hs +93/−0
- src/Distribution/Utils/Structured.hs +476/−0
- src/Distribution/Utils/UnionFind.hs +102/−0
- src/Distribution/Verbosity.hs +345/−0
- src/Distribution/Verbosity/Internal.hs +27/−0
- src/Distribution/Version.hs +185/−0
- src/Distribution/ZinzaPrelude.hs +43/−0
- src/Language/Haskell/Extension.hs +933/−0
- tests/CheckTests.hs +0/−98
- tests/HackageTests.hs +0/−431
- tests/ParserTests.hs +0/−378
- tests/ParserTests/errors/MiniAgda.cabal +0/−89
- tests/ParserTests/errors/MiniAgda.errors +0/−4
- tests/ParserTests/errors/anynone.cabal +0/−10
- tests/ParserTests/errors/anynone.errors +0/−5
- tests/ParserTests/errors/big-version.cabal +0/−7
- tests/ParserTests/errors/big-version.errors +0/−4
- tests/ParserTests/errors/common1.cabal +0/−29
- tests/ParserTests/errors/common1.errors +0/−2
- tests/ParserTests/errors/common2.cabal +0/−29
- tests/ParserTests/errors/common2.errors +0/−2
- tests/ParserTests/errors/common3.cabal +0/−31
- tests/ParserTests/errors/common3.errors +0/−2
- tests/ParserTests/errors/forward-compat.cabal +0/−4
- tests/ParserTests/errors/forward-compat.errors +0/−2
- tests/ParserTests/errors/forward-compat2.cabal +0/−16
- tests/ParserTests/errors/forward-compat2.errors +0/−2
- tests/ParserTests/errors/forward-compat3.cabal +0/−16
- tests/ParserTests/errors/forward-compat3.errors +0/−2
- tests/ParserTests/errors/issue-5055-2.cabal +0/−25
- tests/ParserTests/errors/issue-5055-2.errors +0/−2
- tests/ParserTests/errors/issue-5055.cabal +0/−21
- tests/ParserTests/errors/issue-5055.errors +0/−2
- tests/ParserTests/errors/leading-comma-2.cabal +0/−23
- tests/ParserTests/errors/leading-comma-2.errors +0/−5
- tests/ParserTests/errors/leading-comma-2b.cabal +0/−23
- tests/ParserTests/errors/leading-comma-2b.errors +0/−5
- tests/ParserTests/errors/leading-comma-2c.cabal +0/−21
- tests/ParserTests/errors/leading-comma-2c.errors +0/−5
- tests/ParserTests/errors/leading-comma.cabal +0/−20
- tests/ParserTests/errors/leading-comma.errors +0/−5
- tests/ParserTests/errors/libpq1.cabal +0/−81
- tests/ParserTests/errors/libpq1.errors +0/−5
- tests/ParserTests/errors/libpq2.cabal +0/−81
- tests/ParserTests/errors/libpq2.errors +0/−5
- tests/ParserTests/errors/mixin-1.cabal +0/−15
- tests/ParserTests/errors/mixin-1.errors +0/−4
- tests/ParserTests/errors/mixin-2.cabal +0/−14
- tests/ParserTests/errors/mixin-2.errors +0/−4
- tests/ParserTests/errors/multiple-libs.cabal +0/−14
- tests/ParserTests/errors/multiple-libs.errors +0/−2
- tests/ParserTests/errors/noVersion.cabal +0/−10
- tests/ParserTests/errors/noVersion.errors +0/−4
- tests/ParserTests/errors/noVersion2.cabal +0/−10
- tests/ParserTests/errors/noVersion2.errors +0/−5
- tests/ParserTests/errors/range-ge-wild.cabal +0/−10
- tests/ParserTests/errors/range-ge-wild.errors +0/−4
- tests/ParserTests/errors/removed-fields.cabal +0/−14
- tests/ParserTests/errors/removed-fields.errors +0/−3
- tests/ParserTests/errors/spdx-1.cabal +0/−9
- tests/ParserTests/errors/spdx-1.errors +0/−4
- tests/ParserTests/errors/spdx-2.cabal +0/−9
- tests/ParserTests/errors/spdx-2.errors +0/−4
- tests/ParserTests/errors/spdx-3.cabal +0/−9
- tests/ParserTests/errors/spdx-3.errors +0/−4
- tests/ParserTests/errors/undefined-flag.cabal +0/−26
- tests/ParserTests/errors/undefined-flag.errors +0/−2
- tests/ParserTests/errors/version-sets-1.cabal +0/−8
- tests/ParserTests/errors/version-sets-1.errors +0/−5
- tests/ParserTests/errors/version-sets-2.cabal +0/−8
- tests/ParserTests/errors/version-sets-2.errors +0/−5
- tests/ParserTests/errors/version-sets-3.cabal +0/−8
- tests/ParserTests/errors/version-sets-3.errors +0/−5
- tests/ParserTests/errors/version-sets-4.cabal +0/−8
- tests/ParserTests/errors/version-sets-4.errors +0/−5
- tests/ParserTests/ipi/Includes2.cabal +0/−27
- tests/ParserTests/ipi/Includes2.expr +0/−58
- tests/ParserTests/ipi/Includes2.format +0/−35
- tests/ParserTests/ipi/internal-preprocessor-test.cabal +0/−26
- tests/ParserTests/ipi/internal-preprocessor-test.expr +0/−48
- tests/ParserTests/ipi/internal-preprocessor-test.format +0/−32
- tests/ParserTests/ipi/issue-2276-ghc-9885.cabal +0/−175
- tests/ParserTests/ipi/issue-2276-ghc-9885.expr +0/−2133
- tests/ParserTests/ipi/issue-2276-ghc-9885.format +0/−182
- tests/ParserTests/ipi/transformers.cabal +0/−59
- tests/ParserTests/ipi/transformers.expr +0/−133
- tests/ParserTests/ipi/transformers.format +0/−62
- tests/ParserTests/regressions/Octree-0.5.cabal +0/−44
- tests/ParserTests/regressions/Octree-0.5.expr +0/−357
- tests/ParserTests/regressions/Octree-0.5.format +0/−51
- tests/ParserTests/regressions/anynone.cabal +0/−10
- tests/ParserTests/regressions/anynone.expr +0/−105
- tests/ParserTests/regressions/anynone.format +0/−10
- tests/ParserTests/regressions/assoc-cpp-options.cabal +0/−48
- tests/ParserTests/regressions/assoc-cpp-options.check +0/−1
- tests/ParserTests/regressions/bad-glob-syntax.cabal +0/−16
- tests/ParserTests/regressions/bad-glob-syntax.check +0/−2
- tests/ParserTests/regressions/big-version.cabal +0/−7
- tests/ParserTests/regressions/big-version.expr +0/−96
- tests/ParserTests/regressions/big-version.format +0/−6
- tests/ParserTests/regressions/cc-options-with-optimization.cabal +0/−15
- tests/ParserTests/regressions/cc-options-with-optimization.check +0/−1
- tests/ParserTests/regressions/common-conditional.cabal +0/−49
- tests/ParserTests/regressions/common-conditional.expr +0/−682
- tests/ParserTests/regressions/common-conditional.format +0/−44
- tests/ParserTests/regressions/common.cabal +0/−35
- tests/ParserTests/regressions/common.expr +0/−176
- tests/ParserTests/regressions/common.format +0/−24
- tests/ParserTests/regressions/common2.cabal +0/−53
- tests/ParserTests/regressions/common2.expr +0/−707
- tests/ParserTests/regressions/common2.format +0/−48
- tests/ParserTests/regressions/common3.cabal +0/−36
- tests/ParserTests/regressions/common3.expr +0/−206
- tests/ParserTests/regressions/common3.format +0/−25
- tests/ParserTests/regressions/cxx-options-with-optimization.cabal +0/−15
- tests/ParserTests/regressions/cxx-options-with-optimization.check +0/−1
- tests/ParserTests/regressions/denormalised-paths.cabal +0/−71
- tests/ParserTests/regressions/denormalised-paths.check +0/−12
- tests/ParserTests/regressions/elif.cabal +0/−20
- tests/ParserTests/regressions/elif.expr +0/−178
- tests/ParserTests/regressions/elif.format +0/−18
- tests/ParserTests/regressions/elif2.cabal +0/−20
- tests/ParserTests/regressions/elif2.expr +0/−378
- tests/ParserTests/regressions/elif2.format +0/−23
- tests/ParserTests/regressions/encoding-0.8.cabal +0/−24
- tests/ParserTests/regressions/encoding-0.8.expr +0/−127
- tests/ParserTests/regressions/encoding-0.8.format +0/−19
- tests/ParserTests/regressions/extensions-paths-5054.cabal +0/−39
- tests/ParserTests/regressions/extensions-paths-5054.check +0/−1
- tests/ParserTests/regressions/generics-sop.cabal +0/−128
- tests/ParserTests/regressions/generics-sop.expr +0/−789
- tests/ParserTests/regressions/generics-sop.format +0/−129
- tests/ParserTests/regressions/ghc-option-j.cabal +0/−18
- tests/ParserTests/regressions/ghc-option-j.check +0/−2
- tests/ParserTests/regressions/haddock-api-2.18.1-check.cabal +0/−147
- tests/ParserTests/regressions/haddock-api-2.18.1-check.check +0/−4
- tests/ParserTests/regressions/hasktorch.cabal +0/−558
- tests/ParserTests/regressions/hasktorch.expr +0/−9817
- tests/ParserTests/regressions/hasktorch.format +0/−565
- tests/ParserTests/regressions/hidden-main-lib.cabal +0/−11
- tests/ParserTests/regressions/hidden-main-lib.expr +0/−105
- tests/ParserTests/regressions/hidden-main-lib.format +0/−11
- tests/ParserTests/regressions/indentation.cabal +0/−18
- tests/ParserTests/regressions/indentation.expr +0/−106
- tests/ParserTests/regressions/indentation.format +0/−17
- tests/ParserTests/regressions/indentation2.cabal +0/−9
- tests/ParserTests/regressions/indentation2.expr +0/−96
- tests/ParserTests/regressions/indentation2.format +0/−10
- tests/ParserTests/regressions/indentation3.cabal +0/−11
- tests/ParserTests/regressions/indentation3.expr +0/−101
- tests/ParserTests/regressions/indentation3.format +0/−12
- tests/ParserTests/regressions/issue-5055.cabal +0/−25
- tests/ParserTests/regressions/issue-5055.expr +0/−246
- tests/ParserTests/regressions/issue-5055.format +0/−21
- tests/ParserTests/regressions/issue-5846.cabal +0/−11
- tests/ParserTests/regressions/issue-5846.expr +0/−170
- tests/ParserTests/regressions/issue-5846.format +0/−15
- tests/ParserTests/regressions/issue-6083-a.cabal +0/−19
- tests/ParserTests/regressions/issue-6083-a.expr +0/−333
- tests/ParserTests/regressions/issue-6083-a.format +0/−26
- tests/ParserTests/regressions/issue-6083-b.cabal +0/−19
- tests/ParserTests/regressions/issue-6083-b.expr +0/−340
- tests/ParserTests/regressions/issue-6083-b.format +0/−25
- tests/ParserTests/regressions/issue-6083-c.cabal +0/−11
- tests/ParserTests/regressions/issue-6083-c.expr +0/−181
- tests/ParserTests/regressions/issue-6083-c.format +0/−12
- tests/ParserTests/regressions/issue-6083-pkg-pkg.cabal +0/−9
- tests/ParserTests/regressions/issue-6083-pkg-pkg.expr +0/−116
- tests/ParserTests/regressions/issue-6083-pkg-pkg.format +0/−10
- tests/ParserTests/regressions/issue-6288-a.cabal +0/−14
- tests/ParserTests/regressions/issue-6288-a.check +0/−1
- tests/ParserTests/regressions/issue-6288-b.cabal +0/−13
- tests/ParserTests/regressions/issue-6288-b.check +0/−0
- tests/ParserTests/regressions/issue-6288-c.cabal +0/−14
- tests/ParserTests/regressions/issue-6288-c.check +0/−0
- tests/ParserTests/regressions/issue-6288-d.cabal +0/−13
- tests/ParserTests/regressions/issue-6288-d.check +0/−1
- tests/ParserTests/regressions/issue-6288-e.cabal +0/−13
- tests/ParserTests/regressions/issue-6288-e.check +0/−0
- tests/ParserTests/regressions/issue-6288-f.cabal +0/−13
- tests/ParserTests/regressions/issue-6288-f.check +0/−0
- tests/ParserTests/regressions/issue-774.cabal +0/−21
- tests/ParserTests/regressions/issue-774.check +0/−7
- tests/ParserTests/regressions/issue-774.expr +0/−108
- tests/ParserTests/regressions/issue-774.format +0/−22
- tests/ParserTests/regressions/jaeger-flamegraph.cabal +0/−70
- tests/ParserTests/regressions/jaeger-flamegraph.expr +0/−471
- tests/ParserTests/regressions/jaeger-flamegraph.format +0/−70
- tests/ParserTests/regressions/leading-comma-2.cabal +0/−33
- tests/ParserTests/regressions/leading-comma-2.expr +0/−167
- tests/ParserTests/regressions/leading-comma-2.format +0/−25
- tests/ParserTests/regressions/leading-comma.cabal +0/−19
- tests/ParserTests/regressions/leading-comma.expr +0/−160
- tests/ParserTests/regressions/leading-comma.format +0/−16
- tests/ParserTests/regressions/libpq1.cabal +0/−81
- tests/ParserTests/regressions/libpq1.expr +0/−688
- tests/ParserTests/regressions/libpq1.format +0/−74
- tests/ParserTests/regressions/libpq2.cabal +0/−81
- tests/ParserTests/regressions/libpq2.expr +0/−689
- tests/ParserTests/regressions/libpq2.format +0/−74
- tests/ParserTests/regressions/mixin-1.cabal +0/−11
- tests/ParserTests/regressions/mixin-1.expr +0/−147
- tests/ParserTests/regressions/mixin-1.format +0/−16
- tests/ParserTests/regressions/mixin-2.cabal +0/−13
- tests/ParserTests/regressions/mixin-2.expr +0/−147
- tests/ParserTests/regressions/mixin-2.format +0/−15
- tests/ParserTests/regressions/mixin-3.cabal +0/−12
- tests/ParserTests/regressions/mixin-3.expr +0/−132
- tests/ParserTests/regressions/mixin-3.format +0/−13
- tests/ParserTests/regressions/monad-param.cabal +0/−25
- tests/ParserTests/regressions/monad-param.expr +0/−142
- tests/ParserTests/regressions/monad-param.format +0/−31
- tests/ParserTests/regressions/multiple-libs-2.cabal +0/−17
- tests/ParserTests/regressions/multiple-libs-2.check +0/−6
- tests/ParserTests/regressions/multiple-libs-2.expr +0/−172
- tests/ParserTests/regressions/multiple-libs-2.format +0/−16
- tests/ParserTests/regressions/noVersion.cabal +0/−11
- tests/ParserTests/regressions/noVersion.expr +0/−105
- tests/ParserTests/regressions/noVersion.format +0/−10
- tests/ParserTests/regressions/nothing-unicode.cabal +0/−21
- tests/ParserTests/regressions/nothing-unicode.check +0/−6
- tests/ParserTests/regressions/nothing-unicode.expr +0/−170
- tests/ParserTests/regressions/nothing-unicode.format +0/−20
- tests/ParserTests/regressions/pre-1.6-glob.cabal +0/−17
- tests/ParserTests/regressions/pre-1.6-glob.check +0/−1
- tests/ParserTests/regressions/pre-2.4-globstar.cabal +0/−19
- tests/ParserTests/regressions/pre-2.4-globstar.check +0/−3
- tests/ParserTests/regressions/public-multilib-1.cabal +0/−17
- tests/ParserTests/regressions/public-multilib-1.check +0/−3
- tests/ParserTests/regressions/public-multilib-2.cabal +0/−14
- tests/ParserTests/regressions/public-multilib-2.check +0/−3
- tests/ParserTests/regressions/shake.cabal +0/−405
- tests/ParserTests/regressions/shake.expr +0/−2506
- tests/ParserTests/regressions/shake.format +0/−412
- tests/ParserTests/regressions/spdx-1.cabal +0/−9
- tests/ParserTests/regressions/spdx-1.expr +0/−95
- tests/ParserTests/regressions/spdx-1.format +0/−9
- tests/ParserTests/regressions/spdx-2.cabal +0/−9
- tests/ParserTests/regressions/spdx-2.expr +0/−96
- tests/ParserTests/regressions/spdx-2.format +0/−9
- tests/ParserTests/regressions/spdx-3.cabal +0/−9
- tests/ParserTests/regressions/spdx-3.expr +0/−96
- tests/ParserTests/regressions/spdx-3.format +0/−9
- tests/ParserTests/regressions/th-lift-instances.cabal +0/−76
- tests/ParserTests/regressions/th-lift-instances.expr +0/−570
- tests/ParserTests/regressions/th-lift-instances.format +0/−77
- tests/ParserTests/regressions/version-sets.cabal +0/−18
- tests/ParserTests/regressions/version-sets.expr +0/−283
- tests/ParserTests/regressions/version-sets.format +0/−19
- tests/ParserTests/regressions/wl-pprint-indef.cabal +0/−34
- tests/ParserTests/regressions/wl-pprint-indef.expr +0/−218
- tests/ParserTests/regressions/wl-pprint-indef.format +0/−37
- tests/ParserTests/warnings/bom.cabal +0/−7
- tests/ParserTests/warnings/bool.cabal +0/−12
- tests/ParserTests/warnings/deprecatedfield.cabal +0/−7
- tests/ParserTests/warnings/doubledash.cabal +0/−9
- tests/ParserTests/warnings/extratestmodule.cabal +0/−11
- tests/ParserTests/warnings/gluedop.cabal +0/−9
- tests/ParserTests/warnings/multiplesingular.cabal +0/−8
- tests/ParserTests/warnings/nbsp.cabal +0/−7
- tests/ParserTests/warnings/newsyntax.cabal +0/−6
- tests/ParserTests/warnings/oldsyntax.cabal +0/−6
- tests/ParserTests/warnings/operator.cabal +0/−7
- tests/ParserTests/warnings/specversion-a.cabal +0/−7
- tests/ParserTests/warnings/specversion-b.cabal +0/−7
- tests/ParserTests/warnings/specversion-c.cabal +0/−7
- tests/ParserTests/warnings/subsection.cabal +0/−9
- tests/ParserTests/warnings/tab.cabal +0/−12
- tests/ParserTests/warnings/trailingfield.cabal +0/−9
- tests/ParserTests/warnings/unknownfield.cabal +0/−8
- tests/ParserTests/warnings/unknownsection.cabal +0/−10
- tests/ParserTests/warnings/utf8.cabal +0/−8
- tests/ParserTests/warnings/versiontag.cabal +0/−7
- tests/ParserTests/warnings/wildcard.cabal +0/−7
- tests/README.md +0/−5
- tests/RPMVerCmp.hs +0/−103
- tests/Test/Laws.hs +0/−79
- tests/Test/QuickCheck/Utils.hs +0/−29
- tests/UnitTests.hs +0/−117
- tests/UnitTests/Distribution/CabalSpecVersion.hs +0/−42
- tests/UnitTests/Distribution/Compat/CreatePipe.hs +0/−56
- tests/UnitTests/Distribution/Compat/Graph.hs +0/−91
- tests/UnitTests/Distribution/Compat/Time.hs +0/−49
- tests/UnitTests/Distribution/Described.hs +0/−49
- tests/UnitTests/Distribution/PkgconfigVersion.hs +0/−21
- tests/UnitTests/Distribution/SPDX.hs +0/−180
- tests/UnitTests/Distribution/Simple/Glob.hs +0/−164
- tests/UnitTests/Distribution/Simple/Program/GHC.hs +0/−172
- tests/UnitTests/Distribution/Simple/Program/Internal.hs +0/−36
- tests/UnitTests/Distribution/Simple/Utils.hs +0/−110
- tests/UnitTests/Distribution/System.hs +0/−30
- tests/UnitTests/Distribution/Types/GenericPackageDescription.hs +0/−37
- tests/UnitTests/Distribution/Utils/CharSet.hs +0/−27
- tests/UnitTests/Distribution/Utils/Generic.hs +0/−71
- tests/UnitTests/Distribution/Utils/NubList.hs +0/−76
- tests/UnitTests/Distribution/Utils/ShortText.hs +0/−33
- tests/UnitTests/Distribution/Utils/Structured.hs +0/−30
- tests/UnitTests/Distribution/Version.hs +0/−656
- tests/UnitTests/Orphans.hs +0/−10
- tests/cbits/rpmvercmp.c +0/−141
- tests/custom-setup/CabalDoctestSetup.hs +0/−498
- tests/custom-setup/CustomSetupTests.hs +0/−8
- tests/custom-setup/IdrisSetup.hs +0/−388
- tests/hackage/check.sh +0/−25
- tests/hackage/download.sh +0/−19
- tests/hackage/unpack.sh +0/−16
- tests/misc/ghc-supported-languages.hs +0/−97
− Cabal-QuickCheck/src/Test/QuickCheck/GenericArbitrary.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeOperators #-}-module Test.QuickCheck.GenericArbitrary (- genericArbitrary,- GArbitrary,-) where--import GHC.Generics-import Test.QuickCheck--#if !MIN_VERSION_base(4,8,0)-import Control.Applicative (pure, (<$>), (<*>))-#endif---- Generic arbitary for non-recursive types-genericArbitrary :: (Generic a, GArbitrary (Rep a)) => Gen a-genericArbitrary = fmap to garbitrary--class GArbitrary f where- garbitrary :: Gen (f ())--class GArbitrarySum f where- garbitrarySum :: [Gen (f ())]--class GArbitraryProd f where- garbitraryProd :: Gen (f ())--instance (GArbitrarySum f, i ~ D) => GArbitrary (M1 i c f) where- garbitrary = fmap M1 (oneof garbitrarySum)--instance (GArbitraryProd f, i ~ C) => GArbitrarySum (M1 i c f) where- garbitrarySum = [fmap M1 garbitraryProd]--instance (GArbitrarySum f, GArbitrarySum g) => GArbitrarySum (f :+: g) where- garbitrarySum = map (fmap L1) garbitrarySum ++ map (fmap R1) garbitrarySum--instance (GArbitraryProd f, i ~ S) => GArbitraryProd (M1 i c f) where- garbitraryProd = fmap M1 garbitraryProd--instance GArbitraryProd U1 where- garbitraryProd = pure U1--instance (GArbitraryProd f, GArbitraryProd g) => GArbitraryProd (f :*: g) where- garbitraryProd = (:*:) <$> garbitraryProd <*> garbitraryProd--instance (Arbitrary a) => GArbitraryProd (K1 i a) where- garbitraryProd = fmap K1 arbitrary
− Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs
@@ -1,548 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Test.QuickCheck.Instances.Cabal () where--import Control.Applicative (liftA2)-import Data.Bits (shiftR)-import Data.Char (isAlphaNum, isDigit)-import Data.List (intercalate, isPrefixOf)-import Data.List.NonEmpty (NonEmpty (..))-import Distribution.Utils.Generic (lowercase)-import Test.QuickCheck--#if MIN_VERSION_base(4,8,0)-import Data.Bits (countLeadingZeros, finiteBitSize, shiftL)-#else-import Data.Bits (popCount)-#endif--import Distribution.CabalSpecVersion-import Distribution.Compat.NonEmptySet (NonEmptySet)-import Distribution.Compiler-import Distribution.FieldGrammar.Newtypes-import Distribution.ModuleName-import Distribution.Simple.Compiler (DebugInfoLevel (..), OptimisationLevel (..), PackageDB (..), ProfDetailLevel (..), knownProfDetailLevels)-import Distribution.Simple.Flag (Flag (..))-import Distribution.Simple.InstallDirs-import Distribution.Simple.Setup (HaddockTarget (..), TestShowDetails (..))-import Distribution.SPDX-import Distribution.System-import Distribution.Types.Dependency-import Distribution.Types.Flag (FlagAssignment, FlagName, mkFlagAssignment, mkFlagName, unFlagAssignment)-import Distribution.Types.IncludeRenaming-import Distribution.Types.LibraryName-import Distribution.Types.LibraryVisibility-import Distribution.Types.Mixin-import Distribution.Types.ModuleRenaming-import Distribution.Types.PackageId-import Distribution.Types.PackageName-import Distribution.Types.PackageVersionConstraint-import Distribution.Types.PkgconfigVersion-import Distribution.Types.PkgconfigVersionRange-import Distribution.Types.SourceRepo-import Distribution.Types.UnqualComponentName-import Distribution.Types.VersionRange.Internal-import Distribution.Utils.NubList-import Distribution.Verbosity-import Distribution.Version--import Test.QuickCheck.GenericArbitrary--import qualified Data.ByteString.Char8 as BS8-import qualified Distribution.Compat.NonEmptySet as NES--#if !MIN_VERSION_base(4,8,0)-import Control.Applicative (pure, (<$>), (<*>))-#endif------------------------------------------------------------------------------------ CabalSpecVersion----------------------------------------------------------------------------------instance Arbitrary CabalSpecVersion where- arbitrary = arbitraryBoundedEnum--instance Arbitrary SpecVersion where- arbitrary = fmap SpecVersion arbitrary------------------------------------------------------------------------------------ PackageName and PackageIdentifier----------------------------------------------------------------------------------instance Arbitrary PackageName where- arbitrary = mkPackageName . intercalate "-" <$> shortListOf1 2 nameComponent- where- nameComponent = shortListOf1 5 (elements packageChars)- `suchThat` (not . all isDigit)- packageChars = filter isAlphaNum ['\0'..'\127']--instance Arbitrary PackageIdentifier where- arbitrary = PackageIdentifier <$> arbitrary <*> arbitrary-- shrink (PackageIdentifier pn vr) = uncurry PackageIdentifier <$> shrink (pn, vr)------------------------------------------------------------------------------------ Version------------------------------------------------------------------------------------ | Does *NOT* generate 'nullVersion'-instance Arbitrary Version where- arbitrary = do- branch <- smallListOf1 $- frequency [(3, return 0)- ,(3, return 1)- ,(2, return 2)- ,(2, return 3)- ,(1, return 0xfffd)- ,(1, return 0xfffe) -- max fitting into packed W64- ,(1, return 0xffff)- ,(1, return 999999998)- ,(1, return 999999999)- ,(1, return 0x10000)]- return (mkVersion branch)- where- smallListOf1 = scale (\n -> min 6 (n `div` 3)) . listOf1-- shrink ver = [ mkVersion ns | ns <- shrink (versionNumbers ver)- , not (null ns) ]--instance Arbitrary VersionRange where- arbitrary = sized $ \n -> chooseInt (0, n) >>= verRangeExp . intSqrt- where- verRangeExp n- | n > 0 = oneof- [ recurse unionVersionRanges n- , recurse intersectVersionRanges n- ]- | otherwise = oneof- [ return anyVersion- , fmap thisVersion arbitrary- , fmap laterVersion arbitrary- , fmap orLaterVersion arbitrary- , fmap orLaterVersion' arbitrary- , fmap earlierVersion arbitrary- , fmap orEarlierVersion arbitrary- , fmap orEarlierVersion' arbitrary- , fmap withinVersion arbitraryV- , fmap majorBoundVersion arbitrary- ]-- recurse mk n = do- k <- chooseInt (0, n - 1)- liftA2 mk (verRangeExp k) (verRangeExp (n - k - 1))-- arbitraryV :: Gen Version- arbitraryV = arbitrary `suchThat` \v -> all (< 999999999) (versionNumbers v)-- orLaterVersion' v =- unionVersionRanges (LaterVersion v) (ThisVersion v)- orEarlierVersion' v =- unionVersionRanges (EarlierVersion v) (ThisVersion v)-- shrink (ThisVersion v) = map ThisVersion (shrink v)- shrink (LaterVersion v) = map LaterVersion (shrink v)- shrink (EarlierVersion v) = map EarlierVersion (shrink v)- shrink (OrLaterVersion v) = LaterVersion v : map OrLaterVersion (shrink v)- shrink (OrEarlierVersion v) = EarlierVersion v : map OrEarlierVersion (shrink v)- shrink (MajorBoundVersion v) = map MajorBoundVersion (shrink v)- shrink (UnionVersionRanges a b) = a : b : map (uncurry UnionVersionRanges) (shrink (a, b))- shrink (IntersectVersionRanges a b) = a : b : map (uncurry IntersectVersionRanges) (shrink (a, b))---- | 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'.-----instance Arbitrary VersionIntervals where- arbitrary = fmap mkVersionIntervals' arbitrary- where- mkVersionIntervals' :: [(Version, Bound)] -> VersionIntervals- mkVersionIntervals' = mkVersionIntervals . go version0- where- go :: Version -> [(Version, Bound)] -> [VersionInterval]- go _ [] = []- go v [(lv, lb)] =- [(LowerBound (addVersion lv v) lb, NoUpperBound)]- go v ((lv, lb) : (uv, ub) : rest) =- (LowerBound lv' lb, UpperBound uv' ub) : go uv' rest- where- lv' = addVersion v lv- uv' = addVersion lv' uv-- addVersion :: Version -> Version -> Version- addVersion xs ys = mkVersion $ z (versionNumbers xs) (versionNumbers ys)- where- z [] ys' = ys'- z xs' [] = xs'- z (x : xs') (y : ys') = x + y : z xs' ys'--instance Arbitrary Bound where- arbitrary = elements [ExclusiveBound, InclusiveBound]------------------------------------------------------------------------------------ Backpack----------------------------------------------------------------------------------instance Arbitrary Mixin where- arbitrary = normaliseMixin <$> genericArbitrary- shrink = fmap normaliseMixin . genericShrink--instance Arbitrary IncludeRenaming where- arbitrary = genericArbitrary- shrink = genericShrink--instance Arbitrary ModuleRenaming where- arbitrary = genericArbitrary- shrink = genericShrink----------------------------------------------------------------------------------------------------------------------------------------------------------------------instance Arbitrary LibraryVisibility where- arbitrary = elements [LibraryVisibilityPrivate, LibraryVisibilityPublic]-- shrink LibraryVisibilityPublic = [LibraryVisibilityPrivate]- shrink LibraryVisibilityPrivate = []------------------------------------------------------------------------------------ ModuleName----------------------------------------------------------------------------------instance Arbitrary ModuleName where- arbitrary = fromString . intercalate "." <$> shortListOf1 4 comp where- comp = (:) <$> elements upper <*> shortListOf1 10 (elements moduleChar)- upper = ['A'..'Z']- moduleChar = [ c | c <- ['\0' .. '\255'], isAlphaNum c || c `elem` "_'" ]------------------------------------------------------------------------------------ Dependency----------------------------------------------------------------------------------instance Arbitrary Dependency where- arbitrary = mkDependency- <$> arbitrary- <*> arbitrary- <*> (arbitrary `suchThat` const True) -- should be (not . null)-- shrink (Dependency pn vr lb) =- [ mkDependency pn' vr' lb'- | (pn', vr', lb') <- shrink (pn, vr, lb)- ]------------------------------------------------------------------------------------ PackageVersionConstraint----------------------------------------------------------------------------------instance Arbitrary PackageVersionConstraint where- arbitrary = PackageVersionConstraint- <$> arbitrary- <*> arbitrary-- shrink (PackageVersionConstraint pn vr) =- [ PackageVersionConstraint pn' vr'- | (pn', vr') <- shrink (pn, vr)- ]------------------------------------------------------------------------------------ System----------------------------------------------------------------------------------instance Arbitrary OS where- arbitrary = elements knownOSs--instance Arbitrary Arch where- arbitrary = elements knownArches--instance Arbitrary Platform where- arbitrary = Platform <$> arbitrary <*> arbitrary------------------------------------------------------------------------------------ Various names----------------------------------------------------------------------------------instance Arbitrary UnqualComponentName where- -- same rules as package names- arbitrary = packageNameToUnqualComponentName <$> arbitrary--instance Arbitrary LibraryName where- arbitrary = oneof- [ LSubLibName <$> arbitrary- , pure LMainLibName- ]-- shrink (LSubLibName _) = [LMainLibName]- shrink _ = []------------------------------------------------------------------------------------ option flags----------------------------------------------------------------------------------instance Arbitrary a => Arbitrary (Flag a) where- arbitrary = arbitrary1-- shrink NoFlag = []- shrink (Flag x) = NoFlag : [ Flag x' | x' <- shrink x ]--instance Arbitrary1 Flag where- liftArbitrary genA = sized $ \sz ->- if sz <= 0- then pure NoFlag- else frequency [ (1, pure NoFlag)- , (3, Flag <$> genA) ]------------------------------------------------------------------------------------ GPD flags----------------------------------------------------------------------------------instance Arbitrary FlagName where- arbitrary = mkFlagName <$> frequency- [ (20, flagident)- -- special nasty cases- , (1, pure "none")- , (1, pure "any")- ]- where- flagident = lowercase <$> shortListOf1 5 (elements flagChars)- `suchThat` (("-" /=) . take 1)- flagChars = "-_" ++ ['a'..'z']--instance Arbitrary FlagAssignment where- arbitrary = mkFlagAssignment <$> arbitrary- shrink x = mkFlagAssignment <$> shrink (unFlagAssignment x)------------------------------------------------------------------------------------ Verbosity----------------------------------------------------------------------------------instance Arbitrary Verbosity where- arbitrary = do- v <- elements [minBound..maxBound]- -- verbose markoutput is left out on purpose- flags <- listOf $ elements- [ verboseCallSite- , verboseCallStack- , verboseNoWrap- , verboseTimestamp- , verboseStderr- ]- return (foldr ($) v flags)------------------------------------------------------------------------------------ SourceRepo----------------------------------------------------------------------------------instance Arbitrary RepoType where- arbitrary = elements (KnownRepoType <$> knownRepoTypes)--instance Arbitrary RepoKind where- arbitrary = elements [RepoHead, RepoThis]------------------------------------------------------------------------------------ SPDX----------------------------------------------------------------------------------instance Arbitrary LicenseId where- arbitrary = elements $ licenseIdList currentLicenseListVersion--instance Arbitrary LicenseExceptionId where- arbitrary = elements $ licenseExceptionIdList currentLicenseListVersion--currentLicenseListVersion :: LicenseListVersion-currentLicenseListVersion = cabalSpecVersionToSPDXListVersion cabalSpecLatest--instance Arbitrary LicenseRef where- arbitrary = mkLicenseRef' <$> ids' <*> ids- where- ids = listOf1 $ elements $ ['a'..'z'] ++ ['A' .. 'Z'] ++ ['0'..'9'] ++ "_-"- ids' = oneof [ pure Nothing, Just <$> ids ]--instance Arbitrary SimpleLicenseExpression where- arbitrary = oneof- [ ELicenseId <$> arbitrary- , ELicenseIdPlus <$> arbitrary- , ELicenseRef <$> arbitrary- ]--instance Arbitrary LicenseExpression where- arbitrary = sized arb- where- arb n- | n <= 0 = ELicense <$> arbitrary <*> pure Nothing- | otherwise = oneof- [ ELicense <$> arbitrary <*> arbitrary- , EAnd <$> arbA <*> arbB- , EOr <$> arbA <*> arbB- ]- where- m = n `div` 2- arbA = arb m- arbB = arb (n - m)-- shrink (EAnd a b) = a : b : map (uncurry EAnd) (shrink (a, b))- shrink (EOr a b) = a : b : map (uncurry EOr) (shrink (a, b))- shrink _ = []------------------------------------------------------------------------------------ Compiler----------------------------------------------------------------------------------instance Arbitrary CompilerFlavor where- arbitrary = elements knownCompilerFlavors--instance Arbitrary CompilerId where- arbitrary = genericArbitrary- shrink = genericShrink--instance Arbitrary ProfDetailLevel where- arbitrary = elements [ d | (_,_,d) <- knownProfDetailLevels ]--instance Arbitrary OptimisationLevel where- arbitrary = elements [minBound..maxBound]--instance Arbitrary DebugInfoLevel where- arbitrary = elements [minBound..maxBound]------------------------------------------------------------------------------------ NonEmptySet----------------------------------------------------------------------------------instance (Arbitrary a, Ord a) => Arbitrary (NonEmptySet a) where- arbitrary = mk <$> arbitrary <*> arbitrary where- mk x xs = NES.fromNonEmpty (x :| xs)-- shrink nes = case NES.toNonEmpty nes of- x :| xs -> map mk (shrink (x, xs))- where- mk (x,xs) = NES.fromNonEmpty (x :| xs)------------------------------------------------------------------------------------ NubList----------------------------------------------------------------------------------instance (Arbitrary a, Ord a) => Arbitrary (NubList a) where- arbitrary = toNubList <$> arbitrary- shrink xs = [ toNubList [] | (not . null) (fromNubList xs) ]- -- try empty, otherwise don't shrink as it can loop------------------------------------------------------------------------------------ InstallDirs----------------------------------------------------------------------------------instance Arbitrary a => Arbitrary (InstallDirs a) where- arbitrary = InstallDirs- <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 4- <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 8- <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 12- <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 16--instance Arbitrary PathTemplate where- arbitrary = toPathTemplate <$> arbitraryShortToken- shrink t = [ toPathTemplate s- | s <- shrink (fromPathTemplate t)- , not (null s) ]------------------------------------------------------------------------------------ Pkgconfig----------------------------------------------------------------------------------instance Arbitrary PkgconfigVersion where- arbitrary = PkgconfigVersion . BS8.pack . dropDash . concat <$> listOf1 elems where- elems = frequency- [ (2, pure ".")- , (1, pure "-")- , (5, listOf1 $ elements ['0' .. '9'])- , (1, listOf1 $ elements ['A' .. 'Z'])- , (1, listOf1 $ elements ['a' .. 'z'])- ]-- -- disallow versions starting with dash- dropDash = notEmpty . dropWhile (== '-')- notEmpty x- | null x = "0"- | otherwise = x--instance Arbitrary PkgconfigVersionRange where- arbitrary = sized $ \n -> chooseInt (0, n) >>= verRangeExp . intSqrt- where- verRangeExp n- | n > 0 = oneof- [ recurse PcUnionVersionRanges n- , recurse PcIntersectVersionRanges n- ]- | otherwise = oneof- [ return PcAnyVersion- , fmap PcThisVersion arbitrary- , fmap PcLaterVersion arbitrary- , fmap PcOrLaterVersion arbitrary- , fmap orLaterVersion' arbitrary- , fmap PcEarlierVersion arbitrary- , fmap PcOrEarlierVersion arbitrary- , fmap orEarlierVersion' arbitrary- ]-- recurse mk n = do- k <- chooseInt (0, n - 1)- liftA2 mk (verRangeExp k) (verRangeExp (n - k - 1))-- orLaterVersion' v =- PcUnionVersionRanges (PcLaterVersion v) (PcThisVersion v)- orEarlierVersion' v =- PcUnionVersionRanges (PcEarlierVersion v) (PcThisVersion v)------------------------------------------------------------------------------------ Setup----------------------------------------------------------------------------------instance Arbitrary HaddockTarget where- arbitrary = elements [ForHackage, ForDevelopment]--instance Arbitrary TestShowDetails where- arbitrary = arbitraryBoundedEnum------------------------------------------------------------------------------------ PackageDB----------------------------------------------------------------------------------instance Arbitrary PackageDB where- arbitrary = oneof [ pure GlobalPackageDB- , pure UserPackageDB- , SpecificPackageDB <$> arbitraryShortToken- ]------------------------------------------------------------------------------------- Helpers----------------------------------------------------------------------------------shortListOf1 :: Int -> Gen a -> Gen [a]-shortListOf1 bound gen = sized $ \n -> do- k <- choose (1, 1 `max` ((n `div` 2) `min` bound))- vectorOf k gen--arbitraryShortToken :: Gen String-arbitraryShortToken =- shortListOf1 5 (choose ('#', '~')) `suchThat` (not . ("[]" `isPrefixOf`))---- |-intSqrt :: Int -> Int-intSqrt 0 = 0-intSqrt 1 = 1-intSqrt n = case compare n 0 of- LT -> 0 -- whatever- EQ -> 0- GT -> iter (iter guess) -- two iterations give good results- where- iter :: Int -> Int- iter 0 = 0- iter x = shiftR (x + n `div` x) 1-- guess :: Int-#if MIN_VERSION_base(4,8,0)- guess = shiftR n (shiftL (finiteBitSize n - countLeadingZeros n) 1)-#else- guess = shiftR n (shiftR (popCount n) 1)-#endif
− Cabal-described/src/Distribution/Described.hs
@@ -1,577 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-module Distribution.Described (- Described (..),- describeDoc,- -- * Regular expressions- GrammarRegex (..),- reEps,- reChar,- reChars,- reMunchCS,- reMunch1CS,- -- * Variables- reVar0,- reVar1,- -- * Special expressions- reDot,- reComma,- reSpacedComma,- reHsString,- reUnqualComponent,- -- *- describeFlagAssignmentNonEmpty,- -- * Lists- reSpacedList,- reCommaList,- reCommaNonEmpty,- reOptCommaList,- -- * Character Sets- csChar,- csAlpha,- csAlphaNum,- csUpper,- csNotSpace,- csNotSpaceOrComma,- -- * tasty- testDescribed,- ) where--import Prelude- (Bool (..), Char, Either (..), Enum (..), Eq (..), Ord (..), Show (..), String, elem, fmap, foldr, id, map, maybe, otherwise, return, undefined, ($),- (.))--import Data.Functor.Identity (Identity (..))-import Data.Maybe (fromMaybe)-import Data.Proxy (Proxy (..))-import Data.String (IsString (..))-import Data.Typeable (Typeable, typeOf)-import Data.Void (Void, vacuous)-import Test.QuickCheck (Arbitrary (..), Property, counterexample)-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.QuickCheck (testProperty)--import Distribution.Compat.Semigroup (Semigroup (..))-import Distribution.Parsec (Parsec, eitherParsec)-import Distribution.Pretty (Pretty, prettyShow)--import qualified Distribution.Utils.CharSet as CS-import qualified RERE as RE-import qualified RERE.CharSet as RE-import qualified Text.PrettyPrint as PP--import Distribution.Utils.GrammarRegex---- Types-import Distribution.Compat.Newtype-import Distribution.Compiler (CompilerFlavor, CompilerId, knownCompilerFlavors)-import Distribution.FieldGrammar.Newtypes-import Distribution.ModuleName (ModuleName)-import Distribution.System (Arch, OS, knownArches, knownOSs)-import Distribution.Types.AbiDependency (AbiDependency)-import Distribution.Types.AbiHash (AbiHash)-import Distribution.Types.BenchmarkType (BenchmarkType)-import Distribution.Types.BuildType (BuildType)-import Distribution.Types.Dependency (Dependency)-import Distribution.Types.ExecutableScope (ExecutableScope)-import Distribution.Types.ExeDependency (ExeDependency)-import Distribution.Types.ExposedModule (ExposedModule)-import Distribution.Types.Flag (FlagAssignment, FlagName)-import Distribution.Types.ForeignLib (LibVersionInfo)-import Distribution.Types.ForeignLibOption (ForeignLibOption)-import Distribution.Types.ForeignLibType (ForeignLibType)-import Distribution.Types.IncludeRenaming (IncludeRenaming)-import Distribution.Types.LegacyExeDependency (LegacyExeDependency)-import Distribution.Types.LibraryVisibility (LibraryVisibility)-import Distribution.Types.Mixin (Mixin)-import Distribution.Types.ModuleReexport (ModuleReexport)-import Distribution.Types.ModuleRenaming (ModuleRenaming)-import Distribution.Types.MungedPackageName (MungedPackageName)-import Distribution.Types.PackageId (PackageIdentifier)-import Distribution.Types.PackageName (PackageName)-import Distribution.Types.PackageVersionConstraint (PackageVersionConstraint)-import Distribution.Types.PkgconfigDependency (PkgconfigDependency)-import Distribution.Types.SourceRepo (RepoType)-import Distribution.Types.TestType (TestType)-import Distribution.Types.UnitId (UnitId)-import Distribution.Types.UnqualComponentName (UnqualComponentName)-import Distribution.Verbosity (Verbosity)-import Distribution.Version (Version, VersionRange)-import Language.Haskell.Extension (Extension, Language)---- | Class describing the pretty/parsec format of a.-class (Pretty a, Parsec a) => Described a where- -- | A pretty document of "regex" describing the field format- describe :: proxy a -> GrammarRegex void---- | Pretty-print description.------ >>> describeDoc ([] :: [Bool])--- \left\{ \mathop{\mathord{``}\mathtt{True}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{False}\mathord{"}} \right\}----describeDoc :: Described a => proxy a -> PP.Doc-describeDoc p = regexDoc (describe p)--instance Described Bool where- describe _ = REUnion ["True", "False"]--instance Described a => Described (Identity a) where- describe _ = describe ([] :: [a])------------------------------------------------------------------------------------ Lists---------------------------------------------------------------------------------reSpacedList :: GrammarRegex a -> GrammarRegex a-reSpacedList = REMunch RESpaces1--reCommaList :: GrammarRegex a -> GrammarRegex a-reCommaList = RECommaList--reCommaNonEmpty :: GrammarRegex a -> GrammarRegex a-reCommaNonEmpty = RECommaNonEmpty--reOptCommaList :: GrammarRegex a -> GrammarRegex a-reOptCommaList = REOptCommaList------------------------------------------------------------------------------------ Specific grammars----------------------------------------------------------------------------------reHsString :: GrammarRegex a-reHsString = RENamed "hs-string" impl where- impl = reChar '"' <> REMunch reEps (REUnion [strChar, escChar]) <> reChar '"'- strChar = RECharSet $ CS.difference CS.universe (CS.fromList "\"\\")-- escChar = REUnion- [ "\\&"- , "\\\\"- , REUnion ["\\n", RENamed "escapes" "\\n"] -- TODO- , "\\" <> RECharSet "0123456789"- , "\\o" <> RECharSet "01234567"- , "\\x" <> RECharSet "0123456789abcdefABCDEF"- , REUnion ["\\^@", RENamed "control" "\\^@"] -- TODO- , REUnion ["\\NUL", RENamed "ascii" "\\NUL"] -- TODO- ]--reUnqualComponent :: GrammarRegex a-reUnqualComponent = RENamed "unqual-name" $- REMunch1 (reChar '-') component- where- component- = REMunch reEps (RECharSet csAlphaNum)- -- currently the parser accepts "csAlphaNum `difference` "0123456789"- -- which is larger set than CS.alpha- --- -- Hackage rejects non ANSI names, so it's not so relevant.- <> RECharSet CS.alpha- <> REMunch reEps (RECharSet csAlphaNum)--reDot :: GrammarRegex a-reDot = reChar '.'--reComma :: GrammarRegex a-reComma = reChar ','--reSpacedComma :: GrammarRegex a-reSpacedComma = RESpaces <> reComma <> RESpaces------------------------------------------------------------------------------------ Character sets----------------------------------------------------------------------------------csChar :: Char -> CS.CharSet-csChar = CS.singleton--csAlpha :: CS.CharSet-csAlpha = CS.alpha--csAlphaNum :: CS.CharSet-csAlphaNum = CS.alphanum--csUpper :: CS.CharSet-csUpper = CS.upper--csNotSpace :: CS.CharSet-csNotSpace = CS.difference CS.universe $ CS.singleton ' '--csNotSpaceOrComma :: CS.CharSet-csNotSpaceOrComma = CS.difference csNotSpace $ CS.singleton ','------------------------------------------------------------------------------------ Special----------------------------------------------------------------------------------describeFlagAssignmentNonEmpty :: GrammarRegex void-describeFlagAssignmentNonEmpty = REMunch1 RESpaces1 $- REUnion [fromString "+", fromString "-"] <> describe (Proxy :: Proxy FlagName)------------------------------------------------------------------------------------ Conversion----------------------------------------------------------------------------------convert :: GrammarRegex Void -> RE.RE Void-convert = go id . vacuous where- go :: Ord b => (a -> b) -> GrammarRegex a -> RE.RE b- go f (REAppend rs) = foldr (\r acc -> go f r <> acc) RE.Eps rs- go f (REUnion rs) = foldr (\r acc -> go f r RE.\/ acc) RE.Null rs- go _ (RECharSet cs) = RE.Ch (convertCS cs)- go _ (REString str) = RE.string_ str-- go f (REMunch sep r) = RE.Eps RE.\/ r' <> RE.star_ (sep' <> r') where- sep' = go f sep- r' = go f r- go f (REMunch1 sep r) = r' <> RE.star_ (sep' <> r') where- sep' = go f sep- r' = go f r- go f (REMunchR n sep r)- | n <= 0 = RE.Eps- | otherwise = RE.Eps RE.\/ r' <> go' (pred n)- where- sep' = go f sep- r' = go f r-- go' m | m <= 0 = RE.Eps- | otherwise = RE.Eps RE.\/ sep' <> r' <> go' (pred m)-- go f (REOpt r) = RE.Eps RE.\/ go f r-- go f (REVar a) = RE.Var (f a)- go f (RENamed _ r) = go f r- go f (RERec n r) = RE.fix_ (fromString n)- (go (maybe RE.B (RE.F . f)) r)-- go _ RESpaces = RE.Eps RE.\/ RE.ch_ ' ' RE.\/ " " RE.\/ "\n"- go _ RESpaces1 = RE.ch_ ' ' RE.\/ " " RE.\/ "\n"-- go f (RECommaList r) = go f (expandedCommaList r)- go f (RECommaNonEmpty r)= go f (expandedCommaNonEmpty r)- go f (REOptCommaList r) = go f (expandedOptCommaList r)-- go _ RETodo = RE.Null--expandedCommaList :: GrammarRegex a -> GrammarRegex a-expandedCommaList = REUnion . expandedCommaList'--expandedCommaNonEmpty :: GrammarRegex a -> GrammarRegex a-expandedCommaNonEmpty r = REUnion- [ REMunch1 reSpacedComma r- , reComma <> RESpaces <> REMunch1 reSpacedComma r- , REMunch1 reSpacedComma r <> RESpaces <> reComma- ]--expandedCommaList' :: GrammarRegex a -> [GrammarRegex a]-expandedCommaList' r =- [ REMunch reSpacedComma r- , reComma <> RESpaces <> REMunch1 reSpacedComma r- , REMunch1 reSpacedComma r <> RESpaces <> reComma- ]--expandedOptCommaList :: GrammarRegex a -> GrammarRegex a-expandedOptCommaList r = REUnion $ reSpacedList r : expandedCommaList' r--convertCS :: CS.CharSet -> RE.CharSet-convertCS = RE.fromIntervalList . CS.toIntervalList------------------------------------------------------------------------------------ tasty----------------------------------------------------------------------------------testDescribed- :: forall a. (Arbitrary a, Described a, Typeable a, Eq a, Show a)- => Proxy a- -> TestTree-testDescribed _ = testGroup name- [ testProperty "parsec" propParsec- , testProperty "pretty" propPretty- , testProperty "roundtrip" propRoundtrip- ]- where- name = show (typeOf (undefined :: a))-- propParsec :: Ex a -> Property- propParsec (Example str) = counterexample (show res) $ case res of- Right _ -> True- Left _ -> False- where- res :: Either String a- res = eitherParsec str-- rr :: RE.RE Void- rr = convert $ describe (Proxy :: Proxy a)-- propPretty :: a -> Property- propPretty x = counterexample str $ RE.matchR rr str- where- str = prettyShow x-- propRoundtrip :: a -> Property- propRoundtrip x = counterexample (show (res, str)) $ case res of- Right y -> x == y- Left _ -> False- where- str = prettyShow x- res = eitherParsec str--newtype Ex a = Example String- deriving (Show)--instance Described a => Arbitrary (Ex a) where- arbitrary- = fmap Example- $ fromMaybe (return "")- $ RE.generate 10 5- $ convert $ describe (Proxy :: Proxy a)-- shrink (Example s)- | '\n' `elem` s = [ Example $ map (\c -> if c == '\n' then ' ' else c) s ]- | otherwise = []------------------------------------------------------------------------------------ Instances----------------------------------------------------------------------------------instance Described AbiDependency where- describe _ =- describe (Proxy :: Proxy UnitId) <>- reChar '=' <>- describe (Proxy :: Proxy AbiHash)--instance Described AbiHash where- describe _ = reMunchCS csAlphaNum--instance Described Arch where- describe _ = REUnion- [ fromString (prettyShow arch)- | arch <- knownArches- ]--instance Described BenchmarkType where- describe _ = "exitcode-stdio-1.0"--instance Described BuildType where- describe _ = REUnion ["Simple","Configure","Custom","Make","Default"]--instance Described CompilerFlavor where- describe _ = REUnion- [ fromString (prettyShow c)- | c <- knownCompilerFlavors- ]--instance Described CompilerId where- describe _ =- describe (Proxy :: Proxy CompilerFlavor)- <> fromString "-"- <> describe (Proxy :: Proxy Version)--instance Described Dependency where- describe _ = REAppend- [ RENamed "pkg-name" (describe (Proxy :: Proxy PackageName))- , REOpt $- reChar ':'- <> REUnion- [ reUnqualComponent- , REAppend- [ reChar '{'- , RESpaces- -- no leading or trailing comma- , REMunch1 reSpacedComma reUnqualComponent- , RESpaces- , reChar '}'- ]- ]-- , REOpt $ RESpaces <> vr- ]- where- vr = RENamed "version-range" (describe (Proxy :: Proxy VersionRange))--instance Described ExecutableScope where- describe _ = REUnion ["public","private"]--instance Described ExeDependency where- describe _ = RETodo--instance Described ExposedModule where- describe _ = RETodo--instance Described Extension where- describe _ = RETodo--instance Described FlagAssignment where- describe _ = REMunch RESpaces1 $- REUnion [fromString "+", fromString "-"] <> describe (Proxy :: Proxy FlagName)--instance Described FlagName where- describe _ = lead <> rest where- lead = RECharSet $ csAlphaNum <> fromString "_"- rest = reMunchCS $ csAlphaNum <> fromString "_-"--instance Described ForeignLibOption where- describe _ = "standalone"--instance Described ForeignLibType where- describe _ = REUnion ["native-shared","native-static"]--instance Described IncludeRenaming where- describe _ = mr <> REOpt (RESpaces <> "requires" <> RESpaces1 <> mr)- where- mr = describe (Proxy :: Proxy ModuleRenaming)--instance Described Language where- describe _ = REUnion ["Haskell98", "Haskell2010"]--instance Described LegacyExeDependency where- describe _ = RETodo--instance Described LibraryVisibility where- describe _ = REUnion ["public","private"]--instance Described LibVersionInfo where- describe _ = reDigits <> REOpt (reChar ':' <> reDigits <> REOpt (reChar ':' <> reDigits)) where- reDigits = reChars ['0'..'9']--instance Described Mixin where- describe _ =- RENamed "package-name" (describe (Proxy :: Proxy PackageName)) <>- REOpt (reChar ':' <> RENamed "library-name" (describe (Proxy :: Proxy UnqualComponentName))) <>- REOpt (RESpaces1 <> describe (Proxy :: Proxy IncludeRenaming))--instance Described ModuleName where- describe _ = REMunch1 (reChar '.') component where- component = RECharSet csUpper <> REMunch reEps (REUnion [RECharSet csAlphaNum, RECharSet (fromString "_'")])--instance Described ModuleReexport where- describe _ = RETodo--instance Described ModuleRenaming where- describe _ = REUnion- [ reEps- , "hiding" <> RESpaces <> bp (REMunch reSpacedComma mn)- , bp (REMunch reSpacedComma entry)- ]- where- bp r = "(" <> RESpaces <> r <> RESpaces <> ")"- mn = RENamed "module-name" $ describe (Proxy :: Proxy ModuleName)-- entry = mn <> REOpt (RESpaces1 <> "as" <> RESpaces1 <> mn)--instance Described MungedPackageName where- describe _ = RETodo--instance Described OS where- describe _ = REUnion- [ fromString (prettyShow os)- | os <- knownOSs- ]--instance Described PackageIdentifier where- describe _ = describe (Proxy :: Proxy PackageName) <> fromString "-" <> describe (Proxy :: Proxy Version)--instance Described PackageName where- describe _ = reUnqualComponent--instance Described PackageVersionConstraint where- describe _ = describe (Proxy :: Proxy PackageName) <> REUnion- [ fromString "-" <> describe (Proxy :: Proxy Version)- , RESpaces <> describe (Proxy :: Proxy VersionRange)- ]--instance Described PkgconfigDependency where- describe _ = RETodo--instance Described RepoType where- describe _ = reMunch1CS $ csAlphaNum <> csChar '_' <> csChar '-'--instance Described TestType where- describe _ = REUnion ["exitcode-stdio-1.0", "detailed-0.9"]--instance Described Verbosity where- describe _ = REUnion- [ REUnion ["0", "1", "2", "3"]- , REUnion ["silent", "normal", "verbose", "debug", "deafening"]- <> REMunch reEps (RESpaces <> "+" <>- -- markoutput is left out on purpose- REUnion ["callsite", "callstack", "nowrap", "timestamp", "stderr", "stdout" ])- ]--instance Described Version where- describe _ = REMunch1 reDot reDigits where- reDigits = REUnion- [ reChar '0'- , reChars ['1'..'9'] <> REMunchR 8 reEps (reChars ['0'..'9'])- ]--instance Described VersionRange where- describe _ = RERec "version-range" $ REUnion- [ "==" <> RESpaces <> ver- , ">" <> RESpaces <> ver- , "<" <> RESpaces <> ver- , "<=" <> RESpaces <> ver- , ">=" <> RESpaces <> ver- , "^>=" <> RESpaces <> ver-- -- ==0.1.*- , "==" <> RESpaces <> wildVer-- , reVar0 <> RESpaces <> "||" <> RESpaces <> reVar0- , reVar0 <> RESpaces <> "&&" <> RESpaces <> reVar0- , "(" <> RESpaces <> reVar0 <> RESpaces <> ")"-- -- == { 0.1.2 }- -- silly haddock: ^>= { 0.1.2, 3.4.5 }- , "==" <> RESpaces <> verSet- , "^>=" <> RESpaces <> verSet- ]- where- ver' = describe (Proxy :: Proxy Version)- ver = RENamed "version" ver'- wildVer = ver' <> ".*"- verSet = "{" <> RESpaces <> REMunch1 reSpacedComma ver <> RESpaces <> "}"--instance Described UnitId where- describe _ = reMunch1CS $ csAlphaNum <> csChar '-' <> csChar '_' <> csChar '.' <> csChar '+'--instance Described UnqualComponentName where- describe _ = reUnqualComponent------------------------------------------------------------------------------------ Instances: Newtypes----------------------------------------------------------------------------------class Sep sep => DescribeSep sep where- describeSep :: Proxy sep -> GrammarRegex a -> GrammarRegex a--instance DescribeSep CommaVCat where describeSep _ = reCommaList-instance DescribeSep CommaFSep where describeSep _ = reCommaList-instance DescribeSep VCat where describeSep _ = reCommaList-instance DescribeSep FSep where describeSep _ = reOptCommaList-instance DescribeSep NoCommaFSep where describeSep _ = reSpacedList--instance (Newtype a b, DescribeSep sep, Described b) => Described (List sep b a) where- describe _ = describeSep (Proxy :: Proxy sep) (describe (Proxy :: Proxy b))--instance (Newtype a b, Ord a, DescribeSep sep, Described b) => Described (Set' sep b a) where- describe _ = describeSep (Proxy :: Proxy sep) (describe (Proxy :: Proxy b))--instance Described Token where- describe _ = REUnion [reHsString, reMunch1CS csNotSpaceOrComma]--instance Described Token' where- describe _ = REUnion [reHsString, reMunch1CS csNotSpace]--instance Described a => Described (MQuoted a) where- -- TODO: this is simplification- describe _ = describe ([] :: [a])--instance Described SpecVersion where- describe _ = "3.4" -- :)--instance Described SpecLicense where- describe _ = RETodo--instance Described TestedWith where- describe _ = RETodo--instance Described FilePathNT where- describe _ = describe ([] :: [Token])
− Cabal-described/src/Distribution/Utils/CharSet.hs
@@ -1,242 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}--- | Sets of characters.------ Using this is more efficint than 'RE.Type.Alt':ng individual characters.-module Distribution.Utils.CharSet (- -- * Set of characters- CharSet,- -- * Construction- empty,- universe,- singleton,- insert,- union,- intersection,- complement,- difference,- -- * Query- size,- null,- member,- -- * Conversions- fromList,- toList,- fromIntervalList,- toIntervalList,- -- * Special lists- alpha,- alphanum,- upper,- ) where--import Data.Char (chr, isAlpha, isAlphaNum, isUpper, ord)-import Data.List (foldl', sortBy)-import Data.Monoid (Monoid (..))-import Data.String (IsString (..))-import Distribution.Compat.Semigroup (Semigroup (..))-import Prelude- (Bool (..), Bounded (..), Char, Enum (..), Eq (..), Int, Maybe (..), Num (..), Ord (..), Show (..), String, concatMap, flip, fst, otherwise, showParen,- showString, uncurry, ($), (.))--#if MIN_VERSION_containers(0,5,0)-import qualified Data.IntMap.Strict as IM-#else-import qualified Data.IntMap as IM-#endif---- | A set of 'Char's.------ We use range set, which works great with 'Char'.-newtype CharSet = CS { unCS :: IM.IntMap Int }- deriving (Eq, Ord)--instance IsString CharSet where- fromString = fromList--instance Show CharSet where- showsPrec d cs- | size cs < 20- = showsPrec d (toList cs)- | otherwise- = showParen (d > 10)- $ showString "CS "- . showsPrec 11 (unCS cs)--instance Semigroup CharSet where- (<>) = union--instance Monoid CharSet where- mempty = empty- mappend = (<>)---- | Empty character set.-empty :: CharSet-empty = CS IM.empty---- | universe-universe :: CharSet-universe = CS $ IM.singleton 0 0x10ffff---- | Check whether 'CharSet' is 'empty'.-null :: CharSet -> Bool-null (CS cs) = IM.null cs---- | Size of 'CharSet'------ >>> size $ fromIntervalList [('a','f'), ('0','9')]--- 16------ >>> length $ toList $ fromIntervalList [('a','f'), ('0','9')]--- 16----size :: CharSet -> Int-size (CS m) = foldl' (\ !acc (lo, hi) -> acc + (hi - lo) + 1) 0 (IM.toList m)---- | Singleton character set.-singleton :: Char -> CharSet-singleton c = CS (IM.singleton (ord c) (ord c))---- | Test whether character is in the set.-member :: Char -> CharSet -> Bool-#if MIN_VERSION_containers(0,5,0)-member c (CS m) = case IM.lookupLE i m of- Nothing -> False- Just (_, hi) -> i <= hi- where-#else-member c (CS m) = go (IM.toList m)- where- go [] = False- go ((x,y):zs) = (x <= i && i <= y) || go zs-#endif- i = ord c---- | Insert 'Char' into 'CharSet'.-insert :: Char -> CharSet -> CharSet-insert c (CS m) = normalise (IM.insert (ord c) (ord c) m)---- | Union of two 'CharSet's.-union :: CharSet -> CharSet -> CharSet-union (CS xs) (CS ys) = normalise (IM.unionWith max xs ys)---- | Intersection of two 'CharSet's-intersection :: CharSet -> CharSet -> CharSet-intersection (CS xs) (CS ys) = CS $- IM.fromList (intersectRangeList (IM.toList xs) (IM.toList ys))---- | Compute the intersection.-intersectRangeList :: Ord a => [(a, a)] -> [(a, a)] -> [(a, a)]-intersectRangeList aset@((x,y):as) bset@((u,v):bs)- | y < u = intersectRangeList as bset- | v < x = intersectRangeList aset bs- | y < v = (max x u, y) : intersectRangeList as bset- | otherwise = (max x u, v) : intersectRangeList aset bs-intersectRangeList _ [] = []-intersectRangeList [] _ = []---- | Complement of a CharSet-complement :: CharSet -> CharSet-complement (CS xs) = CS $ IM.fromList $ complementRangeList (IM.toList xs)---- | Compute the complement intersected with @[x,)@ assuming @x<u@.-complementRangeList' :: Int -> [(Int, Int)] -> [(Int, Int)]-complementRangeList' x ((u,v):s) = (x,pred u) : complementRangeList'' v s-complementRangeList' x [] = [(x,0x10ffff)]---- | Compute the complement intersected with @(x,)@.-complementRangeList'' :: Int -> [(Int, Int)] -> [(Int, Int)]-complementRangeList'' x s- | x == 0x10ffff = []- | otherwise = complementRangeList' (succ x) s---- | Compute the complement.------ Note: we treat Ints as codepoints, i.e minBound is 0, and maxBound is 0x10ffff-complementRangeList :: [(Int, Int)] -> [(Int, Int)]-complementRangeList s@((x,y):s')- | x == 0 = complementRangeList'' y s'- | otherwise = complementRangeList' 0 s-complementRangeList [] = [(0, 0x10ffff)]---- | Difference of two 'CharSet's.-difference :: CharSet -> CharSet -> CharSet-difference xs ys = intersection xs (complement ys)---- | Make 'CharSet' from a list of characters, i.e. 'String'.-fromList :: String -> CharSet-fromList = normalise . foldl' (\ acc c -> IM.insert (ord c) (ord c) acc) IM.empty---- | Convert 'CharSet' to a list of characters i.e. 'String'.-toList :: CharSet -> String-toList = concatMap (uncurry enumFromTo) . toIntervalList---- | Convert to interval list------ >>> toIntervalList $ union "01234" "56789"--- [('0','9')]----toIntervalList :: CharSet -> [(Char, Char)]-toIntervalList (CS m) = [ (chr lo, chr hi) | (lo, hi) <- IM.toList m ]---- | Convert from interval pairs.------ >>> fromIntervalList []--- ""------ >>> fromIntervalList [('a','f'), ('0','9')]--- "0123456789abcdef"------ >>> fromIntervalList [('Z','A')]--- ""----fromIntervalList :: [(Char,Char)] -> CharSet-fromIntervalList xs = normalise' $ sortBy (\a b -> compare (fst a) (fst b))- [ (ord lo, ord hi)- | (lo, hi) <- xs- , lo <= hi- ]------------------------------------------------------------------------------------ Normalisation----------------------------------------------------------------------------------normalise :: IM.IntMap Int -> CharSet-normalise = normalise'. IM.toList--normalise' :: [(Int,Int)] -> CharSet-normalise' = CS . IM.fromList . go where- go :: [(Int,Int)] -> [(Int,Int)]- go [] = []- go ((x,y):zs) = go' x y zs-- go' :: Int -> Int -> [(Int, Int)] -> [(Int, Int)]- go' lo hi [] = [(lo, hi)]- go' lo hi ws0@((u,v):ws)- | u <= succ hi = go' lo (max v hi) ws- | otherwise = (lo,hi) : go ws0------------------------------------------------------------------------------------ Alpha Numeric character list------------------------------------------------------------------------------------ Computing this takes some time,--- but they are not used in-non testing in Cabal's normal operation.---- | Note: this set varies depending on @base@ version.----alpha :: CharSet-alpha = foldl' (flip insert) empty [ c | c <- [ minBound .. maxBound ], isAlpha c ]-{-# NOINLINE alpha #-}---- | Note: this set varies depending on @base@ version.----alphanum :: CharSet-alphanum = foldl' (flip insert) empty [ c | c <- [ minBound .. maxBound ], isAlphaNum c ]-{-# NOINLINE alphanum #-}---- | Note: this set varies depending on @base@ version.----upper :: CharSet-upper = foldl' (flip insert) empty [ c | c <- [ minBound .. maxBound ], isUpper c ]-{-# NOINLINE upper #-}
− Cabal-described/src/Distribution/Utils/GrammarRegex.hs
@@ -1,215 +0,0 @@-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-module Distribution.Utils.GrammarRegex (- -- * Regular expressions- GrammarRegex (..),- reEps,- reChar,- reChars,- reMunchCS,- reMunch1CS,- -- * Variables- reVar0,- reVar1,- -- * Pretty-printing- regexDoc,- ) where--import Data.Char (isAlphaNum, isControl, ord)-import Data.Foldable (Foldable)-import Data.Maybe (fromMaybe)-import Data.Monoid (Monoid (..))-import Data.String (IsString (..))-import Data.Traversable (Traversable)-import Data.Void (Void, vacuous)-import Distribution.Compat.Semigroup (Semigroup (..))-import Prelude (Bool (..), Char, Eq (..), Functor, Int, Maybe (..), Ord (..), Show, String, fmap, length, map, otherwise, ($), (++), (.))--import qualified Distribution.Utils.CharSet as CS-import qualified Text.PrettyPrint as PP--(<<>>) :: PP.Doc -> PP.Doc -> PP.Doc-(<<>>) = (PP.<>)------------------------------------------------------------------------------------ GrammarRegex------------------------------------------------------------------------------------ | Recursive regular expressions tuned for 'Described' use-case.-data GrammarRegex a- = REAppend [GrammarRegex a] -- ^ append @ab@- | REUnion [GrammarRegex a] -- ^ union @a|b@-- -- repetition- | REMunch (GrammarRegex a) (GrammarRegex a) -- ^ star @a*@, with a separator- | REMunch1 (GrammarRegex a) (GrammarRegex a) -- ^ plus @a+@, with a separator- | REMunchR Int (GrammarRegex a) (GrammarRegex a) -- ^ 1-n, with a separator- | REOpt (GrammarRegex a) -- ^ optional @r?@-- | REString String -- ^ literal string @abcd@- | RECharSet CS.CharSet -- ^ charset @[:alnum:]@- | REVar a -- ^ variable- | RENamed String (GrammarRegex a) -- ^ named expression- | RERec String (GrammarRegex (Maybe a)) -- ^ recursive expressions-- -- cabal syntax specifics- | RESpaces -- ^ zero-or-more spaces- | RESpaces1 -- ^ one-or-more spaces- | RECommaList (GrammarRegex a) -- ^ comma list (note, leading or trailing commas)- | RECommaNonEmpty (GrammarRegex a) -- ^ comma non-empty list (note, leading or trailing commas)- | REOptCommaList (GrammarRegex a) -- ^ opt comma list-- | RETodo -- ^ unspecified- deriving (Eq, Ord, Show, Functor, Foldable, Traversable)------------------------------------------------------------------------------------ Instances----------------------------------------------------------------------------------instance IsString (GrammarRegex a) where- fromString = REString--instance Semigroup (GrammarRegex a) where- x <> y = REAppend (unAppend x ++ unAppend y) where- unAppend (REAppend rs) = rs- unAppend r = [r]--instance Monoid (GrammarRegex a) where- mempty = REAppend []- mappend = (<>)------------------------------------------------------------------------------------ Smart constructors----------------------------------------------------------------------------------reEps :: GrammarRegex a-reEps = REAppend []--reChar :: Char -> GrammarRegex a-reChar = RECharSet . CS.singleton--reChars :: [Char] -> GrammarRegex a-reChars = RECharSet . CS.fromList--reMunch1CS :: CS.CharSet -> GrammarRegex a-reMunch1CS = REMunch1 reEps . RECharSet--reMunchCS :: CS.CharSet -> GrammarRegex a-reMunchCS = REMunch reEps . RECharSet------------------------------------------------------------------------------------ Variables----------------------------------------------------------------------------------reVar0 :: GrammarRegex (Maybe a)-reVar0 = REVar Nothing--reVar1 :: GrammarRegex (Maybe (Maybe a))-reVar1 = REVar (Just Nothing)------------------------------------------------------------------------------------ Pretty-printing------------------------------------------------------------------------------------ |------ >>> regexDoc $ REString "True"--- \mathop{\mathord{``}\mathtt{True}\mathord{"}}------ Note: we don't simplify regexps yet:------ >>> regexDoc $ REString "foo" <> REString "bar"--- \mathop{\mathord{``}\mathtt{foo}\mathord{"}}\mathop{\mathord{``}\mathtt{bar}\mathord{"}}----regexDoc :: GrammarRegex Void -> PP.Doc-regexDoc = go 0 . vacuous where- go :: Int -> GrammarRegex PP.Doc -> PP.Doc- go _ (REAppend []) = ""- go d (REAppend rs) = parensIf (d > 2) $ PP.hcat (map (go 2) rs)- go d (REUnion [r]) = go d r- go _ (REUnion rs) = PP.hsep- [ "\\left\\{"- , if length rs < 4- then PP.hcat (PP.punctuate (PP.text "\\mid") (map (go 0) rs))- else "\\begin{gathered}" <<>>- PP.hcat (PP.punctuate "\\\\" (map (go 0) rs)) <<>>- "\\end{gathered}"- , "\\right\\}" ]-- go d (REMunch sep r) = parensIf (d > 3) $- PP.text "{" <<>> go 4 r <<>> PP.text "}^\\ast_{" <<>> go 4 sep <<>> PP.text "}"- go d (REMunch1 sep r) = parensIf (d > 3) $- PP.text "{" <<>> go 4 r <<>> PP.text "}^+_{" <<>> go 4 sep <<>> PP.text "}"- go d (REMunchR n sep r) = parensIf (d > 3) $- PP.text "{" <<>> go 4 r <<>> PP.text "}^{\\in [0\\ldots" <<>> PP.int n <<>> "]}_{" <<>> go 4 sep <<>> PP.text "}"- go d (REOpt r) = parensIf (d > 3) $- PP.text "{" <<>> go 4 r <<>> PP.text "}^?"-- go _ (REString s) = PP.text "\\mathop{\\mathord{``}\\mathtt{" <<>> PP.hcat (map charDoc s) <<>> PP.text "}\\mathord{\"}}"- go _ (RECharSet cs) = charsetDoc cs-- go _ RESpaces = "\\circ"- go _ RESpaces1 = "\\bullet"-- go _ (RECommaList r) =- "\\mathrm{commalist}" <<>> go 4 r- go _ (RECommaNonEmpty r) =- "\\mathrm{commanonempty}" <<>> go 4 r- go _ (REOptCommaList r) =- "\\mathrm{optcommalist}" <<>> go 4 r-- go _ (REVar a) = a- go _ (RENamed n _) = terminalDoc n- go d (RERec n r) = parensIf (d > 0) $- "\\mathbf{fix}\\;" <<>> n' <<>> "\\;\\mathbf{in}\\;" <<>>- go 0 (fmap (fromMaybe n') r)- where- n' = terminalDoc n-- go _ RETodo = PP.text "\\mathsf{\\color{red}{TODO}}"-- parensIf :: Bool -> PP.Doc -> PP.Doc- parensIf True d = PP.text "\\left(" <<>> d <<>> PP.text "\\right)"- parensIf False d = d--terminalDoc :: String -> PP.Doc-terminalDoc s = PP.text "\\mathop{\\mathit{" <<>> PP.hcat (map charDoc s) <<>> PP.text "}}"--charDoc :: Char -> PP.Doc-charDoc ' ' = PP.text "\\ "-charDoc '{' = PP.text "\\{"-charDoc '}' = PP.text "\\}"-charDoc '\\' = PP.text "\\text{\\\\}"-charDoc c- | isAlphaNum c = PP.char c- | isControl c = PP.int (ord c) -- TODO: some syntax- | otherwise = PP.text ("\\text{" ++ c : "}")--inquotes :: PP.Doc -> PP.Doc-inquotes d = "\\mathop{\\mathord{``}" <<>> d <<>> "\\mathord{\"}}"--mathtt :: PP.Doc -> PP.Doc-mathtt d = "\\mathtt{" <<>> d <<>> "}"--charsetDoc :: CS.CharSet -> PP.Doc-charsetDoc acs- | acs == CS.alpha = terminalDoc "alpha"- | acs == CS.alphanum = terminalDoc "alpha-num"- | acs == CS.upper = terminalDoc "upper"-charsetDoc acs = case CS.toIntervalList acs of- [] -> "\\emptyset"- [(x,y)] | x == y -> inquotes $ mathtt $ charDoc x- rs- | CS.size acs <= CS.size notAcs- -> PP.brackets $ PP.hcat $ map rangeDoc rs- | otherwise- -> PP.braces $ PP.brackets (PP.hcat $ map rangeDoc (CS.toIntervalList notAcs)) <<>> PP.text "^c"- where- notAcs = CS.complement acs-- rangeDoc :: (Char, Char) -> PP.Doc- rangeDoc (x, y) | x == y = inquotes (mathtt $ charDoc x)- | otherwise = inquotes (mathtt $ charDoc x) <<>> PP.text "\\cdots" <<>> inquotes (mathtt $ charDoc y)
− Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs
@@ -1,135 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__ >= 800-{-# OPTIONS_GHC -freduction-depth=0 #-}-#else-{-# OPTIONS_GHC -fcontext-stack=151 #-}-#endif-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Data.TreeDiff.Instances.Cabal () where--import Data.TreeDiff--import Data.TreeDiff.Instances.CabalLanguage ()-import Data.TreeDiff.Instances.CabalSPDX ()-import Data.TreeDiff.Instances.CabalVersion ()-----------------------------------------------------------------------------------import Distribution.Backpack (OpenModule, OpenUnitId)-import Distribution.CabalSpecVersion (CabalSpecVersion)-import Distribution.Compiler (CompilerFlavor, CompilerId, PerCompilerFlavor)-import Distribution.InstalledPackageInfo (AbiDependency, ExposedModule, InstalledPackageInfo)-import Distribution.ModuleName (ModuleName)-import Distribution.PackageDescription-import Distribution.Simple.Compiler (DebugInfoLevel, OptimisationLevel, ProfDetailLevel)-import Distribution.Simple.Flag (Flag)-import Distribution.Simple.InstallDirs-import Distribution.Simple.InstallDirs.Internal-import Distribution.Simple.Setup (HaddockTarget, TestShowDetails)-import Distribution.System-import Distribution.Types.AbiHash (AbiHash)-import Distribution.Types.ComponentId (ComponentId)-import Distribution.Types.IncludeRenaming (IncludeRenaming)-import Distribution.Types.Mixin-import Distribution.Types.ModuleReexport-import Distribution.Types.ModuleRenaming-import Distribution.Types.PackageVersionConstraint-import Distribution.Types.PkgconfigName (PkgconfigName)-import Distribution.Types.PkgconfigVersion (PkgconfigVersion)-import Distribution.Types.PkgconfigVersionRange (PkgconfigVersionRange)-import Distribution.Types.UnitId (DefUnitId, UnitId)-import Distribution.Utils.NubList (NubList)-import Distribution.Utils.ShortText (ShortText, fromShortText)-import Distribution.Verbosity-import Distribution.Verbosity.Internal--import qualified Distribution.Compat.NonEmptySet as NES------------------------------------------------------------------------------------ instances----------------------------------------------------------------------------------instance (Eq a, Show a) => ToExpr (Condition a) where toExpr = defaultExprViaShow-instance (Show a, ToExpr b, ToExpr c, Show b, Show c, Eq a, Eq c, Eq b) => ToExpr (CondTree a b c)-instance (Show a, ToExpr b, ToExpr c, Show b, Show c, Eq a, Eq c, Eq b) => ToExpr (CondBranch a b c)-instance (ToExpr a) => ToExpr (NubList a)-instance (ToExpr a) => ToExpr (Flag a)-instance ToExpr a => ToExpr (NES.NonEmptySet a) where- toExpr xs = App "NonEmptySet.fromNonEmpty" [toExpr $ NES.toNonEmpty xs]--instance ToExpr a => ToExpr (PerCompilerFlavor a)--instance ToExpr Dependency where- toExpr d@(Dependency pn vr cs)- | cs == mainLibSet = App "Dependency" [toExpr pn, toExpr vr, App "mainLibSet" []]- | otherwise = genericToExpr d--instance ToExpr AbiDependency-instance ToExpr AbiHash-instance ToExpr Arch-instance ToExpr Benchmark-instance ToExpr BenchmarkInterface-instance ToExpr BenchmarkType-instance ToExpr BuildInfo-instance ToExpr BuildType-instance ToExpr CabalSpecVersion-instance ToExpr CompilerFlavor-instance ToExpr CompilerId-instance ToExpr ComponentId-instance ToExpr DebugInfoLevel-instance ToExpr DefUnitId-instance ToExpr ExeDependency-instance ToExpr Executable-instance ToExpr ExecutableScope-instance ToExpr ExposedModule-instance ToExpr FlagAssignment-instance ToExpr FlagName-instance ToExpr ForeignLib-instance ToExpr ForeignLibOption-instance ToExpr ForeignLibType-instance ToExpr GenericPackageDescription-instance ToExpr HaddockTarget-instance ToExpr IncludeRenaming-instance ToExpr InstalledPackageInfo-instance ToExpr KnownRepoType-instance ToExpr LegacyExeDependency-instance ToExpr LibVersionInfo-instance ToExpr Library-instance ToExpr LibraryName-instance ToExpr LibraryVisibility-instance ToExpr Mixin-instance ToExpr ModuleName-instance ToExpr ModuleReexport-instance ToExpr ModuleRenaming-instance ToExpr OS-instance ToExpr OpenModule-instance ToExpr OpenUnitId-instance ToExpr OptimisationLevel-instance ToExpr PackageDescription-instance ToExpr PackageFlag-instance ToExpr PackageIdentifier-instance ToExpr PackageName-instance ToExpr PackageVersionConstraint-instance ToExpr PathComponent-instance ToExpr PathTemplate-instance ToExpr PathTemplateVariable-instance ToExpr PkgconfigDependency-instance ToExpr PkgconfigName-instance ToExpr PkgconfigVersion-instance ToExpr PkgconfigVersionRange-instance ToExpr ProfDetailLevel-instance ToExpr RepoKind-instance ToExpr RepoType-instance ToExpr SetupBuildInfo-instance ToExpr SourceRepo-instance ToExpr TestShowDetails-instance ToExpr TestSuite-instance ToExpr TestSuiteInterface-instance ToExpr TestType-instance ToExpr UnitId-instance ToExpr UnqualComponentName-instance ToExpr Verbosity-instance ToExpr VerbosityFlag-instance ToExpr VerbosityLevel--instance ToExpr ShortText where toExpr = toExpr . fromShortText
− Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalLanguage.hs
@@ -1,17 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__ >= 800-{-# OPTIONS_GHC -freduction-depth=0 #-}-#else-{-# OPTIONS_GHC -fcontext-stack=151 #-}-#endif-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Data.TreeDiff.Instances.CabalLanguage () where--import Data.TreeDiff-import Language.Haskell.Extension (Extension, KnownExtension, Language)---- These are big enums, so they are in separate file.----instance ToExpr Extension-instance ToExpr KnownExtension-instance ToExpr Language
− Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalSPDX.hs
@@ -1,28 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__ >= 800-{-# OPTIONS_GHC -freduction-depth=0 #-}-#else-{-# OPTIONS_GHC -fcontext-stack=151 #-}-#endif-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Data.TreeDiff.Instances.CabalSPDX () where--import Data.TreeDiff-import Distribution.License (License)--import Data.TreeDiff.Instances.CabalVersion ()--import qualified Distribution.SPDX as SPDX---- 'License' almost belongs here.--instance ToExpr License---- Generics instance is too heavy-instance ToExpr SPDX.LicenseId where toExpr = defaultExprViaShow-instance ToExpr SPDX.LicenseExceptionId where toExpr = defaultExprViaShow--instance ToExpr SPDX.License-instance ToExpr SPDX.LicenseExpression-instance ToExpr SPDX.LicenseRef-instance ToExpr SPDX.SimpleLicenseExpression
− Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalVersion.hs
@@ -1,14 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__ >= 800-{-# OPTIONS_GHC -freduction-depth=0 #-}-#else-{-# OPTIONS_GHC -fcontext-stack=151 #-}-#endif-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Data.TreeDiff.Instances.CabalVersion where--import Data.TreeDiff-import Distribution.Version (Version, VersionRange, versionNumbers)--instance ToExpr Version where toExpr v = App "mkVersion" [toExpr $ versionNumbers v]-instance ToExpr VersionRange
Cabal.cabal view
@@ -1,7 +1,7 @@ cabal-version: >=1.10 name: Cabal-version: 3.4.1.0-copyright: 2003-2020, Cabal Development Team (see AUTHORS file)+version: 3.6.0.0+copyright: 2003-2021, Cabal Development Team (see AUTHORS file) license: BSD3 license-file: LICENSE author: Cabal Development Team <cabal-devel@haskell.org>@@ -22,286 +22,7 @@ -- we can bootstrap. extra-source-files:- README.md tests/README.md ChangeLog.md- doc/bugs-and-stability.rst doc/concepts-and-development.rst- doc/conf.py doc/config-and-install.rst doc/developing-packages.rst- doc/images/Cabal-dark.png doc/index.rst doc/installing-packages.rst- doc/intro.rst doc/misc.rst doc/nix-local-build-overview.rst- doc/nix-local-build.rst doc/file-format-changelog.rst doc/README.md- doc/references.inc-- -- Generated with 'make gen-extra-source-files'- -- Do NOT edit this section manually; instead, run the script.- -- BEGIN gen-extra-source-files- tests/ParserTests/errors/MiniAgda.cabal- tests/ParserTests/errors/MiniAgda.errors- tests/ParserTests/errors/anynone.cabal- tests/ParserTests/errors/anynone.errors- tests/ParserTests/errors/big-version.cabal- tests/ParserTests/errors/big-version.errors- tests/ParserTests/errors/common1.cabal- tests/ParserTests/errors/common1.errors- tests/ParserTests/errors/common2.cabal- tests/ParserTests/errors/common2.errors- tests/ParserTests/errors/common3.cabal- tests/ParserTests/errors/common3.errors- tests/ParserTests/errors/forward-compat.cabal- tests/ParserTests/errors/forward-compat.errors- tests/ParserTests/errors/forward-compat2.cabal- tests/ParserTests/errors/forward-compat2.errors- tests/ParserTests/errors/forward-compat3.cabal- tests/ParserTests/errors/forward-compat3.errors- tests/ParserTests/errors/issue-5055-2.cabal- tests/ParserTests/errors/issue-5055-2.errors- tests/ParserTests/errors/issue-5055.cabal- tests/ParserTests/errors/issue-5055.errors- tests/ParserTests/errors/leading-comma-2.cabal- tests/ParserTests/errors/leading-comma-2.errors- tests/ParserTests/errors/leading-comma-2b.cabal- tests/ParserTests/errors/leading-comma-2b.errors- tests/ParserTests/errors/leading-comma-2c.cabal- tests/ParserTests/errors/leading-comma-2c.errors- tests/ParserTests/errors/leading-comma.cabal- tests/ParserTests/errors/leading-comma.errors- tests/ParserTests/errors/libpq1.cabal- tests/ParserTests/errors/libpq1.errors- tests/ParserTests/errors/libpq2.cabal- tests/ParserTests/errors/libpq2.errors- tests/ParserTests/errors/mixin-1.cabal- tests/ParserTests/errors/mixin-1.errors- tests/ParserTests/errors/mixin-2.cabal- tests/ParserTests/errors/mixin-2.errors- tests/ParserTests/errors/multiple-libs.cabal- tests/ParserTests/errors/multiple-libs.errors- tests/ParserTests/errors/noVersion.cabal- tests/ParserTests/errors/noVersion.errors- tests/ParserTests/errors/noVersion2.cabal- tests/ParserTests/errors/noVersion2.errors- tests/ParserTests/errors/range-ge-wild.cabal- tests/ParserTests/errors/range-ge-wild.errors- tests/ParserTests/errors/removed-fields.cabal- tests/ParserTests/errors/removed-fields.errors- tests/ParserTests/errors/spdx-1.cabal- tests/ParserTests/errors/spdx-1.errors- tests/ParserTests/errors/spdx-2.cabal- tests/ParserTests/errors/spdx-2.errors- tests/ParserTests/errors/spdx-3.cabal- tests/ParserTests/errors/spdx-3.errors- tests/ParserTests/errors/undefined-flag.cabal- tests/ParserTests/errors/undefined-flag.errors- tests/ParserTests/errors/version-sets-1.cabal- tests/ParserTests/errors/version-sets-1.errors- tests/ParserTests/errors/version-sets-2.cabal- tests/ParserTests/errors/version-sets-2.errors- tests/ParserTests/errors/version-sets-3.cabal- tests/ParserTests/errors/version-sets-3.errors- tests/ParserTests/errors/version-sets-4.cabal- tests/ParserTests/errors/version-sets-4.errors- tests/ParserTests/ipi/Includes2.cabal- tests/ParserTests/ipi/Includes2.expr- tests/ParserTests/ipi/Includes2.format- tests/ParserTests/ipi/internal-preprocessor-test.cabal- tests/ParserTests/ipi/internal-preprocessor-test.expr- tests/ParserTests/ipi/internal-preprocessor-test.format- tests/ParserTests/ipi/issue-2276-ghc-9885.cabal- tests/ParserTests/ipi/issue-2276-ghc-9885.expr- tests/ParserTests/ipi/issue-2276-ghc-9885.format- tests/ParserTests/ipi/transformers.cabal- tests/ParserTests/ipi/transformers.expr- tests/ParserTests/ipi/transformers.format- tests/ParserTests/regressions/Octree-0.5.cabal- tests/ParserTests/regressions/Octree-0.5.expr- tests/ParserTests/regressions/Octree-0.5.format- tests/ParserTests/regressions/anynone.cabal- tests/ParserTests/regressions/anynone.expr- tests/ParserTests/regressions/anynone.format- tests/ParserTests/regressions/assoc-cpp-options.cabal- tests/ParserTests/regressions/assoc-cpp-options.check- tests/ParserTests/regressions/bad-glob-syntax.cabal- tests/ParserTests/regressions/bad-glob-syntax.check- tests/ParserTests/regressions/big-version.cabal- tests/ParserTests/regressions/big-version.expr- tests/ParserTests/regressions/big-version.format- tests/ParserTests/regressions/cc-options-with-optimization.cabal- tests/ParserTests/regressions/cc-options-with-optimization.check- tests/ParserTests/regressions/common-conditional.cabal- tests/ParserTests/regressions/common-conditional.expr- tests/ParserTests/regressions/common-conditional.format- tests/ParserTests/regressions/common.cabal- tests/ParserTests/regressions/common.expr- tests/ParserTests/regressions/common.format- tests/ParserTests/regressions/common2.cabal- tests/ParserTests/regressions/common2.expr- tests/ParserTests/regressions/common2.format- tests/ParserTests/regressions/common3.cabal- tests/ParserTests/regressions/common3.expr- tests/ParserTests/regressions/common3.format- tests/ParserTests/regressions/cxx-options-with-optimization.cabal- tests/ParserTests/regressions/cxx-options-with-optimization.check- tests/ParserTests/regressions/denormalised-paths.cabal- tests/ParserTests/regressions/denormalised-paths.check- tests/ParserTests/regressions/elif.cabal- tests/ParserTests/regressions/elif.expr- tests/ParserTests/regressions/elif.format- tests/ParserTests/regressions/elif2.cabal- tests/ParserTests/regressions/elif2.expr- tests/ParserTests/regressions/elif2.format- tests/ParserTests/regressions/encoding-0.8.cabal- tests/ParserTests/regressions/encoding-0.8.expr- tests/ParserTests/regressions/encoding-0.8.format- tests/ParserTests/regressions/extensions-paths-5054.cabal- tests/ParserTests/regressions/extensions-paths-5054.check- tests/ParserTests/regressions/generics-sop.cabal- tests/ParserTests/regressions/generics-sop.expr- tests/ParserTests/regressions/generics-sop.format- tests/ParserTests/regressions/ghc-option-j.cabal- tests/ParserTests/regressions/ghc-option-j.check- tests/ParserTests/regressions/haddock-api-2.18.1-check.cabal- tests/ParserTests/regressions/haddock-api-2.18.1-check.check- tests/ParserTests/regressions/hasktorch.cabal- tests/ParserTests/regressions/hasktorch.expr- tests/ParserTests/regressions/hasktorch.format- tests/ParserTests/regressions/hidden-main-lib.cabal- tests/ParserTests/regressions/hidden-main-lib.expr- tests/ParserTests/regressions/hidden-main-lib.format- tests/ParserTests/regressions/indentation.cabal- tests/ParserTests/regressions/indentation.expr- tests/ParserTests/regressions/indentation.format- tests/ParserTests/regressions/indentation2.cabal- tests/ParserTests/regressions/indentation2.expr- tests/ParserTests/regressions/indentation2.format- tests/ParserTests/regressions/indentation3.cabal- tests/ParserTests/regressions/indentation3.expr- tests/ParserTests/regressions/indentation3.format- tests/ParserTests/regressions/issue-5055.cabal- tests/ParserTests/regressions/issue-5055.expr- tests/ParserTests/regressions/issue-5055.format- tests/ParserTests/regressions/issue-5846.cabal- tests/ParserTests/regressions/issue-5846.expr- tests/ParserTests/regressions/issue-5846.format- tests/ParserTests/regressions/issue-6083-a.cabal- tests/ParserTests/regressions/issue-6083-a.expr- tests/ParserTests/regressions/issue-6083-a.format- tests/ParserTests/regressions/issue-6083-b.cabal- tests/ParserTests/regressions/issue-6083-b.expr- tests/ParserTests/regressions/issue-6083-b.format- tests/ParserTests/regressions/issue-6083-c.cabal- tests/ParserTests/regressions/issue-6083-c.expr- tests/ParserTests/regressions/issue-6083-c.format- tests/ParserTests/regressions/issue-6083-pkg-pkg.cabal- tests/ParserTests/regressions/issue-6083-pkg-pkg.expr- tests/ParserTests/regressions/issue-6083-pkg-pkg.format- tests/ParserTests/regressions/issue-6288-a.cabal- tests/ParserTests/regressions/issue-6288-a.check- tests/ParserTests/regressions/issue-6288-b.cabal- tests/ParserTests/regressions/issue-6288-b.check- tests/ParserTests/regressions/issue-6288-c.cabal- tests/ParserTests/regressions/issue-6288-c.check- tests/ParserTests/regressions/issue-6288-d.cabal- tests/ParserTests/regressions/issue-6288-d.check- tests/ParserTests/regressions/issue-6288-e.cabal- tests/ParserTests/regressions/issue-6288-e.check- tests/ParserTests/regressions/issue-6288-f.cabal- tests/ParserTests/regressions/issue-6288-f.check- tests/ParserTests/regressions/issue-774.cabal- tests/ParserTests/regressions/issue-774.check- tests/ParserTests/regressions/issue-774.expr- tests/ParserTests/regressions/issue-774.format- tests/ParserTests/regressions/jaeger-flamegraph.cabal- tests/ParserTests/regressions/jaeger-flamegraph.expr- tests/ParserTests/regressions/jaeger-flamegraph.format- tests/ParserTests/regressions/leading-comma-2.cabal- tests/ParserTests/regressions/leading-comma-2.expr- tests/ParserTests/regressions/leading-comma-2.format- tests/ParserTests/regressions/leading-comma.cabal- tests/ParserTests/regressions/leading-comma.expr- tests/ParserTests/regressions/leading-comma.format- tests/ParserTests/regressions/libpq1.cabal- tests/ParserTests/regressions/libpq1.expr- tests/ParserTests/regressions/libpq1.format- tests/ParserTests/regressions/libpq2.cabal- tests/ParserTests/regressions/libpq2.expr- tests/ParserTests/regressions/libpq2.format- tests/ParserTests/regressions/mixin-1.cabal- tests/ParserTests/regressions/mixin-1.expr- tests/ParserTests/regressions/mixin-1.format- tests/ParserTests/regressions/mixin-2.cabal- tests/ParserTests/regressions/mixin-2.expr- tests/ParserTests/regressions/mixin-2.format- tests/ParserTests/regressions/mixin-3.cabal- tests/ParserTests/regressions/mixin-3.expr- tests/ParserTests/regressions/mixin-3.format- tests/ParserTests/regressions/monad-param.cabal- tests/ParserTests/regressions/monad-param.expr- tests/ParserTests/regressions/monad-param.format- tests/ParserTests/regressions/multiple-libs-2.cabal- tests/ParserTests/regressions/multiple-libs-2.check- tests/ParserTests/regressions/multiple-libs-2.expr- tests/ParserTests/regressions/multiple-libs-2.format- tests/ParserTests/regressions/noVersion.cabal- tests/ParserTests/regressions/noVersion.expr- tests/ParserTests/regressions/noVersion.format- tests/ParserTests/regressions/nothing-unicode.cabal- tests/ParserTests/regressions/nothing-unicode.check- tests/ParserTests/regressions/nothing-unicode.expr- tests/ParserTests/regressions/nothing-unicode.format- tests/ParserTests/regressions/pre-1.6-glob.cabal- tests/ParserTests/regressions/pre-1.6-glob.check- tests/ParserTests/regressions/pre-2.4-globstar.cabal- tests/ParserTests/regressions/pre-2.4-globstar.check- tests/ParserTests/regressions/public-multilib-1.cabal- tests/ParserTests/regressions/public-multilib-1.check- tests/ParserTests/regressions/public-multilib-2.cabal- tests/ParserTests/regressions/public-multilib-2.check- tests/ParserTests/regressions/shake.cabal- tests/ParserTests/regressions/shake.expr- tests/ParserTests/regressions/shake.format- tests/ParserTests/regressions/spdx-1.cabal- tests/ParserTests/regressions/spdx-1.expr- tests/ParserTests/regressions/spdx-1.format- tests/ParserTests/regressions/spdx-2.cabal- tests/ParserTests/regressions/spdx-2.expr- tests/ParserTests/regressions/spdx-2.format- tests/ParserTests/regressions/spdx-3.cabal- tests/ParserTests/regressions/spdx-3.expr- tests/ParserTests/regressions/spdx-3.format- tests/ParserTests/regressions/th-lift-instances.cabal- tests/ParserTests/regressions/th-lift-instances.expr- tests/ParserTests/regressions/th-lift-instances.format- tests/ParserTests/regressions/version-sets.cabal- tests/ParserTests/regressions/version-sets.expr- tests/ParserTests/regressions/version-sets.format- tests/ParserTests/regressions/wl-pprint-indef.cabal- tests/ParserTests/regressions/wl-pprint-indef.expr- tests/ParserTests/regressions/wl-pprint-indef.format- tests/ParserTests/warnings/bom.cabal- tests/ParserTests/warnings/bool.cabal- tests/ParserTests/warnings/deprecatedfield.cabal- tests/ParserTests/warnings/doubledash.cabal- tests/ParserTests/warnings/extratestmodule.cabal- tests/ParserTests/warnings/gluedop.cabal- tests/ParserTests/warnings/multiplesingular.cabal- tests/ParserTests/warnings/nbsp.cabal- tests/ParserTests/warnings/newsyntax.cabal- tests/ParserTests/warnings/oldsyntax.cabal- tests/ParserTests/warnings/operator.cabal- tests/ParserTests/warnings/specversion-a.cabal- tests/ParserTests/warnings/specversion-b.cabal- tests/ParserTests/warnings/specversion-c.cabal- tests/ParserTests/warnings/subsection.cabal- tests/ParserTests/warnings/tab.cabal- tests/ParserTests/warnings/trailingfield.cabal- tests/ParserTests/warnings/unknownfield.cabal- tests/ParserTests/warnings/unknownsection.cabal- tests/ParserTests/warnings/utf8.cabal- tests/ParserTests/warnings/versiontag.cabal- tests/ParserTests/warnings/wildcard.cabal- tests/cbits/rpmvercmp.c- tests/hackage/check.sh- tests/hackage/download.sh- tests/hackage/unpack.sh- tests/misc/ghc-supported-languages.hs- -- END gen-extra-source-files+ README.md ChangeLog.md source-repository head type: git@@ -312,17 +33,20 @@ default: False library+ default-language: Haskell2010+ hs-source-dirs: src+ build-depends: array >= 0.4.0.1 && < 0.6,- base >= 4.6 && < 4.16,- bytestring >= 0.10.0.0 && < 0.11,+ base >= 4.6 && < 5,+ bytestring >= 0.10.0.0 && < 0.12, containers >= 0.5.0.0 && < 0.7, deepseq >= 1.3.0.1 && < 1.5, directory >= 1.2 && < 1.4, filepath >= 1.3.0.1 && < 1.5, pretty >= 1.1.1 && < 1.2, process >= 1.1.0.2 && < 1.7,- time >= 1.4.0.1 && < 1.11+ time >= 1.4.0.1 && < 1.12 if flag(bundled-binary-generic) build-depends: binary >= 0.5.1.1 && < 0.7@@ -330,11 +54,11 @@ build-depends: binary >= 0.7 && < 0.9 if os(windows)- build-depends: Win32 >= 2.3.0.0 && < 2.11+ build-depends: Win32 >= 2.3.0.0 && < 2.13 else build-depends: unix >= 2.6.0.0 && < 2.8 - ghc-options: -Wall -fno-ignore-asserts -fwarn-tabs -fwarn-incomplete-uni-patterns+ ghc-options: -Wall -fno-ignore-asserts -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates if impl(ghc >= 8.0) ghc-options: -Wcompat -Wnoncanonical-monad-instances @@ -366,6 +90,7 @@ Distribution.Backpack.PreModuleShape Distribution.CabalSpecVersion Distribution.Utils.IOData+ Distribution.Utils.Path Distribution.Utils.LogProgress Distribution.Utils.MapAccum Distribution.Utils.MD5@@ -419,7 +144,6 @@ Distribution.Simple.GHC Distribution.Simple.GHCJS Distribution.Simple.Haddock- Distribution.Simple.Doctest Distribution.Simple.Glob Distribution.Simple.HaskellSuite Distribution.Simple.Hpc@@ -526,6 +250,7 @@ Distribution.Types.VersionRange Distribution.Types.VersionRange.Internal Distribution.Types.VersionInterval+ Distribution.Types.VersionInterval.Legacy Distribution.Types.GivenComponent Distribution.Types.PackageVersionConstraint Distribution.Utils.Generic@@ -608,6 +333,7 @@ Distribution.Lex Distribution.Utils.String Distribution.Simple.Build.Macros.Z+ Distribution.Simple.Build.PathsModule.Z Distribution.Simple.GHC.EnvironmentParser Distribution.Simple.GHC.Internal Distribution.Simple.GHC.ImplInfo@@ -620,7 +346,6 @@ Distribution.Compat.Binary.Class Distribution.Compat.Binary.Generic - default-language: Haskell2010 other-extensions: BangPatterns CPP@@ -650,205 +375,3 @@ if impl(ghc >= 7.11) other-extensions: PatternSynonyms---- 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.CabalSpecVersion- UnitTests.Distribution.Compat.CreatePipe- UnitTests.Distribution.Compat.Graph- UnitTests.Distribution.Compat.Time- UnitTests.Distribution.Described- UnitTests.Distribution.Simple.Glob- UnitTests.Distribution.Simple.Program.GHC- UnitTests.Distribution.Simple.Program.Internal- UnitTests.Distribution.Simple.Utils- UnitTests.Distribution.SPDX- UnitTests.Distribution.System- UnitTests.Distribution.Types.GenericPackageDescription- UnitTests.Distribution.Utils.CharSet- UnitTests.Distribution.Utils.Generic- UnitTests.Distribution.Utils.NubList- UnitTests.Distribution.Utils.ShortText- UnitTests.Distribution.Utils.Structured- UnitTests.Distribution.Version- UnitTests.Distribution.PkgconfigVersion- UnitTests.Orphans-- -- Cabal-quickcheck- hs-source-dirs: Cabal-QuickCheck/src- other-modules:- Test.QuickCheck.GenericArbitrary- Test.QuickCheck.Instances.Cabal-- -- Cabal-described- hs-source-dirs: Cabal-described/src- other-modules:- Distribution.Described- Distribution.Utils.CharSet- Distribution.Utils.GrammarRegex- - main-is: UnitTests.hs- build-depends:- array,- async >= 2.2.2 && <2.3,- base,- binary,- bytestring,- containers,- deepseq,- directory,- filepath,- integer-logarithms >= 1.0.2 && <1.1,- pretty,- rere >=0.1 && <0.3,- tagged,- tasty >= 1.2.3 && < 1.4,- tasty-hunit,- tasty-quickcheck,- temporary,- text,- transformers,- Diff >=0.4 && <0.5,- QuickCheck >= 2.14 && < 2.15,- Cabal- ghc-options: -Wall- default-language: Haskell2010-- if !impl(ghc >= 7.10)- build-depends: void-- if !impl(ghc >= 8.0)- build-depends: semigroups--test-suite parser-tests- type: exitcode-stdio-1.0- hs-source-dirs: tests- main-is: ParserTests.hs- build-depends:- base,- base-compat >=0.11.0 && <0.12,- bytestring,- directory,- filepath,- tasty >= 1.2.3 && < 1.4,- tasty-hunit,- tasty-quickcheck,- tasty-golden >=2.3.1.1 && <2.4,- Diff >=0.4 && <0.5,- Cabal- ghc-options: -Wall- default-language: Haskell2010-- if !impl(ghc >= 8.0)- build-depends: semigroups-- if impl(ghc >= 7.8)- build-depends:- tree-diff >= 0.1 && <0.2- hs-source-dirs: Cabal-tree-diff/src- other-modules:- Data.TreeDiff.Instances.Cabal- Data.TreeDiff.Instances.CabalLanguage- Data.TreeDiff.Instances.CabalSPDX- Data.TreeDiff.Instances.CabalVersion--test-suite check-tests- type: exitcode-stdio-1.0- hs-source-dirs: tests- main-is: CheckTests.hs- build-depends:- base,- bytestring,- directory,- filepath,- tasty >= 1.2.3 && < 1.4,- tasty-golden >=2.3.1.1 && <2.4,- Diff >=0.4 && <0.5,- Cabal- ghc-options: -Wall- default-language: Haskell2010- if !impl(ghc >= 8.0)- build-depends: semigroups--test-suite custom-setup-tests- type: exitcode-stdio-1.0- hs-source-dirs: tests/custom-setup- main-is: CustomSetupTests.hs- other-modules:- CabalDoctestSetup- IdrisSetup- build-depends:- Cabal,- base,- directory,- filepath,- process- default-language: Haskell2010--test-suite hackage-tests- type: exitcode-stdio-1.0- main-is: HackageTests.hs-- -- TODO: need to get 01-index.tar on appveyor- if os(windows)- buildable: False-- hs-source-dirs: tests-- build-depends:- base,- Cabal,- bytestring,- deepseq,- containers,- directory,- filepath-- build-depends:- base-compat >=0.11.0 && <0.12,- base-orphans >=0.6 && <0.9,- clock >=0.8 && <0.9,- optparse-applicative >=0.13.2.0 && <0.17,- stm >=2.4.5.0 && <2.6,- tar >=0.5.0.3 && <0.6-- if impl(ghc >= 7.8)- build-depends:- tree-diff >= 0.1 && <0.2- hs-source-dirs: Cabal-tree-diff/src- other-modules:- Data.TreeDiff.Instances.Cabal- Data.TreeDiff.Instances.CabalLanguage- Data.TreeDiff.Instances.CabalSPDX- Data.TreeDiff.Instances.CabalVersion-- ghc-options: -Wall -rtsopts -threaded- default-extensions: CPP- default-language: Haskell2010--test-suite rpmvercmp- type: exitcode-stdio-1.0- main-is: RPMVerCmp.hs-- hs-source-dirs: tests- build-depends:- base,- Cabal,- bytestring-- build-depends:- tasty >= 1.2.3 && < 1.4,- tasty-hunit,- tasty-quickcheck,- QuickCheck-- c-sources: tests/cbits/rpmvercmp.c- cc-options: -Wall-- ghc-options: -Wall- default-language: Haskell2010
ChangeLog.md view
@@ -1,7 +1,7 @@-# 3.4.1.0 [Emily Pillmore](mailto:emilypi@cohomolo.gy) October 2021- * See https://github.com/haskell/cabal/blob/master/release-notes/Cabal-3.4.1.0.md+# 3.6.0.0 [Emily Pillmore](mailgo:emilypi@cohomolo.gy) August 2021+ * See https://github.com/haskell/cabal/blob/master/release-notes/Cabal-3.6.0.0.md -# 3.4.0.0 [Oleg Grenrus](mailto:oleg.grnerus@iki.fi) February 2021+# 3.4.0.0 [Oleg Grenrus](mailgo:oleg.grnerus@iki.fi) February 2021 * See https://github.com/haskell/cabal/blob/master/release-notes/Cabal-3.4.0.0.md # 3.2.1.0 [Oleg Grenrus](mailto:oleg.grenris@iki.fi) October 2020@@ -14,7 +14,7 @@ # 3.2.0.0 [Herbert Valerio Riedel](mailto:hvr@gnu.org) April 2020 * Change free text `String` fields to use `ShortText` in package description- and installed packge info.+ and installed package info. * Split `Distribution.Types.Flag` and `Distribution.Types.ConfVar` `Distribution.Types.GenericPackageDescription`. * Add GHC-8.10 support, including new extensions to@@ -38,26 +38,11 @@ # 3.0.1.0 [Herbert Valerio Riedel](mailto:hvr@gnu.org) April 2020 * Add GHC-8.8 flags to `normaliseGhcFlags` ([#6379](https://github.com/haskell/cabal/pull/6379)).- `Language.Haskell.Extension`- * Use more `NonEmpty` instead of ordinary lists- * Add `Distribution.Utils.Structured` for fingeprinting `Binary` blobs- * Add `null`, `length` and `unsafeFromUTF8BS` to `Distribution.Utils.ShortText`- * Refactor `Distribution.Utils.IOData` module- * Rename `Distribution.Compat.MD5` to `Distribution.Utils.MD5`- * Add `safeHead`, `safeTail`, `safeLast` to `Distribution.Utils.Generic`- * Add `unsnoc` and `unsnocNE` to `Distribution.Utils.Generic`- * Add `Set'` modifier to `Distribution.Parsec.Newtypes`- * Add `Distribution.Compat.Async`- * Add `Distribution.Compat.Process` with `enableProcessJobs`--# 3.0.1.0 TBW- * Add GHC-8.8 flags to normaliseGhcFlags- ([#6379](https://github.com/haskell/cabal/pull/6379)) * Typo fixes ([#6372](https://github.com/haskell/cabal/pull/6372)). * Limit version number parts to contain at most 9 digits ([#6386](https://github.com/haskell/cabal/pull/6386)).- * Fix boundless sublibrary depedency parse failure+ * Fix boundless sublibrary dependency parse failure ([#5846](https://github.com/haskell/cabal/issues/5846)). * `cabal check` verifies `cpp-options` more pedantically, allowing only options starting with `-D` and `-U`.@@ -194,7 +179,7 @@ [#784](https://github.com/haskell/cabal/issues/784), [#5057](https://github.com/haskell/cabal/issues/5057)). * Wildcard syntax errors (misplaced `*`, etc), wildcards that- refer to missing directoies, and wildcards that do not match+ refer to missing directories, and wildcards that do not match anything are now all detected by `cabal check`. * Wildcard ('globbing') functions have been moved from `Distribution.Simple.Utils` to `Distribution.Simple.Glob` and@@ -655,7 +640,7 @@ * Support for finding installed packages for hugs * Cabal version macros now have proper parenthesis * Reverted change to filter out deps of non-buildable components- * Fix for registering implace when using a specific package db+ * Fix for registering inplace when using a specific package db * Fix mismatch between $os and $arch path template variables * Fix for finding ar.exe on Windows, always pick ghc's version * Fix for intra-package dependencies with ghc-6.12@@ -817,7 +802,7 @@ # 1.2.0 [Duncan Coutts](mailto:duncan.coutts@worc.ox.ac.uk) Sept 2007 * To be included in GHC 6.8.x * New configurations feature- * Can make haddock docs link to hilighted sources (with hscolour)+ * Can make haddock docs link to highlighted sources (with hscolour) * New flag to allow linking to haddock docs on the web * Supports pkg-config * New field `build-tools` for tool dependencies@@ -857,7 +842,7 @@ * Released with GHC 6.6 * Added support for hoogle- * Allow profiling and normal builds of libs to be chosen indepentantly+ * Allow profiling and normal builds of libs to be chosen independently * Default installation directories on Win32 changed * Register haddock docs with ghc-pkg * Get haddock to make hyperlinks to dependent package docs@@ -937,7 +922,7 @@ * Lots of bug fixes * spaces can sometimes be used instead of commas * A user manual has appeared (Thanks, ross!)- * for ghc 6.4, configures versionsed depends properly+ * for ghc 6.4, configures versioned depends properly * more features to `./setup haddock` ----
− Distribution/Backpack.hs
@@ -1,269 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}---- | This module defines the core data types for Backpack. For more--- details, see:------ <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>--module Distribution.Backpack (- -- * OpenUnitId- OpenUnitId(..),- openUnitIdFreeHoles,- mkOpenUnitId,-- -- * DefUnitId- DefUnitId,- unDefUnitId,- mkDefUnitId,-- -- * OpenModule- OpenModule(..),- openModuleFreeHoles,-- -- * OpenModuleSubst- OpenModuleSubst,- dispOpenModuleSubst,- dispOpenModuleSubstEntry,- parsecOpenModuleSubst,- parsecOpenModuleSubstEntry,- openModuleSubstFreeHoles,-- -- * Conversions to 'UnitId'- abstractUnitId,- hashModuleSubst,-) where--import Distribution.Compat.Prelude hiding (mod)-import Distribution.Parsec-import Distribution.Pretty-import Prelude ()-import Text.PrettyPrint (hcat)--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp--import Distribution.ModuleName-import Distribution.Types.ComponentId-import Distribution.Types.Module-import Distribution.Types.UnitId-import Distribution.Utils.Base62--import qualified Data.Map as Map-import qualified Data.Set as Set---------------------------------------------------------------------------- OpenUnitId---- | An 'OpenUnitId' describes a (possibly partially) instantiated--- Backpack component, with a description of how the holes are filled--- in. Unlike 'OpenUnitId', the 'ModuleSubst' is kept in a structured--- form that allows for substitution (which fills in holes.) This form--- of unit cannot be installed. It must first be converted to a--- 'UnitId'.------ In the absence of Backpack, there are no holes to fill, so any such--- component always has an empty module substitution; thus we can lossly--- represent it as an 'OpenUnitId uid'.------ For a source component using Backpack, however, there is more--- structure as components may be parametrized over some signatures, and--- these \"holes\" may be partially or wholly filled.------ OpenUnitId plays an important role when we are mix-in linking,--- and is recorded to the installed packaged database for indefinite--- packages; however, for compiled packages that are fully instantiated,--- we instantiate 'OpenUnitId' into 'UnitId'.------ For more details see the Backpack spec--- <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-----data OpenUnitId- -- | Identifies a component which may have some unfilled holes;- -- specifying its 'ComponentId' and its 'OpenModuleSubst'.- -- TODO: Invariant that 'OpenModuleSubst' is non-empty?- -- See also the Text instance.- = IndefFullUnitId ComponentId OpenModuleSubst- -- | Identifies a fully instantiated component, which has- -- been compiled and abbreviated as a hash. The embedded 'UnitId'- -- MUST NOT be for an indefinite component; an 'OpenUnitId'- -- is guaranteed not to have any holes.- | DefiniteUnitId DefUnitId- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)--- TODO: cache holes?--instance Binary OpenUnitId-instance Structured OpenUnitId -instance NFData OpenUnitId where- rnf (IndefFullUnitId cid subst) = rnf cid `seq` rnf subst- rnf (DefiniteUnitId uid) = rnf uid--instance Pretty OpenUnitId where- pretty (IndefFullUnitId cid insts)- -- TODO: arguably a smart constructor to enforce invariant would be- -- better- | Map.null insts = pretty cid- | otherwise = pretty cid <<>> Disp.brackets (dispOpenModuleSubst insts)- pretty (DefiniteUnitId uid) = pretty uid---- |------ >>> eitherParsec "foobar" :: Either String OpenUnitId---Right (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "foobar"}))------ >>> eitherParsec "foo[Str=text-1.2.3:Data.Text.Text]" :: Either String OpenUnitId--- Right (IndefFullUnitId (ComponentId "foo") (fromList [(ModuleName "Str",OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "text-1.2.3"})) (ModuleName "Data.Text.Text"))]))----instance Parsec OpenUnitId where- parsec = P.try parseOpenUnitId <|> fmap DefiniteUnitId parsec- where- parseOpenUnitId = do- cid <- parsec- insts <- P.between (P.char '[') (P.char ']')- parsecOpenModuleSubst- return (IndefFullUnitId cid insts)---- | Get the set of holes ('ModuleVar') embedded in a 'UnitId'.-openUnitIdFreeHoles :: OpenUnitId -> Set ModuleName-openUnitIdFreeHoles (IndefFullUnitId _ insts) = openModuleSubstFreeHoles insts-openUnitIdFreeHoles _ = Set.empty---- | Safe constructor from a UnitId. The only way to do this safely--- is if the instantiation is provided.-mkOpenUnitId :: UnitId -> ComponentId -> OpenModuleSubst -> OpenUnitId-mkOpenUnitId uid cid insts =- if Set.null (openModuleSubstFreeHoles insts)- then DefiniteUnitId (unsafeMkDefUnitId uid) -- invariant holds!- else IndefFullUnitId cid insts---------------------------------------------------------------------------- DefUnitId---- | Create a 'DefUnitId' from a 'ComponentId' and an instantiation--- with no holes.-mkDefUnitId :: ComponentId -> Map ModuleName Module -> DefUnitId-mkDefUnitId cid insts =- unsafeMkDefUnitId (mkUnitId- (unComponentId cid ++ maybe "" ("+"++) (hashModuleSubst insts)))- -- impose invariant!---------------------------------------------------------------------------- OpenModule---- | Unlike a 'Module', an 'OpenModule' is either an ordinary--- module from some unit, OR an 'OpenModuleVar', representing a--- hole that needs to be filled in. Substitutions are over--- module variables.-data OpenModule- = OpenModule OpenUnitId ModuleName- | OpenModuleVar ModuleName- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)--instance Binary OpenModule-instance Structured OpenModule--instance NFData OpenModule where- rnf (OpenModule uid mod_name) = rnf uid `seq` rnf mod_name- rnf (OpenModuleVar mod_name) = rnf mod_name--instance Pretty OpenModule where- pretty (OpenModule uid mod_name) =- hcat [pretty uid, Disp.text ":", pretty mod_name]- pretty (OpenModuleVar mod_name) =- hcat [Disp.char '<', pretty mod_name, Disp.char '>']---- |------ >>> eitherParsec "Includes2-0.1.0.0-inplace-mysql:Database.MySQL" :: Either String OpenModule--- Right (OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "Includes2-0.1.0.0-inplace-mysql"})) (ModuleName "Database.MySQL"))----instance Parsec OpenModule where- parsec = parsecModuleVar <|> parsecOpenModule- where- parsecOpenModule = do- uid <- parsec- _ <- P.char ':'- mod_name <- parsec- return (OpenModule uid mod_name)-- parsecModuleVar = do- _ <- P.char '<'- mod_name <- parsec- _ <- P.char '>'- return (OpenModuleVar mod_name)---- | Get the set of holes ('ModuleVar') embedded in a 'Module'.-openModuleFreeHoles :: OpenModule -> Set ModuleName-openModuleFreeHoles (OpenModuleVar mod_name) = Set.singleton mod_name-openModuleFreeHoles (OpenModule uid _n) = openUnitIdFreeHoles uid---------------------------------------------------------------------------- OpenModuleSubst---- | An explicit substitution on modules.------ NB: These substitutions are NOT idempotent, for example, a--- valid substitution is (A -> B, B -> A).-type OpenModuleSubst = Map ModuleName OpenModule---- | Pretty-print the entries of a module substitution, suitable--- for embedding into a 'OpenUnitId' or passing to GHC via @--instantiate-with@.-dispOpenModuleSubst :: OpenModuleSubst -> Disp.Doc-dispOpenModuleSubst subst- = Disp.hcat- . Disp.punctuate Disp.comma- $ map dispOpenModuleSubstEntry (Map.toAscList subst)---- | Pretty-print a single entry of a module substitution.-dispOpenModuleSubstEntry :: (ModuleName, OpenModule) -> Disp.Doc-dispOpenModuleSubstEntry (k, v) = pretty k <<>> Disp.char '=' <<>> pretty v---- | Inverse to 'dispModSubst'.------ @since 2.2-parsecOpenModuleSubst :: CabalParsing m => m OpenModuleSubst-parsecOpenModuleSubst = fmap Map.fromList- . flip P.sepBy (P.char ',')- $ parsecOpenModuleSubstEntry---- | Inverse to 'dispModSubstEntry'.------ @since 2.2-parsecOpenModuleSubstEntry :: CabalParsing m => m (ModuleName, OpenModule)-parsecOpenModuleSubstEntry =- do k <- parsec- _ <- P.char '='- v <- parsec- return (k, v)---- | Get the set of holes ('ModuleVar') embedded in a 'OpenModuleSubst'.--- This is NOT the domain of the substitution.-openModuleSubstFreeHoles :: OpenModuleSubst -> Set ModuleName-openModuleSubstFreeHoles insts = Set.unions (map openModuleFreeHoles (Map.elems insts))---------------------------------------------------------------------------- Conversions to UnitId---- | When typechecking, we don't demand that a freshly instantiated--- 'IndefFullUnitId' be compiled; instead, we just depend on the--- installed indefinite unit installed at the 'ComponentId'.-abstractUnitId :: OpenUnitId -> UnitId-abstractUnitId (DefiniteUnitId def_uid) = unDefUnitId def_uid-abstractUnitId (IndefFullUnitId cid _) = newSimpleUnitId cid---- | Take a module substitution and hash it into a string suitable for--- 'UnitId'. Note that since this takes 'Module', not 'OpenModule',--- you are responsible for recursively converting 'OpenModule'--- into 'Module'. See also "Distribution.Backpack.ReadyComponent".-hashModuleSubst :: Map ModuleName Module -> Maybe String-hashModuleSubst subst- | Map.null subst = Nothing- | otherwise =- Just . hashToBase62 $- concat [ prettyShow mod_name ++ "=" ++ prettyShow m ++ "\n"- | (mod_name, m) <- Map.toList subst]
− Distribution/Backpack/ComponentsGraph.hs
@@ -1,97 +0,0 @@--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.ComponentsGraph (- ComponentsGraph,- ComponentsWithDeps,- mkComponentsGraph,- componentsGraphToList,- dispComponentsWithDeps,- componentCycleMsg-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Package-import Distribution.PackageDescription-import Distribution.Simple.BuildToolDepends-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.ComponentRequestedSpec-import Distribution.Compat.Graph (Graph, Node(..))-import qualified Distribution.Compat.Graph as Graph-import qualified Distribution.Compat.NonEmptySet as NES-import Distribution.Utils.Generic--import Distribution.Pretty (pretty)-import Text.PrettyPrint----------------------------------------------------------------------------------- Components graph----------------------------------------------------------------------------------- | A graph of source-level components by their source-level--- dependencies----type ComponentsGraph = Graph (Node ComponentName Component)---- | A list of components associated with the source level--- dependencies between them.----type ComponentsWithDeps = [(Component, [ComponentName])]---- | Pretty-print 'ComponentsWithDeps'.----dispComponentsWithDeps :: ComponentsWithDeps -> Doc-dispComponentsWithDeps graph =- vcat [ hang (text "component" <+> pretty (componentName c)) 4- (vcat [ text "dependency" <+> pretty cdep | cdep <- cdeps ])- | (c, cdeps) <- graph ]---- | Create a 'Graph' of 'Component', or report a cycle if there is a--- problem.----mkComponentsGraph :: ComponentRequestedSpec- -> PackageDescription- -> Either [ComponentName] ComponentsGraph-mkComponentsGraph enabled pkg_descr =- let g = Graph.fromDistinctList- [ N c (componentName c) (componentDeps c)- | c <- pkgBuildableComponents pkg_descr- , componentEnabled enabled c ]- in case Graph.cycles g of- [] -> Right g- ccycles -> Left [ componentName c | N c _ _ <- concat ccycles ]- where- -- The dependencies for the given component- componentDeps component =- toolDependencies ++ libDependencies- where- bi = componentBuildInfo component-- toolDependencies = CExeName <$> getAllInternalToolDependencies pkg_descr bi-- libDependencies = do- Dependency pkgname _ lns <- targetBuildDepends bi- guard (pkgname == packageName pkg_descr)-- ln <- NES.toList lns- return (CLibName ln)---- | Given the package description and a 'PackageDescription' (used--- to determine if a package name is internal or not), sort the--- components in dependency order (fewest dependencies first). This is--- NOT necessarily the build order (although it is in the absence of--- Backpack.)----componentsGraphToList :: ComponentsGraph- -> ComponentsWithDeps-componentsGraphToList =- map (\(N c _ cs) -> (c, cs)) . Graph.revTopSort---- | Error message when there is a cycle; takes the SCC of components.-componentCycleMsg :: PackageIdentifier -> [ComponentName] -> Doc-componentCycleMsg pn cnames =- text "Components in the package" <+> pretty pn <+> text "depend on each other in a cyclic way:"- $$- text (intercalate " depends on "- [ "'" ++ showComponentName cname ++ "'"- | cname <- cnames ++ maybeToList (safeHead cnames) ])
− Distribution/Backpack/Configure.hs
@@ -1,359 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE NoMonoLocalBinds #-}-{-# LANGUAGE NondecreasingIndentation #-}---- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>------ WARNING: The contents of this module are HIGHLY experimental.--- We may refactor it under you.-module Distribution.Backpack.Configure (- configureComponentLocalBuildInfos,-) where--import Prelude ()-import Distribution.Compat.Prelude hiding ((<>))--import Distribution.Backpack-import Distribution.Backpack.FullUnitId-import Distribution.Backpack.PreExistingComponent-import Distribution.Backpack.ConfiguredComponent-import Distribution.Backpack.LinkedComponent-import Distribution.Backpack.ReadyComponent-import Distribution.Backpack.ComponentsGraph-import Distribution.Backpack.Id--import Distribution.Simple.Compiler-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-import Distribution.ModuleName-import Distribution.Simple.Setup as Setup-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.AnnotatedId-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.ComponentInclude-import Distribution.Types.MungedPackageName-import Distribution.Verbosity-import qualified Distribution.Compat.Graph as Graph-import Distribution.Compat.Graph (Graph, IsNode(..))-import Distribution.Utils.LogProgress--import Data.Either- ( lefts )-import qualified Data.Set as Set-import qualified Data.Map as Map-import Distribution.Pretty-import Text.PrettyPrint----------------------------------------------------------------------------------- Pipeline---------------------------------------------------------------------------------configureComponentLocalBuildInfos- :: Verbosity- -> Bool -- use_external_internal_deps- -> ComponentRequestedSpec- -> Bool -- deterministic- -> Flag String -- configIPID- -> Flag ComponentId -- configCID- -> PackageDescription- -> [PreExistingComponent]- -> FlagAssignment -- configConfigurationsFlags- -> [(ModuleName, Module)] -- configInstantiateWith- -> InstalledPackageIndex- -> Compiler- -> LogProgress ([ComponentLocalBuildInfo], InstalledPackageIndex)-configureComponentLocalBuildInfos- verbosity use_external_internal_deps enabled deterministic ipid_flag cid_flag pkg_descr- prePkgDeps flagAssignment instantiate_with installedPackageSet comp = do- -- NB: In single component mode, this returns a *single* component.- -- In this graph, the graph is NOT closed.- graph0 <- case mkComponentsGraph enabled pkg_descr of- Left ccycle -> dieProgress (componentCycleMsg (package pkg_descr) ccycle)- Right g -> return (componentsGraphToList g)- infoProgress $ hang (text "Source component graph:") 4- (dispComponentsWithDeps graph0)-- let conf_pkg_map = Map.fromListWith Map.union- [(pc_pkgname pkg,- Map.singleton (pc_compname pkg)- (AnnotatedId {- ann_id = pc_cid pkg,- ann_pid = packageId pkg,- ann_cname = pc_compname pkg- }))- | pkg <- prePkgDeps]- graph1 <- toConfiguredComponents use_external_internal_deps- flagAssignment- deterministic ipid_flag cid_flag pkg_descr- conf_pkg_map (map fst graph0)- infoProgress $ hang (text "Configured component graph:") 4- (vcat (map dispConfiguredComponent graph1))-- let shape_pkg_map = Map.fromList- [ (pc_cid pkg, (pc_open_uid pkg, pc_shape pkg))- | pkg <- prePkgDeps]- uid_lookup def_uid- | Just pkg <- PackageIndex.lookupUnitId installedPackageSet uid- = FullUnitId (Installed.installedComponentId pkg)- (Map.fromList (Installed.instantiatedWith pkg))- | otherwise = error ("uid_lookup: " ++ prettyShow uid)- where uid = unDefUnitId def_uid- graph2 <- toLinkedComponents verbosity uid_lookup- (package pkg_descr) shape_pkg_map graph1-- infoProgress $- hang (text "Linked component graph:") 4- (vcat (map dispLinkedComponent graph2))-- let pid_map = Map.fromList $- [ (pc_uid pkg, pc_munged_id pkg)- | pkg <- prePkgDeps] ++- [ (Installed.installedUnitId pkg, mungedId pkg)- | (_, Module uid _) <- instantiate_with- , Just pkg <- [PackageIndex.lookupUnitId- installedPackageSet (unDefUnitId uid)] ]- subst = Map.fromList instantiate_with- graph3 = toReadyComponents pid_map subst graph2- graph4 = Graph.revTopSort (Graph.fromDistinctList graph3)-- infoProgress $ hang (text "Ready component graph:") 4- (vcat (map dispReadyComponent graph4))-- toComponentLocalBuildInfos comp installedPackageSet pkg_descr prePkgDeps graph4----------------------------------------------------------------------------------- ComponentLocalBuildInfo---------------------------------------------------------------------------------toComponentLocalBuildInfos- :: Compiler- -> InstalledPackageIndex -- FULL set- -> PackageDescription- -> [PreExistingComponent] -- external package deps- -> [ReadyComponent]- -> LogProgress ([ComponentLocalBuildInfo],- InstalledPackageIndex) -- only relevant packages-toComponentLocalBuildInfos- comp installedPackageSet pkg_descr externalPkgDeps graph = do- -- Check and make sure that every instantiated component exists.- -- We have to do this now, because prior to linking/instantiating- -- we don't actually know what the full set of 'UnitId's we need- -- are.- let -- TODO: This is actually a bit questionable performance-wise,- -- since we will pay for the ALL installed packages even if- -- they are not related to what we are building. This was true- -- in the old configure code.- external_graph :: Graph (Either InstalledPackageInfo ReadyComponent)- external_graph = Graph.fromDistinctList- . map Left- $ PackageIndex.allPackages installedPackageSet- internal_graph :: Graph (Either InstalledPackageInfo ReadyComponent)- internal_graph = Graph.fromDistinctList- . map Right- $ graph- combined_graph = Graph.unionRight external_graph internal_graph- local_graph = fromMaybe (error "toComponentLocalBuildInfos: closure returned Nothing")- $ Graph.closure combined_graph (map nodeKey graph)- -- The database of transitively reachable installed packages that the- -- external components the package (as a whole) depends on. This will be- -- used in several ways:- --- -- * We'll use it to do a consistency check so we're not depending- -- on multiple versions of the same package (TODO: someday relax- -- this for private dependencies.) See right below.- --- -- * We'll pass it on in the LocalBuildInfo, where preprocessors- -- and other things will incorrectly use it to determine what- -- the include paths and everything should be.- --- packageDependsIndex = PackageIndex.fromList (lefts local_graph)- fullIndex = Graph.fromDistinctList local_graph- case Graph.broken fullIndex of- [] -> return ()- broken ->- -- TODO: ppr this- dieProgress . text $- "The following packages are broken because other"- ++ " packages they depend on are missing. These broken "- ++ "packages must be rebuilt before they can be used.\n"- -- TODO: Undupe.- ++ unlines [ "installed package "- ++ prettyShow (packageId pkg)- ++ " is broken due to missing package "- ++ intercalate ", " (map prettyShow deps)- | (Left pkg, deps) <- broken ]- ++ unlines [ "planned package "- ++ prettyShow (packageId pkg)- ++ " is broken due to missing package "- ++ intercalate ", " (map prettyShow deps)- | (Right pkg, deps) <- broken ]-- -- In this section, we'd like to look at the 'packageDependsIndex'- -- and see if we've picked multiple versions of the same- -- installed package (this is bad, because it means you might- -- get an error could not match foo-0.1:Type with foo-0.2:Type).- --- -- What is pseudoTopPkg for? I have no idea. It was used- -- in the very original commit which introduced checking for- -- inconsistencies 5115bb2be4e13841ea07dc9166b9d9afa5f0d012,- -- and then moved out of PackageIndex and put here later.- -- TODO: Try this code without it...- --- -- TODO: Move this into a helper function- --- -- TODO: This is probably wrong for Backpack- let pseudoTopPkg :: InstalledPackageInfo- pseudoTopPkg = emptyInstalledPackageInfo {- Installed.installedUnitId = mkLegacyUnitId (packageId pkg_descr),- Installed.sourcePackageId = packageId pkg_descr,- Installed.depends = map pc_uid externalPkgDeps- }- case PackageIndex.dependencyInconsistencies- . PackageIndex.insert pseudoTopPkg- $ packageDependsIndex of- [] -> return ()- inconsistencies ->- warnProgress $- hang (text "This package indirectly depends on multiple versions of the same" <+>- text "package. This is very likely to cause a compile failure.") 2- (vcat [ text "package" <+> pretty (packageName user) <+>- parens (pretty (installedUnitId user)) <+> text "requires" <+>- pretty inst- | (_dep_key, insts) <- inconsistencies- , (inst, users) <- insts- , user <- users ])- let clbis = mkLinkedComponentsLocalBuildInfo comp graph- -- forM clbis $ \(clbi,deps) -> info verbosity $ "UNIT" ++ hashUnitId (componentUnitId clbi) ++ "\n" ++ intercalate "\n" (map hashUnitId deps)- return (clbis, packageDependsIndex)---- Build ComponentLocalBuildInfo for each component we are going--- to build.------ This conversion is lossy; we lose some invariants from ReadyComponent-mkLinkedComponentsLocalBuildInfo- :: Compiler- -> [ReadyComponent]- -> [ComponentLocalBuildInfo]-mkLinkedComponentsLocalBuildInfo comp rcs = map go rcs- where- internalUnits = Set.fromList (map rc_uid rcs)- isInternal x = Set.member x internalUnits- go rc =- case rc_component rc of- CLib lib ->- let convModuleExport (modname', (Module uid modname))- | this_uid == unDefUnitId uid- , modname' == modname- = Installed.ExposedModule modname' Nothing- | otherwise- = Installed.ExposedModule modname'- (Just (OpenModule (DefiniteUnitId uid) modname))- convOpenModuleExport (modname', modu@(OpenModule uid modname))- | uid == this_open_uid- , modname' == modname- = Installed.ExposedModule modname' Nothing- | otherwise- = Installed.ExposedModule modname' (Just modu)- convOpenModuleExport (_, OpenModuleVar _)- = error "convOpenModuleExport: top-level modvar"- exports =- -- Loses invariants- case rc_i rc of- Left indefc -> map convOpenModuleExport- $ Map.toList (indefc_provides indefc)- Right instc -> map convModuleExport- $ Map.toList (instc_provides instc)- insts =- case rc_i rc of- Left indefc -> [ (m, OpenModuleVar m) | m <- indefc_requires indefc ]- Right instc -> [ (m, OpenModule (DefiniteUnitId uid') m')- | (m, Module uid' m') <- instc_insts instc ]-- compat_name = MungedPackageName (packageName rc) (libName lib)- compat_key = computeCompatPackageKey comp compat_name (packageVersion rc) this_uid-- in LibComponentLocalBuildInfo {- componentPackageDeps = cpds,- componentUnitId = this_uid,- componentComponentId = this_cid,- componentInstantiatedWith = insts,- componentIsIndefinite_ = is_indefinite,- componentLocalName = cname,- componentInternalDeps = internal_deps,- componentExeDeps = exe_deps,- componentIncludes = includes,- componentExposedModules = exports,- componentIsPublic = rc_public rc,- componentCompatPackageKey = compat_key,- componentCompatPackageName = compat_name- }- CFLib _ ->- FLibComponentLocalBuildInfo {- componentUnitId = this_uid,- componentComponentId = this_cid,- componentLocalName = cname,- componentPackageDeps = cpds,- componentExeDeps = exe_deps,- componentInternalDeps = internal_deps,- componentIncludes = includes- }- CExe _ ->- ExeComponentLocalBuildInfo {- componentUnitId = this_uid,- componentComponentId = this_cid,- componentLocalName = cname,- componentPackageDeps = cpds,- componentExeDeps = exe_deps,- componentInternalDeps = internal_deps,- componentIncludes = includes- }- CTest _ ->- TestComponentLocalBuildInfo {- componentUnitId = this_uid,- componentComponentId = this_cid,- componentLocalName = cname,- componentPackageDeps = cpds,- componentExeDeps = exe_deps,- componentInternalDeps = internal_deps,- componentIncludes = includes- }- CBench _ ->- BenchComponentLocalBuildInfo {- componentUnitId = this_uid,- componentComponentId = this_cid,- componentLocalName = cname,- componentPackageDeps = cpds,- componentExeDeps = exe_deps,- componentInternalDeps = internal_deps,- componentIncludes = includes- }- where- this_uid = rc_uid rc- this_open_uid = rc_open_uid rc- this_cid = rc_cid rc- cname = componentName (rc_component rc)- cpds = rc_depends rc- exe_deps = map ann_id $ rc_exe_deps rc- is_indefinite =- case rc_i rc of- Left _ -> True- Right _ -> False- includes =- map (\ci -> (ci_id ci, ci_renaming ci)) $- case rc_i rc of- Left indefc ->- indefc_includes indefc- Right instc ->- map (\ci -> ci { ci_ann_id = fmap DefiniteUnitId (ci_ann_id ci) })- (instc_includes instc)- internal_deps = filter isInternal (nodeNeighbors rc)
− Distribution/Backpack/ConfiguredComponent.hs
@@ -1,308 +0,0 @@-{-# LANGUAGE PatternGuards #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.ConfiguredComponent (- ConfiguredComponent(..),- cc_name,- cc_cid,- cc_pkgid,- toConfiguredComponent,- toConfiguredComponents,- dispConfiguredComponent,-- ConfiguredComponentMap,- extendConfiguredComponentMap,-- -- TODO: Should go somewhere else- newPackageDepsBehaviour-) where--import Prelude ()-import Distribution.Compat.Prelude hiding ((<>))--import Distribution.Backpack.Id--import Distribution.CabalSpecVersion-import Distribution.Types.AnnotatedId-import Distribution.Types.Dependency-import Distribution.Types.ExeDependency-import Distribution.Types.IncludeRenaming-import Distribution.Types.ComponentId-import Distribution.Types.PackageId-import Distribution.Types.PackageName-import Distribution.Types.Mixin-import Distribution.Types.ComponentName-import Distribution.Types.LibraryName-import Distribution.Types.ComponentInclude-import Distribution.Package-import Distribution.PackageDescription-import Distribution.Simple.BuildToolDepends-import Distribution.Simple.Setup as Setup-import Distribution.Simple.LocalBuildInfo-import Distribution.Utils.LogProgress-import Distribution.Utils.MapAccum-import Distribution.Utils.Generic--import Control.Monad-import qualified Data.Set as Set-import qualified Distribution.Compat.NonEmptySet as NonEmptySet-import qualified Data.Map as Map-import Distribution.Pretty-import Text.PrettyPrint (Doc, hang, text, vcat, hsep, quotes, ($$))-import qualified Text.PrettyPrint as PP---- | A configured component, we know exactly what its 'ComponentId' is,--- and the 'ComponentId's of the things it depends on.-data ConfiguredComponent- = ConfiguredComponent {- -- | Unique identifier of component, plus extra useful info.- cc_ann_id :: AnnotatedId ComponentId,- -- | The fragment of syntax from the Cabal file describing this- -- component.- cc_component :: Component,- -- | Is this the public library component of the package?- -- (If we invoke Setup with an instantiation, this is the- -- component the instantiation applies to.)- -- Note that in one-component configure mode, this is- -- always True, because any component is the "public" one.)- cc_public :: Bool,- -- | Dependencies on executables from @build-tools@ and- -- @build-tool-depends@.- cc_exe_deps :: [AnnotatedId ComponentId],- -- | The mixins of this package, including both explicit (from- -- the @mixins@ field) and implicit (from @build-depends@). Not- -- mix-in linked yet; component configuration only looks at- -- 'ComponentId's.- cc_includes :: [ComponentInclude ComponentId IncludeRenaming]- }----- | Uniquely identifies a configured component.-cc_cid :: ConfiguredComponent -> ComponentId-cc_cid = ann_id . cc_ann_id---- | The package this component came from.-cc_pkgid :: ConfiguredComponent -> PackageId-cc_pkgid = ann_pid . cc_ann_id---- | The 'ComponentName' of a component; this uniquely identifies--- a fragment of syntax within a specified Cabal file describing the--- component.-cc_name :: ConfiguredComponent -> ComponentName-cc_name = ann_cname . cc_ann_id---- | Pretty-print a 'ConfiguredComponent'.-dispConfiguredComponent :: ConfiguredComponent -> Doc-dispConfiguredComponent cc =- hang (text "component" <+> pretty (cc_cid cc)) 4- (vcat [ hsep $ [ text "include"- , pretty (ci_id incl), pretty (ci_renaming incl) ]- | incl <- cc_includes cc- ])---- | Construct a 'ConfiguredComponent', given that the 'ComponentId'--- and library/executable dependencies are known. The primary--- work this does is handling implicit @backpack-include@ fields.-mkConfiguredComponent- :: PackageDescription- -> ComponentId- -> [AnnotatedId ComponentId] -- lib deps- -> [AnnotatedId ComponentId] -- exe deps- -> Component- -> LogProgress ConfiguredComponent-mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do- -- Resolve each @mixins@ into the actual dependency- -- from @lib_deps@.- explicit_includes <- forM (mixins bi) $ \(Mixin pn ln rns) -> do- aid <- case Map.lookup (pn, CLibName ln) deps_map of- Nothing ->- dieProgress $- text "Mix-in refers to non-existent library" <+>- quotes (pretty pn <<>> prettyLN ln) $$- text "(did you forget to add the package to build-depends?)"- Just r -> return r- return ComponentInclude {- ci_ann_id = aid,- ci_renaming = rns,- ci_implicit = False- }-- -- Any @build-depends@ which is not explicitly mentioned in- -- @backpack-include@ is converted into an "implicit" include.- let used_explicitly = Set.fromList (map ci_id explicit_includes)- implicit_includes- = map (\aid -> ComponentInclude {- ci_ann_id = aid,- ci_renaming = defaultIncludeRenaming,- ci_implicit = True- })- $ filter (flip Set.notMember used_explicitly . ann_id) lib_deps-- return ConfiguredComponent {- cc_ann_id = AnnotatedId {- ann_id = this_cid,- ann_pid = package pkg_descr,- ann_cname = componentName component- },- cc_component = component,- cc_public = is_public,- cc_exe_deps = exe_deps,- cc_includes = explicit_includes ++ implicit_includes- }- where- bi :: BuildInfo- bi = componentBuildInfo component-- prettyLN :: LibraryName -> Doc- prettyLN LMainLibName = PP.empty- prettyLN (LSubLibName n) = PP.colon <<>> pretty n-- deps_map :: Map (PackageName, ComponentName) (AnnotatedId ComponentId)- deps_map = Map.fromList [ ((packageName dep, ann_cname dep), dep)- | dep <- lib_deps ]-- is_public = componentName component == CLibName LMainLibName--type ConfiguredComponentMap =- Map PackageName (Map ComponentName (AnnotatedId ComponentId))--toConfiguredComponent- :: PackageDescription- -> ComponentId- -> ConfiguredComponentMap- -> ConfiguredComponentMap- -> Component- -> LogProgress ConfiguredComponent-toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do- lib_deps <-- if newPackageDepsBehaviour pkg_descr- then fmap concat $ forM (targetBuildDepends bi) $- \(Dependency name _ sublibs) -> do- pkg <- case Map.lookup name lib_dep_map of- Nothing ->- dieProgress $- text "Dependency on unbuildable" <+>- text "package" <+> pretty name- Just p -> return p- -- Return all library components- forM (NonEmptySet.toList sublibs) $ \lib ->- let comp = CLibName lib in- case Map.lookup comp pkg of- Nothing ->- dieProgress $- text "Dependency on unbuildable" <+>- text (showLibraryName lib) <+>- text "from" <+> pretty name- Just v -> return v- else return old_style_lib_deps- mkConfiguredComponent- pkg_descr this_cid- lib_deps exe_deps component- where- bi = componentBuildInfo component- -- lib_dep_map contains a mix of internal and external deps.- -- We want all the public libraries (dep_cn == CLibName)- -- of all external deps (dep /= pn). Note that this- -- excludes the public library of the current package:- -- this is not supported by old-style deps behavior- -- because it would imply a cyclic dependency for the- -- library itself.- old_style_lib_deps = [ e- | (pn, comp_map) <- Map.toList lib_dep_map- , pn /= packageName pkg_descr- , (cn, e) <- Map.toList comp_map- , cn == CLibName LMainLibName ]- -- We have to nub here, because 'getAllToolDependencies' may return- -- duplicates (see #4986). (NB: This is not needed for lib_deps,- -- since those elaborate into includes, for which there explicitly- -- may be multiple instances of a package)- exe_deps = ordNub $- [ exe- | ExeDependency pn cn _ <- getAllToolDependencies pkg_descr bi- -- The error suppression here is important, because in general- -- we won't know about external dependencies (e.g., 'happy')- -- which the package is attempting to use (those deps are only- -- fed in when cabal-install uses this codepath.)- -- TODO: Let cabal-install request errors here- , Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup pn exe_dep_map]- ]---- | Also computes the 'ComponentId', and sets cc_public if necessary.--- This is Cabal-only; cabal-install won't use this.-toConfiguredComponent'- :: Bool -- use_external_internal_deps- -> FlagAssignment- -> PackageDescription- -> Bool -- deterministic- -> Flag String -- configIPID (todo: remove me)- -> Flag ComponentId -- configCID- -> ConfiguredComponentMap- -> Component- -> LogProgress ConfiguredComponent-toConfiguredComponent' use_external_internal_deps flags- pkg_descr deterministic ipid_flag cid_flag- dep_map component = do- cc <- toConfiguredComponent- pkg_descr this_cid- dep_map dep_map component- return $ if use_external_internal_deps- then cc { cc_public = True }- else cc- where- -- TODO: pass component names to it too!- this_cid = computeComponentId deterministic ipid_flag cid_flag- (package pkg_descr) (componentName component) (Just (deps, flags))- deps = [ ann_id aid | m <- Map.elems dep_map- , aid <- Map.elems m ]--extendConfiguredComponentMap- :: ConfiguredComponent- -> ConfiguredComponentMap- -> ConfiguredComponentMap-extendConfiguredComponentMap cc =- Map.insertWith Map.union- (pkgName (cc_pkgid cc))- (Map.singleton (cc_name cc) (cc_ann_id cc))---- Compute the 'ComponentId's for a graph of 'Component's. The--- list of internal components must be topologically sorted--- based on internal package dependencies, so that any internal--- dependency points to an entry earlier in the list.------ TODO: This function currently restricts the input configured components to--- one version per package, by using the type ConfiguredComponentMap. It cannot--- be used to configure a component that depends on one version of a package for--- a library and another version for a build-tool.-toConfiguredComponents- :: Bool -- use_external_internal_deps- -> FlagAssignment- -> Bool -- deterministic- -> Flag String -- configIPID- -> Flag ComponentId -- configCID- -> PackageDescription- -> ConfiguredComponentMap- -> [Component]- -> LogProgress [ConfiguredComponent]-toConfiguredComponents- use_external_internal_deps flags deterministic ipid_flag cid_flag pkg_descr- dep_map comps- = fmap snd (mapAccumM go dep_map comps)- where- go m component = do- cc <- toConfiguredComponent'- use_external_internal_deps flags pkg_descr- deterministic ipid_flag cid_flag- m component- return (extendConfiguredComponentMap cc m, cc)--newPackageDepsBehaviourMinVersion :: CabalSpecVersion-newPackageDepsBehaviourMinVersion = CabalSpecV1_8----- 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
− Distribution/Backpack/DescribeUnitId.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE Rank2Types #-}-module Distribution.Backpack.DescribeUnitId where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Compat.Stack-import Distribution.ModuleName-import Distribution.Pretty-import Distribution.Simple.Utils-import Distribution.Types.ComponentName-import Distribution.Types.PackageId-import Distribution.Verbosity--import Text.PrettyPrint---- Unit identifiers have a well defined, machine-readable format,--- but this format isn't very user-friendly for users. This--- module defines some functions for solving common rendering--- problems one has for displaying these.------ There are three basic problems we tackle:------ - Users don't want to see pkg-0.5-inplace-libname,--- they want to see "library 'libname' from 'pkg-0.5'"------ - Users don't want to see the raw component identifier, which--- usually contains a wordy hash that doesn't matter.------ - Users don't want to see a hash of the instantiation: they--- want to see the actual instantiation, and they want it in--- interpretable form.------- | Print a Setup message stating (1) what operation we are doing,--- for (2) which component (with enough details to uniquely identify--- the build in question.)----setupMessage' :: Pretty a => Verbosity- -> String -- ^ Operation being done (capitalized), on:- -> PackageIdentifier -- ^ Package- -> ComponentName -- ^ Component name- -> Maybe [(ModuleName, a)] -- ^ Instantiation, if available.- -- Polymorphic to take- -- 'OpenModule' or 'Module'- -> IO ()-setupMessage' verbosity msg pkgid cname mb_insts = withFrozenCallStack $ do- noticeDoc verbosity $- case mb_insts of- Just insts | not (null insts) ->- hang (msg_doc <+> text "instantiated with") 2- (vcat [ pretty k <+> text "=" <+> pretty v- | (k,v) <- insts ]) $$- for_doc- _ ->- msg_doc <+> for_doc-- where- msg_doc = text msg <+> text (showComponentName cname)- for_doc = text "for" <+> pretty pkgid <<>> text ".."
− Distribution/Backpack/FullUnitId.hs
@@ -1,26 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Backpack.FullUnitId (- FullUnitId(..),- FullDb,- expandOpenUnitId,- expandUnitId-) where--import Distribution.Backpack-import Distribution.Types.ComponentId-import Distribution.Compat.Prelude---- Unlike OpenUnitId, which could direct to a UnitId.-data FullUnitId = FullUnitId ComponentId OpenModuleSubst- deriving (Show, Generic)--type FullDb = DefUnitId -> FullUnitId--expandOpenUnitId :: FullDb -> OpenUnitId -> FullUnitId-expandOpenUnitId _db (IndefFullUnitId cid subst)- = FullUnitId cid subst-expandOpenUnitId db (DefiniteUnitId uid)- = expandUnitId db uid--expandUnitId :: FullDb -> DefUnitId -> FullUnitId-expandUnitId db uid = db uid
− Distribution/Backpack/Id.hs
@@ -1,145 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE PatternGuards #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.Id(- computeComponentId,- computeCompatPackageKey,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.UnqualComponentName-import Distribution.Simple.Compiler-import Distribution.PackageDescription-import Distribution.Simple.Setup as Setup-import qualified Distribution.Simple.InstallDirs as InstallDirs-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.ComponentId-import Distribution.Types.UnitId-import Distribution.Types.MungedPackageName-import Distribution.Utils.Base62-import Distribution.Version--import Distribution.Pretty- ( prettyShow )-import Distribution.Parsec ( simpleParsec )---- | 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- :: Bool -- deterministic mode- -> Flag String- -> Flag ComponentId- -> PackageIdentifier- -> ComponentName- -- This is used by cabal-install's legacy codepath- -> Maybe ([ComponentId], FlagAssignment)- -> ComponentId-computeComponentId deterministic mb_ipid mb_cid pid cname mb_details =- -- 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_suffix- | Just (dep_ipids, flags) <- mb_details- = "-" ++ hashToBase62- -- For safety, include the package + version here- -- for GHC 7.10, where just the hash is used as- -- the package key- ( prettyShow pid- ++ show dep_ipids- ++ show flags )- | otherwise = ""- generated_base = prettyShow pid ++ hash_suffix- explicit_base cid0 = fromPathTemplate (InstallDirs.substPathTemplate env- (toPathTemplate cid0))- -- Hack to reuse install dirs machinery- -- NB: no real IPID available at this point- where env = packageTemplateEnv pid (mkUnitId "")- actual_base = case mb_ipid of- Flag ipid0 -> explicit_base ipid0- NoFlag | deterministic -> prettyShow pid- | otherwise -> generated_base- in case mb_cid of- Flag cid -> cid- NoFlag -> mkComponentId $ actual_base- ++ (case componentNameString cname of- Nothing -> ""- Just s -> "-" ++ unUnqualComponentName s)---- | 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:------ * We use the *compatibility* package name and version. For--- public libraries this is just the package identifier; for--- internal libraries, it's something like "z-pkgname-z-libname-0.1".--- See 'computeCompatPackageName' for more details.------ 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- -> MungedPackageName- -> Version- -> UnitId- -> String-computeCompatPackageKey comp pkg_name pkg_version uid- | not (packageKeySupported comp || unitIdSupported comp)- = prettyShow pkg_name ++ "-" ++ prettyShow pkg_version- | not (unifiedIPIDRequired comp) =- let str = unUnitId uid -- assume no Backpack support- mb_verbatim_key- = case simpleParsec 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 | prettyShow 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 fromMaybe rehashed_key (mb_verbatim_key `mplus` mb_truncated_key)- | otherwise = prettyShow uid
− Distribution/Backpack/LinkedComponent.hs
@@ -1,396 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.LinkedComponent (- LinkedComponent(..),- lc_insts,- lc_uid,- lc_cid,- lc_pkgid,- toLinkedComponent,- toLinkedComponents,- dispLinkedComponent,- LinkedComponentMap,- extendLinkedComponentMap,-) where--import Prelude ()-import Distribution.Compat.Prelude hiding ((<>))--import Distribution.Backpack-import Distribution.Backpack.FullUnitId-import Distribution.Backpack.ConfiguredComponent-import Distribution.Backpack.ModuleShape-import Distribution.Backpack.PreModuleShape-import Distribution.Backpack.ModuleScope-import Distribution.Backpack.UnifyM-import Distribution.Backpack.MixLink-import Distribution.Utils.MapAccum--import Distribution.Types.AnnotatedId-import Distribution.Types.ComponentName-import Distribution.Types.ModuleReexport-import Distribution.Types.ModuleRenaming-import Distribution.Types.IncludeRenaming-import Distribution.Types.ComponentInclude-import Distribution.Types.ComponentId-import Distribution.Types.PackageId-import Distribution.Package-import Distribution.PackageDescription-import Distribution.ModuleName-import Distribution.Simple.LocalBuildInfo-import Distribution.Verbosity-import Distribution.Utils.LogProgress--import qualified Data.Set as Set-import qualified Data.Map as Map-import Distribution.Pretty (pretty)-import Text.PrettyPrint (Doc, hang, text, vcat, ($+$), hsep, quotes)---- | A linked component is a component that has been mix-in linked, at--- which point we have determined how all the dependencies of the--- component are explicitly instantiated (in the form of an OpenUnitId).--- 'ConfiguredComponent' is mix-in linked into 'LinkedComponent', which--- is then instantiated into 'ReadyComponent'.-data LinkedComponent- = LinkedComponent {- -- | Uniquely identifies linked component- lc_ann_id :: AnnotatedId ComponentId,- -- | Corresponds to 'cc_component'.- lc_component :: Component,- -- | @build-tools@ and @build-tool-depends@ dependencies.- -- Corresponds to 'cc_exe_deps'.- lc_exe_deps :: [AnnotatedId OpenUnitId],- -- | Is this the public library of a package? Corresponds to- -- 'cc_public'.- lc_public :: Bool,- -- | Corresponds to 'cc_includes', but (1) this does not contain- -- includes of signature packages (packages with no exports),- -- and (2) the 'ModuleRenaming' for requirements (stored in- -- 'IncludeRenaming') has been removed, as it is reflected in- -- 'OpenUnitId'.)- lc_includes :: [ComponentInclude OpenUnitId ModuleRenaming],- -- | Like 'lc_includes', but this specifies includes on- -- signature packages which have no exports.- lc_sig_includes :: [ComponentInclude OpenUnitId ModuleRenaming],- -- | The module shape computed by mix-in linking. This is- -- newly computed from 'ConfiguredComponent'- lc_shape :: ModuleShape- }---- | Uniquely identifies a 'LinkedComponent'. Corresponds to--- 'cc_cid'.-lc_cid :: LinkedComponent -> ComponentId-lc_cid = ann_id . lc_ann_id---- | Corresponds to 'cc_pkgid'.-lc_pkgid :: LinkedComponent -> PackageId-lc_pkgid = ann_pid . lc_ann_id---- | The 'OpenUnitId' of this component in the "default" instantiation.--- See also 'lc_insts'. 'LinkedComponent's cannot be instantiated--- (e.g., there is no 'ModSubst' instance for them).-lc_uid :: LinkedComponent -> OpenUnitId-lc_uid lc = IndefFullUnitId (lc_cid lc) . Map.fromList $ lc_insts lc---- | The instantiation of 'lc_uid'; this always has the invariant--- that it is a mapping from a module name @A@ to @<A>@ (the hole A).-lc_insts :: LinkedComponent -> [(ModuleName, OpenModule)]-lc_insts lc = [ (req, OpenModuleVar req)- | req <- Set.toList (modShapeRequires (lc_shape lc)) ]--dispLinkedComponent :: LinkedComponent -> Doc-dispLinkedComponent lc =- hang (text "unit" <+> pretty (lc_uid lc)) 4 $- vcat [ text "include" <+> pretty (ci_id incl) <+> pretty (ci_renaming incl)- | incl <- lc_includes lc ]- $+$- vcat [ text "signature include" <+> pretty (ci_id incl)- | incl <- lc_sig_includes lc ]- $+$ dispOpenModuleSubst (modShapeProvides (lc_shape lc))--instance Package LinkedComponent where- packageId = lc_pkgid--toLinkedComponent- :: Verbosity- -> FullDb- -> PackageId- -> LinkedComponentMap- -> ConfiguredComponent- -> LogProgress LinkedComponent-toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {- cc_ann_id = aid@AnnotatedId { ann_id = this_cid },- cc_component = component,- cc_exe_deps = exe_deps,- cc_public = is_public,- cc_includes = cid_includes- } = do- let- -- The explicitly specified requirements, provisions and- -- reexports from the Cabal file. These are only non-empty for- -- libraries; everything else is trivial.- (src_reqs :: [ModuleName],- src_provs :: [ModuleName],- src_reexports :: [ModuleReexport]) =- case component of- CLib lib -> (signatures lib,- exposedModules lib,- reexportedModules lib)- _ -> ([], [], [])- src_hidden = otherModules (componentBuildInfo component)-- -- Take each included ComponentId and resolve it into an- -- *unlinked* unit identity. We will use unification (relying- -- on the ModuleShape) to resolve these into linked identities.- unlinked_includes :: [ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming]- unlinked_includes = [ ComponentInclude (fmap lookupUid dep_aid) rns i- | ComponentInclude dep_aid rns i <- cid_includes ]-- lookupUid :: ComponentId -> (OpenUnitId, ModuleShape)- lookupUid cid = fromMaybe (error "linkComponent: lookupUid")- (Map.lookup cid pkg_map)-- let orErr (Right x) = return x- orErr (Left [err]) = dieProgress err- orErr (Left errs) = do- dieProgress (vcat (intersperse (text "") -- double newline!- [ hang (text "-") 2 err | err <- errs]))-- -- Pre-shaping- let pre_shape = mixLinkPreModuleShape $- PreModuleShape {- preModShapeProvides = Set.fromList (src_provs ++ src_hidden),- preModShapeRequires = Set.fromList src_reqs- } : [ renamePreModuleShape (toPreModuleShape sh) rns- | ComponentInclude (AnnotatedId { ann_id = (_, sh) }) rns _ <- unlinked_includes ]- reqs = preModShapeRequires pre_shape- insts = [ (req, OpenModuleVar req)- | req <- Set.toList reqs ]- this_uid = IndefFullUnitId this_cid . Map.fromList $ insts-- -- OK, actually do unification- -- TODO: the unification monad might return errors, in which- -- case we have to deal. Use monadic bind for now.- (linked_shape0 :: ModuleScope,- linked_includes0 :: [ComponentInclude OpenUnitId ModuleRenaming],- linked_sig_includes0 :: [ComponentInclude OpenUnitId ModuleRenaming])- <- orErr $ runUnifyM verbosity this_cid db $ do- -- The unification monad is implemented using mutable- -- references. Thus, we must convert our *pure* data- -- structures into mutable ones to perform unification.-- let convertMod :: (ModuleName -> ModuleSource) -> ModuleName -> UnifyM s (ModuleScopeU s)- convertMod from m = do- m_u <- convertModule (OpenModule this_uid m)- return (Map.singleton m [WithSource (from m) m_u], Map.empty)- -- Handle 'exposed-modules'- exposed_mod_shapes_u <- traverse (convertMod FromExposedModules) src_provs- -- Handle 'other-modules'- other_mod_shapes_u <- traverse (convertMod FromOtherModules) src_hidden-- -- Handle 'signatures'- let convertReq :: ModuleName -> UnifyM s (ModuleScopeU s)- convertReq req = do- req_u <- convertModule (OpenModuleVar req)- return (Map.empty, Map.singleton req [WithSource (FromSignatures req) req_u])- req_shapes_u <- traverse convertReq src_reqs-- -- Handle 'mixins'- (incl_shapes_u, all_includes_u) <- fmap unzip (traverse convertInclude unlinked_includes)-- failIfErrs -- Prevent error cascade- -- Mix-in link everything! mixLink is the real workhorse.- shape_u <- mixLink $ exposed_mod_shapes_u- ++ other_mod_shapes_u- ++ req_shapes_u- ++ incl_shapes_u-- -- src_reqs_u <- traverse convertReq src_reqs- -- Read out all the final results by converting back- -- into a pure representation.- let convertIncludeU (ComponentInclude dep_aid rns i) = do- uid <- convertUnitIdU (ann_id dep_aid)- return (ComponentInclude {- ci_ann_id = dep_aid { ann_id = uid },- ci_renaming = rns,- ci_implicit = i- })- shape <- convertModuleScopeU shape_u- let (includes_u, sig_includes_u) = partitionEithers all_includes_u- incls <- traverse convertIncludeU includes_u- sig_incls <- traverse convertIncludeU sig_includes_u- return (shape, incls, sig_incls)-- let isNotLib (CLib _) = False- isNotLib _ = True- when (not (Set.null reqs) && isNotLib component) $- dieProgress $- hang (text "Non-library component has unfilled requirements:")- 4 (vcat [pretty req | req <- Set.toList reqs])-- -- NB: do NOT include hidden modules here: GHC 7.10's ghc-pkg- -- won't allow it (since someone could directly synthesize- -- an 'InstalledPackageInfo' that violates abstraction.)- -- Though, maybe it should be relaxed?- let src_hidden_set = Set.fromList src_hidden- linked_shape = linked_shape0 {- modScopeProvides =- -- Would rather use withoutKeys but need BC- Map.filterWithKey- (\k _ -> not (k `Set.member` src_hidden_set))- (modScopeProvides linked_shape0)- }-- -- OK, compute the reexports- -- TODO: This code reports the errors for reexports one reexport at- -- a time. Better to collect them all up and report them all at- -- once.- let hdl :: [Either Doc a] -> LogProgress [a]- hdl es =- case partitionEithers es of- ([], rs) -> return rs- (ls, _) ->- dieProgress $- hang (text "Problem with module re-exports:") 2- (vcat [hang (text "-") 2 l | l <- ls])- reexports_list <- hdl . (flip map) src_reexports $ \reex@(ModuleReexport mb_pn from to) -> do- case Map.lookup from (modScopeProvides linked_shape) of- Just cands@(x0:xs0) -> do- -- Make sure there is at least one candidate- (x, xs) <-- case mb_pn of- Just pn ->- let matches_pn (FromMixins pn' _ _) = pn == pn'- matches_pn (FromBuildDepends pn' _) = pn == pn'- matches_pn (FromExposedModules _) = pn == packageName this_pid- matches_pn (FromOtherModules _) = pn == packageName this_pid- matches_pn (FromSignatures _) = pn == packageName this_pid- in case filter (matches_pn . getSource) cands of- (x1:xs1) -> return (x1, xs1)- _ -> Left (brokenReexportMsg reex)- Nothing -> return (x0, xs0)- -- Test that all the candidates are consistent- case filter (\x' -> unWithSource x /= unWithSource x') xs of- [] -> return ()- _ -> Left $ ambiguousReexportMsg reex x xs- return (to, unWithSource x)- _ ->- Left (brokenReexportMsg reex)-- -- TODO: maybe check this earlier; it's syntactically obvious.- let build_reexports m (k, v)- | Map.member k m =- dieProgress $ hsep- [ text "Module name ", pretty k, text " is exported multiple times." ]- | otherwise = return (Map.insert k v m)- provs <- foldM build_reexports Map.empty $- -- TODO: doublecheck we have checked for- -- src_provs duplicates already!- [ (mod_name, OpenModule this_uid mod_name) | mod_name <- src_provs ] ++- reexports_list-- let final_linked_shape = ModuleShape provs (Map.keysSet (modScopeRequires linked_shape))-- -- See Note Note [Signature package special case]- let (linked_includes, linked_sig_includes)- | Set.null reqs = (linked_includes0 ++ linked_sig_includes0, [])- | otherwise = (linked_includes0, linked_sig_includes0)-- return $ LinkedComponent {- lc_ann_id = aid,- lc_component = component,- lc_public = is_public,- -- These must be executables- lc_exe_deps = map (fmap (\cid -> IndefFullUnitId cid Map.empty)) exe_deps,- lc_shape = final_linked_shape,- lc_includes = linked_includes,- lc_sig_includes = linked_sig_includes- }---- Note [Signature package special case]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- Suppose we have p-indef, which depends on str-sig and inherits--- the hole from that signature package. When we instantiate p-indef,--- it's a bit pointless to also go ahead and build str-sig, because--- str-sig cannot possibly have contributed any code to the package--- in question. Furthermore, because the signature was inherited to--- p-indef, if we test matching against p-indef, we also have tested--- matching against p-sig. In fact, skipping p-sig is *mandatory*,--- because p-indef may have thinned it (so that an implementation may--- match p-indef but not p-sig.)------ However, suppose that we have a package which mixes together str-sig--- and str-bytestring, with the intent of *checking* that str-sig is--- implemented by str-bytestring. Here, it's quite important to--- build an instantiated str-sig, since that is the only way we will--- actually end up testing if the matching works. Note that this--- admonition only applies if the package has NO requirements; if it--- has any requirements, we will typecheck it as an indefinite--- package, at which point the signature includes will be passed to--- GHC who will in turn actually do the checking to make sure they--- are instantiated correctly.---- Handle mix-in linking for components. In the absence of Backpack,--- every ComponentId gets converted into a UnitId by way of SimpleUnitId.-toLinkedComponents- :: Verbosity- -> FullDb- -> PackageId- -> LinkedComponentMap- -> [ConfiguredComponent]- -> LogProgress [LinkedComponent]-toLinkedComponents verbosity db this_pid lc_map0 comps- = fmap snd (mapAccumM go lc_map0 comps)- where- go :: Map ComponentId (OpenUnitId, ModuleShape)- -> ConfiguredComponent- -> LogProgress (Map ComponentId (OpenUnitId, ModuleShape), LinkedComponent)- go lc_map cc = do- lc <- addProgressCtx (text "In the stanza" <+> text (componentNameStanza (cc_name cc))) $- toLinkedComponent verbosity db this_pid lc_map cc- return (extendLinkedComponentMap lc lc_map, lc)--type LinkedComponentMap = Map ComponentId (OpenUnitId, ModuleShape)--extendLinkedComponentMap :: LinkedComponent- -> LinkedComponentMap- -> LinkedComponentMap-extendLinkedComponentMap lc m =- Map.insert (lc_cid lc) (lc_uid lc, lc_shape lc) m--brokenReexportMsg :: ModuleReexport -> Doc-brokenReexportMsg (ModuleReexport (Just pn) from _to) =- vcat [ text "The package" <+> quotes (pretty pn)- , text "does not export a module" <+> quotes (pretty from) ]-brokenReexportMsg (ModuleReexport Nothing from _to) =- vcat [ text "The module" <+> quotes (pretty from)- , text "is not exported by any suitable package."- , text "It occurs in neither the 'exposed-modules' of this package,"- , text "nor any of its 'build-depends' dependencies." ]--ambiguousReexportMsg :: ModuleReexport -> ModuleWithSource -> [ModuleWithSource] -> Doc-ambiguousReexportMsg (ModuleReexport mb_pn from _to) y1 ys =- vcat [ text "Ambiguous reexport" <+> quotes (pretty from)- , hang (text "It could refer to either:") 2- (vcat (msg : msgs))- , help_msg mb_pn ]- where- msg = text " " <+> displayModuleWithSource y1- msgs = [text "or" <+> displayModuleWithSource y | y <- ys]- help_msg Nothing =- -- TODO: This advice doesn't help if the ambiguous exports- -- come from a package named the same thing- vcat [ text "The ambiguity can be resolved by qualifying the"- , text "re-export with a package name."- , text "The syntax is 'packagename:ModuleName [as NewName]'." ]- -- Qualifying won't help that much.- help_msg (Just _) =- vcat [ text "The ambiguity can be resolved by using the"- , text "mixins field to rename one of the module"- , text "names differently." ]- displayModuleWithSource y- = vcat [ quotes (pretty (unWithSource y))- , text "brought into scope by" <+>- dispModuleSource (getSource y)- ]
− Distribution/Backpack/MixLink.hs
@@ -1,185 +0,0 @@-{-# LANGUAGE NondecreasingIndentation #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.MixLink (- mixLink,-) where--import Prelude ()-import Distribution.Compat.Prelude hiding (mod)--import Distribution.Backpack-import Distribution.Backpack.UnifyM-import Distribution.Backpack.FullUnitId-import Distribution.Backpack.ModuleScope--import qualified Distribution.Utils.UnionFind as UnionFind-import Distribution.ModuleName-import Distribution.Pretty-import Distribution.Types.ComponentId--import Text.PrettyPrint-import Control.Monad-import qualified Data.Map as Map-import qualified Data.Foldable as F---------------------------------------------------------------------------- Linking---- | Given to scopes of provisions and requirements, link them together.-mixLink :: [ModuleScopeU s] -> UnifyM s (ModuleScopeU s)-mixLink scopes = do- let provs = Map.unionsWith (++) (map fst scopes)- -- Invariant: any identically named holes refer to same mutable cell- reqs = Map.unionsWith (++) (map snd scopes)- filled = Map.intersectionWithKey linkProvision provs reqs- F.sequenceA_ filled- let remaining = Map.difference reqs filled- return (provs, remaining)---- | Link a list of possibly provided modules to a single--- requirement. This applies a side-condition that all--- of the provided modules at the same name are *actually*--- the same module.-linkProvision :: ModuleName- -> [ModuleWithSourceU s] -- provs- -> [ModuleWithSourceU s] -- reqs- -> UnifyM s [ModuleWithSourceU s]-linkProvision mod_name ret@(prov:provs) (req:reqs) = do- -- TODO: coalesce all the non-unifying modules together- forM_ provs $ \prov' -> do- -- Careful: read it out BEFORE unifying, because the- -- unification algorithm preemptively unifies modules- mod <- convertModuleU (unWithSource prov)- mod' <- convertModuleU (unWithSource prov')- r <- unify prov prov'- case r of- Just () -> return ()- Nothing -> do- addErr $- text "Ambiguous module" <+> quotes (pretty mod_name) $$- text "It could refer to" <+>- ( text " " <+> (quotes (pretty mod) $$ in_scope_by (getSource prov)) $$- text "or" <+> (quotes (pretty mod') $$ in_scope_by (getSource prov')) ) $$- link_doc- mod <- convertModuleU (unWithSource prov)- req_mod <- convertModuleU (unWithSource req)- self_cid <- fmap unify_self_cid getUnifEnv- case mod of- OpenModule (IndefFullUnitId cid _) _- | cid == self_cid -> addErr $- text "Cannot instantiate requirement" <+> quotes (pretty mod_name) <+>- in_scope_by (getSource req) $$- text "with locally defined module" <+> in_scope_by (getSource prov) $$- text "as this would create a cyclic dependency, which GHC does not support." $$- text "Try moving this module to a separate library, e.g.," $$- text "create a new stanza: library 'sublib'."- _ -> return ()- r <- unify prov req- case r of- Just () -> return ()- Nothing -> do- -- TODO: Record and report WHERE the bad constraint came from- addErr $ text "Could not instantiate requirement" <+> quotes (pretty mod_name) $$- nest 4 (text "Expected:" <+> pretty mod $$- text "Actual: " <+> pretty req_mod) $$- parens (text "This can occur if an exposed module of" <+>- text "a libraries shares a name with another module.") $$- link_doc- return ret- where- unify s1 s2 = tryM $ addErrContext short_link_doc- $ unifyModule (unWithSource s1) (unWithSource s2)- in_scope_by s = text "brought into scope by" <+> dispModuleSource s- short_link_doc = text "While filling requirement" <+> quotes (pretty mod_name)- link_doc = text "While filling requirements of" <+> reqs_doc- reqs_doc- | null reqs = dispModuleSource (getSource req)- | otherwise = ( text " " <+> dispModuleSource (getSource req) $$- vcat [ text "and" <+> dispModuleSource (getSource r) | r <- reqs])-linkProvision _ _ _ = error "linkProvision"------------------------------------------------------------------------------ The unification algorithm---- This is based off of https://gist.github.com/amnn/559551517d020dbb6588--- which is a translation from Huet's thesis.--unifyUnitId :: UnitIdU s -> UnitIdU s -> UnifyM s ()-unifyUnitId uid1_u uid2_u- | uid1_u == uid2_u = return ()- | otherwise = do- xuid1 <- liftST $ UnionFind.find uid1_u- xuid2 <- liftST $ UnionFind.find uid2_u- case (xuid1, xuid2) of- (UnitIdThunkU u1, UnitIdThunkU u2)- | u1 == u2 -> return ()- | otherwise ->- failWith $ hang (text "Couldn't match unit IDs:") 4- (text " " <+> pretty u1 $$- text "and" <+> pretty u2)- (UnitIdThunkU uid1, UnitIdU _ cid2 insts2)- -> unifyThunkWith cid2 insts2 uid2_u uid1 uid1_u- (UnitIdU _ cid1 insts1, UnitIdThunkU uid2)- -> unifyThunkWith cid1 insts1 uid1_u uid2 uid2_u- (UnitIdU _ cid1 insts1, UnitIdU _ cid2 insts2)- -> unifyInner cid1 insts1 uid1_u cid2 insts2 uid2_u--unifyThunkWith :: ComponentId- -> Map ModuleName (ModuleU s)- -> UnitIdU s- -> DefUnitId- -> UnitIdU s- -> UnifyM s ()-unifyThunkWith cid1 insts1 uid1_u uid2 uid2_u = do- db <- fmap unify_db getUnifEnv- let FullUnitId cid2 insts2' = expandUnitId db uid2- insts2 <- convertModuleSubst insts2'- unifyInner cid1 insts1 uid1_u cid2 insts2 uid2_u--unifyInner :: ComponentId- -> Map ModuleName (ModuleU s)- -> UnitIdU s- -> ComponentId- -> Map ModuleName (ModuleU s)- -> UnitIdU s- -> UnifyM s ()-unifyInner cid1 insts1 uid1_u cid2 insts2 uid2_u = do- when (cid1 /= cid2) $- -- TODO: if we had a package identifier, could be an- -- easier to understand error message.- failWith $- hang (text "Couldn't match component IDs:") 4- (text " " <+> pretty cid1 $$- text "and" <+> pretty cid2)- -- The KEY STEP which makes this a Huet-style unification- -- algorithm. (Also a payoff of using union-find.)- -- We can build infinite unit IDs this way, which is necessary- -- for support mutual recursion. NB: union keeps the SECOND- -- descriptor, so we always arrange for a UnitIdThunkU to live- -- there.- liftST $ UnionFind.union uid1_u uid2_u- F.sequenceA_ $ Map.intersectionWith unifyModule insts1 insts2---- | Imperatively unify two modules.-unifyModule :: ModuleU s -> ModuleU s -> UnifyM s ()-unifyModule mod1_u mod2_u- | mod1_u == mod2_u = return ()- | otherwise = do- mod1 <- liftST $ UnionFind.find mod1_u- mod2 <- liftST $ UnionFind.find mod2_u- case (mod1, mod2) of- (ModuleVarU _, _) -> liftST $ UnionFind.union mod1_u mod2_u- (_, ModuleVarU _) -> liftST $ UnionFind.union mod2_u mod1_u- (ModuleU uid1 mod_name1, ModuleU uid2 mod_name2) -> do- when (mod_name1 /= mod_name2) $- failWith $- hang (text "Cannot match module names") 4 $- text " " <+> pretty mod_name1 $$- text "and" <+> pretty mod_name2- -- NB: this is not actually necessary (because we'll- -- detect loops eventually in 'unifyUnitId'), but it- -- seems harmless enough- liftST $ UnionFind.union mod1_u mod2_u- unifyUnitId uid1 uid2
− Distribution/Backpack/ModSubst.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE PatternGuards #-}---- | A type class 'ModSubst' for objects which can have 'ModuleSubst'--- applied to them.------ See also <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>--module Distribution.Backpack.ModSubst (- ModSubst(..),-) where--import Prelude ()-import Distribution.Compat.Prelude hiding (mod)--import Distribution.Backpack-import Distribution.ModuleName--import qualified Data.Map as Map-import qualified Data.Set as Set---- | Applying module substitutions to semantic objects.-class ModSubst a where- -- In notation, substitution is postfix, which implies- -- putting it on the right hand side, but for partial- -- application it's more convenient to have it on the left- -- hand side.- modSubst :: OpenModuleSubst -> a -> a--instance ModSubst OpenModule where- modSubst subst (OpenModule cid mod_name) = OpenModule (modSubst subst cid) mod_name- modSubst subst mod@(OpenModuleVar mod_name)- | Just mod' <- Map.lookup mod_name subst = mod'- | otherwise = mod--instance ModSubst OpenUnitId where- modSubst subst (IndefFullUnitId cid insts) = IndefFullUnitId cid (modSubst subst insts)- modSubst _subst uid = uid--instance ModSubst (Set ModuleName) where- modSubst subst reqs- = Set.union (Set.difference reqs (Map.keysSet subst))- (openModuleSubstFreeHoles subst)---- Substitutions are functorial. NB: this means that--- there is an @instance 'ModSubst' 'ModuleSubst'@!-instance ModSubst a => ModSubst (Map k a) where- modSubst subst = fmap (modSubst subst)-instance ModSubst a => ModSubst [a] where- modSubst subst = fmap (modSubst subst)-instance ModSubst a => ModSubst (k, a) where- modSubst subst (x,y) = (x, modSubst subst y)
− Distribution/Backpack/ModuleScope.hs
@@ -1,132 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE DeriveFoldable #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.ModuleScope (- -- * Module scopes- ModuleScope(..),- ModuleProvides,- ModuleRequires,- ModuleSource(..),- dispModuleSource,- WithSource(..),- unWithSource,- getSource,- ModuleWithSource,- emptyModuleScope,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.ModuleName-import Distribution.Types.IncludeRenaming-import Distribution.Types.PackageName-import Distribution.Types.ComponentName-import Distribution.Types.LibraryName-import Distribution.Pretty--import Distribution.Backpack-import Distribution.Backpack.ModSubst--import qualified Data.Map as Map-import Text.PrettyPrint----------------------------------------------------------------------------- Module scopes---- Why is ModuleProvides so complicated? The basic problem is that--- we want to support this:------ package p where--- include q (A)--- include r (A)--- module B where--- import "q" A--- import "r" A------ Specifically, in Cabal today it is NOT an error have two modules in--- scope with the same identifier. So we need to preserve this for--- Backpack. The modification is that an ambiguous module name is--- OK... as long as it is NOT used to fill a requirement!------ So as a first try, we might try deferring unifying provisions that--- are being glommed together, and check for equality after the fact.--- But this doesn't work, because what if a multi-module provision--- is used to fill a requirement?! So you do the equality test--- IMMEDIATELY before a requirement fill happens... or never at all.------ Alternate strategy: go ahead and unify, and then if it is revealed--- that some requirements got filled "out-of-thin-air", error.----- | A 'ModuleScope' describes the modules and requirements that--- are in-scope as we are processing a Cabal package. Unlike--- a 'ModuleShape', there may be multiple modules in scope at--- the same 'ModuleName'; this is only an error if we attempt--- to use those modules to fill a requirement. A 'ModuleScope'--- can influence the 'ModuleShape' via a reexport.-data ModuleScope = ModuleScope {- modScopeProvides :: ModuleProvides,- modScopeRequires :: ModuleRequires- }---- | An empty 'ModuleScope'.-emptyModuleScope :: ModuleScope-emptyModuleScope = ModuleScope Map.empty Map.empty---- | Every 'Module' in scope at a 'ModuleName' is annotated with--- the 'PackageName' it comes from.-type ModuleProvides = Map ModuleName [ModuleWithSource]--- | INVARIANT: entries for ModuleName m, have msrc_module is OpenModuleVar m-type ModuleRequires = Map ModuleName [ModuleWithSource]--- TODO: consider newtping the two types above.---- | Description of where a module participating in mixin linking came--- from.-data ModuleSource- = FromMixins PackageName ComponentName IncludeRenaming- | FromBuildDepends PackageName ComponentName- | FromExposedModules ModuleName- | FromOtherModules ModuleName- | FromSignatures ModuleName--- We don't have line numbers, but if we did, we'd want to record that--- too---- TODO: Deduplicate this with Distribution.Backpack.UnifyM.ci_msg-dispModuleSource :: ModuleSource -> Doc-dispModuleSource (FromMixins pn cn incls)- = text "mixins:" <+> dispComponent pn cn <+> pretty incls-dispModuleSource (FromBuildDepends pn cn)- = text "build-depends:" <+> dispComponent pn cn-dispModuleSource (FromExposedModules m)- = text "exposed-modules:" <+> pretty m-dispModuleSource (FromOtherModules m)- = text "other-modules:" <+> pretty m-dispModuleSource (FromSignatures m)- = text "signatures:" <+> pretty m---- Dependency-dispComponent :: PackageName -> ComponentName -> Doc-dispComponent pn cn =- -- NB: This syntax isn't quite the source syntax, but it- -- should be clear enough. To do source syntax, we'd- -- need to know what the package we're linking is.- case cn of- CLibName LMainLibName -> pretty pn- CLibName (LSubLibName ucn) -> pretty pn <<>> colon <<>> pretty ucn- -- Case below shouldn't happen- _ -> pretty pn <+> parens (pretty cn)---- | An 'OpenModule', annotated with where it came from in a Cabal file.-data WithSource a = WithSource ModuleSource a- deriving (Functor, Foldable, Traversable)-unWithSource :: WithSource a -> a-unWithSource (WithSource _ x) = x-getSource :: WithSource a -> ModuleSource-getSource (WithSource s _) = s-type ModuleWithSource = WithSource OpenModule--instance ModSubst a => ModSubst (WithSource a) where- modSubst subst (WithSource s m) = WithSource s (modSubst subst m)
− Distribution/Backpack/ModuleShape.hs
@@ -1,84 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.ModuleShape (- -- * Module shapes- ModuleShape(..),- emptyModuleShape,- shapeInstalledPackage,-) where--import Prelude ()-import Distribution.Compat.Prelude hiding (mod)--import Distribution.ModuleName-import Distribution.InstalledPackageInfo as IPI--import Distribution.Backpack.ModSubst-import Distribution.Backpack--import qualified Data.Map as Map-import qualified Data.Set as Set---------------------------------------------------------------------------- Module shapes---- | A 'ModuleShape' describes the provisions and requirements of--- a library. We can extract a 'ModuleShape' from an--- 'InstalledPackageInfo'.-data ModuleShape = ModuleShape {- modShapeProvides :: OpenModuleSubst,- modShapeRequires :: Set ModuleName- }- deriving (Eq, Show, Generic, Typeable)--instance Binary ModuleShape-instance Structured ModuleShape--instance ModSubst ModuleShape where- modSubst subst (ModuleShape provs reqs)- = ModuleShape (modSubst subst provs) (modSubst subst reqs)---- | The default module shape, with no provisions and no requirements.-emptyModuleShape :: ModuleShape-emptyModuleShape = ModuleShape Map.empty Set.empty---- Food for thought: suppose we apply the Merkel tree optimization.--- Imagine this situation:------ component p--- signature H--- module P--- component h--- module H--- component a--- signature P--- module A--- component q(P)--- include p--- include h--- component r--- include q (P)--- include p (P) requires (H)--- include h (H)--- include a (A) requires (P)------ Component r should not have any conflicts, since after mix-in linking--- the two P imports will end up being the same, so we can properly--- instantiate it. But to know that q's P is p:P instantiated with h:H,--- we have to be able to expand its unit id. Maybe we can expand it--- lazily but in some cases it will need to be expanded.------ FWIW, the way that GHC handles this is by improving unit IDs as--- soon as it sees an improved one in the package database. This--- is a bit disgusting.-shapeInstalledPackage :: IPI.InstalledPackageInfo -> ModuleShape-shapeInstalledPackage ipi = ModuleShape (Map.fromList provs) reqs- where- uid = installedOpenUnitId ipi- provs = map shapeExposedModule (IPI.exposedModules ipi)- reqs = requiredSignatures ipi- shapeExposedModule (IPI.ExposedModule mod_name Nothing)- = (mod_name, OpenModule uid mod_name)- shapeExposedModule (IPI.ExposedModule mod_name (Just mod))- = (mod_name, mod)
− Distribution/Backpack/PreExistingComponent.hs
@@ -1,67 +0,0 @@--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.PreExistingComponent (- PreExistingComponent(..),- ipiToPreExistingComponent,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Backpack.ModuleShape-import Distribution.Backpack-import Distribution.Types.ComponentId-import Distribution.Types.MungedPackageId-import Distribution.Types.PackageId-import Distribution.Types.UnitId-import Distribution.Types.ComponentName-import Distribution.Types.PackageName-import Distribution.Package--import qualified Data.Map as Map-import qualified Distribution.InstalledPackageInfo as Installed-import Distribution.InstalledPackageInfo (InstalledPackageInfo)---- | Stripped down version of 'LinkedComponent' for things--- we don't need to know how to build.-data PreExistingComponent- = PreExistingComponent {- -- | The actual name of the package. This may DISAGREE with 'pc_pkgid'- -- for internal dependencies: e.g., an internal component @lib@ may be- -- munged to @z-pkg-z-lib@, but we still want to use it when we see- -- @lib@ in @build-depends@- pc_pkgname :: PackageName,- -- | The actual name of the component.- pc_compname :: ComponentName,- pc_munged_id :: MungedPackageId,- pc_uid :: UnitId,- pc_cid :: ComponentId,- pc_open_uid :: OpenUnitId,- pc_shape :: ModuleShape- }---- | Convert an 'InstalledPackageInfo' into a 'PreExistingComponent',--- which was brought into scope under the 'PackageName' (important for--- a package qualified reference.)-ipiToPreExistingComponent :: InstalledPackageInfo -> PreExistingComponent-ipiToPreExistingComponent ipi =- PreExistingComponent {- pc_pkgname = packageName ipi,- pc_compname = CLibName $ Installed.sourceLibName ipi,- pc_munged_id = mungedId ipi,- pc_uid = Installed.installedUnitId ipi,- pc_cid = Installed.installedComponentId ipi,- pc_open_uid =- IndefFullUnitId (Installed.installedComponentId ipi)- (Map.fromList (Installed.instantiatedWith ipi)),- pc_shape = shapeInstalledPackage ipi- }--instance HasMungedPackageId PreExistingComponent where- mungedId = pc_munged_id--instance Package PreExistingComponent where- packageId pec = PackageIdentifier (pc_pkgname pec) v- where MungedPackageId _ v = pc_munged_id pec--instance HasUnitId PreExistingComponent where- installedUnitId = pc_uid
− Distribution/Backpack/PreModuleShape.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Backpack.PreModuleShape (- PreModuleShape(..),- toPreModuleShape,- renamePreModuleShape,- mixLinkPreModuleShape,-) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Data.Set as Set-import qualified Data.Map as Map--import Distribution.Backpack.ModuleShape-import Distribution.Types.IncludeRenaming-import Distribution.Types.ModuleRenaming-import Distribution.ModuleName--data PreModuleShape = PreModuleShape {- preModShapeProvides :: Set ModuleName,- preModShapeRequires :: Set ModuleName- }- deriving (Eq, Show, Generic)--toPreModuleShape :: ModuleShape -> PreModuleShape-toPreModuleShape (ModuleShape provs reqs) = PreModuleShape (Map.keysSet provs) reqs--renamePreModuleShape :: PreModuleShape -> IncludeRenaming -> PreModuleShape-renamePreModuleShape (PreModuleShape provs reqs) (IncludeRenaming prov_rn req_rn) =- PreModuleShape- (Set.fromList (mapMaybe prov_fn (Set.toList provs)))- (Set.map req_fn reqs)- where- prov_fn = interpModuleRenaming prov_rn- req_fn k = fromMaybe k (interpModuleRenaming req_rn k)--mixLinkPreModuleShape :: [PreModuleShape] -> PreModuleShape-mixLinkPreModuleShape shapes = PreModuleShape provs (Set.difference reqs provs)- where- provs = Set.unions (map preModShapeProvides shapes)- reqs = Set.unions (map preModShapeRequires shapes)
− Distribution/Backpack/ReadyComponent.hs
@@ -1,376 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE PatternGuards #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.ReadyComponent (- ReadyComponent(..),- InstantiatedComponent(..),- IndefiniteComponent(..),- rc_depends,- rc_uid,- rc_pkgid,- dispReadyComponent,- toReadyComponents,-) where--import Prelude ()-import Distribution.Compat.Prelude hiding ((<>))--import Distribution.Backpack-import Distribution.Backpack.LinkedComponent-import Distribution.Backpack.ModuleShape--import Distribution.Types.AnnotatedId-import Distribution.Types.ModuleRenaming-import Distribution.Types.Component-import Distribution.Types.ComponentInclude-import Distribution.Types.ComponentId-import Distribution.Types.ComponentName-import Distribution.Types.PackageId-import Distribution.Types.PackageName.Magic-import Distribution.Types.UnitId-import Distribution.Compat.Graph (IsNode(..))-import Distribution.Types.Module-import Distribution.Types.MungedPackageId-import Distribution.Types.MungedPackageName-import Distribution.Types.Library-import Distribution.Types.LibraryName--import Distribution.ModuleName-import Distribution.Package-import Distribution.Simple.Utils--import Control.Monad-import Text.PrettyPrint-import qualified Data.Map as Map-import qualified Data.Set as Set--import Distribution.Version-import Distribution.Pretty---- | A 'ReadyComponent' is one that we can actually generate build--- products for. We have a ready component for the typecheck-only--- products of every indefinite package, as well as a ready component--- for every way these packages can be fully instantiated.----data ReadyComponent- = ReadyComponent {- rc_ann_id :: AnnotatedId UnitId,- -- | The 'OpenUnitId' for this package. At the moment, this- -- is used in only one case, which is to determine if an- -- export is of a module from this library (indefinite- -- libraries record these exports as 'OpenModule');- -- 'rc_open_uid' can be conveniently used to test for- -- equality, whereas 'UnitId' cannot always be used in this- -- case.- rc_open_uid :: OpenUnitId,- -- | Corresponds to 'lc_cid'. Invariant: if 'rc_open_uid'- -- records a 'ComponentId', it coincides with this one.- rc_cid :: ComponentId,- -- | Corresponds to 'lc_component'.- rc_component :: Component,- -- | Corresponds to 'lc_exe_deps'.- -- Build-tools don't participate in mix-in linking.- -- (but what if they could?)- rc_exe_deps :: [AnnotatedId UnitId],- -- | Corresponds to 'lc_public'.- rc_public :: Bool,- -- | Extra metadata depending on whether or not this is an- -- indefinite library (typechecked only) or an instantiated- -- component (can be compiled).- rc_i :: Either IndefiniteComponent InstantiatedComponent- }---- | The final, string 'UnitId' that will uniquely identify--- the compilation products of this component.-rc_uid :: ReadyComponent -> UnitId-rc_uid = ann_id . rc_ann_id---- | Corresponds to 'lc_pkgid'.-rc_pkgid :: ReadyComponent -> PackageId-rc_pkgid = ann_pid . rc_ann_id---- | An 'InstantiatedComponent' is a library which is fully instantiated--- (or, possibly, has no requirements at all.)-data InstantiatedComponent- = InstantiatedComponent {- -- | How this library was instantiated.- instc_insts :: [(ModuleName, Module)],- -- | Dependencies induced by 'instc_insts'. These are recorded- -- here because there isn't a convenient way otherwise to get- -- the 'PackageId' we need to fill 'componentPackageDeps' as needed.- instc_insts_deps :: [(UnitId, MungedPackageId)],- -- | The modules exported/reexported by this library.- instc_provides :: Map ModuleName Module,- -- | The dependencies which need to be passed to the compiler- -- to bring modules into scope. These always refer to installed- -- fully instantiated libraries.- instc_includes :: [ComponentInclude DefUnitId ModuleRenaming]- }---- | An 'IndefiniteComponent' is a library with requirements--- which we will typecheck only.-data IndefiniteComponent- = IndefiniteComponent {- -- | The requirements of the library.- indefc_requires :: [ModuleName],- -- | The modules exported/reexported by this library.- indefc_provides :: Map ModuleName OpenModule,- -- | The dependencies which need to be passed to the compiler- -- to bring modules into scope. These are 'OpenUnitId' because- -- these may refer to partially instantiated libraries.- indefc_includes :: [ComponentInclude OpenUnitId ModuleRenaming]- }---- | Compute the dependencies of a 'ReadyComponent' that should--- be recorded in the @depends@ field of 'InstalledPackageInfo'.-rc_depends :: ReadyComponent -> [(UnitId, MungedPackageId)]-rc_depends rc = ordNub $- case rc_i rc of- Left indefc ->- map (\ci -> (abstractUnitId $ ci_id ci, toMungedPackageId ci))- (indefc_includes indefc)- Right instc ->- map (\ci -> (unDefUnitId $ ci_id ci, toMungedPackageId ci))- (instc_includes instc)- ++ instc_insts_deps instc- where- toMungedPackageId :: Pretty id => ComponentInclude id rn -> MungedPackageId- toMungedPackageId ci =- computeCompatPackageId- (ci_pkgid ci)- (case ci_cname ci of- CLibName name -> name- _ -> error $ prettyShow (rc_cid rc) ++- " depends on non-library " ++ prettyShow (ci_id ci))---- | Get the 'MungedPackageId' of a 'ReadyComponent' IF it is--- a library.-rc_munged_id :: ReadyComponent -> MungedPackageId-rc_munged_id rc =- computeCompatPackageId- (rc_pkgid rc)- (case rc_component rc of- CLib lib -> libName lib- _ -> error "rc_munged_id: not library")--instance Package ReadyComponent where- packageId = rc_pkgid--instance HasUnitId ReadyComponent where- installedUnitId = rc_uid--instance IsNode ReadyComponent where- type Key ReadyComponent = UnitId- nodeKey = rc_uid- nodeNeighbors rc =- (case rc_i rc of- Right inst | [] <- instc_insts inst- -> []- | otherwise- -> [newSimpleUnitId (rc_cid rc)]- _ -> []) ++- ordNub (map fst (rc_depends rc)) ++- map ann_id (rc_exe_deps rc)--dispReadyComponent :: ReadyComponent -> Doc-dispReadyComponent rc =- hang (text (case rc_i rc of- Left _ -> "indefinite"- Right _ -> "definite")- <+> pretty (nodeKey rc)- {- <+> dispModSubst (Map.fromList (lc_insts lc)) -} ) 4 $- vcat [ text "depends" <+> pretty uid- | uid <- nodeNeighbors rc ]---- | The state of 'InstM'; a mapping from 'UnitId's to their--- ready component, or @Nothing@ if its an external--- component which we don't know how to build.-type InstS = Map UnitId (Maybe ReadyComponent)---- | A state monad for doing instantiations (can't use actual--- State because that would be an extra dependency.)-newtype InstM a = InstM { runInstM :: InstS -> (a, InstS) }--instance Functor InstM where- fmap f (InstM m) = InstM $ \s -> let (x, s') = m s- in (f x, s')--instance Applicative InstM where- pure a = InstM $ \s -> (a, s)- InstM f <*> InstM x = InstM $ \s -> let (f', s') = f s- (x', s'') = x s'- in (f' x', s'')--instance Monad InstM where- return = pure- InstM m >>= f = InstM $ \s -> let (x, s') = m s- in runInstM (f x) s'---- | Given a list of 'LinkedComponent's, expand the module graph--- so that we have an instantiated graph containing all of the--- instantiated components we need to build.------ Instantiation intuitively follows the following algorithm:------ instantiate a definite unit id p[S]:--- recursively instantiate each module M in S--- recursively instantiate modules exported by this unit--- recursively instantiate dependencies substituted by S------ The implementation is a bit more involved to memoize instantiation--- if we have done it already.------ We also call 'improveUnitId' during this process, so that fully--- instantiated components are given 'HashedUnitId'.----toReadyComponents- :: Map UnitId MungedPackageId- -> Map ModuleName Module -- subst for the public component- -> [LinkedComponent]- -> [ReadyComponent]-toReadyComponents pid_map subst0 comps- = catMaybes (Map.elems ready_map)- where- cmap = Map.fromList [ (lc_cid lc, lc) | lc <- comps ]-- instantiateUnitId :: ComponentId -> Map ModuleName Module- -> InstM DefUnitId- instantiateUnitId cid insts = InstM $ \s ->- case Map.lookup uid s of- Nothing ->- -- Knot tied- let (r, s') = runInstM (instantiateComponent uid cid insts)- (Map.insert uid r s)- in (def_uid, Map.insert uid r s')- Just _ -> (def_uid, s)- where- -- The mkDefUnitId here indicates that we assume- -- that Cabal handles unit id hash allocation.- -- Good thing about hashing here: map is only on string.- -- Bad thing: have to repeatedly hash.- def_uid = mkDefUnitId cid insts- uid = unDefUnitId def_uid-- instantiateComponent- :: UnitId -> ComponentId -> Map ModuleName Module- -> InstM (Maybe ReadyComponent)- instantiateComponent uid cid insts- | Just lc <- Map.lookup cid cmap = do- provides <- traverse (substModule insts) (modShapeProvides (lc_shape lc))- -- NB: lc_sig_includes is omitted here, because we don't- -- need them to build- includes <- forM (lc_includes lc) $ \ci -> do- uid' <- substUnitId insts (ci_id ci)- return ci { ci_ann_id = fmap (const uid') (ci_ann_id ci) }- exe_deps <- traverse (substExeDep insts) (lc_exe_deps lc)- s <- InstM $ \s -> (s, s)- let getDep (Module dep_def_uid _)- | let dep_uid = unDefUnitId dep_def_uid- -- Lose DefUnitId invariant for rc_depends- = [(dep_uid,- fromMaybe err_pid $- Map.lookup dep_uid pid_map <|>- fmap rc_munged_id (join (Map.lookup dep_uid s)))]- where- err_pid = MungedPackageId- (MungedPackageName nonExistentPackageThisIsCabalBug LMainLibName)- (mkVersion [0])- instc = InstantiatedComponent {- instc_insts = Map.toList insts,- instc_insts_deps = concatMap getDep (Map.elems insts),- instc_provides = provides,- instc_includes = includes- -- NB: there is no dependency on the- -- indefinite version of this instantiated package here,- -- as (1) it doesn't go in depends in the- -- IPI: it's not a run time dep, and (2)- -- we don't have to tell GHC about it, it- -- will match up the ComponentId- -- automatically- }- return $ Just ReadyComponent {- rc_ann_id = (lc_ann_id lc) { ann_id = uid },- rc_open_uid = DefiniteUnitId (unsafeMkDefUnitId uid),- rc_cid = lc_cid lc,- rc_component = lc_component lc,- rc_exe_deps = exe_deps,- rc_public = lc_public lc,- rc_i = Right instc- }- | otherwise = return Nothing-- substUnitId :: Map ModuleName Module -> OpenUnitId -> InstM DefUnitId- substUnitId _ (DefiniteUnitId uid) =- return uid- substUnitId subst (IndefFullUnitId cid insts) = do- insts' <- substSubst subst insts- instantiateUnitId cid insts'-- -- NB: NOT composition- substSubst :: Map ModuleName Module- -> Map ModuleName OpenModule- -> InstM (Map ModuleName Module)- substSubst subst insts = traverse (substModule subst) insts-- substModule :: Map ModuleName Module -> OpenModule -> InstM Module- substModule subst (OpenModuleVar mod_name)- | Just m <- Map.lookup mod_name subst = return m- | otherwise = error "substModule: non-closing substitution"- substModule subst (OpenModule uid mod_name) = do- uid' <- substUnitId subst uid- return (Module uid' mod_name)-- substExeDep :: Map ModuleName Module- -> AnnotatedId OpenUnitId -> InstM (AnnotatedId UnitId)- substExeDep insts exe_aid = do- exe_uid' <- substUnitId insts (ann_id exe_aid)- return exe_aid { ann_id = unDefUnitId exe_uid' }-- indefiniteUnitId :: ComponentId -> InstM UnitId- indefiniteUnitId cid = do- let uid = newSimpleUnitId cid- r <- indefiniteComponent uid cid- InstM $ \s -> (uid, Map.insert uid r s)-- indefiniteComponent :: UnitId -> ComponentId -> InstM (Maybe ReadyComponent)- indefiniteComponent uid cid- | Just lc <- Map.lookup cid cmap = do- -- We're going to process includes, in case some of them- -- are fully definite even without any substitution. We- -- want to build those too; see #5634.- inst_includes <- forM (lc_includes lc) $ \ci ->- if Set.null (openUnitIdFreeHoles (ci_id ci))- then do uid' <- substUnitId Map.empty (ci_id ci)- return $ ci { ci_ann_id = fmap (const (DefiniteUnitId uid')) (ci_ann_id ci) }- else return ci- exe_deps <- traverse (substExeDep Map.empty) (lc_exe_deps lc)- let indefc = IndefiniteComponent {- indefc_requires = map fst (lc_insts lc),- indefc_provides = modShapeProvides (lc_shape lc),- indefc_includes = inst_includes ++ lc_sig_includes lc- }- return $ Just ReadyComponent {- rc_ann_id = (lc_ann_id lc) { ann_id = uid },- rc_cid = lc_cid lc,- rc_open_uid = lc_uid lc,- rc_component = lc_component lc,- -- It's always fully built- rc_exe_deps = exe_deps,- rc_public = lc_public lc,- rc_i = Left indefc- }- | otherwise = return Nothing-- ready_map = snd $ runInstM work Map.empty-- work- -- Top-level instantiation per subst0- | not (Map.null subst0)- , [lc] <- filter lc_public (Map.elems cmap)- = do _ <- instantiateUnitId (lc_cid lc) subst0- return ()- | otherwise- = forM_ (Map.elems cmap) $ \lc ->- if null (lc_insts lc)- then instantiateUnitId (lc_cid lc) Map.empty >> return ()- else indefiniteUnitId (lc_cid lc) >> return ()
− Distribution/Backpack/UnifyM.hs
@@ -1,627 +0,0 @@-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}--- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>-module Distribution.Backpack.UnifyM (- -- * Unification monad- UnifyM,- runUnifyM,- failWith,- addErr,- failIfErrs,- tryM,- addErrContext,- addErrContextM,- liftST,-- UnifEnv(..),- getUnifEnv,-- -- * Modules and unit IDs- ModuleU,- ModuleU'(..),- convertModule,- convertModuleU,-- UnitIdU,- UnitIdU'(..),- convertUnitId,- convertUnitIdU,-- ModuleSubstU,- convertModuleSubstU,- convertModuleSubst,-- ModuleScopeU,- emptyModuleScopeU,- convertModuleScopeU,-- ModuleWithSourceU,-- convertInclude,- convertModuleProvides,- convertModuleProvidesU,--) where--import Prelude ()-import Distribution.Compat.Prelude hiding (mod)--import Distribution.Backpack.ModuleShape-import Distribution.Backpack.ModuleScope-import Distribution.Backpack.ModSubst-import Distribution.Backpack.FullUnitId-import Distribution.Backpack--import qualified Distribution.Utils.UnionFind as UnionFind-import Distribution.ModuleName-import Distribution.Package-import Distribution.PackageDescription-import Distribution.Pretty-import Distribution.Types.IncludeRenaming-import Distribution.Types.ComponentInclude-import Distribution.Types.AnnotatedId-import Distribution.Types.ModuleRenaming-import Distribution.Verbosity--import Data.STRef-import Data.Traversable-import Control.Monad.ST-import qualified Data.Map as Map-import qualified Data.Set as Set-import Data.IntMap (IntMap)-import qualified Data.IntMap as IntMap-import Text.PrettyPrint---- TODO: more detailed trace output on high verbosity would probably--- be appreciated by users debugging unification errors. Collect--- some good examples!--data ErrMsg = ErrMsg {- err_msg :: Doc,- err_ctx :: [Doc]- }-type MsgDoc = Doc--renderErrMsg :: ErrMsg -> MsgDoc-renderErrMsg ErrMsg { err_msg = msg, err_ctx = ctx } =- msg $$ vcat ctx---- | The unification monad, this monad encapsulates imperative--- unification.-newtype UnifyM s a = UnifyM { unUnifyM :: UnifEnv s -> ST s (Maybe a) }---- | Run a computation in the unification monad.-runUnifyM :: Verbosity -> ComponentId -> FullDb -> (forall s. UnifyM s a) -> Either [MsgDoc] a-runUnifyM verbosity self_cid db m- = runST $ do i <- newSTRef 0- hmap <- newSTRef Map.empty- errs <- newSTRef []- mb_r <- unUnifyM m UnifEnv {- unify_uniq = i,- unify_reqs = hmap,- unify_self_cid = self_cid,- unify_verbosity = verbosity,- unify_ctx = [],- unify_db = db,- unify_errs = errs }- final_errs <- readSTRef errs- case mb_r of- Just x | null final_errs -> return (Right x)- _ -> return (Left (map renderErrMsg (reverse final_errs)))--- NB: GHC 7.6 throws a hissy fit if you pattern match on 'm'.--type ErrCtx s = MsgDoc---- | The unification environment.-data UnifEnv s = UnifEnv {- -- | A supply of unique integers to label 'UnitIdU'- -- cells. This is used to determine loops in unit- -- identifiers (which can happen with mutual recursion.)- unify_uniq :: UnifRef s UnitIdUnique,- -- | The set of requirements in scope. When- -- a provision is brought into scope, we unify with- -- the requirement at the same module name to fill it.- -- This mapping grows monotonically.- unify_reqs :: UnifRef s (Map ModuleName (ModuleU s)),- -- | Component id of the unit we're linking. We use this- -- to detect if we fill a requirement with a local module,- -- which in principle should be OK but is not currently- -- supported by GHC.- unify_self_cid :: ComponentId,- -- | How verbose the error message should be- unify_verbosity :: Verbosity,- -- | The error reporting context- unify_ctx :: [ErrCtx s],- -- | The package index for expanding unit identifiers- unify_db :: FullDb,- -- | Accumulated errors- unify_errs :: UnifRef s [ErrMsg]- }--instance Functor (UnifyM s) where- fmap f (UnifyM m) = UnifyM (fmap (fmap (fmap f)) m)--instance Applicative (UnifyM s) where- pure = UnifyM . pure . pure . pure- UnifyM f <*> UnifyM x = UnifyM $ \r -> do- f' <- f r- case f' of- Nothing -> return Nothing- Just f'' -> do- x' <- x r- case x' of- Nothing -> return Nothing- Just x'' -> return (Just (f'' x''))--instance Monad (UnifyM s) where- return = pure- UnifyM m >>= f = UnifyM $ \r -> do- x <- m r- case x of- Nothing -> return Nothing- Just x' -> unUnifyM (f x') r---- | Lift a computation from 'ST' monad to 'UnifyM' monad.--- Internal use only.-liftST :: ST s a -> UnifyM s a-liftST m = UnifyM $ \_ -> fmap Just m--addErr :: MsgDoc -> UnifyM s ()-addErr msg = do- env <- getUnifEnv- let err = ErrMsg {- err_msg = msg,- err_ctx = unify_ctx env- }- liftST $ modifySTRef (unify_errs env) (\errs -> err:errs)--failWith :: MsgDoc -> UnifyM s a-failWith msg = do- addErr msg- failM--failM :: UnifyM s a-failM = UnifyM $ \_ -> return Nothing--failIfErrs :: UnifyM s ()-failIfErrs = do- env <- getUnifEnv- errs <- liftST $ readSTRef (unify_errs env)- when (not (null errs)) failM--tryM :: UnifyM s a -> UnifyM s (Maybe a)-tryM m =- UnifyM (\env -> do- mb_r <- unUnifyM m env- return (Just mb_r))--{--otherFail :: ErrMsg -> UnifyM s a-otherFail s = UnifyM $ \_ -> return (Left s)--unifyFail :: ErrMsg -> UnifyM s a-unifyFail err = do- env <- getUnifEnv- msg <- case unify_ctx env of- Nothing -> return (text "Unspecified unification error:" <+> err)- Just (ctx, mod1, mod2)- | unify_verbosity env > normal- -> do mod1' <- convertModuleU mod1- mod2' <- convertModuleU mod2- let extra = " (was unifying " ++ display mod1'- ++ " and " ++ display mod2' ++ ")"- return (ctx ++ err ++ extra)- | otherwise- -> return (ctx ++ err ++ " (for more information, pass -v flag)")- UnifyM $ \_ -> return (Left msg)--}---- | A convenient alias for mutable references in the unification monad.-type UnifRef s a = STRef s a---- | Imperatively read a 'UnifRef'.-readUnifRef :: UnifRef s a -> UnifyM s a-readUnifRef = liftST . readSTRef---- | Imperatively write a 'UnifRef'.-writeUnifRef :: UnifRef s a -> a -> UnifyM s ()-writeUnifRef x = liftST . writeSTRef x---- | Get the current unification environment.-getUnifEnv :: UnifyM s (UnifEnv s)-getUnifEnv = UnifyM $ \r -> return (return r)---- | Add a fixed message to the error context.-addErrContext :: Doc -> UnifyM s a -> UnifyM s a-addErrContext ctx m = addErrContextM ctx m---- | Add a message to the error context. It may make monadic queries.-addErrContextM :: ErrCtx s -> UnifyM s a -> UnifyM s a-addErrContextM ctx m =- UnifyM $ \r -> unUnifyM m r { unify_ctx = ctx : unify_ctx r }----------------------------------------------------------------------------- The "unifiable" variants of the data types------ In order to properly do unification over infinite trees, we--- need to union find over 'Module's and 'UnitId's. The pure--- representation is ill-equipped to do this, so we convert--- from the pure representation into one which is indirected--- through union-find. 'ModuleU' handles hole variables;--- 'UnitIdU' handles mu-binders.---- | Contents of a mutable 'ModuleU' reference.-data ModuleU' s- = ModuleU (UnitIdU s) ModuleName- | ModuleVarU ModuleName---- | Contents of a mutable 'UnitIdU' reference.-data UnitIdU' s- = UnitIdU UnitIdUnique ComponentId (Map ModuleName (ModuleU s))- | UnitIdThunkU DefUnitId---- | A mutable version of 'Module' which can be imperatively unified.-type ModuleU s = UnionFind.Point s (ModuleU' s)---- | A mutable version of 'UnitId' which can be imperatively unified.-type UnitIdU s = UnionFind.Point s (UnitIdU' s)---- | An integer for uniquely labeling 'UnitIdU' nodes. We need--- these labels in order to efficiently serialize 'UnitIdU's into--- 'UnitId's (we use the label to check if any parent is the--- node in question, and if so insert a deBruijn index instead.)--- These labels must be unique across all 'UnitId's/'Module's which--- participate in unification!-type UnitIdUnique = Int----------------------------------------------------------------------------- Conversion to the unifiable data types---- An environment for tracking the mu-bindings in scope.--- The invariant for a state @(m, i)@ is that [0..i] are--- keys of @m@; in fact, the @i-k@th entry is the @k@th--- de Bruijn index (this saves us from having to shift as--- we enter mu-binders.)-type MuEnv s = (IntMap (UnitIdU s), Int)--extendMuEnv :: MuEnv s -> UnitIdU s -> MuEnv s-extendMuEnv (m, i) x =- (IntMap.insert (i + 1) x m, i + 1)--{--lookupMuEnv :: MuEnv s -> Int {- de Bruijn index -} -> UnitIdU s-lookupMuEnv (m, i) k =- case IntMap.lookup (i - k) m of- -- Technically a user can trigger this by giving us a- -- bad 'UnitId', so handle this better.- Nothing -> error "lookupMuEnv: out of bounds (malformed de Bruijn index)"- Just v -> v--}--emptyMuEnv :: MuEnv s-emptyMuEnv = (IntMap.empty, -1)---- The workhorse functions. These share an environment:--- * @UnifRef s UnitIdUnique@ - the unique label supply for 'UnitIdU' nodes--- * @UnifRef s (Map ModuleName moduleU)@ - the (lazily initialized)--- environment containing the implicitly universally quantified--- @hole:A@ binders.--- * @MuEnv@ - the environment for mu-binders.--convertUnitId' :: MuEnv s- -> OpenUnitId- -> UnifyM s (UnitIdU s)--- TODO: this could be more lazy if we know there are no internal--- references-convertUnitId' _ (DefiniteUnitId uid) =- liftST $ UnionFind.fresh (UnitIdThunkU uid)-convertUnitId' stk (IndefFullUnitId cid insts) = do- fs <- fmap unify_uniq getUnifEnv- x <- liftST $ UnionFind.fresh (error "convertUnitId") -- tie the knot later- insts_u <- for insts $ convertModule' (extendMuEnv stk x)- u <- readUnifRef fs- writeUnifRef fs (u+1)- y <- liftST $ UnionFind.fresh (UnitIdU u cid insts_u)- liftST $ UnionFind.union x y- return y--- convertUnitId' stk (UnitIdVar i) = return (lookupMuEnv stk i)--convertModule' :: MuEnv s- -> OpenModule -> UnifyM s (ModuleU s)-convertModule' _stk (OpenModuleVar mod_name) = do- hmap <- fmap unify_reqs getUnifEnv- hm <- readUnifRef hmap- case Map.lookup mod_name hm of- Nothing -> do mod <- liftST $ UnionFind.fresh (ModuleVarU mod_name)- writeUnifRef hmap (Map.insert mod_name mod hm)- return mod- Just mod -> return mod-convertModule' stk (OpenModule uid mod_name) = do- uid_u <- convertUnitId' stk uid- liftST $ UnionFind.fresh (ModuleU uid_u mod_name)--convertUnitId :: OpenUnitId -> UnifyM s (UnitIdU s)-convertUnitId = convertUnitId' emptyMuEnv--convertModule :: OpenModule -> UnifyM s (ModuleU s)-convertModule = convertModule' emptyMuEnv------------------------------------------------------------------------------ Substitutions---- | The mutable counterpart of a 'ModuleSubst' (not defined here).-type ModuleSubstU s = Map ModuleName (ModuleU s)---- | Conversion of 'ModuleSubst' to 'ModuleSubstU'-convertModuleSubst :: Map ModuleName OpenModule -> UnifyM s (Map ModuleName (ModuleU s))-convertModuleSubst = traverse convertModule---- | Conversion of 'ModuleSubstU' to 'ModuleSubst'-convertModuleSubstU :: ModuleSubstU s -> UnifyM s OpenModuleSubst-convertModuleSubstU = traverse convertModuleU---------------------------------------------------------------------------- Conversion from the unifiable data types---- An environment for tracking candidates for adding a mu-binding.--- The invariant for a state @(m, i)@, is that if we encounter a node--- labeled @k@ such that @m[k -> v]@, then we can replace this--- node with the de Bruijn index @i-v@ referring to an enclosing--- mu-binder; furthermore, @range(m) = [0..i]@.-type MooEnv = (IntMap Int, Int)--emptyMooEnv :: MooEnv-emptyMooEnv = (IntMap.empty, -1)--extendMooEnv :: MooEnv -> UnitIdUnique -> MooEnv-extendMooEnv (m, i) k = (IntMap.insert k (i + 1) m, i + 1)--lookupMooEnv :: MooEnv -> UnitIdUnique -> Maybe Int-lookupMooEnv (m, i) k =- case IntMap.lookup k m of- Nothing -> Nothing- Just v -> Just (i-v) -- de Bruijn indexize---- The workhorse functions--convertUnitIdU' :: MooEnv -> UnitIdU s -> UnifyM s OpenUnitId-convertUnitIdU' stk uid_u = do- x <- liftST $ UnionFind.find uid_u- case x of- UnitIdThunkU uid -> return (DefiniteUnitId uid)- UnitIdU u cid insts_u ->- case lookupMooEnv stk u of- Just _i ->- failWith (text "Unsupported mutually recursive unit identifier")- -- return (UnitIdVar i)- Nothing -> do- insts <- for insts_u $ convertModuleU' (extendMooEnv stk u)- return (IndefFullUnitId cid insts)--convertModuleU' :: MooEnv -> ModuleU s -> UnifyM s OpenModule-convertModuleU' stk mod_u = do- mod <- liftST $ UnionFind.find mod_u- case mod of- ModuleVarU mod_name -> return (OpenModuleVar mod_name)- ModuleU uid_u mod_name -> do- uid <- convertUnitIdU' stk uid_u- return (OpenModule uid mod_name)---- Helper functions--convertUnitIdU :: UnitIdU s -> UnifyM s OpenUnitId-convertUnitIdU = convertUnitIdU' emptyMooEnv--convertModuleU :: ModuleU s -> UnifyM s OpenModule-convertModuleU = convertModuleU' emptyMooEnv---- | An empty 'ModuleScopeU'.-emptyModuleScopeU :: ModuleScopeU s-emptyModuleScopeU = (Map.empty, Map.empty)----- | The mutable counterpart of 'ModuleScope'.-type ModuleScopeU s = (ModuleProvidesU s, ModuleRequiresU s)--- | The mutable counterpart of 'ModuleProvides'-type ModuleProvidesU s = Map ModuleName [ModuleWithSourceU s]-type ModuleRequiresU s = ModuleProvidesU s-type ModuleWithSourceU s = WithSource (ModuleU s)---- TODO: Deduplicate this with Distribution.Backpack.MixLink.dispSource-ci_msg :: ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming -> Doc-ci_msg ci- | ci_implicit ci = text "build-depends:" <+> pp_pn- | otherwise = text "mixins:" <+> pp_pn <+> pretty (ci_renaming ci)- where- pn = pkgName (ci_pkgid ci)- pp_pn =- case ci_cname ci of- CLibName LMainLibName -> pretty pn- CLibName (LSubLibName cn) -> pretty pn <<>> colon <<>> pretty cn- -- Shouldn't happen- cn -> pretty pn <+> parens (pretty cn)---- | Convert a 'ModuleShape' into a 'ModuleScopeU', so we can do--- unification on it.-convertInclude- :: ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming- -> UnifyM s (ModuleScopeU s,- Either (ComponentInclude (UnitIdU s) ModuleRenaming) {- normal -}- (ComponentInclude (UnitIdU s) ModuleRenaming) {- sig -})-convertInclude ci@(ComponentInclude {- ci_ann_id = AnnotatedId {- ann_id = (uid, ModuleShape provs reqs),- ann_pid = pid,- ann_cname = compname- },- ci_renaming = incl@(IncludeRenaming prov_rns req_rns),- ci_implicit = implicit- }) = addErrContext (text "In" <+> ci_msg ci) $ do- let pn = packageName pid- the_source | implicit- = FromBuildDepends pn compname- | otherwise- = FromMixins pn compname incl- source = WithSource the_source-- -- Suppose our package has two requirements A and B, and- -- we include it with @requires (A as X)@- -- There are three closely related things we compute based- -- off of @reqs@ and @reqs_rns@:- --- -- 1. The requirement renaming (A -> X)- -- 2. The requirement substitution (A -> <X>, B -> <B>)-- -- Requirement renaming. This is read straight off the syntax:- --- -- [nothing] ==> [empty]- -- requires (B as Y) ==> B -> Y- --- -- Requirement renamings are NOT injective: if two requirements- -- are mapped to the same name, the intent is to merge them- -- together. But they are *functions*, so @B as X, B as Y@ is- -- illegal.-- req_rename_list <-- case req_rns of- DefaultRenaming -> return []- HidingRenaming _ -> do- -- Not valid here for requires!- addErr $ text "Unsupported syntax" <+>- quotes (text "requires hiding (...)")- return []- ModuleRenaming rns -> return rns-- let req_rename_listmap :: Map ModuleName [ModuleName]- req_rename_listmap =- Map.fromListWith (++) [ (k,[v]) | (k,v) <- req_rename_list ]- req_rename <- sequenceA . flip Map.mapWithKey req_rename_listmap $ \k vs0 ->- case vs0 of- [] -> error "req_rename"- [v] -> return v- v:vs -> do addErr $- text "Conflicting renamings of requirement" <+> quotes (pretty k) $$- text "Renamed to: " <+> vcat (map pretty (v:vs))- return v-- let req_rename_fn k = case Map.lookup k req_rename of- Nothing -> k- Just v -> v-- -- Requirement substitution.- --- -- A -> X ==> A -> <X>- let req_subst = fmap OpenModuleVar req_rename-- uid_u <- convertUnitId (modSubst req_subst uid)-- -- Requirement mapping. This is just taking the range of the- -- requirement substitution, and making a mapping so that it is- -- convenient to merge things together. It INCLUDES the implicit- -- mappings.- --- -- A -> X ==> X -> <X>, B -> <B>- reqs_u <- convertModuleRequires . Map.fromList $- [ (k, [source (OpenModuleVar k)])- | k <- map req_rename_fn (Set.toList reqs)- ]-- -- Report errors if there were unused renamings- let leftover = Map.keysSet req_rename `Set.difference` reqs- unless (Set.null leftover) $- addErr $- hang (text "The" <+> text (showComponentName compname) <+>- text "from package" <+> quotes (pretty pid)- <+> text "does not require:") 4- (vcat (map pretty (Set.toList leftover)))-- -- Provision computation is more complex.- -- For example, if we have:- --- -- include p (A as X) requires (B as Y)- -- where A -> q[B=<B>]:A- --- -- Then we need:- --- -- X -> [("p", q[B=<B>]:A)]- --- -- There are a bunch of clever ways to present the algorithm- -- but here is the simple one:- --- -- 1. If we have a default renaming, apply req_subst- -- to provs and use that.- --- -- 2. Otherwise, build a map by successively looking- -- up the referenced modules in the renaming in provs.- --- -- Importantly, overlapping rename targets get accumulated- -- together. It's not an (immediate) error.- (pre_prov_scope, prov_rns') <-- case prov_rns of- DefaultRenaming -> return (Map.toList provs, prov_rns)- HidingRenaming hides ->- let hides_set = Set.fromList hides- in let r = [ (k,v)- | (k,v) <- Map.toList provs- , not (k `Set.member` hides_set) ]- -- GHC doesn't understand hiding, so expand it out!- in return (r, ModuleRenaming (map ((\x -> (x,x)).fst) r))- ModuleRenaming rns -> do- r <- sequence- [ case Map.lookup from provs of- Just m -> return (to, m)- Nothing -> failWith $- text "Package" <+> quotes (pretty pid) <+>- text "does not expose the module" <+> quotes (pretty from)- | (from, to) <- rns ]- return (r, prov_rns)- let prov_scope = modSubst req_subst- $ Map.fromListWith (++)- [ (k, [source v])- | (k, v) <- pre_prov_scope ]-- provs_u <- convertModuleProvides prov_scope-- -- TODO: Assert that provs_u is empty if provs was empty- return ((provs_u, reqs_u),- -- NB: We test that requirements is not null so that- -- users can create packages with zero module exports- -- that cause some C library to linked in, etc.- (if Map.null provs && not (Set.null reqs)- then Right -- is sig- else Left) (ComponentInclude {- ci_ann_id = AnnotatedId {- ann_id = uid_u,- ann_pid = pid,- ann_cname = compname- },- ci_renaming = prov_rns',- ci_implicit = ci_implicit ci- }))---- | Convert a 'ModuleScopeU' to a 'ModuleScope'.-convertModuleScopeU :: ModuleScopeU s -> UnifyM s ModuleScope-convertModuleScopeU (provs_u, reqs_u) = do- provs <- convertModuleProvidesU provs_u- reqs <- convertModuleRequiresU reqs_u- -- TODO: Test that the requirements are still free. If they- -- are not, they got unified, and that's dodgy at best.- return (ModuleScope provs reqs)---- | Convert a 'ModuleProvides' to a 'ModuleProvidesU'-convertModuleProvides :: ModuleProvides -> UnifyM s (ModuleProvidesU s)-convertModuleProvides = traverse (traverse (traverse convertModule))---- | Convert a 'ModuleProvidesU' to a 'ModuleProvides'-convertModuleProvidesU :: ModuleProvidesU s -> UnifyM s ModuleProvides-convertModuleProvidesU = traverse (traverse (traverse convertModuleU))--convertModuleRequires :: ModuleRequires -> UnifyM s (ModuleRequiresU s)-convertModuleRequires = convertModuleProvides--convertModuleRequiresU :: ModuleRequiresU s -> UnifyM s ModuleRequires-convertModuleRequiresU = convertModuleProvidesU
− Distribution/CabalSpecVersion.hs
@@ -1,146 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.CabalSpecVersion where--import Prelude ()-import Distribution.Compat.Prelude---- | Different Cabal-the-spec versions.------ We branch based on this at least in the parser.----data CabalSpecVersion- = CabalSpecV1_0 -- ^ this is older than 'CabalSpecV1_2'- | CabalSpecV1_2 -- ^ new syntax (sections)- | CabalSpecV1_4- | CabalSpecV1_6- | CabalSpecV1_8- | CabalSpecV1_10- | CabalSpecV1_12- -- 1.16 -- 1.14: no changes- | CabalSpecV1_18- | CabalSpecV1_20- | CabalSpecV1_22- | CabalSpecV1_24- | CabalSpecV2_0- | CabalSpecV2_2- | CabalSpecV2_4- | CabalSpecV3_0- -- 3.2: no changes- | CabalSpecV3_4- deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data, Generic)--instance Binary CabalSpecVersion-instance Structured CabalSpecVersion-instance NFData CabalSpecVersion where rnf = genericRnf---- | Show cabal spec version, but not the way in the .cabal files------ @since 3.0.0.0-showCabalSpecVersion :: CabalSpecVersion -> String-showCabalSpecVersion CabalSpecV3_4 = "3.4"-showCabalSpecVersion CabalSpecV3_0 = "3.0"-showCabalSpecVersion CabalSpecV2_4 = "2.4"-showCabalSpecVersion CabalSpecV2_2 = "2.2"-showCabalSpecVersion CabalSpecV2_0 = "2.0"-showCabalSpecVersion CabalSpecV1_24 = "1.24"-showCabalSpecVersion CabalSpecV1_22 = "1.22"-showCabalSpecVersion CabalSpecV1_20 = "1.20"-showCabalSpecVersion CabalSpecV1_18 = "1.18"-showCabalSpecVersion CabalSpecV1_12 = "1.12"-showCabalSpecVersion CabalSpecV1_10 = "1.10"-showCabalSpecVersion CabalSpecV1_8 = "1.8"-showCabalSpecVersion CabalSpecV1_6 = "1.6"-showCabalSpecVersion CabalSpecV1_4 = "1.4"-showCabalSpecVersion CabalSpecV1_2 = "1.2"-showCabalSpecVersion CabalSpecV1_0 = "1.0"--cabalSpecLatest :: CabalSpecVersion-cabalSpecLatest = CabalSpecV3_4---- | Parse 'CabalSpecVersion' from version digits.------ It may fail if for recent versions the version is not exact.----cabalSpecFromVersionDigits :: [Int] -> Maybe CabalSpecVersion-cabalSpecFromVersionDigits v- | v == [3,4] = Just CabalSpecV3_4- | v == [3,0] = Just CabalSpecV3_0- | v == [2,4] = Just CabalSpecV2_4- | v == [2,2] = Just CabalSpecV2_2- | v == [2,0] = Just CabalSpecV2_0- | v >= [1,25] = Nothing- | v >= [1,23] = Just CabalSpecV1_24- | v >= [1,21] = Just CabalSpecV1_22- | v >= [1,19] = Just CabalSpecV1_20- | v >= [1,17] = Just CabalSpecV1_18- | v >= [1,11] = Just CabalSpecV1_12- | v >= [1,9] = Just CabalSpecV1_10- | v >= [1,7] = Just CabalSpecV1_8- | v >= [1,5] = Just CabalSpecV1_6- | v >= [1,3] = Just CabalSpecV1_4- | v >= [1,1] = Just CabalSpecV1_2- | otherwise = Just CabalSpecV1_0---- | @since 3.4.0.0-cabalSpecToVersionDigits :: CabalSpecVersion -> [Int]-cabalSpecToVersionDigits CabalSpecV3_4 = [3,4]-cabalSpecToVersionDigits CabalSpecV3_0 = [3,0]-cabalSpecToVersionDigits CabalSpecV2_4 = [2,4]-cabalSpecToVersionDigits CabalSpecV2_2 = [2,2]-cabalSpecToVersionDigits CabalSpecV2_0 = [2,0]-cabalSpecToVersionDigits CabalSpecV1_24 = [1,24]-cabalSpecToVersionDigits CabalSpecV1_22 = [1,22]-cabalSpecToVersionDigits CabalSpecV1_20 = [1,20]-cabalSpecToVersionDigits CabalSpecV1_18 = [1,18]-cabalSpecToVersionDigits CabalSpecV1_12 = [1,12]-cabalSpecToVersionDigits CabalSpecV1_10 = [1,10]-cabalSpecToVersionDigits CabalSpecV1_8 = [1,8]-cabalSpecToVersionDigits CabalSpecV1_6 = [1,6]-cabalSpecToVersionDigits CabalSpecV1_4 = [1,4]-cabalSpecToVersionDigits CabalSpecV1_2 = [1,2]-cabalSpecToVersionDigits CabalSpecV1_0 = [1,0]---- | What is the minimum Cabal library version which knows how handle--- this spec version.------ /Note:/ this is a point where we could decouple cabal-spec and Cabal--- versions, if we ever want that.------ >>> cabalSpecMinimumLibraryVersion CabalSpecV3_0--- [2,5]------ >>> cabalSpecMinimumLibraryVersion CabalSpecV2_4--- [2,3]------ @since 3.4.0.0-cabalSpecMinimumLibraryVersion :: CabalSpecVersion -> [Int]-cabalSpecMinimumLibraryVersion CabalSpecV1_0 = [1,0]-cabalSpecMinimumLibraryVersion csv = case cabalSpecToVersionDigits (pred csv) of- [x,y] -> [x, y+1]- xs -> xs--specHasCommonStanzas :: CabalSpecVersion -> HasCommonStanzas-specHasCommonStanzas v =- if v >= CabalSpecV2_2- then HasCommonStanzas- else NoCommonStanzas--specHasElif :: CabalSpecVersion -> HasElif-specHasElif v = - if v >= CabalSpecV2_2- then HasElif- else NoElif------------------------------------------------------------------------------------ Booleans------------------------------------------------------------------------------------ IDEA: make some kind of tagged booleans?-data HasElif = HasElif | NoElif- deriving (Eq, Show)--data HasCommonStanzas = HasCommonStanzas | NoCommonStanzas- deriving (Eq, Show)--data HasGlobstar = HasGlobstar | NoGlobstar
− Distribution/Compat/Async.hs
@@ -1,148 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}--- | 'Async', yet using 'MVar's.------ Adopted from @async@ library--- Copyright (c) 2012, Simon Marlow--- Licensed under BSD-3-Clause------ @since 3.2.0.0----module Distribution.Compat.Async (- AsyncM,- withAsync, waitCatch,- wait, asyncThreadId,- cancel, uninterruptibleCancel, AsyncCancelled (..),- -- * Cabal extras- withAsyncNF,- ) where--import Control.Concurrent (ThreadId, forkIO)-import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar)-import Control.DeepSeq (NFData, force)-import Control.Exception- (BlockedIndefinitelyOnMVar (..), Exception (..), SomeException (..), catch, evaluate, mask, throwIO, throwTo, try, uninterruptibleMask_)-import Control.Monad (void)-import Data.Typeable (Typeable)-import GHC.Exts (inline)--#if MIN_VERSION_base(4,7,0)-import Control.Exception (asyncExceptionFromException, asyncExceptionToException)-#endif---- | Async, but based on 'MVar', as we don't depend on @stm@.-data AsyncM a = Async- { asyncThreadId :: {-# UNPACK #-} !ThreadId- -- ^ Returns the 'ThreadId' of the thread running- -- the given 'Async'.- , _asyncMVar :: MVar (Either SomeException a)- }---- | Spawn an asynchronous action in a separate thread, and pass its--- @Async@ handle to the supplied function. When the function returns--- or throws an exception, 'uninterruptibleCancel' is called on the @Async@.------ > withAsync action inner = mask $ \restore -> do--- > a <- async (restore action)--- > restore (inner a) `finally` uninterruptibleCancel a------ This is a useful variant of 'async' that ensures an @Async@ is--- never left running unintentionally.------ Note: a reference to the child thread is kept alive until the call--- to `withAsync` returns, so nesting many `withAsync` calls requires--- linear memory.----withAsync :: IO a -> (AsyncM a -> IO b) -> IO b-withAsync = inline withAsyncUsing forkIO--withAsyncNF :: NFData a => IO a -> (AsyncM a -> IO b) -> IO b-withAsyncNF m = inline withAsyncUsing forkIO (m >>= evaluateNF) where- evaluateNF = evaluate . force--withAsyncUsing :: (IO () -> IO ThreadId) -> IO a -> (AsyncM a -> IO b) -> IO b--- The bracket version works, but is slow. We can do better by--- hand-coding it:-withAsyncUsing doFork = \action inner -> do- var <- newEmptyMVar- mask $ \restore -> do- t <- doFork $ try (restore action) >>= putMVar var- let a = Async t var- r <- restore (inner a) `catchAll` \e -> do- uninterruptibleCancel a- throwIO e- uninterruptibleCancel a- return r---- | Wait for an asynchronous action to complete, and return its--- value. If the asynchronous action threw an exception, then the--- exception is re-thrown by 'wait'.------ > wait = atomically . waitSTM----{-# INLINE wait #-}-wait :: AsyncM a -> IO a-wait a = do- res <- waitCatch a- case res of- Left (SomeException e) -> throwIO e- Right x -> return x---- | Wait for an asynchronous action to complete, and return either--- @Left e@ if the action raised an exception @e@, or @Right a@ if it--- returned a value @a@.------ > waitCatch = atomically . waitCatchSTM----{-# INLINE waitCatch #-}-waitCatch :: AsyncM a -> IO (Either SomeException a)-waitCatch (Async _ var) = tryAgain (readMVar var)- where- -- See: https://github.com/simonmar/async/issues/14- tryAgain f = f `catch` \BlockedIndefinitelyOnMVar -> f--catchAll :: IO a -> (SomeException -> IO a) -> IO a-catchAll = catch---- | Cancel an asynchronous action by throwing the @AsyncCancelled@--- exception to it, and waiting for the `Async` thread to quit.--- Has no effect if the 'Async' has already completed.------ > cancel a = throwTo (asyncThreadId a) AsyncCancelled <* waitCatch a------ Note that 'cancel' will not terminate until the thread the 'Async'--- refers to has terminated. This means that 'cancel' will block for--- as long said thread blocks when receiving an asynchronous exception.------ For example, it could block if:------ * It's executing a foreign call, and thus cannot receive the asynchronous--- exception;--- * It's executing some cleanup handler after having received the exception,--- and the handler is blocking.-{-# INLINE cancel #-}-cancel :: AsyncM a -> IO ()-cancel a@(Async t _) = do- throwTo t AsyncCancelled- void (waitCatch a)---- | The exception thrown by `cancel` to terminate a thread.-data AsyncCancelled = AsyncCancelled- deriving (Show, Eq- , Typeable- )--instance Exception AsyncCancelled where-#if MIN_VERSION_base(4,7,0)- -- wraps in SomeAsyncException- -- See https://github.com/ghc/ghc/commit/756a970eacbb6a19230ee3ba57e24999e4157b09- fromException = asyncExceptionFromException- toException = asyncExceptionToException-#endif---- | Cancel an asynchronous action------ This is a variant of `cancel`, but it is not interruptible.-{-# INLINE uninterruptibleCancel #-}-uninterruptibleCancel :: AsyncM a -> IO ()-uninterruptibleCancel = uninterruptibleMask_ . cancel
− Distribution/Compat/Binary.hs
@@ -1,71 +0,0 @@-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__ >= 711-{-# LANGUAGE PatternSynonyms #-}-#endif--#ifndef MIN_VERSION_binary-#define MIN_VERSION_binary(x, y, z) 0-#endif--module Distribution.Compat.Binary- ( decodeOrFailIO- , decodeFileOrFail'-#if __GLASGOW_HASKELL__ >= 708 || MIN_VERSION_binary(0,7,0)- , module Data.Binary-#else- , Binary(..)- , decode, encode, encodeFile-#endif- ) where--import Control.Exception (ErrorCall (..), catch, evaluate)-import Data.ByteString.Lazy (ByteString)--#if __GLASGOW_HASKELL__ >= 708 || MIN_VERSION_binary(0,7,0)--import Data.Binary---- | Lazily reconstruct a value previously written to a file.-decodeFileOrFail' :: Binary a => FilePath -> IO (Either String a)-decodeFileOrFail' f = either (Left . snd) Right `fmap` decodeFileOrFail f--#else--import Data.Binary.Get-import Data.Binary.Put-import qualified Data.ByteString.Lazy as BSL--import Distribution.Compat.Binary.Class-import Distribution.Compat.Binary.Generic ()---- | Decode a value from a lazy ByteString, reconstructing the--- original structure.----decode :: Binary a => ByteString -> a-decode = runGet get---- | Encode a value using binary serialisation to a lazy ByteString.----encode :: Binary a => a -> ByteString-encode = runPut . put-{-# INLINE encode #-}---- | Lazily reconstruct a value previously written to a file.-decodeFileOrFail' :: Binary a => FilePath -> IO (Either String a)-decodeFileOrFail' f = decodeOrFailIO =<< BSL.readFile f---- | Lazily serialise a value to a file-encodeFile :: Binary a => FilePath -> a -> IO ()-encodeFile f = BSL.writeFile f . encode--#endif--decodeOrFailIO :: Binary a => ByteString -> IO (Either String a)-decodeOrFailIO bs =- catch (evaluate (decode bs) >>= return . Right) handler- where-#if MIN_VERSION_base(4,9,0)- handler (ErrorCallWithLocation str _) = return $ Left str-#else- handler (ErrorCall str) = return $ Left str-#endif
− Distribution/Compat/Binary/Class.hs
@@ -1,519 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE DefaultSignatures #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Compat.Binary.Class--- Copyright : Lennart Kolmodin--- License : BSD3-style (see LICENSE)------ Maintainer : Lennart Kolmodin <kolmodin@gmail.com>--- Stability : unstable--- Portability : portable to Hugs and GHC. Requires the FFI and some flexible instances------ Typeclass and instances for binary serialization.-----------------------------------------------------------------------------------module Distribution.Compat.Binary.Class (-- -- * The Binary class- Binary(..)-- -- * Support for generics- , GBinary(..)-- ) where--import Data.Word--import Data.Binary.Put-import Data.Binary.Get--import Control.Applicative ((<$>), (<*>), (*>))-import Foreign--import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString.Lazy as L--import Data.Char (chr,ord)-import Data.List (unfoldr)-import Data.Foldable (traverse_)---- And needed for the instances:-import qualified Data.ByteString as B-import qualified Data.Map as Map-import qualified Data.Set as Set-import qualified Data.IntMap as IntMap-import qualified Data.IntSet as IntSet-import qualified Data.Ratio as R--import qualified Data.Tree as T--import Data.Array.Unboxed--import GHC.Generics--import qualified Data.Sequence as Seq-import qualified Data.Foldable as Fold----------------------------------------------------------------------------class GBinary f where- gput :: f t -> Put- gget :: Get (f t)---- | The 'Binary' class provides 'put' and 'get', methods to encode and--- decode a Haskell value to a lazy 'ByteString'. It mirrors the 'Read' and--- 'Show' classes for textual representation of Haskell types, and is--- suitable for serialising Haskell values to disk, over the network.------ For decoding and generating simple external binary formats (e.g. C--- structures), Binary may be used, but in general is not suitable--- for complex protocols. Instead use the 'Put' and 'Get' primitives--- directly.------ Instances of Binary should satisfy the following property:------ > decode . encode == id------ That is, the 'get' and 'put' methods should be the inverse of each--- other. A range of instances are provided for basic Haskell types.----class Binary t where- -- | Encode a value in the Put monad.- put :: t -> Put- -- | Decode a value in the Get monad- get :: Get t-- default put :: (Generic t, GBinary (Rep t)) => t -> Put- put = gput . from-- default get :: (Generic t, GBinary (Rep t)) => Get t- get = to `fmap` gget----------------------------------------------------------------------------- Simple instances---- The () type need never be written to disk: values of singleton type--- can be reconstructed from the type alone-instance Binary () where- put () = return ()- get = return ()---- Bools are encoded as a byte in the range 0 .. 1-instance Binary Bool where- put = putWord8 . fromIntegral . fromEnum- get = fmap (toEnum . fromIntegral) getWord8---- Values of type 'Ordering' are encoded as a byte in the range 0 .. 2-instance Binary Ordering where- put = putWord8 . fromIntegral . fromEnum- get = fmap (toEnum . fromIntegral) getWord8----------------------------------------------------------------------------- Words and Ints---- Words8s are written as bytes-instance Binary Word8 where- put = putWord8- get = getWord8---- Words16s are written as 2 bytes in big-endian (network) order-instance Binary Word16 where- put = putWord16be- get = getWord16be---- Words32s are written as 4 bytes in big-endian (network) order-instance Binary Word32 where- put = putWord32be- get = getWord32be---- Words64s are written as 8 bytes in big-endian (network) order-instance Binary Word64 where- put = putWord64be- get = getWord64be---- Int8s are written as a single byte.-instance Binary Int8 where- put i = put (fromIntegral i :: Word8)- get = fmap fromIntegral (get :: Get Word8)---- Int16s are written as a 2 bytes in big endian format-instance Binary Int16 where- put i = put (fromIntegral i :: Word16)- get = fmap fromIntegral (get :: Get Word16)---- Int32s are written as a 4 bytes in big endian format-instance Binary Int32 where- put i = put (fromIntegral i :: Word32)- get = fmap fromIntegral (get :: Get Word32)---- Int64s are written as a 4 bytes in big endian format-instance Binary Int64 where- put i = put (fromIntegral i :: Word64)- get = fmap fromIntegral (get :: Get Word64)------------------------------------------------------------------------------ Words are are written as Word64s, that is, 8 bytes in big endian format-instance Binary Word where- put i = put (fromIntegral i :: Word64)- get = fmap fromIntegral (get :: Get Word64)---- Ints are are written as Int64s, that is, 8 bytes in big endian format-instance Binary Int where- put i = put (fromIntegral i :: Int64)- get = fmap fromIntegral (get :: Get Int64)-------------------------------------------------------------------------------- Portable, and pretty efficient, serialisation of Integer------- Fixed-size type for a subset of Integer-type SmallInt = Int32---- Integers are encoded in two ways: if they fit inside a SmallInt,--- they're written as a byte tag, and that value. If the Integer value--- is too large to fit in a SmallInt, it is written as a byte array,--- along with a sign and length field.--instance Binary Integer where-- {-# INLINE put #-}- put n | n >= lo && n <= hi = do- putWord8 0- put (fromIntegral n :: SmallInt) -- fast path- where- lo = fromIntegral (minBound :: SmallInt) :: Integer- hi = fromIntegral (maxBound :: SmallInt) :: Integer-- put n = do- putWord8 1- put sign- put (unroll (abs n)) -- unroll the bytes- where- sign = fromIntegral (signum n) :: Word8-- {-# INLINE get #-}- get = do- tag <- get :: Get Word8- case tag of- 0 -> fmap fromIntegral (get :: Get SmallInt)- _ -> do sign <- get- bytes <- get- let v = roll bytes- return $! if sign == (1 :: Word8) then v else - v------- Fold and unfold an Integer to and from a list of its bytes----unroll :: Integer -> [Word8]-unroll = unfoldr step- where- step 0 = Nothing- step i = Just (fromIntegral i, i `shiftR` 8)--roll :: [Word8] -> Integer-roll = foldr unstep 0- where- unstep b a = a `shiftL` 8 .|. fromIntegral b--{-------- An efficient, raw serialisation for Integer (GHC only)------- TODO This instance is not architecture portable. GMP stores numbers as--- arrays of machine sized words, so the byte format is not portable across--- architectures with different endianness and word size.--import Data.ByteString.Base (toForeignPtr,unsafePackAddress, memcpy)-import GHC.Base hiding (ord, chr)-import GHC.Prim-import GHC.Ptr (Ptr(..))-import GHC.IOBase (IO(..))--instance Binary Integer where- put (S# i) = putWord8 0 *> put (I# i)- put (J# s ba) = do- putWord8 1- put (I# s)- put (BA ba)-- get = do- b <- getWord8- case b of- 0 -> do (I# i#) <- get- return (S# i#)- _ -> do (I# s#) <- get- (BA a#) <- get- return (J# s# a#)--instance Binary ByteArray where-- -- Pretty safe.- put (BA ba) =- let sz = sizeofByteArray# ba -- (primitive) in *bytes*- addr = byteArrayContents# ba- bs = unsafePackAddress (I# sz) addr- in put bs -- write as a ByteString. easy, yay!-- -- Pretty scary. Should be quick though- get = do- (fp, off, n@(I# sz)) <- fmap toForeignPtr get -- so decode a ByteString- assert (off == 0) $ return $ unsafePerformIO $ do- (MBA arr) <- newByteArray sz -- and copy it into a ByteArray#- let to = byteArrayContents# (unsafeCoerce# arr) -- urk, is this safe?- withForeignPtr fp $ \from -> memcpy (Ptr to) from (fromIntegral n)- freezeByteArray arr---- wrapper for ByteArray#-data ByteArray = BA {-# UNPACK #-} !ByteArray#-data MBA = MBA {-# UNPACK #-} !(MutableByteArray# RealWorld)--newByteArray :: Int# -> IO MBA-newByteArray sz = IO $ \s ->- case newPinnedByteArray# sz s of { (# s', arr #) ->- (# s', MBA arr #) }--freezeByteArray :: MutableByteArray# RealWorld -> IO ByteArray-freezeByteArray arr = IO $ \s ->- case unsafeFreezeByteArray# arr s of { (# s', arr' #) ->- (# s', BA arr' #) }---}--instance (Binary a,Integral a) => Binary (R.Ratio a) where- put r = put (R.numerator r) *> put (R.denominator r)- get = (R.%) <$> get <*> get------------------------------------------------------------------------------ Char is serialised as UTF-8-instance Binary Char where- put a | c <= 0x7f = put (fromIntegral c :: Word8)- | c <= 0x7ff = do put (0xc0 .|. y)- put (0x80 .|. z)- | c <= 0xffff = do put (0xe0 .|. x)- put (0x80 .|. y)- put (0x80 .|. z)- | c <= 0x10ffff = do put (0xf0 .|. w)- put (0x80 .|. x)- put (0x80 .|. y)- put (0x80 .|. z)- | otherwise = error "Not a valid Unicode code point"- where- c = ord a- z, y, x, w :: Word8- z = fromIntegral (c .&. 0x3f)- y = fromIntegral (shiftR c 6 .&. 0x3f)- x = fromIntegral (shiftR c 12 .&. 0x3f)- w = fromIntegral (shiftR c 18 .&. 0x7)-- get = do- let getByte = fmap (fromIntegral :: Word8 -> Int) get- shiftL6 = flip shiftL 6 :: Int -> Int- w <- getByte- r <- case () of- _ | w < 0x80 -> return w- | w < 0xe0 -> do- x <- fmap (xor 0x80) getByte- return (x .|. shiftL6 (xor 0xc0 w))- | w < 0xf0 -> do- x <- fmap (xor 0x80) getByte- y <- fmap (xor 0x80) getByte- return (y .|. shiftL6 (x .|. shiftL6- (xor 0xe0 w)))- | otherwise -> do- x <- fmap (xor 0x80) getByte- y <- fmap (xor 0x80) getByte- z <- fmap (xor 0x80) getByte- return (z .|. shiftL6 (y .|. shiftL6- (x .|. shiftL6 (xor 0xf0 w))))- return $! chr r----------------------------------------------------------------------------- Instances for the first few tuples--instance (Binary a, Binary b) => Binary (a,b) where- put (a,b) = put a *> put b- get = (,) <$> get <*> get--instance (Binary a, Binary b, Binary c) => Binary (a,b,c) where- put (a,b,c) = put a *> put b *> put c- get = (,,) <$> get <*> get <*> get--instance (Binary a, Binary b, Binary c, Binary d) => Binary (a,b,c,d) where- put (a,b,c,d) = put a *> put b *> put c *> put d- get = (,,,) <$> get <*> get <*> get <*> get--instance (Binary a, Binary b, Binary c, Binary d, Binary e) => Binary (a,b,c,d,e) where- put (a,b,c,d,e) = put a *> put b *> put c *> put d *> put e- get = (,,,,) <$> get <*> get <*> get <*> get <*> get------- and now just recurse:-----instance (Binary a, Binary b, Binary c, Binary d, Binary e, Binary f)- => Binary (a,b,c,d,e,f) where- put (a,b,c,d,e,f) = put (a,(b,c,d,e,f))- get = do (a,(b,c,d,e,f)) <- get ; return (a,b,c,d,e,f)--instance (Binary a, Binary b, Binary c, Binary d, Binary e, Binary f, Binary g)- => Binary (a,b,c,d,e,f,g) where- put (a,b,c,d,e,f,g) = put (a,(b,c,d,e,f,g))- get = do (a,(b,c,d,e,f,g)) <- get ; return (a,b,c,d,e,f,g)--instance (Binary a, Binary b, Binary c, Binary d, Binary e,- Binary f, Binary g, Binary h)- => Binary (a,b,c,d,e,f,g,h) where- put (a,b,c,d,e,f,g,h) = put (a,(b,c,d,e,f,g,h))- get = do (a,(b,c,d,e,f,g,h)) <- get ; return (a,b,c,d,e,f,g,h)--instance (Binary a, Binary b, Binary c, Binary d, Binary e,- Binary f, Binary g, Binary h, Binary i)- => Binary (a,b,c,d,e,f,g,h,i) where- put (a,b,c,d,e,f,g,h,i) = put (a,(b,c,d,e,f,g,h,i))- get = do (a,(b,c,d,e,f,g,h,i)) <- get ; return (a,b,c,d,e,f,g,h,i)--instance (Binary a, Binary b, Binary c, Binary d, Binary e,- Binary f, Binary g, Binary h, Binary i, Binary j)- => Binary (a,b,c,d,e,f,g,h,i,j) where- put (a,b,c,d,e,f,g,h,i,j) = put (a,(b,c,d,e,f,g,h,i,j))- get = do (a,(b,c,d,e,f,g,h,i,j)) <- get ; return (a,b,c,d,e,f,g,h,i,j)----------------------------------------------------------------------------- Container types--instance Binary a => Binary [a] where- put l = put (length l) *> traverse_ put l- get = do n <- get :: Get Int- getMany n---- | 'getMany n' get 'n' elements in order, without blowing the stack.-getMany :: Binary a => Int -> Get [a]-getMany n = go [] n- where- go xs 0 = return $! reverse xs- go xs i = do x <- get- -- we must seq x to avoid stack overflows due to laziness in- -- (>>=)- x `seq` go (x:xs) (i-1)-{-# INLINE getMany #-}--instance (Binary a) => Binary (Maybe a) where- put Nothing = putWord8 0- put (Just x) = putWord8 1 *> put x- get = do- w <- getWord8- case w of- 0 -> return Nothing- _ -> fmap Just get--instance (Binary a, Binary b) => Binary (Either a b) where- put (Left a) = putWord8 0 *> put a- put (Right b) = putWord8 1 *> put b- get = do- w <- getWord8- case w of- 0 -> fmap Left get- _ -> fmap Right get----------------------------------------------------------------------------- ByteStrings (have specially efficient instances)--instance Binary B.ByteString where- put bs = do put (B.length bs)- putByteString bs- get = get >>= getByteString------- Using old versions of fps, this is a type synonym, and non portable------ Requires 'flexible instances'----instance Binary ByteString where- put bs = do put (fromIntegral (L.length bs) :: Int)- putLazyByteString bs- get = get >>= getLazyByteString----------------------------------------------------------------------------- Maps and Sets--instance (Binary a) => Binary (Set.Set a) where- put s = put (Set.size s) *> traverse_ put (Set.toAscList s)- get = fmap Set.fromDistinctAscList get--instance (Binary k, Binary e) => Binary (Map.Map k e) where- put m = put (Map.size m) *> traverse_ put (Map.toAscList m)- get = fmap Map.fromDistinctAscList get--instance Binary IntSet.IntSet where- put s = put (IntSet.size s) *> traverse_ put (IntSet.toAscList s)- get = fmap IntSet.fromDistinctAscList get--instance (Binary e) => Binary (IntMap.IntMap e) where- put m = put (IntMap.size m) *> traverse_ put (IntMap.toAscList m)- get = fmap IntMap.fromDistinctAscList get----------------------------------------------------------------------------- Queues and Sequences--instance (Binary e) => Binary (Seq.Seq e) where- put s = put (Seq.length s) *> Fold.traverse_ put s- get = do n <- get :: Get Int- rep Seq.empty n get- where rep xs 0 _ = return $! xs- rep xs n g = xs `seq` n `seq` do- x <- g- rep (xs Seq.|> x) (n-1) g----------------------------------------------------------------------------- Floating point--instance Binary Double where- put d = put (decodeFloat d)- get = encodeFloat <$> get <*> get--instance Binary Float where- put f = put (decodeFloat f)- get = encodeFloat <$> get <*> get----------------------------------------------------------------------------- Trees--instance (Binary e) => Binary (T.Tree e) where- put (T.Node r s) = put r *> put s- get = T.Node <$> get <*> get----------------------------------------------------------------------------- Arrays--instance (Binary i, Ix i, Binary e) => Binary (Array i e) where- put a = do- put (bounds a)- put (rangeSize $ bounds a) -- write the length- traverse_ put (elems a) -- now the elems.- get = do- bs <- get- n <- get -- read the length- xs <- getMany n -- now the elems.- return (listArray bs xs)------- The IArray UArray e constraint is non portable. Requires flexible instances----instance (Binary i, Ix i, Binary e, IArray UArray e) => Binary (UArray i e) where- put a = do- put (bounds a)- put (rangeSize $ bounds a) -- now write the length- traverse_ put (elems a)- get = do- bs <- get- n <- get- xs <- getMany n- return (listArray bs xs)
− Distribution/Compat/Binary/Generic.hs
@@ -1,128 +0,0 @@-{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, KindSignatures,- ScopedTypeVariables, Trustworthy, TypeOperators, TypeSynonymInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Compat.Binary.Generic--- Copyright : Bryan O'Sullivan--- License : BSD3-style (see LICENSE)------ Maintainer : Bryan O'Sullivan <bos@serpentine.com>--- Stability : unstable--- Portability : Only works with GHC 7.2 and newer------ Instances for supporting GHC generics.----------------------------------------------------------------------------------module Distribution.Compat.Binary.Generic- (- ) where--import Control.Applicative-import Distribution.Compat.Binary.Class-import Data.Binary.Get-import Data.Binary.Put-import Data.Bits-import Data.Word-import GHC.Generics---- Type without constructors-instance GBinary V1 where- gput _ = return ()- gget = return undefined---- Constructor without arguments-instance GBinary U1 where- gput U1 = return ()- gget = return U1---- Product: constructor with parameters-instance (GBinary a, GBinary b) => GBinary (a :*: b) where- gput (x :*: y) = gput x >> gput y- gget = (:*:) <$> gget <*> gget---- Metadata (constructor name, etc)-instance GBinary a => GBinary (M1 i c a) where- gput = gput . unM1- gget = M1 <$> gget---- Constants, additional parameters, and rank-1 recursion-instance Binary a => GBinary (K1 i a) where- gput = put . unK1- gget = K1 <$> get---- Borrowed from the cereal package.---- The following GBinary instance for sums has support for serializing--- types with up to 2^64-1 constructors. It will use the minimal--- number of bytes needed to encode the constructor. For example when--- a type has 2^8 constructors or less it will use a single byte to--- encode the constructor. If it has 2^16 constructors or less it will--- use two bytes, and so on till 2^64-1.--#define GUARD(WORD) (size - 1) <= fromIntegral (maxBound :: WORD)-#define PUTSUM(WORD) GUARD(WORD) = putSum (0 :: WORD) (fromIntegral size)-#define GETSUM(WORD) GUARD(WORD) = (get :: Get WORD) >>= checkGetSum (fromIntegral size)--instance ( GSum a, GSum b- , GBinary a, GBinary b- , SumSize a, SumSize b) => GBinary (a :+: b) where- gput | PUTSUM(Word8) | PUTSUM(Word16) | PUTSUM(Word32) | PUTSUM(Word64)- | otherwise = sizeError "encode" size- where- size = unTagged (sumSize :: Tagged (a :+: b) Word64)-- gget | GETSUM(Word8) | GETSUM(Word16) | GETSUM(Word32) | GETSUM(Word64)- | otherwise = sizeError "decode" size- where- size = unTagged (sumSize :: Tagged (a :+: b) Word64)--sizeError :: Show size => String -> size -> error-sizeError s size =- error $ "Can't " ++ s ++ " a type with " ++ show size ++ " constructors"----------------------------------------------------------------------------checkGetSum :: (Ord word, Num word, Bits word, GSum f)- => word -> word -> Get (f a)-checkGetSum size code | code < size = getSum code size- | otherwise = fail "Unknown encoding for constructor"-{-# INLINE checkGetSum #-}--class GSum f where- getSum :: (Ord word, Num word, Bits word) => word -> word -> Get (f a)- putSum :: (Num w, Bits w, Binary w) => w -> w -> f a -> Put--instance (GSum a, GSum b, GBinary a, GBinary b) => GSum (a :+: b) where- getSum !code !size | code < sizeL = L1 <$> getSum code sizeL- | otherwise = R1 <$> getSum (code - sizeL) sizeR- where- sizeL = size `shiftR` 1- sizeR = size - sizeL-- putSum !code !size s = case s of- L1 x -> putSum code sizeL x- R1 x -> putSum (code + sizeL) sizeR x- where- sizeL = size `shiftR` 1- sizeR = size - sizeL--instance GBinary a => GSum (C1 c a) where- getSum _ _ = gget-- putSum !code _ x = put code *> gput x----------------------------------------------------------------------------class SumSize f where- sumSize :: Tagged f Word64--newtype Tagged (s :: * -> *) b = Tagged {unTagged :: b}--instance (SumSize a, SumSize b) => SumSize (a :+: b) where- sumSize = Tagged $ unTagged (sumSize :: Tagged a Word64) +- unTagged (sumSize :: Tagged b Word64)--instance SumSize (C1 c a) where- sumSize = Tagged 1
− Distribution/Compat/CharParsing.hs
@@ -1,357 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -fspec-constr -fspec-constr-count=8 #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Compat.CharParsing--- Copyright : (c) Edward Kmett 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable------ Parsers for character streams------ Originally in @parsers@ package.----------------------------------------------------------------------------------module Distribution.Compat.CharParsing- (- -- * Combinators- oneOf -- :: CharParsing m => [Char] -> m Char- , noneOf -- :: CharParsing m => [Char] -> m Char- , spaces -- :: CharParsing m => m ()- , space -- :: CharParsing m => m Char- , newline -- :: CharParsing m => m Char- , tab -- :: CharParsing m => m Char- , upper -- :: CharParsing m => m Char- , lower -- :: CharParsing m => m Char- , alphaNum -- :: CharParsing m => m Char- , letter -- :: CharParsing m => m Char- , digit -- :: CharParsing m => m Char- , hexDigit -- :: CharParsing m => m Char- , octDigit -- :: CharParsing m => m Char- , satisfyRange -- :: CharParsing m => Char -> Char -> m Char- -- * Class- , CharParsing(..)- -- * Cabal additions- , integral- , signedIntegral- , munch1- , munch- , skipSpaces1- , module Distribution.Compat.Parsing- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.State.Lazy as Lazy-import Control.Monad.Trans.State.Strict as Strict-import Control.Monad.Trans.Writer.Lazy as Lazy-import Control.Monad.Trans.Writer.Strict as Strict-import Control.Monad.Trans.RWS.Lazy as Lazy-import Control.Monad.Trans.RWS.Strict as Strict-import Control.Monad.Trans.Reader (ReaderT (..))-import Control.Monad.Trans.Identity (IdentityT (..))-import Data.Char-import Data.Text (Text, unpack)--import qualified Text.Parsec as Parsec--import Distribution.Compat.Parsing---- | @oneOf cs@ succeeds if the current character is in the supplied--- list of characters @cs@. Returns the parsed character. See also--- 'satisfy'.------ > vowel = oneOf "aeiou"-oneOf :: CharParsing m => [Char] -> m Char-oneOf xs = satisfy (\c -> c `elem` xs)-{-# INLINE oneOf #-}---- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current--- character is /not/ in the supplied list of characters @cs@. Returns the--- parsed character.------ > consonant = noneOf "aeiou"-noneOf :: CharParsing m => [Char] -> m Char-noneOf xs = satisfy (\c -> c `notElem` xs)-{-# INLINE noneOf #-}---- | Skips /zero/ or more white space characters. See also 'skipMany'.-spaces :: CharParsing m => m ()-spaces = skipMany space <?> "white space"-{-# INLINE spaces #-}---- | Parses a white space character (any character which satisfies 'isSpace')--- Returns the parsed character.-space :: CharParsing m => m Char-space = satisfy isSpace <?> "space"-{-# INLINE space #-}---- | Parses a newline character (\'\\n\'). Returns a newline character.-newline :: CharParsing m => m Char-newline = char '\n' <?> "new-line"-{-# INLINE newline #-}---- | Parses a tab character (\'\\t\'). Returns a tab character.-tab :: CharParsing m => m Char-tab = char '\t' <?> "tab"-{-# INLINE tab #-}---- | Parses an upper case letter. Returns the parsed character.-upper :: CharParsing m => m Char-upper = satisfy isUpper <?> "uppercase letter"-{-# INLINE upper #-}---- | Parses a lower case character. Returns the parsed character.-lower :: CharParsing m => m Char-lower = satisfy isLower <?> "lowercase letter"-{-# INLINE lower #-}---- | Parses a letter or digit. Returns the parsed character.-alphaNum :: CharParsing m => m Char-alphaNum = satisfy isAlphaNum <?> "letter or digit"-{-# INLINE alphaNum #-}---- | Parses a letter (an upper case or lower case character). Returns the--- parsed character.-letter :: CharParsing m => m Char-letter = satisfy isAlpha <?> "letter"-{-# INLINE letter #-}---- | Parses a digit. Returns the parsed character.-digit :: CharParsing m => m Char-digit = satisfy isDigit <?> "digit"-{-# INLINE digit #-}---- | Parses a hexadecimal digit (a digit or a letter between \'a\' and--- \'f\' or \'A\' and \'F\'). Returns the parsed character.-hexDigit :: CharParsing m => m Char-hexDigit = satisfy isHexDigit <?> "hexadecimal digit"-{-# INLINE hexDigit #-}---- | Parses an octal digit (a character between \'0\' and \'7\'). Returns--- the parsed character.-octDigit :: CharParsing m => m Char-octDigit = satisfy isOctDigit <?> "octal digit"-{-# INLINE octDigit #-}--satisfyRange :: CharParsing m => Char -> Char -> m Char-satisfyRange a z = satisfy (\c -> c >= a && c <= z)-{-# INLINE satisfyRange #-}---- | Additional functionality needed to parse character streams.-class Parsing m => CharParsing m where- -- | Parse a single character of the input, with UTF-8 decoding- satisfy :: (Char -> Bool) -> m Char-- -- | @char c@ parses a single character @c@. Returns the parsed- -- character (i.e. @c@).- --- -- /e.g./- --- -- @semiColon = 'char' ';'@- char :: Char -> m Char- char c = satisfy (c ==) <?> show [c]- {-# INLINE char #-}-- -- | @notChar c@ parses any single character other than @c@. Returns the parsed- -- character.- notChar :: Char -> m Char- notChar c = satisfy (c /=)- {-# INLINE notChar #-}-- -- | This parser succeeds for any character. Returns the parsed character.- anyChar :: m Char- anyChar = satisfy (const True)- {-# INLINE anyChar #-}-- -- | @string s@ parses a sequence of characters given by @s@. Returns- -- the parsed string (i.e. @s@).- --- -- > divOrMod = string "div"- -- > <|> string "mod"- string :: String -> m String- string s = s <$ try (traverse_ char s) <?> show s- {-# INLINE string #-}-- -- | @text t@ parses a sequence of characters determined by the text @t@ Returns- -- the parsed text fragment (i.e. @t@).- --- -- Using @OverloadedStrings@:- --- -- > divOrMod = text "div"- -- > <|> text "mod"- text :: Text -> m Text- text t = t <$ string (unpack t)- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m) => CharParsing (Lazy.StateT s m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m) => CharParsing (Strict.StateT s m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m) => CharParsing (ReaderT e m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Strict.WriterT w m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Lazy.WriterT w m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Lazy.RWST r w s m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Strict.RWST r w s m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance (CharParsing m, MonadPlus m) => CharParsing (IdentityT m) where- satisfy = lift . satisfy- {-# INLINE satisfy #-}- char = lift . char- {-# INLINE char #-}- notChar = lift . notChar- {-# INLINE notChar #-}- anyChar = lift anyChar- {-# INLINE anyChar #-}- string = lift . string- {-# INLINE string #-}- text = lift . text- {-# INLINE text #-}--instance Parsec.Stream s m Char => CharParsing (Parsec.ParsecT s u m) where- satisfy = Parsec.satisfy- char = Parsec.char- notChar c = Parsec.satisfy (/= c)- anyChar = Parsec.anyChar- string = Parsec.string------------------------------------------------------------------------------------ Our additions----------------------------------------------------------------------------------integral :: (CharParsing m, Integral a) => m a-integral = toNumber <$> some d <?> "integral"- where- toNumber = foldl' (\a b -> a * 10 + b) 0- d = f <$> satisfyRange '0' '9'- f '0' = 0- f '1' = 1- f '2' = 2- f '3' = 3- f '4' = 4- f '5' = 5- f '6' = 6- f '7' = 7- f '8' = 8- f '9' = 9- f _ = error "panic! integral"-{-# INLINE integral #-}---- | Accepts negative (starting with @-@) and positive (without sign) integral--- numbers.--- --- @since 3.4.0.0-signedIntegral :: (CharParsing m, Integral a) => m a-signedIntegral = negate <$ char '-' <*> integral <|> integral-{-# INLINE signedIntegral #-}---- | Greedily munch characters while predicate holds.--- Require at least one character.-munch1 :: CharParsing m => (Char -> Bool) -> m String-munch1 = some . satisfy-{-# INLINE munch1 #-}---- | Greedely munch characters while predicate holds.--- Always succeeds.-munch :: CharParsing m => (Char -> Bool) -> m String-munch = many . satisfy-{-# INLINE munch #-}--skipSpaces1 :: CharParsing m => m ()-skipSpaces1 = skipSome space-{-# INLINE skipSpaces1 #-}
− Distribution/Compat/CopyFile.hs
@@ -1,250 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_HADDOCK hide #-}-module Distribution.Compat.CopyFile (- copyFile,- copyFileChanged,- filesEqual,- copyOrdinaryFile,- copyExecutableFile,- setFileOrdinary,- setFileExecutable,- setDirOrdinary,- ) where--import Prelude ()-import Distribution.Compat.Prelude--#ifndef mingw32_HOST_OS-import Distribution.Compat.Internal.TempFile--import Control.Exception- ( bracketOnError )-import qualified Data.ByteString.Lazy as BSL-import System.IO.Error- ( ioeSetLocation )-import System.Directory- ( doesFileExist, renameFile, removeFile )-import System.FilePath- ( takeDirectory )-import System.IO- ( IOMode(ReadMode), hClose, hGetBuf, hPutBuf, hFileSize- , withBinaryFile )-import Foreign- ( allocaBytes )--import System.Posix.Types- ( FileMode )-import System.Posix.Internals- ( c_chmod, withFilePath )-import Foreign.C- ( throwErrnoPathIfMinus1_ )--#else /* else mingw32_HOST_OS */--import qualified Data.ByteString.Lazy as BSL-import System.IO.Error- ( ioeSetLocation )-import System.Directory- ( doesFileExist )-import System.FilePath- ( addTrailingPathSeparator- , hasTrailingPathSeparator- , isPathSeparator- , isRelative- , joinDrive- , joinPath- , pathSeparator- , pathSeparators- , splitDirectories- , splitDrive- )-import System.IO- ( IOMode(ReadMode), hFileSize- , withBinaryFile )--import qualified System.Win32.File as Win32 ( copyFile )-#endif /* mingw32_HOST_OS */--copyOrdinaryFile, copyExecutableFile :: FilePath -> FilePath -> IO ()-copyOrdinaryFile src dest = copyFile src dest >> setFileOrdinary dest-copyExecutableFile src dest = copyFile src dest >> setFileExecutable dest--setFileOrdinary, setFileExecutable, setDirOrdinary :: FilePath -> IO ()-#ifndef mingw32_HOST_OS-setFileOrdinary path = setFileMode path 0o644 -- file perms -rw-r--r---setFileExecutable path = setFileMode path 0o755 -- file perms -rwxr-xr-x--setFileMode :: FilePath -> FileMode -> IO ()-setFileMode name m =- withFilePath name $ \s -> do- throwErrnoPathIfMinus1_ "setFileMode" name (c_chmod s m)-#else-setFileOrdinary _ = return ()-setFileExecutable _ = return ()-#endif--- This happens to be true on Unix and currently on Windows too:-setDirOrdinary = setFileExecutable---- | Copies a file to a new destination.--- Often you should use `copyFileChanged` instead.-copyFile :: FilePath -> FilePath -> IO ()-copyFile fromFPath toFPath =- copy- `catchIO` (\ioe -> throwIO (ioeSetLocation ioe "copyFile"))- where-#ifndef mingw32_HOST_OS- copy = withBinaryFile fromFPath ReadMode $ \hFrom ->- bracketOnError openTmp cleanTmp $ \(tmpFPath, hTmp) ->- do allocaBytes bufferSize $ copyContents hFrom hTmp- hClose hTmp- renameFile tmpFPath toFPath- openTmp = openBinaryTempFile (takeDirectory toFPath) ".copyFile.tmp"- cleanTmp (tmpFPath, hTmp) = do- hClose hTmp `catchIO` \_ -> return ()- removeFile tmpFPath `catchIO` \_ -> return ()- bufferSize = 4096-- copyContents hFrom hTo buffer = do- count <- hGetBuf hFrom buffer bufferSize- when (count > 0) $ do- hPutBuf hTo buffer count- copyContents hFrom hTo buffer-#else- copy = Win32.copyFile (toExtendedLengthPath fromFPath)- (toExtendedLengthPath toFPath)- False---- NOTE: Shamelessly lifted from System.Directory.Internal.Windows---- | Add the @"\\\\?\\"@ prefix if necessary or possible. The path remains--- unchanged if the prefix is not added. This function can sometimes be used--- to bypass the @MAX_PATH@ length restriction in Windows API calls.------ See Note [Path normalization].-toExtendedLengthPath :: FilePath -> FilePath-toExtendedLengthPath path- | isRelative path = path- | otherwise =- case normalisedPath of- '\\' : '?' : '?' : '\\' : _ -> normalisedPath- '\\' : '\\' : '?' : '\\' : _ -> normalisedPath- '\\' : '\\' : '.' : '\\' : _ -> normalisedPath- '\\' : subpath@('\\' : _) -> "\\\\?\\UNC" <> subpath- _ -> "\\\\?\\" <> normalisedPath- where normalisedPath = simplifyWindows path---- | Similar to 'normalise' but:------ * empty paths stay empty,--- * parent dirs (@..@) are expanded, and--- * paths starting with @\\\\?\\@ are preserved.------ The goal is to preserve the meaning of paths better than 'normalise'.------ Note [Path normalization]--- 'normalise' doesn't simplify path names but will convert / into \\--- this would normally not be a problem as once the path hits the RTS we would--- have simplified the path then. However since we're calling the WIn32 API--- directly we have to do the simplification before the call. Without this the--- path Z:// would become Z:\\\\ and when converted to a device path the path--- becomes \\?\Z:\\\\ which is an invalid path.------ This is not a bug in normalise as it explicitly states that it won't simplify--- a FilePath.-simplifyWindows :: FilePath -> FilePath-simplifyWindows "" = ""-simplifyWindows path =- case drive' of- "\\\\?\\" -> drive' <> subpath- _ -> simplifiedPath- where- simplifiedPath = joinDrive drive' subpath'- (drive, subpath) = splitDrive path- drive' = upperDrive (normaliseTrailingSep (normalisePathSeps drive))- subpath' = appendSep . avoidEmpty . prependSep . joinPath .- stripPardirs . expandDots . skipSeps .- splitDirectories $ subpath-- upperDrive d = case d of- c : ':' : s | isAlpha c && all isPathSeparator s -> toUpper c : ':' : s- _ -> d- skipSeps = filter (not . (`elem` (pure <$> pathSeparators)))- stripPardirs | pathIsAbsolute || subpathIsAbsolute = dropWhile (== "..")- | otherwise = id- prependSep | subpathIsAbsolute = (pathSeparator :)- | otherwise = id- avoidEmpty | not pathIsAbsolute- && (null drive || hasTrailingPathSep) -- prefer "C:" over "C:."- = emptyToCurDir- | otherwise = id- appendSep p | hasTrailingPathSep- && not (pathIsAbsolute && null p)- = addTrailingPathSeparator p- | otherwise = p- pathIsAbsolute = not (isRelative path)- subpathIsAbsolute = any isPathSeparator (take 1 subpath)- hasTrailingPathSep = hasTrailingPathSeparator subpath---- | Given a list of path segments, expand @.@ and @..@. The path segments--- must not contain path separators.-expandDots :: [FilePath] -> [FilePath]-expandDots = reverse . go []- where- go ys' xs' =- case xs' of- [] -> ys'- x : xs ->- case x of- "." -> go ys' xs- ".." ->- case ys' of- [] -> go (x : ys') xs- ".." : _ -> go (x : ys') xs- _ : ys -> go ys xs- _ -> go (x : ys') xs---- | Convert to the right kind of slashes.-normalisePathSeps :: FilePath -> FilePath-normalisePathSeps p = (\ c -> if isPathSeparator c then pathSeparator else c) <$> p---- | Remove redundant trailing slashes and pick the right kind of slash.-normaliseTrailingSep :: FilePath -> FilePath-normaliseTrailingSep path = do- let path' = reverse path- let (sep, path'') = span isPathSeparator path'- let addSep = if null sep then id else (pathSeparator :)- reverse (addSep path'')---- | Convert empty paths to the current directory, otherwise leave it--- unchanged.-emptyToCurDir :: FilePath -> FilePath-emptyToCurDir "" = "."-emptyToCurDir path = path-#endif /* mingw32_HOST_OS */---- | Like `copyFile`, but does not touch the target if source and destination--- are already byte-identical. This is recommended as it is useful for--- time-stamp based recompilation avoidance.-copyFileChanged :: FilePath -> FilePath -> IO ()-copyFileChanged src dest = do- equal <- filesEqual src dest- unless equal $ copyFile src dest---- | Checks if two files are byte-identical.--- Returns False if either of the files do not exist or if files--- are of different size.-filesEqual :: FilePath -> FilePath -> IO Bool-filesEqual f1 f2 = do- ex1 <- doesFileExist f1- ex2 <- doesFileExist f2- if not (ex1 && ex2) then return False else- withBinaryFile f1 ReadMode $ \h1 ->- withBinaryFile f2 ReadMode $ \h2 -> do- s1 <- hFileSize h1- s2 <- hFileSize h2- if s1 /= s2- then return False- else do- c1 <- BSL.hGetContents h1- c2 <- BSL.hGetContents h2- return $! c1 == c2
− Distribution/Compat/CreatePipe.hs
@@ -1,81 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--module Distribution.Compat.CreatePipe (createPipe) where--#if MIN_VERSION_process(1,2,1)-import System.Process (createPipe)-#else-import System.IO (Handle, hSetBinaryMode)--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Compat.Stack---- The mingw32_HOST_OS CPP macro is GHC-specific-#ifdef mingw32_HOST_OS-import qualified Prelude-import Control.Exception (onException)-import Foreign.C.Error (throwErrnoIfMinus1_)-import Foreign.C.Types (CInt(..), CUInt(..))-import Foreign.Ptr (Ptr)-import Foreign.Marshal.Array (allocaArray)-import Foreign.Storable (peek, peekElemOff)-import GHC.IO.FD (mkFD)-import GHC.IO.Device (IODeviceType(Stream))-import GHC.IO.Handle.FD (mkHandleFromFD)-import System.IO (IOMode(ReadMode, WriteMode))-#elif defined ghcjs_HOST_OS-#else-import System.Posix.IO (fdToHandle)-import qualified System.Posix.IO as Posix-#endif--createPipe :: IO (Handle, Handle)--- The mingw32_HOST_OS CPP macro is GHC-specific-#ifdef mingw32_HOST_OS-createPipe = do- (readfd, writefd) <- allocaArray 2 $ \ pfds -> do- throwErrnoIfMinus1_ "_pipe" $ c__pipe pfds 2 ({- _O_BINARY -} 32768)- readfd <- peek pfds- writefd <- peekElemOff pfds 1- return (readfd, writefd)- (do readh <- fdToHandle readfd ReadMode- writeh <- fdToHandle writefd WriteMode- hSetBinaryMode readh True- hSetBinaryMode writeh True- return (readh, writeh)) `onException` (close readfd >> close writefd)- where- fdToHandle :: CInt -> IOMode -> IO Handle- fdToHandle fd mode = do- (fd', deviceType) <- mkFD fd mode (Just (Stream, 0, 0)) False False- mkHandleFromFD fd' deviceType "" mode False Nothing-- close :: CInt -> IO ()- close = throwErrnoIfMinus1_ "_close" . c__close- where _ = callStack -- TODO: attach call stack to exception-- _ = callStack -- TODO: attach call stack to exceptions--foreign import ccall "io.h _pipe" c__pipe ::- Ptr CInt -> CUInt -> CInt -> Prelude.IO CInt--foreign import ccall "io.h _close" c__close ::- CInt -> Prelude.IO CInt-#elif defined ghcjs_HOST_OS-createPipe = error "createPipe"- where- _ = callStack-#else-createPipe = do- (readfd, writefd) <- Posix.createPipe- readh <- fdToHandle readfd- writeh <- fdToHandle writefd- hSetBinaryMode readh True- hSetBinaryMode writeh True- return (readh, writeh)- where- _ = callStack-#endif-#endif
− Distribution/Compat/DList.hs
@@ -1,53 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Compat.DList--- Copyright : (c) Ben Gamari 2015-2019--- License : BSD3------ Maintainer : cabal-dev@haskell.org--- Stability : experimental--- Portability : portable------ A very simple difference list.-module Distribution.Compat.DList (- DList,- runDList,- empty,- singleton,- fromList,- toList,- snoc,-) where--import Prelude ()-import Distribution.Compat.Prelude hiding (toList, empty)---- | Difference list.-newtype DList a = DList ([a] -> [a])--runDList :: DList a -> [a]-runDList (DList run) = run []---- | Make 'DList' with containing single element.-singleton :: a -> DList a-singleton a = DList (a:)---- | @since 3.4.0.0-empty :: DList a-empty = DList id--fromList :: [a] -> DList a-fromList as = DList (as ++)--toList :: DList a -> [a]-toList = runDList--snoc :: DList a -> a -> DList a-snoc xs x = xs <> singleton x--instance Monoid (DList a) where- mempty = empty- mappend = (<>)--instance Semigroup (DList a) where- DList a <> DList b = DList (a . b)
− Distribution/Compat/Directory.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE CPP #-}--module Distribution.Compat.Directory-( listDirectory-, makeAbsolute-, doesPathExist-) where--#if MIN_VERSION_directory(1,2,7)-import System.Directory as Dir hiding (doesPathExist)-import System.Directory (doesPathExist)-#else-import System.Directory as Dir-#endif-#if !MIN_VERSION_directory(1,2,2)-import System.FilePath as Path-#endif--#if !MIN_VERSION_directory(1,2,5)--listDirectory :: FilePath -> IO [FilePath]-listDirectory path =- filter f `fmap` Dir.getDirectoryContents path- where f filename = filename /= "." && filename /= ".."--#endif--#if !MIN_VERSION_directory(1,2,2)--makeAbsolute :: FilePath -> IO FilePath-makeAbsolute p | Path.isAbsolute p = return p- | otherwise = do- cwd <- Dir.getCurrentDirectory- return $ cwd </> p--#endif--#if !MIN_VERSION_directory(1,2,7)--doesPathExist :: FilePath -> IO Bool-doesPathExist path = do- -- not using Applicative, as this way we can do less IO- e <- doesDirectoryExist path- if e- then return True- else doesFileExist path--#endif-
− Distribution/Compat/Environment.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# OPTIONS_HADDOCK hide #-}--module Distribution.Compat.Environment- ( getEnvironment, lookupEnv, setEnv, unsetEnv )- where--import Prelude ()-import qualified Prelude-import Distribution.Compat.Prelude--#ifndef mingw32_HOST_OS-#if __GLASGOW_HASKELL__ < 708-import Foreign.C.Error (throwErrnoIf_)-#endif-#endif--import qualified System.Environment as System-import System.Environment (lookupEnv)-#if __GLASGOW_HASKELL__ >= 708-import System.Environment (unsetEnv)-#endif--import Distribution.Compat.Stack--#ifdef mingw32_HOST_OS-import Foreign.C-#if __GLASGOW_HASKELL__ < 708-import Foreign.Ptr (nullPtr)-#endif-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--- On Windows, the names of environment variables are case-insensitive, but are--- often given in mixed-case (e.g. "PATH" is "Path"), so we have to normalise--- them.-getEnvironment = fmap upcaseVars System.getEnvironment- where- upcaseVars = map upcaseVar- upcaseVar (var, val) = (map toUpper var, val)-#else-getEnvironment = System.getEnvironment-#endif---- | @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_ = 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")- where- _ = callStack -- TODO: attach CallStack to exception--# 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 -> Prelude.IO Bool-#else-setEnv_ key value = do- withFilePath key $ \ keyP ->- withFilePath value $ \ valueP ->- throwErrnoIfMinus1_ "setenv" $- c_setenv keyP valueP (fromIntegral (fromEnum True))- where- _ = callStack -- TODO: attach CallStack to exception--foreign import ccall unsafe "setenv"- c_setenv :: CString -> CString -> CInt -> Prelude.IO CInt-#endif /* mingw32_HOST_OS */--#if __GLASGOW_HASKELL__ < 708---- | @unsetEnv name@ removes the specified environment variable from the--- environment of the current process.------ Throws `Control.Exception.IOException` if @name@ is the empty string or--- contains an equals sign.------ @since 4.7.0.0-unsetEnv :: String -> IO ()-#ifdef mingw32_HOST_OS-unsetEnv key = withCWString key $ \k -> do- success <- c_SetEnvironmentVariable k nullPtr- unless success $ do- -- We consider unsetting an environment variable that does not exist not as- -- an error, hence we ignore eRROR_ENVVAR_NOT_FOUND.- err <- c_GetLastError- unless (err == eRROR_ENVVAR_NOT_FOUND) $ do- throwGetLastError "unsetEnv"--eRROR_ENVVAR_NOT_FOUND :: DWORD-eRROR_ENVVAR_NOT_FOUND = 203--foreign import WINDOWS_CCONV unsafe "windows.h GetLastError"- c_GetLastError:: IO DWORD-#else-unsetEnv key = withFilePath key (throwErrnoIf_ (/= 0) "unsetEnv" . c_unsetenv)-#if __GLASGOW_HASKELL__ > 706-foreign import ccall unsafe "__hsbase_unsetenv" c_unsetenv :: CString -> Prelude.IO CInt-#else--- HACK: We hope very hard that !UNSETENV_RETURNS_VOID-foreign import ccall unsafe "unsetenv" c_unsetenv :: CString -> Prelude.IO CInt-#endif-#endif--#endif
− Distribution/Compat/Exception.hs
@@ -1,37 +0,0 @@-{-# LANGUAGE CPP #-}-module Distribution.Compat.Exception (- catchIO,- catchExit,- tryIO,- displayException,- ) where--#ifdef MIN_VERSION_base-#define MINVER_base_48 MIN_VERSION_base(4,8,0)-#else-#define MINVER_base_48 (__GLASGOW_HASKELL__ >= 710)-#endif--import System.Exit-import qualified Control.Exception as Exception--#if MINVER_base_48-import Control.Exception (displayException)-#endif---- | Try 'IOException'.-tryIO :: IO a -> IO (Either Exception.IOException a)-tryIO = Exception.try---- | Catch 'IOException'.-catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a-catchIO = Exception.catch---- | Catch 'ExitCode'-catchExit :: IO a -> (ExitCode -> IO a) -> IO a-catchExit = Exception.catch--#if !MINVER_base_48-displayException :: Exception.Exception e => e -> String-displayException = show-#endif
− Distribution/Compat/FilePath.hs
@@ -1,27 +0,0 @@-{-# LANGUAGE CPP #-}--{-# OPTIONS_GHC -fno-warn-unused-imports #-}--module Distribution.Compat.FilePath-( isExtensionOf-, stripExtension-) where--import Data.List ( isSuffixOf, stripPrefix )-import System.FilePath--#if !MIN_VERSION_filepath(1,4,2)-isExtensionOf :: String -> FilePath -> Bool-isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions-isExtensionOf ext = isSuffixOf ('.':ext) . takeExtensions-#endif--#if !MIN_VERSION_filepath(1,4,1)-stripExtension :: String -> FilePath -> Maybe FilePath-stripExtension [] path = Just path-stripExtension ext@(x:_) path = stripSuffix dotExt path- where- dotExt = if isExtSeparator x then ext else '.':ext- stripSuffix :: Eq a => [a] -> [a] -> Maybe [a]- stripSuffix xs ys = fmap reverse $ stripPrefix (reverse xs) (reverse ys)-#endif
− Distribution/Compat/GetShortPathName.hs
@@ -1,59 +0,0 @@-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Compat.GetShortPathName------ Maintainer : cabal-devel@haskell.org--- Portability : Windows-only------ Win32 API 'GetShortPathName' function.--module Distribution.Compat.GetShortPathName ( getShortPathName )- where--import Prelude ()-import Distribution.Compat.Prelude--#ifdef mingw32_HOST_OS--import qualified Prelude-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 -> Prelude.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.------ From MS's GetShortPathName docs:------ Passing NULL for [the second] parameter and zero for cchBuffer--- will always return the required buffer size for a--- specified lpszLongPath.----getShortPathName :: FilePath -> IO FilePath-getShortPathName path =- Win32.withTString path $ \c_path -> do- c_len <- Win32.failIfZero "GetShortPathName #1 failed!" $- c_GetShortPathName c_path Win32.nullPtr 0- let arr_len = fromIntegral c_len- allocaArray arr_len $ \c_out -> do- void $ Win32.failIfZero "GetShortPathName #2 failed!" $- c_GetShortPathName c_path c_out c_len- Win32.peekTString c_out--#else--getShortPathName :: FilePath -> IO FilePath-getShortPathName path = return path--#endif
− Distribution/Compat/Graph.hs
@@ -1,408 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Compat.Graph--- Copyright : (c) Edward Z. Yang 2016--- License : BSD3------ Maintainer : cabal-dev@haskell.org--- Stability : experimental--- Portability : portable------ A data type representing directed graphs, backed by "Data.Graph".--- It is strict in the node type.------ This is an alternative interface to "Data.Graph". In this interface,--- nodes (identified by the 'IsNode' type class) are associated with a--- key and record the keys of their neighbors. This interface is more--- convenient than 'Data.Graph.Graph', which requires vertices to be--- explicitly handled by integer indexes.------ The current implementation has somewhat peculiar performance--- characteristics. The asymptotics of all map-like operations mirror--- their counterparts in "Data.Map". However, to perform a graph--- operation, we first must build the "Data.Graph" representation, an--- operation that takes /O(V + E log V)/. However, this operation can--- be amortized across all queries on that particular graph.------ Some nodes may be broken, i.e., refer to neighbors which are not--- stored in the graph. In our graph algorithms, we transparently--- ignore such edges; however, you can easily query for the broken--- vertices of a graph using 'broken' (and should, e.g., to ensure that--- a closure of a graph is well-formed.) It's possible to take a closed--- subset of a broken graph and get a well-formed graph.-----------------------------------------------------------------------------------module Distribution.Compat.Graph (- -- * Graph type- Graph,- IsNode(..),- -- * Query- null,- size,- member,- lookup,- -- * Construction- empty,- insert,- deleteKey,- deleteLookup,- -- * Combine- unionLeft,- unionRight,- -- * Graph algorithms- stronglyConnComp,- SCC(..),- cycles,- broken,- neighbors,- revNeighbors,- closure,- revClosure,- topSort,- revTopSort,- -- * Conversions- -- ** Maps- toMap,- -- ** Lists- fromDistinctList,- toList,- keys,- -- ** Sets- keysSet,- -- ** Graphs- toGraph,- -- * Node type- Node(..),- nodeValue,-) where--import Distribution.Compat.Prelude hiding (empty, lookup, null, toList)-import Prelude ()--import Data.Array ((!))-import Data.Graph (SCC (..))-import Distribution.Utils.Structured (Structure (..), Structured (..))--import qualified Data.Array as Array-import qualified Data.Foldable as Foldable-import qualified Data.Graph as G-import qualified Data.Map.Strict as Map-import qualified Data.Set as Set-import qualified Data.Tree as Tree-import qualified Distribution.Compat.Prelude as Prelude---- | A graph of nodes @a@. The nodes are expected to have instance--- of class 'IsNode'.-data Graph a- = Graph {- graphMap :: !(Map (Key a) a),- -- Lazily cached graph representation- graphForward :: G.Graph,- graphAdjoint :: G.Graph,- graphVertexToNode :: G.Vertex -> a,- graphKeyToVertex :: Key a -> Maybe G.Vertex,- graphBroken :: [(a, [Key a])]- }- deriving (Typeable)---- NB: Not a Functor! (or Traversable), because you need--- to restrict Key a ~ Key b. We provide our own mapping--- functions.---- General strategy is most operations are deferred to the--- Map representation.--instance Show a => Show (Graph a) where- show = show . toList--instance (IsNode a, Read a, Show (Key a)) => Read (Graph a) where- readsPrec d s = map (\(a,r) -> (fromDistinctList a, r)) (readsPrec d s)--instance (IsNode a, Binary a, Show (Key a)) => Binary (Graph a) where- put x = put (toList x)- get = fmap fromDistinctList get--instance Structured a => Structured (Graph a) where- structure p = Nominal (typeRep p) 0 "Graph" [structure (Proxy :: Proxy a)]--instance (Eq (Key a), Eq a) => Eq (Graph a) where- g1 == g2 = graphMap g1 == graphMap g2--instance Foldable.Foldable Graph where- fold = Foldable.fold . graphMap- foldr f z = Foldable.foldr f z . graphMap- foldl f z = Foldable.foldl f z . graphMap- foldMap f = Foldable.foldMap f . graphMap- foldl' f z = Foldable.foldl' f z . graphMap- foldr' f z = Foldable.foldr' f z . graphMap-#ifdef MIN_VERSION_base-#if MIN_VERSION_base(4,8,0)- length = Foldable.length . graphMap- null = Foldable.null . graphMap- toList = Foldable.toList . graphMap- elem x = Foldable.elem x . graphMap- maximum = Foldable.maximum . graphMap- minimum = Foldable.minimum . graphMap- sum = Foldable.sum . graphMap- product = Foldable.product . graphMap-#endif-#endif--instance (NFData a, NFData (Key a)) => NFData (Graph a) where- rnf Graph {- graphMap = m,- graphForward = gf,- graphAdjoint = ga,- graphVertexToNode = vtn,- graphKeyToVertex = ktv,- graphBroken = b- } = gf `seq` ga `seq` vtn `seq` ktv `seq` b `seq` rnf m---- TODO: Data instance?---- | The 'IsNode' class is used for datatypes which represent directed--- graph nodes. A node of type @a@ is associated with some unique key of--- type @'Key' a@; given a node we can determine its key ('nodeKey')--- and the keys of its neighbors ('nodeNeighbors').-class Ord (Key a) => IsNode a where- type Key a- nodeKey :: a -> Key a- nodeNeighbors :: a -> [Key a]--instance (IsNode a, IsNode b, Key a ~ Key b) => IsNode (Either a b) where- type Key (Either a b) = Key a- nodeKey (Left x) = nodeKey x- nodeKey (Right x) = nodeKey x- nodeNeighbors (Left x) = nodeNeighbors x- nodeNeighbors (Right x) = nodeNeighbors x---- | A simple, trivial data type which admits an 'IsNode' instance.-data Node k a = N a k [k]- deriving (Show, Eq)---- | Get the value from a 'Node'.-nodeValue :: Node k a -> a-nodeValue (N a _ _) = a--instance Functor (Node k) where- fmap f (N a k ks) = N (f a) k ks--instance Ord k => IsNode (Node k a) where- type Key (Node k a) = k- nodeKey (N _ k _) = k- nodeNeighbors (N _ _ ks) = ks---- TODO: Maybe introduce a typeclass for items which just--- keys (so, Key associated type, and nodeKey method). But--- I didn't need it here, so I didn't introduce it.---- Query---- | /O(1)/. Is the graph empty?-null :: Graph a -> Bool-null = Map.null . toMap---- | /O(1)/. The number of nodes in the graph.-size :: Graph a -> Int-size = Map.size . toMap---- | /O(log V)/. Check if the key is in the graph.-member :: IsNode a => Key a -> Graph a -> Bool-member k g = Map.member k (toMap g)---- | /O(log V)/. Lookup the node at a key in the graph.-lookup :: IsNode a => Key a -> Graph a -> Maybe a-lookup k g = Map.lookup k (toMap g)---- Construction---- | /O(1)/. The empty graph.-empty :: IsNode a => Graph a-empty = fromMap Map.empty---- | /O(log V)/. Insert a node into a graph.-insert :: IsNode a => a -> Graph a -> Graph a-insert !n g = fromMap (Map.insert (nodeKey n) n (toMap g))---- | /O(log V)/. Delete the node at a key from the graph.-deleteKey :: IsNode a => Key a -> Graph a -> Graph a-deleteKey k g = fromMap (Map.delete k (toMap g))---- | /O(log V)/. Lookup and delete. This function returns the deleted--- value if it existed.-deleteLookup :: IsNode a => Key a -> Graph a -> (Maybe a, Graph a)-deleteLookup k g =- let (r, m') = Map.updateLookupWithKey (\_ _ -> Nothing) k (toMap g)- in (r, fromMap m')---- Combining---- | /O(V + V')/. Right-biased union, preferring entries--- from the second map when conflicts occur.--- @'nodeKey' x = 'nodeKey' (f x)@.-unionRight :: IsNode a => Graph a -> Graph a -> Graph a-unionRight g g' = fromMap (Map.union (toMap g') (toMap g))---- | /O(V + V')/. Left-biased union, preferring entries from--- the first map when conflicts occur.-unionLeft :: IsNode a => Graph a -> Graph a -> Graph a-unionLeft = flip unionRight---- Graph-like operations---- | /Ω(V + E)/. Compute the strongly connected components of a graph.--- Requires amortized construction of graph.-stronglyConnComp :: Graph a -> [SCC a]-stronglyConnComp g = map decode forest- where- forest = G.scc (graphForward g)- decode (Tree.Node v [])- | mentions_itself v = CyclicSCC [graphVertexToNode g v]- | otherwise = AcyclicSCC (graphVertexToNode g v)- decode other = CyclicSCC (dec other [])- where dec (Tree.Node v ts) vs- = graphVertexToNode g v : foldr dec vs ts- mentions_itself v = v `elem` (graphForward g ! v)--- Implementation copied from 'stronglyConnCompR' in 'Data.Graph'.---- | /Ω(V + E)/. Compute the cycles of a graph.--- Requires amortized construction of graph.-cycles :: Graph a -> [[a]]-cycles g = [ vs | CyclicSCC vs <- stronglyConnComp g ]---- | /O(1)/. Return a list of nodes paired with their broken--- neighbors (i.e., neighbor keys which are not in the graph).--- Requires amortized construction of graph.-broken :: Graph a -> [(a, [Key a])]-broken g = graphBroken g---- | Lookup the immediate neighbors from a key in the graph.--- Requires amortized construction of graph.-neighbors :: Graph a -> Key a -> Maybe [a]-neighbors g k = do- v <- graphKeyToVertex g k- return (map (graphVertexToNode g) (graphForward g ! v))---- | Lookup the immediate reverse neighbors from a key in the graph.--- Requires amortized construction of graph.-revNeighbors :: Graph a -> Key a -> Maybe [a]-revNeighbors g k = do- v <- graphKeyToVertex g k- return (map (graphVertexToNode g) (graphAdjoint g ! v))---- | Compute the subgraph which is the closure of some set of keys.--- Returns @Nothing@ if one (or more) keys are not present in--- the graph.--- Requires amortized construction of graph.-closure :: Graph a -> [Key a] -> Maybe [a]-closure g ks = do- vs <- traverse (graphKeyToVertex g) ks- return (decodeVertexForest g (G.dfs (graphForward g) vs))---- | Compute the reverse closure of a graph from some set--- of keys. Returns @Nothing@ if one (or more) keys are not present in--- the graph.--- Requires amortized construction of graph.-revClosure :: Graph a -> [Key a] -> Maybe [a]-revClosure g ks = do- vs <- traverse (graphKeyToVertex g) ks- return (decodeVertexForest g (G.dfs (graphAdjoint g) vs))--flattenForest :: Tree.Forest a -> [a]-flattenForest = concatMap Tree.flatten--decodeVertexForest :: Graph a -> Tree.Forest G.Vertex -> [a]-decodeVertexForest g = map (graphVertexToNode g) . flattenForest---- | Topologically sort the nodes of a graph.--- Requires amortized construction of graph.-topSort :: Graph a -> [a]-topSort g = map (graphVertexToNode g) $ G.topSort (graphForward g)---- | Reverse topologically sort the nodes of a graph.--- Requires amortized construction of graph.-revTopSort :: Graph a -> [a]-revTopSort g = map (graphVertexToNode g) $ G.topSort (graphAdjoint g)---- Conversions---- | /O(1)/. Convert a map from keys to nodes into a graph.--- The map must satisfy the invariant that--- @'fromMap' m == 'fromList' ('Data.Map.elems' m)@;--- if you can't fulfill this invariant use @'fromList' ('Data.Map.elems' m)@--- instead. The values of the map are assumed to already--- be in WHNF.-fromMap :: IsNode a => Map (Key a) a -> Graph a-fromMap m- = Graph { graphMap = m- -- These are lazily computed!- , graphForward = g- , graphAdjoint = G.transposeG g- , graphVertexToNode = vertex_to_node- , graphKeyToVertex = key_to_vertex- , graphBroken = broke- }- where- try_key_to_vertex k = maybe (Left k) Right (key_to_vertex k)-- (brokenEdges, edges)- = unzip- $ [ partitionEithers (map try_key_to_vertex (nodeNeighbors n))- | n <- ns ]- broke = filter (not . Prelude.null . snd) (zip ns brokenEdges)-- g = Array.listArray bounds edges-- ns = Map.elems m -- sorted ascending- vertices = zip (map nodeKey ns) [0..]- vertex_map = Map.fromAscList vertices- key_to_vertex k = Map.lookup k vertex_map-- vertex_to_node vertex = nodeTable ! vertex-- nodeTable = Array.listArray bounds ns- bounds = (0, Map.size m - 1)---- | /O(V log V)/. Convert a list of nodes (with distinct keys) into a graph.-fromDistinctList :: (IsNode a, Show (Key a)) => [a] -> Graph a-fromDistinctList = fromMap- . Map.fromListWith (\_ -> duplicateError)- . map (\n -> n `seq` (nodeKey n, n))- where- duplicateError n = error $ "Graph.fromDistinctList: duplicate key: "- ++ show (nodeKey n)---- Map-like operations---- | /O(V)/. Convert a graph into a list of nodes.-toList :: Graph a -> [a]-toList g = Map.elems (toMap g)---- | /O(V)/. Convert a graph into a list of keys.-keys :: Graph a -> [Key a]-keys g = Map.keys (toMap g)---- | /O(V)/. Convert a graph into a set of keys.-keysSet :: Graph a -> Set.Set (Key a)-keysSet g = Map.keysSet (toMap g)---- | /O(1)/. Convert a graph into a map from keys to nodes.--- The resulting map @m@ is guaranteed to have the property that--- @'Prelude.all' (\(k,n) -> k == 'nodeKey' n) ('Data.Map.toList' m)@.-toMap :: Graph a -> Map (Key a) a-toMap = graphMap---- Graph-like operations---- | /O(1)/. Convert a graph into a 'Data.Graph.Graph'.--- Requires amortized construction of graph.-toGraph :: Graph a -> (G.Graph, G.Vertex -> a, Key a -> Maybe G.Vertex)-toGraph g = (graphForward g, graphVertexToNode g, graphKeyToVertex g)
− Distribution/Compat/Internal/TempFile.hs
@@ -1,137 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_HADDOCK hide #-}-module Distribution.Compat.Internal.TempFile (- openTempFile,- openBinaryTempFile,- openNewBinaryFile,- createTempDirectory,- ) where--import Distribution.Compat.Exception--import System.FilePath ((</>))--import System.IO (Handle, openTempFile, openBinaryTempFile)-#if defined(__IO_MANAGER_WINIO__)-import System.IO (openBinaryTempFileWithDefaultPermissions)-#else-import Control.Exception (onException)-import Data.Bits ((.|.))-import Foreign.C (CInt, eEXIST, getErrno, errnoToIOError)-import GHC.IO.Handle.FD (fdToHandle)-import System.Posix.Internals (c_open, c_close, o_EXCL, o_BINARY, withFilePath,- o_CREAT, o_RDWR, o_NONBLOCK, o_NOCTTY)-#endif--import System.Posix.Internals (c_getpid)-import System.IO.Error (isAlreadyExistsError)--#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: This file should probably be removed.---- This is a copy/paste of the openBinaryTempFile definition, but--- it uses 666 rather than 600 for the permissions. Newer versions--- of base have a new function with this behavior which we use on--- Windows when the new IO manager is used.-openNewBinaryFile :: FilePath -> String -> IO (FilePath, Handle)-openNewBinaryFile dir template = do- -- This method can't be used under WINIO. Also the current implementation has- -- thread safety issues depending on which GHC is used. On newer GHC's let's- -- use the built in one.-#if defined(__IO_MANAGER_WINIO__)- openBinaryTempFileWithDefaultPermissions dir template-#else- 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: 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---- FIXME: Should use System.FilePath library-pathSeparator :: Char-#ifdef mingw32_HOST_OS-pathSeparator = '\\'-#else-pathSeparator = '/'-#endif--- /* __IO_MANAGER_WINIO__ */-#endif--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/Lens.hs
@@ -1,262 +0,0 @@-{-# LANGUAGE RankNTypes #-}--- | This module provides very basic lens functionality, without extra dependencies.------ For the documentation of the combinators see <http://hackage.haskell.org/package/lens lens> package.--- This module uses the same vocabulary.-module Distribution.Compat.Lens (- -- * Types- Lens,- Lens',- Traversal,- Traversal',- -- ** LensLike- LensLike,- LensLike',- -- ** rank-1 types- Getting,- AGetter,- ASetter,- ALens,- ALens',- -- * Getter- view,- use,- getting,- -- * Setter- set,- over,- -- * Fold- toDListOf,- toListOf,- toSetOf,- -- * Lens- cloneLens,- aview,- -- * Common lenses- _1, _2,- -- * Operators- (&),- (^.),- (.~), (?~), (%~),- (.=), (?=), (%=),- (^#),- (#~), (#%~),- -- * Internal Comonads- Pretext (..),- -- * Cabal developer info- -- $development- ) where--import Prelude()-import Distribution.Compat.Prelude--import Control.Monad.State.Class (MonadState (..), gets, modify)--import qualified Distribution.Compat.DList as DList-import qualified Data.Set as Set------------------------------------------------------------------------------------ Types----------------------------------------------------------------------------------type LensLike f s t a b = (a -> f b) -> s -> f t-type LensLike' f s a = (a -> f a) -> s -> f s--type Lens s t a b = forall f. Functor f => LensLike f s t a b-type Traversal s t a b = forall f. Applicative f => LensLike f s t a b--type Lens' s a = Lens s s a a-type Traversal' s a = Traversal s s a a--type Getting r s a = LensLike (Const r) s s a a--type AGetter s a = LensLike (Const a) s s a a -- this doesn't exist in 'lens'-type ASetter s t a b = LensLike Identity s t a b-type ALens s t a b = LensLike (Pretext a b) s t a b--type ALens' s a = ALens s s a a------------------------------------------------------------------------------------ Getter----------------------------------------------------------------------------------view :: Getting a s a -> s -> a-view l s = getConst (l Const s)-{-# INLINE view #-}--use :: MonadState s m => Getting a s a -> m a-use l = gets (view l)-{-# INLINE use #-}---- | @since 2.4------ >>> (3 :: Int) ^. getting (+2) . getting show--- "5"-getting :: (s -> a) -> Getting r s a-getting k f = Const . getConst . f . k-{-# INLINE getting #-}------------------------------------------------------------------------------------ Setter----------------------------------------------------------------------------------set :: ASetter s t a b -> b -> s -> t-set l x = over l (const x)--over :: ASetter s t a b -> (a -> b) -> s -> t-over l f s = runIdentity (l (\x -> Identity (f x)) s)------------------------------------------------------------------------------------ Fold----------------------------------------------------------------------------------toDListOf :: Getting (DList.DList a) s a -> s -> DList.DList a-toDListOf l s = getConst (l (\x -> Const (DList.singleton x)) s)--toListOf :: Getting (DList.DList a) s a -> s -> [a]-toListOf l = DList.runDList . toDListOf l--toSetOf :: Getting (Set.Set a) s a -> s -> Set.Set a-toSetOf l s = getConst (l (\x -> Const (Set.singleton x)) s)------------------------------------------------------------------------------------ Lens----------------------------------------------------------------------------------aview :: ALens s t a b -> s -> a-aview l = pretextPos . l pretextSell-{-# INLINE aview #-}--{--lens :: (s -> a) -> (s -> a -> s) -> Lens' s a-lens sa sbt afb s = sbt s <$> afb (sa s)--}------------------------------------------------------------------------------------ Common----------------------------------------------------------------------------------_1 :: Lens (a, c) (b, c) a b-_1 f (a, c) = flip (,) c <$> f a--_2 :: Lens (c, a) (c, b) a b-_2 f (c, a) = (,) c <$> f a------------------------------------------------------------------------------------ Operators------------------------------------------------------------------------------------ | '&' is a reverse application operator-(&) :: a -> (a -> b) -> b-(&) = flip ($)-{-# INLINE (&) #-}-infixl 1 &--infixl 8 ^., ^#-infixr 4 .~, %~, ?~-infixr 4 #~, #%~-infixr 4 .=, %=, ?=--(^.) :: s -> Getting a s a -> a-s ^. l = getConst (l Const s)-{-# INLINE (^.) #-}--(.~) :: ASetter s t a b -> b -> s -> t-(.~) = set-{-# INLINE (.~) #-}--(?~) :: ASetter s t a (Maybe b) -> b -> s -> t-l ?~ b = set l (Just b)-{-# INLINE (?~) #-}--(%~) :: ASetter s t a b -> (a -> b) -> s -> t-(%~) = over-{-# INLINE (%~) #-}--(.=) :: MonadState s m => ASetter s s a b -> b -> m ()-l .= b = modify (l .~ b)-{-# INLINE (.=) #-}--(?=) :: MonadState s m => ASetter s s a (Maybe b) -> b -> m ()-l ?= b = modify (l ?~ b)-{-# INLINE (?=) #-}--(%=) :: MonadState s m => ASetter s s a b -> (a -> b) -> m ()-l %= f = modify (l %~ f)-{-# INLINE (%=) #-}--(^#) :: s -> ALens s t a b -> a-s ^# l = aview l s--(#~) :: ALens s t a b -> b -> s -> t-(#~) l b s = pretextPeek b (l pretextSell s)-{-# INLINE (#~) #-}--(#%~) :: ALens s t a b -> (a -> b) -> s -> t-(#%~) l f s = pretextPeeks f (l pretextSell s)-{-# INLINE (#%~) #-}--pretextSell :: a -> Pretext a b b-pretextSell a = Pretext (\afb -> afb a)-{-# INLINE pretextSell #-}--pretextPeeks :: (a -> b) -> Pretext a b t -> t-pretextPeeks f (Pretext m) = runIdentity $ m (\x -> Identity (f x))-{-# INLINE pretextPeeks #-}--pretextPeek :: b -> Pretext a b t -> t-pretextPeek b (Pretext m) = runIdentity $ m (\_ -> Identity b)-{-# INLINE pretextPeek #-}--pretextPos :: Pretext a b t -> a-pretextPos (Pretext m) = getConst (m Const)-{-# INLINE pretextPos #-}--cloneLens :: Functor f => ALens s t a b -> LensLike f s t a b-cloneLens l f s = runPretext (l pretextSell s) f-{-# INLINE cloneLens #-}------------------------------------------------------------------------------------ Comonads------------------------------------------------------------------------------------ | @lens@ variant is also parametrised by profunctor.-data Pretext a b t = Pretext { runPretext :: forall f. Functor f => (a -> f b) -> f t }--instance Functor (Pretext a b) where- fmap f (Pretext pretext) = Pretext (\afb -> fmap f (pretext afb))------------------------------------------------------------------------------------ Documentation------------------------------------------------------------------------------------ $development------ We cannot depend on @template-haskell@, because Cabal is a boot library.--- This fact makes defining optics a manual task. Here is a small recipe to--- make the process less tedious.------ First start a repl------ > cabal new-repl Cabal:hackage-tests------ Because @--extra-package@ isn't yet implemented, we use a test-suite--- with @generics-sop@ dependency.------ In the repl, we load a helper script:------ > :l ../generics-sop-lens.hs------ Now we are set up to derive lenses!------ > :m +Distribution.Types.SourceRepo--- > putStr $ genericLenses (Proxy :: Proxy SourceRepo)------ @--- repoKind :: Lens' SourceRepo RepoKind--- repoKind f s = fmap (\\x -> s { T.repoKind = x }) (f (T.repoKind s))--- \{-# INLINE repoKind #-\}--- ...--- @------ /Note:/ You may need to adjust type-aliases, e.g. `String` to `FilePath`.
− Distribution/Compat/MonadFail.hs
@@ -1,5 +0,0 @@-{-# LANGUAGE CPP #-}---- | Compatibility layer for "Control.Monad.Fail"-module Distribution.Compat.MonadFail ( Control.Monad.Fail.MonadFail(fail) ) where-import Control.Monad.Fail
− Distribution/Compat/Newtype.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}--- | Per Conor McBride, the 'Newtype' typeclass represents the packing and--- unpacking of a newtype, and allows you to operatate under that newtype with--- functions such as 'ala'.-module Distribution.Compat.Newtype (- Newtype (..),- ala,- alaf,- pack',- unpack',- ) where--import Data.Functor.Identity (Identity (..))-import Data.Monoid (Sum (..), Product (..), Endo (..))--#if MIN_VERSION_base(4,7,0)-import Data.Coerce (coerce, Coercible)-#else-import Unsafe.Coerce (unsafeCoerce)-#endif---- | The @FunctionalDependencies@ version of 'Newtype' type-class.------ Since Cabal-3.0 class arguments are in a different order than in @newtype@ package.--- This change is to allow usage with @DeriveAnyClass@ (and @DerivingStrategies@, in GHC-8.2).--- Unfortunately one have to repeat inner type.------ @--- newtype New = New Old--- deriving anyclass (Newtype Old)--- @------ Another approach would be to use @TypeFamilies@ (and possibly--- compute inner type using "GHC.Generics"), but we think @FunctionalDependencies@--- version gives cleaner type signatures.----class Newtype o n | n -> o where- pack :: o -> n-#if MIN_VERSION_base(4,7,0)- default pack :: Coercible o n => o -> n- pack = coerce-#else- default pack :: o -> n- pack = unsafeCoerce-#endif-- unpack :: n -> o-#if MIN_VERSION_base(4,7,0)- default unpack :: Coercible n o => n -> o- unpack = coerce-#else- default unpack :: n -> o- unpack = unsafeCoerce-#endif--instance Newtype a (Identity a)-instance Newtype a (Sum a)-instance Newtype a (Product a)-instance Newtype (a -> a) (Endo a)---- |------ >>> ala Sum foldMap [1, 2, 3, 4 :: Int]--- 10------ /Note:/ the user supplied function for the newtype is /ignored/.------ >>> ala (Sum . (+1)) foldMap [1, 2, 3, 4 :: Int]--- 10-ala :: (Newtype o n, Newtype o' n') => (o -> n) -> ((o -> n) -> b -> n') -> (b -> o')-ala pa hof = alaf pa hof id---- |------ >>> alaf Sum foldMap length ["cabal", "install"]--- 12------ /Note:/ as with 'ala', the user supplied function for the newtype is /ignored/.-alaf :: (Newtype o n, Newtype o' n') => (o -> n) -> ((a -> n) -> b -> n') -> (a -> o) -> (b -> o')-alaf _ hof f = unpack . hof (pack . f)---- | Variant of 'pack', which takes a phantom type.-pack' :: Newtype o n => (o -> n) -> o -> n-pack' _ = pack---- | Variant of 'pack', which takes a phantom type.-unpack' :: Newtype o n => (o -> n) -> n -> o-unpack' _ = unpack
− Distribution/Compat/NonEmptySet.hs
@@ -1,155 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-module Distribution.Compat.NonEmptySet (- NonEmptySet,- -- * Construction- singleton,- -- * Insertion- insert,- -- * Deletion- delete,- -- * Conversions- toNonEmpty,- fromNonEmpty,- toList,- toSet,- -- * Query- member,- -- * Map- map,-) where--import Prelude (Bool (..), Eq, Maybe (..), Ord (..), Read, Show (..), String, error, otherwise, return, showParen, showString, ($), (++), (.))--import Control.DeepSeq (NFData (..))-import Data.Data (Data)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Semigroup (Semigroup (..))-import Data.Typeable (Typeable)--import qualified Data.Foldable as F-import qualified Data.Set as Set--import Distribution.Compat.Binary (Binary (..))-import Distribution.Utils.Structured--#if MIN_VERSION_binary(0,6,0)-import Control.Applicative (empty)-#else-import Control.Monad (fail)-#endif---- | @since 3.4.0.0-newtype NonEmptySet a = NES (Set.Set a)- deriving (Eq, Ord, Typeable, Data, Read)------------------------------------------------------------------------------------ Instances----------------------------------------------------------------------------------instance Show a => Show (NonEmptySet a) where- showsPrec d s = showParen (d > 10)- $ showString "fromNonEmpty "- . showsPrec 11 (toNonEmpty s)--instance Binary a => Binary (NonEmptySet a) where- put (NES s) = put s- get = do- xs <- get- if Set.null xs-#if MIN_VERSION_binary(0,6,0)- then empty-#else- then fail "NonEmptySet: empty"-#endif- else return (NES xs)--instance Structured a => Structured (NonEmptySet a) where- structure = containerStructure--instance NFData a => NFData (NonEmptySet a) where- rnf (NES x) = rnf x---- | Note: there aren't @Monoid@ instance.-instance Ord a => Semigroup (NonEmptySet a) where- NES x <> NES y = NES (Set.union x y)--instance F.Foldable NonEmptySet where- foldMap f (NES s) = F.foldMap f s- foldr f z (NES s) = F.foldr f z s--#if MIN_VERSION_base(4,8,0)- toList = toList- null _ = False- length (NES s) = F.length s-#endif------------------------------------------------------------------------------------ Constructors----------------------------------------------------------------------------------singleton :: a -> NonEmptySet a-singleton = NES . Set.singleton------------------------------------------------------------------------------------ Insertion----------------------------------------------------------------------------------insert :: Ord a => a -> NonEmptySet a -> NonEmptySet a-insert x (NES xs) = NES (Set.insert x xs)------------------------------------------------------------------------------------ Deletion----------------------------------------------------------------------------------delete :: Ord a => a -> NonEmptySet a -> Maybe (NonEmptySet a)-delete x (NES xs)- | Set.null res = Nothing- | otherwise = Just (NES xs)- where- res = Set.delete x xs------------------------------------------------------------------------------------ Conversions----------------------------------------------------------------------------------fromNonEmpty :: Ord a => NonEmpty a -> NonEmptySet a-fromNonEmpty (x :| xs) = NES (Set.fromList (x : xs))--toNonEmpty :: NonEmptySet a -> NonEmpty a-toNonEmpty (NES s) = case Set.toList s of- [] -> panic "toNonEmpty"- x:xs -> x :| xs--toList :: NonEmptySet a -> [a]-toList (NES s) = Set.toList s--toSet :: NonEmptySet a -> Set.Set a-toSet (NES s) = s------------------------------------------------------------------------------------ Query----------------------------------------------------------------------------------member :: Ord a => a -> NonEmptySet a -> Bool-member x (NES xs) = Set.member x xs------------------------------------------------------------------------------------ Map----------------------------------------------------------------------------------map- :: ( Ord b-#if !MIN_VERSION_containers(0,5,2)- , Ord a-#endif- )- => (a -> b) -> NonEmptySet a -> NonEmptySet b-map f (NES x) = NES (Set.map f x)------------------------------------------------------------------------------------ Internal----------------------------------------------------------------------------------panic :: String -> a-panic msg = error $ "NonEmptySet invariant violated: " ++ msg
− Distribution/Compat/Parsing.hs
@@ -1,362 +0,0 @@-{-# LANGUAGE GADTs, UndecidableInstances #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Compat.Parsing--- Copyright : (c) Edward Kmett 2011-2012--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable------ Alternative parser combinators.------ Originally in @parsers@ package.----------------------------------------------------------------------------------module Distribution.Compat.Parsing- (- -- * Parsing Combinators- choice- , option- , optional -- from Control.Applicative, parsec optionMaybe- , skipOptional -- parsec optional- , between- , some -- from Control.Applicative, parsec many1- , many -- from Control.Applicative- , sepBy- , sepByNonEmpty- , sepEndByNonEmpty- , sepEndBy- , endByNonEmpty- , endBy- , count- , chainl- , chainr- , chainl1- , chainr1- , manyTill- -- * Parsing Class- , Parsing(..)- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Control.Applicative ((<**>), optional)-import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.State.Lazy as Lazy-import Control.Monad.Trans.State.Strict as Strict-import Control.Monad.Trans.Writer.Lazy as Lazy-import Control.Monad.Trans.Writer.Strict as Strict-import Control.Monad.Trans.RWS.Lazy as Lazy-import Control.Monad.Trans.RWS.Strict as Strict-import Control.Monad.Trans.Reader (ReaderT (..))-import Control.Monad.Trans.Identity (IdentityT (..))-import Data.Foldable (asum)--import qualified Data.List.NonEmpty as NE-import qualified Text.Parsec as Parsec---- | @choice ps@ tries to apply the parsers in the list @ps@ in order,--- until one of them succeeds. Returns the value of the succeeding--- parser.-choice :: Alternative m => [m a] -> m a-choice = asum-{-# INLINE choice #-}---- | @option x p@ tries to apply parser @p@. If @p@ fails without--- consuming input, it returns the value @x@, otherwise the value--- returned by @p@.------ > priority = option 0 (digitToInt <$> digit)-option :: Alternative m => a -> m a -> m a-option x p = p <|> pure x-{-# INLINE option #-}---- | @skipOptional p@ tries to apply parser @p@. It will parse @p@ or nothing.--- It only fails if @p@ fails after consuming input. It discards the result--- of @p@. (Plays the role of parsec's optional, which conflicts with Applicative's optional)-skipOptional :: Alternative m => m a -> m ()-skipOptional p = (() <$ p) <|> pure ()-{-# INLINE skipOptional #-}---- | @between open close p@ parses @open@, followed by @p@ and @close@.--- Returns the value returned by @p@.------ > braces = between (symbol "{") (symbol "}")-between :: Applicative m => m bra -> m ket -> m a -> m a-between bra ket p = bra *> p <* ket-{-# INLINE between #-}---- | @sepBy p sep@ parses /zero/ or more occurrences of @p@, separated--- by @sep@. Returns a list of values returned by @p@.------ > commaSep p = p `sepBy` (symbol ",")-sepBy :: Alternative m => m a -> m sep -> m [a]-sepBy p sep = toList <$> sepByNonEmpty p sep <|> pure []-{-# INLINE sepBy #-}---- | @sepByNonEmpty p sep@ parses /one/ or more occurrences of @p@, separated--- by @sep@. Returns a non-empty list of values returned by @p@.-sepByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)-sepByNonEmpty p sep = (:|) <$> p <*> many (sep *> p)-{-# INLINE sepByNonEmpty #-}---- | @sepEndByNonEmpty p sep@ parses /one/ or more occurrences of @p@,--- separated and optionally ended by @sep@. Returns a non-empty list of values--- returned by @p@.-sepEndByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)-sepEndByNonEmpty p sep = (:|) <$> p <*> ((sep *> sepEndBy p sep) <|> pure [])---- | @sepEndBy p sep@ parses /zero/ or more occurrences of @p@,--- separated and optionally ended by @sep@, ie. haskell style--- statements. Returns a list of values returned by @p@.------ > haskellStatements = haskellStatement `sepEndBy` semi-sepEndBy :: Alternative m => m a -> m sep -> m [a]-sepEndBy p sep = toList <$> sepEndByNonEmpty p sep <|> pure []-{-# INLINE sepEndBy #-}---- | @endByNonEmpty p sep@ parses /one/ or more occurrences of @p@, separated--- and ended by @sep@. Returns a non-empty list of values returned by @p@.-endByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)-endByNonEmpty p sep = NE.some1 (p <* sep)-{-# INLINE endByNonEmpty #-}---- | @endBy p sep@ parses /zero/ or more occurrences of @p@, separated--- and ended by @sep@. Returns a list of values returned by @p@.------ > cStatements = cStatement `endBy` semi-endBy :: Alternative m => m a -> m sep -> m [a]-endBy p sep = many (p <* sep)-{-# INLINE endBy #-}---- | @count n p@ parses @n@ occurrences of @p@. If @n@ is smaller or--- equal to zero, the parser equals to @return []@. Returns a list of--- @n@ values returned by @p@.-count :: Applicative m => Int -> m a -> m [a]-count n p | n <= 0 = pure []- | otherwise = sequenceA (replicate n p)-{-# INLINE count #-}---- | @chainr p op x@ parses /zero/ or more occurrences of @p@,--- separated by @op@ Returns a value obtained by a /right/ associative--- application of all functions returned by @op@ to the values returned--- by @p@. If there are no occurrences of @p@, the value @x@ is--- returned.-chainr :: Alternative m => m a -> m (a -> a -> a) -> a -> m a-chainr p op x = chainr1 p op <|> pure x-{-# INLINE chainr #-}---- | @chainl p op x@ parses /zero/ or more occurrences of @p@,--- separated by @op@. Returns a value obtained by a /left/ associative--- application of all functions returned by @op@ to the values returned--- by @p@. If there are zero occurrences of @p@, the value @x@ is--- returned.-chainl :: Alternative m => m a -> m (a -> a -> a) -> a -> m a-chainl p op x = chainl1 p op <|> pure x-{-# INLINE chainl #-}---- | @chainl1 p op x@ parses /one/ or more occurrences of @p@,--- separated by @op@ Returns a value obtained by a /left/ associative--- application of all functions returned by @op@ to the values returned--- by @p@. . This parser can for example be used to eliminate left--- recursion which typically occurs in expression grammars.------ > expr = term `chainl1` addop--- > term = factor `chainl1` mulop--- > factor = parens expr <|> integer--- >--- > mulop = (*) <$ symbol "*"--- > <|> div <$ symbol "/"--- >--- > addop = (+) <$ symbol "+"--- > <|> (-) <$ symbol "-"-chainl1 :: Alternative m => m a -> m (a -> a -> a) -> m a-chainl1 p op = scan where- scan = p <**> rst- rst = (\f y g x -> g (f x y)) <$> op <*> p <*> rst <|> pure id-{-# INLINE chainl1 #-}---- | @chainr1 p op x@ parses /one/ or more occurrences of @p@,--- separated by @op@ Returns a value obtained by a /right/ associative--- application of all functions returned by @op@ to the values returned--- by @p@.-chainr1 :: Alternative m => m a -> m (a -> a -> a) -> m a-chainr1 p op = scan where- scan = p <**> rst- rst = (flip <$> op <*> scan) <|> pure id-{-# INLINE chainr1 #-}---- | @manyTill p end@ applies parser @p@ /zero/ or more times until--- parser @end@ succeeds. Returns the list of values returned by @p@.--- This parser can be used to scan comments:------ > simpleComment = do{ string "<!--"--- > ; manyTill anyChar (try (string "-->"))--- > }------ Note the overlapping parsers @anyChar@ and @string \"-->\"@, and--- therefore the use of the 'try' combinator.-manyTill :: Alternative m => m a -> m end -> m [a]-manyTill p end = go where go = ([] <$ end) <|> ((:) <$> p <*> go)-{-# INLINE manyTill #-}--infixr 0 <?>---- | Additional functionality needed to describe parsers independent of input type.-class Alternative m => Parsing m where- -- | Take a parser that may consume input, and on failure, go back to- -- where we started and fail as if we didn't consume input.- try :: m a -> m a-- -- | Give a parser a name- (<?>) :: m a -> String -> m a-- -- | A version of many that discards its input. Specialized because it- -- can often be implemented more cheaply.- skipMany :: m a -> m ()- skipMany p = () <$ many p- {-# INLINE skipMany #-}-- -- | @skipSome p@ applies the parser @p@ /one/ or more times, skipping- -- its result. (aka skipMany1 in parsec)- skipSome :: m a -> m ()- skipSome p = p *> skipMany p- {-# INLINE skipSome #-}-- -- | Used to emit an error on an unexpected token- unexpected :: String -> m a-- -- | This parser only succeeds at the end of the input. This is not a- -- primitive parser but it is defined using 'notFollowedBy'.- --- -- > eof = notFollowedBy anyChar <?> "end of input"- eof :: m ()-- -- | @notFollowedBy p@ only succeeds when parser @p@ fails. This parser- -- does not consume any input. This parser can be used to implement the- -- \'longest match\' rule. For example, when recognizing keywords (for- -- example @let@), we want to make sure that a keyword is not followed- -- by a legal identifier character, in which case the keyword is- -- actually an identifier (for example @lets@). We can program this- -- behaviour as follows:- --- -- > keywordLet = try $ string "let" <* notFollowedBy alphaNum- notFollowedBy :: Show a => m a -> m ()--instance (Parsing m, MonadPlus m) => Parsing (Lazy.StateT s m) where- try (Lazy.StateT m) = Lazy.StateT $ try . m- {-# INLINE try #-}- Lazy.StateT m <?> l = Lazy.StateT $ \s -> m s <?> l- {-# INLINE (<?>) #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (Lazy.StateT m) = Lazy.StateT- $ \s -> notFollowedBy (fst <$> m s) >> return ((),s)- {-# INLINE notFollowedBy #-}--instance (Parsing m, MonadPlus m) => Parsing (Strict.StateT s m) where- try (Strict.StateT m) = Strict.StateT $ try . m- {-# INLINE try #-}- Strict.StateT m <?> l = Strict.StateT $ \s -> m s <?> l- {-# INLINE (<?>) #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (Strict.StateT m) = Strict.StateT- $ \s -> notFollowedBy (fst <$> m s) >> return ((),s)- {-# INLINE notFollowedBy #-}--instance (Parsing m, MonadPlus m) => Parsing (ReaderT e m) where- try (ReaderT m) = ReaderT $ try . m- {-# INLINE try #-}- ReaderT m <?> l = ReaderT $ \e -> m e <?> l- {-# INLINE (<?>) #-}- skipMany (ReaderT m) = ReaderT $ skipMany . m- {-# INLINE skipMany #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (ReaderT m) = ReaderT $ notFollowedBy . m- {-# INLINE notFollowedBy #-}--instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Strict.WriterT w m) where- try (Strict.WriterT m) = Strict.WriterT $ try m- {-# INLINE try #-}- Strict.WriterT m <?> l = Strict.WriterT (m <?> l)- {-# INLINE (<?>) #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (Strict.WriterT m) = Strict.WriterT- $ notFollowedBy (fst <$> m) >>= \x -> return (x, mempty)- {-# INLINE notFollowedBy #-}--instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Lazy.WriterT w m) where- try (Lazy.WriterT m) = Lazy.WriterT $ try m- {-# INLINE try #-}- Lazy.WriterT m <?> l = Lazy.WriterT (m <?> l)- {-# INLINE (<?>) #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (Lazy.WriterT m) = Lazy.WriterT- $ notFollowedBy (fst <$> m) >>= \x -> return (x, mempty)- {-# INLINE notFollowedBy #-}--instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Lazy.RWST r w s m) where- try (Lazy.RWST m) = Lazy.RWST $ \r s -> try (m r s)- {-# INLINE try #-}- Lazy.RWST m <?> l = Lazy.RWST $ \r s -> m r s <?> l- {-# INLINE (<?>) #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (Lazy.RWST m) = Lazy.RWST- $ \r s -> notFollowedBy ((\(a,_,_) -> a) <$> m r s) >>= \x -> return (x, s, mempty)- {-# INLINE notFollowedBy #-}--instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Strict.RWST r w s m) where- try (Strict.RWST m) = Strict.RWST $ \r s -> try (m r s)- {-# INLINE try #-}- Strict.RWST m <?> l = Strict.RWST $ \r s -> m r s <?> l- {-# INLINE (<?>) #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (Strict.RWST m) = Strict.RWST- $ \r s -> notFollowedBy ((\(a,_,_) -> a) <$> m r s) >>= \x -> return (x, s, mempty)- {-# INLINE notFollowedBy #-}--instance (Parsing m, Monad m) => Parsing (IdentityT m) where- try = IdentityT . try . runIdentityT- {-# INLINE try #-}- IdentityT m <?> l = IdentityT (m <?> l)- {-# INLINE (<?>) #-}- skipMany = IdentityT . skipMany . runIdentityT- {-# INLINE skipMany #-}- unexpected = lift . unexpected- {-# INLINE unexpected #-}- eof = lift eof- {-# INLINE eof #-}- notFollowedBy (IdentityT m) = IdentityT $ notFollowedBy m- {-# INLINE notFollowedBy #-}--instance (Parsec.Stream s m t, Show t) => Parsing (Parsec.ParsecT s u m) where- try = Parsec.try- (<?>) = (Parsec.<?>)- skipMany = Parsec.skipMany- skipSome = Parsec.skipMany1- unexpected = Parsec.unexpected- eof = Parsec.eof- notFollowedBy = Parsec.notFollowedBy
− Distribution/Compat/Prelude.hs
@@ -1,316 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE TypeOperators #-}--#ifdef MIN_VERSION_base-#define MINVER_base_411 MIN_VERSION_base(4,11,0)-#define MINVER_base_48 MIN_VERSION_base(4,8,0)-#define MINVER_base_47 MIN_VERSION_base(4,7,0)-#else-#define MINVER_base_411 (__GLASGOW_HASKELL__ >= 804)-#define MINVER_base_48 (__GLASGOW_HASKELL__ >= 710)-#define MINVER_base_47 (__GLASGOW_HASKELL__ >= 708)-#endif---- | This module does two things:------ * Acts as a compatibility layer, like @base-compat@.------ * Provides commonly used imports.-module Distribution.Compat.Prelude (- -- * Prelude- --- -- Prelude is re-exported, following is hidden:- module BasePrelude,--#if !MINVER_base_48- -- * base 4.8 shim- Applicative(..), (<$), (<$>),- Monoid(..),-#endif-- -- * Common type-classes- Semigroup (..),- gmappend, gmempty,- Typeable, TypeRep, typeRep,- Data,- Generic,- NFData (..), genericRnf,- Binary (..),- Structured,- Alternative (..),- MonadPlus (..),- IsString (..),-- -- * Some types- Map,- Set,- NonEmptySet,- Identity (..),- Proxy (..),- Const (..),- Void,-- -- * Data.Either- partitionEithers,-- -- * Data.Maybe- catMaybes, mapMaybe,- fromMaybe,- maybeToList, listToMaybe,- isNothing, isJust,-- -- * Data.List- unfoldr,- isPrefixOf, isSuffixOf,- intercalate, intersperse,- sort, sortBy,- nub, nubBy,- partition,-- -- * Data.List.NonEmpty- NonEmpty((:|)), foldl1, foldr1,- head, tail, last, init,-- -- * Data.Foldable- Foldable, foldMap, foldr,- null, length,- find, foldl',- traverse_, for_,- any, all,- toList,-- -- * Data.Traversable- Traversable, traverse, sequenceA,- for,-- -- * Data.Function- on,-- -- * Data.Ord- comparing,-- -- * Control.Arrow- first,-- -- * Control.Monad- liftM, liftM2,- unless, when,- ap, void,- foldM, filterM,- join, guard,-- -- * Control.Exception- catch, throwIO, evaluate,- Exception (..), IOException, SomeException (..),-#if !MINVER_base_48- displayException,-#endif- tryIO, catchIO, catchExit,-- -- * Control.DeepSeq- deepseq, force,-- -- * Data.Char- isSpace, isDigit, isUpper, isAlpha, isAlphaNum,- chr, ord,- toLower, toUpper,-- -- * Data.Void- absurd, vacuous,-- -- * Data.Word & Data.Int- Word,- Word8, Word16, Word32, Word64,- Int8, Int16, Int32, Int64,-- -- * Text.PrettyPrint- (<<>>), (Disp.<+>),-- -- * System.Exit- ExitCode (..),- exitWith, exitSuccess, exitFailure,-- -- * Text.Read- readMaybe,-- -- * Debug.Trace (as deprecated functions)- trace, traceShow, traceShowId,- ) where---- We also could hide few partial function-import Prelude as BasePrelude hiding- ( mapM, mapM_, sequence, null, length, foldr, any, all, head, tail, last, init- -- partial functions- , read- , foldr1, foldl1-#if MINVER_base_411- -- As of base 4.11.0.0 Prelude exports part of Semigroup(..).- -- Hide this so we instead rely on Distribution.Compat.Semigroup.- , Semigroup(..)-#endif-#if MINVER_base_48- , Word- -- We hide them, as we import only some members- , Traversable, traverse, sequenceA- , Foldable, foldMap-#endif- )---- AMP-#if !MINVER_base_48-import Control.Applicative (Applicative (..), (<$), (<$>))-import Data.Foldable (toList)-import Distribution.Compat.Semigroup (Monoid (..))-#else-import Data.Foldable (Foldable (toList), length, null)-#endif--import Data.Foldable (Foldable (foldMap, foldr), all, any, find, foldl', for_, traverse_)-import Data.Traversable (Traversable (sequenceA, traverse), for)--import qualified Data.Foldable---- Extra exports-import Control.Applicative (Alternative (..))-import Control.Applicative (Const (..))-import Control.Arrow (first)-import Control.DeepSeq (NFData (..), deepseq, force)-import Control.Exception (Exception (..), IOException, SomeException (..), catch, evaluate, throwIO)-import Control.Monad (MonadPlus (..), ap, filterM, foldM, guard, join, liftM, liftM2, unless, void, when)-import Data.Char (chr, isAlpha, isAlphaNum, isDigit, isSpace, isUpper, ord, toLower, toUpper)-import Data.Data (Data)-import Data.Either (partitionEithers)-import Data.Function (on)-import Data.Functor.Identity (Identity (..))-import Data.Int (Int16, Int32, Int64, Int8)-import Data.List (intercalate, intersperse, isPrefixOf, isSuffixOf, nub, nubBy, partition, sort, sortBy, unfoldr)-import Data.List.NonEmpty (NonEmpty ((:|)), head, init, last, tail)-import Data.Map (Map)-import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, listToMaybe, mapMaybe, maybeToList)-import Data.Ord (comparing)-import Data.Proxy (Proxy (..))-import Data.Set (Set)-import Data.String (IsString (..))-import Data.Void (Void, absurd, vacuous)-import Data.Word (Word, Word16, Word32, Word64, Word8)-import Distribution.Compat.Binary (Binary (..))-import Distribution.Compat.Semigroup (Semigroup (..), gmappend, gmempty)-import Distribution.Compat.Typeable (TypeRep, Typeable, typeRep)-import GHC.Generics ((:*:) ((:*:)), (:+:) (L1, R1), Generic, K1 (unK1), M1 (unM1), Rep (..), U1 (U1), V1)-import System.Exit (ExitCode (..), exitFailure, exitSuccess, exitWith)-import Text.Read (readMaybe)--import qualified Text.PrettyPrint as Disp--import Distribution.Compat.Exception-import Distribution.Compat.NonEmptySet (NonEmptySet)-import Distribution.Utils.Structured (Structured)--import qualified Debug.Trace---- | New name for 'Text.PrettyPrint.<>'-(<<>>) :: Disp.Doc -> Disp.Doc -> Disp.Doc-(<<>>) = (Disp.<>)--#if !MINVER_base_48--- | Test whether the structure is empty. The default implementation is--- optimized for structures that are similar to cons-lists, because there--- is no general way to do better.-null :: Foldable t => t a -> Bool-null = foldr (\_ _ -> False) True---- | Returns the size/length of a finite structure as an 'Int'. The--- default implementation is optimized for structures that are similar to--- cons-lists, because there is no general way to do better.-length :: Foldable t => t a -> Int-length = foldl' (\c _ -> c+1) 0-#endif----- | "GHC.Generics"-based 'rnf' implementation------ This is needed in order to support @deepseq < 1.4@ which didn't--- have a 'Generic'-based default 'rnf' implementation yet.------ In order to define instances, use e.g.------ > instance NFData MyType where rnf = genericRnf------ The implementation has been taken from @deepseq-1.4.2@'s default--- 'rnf' implementation.-genericRnf :: (Generic a, GNFData (Rep a)) => a -> ()-genericRnf = grnf . from---- | Hidden internal type-class-class GNFData f where- grnf :: f a -> ()--instance GNFData V1 where- grnf = error "Control.DeepSeq.rnf: uninhabited type"--instance GNFData U1 where- grnf U1 = ()--instance NFData a => GNFData (K1 i a) where- grnf = rnf . unK1- {-# INLINEABLE grnf #-}--instance GNFData a => GNFData (M1 i c a) where- grnf = grnf . unM1- {-# INLINEABLE grnf #-}--instance (GNFData a, GNFData b) => GNFData (a :*: b) where- grnf (x :*: y) = grnf x `seq` grnf y- {-# INLINEABLE grnf #-}--instance (GNFData a, GNFData b) => GNFData (a :+: b) where- grnf (L1 x) = grnf x- grnf (R1 x) = grnf x- {-# INLINEABLE grnf #-}----- TODO: if we want foldr1/foldl1 to work on more than NonEmpty, we--- can define a local typeclass 'Foldable1', e.g.------ @--- class Foldable f => Foldable1 f------ instance Foldable1 NonEmpty------ foldr1 :: Foldable1 t => (a -> a -> a) -> t a -> a--- foldr1 = Data.Foldable.foldr1------ foldl1 :: Foldable1 t => (a -> a -> a) -> t a -> a--- foldl1 = Data.Foldable.foldl1--- @-----{-# INLINE foldr1 #-}-foldr1 :: (a -> a -> a) -> NonEmpty a -> a-foldr1 = Data.Foldable.foldr1--{-# INLINE foldl1 #-}-foldl1 :: (a -> a -> a) -> NonEmpty a -> a-foldl1 = Data.Foldable.foldl1------------------------------------------------------------------------------------ Trace------------------------------------------------------------------------------------ Functions from Debug.Trace--- but with DEPRECATED pragma, so -Werror will scream on them.--trace :: String -> a -> a-trace = Debug.Trace.trace-{-# DEPRECATED trace "Don't leave me in the code" #-}--traceShowId :: Show a => a -> a-traceShowId x = Debug.Trace.traceShow x x-{-# DEPRECATED traceShowId "Don't leave me in the code" #-}--traceShow :: Show a => a -> b -> b-traceShow = Debug.Trace.traceShow-{-# DEPRECATED traceShow "Don't leave me in the code" #-}
− Distribution/Compat/Prelude/Internal.hs
@@ -1,14 +0,0 @@--- | This module re-exports the non-exposed--- "Distribution.Compat.Prelude" module for--- reuse by @cabal-install@'s--- "Distribution.Client.Compat.Prelude" module.------ It is highly discouraged to rely on this module--- for @Setup.hs@ scripts since its API is /not/--- stable.-module Distribution.Compat.Prelude.Internal- {-# WARNING "This modules' API is not stable. Use at your own risk, or better yet, use @base-compat@!" #-}- ( module Distribution.Compat.Prelude- ) where--import Distribution.Compat.Prelude
− Distribution/Compat/Process.hs
@@ -1,82 +0,0 @@-{-# LANGUAGE CPP #-}-module Distribution.Compat.Process (- -- * Redefined functions- createProcess,- runInteractiveProcess,- rawSystem,- -- * Additions- enableProcessJobs,- ) where--import System.Exit (ExitCode (..))-import System.IO (Handle)--import System.Process (CreateProcess, ProcessHandle)-import qualified System.Process as Process--#if MIN_VERSION_process(1,2,0)-import System.Process (waitForProcess)-#endif------------------------------------------------------------------------------------ enableProcessJobs------------------------------------------------------------------------------------ | Enable process jobs to ensure accurate determination of process completion--- in the presence of @exec(3)@ on Windows.------ Unfortunately the process job support is badly broken in @process@ releases--- prior to 1.6.9, so we disable it in these versions, despite the fact that--- this means we may see sporatic build failures without jobs.-enableProcessJobs :: CreateProcess -> CreateProcess-#ifdef MIN_VERSION_process-#if MIN_VERSION_process(1,6,9)-enableProcessJobs cp = cp {Process.use_process_jobs = True}-#else-enableProcessJobs cp = cp-#endif-#else-enableProcessJobs cp = cp-#endif------------------------------------------------------------------------------------ process redefinitions------------------------------------------------------------------------------------ | 'System.Process.createProcess' with process jobs enabled when appropriate.--- See 'enableProcessJobs'.-createProcess :: CreateProcess- -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)-createProcess = Process.createProcess . enableProcessJobs---- | 'System.Process.rawSystem' with process jobs enabled when appropriate.--- See 'enableProcessJobs'.-rawSystem :: String -> [String] -> IO ExitCode-rawSystem cmd args = do-#if MIN_VERSION_process(1,2,0)- (_,_,_,p) <- createProcess (Process.proc cmd args) { Process.delegate_ctlc = True }- waitForProcess p-#else- -- With very old 'process', just do its rawSystem- Process.rawSystem cmd args-#endif---- | 'System.Process.runInteractiveProcess' with process jobs enabled when--- appropriate. See 'enableProcessJobs'.-runInteractiveProcess- :: FilePath -- ^ Filename of the executable (see 'RawCommand' for details)- -> [String] -- ^ Arguments to pass to the executable- -> Maybe FilePath -- ^ Optional path to the working directory- -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit)- -> IO (Handle,Handle,Handle,ProcessHandle)-runInteractiveProcess cmd args mb_cwd mb_env = do- (mb_in, mb_out, mb_err, p) <-- createProcess (Process.proc cmd args)- { Process.std_in = Process.CreatePipe,- Process.std_out = Process.CreatePipe,- Process.std_err = Process.CreatePipe,- Process.env = mb_env,- Process.cwd = mb_cwd }- return (fromJust mb_in, fromJust mb_out, fromJust mb_err, p)- where- fromJust = maybe (error "runInteractiveProcess: fromJust") id
− Distribution/Compat/ResponseFile.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE CPP, RankNTypes, FlexibleContexts #-}---- Compatibility layer for GHC.ResponseFile--- Implementation from base 4.12.0 is used.--- http://hackage.haskell.org/package/base-4.12.0.0/src/LICENSE-module Distribution.Compat.ResponseFile (expandResponse) where--import Distribution.Compat.Prelude-import Prelude ()--import System.FilePath-import System.IO (hPutStrLn, stderr)-import System.IO.Error--#if MIN_VERSION_base(4,12,0)-import GHC.ResponseFile (unescapeArgs)-#else--unescapeArgs :: String -> [String]-unescapeArgs = filter (not . null) . unescape--data Quoting = NoneQ | SngQ | DblQ--unescape :: String -> [String]-unescape args = reverse . map reverse $ go args NoneQ False [] []- where- -- n.b., the order of these cases matters; these are cribbed from gcc- -- case 1: end of input- go [] _q _bs a as = a:as- -- case 2: back-slash escape in progress- go (c:cs) q True a as = go cs q False (c:a) as- -- case 3: no back-slash escape in progress, but got a back-slash- go (c:cs) q False a as- | '\\' == c = go cs q True a as- -- case 4: single-quote escaping in progress- go (c:cs) SngQ False a as- | '\'' == c = go cs NoneQ False a as- | otherwise = go cs SngQ False (c:a) as- -- case 5: double-quote escaping in progress- go (c:cs) DblQ False a as- | '"' == c = go cs NoneQ False a as- | otherwise = go cs DblQ False (c:a) as- -- case 6: no escaping is in progress- go (c:cs) NoneQ False a as- | isSpace c = go cs NoneQ False [] (a:as)- | '\'' == c = go cs SngQ False a as- | '"' == c = go cs DblQ False a as- | otherwise = go cs NoneQ False (c:a) as--#endif--expandResponse :: [String] -> IO [String]-expandResponse = go recursionLimit "."- where- recursionLimit = 100-- go :: Int -> FilePath -> [String] -> IO [String]- go n dir- | n >= 0 = fmap concat . traverse (expand n dir)- | otherwise = const $ hPutStrLn stderr "Error: response file recursion limit exceeded." >> exitFailure-- expand :: Int -> FilePath -> String -> IO [String]- expand n dir arg@('@':f) = readRecursively n (dir </> f) `catchIOError` (const $ print "?" >> return [arg])- expand _n _dir x = return [x]-- readRecursively :: Int -> FilePath -> IO [String]- readRecursively n f = go (n - 1) (takeDirectory f) =<< unescapeArgs <$> readFile f
− Distribution/Compat/Semigroup.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE TypeOperators #-}---- | Compatibility layer for "Data.Semigroup"-module Distribution.Compat.Semigroup- ( Semigroup((<>))- , Mon.Monoid(..)- , All(..)- , Any(..)-- , First'(..)- , Last'(..)-- , Option'(..)-- , gmappend- , gmempty- ) where--import Distribution.Compat.Binary (Binary)-import Distribution.Utils.Structured (Structured)-import Data.Typeable (Typeable)--import GHC.Generics--- Data.Semigroup is available since GHC 8.0/base-4.9 in `base`--- for older GHC/base, it's provided by `semigroups`-import Data.Semigroup-import qualified Data.Monoid as Mon----- | A copy of 'Data.Semigroup.First'.-newtype First' a = First' { getFirst' :: a }- deriving (Eq, Ord, Show)--instance Semigroup (First' a) where- a <> _ = a---- | A copy of 'Data.Semigroup.Last'.-newtype Last' a = Last' { getLast' :: a }- deriving (Eq, Ord, Read, Show, Generic, Binary, Typeable)--instance Structured a => Structured (Last' a)--instance Semigroup (Last' a) where- _ <> b = b--instance Functor Last' where- fmap f (Last' x) = Last' (f x)---- | A wrapper around 'Maybe', providing the 'Semigroup' and 'Monoid' instances--- implemented for 'Maybe' since @base-4.11@.-newtype Option' a = Option' { getOption' :: Maybe a }- deriving (Eq, Ord, Read, Show, Binary, Generic, Functor, Typeable)--instance Structured a => Structured (Option' a)--instance Semigroup a => Semigroup (Option' a) where- Option' (Just a) <> Option' (Just b) = Option' (Just (a <> b))- Option' Nothing <> b = b- a <> Option' Nothing = a--instance Semigroup a => Monoid (Option' a) where- mempty = Option' 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/SnocList.hs
@@ -1,33 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Compat.SnocList--- License : BSD3------ Maintainer : cabal-dev@haskell.org--- Stability : experimental--- Portability : portable------ A very reversed list. Has efficient `snoc`-module Distribution.Compat.SnocList (- SnocList,- runSnocList,- snoc,-) where--import Prelude ()-import Distribution.Compat.Prelude--newtype SnocList a = SnocList [a]--snoc :: SnocList a -> a -> SnocList a-snoc (SnocList xs) x = SnocList (x : xs)--runSnocList :: SnocList a -> [a]-runSnocList (SnocList xs) = reverse xs--instance Semigroup (SnocList a) where- SnocList xs <> SnocList ys = SnocList (ys <> xs)--instance Monoid (SnocList a) where- mempty = SnocList []- mappend = (<>)
− Distribution/Compat/Stack.hs
@@ -1,113 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ImplicitParams #-}-module Distribution.Compat.Stack (- WithCallStack,- CallStack,- annotateCallStackIO,- withFrozenCallStack,- withLexicalCallStack,- callStack,- prettyCallStack,- parentSrcLocPrefix-) where--import System.IO.Error--#ifdef MIN_VERSION_base-#if MIN_VERSION_base(4,8,1)-#define GHC_STACK_SUPPORTED 1-#endif-#endif--#ifdef GHC_STACK_SUPPORTED-import GHC.Stack-#endif--#ifdef GHC_STACK_SUPPORTED--#if MIN_VERSION_base(4,9,0)-type WithCallStack a = HasCallStack => a-#elif MIN_VERSION_base(4,8,1)-type WithCallStack a = (?callStack :: CallStack) => a-#endif--#if !MIN_VERSION_base(4,9,0)--- NB: Can't say WithCallStack (WithCallStack a -> a);--- Haskell doesn't support this kind of implicit parameter!--- See https://mail.haskell.org/pipermail/ghc-devs/2016-January/011096.html--- Since this function doesn't do anything, it's OK to--- give it a less good type.-withFrozenCallStack :: WithCallStack (a -> a)-withFrozenCallStack x = x--callStack :: (?callStack :: CallStack) => CallStack-callStack = ?callStack--prettyCallStack :: CallStack -> String-prettyCallStack = showCallStack-#endif---- | Give the *parent* of the person who invoked this;--- so it's most suitable for being called from a utility function.--- You probably want to call this using 'withFrozenCallStack'; otherwise--- it's not very useful. We didn't implement this for base-4.8.1--- because we cannot rely on freezing to have taken place.----parentSrcLocPrefix :: WithCallStack String-#if MIN_VERSION_base(4,9,0)-parentSrcLocPrefix =- case getCallStack callStack of- (_:(_, loc):_) -> showLoc loc- [(_, loc)] -> showLoc loc- [] -> error "parentSrcLocPrefix: empty call stack"- where- showLoc loc =- srcLocFile loc ++ ":" ++ show (srcLocStartLine loc) ++ ": "-#else-parentSrcLocPrefix = "Call sites not available with base < 4.9.0.0 (GHC 8.0): "-#endif---- Yeah, this uses skivvy implementation details.-withLexicalCallStack :: (a -> WithCallStack (IO b)) -> WithCallStack (a -> IO b)-withLexicalCallStack f =- let stk = ?callStack- in \x -> let ?callStack = stk in f x--#else--data CallStack = CallStack- deriving (Eq, Show)--type WithCallStack a = a--withFrozenCallStack :: a -> a-withFrozenCallStack x = x--callStack :: CallStack-callStack = CallStack--prettyCallStack :: CallStack -> String-prettyCallStack _ = "Call stacks not available with base < 4.8.1.0 (GHC 7.10)"--parentSrcLocPrefix :: String-parentSrcLocPrefix = "Call sites not available with base < 4.9.0.0 (GHC 8.0): "--withLexicalCallStack :: (a -> IO b) -> a -> IO b-withLexicalCallStack f = f--#endif---- | This function is for when you *really* want to add a call--- stack to raised IO, but you don't have a--- 'Distribution.Verbosity.Verbosity' so you can't use--- 'Distribution.Simple.Utils.annotateIO'. If you have a 'Verbosity',--- please use that function instead.-annotateCallStackIO :: WithCallStack (IO a -> IO a)-annotateCallStackIO = modifyIOError f- where- f ioe = ioeSetErrorString ioe- . wrapCallStack- $ ioeGetErrorString ioe- wrapCallStack s =- prettyCallStack callStack ++ "\n" ++ s
− Distribution/Compat/Time.hs
@@ -1,194 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Distribution.Compat.Time- ( ModTime(..) -- Needed for testing- , getModTime, getFileAge, getCurTime- , posixSecondsToModTime- , calibrateMtimeChangeDelay )- where--import Prelude ()-import Distribution.Compat.Prelude--import System.Directory ( getModificationTime )--import Distribution.Simple.Utils ( withTempDirectory )-import Distribution.Verbosity ( silent )--import System.FilePath--import Data.Time.Clock.POSIX ( POSIXTime, getPOSIXTime )-import Data.Time ( diffUTCTime, getCurrentTime )-import Data.Time.Clock.POSIX ( posixDayLength )---#if defined mingw32_HOST_OS--import qualified Prelude-import Data.Bits ((.|.), unsafeShiftL)-#if MIN_VERSION_base(4,7,0)-import Data.Bits (finiteBitSize)-#else-import Data.Bits (bitSize)-#endif--import Foreign ( allocaBytes, peekByteOff )-import System.IO.Error ( mkIOError, doesNotExistErrorType )-import System.Win32.Types ( BOOL, DWORD, LPCTSTR, LPVOID, withTString )--#else--import System.Posix.Files ( FileStatus, getFileStatus )--#if MIN_VERSION_unix(2,6,0)-import System.Posix.Files ( modificationTimeHiRes )-#else-import System.Posix.Files ( modificationTime )-#endif--#endif---- | An opaque type representing a file's modification time, represented--- internally as a 64-bit unsigned integer in the Windows UTC format.-newtype ModTime = ModTime Word64- deriving (Binary, Generic, Bounded, Eq, Ord, Typeable)--instance Structured ModTime--instance Show ModTime where- show (ModTime x) = show x--instance Read ModTime where- readsPrec p str = map (first ModTime) (readsPrec p str)---- | Return modification time of the given file. Works around the low clock--- resolution problem that 'getModificationTime' has on GHC < 7.8.------ This is a modified version of the code originally written for Shake by Neil--- Mitchell. See module Development.Shake.FileInfo.-getModTime :: FilePath -> IO ModTime--#if defined mingw32_HOST_OS---- Directly against the Win32 API.-getModTime path = allocaBytes size_WIN32_FILE_ATTRIBUTE_DATA $ \info -> do- res <- getFileAttributesEx path info- if not res- then do- let err = mkIOError doesNotExistErrorType- "Distribution.Compat.Time.getModTime"- Nothing (Just path)- ioError err- else do- dwLow <- peekByteOff info- index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwLowDateTime- dwHigh <- peekByteOff info- index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwHighDateTime-#if MIN_VERSION_base(4,7,0)- let qwTime =- (fromIntegral (dwHigh :: DWORD) `unsafeShiftL` finiteBitSize dwHigh)- .|. (fromIntegral (dwLow :: DWORD))-#else- let qwTime =- (fromIntegral (dwHigh :: DWORD) `unsafeShiftL` bitSize dwHigh)- .|. (fromIntegral (dwLow :: DWORD))-#endif- return $! ModTime (qwTime :: Word64)--#ifdef x86_64_HOST_ARCH-#define CALLCONV ccall-#else-#define CALLCONV stdcall-#endif--foreign import CALLCONV "windows.h GetFileAttributesExW"- c_getFileAttributesEx :: LPCTSTR -> Int32 -> LPVOID -> Prelude.IO BOOL--getFileAttributesEx :: String -> LPVOID -> IO BOOL-getFileAttributesEx path lpFileInformation =- withTString path $ \c_path ->- c_getFileAttributesEx c_path getFileExInfoStandard lpFileInformation--getFileExInfoStandard :: Int32-getFileExInfoStandard = 0--size_WIN32_FILE_ATTRIBUTE_DATA :: Int-size_WIN32_FILE_ATTRIBUTE_DATA = 36--index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwLowDateTime :: Int-index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwLowDateTime = 20--index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwHighDateTime :: Int-index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwHighDateTime = 24--#else---- Directly against the unix library.-getModTime path = do- st <- getFileStatus path- return $! (extractFileTime st)--extractFileTime :: FileStatus -> ModTime-extractFileTime x = posixTimeToModTime (modificationTimeHiRes x)--#endif--windowsTick, secToUnixEpoch :: Word64-windowsTick = 10000000-secToUnixEpoch = 11644473600---- | Convert POSIX seconds to ModTime.-posixSecondsToModTime :: Int64 -> ModTime-posixSecondsToModTime s =- ModTime $ ((fromIntegral s :: Word64) + secToUnixEpoch) * windowsTick---- | Convert 'POSIXTime' to 'ModTime'.-posixTimeToModTime :: POSIXTime -> ModTime-posixTimeToModTime p = ModTime $ (ceiling $ p * 1e7) -- 100 ns precision- + (secToUnixEpoch * windowsTick)---- | Return age of given file in days.-getFileAge :: FilePath -> IO Double-getFileAge file = do- t0 <- getModificationTime file- t1 <- getCurrentTime- return $ realToFrac (t1 `diffUTCTime` t0) / realToFrac posixDayLength---- | Return the current time as 'ModTime'.-getCurTime :: IO ModTime-getCurTime = posixTimeToModTime `fmap` getPOSIXTime -- Uses 'gettimeofday'.---- | Based on code written by Neil Mitchell for Shake. See--- 'sleepFileTimeCalibrate' in 'Test.Type'. Returns a pair--- of microsecond values: first, the maximum delay seen, and the--- recommended delay to use before testing for file modification change.--- The returned delay is never smaller--- than 10 ms, but never larger than 1 second.-calibrateMtimeChangeDelay :: IO (Int, Int)-calibrateMtimeChangeDelay =- withTempDirectory silent "." "calibration-" $ \dir -> do- let fileName = dir </> "probe"- mtimes <- for [1..25] $ \(i::Int) -> time $ do- writeFile fileName $ show i- t0 <- getModTime fileName- let spin j = do- writeFile fileName $ show (i,j)- t1 <- getModTime fileName- unless (t0 < t1) (spin $ j + 1)- spin (0::Int)- let mtimeChange = maximum mtimes- mtimeChange' = min 1000000 $ (max 10000 mtimeChange) * 2- return (mtimeChange, mtimeChange')- where- time :: IO () -> IO Int- time act = do- t0 <- getCurrentTime- act- t1 <- getCurrentTime- return . ceiling $! (t1 `diffUTCTime` t0) * 1e6 -- microseconds
− Distribution/Compat/Typeable.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-module Distribution.Compat.Typeable (- Typeable,- TypeRep,- typeRep,- ) where--#if MIN_VERSION_base(4,7,0)-import Data.Typeable (Typeable, TypeRep, typeRep)-#else-import Data.Typeable (Typeable, TypeRep, typeOf)-#endif--#if !MIN_VERSION_base(4,7,0)-typeRep :: forall a proxy. Typeable a => proxy a -> TypeRep-typeRep _ = typeOf (undefined :: a)-#endif
− Distribution/Compiler.hs
@@ -1,223 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Compiler--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This has an enumeration of the various compilers that Cabal knows about. It--- also specifies the default compiler. Sadly you'll often see code that does--- case analysis on this compiler flavour enumeration like:------ > case compilerFlavor comp of--- > GHC -> GHC.getInstalledPackages verbosity packageDb progdb------ Obviously it would be better to use the proper 'Compiler' abstraction--- because that would keep all the compiler-specific code together.--- Unfortunately we cannot make this change yet without breaking the--- 'UserHooks' api, which would break all custom @Setup.hs@ files, so for the--- moment we just have to live with this deficiency. If you're interested, see--- ticket #57.--module Distribution.Compiler (- -- * Compiler flavor- CompilerFlavor(..),- buildCompilerId,- buildCompilerFlavor,- defaultCompilerFlavor,- classifyCompilerFlavor,- knownCompilerFlavors,-- -- * Per compiler flavor- PerCompilerFlavor (..),- perCompilerFlavorToList,-- -- * Compiler id- CompilerId(..),-- -- * Compiler info- CompilerInfo(..),- unknownCompilerInfo,- AbiTag(..), abiTagString- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Language.Haskell.Extension--import Distribution.Version (Version, mkVersion', nullVersion)--import qualified System.Info (compilerName, compilerVersion)-import Distribution.Parsec (Parsec (..))-import Distribution.Pretty (Pretty (..), prettyShow)-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp--data CompilerFlavor =- GHC | GHCJS | NHC | YHC | Hugs | HBC | Helium | JHC | LHC | UHC | Eta- | HaskellSuite String -- string is the id of the actual compiler- | OtherCompiler String- deriving (Generic, Show, Read, Eq, Ord, Typeable, Data)--instance Binary CompilerFlavor-instance Structured CompilerFlavor-instance NFData CompilerFlavor where rnf = genericRnf--knownCompilerFlavors :: [CompilerFlavor]-knownCompilerFlavors =- [GHC, GHCJS, NHC, YHC, Hugs, HBC, Helium, JHC, LHC, UHC, Eta]--instance Pretty CompilerFlavor where- pretty (OtherCompiler name) = Disp.text name- pretty (HaskellSuite name) = Disp.text name- pretty NHC = Disp.text "nhc98"- pretty other = Disp.text (lowercase (show other))--instance Parsec CompilerFlavor where- parsec = classifyCompilerFlavor <$> component- where- component = do- cs <- P.munch1 isAlphaNum- if all isDigit cs then fail "all digits compiler name" else return cs--classifyCompilerFlavor :: String -> CompilerFlavor-classifyCompilerFlavor s =- fromMaybe (OtherCompiler s) $ lookup (lowercase s) compilerMap- where- compilerMap = [ (lowercase (prettyShow compiler), compiler)- | compiler <- knownCompilerFlavors ]--buildCompilerFlavor :: CompilerFlavor-buildCompilerFlavor = classifyCompilerFlavor System.Info.compilerName--buildCompilerVersion :: Version-buildCompilerVersion = mkVersion' System.Info.compilerVersion--buildCompilerId :: CompilerId-buildCompilerId = CompilerId buildCompilerFlavor buildCompilerVersion---- | The default compiler flavour to pick when compiling stuff. This defaults--- to the compiler used to build the Cabal lib.------ However if it's not a recognised compiler then it's 'Nothing' and the user--- will have to specify which compiler they want.----defaultCompilerFlavor :: Maybe CompilerFlavor-defaultCompilerFlavor = case buildCompilerFlavor of- OtherCompiler _ -> Nothing- _ -> Just buildCompilerFlavor------------------------------------------------------------------------------------ Per compiler data------------------------------------------------------------------------------------ | 'PerCompilerFlavor' carries only info per GHC and GHCJS------ Cabal parses only @ghc-options@ and @ghcjs-options@, others are omitted.----data PerCompilerFlavor v = PerCompilerFlavor v v- deriving (Generic, Show, Read, Eq, Typeable, Data, Functor, Foldable- , Traversable)--instance Binary a => Binary (PerCompilerFlavor a)-instance Structured a => Structured (PerCompilerFlavor a)-instance NFData a => NFData (PerCompilerFlavor a)--perCompilerFlavorToList :: PerCompilerFlavor v -> [(CompilerFlavor, v)]-perCompilerFlavorToList (PerCompilerFlavor a b) = [(GHC, a), (GHCJS, b)]--instance Semigroup a => Semigroup (PerCompilerFlavor a) where- PerCompilerFlavor a b <> PerCompilerFlavor a' b' = PerCompilerFlavor- (a <> a') (b <> b')--instance (Semigroup a, Monoid a) => Monoid (PerCompilerFlavor a) where- mempty = PerCompilerFlavor mempty mempty- mappend = (<>)---- --------------------------------------------------------------- * Compiler Id--- --------------------------------------------------------------data CompilerId = CompilerId CompilerFlavor Version- deriving (Eq, Generic, Ord, Read, Show, Typeable)--instance Binary CompilerId-instance Structured CompilerId-instance NFData CompilerId where rnf = genericRnf--instance Pretty CompilerId where- pretty (CompilerId f v)- | v == nullVersion = pretty f- | otherwise = pretty f <<>> Disp.char '-' <<>> pretty v--instance Parsec CompilerId where- parsec = do- flavour <- parsec- version <- (P.char '-' >> parsec) <|> return nullVersion- return (CompilerId flavour version)--lowercase :: String -> String-lowercase = map toLower---- --------------------------------------------------------------- * Compiler Info--- ---------------------------------------------------------------- | Compiler information used for resolving configurations. Some--- fields can be set to Nothing to indicate that the information is--- unknown.--data CompilerInfo = CompilerInfo {- compilerInfoId :: CompilerId,- -- ^ Compiler flavour and version.- compilerInfoAbiTag :: AbiTag,- -- ^ Tag for distinguishing incompatible ABI's on the same- -- architecture/os.- compilerInfoCompat :: Maybe [CompilerId],- -- ^ Other implementations that this compiler claims to be- -- compatible with, if known.- compilerInfoLanguages :: Maybe [Language],- -- ^ Supported language standards, if known.- compilerInfoExtensions :: Maybe [Extension]- -- ^ Supported extensions, if known.- }- deriving (Generic, Show, Read)--instance Binary CompilerInfo--data AbiTag- = NoAbiTag- | AbiTag String- deriving (Eq, Generic, Show, Read, Typeable)--instance Binary AbiTag-instance Structured AbiTag--instance Pretty AbiTag where- pretty NoAbiTag = Disp.empty- pretty (AbiTag tag) = Disp.text tag--instance Parsec AbiTag where- parsec = do- tag <- P.munch (\c -> isAlphaNum c || c == '_')- if null tag then return NoAbiTag else return (AbiTag tag)--abiTagString :: AbiTag -> String-abiTagString NoAbiTag = ""-abiTagString (AbiTag tag) = tag---- | Make a CompilerInfo of which only the known information is its CompilerId,--- its AbiTag and that it does not claim to be compatible with other--- compiler id's.-unknownCompilerInfo :: CompilerId -> AbiTag -> CompilerInfo-unknownCompilerInfo compilerId abiTag =- CompilerInfo compilerId abiTag (Just []) Nothing Nothing
− Distribution/FieldGrammar.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}--- | This module provides a way to specify a grammar of @.cabal@ -like files.-module Distribution.FieldGrammar (- -- * Field grammar type- FieldGrammar (..),- uniqueField,- optionalField,- optionalFieldDef,- monoidalField,- -- * Concrete grammar implementations- ParsecFieldGrammar,- ParsecFieldGrammar',- parseFieldGrammar,- fieldGrammarKnownFieldList,- PrettyFieldGrammar,- PrettyFieldGrammar',- prettyFieldGrammar,- -- * Auxlilary- (^^^),- Section(..),- Fields,- partitionFields,- takeFields,- runFieldParser,- runFieldParser',- defaultFreeTextFieldDefST,- -- * Newtypes- module Distribution.FieldGrammar.Newtypes,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import qualified Data.Map.Strict as Map--import Distribution.FieldGrammar.Class-import Distribution.FieldGrammar.Newtypes-import Distribution.FieldGrammar.Parsec-import Distribution.FieldGrammar.Pretty-import Distribution.Fields.Field-import Distribution.Utils.Generic (spanMaybe)--type ParsecFieldGrammar' a = ParsecFieldGrammar a a-type PrettyFieldGrammar' a = PrettyFieldGrammar a a--infixl 5 ^^^---- | Reverse function application which binds tighter than '<$>' and '<*>'.--- Useful for refining grammar specification.------ @--- \<*\> 'monoidalFieldAla' "extensions" (alaList' FSep MQuoted) oldExtensions--- ^^^ 'deprecatedSince' [1,12] "Please use 'default-extensions' or 'other-extensions' fields."--- @-(^^^) :: a -> (a -> b) -> b-x ^^^ f = f x---- | Partitioning state-data PS ann = PS (Fields ann) [Section ann] [[Section ann]]---- | Partition field list into field map and groups of sections.-partitionFields :: [Field ann] -> (Fields ann, [[Section ann]])-partitionFields = finalize . foldl' f (PS mempty mempty mempty)- where- finalize :: PS ann -> (Fields ann, [[Section ann]])- finalize (PS fs s ss)- | null s = (fs, reverse ss)- | otherwise = (fs, reverse (reverse s : ss))-- f :: PS ann -> Field ann -> PS ann- f (PS fs s ss) (Field (Name ann name) fss) =- PS (Map.insertWith (flip (++)) name [MkNamelessField ann fss] fs) [] ss'- where- ss' | null s = ss- | otherwise = reverse s : ss- f (PS fs s ss) (Section name sargs sfields) =- PS fs (MkSection name sargs sfields : s) ss---- | Take all fields from the front.-takeFields :: [Field ann] -> (Fields ann, [Field ann])-takeFields = finalize . spanMaybe match- where- finalize (fs, rest) = (Map.fromListWith (flip (++)) fs, rest)-- match (Field (Name ann name) fs) = Just (name, [MkNamelessField ann fs])- match _ = Nothing
− Distribution/FieldGrammar/Class.hs
@@ -1,205 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-#if __GLASGOW_HASKELL__ >= 800-{-# LANGUAGE UndecidableSuperClasses #-}-#else-{-# LANGUAGE UndecidableInstances #-}-#endif-module Distribution.FieldGrammar.Class (- FieldGrammar (..),- uniqueField,- optionalField,- optionalFieldDef,- monoidalField,- defaultFreeTextFieldDefST,-) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.CabalSpecVersion (CabalSpecVersion)-import Distribution.Compat.Newtype (Newtype)-import Distribution.FieldGrammar.Newtypes-import Distribution.Fields.Field-import Distribution.Utils.ShortText---- | 'FieldGrammar' is parametrised by------ * @s@ which is a structure we are parsing. We need this to provide prettyprinter--- functionality------ * @a@ type of the field.------ /Note:/ We'd like to have @forall s. Applicative (f s)@ context.----class- ( c SpecVersion, c TestedWith, c SpecLicense, c Token, c Token', c FilePathNT- )- => FieldGrammar c g | g -> c- where- -- | Unfocus, zoom out, /blur/ 'FieldGrammar'.- blurFieldGrammar :: ALens' a b -> g b d -> g a d-- -- | Field which should be defined, exactly once.- uniqueFieldAla- :: (c b, Newtype a b)- => FieldName -- ^ field name- -> (a -> b) -- ^ 'Newtype' pack- -> ALens' s a -- ^ lens into the field- -> g s a-- -- | Boolean field with a default value.- booleanFieldDef- :: FieldName -- ^ field name- -> ALens' s Bool -- ^ lens into the field- -> Bool -- ^ default- -> g s Bool-- -- | Optional field.- optionalFieldAla- :: (c b, Newtype a b)- => FieldName -- ^ field name- -> (a -> b) -- ^ 'pack'- -> ALens' s (Maybe a) -- ^ lens into the field- -> g s (Maybe a)-- -- | Optional field with default value.- optionalFieldDefAla- :: (c b, Newtype a b, Eq a)- => FieldName -- ^ field name- -> (a -> b) -- ^ 'Newtype' pack- -> ALens' s a -- ^ @'Lens'' s a@: lens into the field- -> a -- ^ default value- -> g s a-- -- | Free text field is essentially 'optionalFieldDefAla` with @""@- -- as the default and "accept everything" parser.- --- -- @since 3.0.0.0- freeTextField- :: FieldName- -> ALens' s (Maybe String) -- ^ lens into the field- -> g s (Maybe String)-- -- | Free text field is essentially 'optionalFieldDefAla` with @""@- -- as the default and "accept everything" parser.- --- -- @since 3.0.0.0- freeTextFieldDef- :: FieldName- -> ALens' s String -- ^ lens into the field- -> g s String-- -- | @since 3.2.0.0- freeTextFieldDefST- :: FieldName- -> ALens' s ShortText -- ^ lens into the field- -> g s ShortText-- -- | Monoidal field.- --- -- Values are combined with 'mappend'.- --- -- /Note:/ 'optionalFieldAla' is a @monoidalField@ with 'Last' monoid.- --- monoidalFieldAla- :: (c b, Monoid a, Newtype a b)- => FieldName -- ^ field name- -> (a -> b) -- ^ 'pack'- -> ALens' s a -- ^ lens into the field- -> g s a-- -- | Parser matching all fields with a name starting with a prefix.- prefixedFields- :: FieldName -- ^ field name prefix- -> ALens' s [(String, String)] -- ^ lens into the field- -> g s [(String, String)]-- -- | Known field, which we don't parse, neither pretty print.- knownField :: FieldName -> g s ()-- -- | Field which is parsed but not pretty printed.- hiddenField :: g s a -> g s a-- -- | Deprecated since- deprecatedSince- :: CabalSpecVersion -- ^ version- -> String -- ^ deprecation message- -> g s a- -> g s a-- -- | Removed in. If we occur removed field, parsing fails.- removedIn- :: CabalSpecVersion -- ^ version- -> String -- ^ removal message- -> g s a- -> g s a-- -- | Annotate field with since spec-version.- availableSince- :: CabalSpecVersion -- ^ spec version- -> a -- ^ default value- -> g s a- -> g s a-- -- | Annotate field with since spec-version.- -- This is used to recognise, but warn about the field.- -- It is used to process @other-extensions@ field.- --- -- Default implementation is to not warn.- --- -- @since 3.4.0.0- availableSinceWarn- :: CabalSpecVersion -- ^ spec version- -> g s a- -> g s a- availableSinceWarn _ = id---- | Field which can be defined at most once.-uniqueField- :: (FieldGrammar c g, c (Identity a))- => FieldName -- ^ field name- -> ALens' s a -- ^ lens into the field- -> g s a-uniqueField fn l = uniqueFieldAla fn Identity l---- | Field which can be defined at most once.-optionalField- :: (FieldGrammar c g, c (Identity a))- => FieldName -- ^ field name- -> ALens' s (Maybe a) -- ^ lens into the field- -> g s (Maybe a)-optionalField fn l = optionalFieldAla fn Identity l---- | Optional field with default value.-optionalFieldDef- :: (FieldGrammar c g, Functor (g s), c (Identity a), Eq a)- => FieldName -- ^ field name- -> ALens' s a -- ^ @'Lens'' s a@: lens into the field- -> a -- ^ default value- -> g s a-optionalFieldDef fn l x = optionalFieldDefAla fn Identity l x---- | Field which can be define multiple times, and the results are @mappend@ed.-monoidalField- :: (FieldGrammar c g, c (Identity a), Monoid a)- => FieldName -- ^ field name- -> ALens' s a -- ^ lens into the field- -> g s a-monoidalField fn l = monoidalFieldAla fn Identity l---- | Default implementation for 'freeTextFieldDefST'.-defaultFreeTextFieldDefST- :: (Functor (g s), FieldGrammar c g)- => FieldName- -> ALens' s ShortText -- ^ lens into the field- -> g s ShortText-defaultFreeTextFieldDefST fn l =- toShortText <$> freeTextFieldDef fn (cloneLens l . st)- where- st :: Lens' ShortText String- st f s = toShortText <$> f (fromShortText s)
− Distribution/FieldGrammar/FieldDescrs.hs
@@ -1,121 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE UndecidableInstances #-}-module Distribution.FieldGrammar.FieldDescrs (- FieldDescrs,- fieldDescrPretty,- fieldDescrParse,- fieldDescrsToList,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Data.List (dropWhileEnd)-import Distribution.Compat.Lens (aview, cloneLens)-import Distribution.Compat.Newtype-import Distribution.FieldGrammar-import Distribution.Pretty (Pretty (..), showFreeText)--import qualified Data.Map as Map-import qualified Distribution.Compat.CharParsing as C-import qualified Distribution.Fields.Field as P-import qualified Distribution.Parsec as P-import qualified Text.PrettyPrint as Disp---- strict pair-data SP s = SP- { pPretty :: !(s -> Disp.Doc)- , pParse :: !(forall m. P.CabalParsing m => s -> m s)- }---- | A collection field parsers and pretty-printers.-newtype FieldDescrs s a = F { runF :: Map P.FieldName (SP s) }- deriving (Functor)--instance Applicative (FieldDescrs s) where- pure _ = F mempty- f <*> x = F (mappend (runF f) (runF x))--singletonF :: P.FieldName -> (s -> Disp.Doc) -> (forall m. P.CabalParsing m => s -> m s) -> FieldDescrs s a-singletonF fn f g = F $ Map.singleton fn (SP f g)---- | Lookup a field value pretty-printer.-fieldDescrPretty :: FieldDescrs s a -> P.FieldName -> Maybe (s -> Disp.Doc)-fieldDescrPretty (F m) fn = pPretty <$> Map.lookup fn m---- | Lookup a field value parser.-fieldDescrParse :: P.CabalParsing m => FieldDescrs s a -> P.FieldName -> Maybe (s -> m s)-fieldDescrParse (F m) fn = (\f -> pParse f) <$> Map.lookup fn m--fieldDescrsToList- :: P.CabalParsing m- => FieldDescrs s a- -> [(P.FieldName, s -> Disp.Doc, s -> m s)]-fieldDescrsToList = map mk . Map.toList . runF where- mk (name, SP ppr parse) = (name, ppr, parse)---- | /Note:/ default values are printed.-instance FieldGrammar ParsecPretty FieldDescrs where- blurFieldGrammar l (F m) = F (fmap blur m) where- blur (SP f g) = SP (f . aview l) (cloneLens l g)-- booleanFieldDef fn l _def = singletonF fn f g where- f s = Disp.text (show (aview l s))- g s = cloneLens l (const P.parsec) s- -- Note: eta expansion is needed for RankNTypes type-checking to work.-- uniqueFieldAla fn _pack l = singletonF fn f g where- f s = pretty (pack' _pack (aview l s))- g s = cloneLens l (const (unpack' _pack <$> P.parsec)) s-- optionalFieldAla fn _pack l = singletonF fn f g where- f s = maybe mempty (pretty . pack' _pack) (aview l s)- g s = cloneLens l (const (Just . unpack' _pack <$> P.parsec)) s-- optionalFieldDefAla fn _pack l _def = singletonF fn f g where- f s = pretty (pack' _pack (aview l s))- g s = cloneLens l (const (unpack' _pack <$> P.parsec)) s-- freeTextField fn l = singletonF fn f g where- f s = maybe mempty showFreeText (aview l s)- g s = cloneLens l (const (Just <$> parsecFreeText)) s-- freeTextFieldDef fn l = singletonF fn f g where- f s = showFreeText (aview l s)- g s = cloneLens l (const parsecFreeText) s-- freeTextFieldDefST = defaultFreeTextFieldDefST-- monoidalFieldAla fn _pack l = singletonF fn f g where- f s = pretty (pack' _pack (aview l s))- g s = cloneLens l (\x -> mappend x . unpack' _pack <$> P.parsec) s-- prefixedFields _fnPfx _l = F mempty- knownField _ = pure ()- deprecatedSince _ _ x = x- removedIn _ _ x = x- availableSince _ _ = id- hiddenField _ = F mempty--parsecFreeText :: P.CabalParsing m => m String-parsecFreeText = dropDotLines <$ C.spaces <*> many C.anyChar- where- -- Example package with dot lines- -- http://hackage.haskell.org/package/copilot-cbmc-0.1/copilot-cbmc.cabal- dropDotLines "." = "."- dropDotLines x = intercalate "\n" . map dotToEmpty . lines $ x-- dotToEmpty x | trim' x == "." = ""- dotToEmpty x = trim x-- trim' :: String -> String- trim' = dropWhileEnd (`elem` (" \t" :: String))-- trim :: String -> String- trim = dropWhile isSpace . dropWhileEnd isSpace--class (P.Parsec a, Pretty a) => ParsecPretty a-instance (P.Parsec a, Pretty a) => ParsecPretty a
− Distribution/FieldGrammar/Newtypes.hs
@@ -1,339 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}--- | This module provides @newtype@ wrappers to be used with "Distribution.FieldGrammar".-module Distribution.FieldGrammar.Newtypes (- -- * List- alaList,- alaList',- -- ** Modifiers- CommaVCat (..),- CommaFSep (..),- VCat (..),- FSep (..),- NoCommaFSep (..),- Sep (..),- -- ** Type- List,- -- * Set- alaSet,- alaSet',- Set',- -- * Version & License- SpecVersion (..),- TestedWith (..),- SpecLicense (..),- -- * Identifiers- Token (..),- Token' (..),- MQuoted (..),- FilePathNT (..),- ) where--import Distribution.Compat.Newtype-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.Compiler (CompilerFlavor)-import Distribution.License (License)-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Version- (LowerBound (..), Version, VersionRange, VersionRangeF (..), anyVersion, asVersionIntervals, cataVersionRange, mkVersion, version0, versionNumbers)-import Text.PrettyPrint (Doc, comma, fsep, punctuate, text, vcat)--import qualified Data.Set as Set-import qualified Distribution.Compat.CharParsing as P-import qualified Distribution.SPDX as SPDX---- | Vertical list with commas. Displayed with 'vcat'-data CommaVCat = CommaVCat---- | Paragraph fill list with commas. Displayed with 'fsep'-data CommaFSep = CommaFSep---- | Vertical list with optional commas. Displayed with 'vcat'.-data VCat = VCat---- | Paragraph fill list with optional commas. Displayed with 'fsep'.-data FSep = FSep---- | Paragraph fill list without commas. Displayed with 'fsep'.-data NoCommaFSep = NoCommaFSep--class Sep sep where- prettySep :: Proxy sep -> [Doc] -> Doc-- parseSep :: CabalParsing m => Proxy sep -> m a -> m [a]--instance Sep CommaVCat where- prettySep _ = vcat . punctuate comma- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p-instance Sep CommaFSep where- prettySep _ = fsep . punctuate comma- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p-instance Sep VCat where- prettySep _ = vcat- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p-instance Sep FSep where- prettySep _ = fsep- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p-instance Sep NoCommaFSep where- prettySep _ = fsep- parseSep _ p = many (p <* P.spaces)---- | List separated with optional commas. Displayed with @sep@, arguments of--- type @a@ are parsed and pretty-printed as @b@.-newtype List sep b a = List { _getList :: [a] }---- | 'alaList' and 'alaList'' are simply 'List', with additional phantom--- arguments to constraint the resulting type------ >>> :t alaList VCat--- alaList VCat :: [a] -> List VCat (Identity a) a------ >>> :t alaList' FSep Token--- alaList' FSep Token :: [String] -> List FSep Token String----alaList :: sep -> [a] -> List sep (Identity a) a-alaList _ = List---- | More general version of 'alaList'.-alaList' :: sep -> (a -> b) -> [a] -> List sep b a-alaList' _ _ = List--instance Newtype [a] (List sep wrapper a)--instance (Newtype a b, Sep sep, Parsec b) => Parsec (List sep b a) where- parsec = pack . map (unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) parsec--instance (Newtype a b, Sep sep, Pretty b) => Pretty (List sep b a) where- pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . unpack------- | Like 'List', but for 'Set'.------ @since 3.2.0.0-newtype Set' sep b a = Set' { _getSet :: Set a }---- | 'alaSet' and 'alaSet'' are simply 'Set'' constructor, with additional phantom--- arguments to constraint the resulting type------ >>> :t alaSet VCat--- alaSet VCat :: Set a -> Set' VCat (Identity a) a------ >>> :t alaSet' FSep Token--- alaSet' FSep Token :: Set String -> Set' FSep Token String------ >>> unpack' (alaSet' FSep Token) <$> eitherParsec "foo bar foo"--- Right (fromList ["bar","foo"])------ @since 3.2.0.0-alaSet :: sep -> Set a -> Set' sep (Identity a) a-alaSet _ = Set'---- | More general version of 'alaSet'.------ @since 3.2.0.0-alaSet' :: sep -> (a -> b) -> Set a -> Set' sep b a-alaSet' _ _ = Set'--instance Newtype (Set a) (Set' sep wrapper a)--instance (Newtype a b, Ord a, Sep sep, Parsec b) => Parsec (Set' sep b a) where- parsec = pack . Set.fromList . map (unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) parsec--instance (Newtype a b, Sep sep, Pretty b) => Pretty (Set' sep b a) where- pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . Set.toList . unpack------------------------------------------------------------------------------------ Identifiers------------------------------------------------------------------------------------ | Haskell string or @[^ ,]+@-newtype Token = Token { getToken :: String }--instance Newtype String Token--instance Parsec Token where- parsec = pack <$> parsecToken--instance Pretty Token where- pretty = showToken . unpack---- | Haskell string or @[^ ]+@-newtype Token' = Token' { getToken' :: String }--instance Newtype String Token'--instance Parsec Token' where- parsec = pack <$> parsecToken'--instance Pretty Token' where- pretty = showToken . unpack---- | Either @"quoted"@ or @un-quoted@.-newtype MQuoted a = MQuoted { getMQuoted :: a }--instance Newtype a (MQuoted a)--instance Parsec a => Parsec (MQuoted a) where- parsec = pack <$> parsecMaybeQuoted parsec--instance Pretty a => Pretty (MQuoted a) where- pretty = pretty . unpack---- | Filepath are parsed as 'Token'.-newtype FilePathNT = FilePathNT { getFilePathNT :: String }--instance Newtype String FilePathNT--instance Parsec FilePathNT where- parsec = pack <$> parsecToken--instance Pretty FilePathNT where- pretty = showFilePath . unpack------------------------------------------------------------------------------------ SpecVersion------------------------------------------------------------------------------------ | Version range or just version, i.e. @cabal-version@ field.------ There are few things to consider:------ * Starting with 2.2 the cabal-version field should be the first field in the--- file and only exact version is accepted. Therefore if we get e.g.--- @>= 2.2@, we fail.--- See <https://github.com/haskell/cabal/issues/4899>------ We have this newtype, as writing Parsec and Pretty instances--- for CabalSpecVersion would cause cycle in modules:--- Version -> CabalSpecVersion -> Parsec -> ...----newtype SpecVersion = SpecVersion { getSpecVersion :: CabalSpecVersion }- deriving (Eq, Show) -- instances needed for tests--instance Newtype CabalSpecVersion SpecVersion--instance Parsec SpecVersion where- parsec = do- e <- parsecSpecVersion- let ver :: Version- ver = either id specVersionFromRange e-- digits :: [Int]- digits = versionNumbers ver-- case cabalSpecFromVersionDigits digits of- Nothing -> fail $ "Unknown cabal spec version specified: " ++ prettyShow ver- Just csv -> do- -- Check some warnings:- case e of- -- example: cabal-version: 1.10- -- should be cabal-version: >=1.10- Left _v | csv < CabalSpecV1_12 -> parsecWarning PWTSpecVersion $ concat- [ "With 1.10 or earlier, the 'cabal-version' field must use "- , "range syntax rather than a simple version number. Use "- , "'cabal-version: >= " ++ prettyShow ver ++ "'."- ]-- -- example: cabal-version: >=1.12- -- should be cabal-version: 1.12- Right _vr | csv >= CabalSpecV1_12 -> parsecWarning PWTSpecVersion $ concat- [ "Packages with 'cabal-version: 1.12' or later should specify a "- , "specific version of the Cabal spec of the form "- , "'cabal-version: x.y'. "- , "Use 'cabal-version: " ++ prettyShow ver ++ "'."- ]-- -- example: cabal-version: >=1.10 && <1.12- -- should be cabal-version: >=1.10- Right vr | csv < CabalSpecV1_12- , not (simpleSpecVersionRangeSyntax vr) -> parsecWarning PWTSpecVersion $ concat- [ "It is recommended that the 'cabal-version' field only specify a "- , "version range of the form '>= x.y' for older cabal versions. Use "- , "'cabal-version: >= " ++ prettyShow ver ++ "'. "- , "Tools based on Cabal 1.10 and later will ignore upper bounds."- ]-- -- otherwise no warnings- _ -> pure ()-- return (pack csv)- where- parsecSpecVersion = Left <$> parsec <|> Right <$> range-- range = do- vr <- parsec- if specVersionFromRange vr >= mkVersion [2,1]- then fail "cabal-version higher than 2.2 cannot be specified as a range. See https://github.com/haskell/cabal/issues/4899"- else return vr-- specVersionFromRange :: VersionRange -> Version- specVersionFromRange versionRange = case asVersionIntervals versionRange of- [] -> version0- ((LowerBound version _, _):_) -> version-- simpleSpecVersionRangeSyntax = cataVersionRange alg where- alg (OrLaterVersionF _) = True- alg _ = False---instance Pretty SpecVersion where- pretty (SpecVersion csv)- | csv >= CabalSpecV1_12 = text (showCabalSpecVersion csv)- | otherwise = text ">=" <<>> text (showCabalSpecVersion csv)------------------------------------------------------------------------------------ SpecLicense------------------------------------------------------------------------------------ | SPDX License expression or legacy license-newtype SpecLicense = SpecLicense { getSpecLicense :: Either SPDX.License License }--instance Newtype (Either SPDX.License License) SpecLicense--instance Parsec SpecLicense where- parsec = do- v <- askCabalSpecVersion- if v >= CabalSpecV2_2- then SpecLicense . Left <$> parsec- else SpecLicense . Right <$> parsec--instance Pretty SpecLicense where- pretty = either pretty pretty . unpack------------------------------------------------------------------------------------ TestedWith------------------------------------------------------------------------------------ | Version range or just version-newtype TestedWith = TestedWith { getTestedWith :: (CompilerFlavor, VersionRange) }--instance Newtype (CompilerFlavor, VersionRange) TestedWith--instance Parsec TestedWith where- parsec = pack <$> parsecTestedWith--instance Pretty TestedWith where- pretty x = case unpack x of- (compiler, vr) -> pretty compiler <+> pretty vr--parsecTestedWith :: CabalParsing m => m (CompilerFlavor, VersionRange)-parsecTestedWith = do- name <- lexemeParsec- ver <- parsec <|> pure anyVersion- return (name, ver)
− Distribution/FieldGrammar/Parsec.hs
@@ -1,439 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}--- | This module provides a 'FieldGrammarParser', one way to parse--- @.cabal@ -like files.------ Fields can be specified multiple times in the .cabal files. The order of--- such entries is important, but the mutual ordering of different fields is--- not.Also conditional sections are considered after non-conditional data.--- The example of this silent-commutation quirk is the fact that------ @--- buildable: True--- if os(linux)--- buildable: False--- @------ and------ @--- if os(linux)--- buildable: False--- buildable: True--- @------ behave the same! This is the limitation of 'GeneralPackageDescription'--- structure.------ So we transform the list of fields @['Field' ann]@ into--- a map of grouped ordinary fields and a list of lists of sections:--- @'Fields' ann = 'Map' 'FieldName' ['NamelessField' ann]@ and @[['Section' ann]]@.------ We need list of list of sections, because we need to distinguish situations--- where there are fields in between. For example------ @--- if flag(bytestring-lt-0_10_4)--- build-depends: bytestring < 0.10.4------ default-language: Haskell2020------ else--- build-depends: bytestring >= 0.10.4------ @------ is obviously invalid specification.------ We can parse 'Fields' like we parse @aeson@ objects, yet we use--- slightly higher-level API, so we can process unspecified fields,--- to report unknown fields and save custom @x-fields@.----module Distribution.FieldGrammar.Parsec (- ParsecFieldGrammar,- parseFieldGrammar,- fieldGrammarKnownFieldList,- -- * Auxiliary- Fields,- NamelessField (..),- namelessFieldAnn,- Section (..),- runFieldParser,- runFieldParser',- fieldLinesToStream,- ) where--import Data.List (dropWhileEnd)-import Distribution.Compat.Newtype-import Distribution.Compat.Prelude-import Distribution.Simple.Utils (fromUTF8BS)-import Prelude ()--import qualified Data.ByteString as BS-import qualified Data.List.NonEmpty as NE-import qualified Data.Map.Strict as Map-import qualified Data.Set as Set-import qualified Distribution.Utils.ShortText as ShortText-import qualified Text.Parsec as P-import qualified Text.Parsec.Error as P--import Distribution.CabalSpecVersion-import Distribution.FieldGrammar.Class-import Distribution.Fields.Field-import Distribution.Fields.ParseResult-import Distribution.Parsec-import Distribution.Parsec.FieldLineStream-import Distribution.Parsec.Position (positionCol, positionRow)------------------------------------------------------------------------------------ Auxiliary types----------------------------------------------------------------------------------type Fields ann = Map FieldName [NamelessField ann]---- | Single field, without name, but with its annotation.-data NamelessField ann = MkNamelessField !ann [FieldLine ann]- deriving (Eq, Show, Functor)--namelessFieldAnn :: NamelessField ann -> ann-namelessFieldAnn (MkNamelessField ann _) = ann---- | The 'Section' constructor of 'Field'.-data Section ann = MkSection !(Name ann) [SectionArg ann] [Field ann]- deriving (Eq, Show, Functor)------------------------------------------------------------------------------------ ParsecFieldGrammar----------------------------------------------------------------------------------data ParsecFieldGrammar s a = ParsecFG- { fieldGrammarKnownFields :: !(Set FieldName)- , fieldGrammarKnownPrefixes :: !(Set FieldName)- , fieldGrammarParser :: !(CabalSpecVersion -> Fields Position -> ParseResult a)- }- deriving (Functor)--parseFieldGrammar :: CabalSpecVersion -> Fields Position -> ParsecFieldGrammar s a -> ParseResult a-parseFieldGrammar v fields grammar = do- for_ (Map.toList (Map.filterWithKey isUnknownField fields)) $ \(name, nfields) ->- for_ nfields $ \(MkNamelessField pos _) ->- parseWarning pos PWTUnknownField $ "Unknown field: " ++ show name- -- TODO: fields allowed in this section-- -- parse- fieldGrammarParser grammar v fields-- where- isUnknownField k _ = not $- k `Set.member` fieldGrammarKnownFields grammar- || any (`BS.isPrefixOf` k) (fieldGrammarKnownPrefixes grammar)--fieldGrammarKnownFieldList :: ParsecFieldGrammar s a -> [FieldName]-fieldGrammarKnownFieldList = Set.toList . fieldGrammarKnownFields--instance Applicative (ParsecFieldGrammar s) where- pure x = ParsecFG mempty mempty (\_ _ -> pure x)- {-# INLINE pure #-}-- ParsecFG f f' f'' <*> ParsecFG x x' x'' = ParsecFG- (mappend f x)- (mappend f' x')- (\v fields -> f'' v fields <*> x'' v fields)- {-# INLINE (<*>) #-}--warnMultipleSingularFields :: FieldName -> [NamelessField Position] -> ParseResult ()-warnMultipleSingularFields _ [] = pure ()-warnMultipleSingularFields fn (x : xs) = do- let pos = namelessFieldAnn x- poss = map namelessFieldAnn xs- parseWarning pos PWTMultipleSingularField $- "The field " <> show fn <> " is specified more than once at positions " ++ intercalate ", " (map showPos (pos : poss))--instance FieldGrammar Parsec ParsecFieldGrammar where- blurFieldGrammar _ (ParsecFG s s' parser) = ParsecFG s s' parser-- uniqueFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser- where- parser v fields = case Map.lookup fn fields of- Nothing -> parseFatalFailure zeroPos $ show fn ++ " field missing"- Just [] -> parseFatalFailure zeroPos $ show fn ++ " field missing"- Just [x] -> parseOne v x- Just xs@(_:y:ys) -> do- warnMultipleSingularFields fn xs- NE.last <$> traverse (parseOne v) (y:|ys)-- parseOne v (MkNamelessField pos fls) =- unpack' _pack <$> runFieldParser pos parsec v fls-- booleanFieldDef fn _extract def = ParsecFG (Set.singleton fn) Set.empty parser- where- parser v fields = case Map.lookup fn fields of- Nothing -> pure def- Just [] -> pure def- Just [x] -> parseOne v x- Just xs@(_:y:ys) -> do- warnMultipleSingularFields fn xs- NE.last <$> traverse (parseOne v) (y:|ys)-- parseOne v (MkNamelessField pos fls) = runFieldParser pos parsec v fls-- optionalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser- where- parser v fields = case Map.lookup fn fields of- Nothing -> pure Nothing- Just [] -> pure Nothing- Just [x] -> parseOne v x- Just xs@(_:y:ys) -> do- warnMultipleSingularFields fn xs- NE.last <$> traverse (parseOne v) (y:|ys)-- parseOne v (MkNamelessField pos fls)- | null fls = pure Nothing- | otherwise = Just . unpack' _pack <$> runFieldParser pos parsec v fls-- optionalFieldDefAla fn _pack _extract def = ParsecFG (Set.singleton fn) Set.empty parser- where- parser v fields = case Map.lookup fn fields of- Nothing -> pure def- Just [] -> pure def- Just [x] -> parseOne v x- Just xs@(_:y:ys) -> do- warnMultipleSingularFields fn xs- NE.last <$> traverse (parseOne v) (y:|ys)-- parseOne v (MkNamelessField pos fls)- | null fls = pure def- | otherwise = unpack' _pack <$> runFieldParser pos parsec v fls-- freeTextField fn _ = ParsecFG (Set.singleton fn) Set.empty parser where- parser v fields = case Map.lookup fn fields of- Nothing -> pure Nothing- Just [] -> pure Nothing- Just [x] -> parseOne v x- Just xs@(_:y:ys) -> do- warnMultipleSingularFields fn xs- NE.last <$> traverse (parseOne v) (y:|ys)-- parseOne v (MkNamelessField pos fls)- | null fls = pure Nothing- | v >= CabalSpecV3_0 = pure (Just (fieldlinesToFreeText3 pos fls))- | otherwise = pure (Just (fieldlinesToFreeText fls))-- freeTextFieldDef fn _ = ParsecFG (Set.singleton fn) Set.empty parser where- parser v fields = case Map.lookup fn fields of- Nothing -> pure ""- Just [] -> pure ""- Just [x] -> parseOne v x- Just xs@(_:y:ys) -> do- warnMultipleSingularFields fn xs- NE.last <$> traverse (parseOne v) (y:|ys)-- parseOne v (MkNamelessField pos fls)- | null fls = pure ""- | v >= CabalSpecV3_0 = pure (fieldlinesToFreeText3 pos fls)- | otherwise = pure (fieldlinesToFreeText fls)-- -- freeTextFieldDefST = defaultFreeTextFieldDefST- freeTextFieldDefST fn _ = ParsecFG (Set.singleton fn) Set.empty parser where- parser v fields = case Map.lookup fn fields of- Nothing -> pure mempty- Just [] -> pure mempty- Just [x] -> parseOne v x- Just xs@(_:y:ys) -> do- warnMultipleSingularFields fn xs- NE.last <$> traverse (parseOne v) (y:|ys)-- parseOne v (MkNamelessField pos fls) = case fls of- [] -> pure mempty- [FieldLine _ bs] -> pure (ShortText.unsafeFromUTF8BS bs)- _ | v >= CabalSpecV3_0 -> pure (ShortText.toShortText $ fieldlinesToFreeText3 pos fls)- | otherwise -> pure (ShortText.toShortText $ fieldlinesToFreeText fls)-- monoidalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser- where- parser v fields = case Map.lookup fn fields of- Nothing -> pure mempty- Just xs -> foldMap (unpack' _pack) <$> traverse (parseOne v) xs-- parseOne v (MkNamelessField pos fls) = runFieldParser pos parsec v fls-- prefixedFields fnPfx _extract = ParsecFG mempty (Set.singleton fnPfx) (\_ fs -> pure (parser fs))- where- parser :: Fields Position -> [(String, String)]- parser values = reorder $ concatMap convert $ filter match $ Map.toList values-- match (fn, _) = fnPfx `BS.isPrefixOf` fn- convert (fn, fields) =- [ (pos, (fromUTF8BS fn, trim $ fromUTF8BS $ fieldlinesToBS fls))- | MkNamelessField pos fls <- fields- ]- -- hack: recover the order of prefixed fields- reorder = map snd . sortBy (comparing fst)- trim :: String -> String- trim = dropWhile isSpace . dropWhileEnd isSpace-- availableSince vs def (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'- where- parser' v values- | v >= vs = parser v values- | otherwise = do- let unknownFields = Map.intersection values $ Map.fromSet (const ()) names- for_ (Map.toList unknownFields) $ \(name, fields) ->- for_ fields $ \(MkNamelessField pos _) ->- parseWarning pos PWTUnknownField $- "The field " <> show name <> " is available only since the Cabal specification version " ++ showCabalSpecVersion vs ++ ". This field will be ignored."-- pure def-- availableSinceWarn vs (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'- where- parser' v values- | v >= vs = parser v values- | otherwise = do- let unknownFields = Map.intersection values $ Map.fromSet (const ()) names- for_ (Map.toList unknownFields) $ \(name, fields) ->- for_ fields $ \(MkNamelessField pos _) ->- parseWarning pos PWTUnknownField $- "The field " <> show name <> " is available only since the Cabal specification version " ++ showCabalSpecVersion vs ++ "."-- parser v values--- -- todo we know about this field- deprecatedSince vs msg (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'- where- parser' v values- | v >= vs = do- let deprecatedFields = Map.intersection values $ Map.fromSet (const ()) names- for_ (Map.toList deprecatedFields) $ \(name, fields) ->- for_ fields $ \(MkNamelessField pos _) ->- parseWarning pos PWTDeprecatedField $- "The field " <> show name <> " is deprecated in the Cabal specification version " ++ showCabalSpecVersion vs ++ ". " ++ msg-- parser v values-- | otherwise = parser v values-- removedIn vs msg (ParsecFG names prefixes parser) = ParsecFG names prefixes parser' where- parser' v values- | v >= vs = do- let msg' = if null msg then "" else ' ' : msg- let unknownFields = Map.intersection values $ Map.fromSet (const ()) names- let namePos =- [ (name, pos)- | (name, fields) <- Map.toList unknownFields- , MkNamelessField pos _ <- fields- ]-- let makeMsg name = "The field " <> show name <> " is removed in the Cabal specification version " ++ showCabalSpecVersion vs ++ "." ++ msg'-- case namePos of- -- no fields => proceed (with empty values, to be sure)- [] -> parser v mempty-- -- if there's single field: fail fatally with it- ((name, pos) : rest) -> do- for_ rest $ \(name', pos') -> parseFailure pos' $ makeMsg name'- parseFatalFailure pos $ makeMsg name-- | otherwise = parser v values-- knownField fn = ParsecFG (Set.singleton fn) Set.empty (\_ _ -> pure ())-- hiddenField = id------------------------------------------------------------------------------------ Parsec----------------------------------------------------------------------------------runFieldParser' :: [Position] -> ParsecParser a -> CabalSpecVersion -> FieldLineStream -> ParseResult a-runFieldParser' inputPoss p v str = case P.runParser p' [] "<field>" str of- Right (pok, ws) -> do- traverse_ (\(PWarning t pos w) -> parseWarning (mapPosition pos) t w) ws- pure pok- Left err -> do- let ppos = P.errorPos err- let epos = mapPosition $ Position (P.sourceLine ppos) (P.sourceColumn ppos)-- let msg = P.showErrorMessages- "or" "unknown parse error" "expecting" "unexpected" "end of input"- (P.errorMessages err)- parseFatalFailure epos $ msg ++ "\n"- where- p' = (,) <$ P.spaces <*> unPP p v <* P.spaces <* P.eof <*> P.getState-- -- Positions start from 1:1, not 0:0- mapPosition (Position prow pcol) = go (prow - 1) inputPoss where- go _ [] = zeroPos- go _ [Position row col] = Position row (col + pcol - 1)- go n (Position row col:_) | n <= 0 = Position row (col + pcol - 1)- go n (_:ps) = go (n - 1) ps--runFieldParser :: Position -> ParsecParser a -> CabalSpecVersion -> [FieldLine Position] -> ParseResult a-runFieldParser pp p v ls = runFieldParser' poss p v (fieldLinesToStream ls)- where- poss = map (\(FieldLine pos _) -> pos) ls ++ [pp] -- add "default" position--fieldlinesToBS :: [FieldLine ann] -> BS.ByteString-fieldlinesToBS = BS.intercalate "\n" . map (\(FieldLine _ bs) -> bs)---- Example package with dot lines--- http://hackage.haskell.org/package/copilot-cbmc-0.1/copilot-cbmc.cabal-fieldlinesToFreeText :: [FieldLine ann] -> String-fieldlinesToFreeText [FieldLine _ "."] = "."-fieldlinesToFreeText fls = intercalate "\n" (map go fls)- where- go (FieldLine _ bs)- | s == "." = ""- | otherwise = s- where- s = trim (fromUTF8BS bs)-- trim :: String -> String- trim = dropWhile isSpace . dropWhileEnd isSpace--fieldlinesToFreeText3 :: Position -> [FieldLine Position] -> String-fieldlinesToFreeText3 _ [] = ""-fieldlinesToFreeText3 _ [FieldLine _ bs] = fromUTF8BS bs-fieldlinesToFreeText3 pos (FieldLine pos1 bs1 : fls2@(FieldLine pos2 _ : _))- -- if first line is on the same line with field name:- -- the indentation level is either- -- 1. the indentation of left most line in rest fields- -- 2. the indentation of the first line- -- whichever is leftmost- | positionRow pos == positionRow pos1 = concat- $ fromUTF8BS bs1- : mealy (mk mcol1) pos1 fls2-- -- otherwise, also indent the first line- | otherwise = concat- $ replicate (positionCol pos1 - mcol2) ' '- : fromUTF8BS bs1- : mealy (mk mcol2) pos1 fls2-- where- mcol1 = foldl' (\a b -> min a $ positionCol $ fieldLineAnn b) (min (positionCol pos1) (positionCol pos2)) fls2- mcol2 = foldl' (\a b -> min a $ positionCol $ fieldLineAnn b) (positionCol pos1) fls2-- mk :: Int -> Position -> FieldLine Position -> (Position, String)- mk col p (FieldLine q bs) =- ( q- , replicate newlines '\n'- ++ replicate indent ' '- ++ fromUTF8BS bs- )- where- newlines = positionRow q - positionRow p- indent = positionCol q - col--mealy :: (s -> a -> (s, b)) -> s -> [a] -> [b]-mealy f = go where- go _ [] = []- go s (x : xs) = let ~(s', y) = f s x in y : go s' xs--fieldLinesToStream :: [FieldLine ann] -> FieldLineStream-fieldLinesToStream [] = fieldLineStreamEnd-fieldLinesToStream [FieldLine _ bs] = FLSLast bs-fieldLinesToStream (FieldLine _ bs : fs) = FLSCons bs (fieldLinesToStream fs)
− Distribution/FieldGrammar/Pretty.hs
@@ -1,104 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE MultiParamTypeClasses #-}-module Distribution.FieldGrammar.Pretty (- PrettyFieldGrammar,- prettyFieldGrammar,- ) where--import Distribution.CabalSpecVersion-import Distribution.Compat.Lens-import Distribution.Compat.Newtype-import Distribution.Compat.Prelude-import Distribution.Fields.Field (FieldName)-import Distribution.Fields.Pretty (PrettyField (..))-import Distribution.Pretty (Pretty (..), showFreeText, showFreeTextV3)-import Distribution.Simple.Utils (toUTF8BS)-import Prelude ()-import Text.PrettyPrint (Doc)-import qualified Text.PrettyPrint as PP--import Distribution.FieldGrammar.Class--newtype PrettyFieldGrammar s a = PrettyFG- { fieldGrammarPretty :: CabalSpecVersion -> s -> [PrettyField ()]- }- deriving (Functor)--instance Applicative (PrettyFieldGrammar s) where- pure _ = PrettyFG (\_ _ -> mempty)- PrettyFG f <*> PrettyFG x = PrettyFG (\v s -> f v s <> x v s)---- | We can use 'PrettyFieldGrammar' to pp print the @s@.------ /Note:/ there is not trailing @($+$ text "")@.-prettyFieldGrammar :: CabalSpecVersion -> PrettyFieldGrammar s a -> s -> [PrettyField ()]-prettyFieldGrammar = flip fieldGrammarPretty--instance FieldGrammar Pretty PrettyFieldGrammar where- blurFieldGrammar f (PrettyFG pp) = PrettyFG (\v -> pp v . aview f)-- uniqueFieldAla fn _pack l = PrettyFG $ \_v s ->- ppField fn (pretty (pack' _pack (aview l s)))-- booleanFieldDef fn l def = PrettyFG pp- where- pp _v s- | b == def = mempty- | otherwise = ppField fn (PP.text (show b))- where- b = aview l s-- optionalFieldAla fn _pack l = PrettyFG pp- where- pp v s = case aview l s of- Nothing -> mempty- Just a -> ppField fn (prettyVersioned v (pack' _pack a))-- optionalFieldDefAla fn _pack l def = PrettyFG pp- where- pp v s- | x == def = mempty- | otherwise = ppField fn (prettyVersioned v (pack' _pack x))- where- x = aview l s-- freeTextField fn l = PrettyFG pp where- pp v s = maybe mempty (ppField fn . showFT) (aview l s) where- showFT | v >= CabalSpecV3_0 = showFreeTextV3- | otherwise = showFreeText-- -- it's ok to just show, as showFreeText of empty string is empty.- freeTextFieldDef fn l = PrettyFG pp where- pp v s = ppField fn (showFT (aview l s)) where- showFT | v >= CabalSpecV3_0 = showFreeTextV3- | otherwise = showFreeText-- freeTextFieldDefST = defaultFreeTextFieldDefST-- monoidalFieldAla fn _pack l = PrettyFG pp- where- pp v s = ppField fn (prettyVersioned v (pack' _pack (aview l s)))-- prefixedFields _fnPfx l = PrettyFG (\_ -> pp . aview l)- where- pp xs =- -- always print the field, even its Doc is empty.- -- i.e. don't use ppField- [ PrettyField () (toUTF8BS n) $ PP.vcat $ map PP.text $ lines s- | (n, s) <- xs- -- fnPfx `isPrefixOf` n- ]-- knownField _ = pure ()- deprecatedSince _ _ x = x- -- TODO: as PrettyFieldGrammar isn't aware of cabal-version: we output the field- -- this doesn't affect roundtrip as `removedIn` fields cannot be parsed- -- so invalid documents can be only manually constructed.- removedIn _ _ x = x- availableSince _ _ = id- hiddenField _ = PrettyFG (\_ -> mempty)--ppField :: FieldName -> Doc -> [PrettyField ()]-ppField name fielddoc- | PP.isEmpty fielddoc = []- | otherwise = [ PrettyField () name fielddoc ]
− Distribution/Fields.hs
@@ -1,42 +0,0 @@--- | Utilitiies to work with @.cabal@ like file structure.-module Distribution.Fields (- -- * Types- Field(..),- Name(..),- FieldLine(..),- SectionArg(..),- FieldName,- -- * Grammar and parsing- --- -- See "Distribution.Fields.Parser" for grammar.- readFields,- readFields',- -- ** ParseResult- ParseResult,- runParseResult,- parseString,- parseWarning,- parseWarnings,- parseFailure,- parseFatalFailure,- -- ** Warnings- PWarnType (..),- PWarning (..),- showPWarning,- -- ** Errors- PError (..),- showPError,- -- * Pretty printing- PrettyField (..),- showFields,- -- ** Transformation from Field- genericFromParsecFields,- fromParsecFields,- ) where--import Distribution.Fields.Field-import Distribution.Fields.Parser-import Distribution.Fields.ParseResult-import Distribution.Fields.Pretty-import Distribution.Parsec.Error-import Distribution.Parsec.Warning
− Distribution/Fields/ConfVar.hs
@@ -1,126 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module Distribution.Fields.ConfVar (parseConditionConfVar) where--import Distribution.Compat.CharParsing (char, integral)-import Distribution.Compat.Prelude-import Distribution.Fields.Field (SectionArg (..))-import Distribution.Fields.ParseResult-import Distribution.Parsec (Parsec (..), Position (..), runParsecParser)-import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS)-import Distribution.Types.Condition-import Distribution.Types.ConfVar (ConfVar (..))-import Distribution.Version- (anyVersion, earlierVersion, intersectVersionRanges, laterVersion, majorBoundVersion,- mkVersion, noVersion, orEarlierVersion, orLaterVersion, thisVersion, unionVersionRanges,- withinVersion)-import Prelude ()--import qualified Text.Parsec as P-import qualified Text.Parsec.Error as P---- | Parse @'Condition' 'ConfVar'@ from section arguments provided by parsec--- based outline parser.-parseConditionConfVar :: [SectionArg Position] -> ParseResult (Condition ConfVar)-parseConditionConfVar args =- -- The name of the input file is irrelevant, as we reformat the error message.- case P.runParser (parser <* P.eof) () "<condition>" args of- Right x -> pure x- Left err -> do- -- Mangle the position to the actual one- let ppos = P.errorPos err- let epos = Position (P.sourceLine ppos) (P.sourceColumn ppos)- let msg = P.showErrorMessages- "or" "unknown parse error" "expecting" "unexpected" "end of input"- (P.errorMessages err)- parseFailure epos msg- pure $ Lit True--type Parser = P.Parsec [SectionArg Position] ()--sepByNonEmpty :: Parser a -> Parser sep -> Parser (NonEmpty a)-sepByNonEmpty p sep = (:|) <$> p <*> many (sep *> p)--parser :: Parser (Condition ConfVar)-parser = condOr- where- condOr = sepByNonEmpty condAnd (oper "||") >>= return . foldl1 COr- condAnd = sepByNonEmpty cond (oper "&&") >>= return . foldl1 CAnd- cond = P.choice- [ boolLiteral, parens condOr, notCond, osCond, archCond, flagCond, implCond ]-- notCond = CNot <$ oper "!" <*> cond-- boolLiteral = Lit <$> boolLiteral'- osCond = Var . OS <$ string "os" <*> parens fromParsec- flagCond = Var . PackageFlag <$ string "flag" <*> parens fromParsec- archCond = Var . Arch <$ string "arch" <*> parens fromParsec- implCond = Var <$ string "impl" <*> parens implCond'-- implCond' = Impl- <$> fromParsec- <*> P.option anyVersion versionRange-- version = fromParsec- versionStar = mkVersion <$> fromParsec' versionStar' <* oper "*"- versionStar' = some (integral <* char '.')-- versionRange = expr- where- expr = foldl1 unionVersionRanges <$> sepByNonEmpty term (oper "||")- term = foldl1 intersectVersionRanges <$> sepByNonEmpty factor (oper "&&")-- factor = P.choice- $ parens expr- : parseAnyVersion- : parseNoVersion- : parseWildcardRange- : map parseRangeOp rangeOps-- parseAnyVersion = anyVersion <$ string "-any"- parseNoVersion = noVersion <$ string "-none"-- parseWildcardRange = P.try $ withinVersion <$ oper "==" <*> versionStar-- parseRangeOp (s,f) = P.try (f <$ oper s <*> version)- rangeOps = [ ("<", earlierVersion),- ("<=", orEarlierVersion),- (">", laterVersion),- (">=", orLaterVersion),- ("^>=", majorBoundVersion),- ("==", thisVersion) ]-- -- Number token can have many dots in it: SecArgNum (Position 65 15) "7.6.1"- identBS = tokenPrim $ \t -> case t of- SecArgName _ s -> Just s- _ -> Nothing-- boolLiteral' = tokenPrim $ \t -> case t of- SecArgName _ s- | s == "True" -> Just True- | s == "true" -> Just True- | s == "False" -> Just False- | s == "false" -> Just False- _ -> Nothing-- string s = tokenPrim $ \t -> case t of- SecArgName _ s' | s == s' -> Just ()- _ -> Nothing-- oper o = tokenPrim $ \t -> case t of- SecArgOther _ o' | o == o' -> Just ()- _ -> Nothing-- parens = P.between (oper "(") (oper ")")-- tokenPrim = P.tokenPrim prettySectionArg updatePosition- -- TODO: check where the errors are reported- updatePosition x _ _ = x- prettySectionArg = show-- fromParsec :: Parsec a => Parser a- fromParsec = fromParsec' parsec-- fromParsec' p = do- bs <- identBS- let fls = fieldLineStreamFromBS bs- either (fail . show) pure (runParsecParser p "<fromParsec'>" fls)
− Distribution/Fields/Field.hs
@@ -1,108 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}--- | Cabal-like file AST types: 'Field', 'Section' etc------ These types are parametrized by an annotation.-module Distribution.Fields.Field (- -- * Cabal file- Field (..),- fieldName,- fieldAnn,- fieldUniverse,- FieldLine (..),- fieldLineAnn,- fieldLineBS,- SectionArg (..),- sectionArgAnn,- -- * Name- FieldName,- Name (..),- mkName,- getName,- nameAnn,- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as B-import qualified Data.Char as Char------------------------------------------------------------------------------------ Cabal file------------------------------------------------------------------------------------ | A Cabal-like file consists of a series of fields (@foo: bar@) and sections (@library ...@).-data Field ann- = Field !(Name ann) [FieldLine ann]- | Section !(Name ann) [SectionArg ann] [Field ann]- deriving (Eq, Show, Functor, Foldable, Traversable)---- | Section of field name-fieldName :: Field ann -> Name ann-fieldName (Field n _ ) = n-fieldName (Section n _ _) = n--fieldAnn :: Field ann -> ann-fieldAnn = nameAnn . fieldName---- | All transitive descendants of 'Field', including itself.------ /Note:/ the resulting list is never empty.----fieldUniverse :: Field ann -> [Field ann]-fieldUniverse f@(Section _ _ fs) = f : concatMap fieldUniverse fs-fieldUniverse f@(Field _ _) = [f]---- | A line of text representing the value of a field from a Cabal file.--- A field may contain multiple lines.------ /Invariant:/ 'ByteString' has no newlines.-data FieldLine ann = FieldLine !ann !ByteString- deriving (Eq, Show, Functor, Foldable, Traversable)---- | @since 3.0.0.0-fieldLineAnn :: FieldLine ann -> ann-fieldLineAnn (FieldLine ann _) = ann---- | @since 3.0.0.0-fieldLineBS :: FieldLine ann -> ByteString-fieldLineBS (FieldLine _ bs) = bs---- | Section arguments, e.g. name of the library-data SectionArg ann- = SecArgName !ann !ByteString- -- ^ identifier, or something which looks like number. Also many dot numbers, i.e. "7.6.3"- | SecArgStr !ann !ByteString- -- ^ quoted string- | SecArgOther !ann !ByteString- -- ^ everything else, mm. operators (e.g. in if-section conditionals)- deriving (Eq, Show, Functor, Foldable, Traversable)---- | Extract annotation from 'SectionArg'.-sectionArgAnn :: SectionArg ann -> ann-sectionArgAnn (SecArgName ann _) = ann-sectionArgAnn (SecArgStr ann _) = ann-sectionArgAnn (SecArgOther ann _) = ann------------------------------------------------------------------------------------ Name----------------------------------------------------------------------------------type FieldName = ByteString---- | A field name.------ /Invariant/: 'ByteString' is lower-case ASCII.-data Name ann = Name !ann !FieldName- deriving (Eq, Show, Functor, Foldable, Traversable)--mkName :: ann -> FieldName -> Name ann-mkName ann bs = Name ann (B.map Char.toLower bs)--getName :: Name ann -> FieldName-getName (Name _ bs) = bs--nameAnn :: Name ann -> ann-nameAnn (Name ann _) = ann
− Distribution/Fields/Lexer.hs
@@ -1,496 +0,0 @@-{-# OPTIONS_GHC -fno-warn-unused-binds -fno-warn-missing-signatures #-}-{-# LANGUAGE CPP,MagicHash #-}-{-# LINE 1 "boot/Lexer.x" #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Fields.Lexer--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Lexer for the cabal files.-{-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-}-#ifdef CABAL_PARSEC_DEBUG-{-# LANGUAGE PatternGuards #-}-#endif-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-module Distribution.Fields.Lexer- (ltest, lexToken, Token(..), LToken(..)- ,bol_section, in_section, in_field_layout, in_field_braces- ,mkLexState) where---- [Note: boostrapping parsec parser]------ We manually produce the `Lexer.hs` file from `boot/Lexer.x` (make lexer)--- because boostrapping cabal-install would be otherwise tricky.--- Alex is (atm) tricky package to build, cabal-install has some magic--- to move bundled generated files in place, so rather we don't depend--- on it before we can build it ourselves.--- Therefore there is one thing less to worry in bootstrap.sh, which is a win.------ See also https://github.com/haskell/cabal/issues/4633-----import Prelude ()-import qualified Prelude as Prelude-import Distribution.Compat.Prelude--import Distribution.Fields.LexerMonad-import Distribution.Parsec.Position (Position (..), incPos, retPos)-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as B.Char8-import qualified Data.Word as Word--#ifdef CABAL_PARSEC_DEBUG-import Debug.Trace-import qualified Data.Vector as V-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Data.Text.Encoding.Error as T-#endif--#if __GLASGOW_HASKELL__ >= 603-#include "ghcconfig.h"-#elif defined(__GLASGOW_HASKELL__)-#include "config.h"-#endif-#if __GLASGOW_HASKELL__ >= 503-import Data.Array-#else-import Array-#endif-#if __GLASGOW_HASKELL__ >= 503-import Data.Array.Base (unsafeAt)-import GHC.Exts-#else-import GlaExts-#endif-alex_tab_size :: Int-alex_tab_size = 8-alex_base :: AlexAddr-alex_base = AlexA#- "\x12\xff\xff\xff\xf9\xff\xff\xff\xfb\xff\xff\xff\x01\x00\x00\x00\x2f\x00\x00\x00\x50\x00\x00\x00\xd0\x00\x00\x00\x48\xff\xff\xff\xdc\xff\xff\xff\x51\xff\xff\xff\x6d\xff\xff\xff\x6f\xff\xff\xff\x50\x01\x00\x00\x74\x01\x00\x00\x70\xff\xff\xff\x68\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\xa3\x01\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6a\x00\x00\x00\xd1\x01\x00\x00\xfb\x01\x00\x00\x7b\x02\x00\x00\xfb\x02\x00\x00\x00\x00\x00\x00\x7b\x03\x00\x00\x7d\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x6d\x00\x00\x00\x6b\x00\x00\x00\xfc\x03\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x6f\x00\x00\x00\x1c\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00"#--alex_table :: AlexAddr-alex_table = AlexA#- "\x00\x00\x09\x00\x0f\x00\x11\x00\x02\x00\x11\x00\x12\x00\x00\x00\x12\x00\x13\x00\x03\x00\x11\x00\x07\x00\x10\x00\x12\x00\x25\x00\x14\x00\x11\x00\x10\x00\x11\x00\x14\x00\x11\x00\x12\x00\x23\x00\x12\x00\x0f\x00\x28\x00\x02\x00\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x08\x00\x10\x00\x00\x00\x14\x00\x00\x00\x00\x00\x08\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2a\x00\x2e\x00\xff\xff\xff\xff\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x26\x00\x28\x00\xff\xff\xff\xff\x29\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x26\x00\x0f\x00\x11\x00\x17\x00\x26\x00\x12\x00\x25\x00\x11\x00\x2a\x00\x00\x00\x12\x00\x00\x00\x15\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x17\x00\x26\x00\x00\x00\x25\x00\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2c\x00\x00\x00\x2d\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0e\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x17\x00\x23\x00\xff\xff\xff\xff\x24\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x17\x00\x1e\x00\x0d\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x1f\x00\x1f\x00\x1e\x00\x1e\x00\x1e\x00\x19\x00\x1a\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x1f\x00\x1e\x00\x1f\x00\x1e\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x21\x00\x1e\x00\x22\x00\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x1d\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1e\x00\xff\xff\x1e\x00\x1e\x00\x1e\x00\x1e\x00\xff\xff\xff\xff\xff\xff\x1e\x00\x1e\x00\x1e\x00\x18\x00\x1a\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1e\x00\xff\xff\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\xff\xff\xff\xff\x1e\x00\x1e\x00\x1e\x00\x1a\x00\x1a\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x1c\x00\x1e\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\xff\xff\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#--alex_check :: AlexAddr-alex_check = AlexA#- "\xff\xff\xef\x00\x09\x00\x0a\x00\x09\x00\x0a\x00\x0d\x00\xbf\x00\x0d\x00\x2d\x00\x09\x00\x0a\x00\xbb\x00\xa0\x00\x0d\x00\xa0\x00\xa0\x00\x0a\x00\x09\x00\x0a\x00\x09\x00\x0a\x00\x0d\x00\x0a\x00\x0d\x00\x20\x00\x0a\x00\x20\x00\x0a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\x2d\x00\x20\x00\xff\xff\x20\x00\xff\xff\xff\xff\x2d\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x09\x00\x0a\x00\x09\x00\x09\x00\x0d\x00\x09\x00\x0a\x00\x09\x00\xff\xff\x0d\x00\xff\xff\x7b\x00\xff\xff\x7d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x20\x00\x20\x00\xff\xff\x20\x00\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\xff\xff\x7d\x00\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\xff\xff\xc2\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\xff\xff\xc2\x00\xff\xff\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xc2\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x22\x00\xff\xff\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x22\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x5c\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x5c\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\xff\xff\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x7f\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\xff\xff\xff\xff\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x22\x00\x21\x00\xff\xff\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\xff\xff\xff\xff\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5c\x00\xff\xff\x5c\x00\xff\xff\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7c\x00\x7f\x00\x7e\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\xff\xff\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\xff\xff\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\xff\xff\x7d\x00\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#--alex_deflt :: AlexAddr-alex_deflt = AlexA#- "\xff\xff\xff\xff\xff\xff\xff\xff\x2b\x00\x27\x00\x1b\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x13\x00\xff\xff\xff\xff\xff\xff\xff\xff\x18\x00\x1b\x00\x1b\x00\x1b\x00\xff\xff\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\x2b\x00\xff\xff\xff\xff\xff\xff\xff\xff"#--alex_accept = listArray (0 :: Int, 47)- [ AlexAcc 29- , AlexAcc 28- , AlexAcc 27- , AlexAcc 26- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAccNone- , AlexAcc 25- , AlexAcc 24- , AlexAccSkip- , AlexAcc 23- , AlexAcc 22- , AlexAcc 21- , AlexAccSkip- , AlexAccSkip- , AlexAcc 20- , AlexAcc 19- , AlexAcc 18- , AlexAcc 17- , AlexAcc 16- , AlexAcc 15- , AlexAcc 14- , AlexAcc 13- , AlexAcc 12- , AlexAcc 11- , AlexAcc 10- , AlexAcc 9- , AlexAcc 8- , AlexAccSkip- , AlexAcc 7- , AlexAcc 6- , AlexAcc 5- , AlexAccSkip- , AlexAcc 4- , AlexAcc 3- , AlexAcc 2- , AlexAcc 1- , AlexAcc 0- ]--alex_actions = array (0 :: Int, 30)- [ (29,alex_action_0)- , (28,alex_action_20)- , (27,alex_action_16)- , (26,alex_action_3)- , (25,alex_action_1)- , (24,alex_action_1)- , (23,alex_action_3)- , (22,alex_action_4)- , (21,alex_action_5)- , (20,alex_action_8)- , (19,alex_action_8)- , (18,alex_action_8)- , (17,alex_action_9)- , (16,alex_action_9)- , (15,alex_action_10)- , (14,alex_action_11)- , (13,alex_action_12)- , (12,alex_action_13)- , (11,alex_action_14)- , (10,alex_action_15)- , (9,alex_action_15)- , (8,alex_action_16)- , (7,alex_action_18)- , (6,alex_action_19)- , (5,alex_action_19)- , (4,alex_action_22)- , (3,alex_action_23)- , (2,alex_action_24)- , (1,alex_action_25)- , (0,alex_action_25)- ]--{-# LINE 151 "boot/Lexer.x" #-}---- | Tokens of outer cabal file structure. Field values are treated opaquely.-data Token = TokSym !ByteString -- ^ Haskell-like identifier, number or operator- | TokStr !ByteString -- ^ String in quotes- | TokOther !ByteString -- ^ Operators and parens- | Indent !Int -- ^ Indentation token- | TokFieldLine !ByteString -- ^ Lines after @:@- | Colon- | OpenBrace- | CloseBrace- | EOF- | LexicalError InputStream --TODO: add separate string lexical error- deriving Show--data LToken = L !Position !Token- deriving Show--toki :: (ByteString -> Token) -> Position -> Int -> ByteString -> Lex LToken-toki t pos len input = return $! L pos (t (B.take len input))--tok :: Token -> Position -> Int -> ByteString -> Lex LToken-tok t pos _len _input = return $! L pos t--checkLeadingWhitespace :: Int -> ByteString -> Lex Int-checkLeadingWhitespace len bs- | B.any (== 9) (B.take len bs) = do- addWarning LexWarningTab- checkWhitespace len bs- | otherwise = checkWhitespace len bs--checkWhitespace :: Int -> ByteString -> Lex Int-checkWhitespace len bs- | B.any (== 194) (B.take len bs) = do- addWarning LexWarningNBSP- return $ len - B.count 194 (B.take len bs)- | otherwise = return len---- -------------------------------------------------------------------------------- The input type--type AlexInput = InputStream--alexInputPrevChar :: AlexInput -> Char-alexInputPrevChar _ = error "alexInputPrevChar not used"--alexGetByte :: AlexInput -> Maybe (Word.Word8,AlexInput)-alexGetByte = B.uncons--lexicalError :: Position -> InputStream -> Lex LToken-lexicalError pos inp = do- setInput B.empty- return $! L pos (LexicalError inp)--lexToken :: Lex LToken-lexToken = do- pos <- getPos- inp <- getInput- st <- getStartCode- case alexScan inp st of- AlexEOF -> return (L pos EOF)- AlexError inp' ->- let !len_bytes = B.length inp - B.length inp' in- --FIXME: we want len_chars here really- -- need to decode utf8 up to this point- lexicalError (incPos len_bytes pos) inp'- AlexSkip inp' len_chars -> do- checkPosition pos inp inp' len_chars- adjustPos (incPos len_chars)- setInput inp'- lexToken- AlexToken inp' len_chars action -> do- checkPosition pos inp inp' len_chars- adjustPos (incPos len_chars)- setInput inp'- let !len_bytes = B.length inp - B.length inp'- t <- action pos len_bytes inp- --traceShow t $ return tok- return t--checkPosition :: Position -> ByteString -> ByteString -> Int -> Lex ()-#ifdef CABAL_PARSEC_DEBUG-checkPosition pos@(Position lineno colno) inp inp' len_chars = do- text_lines <- getDbgText- let len_bytes = B.length inp - B.length inp'- pos_txt | lineno-1 < V.length text_lines = T.take len_chars (T.drop (colno-1) (text_lines V.! (lineno-1)))- | otherwise = T.empty- real_txt = B.take len_bytes inp- when (pos_txt /= T.decodeUtf8 real_txt) $- traceShow (pos, pos_txt, T.decodeUtf8 real_txt) $- traceShow (take 3 (V.toList text_lines)) $ return ()- where- getDbgText = Lex $ \s@LexState{ dbgText = txt } -> LexResult s txt-#else-checkPosition _ _ _ _ = return ()-#endif--lexAll :: Lex [LToken]-lexAll = do- t <- lexToken- case t of- L _ EOF -> return [t]- _ -> do ts <- lexAll- return (t : ts)--ltest :: Int -> String -> Prelude.IO ()-ltest code s =- let (ws, xs) = execLexer (setStartCode code >> lexAll) (B.Char8.pack s)- in traverse_ print ws >> traverse_ print xs--mkLexState :: ByteString -> LexState-mkLexState input = LexState- { curPos = Position 1 1- , curInput = input- , curCode = 0- , warnings = []-#ifdef CABAL_PARSEC_DEBUG- , dbgText = V.fromList . lines' . T.decodeUtf8With T.lenientDecode $ input-#endif- }--#ifdef CABAL_PARSEC_DEBUG-lines' :: T.Text -> [T.Text]-lines' s1- | T.null s1 = []- | otherwise = case T.break (\c -> c == '\r' || c == '\n') s1 of- (l, s2) | Just (c,s3) <- T.uncons s2- -> case T.uncons s3 of- Just ('\n', s4) | c == '\r' -> l `T.snoc` '\r' `T.snoc` '\n' : lines' s4- _ -> l `T.snoc` c : lines' s3-- | otherwise- -> [l]-#endif--bol_field_braces,bol_field_layout,bol_section,in_field_braces,in_field_layout,in_section :: Int-bol_field_braces = 1-bol_field_layout = 2-bol_section = 3-in_field_braces = 4-in_field_layout = 5-in_section = 6-alex_action_0 = \_ len _ -> do- when (len /= 0) $ addWarning LexWarningBOM- setStartCode bol_section- lexToken- -alex_action_1 = \_pos len inp -> checkWhitespace len inp >> adjustPos retPos >> lexToken -alex_action_3 = \pos len inp -> checkLeadingWhitespace len inp >>- if B.length inp == len- then return (L pos EOF)- else setStartCode in_section- >> return (L pos (Indent len)) -alex_action_4 = tok OpenBrace -alex_action_5 = tok CloseBrace -alex_action_8 = toki TokSym -alex_action_9 = \pos len inp -> return $! L pos (TokStr (B.take (len - 2) (B.tail inp))) -alex_action_10 = toki TokOther -alex_action_11 = toki TokOther -alex_action_12 = tok Colon -alex_action_13 = tok OpenBrace -alex_action_14 = tok CloseBrace -alex_action_15 = \_ _ _ -> adjustPos retPos >> setStartCode bol_section >> lexToken -alex_action_16 = \pos len inp -> checkLeadingWhitespace len inp >>= \len' ->- if B.length inp == len- then return (L pos EOF)- else setStartCode in_field_layout- >> return (L pos (Indent len')) -alex_action_18 = toki TokFieldLine -alex_action_19 = \_ _ _ -> adjustPos retPos >> setStartCode bol_field_layout >> lexToken -alex_action_20 = \_ _ _ -> setStartCode in_field_braces >> lexToken -alex_action_22 = toki TokFieldLine -alex_action_23 = tok OpenBrace -alex_action_24 = tok CloseBrace -alex_action_25 = \_ _ _ -> adjustPos retPos >> setStartCode bol_field_braces >> lexToken -{-# LINE 1 "templates/GenericTemplate.hs" #-}--- -------------------------------------------------------------------------------- ALEX TEMPLATE------ This code is in the PUBLIC DOMAIN; you may copy it freely and use--- it for any purpose whatsoever.---- -------------------------------------------------------------------------------- INTERNALS and main scanner engine---- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.-#if __GLASGOW_HASKELL__ > 706-#define GTE(n,m) (tagToEnum# (n >=# m))-#define EQ(n,m) (tagToEnum# (n ==# m))-#else-#define GTE(n,m) (n >=# m)-#define EQ(n,m) (n ==# m)-#endif--data AlexAddr = AlexA# Addr#--- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.-#if __GLASGOW_HASKELL__ < 503-uncheckedShiftL# = shiftL#-#endif--{-# INLINE alexIndexInt16OffAddr #-}-alexIndexInt16OffAddr :: AlexAddr -> Int# -> Int#-alexIndexInt16OffAddr (AlexA# arr) off =-#ifdef WORDS_BIGENDIAN- narrow16Int# i- where- i = word2Int# ((high `uncheckedShiftL#` 8#) `or#` low)- high = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))- low = int2Word# (ord# (indexCharOffAddr# arr off'))- off' = off *# 2#-#else-#if __GLASGOW_HASKELL__ >= 901- int16ToInt#-#endif- (indexInt16OffAddr# arr off)-#endif--{-# INLINE alexIndexInt32OffAddr #-}-alexIndexInt32OffAddr :: AlexAddr -> Int# -> Int#-alexIndexInt32OffAddr (AlexA# arr) off =-#ifdef WORDS_BIGENDIAN- narrow32Int# i- where- i = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#`- (b2 `uncheckedShiftL#` 16#) `or#`- (b1 `uncheckedShiftL#` 8#) `or#` b0)- b3 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#)))- b2 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#)))- b1 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))- b0 = int2Word# (ord# (indexCharOffAddr# arr off'))- off' = off *# 4#-#else-#if __GLASGOW_HASKELL__ >= 901- int32ToInt#-#endif- (indexInt32OffAddr# arr off)-#endif--#if __GLASGOW_HASKELL__ < 503-quickIndex arr i = arr ! i-#else--- GHC >= 503, unsafeAt is available from Data.Array.Base.-quickIndex = unsafeAt-#endif---- -------------------------------------------------------------------------------- Main lexing routines--data AlexReturn a- = AlexEOF- | AlexError !AlexInput- | AlexSkip !AlexInput !Int- | AlexToken !AlexInput !Int a---- alexScan :: AlexInput -> StartCode -> AlexReturn a-alexScan input__ (I# (sc))- = alexScanUser undefined input__ (I# (sc))--alexScanUser user__ input__ (I# (sc))- = case alex_scan_tkn user__ input__ 0# input__ sc AlexNone of- (AlexNone, input__') ->- case alexGetByte input__ of- Nothing ->-- AlexEOF- Just _ ->-- AlexError input__'-- (AlexLastSkip input__'' len, _) ->-- AlexSkip input__'' len-- (AlexLastAcc k input__''' len, _) ->-- AlexToken input__''' len (alex_actions ! k)---- Push the input through the DFA, remembering the most recent accepting--- state it encountered.--alex_scan_tkn user__ orig_input len input__ s last_acc =- input__ `seq` -- strict in the input- let- new_acc = (check_accs (alex_accept `quickIndex` (I# (s))))- in- new_acc `seq`- case alexGetByte input__ of- Nothing -> (new_acc, input__)- Just (c, new_input) ->-- case fromIntegral c of { (I# (ord_c)) ->- let- base = alexIndexInt32OffAddr alex_base s- offset = (base +# ord_c)- check = alexIndexInt16OffAddr alex_check offset-- new_s = if GTE(offset,0#) && EQ(check,ord_c)- then alexIndexInt16OffAddr alex_table offset- else alexIndexInt16OffAddr alex_deflt s- in- case new_s of- -1# -> (new_acc, input__)- -- on an error, we want to keep the input *before* the- -- character that failed, not after.- _ -> alex_scan_tkn user__ orig_input (if c < 0x80 || c >= 0xC0 then (len +# 1#) else len)- -- note that the length is increased ONLY if this is the 1st byte in a char encoding)- new_input new_s new_acc- }- where- check_accs (AlexAccNone) = last_acc- check_accs (AlexAcc a ) = AlexLastAcc a input__ (I# (len))- check_accs (AlexAccSkip) = AlexLastSkip input__ (I# (len))--data AlexLastAcc- = AlexNone- | AlexLastAcc !Int !AlexInput !Int- | AlexLastSkip !AlexInput !Int--data AlexAcc user- = AlexAccNone- | AlexAcc Int- | AlexAccSkip-
− Distribution/Fields/LexerMonad.hs
@@ -1,155 +0,0 @@-{-# LANGUAGE CPP #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Fields.LexerMonad--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable-module Distribution.Fields.LexerMonad (- InputStream,- LexState(..),- LexResult(..),-- Lex(..),- execLexer,-- getPos,- setPos,- adjustPos,-- getInput,- setInput,-- getStartCode,- setStartCode,-- LexWarning(..),- LexWarningType(..),- addWarning,- toPWarnings,-- ) where--import qualified Data.ByteString as B-import qualified Data.List.NonEmpty as NE-import Distribution.Compat.Prelude-import Distribution.Parsec.Position (Position (..), showPos)-import Distribution.Parsec.Warning (PWarnType (..), PWarning (..))-import Prelude ()--import qualified Data.Map.Strict as Map--#ifdef CABAL_PARSEC_DEBUG--- testing only:-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Data.Vector as V-#endif---- simple state monad-newtype Lex a = Lex { unLex :: LexState -> LexResult a }--instance Functor Lex where- fmap = liftM--instance Applicative Lex where- pure = returnLex- (<*>) = ap--instance Monad Lex where- return = pure- (>>=) = thenLex--data LexResult a = LexResult {-# UNPACK #-} !LexState a--data LexWarningType- = LexWarningNBSP -- ^ Encountered non breaking space- | LexWarningBOM -- ^ BOM at the start of the cabal file- | LexWarningTab -- ^ Leading tags- deriving (Eq, Ord, Show)--data LexWarning = LexWarning !LexWarningType- {-# UNPACK #-} !Position- deriving (Show)--toPWarnings :: [LexWarning] -> [PWarning]-toPWarnings- = map (uncurry toWarning)- . Map.toList- . Map.fromListWith (<>)- . map (\(LexWarning t p) -> (t, pure p))- where- toWarning LexWarningBOM poss =- PWarning PWTLexBOM (NE.head poss) "Byte-order mark found at the beginning of the file"- toWarning LexWarningNBSP poss =- PWarning PWTLexNBSP (NE.head poss) $ "Non breaking spaces at " ++ intercalate ", " (NE.toList $ fmap showPos poss)- toWarning LexWarningTab poss =- PWarning PWTLexTab (NE.head poss) $ "Tabs used as indentation at " ++ intercalate ", " (NE.toList $ fmap showPos poss)--data LexState = LexState {- curPos :: {-# UNPACK #-} !Position, -- ^ position at current input location- curInput :: {-# UNPACK #-} !InputStream, -- ^ the current input- curCode :: {-# UNPACK #-} !StartCode, -- ^ lexer code- warnings :: [LexWarning]-#ifdef CABAL_PARSEC_DEBUG- , dbgText :: V.Vector T.Text -- ^ input lines, to print pretty debug info-#endif- } --TODO: check if we should cache the first token- -- since it looks like parsec's uncons can be called many times on the same input--type StartCode = Int -- ^ An @alex@ lexer start code-type InputStream = B.ByteString------ | Execute the given lexer on the supplied input stream.-execLexer :: Lex a -> InputStream -> ([LexWarning], a)-execLexer (Lex lexer) input =- case lexer initialState of- LexResult LexState{ warnings = ws } result -> (ws, result)- where- initialState = LexState- -- TODO: add 'startPosition'- { curPos = Position 1 1- , curInput = input- , curCode = 0- , warnings = []-#ifdef CABAL_PARSEC_DEBUG- , dbgText = V.fromList . T.lines . T.decodeUtf8 $ input-#endif- }--{-# INLINE returnLex #-}-returnLex :: a -> Lex a-returnLex a = Lex $ \s -> LexResult s a--{-# INLINE thenLex #-}-thenLex :: Lex a -> (a -> Lex b) -> Lex b-(Lex m) `thenLex` k = Lex $ \s -> case m s of LexResult s' a -> (unLex (k a)) s'--setPos :: Position -> Lex ()-setPos pos = Lex $ \s -> LexResult s{ curPos = pos } ()--getPos :: Lex Position-getPos = Lex $ \s@LexState{ curPos = pos } -> LexResult s pos--adjustPos :: (Position -> Position) -> Lex ()-adjustPos f = Lex $ \s@LexState{ curPos = pos } -> LexResult s{ curPos = f pos } ()--getInput :: Lex InputStream-getInput = Lex $ \s@LexState{ curInput = i } -> LexResult s i--setInput :: InputStream -> Lex ()-setInput i = Lex $ \s -> LexResult s{ curInput = i } ()--getStartCode :: Lex Int-getStartCode = Lex $ \s@LexState{ curCode = c } -> LexResult s c--setStartCode :: Int -> Lex ()-setStartCode c = Lex $ \s -> LexResult s{ curCode = c } ()---- | Add warning at the current position-addWarning :: LexWarningType -> Lex ()-addWarning wt = Lex $ \s@LexState{ curPos = pos, warnings = ws } ->- LexResult s{ warnings = LexWarning wt pos : ws } ()
− Distribution/Fields/ParseResult.hs
@@ -1,196 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--- | A parse result type for parsers from AST to Haskell types.-module Distribution.Fields.ParseResult (- ParseResult,- runParseResult,- recoverWith,- parseWarning,- parseWarnings,- parseFailure,- parseFatalFailure,- parseFatalFailure',- getCabalSpecVersion,- setCabalSpecVersion,- readAndParseFile,- parseString,- withoutWarnings,- ) where--import qualified Data.ByteString.Char8 as BS-import Distribution.Compat.Prelude-import Distribution.Parsec.Error (PError (..), showPError)-import Distribution.Parsec.Position (Position (..), zeroPos)-import Distribution.Parsec.Warning (PWarnType (..), PWarning (..), showPWarning)-import Distribution.Simple.Utils (die', warn)-import Distribution.Verbosity (Verbosity)-import Distribution.Version (Version)-import Prelude ()-import System.Directory (doesFileExist)--#if MIN_VERSION_base(4,10,0)-import Control.Applicative (Applicative (..))-#endif---- | A monad with failure and accumulating errors and warnings.-newtype ParseResult a = PR- { unPR- :: forall r. PRState- -> (PRState -> r) -- failure, but we were able to recover a new-style spec-version declaration- -> (PRState -> a -> r) -- success- -> r- }---- Note: we have version here, as we could get any version.-data PRState = PRState ![PWarning] ![PError] !(Maybe Version)--emptyPRState :: PRState-emptyPRState = PRState [] [] Nothing---- | Forget 'ParseResult's warnings.------ @since 3.4.0.0-withoutWarnings :: ParseResult a -> ParseResult a-withoutWarnings m = PR $ \s failure success ->- unPR m s failure $ \ !s1 -> success (s1 `withWarningsOf` s)- where- withWarningsOf (PRState _ e v) (PRState w _ _) = PRState w e v---- | Destruct a 'ParseResult' into the emitted warnings and either--- a successful value or--- list of errors and possibly recovered a spec-version declaration.-runParseResult :: ParseResult a -> ([PWarning], Either (Maybe Version, NonEmpty PError) a)-runParseResult pr = unPR pr emptyPRState failure success- where- failure (PRState warns [] v) = (warns, Left (v, PError zeroPos "panic" :| []))- failure (PRState warns (err:errs) v) = (warns, Left (v, err :| errs)) where- success (PRState warns [] _) x = (warns, Right x)- -- If there are any errors, don't return the result- success (PRState warns (err:errs) v) _ = (warns, Left (v, err :| errs))--instance Functor ParseResult where- fmap f (PR pr) = PR $ \ !s failure success ->- pr s failure $ \ !s' a ->- success s' (f a)- {-# INLINE fmap #-}--instance Applicative ParseResult where- pure x = PR $ \ !s _ success -> success s x- {-# INLINE pure #-}-- f <*> x = PR $ \ !s0 failure success ->- unPR f s0 failure $ \ !s1 f' ->- unPR x s1 failure $ \ !s2 x' ->- success s2 (f' x')- {-# INLINE (<*>) #-}-- x *> y = PR $ \ !s0 failure success ->- unPR x s0 failure $ \ !s1 _ ->- unPR y s1 failure success- {-# INLINE (*>) #-}-- x <* y = PR $ \ !s0 failure success ->- unPR x s0 failure $ \ !s1 x' ->- unPR y s1 failure $ \ !s2 _ ->- success s2 x'- {-# INLINE (<*) #-}--#if MIN_VERSION_base(4,10,0)- liftA2 f x y = PR $ \ !s0 failure success ->- unPR x s0 failure $ \ !s1 x' ->- unPR y s1 failure $ \ !s2 y' ->- success s2 (f x' y')- {-# INLINE liftA2 #-}-#endif--instance Monad ParseResult where- return = pure- (>>) = (*>)-- m >>= k = PR $ \ !s failure success ->- unPR m s failure $ \ !s' a ->- unPR (k a) s' failure success- {-# INLINE (>>=) #-}---- | "Recover" the parse result, so we can proceed parsing.--- 'runParseResult' will still result in 'Nothing', if there are recorded errors.-recoverWith :: ParseResult a -> a -> ParseResult a-recoverWith (PR pr) x = PR $ \ !s _failure success ->- pr s (\ !s' -> success s' x) success---- | Set cabal spec version.-setCabalSpecVersion :: Maybe Version -> ParseResult ()-setCabalSpecVersion v = PR $ \(PRState warns errs _) _failure success ->- success (PRState warns errs v) ()---- | Get cabal spec version.-getCabalSpecVersion :: ParseResult (Maybe Version)-getCabalSpecVersion = PR $ \s@(PRState _ _ v) _failure success ->- success s v---- | Add a warning. This doesn't fail the parsing process.-parseWarning :: Position -> PWarnType -> String -> ParseResult ()-parseWarning pos t msg = PR $ \(PRState warns errs v) _failure success ->- success (PRState (PWarning t pos msg : warns) errs v) ()---- | Add multiple warnings at once.-parseWarnings :: [PWarning] -> ParseResult ()-parseWarnings newWarns = PR $ \(PRState warns errs v) _failure success ->- success (PRState (newWarns ++ warns) errs v) ()---- | Add an error, but not fail the parser yet.------ For fatal failure use 'parseFatalFailure'-parseFailure :: Position -> String -> ParseResult ()-parseFailure pos msg = PR $ \(PRState warns errs v) _failure success ->- success (PRState warns (PError pos msg : errs) v) ()---- | Add an fatal error.-parseFatalFailure :: Position -> String -> ParseResult a-parseFatalFailure pos msg = PR $ \(PRState warns errs v) failure _success ->- failure (PRState warns (PError pos msg : errs) v)---- | A 'mzero'.-parseFatalFailure' :: ParseResult a-parseFatalFailure' = PR pr- where- pr (PRState warns [] v) failure _success = failure (PRState warns [err] v)- pr s failure _success = failure s-- err = PError zeroPos "Unknown fatal error"---- | Helper combinator to do parsing plumbing for files.------ Given a parser and a filename, return the parse of the file,--- after checking if the file exists.------ Argument order is chosen to encourage partial application.-readAndParseFile- :: (BS.ByteString -> ParseResult a) -- ^ File contents to final value parser- -> Verbosity -- ^ Verbosity level- -> FilePath -- ^ File to read- -> IO a-readAndParseFile parser verbosity fpath = do- exists <- doesFileExist fpath- unless exists $- die' verbosity $- "Error Parsing: file \"" ++ fpath ++ "\" doesn't exist. Cannot continue."- bs <- BS.readFile fpath- parseString parser verbosity fpath bs--parseString- :: (BS.ByteString -> ParseResult a) -- ^ File contents to final value parser- -> Verbosity -- ^ Verbosity level- -> String -- ^ File name- -> BS.ByteString- -> IO a-parseString parser verbosity name bs = do- let (warnings, result) = runParseResult (parser bs)- traverse_ (warn verbosity . showPWarning name) warnings- case result of- Right x -> return x- Left (_, errors) -> do- traverse_ (warn verbosity . showPError name) errors- die' verbosity $ "Failed parsing \"" ++ name ++ "\"."
− Distribution/Fields/Parser.hs
@@ -1,377 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternGuards #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Fields.Parser--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable-module Distribution.Fields.Parser (- -- * Types- Field(..),- Name(..),- FieldLine(..),- SectionArg(..),- -- * Grammar and parsing- -- $grammar- readFields,- readFields',-#ifdef CABAL_PARSEC_DEBUG- -- * Internal- parseFile,- parseStr,- parseBS,-#endif- ) where--import qualified Data.ByteString.Char8 as B8-import Data.Functor.Identity-import Distribution.Compat.Prelude-import Distribution.Fields.Field-import Distribution.Fields.Lexer-import Distribution.Fields.LexerMonad- (LexResult (..), LexState (..), LexWarning (..), unLex)-import Distribution.Parsec.Position (Position (..))-import Prelude ()-import Text.Parsec.Combinator hiding (eof, notFollowedBy)-import Text.Parsec.Error-import Text.Parsec.Pos-import Text.Parsec.Prim hiding (many, (<|>))--#ifdef CABAL_PARSEC_DEBUG-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Data.Text.Encoding.Error as T-#endif---- | The 'LexState'' (with a prime) is an instance of parsec's 'Stream'--- wrapped around lexer's 'LexState' (without a prime)-data LexState' = LexState' !LexState (LToken, LexState')--mkLexState' :: LexState -> LexState'-mkLexState' st = LexState' st- (case unLex lexToken st of LexResult st' tok -> (tok, mkLexState' st'))--type Parser a = ParsecT LexState' () Identity a--instance Stream LexState' Identity LToken where- uncons (LexState' _ (tok, st')) =- case tok of- L _ EOF -> return Nothing- _ -> return (Just (tok, st'))---- | Get lexer warnings accumulated so far-getLexerWarnings :: Parser [LexWarning]-getLexerWarnings = do- LexState' (LexState { warnings = ws }) _ <- getInput- return ws---- | Set Alex code i.e. the mode "state" lexer is in.-setLexerMode :: Int -> Parser ()-setLexerMode code = do- LexState' ls _ <- getInput- setInput $! mkLexState' ls { curCode = code }--getToken :: (Token -> Maybe a) -> Parser a-getToken getTok = getTokenWithPos (\(L _ t) -> getTok t)--getTokenWithPos :: (LToken -> Maybe a) -> Parser a-getTokenWithPos getTok = tokenPrim (\(L _ t) -> describeToken t) updatePos getTok- where- updatePos :: SourcePos -> LToken -> LexState' -> SourcePos- updatePos pos (L (Position col line) _) _ = newPos (sourceName pos) col line--describeToken :: Token -> String-describeToken t = case t of- TokSym s -> "symbol " ++ show s- TokStr s -> "string " ++ show s- TokOther s -> "operator " ++ show s- Indent _ -> "new line"- TokFieldLine _ -> "field content"- Colon -> "\":\""- OpenBrace -> "\"{\""- CloseBrace -> "\"}\""--- SemiColon -> "\";\""- EOF -> "end of file"- LexicalError is -> "character in input " ++ show (B8.head is)--tokSym :: Parser (Name Position)-tokSym', tokStr, tokOther :: Parser (SectionArg Position)-tokIndent :: Parser Int-tokColon, tokOpenBrace, tokCloseBrace :: Parser ()-tokFieldLine :: Parser (FieldLine Position)--tokSym = getTokenWithPos $ \t -> case t of L pos (TokSym x) -> Just (mkName pos x); _ -> Nothing-tokSym' = getTokenWithPos $ \t -> case t of L pos (TokSym x) -> Just (SecArgName pos x); _ -> Nothing-tokStr = getTokenWithPos $ \t -> case t of L pos (TokStr x) -> Just (SecArgStr pos x); _ -> Nothing-tokOther = getTokenWithPos $ \t -> case t of L pos (TokOther x) -> Just (SecArgOther pos x); _ -> Nothing-tokIndent = getToken $ \t -> case t of Indent x -> Just x; _ -> Nothing-tokColon = getToken $ \t -> case t of Colon -> Just (); _ -> Nothing-tokOpenBrace = getToken $ \t -> case t of OpenBrace -> Just (); _ -> Nothing-tokCloseBrace = getToken $ \t -> case t of CloseBrace -> Just (); _ -> Nothing-tokFieldLine = getTokenWithPos $ \t -> case t of L pos (TokFieldLine s) -> Just (FieldLine pos s); _ -> Nothing--colon, openBrace, closeBrace :: Parser ()--sectionArg :: Parser (SectionArg Position)-sectionArg = tokSym' <|> tokStr <|> tokOther <?> "section parameter"--fieldSecName :: Parser (Name Position)-fieldSecName = tokSym <?> "field or section name"--colon = tokColon <?> "\":\""-openBrace = tokOpenBrace <?> "\"{\""-closeBrace = tokCloseBrace <?> "\"}\""--fieldContent :: Parser (FieldLine Position)-fieldContent = tokFieldLine <?> "field contents"--newtype IndentLevel = IndentLevel Int--zeroIndentLevel :: IndentLevel-zeroIndentLevel = IndentLevel 0--incIndentLevel :: IndentLevel -> IndentLevel-incIndentLevel (IndentLevel i) = IndentLevel (succ i)--indentOfAtLeast :: IndentLevel -> Parser IndentLevel-indentOfAtLeast (IndentLevel i) = try $ do- j <- tokIndent- guard (j >= i) <?> "indentation of at least " ++ show i- return (IndentLevel j)---newtype LexerMode = LexerMode Int--inLexerMode :: LexerMode -> Parser p -> Parser p-inLexerMode (LexerMode mode) p =- do setLexerMode mode; x <- p; setLexerMode in_section; return x----------------------------- Cabal file grammar------- $grammar------ @--- CabalStyleFile ::= SecElems------ SecElems ::= SecElem* '\\n'?--- SecElem ::= '\\n' SecElemLayout | SecElemBraces--- SecElemLayout ::= FieldLayout | FieldBraces | SectionLayout | SectionBraces--- SecElemBraces ::= FieldInline | FieldBraces | SectionBraces--- FieldLayout ::= name ':' line? ('\\n' line)*--- FieldBraces ::= name ':' '\\n'? '{' content '}'--- FieldInline ::= name ':' content--- SectionLayout ::= name arg* SecElems--- SectionBraces ::= name arg* '\\n'? '{' SecElems '}'--- @------ and the same thing but left factored...------ @--- SecElems ::= SecElem*--- SecElem ::= '\\n' name SecElemLayout--- | name SecElemBraces--- SecElemLayout ::= ':' FieldLayoutOrBraces--- | arg* SectionLayoutOrBraces--- FieldLayoutOrBraces ::= '\\n'? '{' content '}'--- | line? ('\\n' line)*--- SectionLayoutOrBraces ::= '\\n'? '{' SecElems '\\n'? '}'--- | SecElems--- SecElemBraces ::= ':' FieldInlineOrBraces--- | arg* '\\n'? '{' SecElems '\\n'? '}'--- FieldInlineOrBraces ::= '\\n'? '{' content '}'--- | content--- @------ Note how we have several productions with the sequence:------ > '\\n'? '{'------ That is, an optional newline (and indent) followed by a @{@ token.--- In the @SectionLayoutOrBraces@ case you can see that this makes it--- not fully left factored (because @SecElems@ can start with a @\\n@).--- Fully left factoring here would be ugly, and though we could use a--- lookahead of two tokens to resolve the alternatives, we can't--- conveniently use Parsec's 'try' here to get a lookahead of only two.--- So instead we deal with this case in the lexer by making a line--- where the first non-space is @{@ lex as just the @{@ token, without--- the usual indent token. Then in the parser we can resolve everything--- with just one token of lookahead and so without using 'try'.---- Top level of a file using cabal syntax----cabalStyleFile :: Parser [Field Position]-cabalStyleFile = do es <- elements zeroIndentLevel- eof- return es---- Elements that live at the top level or inside a section, ie fields--- and sectionscontent------ elements ::= element*-elements :: IndentLevel -> Parser [Field Position]-elements ilevel = many (element ilevel)---- An individual element, ie a field or a section. These can either use--- layout style or braces style. For layout style then it must start on--- a line on its own (so that we know its indentation level).------ element ::= '\\n' name elementInLayoutContext--- | name elementInNonLayoutContext-element :: IndentLevel -> Parser (Field Position)-element ilevel =- (do ilevel' <- indentOfAtLeast ilevel- name <- fieldSecName- elementInLayoutContext (incIndentLevel ilevel') name)- <|> (do name <- fieldSecName- elementInNonLayoutContext name)---- An element (field or section) that is valid in a layout context.--- In a layout context we can have fields and sections that themselves--- either use layout style or that use braces style.------ elementInLayoutContext ::= ':' fieldLayoutOrBraces--- | arg* sectionLayoutOrBraces-elementInLayoutContext :: IndentLevel -> Name Position -> Parser (Field Position)-elementInLayoutContext ilevel name =- (do colon; fieldLayoutOrBraces ilevel name)- <|> (do args <- many sectionArg- elems <- sectionLayoutOrBraces ilevel- return (Section name args elems))---- An element (field or section) that is valid in a non-layout context.--- In a non-layout context we can have only have fields and sections that--- themselves use braces style, or inline style fields.------ elementInNonLayoutContext ::= ':' FieldInlineOrBraces--- | arg* '\\n'? '{' elements '\\n'? '}'-elementInNonLayoutContext :: Name Position -> Parser (Field Position)-elementInNonLayoutContext name =- (do colon; fieldInlineOrBraces name)- <|> (do args <- many sectionArg- openBrace- elems <- elements zeroIndentLevel- optional tokIndent- closeBrace- return (Section name args elems))---- The body of a field, using either layout style or braces style.------ fieldLayoutOrBraces ::= '\\n'? '{' content '}'--- | line? ('\\n' line)*-fieldLayoutOrBraces :: IndentLevel -> Name Position -> Parser (Field Position)-fieldLayoutOrBraces ilevel name = braces <|> fieldLayout- where- braces = do- openBrace- ls <- inLexerMode (LexerMode in_field_braces) (many fieldContent)- closeBrace- return (Field name ls)- fieldLayout = inLexerMode (LexerMode in_field_layout) $ do- l <- optionMaybe fieldContent- ls <- many (do _ <- indentOfAtLeast ilevel; fieldContent)- return $ case l of- Nothing -> Field name ls- Just l' -> Field name (l' : ls)---- The body of a section, using either layout style or braces style.------ sectionLayoutOrBraces ::= '\\n'? '{' elements \\n? '}'--- | elements-sectionLayoutOrBraces :: IndentLevel -> Parser [Field Position]-sectionLayoutOrBraces ilevel =- (do openBrace- elems <- elements zeroIndentLevel- optional tokIndent- closeBrace- return elems)- <|> (elements ilevel)---- The body of a field, using either inline style or braces.------ fieldInlineOrBraces ::= '\\n'? '{' content '}'--- | content-fieldInlineOrBraces :: Name Position -> Parser (Field Position)-fieldInlineOrBraces name =- (do openBrace- ls <- inLexerMode (LexerMode in_field_braces) (many fieldContent)- closeBrace- return (Field name ls))- <|> (do ls <- inLexerMode (LexerMode in_field_braces) (option [] (fmap (\l -> [l]) fieldContent))- return (Field name ls))----- | Parse cabal style 'B8.ByteString' into list of 'Field's, i.e. the cabal AST.-readFields :: B8.ByteString -> Either ParseError [Field Position]-readFields s = fmap fst (readFields' s)---- | Like 'readFields' but also return lexer warnings-readFields' :: B8.ByteString -> Either ParseError ([Field Position], [LexWarning])-readFields' s = do- parse parser "the input" lexSt- where- parser = do- fields <- cabalStyleFile- ws <- getLexerWarnings- pure (fields, ws)-- lexSt = mkLexState' (mkLexState s)--#ifdef CABAL_PARSEC_DEBUG-parseTest' :: Show a => Parsec LexState' () a -> SourceName -> B8.ByteString -> IO ()-parseTest' p fname s =- case parse p fname (lexSt s) of- Left err -> putStrLn (formatError s err)-- Right x -> print x- where- lexSt = mkLexState' . mkLexState--parseFile :: Show a => Parser a -> FilePath -> IO ()-parseFile p f = B8.readFile f >>= \s -> parseTest' p f s--parseStr :: Show a => Parser a -> String -> IO ()-parseStr p = parseBS p . B8.pack--parseBS :: Show a => Parser a -> B8.ByteString -> IO ()-parseBS p = parseTest' p "<input string>"--formatError :: B8.ByteString -> ParseError -> String-formatError input perr =- unlines- [ "Parse error "++ show (errorPos perr) ++ ":"- , errLine- , indicator ++ errmsg ]- where- pos = errorPos perr- ls = lines' (T.decodeUtf8With T.lenientDecode input)- errLine = T.unpack (ls !! (sourceLine pos - 1))- indicator = replicate (sourceColumn pos) ' ' ++ "^"- errmsg = showErrorMessages "or" "unknown parse error"- "expecting" "unexpected" "end of file"- (errorMessages perr)---- | Handles windows/osx/unix line breaks uniformly-lines' :: T.Text -> [T.Text]-lines' s1- | T.null s1 = []- | otherwise = case T.break (\c -> c == '\r' || c == '\n') s1 of- (l, s2) | Just (c,s3) <- T.uncons s2- -> case T.uncons s3 of- Just ('\n', s4) | c == '\r' -> l : lines' s4- _ -> l : lines' s3- | otherwise -> [l]-#endif--eof :: Parser ()-eof = notFollowedBy anyToken <?> "end of file"- where- notFollowedBy :: Parser LToken -> Parser ()- notFollowedBy p = try ( (do L _ t <- try p; unexpected (describeToken t))- <|> return ())
− Distribution/Fields/Pretty.hs
@@ -1,176 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}--- | Cabal-like file AST types: 'Field', 'Section' etc,------ This (intermediate) data type is used for pretty-printing.------ @since 3.0.0.0----module Distribution.Fields.Pretty (- -- * Fields- PrettyField (..),- showFields,- showFields',- -- * Transformation from 'P.Field'- fromParsecFields,- genericFromParsecFields,- prettyFieldLines,- prettySectionArgs,- ) where--import Distribution.Compat.Prelude-import Distribution.Pretty (showToken)-import Prelude ()--import Distribution.Fields.Field (FieldName)-import Distribution.Simple.Utils (fromUTF8BS)--import qualified Distribution.Fields.Parser as P--import qualified Data.ByteString as BS-import qualified Text.PrettyPrint as PP--data PrettyField ann- = PrettyField ann FieldName PP.Doc- | PrettySection ann FieldName [PP.Doc] [PrettyField ann]- deriving (Functor, Foldable, Traversable)---- | Prettyprint a list of fields.------ Note: the first argument should return 'String's without newlines--- and properly prefixes (with @--@) to count as comments.--- This unsafety is left in place so one could generate empty lines--- between comment lines.----showFields :: (ann -> [String]) -> [PrettyField ann] -> String-showFields rann = showFields' rann (const id) 4---- | 'showFields' with user specified indentation.-showFields'- :: (ann -> [String])- -- ^ Convert an annotation to lined to preceed the field or section.- -> (ann -> [String] -> [String])- -- ^ Post-process non-annotation produced lines.- -> Int- -- ^ Indentation level.- -> [PrettyField ann]- -- ^ Fields/sections to show.- -> String-showFields' rann post n = unlines . renderFields (Opts rann indent post)- where- -- few hardcoded, "unrolled" variants.- indent | n == 4 = indent4- | n == 2 = indent2- | otherwise = (replicate (max n 1) ' ' ++)-- indent4 :: String -> String- indent4 [] = []- indent4 xs = ' ' : ' ' : ' ' : ' ' : xs-- indent2 :: String -> String- indent2 [] = []- indent2 xs = ' ' : ' ' : xs--data Opts ann = Opts- { _optAnnotation ::(ann -> [String])- , _optIndent ::(String -> String)- , _optPostprocess :: ann -> [String] -> [String]- }--renderFields :: Opts ann -> [PrettyField ann] -> [String]-renderFields opts fields = flattenBlocks $ map (renderField opts len) fields- where- len = maxNameLength 0 fields-- maxNameLength !acc [] = acc- maxNameLength !acc (PrettyField _ name _ : rest) = maxNameLength (max acc (BS.length name)) rest- maxNameLength !acc (PrettySection {} : rest) = maxNameLength acc rest---- | Block of lines,--- Boolean parameter tells whether block should be surrounded by empty lines-data Block = Block Margin Margin [String]--data Margin = Margin | NoMargin- deriving Eq---- | Collapse margins, any margin = margin-instance Semigroup Margin where- NoMargin <> NoMargin = NoMargin- _ <> _ = Margin--flattenBlocks :: [Block] -> [String]-flattenBlocks = go0 where- go0 [] = []- go0 (Block _before after strs : blocks) = strs ++ go after blocks-- go _surr' [] = []- go surr' (Block before after strs : blocks) = ins $ strs ++ go after blocks where- ins | surr' <> before == Margin = ("" :)- | otherwise = id--renderField :: Opts ann -> Int -> PrettyField ann -> Block-renderField (Opts rann indent post) fw (PrettyField ann name doc) =- Block before after $ comments ++ post ann lines'- where- comments = rann ann- before = if null comments then NoMargin else Margin-- (lines', after) = case lines narrow of- [] -> ([ name' ++ ":" ], NoMargin)- [singleLine] | length singleLine < 60- -> ([ name' ++ ": " ++ replicate (fw - length name') ' ' ++ narrow ], NoMargin)- _ -> ((name' ++ ":") : map indent (lines (PP.render doc)), Margin)-- name' = fromUTF8BS name- narrow = PP.renderStyle narrowStyle doc-- narrowStyle :: PP.Style- narrowStyle = PP.style { PP.lineLength = PP.lineLength PP.style - fw }--renderField opts@(Opts rann indent post) _ (PrettySection ann name args fields) = Block Margin Margin $- rann ann- ++- post ann [ PP.render $ PP.hsep $ PP.text (fromUTF8BS name) : args ]- ++- (map indent $ renderFields opts fields)------------------------------------------------------------------------------------ Transform from Parsec.Field----------------------------------------------------------------------------------genericFromParsecFields- :: Applicative f- => (FieldName -> [P.FieldLine ann] -> f PP.Doc) -- ^ transform field contents- -> (FieldName -> [P.SectionArg ann] -> f [PP.Doc]) -- ^ transform section arguments- -> [P.Field ann]- -> f [PrettyField ann]-genericFromParsecFields f g = goMany where- goMany = traverse go-- go (P.Field (P.Name ann name) fls) = PrettyField ann name <$> f name fls- go (P.Section (P.Name ann name) secargs fs) = PrettySection ann name <$> g name secargs <*> goMany fs---- | Used in 'fromParsecFields'.-prettyFieldLines :: FieldName -> [P.FieldLine ann] -> PP.Doc-prettyFieldLines _ fls = PP.vcat- [ PP.text $ fromUTF8BS bs- | P.FieldLine _ bs <- fls- ]---- | Used in 'fromParsecFields'.-prettySectionArgs :: FieldName -> [P.SectionArg ann] -> [PP.Doc]-prettySectionArgs _ = map $ \sa -> case sa of- P.SecArgName _ bs -> showToken $ fromUTF8BS bs- P.SecArgStr _ bs -> showToken $ fromUTF8BS bs- P.SecArgOther _ bs -> PP.text $ fromUTF8BS bs---- | Simple variant of 'genericFromParsecField'-fromParsecFields :: [P.Field ann] -> [PrettyField ann]-fromParsecFields = runIdentity . genericFromParsecFields- (Identity .: prettyFieldLines)- (Identity .: prettySectionArgs)- where- (.:) :: (a -> b) -> (c -> d -> a) -> (c -> d -> b)- (f .: g) x y = f (g x y)
− Distribution/GetOpt.hs
@@ -1,209 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.GetOpt--- Copyright : (c) Sven Panne 2002-2005--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Portability : portable------ This is a fork of "System.Console.GetOpt" with the following changes:------ * Treat "cabal --flag command" as "cabal command --flag" e.g.--- "cabal -v configure" to mean "cabal configure -v" For flags that are--- not recognised as global flags, pass them on to the sub-command. See--- the difference in 'shortOpt'.------ * Line wrapping in the 'usageInfo' output, plus a more compact--- rendering of short options, and slightly less padding.------ If you want to take on the challenge of merging this with the GetOpt--- from the base package then go for it!----module Distribution.GetOpt (- -- * GetOpt- getOpt, getOpt',- usageInfo,- ArgOrder(..),- OptDescr(..),- ArgDescr(..),-- -- * Example- -- | See "System.Console.GetOpt" for examples-) where--import Prelude ()-import Distribution.Compat.Prelude-import System.Console.GetOpt- ( ArgOrder(..), OptDescr(..), ArgDescr(..) )--data OptKind a -- kind of cmd line arg (internal use only):- = Opt a -- an option- | UnreqOpt String -- an un-recognized option- | NonOpt String -- a non-option- | EndOfOpts -- end-of-options marker (i.e. "--")- | OptErr String -- something went wrong...---- | Return a string describing the usage of a command, derived from--- the header (first argument) and the options described by the--- second argument.-usageInfo :: String -- header- -> [OptDescr a] -- option descriptors- -> String -- nicely formatted decription of options-usageInfo header optDescr = unlines (header:table)- where (ss,ls,ds) = unzip3 [ (intercalate ", " (map (fmtShort ad) sos)- ,concatMap (fmtLong ad) (take 1 los)- ,d)- | Option sos los ad d <- optDescr ]- ssWidth = (maximum . map length) ss- lsWidth = (maximum . map length) ls- dsWidth = 30 `max` (80 - (ssWidth + lsWidth + 3))- table = [ " " ++ padTo ssWidth so' ++- " " ++ padTo lsWidth lo' ++- " " ++ d'- | (so,lo,d) <- zip3 ss ls ds- , (so',lo',d') <- fmtOpt dsWidth so lo d ]- padTo n x = take n (x ++ repeat ' ')--fmtOpt :: Int -> String -> String -> String -> [(String, String, String)]-fmtOpt descrWidth so lo descr =- case wrapText descrWidth descr of- [] -> [(so,lo,"")]- (d:ds) -> (so,lo,d) : [ ("","",d') | d' <- ds ]--fmtShort :: ArgDescr a -> Char -> String-fmtShort (NoArg _ ) so = "-" ++ [so]-fmtShort (ReqArg _ _) so = "-" ++ [so]-fmtShort (OptArg _ _) so = "-" ++ [so]- -- unlike upstream GetOpt we omit the arg name for short options--fmtLong :: ArgDescr a -> String -> String-fmtLong (NoArg _ ) lo = "--" ++ lo-fmtLong (ReqArg _ ad) lo = "--" ++ lo ++ "=" ++ ad-fmtLong (OptArg _ ad) lo = "--" ++ lo ++ "[=" ++ ad ++ "]"--wrapText :: Int -> String -> [String]-wrapText width = map unwords . wrap 0 [] . words- where wrap :: Int -> [String] -> [String] -> [[String]]- wrap 0 [] (w:ws)- | length w + 1 > width- = wrap (length w) [w] ws- wrap col line (w:ws)- | col + length w + 1 > width- = reverse line : wrap 0 [] (w:ws)- wrap col line (w:ws)- = let col' = col + length w + 1- in wrap col' (w:line) ws- wrap _ [] [] = []- wrap _ line [] = [reverse line]--{-|-Process the command-line, and return the list of values that matched-(and those that didn\'t). The arguments are:--* The order requirements (see 'ArgOrder')--* The option descriptions (see 'OptDescr')--* The actual command line arguments (presumably got from- 'System.Environment.getArgs').--'getOpt' returns a triple consisting of the option arguments, a list-of non-options, and a list of error messages.--}-getOpt :: ArgOrder a -- non-option handling- -> [OptDescr a] -- option descriptors- -> [String] -- the command-line arguments- -> ([a],[String],[String]) -- (options,non-options,error messages)-getOpt ordering optDescr args = (os,xs,es ++ map errUnrec us)- where (os,xs,us,es) = getOpt' ordering optDescr args--{-|-This is almost the same as 'getOpt', but returns a quadruple-consisting of the option arguments, a list of non-options, a list of-unrecognized options, and a list of error messages.--}-getOpt' :: ArgOrder a -- non-option handling- -> [OptDescr a] -- option descriptors- -> [String] -- the command-line arguments- -> ([a],[String], [String] ,[String]) -- (options,non-options,unrecognized,error messages)-getOpt' _ _ [] = ([],[],[],[])-getOpt' ordering optDescr (arg:args) = procNextOpt opt ordering- where procNextOpt (Opt o) _ = (o:os,xs,us,es)- procNextOpt (UnreqOpt u) _ = (os,xs,u:us,es)- procNextOpt (NonOpt x) RequireOrder = ([],x:rest,[],[])- procNextOpt (NonOpt x) Permute = (os,x:xs,us,es)- procNextOpt (NonOpt x) (ReturnInOrder f) = (f x :os, xs,us,es)- procNextOpt EndOfOpts RequireOrder = ([],rest,[],[])- procNextOpt EndOfOpts Permute = ([],rest,[],[])- procNextOpt EndOfOpts (ReturnInOrder f) = (map f rest,[],[],[])- procNextOpt (OptErr e) _ = (os,xs,us,e:es)-- (opt,rest) = getNext arg args optDescr- (os,xs,us,es) = getOpt' ordering optDescr rest---- take a look at the next cmd line arg and decide what to do with it-getNext :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])-getNext ('-':'-':[]) rest _ = (EndOfOpts,rest)-getNext ('-':'-':xs) rest optDescr = longOpt xs rest optDescr-getNext ('-': x :xs) rest optDescr = shortOpt x xs rest optDescr-getNext a rest _ = (NonOpt a,rest)---- handle long option-longOpt :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])-longOpt ls rs optDescr = long ads arg rs- where (opt,arg) = break (=='=') ls- getWith p = [ o | o@(Option _ xs _ _) <- optDescr- , isJust (find (p opt) xs)]- exact = getWith (==)- options = if null exact then getWith isPrefixOf else exact- ads = [ ad | Option _ _ ad _ <- options ]- optStr = "--" ++ opt-- long (_:_:_) _ rest = (errAmbig options optStr,rest)- long [NoArg a ] [] rest = (Opt a,rest)- long [NoArg _ ] ('=':_) rest = (errNoArg optStr,rest)- long [ReqArg _ d] [] [] = (errReq d optStr,[])- long [ReqArg f _] [] (r:rest) = (Opt (f r),rest)- long [ReqArg f _] ('=':xs) rest = (Opt (f xs),rest)- long [OptArg f _] [] rest = (Opt (f Nothing),rest)- long [OptArg f _] ('=':xs) rest = (Opt (f (Just xs)),rest)- long _ _ rest = (UnreqOpt ("--"++ls),rest)---- handle short option-shortOpt :: Char -> String -> [String] -> [OptDescr a] -> (OptKind a,[String])-shortOpt y ys rs optDescr = short ads ys rs- where options = [ o | o@(Option ss _ _ _) <- optDescr, s <- ss, y == s ]- ads = [ ad | Option _ _ ad _ <- options ]- optStr = '-':[y]-- short (_:_:_) _ rest = (errAmbig options optStr,rest)- short (NoArg a :_) [] rest = (Opt a,rest)- short (NoArg a :_) xs rest = (Opt a,('-':xs):rest)- short (ReqArg _ d:_) [] [] = (errReq d optStr,[])- short (ReqArg f _:_) [] (r:rest) = (Opt (f r),rest)- short (ReqArg f _:_) xs rest = (Opt (f xs),rest)- short (OptArg f _:_) [] rest = (Opt (f Nothing),rest)- short (OptArg f _:_) xs rest = (Opt (f (Just xs)),rest)- short [] [] rest = (UnreqOpt optStr,rest)- short [] xs rest = (UnreqOpt (optStr++xs),rest)- -- This is different vs upstream = (UnreqOpt optStr,('-':xs):rest)- -- Apparently this was part of the change so that flags that are- -- not recognised as global flags are passed on to the sub-command.- -- But why was no equivalent change required for longOpt? So could- -- this change go upstream?---- miscellaneous error formatting--errAmbig :: [OptDescr a] -> String -> OptKind a-errAmbig ods optStr = OptErr (usageInfo header ods)- where header = "option `" ++ optStr ++ "' is ambiguous; could be one of:"--errReq :: String -> String -> OptKind a-errReq d optStr = OptErr ("option `" ++ optStr ++ "' requires an argument " ++ d ++ "\n")--errUnrec :: String -> String-errUnrec optStr = "unrecognized option `" ++ optStr ++ "'\n"--errNoArg :: String -> OptKind a-errNoArg optStr = OptErr ("option `" ++ optStr ++ "' doesn't allow an argument\n")
− Distribution/InstalledPackageInfo.hs
@@ -1,145 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.InstalledPackageInfo--- Copyright : (c) The University of Glasgow 2004------ Maintainer : libraries@haskell.org--- Portability : portable------ This is the information about an /installed/ package that--- is communicated to the @ghc-pkg@ program in order to register--- a package. @ghc-pkg@ now consumes this package format (as of version--- 6.4). This is specific to GHC at the moment.------ The @.cabal@ file format is for describing a package that is not yet--- installed. It has a lot of flexibility, like conditionals and dependency--- ranges. As such, that format is not at all suitable for describing a package--- that has already been built and installed. By the time we get to that stage,--- we have resolved all conditionals and resolved dependency version--- constraints to exact versions of dependent packages. So, this module defines--- the 'InstalledPackageInfo' data structure that contains all the info we keep--- about an installed package. There is a parser and pretty printer. The--- textual format is rather simpler than the @.cabal@ format: there are no--- sections, for example.---- This module is meant to be local-only to Distribution...--module Distribution.InstalledPackageInfo (- InstalledPackageInfo(..),- installedComponentId,- installedOpenUnitId,- sourceComponentName,- requiredSignatures,- ExposedModule(..),- AbiDependency(..),- emptyInstalledPackageInfo,- parseInstalledPackageInfo,- showInstalledPackageInfo,- showFullInstalledPackageInfo,- showInstalledPackageInfoField,- showSimpleInstalledPackageInfoField,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Backpack-import Distribution.CabalSpecVersion (cabalSpecLatest)-import Distribution.FieldGrammar-import Distribution.FieldGrammar.FieldDescrs-import Distribution.ModuleName-import Distribution.Package hiding (installedUnitId)-import Distribution.Types.ComponentName-import Distribution.Utils.Generic (toUTF8BS)--import Data.ByteString (ByteString)--import qualified Data.Map as Map-import qualified Distribution.Fields as P-import qualified Text.PrettyPrint as Disp--import Distribution.Types.InstalledPackageInfo-import Distribution.Types.InstalledPackageInfo.FieldGrammar---- $setup--- >>> :set -XOverloadedStrings--installedComponentId :: InstalledPackageInfo -> ComponentId-installedComponentId ipi =- case unComponentId (installedComponentId_ ipi) of- "" -> mkComponentId (unUnitId (installedUnitId ipi))- _ -> installedComponentId_ ipi---- | Get the indefinite unit identity representing this package.--- This IS NOT guaranteed to give you a substitution; for--- instantiated packages you will get @DefiniteUnitId (installedUnitId ipi)@.--- For indefinite libraries, however, you will correctly get--- an @OpenUnitId@ with the appropriate 'OpenModuleSubst'.-installedOpenUnitId :: InstalledPackageInfo -> OpenUnitId-installedOpenUnitId ipi- = mkOpenUnitId (installedUnitId ipi) (installedComponentId ipi) (Map.fromList (instantiatedWith ipi))---- | Returns the set of module names which need to be filled for--- an indefinite package, or the empty set if the package is definite.-requiredSignatures :: InstalledPackageInfo -> Set ModuleName-requiredSignatures ipi = openModuleSubstFreeHoles (Map.fromList (instantiatedWith ipi))---- -------------------------------------------------------------------------------- Munging--sourceComponentName :: InstalledPackageInfo -> ComponentName-sourceComponentName = CLibName . sourceLibName---- -------------------------------------------------------------------------------- Parsing---- | Return either errors, or IPI with list of warnings-parseInstalledPackageInfo- :: ByteString- -> Either (NonEmpty String) ([String], InstalledPackageInfo)-parseInstalledPackageInfo s = case P.readFields s of- Left err -> Left (show err :| [])- Right fs -> case partitionFields fs of- (fs', _) -> case P.runParseResult $ parseFieldGrammar cabalSpecLatest fs' ipiFieldGrammar of- (ws, Right x) -> x `deepseq` Right (ws', x) where- ws' = [ P.showPWarning "" w- | w@(P.PWarning wt _ _) <- ws- -- filter out warnings about experimental features- , wt /= P.PWTExperimental- ]- (_, Left (_, errs)) -> Left errs' where- errs' = fmap (P.showPError "") errs---- -------------------------------------------------------------------------------- Pretty-printing---- | Pretty print 'InstalledPackageInfo'.------ @pkgRoot@ isn't printed, as ghc-pkg prints it manually (as GHC-8.4).-showInstalledPackageInfo :: InstalledPackageInfo -> String-showInstalledPackageInfo ipi =- showFullInstalledPackageInfo ipi { pkgRoot = Nothing }---- | The variant of 'showInstalledPackageInfo' which outputs @pkgroot@ field too.-showFullInstalledPackageInfo :: InstalledPackageInfo -> String-showFullInstalledPackageInfo = P.showFields (const []) . prettyFieldGrammar cabalSpecLatest ipiFieldGrammar---- |------ >>> let ipi = emptyInstalledPackageInfo { maintainer = "Tester" }--- >>> fmap ($ ipi) $ showInstalledPackageInfoField "maintainer"--- Just "maintainer: Tester"-showInstalledPackageInfoField :: String -> Maybe (InstalledPackageInfo -> String)-showInstalledPackageInfoField fn =- fmap (\g -> Disp.render . ppField fn . g) $ fieldDescrPretty ipiFieldGrammar (toUTF8BS fn)--showSimpleInstalledPackageInfoField :: String -> Maybe (InstalledPackageInfo -> String)-showSimpleInstalledPackageInfoField fn =- fmap (Disp.renderStyle myStyle .) $ fieldDescrPretty ipiFieldGrammar (toUTF8BS fn)- where- myStyle = Disp.style { Disp.mode = Disp.LeftMode }--ppField :: String -> Disp.Doc -> Disp.Doc-ppField name fielddoc- | Disp.isEmpty fielddoc = mempty- | otherwise = Disp.text name <<>> Disp.colon Disp.<+> fielddoc
− Distribution/Lex.hs
@@ -1,40 +0,0 @@--------------------------------------------------------------------------------- |--- 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 Prelude ()-import Distribution.Compat.Prelude-import Distribution.Compat.DList--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
@@ -1,252 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}---------------------------------------------------------------------------------- |--- Module : Distribution.License--- Description : The License data type.--- Copyright : Isaac Jones 2003-2005--- Duncan Coutts 2008--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Package descriptions contain fields for specifying the name of a software--- license and the name of the file containing the text of that license. While--- package authors may choose any license they like, Cabal provides an--- enumeration of a small set of common free and open source software licenses.--- This is done so that Hackage can recognise licenses, so that tools can detect--- <https://en.wikipedia.org/wiki/License_compatibility licensing conflicts>,--- and to deter--- <https://en.wikipedia.org/wiki/License_proliferation license proliferation>.------ It is recommended that all package authors use the @license-file@ or--- @license-files@ fields in their package descriptions. Further information--- about these fields can be found in the--- <http://www.haskell.org/cabal/users-guide/developing-packages.html#package-descriptions Cabal users guide>.------ = Additional resources------ The following websites provide information about free and open source--- software licenses:------ * <http://www.opensource.org The Open Source Initiative (OSI)>------ * <https://www.fsf.org The Free Software Foundation (FSF)>------ = Disclaimer------ The descriptions of software licenses provided by this documentation are--- intended for informational purposes only and in no way constitute legal--- advice. Please read the text of the licenses and consult a lawyer for any--- advice regarding software licensing.--module Distribution.License (- License(..),- knownLicenses,- licenseToSPDX,- licenseFromSPDX,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Version--import qualified Distribution.Compat.CharParsing as P-import qualified Data.Map.Strict as Map-import qualified Distribution.SPDX as SPDX-import qualified Text.PrettyPrint as Disp---- | Indicates the license under which a package's source code is released.--- Versions of the licenses not listed here will be rejected by Hackage and--- cause @cabal check@ to issue a warning.-data License =- -- TODO: * remove BSD4-- -- | GNU General Public License,- -- <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html version 2> or- -- <https://www.gnu.org/licenses/gpl.html version 3>.- GPL (Maybe Version)-- -- | <https://www.gnu.org/licenses/agpl.html GNU Affero General Public License, version 3>.- | AGPL (Maybe Version)-- -- | GNU Lesser General Public License,- -- <https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html version 2.1> or- -- <https://www.gnu.org/licenses/lgpl.html version 3>.- | LGPL (Maybe Version)-- -- | <http://www.opensource.org/licenses/bsd-license 2-clause BSD license>.- | BSD2-- -- | <http://www.opensource.org/licenses/bsd-3-clause 3-clause BSD license>.- | BSD3-- -- | <http://directory.fsf.org/wiki/License:BSD_4Clause 4-clause BSD license>.- -- This license has not been approved by the OSI and is incompatible with- -- the GNU GPL. It is provided for historical reasons and should be avoided.- | BSD4-- -- | <http://www.opensource.org/licenses/MIT MIT license>.- | MIT-- -- | <http://www.isc.org/downloads/software-support-policy/isc-license/ ISC license>- | ISC-- -- | <https://www.mozilla.org/MPL/ Mozilla Public License, version 2.0>.- | MPL Version-- -- | <https://www.apache.org/licenses/ Apache License, version 2.0>.- | Apache (Maybe Version)-- -- | The author of a package disclaims any copyright to its source code and- -- dedicates it to the public domain. This is not a software license. Please- -- note that it is not possible to dedicate works to the public domain in- -- every jurisdiction, nor is a work that is in the public domain in one- -- jurisdiction necessarily in the public domain elsewhere.- | PublicDomain-- -- | Explicitly 'All Rights Reserved', eg for proprietary software. The- -- package may not be legally modified or redistributed by anyone but the- -- rightsholder.- | AllRightsReserved-- -- | No license specified which legally defaults to 'All Rights Reserved'.- -- The package may not be legally modified or redistributed by anyone but- -- the rightsholder.- | UnspecifiedLicense-- -- | Any other software license.- | OtherLicense-- -- | Indicates an erroneous license name.- | UnknownLicense String- deriving (Generic, Read, Show, Eq, Typeable, Data)--instance Binary License-instance Structured License-instance NFData License where rnf = genericRnf---- | The list of all currently recognised licenses.-knownLicenses :: [License]-knownLicenses = [ GPL unversioned, GPL (version [2]), GPL (version [3])- , LGPL unversioned, LGPL (version [2, 1]), LGPL (version [3])- , AGPL unversioned, AGPL (version [3])- , BSD2, BSD3, MIT, ISC- , MPL (mkVersion [2, 0])- , Apache unversioned, Apache (version [2, 0])- , PublicDomain, AllRightsReserved, OtherLicense]- where- unversioned = Nothing- version = Just . mkVersion---- | Convert old 'License' to SPDX 'SPDX.License'.--- Non-SPDX licenses are converted to 'SPDX.LicenseRef'.------ @since 2.2.0.0-licenseToSPDX :: License -> SPDX.License-licenseToSPDX l = case l of- GPL v | v == version [2] -> spdx SPDX.GPL_2_0_only- GPL v | v == version [3] -> spdx SPDX.GPL_3_0_only- LGPL v | v == version [2,1] -> spdx SPDX.LGPL_2_1_only- LGPL v | v == version [3] -> spdx SPDX.LGPL_3_0_only- AGPL v | v == version [3] -> spdx SPDX.AGPL_3_0_only- BSD2 -> spdx SPDX.BSD_2_Clause- BSD3 -> spdx SPDX.BSD_3_Clause- BSD4 -> spdx SPDX.BSD_4_Clause- MIT -> spdx SPDX.MIT- ISC -> spdx SPDX.ISC- MPL v | v == mkVersion [2,0] -> spdx SPDX.MPL_2_0- Apache v | v == version [2,0] -> spdx SPDX.Apache_2_0- AllRightsReserved -> SPDX.NONE- UnspecifiedLicense -> SPDX.NONE- OtherLicense -> ref (SPDX.mkLicenseRef' Nothing "OtherLicense")- PublicDomain -> ref (SPDX.mkLicenseRef' Nothing "PublicDomain")- UnknownLicense str -> ref (SPDX.mkLicenseRef' Nothing str)- _ -> ref (SPDX.mkLicenseRef' Nothing $ prettyShow l)- where- version = Just . mkVersion- spdx = SPDX.License . SPDX.simpleLicenseExpression- ref r = SPDX.License $ SPDX.ELicense (SPDX.ELicenseRef r) Nothing---- | Convert 'SPDX.License' to 'License',------ This is lossy conversion. We try our best.------ >>> licenseFromSPDX . licenseToSPDX $ BSD3--- BSD3------ >>> licenseFromSPDX . licenseToSPDX $ GPL (Just (mkVersion [3]))--- GPL (Just (mkVersion [3]))------ >>> licenseFromSPDX . licenseToSPDX $ PublicDomain--- UnknownLicense "LicenseRefPublicDomain"------ >>> licenseFromSPDX $ SPDX.License $ SPDX.simpleLicenseExpression SPDX.EUPL_1_1--- UnknownLicense "EUPL-1.1"------ >>> licenseFromSPDX . licenseToSPDX $ AllRightsReserved--- AllRightsReserved------ >>> licenseFromSPDX <$> simpleParsec "BSD-3-Clause OR GPL-3.0-only"--- Just (UnknownLicense "BSD3ClauseORGPL30only")------ @since 2.2.0.0-licenseFromSPDX :: SPDX.License -> License-licenseFromSPDX SPDX.NONE = AllRightsReserved-licenseFromSPDX l =- fromMaybe (mungle $ prettyShow l) $ Map.lookup l m- where- m :: Map.Map SPDX.License License- m = Map.fromList $ filter (isSimple . fst ) $- map (\x -> (licenseToSPDX x, x)) knownLicenses-- isSimple (SPDX.License (SPDX.ELicense (SPDX.ELicenseId _) Nothing)) = True- isSimple _ = False-- mungle name = fromMaybe (UnknownLicense (mapMaybe mangle name)) (simpleParsec name)-- mangle c- | isAlphaNum c = Just c- | otherwise = Nothing--instance Pretty License where- pretty (GPL version) = Disp.text "GPL" <<>> dispOptVersion version- pretty (LGPL version) = Disp.text "LGPL" <<>> dispOptVersion version- pretty (AGPL version) = Disp.text "AGPL" <<>> dispOptVersion version- pretty (MPL version) = Disp.text "MPL" <<>> dispVersion version- pretty (Apache version) = Disp.text "Apache" <<>> dispOptVersion version- pretty (UnknownLicense other) = Disp.text other- pretty other = Disp.text (show other)--instance Parsec License where- parsec = do- name <- P.munch1 isAlphaNum- version <- P.optional (P.char '-' *> parsec)- return $! case (name, version :: Maybe Version) of- ("GPL", _ ) -> GPL version- ("LGPL", _ ) -> LGPL version- ("AGPL", _ ) -> AGPL version- ("BSD2", Nothing) -> BSD2- ("BSD3", Nothing) -> BSD3- ("BSD4", Nothing) -> BSD4- ("ISC", Nothing) -> ISC- ("MIT", Nothing) -> MIT- ("MPL", Just version') -> MPL version'- ("Apache", _ ) -> Apache version- ("PublicDomain", Nothing) -> PublicDomain- ("AllRightsReserved", Nothing) -> AllRightsReserved- ("OtherLicense", Nothing) -> OtherLicense- _ -> UnknownLicense $ name ++- maybe "" (('-':) . prettyShow) version--dispOptVersion :: Maybe Version -> Disp.Doc-dispOptVersion Nothing = Disp.empty-dispOptVersion (Just v) = dispVersion v--dispVersion :: Version -> Disp.Doc-dispVersion v = Disp.char '-' <<>> pretty v
− Distribution/Make.hs
@@ -1,182 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Make--- Copyright : Martin Sjögren 2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is an alternative build system that delegates everything to the @make@--- program. All the commands just end up calling @make@ with appropriate--- arguments. The intention was to allow preexisting packages that used--- makefiles to be wrapped into Cabal packages. In practice essentially all--- such packages were converted over to the \"Simple\" build system instead.--- Consequently this module is not used much and it certainly only sees cursory--- maintenance and no testing. Perhaps at some point we should stop pretending--- that it works.------ Uses the parsed command-line from "Distribution.Simple.Setup" in order to build--- Haskell tools using a back-end build system based on make. Obviously we--- assume that there is a configure script, and that after the ConfigCmd has--- been run, there is a Makefile. Further assumptions:------ [ConfigCmd] We assume the configure script accepts--- @--with-hc@,--- @--with-hc-pkg@,--- @--prefix@,--- @--bindir@,--- @--libdir@,--- @--libexecdir@,--- @--datadir@.------ [BuildCmd] We assume that the default Makefile target will build everything.------ [InstallCmd] We assume there is an @install@ target. Note that we assume that--- this does *not* register the package!------ [CopyCmd] We assume there is a @copy@ target, and a variable @$(destdir)@.--- The @copy@ target should probably just invoke @make install@--- recursively (e.g. @$(MAKE) install prefix=$(destdir)\/$(prefix)--- bindir=$(destdir)\/$(bindir)@. The reason we can\'t invoke @make--- install@ directly here is that we don\'t know the value of @$(prefix)@.------ [SDistCmd] We assume there is a @dist@ target.------ [RegisterCmd] We assume there is a @register@ target and a variable @$(user)@.------ [UnregisterCmd] We assume there is an @unregister@ target.------ [HaddockCmd] We assume there is a @docs@ or @doc@ target.----- copy :--- $(MAKE) install prefix=$(destdir)/$(prefix) \--- bindir=$(destdir)/$(bindir) \--module Distribution.Make (- module Distribution.Package,- License(..), Version,- defaultMain, defaultMainArgs- ) where--import Prelude ()-import Distribution.Compat.Prelude---- local-import Distribution.Package-import Distribution.Simple.Program-import Distribution.Simple.Setup-import Distribution.Simple.Command--import Distribution.Simple.Utils--import Distribution.License-import Distribution.Version-import Distribution.Pretty--import System.Environment (getArgs, getProgName)--defaultMain :: IO ()-defaultMain = getArgs >>= defaultMainArgs--defaultMainArgs :: [String] -> IO ()-defaultMainArgs = defaultMainHelper--defaultMainHelper :: [String] -> IO ()-defaultMainHelper args =- case commandsRun (globalCommand commands) commands args of- CommandHelp help -> printHelp help- CommandList opts -> printOptionsList opts- CommandErrors errs -> printErrors errs- CommandReadyToGo (flags, commandParse) ->- case commandParse of- _ | fromFlag (globalVersion flags) -> printVersion- | fromFlag (globalNumericVersion flags) -> printNumericVersion- CommandHelp help -> printHelp help- CommandList opts -> printOptionsList opts- CommandErrors errs -> printErrors errs- CommandReadyToGo action -> action-- where- printHelp help = getProgName >>= putStr . help- printOptionsList = putStr . unlines- printErrors errs = do- putStr (intercalate "\n" errs)- exitWith (ExitFailure 1)- printNumericVersion = putStrLn $ prettyShow cabalVersion- printVersion = putStrLn $ "Cabal library version "- ++ prettyShow cabalVersion-- progs = defaultProgramDb- commands =- [configureCommand progs `commandAddAction` configureAction- ,buildCommand progs `commandAddAction` buildAction- ,installCommand `commandAddAction` installAction- ,copyCommand `commandAddAction` copyAction- ,haddockCommand `commandAddAction` haddockAction- ,cleanCommand `commandAddAction` cleanAction- ,sdistCommand `commandAddAction` sdistAction- ,registerCommand `commandAddAction` registerAction- ,unregisterCommand `commandAddAction` unregisterAction- ]--configureAction :: ConfigFlags -> [String] -> IO ()-configureAction flags args = do- noExtraFlags args- let verbosity = fromFlag (configVerbosity flags)- rawSystemExit verbosity "sh" $- "configure"- : configureArgs backwardsCompatHack flags- where backwardsCompatHack = True--copyAction :: CopyFlags -> [String] -> IO ()-copyAction flags args = do- noExtraFlags args- let destArgs = case fromFlag $ copyDest flags of- NoCopyDest -> ["install"]- CopyTo path -> ["copy", "destdir=" ++ path]- CopyToDb _ -> error "CopyToDb not supported via Make"-- rawSystemExit (fromFlag $ copyVerbosity flags) "make" destArgs--installAction :: InstallFlags -> [String] -> IO ()-installAction flags args = do- noExtraFlags args- rawSystemExit (fromFlag $ installVerbosity flags) "make" ["install"]- rawSystemExit (fromFlag $ installVerbosity flags) "make" ["register"]--haddockAction :: HaddockFlags -> [String] -> IO ()-haddockAction flags args = do- noExtraFlags args- rawSystemExit (fromFlag $ haddockVerbosity flags) "make" ["docs"]- `catchIO` \_ ->- rawSystemExit (fromFlag $ haddockVerbosity flags) "make" ["doc"]--buildAction :: BuildFlags -> [String] -> IO ()-buildAction flags args = do- noExtraFlags args- rawSystemExit (fromFlag $ buildVerbosity flags) "make" []--cleanAction :: CleanFlags -> [String] -> IO ()-cleanAction flags args = do- noExtraFlags args- rawSystemExit (fromFlag $ cleanVerbosity flags) "make" ["clean"]--sdistAction :: SDistFlags -> [String] -> IO ()-sdistAction flags args = do- noExtraFlags args- rawSystemExit (fromFlag $ sDistVerbosity flags) "make" ["dist"]--registerAction :: RegisterFlags -> [String] -> IO ()-registerAction flags args = do- noExtraFlags args- rawSystemExit (fromFlag $ regVerbosity flags) "make" ["register"]--unregisterAction :: RegisterFlags -> [String] -> IO ()-unregisterAction flags args = do- noExtraFlags args- rawSystemExit (fromFlag $ regVerbosity flags) "make" ["unregister"]
− Distribution/ModuleName.hs
@@ -1,131 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE ScopedTypeVariables #-}--------------------------------------------------------------------------------- |--- Module : Distribution.ModuleName--- Copyright : Duncan Coutts 2008--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Data type for Haskell module names.--module Distribution.ModuleName (- ModuleName,- fromString,- fromComponents,- components,- toFilePath,- main,- -- * Internal- validModuleComponent,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Utils.ShortText (ShortText, fromShortText, toShortText)-import System.FilePath (pathSeparator)--import qualified Distribution.Compat.CharParsing as P-import qualified Distribution.Compat.DList as DList-import qualified Text.PrettyPrint as Disp---- | A valid Haskell module name.----newtype ModuleName = ModuleName ShortText- deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)--unModuleName :: ModuleName -> String-unModuleName (ModuleName s) = fromShortText s--instance Binary ModuleName-instance Structured ModuleName--instance NFData ModuleName where- rnf (ModuleName ms) = rnf ms--instance Pretty ModuleName where- pretty = Disp.text . unModuleName--instance Parsec ModuleName where- parsec = parsecModuleName--parsecModuleName :: forall m. CabalParsing m => m ModuleName-parsecModuleName = state0 DList.empty where- upper :: m Char- !upper = P.satisfy isUpper-- ch :: m Char- !ch = P.satisfy (\c -> validModuleChar c || c == '.')-- alt :: m ModuleName -> m ModuleName -> m ModuleName- !alt = (<|>)-- state0 :: DList.DList Char -> m ModuleName- state0 acc = do- c <- upper- state1 (DList.snoc acc c)-- state1 :: DList.DList Char -> m ModuleName- state1 acc = state1' acc `alt` return (fromString (DList.toList acc))-- state1' :: DList.DList Char -> m ModuleName- state1' acc = do- c <- ch- case c of- '.' -> state0 (DList.snoc acc c)- _ -> state1 (DList.snoc acc c)--validModuleChar :: Char -> Bool-validModuleChar c = isAlphaNum c || c == '_' || c == '\''--validModuleComponent :: String -> Bool-validModuleComponent [] = False-validModuleComponent (c:cs) = isUpper c && all validModuleChar cs---- | Construct a 'ModuleName' from a valid module name 'String'.------ This is just a convenience function intended for valid module strings. It is--- an error if it is used with a string that is not a valid module name. If you--- are parsing user input then use 'Distribution.Text.simpleParse' instead.----instance IsString ModuleName where- fromString = ModuleName . toShortText---- | Construct a 'ModuleName' from valid module components, i.e. parts--- separated by dots.-fromComponents :: [String] -> ModuleName-fromComponents comps = fromString (intercalate "." comps)-{-# DEPRECATED fromComponents "Exists for cabal-install only" #-}---- | The module name @Main@.----main :: ModuleName-main = ModuleName (fromString "Main")---- | The individual components of a hierarchical module name. For example------ > components (fromString "A.B.C") = ["A", "B", "C"]----components :: ModuleName -> [String]-components mn = split (unModuleName mn)- where- split cs = case break (=='.') cs of- (chunk,[]) -> chunk : []- (chunk,_:rest) -> chunk : split rest---- | Convert a module name to a file path, but without any file extension.--- For example:------ > toFilePath (fromString "A.B.C") = "A/B/C"----toFilePath :: ModuleName -> FilePath-toFilePath = map f . unModuleName where- f '.' = pathSeparator- f c = c
− Distribution/Package.hs
@@ -1,96 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Package--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Defines a package identifier along with a parser and pretty printer for it.--- 'PackageIdentifier's consist of a name and an exact version. It also defines--- a 'Dependency' data type. A dependency is a package name and a version--- range, like @\"foo >= 1.2 && < 2\"@.--module Distribution.Package- ( module Distribution.Types.AbiHash- , module Distribution.Types.ComponentId- , module Distribution.Types.PackageId- , module Distribution.Types.UnitId- , module Distribution.Types.Module- , module Distribution.Types.PackageName- , module Distribution.Types.PkgconfigName- , module Distribution.Types.Dependency- , Package(..), packageName, packageVersion- , HasMungedPackageId(..), mungedName', mungedVersion'- , HasUnitId(..)- , PackageInstalled(..)- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Version- ( Version )--import Distribution.Types.AbiHash-import Distribution.Types.ComponentId-import Distribution.Types.Dependency-import Distribution.Types.MungedPackageId-import Distribution.Types.PackageId-import Distribution.Types.UnitId-import Distribution.Types.Module-import Distribution.Types.MungedPackageName-import Distribution.Types.PackageName-import Distribution.Types.PkgconfigName---- | Class of things that have a 'PackageIdentifier'------ Types in this class are all notions of a package. This allows us to have--- different types for the different phases that packages go though, from--- simple name\/id, package description, configured or installed packages.------ Not all kinds of packages can be uniquely identified by a--- 'PackageIdentifier'. In particular, installed packages cannot, there may be--- many installed instances of the same source package.----class Package pkg where- packageId :: pkg -> PackageIdentifier--mungedName' :: HasMungedPackageId pkg => pkg -> MungedPackageName-mungedName' = mungedName . mungedId--mungedVersion' :: HasMungedPackageId munged => munged -> Version-mungedVersion' = mungedVersion . mungedId--class HasMungedPackageId pkg where- mungedId :: pkg -> MungedPackageId--instance Package PackageIdentifier where- packageId = id--packageName :: Package pkg => pkg -> PackageName-packageName = pkgName . packageId--packageVersion :: Package pkg => pkg -> Version-packageVersion = pkgVersion . packageId--instance HasMungedPackageId MungedPackageId where- mungedId = id---- | Packages that have an installed unit ID-class Package pkg => HasUnitId pkg where- installedUnitId :: pkg -> UnitId---- | 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 (HasUnitId pkg) => PackageInstalled pkg where- installedDepends :: pkg -> [UnitId]
− Distribution/PackageDescription.hs
@@ -1,97 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.PackageDescription--- Copyright : Isaac Jones 2003-2005--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Backwards compatibility reexport of most things you need to know--- about @.cabal@ files.--module Distribution.PackageDescription (- -- * PD and GPD- module Distribution.Types.PackageDescription,- module Distribution.Types.GenericPackageDescription,- -- * Components- module Distribution.Types.ComponentName,- -- ** Library- module Distribution.Types.Library,- module Distribution.Types.LibraryName,- module Distribution.Types.LibraryVisibility,- -- ** Executable- module Distribution.Types.Executable,- module Distribution.Types.ExecutableScope,- -- ** TestSuite- module Distribution.Types.TestSuite,- module Distribution.Types.TestType,- module Distribution.Types.TestSuiteInterface,- -- ** Benchmark- module Distribution.Types.Benchmark,- module Distribution.Types.BenchmarkType,- module Distribution.Types.BenchmarkInterface,- -- ** Foreign library- module Distribution.Types.ForeignLib,- module Distribution.Types.ForeignLibType,- module Distribution.Types.ForeignLibOption,- -- * BuildInfo- module Distribution.Types.BuildType,- module Distribution.Types.BuildInfo,- module Distribution.Types.HookedBuildInfo,- module Distribution.Types.SetupBuildInfo,- -- * Flags- module Distribution.Types.Flag,- -- * Identifiers- module Distribution.Types.PackageId,- module Distribution.Types.PackageName,- module Distribution.Types.UnqualComponentName,- -- * Dependencies- module Distribution.Types.Dependency,- module Distribution.Types.ExeDependency,- module Distribution.Types.LegacyExeDependency,- module Distribution.Types.PkgconfigDependency,- -- * Condition trees- module Distribution.Types.CondTree,- module Distribution.Types.Condition,- module Distribution.Types.ConfVar,- -- * Source repository- module Distribution.Types.SourceRepo,- ) where--import Prelude ()---import Distribution.Compat.Prelude--import Distribution.Types.Benchmark-import Distribution.Types.BenchmarkInterface-import Distribution.Types.BenchmarkType-import Distribution.Types.BuildInfo-import Distribution.Types.BuildType-import Distribution.Types.ComponentName-import Distribution.Types.Condition-import Distribution.Types.CondTree-import Distribution.Types.ConfVar-import Distribution.Types.Dependency-import Distribution.Types.Executable-import Distribution.Types.ExecutableScope-import Distribution.Types.ExeDependency-import Distribution.Types.Flag-import Distribution.Types.ForeignLib-import Distribution.Types.ForeignLibOption-import Distribution.Types.ForeignLibType-import Distribution.Types.GenericPackageDescription-import Distribution.Types.HookedBuildInfo-import Distribution.Types.LegacyExeDependency-import Distribution.Types.Library-import Distribution.Types.LibraryName-import Distribution.Types.LibraryVisibility-import Distribution.Types.PackageDescription-import Distribution.Types.PackageId-import Distribution.Types.PackageName-import Distribution.Types.PkgconfigDependency-import Distribution.Types.SetupBuildInfo-import Distribution.Types.SourceRepo-import Distribution.Types.TestSuite-import Distribution.Types.TestSuiteInterface-import Distribution.Types.TestType-import Distribution.Types.UnqualComponentName
− Distribution/PackageDescription/Check.hs
@@ -1,2389 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.PackageDescription.Check--- Copyright : Lennart Kolmodin 2008--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This has code for checking for various problems in packages. There is one--- set of checks that just looks at a 'PackageDescription' in isolation and--- another set of checks that also looks at files in the package. Some of the--- checks are basic sanity checks, others are portability standards that we'd--- like to encourage. There is a 'PackageCheck' type that distinguishes the--- different kinds of check so we can see which ones are appropriate to report--- in different situations. This code gets uses when configuring a package when--- we consider only basic problems. The higher standard is uses when--- preparing a source tarball and by Hackage when uploading new packages. The--- reason for this is that we want to hold packages that are expected to be--- distributed to a higher standard than packages that are only ever expected--- to be used on the author's own environment.--module Distribution.PackageDescription.Check (- -- * Package Checking- PackageCheck(..),- checkPackage,- checkConfiguredPackage,-- -- ** Checking package contents- checkPackageFiles,- checkPackageContent,- CheckPackageContentOps(..),- checkPackageFileNames,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Data.List (group)-import Distribution.CabalSpecVersion-import Distribution.Compat.Lens-import Distribution.Compiler-import Distribution.License-import Distribution.Package-import Distribution.PackageDescription-import Distribution.PackageDescription.Configuration-import Distribution.Pretty (prettyShow)-import Distribution.Simple.BuildPaths (autogenPathsModuleName)-import Distribution.Simple.BuildToolDepends-import Distribution.Simple.CCompiler-import Distribution.Simple.Glob-import Distribution.Simple.Utils hiding (findPackageDesc, notice)-import Distribution.System-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.ModuleReexport-import Distribution.Utils.Generic (isAscii)-import Distribution.Verbosity-import Distribution.Version-import Language.Haskell.Extension-import System.FilePath- (splitDirectories, splitExtension, splitPath, takeExtension, takeFileName, (<.>), (</>))--import qualified Data.ByteString.Lazy as BS-import qualified Data.Map as Map-import qualified Distribution.Compat.DList as DList-import qualified Distribution.SPDX as SPDX-import qualified System.Directory as System--import qualified System.Directory (getDirectoryContents)-import qualified System.FilePath.Windows as FilePath.Windows (isValid)--import qualified Data.Set as Set-import qualified Distribution.Utils.ShortText as ShortText--import qualified Distribution.Types.BuildInfo.Lens as L-import qualified Distribution.Types.GenericPackageDescription.Lens as L-import qualified Distribution.Types.PackageDescription.Lens as L---- $setup--- >>> import Control.Arrow ((&&&))---- | Results of some kind of failed package check.------ There are a range of severities, from merely dubious to totally insane.--- All of them come with a human readable explanation. In future we may augment--- them with more machine readable explanations, for example to help an IDE--- suggest automatic corrections.----data PackageCheck =-- -- | This package description is no good. There's no way it's going to- -- build sensibly. This should give an error at configure time.- PackageBuildImpossible { explanation :: String }-- -- | A problem that is likely to affect building the package, or an- -- issue that we'd like every package author to be aware of, even if- -- the package is never distributed.- | PackageBuildWarning { explanation :: String }-- -- | An issue that might not be a problem for the package author but- -- might be annoying or detrimental when the package is distributed to- -- users. We should encourage distributed packages to be free from these- -- issues, but occasionally there are justifiable reasons so we cannot- -- 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- -- problems.- | PackageDistInexcusable { explanation :: String }- deriving (Eq, Ord)--instance Show PackageCheck where- show notice = explanation notice--check :: Bool -> PackageCheck -> Maybe PackageCheck-check False _ = Nothing-check True pc = Just pc--checkSpecVersion :: PackageDescription -> CabalSpecVersion -> Bool -> PackageCheck- -> Maybe PackageCheck-checkSpecVersion pkg specver cond pc- | specVersion pkg >= specver = Nothing- | otherwise = check cond pc---- --------------------------------------------------------------- * Standard checks--- ---------------------------------------------------------------- | Check for common mistakes and problems in package descriptions.------ This is the standard collection of checks covering all aspects except--- for checks that require looking at files within the package. For those--- see 'checkPackageFiles'.------ It requires the 'GenericPackageDescription' and optionally a particular--- configuration of that package. If you pass 'Nothing' then we just check--- a version of the generic description using 'flattenPackageDescription'.----checkPackage :: GenericPackageDescription- -> Maybe PackageDescription- -> [PackageCheck]-checkPackage gpkg mpkg =- checkConfiguredPackage pkg- ++ checkConditionals gpkg- ++ checkPackageVersions gpkg- ++ checkDevelopmentOnlyFlags gpkg- ++ checkFlagNames gpkg- ++ checkUnusedFlags gpkg- ++ checkUnicodeXFields gpkg- ++ checkPathsModuleExtensions pkg- where- pkg = fromMaybe (flattenPackageDescription gpkg) mpkg----TODO: make this variant go away--- we should always know the GenericPackageDescription-checkConfiguredPackage :: PackageDescription -> [PackageCheck]-checkConfiguredPackage pkg =- checkSanity pkg- ++ checkFields pkg- ++ checkLicense pkg- ++ checkSourceRepos pkg- ++ checkAllGhcOptions pkg- ++ checkCCOptions pkg- ++ checkCxxOptions pkg- ++ checkCPPOptions pkg- ++ checkPaths pkg- ++ checkCabalVersion pkg----- --------------------------------------------------------------- * Basic sanity checks--- ---------------------------------------------------------------- | Check that this package description is sane.----checkSanity :: PackageDescription -> [PackageCheck]-checkSanity pkg =- catMaybes [-- check (null . unPackageName . packageName $ pkg) $- PackageBuildImpossible "No 'name' field."-- , check (nullVersion == packageVersion pkg) $- PackageBuildImpossible "No 'version' field."-- , check (all ($ pkg) [ null . executables- , null . testSuites- , null . benchmarks- , null . allLibraries- , null . foreignLibs ]) $- PackageBuildImpossible- "No executables, libraries, tests, or benchmarks found. Nothing to do."-- , check (any (== LMainLibName) (map libName $ subLibraries pkg)) $- PackageBuildImpossible $ "Found one or more unnamed internal libraries. "- ++ "Only the non-internal library can have the same name as the package."-- , check (not (null duplicateNames)) $- PackageBuildImpossible $ "Duplicate sections: "- ++ commaSep (map unUnqualComponentName duplicateNames)- ++ ". The name of every library, executable, test suite,"- ++ " and benchmark section in"- ++ " the package must be unique."-- -- NB: but it's OK for executables to have the same name!- -- TODO shouldn't need to compare on the string level- , check (any (== prettyShow (packageName pkg)) (prettyShow <$> subLibNames)) $- PackageBuildImpossible $ "Illegal internal library name "- ++ prettyShow (packageName pkg)- ++ ". Internal libraries cannot have the same name as the package."- ++ " Maybe you wanted a non-internal library?"- ++ " If so, rewrite the section stanza"- ++ " from 'library: '" ++ prettyShow (packageName pkg) ++ "' to 'library'."- ]- --TODO: check for name clashes case insensitively: windows file systems cannot- --cope.-- ++ concatMap (checkLibrary pkg) (allLibraries pkg)- ++ concatMap (checkExecutable pkg) (executables pkg)- ++ concatMap (checkTestSuite pkg) (testSuites pkg)- ++ concatMap (checkBenchmark pkg) (benchmarks pkg)-- where- -- The public 'library' gets special dispensation, because it- -- is common practice to export a library and name the executable- -- the same as the package.- subLibNames = mapMaybe (libraryNameString . libName) $ subLibraries pkg- exeNames = map exeName $ executables pkg- testNames = map testName $ testSuites pkg- bmNames = map benchmarkName $ benchmarks pkg- duplicateNames = dups $ subLibNames ++ exeNames ++ testNames ++ bmNames--checkLibrary :: PackageDescription -> Library -> [PackageCheck]-checkLibrary pkg lib =- catMaybes [-- check (not (null moduleDuplicates)) $- PackageBuildImpossible $- "Duplicate modules in library: "- ++ commaSep (map prettyShow moduleDuplicates)-- -- TODO: This check is bogus if a required-signature was passed through- , check (null (explicitLibModules lib) && null (reexportedModules lib)) $- PackageDistSuspiciousWarn $- showLibraryName (libName lib) ++ " does not expose any modules"-- -- check use of signatures sections- , checkVersion CabalSpecV2_0 (not (null (signatures lib))) $- PackageDistInexcusable $- "To use the 'signatures' field the package needs to specify "- ++ "at least 'cabal-version: 2.0'."-- -- check that all autogen-modules appear on other-modules or exposed-modules- , check- (not $ and $ map (flip elem (explicitLibModules lib)) (libModulesAutogen lib)) $- PackageBuildImpossible $- "An 'autogen-module' is neither on 'exposed-modules' or "- ++ "'other-modules'."-- -- check that all autogen-includes appear on includes or install-includes- , check- (not $ and $ map (flip elem (allExplicitIncludes lib)) (view L.autogenIncludes lib)) $- PackageBuildImpossible $- "An include in 'autogen-includes' is neither in 'includes' or "- ++ "'install-includes'."- ]-- where- checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck- checkVersion ver cond pc- | specVersion pkg >= ver = Nothing- | otherwise = check cond pc-- -- TODO: not sure if this check is always right in Backpack- moduleDuplicates = dups (explicitLibModules lib ++- map moduleReexportName (reexportedModules lib))--allExplicitIncludes :: L.HasBuildInfo a => a -> [FilePath]-allExplicitIncludes x = view L.includes x ++ view L.installIncludes x--checkExecutable :: PackageDescription -> Executable -> [PackageCheck]-checkExecutable pkg exe =- catMaybes [-- check (null (modulePath exe)) $- PackageBuildImpossible $- "No 'main-is' field found for executable " ++ prettyShow (exeName exe)-- , check (not (null (modulePath exe))- && (not $ fileExtensionSupportedLanguage $ modulePath exe)) $- PackageBuildImpossible $- "The 'main-is' field must specify a '.hs' or '.lhs' file "- ++ "(even if it is generated by a preprocessor), "- ++ "or it may specify a C/C++/obj-C source file."-- , checkSpecVersion pkg CabalSpecV1_18- (fileExtensionSupportedLanguage (modulePath exe)- && takeExtension (modulePath exe) `notElem` [".hs", ".lhs"]) $- 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'."-- , check (not (null moduleDuplicates)) $- PackageBuildImpossible $- "Duplicate modules in executable '" ++ prettyShow (exeName exe) ++ "': "- ++ commaSep (map prettyShow moduleDuplicates)-- -- check that all autogen-modules appear on other-modules- , check- (not $ and $ map (flip elem (exeModules exe)) (exeModulesAutogen exe)) $- PackageBuildImpossible $- "On executable '" ++ prettyShow (exeName exe) ++ "' an 'autogen-module' is not "- ++ "on 'other-modules'"-- -- check that all autogen-includes appear on includes- , check- (not $ and $ map (flip elem (view L.includes exe)) (view L.autogenIncludes exe)) $- PackageBuildImpossible "An include in 'autogen-includes' is not in 'includes'."- ]- where- moduleDuplicates = dups (exeModules exe)--checkTestSuite :: PackageDescription -> TestSuite -> [PackageCheck]-checkTestSuite pkg test =- catMaybes [-- case testInterface test of- TestSuiteUnsupported tt@(TestTypeUnknown _ _) -> Just $- PackageBuildWarning $- quote (prettyShow tt) ++ " is not a known type of test suite. "- ++ "The known test suite types are: "- ++ commaSep (map prettyShow knownTestTypes)-- TestSuiteUnsupported tt -> Just $- PackageBuildWarning $- quote (prettyShow tt) ++ " is not a supported test suite version. "- ++ "The known test suite types are: "- ++ commaSep (map prettyShow knownTestTypes)- _ -> Nothing-- , check (not $ null moduleDuplicates) $- PackageBuildImpossible $- "Duplicate modules in test suite '" ++ prettyShow (testName test) ++ "': "- ++ commaSep (map prettyShow moduleDuplicates)-- , check mainIsWrongExt $- PackageBuildImpossible $- "The 'main-is' field must specify a '.hs' or '.lhs' file "- ++ "(even if it is generated by a preprocessor), "- ++ "or it may specify a C/C++/obj-C source file."-- , checkSpecVersion pkg CabalSpecV1_18 (mainIsNotHsExt && not mainIsWrongExt) $- 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'."-- -- check that all autogen-modules appear on other-modules- , check- (not $ and $ map (flip elem (testModules test)) (testModulesAutogen test)) $- PackageBuildImpossible $- "On test suite '" ++ prettyShow (testName test) ++ "' an 'autogen-module' is not "- ++ "on 'other-modules'"-- -- check that all autogen-includes appear on includes- , check- (not $ and $ map (flip elem (view L.includes test)) (view L.autogenIncludes test)) $- PackageBuildImpossible "An include in 'autogen-includes' is not in 'includes'."- ]- where- moduleDuplicates = dups $ testModules test-- mainIsWrongExt = case testInterface test of- TestSuiteExeV10 _ f -> not $ fileExtensionSupportedLanguage f- _ -> False-- mainIsNotHsExt = case testInterface test of- TestSuiteExeV10 _ f -> takeExtension f `notElem` [".hs", ".lhs"]- _ -> False--checkBenchmark :: PackageDescription -> Benchmark -> [PackageCheck]-checkBenchmark _pkg bm =- catMaybes [-- case benchmarkInterface bm of- BenchmarkUnsupported tt@(BenchmarkTypeUnknown _ _) -> Just $- PackageBuildWarning $- quote (prettyShow tt) ++ " is not a known type of benchmark. "- ++ "The known benchmark types are: "- ++ commaSep (map prettyShow knownBenchmarkTypes)-- BenchmarkUnsupported tt -> Just $- PackageBuildWarning $- quote (prettyShow tt) ++ " is not a supported benchmark version. "- ++ "The known benchmark types are: "- ++ commaSep (map prettyShow knownBenchmarkTypes)- _ -> Nothing-- , check (not $ null moduleDuplicates) $- PackageBuildImpossible $- "Duplicate modules in benchmark '" ++ prettyShow (benchmarkName bm) ++ "': "- ++ commaSep (map prettyShow moduleDuplicates)-- , check mainIsWrongExt $- PackageBuildImpossible $- "The 'main-is' field must specify a '.hs' or '.lhs' file "- ++ "(even if it is generated by a preprocessor)."-- -- check that all autogen-modules appear on other-modules- , check- (not $ and $ map (flip elem (benchmarkModules bm)) (benchmarkModulesAutogen bm)) $- PackageBuildImpossible $- "On benchmark '" ++ prettyShow (benchmarkName bm) ++ "' an 'autogen-module' is "- ++ "not on 'other-modules'"-- -- check that all autogen-includes appear on includes- , check- (not $ and $ map (flip elem (view L.includes bm)) (view L.autogenIncludes bm)) $- PackageBuildImpossible "An include in 'autogen-includes' is not in 'includes'."- ]- where- moduleDuplicates = dups $ benchmarkModules bm-- mainIsWrongExt = case benchmarkInterface bm of- BenchmarkExeV10 _ f -> takeExtension f `notElem` [".hs", ".lhs"]- _ -> False---- --------------------------------------------------------------- * Additional pure checks--- --------------------------------------------------------------checkFields :: PackageDescription -> [PackageCheck]-checkFields pkg =- catMaybes [-- check (not . FilePath.Windows.isValid . prettyShow . packageName $ pkg) $- PackageDistInexcusable $- "Unfortunately, the package name '" ++ prettyShow (packageName pkg)- ++ "' is one of the reserved system file names on Windows. Many tools "- ++ "need to convert package names to file names so using this name "- ++ "would cause problems."-- , check ((isPrefixOf "z-") . prettyShow . packageName $ pkg) $- PackageDistInexcusable $- "Package names with the prefix 'z-' are reserved by Cabal and "- ++ "cannot be used."-- , check (isNothing (buildTypeRaw pkg) && specVersion pkg < CabalSpecV2_2) $- PackageBuildWarning $- "No 'build-type' specified. If you do not need a custom Setup.hs or "- ++ "./configure script then use 'build-type: Simple'."-- , check (isJust (setupBuildInfo pkg) && buildType pkg /= 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)- ++ " in 'tested-with' field."-- , check (not (null unknownLanguages)) $- PackageBuildWarning $- "Unknown languages: " ++ commaSep unknownLanguages-- , check (not (null unknownExtensions)) $- PackageBuildWarning $- "Unknown extensions: " ++ commaSep unknownExtensions-- , check (not (null languagesUsedAsExtensions)) $- PackageBuildWarning $- "Languages listed as extensions: "- ++ commaSep languagesUsedAsExtensions- ++ ". Languages must be specified in either the 'default-language' "- ++ " or the 'other-languages' field."-- , check (not (null ourDeprecatedExtensions)) $- PackageDistSuspicious $- "Deprecated extensions: "- ++ commaSep (map (quote . prettyShow . fst) ourDeprecatedExtensions)- ++ ". " ++ unwords- [ "Instead of '" ++ prettyShow ext- ++ "' use '" ++ prettyShow replacement ++ "'."- | (ext, Just replacement) <- ourDeprecatedExtensions ]-- , check (ShortText.null (category pkg)) $- PackageDistSuspicious "No 'category' field."-- , check (ShortText.null (maintainer pkg)) $- PackageDistSuspicious "No 'maintainer' field."-- , check (ShortText.null (synopsis pkg) && ShortText.null (description pkg)) $- PackageDistInexcusable "No 'synopsis' or 'description' field."-- , check (ShortText.null (description pkg) && not (ShortText.null (synopsis pkg))) $- PackageDistSuspicious "No 'description' field."-- , check (ShortText.null (synopsis pkg) && not (ShortText.null (description pkg))) $- PackageDistSuspicious "No 'synopsis' field."-- --TODO: recommend the bug reports URL, author and homepage fields- --TODO: recommend not using the stability field- --TODO: recommend specifying a source repo-- , check (ShortText.length (synopsis pkg) >= 80) $- PackageDistSuspicious- "The 'synopsis' field is rather long (max 80 chars is recommended)."-- -- See also https://github.com/haskell/cabal/pull/3479- , check (not (ShortText.null (description pkg))- && ShortText.length (description pkg) <= ShortText.length (synopsis pkg)) $- PackageDistSuspicious $- "The 'description' field should be longer than the 'synopsis' "- ++ "field. "- ++ "It's useful to provide an informative 'description' to allow "- ++ "Haskell programmers who have never heard about your package to "- ++ "understand the purpose of your package. "- ++ "The 'description' field content is typically shown by tooling "- ++ "(e.g. 'cabal info', Haddock, Hackage) below the 'synopsis' which "- ++ "serves as a headline. "- ++ "Please refer to <https://www.haskell.org/"- ++ "cabal/users-guide/developing-packages.html#package-properties>"- ++ " for more details."-- -- check use of impossible constraints "tested-with: GHC== 6.10 && ==6.12"- , check (not (null testedWithImpossibleRanges)) $- PackageDistInexcusable $- "Invalid 'tested-with' version range: "- ++ commaSep (map prettyShow testedWithImpossibleRanges)- ++ ". To indicate that you have tested a package with multiple "- ++ "different versions of the same compiler use multiple entries, "- ++ "for example 'tested-with: GHC==6.10.4, GHC==6.12.3' and not "- ++ "'tested-with: GHC==6.10.4 && ==6.12.3'."-- , check (not (null depInternalLibraryWithExtraVersion)) $- PackageBuildWarning $- "The package has an extraneous version range for a dependency on an "- ++ "internal library: "- ++ commaSep (map prettyShow depInternalLibraryWithExtraVersion)- ++ ". This version range includes the current package but isn't needed "- ++ "as the current package's library will always be used."-- , check (not (null depInternalLibraryWithImpossibleVersion)) $- PackageBuildImpossible $- "The package has an impossible version range for a dependency on an "- ++ "internal library: "- ++ commaSep (map prettyShow depInternalLibraryWithImpossibleVersion)- ++ ". This version range does not include the current package, and must "- ++ "be removed as the current package's library will always be used."-- , check (not (null depInternalExecutableWithExtraVersion)) $- PackageBuildWarning $- "The package has an extraneous version range for a dependency on an "- ++ "internal executable: "- ++ commaSep (map prettyShow depInternalExecutableWithExtraVersion)- ++ ". This version range includes the current package but isn't needed "- ++ "as the current package's executable will always be used."-- , check (not (null depInternalExecutableWithImpossibleVersion)) $- PackageBuildImpossible $- "The package has an impossible version range for a dependency on an "- ++ "internal executable: "- ++ commaSep (map prettyShow depInternalExecutableWithImpossibleVersion)- ++ ". This version range does not include the current package, and must "- ++ "be removed as the current package's executable will always be used."-- , check (not (null depMissingInternalExecutable)) $- PackageBuildImpossible $- "The package depends on a missing internal executable: "- ++ commaSep (map prettyShow depInternalExecutableWithImpossibleVersion)- ]- where- unknownCompilers = [ name | (OtherCompiler name, _) <- testedWith pkg ]- unknownLanguages = [ name | bi <- allBuildInfo pkg- , UnknownLanguage name <- allLanguages bi ]- unknownExtensions = [ name | bi <- allBuildInfo pkg- , UnknownExtension name <- allExtensions bi- , name `notElem` map prettyShow knownLanguages ]- ourDeprecatedExtensions = nub $ catMaybes- [ find ((==ext) . fst) deprecatedExtensions- | bi <- allBuildInfo pkg- , ext <- allExtensions bi ]- languagesUsedAsExtensions =- [ name | bi <- allBuildInfo pkg- , UnknownExtension name <- allExtensions bi- , name `elem` map prettyShow knownLanguages ]-- testedWithImpossibleRanges =- [ Dependency (mkPackageName (prettyShow compiler)) vr mainLibSet- | (compiler, vr) <- testedWith pkg- , isNoVersion vr ]-- internalLibraries =- map (maybe (packageName pkg) (unqualComponentNameToPackageName) . libraryNameString . libName)- (allLibraries pkg)-- internalExecutables = map exeName $ executables pkg-- internalLibDeps =- [ dep- | bi <- allBuildInfo pkg- , dep@(Dependency name _ _) <- targetBuildDepends bi- , name `elem` internalLibraries- ]-- internalExeDeps =- [ dep- | bi <- allBuildInfo pkg- , dep <- getAllToolDependencies pkg bi- , isInternal pkg dep- ]-- depInternalLibraryWithExtraVersion =- [ dep- | dep@(Dependency _ versionRange _) <- internalLibDeps- , not $ isAnyVersion versionRange- , packageVersion pkg `withinRange` versionRange- ]-- depInternalLibraryWithImpossibleVersion =- [ dep- | dep@(Dependency _ versionRange _) <- internalLibDeps- , not $ packageVersion pkg `withinRange` versionRange- ]-- depInternalExecutableWithExtraVersion =- [ dep- | dep@(ExeDependency _ _ versionRange) <- internalExeDeps- , not $ isAnyVersion versionRange- , packageVersion pkg `withinRange` versionRange- ]-- depInternalExecutableWithImpossibleVersion =- [ dep- | dep@(ExeDependency _ _ versionRange) <- internalExeDeps- , not $ packageVersion pkg `withinRange` versionRange- ]-- depMissingInternalExecutable =- [ dep- | dep@(ExeDependency _ eName _) <- internalExeDeps- , not $ eName `elem` internalExecutables- ]---checkLicense :: PackageDescription -> [PackageCheck]-checkLicense pkg = case licenseRaw pkg of- Right l -> checkOldLicense pkg l- Left l -> checkNewLicense pkg l--checkNewLicense :: PackageDescription -> SPDX.License -> [PackageCheck]-checkNewLicense _pkg lic = catMaybes- [ check (lic == SPDX.NONE) $- PackageDistInexcusable- "The 'license' field is missing or is NONE."- ]--checkOldLicense :: PackageDescription -> License -> [PackageCheck]-checkOldLicense pkg lic = catMaybes- [ check (lic == UnspecifiedLicense) $- PackageDistInexcusable- "The 'license' field is missing."-- , check (lic == AllRightsReserved) $- PackageDistSuspicious- "The 'license' is AllRightsReserved. Is that really what you want?"-- , checkVersion CabalSpecV1_4 (lic `notElem` compatLicenses) $- PackageDistInexcusable $- "Unfortunately the license " ++ quote (prettyShow (license pkg))- ++ " messes up the parser in earlier Cabal versions so you need to "- ++ "specify 'cabal-version: >= 1.4'. Alternatively if you require "- ++ "compatibility with earlier Cabal versions then use 'OtherLicense'."-- , case lic of- UnknownLicense l -> Just $- PackageBuildWarning $- quote ("license: " ++ l) ++ " is not a recognised license. The "- ++ "known licenses are: "- ++ commaSep (map prettyShow knownLicenses)- _ -> Nothing-- , check (lic == BSD4) $- PackageDistSuspicious $- "Using 'license: BSD4' is almost always a misunderstanding. 'BSD4' "- ++ "refers to the old 4-clause BSD license with the advertising "- ++ "clause. 'BSD3' refers the new 3-clause BSD license."-- , case unknownLicenseVersion (lic) of- Just knownVersions -> Just $- PackageDistSuspicious $- "'license: " ++ prettyShow (lic) ++ "' is not a known "- ++ "version of that license. The known versions are "- ++ commaSep (map prettyShow knownVersions)- ++ ". If this is not a mistake and you think it should be a known "- ++ "version then please file a ticket."- _ -> Nothing-- , check (lic `notElem` [ AllRightsReserved- , UnspecifiedLicense, PublicDomain]- -- AllRightsReserved and PublicDomain are not strictly- -- licenses so don't need license files.- && null (licenseFiles pkg)) $- PackageDistSuspicious "A 'license-file' is not specified."- ]- where- unknownLicenseVersion (GPL (Just v))- | v `notElem` knownVersions = Just knownVersions- where knownVersions = [ v' | GPL (Just v') <- knownLicenses ]- unknownLicenseVersion (LGPL (Just v))- | v `notElem` knownVersions = Just knownVersions- where knownVersions = [ v' | LGPL (Just v') <- knownLicenses ]- unknownLicenseVersion (AGPL (Just v))- | v `notElem` knownVersions = Just knownVersions- where knownVersions = [ v' | AGPL (Just v') <- knownLicenses ]- unknownLicenseVersion (Apache (Just v))- | v `notElem` knownVersions = Just knownVersions- where knownVersions = [ v' | Apache (Just v') <- knownLicenses ]- unknownLicenseVersion _ = Nothing-- checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck- checkVersion ver cond pc- | specVersion pkg >= ver = Nothing- | otherwise = check cond pc-- compatLicenses = [ GPL Nothing, LGPL Nothing, AGPL Nothing, BSD3, BSD4- , PublicDomain, AllRightsReserved- , UnspecifiedLicense, OtherLicense ]--checkSourceRepos :: PackageDescription -> [PackageCheck]-checkSourceRepos pkg =- catMaybes $ concat [[-- case repoKind repo of- RepoKindUnknown kind -> Just $ PackageDistInexcusable $- quote kind ++ " is not a recognised kind of source-repository. "- ++ "The repo kind is usually 'head' or 'this'"- _ -> Nothing-- , check (isNothing (repoType repo)) $- PackageDistInexcusable- "The source-repository 'type' is a required field."-- , check (isNothing (repoLocation repo)) $- PackageDistInexcusable- "The source-repository 'location' is a required field."-- , check (repoType repo == Just (KnownRepoType CVS) && isNothing (repoModule repo)) $- PackageDistInexcusable- "For a CVS source-repository, the 'module' is a required field."-- , check (repoKind repo == RepoThis && isNothing (repoTag repo)) $- PackageDistInexcusable $- "For the 'this' kind of source-repository, the 'tag' is a required "- ++ "field. It should specify the tag corresponding to this version "- ++ "or release of the package."-- , check (maybe False isAbsoluteOnAnyPlatform (repoSubdir repo)) $- PackageDistInexcusable- "The 'subdir' field of a source-repository must be a relative path."-- , check (maybe False isAbsoluteOnAnyPlatform (repoSubdir repo)) $- PackageDistInexcusable- "The 'subdir' field of a source-repository must be a relative path."-- , do- subdir <- repoSubdir repo- err <- isGoodRelativeDirectoryPath subdir- return $ PackageDistInexcusable $- "The 'subdir' field of a source-repository is not a good relative path: " ++ show err- ]- | repo <- sourceRepos pkg ]----TODO: check location looks like a URL for some repo types.---- | Checks GHC options from all ghc-*-options fields in the given--- PackageDescription and reports commonly misused or non-portable flags-checkAllGhcOptions :: PackageDescription -> [PackageCheck]-checkAllGhcOptions pkg =- checkGhcOptions "ghc-options" (hcOptions GHC) pkg- ++ checkGhcOptions "ghc-prof-options" (hcProfOptions GHC) pkg- ++ checkGhcOptions "ghc-shared-options" (hcSharedOptions GHC) pkg---- | Extracts GHC options belonging to the given field from the given--- PackageDescription using given function and checks them for commonly misused--- or non-portable flags-checkGhcOptions :: String -> (BuildInfo -> [String]) -> PackageDescription -> [PackageCheck]-checkGhcOptions fieldName getOptions pkg =- catMaybes [-- checkFlags ["-fasm"] $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -fasm' is unnecessary and will not work on CPU "- ++ "architectures other than x86, x86-64, ppc or sparc."-- , checkFlags ["-fvia-C"] $- PackageDistSuspicious $- "'" ++ fieldName ++": -fvia-C' is usually unnecessary. If your package "- ++ "needs -via-C for correctness rather than performance then it "- ++ "is using the FFI incorrectly and will probably not work with GHC "- ++ "6.10 or later."-- , checkFlags ["-fhpc"] $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -fhpc' is not necessary. Use the configure flag "- ++ " --enable-coverage instead."-- , checkFlags ["-prof"] $- PackageBuildWarning $- "'" ++ fieldName ++ ": -prof' is not necessary and will lead to problems "- ++ "when used on a library. Use the configure flag "- ++ "--enable-library-profiling and/or --enable-profiling."-- , checkFlags ["-o"] $- PackageBuildWarning $- "'" ++ fieldName ++ ": -o' is not needed. "- ++ "The output files are named automatically."-- , checkFlags ["-hide-package"] $- PackageBuildWarning $- "'" ++ fieldName ++ ": -hide-package' is never needed. "- ++ "Cabal hides all packages."-- , checkFlags ["--make"] $- PackageBuildWarning $- "'" ++ fieldName ++ ": --make' is never needed. Cabal uses this automatically."-- , checkFlags ["-main-is"] $- PackageDistSuspicious $- "'" ++ fieldName ++ ": -main-is' is not portable."-- , checkNonTestAndBenchmarkFlags ["-O0", "-Onot"] $- PackageDistSuspicious $- "'" ++ fieldName ++ ": -O0' is not needed. "- ++ "Use the --disable-optimization configure flag."-- , checkTestAndBenchmarkFlags ["-O0", "-Onot"] $- PackageDistSuspiciousWarn $- "'" ++ fieldName ++ ": -O0' is not needed. "- ++ "Use the --disable-optimization configure flag."-- , checkFlags [ "-O", "-O1"] $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -O' is not needed. "- ++ "Cabal automatically adds the '-O' flag. "- ++ "Setting it yourself interferes with the --disable-optimization flag."-- , checkFlags ["-O2"] $- PackageDistSuspiciousWarn $- "'" ++ fieldName ++ ": -O2' is rarely needed. "- ++ "Check that it is giving a real benefit "- ++ "and not just imposing longer compile times on your users."-- , checkFlags ["-split-sections"] $- PackageBuildWarning $- "'" ++ fieldName ++ ": -split-sections' is not needed. "- ++ "Use the --enable-split-sections configure flag."-- , checkFlags ["-split-objs"] $- PackageBuildWarning $- "'" ++ fieldName ++ ": -split-objs' is not needed. "- ++ "Use the --enable-split-objs configure flag."-- , checkFlags ["-optl-Wl,-s", "-optl-s"] $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -optl-Wl,-s' is not needed and is not portable to all"- ++ " operating systems. Cabal 1.4 and later automatically strip"- ++ " executables. Cabal also has a flag --disable-executable-stripping"- ++ " which is necessary when building packages for some Linux"- ++ " distributions and using '-optl-Wl,-s' prevents that from working."-- , checkFlags ["-fglasgow-exts"] $- PackageDistSuspicious $- "Instead of '" ++ fieldName ++ ": -fglasgow-exts' it is preferable to use "- ++ "the 'extensions' field."-- , check ("-threaded" `elem` lib_ghc_options) $- PackageBuildWarning $- "'" ++ fieldName ++ ": -threaded' has no effect for libraries. It should "- ++ "only be used for executables."-- , check ("-rtsopts" `elem` lib_ghc_options) $- PackageBuildWarning $- "'" ++ fieldName ++ ": -rtsopts' has no effect for libraries. It should "- ++ "only be used for executables."-- , check (any (\opt -> "-with-rtsopts" `isPrefixOf` opt) lib_ghc_options) $- PackageBuildWarning $- "'" ++ fieldName ++ ": -with-rtsopts' has no effect for libraries. It "- ++ "should only be used for executables."-- , checkAlternatives fieldName "extensions"- [ (flag, prettyShow extension) | flag <- all_ghc_options- , Just extension <- [ghcExtension flag] ]-- , checkAlternatives fieldName "extensions"- [ (flag, extension) | flag@('-':'X':extension) <- all_ghc_options ]-- , checkAlternatives fieldName "cpp-options" $- [ (flag, flag) | flag@('-':'D':_) <- all_ghc_options ]- ++ [ (flag, flag) | flag@('-':'U':_) <- all_ghc_options ]-- , checkAlternatives fieldName "include-dirs"- [ (flag, dir) | flag@('-':'I':dir) <- all_ghc_options ]-- , checkAlternatives fieldName "extra-libraries"- [ (flag, lib) | flag@('-':'l':lib) <- all_ghc_options ]-- , checkAlternatives fieldName "extra-lib-dirs"- [ (flag, dir) | flag@('-':'L':dir) <- all_ghc_options ]-- , checkAlternatives fieldName "frameworks"- [ (flag, fmwk) | (flag@"-framework", fmwk) <-- zip all_ghc_options (safeTail all_ghc_options) ]-- , checkAlternatives fieldName "extra-framework-dirs"- [ (flag, dir) | (flag@"-framework-path", dir) <-- zip all_ghc_options (safeTail all_ghc_options) ]- ]-- where- all_ghc_options = concatMap getOptions (allBuildInfo pkg)- lib_ghc_options = concatMap (getOptions . libBuildInfo)- (allLibraries pkg)- test_ghc_options = concatMap (getOptions . testBuildInfo)- (testSuites pkg)- benchmark_ghc_options = concatMap (getOptions . benchmarkBuildInfo)- (benchmarks pkg)- test_and_benchmark_ghc_options = test_ghc_options ++- benchmark_ghc_options- non_test_and_benchmark_ghc_options = concatMap getOptions- (allBuildInfo (pkg { testSuites = []- , benchmarks = []- }))-- checkFlags :: [String] -> PackageCheck -> Maybe PackageCheck- checkFlags flags = check (any (`elem` flags) all_ghc_options)-- checkTestAndBenchmarkFlags :: [String] -> PackageCheck -> Maybe PackageCheck- checkTestAndBenchmarkFlags flags = check (any (`elem` flags) test_and_benchmark_ghc_options)-- checkNonTestAndBenchmarkFlags :: [String] -> PackageCheck -> Maybe PackageCheck- checkNonTestAndBenchmarkFlags flags = check (any (`elem` flags) non_test_and_benchmark_ghc_options)-- ghcExtension ('-':'f':name) = case name of- "allow-overlapping-instances" -> enable OverlappingInstances- "no-allow-overlapping-instances" -> disable OverlappingInstances- "th" -> enable TemplateHaskell- "no-th" -> disable TemplateHaskell- "ffi" -> enable ForeignFunctionInterface- "no-ffi" -> disable ForeignFunctionInterface- "fi" -> enable ForeignFunctionInterface- "no-fi" -> disable ForeignFunctionInterface- "monomorphism-restriction" -> enable MonomorphismRestriction- "no-monomorphism-restriction" -> disable MonomorphismRestriction- "mono-pat-binds" -> enable MonoPatBinds- "no-mono-pat-binds" -> disable MonoPatBinds- "allow-undecidable-instances" -> enable UndecidableInstances- "no-allow-undecidable-instances" -> disable UndecidableInstances- "allow-incoherent-instances" -> enable IncoherentInstances- "no-allow-incoherent-instances" -> disable IncoherentInstances- "arrows" -> enable Arrows- "no-arrows" -> disable Arrows- "generics" -> enable Generics- "no-generics" -> disable Generics- "implicit-prelude" -> enable ImplicitPrelude- "no-implicit-prelude" -> disable ImplicitPrelude- "implicit-params" -> enable ImplicitParams- "no-implicit-params" -> disable ImplicitParams- "bang-patterns" -> enable BangPatterns- "no-bang-patterns" -> disable BangPatterns- "scoped-type-variables" -> enable ScopedTypeVariables- "no-scoped-type-variables" -> disable ScopedTypeVariables- "extended-default-rules" -> enable ExtendedDefaultRules- "no-extended-default-rules" -> disable ExtendedDefaultRules- _ -> Nothing- ghcExtension "-cpp" = enable CPP- ghcExtension _ = Nothing-- enable e = Just (EnableExtension e)- disable e = Just (DisableExtension e)--checkCCOptions :: PackageDescription -> [PackageCheck]-checkCCOptions = checkCLikeOptions "C" "cc-options" ccOptions--checkCxxOptions :: PackageDescription -> [PackageCheck]-checkCxxOptions = checkCLikeOptions "C++" "cxx-options" cxxOptions--checkCLikeOptions :: String -> String -> (BuildInfo -> [String]) -> PackageDescription -> [PackageCheck]-checkCLikeOptions label prefix accessor pkg =- catMaybes [-- checkAlternatives prefix "include-dirs"- [ (flag, dir) | flag@('-':'I':dir) <- all_cLikeOptions ]-- , checkAlternatives prefix "extra-libraries"- [ (flag, lib) | flag@('-':'l':lib) <- all_cLikeOptions ]-- , checkAlternatives prefix "extra-lib-dirs"- [ (flag, dir) | flag@('-':'L':dir) <- all_cLikeOptions ]-- , checkAlternatives "ld-options" "extra-libraries"- [ (flag, lib) | flag@('-':'l':lib) <- all_ldOptions ]-- , checkAlternatives "ld-options" "extra-lib-dirs"- [ (flag, dir) | flag@('-':'L':dir) <- all_ldOptions ]-- , checkCCFlags [ "-O", "-Os", "-O0", "-O1", "-O2", "-O3" ] $- PackageDistSuspicious $- "'"++prefix++": -O[n]' is generally not needed. When building with "- ++ " optimisations Cabal automatically adds '-O2' for "++label++" code. "- ++ "Setting it yourself interferes with the --disable-optimization flag."- ]-- where all_cLikeOptions = [ opts | bi <- allBuildInfo pkg- , opts <- accessor bi ]- all_ldOptions = [ opts | bi <- allBuildInfo pkg- , opts <- ldOptions bi ]-- checkCCFlags :: [String] -> PackageCheck -> Maybe PackageCheck- checkCCFlags flags = check (any (`elem` flags) all_cLikeOptions)--checkCPPOptions :: PackageDescription -> [PackageCheck]-checkCPPOptions pkg = catMaybes- [ checkAlternatives "cpp-options" "include-dirs"- [ (flag, dir) | flag@('-':'I':dir) <- all_cppOptions ]- ]- ++- [ PackageBuildWarning $ "'cpp-options': " ++ opt ++ " is not portable C-preprocessor flag"- | opt <- all_cppOptions- -- "-I" is handled above, we allow only -DNEWSTUFF and -UOLDSTUFF- , not $ any (`isPrefixOf` opt) ["-D", "-U", "-I" ]- ]- where- all_cppOptions = [ opts | bi <- allBuildInfo pkg, opts <- cppOptions bi ]--checkAlternatives :: String -> String -> [(String, String)]- -> Maybe PackageCheck-checkAlternatives badField goodField flags =- check (not (null badFlags)) $- PackageBuildWarning $- "Instead of " ++ quote (badField ++ ": " ++ unwords badFlags)- ++ " use " ++ quote (goodField ++ ": " ++ unwords goodFlags)-- where (badFlags, goodFlags) = unzip flags--data PathKind- = PathKindFile- | PathKindDirectory- | PathKindGlob--checkPaths :: PackageDescription -> [PackageCheck]-checkPaths pkg =- [ PackageBuildWarning $- quote (field ++ ": " ++ path)- ++ " is a relative path outside of the source tree. "- ++ "This will not work when generating a tarball with 'sdist'."- | (path, field, _) <- relPaths ++ absPaths- , isOutsideTree path ]- ++- [ PackageDistInexcusable $- quote (field ++ ": " ++ path) ++ " is an absolute path."- | (path, field, _) <- relPaths- , isAbsoluteOnAnyPlatform path ]- ++- [ PackageDistInexcusable $- quote (field ++ ": " ++ path) ++ " is not good relative path: " ++ err- | (path, field, kind) <- relPaths- -- these are not paths, but globs...- , err <- maybeToList $ case kind of- PathKindFile -> isGoodRelativeFilePath path- PathKindGlob -> isGoodRelativeGlob path- PathKindDirectory -> isGoodRelativeDirectoryPath path- ]- ++- [ PackageDistInexcusable $- quote (field ++ ": " ++ path) ++ " points inside the 'dist' "- ++ "directory. This is not reliable because the location of this "- ++ "directory is configurable by the user (or package manager). In "- ++ "addition the layout of the 'dist' directory is subject to change "- ++ "in future versions of Cabal."- | (path, field, _) <- relPaths ++ absPaths- , isInsideDist path ]- ++- [ PackageDistInexcusable $- "The 'ghc-options' contains the path '" ++ path ++ "' which points "- ++ "inside the 'dist' directory. This is not reliable because the "- ++ "location of this directory is configurable by the user (or package "- ++ "manager). In addition the layout of the 'dist' directory is subject "- ++ "to change in future versions of Cabal."- | bi <- allBuildInfo pkg- , (GHC, flags) <- perCompilerFlavorToList $ options bi- , path <- flags- , isInsideDist path ]- ++- [ PackageDistInexcusable $- "In the 'data-files' field: " ++ explainGlobSyntaxError pat err- | pat <- dataFiles pkg- , Left err <- [parseFileGlob (specVersion pkg) pat]- ]- ++- [ PackageDistInexcusable $- "In the 'extra-source-files' field: " ++ explainGlobSyntaxError pat err- | pat <- extraSrcFiles pkg- , Left err <- [parseFileGlob (specVersion pkg) pat]- ]- ++- [ PackageDistInexcusable $- "In the 'extra-doc-files' field: " ++ explainGlobSyntaxError pat err- | pat <- extraDocFiles pkg- , Left err <- [parseFileGlob (specVersion pkg) pat]- ]- where- isOutsideTree path = case splitDirectories path of- "..":_ -> True- ".":"..":_ -> True- _ -> False- isInsideDist path = case map lowercase (splitDirectories path) of- "dist" :_ -> True- ".":"dist":_ -> True- _ -> False-- -- paths that must be relative- relPaths :: [(FilePath, String, PathKind)]- relPaths =- [ (path, "extra-source-files", PathKindGlob) | path <- extraSrcFiles pkg ] ++- [ (path, "extra-tmp-files", PathKindFile) | path <- extraTmpFiles pkg ] ++- [ (path, "extra-doc-files", PathKindGlob) | path <- extraDocFiles pkg ] ++- [ (path, "data-files", PathKindGlob) | path <- dataFiles pkg ] ++- [ (path, "data-dir", PathKindDirectory) | path <- [dataDir pkg]] ++- [ (path, "license-file", PathKindFile) | path <- licenseFiles pkg ] ++- concat- [ [ (path, "asm-sources", PathKindFile) | path <- asmSources bi ] ++- [ (path, "cmm-sources", PathKindFile) | path <- cmmSources bi ] ++- [ (path, "c-sources", PathKindFile) | path <- cSources bi ] ++- [ (path, "cxx-sources", PathKindFile) | path <- cxxSources bi ] ++- [ (path, "js-sources", PathKindFile) | path <- jsSources bi ] ++- [ (path, "install-includes", PathKindFile) | path <- installIncludes bi ] ++- [ (path, "hs-source-dirs", PathKindDirectory) | path <- hsSourceDirs bi ]- | bi <- allBuildInfo pkg- ]-- -- paths that are allowed to be absolute- absPaths :: [(FilePath, String, PathKind)]- absPaths = concat- [ [ (path, "includes", PathKindFile) | path <- includes bi ] ++- [ (path, "include-dirs", PathKindDirectory) | path <- includeDirs bi ] ++- [ (path, "extra-lib-dirs", PathKindDirectory) | path <- extraLibDirs bi ]- | bi <- allBuildInfo pkg- ]----TODO: check sets of paths that would be interpreted differently between Unix--- and windows, ie case-sensitive or insensitive. Things that might clash, or--- conversely be distinguished.----TODO: use the tar path checks on all the above paths---- | Check that the package declares the version in the @\"cabal-version\"@--- field correctly.----checkCabalVersion :: PackageDescription -> [PackageCheck]-checkCabalVersion pkg =- catMaybes [-- -- check use of test suite sections- checkVersion CabalSpecV1_8 (not (null $ testSuites pkg)) $- PackageDistInexcusable $- "The 'test-suite' section is new in Cabal 1.10. "- ++ "Unfortunately it messes up the parser in older Cabal versions "- ++ "so you must specify at least 'cabal-version: >= 1.8', but note "- ++ "that only Cabal 1.10 and later can actually run such test suites."-- -- check use of default-language field- -- note that we do not need to do an equivalent check for the- -- other-language field since that one does not change behaviour- , checkVersion CabalSpecV1_10 (any isJust (buildInfoField defaultLanguage)) $- PackageBuildWarning $- "To use the 'default-language' field the package needs to specify "- ++ "at least 'cabal-version: >= 1.10'."-- , check (specVersion pkg >= CabalSpecV1_10 && specVersion pkg < CabalSpecV3_4- && (any isNothing (buildInfoField defaultLanguage))) $- PackageBuildWarning $- "Packages using 'cabal-version: >= 1.10' and before 'cabal-version: 3.4' must specify the "- ++ "'default-language' field for each component (e.g. Haskell98 or "- ++ "Haskell2010). If a component uses different languages in "- ++ "different modules then list the other ones in the "- ++ "'other-languages' field."-- , checkVersion CabalSpecV1_18- (not . null $ extraDocFiles pkg) $- PackageDistInexcusable $- "To use the 'extra-doc-files' field the package needs to specify "- ++ "at least 'cabal-version: >= 1.18'."-- , checkVersion CabalSpecV2_0- (not (null (subLibraries pkg))) $- PackageDistInexcusable $- "To use multiple 'library' sections or a named library section "- ++ "the package needs to specify at least 'cabal-version: 2.0'."-- -- check use of reexported-modules sections- , checkVersion CabalSpecV1_22- (any (not.null.reexportedModules) (allLibraries pkg)) $- PackageDistInexcusable $- "To use the 'reexported-module' field the package needs to specify "- ++ "at least 'cabal-version: >= 1.22'."-- -- check use of thinning and renaming- , checkVersion CabalSpecV2_0 usesBackpackIncludes $- PackageDistInexcusable $- "To use the 'mixins' field the package needs to specify "- ++ "at least 'cabal-version: 2.0'."-- -- check use of 'extra-framework-dirs' field- , checkVersion CabalSpecV1_24 (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.24'."-- -- check use of default-extensions field- -- don't need to do the equivalent check for other-extensions- , checkVersion CabalSpecV1_10 (any (not . null) (buildInfoField defaultExtensions)) $- PackageBuildWarning $- "To use the 'default-extensions' field the package needs to specify "- ++ "at least 'cabal-version: >= 1.10'."-- -- check use of extensions field- , check (specVersion pkg >= CabalSpecV1_10- && (any (not . null) (buildInfoField oldExtensions))) $- PackageBuildWarning $- "For packages using 'cabal-version: >= 1.10' the 'extensions' "- ++ "field is deprecated. The new 'default-extensions' field lists "- ++ "extensions that are used in all modules in the component, while "- ++ "the 'other-extensions' field lists extensions that are used in "- ++ "some modules, e.g. via the {-# LANGUAGE #-} pragma."-- , checkVersion CabalSpecV3_0 (any (not . null)- (concatMap buildInfoField- [ asmSources- , cmmSources- , extraBundledLibs- , extraLibFlavours ])) $- PackageDistInexcusable $- "The use of 'asm-sources', 'cmm-sources', 'extra-bundled-libraries' "- ++ " and 'extra-library-flavours' requires the package "- ++ " to specify at least 'cabal-version: 3.0'."-- , checkVersion CabalSpecV3_0 (any (not . null) $ buildInfoField extraDynLibFlavours) $- PackageDistInexcusable $- "The use of 'extra-dynamic-library-flavours' requires the package "- ++ " to specify at least 'cabal-version: 3.0'. The flavours are: "- ++ commaSep [ flav- | flavs <- buildInfoField extraDynLibFlavours- , flav <- flavs ]-- , checkVersion CabalSpecV2_2 (any (not . null)- (buildInfoField virtualModules)) $- PackageDistInexcusable $- "The use of 'virtual-modules' requires the package "- ++ " to specify at least 'cabal-version: 2.2'."-- -- check use of "source-repository" section- , checkVersion CabalSpecV1_6 (not (null (sourceRepos pkg))) $- PackageDistInexcusable $- "The 'source-repository' section is new in Cabal 1.6. "- ++ "Unfortunately it messes up the parser in earlier Cabal versions "- ++ "so you need to specify 'cabal-version: >= 1.6'."-- -- check for new language extensions- , checkVersion CabalSpecV1_4 (not (null mentionedExtensionsThatNeedCabal12)) $- PackageDistInexcusable $- "Unfortunately the language extensions "- ++ commaSep (map (quote . prettyShow) mentionedExtensionsThatNeedCabal12)- ++ " break the parser in earlier Cabal versions so you need to "- ++ "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."-- , checkVersion CabalSpecV1_4 (not (null mentionedExtensionsThatNeedCabal14)) $- PackageDistInexcusable $- "Unfortunately the language extensions "- ++ commaSep (map (quote . prettyShow) mentionedExtensionsThatNeedCabal14)- ++ " break the parser in earlier Cabal versions so you need to "- ++ "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 >= CabalSpecV1_24- && isNothing (setupBuildInfo pkg)- && buildType pkg == Custom) $- PackageBuildWarning $- "Packages using 'cabal-version: >= 1.24' 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 < CabalSpecV1_24- && isNothing (setupBuildInfo pkg)- && buildType pkg == Custom) $- PackageDistSuspiciousWarn $- "From version 1.24 cabal supports specifying explicit dependencies "- ++ "for Custom setup scripts. Consider using cabal-version >= 1.24 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'."-- , check (specVersion pkg >= CabalSpecV2_0- && elem (autogenPathsModuleName pkg) allModuleNames- && not (elem (autogenPathsModuleName pkg) allModuleNamesAutogen) ) $- PackageDistInexcusable $- "Packages using 'cabal-version: 2.0' and the autogenerated "- ++ "module Paths_* must include it also on the 'autogen-modules' field "- ++ "besides 'exposed-modules' and 'other-modules'. This specifies that "- ++ "the module does not come with the package and is generated on "- ++ "setup. Modules built with a custom Setup.hs script also go here "- ++ "to ensure that commands like sdist don't fail."-- ]- where- -- Perform a check on packages that use a version of the spec less than- -- the version given. This is for cases where a new Cabal version adds- -- a new feature and we want to check that it is not used prior to that- -- version.- checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck- checkVersion ver cond pc- | specVersion pkg >= ver = Nothing- | otherwise = check cond pc-- buildInfoField field = map field (allBuildInfo pkg)-- usesBackpackIncludes = any (not . null . mixins) (allBuildInfo pkg)-- mentionedExtensions = [ ext | bi <- allBuildInfo pkg- , ext <- allExtensions bi ]- mentionedExtensionsThatNeedCabal12 =- nub (filter (`elem` compatExtensionsExtra) mentionedExtensions)-- -- As of Cabal-1.4 we can add new extensions without worrying about- -- breaking old versions of cabal.- mentionedExtensionsThatNeedCabal14 =- nub (filter (`notElem` compatExtensions) mentionedExtensions)-- -- The known extensions in Cabal-1.2.3- compatExtensions =- map EnableExtension- [ OverlappingInstances, UndecidableInstances, IncoherentInstances- , RecursiveDo, ParallelListComp, MultiParamTypeClasses- , FunctionalDependencies, Rank2Types- , RankNTypes, PolymorphicComponents, ExistentialQuantification- , ScopedTypeVariables, ImplicitParams, FlexibleContexts- , FlexibleInstances, EmptyDataDecls, CPP, BangPatterns- , TypeSynonymInstances, TemplateHaskell, ForeignFunctionInterface- , Arrows, Generics, NamedFieldPuns, PatternGuards- , GeneralizedNewtypeDeriving, ExtensibleRecords, RestrictedTypeSynonyms- , HereDocuments] ++- map DisableExtension- [MonomorphismRestriction, ImplicitPrelude] ++- compatExtensionsExtra-- -- The extra known extensions in Cabal-1.2.3 vs Cabal-1.1.6- -- (Cabal-1.1.6 came with ghc-6.6. Cabal-1.2 came with ghc-6.8)- compatExtensionsExtra =- map EnableExtension- [ KindSignatures, MagicHash, TypeFamilies, StandaloneDeriving- , UnicodeSyntax, PatternSignatures, UnliftedFFITypes, LiberalTypeSynonyms- , TypeOperators, RecordWildCards, RecordPuns, DisambiguateRecordFields- , OverloadedStrings, GADTs, RelaxedPolyRec- , ExtendedDefaultRules, UnboxedTuples, DeriveDataTypeable- , ConstrainedClassMethods- ] ++- map DisableExtension- [MonoPatBinds]-- allModuleNames =- (case library pkg of- Nothing -> []- (Just lib) -> explicitLibModules lib- )- ++ concatMap otherModules (allBuildInfo pkg)-- allModuleNamesAutogen = concatMap autogenModules (allBuildInfo pkg)---- --------------------------------------------------------------- * Checks on the GenericPackageDescription--- ---------------------------------------------------------------- | Check the build-depends fields for any weirdness or bad practice.----checkPackageVersions :: GenericPackageDescription -> [PackageCheck]-checkPackageVersions pkg =- catMaybes [-- -- Check that the version of base is bounded above.- -- For example this bans "build-depends: base >= 3".- -- It should probably be "build-depends: base >= 3 && < 4"- -- which is the same as "build-depends: base == 3.*"- check (not (boundedAbove baseDependency)) $- PackageDistInexcusable $- "The dependency 'build-depends: base' does not specify an upper "- ++ "bound on the version number. Each major release of the 'base' "- ++ "package changes the API in various ways and most packages will "- ++ "need some changes to compile with it. The recommended practice "- ++ "is to specify an upper bound on the version of the 'base' "- ++ "package. This ensures your package will continue to build when a "- ++ "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 4.5 and 4.6 then use 'build-depends: base >= 4.5 && < 4.7'."-- ]- where- -- TODO: What we really want to do is test if there exists any- -- configuration in which the base version is unbounded above.- -- However that's a bit tricky because there are many possible- -- configurations. As a cheap easy and safe approximation we will- -- pick a single "typical" configuration and check if that has an- -- open upper bound. To get a typical configuration we finalise- -- using no package index and the current platform.- finalised = finalizePD- mempty defaultComponentRequestedSpec (const True)- buildPlatform- (unknownCompilerInfo- (CompilerId buildCompilerFlavor nullVersion)- NoAbiTag)- [] pkg- baseDependency = case finalised of- Right (pkg', _) | not (null baseDeps) ->- foldr intersectVersionRanges anyVersion baseDeps- where- baseDeps =- [ vr | Dependency pname vr _ <- allBuildDepends pkg'- , pname == mkPackageName "base" ]-- -- Just in case finalizePD fails for any reason,- -- or if the package doesn't depend on the base package at all,- -- then we will just skip the check, since boundedAbove noVersion = True- _ -> noVersion-- boundedAbove :: VersionRange -> Bool- boundedAbove vr = case asVersionIntervals vr of- [] -> True -- this is the inconsistent version range.- (x:xs) -> case last (x:|xs) of- (_, UpperBound _ _) -> True- (_, NoUpperBound ) -> False---checkConditionals :: GenericPackageDescription -> [PackageCheck]-checkConditionals pkg =- catMaybes [-- check (not $ null unknownOSs) $- PackageDistInexcusable $- "Unknown operating system name "- ++ commaSep (map quote unknownOSs)-- , check (not $ null unknownArches) $- PackageDistInexcusable $- "Unknown architecture name "- ++ commaSep (map quote unknownArches)-- , check (not $ null unknownImpls) $- PackageDistInexcusable $- "Unknown compiler name "- ++ commaSep (map quote unknownImpls)- ]- where- unknownOSs = [ os | OS (OtherOS os) <- conditions ]- unknownArches = [ arch | Arch (OtherArch arch) <- conditions ]- unknownImpls = [ impl | Impl (OtherCompiler impl) _ <- conditions ]- conditions = concatMap fvs (maybeToList (condLibrary pkg))- ++ concatMap (fvs . snd) (condSubLibraries pkg)- ++ concatMap (fvs . snd) (condForeignLibs pkg)- ++ concatMap (fvs . snd) (condExecutables pkg)- ++ concatMap (fvs . snd) (condTestSuites pkg)- ++ concatMap (fvs . snd) (condBenchmarks pkg)- fvs (CondNode _ _ ifs) = concatMap compfv ifs -- free variables- compfv (CondBranch c ct mct) = condfv c ++ fvs ct ++ maybe [] fvs mct- condfv c = case c of- Var v -> [v]- Lit _ -> []- CNot c1 -> condfv c1- COr c1 c2 -> condfv c1 ++ condfv c2- CAnd c1 c2 -> condfv c1 ++ condfv c2--checkFlagNames :: GenericPackageDescription -> [PackageCheck]-checkFlagNames gpd- | null invalidFlagNames = []- | otherwise = [ PackageDistInexcusable- $ "Suspicious flag names: " ++ unwords invalidFlagNames ++ ". "- ++ "To avoid ambiguity in command line interfaces, flag shouldn't "- ++ "start with a dash. Also for better compatibility, flag names "- ++ "shouldn't contain non-ascii characters."- ]- where- invalidFlagNames =- [ fn- | flag <- genPackageFlags gpd- , let fn = unFlagName (flagName flag)- , invalidFlagName fn- ]- -- starts with dash- invalidFlagName ('-':_) = True- -- mon ascii letter- invalidFlagName cs = any (not . isAscii) cs--checkUnusedFlags :: GenericPackageDescription -> [PackageCheck]-checkUnusedFlags gpd- | declared == used = []- | otherwise = [ PackageDistSuspicious- $ "Declared and used flag sets differ: "- ++ s declared ++ " /= " ++ s used ++ ". "- ]- where- s :: Set.Set FlagName -> String- s = commaSep . map unFlagName . Set.toList-- declared :: Set.Set FlagName- declared = toSetOf (L.genPackageFlags . traverse . L.flagName) gpd-- used :: Set.Set FlagName- used = mconcat- [ toSetOf (L.condLibrary . traverse . traverseCondTreeV . L._PackageFlag) gpd- , toSetOf (L.condSubLibraries . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd- , toSetOf (L.condForeignLibs . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd- , toSetOf (L.condExecutables . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd- , toSetOf (L.condTestSuites . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd- , toSetOf (L.condBenchmarks . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd- ]--checkUnicodeXFields :: GenericPackageDescription -> [PackageCheck]-checkUnicodeXFields gpd- | null nonAsciiXFields = []- | otherwise = [ PackageDistInexcusable- $ "Non ascii custom fields: " ++ unwords nonAsciiXFields ++ ". "- ++ "For better compatibility, custom field names "- ++ "shouldn't contain non-ascii characters."- ]- where- nonAsciiXFields :: [String]- nonAsciiXFields = [ n | (n, _) <- xfields, any (not . isAscii) n ]-- xfields :: [(String,String)]- xfields = DList.runDList $ mconcat- [ toDListOf (L.packageDescription . L.customFieldsPD . traverse) gpd- , toDListOf (L.traverseBuildInfos . L.customFieldsBI . traverse) gpd- ]---- | cabal-version <2.2 + Paths_module + default-extensions: doesn't build.-checkPathsModuleExtensions :: PackageDescription -> [PackageCheck]-checkPathsModuleExtensions pd- | specVersion pd >= CabalSpecV2_2 = []- | any checkBI (allBuildInfo pd) || any checkLib (allLibraries pd)- = return $ PackageBuildImpossible $ unwords- [ "The package uses RebindableSyntax with OverloadedStrings or OverloadedLists"- , "in default-extensions, and also Paths_ autogen module."- , "That configuration is known to cause compile failures with Cabal < 2.2."- , "To use these default-extensions with Paths_ autogen module"- , "specify at least 'cabal-version: 2.2'."- ]- | otherwise = []- where- mn = autogenPathsModuleName pd-- checkLib :: Library -> Bool- checkLib l = mn `elem` exposedModules l && checkExts (l ^. L.defaultExtensions)-- checkBI :: BuildInfo -> Bool- checkBI bi =- (mn `elem` otherModules bi || mn `elem` autogenModules bi) &&- checkExts (bi ^. L.defaultExtensions)-- checkExts exts = rebind `elem` exts && (strings `elem` exts || lists `elem` exts)- where- rebind = EnableExtension RebindableSyntax- strings = EnableExtension OverloadedStrings- lists = EnableExtension OverloadedLists---- | Checks GHC options from all ghc-*-options fields from the given BuildInfo--- and reports flags that are OK during development process, but are--- unacceptable in a distrubuted package-checkDevelopmentOnlyFlagsBuildInfo :: BuildInfo -> [PackageCheck]-checkDevelopmentOnlyFlagsBuildInfo bi =- checkDevelopmentOnlyFlagsOptions "ghc-options" (hcOptions GHC bi)- ++ checkDevelopmentOnlyFlagsOptions "ghc-prof-options" (hcProfOptions GHC bi)- ++ checkDevelopmentOnlyFlagsOptions "ghc-shared-options" (hcSharedOptions GHC bi)---- | Checks the given list of flags belonging to the given field and reports--- flags that are OK during development process, but are unacceptable in a--- distributed package-checkDevelopmentOnlyFlagsOptions :: String -> [String] -> [PackageCheck]-checkDevelopmentOnlyFlagsOptions fieldName ghcOptions =- catMaybes [-- check has_WerrorWall $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -Wall -Werror' makes the package very easy to "- ++ "break with future GHC versions because new GHC versions often "- ++ "add new warnings. Use just '" ++ fieldName ++ ": -Wall' instead."- ++ extraExplanation-- , check (not has_WerrorWall && has_Werror) $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -Werror' makes the package easy to "- ++ "break with future GHC versions because new GHC versions often "- ++ "add new warnings. "- ++ extraExplanation-- , check (has_J) $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -j[N]' can make sense for specific user's setup,"- ++ " but it is not appropriate for a distributed package."- ++ extraExplanation-- , checkFlags ["-fdefer-type-errors"] $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -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")- ghcOptions) $- PackageDistInexcusable $- "'" ++ fieldName ++ ": -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 $- "'" ++ fieldName ++ ": -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` ghcOptions- has_Wall = "-Wall" `elem` ghcOptions- has_W = "-W" `elem` ghcOptions- has_J = any- (\o -> case o of- "-j" -> True- ('-' : 'j' : d : _) -> isDigit d- _ -> False- )- ghcOptions- checkFlags :: [String] -> PackageCheck -> Maybe PackageCheck- checkFlags flags = check (any (`elem` flags) ghcOptions)--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 (PackageFlag 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 (PackageFlag 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 libBuildInfo . snd)- (condSubLibraries 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- | (CondBranch condition ifThen _) <- condTreeComponents condNode ]-- ++ concat- [ go (condition:conditions) elseThen- | (CondBranch condition _ (Just elseThen)) <- condTreeComponents condNode ]----- --------------------------------------------------------------- * Checks involving files in the package--- ---------------------------------------------------------------- | Sanity check things that requires IO. It looks at the files in the--- package and expects to find the package unpacked in at the given file path.----checkPackageFiles :: Verbosity -> PackageDescription -> FilePath -> IO [PackageCheck]-checkPackageFiles verbosity pkg root = do- contentChecks <- checkPackageContent checkFilesIO pkg- preDistributionChecks <- checkPackageFilesPreDistribution verbosity pkg root- -- Sort because different platforms will provide files from- -- `getDirectoryContents` in different orders, and we'd like to be- -- stable for test output.- return (sort contentChecks ++ sort preDistributionChecks)- where- checkFilesIO = CheckPackageContentOps {- doesFileExist = System.doesFileExist . relative,- doesDirectoryExist = System.doesDirectoryExist . relative,- getDirectoryContents = System.Directory.getDirectoryContents . relative,- getFileContents = BS.readFile . relative- }- relative path = root </> path---- | A record of operations needed to check the contents of packages.--- Used by 'checkPackageContent'.----data CheckPackageContentOps m = CheckPackageContentOps {- doesFileExist :: FilePath -> m Bool,- doesDirectoryExist :: FilePath -> m Bool,- getDirectoryContents :: FilePath -> m [FilePath],- getFileContents :: FilePath -> m BS.ByteString- }---- | Sanity check things that requires looking at files in the package.--- This is a generalised version of 'checkPackageFiles' that can work in any--- monad for which you can provide 'CheckPackageContentOps' operations.------ The point of this extra generality is to allow doing checks in some virtual--- file system, for example a tarball in memory.----checkPackageContent :: (Monad m, Applicative m)- => CheckPackageContentOps m- -> PackageDescription- -> m [PackageCheck]-checkPackageContent ops pkg = do- cabalBomError <- checkCabalFileBOM ops- cabalNameError <- checkCabalFileName ops pkg- licenseErrors <- checkLicensesExist ops pkg- setupError <- checkSetupExists ops pkg- configureError <- checkConfigureExists ops pkg- localPathErrors <- checkLocalPathsExist ops pkg- vcsLocation <- checkMissingVcsInfo ops pkg-- return $ licenseErrors- ++ catMaybes [cabalBomError, cabalNameError, setupError, configureError]- ++ localPathErrors- ++ vcsLocation--checkCabalFileBOM :: Monad m => CheckPackageContentOps m- -> m (Maybe PackageCheck)-checkCabalFileBOM ops = do- epdfile <- findPackageDesc ops- case epdfile of- -- MASSIVE HACK. If the Cabal file doesn't exist, that is- -- a very strange situation to be in, because the driver code- -- in 'Distribution.Setup' ought to have noticed already!- -- But this can be an issue, see #3552 and also when- -- --cabal-file is specified. So if you can't find the file,- -- just don't bother with this check.- Left _ -> return $ Nothing- Right pdfile -> (flip check pc . BS.isPrefixOf bomUtf8)- `liftM` (getFileContents ops pdfile)- where pc = PackageDistInexcusable $- pdfile ++ " starts with an Unicode byte order mark (BOM)."- ++ " This may cause problems with older cabal versions."-- where- bomUtf8 :: BS.ByteString- bomUtf8 = BS.pack [0xef,0xbb,0xbf] -- U+FEFF encoded as UTF8--checkCabalFileName :: Monad m => CheckPackageContentOps m- -> PackageDescription- -> m (Maybe PackageCheck)-checkCabalFileName ops pkg = do- -- findPackageDesc already takes care to detect missing/multiple- -- .cabal files; we don't include this check in 'findPackageDesc' in- -- order not to short-cut other checks which call 'findPackageDesc'- epdfile <- findPackageDesc ops- case epdfile of- -- see "MASSIVE HACK" note in 'checkCabalFileBOM'- Left _ -> return Nothing- Right pdfile- | takeFileName pdfile == expectedCabalname -> return Nothing- | otherwise -> return $ Just $ PackageDistInexcusable $- "The filename " ++ pdfile ++ " does not match package name " ++- "(expected: " ++ expectedCabalname ++ ")"- where- pkgname = unPackageName . packageName $ pkg- expectedCabalname = pkgname <.> "cabal"----- |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 while checking.\n"- ++ "Please use only one of: "- ++ intercalate ", " l--checkLicensesExist :: (Monad m, Applicative m)- => CheckPackageContentOps m- -> PackageDescription- -> m [PackageCheck]-checkLicensesExist ops pkg = do- exists <- traverse (doesFileExist ops) (licenseFiles pkg)- return- [ PackageBuildWarning $- "The '" ++ fieldname ++ "' field refers to the file "- ++ quote file ++ " which does not exist."- | (file, False) <- zip (licenseFiles pkg) exists ]- where- fieldname | length (licenseFiles pkg) == 1 = "license-file"- | otherwise = "license-files"--checkSetupExists :: Monad m => CheckPackageContentOps m- -> PackageDescription- -> m (Maybe PackageCheck)-checkSetupExists ops pkg = do- let simpleBuild = buildType pkg == Simple- hsexists <- doesFileExist ops "Setup.hs"- lhsexists <- doesFileExist ops "Setup.lhs"- return $ check (not simpleBuild && not hsexists && not lhsexists) $- PackageDistInexcusable $- "The package is missing a Setup.hs or Setup.lhs script."--checkConfigureExists :: Monad m => CheckPackageContentOps m- -> PackageDescription- -> m (Maybe PackageCheck)-checkConfigureExists ops pd- | buildType pd == Configure = do- exists <- doesFileExist ops "configure"- return $ check (not exists) $- PackageBuildWarning $- "The 'build-type' is 'Configure' but there is no 'configure' script. "- ++ "You probably need to run 'autoreconf -i' to generate it."- | otherwise = return Nothing--checkLocalPathsExist :: Monad m => CheckPackageContentOps m- -> PackageDescription- -> m [PackageCheck]-checkLocalPathsExist ops pkg = do- let dirs = [ (dir, kind)- | 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 ]- , isRelativeOnAnyPlatform dir ]- missing <- filterM (liftM not . doesDirectoryExist ops . fst) dirs- return [ PackageBuildWarning {- explanation = quote (kind ++ ": " ++ dir)- ++ " directory does not exist."- }- | (dir, kind) <- missing ]--checkMissingVcsInfo :: (Monad m, Applicative m)- => CheckPackageContentOps m- -> PackageDescription- -> m [PackageCheck]-checkMissingVcsInfo ops pkg | null (sourceRepos pkg) = do- vcsInUse <- liftM or $ traverse (doesDirectoryExist ops) repoDirnames- if vcsInUse- then return [ PackageDistSuspicious message ]- else return []- where- repoDirnames = [ dirname | repo <- knownRepoTypes- , dirname <- repoTypeDirname repo]- message = "When distributing packages it is encouraged to specify source "- ++ "control information in the .cabal file using one or more "- ++ "'source-repository' sections. See the Cabal user guide for "- ++ "details."--checkMissingVcsInfo _ _ = return []--repoTypeDirname :: KnownRepoType -> [FilePath]-repoTypeDirname Darcs = ["_darcs"]-repoTypeDirname Git = [".git"]-repoTypeDirname SVN = [".svn"]-repoTypeDirname CVS = ["CVS"]-repoTypeDirname Mercurial = [".hg"]-repoTypeDirname GnuArch = [".arch-params"]-repoTypeDirname Bazaar = [".bzr"]-repoTypeDirname Monotone = ["_MTN"]-repoTypeDirname Pijul = [".pijul"]---- --------------------------------------------------------------- * Checks involving files in the package--- ---------------------------------------------------------------- | Check the names of all files in a package for portability problems. This--- should be done for example when creating or validating a package tarball.----checkPackageFileNames :: [FilePath] -> [PackageCheck]-checkPackageFileNames 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.--checkWindowsPath :: FilePath -> Maybe PackageCheck-checkWindowsPath path =- check (not $ FilePath.Windows.isValid path') $- PackageDistInexcusable $- "Unfortunately, the file " ++ quote path ++ " is not a valid file "- ++ "name on Windows which would cause portability problems for this "- ++ "package. Windows file names cannot contain any of the characters "- ++ "\":*?<>|\" and there are a few reserved names including \"aux\", "- ++ "\"nul\", \"con\", \"prn\", \"com1-9\", \"lpt1-9\" and \"clock$\"."- where- path' = ".\\" ++ path- -- force a relative name to catch invalid file names like "f:oo" which- -- otherwise parse as file "oo" in the current directory on the 'f' drive.---- | Check a file name is valid for the portable POSIX tar format.------ The POSIX tar format has a restriction on the length of file names. It is--- unfortunately not a simple restriction like a maximum length. The exact--- restriction is that either the whole path be 100 characters or less, or it--- be possible to split the path on a directory separator such that the first--- part is 155 characters or less and the second part 100 characters or less.----checkTarPath :: FilePath -> Maybe PackageCheck-checkTarPath path- | length path > 255 = Just longPath- | otherwise = case pack nameMax (reverse (splitPath path)) of- Left err -> Just err- Right [] -> Nothing- Right (h:rest) -> case pack prefixMax remainder of- Left err -> Just err- Right [] -> Nothing- Right (_:_) -> Just noSplit- where- -- drop the '/' between the name and prefix:- remainder = safeInit h : rest-- where- nameMax, prefixMax :: Int- nameMax = 100- prefixMax = 155-- pack _ [] = Left emptyName- pack maxLen (c:cs)- | n > maxLen = Left longName- | otherwise = Right (pack' maxLen n cs)- where n = length c-- pack' maxLen n (c:cs)- | n' <= maxLen = pack' maxLen n' cs- where n' = n + length c- pack' _ _ cs = cs-- longPath = PackageDistInexcusable $- "The following file name is too long to store in a portable POSIX "- ++ "format tar archive. The maximum length is 255 ASCII characters.\n"- ++ "The file in question is:\n " ++ path- longName = PackageDistInexcusable $- "The following file name is too long to store in a portable POSIX "- ++ "format tar archive. The maximum length for the name part (including "- ++ "extension) is 100 ASCII characters. The maximum length for any "- ++ "individual directory component is 155.\n"- ++ "The file in question is:\n " ++ path- noSplit = PackageDistInexcusable $- "The following file name is too long to store in a portable POSIX "- ++ "format tar archive. While the total length is less than 255 ASCII "- ++ "characters, there are unfortunately further restrictions. It has to "- ++ "be possible to split the file path on a directory separator into "- ++ "two parts such that the first part fits in 155 characters or less "- ++ "and the second part fits in 100 characters or less. Basically you "- ++ "have to make the file name or directory names shorter, or you could "- ++ "split a long directory name into nested subdirectories with shorter "- ++ "names.\nThe file in question is:\n " ++ path- emptyName = PackageDistInexcusable $- "Encountered a file with an empty name, something is very wrong! "- ++ "Files with an empty name cannot be stored in a tar archive or in "- ++ "standard file systems."---- ----------------------------------------------------------------- * Checks for missing content and other pre-distribution checks--- ------------------------------------------------------------------ | Similar to 'checkPackageContent', 'checkPackageFilesPreDistribution'--- inspects the files included in the package, but is primarily looking for--- files in the working tree that may have been missed or other similar--- problems that can only be detected pre-distribution.------ Because Hackage necessarily checks the uploaded tarball, it is too late to--- check these on the server; these checks only make sense in the development--- and package-creation environment. Hence we can use IO, rather than needing--- to pass a 'CheckPackageContentOps' dictionary around.-checkPackageFilesPreDistribution :: Verbosity -> PackageDescription -> FilePath -> IO [PackageCheck]--- Note: this really shouldn't return any 'Inexcusable' warnings,--- because that will make us say that Hackage would reject the package.--- But, because Hackage doesn't run these tests, that will be a lie!-checkPackageFilesPreDistribution = checkGlobFiles---- | Discover problems with the package's wildcards.-checkGlobFiles :: Verbosity- -> PackageDescription- -> FilePath- -> IO [PackageCheck]-checkGlobFiles verbosity pkg root =- fmap concat $ for allGlobs $ \(field, dir, glob) ->- -- Note: we just skip over parse errors here; they're reported elsewhere.- case parseFileGlob (specVersion pkg) glob of- Left _ -> return []- Right parsedGlob -> do- results <- runDirFileGlob verbosity (root </> dir) parsedGlob- let individualWarnings = results >>= getWarning field glob- noMatchesWarning =- [ PackageDistSuspiciousWarn $- "In '" ++ field ++ "': the pattern '" ++ glob ++ "' does not"- ++ " match any files."- | all (not . suppressesNoMatchesWarning) results- ]- return (noMatchesWarning ++ individualWarnings)- where- adjustedDataDir = if null (dataDir pkg) then "." else dataDir pkg- allGlobs = concat- [ (,,) "extra-source-files" "." <$> extraSrcFiles pkg- , (,,) "extra-doc-files" "." <$> extraDocFiles pkg- , (,,) "data-files" adjustedDataDir <$> dataFiles pkg- ]-- -- If there's a missing directory in play, since our globs don't- -- (currently) support disjunction, that will always mean there are no- -- matches. The no matches error in this case is strictly less informative- -- than the missing directory error, so sit on it.- suppressesNoMatchesWarning (GlobMatch _) = True- suppressesNoMatchesWarning (GlobWarnMultiDot _) = False- suppressesNoMatchesWarning (GlobMissingDirectory _) = True-- getWarning :: String -> FilePath -> GlobResult FilePath -> [PackageCheck]- getWarning _ _ (GlobMatch _) =- []- -- Before Cabal 2.4, the extensions of globs had to match the file- -- exactly. This has been relaxed in 2.4 to allow matching only the- -- suffix. This warning detects when pre-2.4 package descriptions are- -- omitting files purely because of the stricter check.- getWarning field glob (GlobWarnMultiDot file) =- [ PackageDistSuspiciousWarn $- "In '" ++ field ++ "': the pattern '" ++ glob ++ "' does not"- ++ " match the file '" ++ file ++ "' because the extensions do not"- ++ " exactly match (e.g., foo.en.html does not exactly match *.html)."- ++ " To enable looser suffix-only matching, set 'cabal-version: 2.4' or higher."- ]- getWarning field glob (GlobMissingDirectory dir) =- [ PackageDistSuspiciousWarn $- "In '" ++ field ++ "': the pattern '" ++ glob ++ "' attempts to"- ++ " match files in the directory '" ++ dir ++ "', but there is no"- ++ " directory by that name."- ]---- --------------------------------------------------------------- * Utils--- --------------------------------------------------------------quote :: String -> String-quote s = "'" ++ s ++ "'"--commaSep :: [String] -> String-commaSep = intercalate ", "--dups :: Ord a => [a] -> [a]-dups xs = [ x | (x:_:_) <- group (sort xs) ]--fileExtensionSupportedLanguage :: FilePath -> Bool-fileExtensionSupportedLanguage path =- isHaskell || isC- where- extension = takeExtension path- isHaskell = extension `elem` [".hs", ".lhs"]- isC = isJust (filenameCDialect extension)---- | Whether a path is a good relative path.------ >>> let test fp = putStrLn $ show (isGoodRelativeDirectoryPath fp) ++ "; " ++ show (isGoodRelativeFilePath fp)------ >>> test "foo/bar/quu"--- Nothing; Nothing------ Trailing slash is not allowed for files, for directories it is ok.------ >>> test "foo/"--- Nothing; Just "trailing slash"------ Leading @./@ is fine, but @.@ and @./@ are not valid files.------ >>> traverse_ test [".", "./", "./foo/bar"]--- Nothing; Just "trailing dot segment"--- Nothing; Just "trailing slash"--- Nothing; Nothing------ Lastly, not good file nor directory cases:------ >>> traverse_ test ["", "/tmp/src", "foo//bar", "foo/.", "foo/./bar", "foo/../bar", "foo*bar"]--- Just "empty path"; Just "empty path"--- Just "posix absolute path"; Just "posix absolute path"--- Just "empty path segment"; Just "empty path segment"--- Just "trailing same directory segment: ."; Just "trailing same directory segment: ."--- Just "same directory segment: ."; Just "same directory segment: .."--- Just "parent directory segment: .."; Just "parent directory segment: .."--- Just "reserved character '*'"; Just "reserved character '*'"------ For the last case, 'isGoodRelativeGlob' doesn't warn:------ >>> traverse_ (print . isGoodRelativeGlob) ["foo/../bar", "foo*bar"]--- Just "parent directory segment: .."--- Nothing----isGoodRelativeFilePath :: FilePath -> Maybe String-isGoodRelativeFilePath = state0- where- -- Reserved characters- -- https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file- isReserved c = c `elem` "<>:\"\\/|?*"-- -- initial state- state0 [] = Just "empty path"- state0 (c:cs) | c == '.' = state1 cs- | c == '/' = Just "posix absolute path"- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state3 cs-- -- after .- state1 [] = Just "trailing dot segment"- state1 (c:cs) | c == '.' = state4 cs- | c == '/' = state2 cs- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state5 cs-- -- after ./- state2 [] = Just "trailing slash"- state2 (c:cs) | c == '.' = state3 cs- | c == '/' = Just "empty path segment"- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state5 cs-- -- after non-first segment's .- state3 [] = Just "trailing same directory segment: ."- state3 (c:cs) | c == '.' = state4 cs- | c == '/' = Just "same directory segment: .."- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state5 cs-- -- after non-first segment's ..- state4 [] = Just "trailing parent directory segment: .."- state4 (c:cs) | c == '.' = state5 cs- | c == '/' = Just "parent directory segment: .."- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state5 cs-- -- in a segment which is ok.- state5 [] = Nothing- state5 (c:cs) | c == '.' = state3 cs- | c == '/' = state2 cs- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state5 cs---- | See 'isGoodRelativeFilePath'.------ This is barebones function. We check whether the glob is a valid file--- by replacing stars @*@ with @x@ses.-isGoodRelativeGlob :: FilePath -> Maybe String-isGoodRelativeGlob = isGoodRelativeFilePath . map f where- f '*' = 'x'- f c = c---- | See 'isGoodRelativeFilePath'.-isGoodRelativeDirectoryPath :: FilePath -> Maybe String-isGoodRelativeDirectoryPath = state0- where- -- Reserved characters- -- https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file- isReserved c = c `elem` "<>:\"\\/|?*"-- -- initial state- state0 [] = Just "empty path"- state0 (c:cs) | c == '.' = state5 cs- | c == '/' = Just "posix absolute path"- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state4 cs-- -- after ./- state1 [] = Nothing -- "./"- state1 (c:cs) | c == '.' = state2 cs- | c == '/' = Just "empty path segment"- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state4 cs-- -- after non-first setgment's .- state2 [] = Just "trailing same directory segment: ."- state2 (c:cs) | c == '.' = state3 cs- | c == '/' = Just "same directory segment: ."- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state4 cs-- -- after non-first segment's ..- state3 [] = Just "trailing parent directory segment: ."- state3 (c:cs) | c == '.' = state4 cs- | c == '/' = Just "parent directory segment: .."- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state4 cs-- -- in a segment which is ok.- state4 [] = Nothing- state4 (c:cs) | c == '.' = state4 cs- | c == '/' = state1 cs- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state4 cs-- -- after .- state5 [] = Nothing -- "."- state5 (c:cs) | c == '.' = state3 cs- | c == '/' = state1 cs- | isReserved c = Just ("reserved character " ++ show c)- | otherwise = state4 cs---- [Note: Good relative paths]------ Using @kleene@ we can define an extended regex:------ @--- import Algebra.Lattice--- import Kleene--- import Kleene.ERE (ERE (..), intersections)------ data C = CDot | CSlash | COtherReserved | CChar--- deriving (Eq, Ord, Enum, Bounded, Show)------ reservedR :: ERE C--- reservedR = notChar CSlash /\ notChar COtherReserved------ pathPieceR :: ERE C--- pathPieceR = intersections--- [ plus reservedR--- , ERENot (string [CDot])--- , ERENot (string [CDot,CDot])--- ]------ filePathR :: ERE C--- filePathR = optional (string [CDot, CSlash]) <> pathPieceR <> star (char CSlash <> pathPieceR)------ dirPathR :: ERE C--- dirPathR = (char CDot \/ filePathR) <> optional (char CSlash)------ plus :: ERE C -> ERE C--- plus r = r <> star r------ optional :: ERE C -> ERE C--- optional r = mempty \/ r--- @------ Results in following state machine for @filePathR@------ @--- 0 -> \x -> if--- | x <= CDot -> 1--- | x <= COtherReserved -> 6--- | otherwise -> 5--- 1 -> \x -> if--- | x <= CDot -> 4--- | x <= CSlash -> 2--- | x <= COtherReserved -> 6--- | otherwise -> 5--- 2 -> \x -> if--- | x <= CDot -> 3--- | x <= COtherReserved -> 6--- | otherwise -> 5--- 3 -> \x -> if--- | x <= CDot -> 4--- | x <= COtherReserved -> 6--- | otherwise -> 5--- 4 -> \x -> if--- | x <= CDot -> 5--- | x <= COtherReserved -> 6--- | otherwise -> 5--- 5+ -> \x -> if--- | x <= CDot -> 5--- | x <= CSlash -> 2--- | x <= COtherReserved -> 6--- | otherwise -> 5--- 6 -> \_ -> 6 -- black hole--- @------ and @dirPathR@:------ @--- 0 -> \x -> if--- | x <= CDot -> 5--- | x <= COtherReserved -> 6--- | otherwise -> 4--- 1+ -> \x -> if--- | x <= CDot -> 2--- | x <= COtherReserved -> 6--- | otherwise -> 4--- 2 -> \x -> if--- | x <= CDot -> 3--- | x <= COtherReserved -> 6--- | otherwise -> 4--- 3 -> \x -> if--- | x <= CDot -> 4--- | x <= COtherReserved -> 6--- | otherwise -> 4--- 4+ -> \x -> if--- | x <= CDot -> 4--- | x <= CSlash -> 1--- | x <= COtherReserved -> 6--- | otherwise -> 4--- 5+ -> \x -> if--- | x <= CDot -> 3--- | x <= CSlash -> 1--- | x <= COtherReserved -> 6--- | otherwise -> 4--- 6 -> \_ -> 6 -- black hole--- @
− Distribution/PackageDescription/Configuration.hs
@@ -1,599 +0,0 @@--- -fno-warn-deprecations for use of Map.foldWithKey-{-# OPTIONS_GHC -fno-warn-deprecations #-}--------------------------------------------------------------------------------- |--- Module : Distribution.PackageDescription.Configuration--- Copyright : Thomas Schilling, 2007--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is about the cabal configurations feature. It exports--- 'finalizePD' and 'flattenPackageDescription' which are--- functions for converting 'GenericPackageDescription's down to--- 'PackageDescription's. It has code for working with the tree of conditions--- and resolving or flattening conditions.--module Distribution.PackageDescription.Configuration (- finalizePD,- flattenPackageDescription,-- -- Utils- parseCondition,- freeVars,- extractCondition,- extractConditions,- addBuildableCondition,- mapCondTree,- mapTreeData,- mapTreeConds,- mapTreeConstrs,- transformAllBuildInfos,- transformAllBuildDepends,- transformAllBuildDependsN,- ) where--import Distribution.Compat.Prelude-import Prelude ()---- lens-import qualified Distribution.Types.BuildInfo.Lens as L-import qualified Distribution.Types.GenericPackageDescription.Lens as L-import qualified Distribution.Types.PackageDescription.Lens as L-import qualified Distribution.Types.SetupBuildInfo.Lens as L--import Distribution.Compat.CharParsing hiding (char)-import qualified Distribution.Compat.CharParsing as P-import Distribution.Compat.Lens-import Distribution.Compiler-import Distribution.PackageDescription-import Distribution.PackageDescription.Utils-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Simple.Utils-import Distribution.System-import Distribution.Types.Component-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.DependencyMap-import Distribution.Types.PackageVersionConstraint-import Distribution.Version--import qualified Data.Map.Lazy as Map-import Data.Tree (Tree (Node))------------------------------------------------------------------------------------ | Simplify a configuration condition using the OS and arch names. Returns--- the names of all the flags occurring in the condition.-simplifyWithSysParams :: OS -> Arch -> CompilerInfo -> Condition ConfVar- -> (Condition FlagName, [FlagName])-simplifyWithSysParams os arch cinfo cond = (cond', flags)- where- (cond', flags) = simplifyCondition cond interp- interp (OS os') = Right $ os' == os- interp (Arch arch') = Right $ arch' == arch- interp (Impl comp vr)- | matchImpl (compilerInfoId cinfo) = Right True- | otherwise = case compilerInfoCompat cinfo of- -- fixme: treat Nothing as unknown, rather than empty list once we- -- support partial resolution of system parameters- Nothing -> Right False- Just compat -> Right (any matchImpl compat)- where- matchImpl (CompilerId c v) = comp == c && v `withinRange` vr- interp (PackageFlag f) = Left f---- TODO: Add instances and check------ prop_sC_idempotent cond a o = cond' == cond''--- where--- cond' = simplifyCondition cond a o--- cond'' = simplifyCondition cond' a o------ prop_sC_noLits cond a o = isLit res || not (hasLits res)--- where--- res = simplifyCondition cond a o--- hasLits (Lit _) = True--- hasLits (CNot c) = hasLits c--- hasLits (COr l r) = hasLits l || hasLits r--- hasLits (CAnd l r) = hasLits l || hasLits r--- hasLits _ = False------- | Parse a configuration condition from a string.-parseCondition :: CabalParsing m => m (Condition ConfVar)-parseCondition = condOr- where- condOr = sepByNonEmpty condAnd (oper "||") >>= return . foldl1 COr- condAnd = sepByNonEmpty cond (oper "&&")>>= return . foldl1 CAnd- -- TODO: try?- cond = sp >> (boolLiteral <|> inparens condOr <|> notCond <|> osCond- <|> archCond <|> flagCond <|> implCond )- inparens = between (P.char '(' >> sp) (sp >> P.char ')' >> sp)- notCond = P.char '!' >> sp >> cond >>= return . CNot- osCond = string "os" >> sp >> inparens osIdent >>= return . Var- archCond = string "arch" >> sp >> inparens archIdent >>= return . Var- flagCond = string "flag" >> sp >> inparens flagIdent >>= return . Var- implCond = string "impl" >> sp >> inparens implIdent >>= return . Var- boolLiteral = fmap Lit parsec- archIdent = fmap Arch parsec- osIdent = fmap OS parsec- flagIdent = fmap (PackageFlag . mkFlagName . lowercase) (munch1 isIdentChar)- isIdentChar c = isAlphaNum c || c == '_' || c == '-'- oper s = sp >> string s >> sp- sp = spaces- implIdent = do i <- parsec- vr <- sp >> option anyVersion parsec- return $ Impl i vr------------------------------------------------------------------------------------ | Result of dependency test. Isomorphic to @Maybe d@ but renamed for--- clarity.-data DepTestRslt d = DepOk | MissingDeps d--instance Semigroup d => Monoid (DepTestRslt d) where- mempty = DepOk- mappend = (<>)--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.------ Returns either the missing dependencies, or a tuple containing the--- resulting data, the associated dependencies, and the chosen flag--- assignments.------ 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:------ * Rule out possible paths, by taking a look at the associated dependencies.------ * Infer the required values for the conditions of these paths, and--- calculate the required domains for the variables used in these--- conditions. Then picking a flag assignment would be linear (I guess).------ This would require some sort of SAT solving, though, thus it's not--- implemented unless we really need it.----resolveWithFlags ::- [(FlagName,[Bool])]- -- ^ Domain for each flag name, will be tested in order.- -> ComponentRequestedSpec- -> OS -- ^ OS as returned by Distribution.System.buildOS- -> Arch -- ^ Arch as returned by Distribution.System.buildArch- -> CompilerInfo -- ^ Compiler information- -> [PackageVersionConstraint] -- ^ Additional constraints- -> [CondTree ConfVar [Dependency] PDTagged]- -> ([Dependency] -> DepTestRslt [Dependency]) -- ^ Dependency test function.- -> Either [Dependency] (TargetSet PDTagged, FlagAssignment)- -- ^ Either the missing dependencies (error case), or a pair of- -- (set of build targets with dependencies, chosen flag assignments)-resolveWithFlags dom enabled os arch impl constrs trees checkDeps =- either (Left . fromDepMapUnion) Right $ explore (build mempty dom)- where- -- 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- . addBuildableConditionPDTagged- . mapTreeConds (fst . simplifyWithSysParams os arch impl))- trees-- -- @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` constrs) .- simplifyCondTree (env flags)- deps = overallDependencies enabled targetSet- in case checkDeps (fromDepMap deps) of- DepOk | null ts -> Right (targetSet, flags)- | otherwise -> tryAll $ map explore ts- MissingDeps mds -> Left (toDepMapUnion mds)-- -- 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 (insertFlagAssignment 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 :: Either DepMapUnion a -> Either DepMapUnion a -> Either DepMapUnion a- mp m@(Right _) _ = m- mp _ m@(Right _) = m- mp (Left xs) (Left ys) = Left (xs <> ys)-- -- `mzero'- mz :: Either DepMapUnion a- mz = Left (DepMapUnion Map.empty)-- env :: FlagAssignment -> FlagName -> Either FlagName Bool- env flags flag = (maybe (Left flag) Right . lookupFlagAssignment flag) flags---- | 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 [condIfThen c t]---- | This is a special version of 'addBuildableCondition' for the 'PDTagged'--- type.------ It is not simply a specialisation. It is more complicated than it--- ought to be because of the way the 'PDTagged' monoid instance works. The--- @mempty = 'PDNull'@ forgets the component type, which has the effect of--- completely deleting components that are not buildable.------ See <https://github.com/haskell/cabal/pull/4094> for more details.----addBuildableConditionPDTagged :: (Eq v, Monoid c) =>- CondTree v c PDTagged- -> CondTree v c PDTagged-addBuildableConditionPDTagged t =- case extractCondition (buildable . getInfo) t of- Lit True -> t- Lit False -> deleteConstraints t- c -> CondNode mempty mempty [condIfThenElse c t (deleteConstraints t)]- where- deleteConstraints = mapTreeConstrs (const mempty)-- getInfo :: PDTagged -> BuildInfo- getInfo (Lib l) = libBuildInfo l- getInfo (SubComp _ c) = componentBuildInfo c- getInfo PDNull = mempty----- 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 conditions matched by the given predicate from all cond trees in a--- 'GenericPackageDescription'.-extractConditions :: (BuildInfo -> Bool) -> GenericPackageDescription- -> [Condition ConfVar]-extractConditions f gpkg =- concat [- extractCondition (f . libBuildInfo) <$> maybeToList (condLibrary gpkg)- , extractCondition (f . libBuildInfo) . snd <$> condSubLibraries gpkg- , extractCondition (f . buildInfo) . snd <$> condExecutables gpkg- , extractCondition (f . testBuildInfo) . snd <$> condTestSuites gpkg- , extractCondition (f . benchmarkBuildInfo) . snd <$> condBenchmarks gpkg- ]----- | A map of package constraints that combines version ranges using 'unionVersionRanges'.-newtype DepMapUnion = DepMapUnion { unDepMapUnion :: Map PackageName (VersionRange, NonEmptySet LibraryName) }--instance Semigroup DepMapUnion where- DepMapUnion x <> DepMapUnion y = DepMapUnion $- Map.unionWith unionVersionRanges' x y--unionVersionRanges'- :: (VersionRange, NonEmptySet LibraryName)- -> (VersionRange, NonEmptySet LibraryName)- -> (VersionRange, NonEmptySet LibraryName)-unionVersionRanges' (vr, cs) (vr', cs') = (unionVersionRanges vr vr', cs <> cs')--toDepMapUnion :: [Dependency] -> DepMapUnion-toDepMapUnion ds =- DepMapUnion $ Map.fromListWith unionVersionRanges' [ (p,(vr,cs)) | Dependency p vr cs <- ds ]---fromDepMapUnion :: DepMapUnion -> [Dependency]-fromDepMapUnion m = [ Dependency p vr cs | (p,(vr,cs)) <- Map.toList (unDepMapUnion m) ]--freeVars :: CondTree ConfVar c a -> [FlagName]-freeVars t = [ f | PackageFlag f <- freeVars' t ]- where- freeVars' (CondNode _ _ ifs) = concatMap compfv ifs- compfv (CondBranch c ct mct) = condfv c ++ freeVars' ct ++ maybe [] freeVars' mct- condfv c = case c of- Var v -> [v]- Lit _ -> []- CNot c' -> condfv c'- COr c1 c2 -> condfv c1 ++ condfv c2- CAnd c1 c2 -> condfv c1 ++ condfv c2------------------------------------------------------------------------------------- | A set of targets with their package dependencies-newtype TargetSet a = TargetSet [(DependencyMap, a)]---- | Combine the target-specific dependencies in a TargetSet to give the--- dependencies for the package as a whole.-overallDependencies :: ComponentRequestedSpec -> TargetSet PDTagged -> DependencyMap-overallDependencies enabled (TargetSet targets) = mconcat depss- where- (depss, _) = unzip $ filter (removeDisabledSections . snd) targets- removeDisabledSections :: PDTagged -> Bool- -- UGH. The embedded componentName in the 'Component's here is- -- BLANK. I don't know whose fault this is but I'll use the tag- -- instead. -- ezyang- removeDisabledSections (Lib _) = componentNameRequested- enabled- (CLibName LMainLibName)- removeDisabledSections (SubComp t c)- -- Do NOT use componentName- = componentNameRequested enabled- $ case c of- CLib _ -> CLibName (LSubLibName t)- CFLib _ -> CFLibName t- CExe _ -> CExeName t- CTest _ -> CTestName t- CBench _ -> CBenchName t- removeDisabledSections PDNull = True---- | Collect up the targets in a TargetSet of tagged targets, storing the--- dependencies as we go.-flattenTaggedTargets :: TargetSet PDTagged -> (Maybe Library, [(UnqualComponentName, Component)])-flattenTaggedTargets (TargetSet targets) = foldr untag (Nothing, []) targets where- untag (depMap, pdTagged) accum = case (pdTagged, accum) of- (Lib _, (Just _, _)) -> userBug "Only one library expected"- (Lib l, (Nothing, comps)) -> (Just $ redoBD l, comps)- (SubComp n c, (mb_lib, comps))- | any ((== n) . fst) comps ->- userBug $ "There exist several components with the same name: '" ++ prettyShow n ++ "'"- | otherwise -> (mb_lib, (n, redoBD c) : comps)- (PDNull, x) -> x -- actually this should not happen, but let's be liberal- where- redoBD :: L.HasBuildInfo a => a -> a- redoBD = set L.targetBuildDepends $ fromDepMap depMap----------------------------------------------------------------------------------- Convert GenericPackageDescription to PackageDescription-----data PDTagged = Lib Library- | SubComp UnqualComponentName Component- | PDNull- deriving Show--instance Monoid PDTagged where- mempty = PDNull- mappend = (<>)--instance Semigroup PDTagged where- PDNull <> x = x- x <> PDNull = x- Lib l <> Lib l' = Lib (l <> l')- SubComp n x <> SubComp n' x' | n == n' = SubComp n (x <> x')- _ <> _ = cabalBug "Cannot combine incompatible tags"---- | Create a package description with all configurations resolved.------ This function takes a `GenericPackageDescription` and several environment--- parameters and tries to generate `PackageDescription` by finding a flag--- assignment that result in satisfiable dependencies.------ It takes as inputs a not necessarily complete specifications of flags--- assignments, an optional package index as well as platform parameters. If--- some flags are not assigned explicitly, this function will try to pick an--- assignment that causes this function to succeed. The package index is--- optional since on some platforms we cannot determine which packages have--- been installed before. When no package index is supplied, every dependency--- is assumed to be satisfiable, therefore all not explicitly assigned flags--- will get their default values.------ 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 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.------ Note that this drops any stanzas which have @buildable: False@. While--- this is arguably the right thing to do, it means we give bad error--- messages in some situations, see #3858.----finalizePD ::- FlagAssignment -- ^ Explicitly specified flag assignments- -> ComponentRequestedSpec- -> (Dependency -> Bool) -- ^ Is a given dependency satisfiable from the set of- -- available packages? If this is unknown then use- -- True.- -> Platform -- ^ The 'Arch' and 'OS'- -> CompilerInfo -- ^ Compiler information- -> [PackageVersionConstraint] -- ^ Additional constraints- -> GenericPackageDescription- -> Either [Dependency]- (PackageDescription, FlagAssignment)- -- ^ Either missing dependencies or the resolved package- -- description along with the flag assignments chosen.-finalizePD userflags enabled satisfyDep- (Platform arch os) impl constraints- (GenericPackageDescription pkg _ver flags mb_lib0 sub_libs0 flibs0 exes0 tests0 bms0) = do- (targetSet, flagVals) <-- resolveWithFlags flagChoices enabled os arch impl constraints condTrees check- let- (mb_lib, comps) = flattenTaggedTargets targetSet- mb_lib' = fmap libFillInDefaults mb_lib- comps' = flip map comps $ \(n,c) -> foldComponent- (\l -> CLib (libFillInDefaults l) { libName = LSubLibName n- , libExposed = False })- (\l -> CFLib (flibFillInDefaults l) { foreignLibName = n })- (\e -> CExe (exeFillInDefaults e) { exeName = n })- (\t -> CTest (testFillInDefaults t) { testName = n })- (\b -> CBench (benchFillInDefaults b) { benchmarkName = n })- c- (sub_libs', flibs', exes', tests', bms') = partitionComponents comps'- return ( pkg { library = mb_lib'- , subLibraries = sub_libs'- , foreignLibs = flibs'- , executables = exes'- , testSuites = tests'- , benchmarks = bms'- }- , flagVals )- where- -- Combine lib, exes, and tests into one list of @CondTree@s with tagged data- condTrees = maybeToList (fmap (mapTreeData Lib) mb_lib0)- ++ map (\(name,tree) -> mapTreeData (SubComp name . CLib) tree) sub_libs0- ++ map (\(name,tree) -> mapTreeData (SubComp name . CFLib) tree) flibs0- ++ map (\(name,tree) -> mapTreeData (SubComp name . CExe) tree) exes0- ++ map (\(name,tree) -> mapTreeData (SubComp name . CTest) tree) tests0- ++ map (\(name,tree) -> mapTreeData (SubComp name . CBench) tree) bms0-- flagChoices = map (\(MkPackageFlag n _ d manual) -> (n, d2c manual n d)) flags- d2c manual n b = case lookupFlagAssignment n userflags of- Just val -> [val]- Nothing- | manual -> [b]- | otherwise -> [b, not b]- --flagDefaults = map (\(n,x:_) -> (n,x)) flagChoices- check ds = let missingDeps = filter (not . satisfyDep) ds- in if null missingDeps- then DepOk- else MissingDeps missingDeps--{--let tst_p = (CondNode [1::Int] [Distribution.Package.Dependency "a" AnyVersion] [])-let tst_p2 = (CondNode [1::Int] [Distribution.Package.Dependency "a" (EarlierVersion (Version [1,0] [])), Distribution.Package.Dependency "a" (LaterVersion (Version [2,0] []))] [])--let p_index = Distribution.Simple.PackageIndex.fromList [Distribution.Package.PackageIdentifier "a" (Version [0,5] []), Distribution.Package.PackageIdentifier "a" (Version [2,5] [])]-let look = not . null . Distribution.Simple.PackageIndex.lookupDependency p_index-let looks ds = mconcat $ map (\d -> if look d then DepOk else MissingDeps [d]) ds-resolveWithFlags [] Distribution.System.Linux Distribution.System.I386 (Distribution.Compiler.GHC,Version [6,8,2] []) [tst_p] looks ===> Right ...-resolveWithFlags [] Distribution.System.Linux Distribution.System.I386 (Distribution.Compiler.GHC,Version [6,8,2] []) [tst_p2] looks ===> Left ...--}---- | Flatten a generic package description by ignoring all conditions and just--- join the field descriptors into on package description. Note, however,--- that this may lead to inconsistent field values, since all values are--- joined into one field, which may not be possible in the original package--- description, due to the use of exclusive choices (if ... else ...).------ TODO: One particularly tricky case is defaulting. In the original package--- description, e.g., the source directory might either be the default or a--- certain, explicitly set path. Since defaults are filled in only after the--- package has been resolved and when no explicit value has been set, the--- default path will be missing from the package description returned by this--- function.-flattenPackageDescription :: GenericPackageDescription -> PackageDescription-flattenPackageDescription- (GenericPackageDescription pkg _ _ mlib0 sub_libs0 flibs0 exes0 tests0 bms0) =- pkg { library = mlib- , subLibraries = reverse sub_libs- , foreignLibs = reverse flibs- , executables = reverse exes- , testSuites = reverse tests- , benchmarks = reverse bms- }- where- mlib = f <$> mlib0- where f lib = (libFillInDefaults . fst . ignoreConditions $ lib) { libName = LMainLibName }- sub_libs = flattenLib <$> sub_libs0- flibs = flattenFLib <$> flibs0- exes = flattenExe <$> exes0- tests = flattenTst <$> tests0- bms = flattenBm <$> bms0- flattenLib (n, t) = libFillInDefaults $ (fst $ ignoreConditions t)- { libName = LSubLibName n, libExposed = False }- flattenFLib (n, t) = flibFillInDefaults $ (fst $ ignoreConditions t)- { foreignLibName = n }- flattenExe (n, t) = exeFillInDefaults $ (fst $ ignoreConditions t)- { exeName = n }- flattenTst (n, t) = testFillInDefaults $ (fst $ ignoreConditions t)- { testName = n }- flattenBm (n, t) = benchFillInDefaults $ (fst $ ignoreConditions t)- { benchmarkName = n }---- This is in fact rather a hack. The original version just overrode the--- default values, however, when adding conditions we had to switch to a--- modifier-based approach. There, nothing is ever overwritten, but only--- joined together.------ This is the cleanest way i could think of, that doesn't require--- changing all field parsing functions to return modifiers instead.-libFillInDefaults :: Library -> Library-libFillInDefaults lib@(Library { libBuildInfo = bi }) =- lib { libBuildInfo = biFillInDefaults bi }--flibFillInDefaults :: ForeignLib -> ForeignLib-flibFillInDefaults flib@(ForeignLib { foreignLibBuildInfo = bi }) =- flib { foreignLibBuildInfo = biFillInDefaults bi }--exeFillInDefaults :: Executable -> Executable-exeFillInDefaults exe@(Executable { buildInfo = bi }) =- exe { buildInfo = biFillInDefaults bi }--testFillInDefaults :: TestSuite -> TestSuite-testFillInDefaults tst@(TestSuite { testBuildInfo = bi }) =- tst { testBuildInfo = biFillInDefaults bi }--benchFillInDefaults :: Benchmark -> Benchmark-benchFillInDefaults bm@(Benchmark { benchmarkBuildInfo = bi }) =- bm { benchmarkBuildInfo = biFillInDefaults bi }--biFillInDefaults :: BuildInfo -> BuildInfo-biFillInDefaults bi =- 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 =- over L.traverseBuildInfos onBuildInfo- . over (L.packageDescription . L.setupBuildInfo . traverse) onSetupBuildInfo---- | Walk a 'GenericPackageDescription' and apply @f@ to all nested--- @build-depends@ fields.-transformAllBuildDepends :: (Dependency -> Dependency)- -> GenericPackageDescription- -> GenericPackageDescription-transformAllBuildDepends f =- over (L.traverseBuildInfos . L.targetBuildDepends . traverse) f- . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends . traverse) f- -- cannot be point-free as normal because of higher rank- . over (\f' -> L.allCondTrees $ traverseCondTreeC f') (map f)---- | Walk a 'GenericPackageDescription' and apply @f@ to all nested--- @build-depends@ fields.-transformAllBuildDependsN :: ([Dependency] -> [Dependency])- -> GenericPackageDescription- -> GenericPackageDescription-transformAllBuildDependsN f =- over (L.traverseBuildInfos . L.targetBuildDepends) f- . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends) f- -- cannot be point-free as normal because of higher rank- . over (\f' -> L.allCondTrees $ traverseCondTreeC f') f
− Distribution/PackageDescription/FieldGrammar.hs
@@ -1,692 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE OverloadedStrings #-}--- | 'GenericPackageDescription' Field descriptions-module Distribution.PackageDescription.FieldGrammar (- -- * Package description- packageDescriptionFieldGrammar,- -- * Library- libraryFieldGrammar,- -- * Foreign library- foreignLibFieldGrammar,- -- * Executable- executableFieldGrammar,- -- * Test suite- TestSuiteStanza (..),- testSuiteFieldGrammar,- validateTestSuite,- unvalidateTestSuite,- -- ** Lenses- testStanzaTestType,- testStanzaMainIs,- testStanzaTestModule,- testStanzaBuildInfo,- -- * Benchmark- BenchmarkStanza (..),- benchmarkFieldGrammar,- validateBenchmark,- unvalidateBenchmark,- -- * Field grammars- formatDependencyList,- formatExposedModules,- formatExtraSourceFiles,- formatHsSourceDirs,- formatMixinList,- formatOtherExtensions,- formatOtherModules,- -- ** Lenses- benchmarkStanzaBenchmarkType,- benchmarkStanzaMainIs,- benchmarkStanzaBenchmarkModule,- benchmarkStanzaBuildInfo,- -- * Flag- flagFieldGrammar,- -- * Source repository- sourceRepoFieldGrammar,- -- * Setup build info- setupBInfoFieldGrammar,- -- * Component build info- buildInfoFieldGrammar,- ) where---import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Language.Haskell.Extension-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.Compiler (CompilerFlavor (..), PerCompilerFlavor (..))-import Distribution.FieldGrammar-import Distribution.Fields-import Distribution.ModuleName (ModuleName)-import Distribution.Package-import Distribution.PackageDescription-import Distribution.Parsec-import Distribution.Pretty (prettyShow)-import Distribution.Types.ModuleReexport-import Distribution.Types.Mixin (Mixin)-import Distribution.Version (Version, VersionRange)--import qualified Distribution.SPDX as SPDX--import qualified Distribution.Types.Lens as L------------------------------------------------------------------------------------ PackageDescription----------------------------------------------------------------------------------packageDescriptionFieldGrammar- :: ( FieldGrammar c g, Applicative (g PackageDescription), Applicative (g PackageIdentifier)- , c (Identity BuildType)- , c (Identity PackageName)- , c (Identity Version)- , c (List FSep FilePathNT String)- , c (List FSep TestedWith (CompilerFlavor, VersionRange))- , c (List VCat FilePathNT String)- , c FilePathNT- , c SpecLicense- , c SpecVersion- )- => g PackageDescription PackageDescription-packageDescriptionFieldGrammar = PackageDescription- <$> optionalFieldDefAla "cabal-version" SpecVersion L.specVersion CabalSpecV1_0- <*> blurFieldGrammar L.package packageIdentifierGrammar- <*> optionalFieldDefAla "license" SpecLicense L.licenseRaw (Left SPDX.NONE)- <*> licenseFilesGrammar- <*> freeTextFieldDefST "copyright" L.copyright- <*> freeTextFieldDefST "maintainer" L.maintainer- <*> freeTextFieldDefST "author" L.author- <*> freeTextFieldDefST "stability" L.stability- <*> monoidalFieldAla "tested-with" (alaList' FSep TestedWith) L.testedWith- <*> freeTextFieldDefST "homepage" L.homepage- <*> freeTextFieldDefST "package-url" L.pkgUrl- <*> freeTextFieldDefST "bug-reports" L.bugReports- <*> pure [] -- source-repos are stanza- <*> freeTextFieldDefST "synopsis" L.synopsis- <*> freeTextFieldDefST "description" L.description- <*> freeTextFieldDefST "category" L.category- <*> prefixedFields "x-" L.customFieldsPD- <*> optionalField "build-type" L.buildTypeRaw- <*> pure Nothing -- custom-setup- -- components- <*> pure Nothing -- lib- <*> pure [] -- sub libs- <*> pure [] -- executables- <*> pure [] -- foreign libs- <*> pure [] -- test suites- <*> pure [] -- benchmarks- -- * Files- <*> monoidalFieldAla "data-files" (alaList' VCat FilePathNT) L.dataFiles- <*> optionalFieldDefAla "data-dir" FilePathNT L.dataDir "."- <*> monoidalFieldAla "extra-source-files" formatExtraSourceFiles L.extraSrcFiles- <*> monoidalFieldAla "extra-tmp-files" (alaList' VCat FilePathNT) L.extraTmpFiles- <*> monoidalFieldAla "extra-doc-files" (alaList' VCat FilePathNT) L.extraDocFiles- where- packageIdentifierGrammar = PackageIdentifier- <$> uniqueField "name" L.pkgName- <*> uniqueField "version" L.pkgVersion-- licenseFilesGrammar = (++)- -- TODO: neither field is deprecated- -- should we pretty print license-file if there's single license file- -- and license-files when more- <$> monoidalFieldAla "license-file" (alaList' FSep FilePathNT) L.licenseFiles- <*> monoidalFieldAla "license-files" (alaList' FSep FilePathNT) L.licenseFiles- ^^^ hiddenField------------------------------------------------------------------------------------ Library----------------------------------------------------------------------------------libraryFieldGrammar- :: ( FieldGrammar c g, Applicative (g Library), Applicative (g BuildInfo)- , c (Identity LibraryVisibility)- , c (List CommaFSep (Identity ExeDependency) ExeDependency)- , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)- , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)- , c (List CommaVCat (Identity Dependency) Dependency)- , c (List CommaVCat (Identity Mixin) Mixin)- , c (List CommaVCat (Identity ModuleReexport) ModuleReexport)- , c (List FSep (MQuoted Extension) Extension)- , c (List FSep (MQuoted Language) Language)- , c (List FSep FilePathNT String)- , c (List FSep Token String)- , c (List NoCommaFSep Token' String)- , c (List VCat (MQuoted ModuleName) ModuleName)- , c (List VCat FilePathNT String)- , c (List VCat Token String)- , c (MQuoted Language)- ) - => LibraryName- -> g Library Library-libraryFieldGrammar n = Library n- <$> monoidalFieldAla "exposed-modules" formatExposedModules L.exposedModules- <*> monoidalFieldAla "reexported-modules" (alaList CommaVCat) L.reexportedModules- <*> monoidalFieldAla "signatures" (alaList' VCat MQuoted) L.signatures- ^^^ availableSince CabalSpecV2_0 []- <*> booleanFieldDef "exposed" L.libExposed True- <*> visibilityField- <*> blurFieldGrammar L.libBuildInfo buildInfoFieldGrammar- where- visibilityField = case n of- -- nameless/"main" libraries are public- LMainLibName -> pure LibraryVisibilityPublic- -- named libraries have the field- LSubLibName _ ->- optionalFieldDef "visibility" L.libVisibility LibraryVisibilityPrivate- ^^^ availableSince CabalSpecV3_0 LibraryVisibilityPrivate--{-# SPECIALIZE libraryFieldGrammar :: LibraryName -> ParsecFieldGrammar' Library #-}-{-# SPECIALIZE libraryFieldGrammar :: LibraryName -> PrettyFieldGrammar' Library #-}------------------------------------------------------------------------------------ Foreign library----------------------------------------------------------------------------------foreignLibFieldGrammar- :: ( FieldGrammar c g, Applicative (g ForeignLib), Applicative (g BuildInfo)- , c (Identity ForeignLibType)- , c (Identity LibVersionInfo)- , c (Identity Version)- , c (List CommaFSep (Identity ExeDependency) ExeDependency)- , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)- , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)- , c (List CommaVCat (Identity Dependency) Dependency)- , c (List CommaVCat (Identity Mixin) Mixin)- , c (List FSep (Identity ForeignLibOption) ForeignLibOption)- , c (List FSep (MQuoted Extension) Extension)- , c (List FSep (MQuoted Language) Language)- , c (List FSep FilePathNT String)- , c (List FSep Token String)- , c (List NoCommaFSep Token' String)- , c (List VCat (MQuoted ModuleName) ModuleName)- , c (List VCat FilePathNT String), c (List VCat Token String)- , c (MQuoted Language)- )- => UnqualComponentName -> g ForeignLib ForeignLib-foreignLibFieldGrammar n = ForeignLib n- <$> optionalFieldDef "type" L.foreignLibType ForeignLibTypeUnknown- <*> monoidalFieldAla "options" (alaList FSep) L.foreignLibOptions- <*> blurFieldGrammar L.foreignLibBuildInfo buildInfoFieldGrammar- <*> optionalField "lib-version-info" L.foreignLibVersionInfo- <*> optionalField "lib-version-linux" L.foreignLibVersionLinux- <*> monoidalFieldAla "mod-def-file" (alaList' FSep FilePathNT) L.foreignLibModDefFile-{-# SPECIALIZE foreignLibFieldGrammar :: UnqualComponentName -> ParsecFieldGrammar' ForeignLib #-}-{-# SPECIALIZE foreignLibFieldGrammar :: UnqualComponentName -> PrettyFieldGrammar' ForeignLib #-}------------------------------------------------------------------------------------ Executable----------------------------------------------------------------------------------executableFieldGrammar- :: ( FieldGrammar c g, Applicative (g Executable), Applicative (g BuildInfo)- , c (Identity ExecutableScope),- c (List CommaFSep (Identity ExeDependency) ExeDependency),- c (List- CommaFSep (Identity LegacyExeDependency) LegacyExeDependency),- c (List- CommaFSep (Identity PkgconfigDependency) PkgconfigDependency),- c (List CommaVCat (Identity Dependency) Dependency),- c (List CommaVCat (Identity Mixin) Mixin),- c (List FSep (MQuoted Extension) Extension),- c (List FSep (MQuoted Language) Language),- c (List FSep FilePathNT String), c (List FSep Token String),- c (List NoCommaFSep Token' String),- c (List VCat (MQuoted ModuleName) ModuleName),- c (List VCat FilePathNT String), c (List VCat Token String),- c (MQuoted Language)- )- => UnqualComponentName -> g Executable Executable-executableFieldGrammar n = Executable n- -- main-is is optional as conditional blocks don't have it- <$> optionalFieldDefAla "main-is" FilePathNT L.modulePath ""- <*> optionalFieldDef "scope" L.exeScope ExecutablePublic- ^^^ availableSince CabalSpecV2_0 ExecutablePublic- <*> blurFieldGrammar L.buildInfo buildInfoFieldGrammar-{-# SPECIALIZE executableFieldGrammar :: UnqualComponentName -> ParsecFieldGrammar' Executable #-}-{-# SPECIALIZE executableFieldGrammar :: UnqualComponentName -> PrettyFieldGrammar' Executable #-}------------------------------------------------------------------------------------ TestSuite------------------------------------------------------------------------------------ | An intermediate type just used for parsing the test-suite stanza.--- After validation it is converted into the proper 'TestSuite' type.-data TestSuiteStanza = TestSuiteStanza- { _testStanzaTestType :: Maybe TestType- , _testStanzaMainIs :: Maybe FilePath- , _testStanzaTestModule :: Maybe ModuleName- , _testStanzaBuildInfo :: BuildInfo- }--instance L.HasBuildInfo TestSuiteStanza where- buildInfo = testStanzaBuildInfo--testStanzaTestType :: Lens' TestSuiteStanza (Maybe TestType)-testStanzaTestType f s = fmap (\x -> s { _testStanzaTestType = x }) (f (_testStanzaTestType s))-{-# INLINE testStanzaTestType #-}--testStanzaMainIs :: Lens' TestSuiteStanza (Maybe FilePath)-testStanzaMainIs f s = fmap (\x -> s { _testStanzaMainIs = x }) (f (_testStanzaMainIs s))-{-# INLINE testStanzaMainIs #-}--testStanzaTestModule :: Lens' TestSuiteStanza (Maybe ModuleName)-testStanzaTestModule f s = fmap (\x -> s { _testStanzaTestModule = x }) (f (_testStanzaTestModule s))-{-# INLINE testStanzaTestModule #-}--testStanzaBuildInfo :: Lens' TestSuiteStanza BuildInfo-testStanzaBuildInfo f s = fmap (\x -> s { _testStanzaBuildInfo = x }) (f (_testStanzaBuildInfo s))-{-# INLINE testStanzaBuildInfo #-}--testSuiteFieldGrammar- :: ( FieldGrammar c g, Applicative (g TestSuiteStanza), Applicative (g BuildInfo)- , c (Identity ModuleName)- , c (Identity TestType)- , c (List CommaFSep (Identity ExeDependency) ExeDependency)- , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)- , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)- , c (List CommaVCat (Identity Dependency) Dependency)- , c (List CommaVCat (Identity Mixin) Mixin)- , c (List FSep (MQuoted Extension) Extension)- , c (List FSep (MQuoted Language) Language)- , c (List FSep FilePathNT String)- , c (List FSep Token String)- , c (List NoCommaFSep Token' String)- , c (List VCat (MQuoted ModuleName) ModuleName)- , c (List VCat FilePathNT String)- , c (List VCat Token String)- , c (MQuoted Language)- )- => g TestSuiteStanza TestSuiteStanza-testSuiteFieldGrammar = TestSuiteStanza- <$> optionalField "type" testStanzaTestType- <*> optionalFieldAla "main-is" FilePathNT testStanzaMainIs- <*> optionalField "test-module" testStanzaTestModule- <*> blurFieldGrammar testStanzaBuildInfo buildInfoFieldGrammar--validateTestSuite :: Position -> TestSuiteStanza -> ParseResult TestSuite-validateTestSuite pos stanza = case _testStanzaTestType stanza of- Nothing -> return $- emptyTestSuite { testBuildInfo = _testStanzaBuildInfo stanza }-- Just tt@(TestTypeUnknown _ _) ->- pure emptyTestSuite- { testInterface = TestSuiteUnsupported tt- , testBuildInfo = _testStanzaBuildInfo stanza- }-- Just tt | tt `notElem` knownTestTypes ->- pure emptyTestSuite- { testInterface = TestSuiteUnsupported tt- , testBuildInfo = _testStanzaBuildInfo stanza- }-- Just tt@(TestTypeExe ver) -> case _testStanzaMainIs stanza of- Nothing -> do- parseFailure pos (missingField "main-is" tt)- pure emptyTestSuite- Just file -> do- when (isJust (_testStanzaTestModule stanza)) $- parseWarning pos PWTExtraBenchmarkModule (extraField "test-module" tt)- pure emptyTestSuite- { testInterface = TestSuiteExeV10 ver file- , testBuildInfo = _testStanzaBuildInfo stanza- }-- Just tt@(TestTypeLib ver) -> case _testStanzaTestModule stanza of- Nothing -> do- parseFailure pos (missingField "test-module" tt)- pure emptyTestSuite- Just module_ -> do- when (isJust (_testStanzaMainIs stanza)) $- parseWarning pos PWTExtraMainIs (extraField "main-is" tt)- pure emptyTestSuite- { testInterface = TestSuiteLibV09 ver module_- , testBuildInfo = _testStanzaBuildInfo stanza- }-- where- missingField name tt = "The '" ++ name ++ "' field is required for the "- ++ prettyShow tt ++ " test suite type."-- extraField name tt = "The '" ++ name ++ "' field is not used for the '"- ++ prettyShow tt ++ "' test suite type."--unvalidateTestSuite :: TestSuite -> TestSuiteStanza-unvalidateTestSuite t = TestSuiteStanza- { _testStanzaTestType = ty- , _testStanzaMainIs = ma- , _testStanzaTestModule = mo- , _testStanzaBuildInfo = testBuildInfo t- }- where- (ty, ma, mo) = case testInterface t of- TestSuiteExeV10 ver file -> (Just $ TestTypeExe ver, Just file, Nothing)- TestSuiteLibV09 ver modu -> (Just $ TestTypeLib ver, Nothing, Just modu)- _ -> (Nothing, Nothing, Nothing)------------------------------------------------------------------------------------ Benchmark------------------------------------------------------------------------------------ | An intermediate type just used for parsing the benchmark stanza.--- After validation it is converted into the proper 'Benchmark' type.-data BenchmarkStanza = BenchmarkStanza- { _benchmarkStanzaBenchmarkType :: Maybe BenchmarkType- , _benchmarkStanzaMainIs :: Maybe FilePath- , _benchmarkStanzaBenchmarkModule :: Maybe ModuleName- , _benchmarkStanzaBuildInfo :: BuildInfo- }--instance L.HasBuildInfo BenchmarkStanza where- buildInfo = benchmarkStanzaBuildInfo--benchmarkStanzaBenchmarkType :: Lens' BenchmarkStanza (Maybe BenchmarkType)-benchmarkStanzaBenchmarkType f s = fmap (\x -> s { _benchmarkStanzaBenchmarkType = x }) (f (_benchmarkStanzaBenchmarkType s))-{-# INLINE benchmarkStanzaBenchmarkType #-}--benchmarkStanzaMainIs :: Lens' BenchmarkStanza (Maybe FilePath)-benchmarkStanzaMainIs f s = fmap (\x -> s { _benchmarkStanzaMainIs = x }) (f (_benchmarkStanzaMainIs s))-{-# INLINE benchmarkStanzaMainIs #-}--benchmarkStanzaBenchmarkModule :: Lens' BenchmarkStanza (Maybe ModuleName)-benchmarkStanzaBenchmarkModule f s = fmap (\x -> s { _benchmarkStanzaBenchmarkModule = x }) (f (_benchmarkStanzaBenchmarkModule s))-{-# INLINE benchmarkStanzaBenchmarkModule #-}--benchmarkStanzaBuildInfo :: Lens' BenchmarkStanza BuildInfo-benchmarkStanzaBuildInfo f s = fmap (\x -> s { _benchmarkStanzaBuildInfo = x }) (f (_benchmarkStanzaBuildInfo s))-{-# INLINE benchmarkStanzaBuildInfo #-}--benchmarkFieldGrammar- :: ( FieldGrammar c g, Applicative (g BenchmarkStanza), Applicative (g BuildInfo)- , c (Identity BenchmarkType)- , c (Identity ModuleName)- , c (List CommaFSep (Identity ExeDependency) ExeDependency)- , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)- , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)- , c (List CommaVCat (Identity Dependency) Dependency)- , c (List CommaVCat (Identity Mixin) Mixin)- , c (List FSep (MQuoted Extension) Extension)- , c (List FSep (MQuoted Language) Language)- , c (List FSep FilePathNT String)- , c (List FSep Token String)- , c (List NoCommaFSep Token' String)- , c (List VCat (MQuoted ModuleName) ModuleName)- , c (List VCat FilePathNT String)- , c (List VCat Token String)- , c (MQuoted Language)- )- => g BenchmarkStanza BenchmarkStanza-benchmarkFieldGrammar = BenchmarkStanza- <$> optionalField "type" benchmarkStanzaBenchmarkType- <*> optionalFieldAla "main-is" FilePathNT benchmarkStanzaMainIs- <*> optionalField "benchmark-module" benchmarkStanzaBenchmarkModule- <*> blurFieldGrammar benchmarkStanzaBuildInfo buildInfoFieldGrammar--validateBenchmark :: Position -> BenchmarkStanza -> ParseResult Benchmark-validateBenchmark pos stanza = case _benchmarkStanzaBenchmarkType stanza of- Nothing -> pure emptyBenchmark- { benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza }-- Just tt@(BenchmarkTypeUnknown _ _) -> pure emptyBenchmark- { benchmarkInterface = BenchmarkUnsupported tt- , benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza- }-- Just tt | tt `notElem` knownBenchmarkTypes -> pure emptyBenchmark- { benchmarkInterface = BenchmarkUnsupported tt- , benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza- }-- Just tt@(BenchmarkTypeExe ver) -> case _benchmarkStanzaMainIs stanza of- Nothing -> do- parseFailure pos (missingField "main-is" tt)- pure emptyBenchmark- Just file -> do- when (isJust (_benchmarkStanzaBenchmarkModule stanza)) $- parseWarning pos PWTExtraBenchmarkModule (extraField "benchmark-module" tt)- pure emptyBenchmark- { benchmarkInterface = BenchmarkExeV10 ver file- , benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza- }-- where- missingField name tt = "The '" ++ name ++ "' field is required for the "- ++ prettyShow tt ++ " benchmark type."-- extraField name tt = "The '" ++ name ++ "' field is not used for the '"- ++ prettyShow tt ++ "' benchmark type."--unvalidateBenchmark :: Benchmark -> BenchmarkStanza-unvalidateBenchmark b = BenchmarkStanza- { _benchmarkStanzaBenchmarkType = ty- , _benchmarkStanzaMainIs = ma- , _benchmarkStanzaBenchmarkModule = mo- , _benchmarkStanzaBuildInfo = benchmarkBuildInfo b- }- where- (ty, ma, mo) = case benchmarkInterface b of- BenchmarkExeV10 ver "" -> (Just $ BenchmarkTypeExe ver, Nothing, Nothing)- BenchmarkExeV10 ver ma' -> (Just $ BenchmarkTypeExe ver, Just ma', Nothing)- _ -> (Nothing, Nothing, Nothing)------------------------------------------------------------------------------------ Build info----------------------------------------------------------------------------------buildInfoFieldGrammar- :: ( FieldGrammar c g, Applicative (g BuildInfo)- , c (List CommaFSep (Identity ExeDependency) ExeDependency)- , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)- , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)- , c (List CommaVCat (Identity Dependency) Dependency)- , c (List CommaVCat (Identity Mixin) Mixin)- , c (List FSep (MQuoted Extension) Extension)- , c (List FSep (MQuoted Language) Language)- , c (List FSep FilePathNT String)- , c (List FSep Token String)- , c (List NoCommaFSep Token' String)- , c (List VCat (MQuoted ModuleName) ModuleName)- , c (List VCat FilePathNT String)- , c (List VCat Token String)- , c (MQuoted Language)- )- => g BuildInfo BuildInfo-buildInfoFieldGrammar = BuildInfo- <$> booleanFieldDef "buildable" L.buildable True- <*> monoidalFieldAla "build-tools" (alaList CommaFSep) L.buildTools- ^^^ deprecatedSince CabalSpecV2_0- "Please use 'build-tool-depends' field"- ^^^ removedIn CabalSpecV3_0- "Please use 'build-tool-depends' field."- <*> monoidalFieldAla "build-tool-depends" (alaList CommaFSep) L.buildToolDepends- -- {- ^^^ availableSince [2,0] [] -}- -- here, we explicitly want to recognise build-tool-depends for all Cabal files- -- as otherwise cabal new-build cannot really work.- --- -- I.e. we don't want trigger unknown field warning- <*> monoidalFieldAla "cpp-options" (alaList' NoCommaFSep Token') L.cppOptions- <*> monoidalFieldAla "asm-options" (alaList' NoCommaFSep Token') L.asmOptions- ^^^ availableSince CabalSpecV3_0 []- <*> monoidalFieldAla "cmm-options" (alaList' NoCommaFSep Token') L.cmmOptions- ^^^ availableSince CabalSpecV3_0 []- <*> monoidalFieldAla "cc-options" (alaList' NoCommaFSep Token') L.ccOptions- <*> monoidalFieldAla "cxx-options" (alaList' NoCommaFSep Token') L.cxxOptions- ^^^ availableSince CabalSpecV2_2 []- <*> monoidalFieldAla "ld-options" (alaList' NoCommaFSep Token') L.ldOptions- <*> monoidalFieldAla "pkgconfig-depends" (alaList CommaFSep) L.pkgconfigDepends- <*> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks- <*> monoidalFieldAla "extra-framework-dirs" (alaList' FSep FilePathNT) L.extraFrameworkDirs- <*> monoidalFieldAla "asm-sources" (alaList' VCat FilePathNT) L.asmSources- ^^^ availableSince CabalSpecV3_0 []- <*> monoidalFieldAla "cmm-sources" (alaList' VCat FilePathNT) L.cmmSources- ^^^ availableSince CabalSpecV3_0 []- <*> monoidalFieldAla "c-sources" (alaList' VCat FilePathNT) L.cSources- <*> monoidalFieldAla "cxx-sources" (alaList' VCat FilePathNT) L.cxxSources- ^^^ availableSince CabalSpecV2_2 []- <*> monoidalFieldAla "js-sources" (alaList' VCat FilePathNT) L.jsSources- <*> hsSourceDirsGrammar- <*> monoidalFieldAla "other-modules" formatOtherModules L.otherModules- <*> monoidalFieldAla "virtual-modules" (alaList' VCat MQuoted) L.virtualModules- ^^^ availableSince CabalSpecV2_2 []- <*> monoidalFieldAla "autogen-modules" (alaList' VCat MQuoted) L.autogenModules- ^^^ availableSince CabalSpecV2_0 []- <*> optionalFieldAla "default-language" MQuoted L.defaultLanguage- ^^^ availableSince CabalSpecV1_10 Nothing- <*> monoidalFieldAla "other-languages" (alaList' FSep MQuoted) L.otherLanguages- ^^^ availableSince CabalSpecV1_10 []- <*> monoidalFieldAla "default-extensions" (alaList' FSep MQuoted) L.defaultExtensions- ^^^ availableSince CabalSpecV1_10 []- <*> monoidalFieldAla "other-extensions" formatOtherExtensions L.otherExtensions- ^^^ availableSinceWarn CabalSpecV1_10- <*> monoidalFieldAla "extensions" (alaList' FSep MQuoted) L.oldExtensions- ^^^ deprecatedSince CabalSpecV1_12- "Please use 'default-extensions' or 'other-extensions' fields."- ^^^ removedIn CabalSpecV3_0- "Please use 'default-extensions' or 'other-extensions' fields."- <*> monoidalFieldAla "extra-libraries" (alaList' VCat Token) L.extraLibs- <*> monoidalFieldAla "extra-ghci-libraries" (alaList' VCat Token) L.extraGHCiLibs- <*> monoidalFieldAla "extra-bundled-libraries" (alaList' VCat Token) L.extraBundledLibs- <*> monoidalFieldAla "extra-library-flavours" (alaList' VCat Token) L.extraLibFlavours- <*> monoidalFieldAla "extra-dynamic-library-flavours" (alaList' VCat Token) L.extraDynLibFlavours- ^^^ availableSince CabalSpecV3_0 []- <*> monoidalFieldAla "extra-lib-dirs" (alaList' FSep FilePathNT) L.extraLibDirs- <*> monoidalFieldAla "include-dirs" (alaList' FSep FilePathNT) L.includeDirs- <*> monoidalFieldAla "includes" (alaList' FSep FilePathNT) L.includes- <*> monoidalFieldAla "autogen-includes" (alaList' FSep FilePathNT) L.autogenIncludes- ^^^ availableSince CabalSpecV3_0 []- <*> monoidalFieldAla "install-includes" (alaList' FSep FilePathNT) L.installIncludes- <*> optionsFieldGrammar- <*> profOptionsFieldGrammar- <*> sharedOptionsFieldGrammar- <*> pure mempty -- static-options ???- <*> prefixedFields "x-" L.customFieldsBI- <*> monoidalFieldAla "build-depends" formatDependencyList L.targetBuildDepends- <*> monoidalFieldAla "mixins" formatMixinList L.mixins- ^^^ availableSince CabalSpecV2_0 []-{-# SPECIALIZE buildInfoFieldGrammar :: ParsecFieldGrammar' BuildInfo #-}-{-# SPECIALIZE buildInfoFieldGrammar :: PrettyFieldGrammar' BuildInfo #-}--hsSourceDirsGrammar- :: (FieldGrammar c g, Applicative (g BuildInfo), c (List FSep FilePathNT FilePath))- => g BuildInfo [FilePath]-hsSourceDirsGrammar = (++)- <$> monoidalFieldAla "hs-source-dirs" formatHsSourceDirs L.hsSourceDirs- <*> monoidalFieldAla "hs-source-dir" (alaList' FSep FilePathNT) wrongLens- --- https://github.com/haskell/cabal/commit/49e3cdae3bdf21b017ccd42e66670ca402e22b44- ^^^ deprecatedSince CabalSpecV1_2 "Please use 'hs-source-dirs'"- ^^^ removedIn CabalSpecV3_0 "Please use 'hs-source-dirs' field."- where- -- TODO: make pretty printer aware of CabalSpecVersion- wrongLens :: Functor f => LensLike' f BuildInfo [FilePath]- wrongLens f bi = (\fps -> set L.hsSourceDirs fps bi) <$> f []--optionsFieldGrammar- :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String))- => g BuildInfo (PerCompilerFlavor [String])-optionsFieldGrammar = PerCompilerFlavor- <$> monoidalFieldAla "ghc-options" (alaList' NoCommaFSep Token') (extract GHC)- <*> monoidalFieldAla "ghcjs-options" (alaList' NoCommaFSep Token') (extract GHCJS)- -- NOTE: Hugs, NHC and JHC are not supported anymore, but these- -- fields are kept around so that we can still parse legacy .cabal- -- files that have them.- <* knownField "jhc-options"- <* knownField "hugs-options"- <* knownField "nhc98-options"- where- extract :: CompilerFlavor -> ALens' BuildInfo [String]- extract flavor = L.options . lookupLens flavor--profOptionsFieldGrammar- :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String))- => g BuildInfo (PerCompilerFlavor [String])-profOptionsFieldGrammar = PerCompilerFlavor- <$> monoidalFieldAla "ghc-prof-options" (alaList' NoCommaFSep Token') (extract GHC)- <*> monoidalFieldAla "ghcjs-prof-options" (alaList' NoCommaFSep Token') (extract GHCJS)- where- extract :: CompilerFlavor -> ALens' BuildInfo [String]- extract flavor = L.profOptions . lookupLens flavor--sharedOptionsFieldGrammar- :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String))- => g BuildInfo (PerCompilerFlavor [String])-sharedOptionsFieldGrammar = PerCompilerFlavor- <$> monoidalFieldAla "ghc-shared-options" (alaList' NoCommaFSep Token') (extract GHC)- <*> monoidalFieldAla "ghcjs-shared-options" (alaList' NoCommaFSep Token') (extract GHCJS)- where- extract :: CompilerFlavor -> ALens' BuildInfo [String]- extract flavor = L.sharedOptions . lookupLens flavor--lookupLens :: (Functor f, Monoid v) => CompilerFlavor -> LensLike' f (PerCompilerFlavor v) v-lookupLens k f p@(PerCompilerFlavor ghc ghcjs)- | k == GHC = (\n -> PerCompilerFlavor n ghcjs) <$> f ghc- | k == GHCJS = (\n -> PerCompilerFlavor ghc n) <$> f ghcjs- | otherwise = p <$ f mempty------------------------------------------------------------------------------------ Flag----------------------------------------------------------------------------------flagFieldGrammar- :: (FieldGrammar c g, Applicative (g PackageFlag))- => FlagName -> g PackageFlag PackageFlag-flagFieldGrammar name = MkPackageFlag name- <$> freeTextFieldDef "description" L.flagDescription- <*> booleanFieldDef "default" L.flagDefault True- <*> booleanFieldDef "manual" L.flagManual False-{-# SPECIALIZE flagFieldGrammar :: FlagName -> ParsecFieldGrammar' PackageFlag #-}-{-# SPECIALIZE flagFieldGrammar :: FlagName -> PrettyFieldGrammar' PackageFlag #-}------------------------------------------------------------------------------------ SourceRepo----------------------------------------------------------------------------------sourceRepoFieldGrammar- :: (FieldGrammar c g, Applicative (g SourceRepo), c (Identity RepoType), c Token, c FilePathNT)- => RepoKind -> g SourceRepo SourceRepo-sourceRepoFieldGrammar kind = SourceRepo kind- <$> optionalField "type" L.repoType- <*> freeTextField "location" L.repoLocation- <*> optionalFieldAla "module" Token L.repoModule- <*> optionalFieldAla "branch" Token L.repoBranch- <*> optionalFieldAla "tag" Token L.repoTag- <*> optionalFieldAla "subdir" FilePathNT L.repoSubdir-{-# SPECIALIZE sourceRepoFieldGrammar :: RepoKind -> ParsecFieldGrammar' SourceRepo #-}-{-# SPECIALIZE sourceRepoFieldGrammar :: RepoKind -> PrettyFieldGrammar' SourceRepo #-}------------------------------------------------------------------------------------ SetupBuildInfo----------------------------------------------------------------------------------setupBInfoFieldGrammar- :: (FieldGrammar c g, Functor (g SetupBuildInfo), c (List CommaVCat (Identity Dependency) Dependency))- => Bool -> g SetupBuildInfo SetupBuildInfo-setupBInfoFieldGrammar def = flip SetupBuildInfo def- <$> monoidalFieldAla "setup-depends" (alaList CommaVCat) L.setupDepends-{-# SPECIALIZE setupBInfoFieldGrammar :: Bool -> ParsecFieldGrammar' SetupBuildInfo #-}-{-# SPECIALIZE setupBInfoFieldGrammar :: Bool -> PrettyFieldGrammar' SetupBuildInfo #-}------------------------------------------------------------------------------------ Define how field values should be formatted for 'pretty'.----------------------------------------------------------------------------------formatDependencyList :: [Dependency] -> List CommaVCat (Identity Dependency) Dependency-formatDependencyList = alaList CommaVCat--formatMixinList :: [Mixin] -> List CommaVCat (Identity Mixin) Mixin-formatMixinList = alaList CommaVCat--formatExtraSourceFiles :: [FilePath] -> List VCat FilePathNT FilePath-formatExtraSourceFiles = alaList' VCat FilePathNT--formatExposedModules :: [ModuleName] -> List VCat (MQuoted ModuleName) ModuleName-formatExposedModules = alaList' VCat MQuoted--formatHsSourceDirs :: [FilePath] -> List FSep FilePathNT FilePath-formatHsSourceDirs = alaList' FSep FilePathNT--formatOtherExtensions :: [Extension] -> List FSep (MQuoted Extension) Extension-formatOtherExtensions = alaList' FSep MQuoted--formatOtherModules :: [ModuleName] -> List VCat (MQuoted ModuleName) ModuleName-formatOtherModules = alaList' VCat MQuoted
− Distribution/PackageDescription/Parsec.hs
@@ -1,975 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}--------------------------------------------------------------------------------- |--- Module : Distribution.PackageDescription.Parsec--- Copyright : Isaac Jones 2003-2005--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This defined parsers and partial pretty printers for the @.cabal@ format.--module Distribution.PackageDescription.Parsec (- -- * Package descriptions- readGenericPackageDescription,- parseGenericPackageDescription,- parseGenericPackageDescriptionMaybe,-- -- ** Parsing- ParseResult,- runParseResult,-- -- * New-style spec-version- scanSpecVersion,-- -- ** Supplementary build information- readHookedBuildInfo,- parseHookedBuildInfo,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Control.Monad.State.Strict (StateT, execStateT)-import Control.Monad.Trans.Class (lift)-import Distribution.CabalSpecVersion-import Distribution.Compat.Lens-import Distribution.FieldGrammar-import Distribution.FieldGrammar.Parsec (NamelessField (..))-import Distribution.Fields.ConfVar (parseConditionConfVar)-import Distribution.Fields.Field (FieldName, getName)-import Distribution.Fields.LexerMonad (LexWarning, toPWarnings)-import Distribution.Fields.Parser-import Distribution.Fields.ParseResult-import Distribution.PackageDescription-import Distribution.PackageDescription.Configuration (freeVars, transformAllBuildInfos)-import Distribution.PackageDescription.FieldGrammar-import Distribution.PackageDescription.Quirks (patchQuirks)-import Distribution.Parsec (parsec, simpleParsecBS)-import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS)-import Distribution.Parsec.Position (Position (..), zeroPos)-import Distribution.Parsec.Warning (PWarnType (..))-import Distribution.Pretty (prettyShow)-import Distribution.Simple.Utils (fromUTF8BS, toUTF8BS)-import Distribution.Types.Mixin (Mixin (..), mkMixin)-import Distribution.Utils.Generic (breakMaybe, unfoldrM, validateUTF8)-import Distribution.Verbosity (Verbosity)-import Distribution.Version (Version, mkVersion, versionNumbers)--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS8-import qualified Data.Map.Strict as Map-import qualified Data.Set as Set-import qualified Distribution.Compat.Newtype as Newtype-import qualified Distribution.Compat.NonEmptySet as NES-import qualified Distribution.Types.BuildInfo.Lens as L-import qualified Distribution.Types.Executable.Lens as L-import qualified Distribution.Types.ForeignLib.Lens as L-import qualified Distribution.Types.GenericPackageDescription.Lens as L-import qualified Distribution.Types.PackageDescription.Lens as L-import qualified Distribution.Types.SetupBuildInfo.Lens as L-import qualified Text.Parsec as P---- ------------------------------------------------------------------ Parsing--- ------------------------------------------------------------------- | Parse the given package file.-readGenericPackageDescription :: Verbosity -> FilePath -> IO GenericPackageDescription-readGenericPackageDescription = readAndParseFile parseGenericPackageDescription----------------------------------------------------------------------------------- | Parses the given file into a 'GenericPackageDescription'.------ In Cabal 1.2 the syntax for package descriptions was changed to a format--- with sections and possibly indented property descriptions.----parseGenericPackageDescription :: BS.ByteString -> ParseResult GenericPackageDescription-parseGenericPackageDescription bs = do- -- set scanned version- setCabalSpecVersion ver-- csv <- case ver of- -- if we get too new version, fail right away- Just v -> case cabalSpecFromVersionDigits (versionNumbers v) of- Just csv -> return (Just csv)- Nothing -> parseFatalFailure zeroPos $- "Unsupported cabal-version " ++ prettyShow v ++ ". See https://github.com/haskell/cabal/issues/4899."- _ -> pure Nothing-- case readFields' bs'' of- Right (fs, lexWarnings) -> do- when patched $- parseWarning zeroPos PWTQuirkyCabalFile "Legacy cabal file"- -- UTF8 is validated in a prepass step, afterwards parsing is lenient.- parseGenericPackageDescription' csv lexWarnings invalidUtf8 fs- -- TODO: better marshalling of errors- Left perr -> parseFatalFailure pos (show perr) where- ppos = P.errorPos perr- pos = Position (P.sourceLine ppos) (P.sourceColumn ppos)- where- (patched, bs') = patchQuirks bs- ver = scanSpecVersion bs'-- invalidUtf8 = validateUTF8 bs'-- -- if there are invalid utf8 characters, we make the bytestring valid.- bs'' = case invalidUtf8 of- Nothing -> bs'- Just _ -> toUTF8BS (fromUTF8BS bs')----- | 'Maybe' variant of 'parseGenericPackageDescription'-parseGenericPackageDescriptionMaybe :: BS.ByteString -> Maybe GenericPackageDescription-parseGenericPackageDescriptionMaybe =- either (const Nothing) Just . snd . runParseResult . parseGenericPackageDescription--fieldlinesToBS :: [FieldLine ann] -> BS.ByteString-fieldlinesToBS = BS.intercalate "\n" . map (\(FieldLine _ bs) -> bs)---- Monad in which sections are parsed-type SectionParser = StateT SectionS ParseResult---- | State of section parser-data SectionS = SectionS- { _stateGpd :: !GenericPackageDescription- , _stateCommonStanzas :: !(Map String CondTreeBuildInfo)- }--stateGpd :: Lens' SectionS GenericPackageDescription-stateGpd f (SectionS gpd cs) = (\x -> SectionS x cs) <$> f gpd-{-# INLINE stateGpd #-}--stateCommonStanzas :: Lens' SectionS (Map String CondTreeBuildInfo)-stateCommonStanzas f (SectionS gpd cs) = SectionS gpd <$> f cs-{-# INLINE stateCommonStanzas #-}---- Note [Accumulating parser]------ This parser has two "states":--- * first we parse fields of PackageDescription--- * then we parse sections (libraries, executables, etc)-parseGenericPackageDescription'- :: Maybe CabalSpecVersion- -> [LexWarning]- -> Maybe Int- -> [Field Position]- -> ParseResult GenericPackageDescription-parseGenericPackageDescription' scannedVer lexWarnings utf8WarnPos fs = do- parseWarnings (toPWarnings lexWarnings)- for_ utf8WarnPos $ \pos ->- parseWarning zeroPos PWTUTF $ "UTF8 encoding problem at byte offset " ++ show pos- let (syntax, fs') = sectionizeFields fs- let (fields, sectionFields) = takeFields fs'-- -- cabal-version- specVer <- case scannedVer of- Just v -> return v- Nothing -> case Map.lookup "cabal-version" fields >>= safeLast of- Nothing -> return CabalSpecV1_0- Just (MkNamelessField pos fls) -> do- -- version will be parsed twice, therefore we parse without warnings.- v <- withoutWarnings $- Newtype.unpack' SpecVersion <$>- -- Use version with || and && but before addition of ^>= and removal of -any- runFieldParser pos parsec CabalSpecV1_24 fls-- -- if it were at the beginning, scanner would found it- when (v >= CabalSpecV2_2) $ parseFailure pos $- "cabal-version should be at the beginning of the file starting with spec version 2.2. " ++- "See https://github.com/haskell/cabal/issues/4899"-- return v-- -- reset cabal version, it might not be set- let specVer' = mkVersion (cabalSpecToVersionDigits specVer)- setCabalSpecVersion (Just specVer')-- -- Package description- pd <- parseFieldGrammar specVer fields packageDescriptionFieldGrammar-- -- Check that scanned and parsed versions match.- unless (specVer == specVersion pd) $ parseFailure zeroPos $- "Scanned and parsed cabal-versions don't match " ++- prettyShow (SpecVersion specVer) ++ " /= " ++ prettyShow (SpecVersion (specVersion pd))-- maybeWarnCabalVersion syntax pd-- -- Sections- let gpd = emptyGenericPackageDescription- & L.packageDescription .~ pd- gpd1 <- view stateGpd <$> execStateT (goSections specVer sectionFields) (SectionS gpd Map.empty)-- let gpd2 = postProcessInternalDeps specVer gpd1- checkForUndefinedFlags gpd2- checkForUndefinedCustomSetup gpd2- gpd2 `deepseq` return gpd2- where- safeLast :: [a] -> Maybe a- safeLast = listToMaybe . reverse-- newSyntaxVersion :: CabalSpecVersion- newSyntaxVersion = CabalSpecV1_2-- maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult ()- maybeWarnCabalVersion syntax pkg- | syntax == NewSyntax && specVersion pkg < newSyntaxVersion- = parseWarning zeroPos PWTNewSyntax $- "A package using section syntax must specify at least\n"- ++ "'cabal-version: >= 1.2'."-- maybeWarnCabalVersion syntax pkg- | syntax == OldSyntax && specVersion pkg >= newSyntaxVersion- = parseWarning zeroPos PWTOldSyntax $- "A package using 'cabal-version: "- ++ prettyShow (SpecVersion (specVersion pkg))- ++ "' must use section syntax. See the Cabal user guide for details."-- maybeWarnCabalVersion _ _ = return ()--goSections :: CabalSpecVersion -> [Field Position] -> SectionParser ()-goSections specVer = traverse_ process- where- process (Field (Name pos name) _) =- lift $ parseWarning pos PWTTrailingFields $- "Ignoring trailing fields after sections: " ++ show name- process (Section name args secFields) =- parseSection name args secFields-- snoc x xs = xs ++ [x]-- hasCommonStanzas = specHasCommonStanzas specVer-- -- we need signature, because this is polymorphic, but not-closed- parseCondTree'- :: L.HasBuildInfo a- => ParsecFieldGrammar' a -- ^ grammar- -> (BuildInfo -> a)- -> Map String CondTreeBuildInfo -- ^ common stanzas- -> [Field Position]- -> ParseResult (CondTree ConfVar [Dependency] a)- parseCondTree' = parseCondTreeWithCommonStanzas specVer-- parseSection :: Name Position -> [SectionArg Position] -> [Field Position] -> SectionParser ()- parseSection (Name pos name) args fields- | hasCommonStanzas == NoCommonStanzas, name == "common" = lift $ do- parseWarning pos PWTUnknownSection $ "Ignoring section: common. You should set cabal-version: 2.2 or larger to use common stanzas."-- | name == "common" = do- commonStanzas <- use stateCommonStanzas- name' <- lift $ parseCommonName pos args- biTree <- lift $ parseCondTree' buildInfoFieldGrammar id commonStanzas fields-- case Map.lookup name' commonStanzas of- Nothing -> stateCommonStanzas .= Map.insert name' biTree commonStanzas- Just _ -> lift $ parseFailure pos $- "Duplicate common stanza: " ++ name'-- | name == "library" && null args = do- prev <- use $ stateGpd . L.condLibrary- when (isJust prev) $ lift $ parseFailure pos $- "Multiple main libraries; have you forgotten to specify a name for an internal library?"-- commonStanzas <- use stateCommonStanzas- let name'' = LMainLibName- lib <- lift $ parseCondTree' (libraryFieldGrammar name'') (libraryFromBuildInfo name'') commonStanzas fields- --- -- TODO check that not set- stateGpd . L.condLibrary ?= lib-- -- Sublibraries- -- TODO: check cabal-version- | name == "library" = do- commonStanzas <- use stateCommonStanzas- name' <- parseUnqualComponentName pos args- let name'' = LSubLibName name'- lib <- lift $ parseCondTree' (libraryFieldGrammar name'') (libraryFromBuildInfo name'') commonStanzas fields- -- TODO check duplicate name here?- stateGpd . L.condSubLibraries %= snoc (name', lib)-- -- TODO: check cabal-version- | name == "foreign-library" = do- commonStanzas <- use stateCommonStanzas- name' <- parseUnqualComponentName pos args- flib <- lift $ parseCondTree' (foreignLibFieldGrammar name') (fromBuildInfo' name') commonStanzas fields-- let hasType ts = foreignLibType ts /= foreignLibType mempty- unless (onAllBranches hasType flib) $ lift $ parseFailure pos $ concat- [ "Foreign library " ++ show (prettyShow name')- , " is missing required field \"type\" or the field "- , "is not present in all conditional branches. The "- , "available test types are: "- , intercalate ", " (map prettyShow knownForeignLibTypes)- ]-- -- TODO check duplicate name here?- stateGpd . L.condForeignLibs %= snoc (name', flib)-- | name == "executable" = do- commonStanzas <- use stateCommonStanzas- name' <- parseUnqualComponentName pos args- exe <- lift $ parseCondTree' (executableFieldGrammar name') (fromBuildInfo' name') commonStanzas fields- -- TODO check duplicate name here?- stateGpd . L.condExecutables %= snoc (name', exe)-- | name == "test-suite" = do- commonStanzas <- use stateCommonStanzas- name' <- parseUnqualComponentName pos args- testStanza <- lift $ parseCondTree' testSuiteFieldGrammar (fromBuildInfo' name') commonStanzas fields- testSuite <- lift $ traverse (validateTestSuite pos) testStanza-- let hasType ts = testInterface ts /= testInterface mempty- unless (onAllBranches hasType testSuite) $ lift $ parseFailure pos $ concat- [ "Test suite " ++ show (prettyShow name')- , " is missing required field \"type\" or the field "- , "is not present in all conditional branches. The "- , "available test types are: "- , intercalate ", " (map prettyShow knownTestTypes)- ]-- -- TODO check duplicate name here?- stateGpd . L.condTestSuites %= snoc (name', testSuite)-- | name == "benchmark" = do- commonStanzas <- use stateCommonStanzas- name' <- parseUnqualComponentName pos args- benchStanza <- lift $ parseCondTree' benchmarkFieldGrammar (fromBuildInfo' name') commonStanzas fields- bench <- lift $ traverse (validateBenchmark pos) benchStanza-- let hasType ts = benchmarkInterface ts /= benchmarkInterface mempty- unless (onAllBranches hasType bench) $ lift $ parseFailure pos $ concat- [ "Benchmark " ++ show (prettyShow name')- , " is missing required field \"type\" or the field "- , "is not present in all conditional branches. The "- , "available benchmark types are: "- , intercalate ", " (map prettyShow knownBenchmarkTypes)- ]-- -- TODO check duplicate name here?- stateGpd . L.condBenchmarks %= snoc (name', bench)-- | name == "flag" = do- name' <- parseNameBS pos args- name'' <- lift $ runFieldParser' [pos] parsec specVer (fieldLineStreamFromBS name') `recoverWith` mkFlagName ""- flag <- lift $ parseFields specVer fields (flagFieldGrammar name'')- -- Check default flag- stateGpd . L.genPackageFlags %= snoc flag-- | name == "custom-setup" && null args = do- sbi <- lift $ parseFields specVer fields (setupBInfoFieldGrammar False)- stateGpd . L.packageDescription . L.setupBuildInfo ?= sbi-- | name == "source-repository" = do- kind <- lift $ case args of- [SecArgName spos secName] ->- runFieldParser' [spos] parsec specVer (fieldLineStreamFromBS secName) `recoverWith` RepoHead- [] -> do- parseFailure pos "'source-repository' requires exactly one argument"- pure RepoHead- _ -> do- parseFailure pos $ "Invalid source-repository kind " ++ show args- pure RepoHead-- sr <- lift $ parseFields specVer fields (sourceRepoFieldGrammar kind)- stateGpd . L.packageDescription . L.sourceRepos %= snoc sr-- | otherwise = lift $- parseWarning pos PWTUnknownSection $ "Ignoring section: " ++ show name--parseName :: Position -> [SectionArg Position] -> SectionParser String-parseName pos args = fromUTF8BS <$> parseNameBS pos args--parseNameBS :: Position -> [SectionArg Position] -> SectionParser BS.ByteString--- TODO: use strict parser-parseNameBS pos args = case args of- [SecArgName _pos secName] ->- pure secName- [SecArgStr _pos secName] ->- pure secName- [] -> do- lift $ parseFailure pos "name required"- pure ""- _ -> do- -- TODO: pretty print args- lift $ parseFailure pos $ "Invalid name " ++ show args- pure ""--parseCommonName :: Position -> [SectionArg Position] -> ParseResult String-parseCommonName pos args = case args of- [SecArgName _pos secName] ->- pure $ fromUTF8BS secName- [SecArgStr _pos secName] ->- pure $ fromUTF8BS secName- [] -> do- parseFailure pos $ "name required"- pure ""- _ -> do- -- TODO: pretty print args- parseFailure pos $ "Invalid name " ++ show args- pure ""---- TODO: avoid conversion to 'String'.-parseUnqualComponentName :: Position -> [SectionArg Position] -> SectionParser UnqualComponentName-parseUnqualComponentName pos args = mkUnqualComponentName <$> parseName pos args---- | Parse a non-recursive list of fields.-parseFields- :: CabalSpecVersion- -> [Field Position] -- ^ fields to be parsed- -> ParsecFieldGrammar' a- -> ParseResult a-parseFields v fields grammar = do- let (fs0, ss) = partitionFields fields- traverse_ (traverse_ warnInvalidSubsection) ss- parseFieldGrammar v fs0 grammar--warnInvalidSubsection :: Section Position -> ParseResult ()-warnInvalidSubsection (MkSection (Name pos name) _ _) =- void $ parseFailure pos $ "invalid subsection " ++ show name--parseCondTree- :: forall a. L.HasBuildInfo a- => CabalSpecVersion- -> HasElif -- ^ accept @elif@- -> ParsecFieldGrammar' a -- ^ grammar- -> Map String CondTreeBuildInfo -- ^ common stanzas- -> (BuildInfo -> a) -- ^ constructor from buildInfo- -> (a -> [Dependency]) -- ^ condition extractor- -> [Field Position]- -> ParseResult (CondTree ConfVar [Dependency] a)-parseCondTree v hasElif grammar commonStanzas fromBuildInfo cond = go- where- go fields0 = do- (fields, endo) <-- if v >= CabalSpecV3_0- then processImports v fromBuildInfo commonStanzas fields0- else traverse (warnImport v) fields0 >>= \fields1 -> return (catMaybes fields1, id)-- let (fs, ss) = partitionFields fields- x <- parseFieldGrammar v fs grammar- branches <- concat <$> traverse parseIfs ss- return $ endo $ CondNode x (cond x) branches-- parseIfs :: [Section Position] -> ParseResult [CondBranch ConfVar [Dependency] a]- parseIfs [] = return []- parseIfs (MkSection (Name _ name) test fields : sections) | name == "if" = do- test' <- parseConditionConfVar test- fields' <- go fields- (elseFields, sections') <- parseElseIfs sections- return (CondBranch test' fields' elseFields : sections')- parseIfs (MkSection (Name pos name) _ _ : sections) = do- parseWarning pos PWTInvalidSubsection $ "invalid subsection " ++ show name- parseIfs sections-- parseElseIfs- :: [Section Position]- -> ParseResult (Maybe (CondTree ConfVar [Dependency] a), [CondBranch ConfVar [Dependency] a])- parseElseIfs [] = return (Nothing, [])- parseElseIfs (MkSection (Name pos name) args fields : sections) | name == "else" = do- unless (null args) $- parseFailure pos $ "`else` section has section arguments " ++ show args- elseFields <- go fields- sections' <- parseIfs sections- return (Just elseFields, sections')-- parseElseIfs (MkSection (Name _ name) test fields : sections) | hasElif == HasElif, name == "elif" = do- test' <- parseConditionConfVar test- fields' <- go fields- (elseFields, sections') <- parseElseIfs sections- -- we parse an empty 'Fields', to get empty value for a node- a <- parseFieldGrammar v mempty grammar- return (Just $ CondNode a (cond a) [CondBranch test' fields' elseFields], sections')-- parseElseIfs (MkSection (Name pos name) _ _ : sections) | name == "elif" = do- parseWarning pos PWTInvalidSubsection $ "invalid subsection \"elif\". You should set cabal-version: 2.2 or larger to use elif-conditionals."- (,) Nothing <$> parseIfs sections-- parseElseIfs sections = (,) Nothing <$> parseIfs sections--{- Note [Accumulating parser]--Note: Outdated a bit--In there parser, @'FieldDescr' a@ is transformed into @Map FieldName (a ->-FieldParser a)@. The weird value is used because we accumulate structure of-@a@ by folding over the fields. There are various reasons for that:--* Almost all fields are optional--* This is simple approach so declarative bi-directional format (parsing and-printing) of structure could be specified (list of @'FieldDescr' a@)--* There are surface syntax fields corresponding to single field in the file:- @license-file@ and @license-files@--* This is quite safe approach.--When/if we re-implement the parser to support formatting preservging roundtrip-with new AST, this all need to be rewritten.--}------------------------------------------------------------------------------------ Common stanzas------------------------------------------------------------------------------------ $commonStanzas------ [Note: Common stanzas]------ In Cabal 2.2 we support simple common stanzas:------ * Commons stanzas define 'BuildInfo'------ * import "fields" can only occur at top of other stanzas (think: imports)------ In particular __there aren't__------ * implicit stanzas------ * More specific common stanzas (executable, test-suite).--------- The approach uses the fact that 'BuildInfo' is a 'Monoid':------ @--- mergeCommonStanza' :: HasBuildInfo comp => BuildInfo -> comp -> comp--- mergeCommonStanza' bi = over L.BuildInfo (bi <>)--- @------ Real 'mergeCommonStanza' is more complicated as we have to deal with--- conditional trees.------ The approach is simple, and have good properties:------ * Common stanzas are parsed exactly once, even if not-used. Thus we report errors in them.----type CondTreeBuildInfo = CondTree ConfVar [Dependency] BuildInfo---- | Create @a@ from 'BuildInfo'.--- This class is used to implement common stanza parsing.------ Law: @view buildInfo . fromBuildInfo = id@------ This takes name, as 'FieldGrammar's take names too.-class L.HasBuildInfo a => FromBuildInfo a where- fromBuildInfo' :: UnqualComponentName -> BuildInfo -> a--libraryFromBuildInfo :: LibraryName -> BuildInfo -> Library-libraryFromBuildInfo n bi = emptyLibrary- { libName = n- , libVisibility = case n of- LMainLibName -> LibraryVisibilityPublic- LSubLibName _ -> LibraryVisibilityPrivate- , libBuildInfo = bi- }--instance FromBuildInfo BuildInfo where fromBuildInfo' _ = id-instance FromBuildInfo ForeignLib where fromBuildInfo' n bi = set L.foreignLibName n $ set L.buildInfo bi emptyForeignLib-instance FromBuildInfo Executable where fromBuildInfo' n bi = set L.exeName n $ set L.buildInfo bi emptyExecutable--instance FromBuildInfo TestSuiteStanza where- fromBuildInfo' _ bi = TestSuiteStanza Nothing Nothing Nothing bi--instance FromBuildInfo BenchmarkStanza where- fromBuildInfo' _ bi = BenchmarkStanza Nothing Nothing Nothing bi--parseCondTreeWithCommonStanzas- :: forall a. L.HasBuildInfo a- => CabalSpecVersion- -> ParsecFieldGrammar' a -- ^ grammar- -> (BuildInfo -> a) -- ^ construct fromBuildInfo- -> Map String CondTreeBuildInfo -- ^ common stanzas- -> [Field Position]- -> ParseResult (CondTree ConfVar [Dependency] a)-parseCondTreeWithCommonStanzas v grammar fromBuildInfo commonStanzas fields = do- (fields', endo) <- processImports v fromBuildInfo commonStanzas fields- x <- parseCondTree v hasElif grammar commonStanzas fromBuildInfo (view L.targetBuildDepends) fields'- return (endo x)- where- hasElif = specHasElif v--processImports- :: forall a. L.HasBuildInfo a- => CabalSpecVersion- -> (BuildInfo -> a) -- ^ construct fromBuildInfo- -> Map String CondTreeBuildInfo -- ^ common stanzas- -> [Field Position]- -> ParseResult ([Field Position], CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)-processImports v fromBuildInfo commonStanzas = go []- where- hasCommonStanzas = specHasCommonStanzas v-- getList' :: List CommaFSep Token String -> [String]- getList' = Newtype.unpack-- go acc (Field (Name pos name) _ : fields) | name == "import", hasCommonStanzas == NoCommonStanzas = do- parseWarning pos PWTUnknownField "Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas"- go acc fields- -- supported:- go acc (Field (Name pos name) fls : fields) | name == "import" = do- names <- getList' <$> runFieldParser pos parsec v fls- names' <- for names $ \commonName ->- case Map.lookup commonName commonStanzas of- Nothing -> do- parseFailure pos $ "Undefined common stanza imported: " ++ commonName- pure Nothing- Just commonTree ->- pure (Just commonTree)-- go (acc ++ catMaybes names') fields-- -- parse actual CondTree- go acc fields = do- fields' <- catMaybes <$> traverse (warnImport v) fields- pure $ (fields', \x -> foldr (mergeCommonStanza fromBuildInfo) x acc)---- | Warn on "import" fields, also map to Maybe, so errorneous fields can be filtered-warnImport :: CabalSpecVersion -> Field Position -> ParseResult (Maybe (Field Position))-warnImport v (Field (Name pos name) _) | name == "import" = do- if specHasCommonStanzas v == NoCommonStanzas- then parseWarning pos PWTUnknownField "Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas"- else parseWarning pos PWTUnknownField "Unknown field: import. Common stanza imports should be at the top of the enclosing section"- return Nothing-warnImport _ f = pure (Just f)--mergeCommonStanza- :: L.HasBuildInfo a- => (BuildInfo -> a)- -> CondTree ConfVar [Dependency] BuildInfo- -> CondTree ConfVar [Dependency] a- -> CondTree ConfVar [Dependency] a-mergeCommonStanza fromBuildInfo (CondNode bi _ bis) (CondNode x _ cs) =- CondNode x' (x' ^. L.targetBuildDepends) cs'- where- -- new value is old value with buildInfo field _prepended_.- x' = x & L.buildInfo %~ (bi <>)-- -- tree components are appended together.- cs' = map (fmap fromBuildInfo) bis ++ cs------------------------------------------------------------------------------------ Branches------------------------------------------------------------------------------------ Check that a property holds on all branches of a condition tree-onAllBranches :: forall v c a. Monoid a => (a -> Bool) -> CondTree v c a -> Bool-onAllBranches p = go mempty- where- -- If the current level of the tree satisfies the property, then we are- -- done. If not, then one of the conditional branches below the current node- -- must satisfy it. Each node may have multiple immediate children; we only- -- one need one to satisfy the property because the configure step uses- -- 'mappend' to join together the results of flag resolution.- go :: a -> CondTree v c a -> Bool- go acc ct = let acc' = acc `mappend` condTreeData ct- in p acc' || any (goBranch acc') (condTreeComponents ct)-- -- Both the 'true' and the 'false' block must satisfy the property.- goBranch :: a -> CondBranch v c a -> Bool- goBranch _ (CondBranch _ _ Nothing) = False- goBranch acc (CondBranch _ t (Just e)) = go acc t && go acc e------------------------------------------------------------------------------------ Post parsing checks------------------------------------------------------------------------------------ | Check that we ------ * don't use undefined flags (very bad)--- * define flags which are unused (just bad)----checkForUndefinedFlags :: GenericPackageDescription -> ParseResult ()-checkForUndefinedFlags gpd = do- let definedFlags, usedFlags :: Set.Set FlagName- definedFlags = toSetOf (L.genPackageFlags . traverse . getting flagName) gpd- usedFlags = getConst $ L.allCondTrees f gpd-- -- Note: we can check for defined, but unused flags here too.- unless (usedFlags `Set.isSubsetOf` definedFlags) $ parseFailure zeroPos $- "These flags are used without having been defined: " ++- intercalate ", " [ unFlagName fn | fn <- Set.toList $ usedFlags `Set.difference` definedFlags ]- where- f :: CondTree ConfVar c a -> Const (Set.Set FlagName) (CondTree ConfVar c a)- f ct = Const (Set.fromList (freeVars ct))---- | Since @cabal-version: 1.24@ one can specify @custom-setup@.--- Let us require it.----checkForUndefinedCustomSetup :: GenericPackageDescription -> ParseResult ()-checkForUndefinedCustomSetup gpd = do- let pd = packageDescription gpd- let csv = specVersion pd-- when (buildType pd == Custom && isNothing (setupBuildInfo pd)) $- when (csv >= CabalSpecV1_24) $ parseFailure zeroPos $- "Since cabal-version: 1.24 specifying custom-setup section is mandatory"------------------------------------------------------------------------------------ Post processing of internal dependencies------------------------------------------------------------------------------------ Note [Dependencies on sublibraries]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~------ This is solution to https://github.com/haskell/cabal/issues/6083------ Before 'cabal-version: 3.0' we didn't have a syntax specially--- for referring to internal libraries. Internal library names--- shadowed the outside ones.------ Since 'cabal-version: 3.0' we have ability to write------ build-depends: some-package:its-sub-lib >=1.2.3------ This allows us to refer also to local packages by `this-package:sublib`.--- So since 'cabal-version: 3.4' to refer to *any*--- sublibrary we must use the two part syntax. Here's small table:------ | pre-3.4 | 3.4 and after |--- ------------------|---------------------|-------------------------------|--- pkg-name | may refer to sublib | always refers to external pkg |--- pkg-name:sublib | refers to sublib | refers to sublib |--- pkg-name:pkg-name | may refer to sublib | always refers to external pkg |------ In pre-3.4 case, if a package 'this-pkg' has a sublibrary 'pkg-name',--- all dependency definitions will refer to that sublirary.------ In 3.4 and after case, 'pkg-name' will always refer to external package,--- and to use internal library you have to say 'this-pkg:pkg-name'.------ In summary, In 3.4 and after, the internal names don't shadow,--- as there is an explicit syntax to refer to them,--- i.e. what you write is what you get;--- For pre-3.4 we post-process the file.------ Similarly, we process mixins.--- See https://github.com/haskell/cabal/issues/6281-----postProcessInternalDeps :: CabalSpecVersion -> GenericPackageDescription -> GenericPackageDescription-postProcessInternalDeps specVer gpd- | specVer >= CabalSpecV3_4 = gpd- | otherwise = transformAllBuildInfos transformBI transformSBI gpd- where- transformBI :: BuildInfo -> BuildInfo- transformBI- = over L.targetBuildDepends (concatMap transformD)- . over L.mixins (map transformM)-- transformSBI :: SetupBuildInfo -> SetupBuildInfo- transformSBI = over L.setupDepends (concatMap transformD)-- transformD :: Dependency -> [Dependency]- transformD (Dependency pn vr ln)- | uqn `Set.member` internalLibs- , LMainLibName `NES.member` ln- = case NES.delete LMainLibName ln of- Nothing -> [dep]- Just ln' -> [dep, Dependency pn vr ln']- where- uqn = packageNameToUnqualComponentName pn- dep = Dependency thisPn vr (NES.singleton (LSubLibName uqn))-- transformD d = [d]-- transformM :: Mixin -> Mixin- transformM (Mixin pn LMainLibName incl)- | uqn `Set.member` internalLibs- = mkMixin thisPn (LSubLibName uqn) incl- where- uqn = packageNameToUnqualComponentName pn-- transformM m = m-- thisPn :: PackageName- thisPn = pkgName (package (packageDescription gpd))-- internalLibs :: Set UnqualComponentName- internalLibs = Set.fromList- [ n- | (n, _) <- condSubLibraries gpd- ]------------------------------------------------------------------------------------ Old syntax------------------------------------------------------------------------------------ TODO: move to own module---- | "Sectionize" an old-style Cabal file. A sectionized file has:------ * all global fields at the beginning, followed by------ * all flag declarations, followed by------ * an optional library section, and an arbitrary number of executable--- sections (in any order).------ The current implementation just gathers all library-specific fields--- in a library section and wraps all executable stanzas in an executable--- section.-sectionizeFields :: [Field ann] -> (Syntax, [Field ann])-sectionizeFields fs = case classifyFields fs of- Just fields -> (OldSyntax, convert fields)- Nothing -> (NewSyntax, fs)- where- -- return 'Just' if all fields are simple fields- classifyFields :: [Field ann] -> Maybe [(Name ann, [FieldLine ann])]- classifyFields = traverse f- where- f (Field name fieldlines) = Just (name, fieldlines)- f _ = Nothing-- trim = BS.dropWhile isSpace' . BS.reverse . BS.dropWhile isSpace' . BS.reverse- isSpace' = (== 32)-- convert :: [(Name ann, [FieldLine ann])] -> [Field ann]- convert fields =- let- toField (name, ls) = Field name ls- -- "build-depends" is a local field now. To be backwards- -- compatible, we still allow it as a global field in old-style- -- package description files and translate it to a local field by- -- adding it to every non-empty section- (hdr0, exes0) = break ((=="executable") . getName . fst) fields- (hdr, libfs0) = partition (not . (`elem` libFieldNames) . getName . fst) hdr0-- (deps, libfs) = partition ((== "build-depends") . getName . fst)- libfs0-- exes = unfoldr toExe exes0- toExe [] = Nothing- toExe ((Name pos n, ls) : r)- | n == "executable" =- let (efs, r') = break ((== "executable") . getName . fst) r- in Just (Section (Name pos "executable") [SecArgName pos $ trim $ fieldlinesToBS ls] (map toField $ deps ++ efs), r')- toExe _ = error "unexpected input to 'toExe'"-- lib = case libfs of- [] -> []- ((Name pos _, _) : _) ->- [Section (Name pos "library") [] (map toField $ deps ++ libfs)]-- in map toField hdr ++ lib ++ exes---- | See 'sectionizeFields'.-data Syntax = OldSyntax | NewSyntax- deriving (Eq, Show)---- TODO:-libFieldNames :: [FieldName]-libFieldNames = fieldGrammarKnownFieldList (libraryFieldGrammar LMainLibName)------------------------------------------------------------------------------------ Suplementary build information----------------------------------------------------------------------------------readHookedBuildInfo :: Verbosity -> FilePath -> IO HookedBuildInfo-readHookedBuildInfo = readAndParseFile parseHookedBuildInfo--parseHookedBuildInfo :: BS.ByteString -> ParseResult HookedBuildInfo-parseHookedBuildInfo bs = case readFields' bs of- Right (fs, lexWarnings) -> do- parseHookedBuildInfo' lexWarnings fs- -- TODO: better marshalling of errors- Left perr -> parseFatalFailure zeroPos (show perr)--parseHookedBuildInfo'- :: [LexWarning]- -> [Field Position]- -> ParseResult HookedBuildInfo-parseHookedBuildInfo' lexWarnings fs = do- parseWarnings (toPWarnings lexWarnings)- (mLibFields, exes) <- stanzas fs- mLib <- parseLib mLibFields- biExes <- traverse parseExe exes- return (mLib, biExes)- where- parseLib :: Fields Position -> ParseResult (Maybe BuildInfo)- parseLib fields- | Map.null fields = pure Nothing- | otherwise = Just <$> parseFieldGrammar cabalSpecLatest fields buildInfoFieldGrammar-- parseExe :: (UnqualComponentName, Fields Position) -> ParseResult (UnqualComponentName, BuildInfo)- parseExe (n, fields) = do- bi <- parseFieldGrammar cabalSpecLatest fields buildInfoFieldGrammar- pure (n, bi)-- stanzas :: [Field Position] -> ParseResult (Fields Position, [(UnqualComponentName, Fields Position)])- stanzas fields = do- let (hdr0, exes0) = breakMaybe isExecutableField fields- hdr <- toFields hdr0- exes <- unfoldrM (traverse toExe) exes0- pure (hdr, exes)-- toFields :: [Field Position] -> ParseResult (Fields Position)- toFields fields = do- let (fields', ss) = partitionFields fields- traverse_ (traverse_ warnInvalidSubsection) ss- pure fields'-- toExe- :: ([FieldLine Position], [Field Position])- -> ParseResult ((UnqualComponentName, Fields Position), Maybe ([FieldLine Position], [Field Position]))- toExe (fss, fields) = do- name <- runFieldParser zeroPos parsec cabalSpecLatest fss- let (hdr0, rest) = breakMaybe isExecutableField fields- hdr <- toFields hdr0- pure ((name, hdr), rest)-- isExecutableField (Field (Name _ name) fss)- | name == "executable" = Just fss- | otherwise = Nothing- isExecutableField _ = Nothing------------------------------------------------------------------------------------ Scan of spec version------------------------------------------------------------------------------------ | Quickly scan new-style spec-version------ A new-style spec-version declaration begins the .cabal file and--- follow the following case-insensitive grammar (expressed in--- RFC5234 ABNF):------ @--- newstyle-spec-version-decl = "cabal-version" *WS ":" *WS newstyle-pec-version *WS------ spec-version = NUM "." NUM [ "." NUM ]------ NUM = DIGIT0 / DIGITP 1*DIGIT0--- DIGIT0 = %x30-39--- DIGITP = %x31-39--- WS = %20--- @----scanSpecVersion :: BS.ByteString -> Maybe Version-scanSpecVersion bs = do- fstline':_ <- pure (BS8.lines bs)-- -- parse <newstyle-spec-version-decl>- -- normalise: remove all whitespace, convert to lower-case- let fstline = BS.map toLowerW8 $ BS.filter (/= 0x20) fstline'- ["cabal-version",vers] <- pure (BS8.split ':' fstline)-- -- parse <spec-version>- --- -- This is currently more tolerant regarding leading 0 digits.- --- ver <- simpleParsecBS vers- guard $ case versionNumbers ver of- [_,_] -> True- [_,_,_] -> True- _ -> False-- pure ver- where- -- | Translate ['A'..'Z'] to ['a'..'z']- toLowerW8 :: Word8 -> Word8- toLowerW8 w | 0x40 < w && w < 0x5b = w+0x20- | otherwise = w
− Distribution/PackageDescription/PrettyPrint.hs
@@ -1,283 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--------------------------------------------------------------------------------- |--- Module : Distribution.PackageDescription.PrettyPrint--- Copyright : Jürgen Nicklisch-Franken 2010--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Stability : provisional--- Portability : portable------ Pretty printing for cabal files-----------------------------------------------------------------------------------module Distribution.PackageDescription.PrettyPrint (- -- * Generic package descriptions- writeGenericPackageDescription,- showGenericPackageDescription,- ppGenericPackageDescription,-- -- * Package descriptions- writePackageDescription,- showPackageDescription,-- -- ** Supplementary build information- writeHookedBuildInfo,- showHookedBuildInfo,-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.Fields.Pretty-import Distribution.Compat.Lens-import Distribution.PackageDescription-import Distribution.Pretty-import Distribution.Simple.Utils (writeFileAtomic, writeUTF8File)-import Distribution.Types.Mixin (Mixin (..), mkMixin)-import Distribution.FieldGrammar (PrettyFieldGrammar', prettyFieldGrammar)-import Distribution.PackageDescription.Configuration (transformAllBuildInfos)-import Distribution.PackageDescription.FieldGrammar- (benchmarkFieldGrammar, buildInfoFieldGrammar, executableFieldGrammar, flagFieldGrammar, foreignLibFieldGrammar, libraryFieldGrammar,- packageDescriptionFieldGrammar, setupBInfoFieldGrammar, sourceRepoFieldGrammar, testSuiteFieldGrammar)--import qualified Distribution.PackageDescription.FieldGrammar as FG-import qualified Distribution.Types.BuildInfo.Lens as L-import qualified Distribution.Types.SetupBuildInfo.Lens as L--import Text.PrettyPrint (Doc, char, hsep, parens, text)--import qualified Data.ByteString.Lazy.Char8 as BS.Char8-import qualified Distribution.Compat.NonEmptySet as NES---- | Writes a .cabal file from a generic package description-writeGenericPackageDescription :: FilePath -> GenericPackageDescription -> IO ()-writeGenericPackageDescription fpath pkg = writeUTF8File fpath (showGenericPackageDescription pkg)---- | Writes a generic package description to a string-showGenericPackageDescription :: GenericPackageDescription -> String-showGenericPackageDescription gpd = showFields (const []) $ ppGenericPackageDescription v gpd- where- v = specVersion $ packageDescription gpd---- | Convert a generic package description to 'PrettyField's.-ppGenericPackageDescription :: CabalSpecVersion -> GenericPackageDescription -> [PrettyField ()]-ppGenericPackageDescription v gpd0 = concat- [ ppPackageDescription v (packageDescription gpd)- , ppSetupBInfo v (setupBuildInfo (packageDescription gpd))- , ppGenPackageFlags v (genPackageFlags gpd)- , ppCondLibrary v (condLibrary gpd)- , ppCondSubLibraries v (condSubLibraries gpd)- , ppCondForeignLibs v (condForeignLibs gpd)- , ppCondExecutables v (condExecutables gpd)- , ppCondTestSuites v (condTestSuites gpd)- , ppCondBenchmarks v (condBenchmarks gpd)- ]- where- gpd = preProcessInternalDeps (specVersion (packageDescription gpd0)) gpd0---ppPackageDescription :: CabalSpecVersion -> PackageDescription -> [PrettyField ()]-ppPackageDescription v pd =- prettyFieldGrammar v packageDescriptionFieldGrammar pd- ++ ppSourceRepos v (sourceRepos pd)--ppSourceRepos :: CabalSpecVersion -> [SourceRepo] -> [PrettyField ()]-ppSourceRepos = map . ppSourceRepo--ppSourceRepo :: CabalSpecVersion -> SourceRepo -> PrettyField ()-ppSourceRepo v repo = PrettySection () "source-repository" [pretty kind] $- prettyFieldGrammar v (sourceRepoFieldGrammar kind) repo- where- kind = repoKind repo--ppSetupBInfo :: CabalSpecVersion -> Maybe SetupBuildInfo -> [PrettyField ()]-ppSetupBInfo _ Nothing = mempty-ppSetupBInfo v (Just sbi)- | defaultSetupDepends sbi = mempty- | otherwise = pure $ PrettySection () "custom-setup" [] $- prettyFieldGrammar v (setupBInfoFieldGrammar False) sbi--ppGenPackageFlags :: CabalSpecVersion -> [PackageFlag] -> [PrettyField ()]-ppGenPackageFlags = map . ppFlag--ppFlag :: CabalSpecVersion -> PackageFlag -> PrettyField ()-ppFlag v flag@(MkPackageFlag name _ _ _) = PrettySection () "flag" [ppFlagName name] $- prettyFieldGrammar v (flagFieldGrammar name) flag--ppCondTree2 :: CabalSpecVersion -> PrettyFieldGrammar' s -> CondTree ConfVar [Dependency] s -> [PrettyField ()]-ppCondTree2 v grammar = go- where- -- TODO: recognise elif opportunities- go (CondNode it _ ifs) =- prettyFieldGrammar v grammar it ++- concatMap ppIf ifs-- ppIf (CondBranch c thenTree Nothing)--- | isEmpty thenDoc = mempty- | otherwise = [ppIfCondition c thenDoc]- where- thenDoc = go thenTree-- ppIf (CondBranch c thenTree (Just elseTree)) =- -- See #6193- [ ppIfCondition c (go thenTree)- , PrettySection () "else" [] (go elseTree)- ]--ppCondLibrary :: CabalSpecVersion -> Maybe (CondTree ConfVar [Dependency] Library) -> [PrettyField ()]-ppCondLibrary _ Nothing = mempty-ppCondLibrary v (Just condTree) = pure $ PrettySection () "library" [] $- ppCondTree2 v (libraryFieldGrammar LMainLibName) condTree--ppCondSubLibraries :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Library)] -> [PrettyField ()]-ppCondSubLibraries v libs =- [ PrettySection () "library" [pretty n]- $ ppCondTree2 v (libraryFieldGrammar $ LSubLibName n) condTree- | (n, condTree) <- libs- ]--ppCondForeignLibs :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)] -> [PrettyField ()]-ppCondForeignLibs v flibs =- [ PrettySection () "foreign-library" [pretty n]- $ ppCondTree2 v (foreignLibFieldGrammar n) condTree- | (n, condTree) <- flibs- ]--ppCondExecutables :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)] -> [PrettyField ()]-ppCondExecutables v exes =- [ PrettySection () "executable" [pretty n]- $ ppCondTree2 v (executableFieldGrammar n) condTree- | (n, condTree) <- exes- ]--ppCondTestSuites :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)] -> [PrettyField ()]-ppCondTestSuites v suites =- [ PrettySection () "test-suite" [pretty n]- $ ppCondTree2 v testSuiteFieldGrammar (fmap FG.unvalidateTestSuite condTree)- | (n, condTree) <- suites- ]--ppCondBenchmarks :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)] -> [PrettyField ()]-ppCondBenchmarks v suites =- [ PrettySection () "benchmark" [pretty n]- $ ppCondTree2 v benchmarkFieldGrammar (fmap FG.unvalidateBenchmark condTree)- | (n, condTree) <- suites- ]--ppCondition :: Condition ConfVar -> Doc-ppCondition (Var x) = ppConfVar x-ppCondition (Lit b) = text (show b)-ppCondition (CNot c) = char '!' <<>> (ppCondition c)-ppCondition (COr c1 c2) = parens (hsep [ppCondition c1, text "||"- <+> ppCondition c2])-ppCondition (CAnd c1 c2) = parens (hsep [ppCondition c1, text "&&"- <+> ppCondition c2])-ppConfVar :: ConfVar -> Doc-ppConfVar (OS os) = text "os" <<>> parens (pretty os)-ppConfVar (Arch arch) = text "arch" <<>> parens (pretty arch)-ppConfVar (PackageFlag name) = text "flag" <<>> parens (ppFlagName name)-ppConfVar (Impl c v) = text "impl" <<>> parens (pretty c <+> pretty v)--ppFlagName :: FlagName -> Doc-ppFlagName = text . unFlagName--ppIfCondition :: Condition ConfVar -> [PrettyField ()] -> PrettyField ()-ppIfCondition c = PrettySection () "if" [ppCondition c]---- | @since 2.0.0.2-writePackageDescription :: FilePath -> PackageDescription -> IO ()-writePackageDescription fpath pkg = writeUTF8File fpath (showPackageDescription pkg)----TODO: make this use section syntax--- add equivalent for GenericPackageDescription---- | @since 2.0.0.2-showPackageDescription :: PackageDescription -> String-showPackageDescription = showGenericPackageDescription . pdToGpd--pdToGpd :: PackageDescription -> GenericPackageDescription-pdToGpd pd = GenericPackageDescription- { packageDescription = pd- , gpdScannedVersion = Nothing- , genPackageFlags = []- , condLibrary = mkCondTree <$> library pd- , condSubLibraries = mkCondTreeL <$> subLibraries pd- , condForeignLibs = mkCondTree' foreignLibName <$> foreignLibs pd- , condExecutables = mkCondTree' exeName <$> executables pd- , condTestSuites = mkCondTree' testName <$> testSuites pd- , condBenchmarks = mkCondTree' benchmarkName <$> benchmarks pd- }- where- -- We set CondTree's [Dependency] to an empty list, as it- -- is not pretty printed anyway.- mkCondTree x = CondNode x [] []- mkCondTreeL l = (fromMaybe (mkUnqualComponentName "") (libraryNameString (libName l)), CondNode l [] [])-- mkCondTree'- :: (a -> UnqualComponentName)- -> a -> (UnqualComponentName, CondTree ConfVar [Dependency] a)- mkCondTree' f x = (f x, CondNode x [] [])------------------------------------------------------------------------------------ Internal libs------------------------------------------------------------------------------------ See Note [Dependencies on sublibraries] in Distribution.PackageDescription.Parsec----preProcessInternalDeps :: CabalSpecVersion -> GenericPackageDescription -> GenericPackageDescription-preProcessInternalDeps specVer gpd- | specVer >= CabalSpecV3_4 = gpd- | otherwise = transformAllBuildInfos transformBI transformSBI gpd- where- transformBI :: BuildInfo -> BuildInfo- transformBI- = over L.targetBuildDepends (concatMap transformD)- . over L.mixins (map transformM)-- transformSBI :: SetupBuildInfo -> SetupBuildInfo- transformSBI = over L.setupDepends (concatMap transformD)-- transformD :: Dependency -> [Dependency]- transformD (Dependency pn vr ln)- | pn == thisPn- = if LMainLibName `NES.member` ln- then Dependency thisPn vr mainLibSet : sublibs- else sublibs- where- sublibs =- [ Dependency (unqualComponentNameToPackageName uqn) vr mainLibSet- | LSubLibName uqn <- NES.toList ln- ]-- transformD d = [d]-- transformM :: Mixin -> Mixin- transformM (Mixin pn (LSubLibName uqn) inc)- | pn == thisPn- = mkMixin (unqualComponentNameToPackageName uqn) LMainLibName inc- transformM m = m-- thisPn :: PackageName- thisPn = pkgName (package (packageDescription gpd))------------------------------------------------------------------------------------ HookedBuildInfo------------------------------------------------------------------------------------ | @since 2.0.0.2-writeHookedBuildInfo :: FilePath -> HookedBuildInfo -> IO ()-writeHookedBuildInfo fpath = writeFileAtomic fpath . BS.Char8.pack- . showHookedBuildInfo---- | @since 2.0.0.2-showHookedBuildInfo :: HookedBuildInfo -> String-showHookedBuildInfo (mb_lib_bi, ex_bis) = showFields (const []) $- maybe mempty (prettyFieldGrammar cabalSpecLatest buildInfoFieldGrammar) mb_lib_bi ++- [ PrettySection () "executable:" [pretty name]- $ prettyFieldGrammar cabalSpecLatest buildInfoFieldGrammar bi- | (name, bi) <- ex_bis- ]
− Distribution/PackageDescription/Quirks.hs
@@ -1,319 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}--- |------ @since 2.2.0.0-module Distribution.PackageDescription.Quirks (patchQuirks) where--import Distribution.Compat.Prelude-import Distribution.Utils.MD5-import GHC.Fingerprint (Fingerprint (..))-import Prelude ()--import qualified Data.ByteString as BS-import qualified Data.Map as Map---- | Patch legacy @.cabal@ file contents to allow parsec parser to accept--- all of Hackage.------ Bool part of the result tells whether the output is modified.------ @since 2.2.0.0-patchQuirks :: BS.ByteString -> (Bool, BS.ByteString)-patchQuirks bs = case Map.lookup (BS.take 256 bs, md5 bs) patches of- Nothing -> (False, bs)- Just (post, f)- | post /= md5 output -> (False, bs)- | otherwise -> (True, output)- where- output = f bs---- | 'patches' contains first 256 bytes, pre- and post-fingerprints and a patch function.-patches :: Map.Map (BS.ByteString, Fingerprint) (Fingerprint, BS.ByteString -> BS.ByteString)-patches = Map.fromList- -- http://hackage.haskell.org/package/unicode-transforms-0.3.3- -- other-modules: .- -- ReadP assumed dot is empty line- [ mk "-- This file has been generated from package.yaml by hpack version 0.17.0.\n--\n-- see: https://github.com/sol/hpack\n\nname: unicode-transforms\nversion: 0.3.3\nsynopsis: Unicode normalization\ndescription: Fast Unic"- (Fingerprint 15958160436627155571 10318709190730872881)- (Fingerprint 11008465475756725834 13815629925116264363)- (bsRemove " other-modules:\n .\n") -- TODO: remove traling \n to test structural-diff- -- http://hackage.haskell.org/package/DSTM-0.1.2- -- http://hackage.haskell.org/package/DSTM-0.1.1- -- http://hackage.haskell.org/package/DSTM-0.1- -- Other Modules: no dash- -- ReadP parsed as section- , mk "Name: DSTM\nVersion: 0.1.2\nCopyright: (c) 2010, Frank Kupke\nLicense: LGPL\nLicense-File: LICENSE\nAuthor: Frank Kupke\nMaintainer: frk@informatik.uni-kiel.de\nCabal-Version: >= 1.2.3\nStability: provisional\nSynopsis: A framework for using STM within distributed "- (Fingerprint 6919263071548559054 9050746360708965827)- (Fingerprint 17015177514298962556 11943164891661867280)- (bsReplace "Other modules:" "-- ")- , mk "Name: DSTM\nVersion: 0.1.1\nCopyright: (c) 2010, Frank Kupke\nLicense: LGPL\nLicense-File: LICENSE\nAuthor: Frank Kupke\nMaintainer: frk@informatik.uni-kiel.de\nCabal-Version: >= 1.2.3\nStability: provisional\nSynopsis: A framework for using STM within distributed "- (Fingerprint 17313105789069667153 9610429408495338584)- (Fingerprint 17250946493484671738 17629939328766863497)- (bsReplace "Other modules:" "-- ")- , mk "Name: DSTM\nVersion: 0.1\nCopyright: (c) 2010, Frank Kupke\nLicense: LGPL\nLicense-File: LICENSE\nAuthor: Frank Kupke\nMaintainer: frk@informatik.uni-kiel.de\nCabal-Version: >= 1.2.3\nStability: provisional\nSynopsis: A framework for using STM within distributed sy"- (Fingerprint 10502599650530614586 16424112934471063115)- (Fingerprint 13562014713536696107 17899511905611879358)- (bsReplace "Other modules:" "-- ")- -- http://hackage.haskell.org/package/control-monad-exception-mtl-0.10.3- , mk "name: control-monad-exception-mtl\nversion: 0.10.3\nCabal-Version: >= 1.10\nbuild-type: Simple\nlicense: PublicDomain\nauthor: Pepe Iborra\nmaintainer: pepeiborra@gmail.com\nhomepage: http://pepeiborra.github.com/control-monad-exception\nsynopsis: MTL instances f"- (Fingerprint 18274748422558568404 4043538769550834851)- (Fingerprint 11395257416101232635 4303318131190196308)- (bsReplace " default- extensions:" "unknown-section")- -- http://hackage.haskell.org/package/vacuum-opengl-0.0- -- \DEL character- , mk "Name: vacuum-opengl\nVersion: 0.0\nSynopsis: Visualize live Haskell data structures using vacuum, graphviz and OpenGL.\nDescription: \DELVisualize live Haskell data structures using vacuum, graphviz and OpenGL.\n "- (Fingerprint 5946760521961682577 16933361639326309422)- (Fingerprint 14034745101467101555 14024175957788447824)- (bsRemove "\DEL")- , mk "Name: vacuum-opengl\nVersion: 0.0.1\nSynopsis: Visualize live Haskell data structures using vacuum, graphviz and OpenGL.\nDescription: \DELVisualize live Haskell data structures using vacuum, graphviz and OpenGL.\n "- (Fingerprint 10790950110330119503 1309560249972452700)- (Fingerprint 1565743557025952928 13645502325715033593)- (bsRemove "\DEL")- -- http://hackage.haskell.org/package/ixset-1.0.4- -- {- comments -}- , mk "Name: ixset\nVersion: 1.0.4\nSynopsis: Efficient relational queries on Haskell sets.\nDescription:\n Create and query sets that are indexed by multiple indices.\nLicense: BSD3\nLicense-file: COPYING\nAut"- (Fingerprint 11886092342440414185 4150518943472101551)- (Fingerprint 5731367240051983879 17473925006273577821)- (bsRemoveStarting "{-")- -- : after section- -- http://hackage.haskell.org/package/ds-kanren- , mk "name: ds-kanren\nversion: 0.2.0.0\nsynopsis: A subset of the miniKanren language\ndescription:\n ds-kanren is an implementation of the <http://minikanren.org miniKanren> language.\n .\n == What's in ds-kanren?\n .\n ['dis"- (Fingerprint 2804006762382336875 9677726932108735838)- (Fingerprint 9830506174094917897 12812107316777006473)- (bsReplace "Test-Suite test-unify:" "Test-Suite \"test-unify:\"" . bsReplace "Test-Suite test-list-ops:" "Test-Suite \"test-list-ops:\"")- , mk "name: ds-kanren\nversion: 0.2.0.1\nsynopsis: A subset of the miniKanren language\ndescription:\n ds-kanren is an implementation of the <http://minikanren.org miniKanren> language.\n\nlicense: MIT\nlicense-file: "- (Fingerprint 9130259649220396193 2155671144384738932)- (Fingerprint 1847988234352024240 4597789823227580457)- (bsReplace "Test-Suite test-unify:" "Test-Suite \"test-unify:\"" . bsReplace "Test-Suite test-list-ops:" "Test-Suite \"test-list-ops:\"")- , mk "name: metric\nversion: 0.1.4\nsynopsis: Metric spaces.\nlicense: MIT\nlicense-file: LICENSE\nauthor: Vikram Verma\nmaintainer: me@vikramverma.com\ncategory: Data\nbuild-type:"- (Fingerprint 6150019278861565482 3066802658031228162)- (Fingerprint 9124826020564520548 15629704249829132420)- (bsReplace "test-suite metric-tests:" "test-suite \"metric-tests:\"")- , mk "name: metric\nversion: 0.2.0\nsynopsis: Metric spaces.\nlicense: MIT\nlicense-file: LICENSE\nauthor: Vikram Verma\nmaintainer: me@vikramverma.com\ncategory: Data\nbuild-type:"- (Fingerprint 4639805967994715694 7859317050376284551)- (Fingerprint 5566222290622325231 873197212916959151)- (bsReplace "test-suite metric-tests:" "test-suite \"metric-tests:\"")- , mk "name: phasechange\ncategory: Data\nversion: 0.1\nauthor: G\195\161bor Lehel\nmaintainer: G\195\161bor Lehel <illissius@gmail.com>\nhomepage: http://github.com/glehel/phasechange\ncopyright: Copyright (C) 2012 G\195\161bor Lehel\nlicense: "- (Fingerprint 10546509771395401582 245508422312751943)- (Fingerprint 5169853482576003304 7247091607933993833)- (bsReplace "impl(ghc >= 7.4):" "erroneous-section" . bsReplace "impl(ghc >= 7.6):" "erroneous-section")- , mk "Name: smartword\nSynopsis: Web based flash card for Word Smart I and II vocabularies\nVersion: 0.0.0.5\nHomepage: http://kyagrd.dyndns.org/~kyagrd/project/smartword/\nCategory: Web,Education\nLicense: "- (Fingerprint 7803544783533485151 10807347873998191750)- (Fingerprint 1665635316718752601 16212378357991151549)- (bsReplace "build depends:" "--")- , mk "name: shelltestrunner\n-- sync with README.md, ANNOUNCE:\nversion: 1.3\ncategory: Testing\nsynopsis: A tool for testing command-line programs.\ndescription:\n shelltestrunner is a cross-platform tool for testing command-line\n program"- (Fingerprint 4403237110790078829 15392625961066653722)- (Fingerprint 10218887328390239431 4644205837817510221)- (bsReplace "other modules:" "--")- -- &&!- -- http://hackage.haskell.org/package/hblas-0.3.0.0- , mk "-- Initial hblas.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP) \n-- "- (Fingerprint 8570120150072467041 18315524331351505945)- (Fingerprint 10838007242302656005 16026440017674974175)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP) \n-- "- (Fingerprint 5262875856214215155 10846626274067555320)- (Fingerprint 3022954285783401045 13395975869915955260)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP) \n-- "- (Fingerprint 54222628930951453 5526514916844166577)- (Fingerprint 1749630806887010665 8607076506606977549)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"- (Fingerprint 6817250511240350300 15278852712000783849)- (Fingerprint 15757717081429529536 15542551865099640223)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"- (Fingerprint 8310050400349211976 201317952074418615)- (Fingerprint 10283381191257209624 4231947623042413334)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"- (Fingerprint 7010988292906098371 11591884496857936132)- (Fingerprint 6158672440010710301 6419743768695725095)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further\r\n-- documentation, see http://haskell.org/cabal/users-guide/\r\n\r\n-- The name of the package.\r\nname: hblas\r\n\r\n-- The package version. See the Haskell package versioning policy (PVP)"- (Fingerprint 2076850805659055833 16615160726215879467)- (Fingerprint 10634706281258477722 5285812379517916984)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further\r\n-- documentation, see http://haskell.org/cabal/users-guide/\r\n\r\n-- The name of the package.\r\nname: hblas\r\n\r\n-- The package version. See the Haskell package versioning policy (PVP)"- (Fingerprint 11850020631622781099 11956481969231030830)- (Fingerprint 13702868780337762025 13383526367149067158)- (bsReplace "&&!" "&& !")- , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"- (Fingerprint 13690322768477779172 19704059263540994)- (Fingerprint 11189374824645442376 8363528115442591078)- (bsReplace "&&!" "&& !")- -- flag used, but not defined- , mk "name: brainheck\nversion: 0.1.0.2\nsynopsis: Brainh*ck interpreter in haskell\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\nhomepage: https://gi"- (Fingerprint 6910727116443152200 15401634478524888973)- (Fingerprint 16551412117098094368 16260377389127603629)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: brainheck\r\nversion: 0.1.0.2\r\nx-revision: 1\r\nsynopsis: Brainh*ck interpreter in haskell\r\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\r\nhomepage: "- (Fingerprint 14320987921316832277 10031098243571536929)- (Fingerprint 7959395602414037224 13279941216182213050)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: brainheck\r\nversion: 0.1.0.2\r\nx-revision: 2\r\nsynopsis: Brainh*ck interpreter in haskell\r\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\r\nhomepage: "- (Fingerprint 3809078390223299128 10796026010775813741)- (Fingerprint 1127231189459220796 12088367524333209349)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: brainheck\r\nversion: 0.1.0.2\r\nx-revision: 3\r\nsynopsis: Brainh*ck interpreter in haskell\r\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\r\nhomepage: "- (Fingerprint 13860013038089410950 12479824176801390651)- (Fingerprint 4687484721703340391 8013395164515771785)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: wordchoice\nversion: 0.1.0.1\nsynopsis: Get word counts and distributions\ndescription: A command line tool to compute the word distribution from various types of document, converting to text with pandoc.\nho"- (Fingerprint 16215911397419608203 15594928482155652475)- (Fingerprint 15120681510314491047 2666192399775157359)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: wordchoice\r\nversion: 0.1.0.1\r\nx-revision: 1\r\nsynopsis: Get word counts and distributions\r\ndescription: A command line tool to compute the word distribution from various types of document, converting to te"- (Fingerprint 16593139224723441188 4052919014346212001)- (Fingerprint 3577381082410411593 11481899387780544641)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: wordchoice\nversion: 0.1.0.2\nsynopsis: Get word counts and distributions\ndescription: A command line tool to compute the word distribution from various types of document, converting to text with pandoc.\nho"- (Fingerprint 9321301260802539374 1316392715016096607)- (Fingerprint 3784628652257760949 12662640594755291035)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: wordchoice\r\nversion: 0.1.0.2\r\nx-revision: 1\r\nsynopsis: Get word counts and distributions\r\ndescription: A command line tool to compute the word distribution from various types of document, converting to te"- (Fingerprint 2546901804824433337 2059732715322561176)- (Fingerprint 8082068680348326500 615008613291421947)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: wordchoice\nversion: 0.1.0.3\nsynopsis: Get word counts and distributions\ndescription: A command line tool to compute the word distribution from various types of document, converting to text with pandoc.\nho"- (Fingerprint 2282380737467965407 12457554753171662424)- (Fingerprint 17324757216926991616 17172911843227482125)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: wordchoice\r\nversion: 0.1.0.3\r\nx-revision: 1\r\nsynopsis: Get word counts and distributions\r\ndescription: A command line tool to compute the word distribution from various types of document, converting to te"- (Fingerprint 12907988890480595481 11078473638628359710)- (Fingerprint 13246185333368731848 4663060731847518614)- (bsReplace "flag(llvm-fast)" "False")- , mk "name: hw-prim-bits\nversion: 0.1.0.0\nsynopsis: Primitive support for bit manipulation\ndescription: Please see README.md\nhomepage: https://github.com/githubuser/hw-prim-bits#readme\nlicense: "- (Fingerprint 12386777729082870356 17414156731912743711)- (Fingerprint 3452290353395041602 14102887112483033720)- (bsReplace "flag(sse42)" "False")- , mk "name: hw-prim-bits\nversion: 0.1.0.1\nsynopsis: Primitive support for bit manipulation\ndescription: Please see README.md\nhomepage: https://github.com/githubuser/hw-prim-bits#readme\nlicen"- (Fingerprint 6870520675313101180 14553457351296240636)- (Fingerprint 12481021059537696455 14711088786769892762)- (bsReplace "flag(sse42)" "False")- -- leading zeros in version digits- -- https://github.com/haskell-infra/hackage-trustees/issues/128- -- https://github.com/haskell/cabal/issues/5092- -- https://github.com/haskell/cabal/issues/5138- , mk "name: Sit\nversion: 0.2017.02.26\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Anonymous\nmaintainer: Anonymous\nhomepage: NONE\ncategory: Dependent"- (Fingerprint 8458530898096910998 3228538743646501413)- (Fingerprint 14470502514907936793 17514354054641875371)- (bsReplace "0.2017.02.26" "0.2017.2.26")- , mk "name: Sit\nversion: 0.2017.05.01\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Andreas Abel <andreas.abel@gu.se>\nmaintainer: Andreas Abel <andreas.abel@gu.se>\n"- (Fingerprint 1450130849535097473 11742099607098860444)- (Fingerprint 16679762943850814021 4253724355613883542)- (bsReplace "0.2017.05.01" "0.2017.5.1")- , mk "name: Sit\nversion: 0.2017.05.02\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Andreas Abel <andreas.abel@gu.se>\nmaintainer: Andreas Abel <andreas.abel@gu.se>\n"- (Fingerprint 297248532398492441 17322625167861324800)- (Fingerprint 634812045126693280 1755581866539318862)- (bsReplace "0.2017.05.02" "0.2017.5.2")- , mk "name: Sit\nversion: 0.2017.5.02\nx-revision: 1\n-- x-revision:1 see https://github.com/haskell-infra/hackage-trustees/issues/128\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: "- (Fingerprint 3697869560530373941 3942982281026987312)- (Fingerprint 14344526114710295386 16386400353475114712)- (bsReplace "0.2017.5.02" "0.2017.5.2")- , mk "name: MiniAgda\nversion: 0.2017.02.18\nbuild-type: Simple\ncabal-version: >= 1.22\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Andreas Abel and Karl Mehltretter\nmaintainer: Andreas Abel <andreas.abel@i"- (Fingerprint 17167128953451088679 4300350537748753465)- (Fingerprint 12402236925293025673 7715084875284020606)- (bsReplace "0.2017.02.18" "0.2017.2.18")- , mk "cabal-version:\n 2.0\nname:\n fast-downward\nversion:\n 0.1.0.0\nbuild-type:\n Simple\nsynopsis:\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\ndescription:\n @fast-downward@ is a library for modelling classical planning probl"- (Fingerprint 11256076039027887363 6867903407496243216)- (Fingerprint 12159816716813155434 5278015399212299853)- (bsReplace "1.2.03.0" "1.2.3.0")- , mk "cabal-version:\r\n 2.0\r\nname:\r\n fast-downward\r\nversion:\r\n 0.1.0.0\r\nx-revision: \r\n 1\r\nbuild-type:\r\n Simple\r\nsynopsis:\r\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\r\ndescription:\r\n @fast-downward@ is a library for mode"- (Fingerprint 9216193973149680231 893446343655828508)- (Fingerprint 10020169545407746427 1828336750379510675)- (bsReplace "1.2.03.0" "1.2.3.0")- , mk "cabal-version:\n 2.0\nname:\n fast-downward\nversion:\n 0.1.0.1\nbuild-type:\n Simple\nsynopsis:\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\ndescription:\n @fast-downward@ is a library for modelling classical planning probl"- (Fingerprint 9899886602574848632 5980433644983783334)- (Fingerprint 12007469255857289958 8321466548645225439)- (bsReplace "1.2.03.0" "1.2.3.0")- , mk "cabal-version:\n 2.0\nname:\n fast-downward\nversion:\n 0.1.1.0\nbuild-type:\n Simple\nsynopsis:\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\ndescription:\n @fast-downward@ is a library for modelling classical planning probl"- (Fingerprint 12694656661460787751 1902242956706735615)- (Fingerprint 15433152131513403849 2284712791516353264)- (bsReplace "1.2.03.0" "1.2.3.0")- -- 9 digits limit- , mk "Name: SGplus\nVersion: 1.1\nSynopsis: (updated) Small geometry library for dealing with vectors and collision detection\nLicense: BSD3\nLicense-file: LICENSE\nAuthor: Neil Brown\nMaintainer: "- (Fingerprint 17735649550442248029 11493772714725351354)- (Fingerprint 9565458801063261772 15955773698774721052)- (bsReplace "1000000000" "100000000")- , mk "-- Initial control-dotdotdot.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\nname: control-dotdotdot\nversion: 0.1.0.1\nsynopsis: Haskell operator\n "- (Fingerprint 1514257173776509942 7756050823377346485)- (Fingerprint 14082092642045505999 18415918653404121035)- (bsReplace "9223372036854775807" "5")- , mk "name: data-foldapp\r\nversion: 0.1.1.0\r\nsynopsis: Fold function applications. Framework for variadic functions.\r\ndescription: Fold function applications. Framework for variadic functions.\r\nhomepage: ht"- (Fingerprint 4511234156311243251 11701153011544112556)- (Fingerprint 11820542702491924189 4902231447612406724)- (bsReplace "9223372036854775807" "999" . bsReplace "9223372036854775807" "999")- , mk "-- Initial data-list-zigzag.cabal generated by cabal init. For further \r\n-- documentation, see http://haskell.org/cabal/users-guide/\r\n\r\nname: data-list-zigzag\r\nversion: 0.1.1.1\r\nsynopsis: A list but with a balanced en"- (Fingerprint 12475837388692175691 18053834261188158945)- (Fingerprint 16279938253437334942 15753349540193002309)- (bsReplace "9223372036854775807" "999")- -- Not UTF8- , mk "Name: nat\nVersion: 0.1\nDescription: Implementation of natural numbers and integers by a binary\n representation. The implementation is supposed to be lazy and\n "- (Fingerprint 9222512268705577108 13085311382746579495)- (Fingerprint 17468921266614378430 13221316288008291892)- (bsReplace "\xf6" "\xc3\xb6")- -- cabal-version: 2- , mk "name: streaming-bracketed\nversion: 0.1.0.0\nsynopsis: A resource management decorator for \"streaming\". \ndescription: This package provides a decorator for the Stream type from\n the \"st"- (Fingerprint 14670044663153191927 1427497586294143829)- (Fingerprint 9233007756654759985 6571998449003682006)- (bsReplace "cabal-version: 2" "cabal-version: 2.0")- , mk "name: streaming-bracketed\nversion: 0.1.0.1\nsynopsis: A resource management decorator for \"streaming\". \ndescription: This package provides a decorator for the Stream type from\n \"stream"- (Fingerprint 7298738862909203815 10141693276062967842)- (Fingerprint 1349949738792220441 3593683359695349293)- (bsReplace "cabal-version: 2" "cabal-version: 2.0")- , mk "name: zsyntax\nversion: 0.2.0.0\ndescription: An automated theorem prover for Zsyntax, a\n logical calculus for molecular biology inspired by linear logic,\n that can be used to automatically verify biological\n"- (Fingerprint 17812331267506881875 3005293725141563863)- (Fingerprint 3445957263137759540 12472369104312474458)- (bsReplace "cabal-version: 2" "cabal-version: 2.0")- ]- where- mk a b c d = ((a, b), (c, d))---- | Helper to create entries in patches-_makePatchKey :: FilePath -> (BS.ByteString -> BS.ByteString) -> IO ()-_makePatchKey fp transform = do- contents <- BS.readFile fp- let output = transform contents- let Fingerprint hi lo = md5 contents- let Fingerprint hi' lo' = md5 output- putStrLn- $ showString " , mk "- . shows (BS.take 256 contents)- . showString "\n (Fingerprint "- . shows hi- . showString " "- . shows lo- . showString ")\n (Fingerprint "- . shows hi'- . showString " "- . shows lo'- . showString ")"- $ ""------------------------------------------------------------------------------------ Patch helpers----------------------------------------------------------------------------------bsRemove- :: BS.ByteString -- ^ needle- -> BS.ByteString -> BS.ByteString-bsRemove needle haystack = case BS.breakSubstring needle haystack of- (h, t) -> BS.append h (BS.drop (BS.length needle) t)--bsReplace- :: BS.ByteString -- ^ needle- -> BS.ByteString -- ^ replacement- -> BS.ByteString -> BS.ByteString-bsReplace needle repl haystack = case BS.breakSubstring needle haystack of- (h, t)- | not (BS.null t) -> BS.append h (BS.append repl (BS.drop (BS.length needle) t))- | otherwise -> haystack--bsRemoveStarting- :: BS.ByteString -- ^ needle- -> BS.ByteString -> BS.ByteString-bsRemoveStarting needle haystack = case BS.breakSubstring needle haystack of- (h, _) -> h
− Distribution/PackageDescription/Utils.hs
@@ -1,23 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.PackageDescription.Utils------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Common utils used by modules under Distribution.PackageDescription.*.--module Distribution.PackageDescription.Utils (- cabalBug, userBug- ) where---- ------------------------------------------------------------------------------- Exception and logging utils--userBug :: String -> a-userBug msg = error $ msg ++ ". This is a bug in your .cabal file."--cabalBug :: String -> a-cabalBug msg = error $ msg ++ ". This is possibly a bug in Cabal.\n"- ++ "Please report it to the developers: "- ++ "https://github.com/haskell/cabal/issues/new"
− Distribution/Parsec.hs
@@ -1,524 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-module Distribution.Parsec (- Parsec(..),- ParsecParser (..),- runParsecParser,- runParsecParser',- simpleParsec,- simpleParsecBS,- simpleParsec',- simpleParsecW',- lexemeParsec,- eitherParsec,- explicitEitherParsec,- explicitEitherParsec',- -- * CabalParsing and diagnostics- CabalParsing (..),- -- ** Warnings- PWarnType (..),- PWarning (..),- showPWarning,- -- ** Errors- PError (..),- showPError,- -- * Position- Position (..),- incPos,- retPos,- showPos,- zeroPos,- -- * Utilities- parsecToken,- parsecToken',- parsecFilePath,- parsecQuoted,- parsecMaybeQuoted,- parsecCommaList,- parsecCommaNonEmpty,- parsecLeadingCommaList,- parsecLeadingCommaNonEmpty,- parsecOptCommaList,- parsecLeadingOptCommaList,- parsecStandard,- parsecUnqualComponentName,- ) where--import Data.ByteString (ByteString)-import Data.Char (digitToInt, intToDigit)-import Data.List (transpose)-import Distribution.CabalSpecVersion-import Distribution.Compat.Prelude-import Distribution.Parsec.Error (PError (..), showPError)-import Distribution.Parsec.FieldLineStream (FieldLineStream, fieldLineStreamFromBS, fieldLineStreamFromString)-import Distribution.Parsec.Position (Position (..), incPos, retPos, showPos, zeroPos)-import Distribution.Parsec.Warning (PWarnType (..), PWarning (..), showPWarning)-import Numeric (showIntAtBase)-import Prelude ()--import qualified Distribution.Compat.CharParsing as P-import qualified Distribution.Compat.DList as DList-import qualified Distribution.Compat.MonadFail as Fail-import qualified Text.Parsec as Parsec------------------------------------------------------------------------------------ Class------------------------------------------------------------------------------------ | Class for parsing with @parsec@. Mainly used for @.cabal@ file fields.------ For parsing @.cabal@ like file structure, see "Distribution.Fields".----class Parsec a where- parsec :: CabalParsing m => m a---- | Parsing class which------ * can report Cabal parser warnings.------ * knows @cabal-version@ we work with----class (P.CharParsing m, MonadPlus m, Fail.MonadFail m) => CabalParsing m where- parsecWarning :: PWarnType -> String -> m ()-- parsecHaskellString :: m String- parsecHaskellString = stringLiteral-- askCabalSpecVersion :: m CabalSpecVersion---- | 'parsec' /could/ consume trailing spaces, this function /will/ consume.-lexemeParsec :: (CabalParsing m, Parsec a) => m a-lexemeParsec = parsec <* P.spaces--newtype ParsecParser a = PP { unPP- :: CabalSpecVersion -> Parsec.Parsec FieldLineStream [PWarning] a- }--liftParsec :: Parsec.Parsec FieldLineStream [PWarning] a -> ParsecParser a-liftParsec p = PP $ \_ -> p--instance Functor ParsecParser where- fmap f p = PP $ \v -> fmap f (unPP p v)- {-# INLINE fmap #-}-- x <$ p = PP $ \v -> x <$ unPP p v- {-# INLINE (<$) #-}--instance Applicative ParsecParser where- pure = liftParsec . pure- {-# INLINE pure #-}-- f <*> x = PP $ \v -> unPP f v <*> unPP x v- {-# INLINE (<*>) #-}- f *> x = PP $ \v -> unPP f v *> unPP x v- {-# INLINE (*>) #-}- f <* x = PP $ \v -> unPP f v <* unPP x v- {-# INLINE (<*) #-}--instance Alternative ParsecParser where- empty = liftParsec empty-- a <|> b = PP $ \v -> unPP a v <|> unPP b v- {-# INLINE (<|>) #-}-- many p = PP $ \v -> many (unPP p v)- {-# INLINE many #-}-- some p = PP $ \v -> some (unPP p v)- {-# INLINE some #-}--instance Monad ParsecParser where- return = pure-- m >>= k = PP $ \v -> unPP m v >>= \x -> unPP (k x) v- {-# INLINE (>>=) #-}- (>>) = (*>)- {-# INLINE (>>) #-}--#if !(MIN_VERSION_base(4,13,0))- fail = Fail.fail-#endif--instance MonadPlus ParsecParser where- mzero = empty- mplus = (<|>)--instance Fail.MonadFail ParsecParser where- fail = P.unexpected--instance P.Parsing ParsecParser where- try p = PP $ \v -> P.try (unPP p v)- p <?> d = PP $ \v -> unPP p v P.<?> d- skipMany p = PP $ \v -> P.skipMany (unPP p v)- skipSome p = PP $ \v -> P.skipSome (unPP p v)- unexpected = liftParsec . P.unexpected- eof = liftParsec P.eof- notFollowedBy p = PP $ \v -> P.notFollowedBy (unPP p v)--instance P.CharParsing ParsecParser where- satisfy = liftParsec . P.satisfy- char = liftParsec . P.char- notChar = liftParsec . P.notChar- anyChar = liftParsec P.anyChar- string = liftParsec . P.string--instance CabalParsing ParsecParser where- parsecWarning t w = liftParsec $ do- spos <- Parsec.getPosition- Parsec.modifyState- (PWarning t (Position (Parsec.sourceLine spos) (Parsec.sourceColumn spos)) w :)- askCabalSpecVersion = PP pure---- | Parse a 'String' with 'lexemeParsec'.-simpleParsec :: Parsec a => String -> Maybe a-simpleParsec- = either (const Nothing) Just- . runParsecParser lexemeParsec "<simpleParsec>"- . fieldLineStreamFromString---- | Like 'simpleParsec' but for 'ByteString'-simpleParsecBS :: Parsec a => ByteString -> Maybe a-simpleParsecBS- = either (const Nothing) Just- . runParsecParser lexemeParsec "<simpleParsec>"- . fieldLineStreamFromBS---- | Parse a 'String' with 'lexemeParsec' using specific 'CabalSpecVersion'.------ @since 3.4.0.0-simpleParsec' :: Parsec a => CabalSpecVersion -> String -> Maybe a-simpleParsec' spec- = either (const Nothing) Just- . runParsecParser' spec lexemeParsec "<simpleParsec>"- . fieldLineStreamFromString---- | Parse a 'String' with 'lexemeParsec' using specific 'CabalSpecVersion'.--- Fail if there are any warnings.------ @since 3.4.0.0-simpleParsecW' :: Parsec a => CabalSpecVersion -> String -> Maybe a-simpleParsecW' spec- = either (const Nothing) (\(x, ws) -> if null ws then Just x else Nothing)- . runParsecParser' spec ((,) <$> lexemeParsec <*> liftParsec Parsec.getState) "<simpleParsec>"- . fieldLineStreamFromString---- | Parse a 'String' with 'lexemeParsec'.-eitherParsec :: Parsec a => String -> Either String a-eitherParsec = explicitEitherParsec parsec---- | Parse a 'String' with given 'ParsecParser'. Trailing whitespace is accepted.-explicitEitherParsec :: ParsecParser a -> String -> Either String a-explicitEitherParsec parser- = either (Left . show) Right- . runParsecParser (parser <* P.spaces) "<eitherParsec>"- . fieldLineStreamFromString---- | Parse a 'String' with given 'ParsecParser' and 'CabalSpecVersion'. Trailing whitespace is accepted.--- See 'explicitEitherParsec'.------ @since 3.4.0.0----explicitEitherParsec' :: CabalSpecVersion -> ParsecParser a -> String -> Either String a-explicitEitherParsec' spec parser- = either (Left . show) Right- . runParsecParser' spec (parser <* P.spaces) "<eitherParsec>"- . fieldLineStreamFromString---- | Run 'ParsecParser' with 'cabalSpecLatest'.-runParsecParser :: ParsecParser a -> FilePath -> FieldLineStream -> Either Parsec.ParseError a-runParsecParser = runParsecParser' cabalSpecLatest---- | Like 'runParsecParser' but lets specify 'CabalSpecVersion' used.------ @since 3.0.0.0----runParsecParser' :: CabalSpecVersion -> ParsecParser a -> FilePath -> FieldLineStream -> Either Parsec.ParseError a-runParsecParser' v p n = Parsec.runParser (unPP p v <* P.eof) [] n--instance Parsec a => Parsec (Identity a) where- parsec = Identity <$> parsec--instance Parsec Bool where- parsec = P.munch1 isAlpha >>= postprocess- where- postprocess str- | str == "True" = pure True- | str == "False" = pure False- | lstr == "true" = parsecWarning PWTBoolCase caseWarning *> pure True- | lstr == "false" = parsecWarning PWTBoolCase caseWarning *> pure False- | otherwise = fail $ "Not a boolean: " ++ str- where- lstr = map toLower str- caseWarning =- "Boolean values are case sensitive, use 'True' or 'False'."---- | @[^ ,]@-parsecToken :: CabalParsing m => m String-parsecToken = parsecHaskellString <|> ((P.munch1 (\x -> not (isSpace x) && x /= ',') P.<?> "identifier" ) >>= checkNotDoubleDash)---- | @[^ ]@-parsecToken' :: CabalParsing m => m String-parsecToken' = parsecHaskellString <|> ((P.munch1 (not . isSpace) P.<?> "token") >>= checkNotDoubleDash)--checkNotDoubleDash :: CabalParsing m => String -> m String-checkNotDoubleDash s = do- when (s == "--") $ parsecWarning PWTDoubleDash $ unwords- [ "Double-dash token found."- , "Note: there are no end-of-line comments in .cabal files, only whole line comments."- , "Use \"--\" (quoted double dash) to silence this warning, if you actually want -- token"- ]-- return s--parsecFilePath :: CabalParsing m => m FilePath-parsecFilePath = parsecToken---- | Parse a benchmark/test-suite types.-parsecStandard :: (CabalParsing m, Parsec ver) => (ver -> String -> a) -> m a-parsecStandard f = do- cs <- some $ P.try (component <* P.char '-')- ver <- parsec- let name = map toLower (intercalate "-" cs)- return $! f ver name- where- component = do- cs <- P.munch1 isAlphaNum- if all isDigit cs then fail "all digit component" else return cs- -- each component must contain an alphabetic character, to avoid- -- ambiguity in identifiers like foo-1 (the 1 is the version number).--parsecCommaList :: CabalParsing m => m a -> m [a]-parsecCommaList p = P.sepBy (p <* P.spaces) (P.char ',' *> P.spaces P.<?> "comma")--parsecCommaNonEmpty :: CabalParsing m => m a -> m (NonEmpty a)-parsecCommaNonEmpty p = P.sepByNonEmpty (p <* P.spaces) (P.char ',' *> P.spaces P.<?> "comma")---- | Like 'parsecCommaList' but accept leading or trailing comma.------ @--- p (comma p)* -- p `sepBy` comma--- (comma p)* -- leading comma--- (p comma)* -- trailing comma--- @-parsecLeadingCommaList :: CabalParsing m => m a -> m [a]-parsecLeadingCommaList p = do- c <- P.optional comma- case c of- Nothing -> toList <$> P.sepEndByNonEmpty lp comma <|> pure []- Just _ -> toList <$> P.sepByNonEmpty lp comma- where- lp = p <* P.spaces- comma = P.char ',' *> P.spaces P.<?> "comma"---- |------ @since 3.4.0.0-parsecLeadingCommaNonEmpty :: CabalParsing m => m a -> m (NonEmpty a)-parsecLeadingCommaNonEmpty p = do- c <- P.optional comma- case c of- Nothing -> P.sepEndByNonEmpty lp comma- Just _ -> P.sepByNonEmpty lp comma- where- lp = p <* P.spaces- comma = P.char ',' *> P.spaces P.<?> "comma"--parsecOptCommaList :: CabalParsing m => m a -> m [a]-parsecOptCommaList p = P.sepBy (p <* P.spaces) (P.optional comma)- where- comma = P.char ',' *> P.spaces---- | Like 'parsecOptCommaList' but------ * require all or none commas--- * accept leading or trailing comma.------ @--- p (comma p)* -- p `sepBy` comma--- (comma p)* -- leading comma--- (p comma)* -- trailing comma--- p* -- no commas: many p--- @------ @since 3.0.0.0----parsecLeadingOptCommaList :: CabalParsing m => m a -> m [a]-parsecLeadingOptCommaList p = do- c <- P.optional comma- case c of- Nothing -> sepEndBy1Start <|> pure []- Just _ -> toList <$> P.sepByNonEmpty lp comma- where- lp = p <* P.spaces- comma = P.char ',' *> P.spaces P.<?> "comma"-- sepEndBy1Start = do- x <- lp- c <- P.optional comma- case c of- Nothing -> (x :) <$> many lp- Just _ -> (x :) <$> P.sepEndBy lp comma---- | Content isn't unquoted-parsecQuoted :: CabalParsing m => m a -> m a-parsecQuoted = P.between (P.char '"') (P.char '"')---- | @parsecMaybeQuoted p = 'parsecQuoted' p <|> p@.-parsecMaybeQuoted :: CabalParsing m => m a -> m a-parsecMaybeQuoted p = parsecQuoted p <|> p--parsecUnqualComponentName :: forall m. CabalParsing m => m String-parsecUnqualComponentName = state0 DList.empty where- --- -- using @kleene@ package we can easily see that- -- we need only two states to recognize- -- unqual-component-name- --- -- Compare with declarative- -- 'Distribution.FieldGrammar.Described.reUnqualComponent'.- --- -- @- -- import Kleene- -- import Kleene.Internal.Pretty- -- import Algebra.Lattice- -- import Data.Char- --- -- import qualified Data.RangeSet.Map as RSet- --- -- main = do- -- -- this is an approximation, to get an idea.- -- let component :: RE Char- -- component = star alphaNum <> alpha <> star alphaNum- --- -- alphaNum = alpha \/ num- -- alpha = unions $ map char ['a'..'z']- -- num = unions $ map char ['0'..'9']- --- -- re :: RE Char- -- re = component <> star (char '-' <> component)- --- -- putPretty re- -- putPretty $ fromTM re- -- @-- state0 :: DList.DList Char -> m String- state0 acc = do- c <- ch -- <|> fail ("Invalid component, after " ++ DList.toList acc)- case () of- _ | isDigit c -> state0 (DList.snoc acc c)- | isAlphaNum c -> state1 (DList.snoc acc c)- | c == '-' -> fail ("Empty component, after " ++ DList.toList acc)- | otherwise -> fail ("Internal error, after " ++ DList.toList acc)-- state1 :: DList.DList Char -> m String- state1 acc = state1' acc `alt` return (DList.toList acc)-- state1' :: DList.DList Char -> m String- state1' acc = do- c <- ch- case () of- _ | isAlphaNum c -> state1 (DList.snoc acc c)- | c == '-' -> state0 (DList.snoc acc c)- | otherwise -> fail ("Internal error, after " ++ DList.toList acc)-- ch :: m Char- !ch = P.satisfy (\c -> isAlphaNum c || c == '-')-- alt :: m String -> m String -> m String- !alt = (<|>)--stringLiteral :: forall m. P.CharParsing m => m String-stringLiteral = lit where- lit :: m String- lit = foldr (maybe id (:)) ""- <$> P.between (P.char '"') (P.char '"' P.<?> "end of string") (many stringChar)- P.<?> "string"-- stringChar :: m (Maybe Char)- stringChar = Just <$> stringLetter- <|> stringEscape- P.<?> "string character"-- stringLetter :: m Char- stringLetter = P.satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026'))-- stringEscape :: m (Maybe Char)- stringEscape = P.char '\\' *> esc where- esc :: m (Maybe Char)- esc = Nothing <$ escapeGap- <|> Nothing <$ escapeEmpty- <|> Just <$> escapeCode-- escapeEmpty, escapeGap :: m Char- escapeEmpty = P.char '&'- escapeGap = P.skipSpaces1 *> (P.char '\\' P.<?> "end of string gap")--escapeCode :: forall m. P.CharParsing m => m Char-escapeCode = (charEsc <|> charNum <|> charAscii <|> charControl) P.<?> "escape code"- where- charControl, charNum :: m Char- charControl = (\c -> toEnum (fromEnum c - fromEnum '@')) <$> (P.char '^' *> (P.upper <|> P.char '@'))- charNum = toEnum <$> num- where- num :: m Int- num = bounded 10 maxchar- <|> (P.char 'o' *> bounded 8 maxchar)- <|> (P.char 'x' *> bounded 16 maxchar)- maxchar = fromEnum (maxBound :: Char)-- bounded :: Int -> Int -> m Int- bounded base bnd = foldl' (\x d -> base * x + digitToInt d) 0- <$> bounded' (take base thedigits) (map digitToInt $ showIntAtBase base intToDigit bnd "")- where- thedigits :: [m Char]- thedigits = map P.char ['0'..'9'] ++ map P.oneOf (transpose [['A'..'F'],['a'..'f']])-- toomuch :: m a- toomuch = P.unexpected "out-of-range numeric escape sequence"-- bounded', bounded'' :: [m Char] -> [Int] -> m [Char]- bounded' dps@(zero:_) bds = P.skipSome zero *> ([] <$ P.notFollowedBy (P.choice dps) <|> bounded'' dps bds)- <|> bounded'' dps bds- bounded' [] _ = error "bounded called with base 0"- bounded'' dps [] = [] <$ P.notFollowedBy (P.choice dps) <|> toomuch- bounded'' dps (bd : bds) = let anyd :: m Char- anyd = P.choice dps-- nomore :: m ()- nomore = P.notFollowedBy anyd <|> toomuch-- (low, ex, high) = case splitAt bd dps of- (low', ex' : high') -> (low', ex', high')- (_, _) -> error "escapeCode: Logic error"- in ((:) <$> P.choice low <*> atMost (length bds) anyd) <* nomore- <|> ((:) <$> ex <*> ([] <$ nomore <|> bounded'' dps bds))- <|> if not (null bds)- then (:) <$> P.choice high <*> atMost (length bds - 1) anyd <* nomore- else empty- atMost n p | n <= 0 = pure []- | otherwise = ((:) <$> p <*> atMost (n - 1) p) <|> pure []-- charEsc :: m Char- charEsc = P.choice $ parseEsc <$> escMap-- parseEsc (c,code) = code <$ P.char c- escMap = zip "abfnrtv\\\"\'" "\a\b\f\n\r\t\v\\\"\'"-- charAscii :: m Char- charAscii = P.choice $ parseAscii <$> asciiMap-- parseAscii (asc,code) = P.try $ code <$ P.string asc- asciiMap = zip (ascii3codes ++ ascii2codes) (ascii3 ++ ascii2)- ascii2codes, ascii3codes :: [String]- ascii2codes = [ "BS","HT","LF","VT","FF","CR","SO"- , "SI","EM","FS","GS","RS","US","SP"]- ascii3codes = ["NUL","SOH","STX","ETX","EOT","ENQ","ACK"- ,"BEL","DLE","DC1","DC2","DC3","DC4","NAK"- ,"SYN","ETB","CAN","SUB","ESC","DEL"]- ascii2, ascii3 :: String- ascii2 = "\BS\HT\LF\VT\FF\CR\SO\SI\EM\FS\GS\RS\US\SP"- ascii3 = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK\BEL\DLE\DC1\DC2\DC3\DC4\NAK\SYN\ETB\CAN\SUB\ESC\DEL"
− Distribution/Parsec/Error.hs
@@ -1,21 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Parsec.Error (- PError (..),- showPError,- ) where--import Distribution.Compat.Prelude-import Distribution.Parsec.Position-import Prelude ()-import System.FilePath (normalise)---- | Parser error.-data PError = PError Position String- deriving (Show, Generic)--instance Binary PError-instance NFData PError where rnf = genericRnf--showPError :: FilePath -> PError -> String-showPError fpath (PError pos msg) =- normalise fpath ++ ":" ++ showPos pos ++ ": " ++ msg
− Distribution/Parsec/FieldLineStream.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -Wall -Werror #-}-module Distribution.Parsec.FieldLineStream (- FieldLineStream (..),- fieldLineStreamFromString,- fieldLineStreamFromBS,- fieldLineStreamEnd,- ) where--import Data.Bits-import Data.ByteString (ByteString)-import Distribution.Compat.Prelude-import Distribution.Utils.Generic (toUTF8BS)-import Prelude ()--import qualified Data.ByteString as BS-import qualified Text.Parsec as Parsec---- | This is essentially a lazy bytestring, but chunks are glued with newline @\'\\n\'@.-data FieldLineStream- = FLSLast !ByteString- | FLSCons {-# UNPACK #-} !ByteString FieldLineStream- deriving Show--fieldLineStreamEnd :: FieldLineStream-fieldLineStreamEnd = FLSLast mempty---- | Convert 'String' to 'FieldLineStream'.------ /Note:/ inefficient!-fieldLineStreamFromString :: String -> FieldLineStream-fieldLineStreamFromString = FLSLast . toUTF8BS--fieldLineStreamFromBS :: ByteString -> FieldLineStream-fieldLineStreamFromBS = FLSLast--instance Monad m => Parsec.Stream FieldLineStream m Char where- uncons (FLSLast bs) = return $ case BS.uncons bs of- Nothing -> Nothing- Just (c, bs') -> Just (unconsChar c bs' (\bs'' -> FLSLast bs'') fieldLineStreamEnd)-- uncons (FLSCons bs s) = return $ case BS.uncons bs of- -- as lines are glued with '\n', we return '\n' here!- Nothing -> Just ('\n', s)- Just (c, bs') -> Just (unconsChar c bs' (\bs'' -> FLSCons bs'' s) s)---- Based on implementation 'decodeStringUtf8'-unconsChar :: forall a. Word8 -> ByteString -> (ByteString -> a) -> a -> (Char, a)-unconsChar c0 bs0 f next- | c0 <= 0x7F = (chr (fromIntegral c0), f bs0)- | c0 <= 0xBF = (replacementChar, f bs0)- | c0 <= 0xDF = twoBytes- | c0 <= 0xEF = moreBytes 3 0x800 bs0 (fromIntegral $ c0 .&. 0xF)- | c0 <= 0xF7 = moreBytes 4 0x10000 bs0 (fromIntegral $ c0 .&. 0x7)- | c0 <= 0xFB = moreBytes 5 0x200000 bs0 (fromIntegral $ c0 .&. 0x3)- | c0 <= 0xFD = moreBytes 6 0x4000000 bs0 (fromIntegral $ c0 .&. 0x1)- | otherwise = error $ "not implemented " ++ show c0- where- twoBytes = case BS.uncons bs0 of- Nothing -> (replacementChar, next)- Just (c1, bs1)- | c1 .&. 0xC0 == 0x80 ->- if d >= 0x80- then (chr d, f bs1)- else (replacementChar, f bs1)- | otherwise -> (replacementChar, f bs1)- where- d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6) .|. fromIntegral (c1 .&. 0x3F)-- moreBytes :: Int -> Int -> ByteString -> Int -> (Char, a)- moreBytes 1 overlong bs' acc- | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc- = (chr acc, f bs')- | otherwise- = (replacementChar, f bs')-- moreBytes byteCount overlong bs' acc = case BS.uncons bs' of- Nothing -> (replacementChar, f bs')- Just (cn, bs1)- | cn .&. 0xC0 == 0x80 -> moreBytes- (byteCount-1)- overlong- bs1- ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)- | otherwise -> (replacementChar, f bs1)--replacementChar :: Char-replacementChar = '\xfffd'
− Distribution/Parsec/Position.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Parsec.Position (- Position (..),- incPos,- retPos,- showPos,- zeroPos,- positionCol,- positionRow,- ) where--import Distribution.Compat.Prelude-import Prelude ()---- | 1-indexed row and column positions in a file.-data Position = Position- {-# UNPACK #-} !Int -- row- {-# UNPACK #-} !Int -- column- deriving (Eq, Ord, Show, Generic)--instance Binary Position-instance NFData Position where rnf = genericRnf---- | Shift position by n columns to the right.-incPos :: Int -> Position -> Position-incPos n (Position row col) = Position row (col + n)---- | Shift position to beginning of next row.-retPos :: Position -> Position-retPos (Position row _col) = Position (row + 1) 1--showPos :: Position -> String-showPos (Position row col) = show row ++ ":" ++ show col--zeroPos :: Position-zeroPos = Position 0 0---- | @since 3.0.0.0-positionCol :: Position -> Int-positionCol (Position _ c) = c---- | @since 3.0.0.0-positionRow :: Position -> Int-positionRow (Position r _) = r
− Distribution/Parsec/Warning.hs
@@ -1,59 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Parsec.Warning (- PWarning (..),- PWarnType (..),- showPWarning,- ) where--import Distribution.Compat.Prelude-import Distribution.Parsec.Position-import Prelude ()-import System.FilePath (normalise)---- | Type of parser warning. We do classify warnings.------ Different application may decide not to show some, or have fatal behaviour on others-data PWarnType- = PWTOther -- ^ Unclassified warning- | PWTUTF -- ^ Invalid UTF encoding- | PWTBoolCase -- ^ @true@ or @false@, not @True@ or @False@- | PWTVersionTag -- ^ there are version with tags- | PWTNewSyntax -- ^ New syntax used, but no @cabal-version: >= 1.2@ specified- | PWTOldSyntax -- ^ Old syntax used, and @cabal-version >= 1.2@ specified- | PWTDeprecatedField- | PWTInvalidSubsection- | PWTUnknownField- | PWTUnknownSection- | PWTTrailingFields- | PWTExtraMainIs -- ^ extra main-is field- | PWTExtraTestModule -- ^ extra test-module field- | PWTExtraBenchmarkModule -- ^ extra benchmark-module field- | PWTLexNBSP- | PWTLexBOM- | PWTLexTab- | PWTQuirkyCabalFile -- ^ legacy cabal file that we know how to patch- | PWTDoubleDash -- ^ Double dash token, most likely it's a mistake - it's not a comment- | PWTMultipleSingularField -- ^ e.g. name or version should be specified only once.- | PWTBuildTypeDefault -- ^ Workaround for derive-package having build-type: Default. See <https://github.com/haskell/cabal/issues/5020>.-- | PWTVersionOperator -- ^ Version operators used (without cabal-version: 1.8)- | PWTVersionWildcard -- ^ Version wildcard used (without cabal-version: 1.6)-- | PWTSpecVersion -- ^ Warnings about cabal-version format.-- | PWTExperimental -- ^ Experimental feature- deriving (Eq, Ord, Show, Enum, Bounded, Generic)--instance Binary PWarnType-instance NFData PWarnType where rnf = genericRnf---- | Parser warning.-data PWarning = PWarning !PWarnType !Position String- deriving (Show, Generic)--instance Binary PWarning-instance NFData PWarning where rnf = genericRnf--showPWarning :: FilePath -> PWarning -> String-showPWarning fpath (PWarning _ pos msg) =- normalise fpath ++ ":" ++ showPos pos ++ ": " ++ msg
− Distribution/Pretty.hs
@@ -1,106 +0,0 @@-module Distribution.Pretty (- Pretty (..),- prettyShow,- defaultStyle,- flatStyle,- -- * Utilities- showFilePath,- showToken,- showFreeText,- showFreeTextV3,- -- * Deprecated- Separator,- ) where--import Distribution.CabalSpecVersion-import Distribution.Compat.Prelude-import Prelude ()--import qualified Text.PrettyPrint as PP--class Pretty a where- pretty :: a -> PP.Doc-- prettyVersioned :: CabalSpecVersion -> a -> PP.Doc- prettyVersioned _ = pretty---- | @since 3.4.0.0-instance Pretty PP.Doc where- pretty = id--instance Pretty Bool where- pretty = PP.text . show--instance Pretty Int where- pretty = PP.text . show--instance Pretty a => Pretty (Identity a) where- pretty = pretty . runIdentity--prettyShow :: Pretty a => a -> String-prettyShow = PP.renderStyle defaultStyle . pretty---- | The default rendering style used in Cabal for console--- output. It has a fixed page width and adds line breaks--- automatically.-defaultStyle :: PP.Style-defaultStyle = PP.Style { PP.mode = PP.PageMode- , PP.lineLength = 79- , PP.ribbonsPerLine = 1.0- }---- | A style for rendering all on one line.-flatStyle :: PP.Style-flatStyle = PP.Style { PP.mode = PP.LeftMode- , PP.lineLength = err "lineLength"- , PP.ribbonsPerLine = err "ribbonsPerLine"- }- where- err x = error ("flatStyle: tried to access " ++ x ++ " in LeftMode. " ++- "This should never happen and indicates a bug in Cabal.")------------------------------------------------------------------------------------ Utilities------------------------------------------------------------------------------------ TODO: remove when ReadP parser is gone.-type Separator = [PP.Doc] -> PP.Doc--showFilePath :: FilePath -> PP.Doc-showFilePath = showToken--showToken :: String -> PP.Doc-showToken str- -- if token looks like a comment (starts with --), print it in quotes- | "--" `isPrefixOf` str = PP.text (show str)- -- also if token ends with a colon (e.g. executable name), print it in quotes- | ":" `isSuffixOf` str = PP.text (show str)- | not (any dodgy str) && not (null str) = PP.text str- | otherwise = PP.text (show str)- where- dodgy c = isSpace c || c == ','----- | Pretty-print free-format text, ensuring that it is vertically aligned,--- and with blank lines replaced by dots for correct re-parsing.-showFreeText :: String -> PP.Doc-showFreeText "" = mempty-showFreeText s = PP.vcat [ PP.text (if null l then "." else l) | l <- lines_ s ]---- | Pretty-print free-format text.--- Since @cabal-version: 3.0@ we don't replace blank lines with dots.------ @since 3.0.0.0-showFreeTextV3 :: String -> PP.Doc-showFreeTextV3 "" = mempty-showFreeTextV3 s = PP.vcat [ PP.text l | l <- lines_ s ]---- | 'lines_' breaks a string up into a list of strings at newline--- characters. The resulting strings do not contain newlines.-lines_ :: String -> [String]-lines_ [] = [""]-lines_ s =- let (l, s') = break (== '\n') s- in l : case s' of- [] -> []- (_:s'') -> lines_ s''
− Distribution/ReadE.hs
@@ -1,49 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.ReadE--- Copyright : Jose Iborra 2008--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Simple parsing with failure--module Distribution.ReadE (- -- * ReadE- ReadE(..), succeedReadE, failReadE,- -- * Projections- readEOrFail,- parsecToReadE,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Parsec.FieldLineStream---- | Parser with simple error reporting-newtype ReadE a = ReadE {runReadE :: String -> Either ErrorMsg a}-type ErrorMsg = String--instance Functor ReadE where- fmap f (ReadE p) = ReadE $ \txt -> case p txt of- Right a -> Right (f a)- Left err -> Left err--succeedReadE :: (String -> a) -> ReadE a-succeedReadE f = ReadE (Right . f)--failReadE :: ErrorMsg -> ReadE a-failReadE = ReadE . const . Left--readEOrFail :: ReadE a -> String -> a-readEOrFail r = either error id . runReadE r--parsecToReadE :: (String -> ErrorMsg) -> ParsecParser a -> ReadE a-parsecToReadE err p = ReadE $ \txt ->- case runParsecParser p "<parsecToReadE>" (fieldLineStreamFromString txt) of- Right x -> Right x- Left _e -> Left (err txt)--- TODO: use parsec error to make 'ErrorMsg'.
− Distribution/SPDX.hs
@@ -1,40 +0,0 @@--- | This module implements SPDX specification version 2.1 with a version 3.0 license list.------ Specification is available on <https://spdx.org/specifications>-module Distribution.SPDX (- -- * License- License (..),- -- * License expression- LicenseExpression (..),- SimpleLicenseExpression (..),- simpleLicenseExpression,- -- * License identifier- LicenseId (..),- licenseId,- licenseName,- licenseIsOsiApproved,- mkLicenseId,- licenseIdList,- -- * License exception- LicenseExceptionId (..),- licenseExceptionId,- licenseExceptionName,- mkLicenseExceptionId,- licenseExceptionIdList,- -- * License reference- LicenseRef,- licenseRef,- licenseDocumentRef,- mkLicenseRef,- mkLicenseRef',- -- * License list version- LicenseListVersion (..),- cabalSpecVersionToSPDXListVersion,- ) where--import Distribution.SPDX.LicenseExceptionId-import Distribution.SPDX.License-import Distribution.SPDX.LicenseId-import Distribution.SPDX.LicenseExpression-import Distribution.SPDX.LicenseReference-import Distribution.SPDX.LicenseListVersion
− Distribution/SPDX/License.hs
@@ -1,65 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.SPDX.License (- License (..),- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Pretty-import Distribution.Parsec-import Distribution.SPDX.LicenseExpression--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | Declared license.--- See [section 3.15 of SPDX Specification 2.1](https://spdx.org/spdx-specification-21-web-version#h.1hmsyys)------ /Note:/ the NOASSERTION case is omitted.------ Old 'License' can be migrated using following rules:------ * @AllRightsReserved@ and @UnspecifiedLicense@ to 'NONE'.--- No license specified which legally defaults to /All Rights Reserved/.--- The package may not be legally modified or redistributed by anyone but--- the rightsholder.------ * @OtherLicense@ can be converted to 'LicenseRef' pointing to the file--- in the package.------ * @UnknownLicense@ i.e. other licenses of the form @name-x.y@, should be--- covered by SPDX license list, otherwise use 'LicenseRef'.------ * @PublicDomain@ isn't covered. Consider using CC0.--- See <https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files>--- for more information.----data License- = NONE- -- ^ if the package contains no license information whatsoever; or- | License LicenseExpression- -- ^ A valid SPDX License Expression as defined in Appendix IV.- deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)--instance Binary License-instance Structured License--instance NFData License where- rnf NONE = ()- rnf (License l) = rnf l--instance Pretty License where- pretty NONE = Disp.text "NONE"- pretty (License l) = pretty l---- |--- >>> eitherParsec "BSD-3-Clause AND MIT" :: Either String License--- Right (License (EAnd (ELicense (ELicenseId BSD_3_Clause) Nothing) (ELicense (ELicenseId MIT) Nothing)))------ >>> eitherParsec "NONE" :: Either String License--- Right NONE----instance Parsec License where- parsec = NONE <$ P.try (P.string "NONE") <|> License <$> parsec
− Distribution/SPDX/LicenseExceptionId.hs
@@ -1,294 +0,0 @@--- This file is generated. See Makefile's spdx rule-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.SPDX.LicenseExceptionId (- LicenseExceptionId (..),- licenseExceptionId,- licenseExceptionName,- mkLicenseExceptionId,- licenseExceptionIdList,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Compat.Lens (set)-import Distribution.Pretty-import Distribution.Parsec-import Distribution.Utils.Generic (isAsciiAlphaNum)-import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion)-import Distribution.SPDX.LicenseListVersion--import qualified Data.Binary.Get as Binary-import qualified Data.Binary.Put as Binary-import qualified Data.Map.Strict as Map-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp------------------------------------------------------------------------------------ LicenseExceptionId------------------------------------------------------------------------------------ | SPDX License identifier-data LicenseExceptionId- = DS389_exception -- ^ @389-exception@, 389 Directory Server Exception- | Autoconf_exception_2_0 -- ^ @Autoconf-exception-2.0@, Autoconf exception 2.0- | Autoconf_exception_3_0 -- ^ @Autoconf-exception-3.0@, Autoconf exception 3.0- | Bison_exception_2_2 -- ^ @Bison-exception-2.2@, Bison exception 2.2- | Bootloader_exception -- ^ @Bootloader-exception@, Bootloader Distribution Exception- | Classpath_exception_2_0 -- ^ @Classpath-exception-2.0@, Classpath exception 2.0- | CLISP_exception_2_0 -- ^ @CLISP-exception-2.0@, CLISP exception 2.0- | DigiRule_FOSS_exception -- ^ @DigiRule-FOSS-exception@, DigiRule FOSS License Exception- | ECos_exception_2_0 -- ^ @eCos-exception-2.0@, eCos exception 2.0- | Fawkes_Runtime_exception -- ^ @Fawkes-Runtime-exception@, Fawkes Runtime Exception- | FLTK_exception -- ^ @FLTK-exception@, FLTK exception- | Font_exception_2_0 -- ^ @Font-exception-2.0@, Font exception 2.0- | Freertos_exception_2_0 -- ^ @freertos-exception-2.0@, FreeRTOS Exception 2.0- | GCC_exception_2_0 -- ^ @GCC-exception-2.0@, GCC Runtime Library exception 2.0- | GCC_exception_3_1 -- ^ @GCC-exception-3.1@, GCC Runtime Library exception 3.1- | Gnu_javamail_exception -- ^ @gnu-javamail-exception@, GNU JavaMail exception- | GPL_3_0_linking_exception -- ^ @GPL-3.0-linking-exception@, GPL-3.0 Linking Exception, SPDX License List 3.9- | GPL_3_0_linking_source_exception -- ^ @GPL-3.0-linking-source-exception@, GPL-3.0 Linking Exception (with Corresponding Source), SPDX License List 3.9- | GPL_CC_1_0 -- ^ @GPL-CC-1.0@, GPL Cooperation Commitment 1.0, SPDX License List 3.6, SPDX License List 3.9- | I2p_gpl_java_exception -- ^ @i2p-gpl-java-exception@, i2p GPL+Java Exception- | LGPL_3_0_linking_exception -- ^ @LGPL-3.0-linking-exception@, LGPL-3.0 Linking Exception, SPDX License List 3.9- | Libtool_exception -- ^ @Libtool-exception@, Libtool Exception- | Linux_syscall_note -- ^ @Linux-syscall-note@, Linux Syscall Note- | LLVM_exception -- ^ @LLVM-exception@, LLVM Exception, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | LZMA_exception -- ^ @LZMA-exception@, LZMA exception- | Mif_exception -- ^ @mif-exception@, Macros and Inline Functions Exception- | Nokia_Qt_exception_1_1 -- ^ @Nokia-Qt-exception-1.1@, Nokia Qt LGPL exception 1.1, SPDX License List 3.0, SPDX License List 3.2- | OCaml_LGPL_linking_exception -- ^ @OCaml-LGPL-linking-exception@, OCaml LGPL Linking Exception, SPDX License List 3.6, SPDX License List 3.9- | OCCT_exception_1_0 -- ^ @OCCT-exception-1.0@, Open CASCADE Exception 1.0- | OpenJDK_assembly_exception_1_0 -- ^ @OpenJDK-assembly-exception-1.0@, OpenJDK Assembly exception 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | Openvpn_openssl_exception -- ^ @openvpn-openssl-exception@, OpenVPN OpenSSL Exception- | PS_or_PDF_font_exception_20170817 -- ^ @PS-or-PDF-font-exception-20170817@, PS/PDF font exception (2017-08-17), SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | Qt_GPL_exception_1_0 -- ^ @Qt-GPL-exception-1.0@, Qt GPL exception 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | Qt_LGPL_exception_1_1 -- ^ @Qt-LGPL-exception-1.1@, Qt LGPL exception 1.1, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | Qwt_exception_1_0 -- ^ @Qwt-exception-1.0@, Qwt exception 1.0- | SHL_2_0 -- ^ @SHL-2.0@, Solderpad Hardware License v2.0, SPDX License List 3.9- | SHL_2_1 -- ^ @SHL-2.1@, Solderpad Hardware License v2.1, SPDX License List 3.9- | Swift_exception -- ^ @Swift-exception@, Swift Exception, SPDX License List 3.6, SPDX License List 3.9- | U_boot_exception_2_0 -- ^ @u-boot-exception-2.0@, U-Boot exception 2.0- | Universal_FOSS_exception_1_0 -- ^ @Universal-FOSS-exception-1.0@, Universal FOSS Exception, Version 1.0, SPDX License List 3.6, SPDX License List 3.9- | WxWindows_exception_3_1 -- ^ @WxWindows-exception-3.1@, WxWindows Library Exception 3.1- deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)--instance Binary LicenseExceptionId where- put = Binary.putWord8 . fromIntegral . fromEnum- get = do- i <- Binary.getWord8- if i > fromIntegral (fromEnum (maxBound :: LicenseExceptionId))- then fail "Too large LicenseExceptionId tag"- else return (toEnum (fromIntegral i))---- note: remember to bump version each time the definition changes-instance Structured LicenseExceptionId where- structure p = set typeVersion 306 $ nominalStructure p--instance Pretty LicenseExceptionId where- pretty = Disp.text . licenseExceptionId--instance Parsec LicenseExceptionId where- parsec = do- n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'- v <- askCabalSpecVersion- maybe (fail $ "Unknown SPDX license exception identifier: " ++ n) return $- mkLicenseExceptionId (cabalSpecVersionToSPDXListVersion v) n--instance NFData LicenseExceptionId where- rnf l = l `seq` ()------------------------------------------------------------------------------------ License Data------------------------------------------------------------------------------------ | License SPDX identifier, e.g. @"BSD-3-Clause"@.-licenseExceptionId :: LicenseExceptionId -> String-licenseExceptionId DS389_exception = "389-exception"-licenseExceptionId Autoconf_exception_2_0 = "Autoconf-exception-2.0"-licenseExceptionId Autoconf_exception_3_0 = "Autoconf-exception-3.0"-licenseExceptionId Bison_exception_2_2 = "Bison-exception-2.2"-licenseExceptionId Bootloader_exception = "Bootloader-exception"-licenseExceptionId Classpath_exception_2_0 = "Classpath-exception-2.0"-licenseExceptionId CLISP_exception_2_0 = "CLISP-exception-2.0"-licenseExceptionId DigiRule_FOSS_exception = "DigiRule-FOSS-exception"-licenseExceptionId ECos_exception_2_0 = "eCos-exception-2.0"-licenseExceptionId Fawkes_Runtime_exception = "Fawkes-Runtime-exception"-licenseExceptionId FLTK_exception = "FLTK-exception"-licenseExceptionId Font_exception_2_0 = "Font-exception-2.0"-licenseExceptionId Freertos_exception_2_0 = "freertos-exception-2.0"-licenseExceptionId GCC_exception_2_0 = "GCC-exception-2.0"-licenseExceptionId GCC_exception_3_1 = "GCC-exception-3.1"-licenseExceptionId Gnu_javamail_exception = "gnu-javamail-exception"-licenseExceptionId GPL_3_0_linking_exception = "GPL-3.0-linking-exception"-licenseExceptionId GPL_3_0_linking_source_exception = "GPL-3.0-linking-source-exception"-licenseExceptionId GPL_CC_1_0 = "GPL-CC-1.0"-licenseExceptionId I2p_gpl_java_exception = "i2p-gpl-java-exception"-licenseExceptionId LGPL_3_0_linking_exception = "LGPL-3.0-linking-exception"-licenseExceptionId Libtool_exception = "Libtool-exception"-licenseExceptionId Linux_syscall_note = "Linux-syscall-note"-licenseExceptionId LLVM_exception = "LLVM-exception"-licenseExceptionId LZMA_exception = "LZMA-exception"-licenseExceptionId Mif_exception = "mif-exception"-licenseExceptionId Nokia_Qt_exception_1_1 = "Nokia-Qt-exception-1.1"-licenseExceptionId OCaml_LGPL_linking_exception = "OCaml-LGPL-linking-exception"-licenseExceptionId OCCT_exception_1_0 = "OCCT-exception-1.0"-licenseExceptionId OpenJDK_assembly_exception_1_0 = "OpenJDK-assembly-exception-1.0"-licenseExceptionId Openvpn_openssl_exception = "openvpn-openssl-exception"-licenseExceptionId PS_or_PDF_font_exception_20170817 = "PS-or-PDF-font-exception-20170817"-licenseExceptionId Qt_GPL_exception_1_0 = "Qt-GPL-exception-1.0"-licenseExceptionId Qt_LGPL_exception_1_1 = "Qt-LGPL-exception-1.1"-licenseExceptionId Qwt_exception_1_0 = "Qwt-exception-1.0"-licenseExceptionId SHL_2_0 = "SHL-2.0"-licenseExceptionId SHL_2_1 = "SHL-2.1"-licenseExceptionId Swift_exception = "Swift-exception"-licenseExceptionId U_boot_exception_2_0 = "u-boot-exception-2.0"-licenseExceptionId Universal_FOSS_exception_1_0 = "Universal-FOSS-exception-1.0"-licenseExceptionId WxWindows_exception_3_1 = "WxWindows-exception-3.1"---- | License name, e.g. @"GNU General Public License v2.0 only"@-licenseExceptionName :: LicenseExceptionId -> String-licenseExceptionName DS389_exception = "389 Directory Server Exception"-licenseExceptionName Autoconf_exception_2_0 = "Autoconf exception 2.0"-licenseExceptionName Autoconf_exception_3_0 = "Autoconf exception 3.0"-licenseExceptionName Bison_exception_2_2 = "Bison exception 2.2"-licenseExceptionName Bootloader_exception = "Bootloader Distribution Exception"-licenseExceptionName Classpath_exception_2_0 = "Classpath exception 2.0"-licenseExceptionName CLISP_exception_2_0 = "CLISP exception 2.0"-licenseExceptionName DigiRule_FOSS_exception = "DigiRule FOSS License Exception"-licenseExceptionName ECos_exception_2_0 = "eCos exception 2.0"-licenseExceptionName Fawkes_Runtime_exception = "Fawkes Runtime Exception"-licenseExceptionName FLTK_exception = "FLTK exception"-licenseExceptionName Font_exception_2_0 = "Font exception 2.0"-licenseExceptionName Freertos_exception_2_0 = "FreeRTOS Exception 2.0"-licenseExceptionName GCC_exception_2_0 = "GCC Runtime Library exception 2.0"-licenseExceptionName GCC_exception_3_1 = "GCC Runtime Library exception 3.1"-licenseExceptionName Gnu_javamail_exception = "GNU JavaMail exception"-licenseExceptionName GPL_3_0_linking_exception = "GPL-3.0 Linking Exception"-licenseExceptionName GPL_3_0_linking_source_exception = "GPL-3.0 Linking Exception (with Corresponding Source)"-licenseExceptionName GPL_CC_1_0 = "GPL Cooperation Commitment 1.0"-licenseExceptionName I2p_gpl_java_exception = "i2p GPL+Java Exception"-licenseExceptionName LGPL_3_0_linking_exception = "LGPL-3.0 Linking Exception"-licenseExceptionName Libtool_exception = "Libtool Exception"-licenseExceptionName Linux_syscall_note = "Linux Syscall Note"-licenseExceptionName LLVM_exception = "LLVM Exception"-licenseExceptionName LZMA_exception = "LZMA exception"-licenseExceptionName Mif_exception = "Macros and Inline Functions Exception"-licenseExceptionName Nokia_Qt_exception_1_1 = "Nokia Qt LGPL exception 1.1"-licenseExceptionName OCaml_LGPL_linking_exception = "OCaml LGPL Linking Exception"-licenseExceptionName OCCT_exception_1_0 = "Open CASCADE Exception 1.0"-licenseExceptionName OpenJDK_assembly_exception_1_0 = "OpenJDK Assembly exception 1.0"-licenseExceptionName Openvpn_openssl_exception = "OpenVPN OpenSSL Exception"-licenseExceptionName PS_or_PDF_font_exception_20170817 = "PS/PDF font exception (2017-08-17)"-licenseExceptionName Qt_GPL_exception_1_0 = "Qt GPL exception 1.0"-licenseExceptionName Qt_LGPL_exception_1_1 = "Qt LGPL exception 1.1"-licenseExceptionName Qwt_exception_1_0 = "Qwt exception 1.0"-licenseExceptionName SHL_2_0 = "Solderpad Hardware License v2.0"-licenseExceptionName SHL_2_1 = "Solderpad Hardware License v2.1"-licenseExceptionName Swift_exception = "Swift Exception"-licenseExceptionName U_boot_exception_2_0 = "U-Boot exception 2.0"-licenseExceptionName Universal_FOSS_exception_1_0 = "Universal FOSS Exception, Version 1.0"-licenseExceptionName WxWindows_exception_3_1 = "WxWindows Library Exception 3.1"------------------------------------------------------------------------------------ Creation----------------------------------------------------------------------------------licenseExceptionIdList :: LicenseListVersion -> [LicenseExceptionId]-licenseExceptionIdList LicenseListVersion_3_0 =- [ Nokia_Qt_exception_1_1- ]- ++ bulkOfLicenses-licenseExceptionIdList LicenseListVersion_3_2 =- [ LLVM_exception- , Nokia_Qt_exception_1_1- , OpenJDK_assembly_exception_1_0- , PS_or_PDF_font_exception_20170817- , Qt_GPL_exception_1_0- , Qt_LGPL_exception_1_1- ]- ++ bulkOfLicenses-licenseExceptionIdList LicenseListVersion_3_6 =- [ GPL_CC_1_0- , LLVM_exception- , OCaml_LGPL_linking_exception- , OpenJDK_assembly_exception_1_0- , PS_or_PDF_font_exception_20170817- , Qt_GPL_exception_1_0- , Qt_LGPL_exception_1_1- , Swift_exception- , Universal_FOSS_exception_1_0- ]- ++ bulkOfLicenses-licenseExceptionIdList LicenseListVersion_3_9 =- [ GPL_3_0_linking_exception- , GPL_3_0_linking_source_exception- , GPL_CC_1_0- , LGPL_3_0_linking_exception- , LLVM_exception- , OCaml_LGPL_linking_exception- , OpenJDK_assembly_exception_1_0- , PS_or_PDF_font_exception_20170817- , Qt_GPL_exception_1_0- , Qt_LGPL_exception_1_1- , SHL_2_0- , SHL_2_1- , Swift_exception- , Universal_FOSS_exception_1_0- ]- ++ bulkOfLicenses---- | Create a 'LicenseExceptionId' from a 'String'.-mkLicenseExceptionId :: LicenseListVersion -> String -> Maybe LicenseExceptionId-mkLicenseExceptionId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0-mkLicenseExceptionId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2-mkLicenseExceptionId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6-mkLicenseExceptionId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9--stringLookup_3_0 :: Map String LicenseExceptionId-stringLookup_3_0 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $- licenseExceptionIdList LicenseListVersion_3_0--stringLookup_3_2 :: Map String LicenseExceptionId-stringLookup_3_2 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $- licenseExceptionIdList LicenseListVersion_3_2--stringLookup_3_6 :: Map String LicenseExceptionId-stringLookup_3_6 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $- licenseExceptionIdList LicenseListVersion_3_6--stringLookup_3_9 :: Map String LicenseExceptionId-stringLookup_3_9 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $- licenseExceptionIdList LicenseListVersion_3_9---- | License exceptions in all SPDX License lists-bulkOfLicenses :: [LicenseExceptionId]-bulkOfLicenses =- [ DS389_exception- , Autoconf_exception_2_0- , Autoconf_exception_3_0- , Bison_exception_2_2- , Bootloader_exception- , Classpath_exception_2_0- , CLISP_exception_2_0- , DigiRule_FOSS_exception- , ECos_exception_2_0- , Fawkes_Runtime_exception- , FLTK_exception- , Font_exception_2_0- , Freertos_exception_2_0- , GCC_exception_2_0- , GCC_exception_3_1- , Gnu_javamail_exception- , I2p_gpl_java_exception- , Libtool_exception- , Linux_syscall_note- , LZMA_exception- , Mif_exception- , OCCT_exception_1_0- , Openvpn_openssl_exception- , Qwt_exception_1_0- , U_boot_exception_2_0- , WxWindows_exception_3_1- ]
− Distribution/SPDX/LicenseExpression.hs
@@ -1,162 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.SPDX.LicenseExpression (- LicenseExpression (..),- SimpleLicenseExpression (..),- simpleLicenseExpression,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.SPDX.LicenseExceptionId-import Distribution.SPDX.LicenseId-import Distribution.SPDX.LicenseListVersion-import Distribution.SPDX.LicenseReference-import Distribution.Utils.Generic (isAsciiAlphaNum)--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | SPDX License Expression.------ @--- idstring = 1*(ALPHA \/ DIGIT \/ "-" \/ "." )--- license id = \<short form license identifier inAppendix I.1>--- license exception id = \<short form license exception identifier inAppendix I.2>--- license ref = [\"DocumentRef-"1*(idstring)":"]\"LicenseRef-"1*(idstring)------ simple expression = license id \/ license id"+" \/ license ref------ compound expression = 1*1(simple expression \/--- simple expression \"WITH" license exception id \/--- compound expression \"AND" compound expression \/--- compound expression \"OR" compound expression ) \/--- "(" compound expression ")" )------ license expression = 1*1(simple expression / compound expression)--- @-data LicenseExpression- = ELicense !SimpleLicenseExpression !(Maybe LicenseExceptionId)- | EAnd !LicenseExpression !LicenseExpression- | EOr !LicenseExpression !LicenseExpression- deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)---- | Simple License Expressions.-data SimpleLicenseExpression- = ELicenseId LicenseId- -- ^ An SPDX License List Short Form Identifier. For example: @GPL-2.0-only@- | ELicenseIdPlus LicenseId- -- ^ An SPDX License List Short Form Identifier with a unary"+" operator suffix to represent the current version of the license or any later version. For example: @GPL-2.0+@- | ELicenseRef LicenseRef- -- ^ A SPDX user defined license reference: For example: @LicenseRef-23@, @LicenseRef-MIT-Style-1@, or @DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2@- deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)--simpleLicenseExpression :: LicenseId -> LicenseExpression-simpleLicenseExpression i = ELicense (ELicenseId i) Nothing--instance Binary LicenseExpression-instance Binary SimpleLicenseExpression-instance Structured SimpleLicenseExpression-instance Structured LicenseExpression--instance Pretty LicenseExpression where- pretty = go 0- where- go :: Int -> LicenseExpression -> Disp.Doc- go _ (ELicense lic exc) =- let doc = pretty lic- in maybe id (\e d -> d <+> Disp.text "WITH" <+> pretty e) exc doc- go d (EAnd e1 e2) = parens (d < 0) $ go 0 e1 <+> Disp.text "AND" <+> go 0 e2- go d (EOr e1 e2) = parens (d < 1) $ go 1 e1 <+> Disp.text "OR" <+> go 1 e2--- parens False doc = doc- parens True doc = Disp.parens doc--instance Pretty SimpleLicenseExpression where- pretty (ELicenseId i) = pretty i- pretty (ELicenseIdPlus i) = pretty i <<>> Disp.char '+'- pretty (ELicenseRef r) = pretty r--instance Parsec SimpleLicenseExpression where- parsec = idstring >>= simple where- simple n- | Just l <- "LicenseRef-" `isPrefixOfMaybe` n =- maybe (fail $ "Incorrect LicenseRef format: " ++ n) (return . ELicenseRef) $ mkLicenseRef Nothing l- | Just d <- "DocumentRef-" `isPrefixOfMaybe` n = do- _ <- P.string ":LicenseRef-"- l <- idstring- maybe (fail $ "Incorrect LicenseRef format:" ++ n) (return . ELicenseRef) $ mkLicenseRef (Just d) l- | otherwise = do- v <- askCabalSpecVersion- l <- maybe (fail $ "Unknown SPDX license identifier: '" ++ n ++ "' " ++ licenseIdMigrationMessage n) return $- mkLicenseId (cabalSpecVersionToSPDXListVersion v) n- orLater <- isJust <$> P.optional (P.char '+')- if orLater- then return (ELicenseIdPlus l)- else return (ELicenseId l)--idstring :: P.CharParsing m => m String-idstring = P.munch1 $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'---- returns suffix part-isPrefixOfMaybe :: Eq a => [a] -> [a] -> Maybe [a]-isPrefixOfMaybe pfx s- | pfx `isPrefixOf` s = Just (drop (length pfx) s)- | otherwise = Nothing--instance Parsec LicenseExpression where- parsec = expr- where- expr = compoundOr-- simple = do- s <- parsec- exc <- exception- return $ ELicense s exc-- exception = P.optional $ P.try (spaces1 *> P.string "WITH" *> spaces1) *> parsec-- compoundOr = do- x <- compoundAnd- l <- P.optional $ P.try (spaces1 *> P.string "OR" *> spaces1) *> compoundOr- return $ maybe id (flip EOr) l x-- compoundAnd = do- x <- compound- l <- P.optional $ P.try (spaces1 *> P.string "AND" *> spaces1) *> compoundAnd- return $ maybe id (flip EAnd) l x-- compound = braces <|> simple-- -- NOTE: we require that there's a space around AND & OR operators,- -- i.e. @(MIT)AND(MIT)@ will cause parse-error.- braces = do- _ <- P.char '('- _ <- P.spaces- x <- expr- _ <- P.char ')'- return x-- spaces1 = P.space *> P.spaces---- notes:------ There MUST NOT be whitespace between a licenseid and any following "+". This supports easy parsing and--- backwards compatibility. There MUST be whitespace on either side of the operator "WITH". There MUST be--- whitespace and/or parentheses on either side of the operators "AND" and "OR".------ We handle that by having greedy 'idstring' parser, so MITAND would parse as invalid license identifier.--instance NFData LicenseExpression where- rnf (ELicense s e) = rnf s `seq` rnf e- rnf (EAnd x y) = rnf x `seq` rnf y- rnf (EOr x y) = rnf x `seq` rnf y--instance NFData SimpleLicenseExpression where- rnf (ELicenseId i) = rnf i- rnf (ELicenseIdPlus i) = rnf i- rnf (ELicenseRef r) = rnf r
− Distribution/SPDX/LicenseId.hs
@@ -1,2025 +0,0 @@--- This file is generated. See Makefile's spdx rule-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.SPDX.LicenseId (- LicenseId (..),- licenseId,- licenseName,- licenseIsOsiApproved,- licenseIsFsfLibre,- mkLicenseId,- licenseIdList,- -- * Helpers- licenseIdMigrationMessage,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Compat.Lens (set)-import Distribution.Pretty-import Distribution.Parsec-import Distribution.Utils.Generic (isAsciiAlphaNum)-import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion)-import Distribution.SPDX.LicenseListVersion--import qualified Data.Binary.Get as Binary-import qualified Data.Binary.Put as Binary-import qualified Data.Map.Strict as Map-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp------------------------------------------------------------------------------------ LicenseId------------------------------------------------------------------------------------ | SPDX License identifier-data LicenseId- = NullBSD -- ^ @0BSD@, BSD Zero Clause License- | AAL -- ^ @AAL@, Attribution Assurance License- | Abstyles -- ^ @Abstyles@, Abstyles License- | Adobe_2006 -- ^ @Adobe-2006@, Adobe Systems Incorporated Source Code License Agreement- | Adobe_Glyph -- ^ @Adobe-Glyph@, Adobe Glyph List License- | ADSL -- ^ @ADSL@, Amazon Digital Services License- | AFL_1_1 -- ^ @AFL-1.1@, Academic Free License v1.1- | AFL_1_2 -- ^ @AFL-1.2@, Academic Free License v1.2- | AFL_2_0 -- ^ @AFL-2.0@, Academic Free License v2.0- | AFL_2_1 -- ^ @AFL-2.1@, Academic Free License v2.1- | AFL_3_0 -- ^ @AFL-3.0@, Academic Free License v3.0- | Afmparse -- ^ @Afmparse@, Afmparse License- | AGPL_1_0 -- ^ @AGPL-1.0@, Affero General Public License v1.0, SPDX License List 3.0- | AGPL_1_0_only -- ^ @AGPL-1.0-only@, Affero General Public License v1.0 only, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | AGPL_1_0_or_later -- ^ @AGPL-1.0-or-later@, Affero General Public License v1.0 or later, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | AGPL_3_0_only -- ^ @AGPL-3.0-only@, GNU Affero General Public License v3.0 only- | AGPL_3_0_or_later -- ^ @AGPL-3.0-or-later@, GNU Affero General Public License v3.0 or later- | Aladdin -- ^ @Aladdin@, Aladdin Free Public License- | AMDPLPA -- ^ @AMDPLPA@, AMD's plpa_map.c License- | AML -- ^ @AML@, Apple MIT License- | AMPAS -- ^ @AMPAS@, Academy of Motion Picture Arts and Sciences BSD- | ANTLR_PD -- ^ @ANTLR-PD@, ANTLR Software Rights Notice- | Apache_1_0 -- ^ @Apache-1.0@, Apache License 1.0- | Apache_1_1 -- ^ @Apache-1.1@, Apache License 1.1- | Apache_2_0 -- ^ @Apache-2.0@, Apache License 2.0- | APAFML -- ^ @APAFML@, Adobe Postscript AFM License- | APL_1_0 -- ^ @APL-1.0@, Adaptive Public License 1.0- | APSL_1_0 -- ^ @APSL-1.0@, Apple Public Source License 1.0- | APSL_1_1 -- ^ @APSL-1.1@, Apple Public Source License 1.1- | APSL_1_2 -- ^ @APSL-1.2@, Apple Public Source License 1.2- | APSL_2_0 -- ^ @APSL-2.0@, Apple Public Source License 2.0- | Artistic_1_0_cl8 -- ^ @Artistic-1.0-cl8@, Artistic License 1.0 w/clause 8- | Artistic_1_0_Perl -- ^ @Artistic-1.0-Perl@, Artistic License 1.0 (Perl)- | Artistic_1_0 -- ^ @Artistic-1.0@, Artistic License 1.0- | Artistic_2_0 -- ^ @Artistic-2.0@, Artistic License 2.0- | Bahyph -- ^ @Bahyph@, Bahyph License- | Barr -- ^ @Barr@, Barr License- | Beerware -- ^ @Beerware@, Beerware License- | BitTorrent_1_0 -- ^ @BitTorrent-1.0@, BitTorrent Open Source License v1.0- | BitTorrent_1_1 -- ^ @BitTorrent-1.1@, BitTorrent Open Source License v1.1- | Blessing -- ^ @blessing@, SQLite Blessing, SPDX License List 3.6, SPDX License List 3.9- | BlueOak_1_0_0 -- ^ @BlueOak-1.0.0@, Blue Oak Model License 1.0.0, SPDX License List 3.6, SPDX License List 3.9- | Borceux -- ^ @Borceux@, Borceux license- | BSD_1_Clause -- ^ @BSD-1-Clause@, BSD 1-Clause License- | BSD_2_Clause_FreeBSD -- ^ @BSD-2-Clause-FreeBSD@, BSD 2-Clause FreeBSD License- | BSD_2_Clause_NetBSD -- ^ @BSD-2-Clause-NetBSD@, BSD 2-Clause NetBSD License, SPDX License List 3.0, SPDX License List 3.2, SPDX License List 3.6- | BSD_2_Clause_Patent -- ^ @BSD-2-Clause-Patent@, BSD-2-Clause Plus Patent License- | BSD_2_Clause -- ^ @BSD-2-Clause@, BSD 2-Clause "Simplified" License- | BSD_3_Clause_Attribution -- ^ @BSD-3-Clause-Attribution@, BSD with attribution- | BSD_3_Clause_Clear -- ^ @BSD-3-Clause-Clear@, BSD 3-Clause Clear License- | BSD_3_Clause_LBNL -- ^ @BSD-3-Clause-LBNL@, Lawrence Berkeley National Labs BSD variant license- | BSD_3_Clause_No_Nuclear_License_2014 -- ^ @BSD-3-Clause-No-Nuclear-License-2014@, BSD 3-Clause No Nuclear License 2014- | BSD_3_Clause_No_Nuclear_License -- ^ @BSD-3-Clause-No-Nuclear-License@, BSD 3-Clause No Nuclear License- | BSD_3_Clause_No_Nuclear_Warranty -- ^ @BSD-3-Clause-No-Nuclear-Warranty@, BSD 3-Clause No Nuclear Warranty- | BSD_3_Clause_Open_MPI -- ^ @BSD-3-Clause-Open-MPI@, BSD 3-Clause Open MPI variant, SPDX License List 3.6, SPDX License List 3.9- | BSD_3_Clause -- ^ @BSD-3-Clause@, BSD 3-Clause "New" or "Revised" License- | BSD_4_Clause_UC -- ^ @BSD-4-Clause-UC@, BSD-4-Clause (University of California-Specific)- | BSD_4_Clause -- ^ @BSD-4-Clause@, BSD 4-Clause "Original" or "Old" License- | BSD_Protection -- ^ @BSD-Protection@, BSD Protection License- | BSD_Source_Code -- ^ @BSD-Source-Code@, BSD Source Code Attribution- | BSL_1_0 -- ^ @BSL-1.0@, Boost Software License 1.0- | Bzip2_1_0_5 -- ^ @bzip2-1.0.5@, bzip2 and libbzip2 License v1.0.5- | Bzip2_1_0_6 -- ^ @bzip2-1.0.6@, bzip2 and libbzip2 License v1.0.6- | CAL_1_0_Combined_Work_Exception -- ^ @CAL-1.0-Combined-Work-Exception@, Cryptographic Autonomy License 1.0 (Combined Work Exception), SPDX License List 3.9- | CAL_1_0 -- ^ @CAL-1.0@, Cryptographic Autonomy License 1.0, SPDX License List 3.9- | Caldera -- ^ @Caldera@, Caldera License- | CATOSL_1_1 -- ^ @CATOSL-1.1@, Computer Associates Trusted Open Source License 1.1- | CC_BY_1_0 -- ^ @CC-BY-1.0@, Creative Commons Attribution 1.0 Generic- | CC_BY_2_0 -- ^ @CC-BY-2.0@, Creative Commons Attribution 2.0 Generic- | CC_BY_2_5 -- ^ @CC-BY-2.5@, Creative Commons Attribution 2.5 Generic- | CC_BY_3_0 -- ^ @CC-BY-3.0@, Creative Commons Attribution 3.0 Unported- | CC_BY_4_0 -- ^ @CC-BY-4.0@, Creative Commons Attribution 4.0 International- | CC_BY_NC_1_0 -- ^ @CC-BY-NC-1.0@, Creative Commons Attribution Non Commercial 1.0 Generic- | CC_BY_NC_2_0 -- ^ @CC-BY-NC-2.0@, Creative Commons Attribution Non Commercial 2.0 Generic- | CC_BY_NC_2_5 -- ^ @CC-BY-NC-2.5@, Creative Commons Attribution Non Commercial 2.5 Generic- | CC_BY_NC_3_0 -- ^ @CC-BY-NC-3.0@, Creative Commons Attribution Non Commercial 3.0 Unported- | CC_BY_NC_4_0 -- ^ @CC-BY-NC-4.0@, Creative Commons Attribution Non Commercial 4.0 International- | CC_BY_NC_ND_1_0 -- ^ @CC-BY-NC-ND-1.0@, Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic- | CC_BY_NC_ND_2_0 -- ^ @CC-BY-NC-ND-2.0@, Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic- | CC_BY_NC_ND_2_5 -- ^ @CC-BY-NC-ND-2.5@, Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic- | CC_BY_NC_ND_3_0 -- ^ @CC-BY-NC-ND-3.0@, Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported- | CC_BY_NC_ND_4_0 -- ^ @CC-BY-NC-ND-4.0@, Creative Commons Attribution Non Commercial No Derivatives 4.0 International- | CC_BY_NC_SA_1_0 -- ^ @CC-BY-NC-SA-1.0@, Creative Commons Attribution Non Commercial Share Alike 1.0 Generic- | CC_BY_NC_SA_2_0 -- ^ @CC-BY-NC-SA-2.0@, Creative Commons Attribution Non Commercial Share Alike 2.0 Generic- | CC_BY_NC_SA_2_5 -- ^ @CC-BY-NC-SA-2.5@, Creative Commons Attribution Non Commercial Share Alike 2.5 Generic- | CC_BY_NC_SA_3_0 -- ^ @CC-BY-NC-SA-3.0@, Creative Commons Attribution Non Commercial Share Alike 3.0 Unported- | CC_BY_NC_SA_4_0 -- ^ @CC-BY-NC-SA-4.0@, Creative Commons Attribution Non Commercial Share Alike 4.0 International- | CC_BY_ND_1_0 -- ^ @CC-BY-ND-1.0@, Creative Commons Attribution No Derivatives 1.0 Generic- | CC_BY_ND_2_0 -- ^ @CC-BY-ND-2.0@, Creative Commons Attribution No Derivatives 2.0 Generic- | CC_BY_ND_2_5 -- ^ @CC-BY-ND-2.5@, Creative Commons Attribution No Derivatives 2.5 Generic- | CC_BY_ND_3_0 -- ^ @CC-BY-ND-3.0@, Creative Commons Attribution No Derivatives 3.0 Unported- | CC_BY_ND_4_0 -- ^ @CC-BY-ND-4.0@, Creative Commons Attribution No Derivatives 4.0 International- | CC_BY_SA_1_0 -- ^ @CC-BY-SA-1.0@, Creative Commons Attribution Share Alike 1.0 Generic- | CC_BY_SA_2_0 -- ^ @CC-BY-SA-2.0@, Creative Commons Attribution Share Alike 2.0 Generic- | CC_BY_SA_2_5 -- ^ @CC-BY-SA-2.5@, Creative Commons Attribution Share Alike 2.5 Generic- | CC_BY_SA_3_0 -- ^ @CC-BY-SA-3.0@, Creative Commons Attribution Share Alike 3.0 Unported- | CC_BY_SA_4_0 -- ^ @CC-BY-SA-4.0@, Creative Commons Attribution Share Alike 4.0 International- | CC_PDDC -- ^ @CC-PDDC@, Creative Commons Public Domain Dedication and Certification, SPDX License List 3.6, SPDX License List 3.9- | CC0_1_0 -- ^ @CC0-1.0@, Creative Commons Zero v1.0 Universal- | CDDL_1_0 -- ^ @CDDL-1.0@, Common Development and Distribution License 1.0- | CDDL_1_1 -- ^ @CDDL-1.1@, Common Development and Distribution License 1.1- | CDLA_Permissive_1_0 -- ^ @CDLA-Permissive-1.0@, Community Data License Agreement Permissive 1.0- | CDLA_Sharing_1_0 -- ^ @CDLA-Sharing-1.0@, Community Data License Agreement Sharing 1.0- | CECILL_1_0 -- ^ @CECILL-1.0@, CeCILL Free Software License Agreement v1.0- | CECILL_1_1 -- ^ @CECILL-1.1@, CeCILL Free Software License Agreement v1.1- | CECILL_2_0 -- ^ @CECILL-2.0@, CeCILL Free Software License Agreement v2.0- | CECILL_2_1 -- ^ @CECILL-2.1@, CeCILL Free Software License Agreement v2.1- | CECILL_B -- ^ @CECILL-B@, CeCILL-B Free Software License Agreement- | CECILL_C -- ^ @CECILL-C@, CeCILL-C Free Software License Agreement- | CERN_OHL_1_1 -- ^ @CERN-OHL-1.1@, CERN Open Hardware Licence v1.1, SPDX License List 3.6, SPDX License List 3.9- | CERN_OHL_1_2 -- ^ @CERN-OHL-1.2@, CERN Open Hardware Licence v1.2, SPDX License List 3.6, SPDX License List 3.9- | CERN_OHL_P_2_0 -- ^ @CERN-OHL-P-2.0@, CERN Open Hardware Licence Version 2 - Permissive, SPDX License List 3.9- | CERN_OHL_S_2_0 -- ^ @CERN-OHL-S-2.0@, CERN Open Hardware Licence Version 2 - Strongly Reciprocal, SPDX License List 3.9- | CERN_OHL_W_2_0 -- ^ @CERN-OHL-W-2.0@, CERN Open Hardware Licence Version 2 - Weakly Reciprocal, SPDX License List 3.9- | ClArtistic -- ^ @ClArtistic@, Clarified Artistic License- | CNRI_Jython -- ^ @CNRI-Jython@, CNRI Jython License- | CNRI_Python_GPL_Compatible -- ^ @CNRI-Python-GPL-Compatible@, CNRI Python Open Source GPL Compatible License Agreement- | CNRI_Python -- ^ @CNRI-Python@, CNRI Python License- | Condor_1_1 -- ^ @Condor-1.1@, Condor Public License v1.1- | Copyleft_next_0_3_0 -- ^ @copyleft-next-0.3.0@, copyleft-next 0.3.0, SPDX License List 3.6, SPDX License List 3.9- | Copyleft_next_0_3_1 -- ^ @copyleft-next-0.3.1@, copyleft-next 0.3.1, SPDX License List 3.6, SPDX License List 3.9- | CPAL_1_0 -- ^ @CPAL-1.0@, Common Public Attribution License 1.0- | CPL_1_0 -- ^ @CPL-1.0@, Common Public License 1.0- | CPOL_1_02 -- ^ @CPOL-1.02@, Code Project Open License 1.02- | Crossword -- ^ @Crossword@, Crossword License- | CrystalStacker -- ^ @CrystalStacker@, CrystalStacker License- | CUA_OPL_1_0 -- ^ @CUA-OPL-1.0@, CUA Office Public License v1.0- | Cube -- ^ @Cube@, Cube License- | Curl -- ^ @curl@, curl License- | D_FSL_1_0 -- ^ @D-FSL-1.0@, Deutsche Freie Software Lizenz- | Diffmark -- ^ @diffmark@, diffmark license- | DOC -- ^ @DOC@, DOC License- | Dotseqn -- ^ @Dotseqn@, Dotseqn License- | DSDP -- ^ @DSDP@, DSDP License- | Dvipdfm -- ^ @dvipdfm@, dvipdfm License- | ECL_1_0 -- ^ @ECL-1.0@, Educational Community License v1.0- | ECL_2_0 -- ^ @ECL-2.0@, Educational Community License v2.0- | EFL_1_0 -- ^ @EFL-1.0@, Eiffel Forum License v1.0- | EFL_2_0 -- ^ @EFL-2.0@, Eiffel Forum License v2.0- | EGenix -- ^ @eGenix@, eGenix.com Public License 1.1.0- | Entessa -- ^ @Entessa@, Entessa Public License v1.0- | EPL_1_0 -- ^ @EPL-1.0@, Eclipse Public License 1.0- | EPL_2_0 -- ^ @EPL-2.0@, Eclipse Public License 2.0- | ErlPL_1_1 -- ^ @ErlPL-1.1@, Erlang Public License v1.1- | Etalab_2_0 -- ^ @etalab-2.0@, Etalab Open License 2.0, SPDX License List 3.9- | EUDatagrid -- ^ @EUDatagrid@, EU DataGrid Software License- | EUPL_1_0 -- ^ @EUPL-1.0@, European Union Public License 1.0- | EUPL_1_1 -- ^ @EUPL-1.1@, European Union Public License 1.1- | EUPL_1_2 -- ^ @EUPL-1.2@, European Union Public License 1.2- | Eurosym -- ^ @Eurosym@, Eurosym License- | Fair -- ^ @Fair@, Fair License- | Frameworx_1_0 -- ^ @Frameworx-1.0@, Frameworx Open License 1.0- | FreeImage -- ^ @FreeImage@, FreeImage Public License v1.0- | FSFAP -- ^ @FSFAP@, FSF All Permissive License- | FSFULLR -- ^ @FSFULLR@, FSF Unlimited License (with License Retention)- | FSFUL -- ^ @FSFUL@, FSF Unlimited License- | FTL -- ^ @FTL@, Freetype Project License- | GFDL_1_1_only -- ^ @GFDL-1.1-only@, GNU Free Documentation License v1.1 only- | GFDL_1_1_or_later -- ^ @GFDL-1.1-or-later@, GNU Free Documentation License v1.1 or later- | GFDL_1_2_only -- ^ @GFDL-1.2-only@, GNU Free Documentation License v1.2 only- | GFDL_1_2_or_later -- ^ @GFDL-1.2-or-later@, GNU Free Documentation License v1.2 or later- | GFDL_1_3_only -- ^ @GFDL-1.3-only@, GNU Free Documentation License v1.3 only- | GFDL_1_3_or_later -- ^ @GFDL-1.3-or-later@, GNU Free Documentation License v1.3 or later- | Giftware -- ^ @Giftware@, Giftware License- | GL2PS -- ^ @GL2PS@, GL2PS License- | Glide -- ^ @Glide@, 3dfx Glide License- | Glulxe -- ^ @Glulxe@, Glulxe License- | Gnuplot -- ^ @gnuplot@, gnuplot License- | GPL_1_0_only -- ^ @GPL-1.0-only@, GNU General Public License v1.0 only- | GPL_1_0_or_later -- ^ @GPL-1.0-or-later@, GNU General Public License v1.0 or later- | GPL_2_0_only -- ^ @GPL-2.0-only@, GNU General Public License v2.0 only- | GPL_2_0_or_later -- ^ @GPL-2.0-or-later@, GNU General Public License v2.0 or later- | GPL_3_0_only -- ^ @GPL-3.0-only@, GNU General Public License v3.0 only- | GPL_3_0_or_later -- ^ @GPL-3.0-or-later@, GNU General Public License v3.0 or later- | GSOAP_1_3b -- ^ @gSOAP-1.3b@, gSOAP Public License v1.3b- | HaskellReport -- ^ @HaskellReport@, Haskell Language Report License- | Hippocratic_2_1 -- ^ @Hippocratic-2.1@, Hippocratic License 2.1, SPDX License List 3.9- | HPND_sell_variant -- ^ @HPND-sell-variant@, Historical Permission Notice and Disclaimer - sell variant, SPDX License List 3.6, SPDX License List 3.9- | HPND -- ^ @HPND@, Historical Permission Notice and Disclaimer- | IBM_pibs -- ^ @IBM-pibs@, IBM PowerPC Initialization and Boot Software- | ICU -- ^ @ICU@, ICU License- | IJG -- ^ @IJG@, Independent JPEG Group License- | ImageMagick -- ^ @ImageMagick@, ImageMagick License- | IMatix -- ^ @iMatix@, iMatix Standard Function Library Agreement- | Imlib2 -- ^ @Imlib2@, Imlib2 License- | Info_ZIP -- ^ @Info-ZIP@, Info-ZIP License- | Intel_ACPI -- ^ @Intel-ACPI@, Intel ACPI Software License Agreement- | Intel -- ^ @Intel@, Intel Open Source License- | Interbase_1_0 -- ^ @Interbase-1.0@, Interbase Public License v1.0- | IPA -- ^ @IPA@, IPA Font License- | IPL_1_0 -- ^ @IPL-1.0@, IBM Public License v1.0- | ISC -- ^ @ISC@, ISC License- | JasPer_2_0 -- ^ @JasPer-2.0@, JasPer License- | JPNIC -- ^ @JPNIC@, Japan Network Information Center License, SPDX License List 3.6, SPDX License List 3.9- | JSON -- ^ @JSON@, JSON License- | LAL_1_2 -- ^ @LAL-1.2@, Licence Art Libre 1.2- | LAL_1_3 -- ^ @LAL-1.3@, Licence Art Libre 1.3- | Latex2e -- ^ @Latex2e@, Latex2e License- | Leptonica -- ^ @Leptonica@, Leptonica License- | LGPL_2_0_only -- ^ @LGPL-2.0-only@, GNU Library General Public License v2 only- | LGPL_2_0_or_later -- ^ @LGPL-2.0-or-later@, GNU Library General Public License v2 or later- | LGPL_2_1_only -- ^ @LGPL-2.1-only@, GNU Lesser General Public License v2.1 only- | LGPL_2_1_or_later -- ^ @LGPL-2.1-or-later@, GNU Lesser General Public License v2.1 or later- | LGPL_3_0_only -- ^ @LGPL-3.0-only@, GNU Lesser General Public License v3.0 only- | LGPL_3_0_or_later -- ^ @LGPL-3.0-or-later@, GNU Lesser General Public License v3.0 or later- | LGPLLR -- ^ @LGPLLR@, Lesser General Public License For Linguistic Resources- | Libpng_2_0 -- ^ @libpng-2.0@, PNG Reference Library version 2, SPDX License List 3.6, SPDX License List 3.9- | Libpng -- ^ @Libpng@, libpng License- | Libselinux_1_0 -- ^ @libselinux-1.0@, libselinux public domain notice, SPDX License List 3.9- | Libtiff -- ^ @libtiff@, libtiff License- | LiLiQ_P_1_1 -- ^ @LiLiQ-P-1.1@, Licence Libre du Québec – Permissive version 1.1- | LiLiQ_R_1_1 -- ^ @LiLiQ-R-1.1@, Licence Libre du Québec – Réciprocité version 1.1- | LiLiQ_Rplus_1_1 -- ^ @LiLiQ-Rplus-1.1@, Licence Libre du Québec – Réciprocité forte version 1.1- | Linux_OpenIB -- ^ @Linux-OpenIB@, Linux Kernel Variant of OpenIB.org license, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | LPL_1_02 -- ^ @LPL-1.02@, Lucent Public License v1.02- | LPL_1_0 -- ^ @LPL-1.0@, Lucent Public License Version 1.0- | LPPL_1_0 -- ^ @LPPL-1.0@, LaTeX Project Public License v1.0- | LPPL_1_1 -- ^ @LPPL-1.1@, LaTeX Project Public License v1.1- | LPPL_1_2 -- ^ @LPPL-1.2@, LaTeX Project Public License v1.2- | LPPL_1_3a -- ^ @LPPL-1.3a@, LaTeX Project Public License v1.3a- | LPPL_1_3c -- ^ @LPPL-1.3c@, LaTeX Project Public License v1.3c- | MakeIndex -- ^ @MakeIndex@, MakeIndex License- | MirOS -- ^ @MirOS@, The MirOS Licence- | MIT_0 -- ^ @MIT-0@, MIT No Attribution, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | MIT_advertising -- ^ @MIT-advertising@, Enlightenment License (e16)- | MIT_CMU -- ^ @MIT-CMU@, CMU License- | MIT_enna -- ^ @MIT-enna@, enna License- | MIT_feh -- ^ @MIT-feh@, feh License- | MITNFA -- ^ @MITNFA@, MIT +no-false-attribs license- | MIT -- ^ @MIT@, MIT License- | Motosoto -- ^ @Motosoto@, Motosoto License- | Mpich2 -- ^ @mpich2@, mpich2 License- | MPL_1_0 -- ^ @MPL-1.0@, Mozilla Public License 1.0- | MPL_1_1 -- ^ @MPL-1.1@, Mozilla Public License 1.1- | MPL_2_0_no_copyleft_exception -- ^ @MPL-2.0-no-copyleft-exception@, Mozilla Public License 2.0 (no copyleft exception)- | MPL_2_0 -- ^ @MPL-2.0@, Mozilla Public License 2.0- | MS_PL -- ^ @MS-PL@, Microsoft Public License- | MS_RL -- ^ @MS-RL@, Microsoft Reciprocal License- | MTLL -- ^ @MTLL@, Matrix Template Library License- | MulanPSL_1_0 -- ^ @MulanPSL-1.0@, Mulan Permissive Software License, Version 1, SPDX License List 3.9- | MulanPSL_2_0 -- ^ @MulanPSL-2.0@, Mulan Permissive Software License, Version 2, SPDX License List 3.9- | Multics -- ^ @Multics@, Multics License- | Mup -- ^ @Mup@, Mup License- | NASA_1_3 -- ^ @NASA-1.3@, NASA Open Source Agreement 1.3- | Naumen -- ^ @Naumen@, Naumen Public License- | NBPL_1_0 -- ^ @NBPL-1.0@, Net Boolean Public License v1- | NCGL_UK_2_0 -- ^ @NCGL-UK-2.0@, Non-Commercial Government Licence, SPDX License List 3.9- | NCSA -- ^ @NCSA@, University of Illinois/NCSA Open Source License- | Net_SNMP -- ^ @Net-SNMP@, Net-SNMP License- | NetCDF -- ^ @NetCDF@, NetCDF license- | Newsletr -- ^ @Newsletr@, Newsletr License- | NGPL -- ^ @NGPL@, Nethack General Public License- | NLOD_1_0 -- ^ @NLOD-1.0@, Norwegian Licence for Open Government Data- | NLPL -- ^ @NLPL@, No Limit Public License- | Nokia -- ^ @Nokia@, Nokia Open Source License- | NOSL -- ^ @NOSL@, Netizen Open Source License- | Noweb -- ^ @Noweb@, Noweb License- | NPL_1_0 -- ^ @NPL-1.0@, Netscape Public License v1.0- | NPL_1_1 -- ^ @NPL-1.1@, Netscape Public License v1.1- | NPOSL_3_0 -- ^ @NPOSL-3.0@, Non-Profit Open Software License 3.0- | NRL -- ^ @NRL@, NRL License- | NTP_0 -- ^ @NTP-0@, NTP No Attribution, SPDX License List 3.9- | NTP -- ^ @NTP@, NTP License- | O_UDA_1_0 -- ^ @O-UDA-1.0@, Open Use of Data Agreement v1.0, SPDX License List 3.9- | OCCT_PL -- ^ @OCCT-PL@, Open CASCADE Technology Public License- | OCLC_2_0 -- ^ @OCLC-2.0@, OCLC Research Public License 2.0- | ODbL_1_0 -- ^ @ODbL-1.0@, ODC Open Database License v1.0- | ODC_By_1_0 -- ^ @ODC-By-1.0@, Open Data Commons Attribution License v1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | OFL_1_0_no_RFN -- ^ @OFL-1.0-no-RFN@, SIL Open Font License 1.0 with no Reserved Font Name, SPDX License List 3.9- | OFL_1_0_RFN -- ^ @OFL-1.0-RFN@, SIL Open Font License 1.0 with Reserved Font Name, SPDX License List 3.9- | OFL_1_0 -- ^ @OFL-1.0@, SIL Open Font License 1.0- | OFL_1_1_no_RFN -- ^ @OFL-1.1-no-RFN@, SIL Open Font License 1.1 with no Reserved Font Name, SPDX License List 3.9- | OFL_1_1_RFN -- ^ @OFL-1.1-RFN@, SIL Open Font License 1.1 with Reserved Font Name, SPDX License List 3.9- | OFL_1_1 -- ^ @OFL-1.1@, SIL Open Font License 1.1- | OGC_1_0 -- ^ @OGC-1.0@, OGC Software License, Version 1.0, SPDX License List 3.9- | OGL_Canada_2_0 -- ^ @OGL-Canada-2.0@, Open Government Licence - Canada, SPDX License List 3.9- | OGL_UK_1_0 -- ^ @OGL-UK-1.0@, Open Government Licence v1.0, SPDX License List 3.6, SPDX License List 3.9- | OGL_UK_2_0 -- ^ @OGL-UK-2.0@, Open Government Licence v2.0, SPDX License List 3.6, SPDX License List 3.9- | OGL_UK_3_0 -- ^ @OGL-UK-3.0@, Open Government Licence v3.0, SPDX License List 3.6, SPDX License List 3.9- | OGTSL -- ^ @OGTSL@, Open Group Test Suite License- | OLDAP_1_1 -- ^ @OLDAP-1.1@, Open LDAP Public License v1.1- | OLDAP_1_2 -- ^ @OLDAP-1.2@, Open LDAP Public License v1.2- | OLDAP_1_3 -- ^ @OLDAP-1.3@, Open LDAP Public License v1.3- | OLDAP_1_4 -- ^ @OLDAP-1.4@, Open LDAP Public License v1.4- | OLDAP_2_0_1 -- ^ @OLDAP-2.0.1@, Open LDAP Public License v2.0.1- | OLDAP_2_0 -- ^ @OLDAP-2.0@, Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)- | OLDAP_2_1 -- ^ @OLDAP-2.1@, Open LDAP Public License v2.1- | OLDAP_2_2_1 -- ^ @OLDAP-2.2.1@, Open LDAP Public License v2.2.1- | OLDAP_2_2_2 -- ^ @OLDAP-2.2.2@, Open LDAP Public License 2.2.2- | OLDAP_2_2 -- ^ @OLDAP-2.2@, Open LDAP Public License v2.2- | OLDAP_2_3 -- ^ @OLDAP-2.3@, Open LDAP Public License v2.3- | OLDAP_2_4 -- ^ @OLDAP-2.4@, Open LDAP Public License v2.4- | OLDAP_2_5 -- ^ @OLDAP-2.5@, Open LDAP Public License v2.5- | OLDAP_2_6 -- ^ @OLDAP-2.6@, Open LDAP Public License v2.6- | OLDAP_2_7 -- ^ @OLDAP-2.7@, Open LDAP Public License v2.7- | OLDAP_2_8 -- ^ @OLDAP-2.8@, Open LDAP Public License v2.8- | OML -- ^ @OML@, Open Market License- | OpenSSL -- ^ @OpenSSL@, OpenSSL License- | OPL_1_0 -- ^ @OPL-1.0@, Open Public License v1.0- | OSET_PL_2_1 -- ^ @OSET-PL-2.1@, OSET Public License version 2.1- | OSL_1_0 -- ^ @OSL-1.0@, Open Software License 1.0- | OSL_1_1 -- ^ @OSL-1.1@, Open Software License 1.1- | OSL_2_0 -- ^ @OSL-2.0@, Open Software License 2.0- | OSL_2_1 -- ^ @OSL-2.1@, Open Software License 2.1- | OSL_3_0 -- ^ @OSL-3.0@, Open Software License 3.0- | Parity_6_0_0 -- ^ @Parity-6.0.0@, The Parity Public License 6.0.0, SPDX License List 3.6, SPDX License List 3.9- | Parity_7_0_0 -- ^ @Parity-7.0.0@, The Parity Public License 7.0.0, SPDX License List 3.9- | PDDL_1_0 -- ^ @PDDL-1.0@, ODC Public Domain Dedication & License 1.0- | PHP_3_01 -- ^ @PHP-3.01@, PHP License v3.01- | PHP_3_0 -- ^ @PHP-3.0@, PHP License v3.0- | Plexus -- ^ @Plexus@, Plexus Classworlds License- | PolyForm_Noncommercial_1_0_0 -- ^ @PolyForm-Noncommercial-1.0.0@, PolyForm Noncommercial License 1.0.0, SPDX License List 3.9- | PolyForm_Small_Business_1_0_0 -- ^ @PolyForm-Small-Business-1.0.0@, PolyForm Small Business License 1.0.0, SPDX License List 3.9- | PostgreSQL -- ^ @PostgreSQL@, PostgreSQL License- | PSF_2_0 -- ^ @PSF-2.0@, Python Software Foundation License 2.0, SPDX License List 3.9- | Psfrag -- ^ @psfrag@, psfrag License- | Psutils -- ^ @psutils@, psutils License- | Python_2_0 -- ^ @Python-2.0@, Python License 2.0- | Qhull -- ^ @Qhull@, Qhull License- | QPL_1_0 -- ^ @QPL-1.0@, Q Public License 1.0- | Rdisc -- ^ @Rdisc@, Rdisc License- | RHeCos_1_1 -- ^ @RHeCos-1.1@, Red Hat eCos Public License v1.1- | RPL_1_1 -- ^ @RPL-1.1@, Reciprocal Public License 1.1- | RPL_1_5 -- ^ @RPL-1.5@, Reciprocal Public License 1.5- | RPSL_1_0 -- ^ @RPSL-1.0@, RealNetworks Public Source License v1.0- | RSA_MD -- ^ @RSA-MD@, RSA Message-Digest License - | RSCPL -- ^ @RSCPL@, Ricoh Source Code Public License- | Ruby -- ^ @Ruby@, Ruby License- | SAX_PD -- ^ @SAX-PD@, Sax Public Domain Notice- | Saxpath -- ^ @Saxpath@, Saxpath License- | SCEA -- ^ @SCEA@, SCEA Shared Source License- | Sendmail_8_23 -- ^ @Sendmail-8.23@, Sendmail License 8.23, SPDX License List 3.6, SPDX License List 3.9- | Sendmail -- ^ @Sendmail@, Sendmail License- | SGI_B_1_0 -- ^ @SGI-B-1.0@, SGI Free Software License B v1.0- | SGI_B_1_1 -- ^ @SGI-B-1.1@, SGI Free Software License B v1.1- | SGI_B_2_0 -- ^ @SGI-B-2.0@, SGI Free Software License B v2.0- | SHL_0_51 -- ^ @SHL-0.51@, Solderpad Hardware License, Version 0.51, SPDX License List 3.6, SPDX License List 3.9- | SHL_0_5 -- ^ @SHL-0.5@, Solderpad Hardware License v0.5, SPDX License List 3.6, SPDX License List 3.9- | SimPL_2_0 -- ^ @SimPL-2.0@, Simple Public License 2.0- | SISSL_1_2 -- ^ @SISSL-1.2@, Sun Industry Standards Source License v1.2- | SISSL -- ^ @SISSL@, Sun Industry Standards Source License v1.1- | Sleepycat -- ^ @Sleepycat@, Sleepycat License- | SMLNJ -- ^ @SMLNJ@, Standard ML of New Jersey License- | SMPPL -- ^ @SMPPL@, Secure Messaging Protocol Public License- | SNIA -- ^ @SNIA@, SNIA Public License 1.1- | Spencer_86 -- ^ @Spencer-86@, Spencer License 86- | Spencer_94 -- ^ @Spencer-94@, Spencer License 94- | Spencer_99 -- ^ @Spencer-99@, Spencer License 99- | SPL_1_0 -- ^ @SPL-1.0@, Sun Public License v1.0- | SSH_OpenSSH -- ^ @SSH-OpenSSH@, SSH OpenSSH license, SPDX License List 3.9- | SSH_short -- ^ @SSH-short@, SSH short notice, SPDX License List 3.9- | SSPL_1_0 -- ^ @SSPL-1.0@, Server Side Public License, v 1, SPDX License List 3.6, SPDX License List 3.9- | SugarCRM_1_1_3 -- ^ @SugarCRM-1.1.3@, SugarCRM Public License v1.1.3- | SWL -- ^ @SWL@, Scheme Widget Library (SWL) Software License Agreement- | TAPR_OHL_1_0 -- ^ @TAPR-OHL-1.0@, TAPR Open Hardware License v1.0, SPDX License List 3.6, SPDX License List 3.9- | TCL -- ^ @TCL@, TCL/TK License- | TCP_wrappers -- ^ @TCP-wrappers@, TCP Wrappers License- | TMate -- ^ @TMate@, TMate Open Source License- | TORQUE_1_1 -- ^ @TORQUE-1.1@, TORQUE v2.5+ Software License v1.1- | TOSL -- ^ @TOSL@, Trusster Open Source License- | TU_Berlin_1_0 -- ^ @TU-Berlin-1.0@, Technische Universitaet Berlin License 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | TU_Berlin_2_0 -- ^ @TU-Berlin-2.0@, Technische Universitaet Berlin License 2.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9- | UCL_1_0 -- ^ @UCL-1.0@, Upstream Compatibility License v1.0, SPDX License List 3.9- | Unicode_DFS_2015 -- ^ @Unicode-DFS-2015@, Unicode License Agreement - Data Files and Software (2015)- | Unicode_DFS_2016 -- ^ @Unicode-DFS-2016@, Unicode License Agreement - Data Files and Software (2016)- | Unicode_TOU -- ^ @Unicode-TOU@, Unicode Terms of Use- | Unlicense -- ^ @Unlicense@, The Unlicense- | UPL_1_0 -- ^ @UPL-1.0@, Universal Permissive License v1.0- | Vim -- ^ @Vim@, Vim License- | VOSTROM -- ^ @VOSTROM@, VOSTROM Public License for Open Source- | VSL_1_0 -- ^ @VSL-1.0@, Vovida Software License v1.0- | W3C_19980720 -- ^ @W3C-19980720@, W3C Software Notice and License (1998-07-20)- | W3C_20150513 -- ^ @W3C-20150513@, W3C Software Notice and Document License (2015-05-13)- | W3C -- ^ @W3C@, W3C Software Notice and License (2002-12-31)- | Watcom_1_0 -- ^ @Watcom-1.0@, Sybase Open Watcom Public License 1.0- | Wsuipa -- ^ @Wsuipa@, Wsuipa License- | WTFPL -- ^ @WTFPL@, Do What The F*ck You Want To Public License- | X11 -- ^ @X11@, X11 License- | Xerox -- ^ @Xerox@, Xerox License- | XFree86_1_1 -- ^ @XFree86-1.1@, XFree86 License 1.1- | Xinetd -- ^ @xinetd@, xinetd License- | Xnet -- ^ @Xnet@, X.Net License- | Xpp -- ^ @xpp@, XPP License- | XSkat -- ^ @XSkat@, XSkat License- | YPL_1_0 -- ^ @YPL-1.0@, Yahoo! Public License v1.0- | YPL_1_1 -- ^ @YPL-1.1@, Yahoo! Public License v1.1- | Zed -- ^ @Zed@, Zed License- | Zend_2_0 -- ^ @Zend-2.0@, Zend License v2.0- | Zimbra_1_3 -- ^ @Zimbra-1.3@, Zimbra Public License v1.3- | Zimbra_1_4 -- ^ @Zimbra-1.4@, Zimbra Public License v1.4- | Zlib_acknowledgement -- ^ @zlib-acknowledgement@, zlib/libpng License with Acknowledgement- | Zlib -- ^ @Zlib@, zlib License- | ZPL_1_1 -- ^ @ZPL-1.1@, Zope Public License 1.1- | ZPL_2_0 -- ^ @ZPL-2.0@, Zope Public License 2.0- | ZPL_2_1 -- ^ @ZPL-2.1@, Zope Public License 2.1- deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)--instance Binary LicenseId where- -- Word16 is encoded in big endianess- -- https://github.com/kolmodin/binary/blob/master/src/Data/Binary/Class.hs#L220-LL227- put = Binary.putWord16be . fromIntegral . fromEnum- get = do- i <- Binary.getWord16be- if i > fromIntegral (fromEnum (maxBound :: LicenseId))- then fail "Too large LicenseId tag"- else return (toEnum (fromIntegral i))---- note: remember to bump version each time the definition changes-instance Structured LicenseId where- structure p = set typeVersion 306 $ nominalStructure p--instance Pretty LicenseId where- pretty = Disp.text . licenseId---- |--- >>> eitherParsec "BSD-3-Clause" :: Either String LicenseId--- Right BSD_3_Clause------ >>> eitherParsec "BSD3" :: Either String LicenseId--- Left "...Unknown SPDX license identifier: 'BSD3' Do you mean BSD-3-Clause?"----instance Parsec LicenseId where- parsec = do- n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'- v <- askCabalSpecVersion- maybe (fail $ "Unknown SPDX license identifier: '" ++ n ++ "' " ++ licenseIdMigrationMessage n) return $- mkLicenseId (cabalSpecVersionToSPDXListVersion v) n--instance NFData LicenseId where- rnf l = l `seq` ()---- | Help message for migrating from non-SPDX license identifiers.------ Old 'License' is almost SPDX, except for 'BSD2', 'BSD3'. This function--- suggests SPDX variant:------ >>> licenseIdMigrationMessage "BSD3"--- "Do you mean BSD-3-Clause?"------ Also 'OtherLicense', 'AllRightsReserved', and 'PublicDomain' aren't--- valid SPDX identifiers------ >>> traverse_ (print . licenseIdMigrationMessage) [ "OtherLicense", "AllRightsReserved", "PublicDomain" ]--- "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."--- "You can use NONE as a value of license field."--- "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."------ SPDX License list version 3.0 introduced "-only" and "-or-later" variants for GNU family of licenses.--- See <https://spdx.org/news/news/2018/01/license-list-30-released>--- >>> licenseIdMigrationMessage "GPL-2.0"--- "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use GPL-2.0-only or GPL-2.0-or-later."------ For other common licenses their old license format coincides with the SPDX identifiers:------ >>> traverse eitherParsec ["GPL-2.0-only", "GPL-3.0-only", "LGPL-2.1-only", "MIT", "ISC", "MPL-2.0", "Apache-2.0"] :: Either String [LicenseId]--- Right [GPL_2_0_only,GPL_3_0_only,LGPL_2_1_only,MIT,ISC,MPL_2_0,Apache_2_0]----licenseIdMigrationMessage :: String -> String-licenseIdMigrationMessage = go where- go l | gnuVariant l = "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use " ++ l ++ "-only or " ++ l ++ "-or-later."- go "BSD3" = "Do you mean BSD-3-Clause?"- go "BSD2" = "Do you mean BSD-2-Clause?"- go "AllRightsReserved" = "You can use NONE as a value of license field."- go "OtherLicense" = "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."- go "PublicDomain" = "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."-- -- otherwise, we don't know- go _ = ""-- gnuVariant = flip elem ["GPL-2.0", "GPL-3.0", "LGPL-2.1", "LGPL-3.0", "AGPL-3.0" ]------------------------------------------------------------------------------------ License Data------------------------------------------------------------------------------------ | License SPDX identifier, e.g. @"BSD-3-Clause"@.-licenseId :: LicenseId -> String-licenseId NullBSD = "0BSD"-licenseId AAL = "AAL"-licenseId Abstyles = "Abstyles"-licenseId Adobe_2006 = "Adobe-2006"-licenseId Adobe_Glyph = "Adobe-Glyph"-licenseId ADSL = "ADSL"-licenseId AFL_1_1 = "AFL-1.1"-licenseId AFL_1_2 = "AFL-1.2"-licenseId AFL_2_0 = "AFL-2.0"-licenseId AFL_2_1 = "AFL-2.1"-licenseId AFL_3_0 = "AFL-3.0"-licenseId Afmparse = "Afmparse"-licenseId AGPL_1_0 = "AGPL-1.0"-licenseId AGPL_1_0_only = "AGPL-1.0-only"-licenseId AGPL_1_0_or_later = "AGPL-1.0-or-later"-licenseId AGPL_3_0_only = "AGPL-3.0-only"-licenseId AGPL_3_0_or_later = "AGPL-3.0-or-later"-licenseId Aladdin = "Aladdin"-licenseId AMDPLPA = "AMDPLPA"-licenseId AML = "AML"-licenseId AMPAS = "AMPAS"-licenseId ANTLR_PD = "ANTLR-PD"-licenseId Apache_1_0 = "Apache-1.0"-licenseId Apache_1_1 = "Apache-1.1"-licenseId Apache_2_0 = "Apache-2.0"-licenseId APAFML = "APAFML"-licenseId APL_1_0 = "APL-1.0"-licenseId APSL_1_0 = "APSL-1.0"-licenseId APSL_1_1 = "APSL-1.1"-licenseId APSL_1_2 = "APSL-1.2"-licenseId APSL_2_0 = "APSL-2.0"-licenseId Artistic_1_0_cl8 = "Artistic-1.0-cl8"-licenseId Artistic_1_0_Perl = "Artistic-1.0-Perl"-licenseId Artistic_1_0 = "Artistic-1.0"-licenseId Artistic_2_0 = "Artistic-2.0"-licenseId Bahyph = "Bahyph"-licenseId Barr = "Barr"-licenseId Beerware = "Beerware"-licenseId BitTorrent_1_0 = "BitTorrent-1.0"-licenseId BitTorrent_1_1 = "BitTorrent-1.1"-licenseId Blessing = "blessing"-licenseId BlueOak_1_0_0 = "BlueOak-1.0.0"-licenseId Borceux = "Borceux"-licenseId BSD_1_Clause = "BSD-1-Clause"-licenseId BSD_2_Clause_FreeBSD = "BSD-2-Clause-FreeBSD"-licenseId BSD_2_Clause_NetBSD = "BSD-2-Clause-NetBSD"-licenseId BSD_2_Clause_Patent = "BSD-2-Clause-Patent"-licenseId BSD_2_Clause = "BSD-2-Clause"-licenseId BSD_3_Clause_Attribution = "BSD-3-Clause-Attribution"-licenseId BSD_3_Clause_Clear = "BSD-3-Clause-Clear"-licenseId BSD_3_Clause_LBNL = "BSD-3-Clause-LBNL"-licenseId BSD_3_Clause_No_Nuclear_License_2014 = "BSD-3-Clause-No-Nuclear-License-2014"-licenseId BSD_3_Clause_No_Nuclear_License = "BSD-3-Clause-No-Nuclear-License"-licenseId BSD_3_Clause_No_Nuclear_Warranty = "BSD-3-Clause-No-Nuclear-Warranty"-licenseId BSD_3_Clause_Open_MPI = "BSD-3-Clause-Open-MPI"-licenseId BSD_3_Clause = "BSD-3-Clause"-licenseId BSD_4_Clause_UC = "BSD-4-Clause-UC"-licenseId BSD_4_Clause = "BSD-4-Clause"-licenseId BSD_Protection = "BSD-Protection"-licenseId BSD_Source_Code = "BSD-Source-Code"-licenseId BSL_1_0 = "BSL-1.0"-licenseId Bzip2_1_0_5 = "bzip2-1.0.5"-licenseId Bzip2_1_0_6 = "bzip2-1.0.6"-licenseId CAL_1_0_Combined_Work_Exception = "CAL-1.0-Combined-Work-Exception"-licenseId CAL_1_0 = "CAL-1.0"-licenseId Caldera = "Caldera"-licenseId CATOSL_1_1 = "CATOSL-1.1"-licenseId CC_BY_1_0 = "CC-BY-1.0"-licenseId CC_BY_2_0 = "CC-BY-2.0"-licenseId CC_BY_2_5 = "CC-BY-2.5"-licenseId CC_BY_3_0 = "CC-BY-3.0"-licenseId CC_BY_4_0 = "CC-BY-4.0"-licenseId CC_BY_NC_1_0 = "CC-BY-NC-1.0"-licenseId CC_BY_NC_2_0 = "CC-BY-NC-2.0"-licenseId CC_BY_NC_2_5 = "CC-BY-NC-2.5"-licenseId CC_BY_NC_3_0 = "CC-BY-NC-3.0"-licenseId CC_BY_NC_4_0 = "CC-BY-NC-4.0"-licenseId CC_BY_NC_ND_1_0 = "CC-BY-NC-ND-1.0"-licenseId CC_BY_NC_ND_2_0 = "CC-BY-NC-ND-2.0"-licenseId CC_BY_NC_ND_2_5 = "CC-BY-NC-ND-2.5"-licenseId CC_BY_NC_ND_3_0 = "CC-BY-NC-ND-3.0"-licenseId CC_BY_NC_ND_4_0 = "CC-BY-NC-ND-4.0"-licenseId CC_BY_NC_SA_1_0 = "CC-BY-NC-SA-1.0"-licenseId CC_BY_NC_SA_2_0 = "CC-BY-NC-SA-2.0"-licenseId CC_BY_NC_SA_2_5 = "CC-BY-NC-SA-2.5"-licenseId CC_BY_NC_SA_3_0 = "CC-BY-NC-SA-3.0"-licenseId CC_BY_NC_SA_4_0 = "CC-BY-NC-SA-4.0"-licenseId CC_BY_ND_1_0 = "CC-BY-ND-1.0"-licenseId CC_BY_ND_2_0 = "CC-BY-ND-2.0"-licenseId CC_BY_ND_2_5 = "CC-BY-ND-2.5"-licenseId CC_BY_ND_3_0 = "CC-BY-ND-3.0"-licenseId CC_BY_ND_4_0 = "CC-BY-ND-4.0"-licenseId CC_BY_SA_1_0 = "CC-BY-SA-1.0"-licenseId CC_BY_SA_2_0 = "CC-BY-SA-2.0"-licenseId CC_BY_SA_2_5 = "CC-BY-SA-2.5"-licenseId CC_BY_SA_3_0 = "CC-BY-SA-3.0"-licenseId CC_BY_SA_4_0 = "CC-BY-SA-4.0"-licenseId CC_PDDC = "CC-PDDC"-licenseId CC0_1_0 = "CC0-1.0"-licenseId CDDL_1_0 = "CDDL-1.0"-licenseId CDDL_1_1 = "CDDL-1.1"-licenseId CDLA_Permissive_1_0 = "CDLA-Permissive-1.0"-licenseId CDLA_Sharing_1_0 = "CDLA-Sharing-1.0"-licenseId CECILL_1_0 = "CECILL-1.0"-licenseId CECILL_1_1 = "CECILL-1.1"-licenseId CECILL_2_0 = "CECILL-2.0"-licenseId CECILL_2_1 = "CECILL-2.1"-licenseId CECILL_B = "CECILL-B"-licenseId CECILL_C = "CECILL-C"-licenseId CERN_OHL_1_1 = "CERN-OHL-1.1"-licenseId CERN_OHL_1_2 = "CERN-OHL-1.2"-licenseId CERN_OHL_P_2_0 = "CERN-OHL-P-2.0"-licenseId CERN_OHL_S_2_0 = "CERN-OHL-S-2.0"-licenseId CERN_OHL_W_2_0 = "CERN-OHL-W-2.0"-licenseId ClArtistic = "ClArtistic"-licenseId CNRI_Jython = "CNRI-Jython"-licenseId CNRI_Python_GPL_Compatible = "CNRI-Python-GPL-Compatible"-licenseId CNRI_Python = "CNRI-Python"-licenseId Condor_1_1 = "Condor-1.1"-licenseId Copyleft_next_0_3_0 = "copyleft-next-0.3.0"-licenseId Copyleft_next_0_3_1 = "copyleft-next-0.3.1"-licenseId CPAL_1_0 = "CPAL-1.0"-licenseId CPL_1_0 = "CPL-1.0"-licenseId CPOL_1_02 = "CPOL-1.02"-licenseId Crossword = "Crossword"-licenseId CrystalStacker = "CrystalStacker"-licenseId CUA_OPL_1_0 = "CUA-OPL-1.0"-licenseId Cube = "Cube"-licenseId Curl = "curl"-licenseId D_FSL_1_0 = "D-FSL-1.0"-licenseId Diffmark = "diffmark"-licenseId DOC = "DOC"-licenseId Dotseqn = "Dotseqn"-licenseId DSDP = "DSDP"-licenseId Dvipdfm = "dvipdfm"-licenseId ECL_1_0 = "ECL-1.0"-licenseId ECL_2_0 = "ECL-2.0"-licenseId EFL_1_0 = "EFL-1.0"-licenseId EFL_2_0 = "EFL-2.0"-licenseId EGenix = "eGenix"-licenseId Entessa = "Entessa"-licenseId EPL_1_0 = "EPL-1.0"-licenseId EPL_2_0 = "EPL-2.0"-licenseId ErlPL_1_1 = "ErlPL-1.1"-licenseId Etalab_2_0 = "etalab-2.0"-licenseId EUDatagrid = "EUDatagrid"-licenseId EUPL_1_0 = "EUPL-1.0"-licenseId EUPL_1_1 = "EUPL-1.1"-licenseId EUPL_1_2 = "EUPL-1.2"-licenseId Eurosym = "Eurosym"-licenseId Fair = "Fair"-licenseId Frameworx_1_0 = "Frameworx-1.0"-licenseId FreeImage = "FreeImage"-licenseId FSFAP = "FSFAP"-licenseId FSFULLR = "FSFULLR"-licenseId FSFUL = "FSFUL"-licenseId FTL = "FTL"-licenseId GFDL_1_1_only = "GFDL-1.1-only"-licenseId GFDL_1_1_or_later = "GFDL-1.1-or-later"-licenseId GFDL_1_2_only = "GFDL-1.2-only"-licenseId GFDL_1_2_or_later = "GFDL-1.2-or-later"-licenseId GFDL_1_3_only = "GFDL-1.3-only"-licenseId GFDL_1_3_or_later = "GFDL-1.3-or-later"-licenseId Giftware = "Giftware"-licenseId GL2PS = "GL2PS"-licenseId Glide = "Glide"-licenseId Glulxe = "Glulxe"-licenseId Gnuplot = "gnuplot"-licenseId GPL_1_0_only = "GPL-1.0-only"-licenseId GPL_1_0_or_later = "GPL-1.0-or-later"-licenseId GPL_2_0_only = "GPL-2.0-only"-licenseId GPL_2_0_or_later = "GPL-2.0-or-later"-licenseId GPL_3_0_only = "GPL-3.0-only"-licenseId GPL_3_0_or_later = "GPL-3.0-or-later"-licenseId GSOAP_1_3b = "gSOAP-1.3b"-licenseId HaskellReport = "HaskellReport"-licenseId Hippocratic_2_1 = "Hippocratic-2.1"-licenseId HPND_sell_variant = "HPND-sell-variant"-licenseId HPND = "HPND"-licenseId IBM_pibs = "IBM-pibs"-licenseId ICU = "ICU"-licenseId IJG = "IJG"-licenseId ImageMagick = "ImageMagick"-licenseId IMatix = "iMatix"-licenseId Imlib2 = "Imlib2"-licenseId Info_ZIP = "Info-ZIP"-licenseId Intel_ACPI = "Intel-ACPI"-licenseId Intel = "Intel"-licenseId Interbase_1_0 = "Interbase-1.0"-licenseId IPA = "IPA"-licenseId IPL_1_0 = "IPL-1.0"-licenseId ISC = "ISC"-licenseId JasPer_2_0 = "JasPer-2.0"-licenseId JPNIC = "JPNIC"-licenseId JSON = "JSON"-licenseId LAL_1_2 = "LAL-1.2"-licenseId LAL_1_3 = "LAL-1.3"-licenseId Latex2e = "Latex2e"-licenseId Leptonica = "Leptonica"-licenseId LGPL_2_0_only = "LGPL-2.0-only"-licenseId LGPL_2_0_or_later = "LGPL-2.0-or-later"-licenseId LGPL_2_1_only = "LGPL-2.1-only"-licenseId LGPL_2_1_or_later = "LGPL-2.1-or-later"-licenseId LGPL_3_0_only = "LGPL-3.0-only"-licenseId LGPL_3_0_or_later = "LGPL-3.0-or-later"-licenseId LGPLLR = "LGPLLR"-licenseId Libpng_2_0 = "libpng-2.0"-licenseId Libpng = "Libpng"-licenseId Libselinux_1_0 = "libselinux-1.0"-licenseId Libtiff = "libtiff"-licenseId LiLiQ_P_1_1 = "LiLiQ-P-1.1"-licenseId LiLiQ_R_1_1 = "LiLiQ-R-1.1"-licenseId LiLiQ_Rplus_1_1 = "LiLiQ-Rplus-1.1"-licenseId Linux_OpenIB = "Linux-OpenIB"-licenseId LPL_1_02 = "LPL-1.02"-licenseId LPL_1_0 = "LPL-1.0"-licenseId LPPL_1_0 = "LPPL-1.0"-licenseId LPPL_1_1 = "LPPL-1.1"-licenseId LPPL_1_2 = "LPPL-1.2"-licenseId LPPL_1_3a = "LPPL-1.3a"-licenseId LPPL_1_3c = "LPPL-1.3c"-licenseId MakeIndex = "MakeIndex"-licenseId MirOS = "MirOS"-licenseId MIT_0 = "MIT-0"-licenseId MIT_advertising = "MIT-advertising"-licenseId MIT_CMU = "MIT-CMU"-licenseId MIT_enna = "MIT-enna"-licenseId MIT_feh = "MIT-feh"-licenseId MITNFA = "MITNFA"-licenseId MIT = "MIT"-licenseId Motosoto = "Motosoto"-licenseId Mpich2 = "mpich2"-licenseId MPL_1_0 = "MPL-1.0"-licenseId MPL_1_1 = "MPL-1.1"-licenseId MPL_2_0_no_copyleft_exception = "MPL-2.0-no-copyleft-exception"-licenseId MPL_2_0 = "MPL-2.0"-licenseId MS_PL = "MS-PL"-licenseId MS_RL = "MS-RL"-licenseId MTLL = "MTLL"-licenseId MulanPSL_1_0 = "MulanPSL-1.0"-licenseId MulanPSL_2_0 = "MulanPSL-2.0"-licenseId Multics = "Multics"-licenseId Mup = "Mup"-licenseId NASA_1_3 = "NASA-1.3"-licenseId Naumen = "Naumen"-licenseId NBPL_1_0 = "NBPL-1.0"-licenseId NCGL_UK_2_0 = "NCGL-UK-2.0"-licenseId NCSA = "NCSA"-licenseId Net_SNMP = "Net-SNMP"-licenseId NetCDF = "NetCDF"-licenseId Newsletr = "Newsletr"-licenseId NGPL = "NGPL"-licenseId NLOD_1_0 = "NLOD-1.0"-licenseId NLPL = "NLPL"-licenseId Nokia = "Nokia"-licenseId NOSL = "NOSL"-licenseId Noweb = "Noweb"-licenseId NPL_1_0 = "NPL-1.0"-licenseId NPL_1_1 = "NPL-1.1"-licenseId NPOSL_3_0 = "NPOSL-3.0"-licenseId NRL = "NRL"-licenseId NTP_0 = "NTP-0"-licenseId NTP = "NTP"-licenseId O_UDA_1_0 = "O-UDA-1.0"-licenseId OCCT_PL = "OCCT-PL"-licenseId OCLC_2_0 = "OCLC-2.0"-licenseId ODbL_1_0 = "ODbL-1.0"-licenseId ODC_By_1_0 = "ODC-By-1.0"-licenseId OFL_1_0_no_RFN = "OFL-1.0-no-RFN"-licenseId OFL_1_0_RFN = "OFL-1.0-RFN"-licenseId OFL_1_0 = "OFL-1.0"-licenseId OFL_1_1_no_RFN = "OFL-1.1-no-RFN"-licenseId OFL_1_1_RFN = "OFL-1.1-RFN"-licenseId OFL_1_1 = "OFL-1.1"-licenseId OGC_1_0 = "OGC-1.0"-licenseId OGL_Canada_2_0 = "OGL-Canada-2.0"-licenseId OGL_UK_1_0 = "OGL-UK-1.0"-licenseId OGL_UK_2_0 = "OGL-UK-2.0"-licenseId OGL_UK_3_0 = "OGL-UK-3.0"-licenseId OGTSL = "OGTSL"-licenseId OLDAP_1_1 = "OLDAP-1.1"-licenseId OLDAP_1_2 = "OLDAP-1.2"-licenseId OLDAP_1_3 = "OLDAP-1.3"-licenseId OLDAP_1_4 = "OLDAP-1.4"-licenseId OLDAP_2_0_1 = "OLDAP-2.0.1"-licenseId OLDAP_2_0 = "OLDAP-2.0"-licenseId OLDAP_2_1 = "OLDAP-2.1"-licenseId OLDAP_2_2_1 = "OLDAP-2.2.1"-licenseId OLDAP_2_2_2 = "OLDAP-2.2.2"-licenseId OLDAP_2_2 = "OLDAP-2.2"-licenseId OLDAP_2_3 = "OLDAP-2.3"-licenseId OLDAP_2_4 = "OLDAP-2.4"-licenseId OLDAP_2_5 = "OLDAP-2.5"-licenseId OLDAP_2_6 = "OLDAP-2.6"-licenseId OLDAP_2_7 = "OLDAP-2.7"-licenseId OLDAP_2_8 = "OLDAP-2.8"-licenseId OML = "OML"-licenseId OpenSSL = "OpenSSL"-licenseId OPL_1_0 = "OPL-1.0"-licenseId OSET_PL_2_1 = "OSET-PL-2.1"-licenseId OSL_1_0 = "OSL-1.0"-licenseId OSL_1_1 = "OSL-1.1"-licenseId OSL_2_0 = "OSL-2.0"-licenseId OSL_2_1 = "OSL-2.1"-licenseId OSL_3_0 = "OSL-3.0"-licenseId Parity_6_0_0 = "Parity-6.0.0"-licenseId Parity_7_0_0 = "Parity-7.0.0"-licenseId PDDL_1_0 = "PDDL-1.0"-licenseId PHP_3_01 = "PHP-3.01"-licenseId PHP_3_0 = "PHP-3.0"-licenseId Plexus = "Plexus"-licenseId PolyForm_Noncommercial_1_0_0 = "PolyForm-Noncommercial-1.0.0"-licenseId PolyForm_Small_Business_1_0_0 = "PolyForm-Small-Business-1.0.0"-licenseId PostgreSQL = "PostgreSQL"-licenseId PSF_2_0 = "PSF-2.0"-licenseId Psfrag = "psfrag"-licenseId Psutils = "psutils"-licenseId Python_2_0 = "Python-2.0"-licenseId Qhull = "Qhull"-licenseId QPL_1_0 = "QPL-1.0"-licenseId Rdisc = "Rdisc"-licenseId RHeCos_1_1 = "RHeCos-1.1"-licenseId RPL_1_1 = "RPL-1.1"-licenseId RPL_1_5 = "RPL-1.5"-licenseId RPSL_1_0 = "RPSL-1.0"-licenseId RSA_MD = "RSA-MD"-licenseId RSCPL = "RSCPL"-licenseId Ruby = "Ruby"-licenseId SAX_PD = "SAX-PD"-licenseId Saxpath = "Saxpath"-licenseId SCEA = "SCEA"-licenseId Sendmail_8_23 = "Sendmail-8.23"-licenseId Sendmail = "Sendmail"-licenseId SGI_B_1_0 = "SGI-B-1.0"-licenseId SGI_B_1_1 = "SGI-B-1.1"-licenseId SGI_B_2_0 = "SGI-B-2.0"-licenseId SHL_0_51 = "SHL-0.51"-licenseId SHL_0_5 = "SHL-0.5"-licenseId SimPL_2_0 = "SimPL-2.0"-licenseId SISSL_1_2 = "SISSL-1.2"-licenseId SISSL = "SISSL"-licenseId Sleepycat = "Sleepycat"-licenseId SMLNJ = "SMLNJ"-licenseId SMPPL = "SMPPL"-licenseId SNIA = "SNIA"-licenseId Spencer_86 = "Spencer-86"-licenseId Spencer_94 = "Spencer-94"-licenseId Spencer_99 = "Spencer-99"-licenseId SPL_1_0 = "SPL-1.0"-licenseId SSH_OpenSSH = "SSH-OpenSSH"-licenseId SSH_short = "SSH-short"-licenseId SSPL_1_0 = "SSPL-1.0"-licenseId SugarCRM_1_1_3 = "SugarCRM-1.1.3"-licenseId SWL = "SWL"-licenseId TAPR_OHL_1_0 = "TAPR-OHL-1.0"-licenseId TCL = "TCL"-licenseId TCP_wrappers = "TCP-wrappers"-licenseId TMate = "TMate"-licenseId TORQUE_1_1 = "TORQUE-1.1"-licenseId TOSL = "TOSL"-licenseId TU_Berlin_1_0 = "TU-Berlin-1.0"-licenseId TU_Berlin_2_0 = "TU-Berlin-2.0"-licenseId UCL_1_0 = "UCL-1.0"-licenseId Unicode_DFS_2015 = "Unicode-DFS-2015"-licenseId Unicode_DFS_2016 = "Unicode-DFS-2016"-licenseId Unicode_TOU = "Unicode-TOU"-licenseId Unlicense = "Unlicense"-licenseId UPL_1_0 = "UPL-1.0"-licenseId Vim = "Vim"-licenseId VOSTROM = "VOSTROM"-licenseId VSL_1_0 = "VSL-1.0"-licenseId W3C_19980720 = "W3C-19980720"-licenseId W3C_20150513 = "W3C-20150513"-licenseId W3C = "W3C"-licenseId Watcom_1_0 = "Watcom-1.0"-licenseId Wsuipa = "Wsuipa"-licenseId WTFPL = "WTFPL"-licenseId X11 = "X11"-licenseId Xerox = "Xerox"-licenseId XFree86_1_1 = "XFree86-1.1"-licenseId Xinetd = "xinetd"-licenseId Xnet = "Xnet"-licenseId Xpp = "xpp"-licenseId XSkat = "XSkat"-licenseId YPL_1_0 = "YPL-1.0"-licenseId YPL_1_1 = "YPL-1.1"-licenseId Zed = "Zed"-licenseId Zend_2_0 = "Zend-2.0"-licenseId Zimbra_1_3 = "Zimbra-1.3"-licenseId Zimbra_1_4 = "Zimbra-1.4"-licenseId Zlib_acknowledgement = "zlib-acknowledgement"-licenseId Zlib = "Zlib"-licenseId ZPL_1_1 = "ZPL-1.1"-licenseId ZPL_2_0 = "ZPL-2.0"-licenseId ZPL_2_1 = "ZPL-2.1"---- | License name, e.g. @"GNU General Public License v2.0 only"@-licenseName :: LicenseId -> String-licenseName NullBSD = "BSD Zero Clause License"-licenseName AAL = "Attribution Assurance License"-licenseName Abstyles = "Abstyles License"-licenseName Adobe_2006 = "Adobe Systems Incorporated Source Code License Agreement"-licenseName Adobe_Glyph = "Adobe Glyph List License"-licenseName ADSL = "Amazon Digital Services License"-licenseName AFL_1_1 = "Academic Free License v1.1"-licenseName AFL_1_2 = "Academic Free License v1.2"-licenseName AFL_2_0 = "Academic Free License v2.0"-licenseName AFL_2_1 = "Academic Free License v2.1"-licenseName AFL_3_0 = "Academic Free License v3.0"-licenseName Afmparse = "Afmparse License"-licenseName AGPL_1_0 = "Affero General Public License v1.0"-licenseName AGPL_1_0_only = "Affero General Public License v1.0 only"-licenseName AGPL_1_0_or_later = "Affero General Public License v1.0 or later"-licenseName AGPL_3_0_only = "GNU Affero General Public License v3.0 only"-licenseName AGPL_3_0_or_later = "GNU Affero General Public License v3.0 or later"-licenseName Aladdin = "Aladdin Free Public License"-licenseName AMDPLPA = "AMD's plpa_map.c License"-licenseName AML = "Apple MIT License"-licenseName AMPAS = "Academy of Motion Picture Arts and Sciences BSD"-licenseName ANTLR_PD = "ANTLR Software Rights Notice"-licenseName Apache_1_0 = "Apache License 1.0"-licenseName Apache_1_1 = "Apache License 1.1"-licenseName Apache_2_0 = "Apache License 2.0"-licenseName APAFML = "Adobe Postscript AFM License"-licenseName APL_1_0 = "Adaptive Public License 1.0"-licenseName APSL_1_0 = "Apple Public Source License 1.0"-licenseName APSL_1_1 = "Apple Public Source License 1.1"-licenseName APSL_1_2 = "Apple Public Source License 1.2"-licenseName APSL_2_0 = "Apple Public Source License 2.0"-licenseName Artistic_1_0_cl8 = "Artistic License 1.0 w/clause 8"-licenseName Artistic_1_0_Perl = "Artistic License 1.0 (Perl)"-licenseName Artistic_1_0 = "Artistic License 1.0"-licenseName Artistic_2_0 = "Artistic License 2.0"-licenseName Bahyph = "Bahyph License"-licenseName Barr = "Barr License"-licenseName Beerware = "Beerware License"-licenseName BitTorrent_1_0 = "BitTorrent Open Source License v1.0"-licenseName BitTorrent_1_1 = "BitTorrent Open Source License v1.1"-licenseName Blessing = "SQLite Blessing"-licenseName BlueOak_1_0_0 = "Blue Oak Model License 1.0.0"-licenseName Borceux = "Borceux license"-licenseName BSD_1_Clause = "BSD 1-Clause License"-licenseName BSD_2_Clause_FreeBSD = "BSD 2-Clause FreeBSD License"-licenseName BSD_2_Clause_NetBSD = "BSD 2-Clause NetBSD License"-licenseName BSD_2_Clause_Patent = "BSD-2-Clause Plus Patent License"-licenseName BSD_2_Clause = "BSD 2-Clause \"Simplified\" License"-licenseName BSD_3_Clause_Attribution = "BSD with attribution"-licenseName BSD_3_Clause_Clear = "BSD 3-Clause Clear License"-licenseName BSD_3_Clause_LBNL = "Lawrence Berkeley National Labs BSD variant license"-licenseName BSD_3_Clause_No_Nuclear_License_2014 = "BSD 3-Clause No Nuclear License 2014"-licenseName BSD_3_Clause_No_Nuclear_License = "BSD 3-Clause No Nuclear License"-licenseName BSD_3_Clause_No_Nuclear_Warranty = "BSD 3-Clause No Nuclear Warranty"-licenseName BSD_3_Clause_Open_MPI = "BSD 3-Clause Open MPI variant"-licenseName BSD_3_Clause = "BSD 3-Clause \"New\" or \"Revised\" License"-licenseName BSD_4_Clause_UC = "BSD-4-Clause (University of California-Specific)"-licenseName BSD_4_Clause = "BSD 4-Clause \"Original\" or \"Old\" License"-licenseName BSD_Protection = "BSD Protection License"-licenseName BSD_Source_Code = "BSD Source Code Attribution"-licenseName BSL_1_0 = "Boost Software License 1.0"-licenseName Bzip2_1_0_5 = "bzip2 and libbzip2 License v1.0.5"-licenseName Bzip2_1_0_6 = "bzip2 and libbzip2 License v1.0.6"-licenseName CAL_1_0_Combined_Work_Exception = "Cryptographic Autonomy License 1.0 (Combined Work Exception)"-licenseName CAL_1_0 = "Cryptographic Autonomy License 1.0"-licenseName Caldera = "Caldera License"-licenseName CATOSL_1_1 = "Computer Associates Trusted Open Source License 1.1"-licenseName CC_BY_1_0 = "Creative Commons Attribution 1.0 Generic"-licenseName CC_BY_2_0 = "Creative Commons Attribution 2.0 Generic"-licenseName CC_BY_2_5 = "Creative Commons Attribution 2.5 Generic"-licenseName CC_BY_3_0 = "Creative Commons Attribution 3.0 Unported"-licenseName CC_BY_4_0 = "Creative Commons Attribution 4.0 International"-licenseName CC_BY_NC_1_0 = "Creative Commons Attribution Non Commercial 1.0 Generic"-licenseName CC_BY_NC_2_0 = "Creative Commons Attribution Non Commercial 2.0 Generic"-licenseName CC_BY_NC_2_5 = "Creative Commons Attribution Non Commercial 2.5 Generic"-licenseName CC_BY_NC_3_0 = "Creative Commons Attribution Non Commercial 3.0 Unported"-licenseName CC_BY_NC_4_0 = "Creative Commons Attribution Non Commercial 4.0 International"-licenseName CC_BY_NC_ND_1_0 = "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic"-licenseName CC_BY_NC_ND_2_0 = "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic"-licenseName CC_BY_NC_ND_2_5 = "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic"-licenseName CC_BY_NC_ND_3_0 = "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported"-licenseName CC_BY_NC_ND_4_0 = "Creative Commons Attribution Non Commercial No Derivatives 4.0 International"-licenseName CC_BY_NC_SA_1_0 = "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic"-licenseName CC_BY_NC_SA_2_0 = "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic"-licenseName CC_BY_NC_SA_2_5 = "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic"-licenseName CC_BY_NC_SA_3_0 = "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported"-licenseName CC_BY_NC_SA_4_0 = "Creative Commons Attribution Non Commercial Share Alike 4.0 International"-licenseName CC_BY_ND_1_0 = "Creative Commons Attribution No Derivatives 1.0 Generic"-licenseName CC_BY_ND_2_0 = "Creative Commons Attribution No Derivatives 2.0 Generic"-licenseName CC_BY_ND_2_5 = "Creative Commons Attribution No Derivatives 2.5 Generic"-licenseName CC_BY_ND_3_0 = "Creative Commons Attribution No Derivatives 3.0 Unported"-licenseName CC_BY_ND_4_0 = "Creative Commons Attribution No Derivatives 4.0 International"-licenseName CC_BY_SA_1_0 = "Creative Commons Attribution Share Alike 1.0 Generic"-licenseName CC_BY_SA_2_0 = "Creative Commons Attribution Share Alike 2.0 Generic"-licenseName CC_BY_SA_2_5 = "Creative Commons Attribution Share Alike 2.5 Generic"-licenseName CC_BY_SA_3_0 = "Creative Commons Attribution Share Alike 3.0 Unported"-licenseName CC_BY_SA_4_0 = "Creative Commons Attribution Share Alike 4.0 International"-licenseName CC_PDDC = "Creative Commons Public Domain Dedication and Certification"-licenseName CC0_1_0 = "Creative Commons Zero v1.0 Universal"-licenseName CDDL_1_0 = "Common Development and Distribution License 1.0"-licenseName CDDL_1_1 = "Common Development and Distribution License 1.1"-licenseName CDLA_Permissive_1_0 = "Community Data License Agreement Permissive 1.0"-licenseName CDLA_Sharing_1_0 = "Community Data License Agreement Sharing 1.0"-licenseName CECILL_1_0 = "CeCILL Free Software License Agreement v1.0"-licenseName CECILL_1_1 = "CeCILL Free Software License Agreement v1.1"-licenseName CECILL_2_0 = "CeCILL Free Software License Agreement v2.0"-licenseName CECILL_2_1 = "CeCILL Free Software License Agreement v2.1"-licenseName CECILL_B = "CeCILL-B Free Software License Agreement"-licenseName CECILL_C = "CeCILL-C Free Software License Agreement"-licenseName CERN_OHL_1_1 = "CERN Open Hardware Licence v1.1"-licenseName CERN_OHL_1_2 = "CERN Open Hardware Licence v1.2"-licenseName CERN_OHL_P_2_0 = "CERN Open Hardware Licence Version 2 - Permissive"-licenseName CERN_OHL_S_2_0 = "CERN Open Hardware Licence Version 2 - Strongly Reciprocal"-licenseName CERN_OHL_W_2_0 = "CERN Open Hardware Licence Version 2 - Weakly Reciprocal"-licenseName ClArtistic = "Clarified Artistic License"-licenseName CNRI_Jython = "CNRI Jython License"-licenseName CNRI_Python_GPL_Compatible = "CNRI Python Open Source GPL Compatible License Agreement"-licenseName CNRI_Python = "CNRI Python License"-licenseName Condor_1_1 = "Condor Public License v1.1"-licenseName Copyleft_next_0_3_0 = "copyleft-next 0.3.0"-licenseName Copyleft_next_0_3_1 = "copyleft-next 0.3.1"-licenseName CPAL_1_0 = "Common Public Attribution License 1.0"-licenseName CPL_1_0 = "Common Public License 1.0"-licenseName CPOL_1_02 = "Code Project Open License 1.02"-licenseName Crossword = "Crossword License"-licenseName CrystalStacker = "CrystalStacker License"-licenseName CUA_OPL_1_0 = "CUA Office Public License v1.0"-licenseName Cube = "Cube License"-licenseName Curl = "curl License"-licenseName D_FSL_1_0 = "Deutsche Freie Software Lizenz"-licenseName Diffmark = "diffmark license"-licenseName DOC = "DOC License"-licenseName Dotseqn = "Dotseqn License"-licenseName DSDP = "DSDP License"-licenseName Dvipdfm = "dvipdfm License"-licenseName ECL_1_0 = "Educational Community License v1.0"-licenseName ECL_2_0 = "Educational Community License v2.0"-licenseName EFL_1_0 = "Eiffel Forum License v1.0"-licenseName EFL_2_0 = "Eiffel Forum License v2.0"-licenseName EGenix = "eGenix.com Public License 1.1.0"-licenseName Entessa = "Entessa Public License v1.0"-licenseName EPL_1_0 = "Eclipse Public License 1.0"-licenseName EPL_2_0 = "Eclipse Public License 2.0"-licenseName ErlPL_1_1 = "Erlang Public License v1.1"-licenseName Etalab_2_0 = "Etalab Open License 2.0"-licenseName EUDatagrid = "EU DataGrid Software License"-licenseName EUPL_1_0 = "European Union Public License 1.0"-licenseName EUPL_1_1 = "European Union Public License 1.1"-licenseName EUPL_1_2 = "European Union Public License 1.2"-licenseName Eurosym = "Eurosym License"-licenseName Fair = "Fair License"-licenseName Frameworx_1_0 = "Frameworx Open License 1.0"-licenseName FreeImage = "FreeImage Public License v1.0"-licenseName FSFAP = "FSF All Permissive License"-licenseName FSFULLR = "FSF Unlimited License (with License Retention)"-licenseName FSFUL = "FSF Unlimited License"-licenseName FTL = "Freetype Project License"-licenseName GFDL_1_1_only = "GNU Free Documentation License v1.1 only"-licenseName GFDL_1_1_or_later = "GNU Free Documentation License v1.1 or later"-licenseName GFDL_1_2_only = "GNU Free Documentation License v1.2 only"-licenseName GFDL_1_2_or_later = "GNU Free Documentation License v1.2 or later"-licenseName GFDL_1_3_only = "GNU Free Documentation License v1.3 only"-licenseName GFDL_1_3_or_later = "GNU Free Documentation License v1.3 or later"-licenseName Giftware = "Giftware License"-licenseName GL2PS = "GL2PS License"-licenseName Glide = "3dfx Glide License"-licenseName Glulxe = "Glulxe License"-licenseName Gnuplot = "gnuplot License"-licenseName GPL_1_0_only = "GNU General Public License v1.0 only"-licenseName GPL_1_0_or_later = "GNU General Public License v1.0 or later"-licenseName GPL_2_0_only = "GNU General Public License v2.0 only"-licenseName GPL_2_0_or_later = "GNU General Public License v2.0 or later"-licenseName GPL_3_0_only = "GNU General Public License v3.0 only"-licenseName GPL_3_0_or_later = "GNU General Public License v3.0 or later"-licenseName GSOAP_1_3b = "gSOAP Public License v1.3b"-licenseName HaskellReport = "Haskell Language Report License"-licenseName Hippocratic_2_1 = "Hippocratic License 2.1"-licenseName HPND_sell_variant = "Historical Permission Notice and Disclaimer - sell variant"-licenseName HPND = "Historical Permission Notice and Disclaimer"-licenseName IBM_pibs = "IBM PowerPC Initialization and Boot Software"-licenseName ICU = "ICU License"-licenseName IJG = "Independent JPEG Group License"-licenseName ImageMagick = "ImageMagick License"-licenseName IMatix = "iMatix Standard Function Library Agreement"-licenseName Imlib2 = "Imlib2 License"-licenseName Info_ZIP = "Info-ZIP License"-licenseName Intel_ACPI = "Intel ACPI Software License Agreement"-licenseName Intel = "Intel Open Source License"-licenseName Interbase_1_0 = "Interbase Public License v1.0"-licenseName IPA = "IPA Font License"-licenseName IPL_1_0 = "IBM Public License v1.0"-licenseName ISC = "ISC License"-licenseName JasPer_2_0 = "JasPer License"-licenseName JPNIC = "Japan Network Information Center License"-licenseName JSON = "JSON License"-licenseName LAL_1_2 = "Licence Art Libre 1.2"-licenseName LAL_1_3 = "Licence Art Libre 1.3"-licenseName Latex2e = "Latex2e License"-licenseName Leptonica = "Leptonica License"-licenseName LGPL_2_0_only = "GNU Library General Public License v2 only"-licenseName LGPL_2_0_or_later = "GNU Library General Public License v2 or later"-licenseName LGPL_2_1_only = "GNU Lesser General Public License v2.1 only"-licenseName LGPL_2_1_or_later = "GNU Lesser General Public License v2.1 or later"-licenseName LGPL_3_0_only = "GNU Lesser General Public License v3.0 only"-licenseName LGPL_3_0_or_later = "GNU Lesser General Public License v3.0 or later"-licenseName LGPLLR = "Lesser General Public License For Linguistic Resources"-licenseName Libpng_2_0 = "PNG Reference Library version 2"-licenseName Libpng = "libpng License"-licenseName Libselinux_1_0 = "libselinux public domain notice"-licenseName Libtiff = "libtiff License"-licenseName LiLiQ_P_1_1 = "Licence Libre du Qu\233bec \8211 Permissive version 1.1"-licenseName LiLiQ_R_1_1 = "Licence Libre du Qu\233bec \8211 R\233ciprocit\233 version 1.1"-licenseName LiLiQ_Rplus_1_1 = "Licence Libre du Qu\233bec \8211 R\233ciprocit\233 forte version 1.1"-licenseName Linux_OpenIB = "Linux Kernel Variant of OpenIB.org license"-licenseName LPL_1_02 = "Lucent Public License v1.02"-licenseName LPL_1_0 = "Lucent Public License Version 1.0"-licenseName LPPL_1_0 = "LaTeX Project Public License v1.0"-licenseName LPPL_1_1 = "LaTeX Project Public License v1.1"-licenseName LPPL_1_2 = "LaTeX Project Public License v1.2"-licenseName LPPL_1_3a = "LaTeX Project Public License v1.3a"-licenseName LPPL_1_3c = "LaTeX Project Public License v1.3c"-licenseName MakeIndex = "MakeIndex License"-licenseName MirOS = "The MirOS Licence"-licenseName MIT_0 = "MIT No Attribution"-licenseName MIT_advertising = "Enlightenment License (e16)"-licenseName MIT_CMU = "CMU License"-licenseName MIT_enna = "enna License"-licenseName MIT_feh = "feh License"-licenseName MITNFA = "MIT +no-false-attribs license"-licenseName MIT = "MIT License"-licenseName Motosoto = "Motosoto License"-licenseName Mpich2 = "mpich2 License"-licenseName MPL_1_0 = "Mozilla Public License 1.0"-licenseName MPL_1_1 = "Mozilla Public License 1.1"-licenseName MPL_2_0_no_copyleft_exception = "Mozilla Public License 2.0 (no copyleft exception)"-licenseName MPL_2_0 = "Mozilla Public License 2.0"-licenseName MS_PL = "Microsoft Public License"-licenseName MS_RL = "Microsoft Reciprocal License"-licenseName MTLL = "Matrix Template Library License"-licenseName MulanPSL_1_0 = "Mulan Permissive Software License, Version 1"-licenseName MulanPSL_2_0 = "Mulan Permissive Software License, Version 2"-licenseName Multics = "Multics License"-licenseName Mup = "Mup License"-licenseName NASA_1_3 = "NASA Open Source Agreement 1.3"-licenseName Naumen = "Naumen Public License"-licenseName NBPL_1_0 = "Net Boolean Public License v1"-licenseName NCGL_UK_2_0 = "Non-Commercial Government Licence"-licenseName NCSA = "University of Illinois/NCSA Open Source License"-licenseName Net_SNMP = "Net-SNMP License"-licenseName NetCDF = "NetCDF license"-licenseName Newsletr = "Newsletr License"-licenseName NGPL = "Nethack General Public License"-licenseName NLOD_1_0 = "Norwegian Licence for Open Government Data"-licenseName NLPL = "No Limit Public License"-licenseName Nokia = "Nokia Open Source License"-licenseName NOSL = "Netizen Open Source License"-licenseName Noweb = "Noweb License"-licenseName NPL_1_0 = "Netscape Public License v1.0"-licenseName NPL_1_1 = "Netscape Public License v1.1"-licenseName NPOSL_3_0 = "Non-Profit Open Software License 3.0"-licenseName NRL = "NRL License"-licenseName NTP_0 = "NTP No Attribution"-licenseName NTP = "NTP License"-licenseName O_UDA_1_0 = "Open Use of Data Agreement v1.0"-licenseName OCCT_PL = "Open CASCADE Technology Public License"-licenseName OCLC_2_0 = "OCLC Research Public License 2.0"-licenseName ODbL_1_0 = "ODC Open Database License v1.0"-licenseName ODC_By_1_0 = "Open Data Commons Attribution License v1.0"-licenseName OFL_1_0_no_RFN = "SIL Open Font License 1.0 with no Reserved Font Name"-licenseName OFL_1_0_RFN = "SIL Open Font License 1.0 with Reserved Font Name"-licenseName OFL_1_0 = "SIL Open Font License 1.0"-licenseName OFL_1_1_no_RFN = "SIL Open Font License 1.1 with no Reserved Font Name"-licenseName OFL_1_1_RFN = "SIL Open Font License 1.1 with Reserved Font Name"-licenseName OFL_1_1 = "SIL Open Font License 1.1"-licenseName OGC_1_0 = "OGC Software License, Version 1.0"-licenseName OGL_Canada_2_0 = "Open Government Licence - Canada"-licenseName OGL_UK_1_0 = "Open Government Licence v1.0"-licenseName OGL_UK_2_0 = "Open Government Licence v2.0"-licenseName OGL_UK_3_0 = "Open Government Licence v3.0"-licenseName OGTSL = "Open Group Test Suite License"-licenseName OLDAP_1_1 = "Open LDAP Public License v1.1"-licenseName OLDAP_1_2 = "Open LDAP Public License v1.2"-licenseName OLDAP_1_3 = "Open LDAP Public License v1.3"-licenseName OLDAP_1_4 = "Open LDAP Public License v1.4"-licenseName OLDAP_2_0_1 = "Open LDAP Public License v2.0.1"-licenseName OLDAP_2_0 = "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)"-licenseName OLDAP_2_1 = "Open LDAP Public License v2.1"-licenseName OLDAP_2_2_1 = "Open LDAP Public License v2.2.1"-licenseName OLDAP_2_2_2 = "Open LDAP Public License 2.2.2"-licenseName OLDAP_2_2 = "Open LDAP Public License v2.2"-licenseName OLDAP_2_3 = "Open LDAP Public License v2.3"-licenseName OLDAP_2_4 = "Open LDAP Public License v2.4"-licenseName OLDAP_2_5 = "Open LDAP Public License v2.5"-licenseName OLDAP_2_6 = "Open LDAP Public License v2.6"-licenseName OLDAP_2_7 = "Open LDAP Public License v2.7"-licenseName OLDAP_2_8 = "Open LDAP Public License v2.8"-licenseName OML = "Open Market License"-licenseName OpenSSL = "OpenSSL License"-licenseName OPL_1_0 = "Open Public License v1.0"-licenseName OSET_PL_2_1 = "OSET Public License version 2.1"-licenseName OSL_1_0 = "Open Software License 1.0"-licenseName OSL_1_1 = "Open Software License 1.1"-licenseName OSL_2_0 = "Open Software License 2.0"-licenseName OSL_2_1 = "Open Software License 2.1"-licenseName OSL_3_0 = "Open Software License 3.0"-licenseName Parity_6_0_0 = "The Parity Public License 6.0.0"-licenseName Parity_7_0_0 = "The Parity Public License 7.0.0"-licenseName PDDL_1_0 = "ODC Public Domain Dedication & License 1.0"-licenseName PHP_3_01 = "PHP License v3.01"-licenseName PHP_3_0 = "PHP License v3.0"-licenseName Plexus = "Plexus Classworlds License"-licenseName PolyForm_Noncommercial_1_0_0 = "PolyForm Noncommercial License 1.0.0"-licenseName PolyForm_Small_Business_1_0_0 = "PolyForm Small Business License 1.0.0"-licenseName PostgreSQL = "PostgreSQL License"-licenseName PSF_2_0 = "Python Software Foundation License 2.0"-licenseName Psfrag = "psfrag License"-licenseName Psutils = "psutils License"-licenseName Python_2_0 = "Python License 2.0"-licenseName Qhull = "Qhull License"-licenseName QPL_1_0 = "Q Public License 1.0"-licenseName Rdisc = "Rdisc License"-licenseName RHeCos_1_1 = "Red Hat eCos Public License v1.1"-licenseName RPL_1_1 = "Reciprocal Public License 1.1"-licenseName RPL_1_5 = "Reciprocal Public License 1.5"-licenseName RPSL_1_0 = "RealNetworks Public Source License v1.0"-licenseName RSA_MD = "RSA Message-Digest License "-licenseName RSCPL = "Ricoh Source Code Public License"-licenseName Ruby = "Ruby License"-licenseName SAX_PD = "Sax Public Domain Notice"-licenseName Saxpath = "Saxpath License"-licenseName SCEA = "SCEA Shared Source License"-licenseName Sendmail_8_23 = "Sendmail License 8.23"-licenseName Sendmail = "Sendmail License"-licenseName SGI_B_1_0 = "SGI Free Software License B v1.0"-licenseName SGI_B_1_1 = "SGI Free Software License B v1.1"-licenseName SGI_B_2_0 = "SGI Free Software License B v2.0"-licenseName SHL_0_51 = "Solderpad Hardware License, Version 0.51"-licenseName SHL_0_5 = "Solderpad Hardware License v0.5"-licenseName SimPL_2_0 = "Simple Public License 2.0"-licenseName SISSL_1_2 = "Sun Industry Standards Source License v1.2"-licenseName SISSL = "Sun Industry Standards Source License v1.1"-licenseName Sleepycat = "Sleepycat License"-licenseName SMLNJ = "Standard ML of New Jersey License"-licenseName SMPPL = "Secure Messaging Protocol Public License"-licenseName SNIA = "SNIA Public License 1.1"-licenseName Spencer_86 = "Spencer License 86"-licenseName Spencer_94 = "Spencer License 94"-licenseName Spencer_99 = "Spencer License 99"-licenseName SPL_1_0 = "Sun Public License v1.0"-licenseName SSH_OpenSSH = "SSH OpenSSH license"-licenseName SSH_short = "SSH short notice"-licenseName SSPL_1_0 = "Server Side Public License, v 1"-licenseName SugarCRM_1_1_3 = "SugarCRM Public License v1.1.3"-licenseName SWL = "Scheme Widget Library (SWL) Software License Agreement"-licenseName TAPR_OHL_1_0 = "TAPR Open Hardware License v1.0"-licenseName TCL = "TCL/TK License"-licenseName TCP_wrappers = "TCP Wrappers License"-licenseName TMate = "TMate Open Source License"-licenseName TORQUE_1_1 = "TORQUE v2.5+ Software License v1.1"-licenseName TOSL = "Trusster Open Source License"-licenseName TU_Berlin_1_0 = "Technische Universitaet Berlin License 1.0"-licenseName TU_Berlin_2_0 = "Technische Universitaet Berlin License 2.0"-licenseName UCL_1_0 = "Upstream Compatibility License v1.0"-licenseName Unicode_DFS_2015 = "Unicode License Agreement - Data Files and Software (2015)"-licenseName Unicode_DFS_2016 = "Unicode License Agreement - Data Files and Software (2016)"-licenseName Unicode_TOU = "Unicode Terms of Use"-licenseName Unlicense = "The Unlicense"-licenseName UPL_1_0 = "Universal Permissive License v1.0"-licenseName Vim = "Vim License"-licenseName VOSTROM = "VOSTROM Public License for Open Source"-licenseName VSL_1_0 = "Vovida Software License v1.0"-licenseName W3C_19980720 = "W3C Software Notice and License (1998-07-20)"-licenseName W3C_20150513 = "W3C Software Notice and Document License (2015-05-13)"-licenseName W3C = "W3C Software Notice and License (2002-12-31)"-licenseName Watcom_1_0 = "Sybase Open Watcom Public License 1.0"-licenseName Wsuipa = "Wsuipa License"-licenseName WTFPL = "Do What The F*ck You Want To Public License"-licenseName X11 = "X11 License"-licenseName Xerox = "Xerox License"-licenseName XFree86_1_1 = "XFree86 License 1.1"-licenseName Xinetd = "xinetd License"-licenseName Xnet = "X.Net License"-licenseName Xpp = "XPP License"-licenseName XSkat = "XSkat License"-licenseName YPL_1_0 = "Yahoo! Public License v1.0"-licenseName YPL_1_1 = "Yahoo! Public License v1.1"-licenseName Zed = "Zed License"-licenseName Zend_2_0 = "Zend License v2.0"-licenseName Zimbra_1_3 = "Zimbra Public License v1.3"-licenseName Zimbra_1_4 = "Zimbra Public License v1.4"-licenseName Zlib_acknowledgement = "zlib/libpng License with Acknowledgement"-licenseName Zlib = "zlib License"-licenseName ZPL_1_1 = "Zope Public License 1.1"-licenseName ZPL_2_0 = "Zope Public License 2.0"-licenseName ZPL_2_1 = "Zope Public License 2.1"---- | Whether the license is approved by Open Source Initiative (OSI).------ See <https://opensource.org/licenses/alphabetical>.-licenseIsOsiApproved :: LicenseId -> Bool-licenseIsOsiApproved NullBSD = True-licenseIsOsiApproved AAL = True-licenseIsOsiApproved AFL_1_1 = True-licenseIsOsiApproved AFL_1_2 = True-licenseIsOsiApproved AFL_2_0 = True-licenseIsOsiApproved AFL_2_1 = True-licenseIsOsiApproved AFL_3_0 = True-licenseIsOsiApproved AGPL_3_0_only = True-licenseIsOsiApproved AGPL_3_0_or_later = True-licenseIsOsiApproved Apache_1_1 = True-licenseIsOsiApproved Apache_2_0 = True-licenseIsOsiApproved APL_1_0 = True-licenseIsOsiApproved APSL_1_0 = True-licenseIsOsiApproved APSL_1_1 = True-licenseIsOsiApproved APSL_1_2 = True-licenseIsOsiApproved APSL_2_0 = True-licenseIsOsiApproved Artistic_1_0_cl8 = True-licenseIsOsiApproved Artistic_1_0_Perl = True-licenseIsOsiApproved Artistic_1_0 = True-licenseIsOsiApproved Artistic_2_0 = True-licenseIsOsiApproved BSD_1_Clause = True-licenseIsOsiApproved BSD_2_Clause_Patent = True-licenseIsOsiApproved BSD_2_Clause = True-licenseIsOsiApproved BSD_3_Clause_LBNL = True-licenseIsOsiApproved BSD_3_Clause = True-licenseIsOsiApproved BSL_1_0 = True-licenseIsOsiApproved CAL_1_0_Combined_Work_Exception = True-licenseIsOsiApproved CAL_1_0 = True-licenseIsOsiApproved CATOSL_1_1 = True-licenseIsOsiApproved CDDL_1_0 = True-licenseIsOsiApproved CECILL_2_1 = True-licenseIsOsiApproved CNRI_Python = True-licenseIsOsiApproved CPAL_1_0 = True-licenseIsOsiApproved CPL_1_0 = True-licenseIsOsiApproved CUA_OPL_1_0 = True-licenseIsOsiApproved ECL_1_0 = True-licenseIsOsiApproved ECL_2_0 = True-licenseIsOsiApproved EFL_1_0 = True-licenseIsOsiApproved EFL_2_0 = True-licenseIsOsiApproved Entessa = True-licenseIsOsiApproved EPL_1_0 = True-licenseIsOsiApproved EPL_2_0 = True-licenseIsOsiApproved EUDatagrid = True-licenseIsOsiApproved EUPL_1_1 = True-licenseIsOsiApproved EUPL_1_2 = True-licenseIsOsiApproved Fair = True-licenseIsOsiApproved Frameworx_1_0 = True-licenseIsOsiApproved GPL_2_0_only = True-licenseIsOsiApproved GPL_2_0_or_later = True-licenseIsOsiApproved GPL_3_0_only = True-licenseIsOsiApproved GPL_3_0_or_later = True-licenseIsOsiApproved HPND = True-licenseIsOsiApproved Intel = True-licenseIsOsiApproved IPA = True-licenseIsOsiApproved IPL_1_0 = True-licenseIsOsiApproved ISC = True-licenseIsOsiApproved LGPL_2_0_only = True-licenseIsOsiApproved LGPL_2_0_or_later = True-licenseIsOsiApproved LGPL_2_1_only = True-licenseIsOsiApproved LGPL_2_1_or_later = True-licenseIsOsiApproved LGPL_3_0_only = True-licenseIsOsiApproved LGPL_3_0_or_later = True-licenseIsOsiApproved LiLiQ_P_1_1 = True-licenseIsOsiApproved LiLiQ_R_1_1 = True-licenseIsOsiApproved LiLiQ_Rplus_1_1 = True-licenseIsOsiApproved LPL_1_02 = True-licenseIsOsiApproved LPL_1_0 = True-licenseIsOsiApproved LPPL_1_3c = True-licenseIsOsiApproved MirOS = True-licenseIsOsiApproved MIT = True-licenseIsOsiApproved Motosoto = True-licenseIsOsiApproved MPL_1_0 = True-licenseIsOsiApproved MPL_1_1 = True-licenseIsOsiApproved MPL_2_0_no_copyleft_exception = True-licenseIsOsiApproved MPL_2_0 = True-licenseIsOsiApproved MS_PL = True-licenseIsOsiApproved MS_RL = True-licenseIsOsiApproved MulanPSL_2_0 = True-licenseIsOsiApproved Multics = True-licenseIsOsiApproved NASA_1_3 = True-licenseIsOsiApproved Naumen = True-licenseIsOsiApproved NCSA = True-licenseIsOsiApproved NGPL = True-licenseIsOsiApproved Nokia = True-licenseIsOsiApproved NPOSL_3_0 = True-licenseIsOsiApproved NTP = True-licenseIsOsiApproved OCLC_2_0 = True-licenseIsOsiApproved OFL_1_1_no_RFN = True-licenseIsOsiApproved OFL_1_1_RFN = True-licenseIsOsiApproved OFL_1_1 = True-licenseIsOsiApproved OGTSL = True-licenseIsOsiApproved OSET_PL_2_1 = True-licenseIsOsiApproved OSL_1_0 = True-licenseIsOsiApproved OSL_2_0 = True-licenseIsOsiApproved OSL_2_1 = True-licenseIsOsiApproved OSL_3_0 = True-licenseIsOsiApproved PHP_3_0 = True-licenseIsOsiApproved PostgreSQL = True-licenseIsOsiApproved Python_2_0 = True-licenseIsOsiApproved QPL_1_0 = True-licenseIsOsiApproved RPL_1_1 = True-licenseIsOsiApproved RPL_1_5 = True-licenseIsOsiApproved RPSL_1_0 = True-licenseIsOsiApproved RSCPL = True-licenseIsOsiApproved SimPL_2_0 = True-licenseIsOsiApproved SISSL = True-licenseIsOsiApproved Sleepycat = True-licenseIsOsiApproved SPL_1_0 = True-licenseIsOsiApproved UCL_1_0 = True-licenseIsOsiApproved UPL_1_0 = True-licenseIsOsiApproved VSL_1_0 = True-licenseIsOsiApproved W3C = True-licenseIsOsiApproved Watcom_1_0 = True-licenseIsOsiApproved Xnet = True-licenseIsOsiApproved Zlib = True-licenseIsOsiApproved ZPL_2_0 = True-licenseIsOsiApproved _ = False---- | Whether the license is considered libre by Free Software Foundation (FSF).------ See <https://www.gnu.org/licenses/license-list.en.html>------ @since 3.4.0.0----licenseIsFsfLibre :: LicenseId -> Bool-licenseIsFsfLibre AFL_1_1 = True-licenseIsFsfLibre AFL_1_2 = True-licenseIsFsfLibre AFL_2_0 = True-licenseIsFsfLibre AFL_2_1 = True-licenseIsFsfLibre AFL_3_0 = True-licenseIsFsfLibre AGPL_1_0 = True-licenseIsFsfLibre AGPL_3_0_only = True-licenseIsFsfLibre AGPL_3_0_or_later = True-licenseIsFsfLibre Apache_1_0 = True-licenseIsFsfLibre Apache_1_1 = True-licenseIsFsfLibre Apache_2_0 = True-licenseIsFsfLibre APSL_2_0 = True-licenseIsFsfLibre Artistic_2_0 = True-licenseIsFsfLibre BitTorrent_1_1 = True-licenseIsFsfLibre BSD_2_Clause_FreeBSD = True-licenseIsFsfLibre BSD_3_Clause_Clear = True-licenseIsFsfLibre BSD_3_Clause = True-licenseIsFsfLibre BSD_4_Clause = True-licenseIsFsfLibre BSL_1_0 = True-licenseIsFsfLibre CC_BY_4_0 = True-licenseIsFsfLibre CC_BY_SA_4_0 = True-licenseIsFsfLibre CC0_1_0 = True-licenseIsFsfLibre CDDL_1_0 = True-licenseIsFsfLibre CECILL_2_0 = True-licenseIsFsfLibre CECILL_B = True-licenseIsFsfLibre CECILL_C = True-licenseIsFsfLibre ClArtistic = True-licenseIsFsfLibre Condor_1_1 = True-licenseIsFsfLibre CPAL_1_0 = True-licenseIsFsfLibre CPL_1_0 = True-licenseIsFsfLibre ECL_2_0 = True-licenseIsFsfLibre EFL_2_0 = True-licenseIsFsfLibre EPL_1_0 = True-licenseIsFsfLibre EPL_2_0 = True-licenseIsFsfLibre EUDatagrid = True-licenseIsFsfLibre EUPL_1_1 = True-licenseIsFsfLibre EUPL_1_2 = True-licenseIsFsfLibre FSFAP = True-licenseIsFsfLibre FTL = True-licenseIsFsfLibre GFDL_1_1_only = True-licenseIsFsfLibre GFDL_1_1_or_later = True-licenseIsFsfLibre GFDL_1_2_only = True-licenseIsFsfLibre GFDL_1_2_or_later = True-licenseIsFsfLibre GFDL_1_3_only = True-licenseIsFsfLibre GFDL_1_3_or_later = True-licenseIsFsfLibre Gnuplot = True-licenseIsFsfLibre GPL_2_0_only = True-licenseIsFsfLibre GPL_2_0_or_later = True-licenseIsFsfLibre GPL_3_0_only = True-licenseIsFsfLibre GPL_3_0_or_later = True-licenseIsFsfLibre HPND = True-licenseIsFsfLibre IJG = True-licenseIsFsfLibre IMatix = True-licenseIsFsfLibre Imlib2 = True-licenseIsFsfLibre Intel = True-licenseIsFsfLibre IPA = True-licenseIsFsfLibre IPL_1_0 = True-licenseIsFsfLibre ISC = True-licenseIsFsfLibre LGPL_2_1_only = True-licenseIsFsfLibre LGPL_2_1_or_later = True-licenseIsFsfLibre LGPL_3_0_only = True-licenseIsFsfLibre LGPL_3_0_or_later = True-licenseIsFsfLibre LPL_1_02 = True-licenseIsFsfLibre LPPL_1_2 = True-licenseIsFsfLibre LPPL_1_3a = True-licenseIsFsfLibre MIT = True-licenseIsFsfLibre MPL_1_1 = True-licenseIsFsfLibre MPL_2_0 = True-licenseIsFsfLibre MS_PL = True-licenseIsFsfLibre MS_RL = True-licenseIsFsfLibre NCSA = True-licenseIsFsfLibre Nokia = True-licenseIsFsfLibre NOSL = True-licenseIsFsfLibre NPL_1_0 = True-licenseIsFsfLibre NPL_1_1 = True-licenseIsFsfLibre ODbL_1_0 = True-licenseIsFsfLibre OFL_1_0 = True-licenseIsFsfLibre OFL_1_1 = True-licenseIsFsfLibre OLDAP_2_3 = True-licenseIsFsfLibre OLDAP_2_7 = True-licenseIsFsfLibre OpenSSL = True-licenseIsFsfLibre OSL_1_0 = True-licenseIsFsfLibre OSL_1_1 = True-licenseIsFsfLibre OSL_2_0 = True-licenseIsFsfLibre OSL_2_1 = True-licenseIsFsfLibre OSL_3_0 = True-licenseIsFsfLibre PHP_3_01 = True-licenseIsFsfLibre Python_2_0 = True-licenseIsFsfLibre QPL_1_0 = True-licenseIsFsfLibre RPSL_1_0 = True-licenseIsFsfLibre Ruby = True-licenseIsFsfLibre SGI_B_2_0 = True-licenseIsFsfLibre SISSL = True-licenseIsFsfLibre Sleepycat = True-licenseIsFsfLibre SMLNJ = True-licenseIsFsfLibre SPL_1_0 = True-licenseIsFsfLibre Unlicense = True-licenseIsFsfLibre UPL_1_0 = True-licenseIsFsfLibre Vim = True-licenseIsFsfLibre W3C = True-licenseIsFsfLibre WTFPL = True-licenseIsFsfLibre X11 = True-licenseIsFsfLibre XFree86_1_1 = True-licenseIsFsfLibre Xinetd = True-licenseIsFsfLibre YPL_1_1 = True-licenseIsFsfLibre Zend_2_0 = True-licenseIsFsfLibre Zimbra_1_3 = True-licenseIsFsfLibre Zlib = True-licenseIsFsfLibre ZPL_2_0 = True-licenseIsFsfLibre ZPL_2_1 = True-licenseIsFsfLibre _ = False------------------------------------------------------------------------------------ Creation----------------------------------------------------------------------------------licenseIdList :: LicenseListVersion -> [LicenseId]-licenseIdList LicenseListVersion_3_0 =- [ AGPL_1_0- , BSD_2_Clause_NetBSD- ]- ++ bulkOfLicenses-licenseIdList LicenseListVersion_3_2 =- [ AGPL_1_0_only- , AGPL_1_0_or_later- , BSD_2_Clause_NetBSD- , Linux_OpenIB- , MIT_0- , ODC_By_1_0- , TU_Berlin_1_0- , TU_Berlin_2_0- ]- ++ bulkOfLicenses-licenseIdList LicenseListVersion_3_6 =- [ AGPL_1_0_only- , AGPL_1_0_or_later- , Blessing- , BlueOak_1_0_0- , BSD_2_Clause_NetBSD- , BSD_3_Clause_Open_MPI- , CC_PDDC- , CERN_OHL_1_1- , CERN_OHL_1_2- , Copyleft_next_0_3_0- , Copyleft_next_0_3_1- , HPND_sell_variant- , JPNIC- , Libpng_2_0- , Linux_OpenIB- , MIT_0- , ODC_By_1_0- , OGL_UK_1_0- , OGL_UK_2_0- , OGL_UK_3_0- , Parity_6_0_0- , Sendmail_8_23- , SHL_0_51- , SHL_0_5- , SSPL_1_0- , TAPR_OHL_1_0- , TU_Berlin_1_0- , TU_Berlin_2_0- ]- ++ bulkOfLicenses-licenseIdList LicenseListVersion_3_9 =- [ AGPL_1_0_only- , AGPL_1_0_or_later- , Blessing- , BlueOak_1_0_0- , BSD_3_Clause_Open_MPI- , CAL_1_0_Combined_Work_Exception- , CAL_1_0- , CC_PDDC- , CERN_OHL_1_1- , CERN_OHL_1_2- , CERN_OHL_P_2_0- , CERN_OHL_S_2_0- , CERN_OHL_W_2_0- , Copyleft_next_0_3_0- , Copyleft_next_0_3_1- , Etalab_2_0- , Hippocratic_2_1- , HPND_sell_variant- , JPNIC- , Libpng_2_0- , Libselinux_1_0- , Linux_OpenIB- , MIT_0- , MulanPSL_1_0- , MulanPSL_2_0- , NCGL_UK_2_0- , NTP_0- , O_UDA_1_0- , ODC_By_1_0- , OFL_1_0_no_RFN- , OFL_1_0_RFN- , OFL_1_1_no_RFN- , OFL_1_1_RFN- , OGC_1_0- , OGL_Canada_2_0- , OGL_UK_1_0- , OGL_UK_2_0- , OGL_UK_3_0- , Parity_6_0_0- , Parity_7_0_0- , PolyForm_Noncommercial_1_0_0- , PolyForm_Small_Business_1_0_0- , PSF_2_0- , Sendmail_8_23- , SHL_0_51- , SHL_0_5- , SSH_OpenSSH- , SSH_short- , SSPL_1_0- , TAPR_OHL_1_0- , TU_Berlin_1_0- , TU_Berlin_2_0- , UCL_1_0- ]- ++ bulkOfLicenses---- | Create a 'LicenseId' from a 'String'.-mkLicenseId :: LicenseListVersion -> String -> Maybe LicenseId-mkLicenseId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0-mkLicenseId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2-mkLicenseId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6-mkLicenseId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9--stringLookup_3_0 :: Map String LicenseId-stringLookup_3_0 = Map.fromList $ map (\i -> (licenseId i, i)) $- licenseIdList LicenseListVersion_3_0--stringLookup_3_2 :: Map String LicenseId-stringLookup_3_2 = Map.fromList $ map (\i -> (licenseId i, i)) $- licenseIdList LicenseListVersion_3_2--stringLookup_3_6 :: Map String LicenseId-stringLookup_3_6 = Map.fromList $ map (\i -> (licenseId i, i)) $- licenseIdList LicenseListVersion_3_6--stringLookup_3_9 :: Map String LicenseId-stringLookup_3_9 = Map.fromList $ map (\i -> (licenseId i, i)) $- licenseIdList LicenseListVersion_3_9---- | Licenses in all SPDX License lists-bulkOfLicenses :: [LicenseId]-bulkOfLicenses =- [ NullBSD- , AAL- , Abstyles- , Adobe_2006- , Adobe_Glyph- , ADSL- , AFL_1_1- , AFL_1_2- , AFL_2_0- , AFL_2_1- , AFL_3_0- , Afmparse- , AGPL_3_0_only- , AGPL_3_0_or_later- , Aladdin- , AMDPLPA- , AML- , AMPAS- , ANTLR_PD- , Apache_1_0- , Apache_1_1- , Apache_2_0- , APAFML- , APL_1_0- , APSL_1_0- , APSL_1_1- , APSL_1_2- , APSL_2_0- , Artistic_1_0_cl8- , Artistic_1_0_Perl- , Artistic_1_0- , Artistic_2_0- , Bahyph- , Barr- , Beerware- , BitTorrent_1_0- , BitTorrent_1_1- , Borceux- , BSD_1_Clause- , BSD_2_Clause_FreeBSD- , BSD_2_Clause_Patent- , BSD_2_Clause- , BSD_3_Clause_Attribution- , BSD_3_Clause_Clear- , BSD_3_Clause_LBNL- , BSD_3_Clause_No_Nuclear_License_2014- , BSD_3_Clause_No_Nuclear_License- , BSD_3_Clause_No_Nuclear_Warranty- , BSD_3_Clause- , BSD_4_Clause_UC- , BSD_4_Clause- , BSD_Protection- , BSD_Source_Code- , BSL_1_0- , Bzip2_1_0_5- , Bzip2_1_0_6- , Caldera- , CATOSL_1_1- , CC_BY_1_0- , CC_BY_2_0- , CC_BY_2_5- , CC_BY_3_0- , CC_BY_4_0- , CC_BY_NC_1_0- , CC_BY_NC_2_0- , CC_BY_NC_2_5- , CC_BY_NC_3_0- , CC_BY_NC_4_0- , CC_BY_NC_ND_1_0- , CC_BY_NC_ND_2_0- , CC_BY_NC_ND_2_5- , CC_BY_NC_ND_3_0- , CC_BY_NC_ND_4_0- , CC_BY_NC_SA_1_0- , CC_BY_NC_SA_2_0- , CC_BY_NC_SA_2_5- , CC_BY_NC_SA_3_0- , CC_BY_NC_SA_4_0- , CC_BY_ND_1_0- , CC_BY_ND_2_0- , CC_BY_ND_2_5- , CC_BY_ND_3_0- , CC_BY_ND_4_0- , CC_BY_SA_1_0- , CC_BY_SA_2_0- , CC_BY_SA_2_5- , CC_BY_SA_3_0- , CC_BY_SA_4_0- , CC0_1_0- , CDDL_1_0- , CDDL_1_1- , CDLA_Permissive_1_0- , CDLA_Sharing_1_0- , CECILL_1_0- , CECILL_1_1- , CECILL_2_0- , CECILL_2_1- , CECILL_B- , CECILL_C- , ClArtistic- , CNRI_Jython- , CNRI_Python_GPL_Compatible- , CNRI_Python- , Condor_1_1- , CPAL_1_0- , CPL_1_0- , CPOL_1_02- , Crossword- , CrystalStacker- , CUA_OPL_1_0- , Cube- , Curl- , D_FSL_1_0- , Diffmark- , DOC- , Dotseqn- , DSDP- , Dvipdfm- , ECL_1_0- , ECL_2_0- , EFL_1_0- , EFL_2_0- , EGenix- , Entessa- , EPL_1_0- , EPL_2_0- , ErlPL_1_1- , EUDatagrid- , EUPL_1_0- , EUPL_1_1- , EUPL_1_2- , Eurosym- , Fair- , Frameworx_1_0- , FreeImage- , FSFAP- , FSFULLR- , FSFUL- , FTL- , GFDL_1_1_only- , GFDL_1_1_or_later- , GFDL_1_2_only- , GFDL_1_2_or_later- , GFDL_1_3_only- , GFDL_1_3_or_later- , Giftware- , GL2PS- , Glide- , Glulxe- , Gnuplot- , GPL_1_0_only- , GPL_1_0_or_later- , GPL_2_0_only- , GPL_2_0_or_later- , GPL_3_0_only- , GPL_3_0_or_later- , GSOAP_1_3b- , HaskellReport- , HPND- , IBM_pibs- , ICU- , IJG- , ImageMagick- , IMatix- , Imlib2- , Info_ZIP- , Intel_ACPI- , Intel- , Interbase_1_0- , IPA- , IPL_1_0- , ISC- , JasPer_2_0- , JSON- , LAL_1_2- , LAL_1_3- , Latex2e- , Leptonica- , LGPL_2_0_only- , LGPL_2_0_or_later- , LGPL_2_1_only- , LGPL_2_1_or_later- , LGPL_3_0_only- , LGPL_3_0_or_later- , LGPLLR- , Libpng- , Libtiff- , LiLiQ_P_1_1- , LiLiQ_R_1_1- , LiLiQ_Rplus_1_1- , LPL_1_02- , LPL_1_0- , LPPL_1_0- , LPPL_1_1- , LPPL_1_2- , LPPL_1_3a- , LPPL_1_3c- , MakeIndex- , MirOS- , MIT_advertising- , MIT_CMU- , MIT_enna- , MIT_feh- , MITNFA- , MIT- , Motosoto- , Mpich2- , MPL_1_0- , MPL_1_1- , MPL_2_0_no_copyleft_exception- , MPL_2_0- , MS_PL- , MS_RL- , MTLL- , Multics- , Mup- , NASA_1_3- , Naumen- , NBPL_1_0- , NCSA- , Net_SNMP- , NetCDF- , Newsletr- , NGPL- , NLOD_1_0- , NLPL- , Nokia- , NOSL- , Noweb- , NPL_1_0- , NPL_1_1- , NPOSL_3_0- , NRL- , NTP- , OCCT_PL- , OCLC_2_0- , ODbL_1_0- , OFL_1_0- , OFL_1_1- , OGTSL- , OLDAP_1_1- , OLDAP_1_2- , OLDAP_1_3- , OLDAP_1_4- , OLDAP_2_0_1- , OLDAP_2_0- , OLDAP_2_1- , OLDAP_2_2_1- , OLDAP_2_2_2- , OLDAP_2_2- , OLDAP_2_3- , OLDAP_2_4- , OLDAP_2_5- , OLDAP_2_6- , OLDAP_2_7- , OLDAP_2_8- , OML- , OpenSSL- , OPL_1_0- , OSET_PL_2_1- , OSL_1_0- , OSL_1_1- , OSL_2_0- , OSL_2_1- , OSL_3_0- , PDDL_1_0- , PHP_3_01- , PHP_3_0- , Plexus- , PostgreSQL- , Psfrag- , Psutils- , Python_2_0- , Qhull- , QPL_1_0- , Rdisc- , RHeCos_1_1- , RPL_1_1- , RPL_1_5- , RPSL_1_0- , RSA_MD- , RSCPL- , Ruby- , SAX_PD- , Saxpath- , SCEA- , Sendmail- , SGI_B_1_0- , SGI_B_1_1- , SGI_B_2_0- , SimPL_2_0- , SISSL_1_2- , SISSL- , Sleepycat- , SMLNJ- , SMPPL- , SNIA- , Spencer_86- , Spencer_94- , Spencer_99- , SPL_1_0- , SugarCRM_1_1_3- , SWL- , TCL- , TCP_wrappers- , TMate- , TORQUE_1_1- , TOSL- , Unicode_DFS_2015- , Unicode_DFS_2016- , Unicode_TOU- , Unlicense- , UPL_1_0- , Vim- , VOSTROM- , VSL_1_0- , W3C_19980720- , W3C_20150513- , W3C- , Watcom_1_0- , Wsuipa- , WTFPL- , X11- , Xerox- , XFree86_1_1- , Xinetd- , Xnet- , Xpp- , XSkat- , YPL_1_0- , YPL_1_1- , Zed- , Zend_2_0- , Zimbra_1_3- , Zimbra_1_4- , Zlib_acknowledgement- , Zlib- , ZPL_1_1- , ZPL_2_0- , ZPL_2_1- ]
− Distribution/SPDX/LicenseListVersion.hs
@@ -1,20 +0,0 @@-module Distribution.SPDX.LicenseListVersion (- LicenseListVersion (..),- cabalSpecVersionToSPDXListVersion,- ) where--import Distribution.CabalSpecVersion---- | SPDX License List version @Cabal@ is aware of.-data LicenseListVersion- = LicenseListVersion_3_0- | LicenseListVersion_3_2- | LicenseListVersion_3_6- | LicenseListVersion_3_9- deriving (Eq, Ord, Show, Enum, Bounded)--cabalSpecVersionToSPDXListVersion :: CabalSpecVersion -> LicenseListVersion-cabalSpecVersionToSPDXListVersion CabalSpecV3_4 = LicenseListVersion_3_9-cabalSpecVersionToSPDXListVersion CabalSpecV3_0 = LicenseListVersion_3_6-cabalSpecVersionToSPDXListVersion CabalSpecV2_4 = LicenseListVersion_3_2-cabalSpecVersionToSPDXListVersion _ = LicenseListVersion_3_0
− Distribution/SPDX/LicenseReference.hs
@@ -1,80 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.SPDX.LicenseReference (- LicenseRef,- licenseRef,- licenseDocumentRef,- mkLicenseRef,- mkLicenseRef',- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Utils.Generic (isAsciiAlphaNum)-import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | A user defined license reference denoted by @LicenseRef-[idstring]@ (for a license not on the SPDX License List);-data LicenseRef = LicenseRef- { _lrDocument :: !(Maybe String)- , _lrLicense :: !String- }- deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)---- | License reference.-licenseRef :: LicenseRef -> String-licenseRef = _lrLicense---- | Document reference.-licenseDocumentRef :: LicenseRef -> Maybe String-licenseDocumentRef = _lrDocument--instance Binary LicenseRef-instance Structured LicenseRef--instance NFData LicenseRef where- rnf (LicenseRef d l) = rnf d `seq` rnf l--instance Pretty LicenseRef where- pretty (LicenseRef Nothing l) = Disp.text "LicenseRef-" <<>> Disp.text l- pretty (LicenseRef (Just d) l) =- Disp.text "DocumentRef-" <<>> Disp.text d <<>> Disp.char ':' <<>> Disp.text "LicenseRef-" <<>> Disp.text l--instance Parsec LicenseRef where- parsec = name <|> doc- where- name = do- _ <- P.string "LicenseRef-"- n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'- pure (LicenseRef Nothing n)-- doc = do- _ <- P.string "DocumentRef-"- d <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'- _ <- P.char ':'- _ <- P.string "LicenseRef-"- n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'- pure (LicenseRef (Just d) n)---- | Create 'LicenseRef' from optional document ref and name.-mkLicenseRef :: Maybe String -> String -> Maybe LicenseRef-mkLicenseRef d l = do- d' <- traverse checkIdString d- l' <- checkIdString l- pure (LicenseRef d' l')- where- checkIdString s- | all (\c -> isAsciiAlphaNum c || c == '-' || c == '.') s = Just s- | otherwise = Nothing---- | Like 'mkLicenseRef' but convert invalid characters into @-@.-mkLicenseRef' :: Maybe String -> String -> LicenseRef-mkLicenseRef' d l = LicenseRef (fmap f d) (f l)- where- f = map g- g c | isAsciiAlphaNum c || c == '-' || c == '.' = c- | otherwise = '-'
− Distribution/Simple.hs
@@ -1,855 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE CPP #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Simple--- Copyright : Isaac Jones 2003-2005--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is the command line front end to the Simple build system. When given--- the parsed command-line args and package information, is able to perform--- basic commands like configure, build, install, register, etc.------ This module exports the main functions that Setup.hs scripts use. It--- re-exports the 'UserHooks' type, the standard entry points like--- 'defaultMain' and 'defaultMainWithHooks' and the predefined sets of--- 'UserHooks' that custom @Setup.hs@ scripts can extend to add their own--- behaviour.------ This module isn't called \"Simple\" because it's simple. Far from--- it. It's called \"Simple\" because it does complicated things to--- simple software.------ The original idea was that there could be different build systems that all--- presented the same compatible command line interfaces. There is still a--- "Distribution.Make" system but in practice no packages use it.--{--Work around this warning:-libraries/Cabal/Distribution/Simple.hs:78:0:- Warning: In the use of `runTests'- (imported from Distribution.Simple.UserHooks):- Deprecated: "Please use the new testing interface instead!"--}-{-# OPTIONS_GHC -fno-warn-deprecations #-}--module Distribution.Simple (- module Distribution.Package,- module Distribution.Version,- module Distribution.License,- module Distribution.Simple.Compiler,- module Language.Haskell.Extension,- -- * Simple interface- defaultMain, defaultMainNoRead, defaultMainArgs,- -- * Customization- UserHooks(..), Args,- defaultMainWithHooks, defaultMainWithHooksArgs,- defaultMainWithHooksNoRead, defaultMainWithHooksNoReadArgs,- -- ** Standard sets of hooks- simpleUserHooks,- autoconfUserHooks,- emptyUserHooks,- ) where--import Control.Exception (try)--import Prelude ()-import Distribution.Compat.Prelude---- local-import Distribution.Simple.Compiler-import Distribution.Simple.UserHooks-import Distribution.Package-import Distribution.PackageDescription-import Distribution.PackageDescription.Configuration-import Distribution.Simple.Program-import Distribution.Simple.Program.Db-import Distribution.Simple.PreProcess-import Distribution.Simple.Setup-import Distribution.Simple.Command--import Distribution.Simple.Build-import Distribution.Simple.SrcDist-import Distribution.Simple.Register--import Distribution.Simple.Configure--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.Doctest-import Distribution.Simple.Utils-import Distribution.Utils.NubList-import Distribution.Verbosity-import Language.Haskell.Extension-import Distribution.Version-import Distribution.License-import Distribution.Pretty-import Distribution.System (buildPlatform)---- Base-import System.Environment (getArgs, getProgName)-import System.Directory (removeFile, doesFileExist- ,doesDirectoryExist, removeDirectoryRecursive)-import System.FilePath (searchPathSeparator, takeDirectory, (</>),- splitDirectories, dropDrive)-#ifdef mingw32_HOST_OS-import System.FilePath (normalise, splitDrive)-#endif-import Distribution.Compat.ResponseFile (expandResponse)-import Distribution.Compat.Directory (makeAbsolute)-import Distribution.Compat.Environment (getEnvironment)-import Distribution.Compat.GetShortPathName (getShortPathName)--import Data.List (unionBy, (\\))--import Distribution.PackageDescription.Parsec---- | A simple implementation of @main@ for a Cabal setup script.--- It reads the package description file using IO, and performs the--- action specified on the command line.-defaultMain :: IO ()-defaultMain = getArgs >>= defaultMainHelper simpleUserHooks---- | A version of 'defaultMain' that is passed the command line--- arguments, rather than getting them from the environment.-defaultMainArgs :: [String] -> IO ()-defaultMainArgs = defaultMainHelper simpleUserHooks---- | A customizable version of 'defaultMain'.-defaultMainWithHooks :: UserHooks -> IO ()-defaultMainWithHooks hooks = getArgs >>= defaultMainHelper hooks---- | A customizable version of 'defaultMain' that also takes the command--- line arguments.-defaultMainWithHooksArgs :: UserHooks -> [String] -> IO ()-defaultMainWithHooksArgs = defaultMainHelper---- | Like 'defaultMain', but accepts the package description as input--- rather than using IO to read it.-defaultMainNoRead :: GenericPackageDescription -> IO ()-defaultMainNoRead = defaultMainWithHooksNoRead simpleUserHooks---- | A customizable version of 'defaultMainNoRead'.-defaultMainWithHooksNoRead :: UserHooks -> GenericPackageDescription -> IO ()-defaultMainWithHooksNoRead hooks pkg_descr =- getArgs >>=- defaultMainHelper hooks { readDesc = return (Just pkg_descr) }---- | A customizable version of 'defaultMainNoRead' that also takes the--- command line arguments.------ @since 2.2.0.0-defaultMainWithHooksNoReadArgs :: UserHooks -> GenericPackageDescription -> [String] -> IO ()-defaultMainWithHooksNoReadArgs hooks pkg_descr =- defaultMainHelper hooks { readDesc = return (Just pkg_descr) }--defaultMainHelper :: UserHooks -> Args -> IO ()-defaultMainHelper hooks args = topHandler $ do- args' <- expandResponse args- case commandsRun (globalCommand commands) commands args' of- CommandHelp help -> printHelp help- CommandList opts -> printOptionsList opts- CommandErrors errs -> printErrors errs- CommandReadyToGo (flags, commandParse) ->- case commandParse of- _ | fromFlag (globalVersion flags) -> printVersion- | fromFlag (globalNumericVersion flags) -> printNumericVersion- CommandHelp help -> printHelp help- CommandList opts -> printOptionsList opts- CommandErrors errs -> printErrors errs- CommandReadyToGo action -> action-- where- printHelp help = getProgName >>= putStr . help- printOptionsList = putStr . unlines- printErrors errs = do- putStr (intercalate "\n" errs)- exitWith (ExitFailure 1)- printNumericVersion = putStrLn $ prettyShow cabalVersion- printVersion = putStrLn $ "Cabal library version "- ++ prettyShow cabalVersion-- progs = addKnownPrograms (hookedPrograms hooks) defaultProgramDb- commands =- [configureCommand progs `commandAddAction`- \fs as -> configureAction hooks fs as >> return ()- ,buildCommand progs `commandAddAction` buildAction hooks- ,showBuildInfoCommand progs `commandAddAction` showBuildInfoAction hooks- ,replCommand progs `commandAddAction` replAction hooks- ,installCommand `commandAddAction` installAction hooks- ,copyCommand `commandAddAction` copyAction hooks- ,doctestCommand `commandAddAction` doctestAction hooks- ,haddockCommand `commandAddAction` haddockAction hooks- ,cleanCommand `commandAddAction` cleanAction hooks- ,sdistCommand `commandAddAction` sdistAction hooks- ,hscolourCommand `commandAddAction` hscolourAction hooks- ,registerCommand `commandAddAction` registerAction hooks- ,unregisterCommand `commandAddAction` unregisterAction hooks- ,testCommand `commandAddAction` testAction hooks- ,benchmarkCommand `commandAddAction` benchAction hooks- ]---- | Combine the preprocessors in the given hooks with the--- preprocessors built into cabal.-allSuffixHandlers :: UserHooks- -> [PPSuffixHandler]-allSuffixHandlers hooks- = overridesPP (hookedPreProcessors hooks) knownSuffixHandlers- where- overridesPP :: [PPSuffixHandler] -> [PPSuffixHandler] -> [PPSuffixHandler]- overridesPP = unionBy (\x y -> fst x == fst y)--configureAction :: UserHooks -> ConfigFlags -> Args -> IO LocalBuildInfo-configureAction hooks flags args = do- distPref <- findDistPrefOrDefault (configDistPref flags)- let flags' = flags { configDistPref = toFlag distPref- , configArgs = args }-- -- See docs for 'HookedBuildInfo'- pbi <- preConf hooks args flags'-- (mb_pd_file, pkg_descr0) <- confPkgDescr hooks verbosity- (flagToMaybe (configCabalFilePath flags))-- let epkg_descr = (pkg_descr0, pbi)-- 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-- let pkg_descr = localPkgDescr localbuildinfo- postConf hooks args flags' pkg_descr localbuildinfo- return localbuildinfo- where- verbosity = fromFlag (configVerbosity flags)--confPkgDescr :: UserHooks -> Verbosity -> Maybe FilePath- -> IO (Maybe FilePath, GenericPackageDescription)-confPkgDescr hooks verbosity mb_path = do- mdescr <- readDesc hooks- case mdescr of- Just descr -> return (Nothing, descr)- Nothing -> do- pdfile <- case mb_path of- Nothing -> defaultPackageDesc verbosity- Just path -> return path- info verbosity "Using Parsec parser"- descr <- readGenericPackageDescription verbosity pdfile- return (Just pdfile, descr)--buildAction :: UserHooks -> BuildFlags -> Args -> IO ()-buildAction hooks flags args = do- distPref <- findDistPrefOrDefault (buildDistPref flags)- let verbosity = fromFlag $ buildVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { buildDistPref = toFlag distPref- , buildCabalFilePath = maybeToFlag (cabalFilePath lbi)}-- progs <- reconfigurePrograms verbosity- (buildProgramPaths flags')- (buildProgramArgs flags')- (withPrograms lbi)-- hookedAction verbosity preBuild buildHook postBuild- (return lbi { withPrograms = progs })- hooks flags' { buildArgs = args } args--showBuildInfoAction :: UserHooks -> ShowBuildInfoFlags -> Args -> IO ()-showBuildInfoAction hooks (ShowBuildInfoFlags flags fileOutput) args = do- distPref <- findDistPrefOrDefault (buildDistPref flags)- let verbosity = fromFlag $ buildVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { buildDistPref = toFlag distPref- , buildCabalFilePath = maybeToFlag (cabalFilePath lbi)- }-- progs <- reconfigurePrograms verbosity- (buildProgramPaths flags')- (buildProgramArgs flags')- (withPrograms lbi)-- pbi <- preBuild hooks args flags'- let lbi' = lbi { withPrograms = progs }- pkg_descr0 = localPkgDescr lbi'- pkg_descr = updatePackageDescription pbi pkg_descr0- -- TODO: Somehow don't ignore build hook?- buildInfoString <- showBuildInfo pkg_descr lbi' flags-- case fileOutput of- Nothing -> putStr buildInfoString- Just fp -> writeFile fp buildInfoString-- postBuild hooks args flags' pkg_descr lbi'--replAction :: UserHooks -> ReplFlags -> Args -> IO ()-replAction hooks flags args = do- 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')- (withPrograms lbi)-- -- As far as I can tell, the only reason this doesn't use- -- 'hookedActionWithArgs' is because the arguments of 'replHook'- -- takes the args explicitly. UGH. -- ezyang- pbi <- preRepl hooks args flags'- let pkg_descr0 = localPkgDescr lbi- sanityCheckHookedBuildInfo verbosity pkg_descr0 pbi- let pkg_descr = updatePackageDescription pbi pkg_descr0- lbi' = lbi { withPrograms = progs- , localPkgDescr = pkg_descr }- 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- distPref <- findDistPrefOrDefault (hscolourDistPref flags)- let verbosity = fromFlag $ hscolourVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { hscolourDistPref = toFlag distPref- , hscolourCabalFilePath = maybeToFlag (cabalFilePath lbi)}-- hookedAction verbosity preHscolour hscolourHook postHscolour- (getBuildConfig hooks verbosity distPref)- hooks flags' args--doctestAction :: UserHooks -> DoctestFlags -> Args -> IO ()-doctestAction hooks flags args = do- distPref <- findDistPrefOrDefault (doctestDistPref flags)- let verbosity = fromFlag $ doctestVerbosity flags- flags' = flags { doctestDistPref = toFlag distPref }-- lbi <- getBuildConfig hooks verbosity distPref- progs <- reconfigurePrograms verbosity- (doctestProgramPaths flags')- (doctestProgramArgs flags')- (withPrograms lbi)-- hookedAction verbosity preDoctest doctestHook postDoctest- (return lbi { withPrograms = progs })- hooks flags' args--haddockAction :: UserHooks -> HaddockFlags -> Args -> IO ()-haddockAction hooks flags args = do- distPref <- findDistPrefOrDefault (haddockDistPref flags)- let verbosity = fromFlag $ haddockVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { haddockDistPref = toFlag distPref- , haddockCabalFilePath = maybeToFlag (cabalFilePath lbi)}-- progs <- reconfigurePrograms verbosity- (haddockProgramPaths flags')- (haddockProgramArgs flags')- (withPrograms lbi)-- hookedAction verbosity preHaddock haddockHook postHaddock- (return lbi { withPrograms = progs })- hooks flags' { haddockArgs = args } args--cleanAction :: UserHooks -> CleanFlags -> Args -> IO ()-cleanAction hooks flags args = do- distPref <- findDistPrefOrDefault (cleanDistPref flags)-- elbi <- tryGetBuildConfig hooks verbosity distPref- let flags' = flags { cleanDistPref = toFlag distPref- , cleanCabalFilePath = case elbi of- Left _ -> mempty- Right lbi -> maybeToFlag (cabalFilePath lbi)}-- pbi <- preClean hooks args flags'-- (_, ppd) <- confPkgDescr hooks verbosity Nothing- -- It might seem like we are doing something clever here- -- but we're really not: if you look at the implementation- -- of 'clean' in the end all the package description is- -- used for is to clear out @extra-tmp-files@. IMO,- -- the configure script goo should go into @dist@ too!- -- -- ezyang- let pkg_descr0 = flattenPackageDescription ppd- -- We don't sanity check for clean as an error- -- here would prevent cleaning:- --sanityCheckHookedBuildInfo verbosity 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- distPref <- findDistPrefOrDefault (copyDistPref flags)- let verbosity = fromFlag $ copyVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { copyDistPref = toFlag distPref- , copyCabalFilePath = maybeToFlag (cabalFilePath lbi)}- hookedAction verbosity preCopy copyHook postCopy- (getBuildConfig hooks verbosity distPref)- hooks flags' { copyArgs = args } args--installAction :: UserHooks -> InstallFlags -> Args -> IO ()-installAction hooks flags args = do- distPref <- findDistPrefOrDefault (installDistPref flags)- let verbosity = fromFlag $ installVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { installDistPref = toFlag distPref- , installCabalFilePath = maybeToFlag (cabalFilePath lbi)}- hookedAction verbosity preInst instHook postInst- (getBuildConfig hooks verbosity distPref)- hooks flags' args---- Since Cabal-3.4 UserHooks are completely ignored-sdistAction :: UserHooks -> SDistFlags -> Args -> IO ()-sdistAction _hooks flags _args = do- (_, ppd) <- confPkgDescr emptyUserHooks verbosity Nothing- let pkg_descr = flattenPackageDescription ppd- sdist pkg_descr flags srcPref knownSuffixHandlers- where- verbosity = fromFlag (sDistVerbosity flags)--testAction :: UserHooks -> TestFlags -> Args -> IO ()-testAction hooks flags args = do- distPref <- findDistPrefOrDefault (testDistPref flags)- let verbosity = fromFlag $ testVerbosity flags- flags' = flags { testDistPref = toFlag distPref }-- hookedActionWithArgs verbosity preTest testHook postTest- (getBuildConfig hooks verbosity distPref)- hooks flags' args--benchAction :: UserHooks -> BenchmarkFlags -> Args -> IO ()-benchAction hooks flags args = do- distPref <- findDistPrefOrDefault (benchmarkDistPref flags)- let verbosity = fromFlag $ benchmarkVerbosity flags- flags' = flags { benchmarkDistPref = toFlag distPref }- hookedActionWithArgs verbosity preBench benchHook postBench- (getBuildConfig hooks verbosity distPref)- hooks flags' args--registerAction :: UserHooks -> RegisterFlags -> Args -> IO ()-registerAction hooks flags args = do- distPref <- findDistPrefOrDefault (regDistPref flags)- let verbosity = fromFlag $ regVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { regDistPref = toFlag distPref- , regCabalFilePath = maybeToFlag (cabalFilePath lbi)}- hookedAction verbosity preReg regHook postReg- (getBuildConfig hooks verbosity distPref)- hooks flags' { regArgs = args } args--unregisterAction :: UserHooks -> RegisterFlags -> Args -> IO ()-unregisterAction hooks flags args = do- distPref <- findDistPrefOrDefault (regDistPref flags)- let verbosity = fromFlag $ regVerbosity flags- lbi <- getBuildConfig hooks verbosity distPref- let flags' = flags { regDistPref = toFlag distPref- , regCabalFilePath = maybeToFlag (cabalFilePath lbi)}- hookedAction verbosity preUnreg unregHook postUnreg- (getBuildConfig hooks verbosity distPref)- hooks flags' args--hookedAction- :: Verbosity- -> (UserHooks -> Args -> flags -> IO HookedBuildInfo)- -> (UserHooks -> PackageDescription -> LocalBuildInfo- -> UserHooks -> flags -> IO ())- -> (UserHooks -> Args -> flags -> PackageDescription- -> LocalBuildInfo -> IO ())- -> IO LocalBuildInfo- -> UserHooks -> flags -> Args -> IO ()-hookedAction verbosity pre_hook cmd_hook =- hookedActionWithArgs verbosity pre_hook- (\h _ pd lbi uh flags ->- cmd_hook h pd lbi uh flags)--hookedActionWithArgs- :: Verbosity- -> (UserHooks -> Args -> flags -> IO HookedBuildInfo)- -> (UserHooks -> Args -> PackageDescription -> LocalBuildInfo- -> UserHooks -> flags -> IO ())- -> (UserHooks -> Args -> flags -> PackageDescription- -> LocalBuildInfo -> IO ())- -> IO LocalBuildInfo- -> UserHooks -> flags -> Args -> IO ()-hookedActionWithArgs verbosity pre_hook cmd_hook post_hook- get_build_config hooks flags args = do- pbi <- pre_hook hooks args flags- lbi0 <- get_build_config- let pkg_descr0 = localPkgDescr lbi0- sanityCheckHookedBuildInfo verbosity pkg_descr0 pbi- let pkg_descr = updatePackageDescription pbi pkg_descr0- lbi = lbi0 { localPkgDescr = pkg_descr }- cmd_hook hooks args pkg_descr lbi hooks flags- post_hook hooks args flags pkg_descr lbi--sanityCheckHookedBuildInfo- :: Verbosity -> PackageDescription -> HookedBuildInfo -> IO ()-sanityCheckHookedBuildInfo verbosity- (PackageDescription { library = Nothing }) (Just _,_)- = die' verbosity $ "The buildinfo contains info for a library, "- ++ "but the package does not have a library."--sanityCheckHookedBuildInfo verbosity pkg_descr (_, hookExes)- | exe1 : _ <- nonExistant- = die' verbosity $ "The buildinfo contains info for an executable called '"- ++ prettyShow exe1 ++ "' but the package does not have a "- ++ "executable with that name."- where- pkgExeNames = nub (map exeName (executables pkg_descr))- hookExeNames = nub (map fst hookExes)- nonExistant = hookExeNames \\ pkgExeNames--sanityCheckHookedBuildInfo _ _ _ = return ()---- | Try to read the 'localBuildInfoFile'-tryGetBuildConfig :: UserHooks -> Verbosity -> FilePath- -> IO (Either ConfigStateFileError LocalBuildInfo)-tryGetBuildConfig u v = try . getBuildConfig u v----- | Read the 'localBuildInfoFile' or throw an exception.-getBuildConfig :: UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfo-getBuildConfig hooks verbosity distPref = do- lbi_wo_programs <- getPersistBuildConfig distPref- -- Restore info about unconfigured programs, since it is not serialized- let lbi = lbi_wo_programs {- withPrograms = restoreProgramDb- (builtinPrograms ++ hookedPrograms hooks)- (withPrograms lbi_wo_programs)- }-- case pkgDescrFile lbi of- Nothing -> return lbi- Just pkg_descr_file -> do- outdated <- checkPersistBuildConfigOutdated distPref pkg_descr_file- if outdated- then reconfigure pkg_descr_file lbi- else return lbi-- where- reconfigure :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo- reconfigure pkg_descr_file lbi = do- notice verbosity $ pkg_descr_file ++ " has been changed. "- ++ "Re-configuring with most recently used options. "- ++ "If this fails, please run configure manually.\n"- let cFlags = configFlags lbi- let cFlags' = cFlags {- -- 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_ = fmap (restoreProgramDb- (builtinPrograms ++ hookedPrograms hooks))- `fmap` configPrograms_ cFlags,-- -- Use the current, not saved verbosity level:- configVerbosity = Flag verbosity- }- configureAction hooks cFlags' (extraConfigArgs lbi)----- ----------------------------------------------------------------------------- Cleaning--clean :: PackageDescription -> CleanFlags -> IO ()-clean pkg_descr flags = do- let distPref = fromFlagOrDefault defaultDistPref $ cleanDistPref flags- notice verbosity "cleaning..."-- maybeConfig <- if fromFlag (cleanSaveConf flags)- then maybeGetPersistBuildConfig distPref- else return Nothing-- -- remove the whole dist/ directory rather than tracking exactly what files- -- we created in there.- chattyTry "removing dist/" $ do- exists <- doesDirectoryExist distPref- when exists (removeDirectoryRecursive distPref)-- -- Any extra files the user wants to remove- traverse_ removeFileOrDirectory (extraTmpFiles pkg_descr)-- -- If the user wanted to save the config, write it back- traverse_ (writePersistBuildConfig distPref) maybeConfig-- where- removeFileOrDirectory :: FilePath -> IO ()- removeFileOrDirectory fname = do- isDir <- doesDirectoryExist fname- isFile <- doesFileExist fname- if isDir then removeDirectoryRecursive fname- else when isFile $ removeFile fname- verbosity = fromFlag (cleanVerbosity flags)---- ----------------------------------------------------------------------------- Default hooks---- | Hooks that correspond to a plain instantiation of the--- \"simple\" build system-simpleUserHooks :: UserHooks-simpleUserHooks =- emptyUserHooks {- confHook = configure,- postConf = finalChecks,- buildHook = defaultBuildHook,- replHook = defaultReplHook,- copyHook = \desc lbi _ f -> install desc lbi f,- -- 'install' has correct 'copy' behavior with params- testHook = defaultTestHook,- benchHook = defaultBenchHook,- instHook = defaultInstallHook,- cleanHook = \p _ _ f -> clean p f,- hscolourHook = \p l h f -> hscolour p l (allSuffixHandlers h) f,- haddockHook = \p l h f -> haddock p l (allSuffixHandlers h) f,- doctestHook = \p l h f -> doctest p l (allSuffixHandlers h) f,- regHook = defaultRegHook,- unregHook = \p l _ f -> unregister p l f- }- where- finalChecks _args flags pkg_descr lbi =- checkForeignDeps pkg_descr lbi (lessVerbose verbosity)- where- verbosity = fromFlag (configVerbosity flags)---- | Basic autoconf 'UserHooks':------ * 'postConf' runs @.\/configure@, if present.------ * the pre-hooks 'preBuild', 'preClean', 'preCopy', 'preInst',--- 'preReg' and 'preUnreg' read additional build information from--- /package/@.buildinfo@, if present.------ Thus @configure@ can use local system information to generate--- /package/@.buildinfo@ and possibly other files.--autoconfUserHooks :: UserHooks-autoconfUserHooks- = simpleUserHooks- {- postConf = defaultPostConf,- preBuild = readHookWithArgs buildVerbosity buildDistPref, -- buildCabalFilePath,- preCopy = readHookWithArgs copyVerbosity copyDistPref,- preClean = readHook cleanVerbosity cleanDistPref,- preInst = readHook installVerbosity installDistPref,- preHscolour = readHook hscolourVerbosity hscolourDistPref,- preHaddock = readHookWithArgs haddockVerbosity haddockDistPref,- preReg = readHook regVerbosity regDistPref,- preUnreg = readHook regVerbosity regDistPref- }- where defaultPostConf :: Args -> ConfigFlags -> PackageDescription- -> LocalBuildInfo -> IO ()- defaultPostConf args flags pkg_descr lbi- = do let verbosity = fromFlag (configVerbosity flags)- baseDir lbi' = fromMaybe ""- (takeDirectory <$> cabalFilePath lbi')- confExists <- doesFileExist $ (baseDir lbi) </> "configure"- if confExists- then runConfigureScript verbosity- backwardsCompatHack flags lbi- else die' verbosity "configure script not found."-- pbi <- getHookedBuildInfo verbosity (buildDir lbi)- sanityCheckHookedBuildInfo verbosity pkg_descr pbi- let pkg_descr' = updatePackageDescription pbi pkg_descr- lbi' = lbi { localPkgDescr = pkg_descr' }- postConf simpleUserHooks args flags pkg_descr' lbi'-- backwardsCompatHack = False-- readHookWithArgs :: (a -> Flag Verbosity)- -> (a -> Flag FilePath)- -> Args -> a- -> IO HookedBuildInfo- readHookWithArgs get_verbosity get_dist_pref _ flags = do- dist_dir <- findDistPrefOrDefault (get_dist_pref flags)- getHookedBuildInfo verbosity (dist_dir </> "build")- where- verbosity = fromFlag (get_verbosity flags)-- readHook :: (a -> Flag Verbosity)- -> (a -> Flag FilePath)- -> Args -> a -> IO HookedBuildInfo- readHook get_verbosity get_dist_pref a flags = do- noExtraFlags a- dist_dir <- findDistPrefOrDefault (get_dist_pref flags)- getHookedBuildInfo verbosity (dist_dir </> "build")- where- verbosity = fromFlag (get_verbosity flags)--runConfigureScript :: Verbosity -> Bool -> ConfigFlags -> LocalBuildInfo- -> IO ()-runConfigureScript verbosity backwardsCompatHack flags lbi = do- env <- getEnvironment- let programDb = withPrograms lbi- (ccProg, ccFlags) <- configureCCompiler verbosity programDb- 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- configureFile <- makeAbsolute $- fromMaybe "." (takeDirectory <$> cabalFilePath lbi) </> "configure"- -- autoconf is fussy about filenames, and has a set of forbidden- -- characters that can't appear in the build directory, etc:- -- https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions- --- -- This has caused hard-to-debug failures in the past (#5368), so we- -- detect some cases early and warn with a clear message. Windows's- -- use of backslashes is problematic here, so we'll switch to- -- slashes, but we do still want to fail on backslashes in POSIX- -- paths.- --- -- TODO: We don't check for colons, tildes or leading dashes. We- -- also should check the builddir's path, destdir, and all other- -- paths as well.- let configureFile' = toUnix configureFile- for_ badAutoconfCharacters $ \(c, cname) ->- when (c `elem` dropDrive configureFile') $- warn verbosity $ concat- [ "The path to the './configure' script, '", configureFile'- , "', contains the character '", [c], "' (", cname, ")."- , " This may cause the script to fail with an obscure error, or for"- , " building the package to fail later."- ]-- 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)]- hp = hostPlatform lbi- maybeHostFlag = if hp == buildPlatform then [] else ["--host=" ++ show (pretty hp)]- args' = configureFile':args ++ ["CC=" ++ ccProgShort] ++ maybeHostFlag- 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')- { progInvokeCwd = Just (buildDir lbi) }- Nothing -> die' verbosity notFoundMsg- where- args = configureArgs backwardsCompatHack flags-- 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."---- | Convert Windows path to Unix ones-toUnix :: String -> String-#ifdef mingw32_HOST_OS-toUnix s = let tmp = normalise s- (l, rest) = case splitDrive tmp of- ([], x) -> ("/" , x)- (h:_, x) -> ('/':h:"/", x)- parts = splitDirectories rest- in l ++ intercalate "/" parts-#else-toUnix s = intercalate "/" $ splitDirectories s-#endif--badAutoconfCharacters :: [(Char, String)]-badAutoconfCharacters =- [ (' ', "space")- , ('\t', "tab")- , ('\n', "newline")- , ('\0', "null")- , ('"', "double quote")- , ('#', "hash")- , ('$', "dollar sign")- , ('&', "ampersand")- , ('\'', "single quote")- , ('(', "left bracket")- , (')', "right bracket")- , ('*', "star")- , (';', "semicolon")- , ('<', "less-than sign")- , ('=', "equals sign")- , ('>', "greater-than sign")- , ('?', "question mark")- , ('[', "left square bracket")- , ('\\', "backslash")- , ('`', "backtick")- , ('|', "pipe")- ]--getHookedBuildInfo :: Verbosity -> FilePath -> IO HookedBuildInfo-getHookedBuildInfo verbosity build_dir = do- maybe_infoFile <- findHookedPackageDesc verbosity build_dir- case maybe_infoFile of- Nothing -> return emptyHookedBuildInfo- Just infoFile -> do- info verbosity $ "Reading parameters from " ++ infoFile- readHookedBuildInfo verbosity infoFile--defaultTestHook :: Args -> PackageDescription -> LocalBuildInfo- -> UserHooks -> TestFlags -> IO ()-defaultTestHook args pkg_descr localbuildinfo _ flags =- test args pkg_descr localbuildinfo flags--defaultBenchHook :: Args -> PackageDescription -> LocalBuildInfo- -> UserHooks -> BenchmarkFlags -> IO ()-defaultBenchHook args pkg_descr localbuildinfo _ flags =- bench args pkg_descr localbuildinfo flags--defaultInstallHook :: PackageDescription -> LocalBuildInfo- -> UserHooks -> InstallFlags -> IO ()-defaultInstallHook pkg_descr localbuildinfo _ flags = do- let copyFlags = defaultCopyFlags {- copyDistPref = installDistPref flags,- copyDest = installDest flags,- copyVerbosity = installVerbosity flags- }- install pkg_descr localbuildinfo copyFlags- let registerFlags = defaultRegisterFlags {- regDistPref = installDistPref flags,- regInPlace = installInPlace flags,- regPackageDB = installPackageDB flags,- regVerbosity = installVerbosity flags- }- when (hasLibs pkg_descr) $ register pkg_descr localbuildinfo registerFlags--defaultBuildHook :: PackageDescription -> LocalBuildInfo- -> UserHooks -> BuildFlags -> IO ()-defaultBuildHook pkg_descr localbuildinfo hooks flags =- build pkg_descr localbuildinfo flags (allSuffixHandlers hooks)--defaultReplHook :: PackageDescription -> LocalBuildInfo- -> UserHooks -> ReplFlags -> [String] -> IO ()-defaultReplHook pkg_descr localbuildinfo hooks flags args =- repl pkg_descr localbuildinfo flags (allSuffixHandlers hooks) args--defaultRegHook :: PackageDescription -> LocalBuildInfo- -> UserHooks -> RegisterFlags -> IO ()-defaultRegHook pkg_descr localbuildinfo _ flags =- if hasLibs pkg_descr- then register pkg_descr localbuildinfo flags- else setupMessage (fromFlag (regVerbosity flags))- "Package contains no library to register:" (packageId pkg_descr)
− Distribution/Simple/Bench.hs
@@ -1,125 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Bench--- Copyright : Johan Tibell 2011--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is the entry point into running the benchmarks in a built--- package. It performs the \"@.\/setup bench@\" action. It runs--- benchmarks designated in the package description.--module Distribution.Simple.Bench- ( bench- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.UnqualComponentName-import qualified Distribution.PackageDescription as PD-import Distribution.Simple.BuildPaths-import Distribution.Simple.Compiler-import Distribution.Simple.InstallDirs-import qualified Distribution.Simple.LocalBuildInfo as LBI-import Distribution.Simple.Setup-import Distribution.Simple.UserHooks-import Distribution.Simple.Utils-import Distribution.Pretty--import System.Directory ( doesFileExist )-import System.FilePath ( (</>), (<.>) )---- | Perform the \"@.\/setup bench@\" action.-bench :: Args -- ^positional command-line arguments- -> PD.PackageDescription -- ^information from the .cabal file- -> LBI.LocalBuildInfo -- ^information from the configure step- -> BenchmarkFlags -- ^flags sent to benchmark- -> IO ()-bench args pkg_descr lbi flags = do- let verbosity = fromFlag $ benchmarkVerbosity flags- benchmarkNames = args- pkgBenchmarks = PD.benchmarks pkg_descr- enabledBenchmarks = map fst (LBI.enabledBenchLBIs pkg_descr lbi)-- -- Run the benchmark- doBench :: PD.Benchmark -> IO ExitCode- doBench bm =- case PD.benchmarkInterface bm of- PD.BenchmarkExeV10 _ _ -> do- let cmd = LBI.buildDir lbi </> name </> name <.> exeExtension (LBI.hostPlatform lbi)- options = map (benchOption pkg_descr lbi bm) $- benchmarkOptions flags- -- Check that the benchmark executable exists.- exists <- doesFileExist cmd- unless exists $ die' verbosity $- "Error: Could not find benchmark program \""- ++ cmd ++ "\". Did you build the package first?"-- notice verbosity $ startMessage name- -- This will redirect the child process- -- stdout/stderr to the parent process.- exitcode <- rawSystemExitCode verbosity cmd options- notice verbosity $ finishMessage name exitcode- return exitcode-- _ -> do- notice verbosity $ "No support for running "- ++ "benchmark " ++ name ++ " of type: "- ++ prettyShow (PD.benchmarkType bm)- exitFailure- where name = unUnqualComponentName $ PD.benchmarkName bm-- unless (PD.hasBenchmarks pkg_descr) $ do- notice verbosity "Package has no benchmarks."- exitSuccess-- when (PD.hasBenchmarks pkg_descr && null enabledBenchmarks) $- die' verbosity $ "No benchmarks enabled. Did you remember to configure with "- ++ "\'--enable-benchmarks\'?"-- bmsToRun <- case benchmarkNames of- [] -> return enabledBenchmarks- names -> for names $ \bmName ->- let benchmarkMap = zip enabledNames enabledBenchmarks- enabledNames = map PD.benchmarkName enabledBenchmarks- allNames = map PD.benchmarkName pkgBenchmarks- in case lookup (mkUnqualComponentName bmName) benchmarkMap of- Just t -> return t- _ | mkUnqualComponentName bmName `elem` allNames ->- die' verbosity $ "Package configured with benchmark "- ++ bmName ++ " disabled."- | otherwise -> die' verbosity $ "no such benchmark: " ++ bmName-- let totalBenchmarks = length bmsToRun- notice verbosity $ "Running " ++ show totalBenchmarks ++ " benchmarks..."- exitcodes <- traverse doBench bmsToRun- let allOk = totalBenchmarks == length (filter (== ExitSuccess) exitcodes)- unless allOk exitFailure- where- startMessage name = "Benchmark " ++ name ++ ": RUNNING...\n"- finishMessage name exitcode = "Benchmark " ++ name ++ ": "- ++ (case exitcode of- ExitSuccess -> "FINISH"- ExitFailure _ -> "ERROR")----- TODO: This is abusing the notion of a 'PathTemplate'. The result isn't--- necessarily a path.-benchOption :: PD.PackageDescription- -> LBI.LocalBuildInfo- -> PD.Benchmark- -> PathTemplate- -> String-benchOption pkg_descr lbi bm template =- fromPathTemplate $ substPathTemplate env template- where- env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.localUnitId lbi)- (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++- [(BenchmarkNameVar, toPathTemplate $ unUnqualComponentName $ PD.benchmarkName bm)]
− Distribution/Simple/Build.hs
@@ -1,733 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Build--- Copyright : Isaac Jones 2003-2005,--- Ross Paterson 2006,--- Duncan Coutts 2007-2008, 2012--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is the entry point to actually building the modules in a package. It--- doesn't actually do much itself, most of the work is delegated to--- compiler-specific actions. It does do some non-compiler specific bits like--- running pre-processors.-----module Distribution.Simple.Build (- build, showBuildInfo, repl,- startInterpreter,-- initialBuildSteps,- createInternalPackageDB,- componentInitialBuildSteps,- writeAutogenFiles,- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.Generic--import Distribution.Types.ComponentLocalBuildInfo-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.Dependency-import Distribution.Types.ExecutableScope-import Distribution.Types.ForeignLib-import Distribution.Types.LibraryVisibility-import Distribution.Types.LocalBuildInfo-import Distribution.Types.MungedPackageId-import Distribution.Types.MungedPackageName-import Distribution.Types.ModuleRenaming-import Distribution.Types.TargetInfo--import Distribution.Package-import Distribution.Backpack-import Distribution.Backpack.DescribeUnitId-import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS-import qualified Distribution.Simple.UHC as UHC-import qualified Distribution.Simple.HaskellSuite as HaskellSuite-import qualified Distribution.Simple.PackageIndex as Index--import Distribution.Simple.Build.Macros (generateCabalMacrosHeader)-import Distribution.Simple.Build.PathsModule (generatePathsModule)-import qualified Distribution.Simple.Program.HcPkg as HcPkg--import Distribution.Simple.Compiler-import Distribution.PackageDescription-import qualified Distribution.InstalledPackageInfo as IPI-import Distribution.InstalledPackageInfo (InstalledPackageInfo)-import qualified Distribution.ModuleName as ModuleName--import Distribution.Simple.Setup-import Distribution.Simple.BuildTarget-import Distribution.Simple.BuildToolDepends-import Distribution.Simple.PreProcess-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.Program.Types-import Distribution.Simple.Program.Db-import Distribution.Simple.ShowBuildInfo-import Distribution.Simple.BuildPaths-import Distribution.Simple.Configure-import Distribution.Simple.Register-import Distribution.Simple.Test.LibV09-import Distribution.Simple.Utils-import Distribution.Simple.Utils.Json--import Distribution.System-import Distribution.Pretty-import Distribution.Verbosity-import Distribution.Version (thisVersion)--import Distribution.Compat.Graph (IsNode(..))--import Control.Monad-import qualified Data.Set as Set-import System.FilePath ( (</>), (<.>), takeDirectory )-import System.Directory ( getCurrentDirectory )---- -------------------------------------------------------------------------------- |Build the libraries and executables in this package.--build :: PackageDescription -- ^ Mostly information from the .cabal file- -> LocalBuildInfo -- ^ Configuration information- -> BuildFlags -- ^ Flags that the user passed to build- -> [ PPSuffixHandler ] -- ^ preprocessors to run before compiling- -> IO ()-build pkg_descr lbi flags suffixes = do- targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs flags)- let componentsToBuild = neededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets)- info verbosity $ "Component build order: "- ++ intercalate ", "- (map (showComponentName . componentLocalName . targetCLBI)- componentsToBuild)-- when (null targets) $- -- Only bother with this message if we're building the whole package- setupMessage verbosity "Building" (packageId pkg_descr)-- internalPackageDB <- createInternalPackageDB verbosity lbi distPref-- (\f -> foldM_ f (installedPkgs lbi) componentsToBuild) $ \index target -> do- let comp = targetComponent target- clbi = targetCLBI target- componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity- let bi = componentBuildInfo comp- progs' = addInternalBuildTools pkg_descr lbi bi (withPrograms lbi)- lbi' = lbi {- withPrograms = progs',- withPackageDB = withPackageDB lbi ++ [internalPackageDB],- installedPkgs = index- }- mb_ipi <- buildComponent verbosity (buildNumJobs flags) pkg_descr- lbi' suffixes comp clbi distPref- return (maybe index (Index.insert `flip` index) mb_ipi)- return ()- where- distPref = fromFlag (buildDistPref flags)- verbosity = fromFlag (buildVerbosity flags)---showBuildInfo :: PackageDescription -- ^ Mostly information from the .cabal file- -> LocalBuildInfo -- ^ Configuration information- -> BuildFlags -- ^ Flags that the user passed to build- -> IO String-showBuildInfo pkg_descr lbi flags = do- let verbosity = fromFlag (buildVerbosity flags)- targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs flags)- let targetsToBuild = neededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets)- doc = mkBuildInfo pkg_descr lbi flags targetsToBuild- return $ renderJson doc ""---repl :: PackageDescription -- ^ Mostly information from the .cabal file- -> LocalBuildInfo -- ^ Configuration information- -> ReplFlags -- ^ Flags that the user passed to build- -> [ PPSuffixHandler ] -- ^ preprocessors to run before compiling- -> [String]- -> IO ()-repl pkg_descr lbi flags suffixes args = do- let distPref = fromFlag (replDistPref flags)- verbosity = fromFlag (replVerbosity flags)-- target <- readTargetInfos verbosity pkg_descr lbi args >>= \r -> case r of- -- This seems DEEPLY questionable.- [] -> case allTargetsInBuildOrder' pkg_descr lbi of- (target:_) -> return target- [] -> die' verbosity $ "Failed to determine target."- [target] -> return target- _ -> die' verbosity $ "The 'repl' command does not support multiple targets at once."- let componentsToBuild = neededTargetsInBuildOrder' pkg_descr lbi [nodeKey target]- debug verbosity $ "Component build order: "- ++ intercalate ", "- (map (showComponentName . componentLocalName . targetCLBI)- componentsToBuild)-- internalPackageDB <- createInternalPackageDB verbosity lbi distPref-- let lbiForComponent comp lbi' =- lbi' {- withPackageDB = withPackageDB lbi ++ [internalPackageDB],- withPrograms = addInternalBuildTools pkg_descr lbi'- (componentBuildInfo comp) (withPrograms lbi')- }-- -- build any dependent components- sequence_- [ do let clbi = targetCLBI subtarget- comp = targetComponent subtarget- lbi' = lbiForComponent comp lbi- componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity- buildComponent verbosity NoFlag- pkg_descr lbi' suffixes comp clbi distPref- | subtarget <- safeInit componentsToBuild ]-- -- REPL for target components- let clbi = targetCLBI target- comp = targetComponent target- lbi' = lbiForComponent comp lbi- replFlags = replReplOptions flags- componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity- replComponent replFlags verbosity pkg_descr lbi' suffixes comp clbi distPref----- | Start an interpreter without loading any package files.-startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform- -> PackageDBStack -> IO ()-startInterpreter verbosity programDb comp platform packageDBs =- case compilerFlavor comp of- GHC -> GHC.startInterpreter verbosity programDb comp platform packageDBs- GHCJS -> GHCJS.startInterpreter verbosity programDb comp platform packageDBs- _ -> die' verbosity "A REPL is not supported with this compiler."--buildComponent :: Verbosity- -> Flag (Maybe Int)- -> PackageDescription- -> LocalBuildInfo- -> [PPSuffixHandler]- -> Component- -> ComponentLocalBuildInfo- -> FilePath- -> IO (Maybe InstalledPackageInfo)-buildComponent verbosity numJobs pkg_descr lbi suffixes- comp@(CLib lib) clbi distPref = do- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- setupMessage' verbosity "Building" (packageId pkg_descr)- (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)- let libbi = libBuildInfo lib- lib' = lib { libBuildInfo = flip addExtraAsmSources extras- $ flip addExtraCmmSources extras- $ flip addExtraCxxSources extras- $ flip addExtraCSources extras- $ libbi- }-- buildLib verbosity numJobs pkg_descr lbi lib' clbi-- let oneComponentRequested (OneComponentRequestedSpec _) = True- oneComponentRequested _ = False- -- Don't register inplace if we're only building a single component;- -- it's not necessary because there won't be any subsequent builds- -- that need to tag us- if (not (oneComponentRequested (componentEnabledSpec lbi)))- then do- -- 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- installedPkgInfo = inplaceInstalledPackageInfo pwd distPref pkg_descr- -- NB: Use a fake ABI hash to avoid- -- needing to recompute it every build.- (mkAbiHash "inplace") lib' lbi clbi-- debug verbosity $ "Registering inplace:\n" ++ (IPI.showInstalledPackageInfo installedPkgInfo)- registerPackage verbosity (compiler lbi) (withPrograms lbi)- (withPackageDB lbi) installedPkgInfo- HcPkg.defaultRegisterOptions {- HcPkg.registerMultiInstance = True- }- return (Just installedPkgInfo)- else return Nothing--buildComponent verbosity numJobs pkg_descr lbi suffixes- comp@(CFLib flib) clbi _distPref = do- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- setupMessage' verbosity "Building" (packageId pkg_descr)- (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)- buildFLib verbosity numJobs pkg_descr lbi flib clbi- return Nothing--buildComponent verbosity numJobs pkg_descr lbi suffixes- comp@(CExe exe) clbi _ = do- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- setupMessage' verbosity "Building" (packageId pkg_descr)- (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)- let ebi = buildInfo exe- exe' = exe { buildInfo = addExtraCSources ebi extras }- buildExe verbosity numJobs pkg_descr lbi exe' clbi- return Nothing---buildComponent verbosity numJobs pkg_descr lbi suffixes- comp@(CTest test@TestSuite { testInterface = TestSuiteExeV10{} })- clbi _distPref = do- let exe = testSuiteExeV10AsExe test- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- setupMessage' verbosity "Building" (packageId pkg_descr)- (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)- let ebi = buildInfo exe- exe' = exe { buildInfo = addExtraCSources ebi extras }- buildExe verbosity numJobs pkg_descr lbi exe' clbi- return Nothing---buildComponent verbosity numJobs pkg_descr lbi0 suffixes- comp@(CTest- test@TestSuite { testInterface = TestSuiteLibV09{} })- clbi -- This ComponentLocalBuildInfo corresponds to a detailed- -- test suite and not a real component. It should not- -- be used, except to construct the CLBIs for the- -- library and stub executable that will actually be- -- built.- distPref = do- pwd <- getCurrentDirectory- let (pkg, lib, libClbi, lbi, ipi, exe, exeClbi) =- testSuiteLibV09AsLibAndExe pkg_descr test clbi lbi0 distPref pwd- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- setupMessage' verbosity "Building" (packageId pkg_descr)- (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)- buildLib verbosity numJobs pkg lbi lib libClbi- -- 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)- (withPackageDB lbi) ipi- HcPkg.defaultRegisterOptions {- HcPkg.registerMultiInstance = True- }- let ebi = buildInfo exe- -- NB: The stub executable is linked against the test-library- -- which already contains all `other-modules`, so we need- -- to remove those from the stub-exe's build-info- exe' = exe { buildInfo = (addExtraCSources ebi extras) { otherModules = [] } }- buildExe verbosity numJobs pkg_descr lbi exe' exeClbi- return Nothing -- Can't depend on test suite---buildComponent verbosity _ _ _ _- (CTest TestSuite { testInterface = TestSuiteUnsupported tt })- _ _ =- die' verbosity $ "No support for building test suite type " ++ prettyShow tt---buildComponent verbosity numJobs pkg_descr lbi suffixes- comp@(CBench bm@Benchmark { benchmarkInterface = BenchmarkExeV10 {} })- clbi _distPref = do- let exe = benchmarkExeV10asExe bm- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- setupMessage' verbosity "Building" (packageId pkg_descr)- (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)- let ebi = buildInfo exe- exe' = exe { buildInfo = addExtraCSources ebi extras }- buildExe verbosity numJobs pkg_descr lbi exe' clbi- return Nothing---buildComponent verbosity _ _ _ _- (CBench Benchmark { benchmarkInterface = BenchmarkUnsupported tt })- _ _ =- die' verbosity $ "No support for building benchmark type " ++ prettyShow 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----- | Add extra C++ sources generated by preprocessing to build--- information.-addExtraCxxSources :: BuildInfo -> [FilePath] -> BuildInfo-addExtraCxxSources bi extras = bi { cxxSources = new }- where new = Set.toList $ old `Set.union` exs- old = Set.fromList $ cxxSources bi- exs = Set.fromList extras----- | Add extra C-- sources generated by preprocessing to build--- information.-addExtraCmmSources :: BuildInfo -> [FilePath] -> BuildInfo-addExtraCmmSources bi extras = bi { cmmSources = new }- where new = Set.toList $ old `Set.union` exs- old = Set.fromList $ cmmSources bi- exs = Set.fromList extras----- | Add extra ASM sources generated by preprocessing to build--- information.-addExtraAsmSources :: BuildInfo -> [FilePath] -> BuildInfo-addExtraAsmSources bi extras = bi { asmSources = new }- where new = Set.toList $ old `Set.union` exs- old = Set.fromList $ asmSources bi- exs = Set.fromList extras---replComponent :: [String]- -> Verbosity- -> PackageDescription- -> LocalBuildInfo- -> [PPSuffixHandler]- -> Component- -> ComponentLocalBuildInfo- -> FilePath- -> IO ()-replComponent replFlags verbosity pkg_descr lbi suffixes- comp@(CLib lib) clbi _ = do- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- let libbi = libBuildInfo lib- lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }- replLib replFlags verbosity pkg_descr lbi lib' clbi--replComponent replFlags verbosity pkg_descr lbi suffixes- comp@(CFLib flib) clbi _ = do- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- replFLib replFlags verbosity pkg_descr lbi flib clbi--replComponent replFlags verbosity pkg_descr lbi suffixes- comp@(CExe exe) clbi _ = do- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- let ebi = buildInfo exe- exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }- replExe replFlags verbosity pkg_descr lbi exe' clbi---replComponent replFlags verbosity pkg_descr lbi suffixes- comp@(CTest test@TestSuite { testInterface = TestSuiteExeV10{} })- clbi _distPref = do- let exe = testSuiteExeV10AsExe test- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- let ebi = buildInfo exe- exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }- replExe replFlags verbosity pkg_descr lbi exe' clbi---replComponent replFlags verbosity pkg_descr lbi0 suffixes- comp@(CTest- test@TestSuite { testInterface = TestSuiteLibV09{} })- clbi distPref = do- pwd <- getCurrentDirectory- let (pkg, lib, libClbi, lbi, _, _, _) =- testSuiteLibV09AsLibAndExe pkg_descr test clbi lbi0 distPref pwd- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- let libbi = libBuildInfo lib- lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }- replLib replFlags verbosity pkg lbi lib' libClbi---replComponent _ verbosity _ _ _- (CTest TestSuite { testInterface = TestSuiteUnsupported tt })- _ _ =- die' verbosity $ "No support for building test suite type " ++ prettyShow tt---replComponent replFlags verbosity pkg_descr lbi suffixes- comp@(CBench bm@Benchmark { benchmarkInterface = BenchmarkExeV10 {} })- clbi _distPref = do- let exe = benchmarkExeV10asExe bm- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- extras <- preprocessExtras verbosity comp lbi- let ebi = buildInfo exe- exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }- replExe replFlags verbosity pkg_descr lbi exe' clbi---replComponent _ verbosity _ _ _- (CBench Benchmark { benchmarkInterface = BenchmarkUnsupported tt })- _ _ =- die' verbosity $ "No support for building benchmark type " ++ prettyShow tt--------------------------------------------------------- Shared code for buildComponent and replComponent------- | Translate a exe-style 'TestSuite' component into an exe for building-testSuiteExeV10AsExe :: TestSuite -> Executable-testSuiteExeV10AsExe test@TestSuite { testInterface = TestSuiteExeV10 _ mainFile } =- Executable {- exeName = testName test,- modulePath = mainFile,- exeScope = ExecutablePublic,- buildInfo = testBuildInfo test- }-testSuiteExeV10AsExe TestSuite{} = error "testSuiteExeV10AsExe: wrong kind"---- | Translate a exe-style 'Benchmark' component into an exe for building-benchmarkExeV10asExe :: Benchmark -> Executable-benchmarkExeV10asExe bm@Benchmark { benchmarkInterface = BenchmarkExeV10 _ mainFile } =- Executable {- exeName = benchmarkName bm,- modulePath = mainFile,- exeScope = ExecutablePublic,- buildInfo = benchmarkBuildInfo bm- }-benchmarkExeV10asExe Benchmark{} = error "benchmarkExeV10asExe: wrong kind"---- | Translate a lib-style 'TestSuite' component into a lib + exe for building-testSuiteLibV09AsLibAndExe :: PackageDescription- -> TestSuite- -> ComponentLocalBuildInfo- -> LocalBuildInfo- -> FilePath- -> FilePath- -> (PackageDescription,- Library, ComponentLocalBuildInfo,- LocalBuildInfo,- IPI.InstalledPackageInfo,- Executable, ComponentLocalBuildInfo)-testSuiteLibV09AsLibAndExe pkg_descr- test@TestSuite { testInterface = TestSuiteLibV09 _ m }- clbi lbi distPref pwd =- (pkg, lib, libClbi, lbi, ipi, exe, exeClbi)- where- bi = testBuildInfo test- lib = Library {- libName = LMainLibName,- exposedModules = [ m ],- reexportedModules = [],- signatures = [],- libExposed = True,- libVisibility = LibraryVisibilityPrivate,- libBuildInfo = bi- }- -- This is, like, the one place where we use a CTestName for a library.- -- Should NOT use library name, since that could conflict!- PackageIdentifier pkg_name pkg_ver = package pkg_descr- -- Note: we do make internal library from the test!- compat_name = MungedPackageName pkg_name (LSubLibName (testName test))- compat_key = computeCompatPackageKey (compiler lbi) compat_name pkg_ver (componentUnitId clbi)- libClbi = LibComponentLocalBuildInfo- { componentPackageDeps = componentPackageDeps clbi- , componentInternalDeps = componentInternalDeps clbi- , componentIsIndefinite_ = False- , componentExeDeps = componentExeDeps clbi- , componentLocalName = CLibName $ LSubLibName $ testName test- , componentIsPublic = False- , componentIncludes = componentIncludes clbi- , componentUnitId = componentUnitId clbi- , componentComponentId = componentComponentId clbi- , componentInstantiatedWith = []- , componentCompatPackageName = compat_name- , componentCompatPackageKey = compat_key- , componentExposedModules = [IPI.ExposedModule m Nothing]- }- pkgName' = mkPackageName $ prettyShow compat_name- pkg = pkg_descr {- package = (package pkg_descr) { pkgName = pkgName' }- , executables = []- , testSuites = []- , subLibraries = [lib]- }- ipi = inplaceInstalledPackageInfo pwd distPref pkg (mkAbiHash "") lib lbi libClbi- testDir = buildDir lbi </> stubName test- </> stubName test ++ "-tmp"- testLibDep = Dependency- pkgName'- (thisVersion $ pkgVersion $ package pkg_descr)- mainLibSet- exe = Executable {- exeName = mkUnqualComponentName $ stubName test,- modulePath = stubFilePath test,- exeScope = ExecutablePublic,- buildInfo = (testBuildInfo test) {- hsSourceDirs = [ testDir ],- targetBuildDepends = testLibDep- : (targetBuildDepends $ testBuildInfo test)- }- }- -- | The stub executable needs a new 'ComponentLocalBuildInfo'- -- that exposes the relevant test suite library.- deps = (IPI.installedUnitId ipi, mungedId ipi)- : (filter (\(_, x) -> let name = prettyShow $ mungedName x- in name == "Cabal" || name == "base")- (componentPackageDeps clbi))- exeClbi = ExeComponentLocalBuildInfo {- -- TODO: this is a hack, but as long as this is unique- -- (doesn't clobber something) we won't run into trouble- componentUnitId = mkUnitId (stubName test),- componentComponentId = mkComponentId (stubName test),- componentInternalDeps = [componentUnitId clbi],- componentExeDeps = [],- componentLocalName = CExeName $ mkUnqualComponentName $ stubName test,- componentPackageDeps = deps,- -- Assert DefUnitId invariant!- -- Executable can't be indefinite, so dependencies must- -- be definite packages.- componentIncludes = zip (map (DefiniteUnitId . unsafeMkDefUnitId . fst) deps)- (repeat defaultRenaming)- }-testSuiteLibV09AsLibAndExe _ TestSuite{} _ _ _ _ = error "testSuiteLibV09AsLibAndExe: wrong kind"----- | Initialize a new package db file for libraries defined--- internally to the package.-createInternalPackageDB :: Verbosity -> LocalBuildInfo -> FilePath- -> IO PackageDB-createInternalPackageDB verbosity lbi distPref = do- existsAlready <- doesPackageDBExist dbPath- when existsAlready $ deletePackageDB dbPath- createPackageDB verbosity (compiler lbi) (withPrograms lbi) False dbPath- return (SpecificPackageDB dbPath)- where- dbPath = internalPackageDBPath lbi distPref--addInternalBuildTools :: PackageDescription -> LocalBuildInfo -> BuildInfo- -> ProgramDb -> ProgramDb-addInternalBuildTools pkg lbi bi progs =- foldr updateProgram progs internalBuildTools- where- internalBuildTools =- [ simpleConfiguredProgram toolName' (FoundOnSystem toolLocation)- | toolName <- getAllInternalToolDependencies pkg bi- , let toolName' = unUnqualComponentName toolName- , let toolLocation = buildDir lbi </> toolName' </> toolName' <.> exeExtension (hostPlatform lbi) ]----- TODO: build separate libs in separate dirs so that we can build--- multiple libs, e.g. for 'LibTest' library-style test suites-buildLib :: Verbosity -> Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> Library -> ComponentLocalBuildInfo -> IO ()-buildLib verbosity numJobs pkg_descr lbi lib clbi =- case compilerFlavor (compiler lbi) of- GHC -> GHC.buildLib verbosity numJobs pkg_descr lbi lib clbi- GHCJS -> GHCJS.buildLib verbosity numJobs pkg_descr lbi lib clbi- UHC -> UHC.buildLib verbosity pkg_descr lbi lib clbi- HaskellSuite {} -> HaskellSuite.buildLib verbosity pkg_descr lbi lib clbi- _ -> die' verbosity "Building is not supported with this compiler."---- | Build a foreign library------ NOTE: We assume that we already checked that we can actually build the--- foreign library in configure.-buildFLib :: Verbosity -> Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> ForeignLib -> ComponentLocalBuildInfo -> IO ()-buildFLib verbosity numJobs pkg_descr lbi flib clbi =- case compilerFlavor (compiler lbi) of- GHC -> GHC.buildFLib verbosity numJobs pkg_descr lbi flib clbi- _ -> die' verbosity "Building is not supported with this compiler."--buildExe :: Verbosity -> Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> Executable -> ComponentLocalBuildInfo -> IO ()-buildExe verbosity numJobs pkg_descr lbi exe clbi =- case compilerFlavor (compiler lbi) of- GHC -> GHC.buildExe verbosity numJobs pkg_descr lbi exe clbi- GHCJS -> GHCJS.buildExe verbosity numJobs pkg_descr lbi exe clbi- UHC -> UHC.buildExe verbosity pkg_descr lbi exe clbi- _ -> die' verbosity "Building is not supported with this compiler."--replLib :: [String] -> Verbosity -> PackageDescription- -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo- -> IO ()-replLib replFlags verbosity pkg_descr lbi lib clbi =- case compilerFlavor (compiler lbi) of- -- 'cabal repl' doesn't need to support 'ghc --make -j', so we just pass- -- NoFlag as the numJobs parameter.- GHC -> GHC.replLib replFlags verbosity NoFlag pkg_descr lbi lib clbi- GHCJS -> GHCJS.replLib replFlags verbosity NoFlag pkg_descr lbi lib clbi- _ -> die' verbosity "A REPL is not supported for this compiler."--replExe :: [String] -> Verbosity -> PackageDescription- -> LocalBuildInfo -> Executable -> ComponentLocalBuildInfo- -> IO ()-replExe replFlags verbosity pkg_descr lbi exe clbi =- case compilerFlavor (compiler lbi) of- GHC -> GHC.replExe replFlags verbosity NoFlag pkg_descr lbi exe clbi- GHCJS -> GHCJS.replExe replFlags verbosity NoFlag pkg_descr lbi exe clbi- _ -> die' verbosity "A REPL is not supported for this compiler."--replFLib :: [String] -> Verbosity -> PackageDescription- -> LocalBuildInfo -> ForeignLib -> ComponentLocalBuildInfo- -> IO ()-replFLib replFlags verbosity pkg_descr lbi exe clbi =- case compilerFlavor (compiler lbi) of- GHC -> GHC.replFLib replFlags verbosity NoFlag pkg_descr lbi exe clbi- _ -> die' verbosity "A REPL is not supported for this compiler."---- | Runs 'componentInitialBuildSteps' on every configured component.-initialBuildSteps :: FilePath -- ^"dist" prefix- -> PackageDescription -- ^mostly information from the .cabal file- -> LocalBuildInfo -- ^Configuration information- -> Verbosity -- ^The verbosity to use- -> IO ()-initialBuildSteps distPref pkg_descr lbi verbosity =- withAllComponentsInBuildOrder pkg_descr lbi $ \_comp clbi ->- componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity---- | Creates the autogenerated files for a particular configured component.-componentInitialBuildSteps :: FilePath -- ^"dist" prefix- -> PackageDescription -- ^mostly information from the .cabal file- -> LocalBuildInfo -- ^Configuration information- -> ComponentLocalBuildInfo- -> Verbosity -- ^The verbosity to use- -> IO ()-componentInitialBuildSteps _distPref pkg_descr lbi clbi verbosity = do- createDirectoryIfMissingVerbose verbosity True (componentBuildDir lbi clbi)-- writeAutogenFiles verbosity pkg_descr lbi clbi---- | Generate and write out the Paths_<pkg>.hs and cabal_macros.h files----writeAutogenFiles :: Verbosity- -> PackageDescription- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> IO ()-writeAutogenFiles verbosity pkg lbi clbi = do- createDirectoryIfMissingVerbose verbosity True (autogenComponentModulesDir lbi clbi)-- let pathsModulePath = autogenComponentModulesDir lbi clbi- </> ModuleName.toFilePath (autogenPathsModuleName pkg) <.> "hs"- pathsModuleDir = takeDirectory pathsModulePath- -- Ensure that the directory exists!- createDirectoryIfMissingVerbose verbosity True pathsModuleDir- rewriteFileEx verbosity pathsModulePath (generatePathsModule pkg lbi clbi)-- --TODO: document what we're doing here, and move it to its own function- case clbi of- LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->- -- Write out empty hsig files for all requirements, so that GHC- -- has a source file to look at it when it needs to typecheck- -- a signature. It's harmless to write these out even when- -- there is a real hsig file written by the user, since- -- include path ordering ensures that the real hsig file- -- will always be picked up before the autogenerated one.- for_ (map fst insts) $ \mod_name -> do- let sigPath = autogenComponentModulesDir lbi clbi- </> ModuleName.toFilePath mod_name <.> "hsig"- createDirectoryIfMissingVerbose verbosity True (takeDirectory sigPath)- rewriteFileEx verbosity sigPath $- "{-# OPTIONS_GHC -w #-}\n" ++- "{-# LANGUAGE NoImplicitPrelude #-}\n" ++- "signature " ++ prettyShow mod_name ++ " where"- _ -> return ()-- let cppHeaderPath = autogenComponentModulesDir lbi clbi </> cppHeaderName- rewriteFileEx verbosity cppHeaderPath (generateCabalMacrosHeader pkg lbi clbi)
− Distribution/Simple/Build/Macros.hs
@@ -1,110 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Build.Macros--- Copyright : Simon Marlow 2008------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Generate cabal_macros.h - CPP macros for package version testing------ When using CPP you get------ > VERSION_<package>--- > MIN_VERSION_<package>(A,B,C)------ for each /package/ in @build-depends@, which is true if the version of--- /package/ in use is @>= A.B.C@, using the normal ordering on version--- numbers.------ TODO Figure out what to do about backpack and internal libraries. It is very--- suspecious that this stuff works with munged package identifiers-module Distribution.Simple.Build.Macros (- generateCabalMacrosHeader,- generatePackageVersionMacros,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Version-import Distribution.PackageDescription-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.Program.Db-import Distribution.Simple.Program.Types-import Distribution.Types.MungedPackageId-import Distribution.Types.MungedPackageName-import Distribution.Pretty--import qualified Distribution.Simple.Build.Macros.Z as Z---- | The contents of the @cabal_macros.h@ for the given configured package.----generateCabalMacrosHeader :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> String-generateCabalMacrosHeader pkg_descr lbi clbi = Z.render Z.Z- { Z.zPackages = map mkZPackage $ package pkg_descr : map getPid (componentPackageDeps clbi)- , Z.zTools =- [ Z.ZTool- { Z.ztoolName = programId prog- , Z.ztoolVersion = ver- , Z.ztoolX = major1- , Z.ztoolY = major2- , Z.ztoolZ = minor- }- | prog <- configuredPrograms $ withPrograms lbi- , ver <- maybeToList (programVersion prog)- , let (major1,major2,minor) = majorMinor ver- ]- , Z.zPackageKey = case clbi of- LibComponentLocalBuildInfo{} -> componentCompatPackageKey clbi- _ -> ""- , Z.zComponentId = prettyShow (componentComponentId clbi)- , Z.zPackageVersion = pkgVersion (package pkg_descr)- , Z.zNotNull = not . null- , Z.zManglePkgName = map fixchar . unPackageName- , Z.zMangleStr = map fixchar- }- where- getPid (_, MungedPackageId (MungedPackageName pn _) v) =- -- NB: Drop the library name! We're just reporting package versions.- -- This would have to be revisited if you are allowed to depend- -- on different versions of the same package- PackageIdentifier pn v---- | 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--- a configured package).----generatePackageVersionMacros :: Version -> [PackageId] -> String-generatePackageVersionMacros ver pkgids = Z.render Z.Z- { Z.zPackages = map mkZPackage pkgids- , Z.zTools = []- , Z.zPackageKey = ""- , Z.zComponentId = ""- , Z.zPackageVersion = ver- , Z.zNotNull = not . null- , Z.zManglePkgName = map fixchar . unPackageName- , Z.zMangleStr = map fixchar- }--mkZPackage :: PackageId -> Z.ZPackage-mkZPackage (PackageIdentifier name ver) = Z.ZPackage- { Z.zpkgName = name- , Z.zpkgVersion = ver- , Z.zpkgX = major1- , Z.zpkgY = major2- , Z.zpkgZ = minor- }- where- (major1,major2,minor) = majorMinor ver--majorMinor :: Version -> (String, String, String)-majorMinor ver = case map show (versionNumbers ver) of- [] -> ("0", "0", "0")- [x] -> (x, "0", "0")- [x,y] -> (x, y, "0")- (x:y:z:_) -> (x, y, z)--fixchar :: Char -> Char-fixchar '-' = '_'-fixchar c = c
− Distribution/Simple/Build/Macros/Z.hs
@@ -1,140 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Simple.Build.Macros.Z (render, Z(..), ZPackage (..), ZTool (..)) where-import Distribution.ZinzaPrelude-data Z- = Z {zPackages :: ([ZPackage]),- zTools :: ([ZTool]),- zPackageKey :: String,- zComponentId :: String,- zPackageVersion :: Version,- zNotNull :: (String -> Bool),- zManglePkgName :: (PackageName -> String),- zMangleStr :: (String -> String)}- deriving Generic-data ZPackage- = ZPackage {zpkgName :: PackageName,- zpkgVersion :: Version,- zpkgX :: String,- zpkgY :: String,- zpkgZ :: String}- deriving Generic-data ZTool- = ZTool {ztoolName :: String,- ztoolVersion :: Version,- ztoolX :: String,- ztoolY :: String,- ztoolZ :: String}- deriving Generic-render :: Z -> String-render z_root = execWriter $ do- tell "/* DO NOT EDIT: This file is automatically generated by Cabal */\n"- tell "\n"- forM_ (zPackages z_root) $ \z_var0_pkg -> do- tell "/* package "- tell (prettyShow (zpkgName z_var0_pkg))- tell "-"- tell (prettyShow (zpkgVersion z_var0_pkg))- tell " */\n"- tell "#ifndef VERSION_"- tell (zManglePkgName z_root (zpkgName z_var0_pkg))- tell "\n"- tell "#define VERSION_"- tell (zManglePkgName z_root (zpkgName z_var0_pkg))- tell " \""- tell (prettyShow (zpkgVersion z_var0_pkg))- tell "\"\n"- tell "#endif /* VERSION_"- tell (zManglePkgName z_root (zpkgName z_var0_pkg))- tell " */\n"- tell "#ifndef MIN_VERSION_"- tell (zManglePkgName z_root (zpkgName z_var0_pkg))- tell "\n"- tell "#define MIN_VERSION_"- tell (zManglePkgName z_root (zpkgName z_var0_pkg))- tell "(major1,major2,minor) (\\\n"- tell " (major1) < "- tell (zpkgX z_var0_pkg)- tell " || \\\n"- tell " (major1) == "- tell (zpkgX z_var0_pkg)- tell " && (major2) < "- tell (zpkgY z_var0_pkg)- tell " || \\\n"- tell " (major1) == "- tell (zpkgX z_var0_pkg)- tell " && (major2) == "- tell (zpkgY z_var0_pkg)- tell " && (minor) <= "- tell (zpkgZ z_var0_pkg)- tell ")\n"- tell "#endif /* MIN_VERSION_"- tell (zManglePkgName z_root (zpkgName z_var0_pkg))- tell " */\n"- tell "\n"- forM_ (zTools z_root) $ \z_var1_tool -> do- tell "/* tool "- tell (ztoolName z_var1_tool)- tell "-"- tell (prettyShow (ztoolVersion z_var1_tool))- tell " */\n"- tell "#ifndef TOOL_VERSION_"- tell (zMangleStr z_root (ztoolName z_var1_tool))- tell "\n"- tell "#define TOOL_VERSION_"- tell (zMangleStr z_root (ztoolName z_var1_tool))- tell " \""- tell (prettyShow (ztoolVersion z_var1_tool))- tell "\"\n"- tell "#endif /* TOOL_VERSION_"- tell (zMangleStr z_root (ztoolName z_var1_tool))- tell " */\n"- tell "#ifndef MIN_TOOL_VERSION_"- tell (zMangleStr z_root (ztoolName z_var1_tool))- tell "\n"- tell "#define MIN_TOOL_VERSION_"- tell (zMangleStr z_root (ztoolName z_var1_tool))- tell "(major1,major2,minor) (\\\n"- tell " (major1) < "- tell (ztoolX z_var1_tool)- tell " || \\\n"- tell " (major1) == "- tell (ztoolX z_var1_tool)- tell " && (major2) < "- tell (ztoolY z_var1_tool)- tell " || \\\n"- tell " (major1) == "- tell (ztoolX z_var1_tool)- tell " && (major2) == "- tell (ztoolY z_var1_tool)- tell " && (minor) <= "- tell (ztoolZ z_var1_tool)- tell ")\n"- tell "#endif /* MIN_TOOL_VERSION_"- tell (zMangleStr z_root (ztoolName z_var1_tool))- tell " */\n"- tell "\n"- if (zNotNull z_root (zPackageKey z_root))- then do- tell "#ifndef CURRENT_PACKAGE_KEY\n"- tell "#define CURRENT_PACKAGE_KEY \""- tell (zPackageKey z_root)- tell "\"\n"- tell "#endif /* CURRENT_packageKey */\n"- return ()- else do- return ()- if (zNotNull z_root (zComponentId z_root))- then do- tell "#ifndef CURRENT_COMPONENT_ID\n"- tell "#define CURRENT_COMPONENT_ID \""- tell (zComponentId z_root)- tell "\"\n"- tell "#endif /* CURRENT_COMPONENT_ID */\n"- return ()- else do- return ()- tell "#ifndef CURRENT_PACKAGE_VERSION\n"- tell "#define CURRENT_PACKAGE_VERSION \""- tell (prettyShow (zPackageVersion z_root))- tell "\"\n"- tell "#endif /* CURRENT_PACKAGE_VERSION */\n"
− Distribution/Simple/Build/PathsModule.hs
@@ -1,356 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Build.Macros--- Copyright : Isaac Jones 2003-2005,--- Ross Paterson 2006,--- Duncan Coutts 2007-2008------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Generating the Paths_pkgname module.------ This is a module that Cabal generates for the benefit of packages. It--- enables them to find their version number and find any installed data files--- at runtime. This code should probably be split off into another module.----module Distribution.Simple.Build.PathsModule (- generatePathsModule, pkgPathEnvVar- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.System-import Distribution.Simple.Compiler-import Distribution.Package-import Distribution.PackageDescription-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.BuildPaths-import Distribution.Simple.Utils-import Distribution.Pretty-import Distribution.Version--import System.FilePath ( pathSeparator )---- --------------------------------------------------------------- * Building Paths_<pkg>.hs--- --------------------------------------------------------------generatePathsModule :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> String-generatePathsModule pkg_descr lbi clbi =- let pragmas =- cpp_pragma- ++ no_rebindable_syntax_pragma- ++ ffi_pragmas- ++ warning_pragmas-- cpp_pragma- | supports_cpp = "{-# LANGUAGE CPP #-}\n"- | otherwise = ""-- -- -XRebindableSyntax is problematic because when paired with- -- -XOverloadedLists, 'fromListN' is not in scope,- -- or -XOverloadedStrings 'fromString' is not in scope,- -- so we disable 'RebindableSyntax'.- no_rebindable_syntax_pragma- | supports_rebindable_syntax = "{-# LANGUAGE NoRebindableSyntax #-}\n"- | otherwise = ""-- ffi_pragmas- | absolute = ""- | supports_language_pragma =- "{-# LANGUAGE ForeignFunctionInterface #-}\n"- | otherwise =- "{-# OPTIONS_GHC -fffi #-}\n"-- warning_pragmas = unlines $- [ "{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}" ] ++- [ "{-# OPTIONS_GHC -Wno-missing-safe-haskell-mode #-}" | supports_missing_safehaskell ]-- foreign_imports- | absolute = ""- | otherwise =- "import Foreign\n"++- "import Foreign.C\n"-- reloc_imports- | reloc =- "import System.Environment (getExecutablePath)\n"- | otherwise = ""-- header =- pragmas++- "module " ++ prettyShow paths_modulename ++ " (\n"++- " version,\n"++- " getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,\n"++- " getDataFileName, getSysconfDir\n"++- " ) where\n"++- "\n"++- foreign_imports++- "import qualified Control.Exception as Exception\n"++- "import Data.Version (Version(..))\n"++- "import System.Environment (getEnv)\n"++- reloc_imports ++- "import Prelude\n"++- "\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"++- "\nversion = Version " ++ show branch ++ " []"- where branch = versionNumbers $ packageVersion pkg_descr-- body- | reloc =- "\n\nbindirrel :: FilePath\n" ++- "bindirrel = " ++ show flat_bindirreloc ++- "\n"++- "\ngetBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++- "getBinDir = "++mkGetEnvOrReloc "bindir" flat_bindirreloc++"\n"++- "getLibDir = "++mkGetEnvOrReloc "libdir" flat_libdirreloc++"\n"++- "getDynLibDir = "++mkGetEnvOrReloc "libdir" flat_dynlibdirreloc++"\n"++- "getDataDir = "++mkGetEnvOrReloc "datadir" flat_datadirreloc++"\n"++- "getLibexecDir = "++mkGetEnvOrReloc "libexecdir" flat_libexecdirreloc++"\n"++- "getSysconfDir = "++mkGetEnvOrReloc "sysconfdir" flat_sysconfdirreloc++"\n"++- "\n"++- "getDataFileName :: FilePath -> IO FilePath\n"++- "getDataFileName name = do\n"++- " dir <- getDataDir\n"++- " return (dir `joinFileName` name)\n"++- "\n"++- get_prefix_reloc_stuff++- "\n"++- filename_stuff- | absolute =- "\nbindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath\n"++- "\nbindir = " ++ show flat_bindir ++- "\nlibdir = " ++ show flat_libdir ++- "\ndynlibdir = " ++ show flat_dynlibdir ++- "\ndatadir = " ++ show flat_datadir ++- "\nlibexecdir = " ++ show flat_libexecdir ++- "\nsysconfdir = " ++ show flat_sysconfdir ++- "\n"++- "\ngetBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++- "getBinDir = "++mkGetEnvOr "bindir" "return bindir"++"\n"++- "getLibDir = "++mkGetEnvOr "libdir" "return libdir"++"\n"++- "getDynLibDir = "++mkGetEnvOr "dynlibdir" "return dynlibdir"++"\n"++- "getDataDir = "++mkGetEnvOr "datadir" "return datadir"++"\n"++- "getLibexecDir = "++mkGetEnvOr "libexecdir" "return libexecdir"++"\n"++- "getSysconfDir = "++mkGetEnvOr "sysconfdir" "return sysconfdir"++"\n"++- "\n"++- "getDataFileName :: FilePath -> IO FilePath\n"++- "getDataFileName name = do\n"++- " dir <- getDataDir\n"++- " return (dir ++ "++path_sep++" ++ name)\n"- | otherwise =- "\nprefix, bindirrel :: FilePath" ++- "\nprefix = " ++ show flat_prefix ++- "\nbindirrel = " ++ show (fromMaybe (error "PathsModule.generate") flat_bindirrel) ++- "\n\n"++- "getBinDir :: IO FilePath\n"++- "getBinDir = getPrefixDirRel bindirrel\n\n"++- "getLibDir :: IO FilePath\n"++- "getLibDir = "++mkGetDir flat_libdir flat_libdirrel++"\n\n"++- "getDynLibDir :: IO FilePath\n"++- "getDynLibDir = "++mkGetDir flat_dynlibdir flat_dynlibdirrel++"\n\n"++- "getDataDir :: IO FilePath\n"++- "getDataDir = "++ mkGetEnvOr "datadir"- (mkGetDir flat_datadir flat_datadirrel)++"\n\n"++- "getLibexecDir :: IO FilePath\n"++- "getLibexecDir = "++mkGetDir flat_libexecdir flat_libexecdirrel++"\n\n"++- "getSysconfDir :: IO FilePath\n"++- "getSysconfDir = "++mkGetDir flat_sysconfdir flat_sysconfdirrel++"\n\n"++- "getDataFileName :: FilePath -> IO FilePath\n"++- "getDataFileName name = do\n"++- " dir <- getDataDir\n"++- " return (dir `joinFileName` name)\n"++- "\n"++- get_prefix_stuff++- "\n"++- filename_stuff- in header++body-- where- cid = componentUnitId clbi-- InstallDirs {- prefix = flat_prefix,- bindir = flat_bindir,- libdir = flat_libdir,- dynlibdir = flat_dynlibdir,- datadir = flat_datadir,- libexecdir = flat_libexecdir,- sysconfdir = flat_sysconfdir- } = absoluteInstallCommandDirs pkg_descr lbi cid NoCopyDest-- InstallDirs {- bindir = flat_bindirrel,- libdir = flat_libdirrel,- dynlibdir = flat_dynlibdirrel,- datadir = flat_datadirrel,- libexecdir = flat_libexecdirrel,- sysconfdir = flat_sysconfdirrel- } = prefixRelativeComponentInstallDirs (packageId pkg_descr) lbi cid-- flat_bindirreloc = shortRelativePath flat_prefix flat_bindir- flat_libdirreloc = shortRelativePath flat_prefix flat_libdir- flat_dynlibdirreloc = shortRelativePath flat_prefix flat_dynlibdir- flat_datadirreloc = shortRelativePath flat_prefix flat_datadir- flat_libexecdirreloc = shortRelativePath flat_prefix flat_libexecdir- flat_sysconfdirreloc = shortRelativePath flat_prefix flat_sysconfdir-- mkGetDir _ (Just dirrel) = "getPrefixDirRel " ++ show dirrel- mkGetDir dir Nothing = "return " ++ show dir-- mkGetEnvOrReloc var dirrel = "catchIO (getEnv \""++var'++"\")" ++- " (\\_ -> getPrefixDirReloc \"" ++ dirrel ++- "\")"- where var' = pkgPathEnvVar pkg_descr var-- mkGetEnvOr var expr = "catchIO (getEnv \""++var'++"\")"++- " (\\_ -> "++expr++")"- where var' = pkgPathEnvVar pkg_descr var-- -- In several cases we cannot make relocatable installations- absolute =- hasLibs pkg_descr -- we can only make progs relocatable- || isNothing flat_bindirrel -- if the bin dir is an absolute path- || not (supportsRelocatableProgs (compilerFlavor (compiler lbi)))-- reloc = relocatable lbi-- supportsRelocatableProgs GHC = case buildOS of- Windows -> True- _ -> False- supportsRelocatableProgs GHCJS = case buildOS of- Windows -> True- _ -> False- supportsRelocatableProgs _ = False-- paths_modulename = autogenPathsModuleName pkg_descr-- get_prefix_stuff = get_prefix_win32 supports_cpp buildArch-- path_sep = show [pathSeparator]-- supports_cpp = supports_language_pragma- supports_rebindable_syntax= ghc_newer_than (mkVersion [7,0,1])- supports_language_pragma = ghc_newer_than (mkVersion [6,6,1])- supports_missing_safehaskell = ghc_newer_than (mkVersion [8,10,1])-- ghc_newer_than minVersion =- case compilerCompatVersion GHC (compiler lbi) of- Nothing -> False- Just version -> version `withinRange` orLaterVersion minVersion---- | Generates the name of the environment variable controlling the path--- component of interest.------ Note: The format of these strings is part of Cabal's public API;--- changing this function constitutes a *backwards-compatibility* break.-pkgPathEnvVar :: PackageDescription- -> String -- ^ path component; one of \"bindir\", \"libdir\",- -- \"datadir\", \"libexecdir\", or \"sysconfdir\"- -> String -- ^ environment variable name-pkgPathEnvVar pkg_descr var =- showPkgName (packageName pkg_descr) ++ "_" ++ var- where- showPkgName = map fixchar . prettyShow- fixchar '-' = '_'- fixchar c = c--get_prefix_reloc_stuff :: String-get_prefix_reloc_stuff =- "getPrefixDirReloc :: FilePath -> IO FilePath\n"++- "getPrefixDirReloc dirRel = do\n"++- " exePath <- getExecutablePath\n"++- " let (bindir,_) = splitFileName exePath\n"++- " return ((bindir `minusFileName` bindirrel) `joinFileName` dirRel)\n"--get_prefix_win32 :: Bool -> Arch -> String-get_prefix_win32 supports_cpp arch =- "getPrefixDirRel :: FilePath -> IO FilePath\n"++- "getPrefixDirRel dirRel = try_size 2048 -- plenty, PATH_MAX is 512 under Win32.\n"++- " where\n"++- " try_size size = allocaArray (fromIntegral size) $ \\buf -> do\n"++- " ret <- c_GetModuleFileName nullPtr buf size\n"++- " case ret of\n"++- " 0 -> return (prefix `joinFileName` dirRel)\n"++- " _ | ret < size -> do\n"++- " exePath <- peekCWString buf\n"++- " let (bindir,_) = splitFileName exePath\n"++- " return ((bindir `minusFileName` bindirrel) `joinFileName` dirRel)\n"++- " | otherwise -> try_size (size * 2)\n"++- "\n"++- (case supports_cpp of- False -> ""- True -> "#if defined(i386_HOST_ARCH)\n"++- "# define WINDOWS_CCONV stdcall\n"++- "#elif defined(x86_64_HOST_ARCH)\n"++- "# define WINDOWS_CCONV ccall\n"++- "#else\n"++- "# error Unknown mingw32 arch\n"++- "#endif\n")++- "foreign import " ++ cconv ++ " unsafe \"windows.h GetModuleFileNameW\"\n"++- " c_GetModuleFileName :: Ptr () -> CWString -> Int32 -> IO Int32\n"- where cconv = if supports_cpp- then "WINDOWS_CCONV"- else case arch of- I386 -> "stdcall"- X86_64 -> "ccall"- _ -> error "win32 supported only with I386, X86_64"--filename_stuff :: String-filename_stuff =- "minusFileName :: FilePath -> String -> FilePath\n"++- "minusFileName dir \"\" = dir\n"++- "minusFileName dir \".\" = dir\n"++- "minusFileName dir suffix =\n"++- " minusFileName (fst (splitFileName dir)) (fst (splitFileName suffix))\n"++- "\n"++- "joinFileName :: String -> String -> FilePath\n"++- "joinFileName \"\" fname = fname\n"++- "joinFileName \".\" fname = fname\n"++- "joinFileName dir \"\" = dir\n"++- "joinFileName dir fname\n"++- " | isPathSeparator (last dir) = dir++fname\n"++- " | otherwise = dir++pathSeparator:fname\n"++- "\n"++- "splitFileName :: FilePath -> (String, String)\n"++- "splitFileName p = (reverse (path2++drive), reverse fname)\n"++- " where\n"++- " (path,drive) = case p of\n"++- " (c:':':p') -> (reverse p',[':',c])\n"++- " _ -> (reverse p ,\"\")\n"++- " (fname,path1) = break isPathSeparator path\n"++- " path2 = case path1 of\n"++- " [] -> \".\"\n"++- " [_] -> path1 -- don't remove the trailing slash if \n"++- " -- there is only one character\n"++- " (c:path') | isPathSeparator c -> path'\n"++- " _ -> path1\n"++- "\n"++- "pathSeparator :: Char\n"++- (case buildOS of- Windows -> "pathSeparator = '\\\\'\n"- _ -> "pathSeparator = '/'\n") ++- "\n"++- "isPathSeparator :: Char -> Bool\n"++- (case buildOS of- Windows -> "isPathSeparator c = c == '/' || c == '\\\\'\n"- _ -> "isPathSeparator c = c == '/'\n")
− Distribution/Simple/BuildPaths.hs
@@ -1,256 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.BuildPaths--- Copyright : Isaac Jones 2003-2004,--- Duncan Coutts 2008--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ A bunch of dirs, paths and file names used for intermediate build steps.-----module Distribution.Simple.BuildPaths (- defaultDistPref, srcPref,- haddockDirName, hscolourPref, haddockPref,- autogenPackageModulesDir,- autogenComponentModulesDir,-- autogenPathsModuleName,- cppHeaderName,- haddockName,-- mkGenericStaticLibName,- mkLibName,- mkProfLibName,- mkGenericSharedLibName,- mkSharedLibName,- mkStaticLibName,- mkGenericSharedBundledLibName,-- exeExtension,- objExtension,- dllExtension,- staticLibExtension,- -- * Source files & build directories- getSourceFiles, getLibSourceFiles, getExeSourceFiles,- getFLibSourceFiles, exeBuildDir, flibBuildDir,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Package-import Distribution.ModuleName as ModuleName-import Distribution.Compiler-import Distribution.PackageDescription-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.Setup-import Distribution.Pretty-import Distribution.System-import Distribution.Verbosity-import Distribution.Simple.Utils--import Data.List (stripPrefix)-import System.FilePath ((</>), (<.>), normalise)---- ------------------------------------------------------------------------------ Build directories and files--srcPref :: FilePath -> FilePath-srcPref distPref = distPref </> "src"--hscolourPref :: HaddockTarget -> FilePath -> PackageDescription -> FilePath-hscolourPref = haddockPref---- | This is the name of the directory in which the generated haddocks--- should be stored. It does not include the @<dist>/doc/html@ prefix.-haddockDirName :: HaddockTarget -> PackageDescription -> FilePath-haddockDirName ForDevelopment = prettyShow . packageName-haddockDirName ForHackage = (++ "-docs") . prettyShow . packageId---- | The directory to which generated haddock documentation should be written.-haddockPref :: HaddockTarget -> FilePath -> PackageDescription -> FilePath-haddockPref haddockTarget distPref pkg_descr- = distPref </> "doc" </> "html" </> haddockDirName haddockTarget pkg_descr---- | The directory in which we put auto-generated modules for EVERY--- component in the package.-autogenPackageModulesDir :: LocalBuildInfo -> String-autogenPackageModulesDir lbi = buildDir lbi </> "global-autogen"---- | The directory in which we put auto-generated modules for a--- particular component.-autogenComponentModulesDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> String-autogenComponentModulesDir lbi clbi = componentBuildDir lbi clbi </> "autogen"--- NB: Look at 'checkForeignDeps' for where a simplified version of this--- has been copy-pasted.--cppHeaderName :: String-cppHeaderName = "cabal_macros.h"---- | The name of the auto-generated Paths_* module associated with a package-autogenPathsModuleName :: PackageDescription -> ModuleName-autogenPathsModuleName pkg_descr =- ModuleName.fromString $- "Paths_" ++ map fixchar (prettyShow (packageName pkg_descr))- where fixchar '-' = '_'- fixchar c = c--haddockName :: PackageDescription -> FilePath-haddockName pkg_descr = prettyShow (packageName pkg_descr) <.> "haddock"---- -------------------------------------------------------------------------------- Source File helper--getLibSourceFiles :: Verbosity- -> LocalBuildInfo- -> Library- -> ComponentLocalBuildInfo- -> IO [(ModuleName.ModuleName, FilePath)]-getLibSourceFiles verbosity lbi lib clbi = getSourceFiles verbosity searchpaths modules- where- bi = libBuildInfo lib- modules = allLibModules lib clbi- searchpaths = componentBuildDir lbi clbi : hsSourceDirs bi ++- [ autogenComponentModulesDir lbi clbi- , autogenPackageModulesDir lbi ]--getExeSourceFiles :: Verbosity- -> LocalBuildInfo- -> Executable- -> ComponentLocalBuildInfo- -> IO [(ModuleName.ModuleName, FilePath)]-getExeSourceFiles verbosity lbi exe clbi = do- moduleFiles <- getSourceFiles verbosity searchpaths modules- srcMainPath <- findFileEx verbosity (hsSourceDirs bi) (modulePath exe)- return ((ModuleName.main, srcMainPath) : moduleFiles)- where- bi = buildInfo exe- modules = otherModules bi- searchpaths = autogenComponentModulesDir lbi clbi- : autogenPackageModulesDir lbi- : exeBuildDir lbi exe : hsSourceDirs bi--getFLibSourceFiles :: Verbosity- -> LocalBuildInfo- -> ForeignLib- -> ComponentLocalBuildInfo- -> IO [(ModuleName.ModuleName, FilePath)]-getFLibSourceFiles verbosity lbi flib clbi = getSourceFiles verbosity searchpaths modules- where- bi = foreignLibBuildInfo flib- modules = otherModules bi- searchpaths = autogenComponentModulesDir lbi clbi- : autogenPackageModulesDir lbi- : flibBuildDir lbi flib : hsSourceDirs bi--getSourceFiles :: Verbosity -> [FilePath]- -> [ModuleName.ModuleName]- -> IO [(ModuleName.ModuleName, FilePath)]-getSourceFiles verbosity dirs modules = flip traverse modules $ \m -> fmap ((,) m) $- findFileWithExtension ["hs", "lhs", "hsig", "lhsig"] dirs (ModuleName.toFilePath m)- >>= maybe (notFound m) (return . normalise)- where- notFound module_ = die' verbosity $ "can't find source for module " ++ prettyShow module_---- | The directory where we put build results for an executable-exeBuildDir :: LocalBuildInfo -> Executable -> FilePath-exeBuildDir lbi exe = buildDir lbi </> nm </> nm ++ "-tmp"- where- nm = unUnqualComponentName $ exeName exe---- | The directory where we put build results for a foreign library-flibBuildDir :: LocalBuildInfo -> ForeignLib -> FilePath-flibBuildDir lbi flib = buildDir lbi </> nm </> nm ++ "-tmp"- where- nm = unUnqualComponentName $ foreignLibName flib---- ------------------------------------------------------------------------------ Library file names---- | Create a library name for a static library from a given name.--- Prepends @lib@ and appends the static library extension (@.a@).-mkGenericStaticLibName :: String -> String-mkGenericStaticLibName lib = "lib" ++ lib <.> "a"--mkLibName :: UnitId -> String-mkLibName lib = mkGenericStaticLibName (getHSLibraryName lib)--mkProfLibName :: UnitId -> String-mkProfLibName lib = mkGenericStaticLibName (getHSLibraryName lib ++ "_p")---- | Create a library name for a shared library from a given name.--- Prepends @lib@ and appends the @-\<compilerFlavour\>\<compilerVersion\>@--- as well as the shared library extension.-mkGenericSharedLibName :: Platform -> CompilerId -> String -> String-mkGenericSharedLibName platform (CompilerId compilerFlavor compilerVersion) lib- = mconcat [ "lib", lib, "-", comp <.> dllExtension platform ]- where comp = prettyShow compilerFlavor ++ prettyShow compilerVersion---- Implement proper name mangling for dynamical shared objects--- @libHS\<packagename\>-\<compilerFlavour\>\<compilerVersion\>@--- e.g. @libHSbase-2.1-ghc6.6.1.so@-mkSharedLibName :: Platform -> CompilerId -> UnitId -> String-mkSharedLibName platform comp lib- = mkGenericSharedLibName platform comp (getHSLibraryName lib)---- Static libs are named the same as shared libraries, only with--- a different extension.-mkStaticLibName :: Platform -> CompilerId -> UnitId -> String-mkStaticLibName platform (CompilerId compilerFlavor compilerVersion) lib- = "lib" ++ getHSLibraryName lib ++ "-" ++ comp <.> staticLibExtension platform- where comp = prettyShow compilerFlavor ++ prettyShow compilerVersion---- | Create a library name for a bundled shared library from a given name.--- This matches the naming convention for shared libraries as implemented in--- GHC's packageHsLibs function in the Packages module.--- If the given name is prefixed with HS, then this prepends 'lib' and appends--- the compiler flavour/version and shared library extension e.g.:--- "HSrts-1.0" -> "libHSrts-1.0-ghc8.7.20190109.so"--- Otherwise the given name should be prefixed with 'C', then this strips the--- 'C', prepends 'lib' and appends the shared library extension e.g.:--- "Cffi" -> "libffi.so"-mkGenericSharedBundledLibName :: Platform -> CompilerId -> String -> String-mkGenericSharedBundledLibName platform comp lib- | "HS" `isPrefixOf` lib- = mkGenericSharedLibName platform comp lib- | Just lib' <- stripPrefix "C" lib- = "lib" ++ lib' <.> dllExtension platform- | otherwise- = error ("Don't understand library name " ++ lib)---- --------------------------------------------------------------- * Platform file extensions--- ---------------------------------------------------------------- | Default extension for executable files on the current platform.--- (typically @\"\"@ on Unix and @\"exe\"@ on Windows or OS\/2)-exeExtension :: Platform -> String-exeExtension (Platform _arch os) = case os of- Windows -> "exe"- _ -> ""---- | Extension for object files. For GHC the extension is @\"o\"@.-objExtension :: String-objExtension = "o"---- | Extension for dynamically linked (or shared) libraries--- (typically @\"so\"@ on Unix and @\"dll\"@ on Windows)-dllExtension :: Platform -> String-dllExtension (Platform _arch os)= case os of- Windows -> "dll"- OSX -> "dylib"- _ -> "so"---- | Extension for static libraries------ TODO: Here, as well as in dllExtension, it's really the target OS that we're--- interested in, not the build OS.-staticLibExtension :: Platform -> String-staticLibExtension (Platform _arch os) = case os of- Windows -> "lib"- _ -> "a"
− Distribution/Simple/BuildTarget.hs
@@ -1,1063 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Client.BuildTargets--- Copyright : (c) Duncan Coutts 2012--- License : BSD-like------ Maintainer : duncan@community.haskell.org------ Handling for user-specified build targets-------------------------------------------------------------------------------module Distribution.Simple.BuildTarget (- -- * Main interface- readTargetInfos,- readBuildTargets, -- in case you don't have LocalBuildInfo-- -- * Build targets- BuildTarget(..),- showBuildTarget,- QualLevel(..),- buildTargetComponentName,-- -- * Parsing user build targets- UserBuildTarget,- readUserBuildTargets,- showUserBuildTarget,- UserBuildTargetProblem(..),- reportUserBuildTargetProblems,-- -- * Resolving build targets- resolveBuildTargets,- BuildTargetProblem(..),- reportBuildTargetProblems,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.TargetInfo-import Distribution.Types.LocalBuildInfo-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.ForeignLib-import Distribution.Types.UnqualComponentName--import Distribution.Package-import Distribution.PackageDescription-import Distribution.ModuleName-import Distribution.Simple.LocalBuildInfo-import Distribution.Pretty-import Distribution.Parsec-import Distribution.Simple.Utils-import Distribution.Verbosity--import qualified Distribution.Compat.CharParsing as P--import Control.Monad ( msum )-import Data.List ( stripPrefix, groupBy )-import qualified Data.List.NonEmpty as NE-import System.FilePath as FilePath- ( dropExtension, normalise, splitDirectories, joinPath, splitPath- , hasTrailingPathSeparator )-import System.Directory ( doesFileExist, doesDirectoryExist )-import qualified Data.Map as Map---- | Take a list of 'String' build targets, and parse and validate them--- into actual 'TargetInfo's to be built/registered/whatever.-readTargetInfos :: Verbosity -> PackageDescription -> LocalBuildInfo -> [String] -> IO [TargetInfo]-readTargetInfos verbosity pkg_descr lbi args = do- build_targets <- readBuildTargets verbosity pkg_descr args- checkBuildTargets verbosity pkg_descr lbi build_targets---- --------------------------------------------------------------- * User build targets--- ---------------------------------------------------------------- | Various ways that a user may specify a build target.----data UserBuildTarget =-- -- | A target specified by a single name. This could be a component- -- module or file.- --- -- > cabal build foo- -- > cabal build Data.Foo- -- > cabal build Data/Foo.hs Data/Foo.hsc- --- UserBuildTargetSingle String-- -- | A target specified by a qualifier and name. This could be a component- -- name qualified by the component namespace kind, or a module or file- -- qualified by the component name.- --- -- > cabal build lib:foo exe:foo- -- > cabal build foo:Data.Foo- -- > cabal build foo:Data/Foo.hs- --- | UserBuildTargetDouble String String-- -- | A fully qualified target, either a module or file qualified by a- -- component name with the component namespace kind.- --- -- > cabal build lib:foo:Data/Foo.hs exe:foo:Data/Foo.hs- -- > cabal build lib:foo:Data.Foo exe:foo:Data.Foo- --- | UserBuildTargetTriple String String String- deriving (Show, Eq, Ord)----- --------------------------------------------------------------- * Resolved build targets--- ---------------------------------------------------------------- | A fully resolved build target.----data BuildTarget =-- -- | A specific component- --- BuildTargetComponent ComponentName-- -- | A specific module within a specific component.- --- | BuildTargetModule ComponentName ModuleName-- -- | A specific file within a specific component.- --- | BuildTargetFile ComponentName FilePath- deriving (Eq, Show, Generic)--instance Binary BuildTarget--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 :: Verbosity -> PackageDescription -> [String] -> IO [BuildTarget]-readBuildTargets verbosity pkg targetStrs = do- let (uproblems, utargets) = readUserBuildTargets targetStrs- reportUserBuildTargetProblems verbosity uproblems-- utargets' <- traverse checkTargetExistsAsFile utargets-- let (bproblems, btargets) = resolveBuildTargets pkg utargets'- reportBuildTargetProblems verbosity bproblems-- return btargets--checkTargetExistsAsFile :: UserBuildTarget -> IO (UserBuildTarget, Bool)-checkTargetExistsAsFile t = do- fexists <- existsAsFile (fileComponentOfTarget t)- return (t, fexists)-- where- existsAsFile f = do- exists <- doesFileExist f- case splitPath f of- (d:_) | hasTrailingPathSeparator d -> doesDirectoryExist d- (d:_:_) | not exists -> doesDirectoryExist d- _ -> return exists-- fileComponentOfTarget (UserBuildTargetSingle s1) = s1- fileComponentOfTarget (UserBuildTargetDouble _ s2) = s2- fileComponentOfTarget (UserBuildTargetTriple _ _ s3) = s3----- --------------------------------------------------------------- * Parsing user targets--- --------------------------------------------------------------readUserBuildTargets :: [String] -> ([UserBuildTargetProblem]- ,[UserBuildTarget])-readUserBuildTargets = partitionEithers . map readUserBuildTarget---- |------ >>> readUserBuildTarget "comp"--- Right (UserBuildTargetSingle "comp")------ >>> readUserBuildTarget "lib:comp"--- Right (UserBuildTargetDouble "lib" "comp")------ >>> readUserBuildTarget "pkg:lib:comp"--- Right (UserBuildTargetTriple "pkg" "lib" "comp")------ >>> readUserBuildTarget "\"comp\""--- Right (UserBuildTargetSingle "comp")------ >>> readUserBuildTarget "lib:\"comp\""--- Right (UserBuildTargetDouble "lib" "comp")------ >>> readUserBuildTarget "pkg:lib:\"comp\""--- Right (UserBuildTargetTriple "pkg" "lib" "comp")------ >>> readUserBuildTarget "pkg:lib:comp:more"--- Left (UserBuildTargetUnrecognised "pkg:lib:comp:more")------ >>> readUserBuildTarget "pkg:\"lib\":comp"--- Left (UserBuildTargetUnrecognised "pkg:\"lib\":comp")----readUserBuildTarget :: String -> Either UserBuildTargetProblem- UserBuildTarget-readUserBuildTarget targetstr =- case explicitEitherParsec parseTargetApprox targetstr of- Left _ -> Left (UserBuildTargetUnrecognised targetstr)- Right tgt -> Right tgt-- where- parseTargetApprox :: CabalParsing m => m UserBuildTarget- parseTargetApprox = do- -- read one, two, or three tokens, where last could be "hs-string"- ts <- tokens- return $ case ts of- (a, Nothing) -> UserBuildTargetSingle a- (a, Just (b, Nothing)) -> UserBuildTargetDouble a b- (a, Just (b, Just c)) -> UserBuildTargetTriple a b c-- tokens :: CabalParsing m => m (String, Maybe (String, Maybe String))- tokens = (\s -> (s, Nothing)) <$> parsecHaskellString- <|> (,) <$> token <*> P.optional (P.char ':' *> tokens2)-- tokens2 :: CabalParsing m => m (String, Maybe String)- tokens2 = (\s -> (s, Nothing)) <$> parsecHaskellString- <|> (,) <$> token <*> P.optional (P.char ':' *> (parsecHaskellString <|> token))-- token :: CabalParsing m => m String- token = P.munch1 (\x -> not (isSpace x) && x /= ':')--data UserBuildTargetProblem- = UserBuildTargetUnrecognised String- deriving Show--reportUserBuildTargetProblems :: Verbosity -> [UserBuildTargetProblem] -> IO ()-reportUserBuildTargetProblems verbosity problems = do- case [ target | UserBuildTargetUnrecognised target <- problems ] of- [] -> return ()- target ->- die' verbosity $ unlines- [ "Unrecognised build target '" ++ name ++ "'."- | name <- target ]- ++ "Examples:\n"- ++ " - build foo -- component name "- ++ "(library, executable, test-suite or benchmark)\n"- ++ " - build Data.Foo -- module name\n"- ++ " - build Data/Foo.hsc -- file name\n"- ++ " - build lib:foo exe:foo -- component qualified by kind\n"- ++ " - build foo:Data.Foo -- module qualified by component\n"- ++ " - build foo:Data/Foo.hsc -- file qualified by component"--showUserBuildTarget :: UserBuildTarget -> String-showUserBuildTarget = intercalate ":" . getComponents- where- getComponents (UserBuildTargetSingle s1) = [s1]- getComponents (UserBuildTargetDouble s1 s2) = [s1,s2]- getComponents (UserBuildTargetTriple s1 s2 s3) = [s1,s2,s3]---- | Unless you use 'QL1', this function is PARTIAL;--- use 'showBuildTarget' instead.-showBuildTarget' :: QualLevel -> PackageId -> BuildTarget -> String-showBuildTarget' ql pkgid bt =- showUserBuildTarget (renderBuildTarget ql bt pkgid)---- | Unambiguously render a 'BuildTarget', so that it can--- be parsed in all situations.-showBuildTarget :: PackageId -> BuildTarget -> String-showBuildTarget pkgid t =- showBuildTarget' (qlBuildTarget t) pkgid t- where- qlBuildTarget BuildTargetComponent{} = QL2- qlBuildTarget _ = QL3----- --------------------------------------------------------------- * Resolving user targets to build targets--- --------------------------------------------------------------{--stargets =- [ BuildTargetComponent (CExeName "foo")- , BuildTargetModule (CExeName "foo") (mkMn "Foo")- , BuildTargetModule (CExeName "tst") (mkMn "Foo")- ]- where- mkMn :: String -> ModuleName- mkMn = fromJust . simpleParse--ex_pkgid :: PackageIdentifier-Just ex_pkgid = simpleParse "thelib"--}---- | Given a bunch of user-specified targets, try to resolve what it is they--- refer to.----resolveBuildTargets :: PackageDescription- -> [(UserBuildTarget, Bool)]- -> ([BuildTargetProblem], [BuildTarget])-resolveBuildTargets pkg = partitionEithers- . map (uncurry (resolveBuildTarget pkg))--resolveBuildTarget :: PackageDescription -> UserBuildTarget -> Bool- -> Either BuildTargetProblem BuildTarget-resolveBuildTarget pkg userTarget fexists =- case findMatch (matchBuildTarget pkg userTarget fexists) of- Unambiguous target -> Right target- Ambiguous targets -> Left (BuildTargetAmbiguous userTarget targets')- where targets' = disambiguateBuildTargets- (packageId pkg)- userTarget- targets- None errs -> Left (classifyMatchErrors errs)-- where- classifyMatchErrors errs- | Just expected' <- NE.nonEmpty expected- = let (things, got:|_) = NE.unzip expected' in- BuildTargetExpected userTarget (NE.toList things) got- | not (null nosuch) = BuildTargetNoSuch userTarget nosuch- | otherwise = error $ "resolveBuildTarget: internal error in matching"- where- expected = [ (thing, got) | MatchErrorExpected thing got <- errs ]- nosuch = [ (thing, got) | MatchErrorNoSuch thing got <- errs ]---data BuildTargetProblem- = BuildTargetExpected UserBuildTarget [String] String- -- ^ [expected thing] (actually got)- | BuildTargetNoSuch UserBuildTarget [(String, String)]- -- ^ [(no such thing, actually got)]- | BuildTargetAmbiguous UserBuildTarget [(UserBuildTarget, BuildTarget)]- deriving Show---disambiguateBuildTargets :: PackageId -> UserBuildTarget -> [BuildTarget]- -> [(UserBuildTarget, BuildTarget)]-disambiguateBuildTargets pkgid original =- disambiguate (userTargetQualLevel original)- where- disambiguate ql ts- | null amb = unamb- | otherwise = unamb ++ disambiguate (succ ql) amb- where- (amb, unamb) = step ql ts-- userTargetQualLevel (UserBuildTargetSingle _ ) = QL1- userTargetQualLevel (UserBuildTargetDouble _ _ ) = QL2- userTargetQualLevel (UserBuildTargetTriple _ _ _) = QL3-- step :: QualLevel -> [BuildTarget]- -> ([BuildTarget], [(UserBuildTarget, BuildTarget)])- step ql = (\(amb, unamb) -> (map snd $ concat amb, concat unamb))- . partition (\g -> length g > 1)- . groupBy (equating fst)- . sortBy (comparing fst)- . map (\t -> (renderBuildTarget ql t pkgid, t))--data QualLevel = QL1 | QL2 | QL3- deriving (Enum, Show)--renderBuildTarget :: QualLevel -> BuildTarget -> PackageId -> UserBuildTarget-renderBuildTarget ql target pkgid =- case ql of- QL1 -> UserBuildTargetSingle s1 where s1 = single target- QL2 -> UserBuildTargetDouble s1 s2 where (s1, s2) = double target- QL3 -> UserBuildTargetTriple s1 s2 s3 where (s1, s2, s3) = triple target-- where- single (BuildTargetComponent cn ) = dispCName cn- single (BuildTargetModule _ m) = prettyShow m- single (BuildTargetFile _ f) = f-- double (BuildTargetComponent cn ) = (dispKind cn, dispCName cn)- double (BuildTargetModule cn m) = (dispCName cn, prettyShow m)- double (BuildTargetFile cn f) = (dispCName cn, f)-- triple (BuildTargetComponent _ ) = error "triple BuildTargetComponent"- triple (BuildTargetModule cn m) = (dispKind cn, dispCName cn, prettyShow m)- triple (BuildTargetFile cn f) = (dispKind cn, dispCName cn, f)-- dispCName = componentStringName pkgid- dispKind = showComponentKindShort . componentKind--reportBuildTargetProblems :: Verbosity -> [BuildTargetProblem] -> IO ()-reportBuildTargetProblems verbosity problems = do-- case [ (t, e, g) | BuildTargetExpected t e g <- problems ] of- [] -> return ()- targets ->- die' verbosity $ unlines- [ "Unrecognised build target '" ++ showUserBuildTarget target- ++ "'.\n"- ++ "Expected a " ++ intercalate " or " expected- ++ ", rather than '" ++ got ++ "'."- | (target, expected, got) <- targets ]-- case [ (t, e) | BuildTargetNoSuch t e <- problems ] of- [] -> return ()- targets ->- die' verbosity $ unlines- [ "Unknown build target '" ++ showUserBuildTarget target- ++ "'.\nThere is no "- ++ intercalate " or " [ mungeThing thing ++ " '" ++ got ++ "'"- | (thing, got) <- nosuch ] ++ "."- | (target, nosuch) <- targets ]- where- mungeThing "file" = "file target"- mungeThing thing = thing-- case [ (t, ts) | BuildTargetAmbiguous t ts <- problems ] of- [] -> return ()- targets ->- die' verbosity $ unlines- [ "Ambiguous build target '" ++ showUserBuildTarget target- ++ "'. It could be:\n "- ++ unlines [ " "++ showUserBuildTarget ut ++- " (" ++ showBuildTargetKind bt ++ ")"- | (ut, bt) <- amb ]- | (target, amb) <- targets ]-- where- showBuildTargetKind (BuildTargetComponent _ ) = "component"- showBuildTargetKind (BuildTargetModule _ _) = "module"- showBuildTargetKind (BuildTargetFile _ _) = "file"---------------------------------------- Top level BuildTarget matcher-----matchBuildTarget :: PackageDescription- -> UserBuildTarget -> Bool -> Match BuildTarget-matchBuildTarget pkg = \utarget fexists ->- case utarget of- UserBuildTargetSingle str1 ->- matchBuildTarget1 cinfo str1 fexists-- UserBuildTargetDouble str1 str2 ->- matchBuildTarget2 cinfo str1 str2 fexists-- UserBuildTargetTriple str1 str2 str3 ->- matchBuildTarget3 cinfo str1 str2 str3 fexists- where- cinfo = pkgComponentInfo pkg--matchBuildTarget1 :: [ComponentInfo] -> String -> Bool -> Match BuildTarget-matchBuildTarget1 cinfo str1 fexists =- matchComponent1 cinfo str1- `matchPlusShadowing` matchModule1 cinfo str1- `matchPlusShadowing` matchFile1 cinfo str1 fexists---matchBuildTarget2 :: [ComponentInfo] -> String -> String -> Bool- -> Match BuildTarget-matchBuildTarget2 cinfo str1 str2 fexists =- matchComponent2 cinfo str1 str2- `matchPlusShadowing` matchModule2 cinfo str1 str2- `matchPlusShadowing` matchFile2 cinfo str1 str2 fexists---matchBuildTarget3 :: [ComponentInfo] -> String -> String -> String -> Bool- -> Match BuildTarget-matchBuildTarget3 cinfo str1 str2 str3 fexists =- matchModule3 cinfo str1 str2 str3- `matchPlusShadowing` matchFile3 cinfo str1 str2 str3 fexists---data ComponentInfo = ComponentInfo {- cinfoName :: ComponentName,- cinfoStrName :: ComponentStringName,- cinfoSrcDirs :: [FilePath],- cinfoModules :: [ModuleName],- cinfoHsFiles :: [FilePath], -- other hs files (like main.hs)- cinfoAsmFiles:: [FilePath],- cinfoCmmFiles:: [FilePath],- cinfoCFiles :: [FilePath],- cinfoCxxFiles:: [FilePath],- cinfoJsFiles :: [FilePath]- }--type ComponentStringName = String--pkgComponentInfo :: PackageDescription -> [ComponentInfo]-pkgComponentInfo pkg =- [ ComponentInfo {- cinfoName = componentName c,- cinfoStrName = componentStringName pkg (componentName c),- cinfoSrcDirs = hsSourceDirs bi,- cinfoModules = componentModules c,- cinfoHsFiles = componentHsFiles c,- cinfoAsmFiles= asmSources bi,- cinfoCmmFiles= cmmSources bi,- cinfoCFiles = cSources bi,- cinfoCxxFiles= cxxSources bi,- cinfoJsFiles = jsSources bi- }- | c <- pkgComponents pkg- , let bi = componentBuildInfo c ]--componentStringName :: Package pkg => pkg -> ComponentName -> ComponentStringName-componentStringName pkg (CLibName LMainLibName ) = prettyShow (packageName pkg)-componentStringName _ (CLibName (LSubLibName name)) = unUnqualComponentName name-componentStringName _ (CFLibName name) = unUnqualComponentName name-componentStringName _ (CExeName name) = unUnqualComponentName name-componentStringName _ (CTestName name) = unUnqualComponentName name-componentStringName _ (CBenchName name) = unUnqualComponentName name--componentModules :: Component -> [ModuleName]--- TODO: Use of 'explicitLibModules' here is a bit wrong:--- a user could very well ask to build a specific signature--- that was inherited from other packages. To fix this--- we have to plumb 'LocalBuildInfo' through this code.--- Fortunately, this is only used by 'pkgComponentInfo'--- Please don't export this function unless you plan on fixing--- this.-componentModules (CLib lib) = explicitLibModules lib-componentModules (CFLib flib) = foreignLibModules flib-componentModules (CExe exe) = exeModules exe-componentModules (CTest test) = testModules test-componentModules (CBench bench) = benchmarkModules bench--componentHsFiles :: Component -> [FilePath]-componentHsFiles (CExe exe) = [modulePath exe]-componentHsFiles (CTest TestSuite {- testInterface = TestSuiteExeV10 _ mainfile- }) = [mainfile]-componentHsFiles (CBench Benchmark {- benchmarkInterface = BenchmarkExeV10 _ mainfile- }) = [mainfile]-componentHsFiles _ = []--{--ex_cs :: [ComponentInfo]-ex_cs =- [ (mkC (CExeName "foo") ["src1", "src1/src2"] ["Foo", "Src2.Bar", "Bar"])- , (mkC (CExeName "tst") ["src1", "test"] ["Foo"])- ]- where- mkC n ds ms = ComponentInfo n (componentStringName pkgid n) ds (map mkMn ms)- mkMn :: String -> ModuleName- mkMn = fromJust . simpleParse- pkgid :: PackageIdentifier- Just pkgid = simpleParse "thelib"--}----------------------------------- Matching component kinds-----data ComponentKind = LibKind | FLibKind | ExeKind | TestKind | BenchKind- deriving (Eq, Ord, Show, Enum, Bounded)--componentKind :: ComponentName -> ComponentKind-componentKind (CLibName _) = LibKind-componentKind (CFLibName _) = FLibKind-componentKind (CExeName _) = ExeKind-componentKind (CTestName _) = TestKind-componentKind (CBenchName _) = BenchKind--cinfoKind :: ComponentInfo -> ComponentKind-cinfoKind = componentKind . cinfoName--matchComponentKind :: String -> Match ComponentKind-matchComponentKind s- | s `elem` ["lib", "library"] = return' LibKind- | s `elem` ["flib", "foreign-lib", "foreign-library"] = return' FLibKind- | s `elem` ["exe", "executable"] = return' ExeKind- | s `elem` ["tst", "test", "test-suite"] = return' TestKind- | s `elem` ["bench", "benchmark"] = return' BenchKind- | otherwise = matchErrorExpected "component kind" s- where- return' ck = increaseConfidence >> return ck--showComponentKind :: ComponentKind -> String-showComponentKind LibKind = "library"-showComponentKind FLibKind = "foreign-library"-showComponentKind ExeKind = "executable"-showComponentKind TestKind = "test-suite"-showComponentKind BenchKind = "benchmark"--showComponentKindShort :: ComponentKind -> String-showComponentKindShort LibKind = "lib"-showComponentKindShort FLibKind = "flib"-showComponentKindShort ExeKind = "exe"-showComponentKindShort TestKind = "test"-showComponentKindShort BenchKind = "bench"----------------------------------- Matching component targets-----matchComponent1 :: [ComponentInfo] -> String -> Match BuildTarget-matchComponent1 cs = \str1 -> do- guardComponentName str1- c <- matchComponentName cs str1- return (BuildTargetComponent (cinfoName c))--matchComponent2 :: [ComponentInfo] -> String -> String -> Match BuildTarget-matchComponent2 cs = \str1 str2 -> do- ckind <- matchComponentKind str1- guardComponentName str2- c <- matchComponentKindAndName cs ckind str2- return (BuildTargetComponent (cinfoName c))---- utils:--guardComponentName :: String -> Match ()-guardComponentName s- | all validComponentChar s- && not (null s) = increaseConfidence- | otherwise = matchErrorExpected "component name" s- where- validComponentChar c = isAlphaNum c || c == '.'- || c == '_' || c == '-' || c == '\''--matchComponentName :: [ComponentInfo] -> String -> Match ComponentInfo-matchComponentName cs str =- orNoSuchThing "component" str- $ increaseConfidenceFor- $ matchInexactly caseFold- [ (cinfoStrName c, c) | c <- cs ]- str--matchComponentKindAndName :: [ComponentInfo] -> ComponentKind -> String- -> Match ComponentInfo-matchComponentKindAndName cs ckind str =- orNoSuchThing (showComponentKind ckind ++ " component") str- $ increaseConfidenceFor- $ matchInexactly (\(ck, cn) -> (ck, caseFold cn))- [ ((cinfoKind c, cinfoStrName c), c) | c <- cs ]- (ckind, str)------------------------------------ Matching module targets-----matchModule1 :: [ComponentInfo] -> String -> Match BuildTarget-matchModule1 cs = \str1 -> do- guardModuleName str1- nubMatchErrors $ do- c <- tryEach cs- let ms = cinfoModules c- m <- matchModuleName ms str1- return (BuildTargetModule (cinfoName c) m)--matchModule2 :: [ComponentInfo] -> String -> String -> Match BuildTarget-matchModule2 cs = \str1 str2 -> do- guardComponentName str1- guardModuleName str2- c <- matchComponentName cs str1- let ms = cinfoModules c- m <- matchModuleName ms str2- return (BuildTargetModule (cinfoName c) m)--matchModule3 :: [ComponentInfo] -> String -> String -> String- -> Match BuildTarget-matchModule3 cs str1 str2 str3 = do- ckind <- matchComponentKind str1- guardComponentName str2- c <- matchComponentKindAndName cs ckind str2- guardModuleName str3- let ms = cinfoModules c- m <- matchModuleName ms str3- return (BuildTargetModule (cinfoName c) m)---- utils:--guardModuleName :: String -> Match ()-guardModuleName s- | all validModuleChar s- && not (null s) = increaseConfidence- | otherwise = matchErrorExpected "module name" s- where- validModuleChar c = isAlphaNum c || c == '.' || c == '_' || c == '\''--matchModuleName :: [ModuleName] -> String -> Match ModuleName-matchModuleName ms str =- orNoSuchThing "module" str- $ increaseConfidenceFor- $ matchInexactly caseFold- [ (prettyShow m, m)- | m <- ms ]- str------------------------------------ Matching file targets-----matchFile1 :: [ComponentInfo] -> String -> Bool -> Match BuildTarget-matchFile1 cs str1 exists =- nubMatchErrors $ do- c <- tryEach cs- filepath <- matchComponentFile c str1 exists- return (BuildTargetFile (cinfoName c) filepath)---matchFile2 :: [ComponentInfo] -> String -> String -> Bool -> Match BuildTarget-matchFile2 cs str1 str2 exists = do- guardComponentName str1- c <- matchComponentName cs str1- filepath <- matchComponentFile c str2 exists- return (BuildTargetFile (cinfoName c) filepath)---matchFile3 :: [ComponentInfo] -> String -> String -> String -> Bool- -> Match BuildTarget-matchFile3 cs str1 str2 str3 exists = do- ckind <- matchComponentKind str1- guardComponentName str2- c <- matchComponentKindAndName cs ckind str2- filepath <- matchComponentFile c str3 exists- return (BuildTargetFile (cinfoName c) filepath)---matchComponentFile :: ComponentInfo -> String -> Bool -> Match FilePath-matchComponentFile c str fexists =- expecting "file" str $- matchPlus- (matchFileExists str fexists)- (matchPlusShadowing- (msum [ matchModuleFileRooted dirs ms str- , matchOtherFileRooted dirs hsFiles str ])- (msum [ matchModuleFileUnrooted ms str- , matchOtherFileUnrooted hsFiles str- , matchOtherFileUnrooted cFiles str- , matchOtherFileUnrooted jsFiles str ]))- where- dirs = cinfoSrcDirs c- ms = cinfoModules c- hsFiles = cinfoHsFiles c- cFiles = cinfoCFiles c- jsFiles = cinfoJsFiles c----- utils--matchFileExists :: FilePath -> Bool -> Match a-matchFileExists _ False = mzero-matchFileExists fname True = do increaseConfidence- matchErrorNoSuch "file" fname--matchModuleFileUnrooted :: [ModuleName] -> String -> Match FilePath-matchModuleFileUnrooted ms str = do- let filepath = normalise str- _ <- matchModuleFileStem ms filepath- return filepath--matchModuleFileRooted :: [FilePath] -> [ModuleName] -> String -> Match FilePath-matchModuleFileRooted dirs ms str = nubMatches $ do- let filepath = normalise str- filepath' <- matchDirectoryPrefix dirs filepath- _ <- matchModuleFileStem ms filepath'- return filepath--matchModuleFileStem :: [ModuleName] -> FilePath -> Match ModuleName-matchModuleFileStem ms =- increaseConfidenceFor- . matchInexactly caseFold- [ (toFilePath m, m) | m <- ms ]- . dropExtension--matchOtherFileRooted :: [FilePath] -> [FilePath] -> FilePath -> Match FilePath-matchOtherFileRooted dirs fs str = do- let filepath = normalise str- filepath' <- matchDirectoryPrefix dirs filepath- _ <- matchFile fs filepath'- return filepath--matchOtherFileUnrooted :: [FilePath] -> FilePath -> Match FilePath-matchOtherFileUnrooted fs str = do- let filepath = normalise str- _ <- matchFile fs filepath- return filepath--matchFile :: [FilePath] -> FilePath -> Match FilePath-matchFile fs = increaseConfidenceFor- . matchInexactly caseFold [ (f, f) | f <- fs ]--matchDirectoryPrefix :: [FilePath] -> FilePath -> Match FilePath-matchDirectoryPrefix dirs filepath =- exactMatches $- catMaybes- [ stripDirectory (normalise dir) filepath | dir <- dirs ]- where- stripDirectory :: FilePath -> FilePath -> Maybe FilePath- stripDirectory dir fp =- joinPath `fmap` stripPrefix (splitDirectories dir) (splitDirectories fp)------------------------------------ Matching monad------- | A matcher embodies a way to match some input as being some recognised--- value. In particular it deals with multiple and ambiguous matches.------ There are various matcher primitives ('matchExactly', 'matchInexactly'),--- ways to combine matchers ('ambiguousWith', 'shadows') and finally we can--- run a matcher against an input using 'findMatch'.-----data Match a = NoMatch Confidence [MatchError]- | ExactMatch Confidence [a]- | InexactMatch Confidence [a]- deriving Show--type Confidence = Int--data MatchError = MatchErrorExpected String String- | MatchErrorNoSuch String String- deriving (Show, Eq)---instance Alternative Match where- empty = mzero- (<|>) = mplus--instance MonadPlus Match where- mzero = matchZero- mplus = matchPlus--matchZero :: Match a-matchZero = NoMatch 0 []---- | Combine two matchers. Exact matches are used over inexact matches--- but if we have multiple exact, or inexact then the we collect all the--- ambiguous matches.----matchPlus :: Match a -> Match a -> Match a-matchPlus (ExactMatch d1 xs) (ExactMatch d2 xs') =- ExactMatch (max d1 d2) (xs ++ xs')-matchPlus a@(ExactMatch _ _ ) (InexactMatch _ _ ) = a-matchPlus a@(ExactMatch _ _ ) (NoMatch _ _ ) = a-matchPlus (InexactMatch _ _ ) b@(ExactMatch _ _ ) = b-matchPlus (InexactMatch d1 xs) (InexactMatch d2 xs') =- InexactMatch (max d1 d2) (xs ++ xs')-matchPlus a@(InexactMatch _ _ ) (NoMatch _ _ ) = a-matchPlus (NoMatch _ _ ) b@(ExactMatch _ _ ) = b-matchPlus (NoMatch _ _ ) b@(InexactMatch _ _ ) = b-matchPlus a@(NoMatch d1 ms) b@(NoMatch d2 ms')- | d1 > d2 = a- | d1 < d2 = b- | otherwise = NoMatch d1 (ms ++ ms')---- | 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.----matchPlusShadowing :: Match a -> Match a -> Match a-matchPlusShadowing a@(ExactMatch _ _) (ExactMatch _ _) = a-matchPlusShadowing a b = matchPlus a b--instance Functor Match where- fmap _ (NoMatch d ms) = NoMatch d ms- fmap f (ExactMatch d xs) = ExactMatch d (fmap f xs)- fmap f (InexactMatch d xs) = InexactMatch d (fmap f xs)--instance Applicative Match where- pure a = ExactMatch 0 [a]- (<*>) = ap--instance Monad Match where- return = pure-- NoMatch d ms >>= _ = NoMatch d ms- ExactMatch d xs >>= f = addDepth d- $ foldr matchPlus matchZero (map f xs)- InexactMatch d xs >>= f = addDepth d . forceInexact- $ foldr matchPlus matchZero (map f xs)--addDepth :: Confidence -> Match a -> Match a-addDepth d' (NoMatch d msgs) = NoMatch (d'+d) msgs-addDepth d' (ExactMatch d xs) = ExactMatch (d'+d) xs-addDepth d' (InexactMatch d xs) = InexactMatch (d'+d) xs--forceInexact :: Match a -> Match a-forceInexact (ExactMatch d ys) = InexactMatch d ys-forceInexact m = m----------------------------------- Various match primitives-----matchErrorExpected, matchErrorNoSuch :: String -> String -> Match a-matchErrorExpected thing got = NoMatch 0 [MatchErrorExpected thing got]-matchErrorNoSuch thing got = NoMatch 0 [MatchErrorNoSuch thing got]--expecting :: String -> String -> Match a -> Match a-expecting thing got (NoMatch 0 _) = matchErrorExpected thing got-expecting _ _ m = m--orNoSuchThing :: String -> String -> Match a -> Match a-orNoSuchThing thing got (NoMatch 0 _) = matchErrorNoSuch thing got-orNoSuchThing _ _ m = m--increaseConfidence :: Match ()-increaseConfidence = ExactMatch 1 [()]--increaseConfidenceFor :: Match a -> Match a-increaseConfidenceFor m = m >>= \r -> increaseConfidence >> return r--nubMatches :: Eq a => Match a -> Match a-nubMatches (NoMatch d msgs) = NoMatch d msgs-nubMatches (ExactMatch d xs) = ExactMatch d (nub xs)-nubMatches (InexactMatch d xs) = InexactMatch d (nub xs)--nubMatchErrors :: Match a -> Match a-nubMatchErrors (NoMatch d msgs) = NoMatch d (nub msgs)-nubMatchErrors (ExactMatch d xs) = ExactMatch d xs-nubMatchErrors (InexactMatch d xs) = InexactMatch d xs---- | Lift a list of matches to an exact match.----exactMatches, inexactMatches :: [a] -> Match a--exactMatches [] = matchZero-exactMatches xs = ExactMatch 0 xs--inexactMatches [] = matchZero-inexactMatches xs = InexactMatch 0 xs--tryEach :: [a] -> Match a-tryEach = exactMatches------------------------------------ Top level match runner------- | Given a matcher and a key to look up, use the matcher to find all the--- 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 -> MaybeAmbiguous b-findMatch match =- case match of- NoMatch _ msgs -> None (nub msgs)- ExactMatch _ xs -> checkAmbiguous xs- InexactMatch _ xs -> checkAmbiguous xs- where- checkAmbiguous xs = case nub xs of- [x] -> Unambiguous x- xs' -> Ambiguous xs'--data MaybeAmbiguous a = None [MatchError] | Unambiguous a | Ambiguous [a]- deriving Show------------------------------------ Basic matchers-----{---- | A primitive matcher that looks up a value in a finite 'Map'. The--- value must match exactly.----matchExactly :: forall a b. Ord a => [(a, b)] -> (a -> Match b)-matchExactly xs =- \x -> case Map.lookup x m of- Nothing -> matchZero- Just ys -> ExactMatch 0 ys- where- m :: Ord a => Map a [b]- m = Map.fromListWith (++) [ (k,[x]) | (k,x) <- xs ]--}---- | A primitive matcher that looks up a value in a finite 'Map'. It checks--- for an exact or inexact match. We get an inexact match if the match--- is not exact, but the canonical forms match. It takes a canonicalisation--- function for this purpose.------ So for example if we used string case fold as the canonicalisation--- function, then we would get case insensitive matching (but it will still--- report an exact match when the case matches too).----matchInexactly :: (Ord a, Ord a') =>- (a -> a') ->- [(a, b)] -> (a -> Match b)-matchInexactly cannonicalise xs =- \x -> case Map.lookup x m of- Just ys -> exactMatches ys- Nothing -> case Map.lookup (cannonicalise x) m' of- Just ys -> inexactMatches ys- Nothing -> matchZero- where- m = Map.fromListWith (++) [ (k,[x]) | (k,x) <- xs ]-- -- the map of canonicalised keys to groups of inexact matches- m' = Map.mapKeysWith (++) cannonicalise m------------------------------------- Utils-----caseFold :: String -> String-caseFold = lowercase----- | Check that the given build targets are valid in the current context.------ Also swizzle into a more convenient form.----checkBuildTargets :: Verbosity -> PackageDescription -> LocalBuildInfo -> [BuildTarget]- -> IO [TargetInfo]-checkBuildTargets _ pkg_descr lbi [] =- return (allTargetsInBuildOrder' pkg_descr lbi)--checkBuildTargets verbosity pkg_descr lbi targets = do-- let (enabled, disabled) =- partitionEithers- [ case componentDisabledReason (componentEnabledSpec lbi) comp of- Nothing -> Left target'- Just reason -> Right (cname, reason)- | target <- targets- , let target'@(cname,_) = swizzleTarget target- , let comp = getComponent pkg_descr cname ]-- case disabled of- [] -> return ()- ((cname,reason):_) -> die' verbosity $ formatReason (showComponentName cname) reason-- for_ [ (c, t) | (c, Just t) <- enabled ] $ \(c, t) ->- warn verbosity $ "Ignoring '" ++ either prettyShow id t ++ ". The whole "- ++ showComponentName c ++ " will be processed. (Support for "- ++ "module and file targets has not been implemented yet.)"-- -- Pick out the actual CLBIs for each of these cnames- enabled' <- for enabled $ \(cname, _) -> do- case componentNameTargets' pkg_descr lbi cname of- [] -> error "checkBuildTargets: nothing enabled"- [target] -> return target- _targets -> error "checkBuildTargets: multiple copies enabled"-- return enabled'-- where- swizzleTarget (BuildTargetComponent c) = (c, Nothing)- swizzleTarget (BuildTargetModule c m) = (c, Just (Left m))- swizzleTarget (BuildTargetFile c f) = (c, Just (Right f))-- formatReason cn DisabledComponent =- "Cannot process the " ++ cn ++ " because the component is marked "- ++ "as disabled in the .cabal file."- formatReason cn DisabledAllTests =- "Cannot process the " ++ cn ++ " because test suites are not "- ++ "enabled. Run configure with the flag --enable-tests"- formatReason cn DisabledAllBenchmarks =- "Cannot process the " ++ cn ++ " because benchmarks are not "- ++ "enabled. Re-run configure with the flag --enable-benchmarks"- formatReason cn (DisabledAllButOne cn') =- "Cannot process the " ++ cn ++ " because this package was "- ++ "configured only to build " ++ cn' ++ ". Re-run configure "- ++ "with the argument " ++ cn
− Distribution/Simple/BuildToolDepends.hs
@@ -1,93 +0,0 @@--- |------ This modules provides functions for working with both the legacy--- "build-tools" field, and its replacement, "build-tool-depends". Prefer using--- the functions contained to access those fields directly.-module Distribution.Simple.BuildToolDepends where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Data.Map as Map--import Distribution.Package-import Distribution.PackageDescription---- | Desugar a "build-tools" entry into proper a executable dependency if--- possible.------ An entry can be so desguared in two cases:------ 1. The name in build-tools matches a locally defined executable. The--- executable dependency produced is on that exe in the current package.------ 2. The name in build-tools matches a hard-coded set of known tools. For now,--- the executable dependency produced is one an executable in a package of--- the same, but the hard-coding could just as well be per-key.------ The first cases matches first.-desugarBuildTool :: PackageDescription- -> LegacyExeDependency- -> Maybe ExeDependency-desugarBuildTool pkg led =- if foundLocal- then Just $ ExeDependency (packageName pkg) toolName reqVer- else Map.lookup name whiteMap- where- LegacyExeDependency name reqVer = led- toolName = mkUnqualComponentName name- foundLocal = toolName `elem` map exeName (executables pkg)- whitelist = [ "hscolour", "haddock", "happy", "alex", "hsc2hs", "c2hs"- , "cpphs", "greencard", "hspec-discover"- ]- whiteMap = Map.fromList $ flip map whitelist $ \n ->- (n, ExeDependency (mkPackageName n) (mkUnqualComponentName n) reqVer)---- | Get everything from "build-tool-depends", along with entries from--- "build-tools" that we know how to desugar.------ This should almost always be used instead of just accessing the--- `buildToolDepends` field directly.-getAllToolDependencies :: PackageDescription- -> BuildInfo- -> [ExeDependency]-getAllToolDependencies pkg bi =- buildToolDepends bi ++ mapMaybe (desugarBuildTool pkg) (buildTools bi)---- | Does the given executable dependency map to this current package?------ This is a tiny function, but used in a number of places.------ This function is only sound to call on `BuildInfo`s from the given package--- description. This is because it just filters the package names of each--- dependency, and does not check whether version bounds in fact exclude the--- current package, or the referenced components in fact exist in the current--- package.------ This is OK because when a package is loaded, it is checked (in--- `Distribution.Package.Check`) that dependencies matching internal components--- do indeed have version bounds accepting the current package, and any--- depended-on component in the current package actually exists. In fact this--- check is performed by gathering the internal tool dependencies of each--- component of the package according to this module, and ensuring those--- properties on each so-gathered dependency.------ version bounds and components of the package are unchecked. This is because--- we sanitize exe deps so that the matching name implies these other--- conditions.-isInternal :: PackageDescription -> ExeDependency -> Bool-isInternal pkg (ExeDependency n _ _) = n == packageName pkg----- | Get internal "build-tool-depends", along with internal "build-tools"------ This is a tiny function, but used in a number of places. The same--- restrictions that apply to `isInternal` also apply to this function.-getAllInternalToolDependencies :: PackageDescription- -> BuildInfo- -> [UnqualComponentName]-getAllInternalToolDependencies pkg bi =- [ toolname- | dep@(ExeDependency _ toolname _) <- getAllToolDependencies pkg bi- , isInternal pkg dep- ]
− Distribution/Simple/CCompiler.hs
@@ -1,123 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.CCompiler--- Copyright : 2011, Dan Knapp------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This simple package provides types and functions for interacting with--- C compilers. Currently it's just a type enumerating extant C-like--- languages, which we call dialects.--{--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are-met:-- * Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above- copyright notice, this list of conditions and the following- disclaimer in the documentation and/or other materials provided- with the distribution.-- * Neither the name of Isaac Jones nor the names of other- contributors may be used to endorse or promote products derived- from this software without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -}--module Distribution.Simple.CCompiler (- CDialect(..),- cSourceExtensions,- cDialectFilenameExtension,- filenameCDialect- ) where--import Prelude ()-import Distribution.Compat.Prelude--import System.FilePath- ( takeExtension )----- | Represents a dialect of C. The Monoid instance expresses backward--- compatibility, in the sense that 'mappend a b' is the least inclusive--- dialect which both 'a' and 'b' can be correctly interpreted as.-data CDialect = C- | ObjectiveC- | CPlusPlus- | ObjectiveCPlusPlus- deriving (Eq, Show)--instance Monoid CDialect where- mempty = C- mappend = (<>)--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,--- not for header files.-cSourceExtensions :: [String]-cSourceExtensions = ["c", "i", "ii", "m", "mi", "mm", "M", "mii", "cc", "cp",- "cxx", "cpp", "CPP", "c++", "C"]----- | Takes a dialect of C and whether code is intended to be passed through--- the preprocessor, and returns a filename extension for containing that--- code.-cDialectFilenameExtension :: CDialect -> Bool -> String-cDialectFilenameExtension C True = "c"-cDialectFilenameExtension C False = "i"-cDialectFilenameExtension ObjectiveC True = "m"-cDialectFilenameExtension ObjectiveC False = "mi"-cDialectFilenameExtension CPlusPlus True = "cpp"-cDialectFilenameExtension CPlusPlus False = "ii"-cDialectFilenameExtension ObjectiveCPlusPlus True = "mm"-cDialectFilenameExtension ObjectiveCPlusPlus False = "mii"----- | Infers from a filename's extension the dialect of C which it contains,--- and whether it is intended to be passed through the preprocessor.-filenameCDialect :: String -> Maybe (CDialect, Bool)-filenameCDialect filename = do- extension <- case takeExtension filename of- '.':ext -> Just ext- _ -> Nothing- case extension of- "c" -> return (C, True)- "i" -> return (C, False)- "ii" -> return (CPlusPlus, False)- "m" -> return (ObjectiveC, True)- "mi" -> return (ObjectiveC, False)- "mm" -> return (ObjectiveCPlusPlus, True)- "M" -> return (ObjectiveCPlusPlus, True)- "mii" -> return (ObjectiveCPlusPlus, False)- "cc" -> return (CPlusPlus, True)- "cp" -> return (CPlusPlus, True)- "cxx" -> return (CPlusPlus, True)- "cpp" -> return (CPlusPlus, True)- "CPP" -> return (CPlusPlus, True)- "c++" -> return (CPlusPlus, True)- "C" -> return (CPlusPlus, True)- _ -> Nothing
− Distribution/Simple/Command.hs
@@ -1,555 +0,0 @@-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Command--- Copyright : Duncan Coutts 2007--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- 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--- 'CommandUI' abstraction represents one of these sub-commands, with a name,--- description, a set of flags. Commands can be associated with actions and--- run. It handles some common stuff automatically, like the @--help@ and--- command line completion flags. It is designed to allow other tools make--- derived commands. This feature is used heavily in @cabal-install@.--module Distribution.Simple.Command (-- -- * Command interface- CommandUI(..),- commandShowOptions,- CommandParse(..),- commandParseArgs,- getNormalCommandDescriptions,- helpCommandUI,-- -- ** Constructing commands- ShowOrParseArgs(..),- usageDefault,- usageAlternatives,- mkCommandUI,- hiddenCommand,-- -- ** Associating actions with commands- Command,- commandAddAction,- noExtraFlags,-- -- ** Building lists of commands- CommandType(..),- CommandSpec(..),- commandFromSpec,-- -- ** Running commands- commandsRun,---- * Option Fields- OptionField(..), Name,---- ** Constructing Option Fields- option, multiOption,---- ** Liftings & Projections- liftOption, liftOptionL,---- * Option Descriptions- OptDescr(..), Description, SFlags, LFlags, OptFlags, ArgPlaceHolder,---- ** OptDescr 'smart' constructors- MkOptDescr,- reqArg, reqArg', optArg, optArg', noArg,- boolOpt, boolOpt', choiceOpt, choiceOptFromEnum-- ) where--import Prelude ()-import Distribution.Compat.Prelude hiding (get)--import qualified Distribution.GetOpt as GetOpt-import Distribution.ReadE-import Distribution.Simple.Utils-import Distribution.Compat.Lens (ALens', (^#), (#~))---data CommandUI flags = CommandUI {- -- | The name of the command as it would be entered on the command line.- -- For example @\"build\"@.- commandName :: String,- -- | A short, one line description of the command to use in help texts.- commandSynopsis :: String,- -- | A function that maps a program name to a usage summary for this- -- command.- commandUsage :: String -> String,- -- | Additional explanation of the command to use in help texts.- commandDescription :: Maybe (String -> String),- -- | Post-Usage notes and examples in help texts- commandNotes :: Maybe (String -> String),- -- | Initial \/ empty flags- commandDefaultFlags :: flags,- -- | All the Option fields for this command- commandOptions :: ShowOrParseArgs -> [OptionField flags]- }--data ShowOrParseArgs = ShowArgs | ParseArgs-type Name = String-type Description = String---- | We usually have a data type for storing configuration values, where--- every field stores a configuration option, and the user sets--- the value either via command line flags or a configuration file.--- An individual OptionField models such a field, and we usually--- build a list of options associated to a configuration data type.-data OptionField a = OptionField {- optionName :: Name,- optionDescr :: [OptDescr a] }---- | An OptionField takes one or more OptDescrs, describing the command line--- interface for the field.-data OptDescr a = ReqArg Description OptFlags ArgPlaceHolder- (ReadE (a->a)) (a -> [String])-- | OptArg Description OptFlags ArgPlaceHolder- (ReadE (a->a)) (a->a) (a -> [Maybe String])-- | ChoiceOpt [(Description, OptFlags, a->a, a -> Bool)]-- | BoolOpt Description OptFlags{-True-} OptFlags{-False-}- (Bool -> a -> a) (a-> Maybe Bool)---- | Short command line option strings-type SFlags = [Char]--- | Long command line option strings-type LFlags = [String]-type OptFlags = (SFlags,LFlags)-type ArgPlaceHolder = String----- | Create an option taking a single OptDescr.--- No explicit Name is given for the Option, the name is the first LFlag given.-option :: SFlags -> LFlags -> Description -> get -> set -> MkOptDescr get set a- -> OptionField a-option sf lf@(n:_) d get set arg = OptionField n [arg sf lf d get set]-option _ _ _ _ _ _ = error $ "Distribution.command.option: "- ++ "An OptionField must have at least one LFlag"---- | Create an option taking several OptDescrs.--- You will have to give the flags and description individually to the--- OptDescr constructor.-multiOption :: Name -> get -> set- -> [get -> set -> OptDescr a] -- ^MkOptDescr constructors partially- -- applied to flags and description.- -> OptionField a-multiOption n get set args = OptionField n [arg get set | arg <- args]--type MkOptDescr get set a = SFlags -> LFlags -> Description -> get -> set- -> OptDescr a---- | Create a string-valued command line interface.-reqArg :: Monoid b => ArgPlaceHolder -> ReadE b -> (b -> [String])- -> MkOptDescr (a -> b) (b -> a -> a) a-reqArg ad mkflag showflag sf lf d get set =- ReqArg d (sf,lf) ad (fmap (\a b -> set (get b `mappend` a) b) mkflag)- (showflag . get)---- | Create a string-valued command line interface with a default value.-optArg :: Monoid b => ArgPlaceHolder -> ReadE b -> b -> (b -> [Maybe String])- -> MkOptDescr (a -> b) (b -> a -> a) a-optArg ad mkflag def showflag sf lf d get set =- OptArg d (sf,lf) ad (fmap (\a b -> set (get b `mappend` a) b) mkflag)- (\b -> set (get b `mappend` def) b)- (showflag . get)---- | (String -> a) variant of "reqArg"-reqArg' :: Monoid b => ArgPlaceHolder -> (String -> b) -> (b -> [String])- -> MkOptDescr (a -> b) (b -> a -> a) a-reqArg' ad mkflag showflag =- reqArg ad (succeedReadE mkflag) showflag---- | (String -> a) variant of "optArg"-optArg' :: 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) => 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- -> MkOptDescr (a -> b) (b -> a -> a) a-boolOpt g s sfT sfF _sf _lf@(n:_) d get set =- BoolOpt d (sfT, ["enable-"++n]) (sfF, ["disable-"++n]) (set.s) (g.get)-boolOpt _ _ _ _ _ _ _ _ _ = error- "Distribution.Simple.Setup.boolOpt: unreachable"--boolOpt' :: (b -> Maybe Bool) -> (Bool -> b) -> OptFlags -> OptFlags- -> MkOptDescr (a -> b) (b -> a -> a) a-boolOpt' g s ffT ffF _sf _lf d get set = BoolOpt d ffT ffF (set.s) (g . get)---- | create a Choice option-choiceOpt :: Eq b => [(b,OptFlags,Description)]- -> MkOptDescr (a -> b) (b -> a -> a) a-choiceOpt aa_ff _sf _lf _d get set = ChoiceOpt alts- where alts = [(d,flags, set alt, (==alt) . get) | (alt,flags,d) <- aa_ff]---- | create a Choice option out of an enumeration type.--- As long flags, the Show output is used. As short flags, the first character--- which does not conflict with a previous one is used.-choiceOptFromEnum :: (Bounded b, Enum b, Show b, Eq b) =>- MkOptDescr (a -> b) (b -> a -> a) a-choiceOptFromEnum _sf _lf d get =- choiceOpt [ (x, (sf, [map toLower $ show x]), d')- | (x, sf) <- sflags'- , let d' = d ++ show x]- _sf _lf d get- where sflags' = foldl f [] [firstOne..]- f prev x = let prevflags = concatMap snd prev in- prev ++ take 1 [(x, [toLower sf])- | sf <- show x, isAlpha sf- , toLower sf `notElem` prevflags]- firstOne = minBound `asTypeOf` get undefined--commandGetOpts :: ShowOrParseArgs -> CommandUI flags- -> [GetOpt.OptDescr (flags -> flags)]-commandGetOpts showOrParse command =- concatMap viewAsGetOpt (commandOptions command showOrParse)--viewAsGetOpt :: OptionField a -> [GetOpt.OptDescr (a->a)]-viewAsGetOpt (OptionField _n aa) = concatMap optDescrToGetOpt aa- where- optDescrToGetOpt (ReqArg d (cs,ss) arg_desc set _) =- [GetOpt.Option cs ss (GetOpt.ReqArg set' arg_desc) d]- where set' = readEOrFail set- optDescrToGetOpt (OptArg d (cs,ss) arg_desc set def _) =- [GetOpt.Option cs ss (GetOpt.OptArg set' arg_desc) d]- where set' Nothing = def- set' (Just txt) = readEOrFail set txt- optDescrToGetOpt (ChoiceOpt alts) =- [GetOpt.Option sf lf (GetOpt.NoArg set) d | (d,(sf,lf),set,_) <- alts ]- optDescrToGetOpt (BoolOpt d (sfT, lfT) ([], []) set _) =- [ GetOpt.Option sfT lfT (GetOpt.NoArg (set True)) d ]- optDescrToGetOpt (BoolOpt d ([], []) (sfF, lfF) set _) =- [ GetOpt.Option sfF lfF (GetOpt.NoArg (set False)) d ]- optDescrToGetOpt (BoolOpt d (sfT,lfT) (sfF, lfF) set _) =- [ GetOpt.Option sfT lfT (GetOpt.NoArg (set True)) ("Enable " ++ d)- , GetOpt.Option sfF lfF (GetOpt.NoArg (set False)) ("Disable " ++ d) ]--getCurrentChoice :: OptDescr a -> a -> [String]-getCurrentChoice (ChoiceOpt alts) a =- [ lf | (_,(_sf,lf:_), _, currentChoice) <- alts, currentChoice a]--getCurrentChoice _ _ = error "Command.getChoice: expected a Choice OptDescr"---liftOption :: (b -> a) -> (a -> (b -> b)) -> OptionField a -> OptionField b-liftOption get' set' opt =- opt { optionDescr = liftOptDescr get' set' `map` optionDescr opt}---- | @since 3.4.0.0-liftOptionL :: ALens' b a -> OptionField a -> OptionField b-liftOptionL l = liftOption (^# l) (l #~)---liftOptDescr :: (b -> a) -> (a -> (b -> b)) -> OptDescr a -> OptDescr b-liftOptDescr get' set' (ChoiceOpt opts) =- ChoiceOpt [ (d, ff, liftSet get' set' set , (get . get'))- | (d, ff, set, get) <- opts]--liftOptDescr get' set' (OptArg d ff ad set def get) =- OptArg d ff ad (liftSet get' set' `fmap` set)- (liftSet get' set' def) (get . get')--liftOptDescr get' set' (ReqArg d ff ad set get) =- ReqArg d ff ad (liftSet get' set' `fmap` set) (get . get')--liftOptDescr get' set' (BoolOpt d ffT ffF set get) =- BoolOpt d ffT ffF (liftSet get' set' . set) (get . get')--liftSet :: (b -> a) -> (a -> (b -> b)) -> (a -> a) -> b -> b-liftSet get' set' set x = set' (set $ get' x) x---- | Show flags in the standard long option command line format-commandShowOptions :: CommandUI flags -> flags -> [String]-commandShowOptions command v = concat- [ showOptDescr v od | o <- commandOptions command ParseArgs- , od <- optionDescr o]- where- maybePrefix [] = []- maybePrefix (lOpt:_) = ["--" ++ lOpt]-- showOptDescr :: a -> OptDescr a -> [String]- showOptDescr x (BoolOpt _ (_,lfTs) (_,lfFs) _ enabled)- = case enabled x of- Nothing -> []- Just True -> maybePrefix lfTs- Just False -> maybePrefix lfFs- showOptDescr x c@ChoiceOpt{}- = ["--" ++ val | val <- getCurrentChoice c x]- showOptDescr x (ReqArg _ (_ssff,lf:_) _ _ showflag)- = [ "--"++lf++"="++flag- | flag <- showflag x ]- showOptDescr x (OptArg _ (_ssff,lf:_) _ _ _ showflag)- = [ case flag of- Just s -> "--"++lf++"="++s- Nothing -> "--"++lf- | flag <- showflag x ]- showOptDescr _ _- = error "Distribution.Simple.Command.showOptDescr: unreachable"---commandListOptions :: CommandUI flags -> [String]-commandListOptions command =- concatMap listOption $- addCommonFlags ShowArgs $ -- This is a slight hack, we don't want- -- "--list-options" showing up in the- -- list options output, so use ShowArgs- commandGetOpts ShowArgs command- where- listOption (GetOpt.Option shortNames longNames _ _) =- [ "-" ++ [name] | name <- shortNames ]- ++ [ "--" ++ name | name <- longNames ]---- | The help text for this command with descriptions of all the options.-commandHelp :: CommandUI flags -> String -> String-commandHelp command pname =- commandSynopsis command- ++ "\n\n"- ++ commandUsage command pname- ++ ( case commandDescription command of- Nothing -> ""- Just desc -> '\n': desc pname)- ++ "\n"- ++ ( if cname == ""- then "Global flags:"- else "Flags for " ++ cname ++ ":" )- ++ ( GetOpt.usageInfo ""- . addCommonFlags ShowArgs- $ commandGetOpts ShowArgs command )- ++ ( case commandNotes command of- Nothing -> ""- Just notes -> '\n': notes pname)- where cname = commandName command---- | Default "usage" documentation text for commands.-usageDefault :: String -> String -> String-usageDefault name pname =- "Usage: " ++ pname ++ " " ++ name ++ " [FLAGS]\n\n"- ++ "Flags for " ++ name ++ ":"---- | Create "usage" documentation from a list of parameter--- configurations.-usageAlternatives :: String -> [String] -> String -> String-usageAlternatives name strs pname = unlines- [ start ++ pname ++ " " ++ name ++ " " ++ s- | let starts = "Usage: " : repeat " or: "- , (start, s) <- zip starts strs- ]---- | Make a Command from standard 'GetOpt' options.-mkCommandUI :: String -- ^ name- -> String -- ^ synopsis- -> [String] -- ^ usage alternatives- -> flags -- ^ initial\/empty flags- -> (ShowOrParseArgs -> [OptionField flags]) -- ^ options- -> CommandUI flags-mkCommandUI name synopsis usages flags options = CommandUI- { commandName = name- , commandSynopsis = synopsis- , commandDescription = Nothing- , commandNotes = Nothing- , commandUsage = usageAlternatives name usages- , commandDefaultFlags = flags- , commandOptions = options- }---- | Common flags that apply to every command-data CommonFlag = HelpFlag | ListOptionsFlag--commonFlags :: ShowOrParseArgs -> [GetOpt.OptDescr CommonFlag]-commonFlags showOrParseArgs = case showOrParseArgs of- ShowArgs -> [help]- ParseArgs -> [help, list]- where- help = GetOpt.Option helpShortFlags ["help"] (GetOpt.NoArg HelpFlag)- "Show this help text"- helpShortFlags = case showOrParseArgs of- ShowArgs -> ['h']- ParseArgs -> ['h', '?']- list = GetOpt.Option [] ["list-options"] (GetOpt.NoArg ListOptionsFlag)- "Print a list of command line flags"--addCommonFlags :: ShowOrParseArgs- -> [GetOpt.OptDescr a]- -> [GetOpt.OptDescr (Either CommonFlag a)]-addCommonFlags showOrParseArgs options =- map (fmapOptDesc Left) (commonFlags showOrParseArgs)- ++ map (fmapOptDesc Right) options- where fmapOptDesc f (GetOpt.Option s l d m) =- GetOpt.Option s l (fmapArgDesc f d) m- fmapArgDesc f (GetOpt.NoArg a) = GetOpt.NoArg (f a)- fmapArgDesc f (GetOpt.ReqArg s d) = GetOpt.ReqArg (f . s) d- fmapArgDesc f (GetOpt.OptArg s d) = GetOpt.OptArg (f . s) d---- | Parse a bunch of command line arguments----commandParseArgs :: CommandUI flags- -> Bool -- ^ Is the command a global or subcommand?- -> [String]- -> CommandParse (flags -> flags, [String])-commandParseArgs command global args =- let options = addCommonFlags ParseArgs- $ commandGetOpts ParseArgs command- order | global = GetOpt.RequireOrder- | otherwise = GetOpt.Permute- in case GetOpt.getOpt' order options args of- (flags, _, _, _)- | any listFlag flags -> CommandList (commandListOptions command)- | any helpFlag flags -> CommandHelp (commandHelp command)- where listFlag (Left ListOptionsFlag) = True; listFlag _ = False- helpFlag (Left HelpFlag) = True; helpFlag _ = False- (flags, opts, opts', [])- | global || null opts' -> CommandReadyToGo (accum flags, mix opts opts')- | otherwise -> CommandErrors (unrecognised opts')- (_, _, _, errs) -> CommandErrors errs-- where -- Note: It is crucial to use reverse function composition here or to- -- reverse the flags here as we want to process the flags left to right- -- but data flow in function composition is right to left.- accum flags = foldr (flip (.)) id [ f | Right f <- flags ]- unrecognised opts = [ "unrecognized "- ++ "'" ++ (commandName command) ++ "'"- ++ " option `" ++ opt ++ "'\n"- | opt <- opts ]- -- For unrecognised global flags we put them in the position just after- -- the command, if there is one. This gives us a chance to parse them- -- as sub-command rather than global flags.- mix [] ys = ys- mix (x:xs) ys = x:ys++xs--data CommandParse flags = CommandHelp (String -> String)- | CommandList [String]- | CommandErrors [String]- | CommandReadyToGo flags-instance Functor CommandParse where- fmap _ (CommandHelp help) = CommandHelp help- fmap _ (CommandList opts) = CommandList opts- fmap _ (CommandErrors errs) = CommandErrors errs- fmap f (CommandReadyToGo flags) = CommandReadyToGo (f flags)---data CommandType = NormalCommand | HiddenCommand-data Command action =- Command String String ([String] -> CommandParse action) CommandType---- | Mark command as hidden. Hidden commands don't show up in the 'progname--- help' or 'progname --help' output.-hiddenCommand :: Command action -> Command action-hiddenCommand (Command name synopsys f _cmdType) =- Command name synopsys f HiddenCommand--commandAddAction :: CommandUI flags- -> (flags -> [String] -> action)- -> Command action-commandAddAction command action =- Command (commandName command)- (commandSynopsis command)- (fmap (uncurry applyDefaultArgs) . commandParseArgs command False)- NormalCommand-- where applyDefaultArgs mkflags args =- let flags = mkflags (commandDefaultFlags command)- in action flags args--commandsRun :: CommandUI a- -> [Command action]- -> [String]- -> CommandParse (a, CommandParse action)-commandsRun globalCommand commands args =- case commandParseArgs globalCommand True args of- CommandHelp help -> CommandHelp help- CommandList opts -> CommandList (opts ++ commandNames)- CommandErrors errs -> CommandErrors errs- CommandReadyToGo (mkflags, args') -> case args' of- ("help":cmdArgs) -> handleHelpCommand cmdArgs- (name:cmdArgs) -> case lookupCommand name of- [Command _ _ action _]- -> CommandReadyToGo (flags, action cmdArgs)- _ -> CommandReadyToGo (flags, badCommand name)- [] -> CommandReadyToGo (flags, noCommand)- where flags = mkflags (commandDefaultFlags globalCommand)-- where- lookupCommand cname = [ cmd | cmd@(Command cname' _ _ _) <- commands'- , cname' == cname ]- noCommand = CommandErrors ["no command given (try --help)\n"]- badCommand cname = CommandErrors ["unrecognised command: " ++ cname- ++ " (try --help)\n"]- commands' = commands ++ [commandAddAction helpCommandUI undefined]- commandNames = [ name | (Command name _ _ NormalCommand) <- commands' ]-- -- A bit of a hack: support "prog help" as a synonym of "prog --help"- -- furthermore, support "prog help command" as "prog command --help"- handleHelpCommand cmdArgs =- case commandParseArgs helpCommandUI True cmdArgs of- CommandHelp help -> CommandHelp help- CommandList list -> CommandList (list ++ commandNames)- CommandErrors _ -> CommandHelp globalHelp- CommandReadyToGo (_,[]) -> CommandHelp globalHelp- CommandReadyToGo (_,(name:cmdArgs')) ->- case lookupCommand name of- [Command _ _ action _] ->- case action ("--help":cmdArgs') of- CommandHelp help -> CommandHelp help- CommandList _ -> CommandList []- _ -> CommandHelp globalHelp- _ -> badCommand name-- where globalHelp = commandHelp globalCommand---- | Utility function, many commands do not accept additional flags. This--- action fails with a helpful error message if the user supplies any extra.----noExtraFlags :: [String] -> IO ()-noExtraFlags [] = return ()-noExtraFlags extraFlags =- dieNoVerbosity $ "Unrecognised flags: " ++ intercalate ", " extraFlags---TODO: eliminate this function and turn it into a variant on commandAddAction--- instead like commandAddActionNoArgs that doesn't supply the [String]---- | Helper function for creating globalCommand description-getNormalCommandDescriptions :: [Command action] -> [(String, String)]-getNormalCommandDescriptions cmds =- [ (name, description)- | Command name description _ NormalCommand <- cmds ]--helpCommandUI :: CommandUI ()-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
@@ -1,453 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveDataTypeable #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Compiler--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This should be a much more sophisticated abstraction than it is. Currently--- it's just a bit of data about the compiler, like its flavour and name and--- version. The reason it's just data is because currently it has to be in--- 'Read' and 'Show' so it can be saved along with the 'LocalBuildInfo'. The--- only interesting bit of info it contains is a mapping between language--- extensions and compiler command line flags. This module also defines a--- 'PackageDB' type which is used to refer to package databases. Most compilers--- only know about a single global package collection but GHC has a global and--- per-user one and it lets you create arbitrary other package databases. We do--- not yet fully support this latter feature.--module Distribution.Simple.Compiler (- -- * Haskell implementations- module Distribution.Compiler,- Compiler(..),- showCompilerId, showCompilerIdWithAbi,- compilerFlavor, compilerVersion,- compilerCompatFlavor,- compilerCompatVersion,- compilerInfo,-- -- * Support for package databases- PackageDB(..),- PackageDBStack,- registrationPackageDB,- absolutePackageDBPaths,- absolutePackageDBPath,-- -- * Support for optimisation levels- OptimisationLevel(..),- flagToOptimisationLevel,-- -- * Support for debug info levels- DebugInfoLevel(..),- flagToDebugInfoLevel,-- -- * Support for language extensions- CompilerFlag,- languageToFlags,- unsupportedLanguages,- extensionsToFlags,- unsupportedExtensions,- parmakeSupported,- reexportedModulesSupported,- renamingPackageFlagsSupported,- unifiedIPIDRequired,- packageKeySupported,- unitIdSupported,- coverageSupported,- profilingSupported,- backpackSupported,- arResponseFilesSupported,- libraryDynDirSupported,- libraryVisibilitySupported,-- -- * Support for profiling detail levels- ProfDetailLevel(..),- knownProfDetailLevels,- flagToProfDetailLevel,- showProfDetailLevel,- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Pretty--import Distribution.Compiler-import Distribution.Version-import Language.Haskell.Extension-import Distribution.Simple.Utils--import qualified Data.Map as Map (lookup)-import System.Directory (canonicalizePath)--data Compiler = Compiler {- compilerId :: CompilerId,- -- ^ Compiler flavour and version.- compilerAbiTag :: AbiTag,- -- ^ Tag for distinguishing incompatible ABI's on the same- -- architecture/os.- compilerCompat :: [CompilerId],- -- ^ Other implementations that this compiler claims to be- -- compatible with.- compilerLanguages :: [(Language, CompilerFlag)],- -- ^ Supported language standards.- compilerExtensions :: [(Extension, Maybe CompilerFlag)],- -- ^ Supported extensions.- compilerProperties :: Map String String- -- ^ A key-value map for properties not covered by the above fields.- }- deriving (Eq, Generic, Typeable, Show, Read)--instance Binary Compiler-instance Structured Compiler--showCompilerId :: Compiler -> String-showCompilerId = prettyShow . compilerId--showCompilerIdWithAbi :: Compiler -> String-showCompilerIdWithAbi comp =- prettyShow (compilerId comp) ++- case compilerAbiTag comp of- NoAbiTag -> []- AbiTag xs -> '-':xs--compilerFlavor :: Compiler -> CompilerFlavor-compilerFlavor = (\(CompilerId f _) -> f) . compilerId--compilerVersion :: Compiler -> Version-compilerVersion = (\(CompilerId _ v) -> v) . compilerId----- | Is this compiler compatible with the compiler flavour we're interested in?------ For example this checks if the compiler is actually GHC or is another--- compiler that claims to be compatible with some version of GHC, e.g. GHCJS.------ > if compilerCompatFlavor GHC compiler then ... else ...----compilerCompatFlavor :: CompilerFlavor -> Compiler -> Bool-compilerCompatFlavor flavor comp =- flavor == compilerFlavor comp- || flavor `elem` [ flavor' | CompilerId flavor' _ <- compilerCompat comp ]----- | Is this compiler compatible with the compiler flavour we're interested in,--- and if so what version does it claim to be compatible with.------ For example this checks if the compiler is actually GHC-7.x or is another--- compiler that claims to be compatible with some GHC-7.x version.------ > case compilerCompatVersion GHC compiler of--- > Just (Version (7:_)) -> ...--- > _ -> ...----compilerCompatVersion :: CompilerFlavor -> Compiler -> Maybe Version-compilerCompatVersion flavor comp- | compilerFlavor comp == flavor = Just (compilerVersion comp)- | otherwise =- listToMaybe [ v | CompilerId fl v <- compilerCompat comp, fl == flavor ]--compilerInfo :: Compiler -> CompilerInfo-compilerInfo c = CompilerInfo (compilerId c)- (compilerAbiTag c)- (Just . compilerCompat $ c)- (Just . map fst . compilerLanguages $ c)- (Just . map fst . compilerExtensions $ c)---- --------------------------------------------------------------- * Package databases--- ---------------------------------------------------------------- |Some compilers have a notion of a database of available packages.--- For some there is just one global db of packages, other compilers--- support a per-user or an arbitrary db specified at some location in--- the file system. This can be used to build isloated environments of--- packages, for example to build a collection of related packages--- without installing them globally.----data PackageDB = GlobalPackageDB- | UserPackageDB- | SpecificPackageDB FilePath- deriving (Eq, Generic, Ord, Show, Read, Typeable)--instance Binary PackageDB-instance Structured PackageDB---- | We typically get packages from several databases, and stack them--- together. This type lets us be explicit about that stacking. For example--- typical stacks include:------ > [GlobalPackageDB]--- > [GlobalPackageDB, UserPackageDB]--- > [GlobalPackageDB, SpecificPackageDB "package.conf.inplace"]------ Note that the 'GlobalPackageDB' is invariably at the bottom since it--- contains the rts, base and other special compiler-specific packages.------ We are not restricted to using just the above combinations. In particular--- we can use several custom package dbs and the user package db together.------ When it comes to writing, the top most (last) package is used.----type PackageDBStack = [PackageDB]---- | Return the package that we should register into. This is the package db at--- the top of the stack.----registrationPackageDB :: PackageDBStack -> PackageDB-registrationPackageDB dbs = case safeLast dbs of- Nothing -> error "internal error: empty package db set"- Just p -> p---- | Make package paths absolute---absolutePackageDBPaths :: PackageDBStack -> IO PackageDBStack-absolutePackageDBPaths = traverse absolutePackageDBPath--absolutePackageDBPath :: PackageDB -> IO PackageDB-absolutePackageDBPath GlobalPackageDB = return GlobalPackageDB-absolutePackageDBPath UserPackageDB = return UserPackageDB-absolutePackageDBPath (SpecificPackageDB db) =- SpecificPackageDB `liftM` canonicalizePath db---- --------------------------------------------------------------- * Optimisation levels--- ---------------------------------------------------------------- | Some compilers support optimising. Some have different levels.--- For compilers that do not the level is just capped to the level--- they do support.----data OptimisationLevel = NoOptimisation- | NormalOptimisation- | MaximumOptimisation- deriving (Bounded, Enum, Eq, Generic, Read, Show, Typeable)--instance Binary OptimisationLevel-instance Structured OptimisationLevel--flagToOptimisationLevel :: Maybe String -> OptimisationLevel-flagToOptimisationLevel Nothing = NormalOptimisation-flagToOptimisationLevel (Just s) = case reads s of- [(i, "")]- | i >= fromEnum (minBound :: OptimisationLevel)- && i <= fromEnum (maxBound :: OptimisationLevel)- -> toEnum i- | otherwise -> error $ "Bad optimisation level: " ++ show i- ++ ". Valid values are 0..2"- _ -> error $ "Can't parse optimisation level " ++ s---- --------------------------------------------------------------- * Debug info levels--- ---------------------------------------------------------------- | Some compilers support emitting debug info. Some have different--- levels. For compilers that do not the level is just capped to the--- level they do support.----data DebugInfoLevel = NoDebugInfo- | MinimalDebugInfo- | NormalDebugInfo- | MaximalDebugInfo- deriving (Bounded, Enum, Eq, Generic, Read, Show, Typeable)--instance Binary DebugInfoLevel-instance Structured DebugInfoLevel--flagToDebugInfoLevel :: Maybe String -> DebugInfoLevel-flagToDebugInfoLevel Nothing = NormalDebugInfo-flagToDebugInfoLevel (Just s) = case reads s of- [(i, "")]- | i >= fromEnum (minBound :: DebugInfoLevel)- && i <= fromEnum (maxBound :: DebugInfoLevel)- -> toEnum i- | otherwise -> error $ "Bad debug info level: " ++ show i- ++ ". Valid values are 0..3"- _ -> error $ "Can't parse debug info level " ++ s---- --------------------------------------------------------------- * Languages and Extensions--- --------------------------------------------------------------unsupportedLanguages :: Compiler -> [Language] -> [Language]-unsupportedLanguages comp langs =- [ lang | lang <- langs- , isNothing (languageToFlag comp lang) ]--languageToFlags :: Compiler -> Maybe Language -> [CompilerFlag]-languageToFlags comp = filter (not . null)- . catMaybes . map (languageToFlag comp)- . maybe [Haskell98] (\x->[x])--languageToFlag :: Compiler -> Language -> Maybe CompilerFlag-languageToFlag comp ext = lookup ext (compilerLanguages comp)----- |For the given compiler, return the extensions it does not support.-unsupportedExtensions :: Compiler -> [Extension] -> [Extension]-unsupportedExtensions comp exts =- [ ext | ext <- exts- , isNothing (extensionToFlag' comp ext) ]--type CompilerFlag = String---- |For the given compiler, return the flags for the supported extensions.-extensionsToFlags :: Compiler -> [Extension] -> [CompilerFlag]-extensionsToFlags comp = nub . filter (not . null)- . catMaybes . map (extensionToFlag comp)---- | Looks up the flag for a given extension, for a given compiler.--- Ignores the subtlety of extensions which lack associated flags.-extensionToFlag :: Compiler -> Extension -> Maybe CompilerFlag-extensionToFlag comp ext = join (extensionToFlag' comp ext)---- | Looks up the flag for a given extension, for a given compiler.--- However, the extension may be valid for the compiler but not have a flag.--- For example, NondecreasingIndentation is enabled by default on GHC 7.0.4,--- hence it is considered a supported extension but not an accepted flag.------ The outer layer of Maybe indicates whether the extensions is supported, while--- the inner layer indicates whether it has a flag.--- When building strings, it is often more convenient to use 'extensionToFlag',--- which ignores the difference.-extensionToFlag' :: Compiler -> Extension -> Maybe (Maybe CompilerFlag)-extensionToFlag' comp ext = lookup ext (compilerExtensions comp)---- | Does this compiler support parallel --make mode?-parmakeSupported :: Compiler -> Bool-parmakeSupported = ghcSupported "Support parallel --make"---- | Does this compiler support reexported-modules?-reexportedModulesSupported :: Compiler -> Bool-reexportedModulesSupported = ghcSupported "Support reexported-modules"---- | Does this compiler support thinning/renaming on package flags?-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"---- | Does this compiler support Backpack?-backpackSupported :: Compiler -> Bool-backpackSupported = ghcSupported "Support Backpack"---- | Does this compiler support a package database entry with:--- "dynamic-library-dirs"?-libraryDynDirSupported :: Compiler -> Bool-libraryDynDirSupported comp = case compilerFlavor comp of- GHC ->- -- Not just v >= mkVersion [8,0,1,20161022], as there- -- are many GHC 8.1 nightlies which don't support this.- ((v >= mkVersion [8,0,1,20161022] && v < mkVersion [8,1]) ||- v >= mkVersion [8,1,20161021])- _ -> False- where- v = compilerVersion comp---- | Does this compiler's "ar" command supports response file--- arguments (i.e. @file-style arguments).-arResponseFilesSupported :: Compiler -> Bool-arResponseFilesSupported = ghcSupported "ar supports at file"---- | Does this compiler support Haskell program coverage?-coverageSupported :: Compiler -> Bool-coverageSupported comp =- case compilerFlavor comp of- GHC -> True- GHCJS -> True- _ -> False---- | Does this compiler support profiling?-profilingSupported :: Compiler -> Bool-profilingSupported comp =- case compilerFlavor comp of- GHC -> True- GHCJS -> True- _ -> False---- | Does this compiler support a package database entry with:--- "visibility"?-libraryVisibilitySupported :: Compiler -> Bool-libraryVisibilitySupported comp = case compilerFlavor comp of- GHC -> v >= mkVersion [8,8]- _ -> False- where- v = compilerVersion comp---- | Utility function for GHC only features-ghcSupported :: String -> Compiler -> Bool-ghcSupported key comp =- case compilerFlavor comp of- GHC -> checkProp- GHCJS -> checkProp- _ -> False- where checkProp =- case Map.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, Typeable)--instance Binary ProfDetailLevel-instance Structured 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
@@ -1,2092 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-{-# 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- , getInternalLibraries- , computeComponentId- , computeCompatPackageKey- , localBuildInfoFile- , getInstalledPackages- , getInstalledPackagesMonitorFiles- , getPackageDBContents- , configCompilerEx, configCompilerAuxEx- , computeEffectiveProfiling- , ccLdOptionsBuildInfo- , checkForeignDeps- , interpretPackageDbFlags- , ConfigStateFileError(..)- , tryGetConfigStateFile- , platformDefines,- ) where--import qualified Prelude as Unsafe (tail)-import Distribution.Compat.Prelude--import Distribution.Compiler-import Distribution.Types.IncludeRenaming-import Distribution.Utils.NubList-import Distribution.Simple.Compiler-import Distribution.Simple.PreProcess-import Distribution.Package-import qualified Distribution.InstalledPackageInfo as IPI-import Distribution.InstalledPackageInfo (InstalledPackageInfo)-import qualified Distribution.Simple.PackageIndex as PackageIndex-import Distribution.Simple.PackageIndex (InstalledPackageIndex)-import Distribution.PackageDescription-import Distribution.PackageDescription.PrettyPrint-import Distribution.PackageDescription.Configuration-import Distribution.PackageDescription.Check hiding (doesFileExist)-import Distribution.Simple.BuildToolDepends-import Distribution.Simple.Program-import Distribution.Simple.Setup as Setup-import Distribution.Simple.BuildTarget-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.PackageVersionConstraint-import Distribution.Types.PkgconfigVersion-import Distribution.Types.PkgconfigVersionRange-import Distribution.Types.LocalBuildInfo-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.GivenComponent-import Distribution.Types.Mixin-import Distribution.Simple.Utils-import Distribution.System-import Distribution.Version-import Distribution.Verbosity-import qualified Distribution.Compat.Graph as Graph-import Distribution.Compat.Stack-import Distribution.Backpack.Configure-import Distribution.Backpack.DescribeUnitId-import Distribution.Backpack.PreExistingComponent-import Distribution.Backpack.ConfiguredComponent (newPackageDepsBehaviour)-import Distribution.Backpack.Id-import Distribution.Utils.LogProgress--import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS-import qualified Distribution.Simple.UHC as UHC-import qualified Distribution.Simple.HaskellSuite as HaskellSuite--import Control.Exception- ( try )-import Data.List.NonEmpty ( nonEmpty )-import Distribution.Utils.Structured ( structuredDecodeOrFailIO, structuredEncode )-import Distribution.Compat.Directory ( listDirectory )-import Data.ByteString.Lazy ( ByteString )-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy.Char8 as BLC8-import Data.List- ( (\\), inits, stripPrefix, intersect, dropWhileEnd )-import qualified Data.Map as Map-import System.Directory- ( canonicalizePath, createDirectoryIfMissing, doesFileExist- , getTemporaryDirectory, removeFile)-import System.FilePath- ( (</>), isAbsolute, takeDirectory )-import Distribution.Compat.Directory- ( doesPathExist )-import qualified System.Info- ( compilerName, compilerVersion )-import System.IO- ( hPutStrLn, hClose )-import Distribution.Pretty- ( pretty, defaultStyle, prettyShow )-import Distribution.Parsec- ( simpleParsec )-import Text.PrettyPrint- ( Doc, ($+$), char, comma, hsep, nest- , punctuate, quotes, render, renderStyle, sep, text )-import Distribution.Compat.Environment ( lookupEnv )--import qualified Data.Set as Set-import qualified Distribution.Compat.NonEmptySet as NES---type UseExternalInternalDeps = Bool---- | 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"- <+> pretty oldCabal <+> "to" <+> pretty currentCabalId- badCompiler- | oldCompiler == currentCompilerId = mempty- | otherwise =- text "• the compiler changed from"- <+> pretty oldCompiler <+> "to" <+> pretty 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])-- (cabalId, compId) <- parseHeader header-- let getStoredValue = do- result <- structuredDecodeOrFailIO (BLC8.tail body)- case result of- Left _ -> throwIO ConfigStateFileNoParse- Right x -> return x- deferErrorIfBadVersion act- | cabalId /= currentCabalId = do- eResult <- try act- throwIO $ ConfigStateFileBadVersion cabalId compId eResult- | otherwise = act- deferErrorIfBadVersion getStoredValue- where- _ = callStack -- TODO: attach call stack to exception---- | 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, structuredEncode lbi]- where- pkgId = localPackage lbi---- | Identifier of the current Cabal package.-currentCabalId :: PackageIdentifier-currentCabalId = PackageIdentifier (mkPackageName "Cabal") cabalVersion---- | Identifier of the current compiler package.-currentCompilerId :: PackageIdentifier-currentCompilerId = PackageIdentifier (mkPackageName System.Info.compilerName)- (mkVersion' System.Info.compilerVersion)---- | Parse the @setup-config@ file header, returning the package identifiers--- for Cabal and the compiler.-parseHeader :: ByteString -- ^ The file contents.- -> IO (PackageIdentifier, PackageIdentifier)-parseHeader header = case BLC8.words header of- ["Saved", "package", "config", "for", pkgId, "written", "by", cabalId,- "using", compId] ->- maybe (throwIO ConfigStateFileBadHeader) return $ do- _ <- simpleParsec (fromUTF8LBS pkgId) :: Maybe PackageIdentifier- cabalId' <- simpleParsec (BLC8.unpack cabalId)- compId' <- simpleParsec (BLC8.unpack compId)- return (cabalId', compId')- _ -> throwIO ConfigStateFileNoHeader---- | Generate the @setup-config@ file header.-showHeader :: PackageIdentifier -- ^ The processed package.- -> ByteString-showHeader pkgId = BLC8.unwords- [ "Saved", "package", "config", "for"- , toUTF8LBS $ prettyShow pkgId- , "written", "by"- , BLC8.pack $ prettyShow currentCabalId- , "using"- , BLC8.pack $ prettyShow currentCompilerId- ]---- | Check that localBuildInfoFile is up-to-date with respect to the--- .cabal file.-checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool-checkPersistBuildConfigOutdated distPref pkg_descr_file =- 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- -- Determine the component we are configuring, if a user specified- -- one on the command line. We use a fake, flattened version of- -- the package since at this point, we're not really sure what- -- components we *can* configure. @Nothing@ means that we should- -- configure everything (the old behavior).- (mb_cname :: Maybe ComponentName) <- do- let flat_pkg_descr = flattenPackageDescription pkg_descr0- targets <- readBuildTargets verbosity flat_pkg_descr (configArgs cfg)- -- TODO: bleat if you use the module/file syntax- let targets' = [ cname | BuildTargetComponent cname <- targets ]- case targets' of- _ | null (configArgs cfg) -> return Nothing- [cname] -> return (Just cname)- [] -> die' verbosity "No valid component targets found"- _ -> die' verbosity- "Can only configure either single component or all of them"-- let use_external_internal_deps = isJust mb_cname- case mb_cname of- Nothing -> setupMessage verbosity "Configuring" (packageId pkg_descr0)- Just cname -> setupMessage' verbosity "Configuring" (packageId pkg_descr0)- cname (Just (configInstantiateWith cfg))-- -- configCID is only valid for per-component configure- when (isJust (flagToMaybe (configCID cfg)) && isNothing mb_cname) $- die' verbosity "--cid is only supported for per-component configure"-- checkDeprecatedFlags verbosity cfg- checkExactConfiguration verbosity 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 :: PackageDBStack- packageDbs- = interpretPackageDbFlags- (fromFlag (configUserInstall cfg))- (configPackageDBs cfg)-- -- comp: the compiler we're building with- -- compPlatform: the platform we're building for- -- programDb: location and args of all programs we're- -- building with- (comp :: Compiler,- compPlatform :: Platform,- programDb :: ProgramDb)- <- configCompilerEx- (flagToMaybe (configHcFlavor cfg))- (flagToMaybe (configHcPath cfg))- (flagToMaybe (configHcPkg cfg))- (mkProgramDb cfg (configPrograms cfg))- (lessVerbose verbosity)-- -- The InstalledPackageIndex of all installed packages- installedPackageSet :: InstalledPackageIndex- <- getInstalledPackages (lessVerbose verbosity) comp- packageDbs programDb-- -- The set of package names which are "shadowed" by internal- -- packages, and which component they map to- let internalPackageSet :: Set LibraryName- internalPackageSet = getInternalLibraries pkg_descr0-- -- Make a data structure describing what components are enabled.- let enabled :: ComponentRequestedSpec- enabled = case mb_cname of- Just cname -> OneComponentRequestedSpec cname- Nothing -> ComponentRequestedSpec- -- The flag name (@--enable-tests@) is a- -- little bit of a misnomer, because- -- just passing this flag won't- -- "enable", in our internal- -- nomenclature; it's just a request; a- -- @buildable: False@ might make it- -- not possible to enable.- { testsRequested = fromFlag (configTests cfg)- , benchmarksRequested =- fromFlag (configBenchmarks cfg) }- -- Some sanity checks related to enabling components.- when (isJust mb_cname- && (fromFlag (configTests cfg) || fromFlag (configBenchmarks cfg))) $- die' verbosity $- "--enable-tests/--enable-benchmarks are incompatible with" ++- " explicitly specifying a component to configure."-- -- Some sanity checks related to dynamic/static linking.- when (fromFlag (configDynExe cfg) && fromFlag (configFullyStaticExe cfg)) $- die' verbosity $- "--enable-executable-dynamic and --enable-executable-static" ++- " are incompatible with each other."-- -- 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 :: [PackageVersionConstraint],- requiredDepsMap :: Map (PackageName, ComponentName) InstalledPackageInfo)- <- either (die' verbosity) return $- combinedConstraints (configConstraints cfg)- (configDependencies cfg)- installedPackageSet-- -- pkg_descr: The resolved package description, that does not contain any- -- conditionals, because we 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 :: PackageDescription,- flags :: FlagAssignment)- <- configureFinalizedPackage verbosity cfg enabled- allConstraints- (dependencySatisfiable- use_external_internal_deps- (fromFlagOrDefault False (configExactConfiguration cfg))- (fromFlagOrDefault False (configAllowDependingOnPrivateLibs cfg))- (packageName pkg_descr0)- installedPackageSet- internalPackageSet- requiredDepsMap)- comp- compPlatform- pkg_descr0-- debug verbosity $ "Finalized package description:\n"- ++ showPackageDescription pkg_descr-- let cabalFileDir = maybe "." takeDirectory $- flagToMaybe (configCabalFilePath cfg)- checkCompilerProblems verbosity comp pkg_descr enabled- checkPackageProblems verbosity cabalFileDir pkg_descr0- (updatePackageDescription pbi pkg_descr)-- -- The list of 'InstalledPackageInfo' recording the selected- -- dependencies 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),- --- -- In the presence of Backpack, these package dependencies are- -- NOT complete: they only ever include the INDEFINITE- -- dependencies. After we apply an instantiation, we'll get- -- definite references which constitute extra dependencies.- -- (Why not have cabal-install pass these in explicitly?- -- For one it's deterministic; for two, we need to associate- -- them with renamings which would require a far more complicated- -- input scheme than what we have today.)- externalPkgDeps :: [PreExistingComponent]- <- configureDependencies- verbosity- use_external_internal_deps- internalPackageSet- installedPackageSet- requiredDepsMap- pkg_descr- enabled-- -- Compute installation directory templates, based on user- -- configuration.- --- -- TODO: Move this into a helper function.- defaultDirs :: InstallDirTemplates- <- defaultInstallDirs' use_external_internal_deps- (compilerFlavor comp)- (fromFlag (configUserInstall cfg))- (hasLibs pkg_descr)- let installDirs :: InstallDirTemplates- installDirs = combineInstallDirs fromFlagOrDefault- defaultDirs (configInstallDirs cfg)-- -- Check languages and extensions- -- TODO: Move this into a helper function.- let langlist = nub $ catMaybes $ map defaultLanguage- (enabledBuildInfos pkg_descr enabled)- let langs = unsupportedLanguages comp langlist- when (not (null langs)) $- die' verbosity $ "The package " ++ prettyShow (packageId pkg_descr0)- ++ " requires the following languages which are not "- ++ "supported by " ++ prettyShow (compilerId comp) ++ ": "- ++ intercalate ", " (map prettyShow langs)- let extlist = nub $ concatMap allExtensions- (enabledBuildInfos pkg_descr enabled)- let exts = unsupportedExtensions comp extlist- when (not (null exts)) $- die' verbosity $ "The package " ++ prettyShow (packageId pkg_descr0)- ++ " requires the following language extensions which are not "- ++ "supported by " ++ prettyShow (compilerId comp) ++ ": "- ++ intercalate ", " (map prettyShow exts)-- -- Check foreign library build requirements- let flibs = [flib | CFLib flib <- enabledComponents pkg_descr enabled]- let unsupportedFLibs = unsupportedForeignLibs comp compPlatform flibs- when (not (null unsupportedFLibs)) $- die' verbosity $ "Cannot build some foreign libraries: "- ++ intercalate "," unsupportedFLibs-- -- Configure certain external build tools, see below for which ones.- let requiredBuildTools = do- bi <- enabledBuildInfos pkg_descr enabled- -- First, we collect any tool dep that we know is external. This is,- -- in practice:- --- -- 1. `build-tools` entries on the whitelist- --- -- 2. `build-tool-depends` that aren't from the current package.- let externBuildToolDeps =- [ LegacyExeDependency (unUnqualComponentName eName) versionRange- | buildTool@(ExeDependency _ eName versionRange)- <- getAllToolDependencies pkg_descr bi- , not $ isInternal pkg_descr buildTool ]- -- Second, we collect any build-tools entry we don't know how to- -- desugar. We'll never have any idea how to build them, so we just- -- hope they are already on the PATH.- let unknownBuildTools =- [ buildTool- | buildTool <- buildTools bi- , Nothing == desugarBuildTool pkg_descr buildTool ]- externBuildToolDeps ++ unknownBuildTools-- programDb' <-- configureAllKnownPrograms (lessVerbose verbosity) programDb- >>= configureRequiredPrograms verbosity requiredBuildTools-- (pkg_descr', programDb'') <-- configurePkgconfigPackages verbosity pkg_descr programDb' enabled-- -- Compute internal component graph- --- -- The general idea is that we take a look at all the source level- -- components (which may build-depends on each other) and form a graph.- -- From there, we build a ComponentLocalBuildInfo for each of the- -- components, which lets us actually build each component.- -- internalPackageSet- -- use_external_internal_deps- (buildComponents :: [ComponentLocalBuildInfo],- packageDependsIndex :: InstalledPackageIndex) <-- runLogProgress verbosity $ configureComponentLocalBuildInfos- verbosity- use_external_internal_deps- enabled- (fromFlagOrDefault False (configDeterministic cfg))- (configIPID cfg)- (configCID cfg)- pkg_descr- externalPkgDeps- (configConfigurationsFlags cfg)- (configInstantiateWith cfg)- installedPackageSet- comp-- -- Decide if we're going to compile with split sections.- split_sections :: Bool <-- if not (fromFlag $ configSplitSections cfg)- then return False- else case compilerFlavor comp of- GHC | compilerVersion comp >= mkVersion [8,0]- -> return True- GHCJS- -> return True- _ -> do warn verbosity- ("this compiler does not support " ++- "--enable-split-sections; ignoring")- return False-- -- Decide if we're going to compile with split objects.- split_objs :: Bool <-- if not (fromFlag $ configSplitObjs cfg)- then return False- else case compilerFlavor comp of- _ | split_sections- -> do warn verbosity- ("--enable-split-sections and " ++- "--enable-split-objs are mutually" ++- "exclusive; ignoring the latter")- return False- GHC- -> 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-- withStaticLib_ =- -- build a static library (all dependent libraries rolled- -- into a huge .a archive) via GHCs -staticlib flag.- fromFlagOrDefault False $ configStaticLib cfg-- withDynExe_ = fromFlag $ configDynExe cfg-- withFullyStaticExe_ = fromFlag $ configFullyStaticExe 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."-- setProfLBI <- configureProfiling verbosity cfg comp-- setCoverageLBI <- configureCoverage verbosity cfg comp---- -- Turn off library and executable stripping when `debug-info` is set- -- to anything other than zero.- let- strip_libexe s f =- let defaultStrip = fromFlagOrDefault True (f cfg)- in case fromFlag (configDebugInfo cfg) of- NoDebugInfo -> return defaultStrip- _ -> case f cfg of- Flag True -> do- warn verbosity $ "Setting debug-info implies "- ++ s ++ "-stripping: False"- return False-- _ -> return False-- strip_lib <- strip_libexe "library" configStripLibs- strip_exe <- strip_libexe "executable" configStripExes--- let reloc = fromFlagOrDefault False $ configRelocatable cfg-- let buildComponentsMap =- foldl' (\m clbi -> Map.insertWith (++)- (componentLocalName clbi) [clbi] m)- Map.empty buildComponents-- let lbi = (setCoverageLBI . setProfLBI)- LocalBuildInfo {- configFlags = cfg,- flagAssignment = flags,- componentEnabledSpec = enabled,- extraConfigArgs = [], -- Currently configure does not- -- take extra args, but if it- -- did they would go here.- installDirTemplates = installDirs,- compiler = comp,- hostPlatform = compPlatform,- buildDir = buildDir,- cabalFilePath = flagToMaybe (configCabalFilePath cfg),- componentGraph = Graph.fromDistinctList buildComponents,- componentNameMap = buildComponentsMap,- installedPkgs = packageDependsIndex,- pkgDescrFile = Nothing,- localPkgDescr = pkg_descr',- withPrograms = programDb'',- withVanillaLib = fromFlag $ configVanillaLib cfg,- withSharedLib = withSharedLib_,- withStaticLib = withStaticLib_,- withDynExe = withDynExe_,- withFullyStaticExe = withFullyStaticExe_,- withProfLib = False,- withProfLibDetail = ProfDetailNone,- withProfExe = False,- withProfExeDetail = ProfDetailNone,- withOptimization = fromFlag $ configOptimization cfg,- withDebugInfo = fromFlag $ configDebugInfo cfg,- withGHCiLib = fromFlagOrDefault ghciLibByDefault $- configGHCiLib cfg,- splitSections = split_sections,- splitObjs = split_objs,- stripExes = strip_exe,- stripLibs = strip_lib,- exeCoverage = False,- libCoverage = False,- withPackageDB = packageDbs,- progPrefix = fromFlag $ configProgPrefix cfg,- progSuffix = fromFlag $ configProgSuffix cfg,- relocatable = reloc- }-- when reloc (checkRelocatable verbosity pkg_descr lbi)-- -- TODO: This is not entirely correct, because the dirs may vary- -- across libraries/executables- let dirs = absoluteInstallDirs pkg_descr lbi NoCopyDest- relative = prefixRelativeInstallDirs (packageId pkg_descr) lbi-- -- PKGROOT: allowing ${pkgroot} to be passed as --prefix to- -- cabal configure, is only a hidden option. It allows packages- -- to be relocatable with their package database. This however- -- breaks when the Paths_* or other includes are used that- -- contain hard coded paths. This is still an open TODO.- --- -- Allowing ${pkgroot} here, however requires less custom hooks- -- in scripts that *really* want ${pkgroot}. See haskell/cabal/#4872- unless (isAbsolute (prefix dirs)- || "${pkgroot}" `isPrefixOf` prefix dirs) $ die' verbosity $- "expected an absolute directory name for --prefix: " ++ prefix dirs-- when ("${pkgroot}" `isPrefixOf` prefix dirs) $- warn verbosity $ "Using ${pkgroot} in prefix " ++ prefix dirs- ++ " will not work if you rely on the Path_* module "- ++ " or other hard coded paths. Cabal does not yet "- ++ " support fully relocatable builds! "- ++ " See #462 #2302 #2994 #3305 #3473 #3586 #3909"- ++ " #4097 #4291 #4872"-- info verbosity $ "Using " ++ prettyShow currentCabalId- ++ " compiled by " ++ prettyShow 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 "Executables" (bindir dirs) (bindir relative)- dirinfo "Libraries" (libdir dirs) (libdir relative)- dirinfo "Dynamic Libraries" (dynlibdir dirs) (dynlibdir relative)- dirinfo "Private executables" (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 programDb'' ]-- return lbi-- where- verbosity = fromFlag (configVerbosity cfg)--mkProgramDb :: ConfigFlags -> ProgramDb -> ProgramDb-mkProgramDb cfg initialProgramDb = programDb- where- programDb = userSpecifyArgss (configProgramArgs cfg)- . userSpecifyPaths (configProgramPaths cfg)- . setProgramSearchPath searchpath- $ initialProgramDb- searchpath = getProgramSearchPath initialProgramDb- ++ 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- :: Verbosity -> GenericPackageDescription -> ConfigFlags -> IO ()-checkExactConfiguration verbosity pkg_descr0 cfg =- when (fromFlagOrDefault False (configExactConfiguration cfg)) $ do- let cmdlineFlags = map fst (unFlagAssignment (configConfigurationsFlags cfg))- allFlags = map flagName . genPackageFlags $ pkg_descr0- diffFlags = allFlags \\ cmdlineFlags- when (not . null $ diffFlags) $- die' verbosity $ "'--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. finalizePD--- does the resolution of conditionals, and it takes internalPackageSet--- as part of its input.-getInternalLibraries :: GenericPackageDescription- -> Set LibraryName-getInternalLibraries pkg_descr0 =- -- TODO: some day, executables will be fair game here too!- let pkg_descr = flattenPackageDescription pkg_descr0- in Set.fromList (map libName (allLibraries pkg_descr))---- | Returns true if a dependency is satisfiable. This function may--- report a dependency satisfiable even when it is not, but not vice--- versa. This is to be passed to finalize-dependencySatisfiable- :: Bool -- ^ use external internal deps?- -> Bool -- ^ exact configuration?- -> Bool -- ^ allow depending on private libs?- -> PackageName- -> InstalledPackageIndex -- ^ installed set- -> Set LibraryName -- ^ library components- -> Map (PackageName, ComponentName) InstalledPackageInfo- -- ^ required dependencies- -> (Dependency -> Bool)-dependencySatisfiable- use_external_internal_deps- exact_config- allow_private_deps- pn installedPackageSet packageLibraries requiredDepsMap- (Dependency depName vr sublibs)- | 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,- -- 'finalizePD' will fail.- -- TODO: mention '--exact-configuration' in the error message- -- when this fails?- = if isInternalDep && not use_external_internal_deps- -- Except for internal deps, when we're NOT per-component mode;- -- those are just True.- then internalDepSatisfiable- else- -- Backward compatibility for the old sublibrary syntax- (sublibs == mainLibSet- && Map.member- (pn, CLibName $ LSubLibName $- packageNameToUnqualComponentName depName)- requiredDepsMap)-- || all visible sublibs-- | isInternalDep- = if use_external_internal_deps- -- When we are doing per-component configure, we now need to- -- test if the internal dependency is in the index. This has- -- DIFFERENT semantics from normal dependency satisfiability.- then internalDepSatisfiableExternally- -- If a 'PackageName' is defined by an internal component, the dep is- -- satisfiable (we're going to build it ourselves)- else internalDepSatisfiable-- | otherwise- = depSatisfiable-- where- -- Internal dependency is when dependency is the same as package.- isInternalDep = pn == depName-- depSatisfiable =- not . null $ PackageIndex.lookupDependency installedPackageSet depName vr-- internalDepSatisfiable =- Set.isSubsetOf (NES.toSet sublibs) packageLibraries- internalDepSatisfiableExternally =- all (\ln -> not $ null $ PackageIndex.lookupInternalDependency installedPackageSet pn vr ln) sublibs-- -- Check whether a library exists and is visible.- -- We don't disambiguate between dependency on non-existent or private- -- library yet, so we just return a bool and later report a generic error.- visible lib = maybe- False -- Does not even exist (wasn't in the depsMap)- (\ipi -> IPI.libVisibility ipi == LibraryVisibilityPublic- -- If the override is enabled, the visibility does- -- not matter (it's handled externally)- || allow_private_deps- -- If it's a library of the same package then it's- -- always visible.- -- This is only triggered when passing a component- -- of the same package as --dependency, such as in:- -- cabal-testsuite/PackageTests/ConfigureComponent/SubLib/setup-explicit.test.hs- || pkgName (IPI.sourcePackageId ipi) == pn)- maybeIPI- where maybeIPI = Map.lookup (depName, CLibName lib) requiredDepsMap---- | Finalize a generic package description. The workhorse is--- 'finalizePD' but there's a bit of other nattering--- about necessary.------ TODO: what exactly is the business with @flaggedTests@ and--- @flaggedBenchmarks@?-configureFinalizedPackage- :: Verbosity- -> ConfigFlags- -> ComponentRequestedSpec- -> [PackageVersionConstraint]- -> (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 enabled- allConstraints satisfies comp compPlatform pkg_descr0 = do-- (pkg_descr0', flags) <-- case finalizePD- (configConfigurationsFlags cfg)- enabled- satisfies- compPlatform- (compilerInfo comp)- allConstraints- pkg_descr0- of Right r -> return r- Left missing ->- die' verbosity $ "Encountered missing or private dependencies:\n"- ++ (render . nest 4 . sep . punctuate comma- . map (pretty . 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'-- unless (nullFlagAssignment flags) $- info verbosity $ "Flags chosen: "- ++ intercalate ", " [ unFlagName fn ++ "=" ++ prettyShow value- | (fn, value) <- unFlagAssignment flags ]-- return (pkg_descr, flags)- where- addExtraIncludeLibDirs pkg_descr =- let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg- , extraFrameworkDirs = configExtraFrameworkDirs cfg- , includeDirs = configExtraIncludeDirs cfg}- modifyLib l = l{ libBuildInfo = libBuildInfo l- `mappend` extraBi }- modifyExecutable e = e{ buildInfo = buildInfo e- `mappend` extraBi}- modifyForeignLib f = f{ foreignLibBuildInfo = foreignLibBuildInfo f- `mappend` extraBi}- modifyTestsuite t = t{ testBuildInfo = testBuildInfo t- `mappend` extraBi}- modifyBenchmark b = b{ benchmarkBuildInfo = benchmarkBuildInfo b- `mappend` extraBi}- in pkg_descr- { library = modifyLib `fmap` library pkg_descr- , subLibraries = modifyLib `map` subLibraries pkg_descr- , executables = modifyExecutable `map` executables pkg_descr- , foreignLibs = modifyForeignLib `map` foreignLibs pkg_descr- , testSuites = modifyTestsuite `map` testSuites pkg_descr- , benchmarks = modifyBenchmark `map` benchmarks pkg_descr- }---- | Check for use of Cabal features which require compiler support-checkCompilerProblems- :: Verbosity -> Compiler -> PackageDescription -> ComponentRequestedSpec -> IO ()-checkCompilerProblems verbosity comp pkg_descr enabled = do- unless (renamingPackageFlagsSupported comp ||- all (all (isDefaultIncludeRenaming . mixinIncludeRenaming) . mixins)- (enabledBuildInfos pkg_descr enabled)) $- die' verbosity $- "Your compiler does not support thinning and renaming on "- ++ "package flags. To use this feature you must use "- ++ "GHC 7.9 or later."-- when (any (not.null.reexportedModules) (allLibraries pkg_descr)- && not (reexportedModulesSupported comp)) $- die' verbosity $- "Your compiler does not support module re-exports. To use "- ++ "this feature you must use GHC 7.9 or later."-- when (any (not.null.signatures) (allLibraries pkg_descr)- && not (backpackSupported comp)) $- die' verbosity $- "Your compiler does not support Backpack. To use "- ++ "this feature you must use GHC 8.1 or later."---- | Select dependencies for the package.-configureDependencies- :: Verbosity- -> UseExternalInternalDeps- -> Set LibraryName- -> InstalledPackageIndex -- ^ installed packages- -> Map (PackageName, ComponentName) InstalledPackageInfo -- ^ required deps- -> PackageDescription- -> ComponentRequestedSpec- -> IO [PreExistingComponent]-configureDependencies verbosity use_external_internal_deps- packageLibraries installedPackageSet requiredDepsMap pkg_descr enableSpec = do- let failedDeps :: [FailedDependency]- allPkgDeps :: [ResolvedDependency]- (failedDeps, allPkgDeps) = partitionEithers $ concat- [ fmap (\s -> (dep, s)) <$> status- | dep <- enabledBuildDepends pkg_descr enableSpec- , let status = selectDependency (package pkg_descr)- packageLibraries installedPackageSet- requiredDepsMap use_external_internal_deps dep ]-- internalPkgDeps = [ pkgid- | (_, InternalDependency pkgid) <- allPkgDeps ]- -- NB: we have to SAVE the package name, because this is the only- -- way we can be able to resolve package names in the package- -- description.- externalPkgDeps = [ pec- | (_, ExternalDependency pec) <- allPkgDeps ]-- when (not (null internalPkgDeps)- && not (newPackageDepsBehaviour pkg_descr)) $- die' verbosity $ "The field 'build-depends: "- ++ intercalate ", " (map (prettyShow . 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 verbosity failedDeps- reportSelectedDependencies verbosity allPkgDeps-- return externalPkgDeps---- | Select and apply coverage settings for the build based on the--- 'ConfigFlags' and 'Compiler'.-configureCoverage :: Verbosity -> ConfigFlags -> Compiler- -> IO (LocalBuildInfo -> LocalBuildInfo)-configureCoverage verbosity cfg comp = do- let tryExeCoverage = fromFlagOrDefault False (configCoverage cfg)- tryLibCoverage = fromFlagOrDefault tryExeCoverage- (mappend (configCoverage cfg) (configLibCoverage cfg))- if coverageSupported comp- then do- let apply lbi = lbi { libCoverage = tryLibCoverage- , exeCoverage = tryExeCoverage- }- return apply- else do- let apply lbi = lbi { libCoverage = False- , exeCoverage = False- }- when (tryExeCoverage || tryLibCoverage) $ warn verbosity- ("The compiler " ++ showCompilerId comp ++ " does not support "- ++ "program coverage. Program coverage has been disabled.")- return apply---- | Compute the effective value of the profiling flags--- @--enable-library-profiling@ and @--enable-executable-profiling@--- from the specified 'ConfigFlags'. This may be useful for--- external Cabal tools which need to interact with Setup in--- a backwards-compatible way: the most predictable mechanism--- for enabling profiling across many legacy versions is to--- NOT use @--enable-profiling@ and use those two flags instead.------ Note that @--enable-executable-profiling@ also affects profiling--- of benchmarks and (non-detailed) test suites.-computeEffectiveProfiling :: ConfigFlags -> (Bool {- lib -}, Bool {- exe -})-computeEffectiveProfiling cfg =- -- 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.- --- -- The --profiling-detail and --library-profiling-detail flags behave- -- similarly- let tryExeProfiling = fromFlagOrDefault False- (mappend (configProf cfg) (configProfExe cfg))- tryLibProfiling = fromFlagOrDefault tryExeProfiling- (mappend (configProf cfg) (configProfLib cfg))- in (tryLibProfiling, tryExeProfiling)---- | Select and apply profiling settings for the build based on the--- 'ConfigFlags' and 'Compiler'.-configureProfiling :: Verbosity -> ConfigFlags -> Compiler- -> IO (LocalBuildInfo -> LocalBuildInfo)-configureProfiling verbosity cfg comp = do- let (tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling cfg-- tryExeProfileLevel = fromFlagOrDefault ProfDetailDefault- (configProfDetail cfg)- tryLibProfileLevel = fromFlagOrDefault ProfDetailDefault- (mappend- (configProfDetail cfg)- (configProfLibDetail cfg))-- checkProfileLevel (ProfDetailOther other) = do- warn verbosity- ("Unknown profiling detail level '" ++ other- ++ "', using default.\nThe profiling detail levels are: "- ++ intercalate ", "- [ name | (name, _, _) <- knownProfDetailLevels ])- return ProfDetailDefault- checkProfileLevel other = return other-- (exeProfWithoutLibProf, applyProfiling) <-- if profilingSupported comp- then do- exeLevel <- checkProfileLevel tryExeProfileLevel- libLevel <- checkProfileLevel tryLibProfileLevel- let apply lbi = lbi { withProfLib = tryLibProfiling- , withProfLibDetail = libLevel- , withProfExe = tryExeProfiling- , withProfExeDetail = exeLevel- }- return (tryExeProfiling && not tryLibProfiling, apply)- else do- let apply lbi = lbi { withProfLib = False- , withProfLibDetail = ProfDetailNone- , withProfExe = False- , withProfExeDetail = ProfDetailNone- }- when (tryExeProfiling || tryLibProfiling) $ warn verbosity- ("The compiler " ++ showCompilerId comp ++ " does not support "- ++ "profiling. Profiling has been disabled.")- return (False, apply)-- when exeProfWithoutLibProf $ warn verbosity- ("Executables will be built with profiling, but library "- ++ "profiling is disabled. Linking will fail if any executables "- ++ "depend on the library.")-- return applyProfiling---- -------------------------------------------------------------------------------- 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 " ++ prettyShow v--hackageUrl :: String-hackageUrl = "http://hackage.haskell.org/package/"--type ResolvedDependency = (Dependency, DependencyResolution)--data DependencyResolution- -- | An external dependency from the package database, OR an- -- internal dependency which we are getting from the package- -- database.- = ExternalDependency PreExistingComponent- -- | An internal dependency ('PackageId' should be a library name)- -- which we are going to have to build. (The- -- 'PackageId' here is a hack to get a modest amount of- -- polymorphism out of the 'Package' typeclass.)- | InternalDependency PackageId--data FailedDependency = DependencyNotExists PackageName- | DependencyMissingInternal PackageName LibraryName- | DependencyNoVersion Dependency---- | Test for a package dependency and record the version we have installed.-selectDependency :: PackageId -- ^ Package id of current package- -> Set LibraryName -- ^ package libraries- -> InstalledPackageIndex -- ^ Installed packages- -> Map (PackageName, ComponentName) InstalledPackageInfo- -- ^ Packages for which we have been given specific deps to- -- use- -> UseExternalInternalDeps -- ^ Are we configuring a- -- single component?- -> Dependency- -> [Either FailedDependency DependencyResolution]-selectDependency pkgid internalIndex installedIndex requiredDepsMap- use_external_internal_deps- (Dependency dep_pkgname vr libs) =- -- 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".- if dep_pkgname == pn- then- if use_external_internal_deps- then do_external_internal <$> NES.toList libs- else do_internal <$> NES.toList libs- else- do_external_external <$> NES.toList libs- where- pn = packageName pkgid-- -- It's an internal library, and we're not per-component build- do_internal lib- | Set.member lib internalIndex- = Right $ InternalDependency $ PackageIdentifier dep_pkgname $ packageVersion pkgid-- | otherwise- = Left $ DependencyMissingInternal dep_pkgname lib-- -- We have to look it up externally- do_external_external :: LibraryName -> Either FailedDependency DependencyResolution- do_external_external lib = do- ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of- -- If we know the exact pkg to use, then use it.- Just pkginstance -> Right pkginstance- -- Otherwise we just pick an arbitrary instance of the latest version.- Nothing -> case pickLastIPI $ PackageIndex.lookupDependency installedIndex dep_pkgname vr of- Nothing -> Left (DependencyNotExists dep_pkgname)- Just pkg -> Right pkg- return $ ExternalDependency $ ipiToPreExistingComponent ipi-- do_external_internal :: LibraryName -> Either FailedDependency DependencyResolution- do_external_internal lib = do- ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of- -- If we know the exact pkg to use, then use it.- Just pkginstance -> Right pkginstance- Nothing -> case pickLastIPI $ PackageIndex.lookupInternalDependency installedIndex pn vr lib of- -- It's an internal library, being looked up externally- Nothing -> Left (DependencyMissingInternal dep_pkgname lib)- Just pkg -> Right pkg- return $ ExternalDependency $ ipiToPreExistingComponent ipi-- pickLastIPI :: [(Version, [InstalledPackageInfo])] -> Maybe InstalledPackageInfo- pickLastIPI pkgs = safeHead . snd . last =<< nonEmpty pkgs--reportSelectedDependencies :: Verbosity- -> [ResolvedDependency] -> IO ()-reportSelectedDependencies verbosity deps =- info verbosity $ unlines- [ "Dependency " ++ prettyShow (simplifyDependency dep)- ++ ": using " ++ prettyShow pkgid- | (dep, resolution) <- deps- , let pkgid = case resolution of- ExternalDependency pkg' -> packageId pkg'- InternalDependency pkgid' -> pkgid' ]--reportFailedDependencies :: Verbosity -> [FailedDependency] -> IO ()-reportFailedDependencies _ [] = return ()-reportFailedDependencies verbosity failed =- die' verbosity (intercalate "\n\n" (map reportFailedDependency failed))-- where- reportFailedDependency (DependencyNotExists pkgname) =- "there is no version of " ++ prettyShow pkgname ++ " installed.\n"- ++ "Perhaps you need to download and install it from\n"- ++ hackageUrl ++ prettyShow pkgname ++ "?"-- reportFailedDependency (DependencyMissingInternal pkgname lib) =- "internal dependency " ++ prettyShow (prettyLibraryNameComponent lib) ++ " not installed.\n"- ++ "Perhaps you need to configure and install it first?\n"- ++ "(This library was defined by " ++ prettyShow pkgname ++ ")"-- reportFailedDependency (DependencyNoVersion dep) =- "cannot satisfy dependency " ++ prettyShow (simplifyDependency dep) ++ "\n"---- | List all installed packages in the given package databases.--- Non-existent package databases do not cause errors, they just get skipped--- with a warning and treated as empty ones, since technically they do not--- contain any package.-getInstalledPackages :: Verbosity -> Compiler- -> PackageDBStack -- ^ The stack of package databases.- -> ProgramDb- -> IO InstalledPackageIndex-getInstalledPackages verbosity comp packageDBs progdb = do- when (null packageDBs) $- die' verbosity $ "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..."- -- do not check empty packagedbs (ghc-pkg would error out)- packageDBs' <- filterM packageDBExists packageDBs- case compilerFlavor comp of- GHC -> GHC.getInstalledPackages verbosity comp packageDBs' progdb- GHCJS -> GHCJS.getInstalledPackages verbosity packageDBs' progdb- UHC -> UHC.getInstalledPackages verbosity comp packageDBs' progdb- HaskellSuite {} ->- HaskellSuite.getInstalledPackages verbosity packageDBs' progdb- flv -> die' verbosity $ "don't know how to find the installed packages for "- ++ prettyShow flv- where- packageDBExists (SpecificPackageDB path) = do- exists <- doesPathExist path- unless exists $- warn verbosity $ "Package db " <> path <> " does not exist yet"- return exists- -- Checking the user and global package dbs is more complicated and needs- -- way more data. Also ghc-pkg won't error out unless the user/global- -- pkgdb is overridden with an empty one, so we just don't check for them.- packageDBExists UserPackageDB = pure True- packageDBExists GlobalPackageDB = pure True---- | 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 -> ProgramDb- -> IO InstalledPackageIndex-getPackageDBContents verbosity comp packageDB progdb = do- info verbosity "Reading installed packages..."- case compilerFlavor comp of- GHC -> GHC.getPackageDBContents verbosity packageDB progdb- GHCJS -> GHCJS.getPackageDBContents verbosity packageDB progdb- -- For other compilers, try to fall back on 'getInstalledPackages'.- _ -> getInstalledPackages verbosity comp [packageDB] progdb----- | 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- -> ProgramDb -> Platform- -> IO [FilePath]-getInstalledPackagesMonitorFiles verbosity comp packageDBs progdb platform =- case compilerFlavor comp of- GHC -> GHC.getInstalledPackagesMonitorFiles- verbosity platform progdb packageDBs- other -> do- warn verbosity $ "don't know how to find change monitoring files for "- ++ "the installed package databases for " ++ prettyShow 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---- 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- :: [PackageVersionConstraint]- -> [GivenComponent]- -> InstalledPackageIndex- -> Either String ([PackageVersionConstraint],- Map (PackageName, ComponentName) InstalledPackageInfo)-combinedConstraints constraints dependencies installedPackages = do-- when (not (null badComponentIds)) $- Left $ render $ text "The following package dependencies were requested"- $+$ nest 4 (dispDependencies badComponentIds)- $+$ text "however the given installed package instance does not exist."-- --TODO: we don't check that all dependencies are used!-- return (allConstraints, idConstraintMap)-- where- allConstraints :: [PackageVersionConstraint]- allConstraints = constraints- ++ [ thisPackageVersionConstraint (packageId pkg)- | (_, _, _, Just pkg) <- dependenciesPkgInfo ]-- idConstraintMap :: Map (PackageName, ComponentName) InstalledPackageInfo- idConstraintMap = Map.fromList- -- NB: do NOT use the packageName from- -- dependenciesPkgInfo!- [ ((pn, cname), pkg)- | (pn, cname, _, Just pkg) <- dependenciesPkgInfo ]-- -- The dependencies along with the installed package info, if it exists- dependenciesPkgInfo :: [(PackageName, ComponentName, ComponentId,- Maybe InstalledPackageInfo)]- dependenciesPkgInfo =- [ (pkgname, CLibName lname, cid, mpkg)- | GivenComponent pkgname lname cid <- dependencies- , let mpkg = PackageIndex.lookupComponentId- installedPackages cid- ]-- -- 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.- badComponentIds =- [ (pkgname, cname, cid)- | (pkgname, cname, cid, Nothing) <- dependenciesPkgInfo ]-- dispDependencies deps =- hsep [ text "--dependency="- <<>> quotes- (pretty pkgname- <<>> case cname of- CLibName LMainLibName -> ""- CLibName (LSubLibName n) -> ":" <<>> pretty n- _ -> ":" <<>> pretty cname- <<>> char '='- <<>> pretty cid)- | (pkgname, cname, cid) <- deps ]---- -------------------------------------------------------------------------------- Configuring program dependencies--configureRequiredPrograms :: Verbosity -> [LegacyExeDependency] -> ProgramDb- -> IO ProgramDb-configureRequiredPrograms verbosity deps progdb =- foldM (configureRequiredProgram verbosity) progdb deps---- | Configure a required program, ensuring that it exists in the PATH--- (or where the user has specified the program must live) and making it--- available for use via the 'ProgramDb' interface. If the program is--- known (exists in the input 'ProgramDb'), we will make sure that the--- program matches the required version; otherwise we will accept--- any version of the program and assume that it is a simpleProgram.-configureRequiredProgram :: Verbosity -> ProgramDb -> LegacyExeDependency- -> IO ProgramDb-configureRequiredProgram verbosity progdb- (LegacyExeDependency progName verRange) =- case lookupKnownProgram progName progdb of- Nothing ->- -- Try to configure it as a 'simpleProgram' automatically- --- -- There's a bit of a story behind this line. In old versions- -- of Cabal, there were only internal build-tools dependencies. So the- -- behavior in this case was:- --- -- - If a build-tool dependency was internal, don't do- -- any checking.- --- -- - If it was external, call 'configureRequiredProgram' to- -- "configure" the executable. In particular, if- -- the program was not "known" (present in 'ProgramDb'),- -- then we would just error. This was fine, because- -- the only way a program could be executed from 'ProgramDb'- -- is if some library code from Cabal actually called it,- -- and the pre-existing Cabal code only calls known- -- programs from 'defaultProgramDb', and so if it- -- is calling something else, you have a Custom setup- -- script, and in that case you are expected to register- -- the program you want to call in the ProgramDb.- --- -- OK, so that was fine, until I (ezyang, in 2016) refactored- -- Cabal to support per-component builds. In this case, what- -- was previously an internal build-tool dependency now became- -- an external one, and now previously "internal" dependencies- -- are now external. But these are permitted to exist even- -- when they are not previously configured (something that- -- can only occur by a Custom script.)- --- -- So, I decided, "Fine, let's just accept these in any- -- case." Thus this line. The alternative would have been to- -- somehow detect when a build-tools dependency was "internal" (by- -- looking at the unflattened package description) but this- -- would also be incompatible with future work to support- -- external executable dependencies: we definitely cannot- -- assume they will be preinitialized in the 'ProgramDb'.- configureProgram verbosity (simpleProgram progName) progdb- 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- (_, progdb') <- requireProgram verbosity prog progdb- return progdb'- | otherwise -> do- (_, _, progdb') <- requireProgramVersion verbosity prog verRange progdb- return progdb'---- -------------------------------------------------------------------------------- Configuring pkg-config package dependencies--configurePkgconfigPackages :: Verbosity -> PackageDescription- -> ProgramDb -> ComponentRequestedSpec- -> IO (PackageDescription, ProgramDb)-configurePkgconfigPackages verbosity pkg_descr progdb enabled- | null allpkgs = return (pkg_descr, progdb)- | otherwise = do- (_, _, progdb') <- requireProgramVersion- (lessVerbose verbosity) pkgConfigProgram- (orLaterVersion $ mkVersion [0,9,0]) progdb- traverse_ requirePkg allpkgs- mlib' <- traverse addPkgConfigBILib (library pkg_descr)- libs' <- traverse addPkgConfigBILib (subLibraries pkg_descr)- exes' <- traverse addPkgConfigBIExe (executables pkg_descr)- tests' <- traverse addPkgConfigBITest (testSuites pkg_descr)- benches' <- traverse addPkgConfigBIBench (benchmarks pkg_descr)- let pkg_descr' = pkg_descr { library = mlib',- subLibraries = libs', executables = exes',- testSuites = tests', benchmarks = benches' }- return (pkg_descr', progdb')-- where- allpkgs = concatMap pkgconfigDepends (enabledBuildInfos pkg_descr enabled)- pkgconfig = getDbProgramOutput (lessVerbose verbosity)- pkgConfigProgram progdb-- requirePkg dep@(PkgconfigDependency pkgn range) = do- version <- pkgconfig ["--modversion", pkg]- `catchIO` (\_ -> die' verbosity notFound)- `catchExit` (\_ -> die' verbosity notFound)- let trim = dropWhile isSpace . dropWhileEnd isSpace- let v = PkgconfigVersion (toUTF8BS $ trim version)- if not (withinPkgconfigVersionRange v range)- then die' verbosity (badVersion v)- else 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 " ++ prettyShow v- depSatisfied v = "Dependency " ++ prettyShow dep- ++ ": using version " ++ prettyShow v-- versionRequirement- | isAnyPkgconfigVersion range = ""- | otherwise = " version " ++ prettyShow range-- pkg = unPkgconfigName pkgn-- -- 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 :: [PkgconfigDependency] -> IO BuildInfo- pkgconfigBuildInfo [] = return mempty- pkgconfigBuildInfo pkgdeps = do- let pkgs = nub [ prettyShow pkg | PkgconfigDependency 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 <- getDbProgramOutput verbosity prog progdb ["--cflags"]--- > ldflags <- getDbProgramOutput verbosity prog progdb ["--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 {- includeDirs = map (drop 2) includeDirs',- extraLibs = map (drop 2) extraLibs',- extraLibDirs = map (drop 2) extraLibDirs',- ccOptions = cflags',- ldOptions = ldflags''- }---- -------------------------------------------------------------------------------- Determining the compiler details--configCompilerAuxEx :: ConfigFlags- -> IO (Compiler, Platform, ProgramDb)-configCompilerAuxEx cfg = configCompilerEx (flagToMaybe $ configHcFlavor cfg)- (flagToMaybe $ configHcPath cfg)- (flagToMaybe $ configHcPkg cfg)- programDb- (fromFlag (configVerbosity cfg))- where- programDb = mkProgramDb cfg defaultProgramDb--configCompilerEx :: Maybe CompilerFlavor -> Maybe FilePath -> Maybe FilePath- -> ProgramDb -> Verbosity- -> IO (Compiler, Platform, ProgramDb)-configCompilerEx Nothing _ _ _ verbosity = die' verbosity "Unknown compiler"-configCompilerEx (Just hcFlavor) hcPath hcPkg progdb verbosity = do- (comp, maybePlatform, programDb) <- case hcFlavor of- GHC -> GHC.configure verbosity hcPath hcPkg progdb- GHCJS -> GHCJS.configure verbosity hcPath hcPkg progdb- UHC -> UHC.configure verbosity hcPath hcPkg progdb- HaskellSuite {} -> HaskellSuite.configure verbosity hcPath hcPkg progdb- _ -> die' verbosity "Unknown compiler"- return (comp, fromMaybe buildPlatform maybePlatform, programDb)---- -------------------------------------------------------------------------------- Testing C lib and header dependencies---- Try to build a test C program which includes every header and links every--- lib. If that fails, try to narrow it down by preprocessing (only) and linking--- with individual headers and libs. If none is the obvious culprit then give a--- generic error message.--- TODO: produce a log file from the compiler errors, if any.-checkForeignDeps :: PackageDescription -> LocalBuildInfo -> Verbosity -> IO ()-checkForeignDeps pkg lbi verbosity =- ifBuildsWith allHeaders (commonCcArgs ++ makeLdArgs allLibs) -- I'm feeling- -- lucky- (return ())- (do missingLibs <- findMissingLibs- missingHdr <- findOffendingHdr- explainErrors missingHdr missingLibs)- where- allHeaders = collectField includes- allLibs = collectField extraLibs-- ifBuildsWith headers args success failure = do- checkDuplicateHeaders- ok <- builds (makeProgram headers) args- if ok then success else failure-- -- Ensure that there is only one header with a given name- -- in either the generated (most likely by `configure`)- -- build directory (e.g. `dist/build`) or in the source directory.- --- -- If it exists in both, we'll remove the one in the source- -- directory, as the generated should take precedence.- --- -- C compilers like to prefer source local relative includes,- -- so the search paths provided to the compiler via -I are- -- ignored if the included file can be found relative to the- -- including file. As such we need to take drastic measures- -- and delete the offending file in the source directory.- checkDuplicateHeaders = do- let relIncDirs = filter (not . isAbsolute) (collectField includeDirs)- isHeader = isSuffixOf ".h"- genHeaders <- for relIncDirs $ \dir ->- fmap (dir </>) . filter isHeader <$>- listDirectory (buildDir lbi </> dir) `catchIO` (\_ -> return [])- srcHeaders <- for relIncDirs $ \dir ->- fmap (dir </>) . filter isHeader <$>- listDirectory (baseDir lbi </> dir) `catchIO` (\_ -> return [])- let commonHeaders = concat genHeaders `intersect` concat srcHeaders- for_ commonHeaders $ \hdr -> do- warn verbosity $ "Duplicate header found in "- ++ (buildDir lbi </> hdr)- ++ " and "- ++ (baseDir lbi </> hdr)- ++ "; removing "- ++ (baseDir lbi </> hdr)- removeFile (baseDir lbi </> hdr)-- findOffendingHdr =- ifBuildsWith allHeaders ccArgs- (return Nothing)- (go . Unsafe.tail . inits $ allHeaders) -- inits always contains at least []- where- go [] = return Nothing -- cannot happen- go (hdrs:hdrsInits) =- -- Try just preprocessing first- ifBuildsWith hdrs cppArgs- -- If that works, try compiling too- (ifBuildsWith hdrs ccArgs- (go hdrsInits)- (return . fmap Right . safeLast $ hdrs))- (return . fmap Left . safeLast $ hdrs)--- cppArgs = "-E":commonCppArgs -- preprocess only- ccArgs = "-c":commonCcArgs -- don't try to link-- findMissingLibs = ifBuildsWith [] (makeLdArgs allLibs)- (return [])- (filterM (fmap not . libExists) allLibs)-- libExists lib = builds (makeProgram []) (makeLdArgs [lib])-- baseDir lbi' = fromMaybe "." (takeDirectory <$> cabalFilePath lbi')-- commonCppArgs = platformDefines lbi- -- TODO: This is a massive hack, to work around the- -- fact that the test performed here should be- -- PER-component (c.f. the "I'm Feeling Lucky"; we- -- should NOT be glomming everything together.)- ++ [ "-I" ++ buildDir lbi </> "autogen" ]- -- `configure' may generate headers in the build directory- ++ [ "-I" ++ buildDir lbi </> dir- | dir <- ordNub (collectField includeDirs)- , not (isAbsolute dir)]- -- we might also reference headers from the- -- packages directory.- ++ [ "-I" ++ baseDir lbi </> dir- | dir <- ordNub (collectField includeDirs)- , not (isAbsolute dir)]- ++ [ "-I" ++ dir | dir <- ordNub (collectField includeDirs)- , isAbsolute dir]- ++ ["-I" ++ baseDir lbi]- ++ collectField cppOptions- ++ collectField ccOptions- ++ [ "-I" ++ dir- | dir <- ordNub [ dir- | dep <- deps- , dir <- IPI.includeDirs dep ]- -- dedupe include dirs of dependencies- -- to prevent quadratic blow-up- ]- ++ [ opt- | dep <- deps- , opt <- IPI.ccOptions dep ]-- commonCcArgs = commonCppArgs- ++ collectField ccOptions- ++ [ opt- | dep <- deps- , opt <- IPI.ccOptions dep ]-- commonLdArgs = [ "-L" ++ dir- | dir <- ordNub (collectField extraLibDirs) ]- ++ collectField ldOptions- ++ [ "-L" ++ dir- | dir <- ordNub [ dir- | dep <- deps- , dir <- IPI.libraryDirs dep ]- ]- --TODO: do we also need dependent packages' ld options?- makeLdArgs libs = [ "-l"++lib | lib <- libs ] ++ commonLdArgs-- makeProgram hdrs = unlines $- [ "#include \"" ++ hdr ++ "\"" | hdr <- hdrs ] ++- ["int main(int argc, char** argv) { return 0; }"]-- collectField f = concatMap f allBi- allBi = enabledBuildInfos pkg (componentEnabledSpec lbi)- deps = PackageIndex.topologicalOrder (installedPkgs lbi)-- builds program args = do- tempDir <- getTemporaryDirectory- withTempFile tempDir ".c" $ \cName cHnd ->- withTempFile tempDir "" $ \oNname oHnd -> do- hPutStrLn cHnd program- hClose cHnd- hClose oHnd- _ <- getDbProgramOutput verbosity- gccProgram (withPrograms lbi) (cName:"-o":oNname:args)- return True- `catchIO` (\_ -> return False)- `catchExit` (\_ -> return False)-- explainErrors Nothing [] = return () -- should be impossible!- explainErrors _ _- | isNothing . lookupProgram gccProgram . withPrograms $ lbi-- = die' verbosity $ unlines- [ "No working gcc",- "This package depends on foreign library but we cannot "- ++ "find a working C compiler. If you have it in a "- ++ "non-standard location you can use the --with-gcc "- ++ "flag to specify it." ]-- explainErrors hdr libs = die' verbosity $ unlines $- [ if plural- then "Missing dependencies on foreign libraries:"- else "Missing dependency on a foreign library:"- | missing ]- ++ case hdr of- Just (Left h) -> ["* Missing (or bad) header file: " ++ h ]- _ -> []- ++ case libs of- [] -> []- [lib] -> ["* Missing (or bad) C library: " ++ lib]- _ -> ["* Missing (or bad) C libraries: " ++- intercalate ", " libs]- ++ [if plural then messagePlural else messageSingular | missing]- ++ case hdr of- Just (Left _) -> [ headerCppMessage ]- Just (Right h) -> [ (if missing then "* " else "")- ++ "Bad header file: " ++ h- , headerCcMessage ]- _ -> []-- where- plural = length libs >= 2- -- Is there something missing? (as opposed to broken)- missing = not (null libs)- || case hdr of Just (Left _) -> True; _ -> False-- messageSingular =- "This problem can usually be solved by installing the system "- ++ "package that provides this library (you may need the "- ++ "\"-dev\" version). If the library is already installed "- ++ "but in a non-standard location then you can use the flags "- ++ "--extra-include-dirs= and --extra-lib-dirs= to specify "- ++ "where it is."- ++ "If the library file does exist, it may contain errors that "- ++ "are caught by the C compiler at the preprocessing stage. "- ++ "In this case you can re-run configure with the verbosity "- ++ "flag -v3 to see the error messages."- messagePlural =- "This problem can usually be solved by installing the system "- ++ "packages that provide these libraries (you may need the "- ++ "\"-dev\" versions). If the libraries are already installed "- ++ "but in a non-standard location then you can use the flags "- ++ "--extra-include-dirs= and --extra-lib-dirs= to specify "- ++ "where they are."- ++ "If the library files do exist, it may contain errors that "- ++ "are caught by the C compiler at the preprocessing stage. "- ++ "In this case you can re-run configure with the verbosity "- ++ "flag -v3 to see the error messages."- headerCppMessage =- "If the header file does exist, it may contain errors that "- ++ "are caught by the C compiler at the preprocessing stage. "- ++ "In this case you can re-run configure with the verbosity "- ++ "flag -v3 to see the error messages."- headerCcMessage =- "The header file contains a compile error. "- ++ "You can re-run configure with the verbosity flag "- ++ "-v3 to see the error messages from the C compiler."---- | Output package check warnings and errors. Exit if any errors.-checkPackageProblems :: Verbosity- -> FilePath- -- ^ Path to the @.cabal@ file's directory- -> GenericPackageDescription- -> PackageDescription- -> IO ()-checkPackageProblems verbosity dir gpkg pkg = do- ioChecks <- checkPackageFiles verbosity pkg dir- let pureChecks = checkPackage gpkg (Just pkg)- errors = [ e | PackageBuildImpossible e <- pureChecks ++ ioChecks ]- warnings = [ w | PackageBuildWarning w <- pureChecks ++ ioChecks ]- if null errors- then traverse_ (warn verbosity) warnings- else die' verbosity (intercalate "\n\n" errors)---- | Preform checks if a relocatable build is allowed-checkRelocatable :: Verbosity- -> PackageDescription- -> LocalBuildInfo- -> IO ()-checkRelocatable verbosity pkg lbi- = sequence_ [ checkOS- , checkCompiler- , packagePrefixRelative- , depsPrefixRelative- ]- where- -- Check if the OS support relocatable builds.- --- -- If you add new OS' to this list, and your OS supports dynamic libraries- -- and RPATH, make sure you add your OS to RPATH-support list of:- -- Distribution.Simple.GHC.getRPaths- checkOS- = unless (os `elem` [ OSX, Linux ])- $ die' verbosity $ "Operating system: " ++ prettyShow os ++- ", does not support relocatable builds"- where- (Platform _ os) = hostPlatform lbi-- -- Check if the Compiler support relocatable builds- checkCompiler- = unless (compilerFlavor comp `elem` [ GHC ])- $ die' verbosity $ "Compiler: " ++ show comp ++- ", does not support relocatable builds"- where- comp = compiler lbi-- -- Check if all the install dirs are relative to same prefix- packagePrefixRelative- = unless (relativeInstallDirs installDirs)- $ die' verbosity $ "Installation directories are not prefix_relative:\n" ++- show installDirs- where- -- NB: should be good enough to check this against the default- -- component ID, but if we wanted to be strictly correct we'd- -- check for each ComponentId.- installDirs = absoluteInstallDirs pkg lbi NoCopyDest- p = prefix installDirs- relativeInstallDirs (InstallDirs {..}) =- all isJust- (fmap (stripPrefix p)- [ bindir, libdir, dynlibdir, libexecdir, includedir, datadir- , docdir, mandir, htmldir, haddockdir, sysconfdir] )-- -- Check if the library dirs of the dependencies that are in the package- -- database to which the package is installed are relative to the- -- prefix of the package- depsPrefixRelative = do- pkgr <- GHC.pkgRoot verbosity lbi (registrationPackageDB (withPackageDB lbi))- traverse_ (doCheck pkgr) ipkgs- where- doCheck pkgr ipkg- | maybe False (== pkgr) (IPI.pkgRoot ipkg)- = for_ (IPI.libraryDirs ipkg) $ \libdir -> do- -- When @prefix@ is not under @pkgroot@,- -- @shortRelativePath prefix pkgroot@ will return a path with- -- @..@s and following check will fail without @canonicalizePath@.- canonicalized <- canonicalizePath libdir- unless (p `isPrefixOf` canonicalized) $- die' verbosity $ msg libdir- | otherwise- = return ()- -- NB: should be good enough to check this against the default- -- component ID, but if we wanted to be strictly correct we'd- -- check for each ComponentId.- installDirs = absoluteInstallDirs pkg lbi NoCopyDest- p = prefix installDirs- ipkgs = PackageIndex.allPackages (installedPkgs lbi)- msg l = "Library directory of a dependency: " ++ show l ++- "\nis not relative to the installation prefix:\n" ++- show p---- -------------------------------------------------------------------------------- Testing foreign library requirements--unsupportedForeignLibs :: Compiler -> Platform -> [ForeignLib] -> [String]-unsupportedForeignLibs comp platform =- mapMaybe (checkForeignLibSupported comp platform)--checkForeignLibSupported :: Compiler -> Platform -> ForeignLib -> Maybe String-checkForeignLibSupported comp platform flib = go (compilerFlavor comp)- where- go :: CompilerFlavor -> Maybe String- go GHC- | compilerVersion comp < mkVersion [7,8] = unsupported [- "Building foreign libraires is only supported with GHC >= 7.8"- ]- | otherwise = goGhcPlatform platform- go _ = unsupported [- "Building foreign libraries is currently only supported with ghc"- ]-- goGhcPlatform :: Platform -> Maybe String- goGhcPlatform (Platform X86_64 OSX ) = goGhcOsx (foreignLibType flib)- goGhcPlatform (Platform _ Linux ) = goGhcLinux (foreignLibType flib)- goGhcPlatform (Platform I386 Windows) = goGhcWindows (foreignLibType flib)- goGhcPlatform (Platform X86_64 Windows) = goGhcWindows (foreignLibType flib)- goGhcPlatform _ = unsupported [- "Building foreign libraries is currently only supported on OSX, "- , "Linux and Windows"- ]-- goGhcOsx :: ForeignLibType -> Maybe String- goGhcOsx ForeignLibNativeShared- | not (null (foreignLibModDefFile flib)) = unsupported [- "Module definition file not supported on OSX"- ]- | not (null (foreignLibVersionInfo flib)) = unsupported [- "Foreign library versioning not currently supported on OSX"- ]- | otherwise =- Nothing- goGhcOsx _ = unsupported [- "We can currently only build shared foreign libraries on OSX"- ]-- goGhcLinux :: ForeignLibType -> Maybe String- goGhcLinux ForeignLibNativeShared- | not (null (foreignLibModDefFile flib)) = unsupported [- "Module definition file not supported on Linux"- ]- | not (null (foreignLibVersionInfo flib))- && not (null (foreignLibVersionLinux flib)) = unsupported [- "You must not specify both lib-version-info and lib-version-linux"- ]- | otherwise =- Nothing- goGhcLinux _ = unsupported [- "We can currently only build shared foreign libraries on Linux"- ]-- goGhcWindows :: ForeignLibType -> Maybe String- goGhcWindows ForeignLibNativeShared- | not standalone = unsupported [- "We can currently only build standalone libraries on Windows. Use\n"- , " if os(Windows)\n"- , " options: standalone\n"- , "in your foreign-library stanza."- ]- | not (null (foreignLibVersionInfo flib)) = unsupported [- "Foreign library versioning not currently supported on Windows.\n"- , "You can specify module definition files in the mod-def-file field."- ]- | otherwise =- Nothing- goGhcWindows _ = unsupported [- "We can currently only build shared foreign libraries on Windows"- ]-- standalone :: Bool- standalone = ForeignLibStandalone `elem` foreignLibOptions flib-- unsupported :: [String] -> Maybe String- unsupported = Just . concat
− Distribution/Simple/Doctest.hs
@@ -1,187 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Doctest--- Copyright : Moritz Angermann 2017--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module deals with the @doctest@ command.---- Note: this module is modelled after Distribution.Simple.Haddock--module Distribution.Simple.Doctest (- doctest- ) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS---- local-import Distribution.PackageDescription-import Distribution.Simple.Compiler-import Distribution.Simple.Program.GHC-import Distribution.Simple.Program-import Distribution.Simple.PreProcess-import Distribution.Simple.Setup-import Distribution.Simple.Build-import Distribution.Simple.LocalBuildInfo hiding (substPathTemplate)-import Distribution.Simple.Register (internalPackageDBPath)-import Distribution.Simple.BuildPaths-import Distribution.Simple.Utils-import Distribution.System-import Distribution.Version-import Distribution.Verbosity---- -------------------------------------------------------------------------------- Types---- | A record that represents the arguments to the doctest executable.-data DoctestArgs = DoctestArgs {- argTargets :: [FilePath]- -- ^ Modules to process- , argGhcOptions :: Flag (GhcOptions, Version)-} deriving (Show, Generic)---- -------------------------------------------------------------------------------- Doctest support--doctest :: PackageDescription- -> LocalBuildInfo- -> [PPSuffixHandler]- -> DoctestFlags- -> IO ()-doctest pkg_descr lbi suffixes doctestFlags = do- let verbosity = flag doctestVerbosity- distPref = flag doctestDistPref- flag f = fromFlag $ f doctestFlags- tmpFileOpts = defaultTempFileOptions- lbi' = lbi { withPackageDB = withPackageDB lbi- ++ [SpecificPackageDB (internalPackageDBPath lbi distPref)] }-- (doctestProg, _version, _) <-- requireProgramVersion verbosity doctestProgram- (orLaterVersion (mkVersion [0,11,3])) (withPrograms lbi)-- withAllComponentsInBuildOrder pkg_descr lbi $ \component clbi -> do- componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity- preprocessComponent pkg_descr component lbi clbi False verbosity suffixes-- case component of- CLib lib -> do- withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi) "tmp" $- \tmp -> do- inFiles <- map snd <$> getLibSourceFiles verbosity lbi lib clbi- args <- mkDoctestArgs verbosity tmp lbi' clbi inFiles (libBuildInfo lib)- runDoctest verbosity (compiler lbi) (hostPlatform lbi) doctestProg args- CExe exe -> do- withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi) "tmp" $- \tmp -> do- inFiles <- map snd <$> getExeSourceFiles verbosity lbi exe clbi- args <- mkDoctestArgs verbosity tmp lbi' clbi inFiles (buildInfo exe)- runDoctest verbosity (compiler lbi) (hostPlatform lbi) doctestProg args- CFLib _ -> return () -- do not doctest foreign libs- CTest _ -> return () -- do not doctest tests- CBench _ -> return () -- do not doctest benchmarks---- -------------------------------------------------------------------------------- Contributions to DoctestArgs (see also Haddock.hs for very similar code).--componentGhcOptions :: Verbosity -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo -> FilePath- -> GhcOptions-componentGhcOptions verbosity lbi bi clbi odir =- let f = case compilerFlavor (compiler lbi) of- GHC -> GHC.componentGhcOptions- GHCJS -> GHCJS.componentGhcOptions- _ -> error $- "Distribution.Simple.Doctest.componentGhcOptions:" ++- "doctest only supports GHC and GHCJS"- in f verbosity lbi bi clbi odir--mkDoctestArgs :: Verbosity- -> FilePath- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> [FilePath]- -> BuildInfo- -> IO DoctestArgs-mkDoctestArgs verbosity tmp lbi clbi inFiles bi = do- let vanillaOpts = (componentGhcOptions normal lbi bi clbi (buildDir lbi))- { ghcOptOptimisation = mempty -- no optimizations when runnign doctest- -- disable -Wmissing-home-modules- , ghcOptWarnMissingHomeModules = mempty- -- clear out ghc-options: these are likely not meant for doctest.- -- If so, should be explicitly specified via doctest-ghc-options: again.- , ghcOptExtra = mempty- , ghcOptCabal = toFlag False-- , ghcOptObjDir = toFlag tmp- , ghcOptHiDir = toFlag tmp- , ghcOptStubDir = toFlag tmp }- sharedOpts = vanillaOpts- { ghcOptDynLinkMode = toFlag GhcDynamicOnly- , ghcOptFPic = toFlag True- , ghcOptHiSuffix = toFlag "dyn_hi"- , ghcOptObjSuffix = toFlag "dyn_o"- , ghcOptExtra = hcSharedOptions GHC bi}- opts <- if withVanillaLib lbi- then return vanillaOpts- else if withSharedLib lbi- then return sharedOpts- else die' verbosity $ "Must have vanilla or shared libraries "- ++ "enabled in order to run doctest"- ghcVersion <- maybe (die' verbosity "Compiler has no GHC version")- return- (compilerCompatVersion GHC (compiler lbi))- return $ DoctestArgs- { argTargets = inFiles- , argGhcOptions = toFlag (opts, ghcVersion)- }----- -------------------------------------------------------------------------------- Call doctest with the specified arguments.-runDoctest :: Verbosity- -> Compiler- -> Platform- -> ConfiguredProgram- -> DoctestArgs- -> IO ()-runDoctest verbosity comp platform doctestProg args = do- renderArgs verbosity comp platform args $- \(flags, files) -> do- runProgram verbosity doctestProg (flags <> files)--renderArgs :: Verbosity- -> Compiler- -> Platform- -> DoctestArgs- -> (([String],[FilePath]) -> IO a)- -> IO a-renderArgs _verbosity comp platform args k = do- k (flags, argTargets args)- where- flags :: [String]- flags = mconcat- [ pure "--no-magic" -- disable doctests automagic discovery heuristics- , pure "-fdiagnostics-color=never" -- disable ghc's color diagnostics.- , [ opt | (opts, _ghcVer) <- flagToList (argGhcOptions args)- , opt <- renderGhcOptions comp platform opts ]- ]---- --------------------------------------------------------------------------------- Boilerplate Monoid instance.-instance Monoid DoctestArgs where- mempty = gmempty- mappend = (<>)--instance Semigroup DoctestArgs where- (<>) = gmappend
− Distribution/Simple/Flag.hs
@@ -1,132 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Flag--- Copyright : Isaac Jones 2003-2004--- Duncan Coutts 2007--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Defines the 'Flag' type and it's 'Monoid' instance, see--- <http://www.haskell.org/pipermail/cabal-devel/2007-December/001509.html>--- for an explanation.------ Split off from "Distribution.Simple.Setup" to break import cycles.-module Distribution.Simple.Flag (- Flag(..),- allFlags,- toFlag,- fromFlag,- fromFlagOrDefault,- flagElim,- flagToMaybe,- flagToList,- maybeToFlag,- BooleanFlag(..) ) where--import Prelude ()-import Distribution.Compat.Prelude hiding (get)-import Distribution.Compat.Stack---- --------------------------------------------------------------- * Flag type--- ---------------------------------------------------------------- | All flags are monoids, they come in two flavours:------ 1. list flags eg------ > --ghc-option=foo --ghc-option=bar------ gives us all the values ["foo", "bar"]------ 2. singular value flags, eg:------ > --enable-foo --disable-foo------ gives us Just False--- So this Flag type is for the latter singular kind of flag.--- Its monoid instance gives us the behaviour where it starts out as--- 'NoFlag' and later flags override earlier ones.----data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read, Typeable)--instance Binary a => Binary (Flag a)-instance Structured a => Structured (Flag a)--instance Functor Flag where- fmap f (Flag x) = Flag (f x)- fmap _ NoFlag = NoFlag--instance Applicative Flag where- (Flag x) <*> y = x <$> y- NoFlag <*> _ = NoFlag- pure = Flag--instance Monoid (Flag a) where- mempty = NoFlag- mappend = (<>)--instance Semigroup (Flag a) where- _ <> f@(Flag _) = f- f <> NoFlag = f--instance Bounded a => Bounded (Flag a) where- minBound = toFlag minBound- maxBound = toFlag maxBound--instance Enum a => Enum (Flag a) where- fromEnum = fromEnum . fromFlag- toEnum = toFlag . toEnum- enumFrom (Flag a) = map toFlag . enumFrom $ a- enumFrom _ = []- enumFromThen (Flag a) (Flag b) = toFlag `map` enumFromThen a b- enumFromThen _ _ = []- enumFromTo (Flag a) (Flag b) = toFlag `map` enumFromTo a b- enumFromTo _ _ = []- enumFromThenTo (Flag a) (Flag b) (Flag c) = toFlag `map` enumFromThenTo a b c- enumFromThenTo _ _ _ = []--toFlag :: a -> Flag a-toFlag = Flag--fromFlag :: WithCallStack (Flag a -> a)-fromFlag (Flag x) = x-fromFlag NoFlag = error "fromFlag NoFlag. Use fromFlagOrDefault"--fromFlagOrDefault :: a -> Flag a -> a-fromFlagOrDefault _ (Flag x) = x-fromFlagOrDefault def NoFlag = def--flagToMaybe :: Flag a -> Maybe a-flagToMaybe (Flag x) = Just x-flagToMaybe NoFlag = Nothing---- | @since 3.4.0.0-flagElim :: b -> (a -> b) -> Flag a -> b-flagElim n _ NoFlag = n-flagElim _ f (Flag x) = f x--flagToList :: Flag a -> [a]-flagToList (Flag x) = [x]-flagToList NoFlag = []--allFlags :: [Flag Bool] -> Flag Bool-allFlags flags = if all (\f -> fromFlagOrDefault False f) flags- then Flag True- else NoFlag--maybeToFlag :: Maybe a -> Flag a-maybeToFlag Nothing = NoFlag-maybeToFlag (Just x) = Flag x---- | Types that represent boolean flags.-class BooleanFlag a where- asBool :: a -> Bool--instance BooleanFlag Bool where- asBool = id
− Distribution/Simple/GHC.hs
@@ -1,2084 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE CPP #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.GHC--- Copyright : Isaac Jones 2003-2007--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is a fairly large module. It contains most of the GHC-specific code for--- configuring, building and installing packages. It also exports a function--- for finding out what packages are already installed. Configuring involves--- finding the @ghc@ and @ghc-pkg@ programs, finding what language extensions--- this version of ghc supports and returning a 'Compiler' value.------ 'getInstalledPackages' involves calling the @ghc-pkg@ program to find out--- what packages are installed.------ Building is somewhat complex as there is quite a bit of information to take--- into account. We have to build libs and programs, possibly for profiling and--- shared libs. We have to support building libraries that will be usable by--- GHCi and also ghc's @-split-objs@ feature. We have to compile any C files--- using ghc. Linking, especially for @split-objs@ is remarkably complex,--- partly because there tend to be 1,000's of @.o@ files and this can often be--- more than we can pass to the @ld@ or @ar@ programs in one go.------ Installing for libs and exes involves finding the right files and copying--- them to the right places. One of the more tricky things about this module is--- remembering the layout of files in the build directory (which is not--- explicitly documented) and thus what search dirs are used for various kinds--- of files.--module Distribution.Simple.GHC (- getGhcInfo,- configure,- getInstalledPackages,- getInstalledPackagesMonitorFiles,- getPackageDBContents,- buildLib, buildFLib, buildExe,- replLib, replFLib, replExe,- startInterpreter,- installLib, installFLib, installExe,- libAbiHash,- hcPkgInfo,- registerPackage,- componentGhcOptions,- componentCcGhcOptions,- getGhcAppDir,- getLibDir,- isDynamic,- getGlobalPackageDB,- pkgRoot,- -- * Constructing and deconstructing GHC environment files- Internal.GhcEnvironmentFileEntry(..),- Internal.simpleGhcEnvironmentFile,- Internal.renderGhcEnvironmentFile,- Internal.writeGhcEnvironmentFile,- Internal.ghcPlatformAndVersionString,- readGhcEnvironmentFile,- parseGhcEnvironmentFile,- ParseErrorExc(..),- -- * Version-specific implementation quirks- getImplInfo,- GhcImplInfo(..)- ) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Distribution.Simple.GHC.Internal as Internal-import Distribution.CabalSpecVersion-import Distribution.Simple.GHC.ImplInfo-import Distribution.Simple.GHC.EnvironmentParser-import Distribution.PackageDescription.Utils (cabalBug)-import Distribution.PackageDescription as PD-import Distribution.InstalledPackageInfo (InstalledPackageInfo)-import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo-import Distribution.Simple.PackageIndex (InstalledPackageIndex)-import qualified Distribution.Simple.PackageIndex as PackageIndex-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.ComponentLocalBuildInfo-import qualified Distribution.Simple.Hpc as Hpc-import Distribution.Simple.BuildPaths-import Distribution.Simple.Utils-import Distribution.Package-import qualified Distribution.ModuleName as ModuleName-import Distribution.ModuleName (ModuleName)-import Distribution.Simple.Program-import Distribution.Simple.Program.Builtin (runghcProgram)-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-import qualified Distribution.Simple.Setup as Cabal-import Distribution.Simple.Compiler-import Distribution.Version-import Distribution.System-import Distribution.Verbosity-import Distribution.Pretty-import Distribution.Utils.NubList-import Language.Haskell.Extension--import Control.Monad (msum, forM_)-import Data.Char (isLower)-import qualified Data.Map as Map-import System.Directory- ( doesFileExist, getAppUserDataDirectory, createDirectoryIfMissing- , canonicalizePath, removeFile, renameFile, getDirectoryContents )-import System.FilePath ( (</>), (<.>), takeExtension- , takeDirectory, replaceExtension- ,isRelative )-import qualified System.Info-#ifndef mingw32_HOST_OS-import System.Posix (createSymbolicLink)-#endif /* mingw32_HOST_OS */---- -------------------------------------------------------------------------------- Configuring--configure :: Verbosity -> Maybe FilePath -> Maybe FilePath- -> ProgramDb- -> IO (Compiler, Maybe Platform, ProgramDb)-configure verbosity hcPath hcPkgPath conf0 = do-- (ghcProg, ghcVersion, progdb1) <-- requireProgramVersion verbosity ghcProgram- (orLaterVersion (mkVersion [7,0,1]))- (userMaybeSpecifyPath "ghc" hcPath conf0)- let implInfo = ghcVersionImplInfo ghcVersion-- -- Cabal currently supports ghc >= 7.0.1 && < 9.1- -- ... and the following odd development version- unless (ghcVersion < mkVersion [9,2]) $- warn verbosity $- "Unknown/unsupported 'ghc' version detected "- ++ "(Cabal " ++ prettyShow cabalVersion ++ " supports 'ghc' version < 9.1): "- ++ programPath ghcProg ++ " is version " ++ prettyShow ghcVersion-- -- This is slightly tricky, we have to configure ghc first, then we use the- -- location of ghc to help find ghc-pkg in the case that the user did not- -- specify the location of ghc-pkg directly:- (ghcPkgProg, ghcPkgVersion, progdb2) <-- requireProgramVersion verbosity ghcPkgProgram {- programFindLocation = guessGhcPkgFromGhcPath ghcProg- }- anyVersion (userMaybeSpecifyPath "ghc-pkg" hcPkgPath progdb1)-- when (ghcVersion /= ghcPkgVersion) $ die' verbosity $- "Version mismatch between ghc and ghc-pkg: "- ++ programPath ghcProg ++ " is version " ++ prettyShow ghcVersion ++ " "- ++ programPath ghcPkgProg ++ " is version " ++ prettyShow ghcPkgVersion-- -- Likewise we try to find the matching hsc2hs and haddock programs.- let hsc2hsProgram' = hsc2hsProgram {- programFindLocation = guessHsc2hsFromGhcPath ghcProg- }- haddockProgram' = haddockProgram {- programFindLocation = guessHaddockFromGhcPath ghcProg- }- hpcProgram' = hpcProgram {- programFindLocation = guessHpcFromGhcPath ghcProg- }- runghcProgram' = runghcProgram {- programFindLocation = guessRunghcFromGhcPath ghcProg- }- progdb3 = addKnownProgram haddockProgram' $- addKnownProgram hsc2hsProgram' $- addKnownProgram hpcProgram' $- addKnownProgram runghcProgram' progdb2-- languages <- Internal.getLanguages verbosity implInfo ghcProg- extensions0 <- Internal.getExtensions verbosity implInfo ghcProg-- ghcInfo <- Internal.getGhcInfo verbosity implInfo ghcProg- let ghcInfoMap = Map.fromList ghcInfo- extensions = -- workaround https://gitlab.haskell.org/ghc/ghc/-/issues/11214- filterExt JavaScriptFFI $- -- see 'filterExtTH' comment below- filterExtTH $ extensions0-- -- 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`- filterExtTH | ghcVersion < mkVersion [8]- , Just "NO" <- Map.lookup "Have interpreter" ghcInfoMap- = filterExt TemplateHaskell- | otherwise = id-- filterExt ext = filter ((/= EnableExtension ext) . fst)-- let comp = Compiler {- compilerId = CompilerId GHC ghcVersion,- compilerAbiTag = NoAbiTag,- compilerCompat = [],- compilerLanguages = languages,- compilerExtensions = extensions,- compilerProperties = ghcInfoMap- }- compPlatform = Internal.targetPlatform ghcInfo- -- configure gcc and ld- progdb4 = Internal.configureToolchain implInfo ghcProg ghcInfoMap progdb3- return (comp, compPlatform, progdb4)---- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find--- the corresponding tool; e.g. if the tool is ghc-pkg, we try looking--- for a versioned or unversioned ghc-pkg in the same dir, that is:------ > /usr/local/bin/ghc-pkg-ghc-6.6.1(.exe)--- > /usr/local/bin/ghc-pkg-6.6.1(.exe)--- > /usr/local/bin/ghc-pkg(.exe)----guessToolFromGhcPath :: Program -> ConfiguredProgram- -> Verbosity -> ProgramSearchPath- -> IO (Maybe (FilePath, [FilePath]))-guessToolFromGhcPath tool ghcProg verbosity searchpath- = do let toolname = programName tool- 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 buildPlatform- guessGhcVersioned dir suf = dir </> (toolname ++ "-ghc" ++ suf)- <.> exeExtension buildPlatform- guessVersioned dir suf = dir </> (toolname ++ suf)- <.> exeExtension buildPlatform- 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 " ++ given_dir- debug verbosity $ "candidate locations: " ++ show guesses- exists <- traverse 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- let lookedAt = map fst- . takeWhile (\(_file, exist) -> not exist)- $ zip guesses exists- return (Just (fp, lookedAt))-- where takeVersionSuffix :: FilePath -> String- takeVersionSuffix = takeWhileEndLE isSuffixChar-- isSuffixChar :: Char -> Bool- isSuffixChar c = isDigit c || c == '.' || c == '-'---- | 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:------ > /usr/local/bin/ghc-pkg-ghc-6.6.1(.exe)--- > /usr/local/bin/ghc-pkg-6.6.1(.exe)--- > /usr/local/bin/ghc-pkg(.exe)----guessGhcPkgFromGhcPath :: ConfiguredProgram- -> 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--- corresponding hsc2hs, we try looking for both a versioned and unversioned--- hsc2hs in the same dir, that is:------ > /usr/local/bin/hsc2hs-ghc-6.6.1(.exe)--- > /usr/local/bin/hsc2hs-6.6.1(.exe)--- > /usr/local/bin/hsc2hs(.exe)----guessHsc2hsFromGhcPath :: ConfiguredProgram- -> 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--guessHpcFromGhcPath :: ConfiguredProgram- -> Verbosity -> ProgramSearchPath- -> IO (Maybe (FilePath, [FilePath]))-guessHpcFromGhcPath = guessToolFromGhcPath hpcProgram--guessRunghcFromGhcPath :: ConfiguredProgram- -> Verbosity -> ProgramSearchPath- -> IO (Maybe (FilePath, [FilePath]))-guessRunghcFromGhcPath = guessToolFromGhcPath runghcProgram---getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)]-getGhcInfo verbosity ghcProg = Internal.getGhcInfo verbosity implInfo ghcProg- where- version = fromMaybe (error "GHC.getGhcInfo: no ghc version") $ programVersion ghcProg- implInfo = ghcVersionImplInfo version---- | Given a single package DB, return all installed packages.-getPackageDBContents :: Verbosity -> PackageDB -> ProgramDb- -> IO InstalledPackageIndex-getPackageDBContents verbosity packagedb progdb = do- pkgss <- getInstalledPackages' verbosity [packagedb] progdb- toPackageIndex verbosity pkgss progdb---- | Given a package DB stack, return all installed packages.-getInstalledPackages :: Verbosity -> Compiler -> PackageDBStack- -> ProgramDb- -> IO InstalledPackageIndex-getInstalledPackages verbosity comp packagedbs progdb = do- checkPackageDbEnvVar verbosity- checkPackageDbStack verbosity comp packagedbs- pkgss <- getInstalledPackages' verbosity packagedbs progdb- index <- toPackageIndex verbosity pkgss progdb- return $! hackRtsPackage index-- where- hackRtsPackage index =- case PackageIndex.lookupPackageName index (mkPackageName "rts") of- [(_,[rts])]- -> PackageIndex.insert (removeMingwIncludeDir rts) index- _ -> index -- No (or multiple) ghc rts package is registered!!- -- Feh, whatever, the ghc test suite does some crazy stuff.---- | Given a list of @(PackageDB, InstalledPackageInfo)@ pairs, produce a--- @PackageIndex@. Helper function used by 'getPackageDBContents' and--- 'getInstalledPackages'.-toPackageIndex :: Verbosity- -> [(PackageDB, [InstalledPackageInfo])]- -> ProgramDb- -> IO InstalledPackageIndex-toPackageIndex verbosity pkgss progdb = do- -- On Windows, various fields have $topdir/foo rather than full- -- paths. We need to substitute the right value in so that when- -- we, for example, call gcc, we have proper paths to give it.- topDir <- getLibDir' verbosity ghcProg- let indices = [ PackageIndex.fromList (map (Internal.substTopDir topDir) pkgs)- | (_, pkgs) <- pkgss ]- return $! mconcat indices-- where- ghcProg = fromMaybe (error "GHC.toPackageIndex: no ghc program") $ lookupProgram ghcProgram progdb---- | Return the 'FilePath' to the GHC application data directory.------ @since 3.4.0.0-getGhcAppDir :: IO FilePath-getGhcAppDir = getAppUserDataDirectory "ghc"--getLibDir :: Verbosity -> LocalBuildInfo -> IO FilePath-getLibDir verbosity lbi =- dropWhileEndLE isSpace `fmap`- getDbProgramOutput verbosity ghcProgram- (withPrograms lbi) ["--print-libdir"]--getLibDir' :: Verbosity -> ConfiguredProgram -> IO FilePath-getLibDir' verbosity ghcProg =- dropWhileEndLE isSpace `fmap`- getProgramOutput verbosity ghcProg ["--print-libdir"]----- | Return the 'FilePath' to the global GHC package database.-getGlobalPackageDB :: Verbosity -> ConfiguredProgram -> IO FilePath-getGlobalPackageDB verbosity ghcProg =- dropWhileEndLE isSpace `fmap`- getProgramOutput 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 = 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 <- getGhcAppDir- return (appdir </> platformAndVersion </> packageConfFileName)- where- platformAndVersion = Internal.ghcPlatformAndVersionString- platform ghcVersion- packageConfFileName = "package.conf.d"- ghcVersion = fromMaybe (error "GHC.getUserPackageDB: no ghc version") $ programVersion ghcProg--checkPackageDbEnvVar :: Verbosity -> IO ()-checkPackageDbEnvVar verbosity =- Internal.checkPackageDbEnvVar verbosity "GHC" "GHC_PACKAGE_PATH"--checkPackageDbStack :: Verbosity -> Compiler -> PackageDBStack -> IO ()-checkPackageDbStack verbosity comp =- if flagPackageConf implInfo- then checkPackageDbStackPre76 verbosity- else checkPackageDbStackPost76 verbosity- where implInfo = ghcVersionImplInfo (compilerVersion comp)--checkPackageDbStackPost76 :: Verbosity -> PackageDBStack -> IO ()-checkPackageDbStackPost76 _ (GlobalPackageDB:rest)- | GlobalPackageDB `notElem` rest = return ()-checkPackageDbStackPost76 verbosity rest- | GlobalPackageDB `elem` rest =- die' verbosity $ "If the global package db is specified, it must be "- ++ "specified first and cannot be specified multiple times"-checkPackageDbStackPost76 _ _ = return ()--checkPackageDbStackPre76 :: Verbosity -> PackageDBStack -> IO ()-checkPackageDbStackPre76 _ (GlobalPackageDB:rest)- | GlobalPackageDB `notElem` rest = return ()-checkPackageDbStackPre76 verbosity rest- | GlobalPackageDB `notElem` rest =- die' verbosity $- "With current ghc versions the global package db is always used "- ++ "and must be listed first. This ghc limitation is lifted in GHC 7.6,"- ++ "see https://gitlab.haskell.org/ghc/ghc/-/issues/5977"-checkPackageDbStackPre76 verbosity _ =- die' verbosity $ "If the global package db is specified, it must be "- ++ "specified first and cannot be specified multiple times"---- GHC < 6.10 put "$topdir/include/mingw" in rts's installDirs. This--- breaks when you want to use a different gcc, so we need to filter--- it out.-removeMingwIncludeDir :: InstalledPackageInfo -> InstalledPackageInfo-removeMingwIncludeDir pkg =- let ids = InstalledPackageInfo.includeDirs pkg- ids' = filter (not . ("mingw" `isSuffixOf`)) ids- in pkg { InstalledPackageInfo.includeDirs = ids' }---- | Get the packages from specific PackageDBs, not cumulative.----getInstalledPackages' :: Verbosity -> [PackageDB] -> ProgramDb- -> IO [(PackageDB, [InstalledPackageInfo])]-getInstalledPackages' verbosity packagedbs progdb =- sequenceA- [ do pkgs <- HcPkg.dump (hcPkgInfo progdb) verbosity packagedb- return (packagedb, pkgs)- | packagedb <- packagedbs ]--getInstalledPackagesMonitorFiles :: Verbosity -> Platform- -> ProgramDb- -> [PackageDB]- -> IO [FilePath]-getInstalledPackagesMonitorFiles verbosity platform progdb =- traverse 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")-- ghcProg = fromMaybe (error "GHC.toPackageIndex: no ghc program") $ lookupProgram ghcProgram progdb----- -------------------------------------------------------------------------------- Building a library--buildLib :: Verbosity -> Cabal.Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> Library -> ComponentLocalBuildInfo -> IO ()-buildLib = buildOrReplLib Nothing--replLib :: [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> Library- -> ComponentLocalBuildInfo -> IO ()-replLib = buildOrReplLib . Just--buildOrReplLib :: Maybe [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> Library- -> ComponentLocalBuildInfo -> IO ()-buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do- let uid = componentUnitId clbi- libTargetDir = componentBuildDir lbi clbi- whenVanillaLib forceVanilla =- when (forceVanilla || withVanillaLib lbi)- whenProfLib = when (withProfLib lbi)- whenSharedLib forceShared =- when (forceShared || withSharedLib lbi)- whenStaticLib forceStatic =- when (forceStatic || withStaticLib lbi)- whenGHCiLib = when (withGHCiLib lbi)- forRepl = maybe False (const True) mReplFlags- whenReplLib = when forRepl- replFlags = fromMaybe mempty mReplFlags- comp = compiler lbi- ghcVersion = compilerVersion comp- implInfo = getImplInfo comp- platform@(Platform _hostArch hostOS) = hostPlatform lbi- has_code = not (componentIsIndefinite clbi)-- (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)- let runGhcProg = runGHC verbosity ghcProg comp platform-- let libBi = libBuildInfo lib-- let isGhcDynamic = isDynamic comp- dynamicTooSupported = supportsDynamicToo comp- doingTH = usesTemplateHaskellOrQQ libBi- forceVanillaLib = doingTH && not isGhcDynamic- forceSharedLib = doingTH && isGhcDynamic- -- TH always needs default libs, even when building for profiling-- -- Determine if program coverage should be enabled and if so, what- -- '-hpcdir' should be.- let isCoverageEnabled = libCoverage lbi- -- TODO: Historically HPC files have been put into a directory which- -- has the package name. I'm going to avoid changing this for- -- now, but it would probably be better for this to be the- -- component ID instead...- pkg_name = prettyShow (PD.package pkg_descr)- distPref = fromFlag $ configDistPref $ configFlags lbi- hpcdir way- | forRepl = mempty -- HPC is not supported in ghci- | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way pkg_name- | otherwise = mempty-- createDirectoryIfMissingVerbose verbosity True libTargetDir- -- TODO: do we need to put hs-boot files into place for mutually recursive- -- modules?- let cLikeFiles = fromNubListR $ mconcat- [ toNubListR (cSources libBi)- , toNubListR (cxxSources libBi)- , toNubListR (cmmSources libBi)- , toNubListR (asmSources libBi)- ]- cObjs = map (`replaceExtension` objExtension) cLikeFiles- baseOpts = componentGhcOptions verbosity lbi libBi clbi libTargetDir- vanillaOpts = baseOpts `mappend` mempty {- ghcOptMode = toFlag GhcModeMake,- ghcOptNumJobs = numJobs,- ghcOptInputModules = toNubListR $ allLibModules lib clbi,- 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 = hcProfOptions GHC libBi,- ghcOptHPCDir = hpcdir Hpc.Prof- }-- sharedOpts = vanillaOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptFPic = toFlag True,- ghcOptHiSuffix = toFlag "dyn_hi",- ghcOptObjSuffix = toFlag "dyn_o",- ghcOptExtra = hcSharedOptions GHC libBi,- ghcOptHPCDir = hpcdir Hpc.Dyn- }- linkerOpts = mempty {- ghcOptLinkOptions = PD.ldOptions libBi- ++ [ "-static"- | withFullyStaticExe lbi ]- -- Pass extra `ld-options` given- -- through to GHC's linker.- ++ maybe [] programOverrideArgs- (lookupProgram ldProgram (withPrograms lbi)),- ghcOptLinkLibs = 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 = Internal.filterGhciFlags- (ghcOptExtra vanillaOpts)- <> replFlags,- ghcOptNumJobs = mempty- }- `mappend` linkerOpts- `mappend` mempty {- ghcOptMode = toFlag GhcModeInteractive,- ghcOptOptimisation = toFlag GhcNoOptimisation- }-- vanillaSharedOpts = vanillaOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,- ghcOptDynHiSuffix = toFlag "dyn_hi",- ghcOptDynObjSuffix = toFlag "dyn_o",- ghcOptHPCDir = hpcdir Hpc.Dyn- }-- unless (forRepl || null (allLibModules lib clbi)) $- do let vanilla = whenVanillaLib forceVanillaLib (runGhcProg vanillaOpts)- shared = whenSharedLib forceSharedLib (runGhcProg sharedOpts)- useDynToo = dynamicTooSupported &&- (forceVanillaLib || withVanillaLib lbi) &&- (forceSharedLib || withSharedLib lbi) &&- null (hcSharedOptions GHC libBi)- if not has_code- then vanilla- else- if useDynToo- then do- runGhcProg vanillaSharedOpts- case (hpcdir Hpc.Dyn, hpcdir Hpc.Vanilla) of- (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- -- static and dynamically linked executables. We copy- -- the modules interfaces so they are available under- -- both ways.- copyDirectoryRecursive verbosity dynDir vanillaDir- _ -> return ()- else if isGhcDynamic- then do shared; vanilla- else do vanilla; shared- whenProfLib (runGhcProg profOpts)-- -- Build any C++ sources separately.- unless (not has_code || null (cxxSources libBi)) $ do- info verbosity "Building C++ Sources..."- sequence_- [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo- lbi libBi clbi libTargetDir filename- vanillaCxxOpts = if isGhcDynamic- then baseCxxOpts { ghcOptFPic = toFlag True }- else baseCxxOpts- profCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptObjSuffix = toFlag "p_o"- }- sharedCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptObjSuffix = toFlag "dyn_o"- }- odir = fromFlag (ghcOptObjDir vanillaCxxOpts)- createDirectoryIfMissingVerbose verbosity True odir- let runGhcProgIfNeeded cxxOpts = do- needsRecomp <- checkNeedsRecompilation filename cxxOpts- when needsRecomp $ runGhcProg cxxOpts- runGhcProgIfNeeded vanillaCxxOpts- unless forRepl $- whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCxxOpts)- unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts)- | filename <- cxxSources libBi]-- -- build any C sources- unless (not has_code || null (cSources libBi)) $ do- info verbosity "Building C Sources..."- sequence_- [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo- lbi libBi clbi libTargetDir filename- vanillaCcOpts = if isGhcDynamic- -- Dynamic GHC requires C sources to be built- -- with -fPIC for REPL to work. See #2207.- then baseCcOpts { ghcOptFPic = toFlag True }- else baseCcOpts- profCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptObjSuffix = toFlag "p_o"- }- sharedCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptObjSuffix = toFlag "dyn_o"- }- odir = fromFlag (ghcOptObjDir vanillaCcOpts)- createDirectoryIfMissingVerbose verbosity True odir- let runGhcProgIfNeeded ccOpts = do- needsRecomp <- checkNeedsRecompilation filename ccOpts- when needsRecomp $ runGhcProg ccOpts- runGhcProgIfNeeded vanillaCcOpts- unless forRepl $- whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCcOpts)- unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts)- | filename <- cSources libBi]-- -- build any ASM sources- unless (not has_code || null (asmSources libBi)) $ do- info verbosity "Building Assembler Sources..."- sequence_- [ do let baseAsmOpts = Internal.componentAsmGhcOptions verbosity implInfo- lbi libBi clbi libTargetDir filename- vanillaAsmOpts = if isGhcDynamic- -- Dynamic GHC requires objects to be built- -- with -fPIC for REPL to work. See #2207.- then baseAsmOpts { ghcOptFPic = toFlag True }- else baseAsmOpts- profAsmOpts = vanillaAsmOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptObjSuffix = toFlag "p_o"- }- sharedAsmOpts = vanillaAsmOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptObjSuffix = toFlag "dyn_o"- }- odir = fromFlag (ghcOptObjDir vanillaAsmOpts)- createDirectoryIfMissingVerbose verbosity True odir- let runGhcProgIfNeeded asmOpts = do- needsRecomp <- checkNeedsRecompilation filename asmOpts- when needsRecomp $ runGhcProg asmOpts- runGhcProgIfNeeded vanillaAsmOpts- unless forRepl $- whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedAsmOpts)- unless forRepl $ whenProfLib (runGhcProgIfNeeded profAsmOpts)- | filename <- asmSources libBi]-- -- build any Cmm sources- unless (not has_code || null (cmmSources libBi)) $ do- info verbosity "Building C-- Sources..."- sequence_- [ do let baseCmmOpts = Internal.componentCmmGhcOptions verbosity implInfo- lbi libBi clbi libTargetDir filename- vanillaCmmOpts = if isGhcDynamic- -- Dynamic GHC requires C sources to be built- -- with -fPIC for REPL to work. See #2207.- then baseCmmOpts { ghcOptFPic = toFlag True }- else baseCmmOpts- profCmmOpts = vanillaCmmOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptObjSuffix = toFlag "p_o"- }- sharedCmmOpts = vanillaCmmOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptObjSuffix = toFlag "dyn_o"- }- odir = fromFlag (ghcOptObjDir vanillaCmmOpts)- createDirectoryIfMissingVerbose verbosity True odir- let runGhcProgIfNeeded cmmOpts = do- needsRecomp <- checkNeedsRecompilation filename cmmOpts- when needsRecomp $ runGhcProg cmmOpts- runGhcProgIfNeeded vanillaCmmOpts- unless forRepl $- whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCmmOpts)- unless forRepl $ whenProfLib (runGhcProgIfNeeded profCmmOpts)- | filename <- cmmSources libBi]-- -- TODO: problem here is we need the .c files built first, so we can load them- -- with ghci, but .c files can depend on .h files generated by ghc by ffi- -- exports.- whenReplLib $ do- when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"- runGhcProg replOpts-- -- link:- when has_code . unless forRepl $ do- info verbosity "Linking..."- let cProfObjs = map (`replaceExtension` ("p_" ++ objExtension))- (cSources libBi ++ cxxSources libBi)- cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))- (cSources libBi ++ cxxSources libBi)- compiler_id = compilerId (compiler lbi)- vanillaLibFilePath = libTargetDir </> mkLibName uid- profileLibFilePath = libTargetDir </> mkProfLibName uid- sharedLibFilePath = libTargetDir </>- mkSharedLibName (hostPlatform lbi) compiler_id uid- staticLibFilePath = libTargetDir </>- mkStaticLibName (hostPlatform lbi) compiler_id uid- ghciLibFilePath = libTargetDir </> Internal.mkGHCiLibName uid- ghciProfLibFilePath = libTargetDir </> Internal.mkGHCiProfLibName uid- libInstallPath = libdir $- absoluteComponentInstallDirs- pkg_descr lbi uid NoCopyDest- sharedLibInstallPath = libInstallPath </>- mkSharedLibName (hostPlatform lbi) compiler_id uid-- stubObjs <- catMaybes <$> sequenceA- [ findFileWithExtension [objExtension] [libTargetDir]- (ModuleName.toFilePath x ++"_stub")- | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files- , x <- allLibModules lib clbi ]- stubProfObjs <- catMaybes <$> sequenceA- [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]- (ModuleName.toFilePath x ++"_stub")- | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files- , x <- allLibModules lib clbi ]- stubSharedObjs <- catMaybes <$> sequenceA- [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]- (ModuleName.toFilePath x ++"_stub")- | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files- , x <- allLibModules lib clbi ]-- hObjs <- Internal.getHaskellObjects implInfo lib lbi clbi- libTargetDir objExtension True- hProfObjs <-- if withProfLib lbi- then Internal.getHaskellObjects implInfo lib lbi clbi- libTargetDir ("p_" ++ objExtension) True- else return []- hSharedObjs <-- if withSharedLib lbi- then Internal.getHaskellObjects implInfo lib lbi clbi- libTargetDir ("dyn_" ++ objExtension) False- else return []-- unless (null hObjs && null cObjs && null stubObjs) $ do- rpaths <- getRPaths lbi clbi-- let staticObjectFiles =- hObjs- ++ map (libTargetDir </>) cObjs- ++ stubObjs- profObjectFiles =- hProfObjs- ++ map (libTargetDir </>) cProfObjs- ++ stubProfObjs- dynamicObjectFiles =- hSharedObjs- ++ map (libTargetDir </>) cSharedObjs- ++ stubSharedObjs- -- After the relocation lib is created we invoke ghc -shared- -- with the dependencies spelled out as -package arguments- -- and ghc invokes the linker with the proper library paths- ghcSharedLinkArgs =- mempty {- ghcOptShared = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptInputFiles = toNubListR dynamicObjectFiles,- ghcOptOutputFile = toFlag sharedLibFilePath,- ghcOptExtra = 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 < mkVersion [7,8]- then toFlag sharedLibInstallPath- else mempty,- ghcOptHideAllPackages = toFlag True,- ghcOptNoAutoLinkPackages = toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptThisUnitId = case clbi of- LibComponentLocalBuildInfo { componentCompatPackageKey = pk }- -> toFlag pk- _ -> mempty,- ghcOptThisComponentId = case clbi of- LibComponentLocalBuildInfo- { componentInstantiatedWith = insts } ->- if null insts- then mempty- else toFlag (componentComponentId clbi)- _ -> mempty,- ghcOptInstantiatedWith = case clbi of- LibComponentLocalBuildInfo- { componentInstantiatedWith = insts }- -> insts- _ -> [],- ghcOptPackages = toNubListR $- Internal.mkGhcOptPackages clbi ,- ghcOptLinkLibs = extraLibs libBi,- ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi,- ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,- ghcOptLinkFrameworkDirs =- toNubListR $ PD.extraFrameworkDirs libBi,- ghcOptRPaths = rpaths- }- ghcStaticLinkArgs =- mempty {- ghcOptStaticLib = toFlag True,- ghcOptInputFiles = toNubListR staticObjectFiles,- ghcOptOutputFile = toFlag staticLibFilePath,- ghcOptExtra = hcStaticOptions GHC libBi,- ghcOptHideAllPackages = toFlag True,- ghcOptNoAutoLinkPackages = toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptThisUnitId = case clbi of- LibComponentLocalBuildInfo { componentCompatPackageKey = pk }- -> toFlag pk- _ -> mempty,- ghcOptThisComponentId = case clbi of- LibComponentLocalBuildInfo- { componentInstantiatedWith = insts } ->- if null insts- then mempty- else toFlag (componentComponentId clbi)- _ -> mempty,- ghcOptInstantiatedWith = case clbi of- LibComponentLocalBuildInfo- { componentInstantiatedWith = insts }- -> insts- _ -> [],- ghcOptPackages = toNubListR $- Internal.mkGhcOptPackages clbi ,- ghcOptLinkLibs = extraLibs libBi,- ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi- }-- info verbosity (show (ghcOptPackages ghcSharedLinkArgs))-- whenVanillaLib False $ do- Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles- whenGHCiLib $ do- (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)- Ld.combineObjectFiles verbosity lbi ldProg- ghciLibFilePath staticObjectFiles-- whenProfLib $ do- Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles- whenGHCiLib $ do- (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)- Ld.combineObjectFiles verbosity lbi ldProg- ghciProfLibFilePath profObjectFiles-- whenSharedLib False $- runGhcProg ghcSharedLinkArgs-- whenStaticLib False $- runGhcProg ghcStaticLinkArgs---- | Start a REPL without loading any source files.-startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform- -> PackageDBStack -> IO ()-startInterpreter verbosity progdb comp platform packageDBs = do- let replOpts = mempty {- ghcOptMode = toFlag GhcModeInteractive,- ghcOptPackageDBs = packageDBs- }- checkPackageDbStack verbosity comp packageDBs- (ghcProg, _) <- requireProgram verbosity ghcProgram progdb- runGHC verbosity ghcProg comp platform replOpts---- -------------------------------------------------------------------------------- Building an executable or foreign library---- | Build a foreign library-buildFLib- :: Verbosity -> Cabal.Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> ForeignLib -> ComponentLocalBuildInfo -> IO ()-buildFLib v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildFLib--replFLib- :: [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> ForeignLib- -> ComponentLocalBuildInfo -> IO ()-replFLib replFlags v njobs pkg lbi =- gbuild v njobs pkg lbi . GReplFLib replFlags---- | Build an executable with GHC.----buildExe- :: Verbosity -> Cabal.Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> Executable -> ComponentLocalBuildInfo -> IO ()-buildExe v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildExe--replExe- :: [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> Executable- -> ComponentLocalBuildInfo -> IO ()-replExe replFlags v njobs pkg lbi =- gbuild v njobs pkg lbi . GReplExe replFlags---- | Building an executable, starting the REPL, and building foreign--- libraries are all very similar and implemented in 'gbuild'. The--- 'GBuildMode' distinguishes between the various kinds of operation.-data GBuildMode =- GBuildExe Executable- | GReplExe [String] Executable- | GBuildFLib ForeignLib- | GReplFLib [String] ForeignLib--gbuildInfo :: GBuildMode -> BuildInfo-gbuildInfo (GBuildExe exe) = buildInfo exe-gbuildInfo (GReplExe _ exe) = buildInfo exe-gbuildInfo (GBuildFLib flib) = foreignLibBuildInfo flib-gbuildInfo (GReplFLib _ flib) = foreignLibBuildInfo flib--gbuildName :: GBuildMode -> String-gbuildName (GBuildExe exe) = unUnqualComponentName $ exeName exe-gbuildName (GReplExe _ exe) = unUnqualComponentName $ exeName exe-gbuildName (GBuildFLib flib) = unUnqualComponentName $ foreignLibName flib-gbuildName (GReplFLib _ flib) = unUnqualComponentName $ foreignLibName flib--gbuildTargetName :: LocalBuildInfo -> GBuildMode -> String-gbuildTargetName lbi (GBuildExe exe) = exeTargetName (hostPlatform lbi) exe-gbuildTargetName lbi (GReplExe _ exe) = exeTargetName (hostPlatform lbi) exe-gbuildTargetName lbi (GBuildFLib flib) = flibTargetName lbi flib-gbuildTargetName lbi (GReplFLib _ flib) = flibTargetName lbi flib--exeTargetName :: Platform -> Executable -> String-exeTargetName platform exe = unUnqualComponentName (exeName exe) `withExt` exeExtension platform---- | Target name for a foreign library (the actual file name)------ We do not use mkLibName and co here because the naming for foreign libraries--- is slightly different (we don't use "_p" or compiler version suffices, and we--- don't want the "lib" prefix on Windows).------ TODO: We do use `dllExtension` and co here, but really that's wrong: they--- use the OS used to build cabal to determine which extension to use, rather--- than the target OS (but this is wrong elsewhere in Cabal as well).-flibTargetName :: LocalBuildInfo -> ForeignLib -> String-flibTargetName lbi flib =- case (os, foreignLibType flib) of- (Windows, ForeignLibNativeShared) -> nm <.> "dll"- (Windows, ForeignLibNativeStatic) -> nm <.> "lib"- (Linux, ForeignLibNativeShared) -> "lib" ++ nm <.> versionedExt- (_other, ForeignLibNativeShared) ->- "lib" ++ nm <.> dllExtension (hostPlatform lbi)- (_other, ForeignLibNativeStatic) ->- "lib" ++ nm <.> staticLibExtension (hostPlatform lbi)- (_any, ForeignLibTypeUnknown) -> cabalBug "unknown foreign lib type"- where- nm :: String- nm = unUnqualComponentName $ foreignLibName flib-- os :: OS- os = let (Platform _ os') = hostPlatform lbi- in os'-- -- If a foreign lib foo has lib-version-info 5:1:2 or- -- lib-version-linux 3.2.1, it should be built as libfoo.so.3.2.1- -- Libtool's version-info data is translated into library versions in a- -- nontrivial way: so refer to libtool documentation.- versionedExt :: String- versionedExt =- let nums = foreignLibVersion flib os- in foldl (<.>) "so" (map show nums)---- | Name for the library when building.------ If the `lib-version-info` field or the `lib-version-linux` field of--- a foreign library target is set, we need to incorporate that--- version into the SONAME field.------ If a foreign library foo has lib-version-info 5:1:2, it should be--- built as libfoo.so.3.2.1. We want it to get soname libfoo.so.3.--- However, GHC does not allow overriding soname by setting linker--- options, as it sets a soname of its own (namely the output--- filename), after the user-supplied linker options. Hence, we have--- to compile the library with the soname as its filename. We rename--- the compiled binary afterwards.------ This method allows to adjust the name of the library at build time--- such that the correct soname can be set.-flibBuildName :: LocalBuildInfo -> ForeignLib -> String-flibBuildName lbi flib- -- On linux, if a foreign-library has version data, the first digit is used- -- to produce the SONAME.- | (os, foreignLibType flib) ==- (Linux, ForeignLibNativeShared)- = let nums = foreignLibVersion flib os- in "lib" ++ nm <.> foldl (<.>) "so" (map show (take 1 nums))- | otherwise = flibTargetName lbi flib- where- os :: OS- os = let (Platform _ os') = hostPlatform lbi- in os'-- nm :: String- nm = unUnqualComponentName $ foreignLibName flib--gbuildIsRepl :: GBuildMode -> Bool-gbuildIsRepl (GBuildExe _) = False-gbuildIsRepl (GReplExe _ _) = True-gbuildIsRepl (GBuildFLib _) = False-gbuildIsRepl (GReplFLib _ _) = True--gbuildNeedDynamic :: LocalBuildInfo -> GBuildMode -> Bool-gbuildNeedDynamic lbi bm =- case bm of- GBuildExe _ -> withDynExe lbi- GReplExe _ _ -> withDynExe lbi- GBuildFLib flib -> withDynFLib flib- GReplFLib _ flib -> withDynFLib flib- where- withDynFLib flib =- case foreignLibType flib of- ForeignLibNativeShared ->- ForeignLibStandalone `notElem` foreignLibOptions flib- ForeignLibNativeStatic ->- False- ForeignLibTypeUnknown ->- cabalBug "unknown foreign lib type"--gbuildModDefFiles :: GBuildMode -> [FilePath]-gbuildModDefFiles (GBuildExe _) = []-gbuildModDefFiles (GReplExe _ _) = []-gbuildModDefFiles (GBuildFLib flib) = foreignLibModDefFile flib-gbuildModDefFiles (GReplFLib _ flib) = foreignLibModDefFile flib---- | "Main" module name when overridden by @ghc-options: -main-is ...@--- or 'Nothing' if no @-main-is@ flag could be found.------ In case of 'Nothing', 'Distribution.ModuleName.main' can be assumed.-exeMainModuleName :: Executable -> Maybe ModuleName-exeMainModuleName Executable{buildInfo = bnfo} =- -- GHC honors the last occurrence of a module name updated via -main-is- --- -- Moreover, -main-is when parsed left-to-right can update either- -- the "Main" module name, or the "main" function name, or both,- -- see also 'decodeMainIsArg'.- msum $ reverse $ map decodeMainIsArg $ findIsMainArgs ghcopts- where- ghcopts = hcOptions GHC bnfo-- findIsMainArgs [] = []- findIsMainArgs ("-main-is":arg:rest) = arg : findIsMainArgs rest- findIsMainArgs (_:rest) = findIsMainArgs rest---- | Decode argument to '-main-is'------ Returns 'Nothing' if argument set only the function name.------ This code has been stolen/refactored from GHC's DynFlags.setMainIs--- function. The logic here is deliberately imperfect as it is--- intended to be bug-compatible with GHC's parser. See discussion in--- https://github.com/haskell/cabal/pull/4539#discussion_r118981753.-decodeMainIsArg :: String -> Maybe ModuleName-decodeMainIsArg arg- | headOf main_fn isLower- -- The arg looked like "Foo.Bar.baz"- = Just (ModuleName.fromString main_mod)- | headOf arg isUpper -- The arg looked like "Foo" or "Foo.Bar"- = Just (ModuleName.fromString arg)- | otherwise -- The arg looked like "baz"- = Nothing- where- headOf :: String -> (Char -> Bool) -> Bool- headOf str pred' = any pred' (safeHead str)-- (main_mod, main_fn) = splitLongestPrefix arg (== '.')-- splitLongestPrefix :: String -> (Char -> Bool) -> (String,String)- splitLongestPrefix str pred'- | null r_pre = (str, [])- | otherwise = (reverse (safeTail r_pre), reverse r_suf)- -- 'safeTail' drops the char satisfying 'pred'- where (r_suf, r_pre) = break pred' (reverse str)---- | A collection of:--- * C input files--- * C++ input files--- * GHC input files--- * GHC input modules------ Used to correctly build and link sources.-data BuildSources = BuildSources {- cSourcesFiles :: [FilePath],- cxxSourceFiles :: [FilePath],- inputSourceFiles :: [FilePath],- inputSourceModules :: [ModuleName]- }---- | Locate and return the 'BuildSources' required to build and link.-gbuildSources :: Verbosity- -> CabalSpecVersion- -> FilePath- -> GBuildMode- -> IO BuildSources-gbuildSources verbosity specVer tmpDir bm =- case bm of- GBuildExe exe -> exeSources exe- GReplExe _ exe -> exeSources exe- GBuildFLib flib -> return $ flibSources flib- GReplFLib _ flib -> return $ flibSources flib- where- exeSources :: Executable -> IO BuildSources- exeSources exe@Executable{buildInfo = bnfo, modulePath = modPath} = do- main <- findFileEx verbosity (tmpDir : hsSourceDirs bnfo) modPath- let mainModName = fromMaybe ModuleName.main $ exeMainModuleName exe- otherModNames = exeModules exe-- if isHaskell main- then- if specVer < CabalSpecV2_0 && (mainModName `elem` otherModNames)- then do- -- The cabal manual clearly states that `other-modules` is- -- intended for non-main modules. However, there's at least one- -- important package on Hackage (happy-1.19.5) which- -- violates this. We workaround this here so that we don't- -- invoke GHC with e.g. 'ghc --make Main src/Main.hs' which- -- would result in GHC complaining about duplicate Main- -- modules.- --- -- Finally, we only enable this workaround for- -- specVersion < 2, as 'cabal-version:>=2.0' cabal files- -- have no excuse anymore to keep doing it wrong... ;-)- warn verbosity $ "Enabling workaround for Main module '"- ++ prettyShow mainModName- ++ "' listed in 'other-modules' illegally!"-- return BuildSources {- cSourcesFiles = cSources bnfo,- cxxSourceFiles = cxxSources bnfo,- inputSourceFiles = [main],- inputSourceModules = filter (/= mainModName) $- exeModules exe- }-- else return BuildSources {- cSourcesFiles = cSources bnfo,- cxxSourceFiles = cxxSources bnfo,- inputSourceFiles = [main],- inputSourceModules = exeModules exe- }- else let (csf, cxxsf)- | isCxx main = ( cSources bnfo, main : cxxSources bnfo)- -- if main is not a Haskell source- -- and main is not a C++ source- -- then we assume that it is a C source- | otherwise = (main : cSources bnfo, cxxSources bnfo)-- in return BuildSources {- cSourcesFiles = csf,- cxxSourceFiles = cxxsf,- inputSourceFiles = [],- inputSourceModules = exeModules exe- }-- flibSources :: ForeignLib -> BuildSources- flibSources flib@ForeignLib{foreignLibBuildInfo = bnfo} =- BuildSources {- cSourcesFiles = cSources bnfo,- cxxSourceFiles = cxxSources bnfo,- inputSourceFiles = [],- inputSourceModules = foreignLibModules flib- }-- isHaskell :: FilePath -> Bool- isHaskell fp = elem (takeExtension fp) [".hs", ".lhs"]-- isCxx :: FilePath -> Bool- isCxx fp = elem (takeExtension fp) [".cpp", ".cxx", ".c++"]---- | Generic build function. See comment for 'GBuildMode'.-gbuild :: Verbosity -> Cabal.Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> GBuildMode -> ComponentLocalBuildInfo -> IO ()-gbuild verbosity numJobs pkg_descr lbi bm clbi = do- (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)- let replFlags = case bm of- GReplExe flags _ -> flags- GReplFLib flags _ -> flags- GBuildExe{} -> mempty- GBuildFLib{} -> mempty- comp = compiler lbi- platform = hostPlatform lbi- implInfo = getImplInfo comp- runGhcProg = runGHC verbosity ghcProg comp platform-- let (bnfo, threaded) = case bm of- GBuildFLib _ -> popThreadedFlag (gbuildInfo bm)- _ -> (gbuildInfo bm, False)-- -- the name that GHC really uses (e.g., with .exe on Windows for executables)- let targetName = gbuildTargetName lbi bm- let targetDir = buildDir lbi </> (gbuildName bm)- let tmpDir = targetDir </> (gbuildName bm ++ "-tmp")- createDirectoryIfMissingVerbose verbosity True targetDir- createDirectoryIfMissingVerbose verbosity True tmpDir-- -- TODO: do we need to put hs-boot files into place for mutually recursive- -- modules? FIX: what about exeName.hi-boot?-- -- Determine if program coverage should be enabled and if so, what- -- '-hpcdir' should be.- let isCoverageEnabled = exeCoverage lbi- distPref = fromFlag $ configDistPref $ configFlags lbi- hpcdir way- | gbuildIsRepl bm = mempty -- HPC is not supported in ghci- | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way (gbuildName bm)- | otherwise = mempty-- rpaths <- getRPaths lbi clbi- buildSources <- gbuildSources verbosity (specVersion pkg_descr) tmpDir bm-- let cSrcs = cSourcesFiles buildSources- cxxSrcs = cxxSourceFiles buildSources- inputFiles = inputSourceFiles buildSources- inputModules = inputSourceModules buildSources- isGhcDynamic = isDynamic comp- dynamicTooSupported = supportsDynamicToo comp- cObjs = map (`replaceExtension` objExtension) cSrcs- cxxObjs = map (`replaceExtension` objExtension) cxxSrcs- needDynamic = gbuildNeedDynamic lbi bm- needProfiling = withProfExe lbi-- -- build executables- baseOpts = (componentGhcOptions verbosity lbi bnfo clbi tmpDir)- `mappend` mempty {- ghcOptMode = toFlag GhcModeMake,- ghcOptInputFiles = toNubListR inputFiles,- ghcOptInputModules = toNubListR inputModules- }- staticOpts = baseOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcStaticOnly,- ghcOptHPCDir = hpcdir Hpc.Vanilla- }- profOpts = baseOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptProfilingAuto = Internal.profDetailLevelFlag False- (withProfExeDetail lbi),- ghcOptHiSuffix = toFlag "p_hi",- ghcOptObjSuffix = toFlag "p_o",- ghcOptExtra = hcProfOptions GHC bnfo,- ghcOptHPCDir = hpcdir Hpc.Prof- }- dynOpts = baseOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- -- TODO: Does it hurt to set -fPIC for executables?- ghcOptFPic = toFlag True,- ghcOptHiSuffix = toFlag "dyn_hi",- ghcOptObjSuffix = toFlag "dyn_o",- ghcOptExtra = hcSharedOptions GHC bnfo,- ghcOptHPCDir = hpcdir Hpc.Dyn- }- dynTooOpts = staticOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,- ghcOptDynHiSuffix = toFlag "dyn_hi",- ghcOptDynObjSuffix = toFlag "dyn_o",- ghcOptHPCDir = hpcdir Hpc.Dyn- }- linkerOpts = mempty {- ghcOptLinkOptions = PD.ldOptions bnfo- ++ [ "-static"- | withFullyStaticExe lbi ]- -- Pass extra `ld-options` given- -- through to GHC's linker.- ++ maybe [] programOverrideArgs- (lookupProgram ldProgram (withPrograms lbi)),- ghcOptLinkLibs = extraLibs bnfo,- ghcOptLinkLibPath = toNubListR $ extraLibDirs bnfo,- ghcOptLinkFrameworks = toNubListR $- PD.frameworks bnfo,- ghcOptLinkFrameworkDirs = toNubListR $- PD.extraFrameworkDirs bnfo,- ghcOptInputFiles = toNubListR- [tmpDir </> x | x <- cObjs ++ cxxObjs]- }- dynLinkerOpts = mempty {- ghcOptRPaths = rpaths- }- replOpts = baseOpts {- ghcOptExtra = Internal.filterGhciFlags- (ghcOptExtra baseOpts)- <> replFlags- }- -- For a normal compile we do separate invocations of ghc for- -- compiling as for linking. But for repl we have to do just- -- the one invocation, so that one has to include all the- -- linker stuff too, like -l flags and any .o files from C- -- files etc.- `mappend` linkerOpts- `mappend` mempty {- ghcOptMode = toFlag GhcModeInteractive,- ghcOptOptimisation = toFlag GhcNoOptimisation- }- commonOpts | needProfiling = profOpts- | needDynamic = dynOpts- | otherwise = staticOpts- compileOpts | useDynToo = dynTooOpts- | otherwise = commonOpts- withStaticExe = not needProfiling && not needDynamic-- -- For building exe's that use TH with -prof or -dynamic we actually have- -- to build twice, once without -prof/-dynamic and then again with- -- -prof/-dynamic. This is because the code that TH needs to run at- -- compile time needs to be the vanilla ABI so it can be loaded up and run- -- by the compiler.- -- With dynamic-by-default GHC the TH object files loaded at compile-time- -- need to be .dyn_o instead of .o.- doingTH = usesTemplateHaskellOrQQ bnfo- -- Should we use -dynamic-too instead of compiling twice?- useDynToo = dynamicTooSupported && isGhcDynamic- && doingTH && withStaticExe- && null (hcSharedOptions GHC bnfo)- compileTHOpts | isGhcDynamic = dynOpts- | otherwise = staticOpts- compileForTH- | gbuildIsRepl bm = False- | useDynToo = False- | isGhcDynamic = doingTH && (needProfiling || withStaticExe)- | otherwise = doingTH && (needProfiling || needDynamic)-- -- Build static/dynamic object files for TH, if needed.- when compileForTH $- runGhcProg compileTHOpts { ghcOptNoLink = toFlag True- , ghcOptNumJobs = numJobs }-- -- Do not try to build anything if there are no input files.- -- This can happen if the cabal file ends up with only cSrcs- -- but no Haskell modules.- unless ((null inputFiles && null inputModules)- || gbuildIsRepl bm) $- runGhcProg compileOpts { ghcOptNoLink = toFlag True- , ghcOptNumJobs = numJobs }-- -- build any C++ sources- unless (null cxxSrcs) $ do- info verbosity "Building C++ Sources..."- sequence_- [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo- lbi bnfo clbi tmpDir filename- vanillaCxxOpts = if isGhcDynamic- -- Dynamic GHC requires C++ sources to be built- -- with -fPIC for REPL to work. See #2207.- then baseCxxOpts { ghcOptFPic = toFlag True }- else baseCxxOpts- profCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True- }- sharedCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly- }- opts | needProfiling = profCxxOpts- | needDynamic = sharedCxxOpts- | otherwise = vanillaCxxOpts- -- TODO: Placing all Haskell, C, & C++ objects in a single directory- -- Has the potential for file collisions. In general we would- -- consider this a user error. However, we should strive to- -- add a warning if this occurs.- odir = fromFlag (ghcOptObjDir opts)- createDirectoryIfMissingVerbose verbosity True odir- needsRecomp <- checkNeedsRecompilation filename opts- when needsRecomp $- runGhcProg opts- | filename <- cxxSrcs ]-- -- build any C sources- unless (null cSrcs) $ do- info verbosity "Building C Sources..."- sequence_- [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo- lbi bnfo clbi tmpDir filename- vanillaCcOpts = if isGhcDynamic- -- Dynamic GHC requires C sources to be built- -- with -fPIC for REPL to work. See #2207.- then baseCcOpts { ghcOptFPic = toFlag True }- else baseCcOpts- profCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True- }- sharedCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly- }- opts | needProfiling = profCcOpts- | needDynamic = sharedCcOpts- | otherwise = vanillaCcOpts- odir = fromFlag (ghcOptObjDir opts)- createDirectoryIfMissingVerbose verbosity True odir- needsRecomp <- checkNeedsRecompilation filename opts- when needsRecomp $- runGhcProg opts- | filename <- cSrcs ]-- -- TODO: problem here is we need the .c files built first, so we can load them- -- with ghci, but .c files can depend on .h files generated by ghc by ffi- -- exports.- case bm of- GReplExe _ _ -> runGhcProg replOpts- GReplFLib _ _ -> runGhcProg replOpts- GBuildExe _ -> do- let linkOpts = commonOpts- `mappend` linkerOpts- `mappend` mempty {- ghcOptLinkNoHsMain = toFlag (null inputFiles)- }- `mappend` (if withDynExe lbi then dynLinkerOpts else mempty)-- info verbosity "Linking..."- -- Work around old GHCs not relinking in this- -- situation, see #3294- let target = targetDir </> targetName- when (compilerVersion comp < mkVersion [7,7]) $ do- e <- doesFileExist target- when e (removeFile target)- runGhcProg linkOpts { ghcOptOutputFile = toFlag target }- GBuildFLib flib -> do- let rtsInfo = extractRtsInfo lbi- rtsOptLinkLibs = [- if needDynamic- then if threaded- then dynRtsThreadedLib (rtsDynamicInfo rtsInfo)- else dynRtsVanillaLib (rtsDynamicInfo rtsInfo)- else if threaded- then statRtsThreadedLib (rtsStaticInfo rtsInfo)- else statRtsVanillaLib (rtsStaticInfo rtsInfo)- ]- linkOpts = case foreignLibType flib of- ForeignLibNativeShared ->- commonOpts- `mappend` linkerOpts- `mappend` dynLinkerOpts- `mappend` mempty {- ghcOptLinkNoHsMain = toFlag True,- ghcOptShared = toFlag True,- ghcOptLinkLibs = rtsOptLinkLibs,- ghcOptLinkLibPath = toNubListR $ rtsLibPaths rtsInfo,- ghcOptFPic = toFlag True,- ghcOptLinkModDefFiles = toNubListR $ gbuildModDefFiles bm- }- -- See Note [RPATH]- `mappend` ifNeedsRPathWorkaround lbi mempty {- ghcOptLinkOptions = ["-Wl,--no-as-needed"]- , ghcOptLinkLibs = ["ffi"]- }- ForeignLibNativeStatic ->- -- this should be caught by buildFLib- -- (and if we do implement this, we probably don't even want to call- -- ghc here, but rather Ar.createArLibArchive or something)- cabalBug "static libraries not yet implemented"- ForeignLibTypeUnknown ->- cabalBug "unknown foreign lib type"- -- We build under a (potentially) different filename to set a- -- soname on supported platforms. See also the note for- -- @flibBuildName@.- info verbosity "Linking..."- let buildName = flibBuildName lbi flib- runGhcProg linkOpts { ghcOptOutputFile = toFlag (targetDir </> buildName) }- renameFile (targetDir </> buildName) (targetDir </> targetName)--{--Note [RPATH]-~~~~~~~~~~~~--Suppose that the dynamic library depends on `base`, but not (directly) on-`integer-gmp` (which, however, is a dependency of `base`). We will link the-library as-- gcc ... -lHSbase-4.7.0.2-ghc7.8.4 -lHSinteger-gmp-0.5.1.0-ghc7.8.4 ...--However, on systems (like Ubuntu) where the linker gets called with `-as-needed`-by default, the linker will notice that `integer-gmp` isn't actually a direct-dependency and hence omit the link.--Then when we attempt to link a C program against this dynamic library, the-_static_ linker will attempt to verify that all symbols can be resolved. The-dynamic library itself does not require any symbols from `integer-gmp`, but-`base` does. In order to verify that the symbols used by `base` can be-resolved, the static linker needs to be able to _find_ integer-gmp.--Finding the `base` dependency is simple, because the dynamic elf header-(`readelf -d`) for the library that we have created looks something like-- (NEEDED) Shared library: [libHSbase-4.7.0.2-ghc7.8.4.so]- (RPATH) Library rpath: [/path/to/base-4.7.0.2:...]--However, when it comes to resolving the dependency on `integer-gmp`, it needs-to look at the dynamic header for `base`. On modern ghc (7.8 and higher) this-looks something like-- (NEEDED) Shared library: [libHSinteger-gmp-0.5.1.0-ghc7.8.4.so]- (RPATH) Library rpath: [$ORIGIN/../integer-gmp-0.5.1.0:...]--This specifies the location of `integer-gmp` _in terms of_ the location of base-(using the `$ORIGIN`) variable. But here's the crux: when the static linker-attempts to verify that all symbols can be resolved, [**IT DOES NOT RESOLVE-`$ORIGIN`**](http://stackoverflow.com/questions/6323603/ld-using-rpath-origin-inside-a-shared-library-recursive).-As a consequence, it will not be able to resolve the symbols and report the-missing symbols as errors, _even though the dynamic linker **would** be able to-resolve these symbols_. We can tell the static linker not to report these-errors by using `--unresolved-symbols=ignore-all` and all will be fine when we-run the program ([(indeed, this is what the gold linker-does)](https://sourceware.org/ml/binutils/2013-05/msg00038.html), but it makes-the resulting library more difficult to use.--Instead what we can do is make sure that the generated dynamic library has-explicit top-level dependencies on these libraries. This means that the static-linker knows where to find them, and when we have transitive dependencies on-the same libraries the linker will only load them once, so we avoid needing to-look at the `RPATH` of our dependencies. We can do this by passing-`--no-as-needed` to the linker, so that it doesn't omit any libraries.--Note that on older ghc (7.6 and before) the Haskell libraries don't have an-RPATH set at all, which makes it even more important that we make these-top-level dependencies.--Finally, we have to explicitly link against `libffi` for the same reason. For-newer ghc this _happens_ to be unnecessary on many systems because `libffi` is-a library which is not specific to GHC, and when the static linker verifies-that all symbols can be resolved it will find the `libffi` that is globally-installed (completely independent from ghc). Of course, this may well be the-_wrong_ version of `libffi`, but it's quite possible that symbol resolution-happens to work. This is of course the wrong approach, which is why we link-explicitly against `libffi` so that we will find the _right_ version of-`libffi`.--}---- | Do we need the RPATH workaround?------ See Note [RPATH].-ifNeedsRPathWorkaround :: Monoid a => LocalBuildInfo -> a -> a-ifNeedsRPathWorkaround lbi a =- case hostPlatform lbi of- Platform _ Linux -> a- _otherwise -> mempty--data DynamicRtsInfo = DynamicRtsInfo {- dynRtsVanillaLib :: FilePath- , dynRtsThreadedLib :: FilePath- , dynRtsDebugLib :: FilePath- , dynRtsEventlogLib :: FilePath- , dynRtsThreadedDebugLib :: FilePath- , dynRtsThreadedEventlogLib :: FilePath- }--data StaticRtsInfo = StaticRtsInfo {- statRtsVanillaLib :: FilePath- , statRtsThreadedLib :: FilePath- , statRtsDebugLib :: FilePath- , statRtsEventlogLib :: FilePath- , statRtsThreadedDebugLib :: FilePath- , statRtsThreadedEventlogLib :: FilePath- , statRtsProfilingLib :: FilePath- , statRtsThreadedProfilingLib :: FilePath- }--data RtsInfo = RtsInfo {- rtsDynamicInfo :: DynamicRtsInfo- , rtsStaticInfo :: StaticRtsInfo- , rtsLibPaths :: [FilePath]- }---- | Extract (and compute) information about the RTS library------ TODO: This hardcodes the name as @HSrts-ghc<version>@. I don't know if we can--- find this information somewhere. We can lookup the 'hsLibraries' field of--- 'InstalledPackageInfo' but it will tell us @["HSrts", "Cffi"]@, which--- doesn't really help.-extractRtsInfo :: LocalBuildInfo -> RtsInfo-extractRtsInfo lbi =- case PackageIndex.lookupPackageName- (installedPkgs lbi) (mkPackageName "rts") of- [(_, [rts])] -> aux rts- _otherwise -> error "No (or multiple) ghc rts package is registered"- where- aux :: InstalledPackageInfo -> RtsInfo- aux rts = RtsInfo {- rtsDynamicInfo = DynamicRtsInfo {- dynRtsVanillaLib = withGhcVersion "HSrts"- , dynRtsThreadedLib = withGhcVersion "HSrts_thr"- , dynRtsDebugLib = withGhcVersion "HSrts_debug"- , dynRtsEventlogLib = withGhcVersion "HSrts_l"- , dynRtsThreadedDebugLib = withGhcVersion "HSrts_thr_debug"- , dynRtsThreadedEventlogLib = withGhcVersion "HSrts_thr_l"- }- , rtsStaticInfo = StaticRtsInfo {- statRtsVanillaLib = "HSrts"- , statRtsThreadedLib = "HSrts_thr"- , statRtsDebugLib = "HSrts_debug"- , statRtsEventlogLib = "HSrts_l"- , statRtsThreadedDebugLib = "HSrts_thr_debug"- , statRtsThreadedEventlogLib = "HSrts_thr_l"- , statRtsProfilingLib = "HSrts_p"- , statRtsThreadedProfilingLib = "HSrts_thr_p"- }- , rtsLibPaths = InstalledPackageInfo.libraryDirs rts- }- withGhcVersion = (++ ("-ghc" ++ prettyShow (compilerVersion (compiler lbi))))---- | Returns True if the modification date of the given source file is newer than--- the object file we last compiled for it, or if no object file exists yet.-checkNeedsRecompilation :: FilePath -> GhcOptions -> IO Bool-checkNeedsRecompilation filename opts = filename `moreRecentFile` oname- where oname = getObjectFileName filename opts---- | Finds the object file name of the given source file-getObjectFileName :: FilePath -> GhcOptions -> FilePath-getObjectFileName filename opts = oname- where odir = fromFlag (ghcOptObjDir opts)- oext = fromFlagOrDefault "o" (ghcOptObjSuffix opts)- oname = odir </> replaceExtension filename oext---- | Calculate the RPATHs for the component we are building.------ Calculates relative RPATHs when 'relocatable' is set.-getRPaths :: LocalBuildInfo- -> ComponentLocalBuildInfo -- ^ Component we are building- -> IO (NubListR FilePath)-getRPaths lbi clbi | supportRPaths hostOS = do- libraryPaths <- depLibraryPaths False (relocatable lbi) lbi clbi- let hostPref = case hostOS of- OSX -> "@loader_path"- _ -> "$ORIGIN"- relPath p = if isRelative p then hostPref </> p else p- rpaths = toNubListR (map relPath libraryPaths)- return rpaths- where- (Platform _ hostOS) = hostPlatform lbi- compid = compilerId . compiler $ lbi-- -- The list of RPath-supported operating systems below reflects the- -- platforms on which Cabal's RPATH handling is tested. It does _NOT_- -- reflect whether the OS supports RPATH.-- -- E.g. when this comment was written, the *BSD operating systems were- -- untested with regards to Cabal RPATH handling, and were hence set to- -- 'False', while those operating systems themselves do support RPATH.- supportRPaths Linux = True- supportRPaths Windows = False- supportRPaths OSX = True- supportRPaths FreeBSD =- case compid of- CompilerId GHC ver | ver >= mkVersion [7,10,2] -> True- _ -> False- supportRPaths OpenBSD = False- supportRPaths NetBSD = False- supportRPaths DragonFly = False- supportRPaths Solaris = False- supportRPaths AIX = False- supportRPaths HPUX = False- 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.--getRPaths _ _ = return mempty---- | Remove the "-threaded" flag when building a foreign library, as it has no--- effect when used with "-shared". Returns the updated 'BuildInfo', along--- with whether or not the flag was present, so we can use it to link against--- the appropriate RTS on our own.-popThreadedFlag :: BuildInfo -> (BuildInfo, Bool)-popThreadedFlag bi =- ( bi { options = filterHcOptions (/= "-threaded") (options bi) }- , hasThreaded (options bi))-- where- filterHcOptions :: (String -> Bool)- -> PerCompilerFlavor [String]- -> PerCompilerFlavor [String]- filterHcOptions p (PerCompilerFlavor ghc ghcjs) =- PerCompilerFlavor (filter p ghc) ghcjs-- hasThreaded :: PerCompilerFlavor [String] -> Bool- hasThreaded (PerCompilerFlavor ghc _) = elem "-threaded" ghc---- | Extracts a String representing a hash of the ABI of a built--- library. It can fail if the library has not yet been built.----libAbiHash :: Verbosity -> PackageDescription -> LocalBuildInfo- -> Library -> ComponentLocalBuildInfo -> IO String-libAbiHash verbosity _pkg_descr lbi lib clbi = do- let- libBi = libBuildInfo lib- comp = compiler lbi- platform = hostPlatform lbi- vanillaArgs0 =- (componentGhcOptions verbosity lbi libBi clbi (componentBuildDir lbi clbi))- `mappend` mempty {- ghcOptMode = toFlag GhcModeAbiHash,- ghcOptInputModules = toNubListR $ exposedModules lib- }- vanillaArgs =- -- Package DBs unnecessary, and break ghc-cabal. See #3633- -- BUT, put at least the global database so that 7.4 doesn't- -- break.- vanillaArgs0 { ghcOptPackageDBs = [GlobalPackageDB]- , ghcOptPackages = mempty }- sharedArgs = vanillaArgs `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptFPic = toFlag True,- ghcOptHiSuffix = toFlag "dyn_hi",- ghcOptObjSuffix = toFlag "dyn_o",- ghcOptExtra = hcSharedOptions GHC libBi- }- profArgs = vanillaArgs `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptProfilingAuto = Internal.profDetailLevelFlag True- (withProfLibDetail lbi),- ghcOptHiSuffix = toFlag "p_hi",- ghcOptObjSuffix = toFlag "p_o",- ghcOptExtra = hcProfOptions GHC libBi- }- 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 platform ghcArgs)- return (takeWhile (not . isSpace) hash)--componentGhcOptions :: Verbosity -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo -> FilePath- -> GhcOptions-componentGhcOptions verbosity lbi =- Internal.componentGhcOptions verbosity implInfo lbi- where- comp = compiler lbi- implInfo = getImplInfo comp--componentCcGhcOptions :: Verbosity -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo- -> FilePath -> FilePath- -> GhcOptions-componentCcGhcOptions verbosity lbi =- Internal.componentCcGhcOptions verbosity implInfo lbi- where- comp = compiler lbi- implInfo = getImplInfo comp---- -------------------------------------------------------------------------------- Installing---- |Install executables for GHC.-installExe :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^Where to copy the files to- -> FilePath -- ^Build location- -> (FilePath, FilePath) -- ^Executable (prefix,suffix)- -> PackageDescription- -> Executable- -> IO ()-installExe verbosity lbi binDir buildPref- (progprefix, progsuffix) _pkg exe = do- createDirectoryIfMissingVerbose verbosity True binDir- let exeName' = unUnqualComponentName $ exeName exe- exeFileName = exeTargetName (hostPlatform lbi) exe- fixedExeBaseName = progprefix ++ exeName' ++ progsuffix- installBinary dest = do- installExecutableFile verbosity- (buildPref </> exeName' </> exeFileName)- (dest <.> exeExtension (hostPlatform lbi))- when (stripExes lbi) $- Strip.stripExe verbosity (hostPlatform lbi) (withPrograms lbi)- (dest <.> exeExtension (hostPlatform lbi))- installBinary (binDir </> fixedExeBaseName)---- |Install foreign library for GHC.-installFLib :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^install location- -> FilePath -- ^Build location- -> PackageDescription- -> ForeignLib- -> IO ()-installFLib verbosity lbi targetDir builtDir _pkg flib =- install (foreignLibIsShared flib)- builtDir- targetDir- (flibTargetName lbi flib)- where- install isShared srcDir dstDir name = do- let src = srcDir </> name- dst = dstDir </> name- createDirectoryIfMissingVerbose verbosity True targetDir- -- TODO: Should we strip? (stripLibs lbi)- if isShared- then installExecutableFile verbosity src dst- else installOrdinaryFile verbosity src dst- -- Now install appropriate symlinks if library is versioned- let (Platform _ os) = hostPlatform lbi- when (not (null (foreignLibVersion flib os))) $ do- when (os /= Linux) $ die' verbosity- -- It should be impossible to get here.- "Can't install foreign-library symlink on non-Linux OS"-#ifndef mingw32_HOST_OS- -- 'createSymbolicLink file1 file2' creates a symbolic link- -- named 'file2' which points to the file 'file1'.- -- Note that we do want a symlink to 'name' rather than- -- 'dst', because the symlink will be relative to the- -- directory it's created in.- -- Finally, we first create the symlinks in a temporary- -- directory and then rename to simulate 'ln --force'.- withTempDirectory verbosity dstDir nm $ \tmpDir -> do- let link1 = flibBuildName lbi flib- link2 = "lib" ++ nm <.> "so"- createSymbolicLink name (tmpDir </> link1)- renameFile (tmpDir </> link1) (dstDir </> link1)- createSymbolicLink name (tmpDir </> link2)- renameFile (tmpDir </> link2) (dstDir </> link2)- where- nm :: String- nm = unUnqualComponentName $ foreignLibName flib-#endif /* mingw32_HOST_OS */----- |Install for ghc, .hi, .a and, if --with-ghci given, .o-installLib :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^install location- -> FilePath -- ^install location for dynamic libraries- -> FilePath -- ^Build location- -> PackageDescription- -> Library- -> ComponentLocalBuildInfo- -> IO ()-installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do- -- copy .hi files over:- whenVanilla $ copyModuleFiles "hi"- whenProf $ copyModuleFiles "p_hi"- whenShared $ copyModuleFiles "dyn_hi"-- -- copy the built library files over:- whenHasCode $ do- whenVanilla $ do- sequence_ [ installOrdinary- builtDir- targetDir- (mkGenericStaticLibName (l ++ f))- | l <- getHSLibraryName- (componentUnitId clbi):(extraBundledLibs (libBuildInfo lib))- , f <- "":extraLibFlavours (libBuildInfo lib)- ]- whenGHCi $ installOrdinary builtDir targetDir ghciLibName- whenProf $ do- installOrdinary builtDir targetDir profileLibName- whenGHCi $ installOrdinary builtDir targetDir ghciProfLibName- whenShared $ if- -- The behavior for "extra-bundled-libraries" changed in version 2.5.0.- -- See ghc issue #15837 and Cabal PR #5855.- | specVersion pkg < CabalSpecV3_0 -> do- sequence_ [ installShared builtDir dynlibTargetDir- (mkGenericSharedLibName platform compiler_id (l ++ f))- | l <- getHSLibraryName uid : extraBundledLibs (libBuildInfo lib)- , f <- "":extraDynLibFlavours (libBuildInfo lib)- ]- | otherwise -> do- sequence_ [ installShared- builtDir- dynlibTargetDir- (mkGenericSharedLibName- platform- compiler_id- (getHSLibraryName uid ++ f))- | f <- "":extraDynLibFlavours (libBuildInfo lib)- ]- sequence_ [ do- files <- getDirectoryContents builtDir- let l' = mkGenericSharedBundledLibName- platform- compiler_id- l- forM_ files $ \ file ->- when (l' `isPrefixOf` file) $ do- isFile <- doesFileExist (builtDir </> file)- when isFile $ do- installShared- builtDir- dynlibTargetDir- file- | l <- extraBundledLibs (libBuildInfo lib)- ]-- where- builtDir = componentBuildDir lbi clbi-- install isShared srcDir dstDir name = do- let src = srcDir </> name- dst = dstDir </> name-- createDirectoryIfMissingVerbose verbosity True dstDir-- if isShared- then installExecutableFile verbosity src dst- else installOrdinaryFile verbosity src dst-- when (stripLibs lbi) $ Strip.stripLib verbosity- platform (withPrograms lbi) dst-- installOrdinary = install False- installShared = install True-- copyModuleFiles ext =- findModuleFilesEx verbosity [builtDir] [ext] (allLibModules lib clbi)- >>= installOrdinaryFiles verbosity targetDir-- compiler_id = compilerId (compiler lbi)- platform = hostPlatform lbi- uid = componentUnitId clbi- profileLibName = mkProfLibName uid- ghciLibName = Internal.mkGHCiLibName uid- ghciProfLibName = Internal.mkGHCiProfLibName uid-- hasLib = not $ null (allLibModules lib clbi)- && null (cSources (libBuildInfo lib))- && null (cxxSources (libBuildInfo lib))- && null (cmmSources (libBuildInfo lib))- && null (asmSources (libBuildInfo lib))- has_code = not (componentIsIndefinite clbi)- whenHasCode = when has_code- whenVanilla = when (hasLib && withVanillaLib lbi)- whenProf = when (hasLib && withProfLib lbi && has_code)- whenGHCi = when (hasLib && withGHCiLib lbi && has_code)- whenShared = when (hasLib && withSharedLib lbi && has_code)---- -------------------------------------------------------------------------------- Registering--hcPkgInfo :: ProgramDb -> HcPkg.HcPkgInfo-hcPkgInfo progdb = HcPkg.HcPkgInfo- { HcPkg.hcPkgProgram = ghcPkgProg- , HcPkg.noPkgDbStack = v < [6,9]- , HcPkg.noVerboseFlag = v < [6,11]- , HcPkg.flagPackageConf = v < [7,5]- , HcPkg.supportsDirDbs = v >= [6,8]- , HcPkg.requiresDirDbs = v >= [7,10]- , HcPkg.nativeMultiInstance = v >= [7,10]- , HcPkg.recacheMultiInstance = v >= [6,12]- , HcPkg.suppressFilesCheck = v >= [6,6]- }- where- v = versionNumbers ver- ghcPkgProg = fromMaybe (error "GHC.hcPkgInfo: no ghc program") $ lookupProgram ghcPkgProgram progdb- ver = fromMaybe (error "GHC.hcPkgInfo: no ghc version") $ programVersion ghcPkgProg--registerPackage- :: Verbosity- -> ProgramDb- -> PackageDBStack- -> InstalledPackageInfo- -> HcPkg.RegisterOptions- -> IO ()-registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions =- HcPkg.register (hcPkgInfo progdb) verbosity packageDbs- installedPkgInfo registerOptions--pkgRoot :: Verbosity -> LocalBuildInfo -> PackageDB -> IO FilePath-pkgRoot verbosity lbi = pkgRoot'- where- pkgRoot' GlobalPackageDB =- let ghcProg = fromMaybe (error "GHC.pkgRoot: no ghc program") $ lookupProgram ghcProgram (withPrograms lbi)- in fmap takeDirectory (getGlobalPackageDB verbosity ghcProg)- pkgRoot' UserPackageDB = do- appDir <- getGhcAppDir- let ver = compilerVersion (compiler lbi)- subdir = System.Info.arch ++ '-':System.Info.os- ++ '-':prettyShow 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- -- directory at the time of 'ghc-pkg register', and registration will- -- fail.- createDirectoryIfMissing True rootDir- return rootDir- pkgRoot' (SpecificPackageDB fp) = return (takeDirectory fp)---- -------------------------------------------------------------------------------- Utils--isDynamic :: Compiler -> Bool-isDynamic = Internal.ghcLookupProperty "GHC Dynamic"--supportsDynamicToo :: Compiler -> Bool-supportsDynamicToo = Internal.ghcLookupProperty "Support dynamic-too"--withExt :: FilePath -> String -> FilePath-withExt fp ext = fp <.> if takeExtension fp /= ('.':ext) then ext else ""
− Distribution/Simple/GHC/EnvironmentParser.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RecordWildCards #-}-module Distribution.Simple.GHC.EnvironmentParser- ( parseGhcEnvironmentFile, readGhcEnvironmentFile, ParseErrorExc(..) ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.Compiler- ( PackageDB(..) )-import Distribution.Simple.GHC.Internal- ( GhcEnvironmentFileEntry(..) )-import Distribution.Types.UnitId- ( mkUnitId )--import qualified Text.Parsec as P-import Text.Parsec.String- ( Parser, parseFromFile )--parseEnvironmentFileLine :: Parser GhcEnvironmentFileEntry-parseEnvironmentFileLine = GhcEnvFileComment <$> comment- <|> GhcEnvFilePackageId <$> unitId- <|> GhcEnvFilePackageDb <$> packageDb- <|> pure GhcEnvFileClearPackageDbStack <* clearDb- where- comment = P.string "--" *> P.many (P.noneOf "\r\n")- unitId = P.try $ P.string "package-id" *> P.spaces *>- (mkUnitId <$> P.many1 (P.satisfy $ \c -> isAlphaNum c || c `elem` "-_.+"))- packageDb = (P.string "global-package-db" *> pure GlobalPackageDB)- <|> (P.string "user-package-db" *> pure UserPackageDB)- <|> (P.string "package-db" *> P.spaces *> (SpecificPackageDB <$> P.many1 (P.noneOf "\r\n") <* P.lookAhead P.endOfLine))- clearDb = P.string "clear-package-db"--newtype ParseErrorExc = ParseErrorExc P.ParseError- deriving (Show, Typeable)--instance Exception ParseErrorExc--parseGhcEnvironmentFile :: Parser [GhcEnvironmentFileEntry]-parseGhcEnvironmentFile = parseEnvironmentFileLine `P.sepEndBy` P.endOfLine <* P.eof--readGhcEnvironmentFile :: FilePath -> IO [GhcEnvironmentFileEntry]-readGhcEnvironmentFile path =- either (throwIO . ParseErrorExc) return =<<- parseFromFile parseGhcEnvironmentFile path
− Distribution/Simple/GHC/ImplInfo.hs
@@ -1,93 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.GHC.ImplInfo------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module contains the data structure describing invocation--- details for a GHC or GHC-derived compiler, such as supported flags--- and workarounds for bugs.--module Distribution.Simple.GHC.ImplInfo (- GhcImplInfo(..), getImplInfo,- ghcVersionImplInfo, ghcjsVersionImplInfo- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.Compiler-import Distribution.Version--{- |- Information about features and quirks of a GHC-based implementation.-- Compiler flavors based on GHC behave similarly enough that some of- the support code for them is shared. Every implementation has its- own peculiarities, that may or may not be a direct result of the- underlying GHC version. This record keeps track of these differences.-- All shared code (i.e. everything not in the Distribution.Simple.FLAVOR- module) should use implementation info rather than version numbers- to test for supported features.--}--data GhcImplInfo = GhcImplInfo- { supportsHaskell2010 :: Bool -- ^ -XHaskell2010 and -XHaskell98 flags- , 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- , supportsDebugLevels :: Bool -- ^ supports numeric @-g@ levels- , supportsPkgEnvFiles :: Bool -- ^ picks up @.ghc.environment@ files- , flagWarnMissingHomeModules :: Bool -- ^ -Wmissing-home-modules is supported- }--getImplInfo :: Compiler -> GhcImplInfo-getImplInfo comp =- case compilerFlavor comp of- GHC -> ghcVersionImplInfo (compilerVersion comp)- GHCJS -> case compilerCompatVersion GHC comp of- Just ghcVer -> ghcjsVersionImplInfo (compilerVersion comp) ghcVer- _ -> error ("Distribution.Simple.GHC.Props.getImplProps: " ++- "could not find GHC version for GHCJS compiler")- x -> error ("Distribution.Simple.GHC.Props.getImplProps only works" ++- "for GHC-like compilers (GHC, GHCJS)" ++- ", but found " ++ show x)--ghcVersionImplInfo :: Version -> GhcImplInfo-ghcVersionImplInfo ver = GhcImplInfo- { supportsHaskell2010 = v >= [7]- , reportsNoExt = v >= [7]- , alwaysNondecIndent = v < [7,1]- , flagGhciScript = v >= [7,2]- , flagProfAuto = v >= [7,4]- , flagPackageConf = v < [7,5]- , flagDebugInfo = v >= [7,10]- , supportsDebugLevels = v >= [8,0]- , supportsPkgEnvFiles = v >= [8,0,1,20160901] -- broken in 8.0.1, fixed in 8.0.2- , flagWarnMissingHomeModules = v >= [8,2]- }- where- v = versionNumbers ver--ghcjsVersionImplInfo :: Version -- ^ The GHCJS version- -> Version -- ^ The GHC version- -> GhcImplInfo-ghcjsVersionImplInfo _ghcjsver ghcver = GhcImplInfo- { supportsHaskell2010 = True- , reportsNoExt = True- , alwaysNondecIndent = False- , flagGhciScript = True- , flagProfAuto = True- , flagPackageConf = False- , flagDebugInfo = False- , supportsDebugLevels = ghcv >= [8,0]- , supportsPkgEnvFiles = ghcv >= [8,0,2] --TODO: check this works in ghcjs- , flagWarnMissingHomeModules = ghcv >= [8,2]- }- where- ghcv = versionNumbers ghcver
− Distribution/Simple/GHC/Internal.hs
@@ -1,681 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.GHC.Internal--- Copyright : Isaac Jones 2003-2007------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module contains functions shared by GHC (Distribution.Simple.GHC)--- and GHC-derived compilers.--module Distribution.Simple.GHC.Internal (- configureToolchain,- getLanguages,- getExtensions,- targetPlatform,- getGhcInfo,- componentCcGhcOptions,- componentCmmGhcOptions,- componentCxxGhcOptions,- componentAsmGhcOptions,- componentGhcOptions,- mkGHCiLibName,- mkGHCiProfLibName,- filterGhciFlags,- ghcLookupProperty,- getHaskellObjects,- mkGhcOptPackages,- substTopDir,- checkPackageDbEnvVar,- profDetailLevelFlag,- -- * GHC platform and version strings- ghcArchString,- ghcOsString,- ghcPlatformAndVersionString,- -- * Constructing GHC environment files- GhcEnvironmentFileEntry(..),- writeGhcEnvironmentFile,- simpleGhcEnvironmentFile,- ghcEnvironmentFileName,- renderGhcEnvironmentFile,- renderGhcEnvironmentFileEntry,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.GHC.ImplInfo-import Distribution.Types.ComponentLocalBuildInfo-import Distribution.Backpack-import qualified Distribution.InstalledPackageInfo as IPI-import Distribution.PackageDescription-import Distribution.Lex-import Distribution.Simple.Compiler-import Distribution.Simple.Program.GHC-import Distribution.Simple.Setup-import qualified Distribution.ModuleName as ModuleName-import Distribution.Simple.Program-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.UnitId-import Distribution.Types.LocalBuildInfo-import Distribution.Types.TargetInfo-import Distribution.Types.ModuleRenaming-import Distribution.Simple.Utils-import Distribution.Simple.BuildPaths-import Distribution.System-import Distribution.Pretty ( prettyShow )-import Distribution.Parsec ( simpleParsec )-import Distribution.Utils.NubList ( toNubListR )-import Distribution.Verbosity-import Distribution.Compat.Stack-import Distribution.Version (Version)-import Language.Haskell.Extension--import qualified Data.Map as Map-import qualified Data.ByteString.Lazy.Char8 as BS-import System.Directory ( getDirectoryContents, getTemporaryDirectory )-import System.Environment ( getEnv )-import System.FilePath ( (</>), (<.>), takeExtension- , takeDirectory, takeFileName)-import System.IO ( hClose, hPutStrLn )--targetPlatform :: [(String, String)] -> Maybe Platform-targetPlatform ghcInfo = platformFromTriple =<< lookup "Target platform" ghcInfo---- | Adjust the way we find and configure gcc and ld----configureToolchain :: GhcImplInfo- -> ConfiguredProgram- -> Map String String- -> ProgramDb- -> ProgramDb-configureToolchain _implInfo ghcProg ghcInfo =- addKnownProgram gccProgram {- programFindLocation = findProg gccProgramName extraGccPath,- programPostConf = configureGcc- }- . addKnownProgram ldProgram {- programFindLocation = findProg ldProgramName extraLdPath,- programPostConf = configureLd- }- . addKnownProgram arProgram {- programFindLocation = findProg arProgramName extraArPath- }- . addKnownProgram stripProgram {- programFindLocation = findProg stripProgramName extraStripPath- }- where- compilerDir = takeDirectory (programPath ghcProg)- base_dir = takeDirectory compilerDir- mingwBinDir = base_dir </> "mingw" </> "bin"- 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- where- mbDir = maybeToList . fmap takeDirectory $ mbPath-- extraGccPath = mkExtraPath mbGccLocation windowsExtraGccDir- extraLdPath = mkExtraPath mbLdLocation windowsExtraLdDir- extraArPath = mkExtraPath mbArLocation windowsExtraArDir- extraStripPath = mkExtraPath mbStripLocation windowsExtraStripDir-- -- on Windows finding and configuring ghc's gcc & binutils is a bit special- (windowsExtraGccDir, windowsExtraLdDir,- windowsExtraArDir, windowsExtraStripDir) =- let b = mingwBinDir </> binPrefix- in (b, b, b, b)-- findProg :: String -> [FilePath]- -> Verbosity -> ProgramSearchPath- -> IO (Maybe (FilePath, [FilePath]))- findProg progName extraPath v searchpath =- findProgramOnSearchPath v searchpath' progName- where- searchpath' = (map ProgramSearchPathDir extraPath) ++ searchpath-- -- Read tool locations from the 'ghc --info' output. Useful when- -- cross-compiling.- mbGccLocation = Map.lookup "C compiler command" ghcInfo- mbLdLocation = Map.lookup "ld command" ghcInfo- mbArLocation = Map.lookup "ar command" ghcInfo- mbStripLocation = Map.lookup "strip command" ghcInfo-- ccFlags = getFlags "C compiler flags"- -- GHC 7.8 renamed "Gcc Linker flags" to "C compiler link flags"- -- and "Ld Linker flags" to "ld flags" (GHC #4862).- gccLinkerFlags = getFlags "Gcc Linker flags" ++ getFlags "C compiler link flags"- ldLinkerFlags = getFlags "Ld Linker flags" ++ getFlags "ld flags"-- -- 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 Map.lookup key ghcInfo of- Nothing -> []- Just flags- | (flags', ""):_ <- reads flags -> flags'- | otherwise -> tokenizeQuotedWords flags-- configureGcc :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram- configureGcc _v gccProg = do- return gccProg {- programDefaultArgs = programDefaultArgs gccProg- ++ ccFlags ++ gccLinkerFlags- }-- configureLd :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram- configureLd v ldProg = do- ldProg' <- configureLd' v ldProg- return ldProg' {- programDefaultArgs = programDefaultArgs ldProg' ++ ldLinkerFlags- }-- -- we need to find out if ld supports the -x flag- configureLd' :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram- configureLd' verbosity ldProg = do- tempDir <- getTemporaryDirectory- ldx <- withTempFile tempDir ".c" $ \testcfile testchnd ->- withTempFile tempDir ".o" $ \testofile testohnd -> do- hPutStrLn testchnd "int foo() { return 0; }"- hClose testchnd; hClose testohnd- runProgram verbosity ghcProg- [ "-hide-all-packages"- , "-c", testcfile- , "-o", testofile- ]- withTempFile tempDir ".o" $ \testofile' testohnd' ->- do- hClose testohnd'- _ <- getProgramOutput verbosity ldProg- ["-x", "-r", testofile, "-o", testofile']- return True- `catchIO` (\_ -> return False)- `catchExit` (\_ -> return False)- if ldx- then return ldProg { programDefaultArgs = ["-x"] }- else return ldProg--getLanguages :: Verbosity -> GhcImplInfo -> ConfiguredProgram- -> IO [(Language, String)]-getLanguages _ implInfo _- -- TODO: should be using --supported-languages rather than hard coding- | supportsHaskell2010 implInfo = return [(Haskell98, "-XHaskell98")- ,(Haskell2010, "-XHaskell2010")]- | otherwise = return [(Haskell98, "")]--getGhcInfo :: Verbosity -> GhcImplInfo -> ConfiguredProgram- -> IO [(String, String)]-getGhcInfo verbosity _implInfo ghcProg = do- xs <- getProgramOutput verbosity (suppressOverrideArgs ghcProg)- ["--info"]- case reads xs of- [(i, ss)]- | all isSpace ss ->- return i- _ ->- die' verbosity "Can't parse --info output of GHC"--getExtensions :: Verbosity -> GhcImplInfo -> ConfiguredProgram- -> IO [(Extension, Maybe String)]-getExtensions verbosity implInfo ghcProg = do- str <- getProgramOutput verbosity (suppressOverrideArgs ghcProg)- ["--supported-languages"]- let extStrs = if reportsNoExt implInfo- then lines str- else -- Older GHCs only gave us either Foo or NoFoo,- -- so we have to work out the other one ourselves- [ extStr''- | extStr <- lines str- , let extStr' = case extStr of- 'N' : 'o' : xs -> xs- _ -> "No" ++ extStr- , extStr'' <- [extStr, extStr']- ]- let extensions0 = [ (ext, Just $ "-X" ++ prettyShow ext)- | Just ext <- map simpleParsec extStrs ]- extensions1 = if alwaysNondecIndent implInfo- then -- ghc-7.2 split NondecreasingIndentation off- -- into a proper extension. Before that it- -- was always on.- -- Since it was not a proper extension, it could- -- not be turned off, hence we omit a- -- DisableExtension entry here.- (EnableExtension NondecreasingIndentation, Nothing) :- extensions0- else extensions0- return extensions1--componentCcGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo- -> FilePath -> FilePath- -> GhcOptions-componentCcGhcOptions verbosity _implInfo lbi bi clbi odir filename =- mempty {- -- Respect -v0, but don't crank up verbosity on GHC if- -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!- ghcOptVerbosity = toFlag (min verbosity normal),- ghcOptMode = toFlag GhcModeCompile,- ghcOptInputFiles = toNubListR [filename],-- ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi- ,odir]- -- includes relative to the package- ++ includeDirs bi- -- potential includes generated by `configure'- -- in the build directory- ++ [buildDir lbi </> dir | dir <- includeDirs bi],- ghcOptHideAllPackages= toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,- ghcOptCcOptions = (case withOptimization lbi of- NoOptimisation -> []- _ -> ["-O2"]) ++- (case withDebugInfo lbi of- NoDebugInfo -> []- MinimalDebugInfo -> ["-g1"]- NormalDebugInfo -> ["-g"]- MaximalDebugInfo -> ["-g3"]) ++- ccOptions bi,- ghcOptObjDir = toFlag odir- }---componentCxxGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo- -> FilePath -> FilePath- -> GhcOptions-componentCxxGhcOptions verbosity _implInfo lbi bi clbi odir filename =- mempty {- -- Respect -v0, but don't crank up verbosity on GHC if- -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!- ghcOptVerbosity = toFlag (min verbosity normal),- ghcOptMode = toFlag GhcModeCompile,- ghcOptInputFiles = toNubListR [filename],-- ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi- ,odir]- -- includes relative to the package- ++ includeDirs bi- -- potential includes generated by `configure'- -- in the build directory- ++ [buildDir lbi </> dir | dir <- includeDirs bi],- ghcOptHideAllPackages= toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,- ghcOptCxxOptions = (case withOptimization lbi of- NoOptimisation -> []- _ -> ["-O2"]) ++- (case withDebugInfo lbi of- NoDebugInfo -> []- MinimalDebugInfo -> ["-g1"]- NormalDebugInfo -> ["-g"]- MaximalDebugInfo -> ["-g3"]) ++- cxxOptions bi,- ghcOptObjDir = toFlag odir- }---componentAsmGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo- -> FilePath -> FilePath- -> GhcOptions-componentAsmGhcOptions verbosity _implInfo lbi bi clbi odir filename =- mempty {- -- Respect -v0, but don't crank up verbosity on GHC if- -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!- ghcOptVerbosity = toFlag (min verbosity normal),- ghcOptMode = toFlag GhcModeCompile,- ghcOptInputFiles = toNubListR [filename],-- ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi- ,odir]- -- includes relative to the package- ++ includeDirs bi- -- potential includes generated by `configure'- -- in the build directory- ++ [buildDir lbi </> dir | dir <- includeDirs bi],- ghcOptHideAllPackages= toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,- ghcOptAsmOptions = (case withOptimization lbi of- NoOptimisation -> []- _ -> ["-O2"]) ++- (case withDebugInfo lbi of- NoDebugInfo -> []- MinimalDebugInfo -> ["-g1"]- NormalDebugInfo -> ["-g"]- MaximalDebugInfo -> ["-g3"]) ++- asmOptions bi,- ghcOptObjDir = toFlag odir- }---componentGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo -> FilePath- -> GhcOptions-componentGhcOptions verbosity implInfo lbi bi clbi odir =- mempty {- -- Respect -v0, but don't crank up verbosity on GHC if- -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!- ghcOptVerbosity = toFlag (min verbosity normal),- ghcOptCabal = toFlag True,- ghcOptThisUnitId = case clbi of- LibComponentLocalBuildInfo { componentCompatPackageKey = pk }- -> toFlag pk- _ -> mempty,- ghcOptThisComponentId = case clbi of- LibComponentLocalBuildInfo { componentComponentId = cid- , componentInstantiatedWith = insts } ->- if null insts- then mempty- else toFlag cid- _ -> mempty,- ghcOptInstantiatedWith = case clbi of- LibComponentLocalBuildInfo { componentInstantiatedWith = insts }- -> insts- _ -> [],- ghcOptNoCode = toFlag $ componentIsIndefinite clbi,- ghcOptHideAllPackages = toFlag True,- ghcOptWarnMissingHomeModules = toFlag $ flagWarnMissingHomeModules implInfo,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,- ghcOptSplitSections = toFlag (splitSections lbi),- ghcOptSplitObjs = toFlag (splitObjs lbi),- ghcOptSourcePathClear = toFlag True,- ghcOptSourcePath = toNubListR $ [odir] ++ (hsSourceDirs bi)- ++ [autogenComponentModulesDir lbi clbi]- ++ [autogenPackageModulesDir lbi],- ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi- ,odir]- -- includes relative to the package- ++ includeDirs bi- -- potential includes generated by `configure'- -- in the build directory- ++ [buildDir lbi </> dir | dir <- includeDirs bi],- ghcOptCppOptions = cppOptions bi,- ghcOptCppIncludes = toNubListR $- [autogenComponentModulesDir lbi clbi </> cppHeaderName],- ghcOptFfiIncludes = toNubListR $ includes bi,- ghcOptObjDir = toFlag odir,- ghcOptHiDir = toFlag odir,- ghcOptStubDir = toFlag odir,- ghcOptOutputDir = toFlag odir,- ghcOptOptimisation = toGhcOptimisation (withOptimization lbi),- ghcOptDebugInfo = toFlag (withDebugInfo lbi),- ghcOptExtra = hcOptions GHC bi,- ghcOptExtraPath = toNubListR $ exe_paths,- ghcOptLanguage = toFlag (fromMaybe Haskell98 (defaultLanguage bi)),- -- Unsupported extensions have already been checked by configure- ghcOptExtensions = toNubListR $ usedExtensions bi,- ghcOptExtensionMap = Map.fromList . compilerExtensions $ (compiler lbi)- }- where- exe_paths = [ componentBuildDir lbi (targetCLBI exe_tgt)- | uid <- componentExeDeps clbi- -- TODO: Ugh, localPkgDescr- , Just exe_tgt <- [unitIdTarget' (localPkgDescr lbi) lbi uid] ]--toGhcOptimisation :: OptimisationLevel -> Flag GhcOptimisation-toGhcOptimisation NoOptimisation = mempty --TODO perhaps override?-toGhcOptimisation NormalOptimisation = toFlag GhcNormalOptimisation-toGhcOptimisation MaximumOptimisation = toFlag GhcMaximumOptimisation---componentCmmGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo- -> FilePath -> FilePath- -> GhcOptions-componentCmmGhcOptions verbosity _implInfo lbi bi clbi odir filename =- mempty {- -- Respect -v0, but don't crank up verbosity on GHC if- -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!- ghcOptVerbosity = toFlag (min verbosity normal),- ghcOptMode = toFlag GhcModeCompile,- ghcOptInputFiles = toNubListR [filename],-- ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi- ,odir]- -- includes relative to the package- ++ includeDirs bi- -- potential includes generated by `configure'- -- in the build directory- ++ [buildDir lbi </> dir | dir <- includeDirs bi],- ghcOptCppOptions = cppOptions bi,- ghcOptCppIncludes = toNubListR $- [autogenComponentModulesDir lbi clbi </> cppHeaderName],- ghcOptHideAllPackages= toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,- ghcOptOptimisation = toGhcOptimisation (withOptimization lbi),- ghcOptDebugInfo = toFlag (withDebugInfo lbi),- ghcOptExtra = cmmOptions bi,- ghcOptObjDir = toFlag odir- }----- | Strip out flags that are not supported in ghci-filterGhciFlags :: [String] -> [String]-filterGhciFlags = filter supported- where- supported ('-':'O':_) = False- supported "-debug" = False- supported "-threaded" = False- supported "-ticky" = False- supported "-eventlog" = False- supported "-prof" = False- supported "-unreg" = False- supported _ = True--mkGHCiLibName :: UnitId -> String-mkGHCiLibName lib = getHSLibraryName lib <.> "o"--mkGHCiProfLibName :: UnitId -> String-mkGHCiProfLibName lib = getHSLibraryName lib <.> "p_o"--ghcLookupProperty :: String -> Compiler -> Bool-ghcLookupProperty prop comp =- case Map.lookup prop (compilerProperties comp) of- Just "YES" -> True- _ -> False---- when using -split-objs, we need to search for object files in the--- Module_split directory for each module.-getHaskellObjects :: GhcImplInfo -> Library -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> FilePath -> String -> Bool -> IO [FilePath]-getHaskellObjects _implInfo lib lbi clbi pref wanted_obj_ext allow_split_objs- | splitObjs lbi && allow_split_objs = do- let splitSuffix = "_" ++ wanted_obj_ext ++ "_split"- dirs = [ pref </> (ModuleName.toFilePath x ++ splitSuffix)- | x <- allLibModules lib clbi ]- objss <- traverse getDirectoryContents dirs- let objs = [ dir </> obj- | (objs',dir) <- zip objss dirs, obj <- objs',- let obj_ext = takeExtension obj,- '.':wanted_obj_ext == obj_ext ]- return objs- | otherwise =- return [ pref </> ModuleName.toFilePath x <.> wanted_obj_ext- | x <- allLibModules lib clbi ]--mkGhcOptPackages :: ComponentLocalBuildInfo- -> [(OpenUnitId, ModuleRenaming)]-mkGhcOptPackages = componentIncludes--substTopDir :: FilePath -> IPI.InstalledPackageInfo -> IPI.InstalledPackageInfo-substTopDir topDir ipo- = ipo {- IPI.importDirs = map f (IPI.importDirs ipo),- IPI.libraryDirs = map f (IPI.libraryDirs ipo),- IPI.includeDirs = map f (IPI.includeDirs ipo),- IPI.frameworkDirs = map f (IPI.frameworkDirs ipo),- IPI.haddockInterfaces = map f (IPI.haddockInterfaces ipo),- IPI.haddockHTMLs = map f (IPI.haddockHTMLs ipo)- }- where f ('$':'t':'o':'p':'d':'i':'r':rest) = topDir ++ rest- f x = x---- Cabal does not use the environment variable GHC{,JS}_PACKAGE_PATH; let--- users know that this is the case. See ticket #335. Simply ignoring it is--- not a good idea, since then ghc and cabal are looking at different sets--- of package DBs and chaos is likely to ensue.------ An exception to this is when running cabal from within a `cabal exec`--- environment. In this case, `cabal exec` will set the--- CABAL_SANDBOX_PACKAGE_PATH to the same value that it set--- GHC{,JS}_PACKAGE_PATH to. If that is the case it is OK to allow--- GHC{,JS}_PACKAGE_PATH.-checkPackageDbEnvVar :: Verbosity -> String -> String -> IO ()-checkPackageDbEnvVar verbosity compilerName packagePathEnvVar = do- mPP <- lookupEnv packagePathEnvVar- when (isJust mPP) $ do- mcsPP <- lookupEnv "CABAL_SANDBOX_PACKAGE_PATH"- unless (mPP == mcsPP) abort- where- lookupEnv :: String -> IO (Maybe String)- lookupEnv name = (Just `fmap` getEnv name)- `catchIO` const (return Nothing)- abort =- die' verbosity $ "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)."-- _ = callStack -- TODO: output stack when erroring--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 platform and version strings---- | GHC's rendering of its host or target 'Arch' as used in its platform--- strings and certain file locations (such as user package db location).----ghcArchString :: Arch -> String-ghcArchString PPC = "powerpc"-ghcArchString PPC64 = "powerpc64"-ghcArchString other = prettyShow other---- | GHC's rendering of its host or target 'OS' as used in its platform--- strings and certain file locations (such as user package db location).----ghcOsString :: OS -> String-ghcOsString Windows = "mingw32"-ghcOsString OSX = "darwin"-ghcOsString Solaris = "solaris2"-ghcOsString other = prettyShow other---- | GHC's rendering of its platform and compiler version string as used in--- certain file locations (such as user package db location).--- For example @x86_64-linux-7.10.4@----ghcPlatformAndVersionString :: Platform -> Version -> String-ghcPlatformAndVersionString (Platform arch os) version =- intercalate "-" [ ghcArchString arch, ghcOsString os, prettyShow version ]----- -------------------------------------------------------------------------------- Constructing GHC environment files---- | The kinds of entries we can stick in a @.ghc.environment@ file.----data GhcEnvironmentFileEntry =- GhcEnvFileComment String -- ^ @-- a comment@- | GhcEnvFilePackageId UnitId -- ^ @package-id foo-1.0-4fe301a...@- | GhcEnvFilePackageDb PackageDB -- ^ @global-package-db@,- -- @user-package-db@ or- -- @package-db blah/package.conf.d/@- | GhcEnvFileClearPackageDbStack -- ^ @clear-package-db@- deriving (Eq, Ord, Show)---- | Make entries for a GHC environment file based on a 'PackageDBStack' and--- a bunch of package (unit) ids.------ If you need to do anything more complicated then either use this as a basis--- and add more entries, or just make all the entries directly.----simpleGhcEnvironmentFile :: PackageDBStack- -> [UnitId]- -> [GhcEnvironmentFileEntry]-simpleGhcEnvironmentFile packageDBs pkgids =- GhcEnvFileClearPackageDbStack- : map GhcEnvFilePackageDb packageDBs- ++ map GhcEnvFilePackageId pkgids---- | Write a @.ghc.environment-$arch-$os-$ver@ file in the given directory.------ The 'Platform' and GHC 'Version' are needed as part of the file name.------ Returns the name of the file written.-writeGhcEnvironmentFile :: FilePath -- ^ directory in which to put it- -> Platform -- ^ the GHC target platform- -> Version -- ^ the GHC version- -> [GhcEnvironmentFileEntry] -- ^ the content- -> IO FilePath-writeGhcEnvironmentFile directory platform ghcversion entries = do- writeFileAtomic envfile . BS.pack . renderGhcEnvironmentFile $ entries- return envfile- where- envfile = directory </> ghcEnvironmentFileName platform ghcversion---- | The @.ghc.environment-$arch-$os-$ver@ file name----ghcEnvironmentFileName :: Platform -> Version -> FilePath-ghcEnvironmentFileName platform ghcversion =- ".ghc.environment." ++ ghcPlatformAndVersionString platform ghcversion---- | Render a bunch of GHC environment file entries----renderGhcEnvironmentFile :: [GhcEnvironmentFileEntry] -> String-renderGhcEnvironmentFile =- unlines . map renderGhcEnvironmentFileEntry---- | Render an individual GHC environment file entry----renderGhcEnvironmentFileEntry :: GhcEnvironmentFileEntry -> String-renderGhcEnvironmentFileEntry entry = case entry of- GhcEnvFileComment comment -> format comment- where format = intercalate "\n" . map ("--" <++>) . lines- pref <++> "" = pref- pref <++> str = pref ++ " " ++ str- GhcEnvFilePackageId pkgid -> "package-id " ++ prettyShow pkgid- GhcEnvFilePackageDb pkgdb ->- case pkgdb of- GlobalPackageDB -> "global-package-db"- UserPackageDB -> "user-package-db"- SpecificPackageDB dbfile -> "package-db " ++ dbfile- GhcEnvFileClearPackageDbStack -> "clear-package-db"
− Distribution/Simple/GHCJS.hs
@@ -1,1830 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE CPP #-}--module Distribution.Simple.GHCJS (- getGhcInfo,- configure,- getInstalledPackages,- getInstalledPackagesMonitorFiles,- getPackageDBContents,- buildLib, buildFLib, buildExe,- replLib, replFLib, replExe,- startInterpreter,- installLib, installFLib, installExe,- libAbiHash,- hcPkgInfo,- registerPackage,- componentGhcOptions,- componentCcGhcOptions,- getLibDir,- isDynamic,- getGlobalPackageDB,- pkgRoot,- runCmd,- -- * Constructing and deconstructing GHC environment files- Internal.GhcEnvironmentFileEntry(..),- Internal.simpleGhcEnvironmentFile,- Internal.renderGhcEnvironmentFile,- Internal.writeGhcEnvironmentFile,- Internal.ghcPlatformAndVersionString,- readGhcEnvironmentFile,- parseGhcEnvironmentFile,- ParseErrorExc(..),- -- * Version-specific implementation quirks- getImplInfo,- GhcImplInfo(..)- ) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Distribution.Simple.GHC.Internal as Internal-import Distribution.Simple.GHC.ImplInfo-import Distribution.Simple.GHC.EnvironmentParser-import Distribution.PackageDescription.Utils (cabalBug)-import Distribution.PackageDescription as PD-import Distribution.InstalledPackageInfo (InstalledPackageInfo)-import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo-import Distribution.Simple.PackageIndex (InstalledPackageIndex)-import qualified Distribution.Simple.PackageIndex as PackageIndex-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.ComponentLocalBuildInfo-import qualified Distribution.Simple.Hpc as Hpc-import Distribution.Simple.BuildPaths-import Distribution.Simple.Utils-import Distribution.Package-import qualified Distribution.ModuleName as ModuleName-import Distribution.ModuleName (ModuleName)-import Distribution.Simple.Program-import qualified Distribution.Simple.Program.HcPkg as HcPkg-import qualified Distribution.Simple.Program.Strip as Strip-import Distribution.Simple.Program.GHC-import Distribution.Simple.Setup-import qualified Distribution.Simple.Setup as Cabal-import Distribution.Simple.Compiler-import Distribution.CabalSpecVersion-import Distribution.Version-import Distribution.System-import Distribution.Verbosity-import Distribution.Pretty-import Distribution.Utils.NubList--import Control.Monad (msum)-import Data.Char (isLower)-import qualified Data.Map as Map-import System.Directory- ( doesFileExist, getAppUserDataDirectory, createDirectoryIfMissing- , canonicalizePath, removeFile, renameFile )-import System.FilePath ( (</>), (<.>), takeExtension- , takeDirectory, replaceExtension- ,isRelative )-import qualified System.Info---- -------------------------------------------------------------------------------- Configuring--configure :: Verbosity -> Maybe FilePath -> Maybe FilePath- -> ProgramDb- -> IO (Compiler, Maybe Platform, ProgramDb)-configure verbosity hcPath hcPkgPath conf0 = do-- (ghcjsProg, ghcjsVersion, progdb1) <-- requireProgramVersion verbosity ghcjsProgram- (orLaterVersion (mkVersion [0,1]))- (userMaybeSpecifyPath "ghcjs" hcPath conf0)-- Just ghcjsGhcVersion <- findGhcjsGhcVersion verbosity (programPath ghcjsProg)- unless (ghcjsGhcVersion < mkVersion [8,8]) $- warn verbosity $- "Unknown/unsupported 'ghc' version detected "- ++ "(Cabal " ++ prettyShow cabalVersion ++ " supports 'ghc' version < 8.8): "- ++ programPath ghcjsProg ++ " is based on GHC version " ++- prettyShow ghcjsGhcVersion-- let implInfo = ghcjsVersionImplInfo ghcjsVersion ghcjsGhcVersion-- -- This is slightly tricky, we have to configure ghc first, then we use the- -- location of ghc to help find ghc-pkg in the case that the user did not- -- specify the location of ghc-pkg directly:- (ghcjsPkgProg, ghcjsPkgVersion, progdb2) <-- requireProgramVersion verbosity ghcjsPkgProgram {- programFindLocation = guessGhcjsPkgFromGhcjsPath ghcjsProg- }- anyVersion (userMaybeSpecifyPath "ghcjs-pkg" hcPkgPath progdb1)-- Just ghcjsPkgGhcjsVersion <- findGhcjsPkgGhcjsVersion- verbosity (programPath ghcjsPkgProg)-- when (ghcjsVersion /= ghcjsPkgGhcjsVersion) $ die' verbosity $- "Version mismatch between ghcjs and ghcjs-pkg: "- ++ programPath ghcjsProg ++ " is version " ++ prettyShow ghcjsVersion ++ " "- ++ programPath ghcjsPkgProg ++ " is version " ++ prettyShow ghcjsPkgGhcjsVersion-- when (ghcjsGhcVersion /= ghcjsPkgVersion) $ die' verbosity $- "Version mismatch between ghcjs and ghcjs-pkg: "- ++ programPath ghcjsProg- ++ " was built with GHC version " ++ prettyShow ghcjsGhcVersion ++ " "- ++ programPath ghcjsPkgProg- ++ " was built with GHC version " ++ prettyShow ghcjsPkgVersion--- -- Likewise we try to find the matching hsc2hs and haddock programs.- let hsc2hsProgram' = hsc2hsProgram {- programFindLocation =- guessHsc2hsFromGhcjsPath ghcjsProg- }- haddockProgram' = haddockProgram {- programFindLocation =- guessHaddockFromGhcjsPath ghcjsProg- }- hpcProgram' = hpcProgram {- programFindLocation = guessHpcFromGhcjsPath ghcjsProg- }- {-- runghcProgram' = runghcProgram {- programFindLocation = guessRunghcFromGhcjsPath ghcjsProg- } -}- progdb3 = addKnownProgram haddockProgram' $- addKnownProgram hsc2hsProgram' $- addKnownProgram hpcProgram' $- {- addKnownProgram runghcProgram' -} progdb2-- languages <- Internal.getLanguages verbosity implInfo ghcjsProg- extensions <- Internal.getExtensions verbosity implInfo ghcjsProg-- ghcjsInfo <- Internal.getGhcInfo verbosity implInfo ghcjsProg- let ghcInfoMap = Map.fromList ghcjsInfo-- let comp = Compiler {- compilerId = CompilerId GHCJS ghcjsVersion,- compilerAbiTag = AbiTag $- "ghc" ++ intercalate "_" (map show . versionNumbers $ ghcjsGhcVersion),- compilerCompat = [CompilerId GHC ghcjsGhcVersion],- compilerLanguages = languages,- compilerExtensions = extensions,- compilerProperties = ghcInfoMap- }- compPlatform = Internal.targetPlatform ghcjsInfo- return (comp, compPlatform, progdb3)--guessGhcjsPkgFromGhcjsPath :: ConfiguredProgram -> Verbosity- -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))-guessGhcjsPkgFromGhcjsPath = guessToolFromGhcjsPath ghcjsPkgProgram--guessHsc2hsFromGhcjsPath :: ConfiguredProgram -> Verbosity- -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))-guessHsc2hsFromGhcjsPath = guessToolFromGhcjsPath hsc2hsProgram--guessHaddockFromGhcjsPath :: ConfiguredProgram -> Verbosity- -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))-guessHaddockFromGhcjsPath = guessToolFromGhcjsPath haddockProgram--guessHpcFromGhcjsPath :: ConfiguredProgram- -> Verbosity -> ProgramSearchPath- -> IO (Maybe (FilePath, [FilePath]))-guessHpcFromGhcjsPath = guessToolFromGhcjsPath hpcProgram---guessToolFromGhcjsPath :: Program -> ConfiguredProgram- -> Verbosity -> ProgramSearchPath- -> IO (Maybe (FilePath, [FilePath]))-guessToolFromGhcjsPath tool ghcjsProg verbosity searchpath- = do let toolname = programName tool- given_path = programPath ghcjsProg- 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 buildPlatform- guessGhcjs dir = dir </> (toolname ++ "-ghcjs")- <.> exeExtension buildPlatform- guessGhcjsVersioned dir suf = dir </> (toolname ++ "-ghcjs" ++ suf)- <.> exeExtension buildPlatform- guessVersioned dir suf = dir </> (toolname ++ suf)- <.> exeExtension buildPlatform- mkGuesses dir suf | null suf = [guessGhcjs dir, guessNormal dir]- | otherwise = [guessGhcjsVersioned dir suf,- guessVersioned dir suf,- guessGhcjs dir,- 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 " ++ given_dir- debug verbosity $ "candidate locations: " ++ show guesses- exists <- traverse 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- let lookedAt = map fst- . takeWhile (\(_file, exist) -> not exist)- $ zip guesses exists- return (Just (fp, lookedAt))-- where takeVersionSuffix :: FilePath -> String- takeVersionSuffix = takeWhileEndLE isSuffixChar-- isSuffixChar :: Char -> Bool- isSuffixChar c = isDigit c || c == '.' || c == '-'--getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)]-getGhcInfo verbosity ghcjsProg = Internal.getGhcInfo verbosity implInfo ghcjsProg- where- version = fromMaybe (error "GHCJS.getGhcInfo: no version") $ programVersion ghcjsProg- implInfo = ghcVersionImplInfo version---- | Given a single package DB, return all installed packages.-getPackageDBContents :: Verbosity -> PackageDB -> ProgramDb- -> IO InstalledPackageIndex-getPackageDBContents verbosity packagedb progdb = do- pkgss <- getInstalledPackages' verbosity [packagedb] progdb- toPackageIndex verbosity pkgss progdb---- | Given a package DB stack, return all installed packages.-getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramDb- -> IO InstalledPackageIndex-getInstalledPackages verbosity packagedbs progdb = do- checkPackageDbEnvVar verbosity- checkPackageDbStack verbosity packagedbs- pkgss <- getInstalledPackages' verbosity packagedbs progdb- index <- toPackageIndex verbosity pkgss progdb- return $! index--toPackageIndex :: Verbosity- -> [(PackageDB, [InstalledPackageInfo])]- -> ProgramDb- -> IO InstalledPackageIndex-toPackageIndex verbosity pkgss progdb = do- -- On Windows, various fields have $topdir/foo rather than full- -- paths. We need to substitute the right value in so that when- -- we, for example, call gcc, we have proper paths to give it.- topDir <- getLibDir' verbosity ghcjsProg- let indices = [ PackageIndex.fromList (map (Internal.substTopDir topDir) pkgs)- | (_, pkgs) <- pkgss ]- return $! (mconcat indices)-- where- ghcjsProg = fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb--getLibDir :: Verbosity -> LocalBuildInfo -> IO FilePath-getLibDir verbosity lbi =- dropWhileEndLE isSpace `fmap`- getDbProgramOutput verbosity ghcjsProgram- (withPrograms lbi) ["--print-libdir"]--getLibDir' :: Verbosity -> ConfiguredProgram -> IO FilePath-getLibDir' verbosity ghcjsProg =- dropWhileEndLE isSpace `fmap`- getProgramOutput verbosity ghcjsProg ["--print-libdir"]----- | Return the 'FilePath' to the global GHC package database.-getGlobalPackageDB :: Verbosity -> ConfiguredProgram -> IO FilePath-getGlobalPackageDB verbosity ghcProg =- dropWhileEndLE isSpace `fmap`- getProgramOutput verbosity ghcProg ["--print-global-package-db"]---- | Return the 'FilePath' to the per-user GHC package database.-getUserPackageDB :: Verbosity -> ConfiguredProgram -> Platform -> IO FilePath-getUserPackageDB _verbosity ghcjsProg platform = 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 "ghcjs"- return (appdir </> platformAndVersion </> packageConfFileName)- where- platformAndVersion = Internal.ghcPlatformAndVersionString- platform ghcjsVersion- packageConfFileName = "package.conf.d"- ghcjsVersion = fromMaybe (error "GHCJS.getUserPackageDB: no version") $ programVersion ghcjsProg--checkPackageDbEnvVar :: Verbosity -> IO ()-checkPackageDbEnvVar verbosity =- Internal.checkPackageDbEnvVar verbosity "GHCJS" "GHCJS_PACKAGE_PATH"--checkPackageDbStack :: Verbosity -> PackageDBStack -> IO ()-checkPackageDbStack _ (GlobalPackageDB:rest)- | GlobalPackageDB `notElem` rest = return ()-checkPackageDbStack verbosity rest- | GlobalPackageDB `notElem` rest =- die' verbosity $ "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 https://gitlab.haskell.org/ghc/ghc/-/issues/5977"-checkPackageDbStack verbosity _ =- die' verbosity $ "If the global package db is specified, it must be "- ++ "specified first and cannot be specified multiple times"--getInstalledPackages' :: Verbosity -> [PackageDB] -> ProgramDb- -> IO [(PackageDB, [InstalledPackageInfo])]-getInstalledPackages' verbosity packagedbs progdb =- sequenceA- [ do pkgs <- HcPkg.dump (hcPkgInfo progdb) verbosity packagedb- return (packagedb, pkgs)- | packagedb <- packagedbs ]---- | Get the packages from specific PackageDBs, not cumulative.----getInstalledPackagesMonitorFiles :: Verbosity -> Platform- -> ProgramDb- -> [PackageDB]- -> IO [FilePath]-getInstalledPackagesMonitorFiles verbosity platform progdb =- traverse getPackageDBPath- where- getPackageDBPath :: PackageDB -> IO FilePath- getPackageDBPath GlobalPackageDB =- selectMonitorFile =<< getGlobalPackageDB verbosity ghcjsProg-- getPackageDBPath UserPackageDB =- selectMonitorFile =<< getUserPackageDB verbosity ghcjsProg 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")-- ghcjsProg = fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb---toJSLibName :: String -> String-toJSLibName lib- | takeExtension lib `elem` [".dll",".dylib",".so"]- = replaceExtension lib "js_so"- | takeExtension lib == ".a" = replaceExtension lib "js_a"- | otherwise = lib <.> "js_a"---- -------------------------------------------------------------------------------- Building a library--buildLib :: Verbosity -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo- -> IO ()-buildLib = buildOrReplLib Nothing--replLib :: [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> Library- -> ComponentLocalBuildInfo -> IO ()-replLib = buildOrReplLib . Just--buildOrReplLib :: Maybe [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> Library- -> ComponentLocalBuildInfo -> IO ()-buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do- let uid = componentUnitId clbi- libTargetDir = componentBuildDir lbi clbi- whenVanillaLib forceVanilla =- when (forceVanilla || withVanillaLib lbi)- whenProfLib = when (withProfLib lbi)- whenSharedLib forceShared =- when (forceShared || withSharedLib lbi)- whenStaticLib forceStatic =- when (forceStatic || withStaticLib lbi)- -- whenGHCiLib = when (withGHCiLib lbi)- forRepl = maybe False (const True) mReplFlags- -- ifReplLib = when forRepl- comp = compiler lbi- implInfo = getImplInfo comp- platform@(Platform _hostArch _hostOS) = hostPlatform lbi- has_code = not (componentIsIndefinite clbi)-- (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)- let runGhcjsProg = runGHC verbosity ghcjsProg comp platform-- let libBi = libBuildInfo lib-- -- fixme flags shouldn't depend on ghcjs being dynamic or not- let isGhcjsDynamic = isDynamic comp- dynamicTooSupported = supportsDynamicToo comp- doingTH = usesTemplateHaskellOrQQ libBi- forceVanillaLib = doingTH && not isGhcjsDynamic- forceSharedLib = doingTH && isGhcjsDynamic- -- TH always needs default libs, even when building for profiling-- -- Determine if program coverage should be enabled and if so, what- -- '-hpcdir' should be.- let isCoverageEnabled = libCoverage lbi- -- TODO: Historically HPC files have been put into a directory which- -- has the package name. I'm going to avoid changing this for- -- now, but it would probably be better for this to be the- -- component ID instead...- pkg_name = prettyShow (PD.package pkg_descr)- distPref = fromFlag $ configDistPref $ configFlags lbi- hpcdir way- | forRepl = mempty -- HPC is not supported in ghci- | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way pkg_name- | otherwise = mempty-- createDirectoryIfMissingVerbose verbosity True libTargetDir- -- TODO: do we need to put hs-boot files into place for mutually recursive- -- modules?- let cLikeFiles = fromNubListR $ toNubListR (cSources libBi) <> toNubListR (cxxSources libBi)- jsSrcs = jsSources libBi- cObjs = map (`replaceExtension` objExtension) cLikeFiles- baseOpts = componentGhcOptions verbosity lbi libBi clbi libTargetDir- linkJsLibOpts = mempty {- ghcOptExtra =- [ "-link-js-lib" , getHSLibraryName uid- , "-js-lib-outputdir", libTargetDir ] ++- jsSrcs- }- vanillaOptsNoJsLib = baseOpts `mappend` mempty {- ghcOptMode = toFlag GhcModeMake,- ghcOptNumJobs = numJobs,- ghcOptInputModules = toNubListR $ allLibModules lib clbi,- ghcOptHPCDir = hpcdir Hpc.Vanilla- }- vanillaOpts = vanillaOptsNoJsLib `mappend` linkJsLibOpts-- profOpts = adjustExts "p_hi" "p_o" vanillaOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptProfilingAuto = Internal.profDetailLevelFlag True- (withProfLibDetail lbi),- -- ghcOptHiSuffix = toFlag "p_hi",- -- ghcOptObjSuffix = toFlag "p_o",- ghcOptExtra = hcProfOptions GHC libBi,- ghcOptHPCDir = hpcdir Hpc.Prof- }-- sharedOpts = adjustExts "dyn_hi" "dyn_o" vanillaOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptFPic = toFlag True,- -- ghcOptHiSuffix = toFlag "dyn_hi",- -- ghcOptObjSuffix = toFlag "dyn_o",- ghcOptExtra = hcSharedOptions GHC libBi,- ghcOptHPCDir = hpcdir Hpc.Dyn- }-- vanillaSharedOpts = vanillaOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,- ghcOptDynHiSuffix = toFlag "js_dyn_hi",- ghcOptDynObjSuffix = toFlag "js_dyn_o",- ghcOptHPCDir = hpcdir Hpc.Dyn- }-- unless (forRepl || null (allLibModules lib clbi) && null jsSrcs && null cObjs) $- do let vanilla = whenVanillaLib forceVanillaLib (runGhcjsProg vanillaOpts)- shared = whenSharedLib forceSharedLib (runGhcjsProg sharedOpts)- useDynToo = dynamicTooSupported &&- (forceVanillaLib || withVanillaLib lbi) &&- (forceSharedLib || withSharedLib lbi) &&- null (hcSharedOptions GHC libBi)- if not has_code- then vanilla- else- if useDynToo- then do- runGhcjsProg vanillaSharedOpts- case (hpcdir Hpc.Dyn, hpcdir Hpc.Vanilla) of- (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- -- static and dynamically linked executables. We copy- -- the modules interfaces so they are available under- -- both ways.- copyDirectoryRecursive verbosity dynDir vanillaDir- _ -> return ()- else if isGhcjsDynamic- then do shared; vanilla- else do vanilla; shared- whenProfLib (runGhcjsProg profOpts)-- -- Build any C++ sources separately.- {-- unless (not has_code || null (cxxSources libBi) || not nativeToo) $ do- info verbosity "Building C++ Sources..."- sequence_- [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo- lbi libBi clbi libTargetDir filename- vanillaCxxOpts = if isGhcjsDynamic- then baseCxxOpts { ghcOptFPic = toFlag True }- else baseCxxOpts- profCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptObjSuffix = toFlag "p_o"- }- sharedCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptObjSuffix = toFlag "dyn_o"- }- odir = fromFlag (ghcOptObjDir vanillaCxxOpts)- createDirectoryIfMissingVerbose verbosity True odir- let runGhcProgIfNeeded cxxOpts = do- needsRecomp <- checkNeedsRecompilation filename cxxOpts- when needsRecomp $ runGhcjsProg cxxOpts- runGhcProgIfNeeded vanillaCxxOpts- unless forRepl $- whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCxxOpts)- unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts)- | filename <- cxxSources libBi]-- ifReplLib $ do- when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"- ifReplLib (runGhcjsProg replOpts)--}- -- build any C sources- -- TODO: Add support for S and CMM files.- {-- unless (not has_code || null (cSources libBi) || not nativeToo) $ do- info verbosity "Building C Sources..."- sequence_- [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo- lbi libBi clbi libTargetDir filename- vanillaCcOpts = if isGhcjsDynamic- -- Dynamic GHC requires C sources to be built- -- with -fPIC for REPL to work. See #2207.- then baseCcOpts { ghcOptFPic = toFlag True }- else baseCcOpts- profCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptObjSuffix = toFlag "p_o"- }- sharedCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptObjSuffix = toFlag "dyn_o"- }- odir = fromFlag (ghcOptObjDir vanillaCcOpts)- createDirectoryIfMissingVerbose verbosity True odir- let runGhcProgIfNeeded ccOpts = do- needsRecomp <- checkNeedsRecompilation filename ccOpts- when needsRecomp $ runGhcjsProg ccOpts- runGhcProgIfNeeded vanillaCcOpts- unless forRepl $- whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCcOpts)- unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts)- | filename <- cSources libBi]--}- -- TODO: problem here is we need the .c files built first, so we can load them- -- with ghci, but .c files can depend on .h files generated by ghc by ffi- -- exports.-- -- link:-- when has_code . when False {- fixme nativeToo -} . unless forRepl $ do- info verbosity "Linking..."- let cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))- (cSources libBi ++ cxxSources libBi)- compiler_id = compilerId (compiler lbi)- sharedLibFilePath = libTargetDir </> mkSharedLibName (hostPlatform lbi) compiler_id uid- staticLibFilePath = libTargetDir </> mkStaticLibName (hostPlatform lbi) compiler_id uid-- let stubObjs = []- stubSharedObjs = []--{-- stubObjs <- catMaybes <$> sequenceA- [ findFileWithExtension [objExtension] [libTargetDir]- (ModuleName.toFilePath x ++"_stub")- | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files- , x <- allLibModules lib clbi ]- stubProfObjs <- catMaybes <$> sequenceA- [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]- (ModuleName.toFilePath x ++"_stub")- | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files- , x <- allLibModules lib clbi ]- stubSharedObjs <- catMaybes <$> sequenceA- [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]- (ModuleName.toFilePath x ++"_stub")- | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files- , x <- allLibModules lib clbi ]--}- hObjs <- Internal.getHaskellObjects implInfo lib lbi clbi- libTargetDir objExtension True- hSharedObjs <-- if withSharedLib lbi- then Internal.getHaskellObjects implInfo lib lbi clbi- libTargetDir ("dyn_" ++ objExtension) False- else return []-- unless (null hObjs && null cObjs && null stubObjs) $ do- rpaths <- getRPaths lbi clbi-- let staticObjectFiles =- hObjs- ++ map (libTargetDir </>) cObjs- ++ stubObjs- dynamicObjectFiles =- hSharedObjs- ++ map (libTargetDir </>) cSharedObjs- ++ stubSharedObjs- -- After the relocation lib is created we invoke ghc -shared- -- with the dependencies spelled out as -package arguments- -- and ghc invokes the linker with the proper library paths- ghcSharedLinkArgs =- mempty {- ghcOptShared = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptInputFiles = toNubListR dynamicObjectFiles,- ghcOptOutputFile = toFlag sharedLibFilePath,- ghcOptExtra = 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 < mkVersion [7,8]- then toFlag sharedLibInstallPath- else mempty, -}- ghcOptHideAllPackages = toFlag True,- ghcOptNoAutoLinkPackages = toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptThisUnitId = case clbi of- LibComponentLocalBuildInfo { componentCompatPackageKey = pk }- -> toFlag pk- _ -> mempty,- ghcOptThisComponentId = case clbi of- LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->- if null insts- then mempty- else toFlag (componentComponentId clbi)- _ -> mempty,- ghcOptInstantiatedWith = case clbi of- LibComponentLocalBuildInfo { componentInstantiatedWith = insts }- -> insts- _ -> [],- ghcOptPackages = toNubListR $- Internal.mkGhcOptPackages clbi ,- ghcOptLinkLibs = extraLibs libBi,- ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi,- ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,- ghcOptLinkFrameworkDirs =- toNubListR $ PD.extraFrameworkDirs libBi,- ghcOptRPaths = rpaths- }- ghcStaticLinkArgs =- mempty {- ghcOptStaticLib = toFlag True,- ghcOptInputFiles = toNubListR staticObjectFiles,- ghcOptOutputFile = toFlag staticLibFilePath,- ghcOptExtra = hcStaticOptions GHC libBi,- ghcOptHideAllPackages = toFlag True,- ghcOptNoAutoLinkPackages = toFlag True,- ghcOptPackageDBs = withPackageDB lbi,- ghcOptThisUnitId = case clbi of- LibComponentLocalBuildInfo { componentCompatPackageKey = pk }- -> toFlag pk- _ -> mempty,- ghcOptThisComponentId = case clbi of- LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->- if null insts- then mempty- else toFlag (componentComponentId clbi)- _ -> mempty,- ghcOptInstantiatedWith = case clbi of- LibComponentLocalBuildInfo { componentInstantiatedWith = insts }- -> insts- _ -> [],- ghcOptPackages = toNubListR $- Internal.mkGhcOptPackages clbi ,- ghcOptLinkLibs = extraLibs libBi,- ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi- }-- info verbosity (show (ghcOptPackages ghcSharedLinkArgs))-{-- whenVanillaLib False $ do- Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles- whenGHCiLib $ do- (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)- Ld.combineObjectFiles verbosity lbi ldProg- ghciLibFilePath staticObjectFiles- -}-{-- whenProfLib $ do- Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles- whenGHCiLib $ do- (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)- Ld.combineObjectFiles verbosity lbi ldProg- ghciProfLibFilePath profObjectFiles--}- whenSharedLib False $- runGhcjsProg ghcSharedLinkArgs-- whenStaticLib False $- runGhcjsProg ghcStaticLinkArgs---- | Start a REPL without loading any source files.-startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform- -> PackageDBStack -> IO ()-startInterpreter verbosity progdb comp platform packageDBs = do- let replOpts = mempty {- ghcOptMode = toFlag GhcModeInteractive,- ghcOptPackageDBs = packageDBs- }- checkPackageDbStack verbosity packageDBs- (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram progdb- runGHC verbosity ghcjsProg comp platform replOpts---- -------------------------------------------------------------------------------- Building an executable or foreign library---- | Build a foreign library-buildFLib- :: Verbosity -> Cabal.Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> ForeignLib -> ComponentLocalBuildInfo -> IO ()-buildFLib v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildFLib--replFLib- :: [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> ForeignLib- -> ComponentLocalBuildInfo -> IO ()-replFLib replFlags v njobs pkg lbi =- gbuild v njobs pkg lbi . GReplFLib replFlags---- | Build an executable with GHC.----buildExe- :: Verbosity -> Cabal.Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> Executable -> ComponentLocalBuildInfo -> IO ()-buildExe v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildExe--replExe- :: [String] -> Verbosity- -> Cabal.Flag (Maybe Int) -> PackageDescription- -> LocalBuildInfo -> Executable- -> ComponentLocalBuildInfo -> IO ()-replExe replFlags v njobs pkg lbi =- gbuild v njobs pkg lbi . GReplExe replFlags---- | Building an executable, starting the REPL, and building foreign--- libraries are all very similar and implemented in 'gbuild'. The--- 'GBuildMode' distinguishes between the various kinds of operation.-data GBuildMode =- GBuildExe Executable- | GReplExe [String] Executable- | GBuildFLib ForeignLib- | GReplFLib [String] ForeignLib--gbuildInfo :: GBuildMode -> BuildInfo-gbuildInfo (GBuildExe exe) = buildInfo exe-gbuildInfo (GReplExe _ exe) = buildInfo exe-gbuildInfo (GBuildFLib flib) = foreignLibBuildInfo flib-gbuildInfo (GReplFLib _ flib) = foreignLibBuildInfo flib--gbuildName :: GBuildMode -> String-gbuildName (GBuildExe exe) = unUnqualComponentName $ exeName exe-gbuildName (GReplExe _ exe) = unUnqualComponentName $ exeName exe-gbuildName (GBuildFLib flib) = unUnqualComponentName $ foreignLibName flib-gbuildName (GReplFLib _ flib) = unUnqualComponentName $ foreignLibName flib--gbuildTargetName :: LocalBuildInfo -> GBuildMode -> String-gbuildTargetName lbi (GBuildExe exe) = exeTargetName (hostPlatform lbi) exe-gbuildTargetName lbi (GReplExe _ exe) = exeTargetName (hostPlatform lbi) exe-gbuildTargetName lbi (GBuildFLib flib) = flibTargetName lbi flib-gbuildTargetName lbi (GReplFLib _ flib) = flibTargetName lbi flib--exeTargetName :: Platform -> Executable -> String-exeTargetName platform exe = unUnqualComponentName (exeName exe) `withExt` exeExtension platform---- | Target name for a foreign library (the actual file name)------ We do not use mkLibName and co here because the naming for foreign libraries--- is slightly different (we don't use "_p" or compiler version suffices, and we--- don't want the "lib" prefix on Windows).------ TODO: We do use `dllExtension` and co here, but really that's wrong: they--- use the OS used to build cabal to determine which extension to use, rather--- than the target OS (but this is wrong elsewhere in Cabal as well).-flibTargetName :: LocalBuildInfo -> ForeignLib -> String-flibTargetName lbi flib =- case (os, foreignLibType flib) of- (Windows, ForeignLibNativeShared) -> nm <.> "dll"- (Windows, ForeignLibNativeStatic) -> nm <.> "lib"- (Linux, ForeignLibNativeShared) -> "lib" ++ nm <.> versionedExt- (_other, ForeignLibNativeShared) -> "lib" ++ nm <.> dllExtension (hostPlatform lbi)- (_other, ForeignLibNativeStatic) -> "lib" ++ nm <.> staticLibExtension (hostPlatform lbi)- (_any, ForeignLibTypeUnknown) -> cabalBug "unknown foreign lib type"- where- nm :: String- nm = unUnqualComponentName $ foreignLibName flib-- os :: OS- os = let (Platform _ os') = hostPlatform lbi- in os'-- -- If a foreign lib foo has lib-version-info 5:1:2 or- -- lib-version-linux 3.2.1, it should be built as libfoo.so.3.2.1- -- Libtool's version-info data is translated into library versions in a- -- nontrivial way: so refer to libtool documentation.- versionedExt :: String- versionedExt =- let nums = foreignLibVersion flib os- in foldl (<.>) "so" (map show nums)---- | Name for the library when building.------ If the `lib-version-info` field or the `lib-version-linux` field of--- a foreign library target is set, we need to incorporate that--- version into the SONAME field.------ If a foreign library foo has lib-version-info 5:1:2, it should be--- built as libfoo.so.3.2.1. We want it to get soname libfoo.so.3.--- However, GHC does not allow overriding soname by setting linker--- options, as it sets a soname of its own (namely the output--- filename), after the user-supplied linker options. Hence, we have--- to compile the library with the soname as its filename. We rename--- the compiled binary afterwards.------ This method allows to adjust the name of the library at build time--- such that the correct soname can be set.-flibBuildName :: LocalBuildInfo -> ForeignLib -> String-flibBuildName lbi flib- -- On linux, if a foreign-library has version data, the first digit is used- -- to produce the SONAME.- | (os, foreignLibType flib) ==- (Linux, ForeignLibNativeShared)- = let nums = foreignLibVersion flib os- in "lib" ++ nm <.> foldl (<.>) "so" (map show (take 1 nums))- | otherwise = flibTargetName lbi flib- where- os :: OS- os = let (Platform _ os') = hostPlatform lbi- in os'-- nm :: String- nm = unUnqualComponentName $ foreignLibName flib--gbuildIsRepl :: GBuildMode -> Bool-gbuildIsRepl (GBuildExe _) = False-gbuildIsRepl (GReplExe _ _) = True-gbuildIsRepl (GBuildFLib _) = False-gbuildIsRepl (GReplFLib _ _) = True--gbuildNeedDynamic :: LocalBuildInfo -> GBuildMode -> Bool-gbuildNeedDynamic lbi bm =- case bm of- GBuildExe _ -> withDynExe lbi- GReplExe _ _ -> withDynExe lbi- GBuildFLib flib -> withDynFLib flib- GReplFLib _ flib -> withDynFLib flib- where- withDynFLib flib =- case foreignLibType flib of- ForeignLibNativeShared ->- ForeignLibStandalone `notElem` foreignLibOptions flib- ForeignLibNativeStatic ->- False- ForeignLibTypeUnknown ->- cabalBug "unknown foreign lib type"--gbuildModDefFiles :: GBuildMode -> [FilePath]-gbuildModDefFiles (GBuildExe _) = []-gbuildModDefFiles (GReplExe _ _) = []-gbuildModDefFiles (GBuildFLib flib) = foreignLibModDefFile flib-gbuildModDefFiles (GReplFLib _ flib) = foreignLibModDefFile flib---- | "Main" module name when overridden by @ghc-options: -main-is ...@--- or 'Nothing' if no @-main-is@ flag could be found.------ In case of 'Nothing', 'Distribution.ModuleName.main' can be assumed.-exeMainModuleName :: Executable -> Maybe ModuleName-exeMainModuleName Executable{buildInfo = bnfo} =- -- GHC honors the last occurrence of a module name updated via -main-is- --- -- Moreover, -main-is when parsed left-to-right can update either- -- the "Main" module name, or the "main" function name, or both,- -- see also 'decodeMainIsArg'.- msum $ reverse $ map decodeMainIsArg $ findIsMainArgs ghcopts- where- ghcopts = hcOptions GHC bnfo-- findIsMainArgs [] = []- findIsMainArgs ("-main-is":arg:rest) = arg : findIsMainArgs rest- findIsMainArgs (_:rest) = findIsMainArgs rest---- | Decode argument to '-main-is'------ Returns 'Nothing' if argument set only the function name.------ This code has been stolen/refactored from GHC's DynFlags.setMainIs--- function. The logic here is deliberately imperfect as it is--- intended to be bug-compatible with GHC's parser. See discussion in--- https://github.com/haskell/cabal/pull/4539#discussion_r118981753.-decodeMainIsArg :: String -> Maybe ModuleName-decodeMainIsArg arg- | headOf main_fn isLower- -- The arg looked like "Foo.Bar.baz"- = Just (ModuleName.fromString main_mod)- | headOf arg isUpper -- The arg looked like "Foo" or "Foo.Bar"- = Just (ModuleName.fromString arg)- | otherwise -- The arg looked like "baz"- = Nothing- where- headOf :: String -> (Char -> Bool) -> Bool- headOf str pred' = any pred' (safeHead str)-- (main_mod, main_fn) = splitLongestPrefix arg (== '.')-- splitLongestPrefix :: String -> (Char -> Bool) -> (String,String)- splitLongestPrefix str pred'- | null r_pre = (str, [])- | otherwise = (reverse (safeTail r_pre), reverse r_suf)- -- 'safeTail' drops the char satisfying 'pred'- where (r_suf, r_pre) = break pred' (reverse str)----- | A collection of:--- * C input files--- * C++ input files--- * GHC input files--- * GHC input modules------ Used to correctly build and link sources.-data BuildSources = BuildSources {- cSourcesFiles :: [FilePath],- cxxSourceFiles :: [FilePath],- inputSourceFiles :: [FilePath],- inputSourceModules :: [ModuleName]- }---- | Locate and return the 'BuildSources' required to build and link.-gbuildSources :: Verbosity- -> CabalSpecVersion- -> FilePath- -> GBuildMode- -> IO BuildSources-gbuildSources verbosity specVer tmpDir bm =- case bm of- GBuildExe exe -> exeSources exe- GReplExe _ exe -> exeSources exe- GBuildFLib flib -> return $ flibSources flib- GReplFLib _ flib -> return $ flibSources flib- where- exeSources :: Executable -> IO BuildSources- exeSources exe@Executable{buildInfo = bnfo, modulePath = modPath} = do- main <- findFileEx verbosity (tmpDir : hsSourceDirs bnfo) modPath- let mainModName = fromMaybe ModuleName.main $ exeMainModuleName exe- otherModNames = exeModules exe-- if isHaskell main- then- if specVer < CabalSpecV2_0 && (mainModName `elem` otherModNames)- then do- -- The cabal manual clearly states that `other-modules` is- -- intended for non-main modules. However, there's at least one- -- important package on Hackage (happy-1.19.5) which- -- violates this. We workaround this here so that we don't- -- invoke GHC with e.g. 'ghc --make Main src/Main.hs' which- -- would result in GHC complaining about duplicate Main- -- modules.- --- -- Finally, we only enable this workaround for- -- specVersion < 2, as 'cabal-version:>=2.0' cabal files- -- have no excuse anymore to keep doing it wrong... ;-)- warn verbosity $ "Enabling workaround for Main module '"- ++ prettyShow mainModName- ++ "' listed in 'other-modules' illegally!"-- return BuildSources {- cSourcesFiles = cSources bnfo,- cxxSourceFiles = cxxSources bnfo,- inputSourceFiles = [main],- inputSourceModules = filter (/= mainModName) $ exeModules exe- }-- else return BuildSources {- cSourcesFiles = cSources bnfo,- cxxSourceFiles = cxxSources bnfo,- inputSourceFiles = [main],- inputSourceModules = exeModules exe- }- else let (csf, cxxsf)- | isCxx main = ( cSources bnfo, main : cxxSources bnfo)- -- if main is not a Haskell source- -- and main is not a C++ source- -- then we assume that it is a C source- | otherwise = (main : cSources bnfo, cxxSources bnfo)-- in return BuildSources {- cSourcesFiles = csf,- cxxSourceFiles = cxxsf,- inputSourceFiles = [],- inputSourceModules = exeModules exe- }-- flibSources :: ForeignLib -> BuildSources- flibSources flib@ForeignLib{foreignLibBuildInfo = bnfo} =- BuildSources {- cSourcesFiles = cSources bnfo,- cxxSourceFiles = cxxSources bnfo,- inputSourceFiles = [],- inputSourceModules = foreignLibModules flib- }-- isHaskell :: FilePath -> Bool- isHaskell fp = elem (takeExtension fp) [".hs", ".lhs"]-- isCxx :: FilePath -> Bool- isCxx fp = elem (takeExtension fp) [".cpp", ".cxx", ".c++"]---- | Generic build function. See comment for 'GBuildMode'.-gbuild :: Verbosity -> Cabal.Flag (Maybe Int)- -> PackageDescription -> LocalBuildInfo- -> GBuildMode -> ComponentLocalBuildInfo -> IO ()-gbuild verbosity numJobs pkg_descr lbi bm clbi = do- (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)- let replFlags = case bm of- GReplExe flags _ -> flags- GReplFLib flags _ -> flags- GBuildExe{} -> mempty- GBuildFLib{} -> mempty- comp = compiler lbi- platform = hostPlatform lbi- implInfo = getImplInfo comp- runGhcProg = runGHC verbosity ghcjsProg comp platform-- let (bnfo, threaded) = case bm of- GBuildFLib _ -> popThreadedFlag (gbuildInfo bm)- _ -> (gbuildInfo bm, False)-- -- the name that GHC really uses (e.g., with .exe on Windows for executables)- let targetName = gbuildTargetName lbi bm- let targetDir = buildDir lbi </> (gbuildName bm)- let tmpDir = targetDir </> (gbuildName bm ++ "-tmp")- createDirectoryIfMissingVerbose verbosity True targetDir- createDirectoryIfMissingVerbose verbosity True tmpDir-- -- TODO: do we need to put hs-boot files into place for mutually recursive- -- modules? FIX: what about exeName.hi-boot?-- -- Determine if program coverage should be enabled and if so, what- -- '-hpcdir' should be.- let isCoverageEnabled = exeCoverage lbi- distPref = fromFlag $ configDistPref $ configFlags lbi- hpcdir way- | gbuildIsRepl bm = mempty -- HPC is not supported in ghci- | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way (gbuildName bm)- | otherwise = mempty-- rpaths <- getRPaths lbi clbi- buildSources <- gbuildSources verbosity (specVersion pkg_descr) tmpDir bm-- let cSrcs = cSourcesFiles buildSources- cxxSrcs = cxxSourceFiles buildSources- inputFiles = inputSourceFiles buildSources- inputModules = inputSourceModules buildSources- isGhcDynamic = isDynamic comp- dynamicTooSupported = supportsDynamicToo comp- cObjs = map (`replaceExtension` objExtension) cSrcs- cxxObjs = map (`replaceExtension` objExtension) cxxSrcs- needDynamic = gbuildNeedDynamic lbi bm- needProfiling = withProfExe lbi-- -- build executables- baseOpts = (componentGhcOptions verbosity lbi bnfo clbi tmpDir)- `mappend` mempty {- ghcOptMode = toFlag GhcModeMake,- ghcOptInputFiles = toNubListR inputFiles,- ghcOptInputModules = toNubListR inputModules- }- staticOpts = baseOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcStaticOnly,- ghcOptHPCDir = hpcdir Hpc.Vanilla- }- profOpts = baseOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptProfilingAuto = Internal.profDetailLevelFlag False- (withProfExeDetail lbi),- ghcOptHiSuffix = toFlag "p_hi",- ghcOptObjSuffix = toFlag "p_o",- ghcOptExtra = hcProfOptions GHC bnfo,- ghcOptHPCDir = hpcdir Hpc.Prof- }- dynOpts = baseOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- -- TODO: Does it hurt to set -fPIC for executables?- ghcOptFPic = toFlag True,- ghcOptHiSuffix = toFlag "dyn_hi",- ghcOptObjSuffix = toFlag "dyn_o",- ghcOptExtra = hcSharedOptions GHC bnfo,- ghcOptHPCDir = hpcdir Hpc.Dyn- }- dynTooOpts = staticOpts `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,- ghcOptDynHiSuffix = toFlag "dyn_hi",- ghcOptDynObjSuffix = toFlag "dyn_o",- ghcOptHPCDir = hpcdir Hpc.Dyn- }- linkerOpts = mempty {- ghcOptLinkOptions = PD.ldOptions bnfo,- ghcOptLinkLibs = extraLibs bnfo,- ghcOptLinkLibPath = toNubListR $ extraLibDirs bnfo,- ghcOptLinkFrameworks = toNubListR $- PD.frameworks bnfo,- ghcOptLinkFrameworkDirs = toNubListR $- PD.extraFrameworkDirs bnfo,- ghcOptInputFiles = toNubListR- [tmpDir </> x | x <- cObjs ++ cxxObjs]- }- dynLinkerOpts = mempty {- ghcOptRPaths = rpaths- }- replOpts = baseOpts {- ghcOptExtra = Internal.filterGhciFlags- (ghcOptExtra baseOpts)- <> replFlags- }- -- For a normal compile we do separate invocations of ghc for- -- compiling as for linking. But for repl we have to do just- -- the one invocation, so that one has to include all the- -- linker stuff too, like -l flags and any .o files from C- -- files etc.- `mappend` linkerOpts- `mappend` mempty {- ghcOptMode = toFlag GhcModeInteractive,- ghcOptOptimisation = toFlag GhcNoOptimisation- }- commonOpts | needProfiling = profOpts- | needDynamic = dynOpts- | otherwise = staticOpts- compileOpts | useDynToo = dynTooOpts- | otherwise = commonOpts- withStaticExe = not needProfiling && not needDynamic-- -- For building exe's that use TH with -prof or -dynamic we actually have- -- to build twice, once without -prof/-dynamic and then again with- -- -prof/-dynamic. This is because the code that TH needs to run at- -- compile time needs to be the vanilla ABI so it can be loaded up and run- -- by the compiler.- -- With dynamic-by-default GHC the TH object files loaded at compile-time- -- need to be .dyn_o instead of .o.- doingTH = usesTemplateHaskellOrQQ bnfo- -- Should we use -dynamic-too instead of compiling twice?- useDynToo = dynamicTooSupported && isGhcDynamic- && doingTH && withStaticExe- && null (hcSharedOptions GHC bnfo)- compileTHOpts | isGhcDynamic = dynOpts- | otherwise = staticOpts- compileForTH- | gbuildIsRepl bm = False- | useDynToo = False- | isGhcDynamic = doingTH && (needProfiling || withStaticExe)- | otherwise = doingTH && (needProfiling || needDynamic)-- -- Build static/dynamic object files for TH, if needed.- when compileForTH $- runGhcProg compileTHOpts { ghcOptNoLink = toFlag True- , ghcOptNumJobs = numJobs }-- -- Do not try to build anything if there are no input files.- -- This can happen if the cabal file ends up with only cSrcs- -- but no Haskell modules.- unless ((null inputFiles && null inputModules)- || gbuildIsRepl bm) $- runGhcProg compileOpts { ghcOptNoLink = toFlag True- , ghcOptNumJobs = numJobs }-- -- build any C++ sources- unless (null cxxSrcs) $ do- info verbosity "Building C++ Sources..."- sequence_- [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo- lbi bnfo clbi tmpDir filename- vanillaCxxOpts = if isGhcDynamic- -- Dynamic GHC requires C++ sources to be built- -- with -fPIC for REPL to work. See #2207.- then baseCxxOpts { ghcOptFPic = toFlag True }- else baseCxxOpts- profCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True- }- sharedCxxOpts = vanillaCxxOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly- }- opts | needProfiling = profCxxOpts- | needDynamic = sharedCxxOpts- | otherwise = vanillaCxxOpts- -- TODO: Placing all Haskell, C, & C++ objects in a single directory- -- Has the potential for file collisions. In general we would- -- consider this a user error. However, we should strive to- -- add a warning if this occurs.- odir = fromFlag (ghcOptObjDir opts)- createDirectoryIfMissingVerbose verbosity True odir- needsRecomp <- checkNeedsRecompilation filename opts- when needsRecomp $- runGhcProg opts- | filename <- cxxSrcs ]-- -- build any C sources- unless (null cSrcs) $ do- info verbosity "Building C Sources..."- sequence_- [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo- lbi bnfo clbi tmpDir filename- vanillaCcOpts = if isGhcDynamic- -- Dynamic GHC requires C sources to be built- -- with -fPIC for REPL to work. See #2207.- then baseCcOpts { ghcOptFPic = toFlag True }- else baseCcOpts- profCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptProfilingMode = toFlag True- }- sharedCcOpts = vanillaCcOpts `mappend` mempty {- ghcOptFPic = toFlag True,- ghcOptDynLinkMode = toFlag GhcDynamicOnly- }- opts | needProfiling = profCcOpts- | needDynamic = sharedCcOpts- | otherwise = vanillaCcOpts- odir = fromFlag (ghcOptObjDir opts)- createDirectoryIfMissingVerbose verbosity True odir- needsRecomp <- checkNeedsRecompilation filename opts- when needsRecomp $- runGhcProg opts- | filename <- cSrcs ]-- -- TODO: problem here is we need the .c files built first, so we can load them- -- with ghci, but .c files can depend on .h files generated by ghc by ffi- -- exports.- case bm of- GReplExe _ _ -> runGhcProg replOpts- GReplFLib _ _ -> runGhcProg replOpts- GBuildExe _ -> do- let linkOpts = commonOpts- `mappend` linkerOpts- `mappend` mempty {- ghcOptLinkNoHsMain = toFlag (null inputFiles)- }- `mappend` (if withDynExe lbi then dynLinkerOpts else mempty)-- info verbosity "Linking..."- -- Work around old GHCs not relinking in this- -- situation, see #3294- let target = targetDir </> targetName- when (compilerVersion comp < mkVersion [7,7]) $ do- e <- doesFileExist target- when e (removeFile target)- runGhcProg linkOpts { ghcOptOutputFile = toFlag target }- GBuildFLib flib -> do- let rtsInfo = extractRtsInfo lbi- rtsOptLinkLibs = [- if needDynamic- then if threaded- then dynRtsThreadedLib (rtsDynamicInfo rtsInfo)- else dynRtsVanillaLib (rtsDynamicInfo rtsInfo)- else if threaded- then statRtsThreadedLib (rtsStaticInfo rtsInfo)- else statRtsVanillaLib (rtsStaticInfo rtsInfo)- ]- linkOpts = case foreignLibType flib of- ForeignLibNativeShared ->- commonOpts- `mappend` linkerOpts- `mappend` dynLinkerOpts- `mappend` mempty {- ghcOptLinkNoHsMain = toFlag True,- ghcOptShared = toFlag True,- ghcOptLinkLibs = rtsOptLinkLibs,- ghcOptLinkLibPath = toNubListR $ rtsLibPaths rtsInfo,- ghcOptFPic = toFlag True,- ghcOptLinkModDefFiles = toNubListR $ gbuildModDefFiles bm- }- -- See Note [RPATH]- `mappend` ifNeedsRPathWorkaround lbi mempty {- ghcOptLinkOptions = ["-Wl,--no-as-needed"]- , ghcOptLinkLibs = ["ffi"]- }- ForeignLibNativeStatic ->- -- this should be caught by buildFLib- -- (and if we do implement this, we probably don't even want to call- -- ghc here, but rather Ar.createArLibArchive or something)- cabalBug "static libraries not yet implemented"- ForeignLibTypeUnknown ->- cabalBug "unknown foreign lib type"- -- We build under a (potentially) different filename to set a- -- soname on supported platforms. See also the note for- -- @flibBuildName@.- info verbosity "Linking..."- let buildName = flibBuildName lbi flib- runGhcProg linkOpts { ghcOptOutputFile = toFlag (targetDir </> buildName) }- renameFile (targetDir </> buildName) (targetDir </> targetName)--{--Note [RPATH]-~~~~~~~~~~~~--Suppose that the dynamic library depends on `base`, but not (directly) on-`integer-gmp` (which, however, is a dependency of `base`). We will link the-library as-- gcc ... -lHSbase-4.7.0.2-ghc7.8.4 -lHSinteger-gmp-0.5.1.0-ghc7.8.4 ...--However, on systems (like Ubuntu) where the linker gets called with `-as-needed`-by default, the linker will notice that `integer-gmp` isn't actually a direct-dependency and hence omit the link.--Then when we attempt to link a C program against this dynamic library, the-_static_ linker will attempt to verify that all symbols can be resolved. The-dynamic library itself does not require any symbols from `integer-gmp`, but-`base` does. In order to verify that the symbols used by `base` can be-resolved, the static linker needs to be able to _find_ integer-gmp.--Finding the `base` dependency is simple, because the dynamic elf header-(`readelf -d`) for the library that we have created looks something like-- (NEEDED) Shared library: [libHSbase-4.7.0.2-ghc7.8.4.so]- (RPATH) Library rpath: [/path/to/base-4.7.0.2:...]--However, when it comes to resolving the dependency on `integer-gmp`, it needs-to look at the dynamic header for `base`. On modern ghc (7.8 and higher) this-looks something like-- (NEEDED) Shared library: [libHSinteger-gmp-0.5.1.0-ghc7.8.4.so]- (RPATH) Library rpath: [$ORIGIN/../integer-gmp-0.5.1.0:...]--This specifies the location of `integer-gmp` _in terms of_ the location of base-(using the `$ORIGIN`) variable. But here's the crux: when the static linker-attempts to verify that all symbols can be resolved, [**IT DOES NOT RESOLVE-`$ORIGIN`**](http://stackoverflow.com/questions/6323603/ld-using-rpath-origin-inside-a-shared-library-recursive).-As a consequence, it will not be able to resolve the symbols and report the-missing symbols as errors, _even though the dynamic linker **would** be able to-resolve these symbols_. We can tell the static linker not to report these-errors by using `--unresolved-symbols=ignore-all` and all will be fine when we-run the program ([(indeed, this is what the gold linker-does)](https://sourceware.org/ml/binutils/2013-05/msg00038.html), but it makes-the resulting library more difficult to use.--Instead what we can do is make sure that the generated dynamic library has-explicit top-level dependencies on these libraries. This means that the static-linker knows where to find them, and when we have transitive dependencies on-the same libraries the linker will only load them once, so we avoid needing to-look at the `RPATH` of our dependencies. We can do this by passing-`--no-as-needed` to the linker, so that it doesn't omit any libraries.--Note that on older ghc (7.6 and before) the Haskell libraries don't have an-RPATH set at all, which makes it even more important that we make these-top-level dependencies.--Finally, we have to explicitly link against `libffi` for the same reason. For-newer ghc this _happens_ to be unnecessary on many systems because `libffi` is-a library which is not specific to GHC, and when the static linker verifies-that all symbols can be resolved it will find the `libffi` that is globally-installed (completely independent from ghc). Of course, this may well be the-_wrong_ version of `libffi`, but it's quite possible that symbol resolution-happens to work. This is of course the wrong approach, which is why we link-explicitly against `libffi` so that we will find the _right_ version of-`libffi`.--}---- | Do we need the RPATH workaround?------ See Note [RPATH].-ifNeedsRPathWorkaround :: Monoid a => LocalBuildInfo -> a -> a-ifNeedsRPathWorkaround lbi a =- case hostPlatform lbi of- Platform _ Linux -> a- _otherwise -> mempty--data DynamicRtsInfo = DynamicRtsInfo {- dynRtsVanillaLib :: FilePath- , dynRtsThreadedLib :: FilePath- , dynRtsDebugLib :: FilePath- , dynRtsEventlogLib :: FilePath- , dynRtsThreadedDebugLib :: FilePath- , dynRtsThreadedEventlogLib :: FilePath- }--data StaticRtsInfo = StaticRtsInfo {- statRtsVanillaLib :: FilePath- , statRtsThreadedLib :: FilePath- , statRtsDebugLib :: FilePath- , statRtsEventlogLib :: FilePath- , statRtsThreadedDebugLib :: FilePath- , statRtsThreadedEventlogLib :: FilePath- , statRtsProfilingLib :: FilePath- , statRtsThreadedProfilingLib :: FilePath- }--data RtsInfo = RtsInfo {- rtsDynamicInfo :: DynamicRtsInfo- , rtsStaticInfo :: StaticRtsInfo- , rtsLibPaths :: [FilePath]- }---- | Extract (and compute) information about the RTS library------ TODO: This hardcodes the name as @HSrts-ghc<version>@. I don't know if we can--- find this information somewhere. We can lookup the 'hsLibraries' field of--- 'InstalledPackageInfo' but it will tell us @["HSrts", "Cffi"]@, which--- doesn't really help.-extractRtsInfo :: LocalBuildInfo -> RtsInfo-extractRtsInfo lbi =- case PackageIndex.lookupPackageName (installedPkgs lbi) (mkPackageName "rts") of- [(_, [rts])] -> aux rts- _otherwise -> error "No (or multiple) ghc rts package is registered"- where- aux :: InstalledPackageInfo -> RtsInfo- aux rts = RtsInfo {- rtsDynamicInfo = DynamicRtsInfo {- dynRtsVanillaLib = withGhcVersion "HSrts"- , dynRtsThreadedLib = withGhcVersion "HSrts_thr"- , dynRtsDebugLib = withGhcVersion "HSrts_debug"- , dynRtsEventlogLib = withGhcVersion "HSrts_l"- , dynRtsThreadedDebugLib = withGhcVersion "HSrts_thr_debug"- , dynRtsThreadedEventlogLib = withGhcVersion "HSrts_thr_l"- }- , rtsStaticInfo = StaticRtsInfo {- statRtsVanillaLib = "HSrts"- , statRtsThreadedLib = "HSrts_thr"- , statRtsDebugLib = "HSrts_debug"- , statRtsEventlogLib = "HSrts_l"- , statRtsThreadedDebugLib = "HSrts_thr_debug"- , statRtsThreadedEventlogLib = "HSrts_thr_l"- , statRtsProfilingLib = "HSrts_p"- , statRtsThreadedProfilingLib = "HSrts_thr_p"- }- , rtsLibPaths = InstalledPackageInfo.libraryDirs rts- }- withGhcVersion = (++ ("-ghc" ++ prettyShow (compilerVersion (compiler lbi))))---- | Returns True if the modification date of the given source file is newer than--- the object file we last compiled for it, or if no object file exists yet.-checkNeedsRecompilation :: FilePath -> GhcOptions -> IO Bool-checkNeedsRecompilation filename opts = filename `moreRecentFile` oname- where oname = getObjectFileName filename opts---- | Finds the object file name of the given source file-getObjectFileName :: FilePath -> GhcOptions -> FilePath-getObjectFileName filename opts = oname- where odir = fromFlag (ghcOptObjDir opts)- oext = fromFlagOrDefault "o" (ghcOptObjSuffix opts)- oname = odir </> replaceExtension filename oext---- | Calculate the RPATHs for the component we are building.------ Calculates relative RPATHs when 'relocatable' is set.-getRPaths :: LocalBuildInfo- -> ComponentLocalBuildInfo -- ^ Component we are building- -> IO (NubListR FilePath)-getRPaths lbi clbi | supportRPaths hostOS = do- libraryPaths <- depLibraryPaths False (relocatable lbi) lbi clbi- let hostPref = case hostOS of- OSX -> "@loader_path"- _ -> "$ORIGIN"- relPath p = if isRelative p then hostPref </> p else p- rpaths = toNubListR (map relPath libraryPaths)- return rpaths- where- (Platform _ hostOS) = hostPlatform lbi- compid = compilerId . compiler $ lbi-- -- The list of RPath-supported operating systems below reflects the- -- platforms on which Cabal's RPATH handling is tested. It does _NOT_- -- reflect whether the OS supports RPATH.-- -- E.g. when this comment was written, the *BSD operating systems were- -- untested with regards to Cabal RPATH handling, and were hence set to- -- 'False', while those operating systems themselves do support RPATH.- supportRPaths Linux = True- supportRPaths Windows = False- supportRPaths OSX = True- supportRPaths FreeBSD =- case compid of- CompilerId GHC ver | ver >= mkVersion [7,10,2] -> True- _ -> False- supportRPaths OpenBSD = False- supportRPaths NetBSD = False- supportRPaths DragonFly = False- supportRPaths Solaris = False- supportRPaths AIX = False- supportRPaths HPUX = False- 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.--getRPaths _ _ = return mempty---- | Remove the "-threaded" flag when building a foreign library, as it has no--- effect when used with "-shared". Returns the updated 'BuildInfo', along--- with whether or not the flag was present, so we can use it to link against--- the appropriate RTS on our own.-popThreadedFlag :: BuildInfo -> (BuildInfo, Bool)-popThreadedFlag bi =- ( bi { options = filterHcOptions (/= "-threaded") (options bi) }- , hasThreaded (options bi))-- where- filterHcOptions :: (String -> Bool)- -> PerCompilerFlavor [String]- -> PerCompilerFlavor [String]- filterHcOptions p (PerCompilerFlavor ghc ghcjs) =- PerCompilerFlavor (filter p ghc) ghcjs-- hasThreaded :: PerCompilerFlavor [String] -> Bool- hasThreaded (PerCompilerFlavor ghc _) = elem "-threaded" ghc---- | Extracts a String representing a hash of the ABI of a built--- library. It can fail if the library has not yet been built.----libAbiHash :: Verbosity -> PackageDescription -> LocalBuildInfo- -> Library -> ComponentLocalBuildInfo -> IO String-libAbiHash verbosity _pkg_descr lbi lib clbi = do- let- libBi = libBuildInfo lib- comp = compiler lbi- platform = hostPlatform lbi- vanillaArgs0 =- (componentGhcOptions verbosity lbi libBi clbi (componentBuildDir lbi clbi))- `mappend` mempty {- ghcOptMode = toFlag GhcModeAbiHash,- ghcOptInputModules = toNubListR $ exposedModules lib- }- vanillaArgs =- -- Package DBs unnecessary, and break ghc-cabal. See #3633- -- BUT, put at least the global database so that 7.4 doesn't- -- break.- vanillaArgs0 { ghcOptPackageDBs = [GlobalPackageDB]- , ghcOptPackages = mempty }- sharedArgs = vanillaArgs `mappend` mempty {- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptFPic = toFlag True,- ghcOptHiSuffix = toFlag "js_dyn_hi",- ghcOptObjSuffix = toFlag "js_dyn_o",- ghcOptExtra = hcSharedOptions GHC libBi- }- profArgs = vanillaArgs `mappend` mempty {- ghcOptProfilingMode = toFlag True,- ghcOptProfilingAuto = Internal.profDetailLevelFlag True- (withProfLibDetail lbi),- ghcOptHiSuffix = toFlag "js_p_hi",- ghcOptObjSuffix = toFlag "js_p_o",- ghcOptExtra = hcProfOptions GHC libBi- }- ghcArgs- | withVanillaLib lbi = vanillaArgs- | withSharedLib lbi = sharedArgs- | withProfLib lbi = profArgs- | otherwise = error "libAbiHash: Can't find an enabled library way"-- (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)- hash <- getProgramInvocationOutput verbosity- (ghcInvocation ghcjsProg comp platform ghcArgs)- return (takeWhile (not . isSpace) hash)--componentGhcOptions :: Verbosity -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo -> FilePath- -> GhcOptions-componentGhcOptions verbosity lbi bi clbi odir =- let opts = Internal.componentGhcOptions verbosity implInfo lbi bi clbi odir- comp = compiler lbi- implInfo = getImplInfo comp- in opts { ghcOptExtra = ghcOptExtra opts `mappend` hcOptions GHCJS bi- }---componentCcGhcOptions :: Verbosity -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo- -> FilePath -> FilePath- -> GhcOptions-componentCcGhcOptions verbosity lbi =- Internal.componentCcGhcOptions verbosity implInfo lbi- where- comp = compiler lbi- implInfo = getImplInfo comp----- -------------------------------------------------------------------------------- Installing---- |Install executables for GHCJS.-installExe :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^Where to copy the files to- -> FilePath -- ^Build location- -> (FilePath, FilePath) -- ^Executable (prefix,suffix)- -> PackageDescription- -> Executable- -> IO ()-installExe verbosity lbi binDir buildPref- (progprefix, progsuffix) _pkg exe = do- createDirectoryIfMissingVerbose verbosity True binDir- let exeName' = unUnqualComponentName $ exeName exe- exeFileName = exeName'- fixedExeBaseName = progprefix ++ exeName' ++ progsuffix- installBinary dest = do- runDbProgram verbosity ghcjsProgram (withPrograms lbi) $- [ "--install-executable"- , buildPref </> exeName' </> exeFileName- , "-o", dest- ] ++- case (stripExes lbi, lookupProgram stripProgram $ withPrograms lbi) of- (True, Just strip) -> ["-strip-program", programPath strip]- _ -> []- installBinary (binDir </> fixedExeBaseName)----- |Install foreign library for GHC.-installFLib :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^install location- -> FilePath -- ^Build location- -> PackageDescription- -> ForeignLib- -> IO ()-installFLib verbosity lbi targetDir builtDir _pkg flib =- install (foreignLibIsShared flib)- builtDir- targetDir- (flibTargetName lbi flib)- where- install _isShared srcDir dstDir name = do- let src = srcDir </> name- dst = dstDir </> name- createDirectoryIfMissingVerbose verbosity True targetDir- installOrdinaryFile verbosity src dst----- |Install for ghc, .hi, .a and, if --with-ghci given, .o-installLib :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^install location- -> FilePath -- ^install location for dynamic libraries- -> FilePath -- ^Build location- -> PackageDescription- -> Library- -> ComponentLocalBuildInfo- -> IO ()-installLib verbosity lbi targetDir dynlibTargetDir _builtDir _pkg lib clbi = do- whenVanilla $ copyModuleFiles "js_hi"- whenProf $ copyModuleFiles "js_p_hi"- whenShared $ copyModuleFiles "js_dyn_hi"-- -- whenVanilla $ installOrdinary builtDir targetDir $ toJSLibName vanillaLibName- -- whenProf $ installOrdinary builtDir targetDir $ toJSLibName profileLibName- -- whenShared $ installShared builtDir dynlibTargetDir $ toJSLibName sharedLibName- -- fixme do these make the correct lib names?- whenHasCode $ do- whenVanilla $ do- sequence_ [ installOrdinary builtDir' targetDir (toJSLibName $ mkGenericStaticLibName (l ++ f))- | l <- getHSLibraryName (componentUnitId clbi):(extraBundledLibs (libBuildInfo lib))- , f <- "":extraLibFlavours (libBuildInfo lib)- ]- -- whenGHCi $ installOrdinary builtDir targetDir (toJSLibName ghciLibName)- whenProf $ do- installOrdinary builtDir' targetDir (toJSLibName profileLibName)- -- whenGHCi $ installOrdinary builtDir targetDir (toJSLibName ghciProfLibName)- whenShared $- sequence_ [ installShared builtDir' dynlibTargetDir- (toJSLibName $ mkGenericSharedLibName platform compiler_id (l ++ f))- | l <- getHSLibraryName uid : extraBundledLibs (libBuildInfo lib)- , f <- "":extraDynLibFlavours (libBuildInfo lib)- ]- where- builtDir' = componentBuildDir lbi clbi-- install isShared isJS srcDir dstDir name = do- let src = srcDir </> name- dst = dstDir </> name- createDirectoryIfMissingVerbose verbosity True dstDir-- if isShared- then installExecutableFile verbosity src dst- else installOrdinaryFile verbosity src dst-- when (stripLibs lbi && not isJS) $- Strip.stripLib verbosity- (hostPlatform lbi) (withPrograms lbi) dst-- installOrdinary = install False True- installShared = install True True-- copyModuleFiles ext =- findModuleFilesEx verbosity [builtDir'] [ext] (allLibModules lib clbi)- >>= installOrdinaryFiles verbosity targetDir-- compiler_id = compilerId (compiler lbi)- platform = hostPlatform lbi- uid = componentUnitId clbi- -- vanillaLibName = mkLibName uid- profileLibName = mkProfLibName uid- -- sharedLibName = (mkSharedLibName (hostPlatform lbi) compiler_id) uid-- hasLib = not $ null (allLibModules lib clbi)- && null (cSources (libBuildInfo lib))- && null (cxxSources (libBuildInfo lib))- && null (jsSources (libBuildInfo lib))- has_code = not (componentIsIndefinite clbi)- whenHasCode = when has_code- whenVanilla = when (hasLib && withVanillaLib lbi)- whenProf = when (hasLib && withProfLib lbi && has_code)- -- whenGHCi = when (hasLib && withGHCiLib lbi && has_code)- whenShared = when (hasLib && withSharedLib lbi && has_code)---adjustExts :: String -> String -> GhcOptions -> GhcOptions-adjustExts hiSuf objSuf opts =- opts `mappend` mempty {- ghcOptHiSuffix = toFlag hiSuf,- ghcOptObjSuffix = toFlag objSuf- }--isDynamic :: Compiler -> Bool-isDynamic = Internal.ghcLookupProperty "GHC Dynamic"--supportsDynamicToo :: Compiler -> Bool-supportsDynamicToo = Internal.ghcLookupProperty "Support dynamic-too"--withExt :: FilePath -> String -> FilePath-withExt fp ext = fp <.> if takeExtension fp /= ('.':ext) then ext else ""--findGhcjsGhcVersion :: Verbosity -> FilePath -> IO (Maybe Version)-findGhcjsGhcVersion verbosity pgm =- findProgramVersion "--numeric-ghc-version" id verbosity pgm--findGhcjsPkgGhcjsVersion :: Verbosity -> FilePath -> IO (Maybe Version)-findGhcjsPkgGhcjsVersion verbosity pgm =- findProgramVersion "--numeric-ghcjs-version" id verbosity pgm---- -------------------------------------------------------------------------------- Registering--hcPkgInfo :: ProgramDb -> HcPkg.HcPkgInfo-hcPkgInfo progdb = HcPkg.HcPkgInfo { HcPkg.hcPkgProgram = ghcjsPkgProg- , HcPkg.noPkgDbStack = False- , HcPkg.noVerboseFlag = False- , HcPkg.flagPackageConf = False- , HcPkg.supportsDirDbs = True- , HcPkg.requiresDirDbs = ver >= v7_10- , HcPkg.nativeMultiInstance = ver >= v7_10- , HcPkg.recacheMultiInstance = True- , HcPkg.suppressFilesCheck = True- }- where- v7_10 = mkVersion [7,10]- ghcjsPkgProg = fromMaybe (error "GHCJS.hcPkgInfo no ghcjs program") $ lookupProgram ghcjsPkgProgram progdb- ver = fromMaybe (error "GHCJS.hcPkgInfo no ghcjs version") $ programVersion ghcjsPkgProg--registerPackage- :: Verbosity- -> ProgramDb- -> PackageDBStack- -> InstalledPackageInfo- -> HcPkg.RegisterOptions- -> IO ()-registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions =- HcPkg.register (hcPkgInfo progdb) verbosity packageDbs- installedPkgInfo registerOptions--pkgRoot :: Verbosity -> LocalBuildInfo -> PackageDB -> IO FilePath-pkgRoot verbosity lbi = pkgRoot'- where- pkgRoot' GlobalPackageDB =- let ghcjsProg = fromMaybe (error "GHCJS.pkgRoot: no ghcjs program") $ lookupProgram ghcjsProgram (withPrograms lbi)- in fmap takeDirectory (getGlobalPackageDB verbosity ghcjsProg)- pkgRoot' UserPackageDB = do- appDir <- getAppUserDataDirectory "ghcjs"- -- fixme correct this version- let ver = compilerVersion (compiler lbi)- subdir = System.Info.arch ++ '-':System.Info.os- ++ '-':prettyShow 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- -- directory at the time of 'ghc-pkg register', and registration will- -- fail.- createDirectoryIfMissing True rootDir- return rootDir- pkgRoot' (SpecificPackageDB fp) = return (takeDirectory fp)----- | Get the JavaScript file name and command and arguments to run a--- program compiled by GHCJS--- the exe should be the base program name without exe extension-runCmd :: ProgramDb -> FilePath- -> (FilePath, FilePath, [String])-runCmd progdb exe =- ( script- , programPath ghcjsProg- , programDefaultArgs ghcjsProg ++ programOverrideArgs ghcjsProg ++ ["--run"]- )- where- script = exe <.> "jsexe" </> "all" <.> "js"- ghcjsProg = fromMaybe (error "GHCJS.runCmd: no ghcjs program") $ lookupProgram ghcjsProgram progdb
− Distribution/Simple/Glob.hs
@@ -1,306 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Glob--- Copyright : Isaac Jones, Simon Marlow 2003-2004--- License : BSD3--- portions Copyright (c) 2007, Galois Inc.------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Simple file globbing.--module Distribution.Simple.Glob (- GlobSyntaxError(..),- GlobResult(..),- matchDirFileGlob,- runDirFileGlob,- fileGlobMatches,- parseFileGlob,- explainGlobSyntaxError,- Glob,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.CabalSpecVersion-import Distribution.Simple.Utils-import Distribution.Verbosity--import System.Directory (getDirectoryContents, doesDirectoryExist, doesFileExist)-import System.FilePath (joinPath, splitExtensions, splitDirectories, takeFileName, (</>), (<.>))--import qualified Data.List.NonEmpty as NE---- Note throughout that we use splitDirectories, not splitPath. On--- Posix, this makes no difference, but, because Windows accepts both--- slash and backslash as its path separators, if we left in the--- separators from the glob we might not end up properly normalised.--data GlobResult a- = GlobMatch a- -- ^ The glob matched the value supplied.- | GlobWarnMultiDot a- -- ^ The glob did not match the value supplied because the- -- cabal-version is too low and the extensions on the file did- -- not precisely match the glob's extensions, but rather the- -- glob was a proper suffix of the file's extensions; i.e., if- -- not for the low cabal-version, it would have matched.- | GlobMissingDirectory FilePath- -- ^ The glob couldn't match because the directory named doesn't- -- exist. The directory will be as it appears in the glob (i.e.,- -- relative to the directory passed to 'matchDirFileGlob', and,- -- for 'data-files', relative to 'data-dir').- deriving (Show, Eq, Ord, Functor)---- | Extract the matches from a list of 'GlobResult's.------ Note: throws away the 'GlobMissingDirectory' results; chances are--- that you want to check for these and error out if any are present.-globMatches :: [GlobResult a] -> [a]-globMatches input = [ a | GlobMatch a <- input ]--data GlobSyntaxError- = StarInDirectory- | StarInFileName- | StarInExtension- | NoExtensionOnStar- | EmptyGlob- | LiteralFileNameGlobStar- | VersionDoesNotSupportGlobStar- | VersionDoesNotSupportGlob- deriving (Eq, Show)--explainGlobSyntaxError :: FilePath -> GlobSyntaxError -> String-explainGlobSyntaxError filepath StarInDirectory =- "invalid file glob '" ++ filepath- ++ "'. A wildcard '**' is only allowed as the final parent"- ++ " directory. Stars must not otherwise appear in the parent"- ++ " directories."-explainGlobSyntaxError filepath StarInExtension =- "invalid file glob '" ++ filepath- ++ "'. Wildcards '*' are only allowed as the"- ++ " file's base name, not in the file extension."-explainGlobSyntaxError filepath StarInFileName =- "invalid file glob '" ++ filepath- ++ "'. Wildcards '*' may only totally replace the"- ++ " file's base name, not only parts of it."-explainGlobSyntaxError filepath NoExtensionOnStar =- "invalid file glob '" ++ filepath- ++ "'. If a wildcard '*' is used it must be with an file extension."-explainGlobSyntaxError filepath LiteralFileNameGlobStar =- "invalid file glob '" ++ filepath- ++ "'. If a wildcard '**' is used as a parent directory, the"- ++ " file's base name must be a wildcard '*'."-explainGlobSyntaxError _ EmptyGlob =- "invalid file glob. A glob cannot be the empty string."-explainGlobSyntaxError filepath VersionDoesNotSupportGlobStar =- "invalid file glob '" ++ filepath- ++ "'. Using the double-star syntax requires 'cabal-version: 2.4'"- ++ " or greater. Alternatively, for compatibility with earlier Cabal"- ++ " versions, list the included directories explicitly."-explainGlobSyntaxError filepath VersionDoesNotSupportGlob =- "invalid file glob '" ++ filepath- ++ "'. Using star wildcards requires 'cabal-version: >= 1.6'. "- ++ "Alternatively if you require compatibility with earlier Cabal "- ++ "versions then list all the files explicitly."--data IsRecursive = Recursive | NonRecursive--data MultiDot = MultiDotDisabled | MultiDotEnabled--data Glob- = GlobStem FilePath Glob- -- ^ A single subdirectory component + remainder.- | GlobFinal GlobFinal--data GlobFinal- = FinalMatch IsRecursive MultiDot String- -- ^ First argument: Is this a @**/*.ext@ pattern?- -- Second argument: should we match against the exact extensions, or accept a suffix?- -- Third argument: the extensions to accept.- | FinalLit FilePath- -- ^ Literal file name.--reconstructGlob :: Glob -> FilePath-reconstructGlob (GlobStem dir glob) =- dir </> reconstructGlob glob-reconstructGlob (GlobFinal final) = case final of- FinalMatch Recursive _ exts -> "**" </> "*" <.> exts- FinalMatch NonRecursive _ exts -> "*" <.> exts- FinalLit path -> path---- | Returns 'Nothing' if the glob didn't match at all, or 'Just' the--- result if the glob matched (or would have matched with a higher--- cabal-version).-fileGlobMatches :: Glob -> FilePath -> Maybe (GlobResult FilePath)-fileGlobMatches pat candidate = do- match <- fileGlobMatchesSegments pat (splitDirectories candidate)- return (candidate <$ match)--fileGlobMatchesSegments :: Glob -> [FilePath] -> Maybe (GlobResult ())-fileGlobMatchesSegments _ [] = Nothing-fileGlobMatchesSegments pat (seg : segs) = case pat of- GlobStem dir pat' -> do- guard (dir == seg)- fileGlobMatchesSegments pat' segs- GlobFinal final -> case final of- FinalMatch Recursive multidot ext -> do- let (candidateBase, candidateExts) = splitExtensions (NE.last $ seg:|segs)- guard (not (null candidateBase))- checkExt multidot ext candidateExts- FinalMatch NonRecursive multidot ext -> do- let (candidateBase, candidateExts) = splitExtensions seg- guard (null segs && not (null candidateBase))- checkExt multidot ext candidateExts- FinalLit filename -> do- guard (null segs && filename == seg)- return (GlobMatch ())--checkExt- :: MultiDot- -> String -- ^ The pattern's extension- -> String -- ^ The candidate file's extension- -> Maybe (GlobResult ())-checkExt multidot ext candidate- | ext == candidate = Just (GlobMatch ())- | ext `isSuffixOf` candidate = case multidot of- MultiDotDisabled -> Just (GlobWarnMultiDot ())- MultiDotEnabled -> Just (GlobMatch ())- | otherwise = Nothing--parseFileGlob :: CabalSpecVersion -> FilePath -> Either GlobSyntaxError Glob-parseFileGlob version filepath = case reverse (splitDirectories filepath) of- [] ->- Left EmptyGlob- (filename : "**" : segments)- | allowGlobStar -> do- ext <- case splitExtensions filename of- ("*", ext) | '*' `elem` ext -> Left StarInExtension- | null ext -> Left NoExtensionOnStar- | otherwise -> Right ext- _ -> Left LiteralFileNameGlobStar- foldM addStem (GlobFinal $ FinalMatch Recursive multidot ext) segments- | otherwise -> Left VersionDoesNotSupportGlobStar- (filename : segments) -> do- pat <- case splitExtensions filename of- ("*", ext) | not allowGlob -> Left VersionDoesNotSupportGlob- | '*' `elem` ext -> Left StarInExtension- | null ext -> Left NoExtensionOnStar- | otherwise -> Right (FinalMatch NonRecursive multidot ext)- (_, ext) | '*' `elem` ext -> Left StarInExtension- | '*' `elem` filename -> Left StarInFileName- | otherwise -> Right (FinalLit filename)- foldM addStem (GlobFinal pat) segments- where- allowGlob = version >= CabalSpecV1_6- allowGlobStar = version >= CabalSpecV2_4- addStem pat seg- | '*' `elem` seg = Left StarInDirectory- | otherwise = Right (GlobStem seg pat)- multidot- | version >= CabalSpecV2_4 = MultiDotEnabled- | otherwise = MultiDotDisabled---- | This will 'die'' when the glob matches no files, or if the glob--- refers to a missing directory, or if the glob fails to parse.------ The 'Version' argument must be the spec version of the package--- description being processed, as globs behave slightly differently--- in different spec versions.------ The first 'FilePath' argument is the directory that the glob is--- relative to. It must be a valid directory (and hence it can't be--- the empty string). The returned values will not include this--- prefix.------ The second 'FilePath' is the glob itself.-matchDirFileGlob :: Verbosity -> CabalSpecVersion -> FilePath -> FilePath -> IO [FilePath]-matchDirFileGlob verbosity version dir filepath = case parseFileGlob version filepath of- Left err -> die' verbosity $ explainGlobSyntaxError filepath err- Right glob -> do- results <- runDirFileGlob verbosity dir glob- let missingDirectories =- [ missingDir | GlobMissingDirectory missingDir <- results ]- matches = globMatches results- -- Check for missing directories first, since we'll obviously have- -- no matches in that case.- for_ missingDirectories $ \ missingDir ->- die' verbosity $- "filepath wildcard '" ++ filepath ++ "' refers to the directory"- ++ " '" ++ missingDir ++ "', which does not exist or is not a directory."- when (null matches) $ die' verbosity $- "filepath wildcard '" ++ filepath- ++ "' does not match any files."- return matches---- | Match files against a pre-parsed glob, starting in a directory.------ The 'Version' argument must be the spec version of the package--- description being processed, as globs behave slightly differently--- in different spec versions.------ The 'FilePath' argument is the directory that the glob is relative--- to. It must be a valid directory (and hence it can't be the empty--- string). The returned values will not include this prefix.-runDirFileGlob :: Verbosity -> FilePath -> Glob -> IO [GlobResult FilePath]-runDirFileGlob verbosity rawDir pat = do- -- The default data-dir is null. Our callers -should- be- -- converting that to '.' themselves, but it's a certainty that- -- some future call-site will forget and trigger a really- -- hard-to-debug failure if we don't check for that here.- when (null rawDir) $- warn verbosity $- "Null dir passed to runDirFileGlob; interpreting it "- ++ "as '.'. This is probably an internal error."- let dir = if null rawDir then "." else rawDir- debug verbosity $ "Expanding glob '" ++ reconstructGlob pat ++ "' in directory '" ++ dir ++ "'."- -- This function might be called from the project root with dir as- -- ".". Walking the tree starting there involves going into .git/- -- and dist-newstyle/, which is a lot of work for no reward, so- -- extract the constant prefix from the pattern and start walking- -- there, and only walk as much as we need to: recursively if **,- -- the whole directory if *, and just the specific file if it's a- -- literal.- let (prefixSegments, final) = splitConstantPrefix pat- joinedPrefix = joinPath prefixSegments- case final of- FinalMatch recursive multidot exts -> do- let prefix = dir </> joinedPrefix- directoryExists <- doesDirectoryExist prefix- if directoryExists- then do- candidates <- case recursive of- Recursive -> getDirectoryContentsRecursive prefix- NonRecursive -> filterM (doesFileExist . (prefix </>)) =<< getDirectoryContents prefix- let checkName candidate = do- let (candidateBase, candidateExts) = splitExtensions $ takeFileName candidate- guard (not (null candidateBase))- match <- checkExt multidot exts candidateExts- return (joinedPrefix </> candidate <$ match)- return $ mapMaybe checkName candidates- else- return [ GlobMissingDirectory joinedPrefix ]- FinalLit fn -> do- exists <- doesFileExist (dir </> joinedPrefix </> fn)- return [ GlobMatch (joinedPrefix </> fn) | exists ]--unfoldr' :: (a -> Either r (b, a)) -> a -> ([b], r)-unfoldr' f a = case f a of- Left r -> ([], r)- Right (b, a') -> case unfoldr' f a' of- (bs, r) -> (b : bs, r)---- | Extract the (possibly null) constant prefix from the pattern.--- This has the property that, if @(pref, final) = splitConstantPrefix pat@,--- then @pat === foldr GlobStem (GlobFinal final) pref@.-splitConstantPrefix :: Glob -> ([FilePath], GlobFinal)-splitConstantPrefix = unfoldr' step- where- step (GlobStem seg pat) = Right (seg, pat)- step (GlobFinal pat) = Left pat
− Distribution/Simple/Haddock.hs
@@ -1,926 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Haddock--- Copyright : Isaac Jones 2003-2005--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module deals with the @haddock@ and @hscolour@ commands.--- It uses information about installed packages (from @ghc-pkg@) to find the--- locations of documentation for dependent packages, so it can create links.------ The @hscolour@ support allows generating HTML versions of the original--- source, with coloured syntax highlighting.--module Distribution.Simple.Haddock (- haddock, hscolour,-- haddockPackagePaths- ) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS---- local-import Distribution.Backpack.DescribeUnitId-import Distribution.Backpack (OpenModule)-import Distribution.Types.ForeignLib-import Distribution.Types.UnqualComponentName-import Distribution.Types.ComponentLocalBuildInfo-import Distribution.Types.ExecutableScope-import Distribution.Types.LocalBuildInfo-import Distribution.Types.TargetInfo-import Distribution.Types.ExposedModule-import Distribution.Package-import qualified Distribution.ModuleName as ModuleName-import Distribution.PackageDescription-import Distribution.Simple.Compiler-import Distribution.Simple.Glob-import Distribution.Simple.Program.GHC-import Distribution.Simple.Program.ResponseFile-import Distribution.Simple.Program-import Distribution.Simple.PreProcess-import Distribution.Simple.Setup-import Distribution.Simple.Build-import Distribution.Simple.BuildTarget-import Distribution.Simple.InstallDirs-import Distribution.Simple.LocalBuildInfo hiding (substPathTemplate)-import Distribution.Simple.BuildPaths-import Distribution.Simple.Register-import qualified Distribution.Simple.Program.HcPkg as HcPkg-import qualified Distribution.Simple.PackageIndex as PackageIndex-import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo-import Distribution.InstalledPackageInfo ( InstalledPackageInfo )-import Distribution.Simple.Utils-import Distribution.System-import Distribution.Pretty-import Distribution.Parsec (simpleParsec)-import Distribution.Utils.NubList-import Distribution.Version-import qualified Distribution.Utils.ShortText as ShortText--import Distribution.Verbosity-import Language.Haskell.Extension--import Distribution.Compat.Semigroup (All (..), Any (..))--import Control.Monad-import Data.Either ( rights )--import System.Directory (getCurrentDirectory, doesDirectoryExist, doesFileExist)-import System.FilePath ( (</>), (<.>), normalise, isAbsolute )-import System.IO (hClose, hPutStrLn, hSetEncoding, utf8)---- --------------------------------------------------------------------------------- Types---- | A record that represents the arguments to the haddock executable, a product--- monoid.-data HaddockArgs = HaddockArgs {- argInterfaceFile :: Flag FilePath,- -- ^ Path to the interface file, relative to argOutputDir, required.- argPackageName :: Flag PackageIdentifier,- -- ^ Package name, required.- argHideModules :: (All,[ModuleName.ModuleName]),- -- ^ (Hide modules ?, modules to hide)- argIgnoreExports :: Any,- -- ^ Ignore export lists in modules?- argLinkSource :: Flag (Template,Template,Template),- -- ^ (Template for modules, template for symbols, template for lines).- argLinkedSource :: Flag Bool,- -- ^ Generate hyperlinked sources- argQuickJump :: Flag Bool,- -- ^ Generate quickjump index- argCssFile :: Flag FilePath,- -- ^ Optional custom CSS file.- argContents :: Flag String,- -- ^ Optional URL to contents page.- argVerbose :: Any,- argOutput :: Flag [Output],- -- ^ HTML or Hoogle doc or both? Required.- argInterfaces :: [(FilePath, Maybe String, Maybe String)],- -- ^ [(Interface file, URL to the HTML docs and hyperlinked-source for links)].- argOutputDir :: Directory,- -- ^ Where to generate the documentation.- argTitle :: Flag String,- -- ^ Page title, required.- argPrologue :: Flag String,- -- ^ Prologue text, required.- argGhcOptions :: GhcOptions,- -- ^ Additional flags to pass to GHC.- argGhcLibDir :: Flag FilePath,- -- ^ To find the correct GHC, required.- argReexports :: [OpenModule],- -- ^ Re-exported modules- 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)--unDir :: Directory -> FilePath-unDir = normalise . unDir'--type Template = String--data Output = Html | Hoogle---- --------------------------------------------------------------------------------- Haddock support--haddock :: PackageDescription- -> LocalBuildInfo- -> [PPSuffixHandler]- -> HaddockFlags- -> IO ()-haddock pkg_descr _ _ haddockFlags- | not (hasLibs pkg_descr)- && not (fromFlag $ haddockExecutables haddockFlags)- && not (fromFlag $ haddockTestSuites haddockFlags)- && not (fromFlag $ haddockBenchmarks haddockFlags)- && not (fromFlag $ haddockForeignLibs haddockFlags)- =- warn (fromFlag $ haddockVerbosity haddockFlags) $- "No documentation was generated as this package does not contain "- ++ "a library. Perhaps you want to use the --executables, --tests,"- ++ " --benchmarks or --foreign-libraries flags."--haddock pkg_descr lbi suffixes flags' = do- let verbosity = flag haddockVerbosity- comp = compiler lbi- platform = hostPlatform lbi-- quickJmpFlag = haddockQuickJump flags'- flags = case haddockTarget of- ForDevelopment -> flags'- ForHackage -> flags'- { haddockHoogle = Flag True- , haddockHtml = Flag True- , haddockHtmlLocation = Flag (pkg_url ++ "/docs")- , haddockContents = Flag (toPathTemplate pkg_url)- , haddockLinkedSource = Flag True- , haddockQuickJump = Flag True- }- pkg_url = "/package/$pkg-$version"- flag f = fromFlag $ f flags-- tmpFileOpts = defaultTempFileOptions- { optKeepTempFiles = flag haddockKeepTempFiles }- htmlTemplate = fmap toPathTemplate . flagToMaybe . haddockHtmlLocation- $ flags- haddockTarget =- fromFlagOrDefault ForDevelopment (haddockForHackage flags')-- (haddockProg, version, _) <-- requireProgramVersion verbosity haddockProgram- (orLaterVersion (mkVersion [2,0])) (withPrograms lbi)-- -- various sanity checks- when (flag haddockHoogle && version < mkVersion [2,2]) $- die' verbosity "Haddock 2.0 and 2.1 do not support the --hoogle flag."--- when (flag haddockQuickJump && version < mkVersion [2,19]) $ do- let msg = "Haddock prior to 2.19 does not support the --quickjump flag."- alt = "The generated documentation won't have the QuickJump feature."- if Flag True == quickJmpFlag- then die' verbosity msg- else warn verbosity (msg ++ "\n" ++ alt)-- haddockGhcVersionStr <- getProgramOutput verbosity haddockProg- ["--ghc-version"]- case (simpleParsec haddockGhcVersionStr, compilerCompatVersion GHC comp) of- (Nothing, _) -> die' verbosity "Could not get GHC version from Haddock"- (_, Nothing) -> die' verbosity "Could not get GHC version from compiler"- (Just haddockGhcVersion, Just ghcVersion)- | haddockGhcVersion == ghcVersion -> return ()- | otherwise -> die' verbosity $- "Haddock's internal GHC version must match the configured "- ++ "GHC version.\n"- ++ "The GHC version is " ++ prettyShow ghcVersion ++ " but "- ++ "haddock is using GHC version " ++ prettyShow haddockGhcVersion-- -- the tools match the requests, we can proceed-- -- We fall back to using HsColour only for versions of Haddock which don't- -- support '--hyperlinked-sources'.- when (flag haddockLinkedSource && version < mkVersion [2,17]) $- hscolour' (warn verbosity) haddockTarget pkg_descr lbi suffixes- (defaultHscolourFlags `mappend` haddockToHscolour flags)-- libdirArgs <- getGhcLibDir verbosity lbi- let commonArgs = mconcat- [ libdirArgs- , fromFlags (haddockTemplateEnv lbi (packageId pkg_descr)) flags- , fromPackageDescription haddockTarget pkg_descr ]-- targets <- readTargetInfos verbosity pkg_descr lbi (haddockArgs flags)-- let- targets' =- case targets of- [] -> allTargetsInBuildOrder' pkg_descr lbi- _ -> targets-- internalPackageDB <-- createInternalPackageDB verbosity lbi (flag haddockDistPref)-- (\f -> foldM_ f (installedPkgs lbi) targets') $ \index target -> do-- let component = targetComponent target- clbi = targetCLBI target-- componentInitialBuildSteps (flag haddockDistPref) pkg_descr lbi clbi verbosity-- let- lbi' = lbi {- withPackageDB = withPackageDB lbi ++ [internalPackageDB],- installedPkgs = index- }-- preprocessComponent pkg_descr component lbi' clbi False verbosity suffixes- let- doExe com = case (compToExe com) of- Just exe -> do- withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi') "tmp" $- \tmp -> do- exeArgs <- fromExecutable verbosity tmp lbi' clbi htmlTemplate- version exe- let exeArgs' = commonArgs `mappend` exeArgs- runHaddock verbosity tmpFileOpts comp platform- haddockProg exeArgs'- Nothing -> do- warn (fromFlag $ haddockVerbosity flags)- "Unsupported component, skipping..."- return ()- -- We define 'smsg' once and then reuse it inside the case, so that- -- we don't say we are running Haddock when we actually aren't- -- (e.g., Haddock is not run on non-libraries)- smsg :: IO ()- smsg = setupMessage' verbosity "Running Haddock on" (packageId pkg_descr)- (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)- case component of- CLib lib -> do- withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi) "tmp" $- \tmp -> do- smsg- libArgs <- fromLibrary verbosity tmp lbi' clbi htmlTemplate- version lib- let libArgs' = commonArgs `mappend` libArgs- runHaddock verbosity tmpFileOpts comp platform haddockProg libArgs'-- case libName lib of- LMainLibName ->- pure index- LSubLibName _ -> do- pwd <- getCurrentDirectory-- let- ipi = inplaceInstalledPackageInfo- pwd (flag haddockDistPref) pkg_descr- (mkAbiHash "inplace") lib lbi' clbi-- debug verbosity $ "Registering inplace:\n"- ++ (InstalledPackageInfo.showInstalledPackageInfo ipi)-- registerPackage verbosity (compiler lbi') (withPrograms lbi')- (withPackageDB lbi') ipi- HcPkg.defaultRegisterOptions {- HcPkg.registerMultiInstance = True- }-- return $ PackageIndex.insert ipi index-- CFLib flib -> (when (flag haddockForeignLibs) $ do- withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi') "tmp" $- \tmp -> do- smsg- flibArgs <- fromForeignLib verbosity tmp lbi' clbi htmlTemplate- version flib- let libArgs' = commonArgs `mappend` flibArgs- runHaddock verbosity tmpFileOpts comp platform haddockProg libArgs')-- >> return index-- CExe _ -> (when (flag haddockExecutables) $ smsg >> doExe component) >> return index- CTest _ -> (when (flag haddockTestSuites) $ smsg >> doExe component) >> return index- CBench _ -> (when (flag haddockBenchmarks) $ smsg >> doExe component) >> return index-- for_ (extraDocFiles pkg_descr) $ \ fpath -> do- files <- matchDirFileGlob verbosity (specVersion pkg_descr) "." fpath- for_ files $ copyFileTo verbosity (unDir $ argOutputDir commonArgs)---- --------------------------------------------------------------------------------- Contributions to HaddockArgs (see also Doctest.hs for very similar code).--fromFlags :: PathTemplateEnv -> HaddockFlags -> HaddockArgs-fromFlags env flags =- mempty {- argHideModules = (maybe mempty (All . not)- $ flagToMaybe (haddockInternal flags), mempty),- argLinkSource = if fromFlag (haddockLinkedSource flags)- then Flag ("src/%{MODULE/./-}.html"- ,"src/%{MODULE/./-}.html#%{NAME}"- ,"src/%{MODULE/./-}.html#line-%{LINE}")- else NoFlag,- argLinkedSource = haddockLinkedSource flags,- argQuickJump = haddockQuickJump flags,- argCssFile = haddockCss flags,- argContents = fmap (fromPathTemplate . substPathTemplate env)- (haddockContents flags),- argVerbose = maybe mempty (Any . (>= deafening))- . flagToMaybe $ haddockVerbosity flags,- argOutput =- Flag $ case [ Html | Flag True <- [haddockHtml flags] ] ++- [ Hoogle | Flag True <- [haddockHoogle flags] ]- of [] -> [ Html ]- os -> os,- argOutputDir = maybe mempty Dir . flagToMaybe $ haddockDistPref flags,-- argGhcOptions = mempty { ghcOptExtra = ghcArgs }- }- where- ghcArgs = fromMaybe [] . lookup "ghc" . haddockProgramArgs $ flags--fromPackageDescription :: HaddockTarget -> PackageDescription -> HaddockArgs-fromPackageDescription haddockTarget pkg_descr = mempty- { argInterfaceFile = Flag $ haddockName pkg_descr- , argPackageName = Flag $ packageId $ pkg_descr- , argOutputDir = Dir $- "doc" </> "html" </> haddockDirName haddockTarget pkg_descr- , argPrologue = Flag $ ShortText.fromShortText $- if ShortText.null desc- then synopsis pkg_descr- else desc- , argTitle = Flag $ showPkg ++ subtitle- }- where- desc = description pkg_descr- showPkg = prettyShow (packageId pkg_descr)- subtitle- | ShortText.null (synopsis pkg_descr) = ""- | otherwise = ": " ++ ShortText.fromShortText (synopsis pkg_descr)--componentGhcOptions :: Verbosity -> LocalBuildInfo- -> BuildInfo -> ComponentLocalBuildInfo -> FilePath- -> GhcOptions-componentGhcOptions verbosity lbi bi clbi odir =- let f = case compilerFlavor (compiler lbi) of- GHC -> GHC.componentGhcOptions- GHCJS -> GHCJS.componentGhcOptions- _ -> error $- "Distribution.Simple.Haddock.componentGhcOptions:" ++- "haddock only supports GHC and GHCJS"- in f verbosity lbi bi clbi odir--mkHaddockArgs :: Verbosity- -> FilePath- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Maybe PathTemplate -- ^ template for HTML location- -> Version- -> [FilePath]- -> BuildInfo- -> IO HaddockArgs-mkHaddockArgs verbosity tmp lbi clbi htmlTemplate haddockVersion inFiles bi = do- ifaceArgs <- getInterfaces verbosity lbi clbi htmlTemplate- let vanillaOpts = (componentGhcOptions normal lbi bi clbi (buildDir lbi)) {- -- Noooooooooo!!!!!111- -- haddock stomps on our precious .hi- -- and .o files. Workaround by telling- -- haddock to write them elsewhere.- ghcOptObjDir = toFlag tmp,- ghcOptHiDir = toFlag tmp,- ghcOptStubDir = toFlag tmp- } `mappend` getGhcCppOpts haddockVersion bi- sharedOpts = vanillaOpts {- ghcOptDynLinkMode = toFlag GhcDynamicOnly,- ghcOptFPic = toFlag True,- ghcOptHiSuffix = toFlag "dyn_hi",- ghcOptObjSuffix = toFlag "dyn_o",- ghcOptExtra = hcSharedOptions GHC bi-- }- opts <- if withVanillaLib lbi- then return vanillaOpts- else if withSharedLib lbi- then return sharedOpts- else die' verbosity $ "Must have vanilla or shared libraries "- ++ "enabled in order to run haddock"-- return ifaceArgs- { argGhcOptions = opts- , argTargets = inFiles- , argReexports = getReexports clbi- }--fromLibrary :: Verbosity- -> FilePath- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Maybe PathTemplate -- ^ template for HTML location- -> Version- -> Library- -> IO HaddockArgs-fromLibrary verbosity tmp lbi clbi htmlTemplate haddockVersion lib = do- inFiles <- map snd `fmap` getLibSourceFiles verbosity lbi lib clbi- args <- mkHaddockArgs verbosity tmp lbi clbi htmlTemplate haddockVersion- inFiles (libBuildInfo lib)- return args {- argHideModules = (mempty, otherModules (libBuildInfo lib))- }--fromExecutable :: Verbosity- -> FilePath- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Maybe PathTemplate -- ^ template for HTML location- -> Version- -> Executable- -> IO HaddockArgs-fromExecutable verbosity tmp lbi clbi htmlTemplate haddockVersion exe = do- inFiles <- map snd `fmap` getExeSourceFiles verbosity lbi exe clbi- args <- mkHaddockArgs verbosity tmp lbi clbi htmlTemplate- haddockVersion inFiles (buildInfo exe)- return args {- argOutputDir = Dir $ unUnqualComponentName $ exeName exe,- argTitle = Flag $ unUnqualComponentName $ exeName exe- }--fromForeignLib :: Verbosity- -> FilePath- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Maybe PathTemplate -- ^ template for HTML location- -> Version- -> ForeignLib- -> IO HaddockArgs-fromForeignLib verbosity tmp lbi clbi htmlTemplate haddockVersion flib = do- inFiles <- map snd `fmap` getFLibSourceFiles verbosity lbi flib clbi- args <- mkHaddockArgs verbosity tmp lbi clbi htmlTemplate- haddockVersion inFiles (foreignLibBuildInfo flib)- return args {- argOutputDir = Dir $ unUnqualComponentName $ foreignLibName flib,- argTitle = Flag $ unUnqualComponentName $ foreignLibName flib- }--compToExe :: Component -> Maybe Executable-compToExe comp =- case comp of- CTest test@TestSuite { testInterface = TestSuiteExeV10 _ f } ->- Just Executable {- exeName = testName test,- modulePath = f,- exeScope = ExecutablePublic,- buildInfo = testBuildInfo test- }- CBench bench@Benchmark { benchmarkInterface = BenchmarkExeV10 _ f } ->- Just Executable {- exeName = benchmarkName bench,- modulePath = f,- exeScope = ExecutablePublic,- buildInfo = benchmarkBuildInfo bench- }- CExe exe -> Just exe- _ -> Nothing--getInterfaces :: Verbosity- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Maybe PathTemplate -- ^ template for HTML location- -> IO HaddockArgs-getInterfaces verbosity lbi clbi htmlTemplate = do- (packageFlags, warnings) <- haddockPackageFlags verbosity lbi clbi htmlTemplate- traverse_ (warn (verboseUnmarkOutput verbosity)) warnings- return $ mempty {- argInterfaces = packageFlags- }--getReexports :: ComponentLocalBuildInfo -> [OpenModule]-getReexports LibComponentLocalBuildInfo {componentExposedModules = mods } =- mapMaybe exposedReexport mods-getReexports _ = []--getGhcCppOpts :: Version- -> BuildInfo- -> GhcOptions-getGhcCppOpts haddockVersion bi =- mempty {- ghcOptExtensions = toNubListR [EnableExtension CPP | needsCpp],- ghcOptCppOptions = defines- }- where- needsCpp = EnableExtension CPP `elem` usedExtensions bi- defines = [haddockVersionMacro]- haddockVersionMacro = "-D__HADDOCK_VERSION__="- ++ show (v1 * 1000 + v2 * 10 + v3)- where- (v1, v2, v3) = case versionNumbers haddockVersion of- [] -> (0,0,0)- [x] -> (x,0,0)- [x,y] -> (x,y,0)- (x:y:z:_) -> (x,y,z)--getGhcLibDir :: Verbosity -> LocalBuildInfo- -> IO HaddockArgs-getGhcLibDir verbosity lbi = do- l <- case compilerFlavor (compiler lbi) of- GHC -> GHC.getLibDir verbosity lbi- GHCJS -> GHCJS.getLibDir verbosity lbi- _ -> error "haddock only supports GHC and GHCJS"- return $ mempty { argGhcLibDir = Flag l }---- --------------------------------------------------------------------------------- | Call haddock with the specified arguments.-runHaddock :: Verbosity- -> TempFileOptions- -> Compiler- -> Platform- -> ConfiguredProgram- -> HaddockArgs- -> IO ()-runHaddock verbosity tmpFileOpts comp platform haddockProg args- | null (argTargets args) = warn verbosity $- "Haddocks are being requested, but there aren't any modules given "- ++ "to create documentation for."- | otherwise = do- let haddockVersion = fromMaybe (error "unable to determine haddock version")- (programVersion haddockProg)- renderArgs verbosity tmpFileOpts haddockVersion comp platform args $- \(flags,result)-> do-- runProgram verbosity haddockProg flags-- notice verbosity $ "Documentation created: " ++ result---renderArgs :: Verbosity- -> TempFileOptions- -> Version- -> Compiler- -> Platform- -> HaddockArgs- -> (([String], FilePath) -> IO a)- -> IO a-renderArgs verbosity tmpFileOpts version comp platform args k = do- let haddockSupportsUTF8 = version >= mkVersion [2,14,4]- haddockSupportsResponseFiles = version > mkVersion [2,16,2]- createDirectoryIfMissingVerbose verbosity True outputDir- withTempFileEx tmpFileOpts outputDir "haddock-prologue.txt" $- \prologueFileName h -> do- do- when haddockSupportsUTF8 (hSetEncoding h utf8)- hPutStrLn h $ fromFlag $ argPrologue args- hClose h- let pflag = "--prologue=" ++ prologueFileName- renderedArgs = pflag : renderPureArgs version comp platform args- if haddockSupportsResponseFiles- then- withResponseFile- verbosity- tmpFileOpts- outputDir- "haddock-response.txt"- (if haddockSupportsUTF8 then Just utf8 else Nothing)- renderedArgs- (\responseFileName -> k (["@" ++ responseFileName], result))- else- k (renderedArgs, result)- where- outputDir = (unDir $ argOutputDir args)- result = intercalate ", "- . map (\o -> outputDir </>- case o of- Html -> "index.html"- Hoogle -> pkgstr <.> "txt")- $ arg argOutput- where- pkgstr = prettyShow $ packageName pkgid- pkgid = arg argPackageName- arg f = fromFlag $ f args--renderPureArgs :: Version -> Compiler -> Platform -> HaddockArgs -> [String]-renderPureArgs version comp platform args = concat- [ (:[]) . (\f -> "--dump-interface="++ unDir (argOutputDir args) </> f)- . fromFlag . argInterfaceFile $ args-- , if isVersion 2 16- then (\pkg -> [ "--package-name=" ++ prettyShow (pkgName pkg)- , "--package-version=" ++ prettyShow (pkgVersion pkg)- ])- . fromFlag . argPackageName $ args- else []-- , [ "--since-qual=external" | isVersion 2 20 ]-- , [ "--quickjump" | isVersion 2 19- , fromFlag . argQuickJump $ args ]-- , [ "--hyperlinked-source" | isVersion 2 17- , fromFlag . argLinkedSource $ args ]-- , (\(All b,xs) -> bool (map (("--hide=" ++) . prettyShow) xs) [] b)- . argHideModules $ args-- , bool ["--ignore-all-exports"] [] . getAny . argIgnoreExports $ args-- , maybe [] (\(m,e,l) ->- ["--source-module=" ++ m- ,"--source-entity=" ++ e]- ++ if isVersion 2 14 then ["--source-entity-line=" ++ l]- else []- ) . flagToMaybe . argLinkSource $ args-- , maybe [] ((:[]) . ("--css="++)) . flagToMaybe . argCssFile $ args-- , maybe [] ((:[]) . ("--use-contents="++)) . flagToMaybe . argContents $ args-- , bool [] [verbosityFlag] . getAny . argVerbose $ args-- , map (\o -> case o of Hoogle -> "--hoogle"; Html -> "--html")- . fromFlag . argOutput $ args-- , renderInterfaces . argInterfaces $ args-- , (:[]) . ("--odir="++) . unDir . argOutputDir $ args-- , (:[]) . ("--title="++)- . (bool (++" (internal documentation)")- id (getAny $ argIgnoreExports args))- . fromFlag . argTitle $ args-- , [ "--optghc=" ++ opt | let opts = argGhcOptions args- , opt <- renderGhcOptions comp platform opts ]-- , maybe [] (\l -> ["-B"++l]) $- flagToMaybe (argGhcLibDir args) -- error if Nothing?-- -- https://github.com/haskell/haddock/pull/547- , [ "--reexport=" ++ prettyShow r- | r <- argReexports args- , isVersion 2 19- ]-- , argTargets $ args- ]- where- renderInterfaces = map renderInterface-- renderInterface :: (FilePath, Maybe FilePath, Maybe FilePath) -> String- renderInterface (i, html, hypsrc) = "--read-interface=" ++- (intercalate "," $ concat [ [ x | Just x <- [html] ]- , [ x | Just _ <- [html]- -- only render hypsrc path if html path- -- is given and hyperlinked-source is- -- enabled- , Just x <- [hypsrc]- , isVersion 2 17- , fromFlag . argLinkedSource $ args- ]- , [ i ]- ])-- bool a b c = if c then a else b- isVersion major minor = version >= mkVersion [major,minor]- verbosityFlag- | isVersion 2 5 = "--verbosity=1"- | otherwise = "--verbose"--------------------------------------------------------------------------------------- | Given a list of 'InstalledPackageInfo's, return a list of interfaces and--- HTML paths, and an optional warning for packages with missing documentation.-haddockPackagePaths :: [InstalledPackageInfo]- -> Maybe (InstalledPackageInfo -> FilePath)- -> IO ([( FilePath -- path to interface- -- file-- , Maybe FilePath -- url to html- -- documentation-- , Maybe FilePath -- url to hyperlinked- -- source- )]- , Maybe String -- warning about- -- missing documentation- )-haddockPackagePaths ipkgs mkHtmlPath = do- interfaces <- sequenceA- [ case interfaceAndHtmlPath ipkg of- Nothing -> return (Left (packageId ipkg))- Just (interface, html) -> do-- (html', hypsrc') <-- case html of- Just htmlPath -> do- let hypSrcPath = htmlPath </> defaultHyperlinkedSourceDirectory- hypSrcExists <- doesDirectoryExist hypSrcPath- return $ ( Just (fixFileUrl htmlPath)- , if hypSrcExists- then Just (fixFileUrl hypSrcPath)- else Nothing- )- Nothing -> return (Nothing, Nothing)-- exists <- doesFileExist interface- if exists- then return (Right (interface, html', hypsrc'))- else return (Left pkgid)- | ipkg <- ipkgs, let pkgid = packageId ipkg- , pkgName pkgid `notElem` noHaddockWhitelist- ]-- let missing = [ pkgid | Left pkgid <- interfaces ]- warning = "The documentation for the following packages are not "- ++ "installed. No links will be generated to these packages: "- ++ intercalate ", " (map prettyShow missing)- flags = rights interfaces-- return (flags, if null missing then Nothing else Just warning)-- where- -- Don't warn about missing documentation for these packages. See #1231.- noHaddockWhitelist = map mkPackageName [ "rts" ]-- -- Actually extract interface and HTML paths from an 'InstalledPackageInfo'.- interfaceAndHtmlPath :: InstalledPackageInfo- -> Maybe (FilePath, Maybe FilePath)- interfaceAndHtmlPath pkg = do- interface <- listToMaybe (InstalledPackageInfo.haddockInterfaces pkg)- html <- case mkHtmlPath of- Nothing -> listToMaybe (InstalledPackageInfo.haddockHTMLs pkg)- Just mkPath -> Just (mkPath pkg)- return (interface, if null html then Nothing else Just html)-- -- The 'haddock-html' field in the hc-pkg output is often set as a- -- native path, but we need it as a URL. See #1064. Also don't "fix"- -- the path if it is an interpolated one.- fixFileUrl f | Nothing <- mkHtmlPath- , isAbsolute f = "file://" ++ f- | otherwise = f-- -- 'src' is the default hyperlinked source directory ever since. It is- -- not possible to configure that directory in any way in haddock.- defaultHyperlinkedSourceDirectory = "src"---haddockPackageFlags :: Verbosity- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Maybe PathTemplate- -> IO ([( FilePath -- path to interface- -- file-- , Maybe FilePath -- url to html- -- documentation-- , Maybe FilePath -- url to hyperlinked- -- source- )]- , Maybe String -- warning about- -- missing documentation- )-haddockPackageFlags verbosity lbi clbi htmlTemplate = do- let allPkgs = installedPkgs lbi- directDeps = map fst (componentPackageDeps clbi)- transitiveDeps <- case PackageIndex.dependencyClosure allPkgs directDeps of- Left x -> return x- Right inf -> die' verbosity $ "internal error when calculating transitive "- ++ "package dependencies.\nDebug info: " ++ show inf- haddockPackagePaths (PackageIndex.allPackages transitiveDeps) mkHtmlPath- where- mkHtmlPath = fmap expandTemplateVars htmlTemplate- expandTemplateVars tmpl pkg =- fromPathTemplate . substPathTemplate (env pkg) $ tmpl- env pkg = haddockTemplateEnv lbi (packageId pkg)---haddockTemplateEnv :: LocalBuildInfo -> PackageIdentifier -> PathTemplateEnv-haddockTemplateEnv lbi pkg_id =- (PrefixVar, prefix (installDirTemplates 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)---- --------------------------------------------------------------------------------- hscolour support.--hscolour :: PackageDescription- -> LocalBuildInfo- -> [PPSuffixHandler]- -> HscolourFlags- -> IO ()-hscolour = hscolour' dieNoVerbosity ForDevelopment--hscolour' :: (String -> IO ()) -- ^ Called when the 'hscolour' exe is not found.- -> HaddockTarget- -> PackageDescription- -> LocalBuildInfo- -> [PPSuffixHandler]- -> HscolourFlags- -> IO ()-hscolour' onNoHsColour haddockTarget pkg_descr lbi suffixes flags =- either onNoHsColour (\(hscolourProg, _, _) -> go hscolourProg) =<<- lookupProgramVersion verbosity hscolourProgram- (orLaterVersion (mkVersion [1,8])) (withPrograms lbi)- where- go :: ConfiguredProgram -> IO ()- go hscolourProg = do- warn verbosity $- "the 'cabal hscolour' command is deprecated in favour of 'cabal " ++- "haddock --hyperlink-source' and will be removed in the next major " ++- "release."-- setupMessage verbosity "Running hscolour for" (packageId pkg_descr)- createDirectoryIfMissingVerbose verbosity True $- hscolourPref haddockTarget distPref pkg_descr-- withAllComponentsInBuildOrder pkg_descr lbi $ \comp clbi -> do- componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity- preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes- let- doExe com = case (compToExe com) of- Just exe -> do- let outputDir = hscolourPref haddockTarget distPref pkg_descr- </> unUnqualComponentName (exeName exe) </> "src"- runHsColour hscolourProg outputDir =<< getExeSourceFiles verbosity lbi exe clbi- Nothing -> do- warn (fromFlag $ hscolourVerbosity flags)- "Unsupported component, skipping..."- return ()- case comp of- CLib lib -> do- let outputDir = hscolourPref haddockTarget distPref pkg_descr </> "src"- runHsColour hscolourProg outputDir =<< getLibSourceFiles verbosity lbi lib clbi- CFLib flib -> do- let outputDir = hscolourPref haddockTarget distPref pkg_descr- </> unUnqualComponentName (foreignLibName flib) </> "src"- runHsColour hscolourProg outputDir =<< getFLibSourceFiles verbosity lbi flib clbi- CExe _ -> when (fromFlag (hscolourExecutables flags)) $ doExe comp- CTest _ -> when (fromFlag (hscolourTestSuites flags)) $ doExe comp- CBench _ -> when (fromFlag (hscolourBenchmarks flags)) $ doExe comp-- stylesheet = flagToMaybe (hscolourCSS flags)-- verbosity = fromFlag (hscolourVerbosity flags)- distPref = fromFlag (hscolourDistPref flags)-- runHsColour prog outputDir moduleFiles = do- createDirectoryIfMissingVerbose verbosity True outputDir-- case stylesheet of -- copy the CSS file- Nothing | programVersion prog >= Just (mkVersion [1,9]) ->- runProgram verbosity prog- ["-print-css", "-o" ++ outputDir </> "hscolour.css"]- | otherwise -> return ()- Just s -> copyFileVerbose verbosity s (outputDir </> "hscolour.css")-- for_ moduleFiles $ \(m, inFile) ->- runProgram verbosity prog- ["-css", "-anchor", "-o" ++ outFile m, inFile]- where- outFile m = outputDir </>- intercalate "-" (ModuleName.components m) <.> "html"--haddockToHscolour :: HaddockFlags -> HscolourFlags-haddockToHscolour flags =- HscolourFlags {- hscolourCSS = haddockHscolourCss flags,- hscolourExecutables = haddockExecutables flags,- hscolourTestSuites = haddockTestSuites flags,- hscolourBenchmarks = haddockBenchmarks flags,- hscolourForeignLibs = haddockForeignLibs flags,- hscolourVerbosity = haddockVerbosity flags,- hscolourDistPref = haddockDistPref flags,- hscolourCabalFilePath = haddockCabalFilePath flags- }---- --------------------------------------------------------------------------------- Boilerplate Monoid instance.-instance Monoid HaddockArgs where- mempty = gmempty- mappend = (<>)--instance Semigroup HaddockArgs where- (<>) = gmappend--instance Monoid Directory where- mempty = Dir "."- mappend = (<>)--instance Semigroup Directory where- Dir m <> Dir n = Dir $ m </> n
− Distribution/Simple/HaskellSuite.hs
@@ -1,227 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--module Distribution.Simple.HaskellSuite where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Data.List.NonEmpty as NE--import Distribution.Simple.Program-import Distribution.Simple.Compiler-import Distribution.Simple.Utils-import Distribution.Simple.BuildPaths-import Distribution.Verbosity-import Distribution.Version-import Distribution.Pretty-import Distribution.Parsec (simpleParsec)-import Distribution.Package-import Distribution.InstalledPackageInfo hiding (includeDirs)-import Distribution.Simple.PackageIndex as PackageIndex-import Distribution.PackageDescription-import Distribution.Simple.LocalBuildInfo-import Distribution.System (Platform)-import Language.Haskell.Extension-import Distribution.Simple.Program.Builtin--configure- :: Verbosity -> Maybe FilePath -> Maybe FilePath- -> ProgramDb -> IO (Compiler, Maybe Platform, ProgramDb)-configure verbosity mbHcPath hcPkgPath progdb0 = do-- -- We have no idea how a haskell-suite tool is named, so we require at- -- least some information from the user.- hcPath <-- let msg = "You have to provide name or path of a haskell-suite tool (-w PATH)"- in maybe (die' verbosity msg) return mbHcPath-- when (isJust hcPkgPath) $- warn verbosity "--with-hc-pkg option is ignored for haskell-suite"-- (comp, confdCompiler, progdb1) <- configureCompiler hcPath progdb0-- -- Update our pkg tool. It uses the same executable as the compiler, but- -- all command start with "pkg"- (confdPkg, _) <- requireProgram verbosity haskellSuitePkgProgram progdb1- let progdb2 =- updateProgram- confdPkg- { programLocation = programLocation confdCompiler- , programDefaultArgs = ["pkg"]- }- progdb1-- return (comp, Nothing, progdb2)-- where- configureCompiler hcPath progdb0' = do- let- haskellSuiteProgram' =- haskellSuiteProgram- { 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.- -- Instead, call configureProgram directly first.- progdb1 <- configureProgram verbosity haskellSuiteProgram' progdb0'- (confdCompiler, progdb2) <- requireProgram verbosity haskellSuiteProgram' progdb1-- extensions <- getExtensions verbosity confdCompiler- languages <- getLanguages verbosity confdCompiler- (compName, compVersion) <-- getCompilerVersion verbosity confdCompiler-- let- comp = Compiler {- compilerId = CompilerId (HaskellSuite compName) compVersion,- compilerAbiTag = NoAbiTag,- compilerCompat = [],- compilerLanguages = languages,- compilerExtensions = extensions,- compilerProperties = mempty- }-- return (comp, confdCompiler, progdb2)--hstoolVersion :: Verbosity -> FilePath -> IO (Maybe Version)-hstoolVersion = findProgramVersion "--hspkg-version" id--numericVersion :: Verbosity -> FilePath -> IO (Maybe Version)-numericVersion = findProgramVersion "--compiler-version" (fromMaybe "" . safeLast . words)--getCompilerVersion :: Verbosity -> ConfiguredProgram -> IO (String, Version)-getCompilerVersion verbosity prog = do- output <- rawSystemStdout verbosity (programPath prog) ["--compiler-version"]- let- parts = words output- name = concat $ safeInit parts -- there shouldn't be any spaces in the name anyway- versionStr = fromMaybe "" $ safeLast parts- version <-- maybe (die' verbosity "haskell-suite: couldn't determine compiler version") return $- simpleParsec versionStr- return (name, version)--getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Maybe CompilerFlag)]-getExtensions verbosity prog = do- extStrs <-- lines `fmap`- rawSystemStdout verbosity (programPath prog) ["--supported-extensions"]- return- [ (ext, Just $ "-X" ++ prettyShow ext) | Just ext <- map simpleParsec extStrs ]--getLanguages :: Verbosity -> ConfiguredProgram -> IO [(Language, CompilerFlag)]-getLanguages verbosity prog = do- langStrs <-- lines `fmap`- rawSystemStdout verbosity (programPath prog) ["--supported-languages"]- return- [ (ext, "-G" ++ prettyShow ext) | Just ext <- map simpleParsec langStrs ]---- Other compilers do some kind of a packagedb stack check here. Not sure--- if we need something like that as well.-getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramDb- -> IO InstalledPackageIndex-getInstalledPackages verbosity packagedbs progdb =- liftM (PackageIndex.fromList . concat) $ for packagedbs $ \packagedb ->- do str <-- getDbProgramOutput verbosity haskellSuitePkgProgram progdb- ["dump", packageDbOpt packagedb]- `catchExit` \_ -> die' verbosity $ "pkg dump failed"- case parsePackages str of- Right ok -> return ok- _ -> die' verbosity "failed to parse output of 'pkg dump'"-- where- parsePackages str =- case partitionEithers $ map (parseInstalledPackageInfo . toUTF8BS) (splitPkgs str) of- ([], ok) -> Right [ pkg | (_, pkg) <- ok ]- (msgss, _) -> Left (foldMap NE.toList msgss)-- splitPkgs :: String -> [String]- splitPkgs = map unlines . splitWith ("---" ==) . lines- where- splitWith :: (a -> Bool) -> [a] -> [[a]]- splitWith p xs = ys : case zs of- [] -> []- _:ws -> splitWith p ws- where (ys,zs) = break p xs--buildLib- :: Verbosity -> PackageDescription -> LocalBuildInfo- -> Library -> ComponentLocalBuildInfo -> IO ()-buildLib verbosity pkg_descr lbi lib clbi = do- -- In future, there should be a mechanism for the compiler to request any- -- number of the above parameters (or their parts) — in particular,- -- pieces of PackageDescription.- --- -- For now, we only pass those that we know are used.-- let odir = buildDir lbi- bi = libBuildInfo lib- srcDirs = hsSourceDirs bi ++ [odir]- dbStack = withPackageDB lbi- language = fromMaybe Haskell98 (defaultLanguage bi)- progdb = withPrograms lbi- pkgid = packageId pkg_descr-- runDbProgram verbosity haskellSuiteProgram progdb $- [ "compile", "--build-dir", odir ] ++- concat [ ["-i", d] | d <- srcDirs ] ++- concat [ ["-I", d] | d <- [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi- ,odir] ++ includeDirs bi ] ++- [ packageDbOpt pkgDb | pkgDb <- dbStack ] ++- [ "--package-name", prettyShow pkgid ] ++- concat [ ["--package-id", prettyShow ipkgid ]- | (ipkgid, _) <- componentPackageDeps clbi ] ++- ["-G", prettyShow language] ++- concat [ ["-X", prettyShow ex] | ex <- usedExtensions bi ] ++- cppOptions (libBuildInfo lib) ++- [ prettyShow modu | modu <- allLibModules lib clbi ]----installLib- :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^install location- -> FilePath -- ^install location for dynamic libraries- -> FilePath -- ^Build location- -> PackageDescription- -> Library- -> ComponentLocalBuildInfo- -> IO ()-installLib verbosity lbi targetDir dynlibTargetDir builtDir pkg lib clbi = do- let progdb = withPrograms lbi- runDbProgram verbosity haskellSuitePkgProgram progdb $- [ "install-library"- , "--build-dir", builtDir- , "--target-dir", targetDir- , "--dynlib-target-dir", dynlibTargetDir- , "--package-id", prettyShow $ packageId pkg- ] ++ map prettyShow (allLibModules lib clbi)--registerPackage- :: Verbosity- -> ProgramDb- -> PackageDBStack- -> InstalledPackageInfo- -> IO ()-registerPackage verbosity progdb packageDbs installedPkgInfo = do- (hspkg, _) <- requireProgram verbosity haskellSuitePkgProgram progdb-- runProgramInvocation verbosity $- (programInvocation hspkg- ["update", packageDbOpt $ registrationPackageDB packageDbs])- { progInvokeInput = Just $ IODataText $ showInstalledPackageInfo installedPkgInfo }--initPackageDB :: Verbosity -> ProgramDb -> FilePath -> IO ()-initPackageDB verbosity progdb dbPath =- runDbProgram verbosity haskellSuitePkgProgram progdb- ["init", dbPath]--packageDbOpt :: PackageDB -> String-packageDbOpt GlobalPackageDB = "--global"-packageDbOpt UserPackageDB = "--user"-packageDbOpt (SpecificPackageDB db) = "--package-db=" ++ db
− Distribution/Simple/Hpc.hs
@@ -1,149 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Hpc--- Copyright : Thomas Tuegel 2011--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides functions for locating various HPC-related paths and--- a function for adding the necessary options to a PackageDescription to--- build test suites with HPC enabled.--module Distribution.Simple.Hpc- ( Way(..), guessWay- , htmlDir- , mixDir- , tixDir- , tixFilePath- , markupPackage- , markupTest- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.UnqualComponentName-import Distribution.ModuleName ( main )-import Distribution.PackageDescription- ( TestSuite(..)- , testModules- )-import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..) )-import Distribution.Simple.Program- ( hpcProgram- , requireProgramVersion- )-import Distribution.Simple.Program.Hpc ( markup, union )-import Distribution.Simple.Utils ( notice )-import Distribution.Version ( anyVersion )-import Distribution.Verbosity ( Verbosity() )-import System.Directory ( createDirectoryIfMissing, doesFileExist )-import System.FilePath---- ---------------------------------------------------------------------------- Haskell Program Coverage--data Way = Vanilla | Prof | Dyn- deriving (Bounded, Enum, Eq, Read, Show)--hpcDir :: FilePath -- ^ \"dist/\" prefix- -> Way- -> FilePath -- ^ Directory containing component's HPC .mix files-hpcDir distPref way = distPref </> "hpc" </> wayDir- where- wayDir = case way of- Vanilla -> "vanilla"- Prof -> "prof"- Dyn -> "dyn"--mixDir :: FilePath -- ^ \"dist/\" prefix- -> Way- -> FilePath -- ^ Component name- -> FilePath -- ^ Directory containing test suite's .mix files-mixDir distPref way name = hpcDir distPref way </> "mix" </> name--tixDir :: FilePath -- ^ \"dist/\" prefix- -> Way- -> FilePath -- ^ Component name- -> FilePath -- ^ Directory containing test suite's .tix files-tixDir distPref way name = hpcDir distPref way </> "tix" </> name---- | Path to the .tix file containing a test suite's sum statistics.-tixFilePath :: FilePath -- ^ \"dist/\" prefix- -> Way- -> FilePath -- ^ Component name- -> FilePath -- ^ Path to test suite's .tix file-tixFilePath distPref way name = tixDir distPref way name </> name <.> "tix"--htmlDir :: FilePath -- ^ \"dist/\" prefix- -> Way- -> FilePath -- ^ Component name- -> FilePath -- ^ Path to test suite's HTML markup directory-htmlDir distPref way name = hpcDir distPref way </> "html" </> name---- | Attempt to guess the way the test suites in this package were compiled--- and linked with the library so the correct module interfaces are found.-guessWay :: LocalBuildInfo -> Way-guessWay lbi- | withProfExe lbi = Prof- | withDynExe lbi = Dyn- | otherwise = Vanilla---- | Generate the HTML markup for a test suite.-markupTest :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^ \"dist/\" prefix- -> String -- ^ Library name- -> TestSuite- -> IO ()-markupTest verbosity lbi distPref libName suite = do- tixFileExists <- doesFileExist $ tixFilePath distPref way $ testName'- when tixFileExists $ do- -- behaviour of 'markup' depends on version, so we need *a* version- -- but no particular one- (hpc, hpcVer, _) <- requireProgramVersion verbosity- hpcProgram anyVersion (withPrograms lbi)- let htmlDir_ = htmlDir distPref way testName'- markup hpc hpcVer verbosity- (tixFilePath distPref way testName') mixDirs- htmlDir_- (testModules suite ++ [ main ])- notice verbosity $ "Test coverage report written to "- ++ htmlDir_ </> "hpc_index" <.> "html"- where- way = guessWay lbi- testName' = unUnqualComponentName $ testName suite- mixDirs = map (mixDir distPref way) [ testName', libName ]---- | Generate the HTML markup for all of a package's test suites.-markupPackage :: Verbosity- -> LocalBuildInfo- -> FilePath -- ^ \"dist/\" prefix- -> String -- ^ Library name- -> [TestSuite]- -> IO ()-markupPackage verbosity lbi distPref libName suites = do- let tixFiles = map (tixFilePath distPref way) testNames- tixFilesExist <- traverse doesFileExist tixFiles- when (and tixFilesExist) $ do- -- behaviour of 'markup' depends on version, so we need *a* version- -- but no particular one- (hpc, hpcVer, _) <- requireProgramVersion verbosity- hpcProgram anyVersion (withPrograms lbi)- let outFile = tixFilePath distPref way libName- htmlDir' = htmlDir distPref way libName- excluded = concatMap testModules suites ++ [ main ]- createDirectoryIfMissing True $ takeDirectory outFile- union hpc verbosity tixFiles outFile excluded- markup hpc hpcVer verbosity outFile mixDirs htmlDir' excluded- notice verbosity $ "Package coverage report written to "- ++ htmlDir' </> "hpc_index.html"- where- way = guessWay lbi- testNames = fmap (unUnqualComponentName . testName) suites- mixDirs = map (mixDir distPref way) $ libName : testNames
− Distribution/Simple/Install.hs
@@ -1,258 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Install--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is the entry point into installing a built package. Performs the--- \"@.\/setup install@\" and \"@.\/setup copy@\" actions. It moves files into--- place based on the prefix argument. It does the generic bits and then calls--- compiler-specific functions to do the rest.--module Distribution.Simple.Install (- install,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.TargetInfo-import Distribution.Types.LocalBuildInfo-import Distribution.Types.ForeignLib-import Distribution.Types.PackageDescription-import Distribution.Types.UnqualComponentName-import Distribution.Types.ExecutableScope--import Distribution.Package-import Distribution.PackageDescription-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.BuildPaths (haddockName, haddockPref)-import Distribution.Simple.Glob (matchDirFileGlob)-import Distribution.Simple.Utils- ( createDirectoryIfMissingVerbose- , installDirectoryContents, installOrdinaryFile, isInSearchPath- , die', info, noticeNoWrap, warn )-import Distribution.Simple.Compiler- ( CompilerFlavor(..), compilerFlavor )-import Distribution.Simple.Setup- ( CopyFlags(..), fromFlag, HaddockTarget(ForDevelopment) )-import Distribution.Simple.BuildTarget--import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS-import qualified Distribution.Simple.UHC as UHC-import qualified Distribution.Simple.HaskellSuite as HaskellSuite-import Distribution.Compat.Graph (IsNode(..))--import System.Directory- ( doesDirectoryExist, doesFileExist )-import System.FilePath- ( takeFileName, takeDirectory, (</>), isRelative )--import Distribution.Verbosity-import Distribution.Pretty- ( prettyShow )---- |Perform the \"@.\/setup install@\" and \"@.\/setup copy@\"--- actions. Move files into place based on the prefix argument.------ This does NOT register libraries, you should call 'register'--- to do that.--install :: PackageDescription -- ^information from the .cabal file- -> LocalBuildInfo -- ^information from the configure step- -> CopyFlags -- ^flags sent to copy or install- -> IO ()-install pkg_descr lbi flags = do- checkHasLibsOrExes- targets <- readTargetInfos verbosity pkg_descr lbi (copyArgs flags)-- copyPackage verbosity pkg_descr lbi distPref copydest-- -- It's not necessary to do these in build-order, but it's harmless- withNeededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets) $ \target ->- let comp = targetComponent target- clbi = targetCLBI target- in copyComponent verbosity pkg_descr lbi comp clbi copydest- where- distPref = fromFlag (copyDistPref flags)- verbosity = fromFlag (copyVerbosity flags)- copydest = fromFlag (copyDest flags)-- checkHasLibsOrExes =- unless (hasLibs pkg_descr || hasForeignLibs pkg_descr || hasExes pkg_descr) $- die' verbosity "No executables and no library found. Nothing to do."---- | Copy package global files.-copyPackage :: Verbosity -> PackageDescription- -> LocalBuildInfo -> FilePath -> CopyDest -> IO ()-copyPackage verbosity pkg_descr lbi distPref copydest = do- let -- This is a bit of a hack, to handle files which are not- -- per-component (data files and Haddock files.)- InstallDirs {- datadir = dataPref,- docdir = docPref,- htmldir = htmlPref,- haddockdir = interfacePref- } = absoluteInstallCommandDirs pkg_descr lbi (localUnitId lbi) copydest-- -- Install (package-global) data files- installDataFiles verbosity pkg_descr dataPref-- -- Install (package-global) Haddock files- -- TODO: these should be done per-library- docExists <- doesDirectoryExist $ haddockPref ForDevelopment distPref pkg_descr- info verbosity ("directory " ++ haddockPref ForDevelopment distPref pkg_descr ++- " does exist: " ++ show docExists)-- -- TODO: this is a bit questionable, Haddock files really should- -- be per library (when there are convenience libraries.)- when docExists $ do- createDirectoryIfMissingVerbose verbosity True htmlPref- installDirectoryContents verbosity- (haddockPref ForDevelopment distPref pkg_descr) htmlPref- -- setPermissionsRecursive [Read] htmlPref- -- The haddock interface file actually already got installed- -- in the recursive copy, but now we install it where we actually- -- want it to be (normally the same place). We could remove the- -- copy in htmlPref first.- let haddockInterfaceFileSrc = haddockPref ForDevelopment distPref pkg_descr- </> haddockName pkg_descr- haddockInterfaceFileDest = interfacePref </> haddockName pkg_descr- -- We only generate the haddock interface file for libs, So if the- -- package consists only of executables there will not be one:- exists <- doesFileExist haddockInterfaceFileSrc- when exists $ do- createDirectoryIfMissingVerbose verbosity True interfacePref- installOrdinaryFile verbosity haddockInterfaceFileSrc- haddockInterfaceFileDest-- let lfiles = licenseFiles pkg_descr- unless (null lfiles) $ do- createDirectoryIfMissingVerbose verbosity True docPref- sequence_- [ installOrdinaryFile verbosity lfile (docPref </> takeFileName lfile)- | lfile <- lfiles ]---- | Copy files associated with a component.-copyComponent :: Verbosity -> PackageDescription- -> LocalBuildInfo -> Component -> ComponentLocalBuildInfo- -> CopyDest- -> IO ()-copyComponent verbosity pkg_descr lbi (CLib lib) clbi copydest = do- let InstallDirs{- libdir = libPref,- dynlibdir = dynlibPref,- includedir = incPref- } = absoluteInstallCommandDirs pkg_descr lbi (componentUnitId clbi) copydest- buildPref = componentBuildDir lbi clbi-- case libName lib of- LMainLibName -> noticeNoWrap verbosity ("Installing library in " ++ libPref)- LSubLibName n -> noticeNoWrap verbosity ("Installing internal library " ++ prettyShow n ++ " in " ++ libPref)-- -- install include files for all compilers - they may be needed to compile- -- haskell files (using the CPP extension)- installIncludeFiles verbosity (libBuildInfo lib) lbi buildPref incPref-- case compilerFlavor (compiler lbi) of- GHC -> GHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi- GHCJS -> GHCJS.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi- UHC -> UHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi- HaskellSuite _ -> HaskellSuite.installLib- verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi- _ -> die' verbosity $ "installing with "- ++ prettyShow (compilerFlavor (compiler lbi))- ++ " is not implemented"--copyComponent verbosity pkg_descr lbi (CFLib flib) clbi copydest = do- let InstallDirs{- flibdir = flibPref,- includedir = incPref- } = absoluteComponentInstallDirs pkg_descr lbi (componentUnitId clbi) copydest- buildPref = componentBuildDir lbi clbi-- noticeNoWrap verbosity ("Installing foreign library " ++ unUnqualComponentName (foreignLibName flib) ++ " in " ++ flibPref)- installIncludeFiles verbosity (foreignLibBuildInfo flib) lbi buildPref incPref-- case compilerFlavor (compiler lbi) of- GHC -> GHC.installFLib verbosity lbi flibPref buildPref pkg_descr flib- GHCJS -> GHCJS.installFLib verbosity lbi flibPref buildPref pkg_descr flib- _ -> die' verbosity $ "installing foreign lib with "- ++ prettyShow (compilerFlavor (compiler lbi))- ++ " is not implemented"--copyComponent verbosity pkg_descr lbi (CExe exe) clbi copydest = do- let installDirs = absoluteComponentInstallDirs pkg_descr lbi (componentUnitId clbi) copydest- -- the installers know how to find the actual location of the- -- binaries- buildPref = buildDir lbi- uid = componentUnitId clbi- pkgid = packageId pkg_descr- binPref | ExecutablePrivate <- exeScope exe = libexecdir installDirs- | otherwise = bindir installDirs- progPrefixPref = substPathTemplate pkgid lbi uid (progPrefix lbi)- progSuffixPref = substPathTemplate pkgid lbi uid (progSuffix lbi)- progFix = (progPrefixPref, progSuffixPref)- noticeNoWrap verbosity ("Installing executable " ++ prettyShow (exeName exe)- ++ " in " ++ binPref)- inPath <- isInSearchPath binPref- when (not inPath) $- warn verbosity ("The directory " ++ binPref- ++ " is not in the system search path.")- case compilerFlavor (compiler lbi) of- GHC -> GHC.installExe verbosity lbi binPref buildPref progFix pkg_descr exe- GHCJS -> GHCJS.installExe verbosity lbi binPref buildPref progFix pkg_descr exe- UHC -> return ()- HaskellSuite {} -> return ()- _ -> die' verbosity $ "installing with "- ++ prettyShow (compilerFlavor (compiler lbi))- ++ " is not implemented"---- Nothing to do for benchmark/testsuite-copyComponent _ _ _ (CBench _) _ _ = return ()-copyComponent _ _ _ (CTest _) _ _ = return ()---- | Install the files listed in data-files----installDataFiles :: Verbosity -> PackageDescription -> FilePath -> IO ()-installDataFiles verbosity pkg_descr destDataDir =- flip traverse_ (dataFiles pkg_descr) $ \ glob -> do- let srcDataDirRaw = dataDir pkg_descr- srcDataDir = if null srcDataDirRaw- then "."- else srcDataDirRaw- files <- matchDirFileGlob verbosity (specVersion pkg_descr) srcDataDir glob- for_ files $ \ file' -> do- let src = srcDataDir </> file'- dst = destDataDir </> file'- createDirectoryIfMissingVerbose verbosity True (takeDirectory dst)- installOrdinaryFile verbosity src dst---- | Install the files listed in install-includes for a library----installIncludeFiles :: Verbosity -> BuildInfo -> LocalBuildInfo -> FilePath -> FilePath -> IO ()-installIncludeFiles verbosity libBi lbi buildPref destIncludeDir = do- let relincdirs = "." : filter isRelative (includeDirs libBi)- incdirs = [ baseDir lbi </> dir | dir <- relincdirs ]- ++ [ buildPref </> dir | dir <- relincdirs ]- incs <- traverse (findInc incdirs) (installIncludes libBi)- sequence_- [ do createDirectoryIfMissingVerbose verbosity True destDir- installOrdinaryFile verbosity srcFile destFile- | (relFile, srcFile) <- incs- , let destFile = destIncludeDir </> relFile- destDir = takeDirectory destFile ]- where- baseDir lbi' = fromMaybe "" (takeDirectory <$> cabalFilePath lbi')- findInc [] file = die' verbosity ("can't find include file " ++ file)- findInc (dir:dirs) file = do- let path = dir </> file- exists <- doesFileExist path- if exists then return (file, path) else findInc dirs file
− Distribution/Simple/InstallDirs.hs
@@ -1,506 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.InstallDirs--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This manages everything to do with where files get installed (though does--- not get involved with actually doing any installation). It provides an--- 'InstallDirs' type which is a set of directories for where to install--- things. It also handles the fact that we use templates in these install--- dirs. For example most install dirs are relative to some @$prefix@ and by--- changing the prefix all other dirs still end up changed appropriately. So it--- provides a 'PathTemplate' type and functions for substituting for these--- templates.--module Distribution.Simple.InstallDirs (- InstallDirs(..),- InstallDirTemplates,- defaultInstallDirs,- defaultInstallDirs',- combineInstallDirs,- absoluteInstallDirs,- CopyDest(..),- prefixRelativeInstallDirs,- substituteInstallDirTemplates,-- PathTemplate,- PathTemplateVariable(..),- PathTemplateEnv,- toPathTemplate,- fromPathTemplate,- combinePathTemplate,- substPathTemplate,- initialPathTemplateEnv,- platformTemplateEnv,- compilerTemplateEnv,- packageTemplateEnv,- abiTemplateEnv,- installDirsTemplateEnv,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Compat.Environment (lookupEnv)-import Distribution.Pretty-import Distribution.Package-import Distribution.System-import Distribution.Compiler-import Distribution.Simple.InstallDirs.Internal--import System.Directory (getAppUserDataDirectory)-import System.FilePath- ( (</>), isPathSeparator- , pathSeparator, dropDrive- , takeDirectory )--#ifdef mingw32_HOST_OS-import qualified Prelude-import Foreign-import Foreign.C-#endif---- ------------------------------------------------------------------------------ Installation directories----- | The directories where we will install files for packages.------ We have several different directories for different types of files since--- many systems have conventions whereby different types of files in a package--- are installed in different directories. This is particularly the case on--- Unix style systems.----data InstallDirs dir = InstallDirs {- prefix :: dir,- bindir :: dir,- libdir :: dir,- libsubdir :: dir,- dynlibdir :: dir,- flibdir :: dir, -- ^ foreign libraries- libexecdir :: dir,- libexecsubdir:: dir,- includedir :: dir,- datadir :: dir,- datasubdir :: dir,- docdir :: dir,- mandir :: dir,- htmldir :: dir,- haddockdir :: dir,- sysconfdir :: dir- } deriving (Eq, Read, Show, Functor, Generic, Typeable)--instance Binary dir => Binary (InstallDirs dir)-instance Structured dir => Structured (InstallDirs dir)--instance (Semigroup dir, Monoid dir) => Monoid (InstallDirs dir) where- mempty = gmempty- mappend = (<>)--instance Semigroup dir => Semigroup (InstallDirs dir) where- (<>) = gmappend--combineInstallDirs :: (a -> b -> c)- -> InstallDirs a- -> InstallDirs b- -> InstallDirs c-combineInstallDirs combine a b = InstallDirs {- prefix = prefix a `combine` prefix b,- bindir = bindir a `combine` bindir b,- libdir = libdir a `combine` libdir b,- libsubdir = libsubdir a `combine` libsubdir b,- dynlibdir = dynlibdir a `combine` dynlibdir b,- flibdir = flibdir a `combine` flibdir b,- libexecdir = libexecdir a `combine` libexecdir b,- libexecsubdir= libexecsubdir a `combine` libexecsubdir b,- includedir = includedir a `combine` includedir b,- datadir = datadir a `combine` datadir b,- datasubdir = datasubdir a `combine` datasubdir b,- docdir = docdir a `combine` docdir b,- mandir = mandir a `combine` mandir b,- htmldir = htmldir a `combine` htmldir b,- haddockdir = haddockdir a `combine` haddockdir b,- sysconfdir = sysconfdir a `combine` sysconfdir b- }--appendSubdirs :: (a -> a -> a) -> InstallDirs a -> InstallDirs a-appendSubdirs append dirs = dirs {- libdir = libdir dirs `append` libsubdir dirs,- libexecdir = libexecdir dirs `append` libexecsubdir dirs,- datadir = datadir dirs `append` datasubdir dirs,- libsubdir = error "internal error InstallDirs.libsubdir",- libexecsubdir = error "internal error InstallDirs.libexecsubdir",- datasubdir = error "internal error InstallDirs.datasubdir"- }---- | The installation directories in terms of 'PathTemplate's that contain--- variables.------ The defaults for most of the directories are relative to each other, in--- particular they are all relative to a single prefix. This makes it--- convenient for the user to override the default installation directory--- by only having to specify --prefix=... rather than overriding each--- individually. This is done by allowing $-style variables in the dirs.--- These are expanded by textual substitution (see 'substPathTemplate').------ A few of these installation directories are split into two components, the--- dir and subdir. The full installation path is formed by combining the two--- together with @\/@. The reason for this is compatibility with other Unix--- build systems which also support @--libdir@ and @--datadir@. We would like--- users to be able to configure @--libdir=\/usr\/lib64@ for example but--- because by default we want to support installing multiple versions of--- packages and building the same package for multiple compilers we append the--- libsubdir to get: @\/usr\/lib64\/$libname\/$compiler@.------ An additional complication is the need to support relocatable packages on--- systems which support such things, like Windows.----type InstallDirTemplates = InstallDirs PathTemplate---- ------------------------------------------------------------------------------ Default installation directories--defaultInstallDirs :: CompilerFlavor -> Bool -> Bool -> IO InstallDirTemplates-defaultInstallDirs = defaultInstallDirs' False--defaultInstallDirs' :: Bool {- use external internal deps -}- -> CompilerFlavor -> Bool -> Bool -> IO InstallDirTemplates-defaultInstallDirs' True comp userInstall hasLibs = do- dflt <- defaultInstallDirs' False comp userInstall hasLibs- -- Be a bit more hermetic about per-component installs- return dflt { datasubdir = toPathTemplate $ "$abi" </> "$libname",- docdir = toPathTemplate $ "$datadir" </> "doc" </> "$abi" </> "$libname"- }-defaultInstallDirs' False comp userInstall _hasLibs = do- installPrefix <-- if userInstall- then do- mDir <- lookupEnv "CABAL_DIR"- case mDir of- Nothing -> getAppUserDataDirectory "cabal"- Just dir -> return dir- else case buildOS of- Windows -> do windowsProgramFilesDir <- getWindowsProgramFilesDir- return (windowsProgramFilesDir </> "Haskell")- _ -> return "/usr/local"- installLibDir <-- case buildOS of- Windows -> return "$prefix"- _ -> return ("$prefix" </> "lib")- return $ fmap toPathTemplate $ InstallDirs {- prefix = installPrefix,- bindir = "$prefix" </> "bin",- libdir = installLibDir,- libsubdir = case comp of- UHC -> "$pkgid"- _other -> "$abi" </> "$libname",- dynlibdir = "$libdir" </> case comp of- UHC -> "$pkgid"- _other -> "$abi",- libexecsubdir= "$abi" </> "$pkgid",- flibdir = "$libdir",- libexecdir = case buildOS of- Windows -> "$prefix" </> "$libname"- _other -> "$prefix" </> "libexec",- includedir = "$libdir" </> "$libsubdir" </> "include",- datadir = case buildOS of- Windows -> "$prefix"- _other -> "$prefix" </> "share",- datasubdir = "$abi" </> "$pkgid",- docdir = "$datadir" </> "doc" </> "$abi" </> "$pkgid",- mandir = "$datadir" </> "man",- htmldir = "$docdir" </> "html",- haddockdir = "$htmldir",- sysconfdir = "$prefix" </> "etc"- }---- ------------------------------------------------------------------------------ Converting directories, absolute or prefix-relative---- | Substitute the install dir templates into each other.------ To prevent cyclic substitutions, only some variables are allowed in--- particular dir templates. If out of scope vars are present, they are not--- substituted for. Checking for any remaining unsubstituted vars can be done--- as a subsequent operation.------ The reason it is done this way is so that in 'prefixRelativeInstallDirs' we--- can replace 'prefix' with the 'PrefixVar' and get resulting--- 'PathTemplate's that still have the 'PrefixVar' in them. Doing this makes it--- each to check which paths are relative to the $prefix.----substituteInstallDirTemplates :: PathTemplateEnv- -> InstallDirTemplates -> InstallDirTemplates-substituteInstallDirTemplates env dirs = dirs'- where- dirs' = InstallDirs {- -- So this specifies exactly which vars are allowed in each template- prefix = subst prefix [],- bindir = subst bindir [prefixVar],- libdir = subst libdir [prefixVar, bindirVar],- libsubdir = subst libsubdir [],- dynlibdir = subst dynlibdir [prefixVar, bindirVar, libdirVar],- flibdir = subst flibdir [prefixVar, bindirVar, libdirVar],- libexecdir = subst libexecdir prefixBinLibVars,- libexecsubdir = subst libexecsubdir [],- includedir = subst includedir prefixBinLibVars,- datadir = subst datadir prefixBinLibVars,- datasubdir = subst datasubdir [],- docdir = subst docdir prefixBinLibDataVars,- mandir = subst mandir (prefixBinLibDataVars ++ [docdirVar]),- htmldir = subst htmldir (prefixBinLibDataVars ++ [docdirVar]),- haddockdir = subst haddockdir (prefixBinLibDataVars ++- [docdirVar, htmldirVar]),- sysconfdir = subst sysconfdir prefixBinLibVars- }- subst dir env' = substPathTemplate (env'++env) (dir dirs)-- prefixVar = (PrefixVar, prefix dirs')- bindirVar = (BindirVar, bindir dirs')- libdirVar = (LibdirVar, libdir dirs')- libsubdirVar = (LibsubdirVar, libsubdir dirs')- datadirVar = (DatadirVar, datadir dirs')- datasubdirVar = (DatasubdirVar, datasubdir dirs')- docdirVar = (DocdirVar, docdir dirs')- htmldirVar = (HtmldirVar, htmldir dirs')- prefixBinLibVars = [prefixVar, bindirVar, libdirVar, libsubdirVar]- prefixBinLibDataVars = prefixBinLibVars ++ [datadirVar, datasubdirVar]---- | Convert from abstract install directories to actual absolute ones by--- substituting for all the variables in the abstract paths, to get real--- absolute path.-absoluteInstallDirs :: PackageIdentifier- -> UnitId- -> CompilerInfo- -> CopyDest- -> Platform- -> InstallDirs PathTemplate- -> InstallDirs FilePath-absoluteInstallDirs pkgId libname compilerId copydest platform dirs =- (case copydest of- CopyTo destdir -> fmap ((destdir </>) . dropDrive)- CopyToDb dbdir -> fmap (substPrefix "${pkgroot}" (takeDirectory dbdir))- _ -> id)- . appendSubdirs (</>)- . fmap fromPathTemplate- $ substituteInstallDirTemplates env dirs- where- env = initialPathTemplateEnv pkgId libname compilerId platform- substPrefix pre root path- | pre `isPrefixOf` path = root ++ drop (length pre) path- | otherwise = path----- |The location prefix for the /copy/ command.-data CopyDest- = NoCopyDest- | CopyTo FilePath- | CopyToDb FilePath- -- ^ when using the ${pkgroot} as prefix. The CopyToDb will- -- adjust the paths to be relative to the provided package- -- database when copying / installing.- deriving (Eq, Show, Generic)--instance Binary CopyDest---- | Check which of the paths are relative to the installation $prefix.------ If any of the paths are not relative, ie they are absolute paths, then it--- prevents us from making a relocatable package (also known as a \"prefix--- independent\" package).----prefixRelativeInstallDirs :: PackageIdentifier- -> UnitId- -> CompilerInfo- -> Platform- -> InstallDirTemplates- -> InstallDirs (Maybe FilePath)-prefixRelativeInstallDirs pkgId libname compilerId platform dirs =- fmap relative- . appendSubdirs combinePathTemplate- $ -- substitute the path template into each other, except that we map- -- \$prefix back to $prefix. We're trying to end up with templates that- -- mention no vars except $prefix.- substituteInstallDirTemplates env dirs {- prefix = PathTemplate [Variable PrefixVar]- }- where- 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- relative dir = case dir of- PathTemplate cs -> fmap (fromPathTemplate . PathTemplate) (relative' cs)- relative' (Variable PrefixVar : Ordinary (s:rest) : rest')- | isPathSeparator s = Just (Ordinary rest : rest')- relative' (Variable PrefixVar : rest) = Just rest- relative' _ = Nothing---- ------------------------------------------------------------------------------ Path templates---- | An abstract path, possibly containing variables that need to be--- substituted for to get a real 'FilePath'.----newtype PathTemplate = PathTemplate [PathComponent]- deriving (Eq, Ord, Generic, Typeable)--instance Binary PathTemplate-instance Structured PathTemplate--type PathTemplateEnv = [(PathTemplateVariable, PathTemplate)]---- | Convert a 'FilePath' to a 'PathTemplate' including any template vars.----toPathTemplate :: FilePath -> PathTemplate-toPathTemplate fp = PathTemplate- . fromMaybe (error $ "panic! toPathTemplate " ++ show fp)- . readMaybe -- TODO: eradicateNoParse- $ fp---- | Convert back to a path, any remaining vars are included----fromPathTemplate :: PathTemplate -> FilePath-fromPathTemplate (PathTemplate template) = show template--combinePathTemplate :: PathTemplate -> PathTemplate -> PathTemplate-combinePathTemplate (PathTemplate t1) (PathTemplate t2) =- PathTemplate (t1 ++ [Ordinary [pathSeparator]] ++ t2)--substPathTemplate :: PathTemplateEnv -> PathTemplate -> PathTemplate-substPathTemplate environment (PathTemplate template) =- PathTemplate (concatMap subst template)-- where subst component@(Ordinary _) = [component]- subst component@(Variable variable) =- case lookup variable environment of- Just (PathTemplate components) -> components- Nothing -> [component]---- | The initial environment has all the static stuff but no paths-initialPathTemplateEnv :: PackageIdentifier- -> UnitId- -> CompilerInfo- -> Platform- -> PathTemplateEnv-initialPathTemplateEnv pkgId libname compiler platform =- packageTemplateEnv pkgId libname- ++ compilerTemplateEnv compiler- ++ platformTemplateEnv platform- ++ abiTemplateEnv compiler platform--packageTemplateEnv :: PackageIdentifier -> UnitId -> PathTemplateEnv-packageTemplateEnv pkgId uid =- [(PkgNameVar, PathTemplate [Ordinary $ prettyShow (packageName pkgId)])- ,(PkgVerVar, PathTemplate [Ordinary $ prettyShow (packageVersion pkgId)])- -- Invariant: uid is actually a HashedUnitId. Hard to enforce because- -- it's an API change.- ,(LibNameVar, PathTemplate [Ordinary $ prettyShow uid])- ,(PkgIdVar, PathTemplate [Ordinary $ prettyShow pkgId])- ]--compilerTemplateEnv :: CompilerInfo -> PathTemplateEnv-compilerTemplateEnv compiler =- [(CompilerVar, PathTemplate [Ordinary $ prettyShow (compilerInfoId compiler)])- ]--platformTemplateEnv :: Platform -> PathTemplateEnv-platformTemplateEnv (Platform arch os) =- [(OSVar, PathTemplate [Ordinary $ prettyShow os])- ,(ArchVar, PathTemplate [Ordinary $ prettyShow arch])- ]--abiTemplateEnv :: CompilerInfo -> Platform -> PathTemplateEnv-abiTemplateEnv compiler (Platform arch os) =- [(AbiVar, PathTemplate [Ordinary $ prettyShow arch ++ '-':prettyShow os ++- '-':prettyShow (compilerInfoId compiler) ++- case compilerInfoAbiTag compiler of- NoAbiTag -> ""- AbiTag tag -> '-':tag])- ,(AbiTagVar, PathTemplate [Ordinary $ abiTagString (compilerInfoAbiTag compiler)])- ]--installDirsTemplateEnv :: InstallDirs PathTemplate -> PathTemplateEnv-installDirsTemplateEnv dirs =- [(PrefixVar, prefix dirs)- ,(BindirVar, bindir dirs)- ,(LibdirVar, libdir dirs)- ,(LibsubdirVar, libsubdir dirs)- ,(DynlibdirVar, dynlibdir dirs)- ,(DatadirVar, datadir dirs)- ,(DatasubdirVar, datasubdir dirs)- ,(DocdirVar, docdir dirs)- ,(HtmldirVar, htmldir dirs)- ]----- ------------------------------------------------------------------------------ Parsing and showing path templates:---- The textual format is that of an ordinary Haskell String, eg--- "$prefix/bin"--- and this gets parsed to the internal representation as a sequence of path--- spans which are either strings or variables, eg:--- PathTemplate [Variable PrefixVar, Ordinary "/bin" ]--instance Show PathTemplate where- show (PathTemplate template) = show (show template)--instance Read PathTemplate where- readsPrec p s = [ (PathTemplate template, s')- | (path, s') <- readsPrec p s- , (template, "") <- reads path ]---- ------------------------------------------------------------------------------ Internal utilities--getWindowsProgramFilesDir :: IO FilePath-getWindowsProgramFilesDir = do-#ifdef mingw32_HOST_OS- m <- shGetFolderPath csidl_PROGRAM_FILES-#else- let m = Nothing-#endif- return (fromMaybe "C:\\Program Files" m)--#ifdef mingw32_HOST_OS-shGetFolderPath :: CInt -> IO (Maybe FilePath)-shGetFolderPath n =- allocaArray long_path_size $ \pPath -> do- r <- c_SHGetFolderPath nullPtr n nullPtr 0 pPath- if (r /= 0)- then return Nothing- else do s <- peekCWString pPath; return (Just s)- where- long_path_size = 1024 -- MAX_PATH is 260, this should be plenty--csidl_PROGRAM_FILES :: CInt-csidl_PROGRAM_FILES = 0x0026--- csidl_PROGRAM_FILES_COMMON :: CInt--- csidl_PROGRAM_FILES_COMMON = 0x002b--#ifdef x86_64_HOST_ARCH-#define CALLCONV ccall-#else-#define CALLCONV stdcall-#endif--foreign import CALLCONV unsafe "shlobj.h SHGetFolderPathW"- c_SHGetFolderPath :: Ptr ()- -> CInt- -> Ptr ()- -> CInt- -> CWString- -> Prelude.IO CInt-#endif
− Distribution/Simple/InstallDirs/Internal.hs
@@ -1,127 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Simple.InstallDirs.Internal- ( PathComponent(..)- , PathTemplateVariable(..)- ) where--import Prelude ()-import Distribution.Compat.Prelude--data PathComponent =- Ordinary FilePath- | Variable PathTemplateVariable- deriving (Eq, Ord, Generic, Typeable)--instance Binary PathComponent-instance Structured PathComponent--data PathTemplateVariable =- PrefixVar -- ^ The @$prefix@ path variable- | BindirVar -- ^ The @$bindir@ path variable- | LibdirVar -- ^ The @$libdir@ path variable- | LibsubdirVar -- ^ The @$libsubdir@ path variable- | DynlibdirVar -- ^ The @$dynlibdir@ path variable- | DatadirVar -- ^ The @$datadir@ path variable- | DatasubdirVar -- ^ The @$datasubdir@ path variable- | DocdirVar -- ^ The @$docdir@ path variable- | HtmldirVar -- ^ The @$htmldir@ path variable- | 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@- | 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@- | AbiVar -- ^ The compiler's ABI identifier,- --- $arch-$os-$compiler-$abitag- | AbiTagVar -- ^ The optional ABI tag for the compiler- | ExecutableNameVar -- ^ The executable name; used in shell wrappers- | TestSuiteNameVar -- ^ The name of the test suite being run- | TestSuiteResultVar -- ^ The result of the test suite being run, eg- -- @pass@, @fail@, or @error@.- | BenchmarkNameVar -- ^ The name of the benchmark being run- deriving (Eq, Ord, Generic, Typeable)--instance Binary PathTemplateVariable-instance Structured PathTemplateVariable--instance Show PathTemplateVariable where- show PrefixVar = "prefix"- show LibNameVar = "libname"- show BindirVar = "bindir"- show LibdirVar = "libdir"- show LibsubdirVar = "libsubdir"- show DynlibdirVar = "dynlibdir"- show DatadirVar = "datadir"- show DatasubdirVar = "datasubdir"- show DocdirVar = "docdir"- show HtmldirVar = "htmldir"- show PkgNameVar = "pkg"- show PkgVerVar = "version"- show PkgIdVar = "pkgid"- show CompilerVar = "compiler"- show OSVar = "os"- show ArchVar = "arch"- show AbiTagVar = "abitag"- show AbiVar = "abi"- show ExecutableNameVar = "executablename"- show TestSuiteNameVar = "test-suite"- show TestSuiteResultVar = "result"- show BenchmarkNameVar = "benchmark"--instance Read PathTemplateVariable where- readsPrec _ s =- take 1- [ (var, drop (length varStr) s)- | (varStr, var) <- vars- , varStr `isPrefixOf` s ]- -- NB: order matters! Longer strings first- where vars = [("prefix", PrefixVar)- ,("bindir", BindirVar)- ,("libdir", LibdirVar)- ,("libsubdir", LibsubdirVar)- ,("dynlibdir", DynlibdirVar)- ,("datadir", DatadirVar)- ,("datasubdir", DatasubdirVar)- ,("docdir", DocdirVar)- ,("htmldir", HtmldirVar)- ,("pkgid", PkgIdVar)- ,("libname", LibNameVar)- ,("pkgkey", LibNameVar) -- backwards compatibility- ,("pkg", PkgNameVar)- ,("version", PkgVerVar)- ,("compiler", CompilerVar)- ,("os", OSVar)- ,("arch", ArchVar)- ,("abitag", AbiTagVar)- ,("abi", AbiVar)- ,("executablename", ExecutableNameVar)- ,("test-suite", TestSuiteNameVar)- ,("result", TestSuiteResultVar)- ,("benchmark", BenchmarkNameVar)]--instance Show PathComponent where- show (Ordinary path) = path- show (Variable var) = '$':show var- showList = foldr (\x -> (shows x .)) id--instance Read PathComponent where- -- for some reason we collapse multiple $ symbols here- readsPrec _ = lex0- where lex0 [] = []- lex0 ('$':'$':s') = lex0 ('$':s')- lex0 ('$':s') = case [ (Variable var, s'')- | (var, s'') <- reads s' ] of- [] -> lex1 "$" s'- ok -> ok- lex0 s' = lex1 [] s'- lex1 "" "" = []- lex1 acc "" = [(Ordinary (reverse acc), "")]- lex1 acc ('$':'$':s) = lex1 acc ('$':s)- lex1 acc ('$':s) = [(Ordinary (reverse acc), '$':s)]- lex1 acc (c:s) = lex1 (c:acc) s- readList [] = [([],"")]- readList s = [ (component:components, s'')- | (component, s') <- reads s- , (components, s'') <- readList s' ]
− Distribution/Simple/LocalBuildInfo.hs
@@ -1,365 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.LocalBuildInfo--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Once a package has been configured we have resolved conditionals and--- dependencies, configured the compiler and other needed external programs.--- The 'LocalBuildInfo' is used to hold all this information. It holds the--- install dirs, the compiler, the exact package dependencies, the configured--- programs, the package database to use and a bunch of miscellaneous configure--- flags. It gets saved and reloaded from a file (@dist\/setup-config@). It gets--- passed in to very many subsequent build actions.--module Distribution.Simple.LocalBuildInfo (- LocalBuildInfo(..),- localComponentId,- localUnitId,- localCompatPackageKey,-- -- * Buildable package components- Component(..),- ComponentName(..),- LibraryName(..),- defaultLibName,- showComponentName,- componentNameString,- ComponentLocalBuildInfo(..),- componentBuildDir,- foldComponent,- componentName,- componentBuildInfo,- componentBuildable,- pkgComponents,- pkgBuildableComponents,- lookupComponent,- getComponent,- allComponentsInBuildOrder,- depLibraryPaths,- allLibModules,-- withAllComponentsInBuildOrder,- withLibLBI,- withExeLBI,- withBenchLBI,- withTestLBI,- enabledTestLBIs,- enabledBenchLBIs,-- -- * Installation directories- module Distribution.Simple.InstallDirs,- absoluteInstallDirs, prefixRelativeInstallDirs,- absoluteInstallCommandDirs,- absoluteComponentInstallDirs, prefixRelativeComponentInstallDirs,- substPathTemplate,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.Component-import Distribution.Types.PackageId-import Distribution.Types.UnitId-import Distribution.Types.ComponentName-import Distribution.Types.UnqualComponentName-import Distribution.Types.PackageDescription-import Distribution.Types.ComponentLocalBuildInfo-import Distribution.Types.LocalBuildInfo-import Distribution.Types.TargetInfo--import Distribution.Simple.InstallDirs hiding (absoluteInstallDirs,- prefixRelativeInstallDirs,- substPathTemplate, )-import qualified Distribution.Simple.InstallDirs as InstallDirs-import Distribution.PackageDescription-import qualified Distribution.InstalledPackageInfo as Installed-import Distribution.Package-import Distribution.ModuleName-import Distribution.Simple.Compiler-import Distribution.Simple.PackageIndex-import Distribution.Simple.Utils-import Distribution.Pretty-import qualified Distribution.Compat.Graph as Graph--import Data.List (stripPrefix)-import System.FilePath--import System.Directory (doesDirectoryExist, canonicalizePath)---- -------------------------------------------------------------------------------- Configuration information of buildable components--componentBuildDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath--- For now, we assume that libraries/executables/test-suites/benchmarks--- are only ever built once. With Backpack, we need a special case for--- libraries so that we can handle building them multiple times.-componentBuildDir lbi clbi- = buildDir lbi </>- case componentLocalName clbi of- CLibName LMainLibName ->- if prettyShow (componentUnitId clbi) == prettyShow (componentComponentId clbi)- then ""- else prettyShow (componentUnitId clbi)- CLibName (LSubLibName s) ->- if prettyShow (componentUnitId clbi) == prettyShow (componentComponentId clbi)- then unUnqualComponentName s- else prettyShow (componentUnitId clbi)- CFLibName s -> unUnqualComponentName s- CExeName s -> unUnqualComponentName s- CTestName s -> unUnqualComponentName s- CBenchName s -> unUnqualComponentName s---- | Perform the action on each enabled 'library' in the package--- description with the 'ComponentLocalBuildInfo'.-withLibLBI :: PackageDescription -> LocalBuildInfo- -> (Library -> ComponentLocalBuildInfo -> IO ()) -> IO ()-withLibLBI pkg lbi f =- withAllTargetsInBuildOrder' pkg lbi $ \target ->- case targetComponent target of- CLib lib -> f lib (targetCLBI target)- _ -> return ()---- | Perform the action on each enabled 'Executable' in the package--- description. Extended version of 'withExe' that also gives corresponding--- build info.-withExeLBI :: PackageDescription -> LocalBuildInfo- -> (Executable -> ComponentLocalBuildInfo -> IO ()) -> IO ()-withExeLBI pkg lbi f =- withAllTargetsInBuildOrder' pkg lbi $ \target ->- case targetComponent target of- CExe exe -> f exe (targetCLBI target)- _ -> return ()---- | Perform the action on each enabled 'Benchmark' in the package--- description.-withBenchLBI :: PackageDescription -> LocalBuildInfo- -> (Benchmark -> ComponentLocalBuildInfo -> IO ()) -> IO ()-withBenchLBI pkg lbi f =- sequence_ [ f bench clbi | (bench, clbi) <- enabledBenchLBIs pkg lbi ]--withTestLBI :: PackageDescription -> LocalBuildInfo- -> (TestSuite -> ComponentLocalBuildInfo -> IO ()) -> IO ()-withTestLBI pkg lbi f =- sequence_ [ f test clbi | (test, clbi) <- enabledTestLBIs pkg lbi ]--enabledTestLBIs :: PackageDescription -> LocalBuildInfo- -> [(TestSuite, ComponentLocalBuildInfo)]-enabledTestLBIs pkg lbi =- [ (test, targetCLBI target)- | target <- allTargetsInBuildOrder' pkg lbi- , CTest test <- [targetComponent target] ]--enabledBenchLBIs :: PackageDescription -> LocalBuildInfo- -> [(Benchmark, ComponentLocalBuildInfo)]-enabledBenchLBIs pkg lbi =- [ (bench, targetCLBI target)- | target <- allTargetsInBuildOrder' pkg lbi- , CBench bench <- [targetComponent target] ]---- | Perform the action on each buildable 'Library' or 'Executable' (Component)--- in the PackageDescription, subject to the build order specified by the--- 'compBuildOrder' field of the given 'LocalBuildInfo'-withAllComponentsInBuildOrder :: PackageDescription -> LocalBuildInfo- -> (Component -> ComponentLocalBuildInfo -> IO ())- -> IO ()-withAllComponentsInBuildOrder pkg lbi f =- withAllTargetsInBuildOrder' pkg lbi $ \target ->- f (targetComponent target) (targetCLBI target)--allComponentsInBuildOrder :: LocalBuildInfo- -> [ComponentLocalBuildInfo]-allComponentsInBuildOrder lbi =- Graph.topSort (componentGraph lbi)---- -------------------------------------------------------------------------------- A random function that has no business in this module---- | Determine the directories containing the dynamic libraries of the--- transitive dependencies of the component we are building.------ When wanted, and possible, returns paths relative to the installDirs 'prefix'-depLibraryPaths :: Bool -- ^ Building for inplace?- -> Bool -- ^ Generate prefix-relative library paths- -> LocalBuildInfo- -> ComponentLocalBuildInfo -- ^ Component that is being built- -> IO [FilePath]-depLibraryPaths inplace relative lbi clbi = do- let pkgDescr = localPkgDescr lbi- installDirs = absoluteComponentInstallDirs pkgDescr lbi (componentUnitId clbi) NoCopyDest- executable = case clbi of- ExeComponentLocalBuildInfo {} -> True- _ -> False- relDir | executable = bindir installDirs- | otherwise = libdir installDirs-- let -- TODO: this is kind of inefficient- internalDeps = [ uid- | (uid, _) <- componentPackageDeps clbi- -- Test that it's internal- , sub_target <- allTargetsInBuildOrder' pkgDescr lbi- , componentUnitId (targetCLBI (sub_target)) == uid ]- internalLibs = [ getLibDir (targetCLBI sub_target)- | sub_target <- neededTargetsInBuildOrder'- pkgDescr lbi internalDeps ]- {-- -- This is better, but it doesn't work, because we may be passed a- -- CLBI which doesn't actually exist, and was faked up when we- -- were building a test suite/benchmark. See #3599 for proposal- -- to fix this.- let internalCLBIs = filter ((/= componentUnitId clbi) . componentUnitId)- . map targetCLBI- $ neededTargetsInBuildOrder lbi [componentUnitId clbi]- internalLibs = map getLibDir internalCLBIs- -}- getLibDir sub_clbi- | inplace = componentBuildDir lbi sub_clbi- | otherwise = dynlibdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)-- -- Why do we go through all the trouble of a hand-crafting- -- internalLibs, when 'installedPkgs' actually contains the- -- internal libraries? The trouble is that 'installedPkgs'- -- may contain *inplace* entries, which we must NOT use for- -- not inplace 'depLibraryPaths' (e.g., for RPATH calculation).- -- See #4025 for more details. This is all horrible but it- -- is a moot point if you are using a per-component build,- -- because you never have any internal libraries in this case;- -- they're all external.- let external_ipkgs = filter is_external (allPackages (installedPkgs lbi))- is_external ipkg = not (installedUnitId ipkg `elem` internalDeps)- -- First look for dynamic libraries in `dynamic-library-dirs`, and use- -- `library-dirs` as a fall back.- getDynDir pkg = case Installed.libraryDynDirs pkg of- [] -> Installed.libraryDirs pkg- d -> d- allDepLibDirs = concatMap getDynDir external_ipkgs-- allDepLibDirs' = internalLibs ++ allDepLibDirs- allDepLibDirsC <- traverse canonicalizePathNoFail allDepLibDirs'-- let p = prefix installDirs- prefixRelative l = isJust (stripPrefix p l)- libPaths- | relative &&- prefixRelative relDir = map (\l ->- if prefixRelative l- then shortRelativePath relDir l- else l- ) allDepLibDirsC- | otherwise = allDepLibDirsC-- return libPaths- where- -- 'canonicalizePath' fails on UNIX when the directory does not exists.- -- So just don't canonicalize when it doesn't exist.- canonicalizePathNoFail p = do- exists <- doesDirectoryExist p- if exists- then canonicalizePath p- else return p---- | Get all module names that needed to be built by GHC; i.e., all--- of these 'ModuleName's have interface files associated with them--- that need to be installed.-allLibModules :: Library -> ComponentLocalBuildInfo -> [ModuleName]-allLibModules lib clbi =- ordNub $- explicitLibModules lib ++- case clbi of- LibComponentLocalBuildInfo { componentInstantiatedWith = insts } -> map fst insts- _ -> []---- -------------------------------------------------------------------------------- Wrappers for a couple functions from InstallDirs---- | Backwards compatibility function which computes the InstallDirs--- assuming that @$libname@ points to the public library (or some fake--- package identifier if there is no public library.) IF AT ALL--- POSSIBLE, please use 'absoluteComponentInstallDirs' instead.-absoluteInstallDirs :: PackageDescription -> LocalBuildInfo- -> CopyDest- -> InstallDirs FilePath-absoluteInstallDirs pkg lbi copydest =- absoluteComponentInstallDirs pkg lbi (localUnitId lbi) copydest---- | See 'InstallDirs.absoluteInstallDirs'.-absoluteComponentInstallDirs :: PackageDescription -> LocalBuildInfo- -> UnitId- -> CopyDest- -> InstallDirs FilePath-absoluteComponentInstallDirs pkg lbi uid copydest =- InstallDirs.absoluteInstallDirs- (packageId pkg)- uid- (compilerInfo (compiler lbi))- copydest- (hostPlatform lbi)- (installDirTemplates lbi)--absoluteInstallCommandDirs :: PackageDescription -> LocalBuildInfo- -> UnitId- -> CopyDest- -> InstallDirs FilePath-absoluteInstallCommandDirs pkg lbi uid copydest =- dirs {- -- Handle files which are not- -- per-component (data files and Haddock files.)- datadir = datadir dirs',- -- NB: The situation with Haddock is a bit delicate. On the- -- one hand, the easiest to understand Haddock documentation- -- path is pkgname-0.1, which means it's per-package (not- -- per-component). But this means that it's impossible to- -- install Haddock documentation for internal libraries. We'll- -- keep this constraint for now; this means you can't use- -- Cabal to Haddock internal libraries. This does not seem- -- like a big problem.- docdir = docdir dirs',- htmldir = htmldir dirs',- haddockdir = haddockdir dirs'- }- where- dirs = absoluteComponentInstallDirs pkg lbi uid copydest- -- Notice use of 'absoluteInstallDirs' (not the- -- per-component variant). This means for non-library- -- packages we'll just pick a nondescriptive foo-0.1- dirs' = absoluteInstallDirs pkg lbi copydest---- | Backwards compatibility function which computes the InstallDirs--- assuming that @$libname@ points to the public library (or some fake--- package identifier if there is no public library.) IF AT ALL--- POSSIBLE, please use 'prefixRelativeComponentInstallDirs' instead.-prefixRelativeInstallDirs :: PackageId -> LocalBuildInfo- -> InstallDirs (Maybe FilePath)-prefixRelativeInstallDirs pkg_descr lbi =- prefixRelativeComponentInstallDirs pkg_descr lbi (localUnitId lbi)---- |See 'InstallDirs.prefixRelativeInstallDirs'-prefixRelativeComponentInstallDirs :: PackageId -> LocalBuildInfo- -> UnitId- -> InstallDirs (Maybe FilePath)-prefixRelativeComponentInstallDirs pkg_descr lbi uid =- InstallDirs.prefixRelativeInstallDirs- (packageId pkg_descr)- uid- (compilerInfo (compiler lbi))- (hostPlatform lbi)- (installDirTemplates lbi)--substPathTemplate :: PackageId -> LocalBuildInfo- -> UnitId- -> PathTemplate -> FilePath-substPathTemplate pkgid lbi uid = fromPathTemplate- . ( InstallDirs.substPathTemplate env )- where env = initialPathTemplateEnv- pkgid- uid- (compilerInfo (compiler lbi))- (hostPlatform lbi)-
− Distribution/Simple/PackageIndex.hs
@@ -1,716 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.PackageIndex--- Copyright : (c) David Himmelstrup 2005,--- Bjorn Bringert 2007,--- Duncan Coutts 2008-2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ An index of packages whose primary key is 'UnitId'. Public libraries--- are additionally indexed by 'PackageName' and 'Version'.--- Technically, these are an index of *units* (so we should eventually--- rename it to 'UnitIndex'); but in the absence of internal libraries--- or Backpack each unit is equivalent to a package.------ While 'PackageIndex' is parametric over what it actually records,--- it is in fact only ever instantiated with a single element:--- The 'InstalledPackageIndex' (defined here) contains a graph of--- 'InstalledPackageInfo's representing the packages in a--- package database stack. It is used in a variety of ways:------ * The primary use to let Cabal access the same installed--- package database which is used by GHC during compilation.--- For example, this data structure is used by 'ghc-pkg'--- and 'Cabal' to do consistency checks on the database--- (are the references closed).------ * Given a set of dependencies, we can compute the transitive--- closure of dependencies. This is to check if the versions--- of packages are consistent, and also needed by multiple--- tools (Haddock must be explicitly told about the every--- transitive package to do cross-package linking;--- preprocessors must know about the include paths of all--- transitive dependencies.)------ This 'PackageIndex' is NOT to be confused with--- 'Distribution.Client.PackageIndex', which indexes packages only by--- 'PackageName' (this makes it suitable for indexing source packages,--- for which we don't know 'UnitId's.)----module Distribution.Simple.PackageIndex (- -- * Package index data type- InstalledPackageIndex,- PackageIndex,-- -- * Creating an index- fromList,-- -- * Updates- merge,-- insert,-- deleteUnitId,- deleteSourcePackageId,- deletePackageName,--- deleteDependency,-- -- * Queries-- -- ** Precise lookups- lookupUnitId,- lookupComponentId,- lookupSourcePackageId,- lookupPackageId,- lookupPackageName,- lookupDependency,- lookupInternalDependency,-- -- ** Case-insensitive searches- searchByName,- SearchResult(..),- searchByNameSubstring,- searchWithPredicate,-- -- ** Bulk queries- allPackages,- allPackagesByName,- allPackagesBySourcePackageId,- allPackagesBySourcePackageIdAndLibName,-- -- ** Special queries- brokenPackages,- dependencyClosure,- reverseDependencyClosure,- topologicalOrder,- reverseTopologicalOrder,- dependencyInconsistencies,- dependencyCycles,- dependencyGraph,- moduleNameIndex- ) where--import Prelude ()-import Distribution.Compat.Prelude hiding (lookup)-import qualified Data.Map.Strict as Map--import Distribution.Package-import Distribution.Backpack-import Distribution.ModuleName-import qualified Distribution.InstalledPackageInfo as IPI-import Distribution.Version-import Distribution.Simple.Utils-import Distribution.Types.LibraryName--import Control.Exception (assert)-import Data.Array ((!))-import qualified Data.Array as Array-import qualified Data.Graph as Graph-import Data.List as List ( groupBy, deleteBy, deleteFirstsBy )-import qualified Data.List.NonEmpty as NE-import qualified Data.Tree as Tree-import Control.Monad-import Distribution.Compat.Stack--import qualified Prelude (foldr1)---- | 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 '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 UnitId.- --- unitIdIndex :: !(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- -- versions satisfying a dependency.- --- -- 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 UnitId- -- and are kept in preference order.- --- -- FIXME: Clarify what "preference order" means. Check that this invariant is- -- preserved. See #1463 for discussion.- packageIdIndex :: !(Map (PackageName, LibraryName) (Map Version [a]))-- } deriving (Eq, Generic, Show, Read, Typeable)--instance Binary a => Binary (PackageIndex a)-instance Structured a => Structured (PackageIndex a)---- | The default package index which contains 'InstalledPackageInfo'. Normally--- use this.-type InstalledPackageIndex = PackageIndex IPI.InstalledPackageInfo--instance Monoid (PackageIndex IPI.InstalledPackageInfo) where- mempty = PackageIndex Map.empty Map.empty- mappend = (<>)- --save one mappend with empty in the common case:- mconcat [] = mempty- mconcat xs = Prelude.foldr1 mappend xs--instance Semigroup (PackageIndex IPI.InstalledPackageInfo) where- (<>) = merge--{-# NOINLINE invariant #-}-invariant :: WithCallStack (InstalledPackageIndex -> Bool)-invariant (PackageIndex pids pnames) =- -- trace (show pids' ++ "\n" ++ show pnames') $- pids' == pnames'- where- pids' = map installedUnitId (Map.elems pids)- pnames' = sort- [ assert pinstOk (installedUnitId pinst)- | ((pname, plib), pvers) <- Map.toList pnames- , let pversOk = not (Map.null pvers)- , (pver, pinsts) <- assert pversOk $ Map.toList pvers- , let pinsts' = sortBy (comparing installedUnitId) pinsts- pinstsOk = all (\g -> length g == 1)- (groupBy (equating installedUnitId) pinsts')- , pinst <- assert pinstsOk $ pinsts'- , let pinstOk = packageName pinst == pname- && packageVersion pinst == pver- && IPI.sourceLibName pinst == plib- ]- -- If you see this invariant failing (ie the assert in mkPackageIndex below)- -- then one thing to check is if it is happening in fromList. Check if the- -- second list above (the sort [...] bit) is ending up with duplicates. This- -- has been observed in practice once due to a messed up ghc-pkg db. How/why- -- it became messed up was not discovered.-------- * Internal helpers-----mkPackageIndex :: WithCallStack (Map UnitId IPI.InstalledPackageInfo- -> Map (PackageName, LibraryName)- (Map Version [IPI.InstalledPackageInfo])- -> InstalledPackageIndex)-mkPackageIndex pids pnames = assert (invariant index) index- where index = PackageIndex pids pnames-------- * Construction------- | Build an index out of a bunch of packages.------ If there are duplicates by 'UnitId' then later ones mask earlier--- ones.----fromList :: [IPI.InstalledPackageInfo] -> InstalledPackageIndex-fromList pkgs = mkPackageIndex pids ((fmap . fmap) toList pnames)- where- pids = Map.fromList [ (installedUnitId pkg, pkg) | pkg <- pkgs ]- pnames =- Map.fromList- [ (liftM2 (,) packageName IPI.sourceLibName (NE.head pkgsN), pvers)- | pkgsN <- NE.groupBy (equating (liftM2 (,) packageName IPI.sourceLibName))- . sortBy (comparing (liftM3 (,,) packageName IPI.sourceLibName packageVersion))- $ pkgs- , let pvers =- Map.fromList- [ (packageVersion (NE.head pkgsNV),- NE.nubBy (equating installedUnitId) (NE.reverse pkgsNV))- | pkgsNV <- NE.groupBy (equating packageVersion) pkgsN- ]- ]------- * Updates------- | Merge two indexes.------ Packages from the second mask packages from the first if they have the exact--- 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 :: InstalledPackageIndex -> InstalledPackageIndex- -> InstalledPackageIndex-merge (PackageIndex pids1 pnames1) (PackageIndex pids2 pnames2) =- mkPackageIndex (Map.unionWith (\_ y -> y) pids1 pids2)- (Map.unionWith (Map.unionWith mergeBuckets) pnames1 pnames2)- where- -- 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 installedUnitId)----- | Inserts a single package into the index.------ This is equivalent to (but slightly quicker than) using 'mappend' or--- 'merge' with a singleton index.----insert :: IPI.InstalledPackageInfo -> InstalledPackageIndex -> InstalledPackageIndex-insert pkg (PackageIndex pids pnames) =- mkPackageIndex pids' pnames'-- where- pids' = Map.insert (installedUnitId pkg) pkg pids- pnames' = insertPackageName pnames- insertPackageName =- Map.insertWith (\_ -> insertPackageVersion)- (packageName pkg, IPI.sourceLibName pkg)- (Map.singleton (packageVersion pkg) [pkg])-- insertPackageVersion =- Map.insertWith (\_ -> insertPackageInstance)- (packageVersion pkg) [pkg]-- insertPackageInstance pkgs =- pkg : deleteBy (equating installedUnitId) pkg pkgs----- | Removes a single installed package from the index.----deleteUnitId :: UnitId -> InstalledPackageIndex- -> InstalledPackageIndex-deleteUnitId ipkgid original@(PackageIndex pids pnames) =- case Map.updateLookupWithKey (\_ _ -> Nothing) ipkgid pids of- (Nothing, _) -> original- (Just spkgid, pids') -> mkPackageIndex pids'- (deletePkgName spkgid pnames)-- where- deletePkgName spkgid =- Map.update (deletePkgVersion spkgid) (packageName spkgid, IPI.sourceLibName spkgid)-- deletePkgVersion spkgid =- (\m -> if Map.null m then Nothing else Just m)- . Map.update deletePkgInstance (packageVersion spkgid)-- deletePkgInstance =- (\xs -> if null xs then Nothing else Just xs)- . List.deleteBy (\_ pkg -> installedUnitId pkg == ipkgid) undefined---- | Removes all packages with this source 'PackageId' from the index.----deleteSourcePackageId :: PackageId -> InstalledPackageIndex- -> InstalledPackageIndex-deleteSourcePackageId pkgid original@(PackageIndex pids pnames) =- -- NB: Doesn't delete internal packages- case Map.lookup (packageName pkgid, LMainLibName) pnames of- Nothing -> original- Just pvers -> case Map.lookup (packageVersion pkgid) pvers of- Nothing -> original- Just pkgs -> mkPackageIndex- (foldl' (flip (Map.delete . installedUnitId)) pids pkgs)- (deletePkgName pnames)- where- deletePkgName =- Map.update deletePkgVersion (packageName pkgid, LMainLibName)-- deletePkgVersion =- (\m -> if Map.null m then Nothing else Just m)- . Map.delete (packageVersion pkgid)----- | Removes all packages with this (case-sensitive) name from the index.------ NB: Does NOT delete internal libraries from this package.----deletePackageName :: PackageName -> InstalledPackageIndex- -> InstalledPackageIndex-deletePackageName name original@(PackageIndex pids pnames) =- case Map.lookup (name, LMainLibName) pnames of- Nothing -> original- Just pvers -> mkPackageIndex- (foldl' (flip (Map.delete . installedUnitId)) pids- (concat (Map.elems pvers)))- (Map.delete (name, LMainLibName) pnames)--{---- | Removes all packages satisfying this dependency from the index.----deleteDependency :: Dependency -> PackageIndex -> PackageIndex-deleteDependency (Dependency name verstionRange) =- delete' name (\pkg -> packageVersion pkg `withinRange` verstionRange)--}------- * Bulk queries------- | Get all the packages from the index.----allPackages :: PackageIndex a -> [a]-allPackages = Map.elems . unitIdIndex---- | Get all the packages from the index.------ They are grouped by package name (case-sensitively).------ (Doesn't include private libraries.)----allPackagesByName :: PackageIndex a -> [(PackageName, [a])]-allPackagesByName index =- [ (pkgname, concat (Map.elems pvers))- | ((pkgname, LMainLibName), pvers) <- Map.toList (packageIdIndex index) ]---- | Get all the packages from the index.------ They are grouped by source package id (package name and version).------ (Doesn't include private libraries)----allPackagesBySourcePackageId :: HasUnitId a => PackageIndex a- -> [(PackageId, [a])]-allPackagesBySourcePackageId index =- [ (packageId ipkg, ipkgs)- | ((_, LMainLibName), pvers) <- Map.toList (packageIdIndex index)- , ipkgs@(ipkg:_) <- Map.elems pvers ]---- | Get all the packages from the index.------ They are grouped by source package id and library name.------ This DOES include internal libraries.-allPackagesBySourcePackageIdAndLibName :: HasUnitId a => PackageIndex a- -> [((PackageId, LibraryName), [a])]-allPackagesBySourcePackageIdAndLibName index =- [ ((packageId ipkg, ln), ipkgs)- | ((_, ln), pvers) <- Map.toList (packageIdIndex index)- , ipkgs@(ipkg:_) <- Map.elems pvers ]------- * Lookups------- | Does a lookup by unit identifier.------ Since multiple package DBs mask each other by 'UnitId',--- then we get back at most one package.----lookupUnitId :: PackageIndex a -> UnitId- -> Maybe a-lookupUnitId index uid = Map.lookup uid (unitIdIndex index)---- | Does a lookup by component identifier. In the absence--- of Backpack, this is just a 'lookupUnitId'.----lookupComponentId :: PackageIndex a -> ComponentId- -> Maybe a-lookupComponentId index cid =- Map.lookup (newSimpleUnitId cid) (unitIdIndex index)---- | Does a lookup by source package id (name & version).------ There can be multiple installed packages with the same source 'PackageId'--- but different 'UnitId'. They are returned in order of--- preference, with the most preferred first.----lookupSourcePackageId :: PackageIndex a -> PackageId -> [a]-lookupSourcePackageId index pkgid =- -- Do not lookup internal libraries- case Map.lookup (packageName pkgid, LMainLibName) (packageIdIndex index) of- Nothing -> []- Just pvers -> case Map.lookup (packageVersion pkgid) pvers of- Nothing -> []- Just pkgs -> pkgs -- in preference order---- | Convenient alias of 'lookupSourcePackageId', but assuming only--- one package per package ID.-lookupPackageId :: PackageIndex a -> PackageId -> Maybe a-lookupPackageId index pkgid = case lookupSourcePackageId index pkgid of- [] -> Nothing- [pkg] -> Just pkg- _ -> error "Distribution.Simple.PackageIndex: multiple matches found"---- | Does a lookup by source package name.----lookupPackageName :: PackageIndex a -> PackageName- -> [(Version, [a])]-lookupPackageName index name =- -- Do not match internal libraries- case Map.lookup (name, LMainLibName) (packageIdIndex index) of- Nothing -> []- Just pvers -> Map.toList pvers----- | Does a lookup by source package name and a range of versions.------ We get back any number of versions of the specified package name, all--- satisfying the version range constraint.------ This does NOT work for internal dependencies, DO NOT use this--- function on those; use 'lookupInternalDependency' instead.------ INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.----lookupDependency :: InstalledPackageIndex -> PackageName -> VersionRange- -> [(Version, [IPI.InstalledPackageInfo])]-lookupDependency index pn vr =- -- Yes, a little bit of a misnomer here!- lookupInternalDependency index pn vr LMainLibName---- | Does a lookup by source package name and a range of versions.------ We get back any number of versions of the specified package name, all--- satisfying the version range constraint.------ INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.----lookupInternalDependency :: InstalledPackageIndex -> PackageName -> VersionRange- -> LibraryName- -> [(Version, [IPI.InstalledPackageInfo])]-lookupInternalDependency index name versionRange libn =- case Map.lookup (name, libn) (packageIdIndex index) of- Nothing -> []- Just pvers -> [ (ver, pkgs')- | (ver, pkgs) <- Map.toList pvers- , ver `withinRange` versionRange- , let pkgs' = filter eligible pkgs- -- Enforce the invariant- , not (null pkgs')- ]- where- -- When we select for dependencies, we ONLY want to pick up indefinite- -- packages, or packages with no instantiations. We'll do mix-in- -- linking to improve any such package into an instantiated one- -- later.- eligible pkg = IPI.indefinite pkg || null (IPI.instantiatedWith pkg)-------- * Case insensitive name lookups------- | Does a case-insensitive search by package name.------ If there is only one package that compares case-insensitively to this name--- then the search is unambiguous and we get back all versions of that package.--- If several match case-insensitively but one matches exactly then it is also--- unambiguous.------ If however several match case-insensitively and none match exactly then we--- have an ambiguous result, and we get back all the versions of all the--- packages. The list of ambiguous results is split by exact package name. So--- it is a non-empty list of non-empty lists.----searchByName :: PackageIndex a -> String -> SearchResult [a]-searchByName index name =- -- Don't match internal packages- case [ pkgs | pkgs@((pname, LMainLibName),_) <- Map.toList (packageIdIndex index)- , lowercase (unPackageName pname) == lname ] of- [] -> None- [(_,pvers)] -> Unambiguous (concat (Map.elems pvers))- pkgss -> case find ((mkPackageName name ==) . fst . fst) pkgss of- Just (_,pvers) -> Unambiguous (concat (Map.elems pvers))- Nothing -> Ambiguous (map (concat . Map.elems . snd) pkgss)- where lname = lowercase name--data SearchResult a = None | Unambiguous a | Ambiguous [a]---- | Does a case-insensitive substring search by package name.------ That is, all packages that contain the given string in their name.----searchByNameSubstring :: PackageIndex a -> String -> [a]-searchByNameSubstring index searchterm =- searchWithPredicate index (\n -> lsearchterm `isInfixOf` lowercase n)- where lsearchterm = lowercase searchterm---- | @since 3.4.0.0-searchWithPredicate :: PackageIndex a -> (String -> Bool) -> [a]-searchWithPredicate index predicate =- [ pkg- -- Don't match internal packages- | ((pname, LMainLibName), pvers) <- Map.toList (packageIdIndex index)- , predicate (unPackageName pname)- , pkgs <- Map.elems pvers- , pkg <- pkgs ]------- * Special queries------- None of the stuff below depends on the internal representation of the index.------- | Find if there are any cycles in the dependency graph. If there are no--- cycles the result is @[]@.------ This actually computes the strongly connected components. So it gives us a--- list of groups of packages where within each group they all depend on each--- other, directly or indirectly.----dependencyCycles :: PackageInstalled a => PackageIndex a -> [[a]]-dependencyCycles index =- [ vs | Graph.CyclicSCC vs <- Graph.stronglyConnComp adjacencyList ]- where- adjacencyList = [ (pkg, installedUnitId pkg, installedDepends pkg)- | pkg <- allPackages index ]----- | All packages that have immediate dependencies that are not in the index.------ Returns such packages along with the dependencies that they're missing.----brokenPackages :: PackageInstalled a => PackageIndex a- -> [(a, [UnitId])]-brokenPackages index =- [ (pkg, missing)- | pkg <- allPackages index- , let missing = [ pkg' | pkg' <- installedDepends pkg- , isNothing (lookupUnitId index pkg') ]- , not (null missing) ]---- | Tries to take the transitive closure of the package dependencies.------ If the transitive closure is complete then it returns that subset of the--- index. Otherwise it returns the broken packages as in 'brokenPackages'.------ * Note that if the result is @Right []@ it is because at least one of--- the original given 'PackageId's do not occur in the index.----dependencyClosure :: InstalledPackageIndex- -> [UnitId]- -> Either (InstalledPackageIndex)- [(IPI.InstalledPackageInfo, [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 lookupUnitId index pkgid of- Nothing -> closure completed (pkgid:failed) pkgids- Just pkg -> case lookupUnitId completed (installedUnitId pkg) of- Just _ -> closure completed failed pkgids- Nothing -> closure completed' failed pkgids'- where completed' = insert pkg completed- pkgids' = installedDepends pkg ++ pkgids---- | Takes the transitive closure of the packages reverse dependencies.------ * The given 'PackageId's must be in the index.----reverseDependencyClosure :: PackageInstalled a => PackageIndex a- -> [UnitId]- -> [a]-reverseDependencyClosure index =- map vertexToPkg- . concatMap Tree.flatten- . Graph.dfs reverseDepGraph- . map (fromMaybe noSuchPkgId . pkgIdToVertex)-- where- (depGraph, vertexToPkg, pkgIdToVertex) = dependencyGraph index- reverseDepGraph = Graph.transposeG depGraph- noSuchPkgId = error "reverseDependencyClosure: package is not in the graph"--topologicalOrder :: PackageInstalled a => PackageIndex a -> [a]-topologicalOrder index = map toPkgId- . Graph.topSort- $ graph- where (graph, toPkgId, _) = dependencyGraph index--reverseTopologicalOrder :: PackageInstalled a => PackageIndex a -> [a]-reverseTopologicalOrder index = map toPkgId- . Graph.topSort- . Graph.transposeG- $ graph- where (graph, toPkgId, _) = dependencyGraph index---- | Builds a graph of the package dependencies.------ Dependencies on other packages that are not in the index are discarded.--- You can check if there are any such dependencies with 'brokenPackages'.----dependencyGraph :: PackageInstalled a => PackageIndex a- -> (Graph.Graph,- Graph.Vertex -> a,- 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 installedUnitId pkgs) [0..]- vertex_map = Map.fromList vertices- id_to_vertex pid = Map.lookup pid vertex_map-- vertex_to_pkg vertex = pkgTable ! vertex-- pkgTable = Array.listArray bounds pkgs- topBound = length pkgs - 1- bounds = (0, topBound)---- | We maintain the invariant that, for any 'DepUniqueKey', there--- is only one instance of the package in our database.-type DepUniqueKey = (PackageName, LibraryName, Map ModuleName OpenModule)---- | Given a package index where we assume we want to use all the packages--- (use 'dependencyClosure' if you need to get such a index subset) find out--- if the dependencies within it use consistent versions of each package.--- Return all cases where multiple packages depend on different versions of--- some other package.------ Each element in the result is a package name along with the packages that--- depend on it and the versions they require. These are guaranteed to be--- distinct.----dependencyInconsistencies :: InstalledPackageIndex- -- At DepUniqueKey...- -> [(DepUniqueKey,- -- There were multiple packages (BAD!)- [(UnitId,- -- And here are the packages which- -- immediately depended on it- [IPI.InstalledPackageInfo])])]-dependencyInconsistencies index = do- (dep_key, insts_map) <- Map.toList inverseIndex- let insts = Map.toList insts_map- guard (length insts >= 2)- return (dep_key, insts)- where- inverseIndex :: Map DepUniqueKey (Map UnitId [IPI.InstalledPackageInfo])- inverseIndex = Map.fromListWith (Map.unionWith (++)) $ do- pkg <- allPackages index- dep_ipid <- installedDepends pkg- Just dep <- [lookupUnitId index dep_ipid]- let dep_key = (packageName dep, IPI.sourceLibName dep,- Map.fromList (IPI.instantiatedWith dep))- return (dep_key, Map.singleton dep_ipid [pkg])---- | 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- case reexport of- Nothing -> return (m, [pkg])- Just (OpenModuleVar _) -> []- Just (OpenModule _ m') | m == m' -> []- | otherwise -> return (m', [pkg])- -- The heuristic is this: we want to prefer the original package- -- which originally exported a module. However, if a reexport- -- also *renamed* the module (m /= m'), then we have to use the- -- downstream package, since the upstream package has the wrong- -- module name!
− Distribution/Simple/PreProcess.hs
@@ -1,751 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.PreProcess--- Copyright : (c) 2003-2005, Isaac Jones, Malcolm Wallace--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This defines a 'PreProcessor' abstraction which represents a pre-processor--- that can transform one kind of file into another. There is also a--- 'PPSuffixHandler' which is a combination of a file extension and a function--- for configuring a 'PreProcessor'. It defines a bunch of known built-in--- preprocessors like @cpp@, @cpphs@, @c2hs@, @hsc2hs@, @happy@, @alex@ etc and--- lists them in 'knownSuffixHandlers'. On top of this it provides a function--- for actually preprocessing some sources given a bunch of known suffix--- 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, preprocessExtras,- knownSuffixHandlers, ppSuffixes,- PPSuffixHandler, PreProcessor(..),- mkSimplePreProcessor, runSimplePreProcessor,- ppCpp, ppCpp', ppGreenCard, ppC2hs, ppHsc2hs,- ppHappy, ppAlex, ppUnlit, platformDefines- )- where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Compat.Stack--import Distribution.Simple.PreProcess.Unlit-import Distribution.Backpack.DescribeUnitId-import Distribution.Package-import qualified Distribution.ModuleName as ModuleName-import Distribution.ModuleName (ModuleName)-import Distribution.PackageDescription as PD-import qualified Distribution.InstalledPackageInfo as Installed-import qualified Distribution.Simple.PackageIndex as PackageIndex-import Distribution.Simple.CCompiler-import Distribution.Simple.Compiler-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.BuildPaths-import Distribution.Simple.Utils-import Distribution.Simple.Program-import Distribution.Simple.Program.ResponseFile-import Distribution.Simple.Test.LibV09-import Distribution.System-import Distribution.Pretty-import Distribution.Version-import Distribution.Verbosity--import System.Directory (doesFileExist)-import System.Info (os, arch)-import System.FilePath (splitExtension, dropExtensions, (</>), (<.>),- 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--- the input file, the name of the output file and a verbosity level.--- Here is a simple example that merely prepends a comment to the given--- source file:------ > ppTestHandler :: PreProcessor--- > ppTestHandler =--- > PreProcessor {--- > platformIndependent = True,--- > runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->--- > do info verbosity (inFile++" has been preprocessed to "++outFile)--- > stuff <- readFile inFile--- > writeFile outFile ("-- preprocessed as a test\n\n" ++ stuff)--- > return ExitSuccess------ We split the input and output file names into a base directory and the--- rest of the file name. The input base dir is the path in the list of search--- dirs that this file was found in. The output base dir is the build dir where--- all the generated source files are put.------ The reason for splitting it up this way is that some pre-processors don't--- simply generate one output .hs file from one input file but have--- dependencies on other generated files (notably c2hs, where building one--- .hs file may require reading other .chi files, and then compiling the .hs--- file may require reading a generated .h file). In these cases the generated--- files need to embed relative path names to each other (eg the generated .hs--- file mentions the .h file in the FFI imports). This path must be relative to--- the base directory where the generated files are located, it cannot be--- relative to the top level of the build tree because the compilers do not--- look for .h files relative to there, ie we do not use \"-I .\", instead we--- use \"-I dist\/build\" (or whatever dist dir has been set by the user)------ Most pre-processors do not care of course, so mkSimplePreProcessor and--- runSimplePreProcessor functions handle the simple case.----data PreProcessor = PreProcessor {-- -- Is the output of the pre-processor platform independent? eg happy output- -- is portable haskell but c2hs's output is platform dependent.- -- This matters since only platform independent generated code can be- -- included into a source tarball.- platformIndependent :: Bool,-- -- TODO: deal with pre-processors that have implementation dependent output- -- eg alex and happy have --ghc flags. However we can't really include- -- ghc-specific code into supposedly portable source tarballs.-- runPreProcessor :: (FilePath, FilePath) -- Location of the source file relative to a base dir- -> (FilePath, FilePath) -- Output file name, relative to an output base dir- -> Verbosity -- verbosity- -> 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 ()-mkSimplePreProcessor simplePP- (inBaseDir, inRelativeFile)- (outBaseDir, outRelativeFile) verbosity = simplePP inFile outFile verbosity- where inFile = normalise (inBaseDir </> inRelativeFile)- outFile = normalise (outBaseDir </> outRelativeFile)--runSimplePreProcessor :: PreProcessor -> FilePath -> FilePath -> Verbosity- -> IO ()-runSimplePreProcessor pp inFile outFile verbosity =- runPreProcessor pp (".", inFile) (".", outFile) verbosity---- |A preprocessor for turning non-Haskell files with the given extension--- into plain Haskell source files.-type PPSuffixHandler- = (String, BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor)---- | Apply preprocessors to the sources from 'hsSourceDirs' for a given--- component (lib, exe, or test suite).-preprocessComponent :: PackageDescription- -> Component- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Bool- -> Verbosity- -> [PPSuffixHandler]- -> IO ()-preprocessComponent pd comp lbi clbi isSrcDist verbosity handlers = do- -- NB: never report instantiation here; we'll report it properly when- -- building.- setupMessage' verbosity "Preprocessing" (packageId pd)- (componentLocalName clbi) (Nothing :: Maybe [(ModuleName, Module)])- case comp of- (CLib lib@Library{ libBuildInfo = bi }) -> do- let dirs = hsSourceDirs bi ++ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi]- for_ (map ModuleName.toFilePath $ allLibModules lib clbi) $- pre dirs (componentBuildDir lbi clbi) (localHandlers bi)- (CFLib flib@ForeignLib { foreignLibBuildInfo = bi, foreignLibName = nm }) -> do- let nm' = unUnqualComponentName nm- let flibDir = buildDir lbi </> nm' </> nm' ++ "-tmp"- dirs = hsSourceDirs bi ++ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi]- for_ (map ModuleName.toFilePath $ foreignLibModules flib) $- pre dirs flibDir (localHandlers bi)- (CExe exe@Executable { buildInfo = bi, exeName = nm }) -> do- let nm' = unUnqualComponentName nm- let exeDir = buildDir lbi </> nm' </> nm' ++ "-tmp"- dirs = hsSourceDirs bi ++ [autogenComponentModulesDir lbi clbi- ,autogenPackageModulesDir lbi]- for_ (map ModuleName.toFilePath $ otherModules bi) $- pre dirs exeDir (localHandlers bi)- pre (hsSourceDirs bi) exeDir (localHandlers bi) $- dropExtensions (modulePath exe)- CTest test@TestSuite{ testName = nm } -> do- let nm' = unUnqualComponentName nm- case testInterface test of- TestSuiteExeV10 _ f ->- preProcessTest test f $ buildDir lbi </> nm' </> nm' ++ "-tmp"- TestSuiteLibV09 _ _ -> do- let testDir = buildDir lbi </> stubName test- </> stubName test ++ "-tmp"- writeSimpleTestStub test testDir- preProcessTest test (stubFilePath test) testDir- TestSuiteUnsupported tt ->- die' verbosity $ "No support for preprocessing test "- ++ "suite type " ++ prettyShow tt- CBench bm@Benchmark{ benchmarkName = nm } -> do- let nm' = unUnqualComponentName nm- case benchmarkInterface bm of- BenchmarkExeV10 _ f ->- preProcessBench bm f $ buildDir lbi </> nm' </> nm' ++ "-tmp"- BenchmarkUnsupported tt ->- die' verbosity $ "No support for preprocessing benchmark "- ++ "type " ++ prettyShow tt- where- builtinHaskellSuffixes = ["hs", "lhs", "hsig", "lhsig"]- builtinCSuffixes = cSourceExtensions- builtinSuffixes = builtinHaskellSuffixes ++ builtinCSuffixes- localHandlers bi = [(ext, h bi lbi clbi) | (ext, h) <- handlers]- pre dirs dir lhndlrs fp =- preprocessFile dirs dir isSrcDist fp verbosity builtinSuffixes lhndlrs- preProcessTest test = preProcessComponent (testBuildInfo test)- (testModules test)- preProcessBench bm = preProcessComponent (benchmarkBuildInfo bm)- (benchmarkModules bm)- preProcessComponent bi modules exePath dir = do- let biHandlers = localHandlers bi- sourceDirs = hsSourceDirs bi ++ [ autogenComponentModulesDir lbi clbi- , autogenPackageModulesDir lbi ]- sequence_ [ preprocessFile sourceDirs dir isSrcDist- (ModuleName.toFilePath modu) verbosity builtinSuffixes- biHandlers- | modu <- modules ]- preprocessFile (dir : (hsSourceDirs bi)) dir isSrcDist- (dropExtensions $ exePath) verbosity- builtinSuffixes biHandlers----TODO: try to list all the modules that could not be found--- not just the first one. It's annoying and slow due to the need--- to reconfigure after editing the .cabal file each time.---- |Find the first extension of the file that exists, and preprocess it--- if required.-preprocessFile- :: [FilePath] -- ^source directories- -> FilePath -- ^build directory- -> Bool -- ^preprocess for sdist- -> FilePath -- ^module file name- -> Verbosity -- ^verbosity- -> [String] -- ^builtin suffixes- -> [(String, PreProcessor)] -- ^possible preprocessors- -> IO ()-preprocessFile searchLoc buildLoc forSDist baseFile verbosity builtinSuffixes handlers = do- -- look for files in the various source dirs with this module name- -- and a file extension of a known preprocessor- psrcFiles <- findFileWithExtension' (map fst handlers) searchLoc baseFile- case psrcFiles of- -- no preprocessor file exists, look for an ordinary source file- -- just to make sure one actually exists at all for this module.- -- Note: by looking in the target/output build dir too, we allow- -- source files to appear magically in the target build dir without- -- any corresponding "real" source file. This lets custom Setup.hs- -- files generate source modules directly into the build dir without- -- the rest of the build system being aware of it (somewhat dodgy)- Nothing -> do- bsrcFiles <- findFileWithExtension builtinSuffixes (buildLoc : searchLoc) baseFile- case bsrcFiles of- Nothing ->- die' verbosity $ "can't find source for " ++ baseFile- ++ " in " ++ intercalate ", " searchLoc- _ -> return ()- -- found a pre-processable file in one of the source dirs- Just (psrcLoc, psrcRelFile) -> do- let (srcStem, ext) = splitExtension psrcRelFile- psrcFile = psrcLoc </> psrcRelFile- pp = fromMaybe (error "Distribution.Simple.PreProcess: Just expected")- (lookup (safeTail ext) handlers)- -- Preprocessing files for 'sdist' is different from preprocessing- -- for 'build'. When preprocessing for sdist we preprocess to- -- avoid that the user has to have the preprocessors available.- -- ATM, we don't have a way to specify which files are to be- -- preprocessed and which not, so for sdist we only process- -- platform independent files and put them into the 'buildLoc'- -- (which we assume is set to the temp. directory that will become- -- the tarball).- --TODO: eliminate sdist variant, just supply different handlers- when (not forSDist || forSDist && platformIndependent pp) $ do- -- look for existing pre-processed source file in the dest dir to- -- see if we really have to re-run the preprocessor.- ppsrcFiles <- findFileWithExtension builtinSuffixes [buildLoc] baseFile- recomp <- case ppsrcFiles of- Nothing -> return True- Just ppsrcFile ->- psrcFile `moreRecentFile` ppsrcFile- when recomp $ do- let destDir = buildLoc </> dirName srcStem- createDirectoryIfMissingVerbose verbosity True destDir- runPreProcessorWithHsBootHack pp- (psrcLoc, psrcRelFile)- (buildLoc, srcStem <.> "hs")-- where- dirName = takeDirectory-- -- FIXME: This is a somewhat nasty hack. GHC requires that hs-boot files- -- be in the same place as the hs files, so if we put the hs file in dist/- -- then we need to copy the hs-boot file there too. This should probably be- -- done another way. Possibly we should also be looking for .lhs-boot- -- files, but I think that preprocessors only produce .hs files.- runPreProcessorWithHsBootHack pp- (inBaseDir, inRelativeFile)- (outBaseDir, outRelativeFile) = do- runPreProcessor pp- (inBaseDir, inRelativeFile)- (outBaseDir, outRelativeFile) verbosity-- exists <- doesFileExist inBoot- when exists $ copyFileVerbose verbosity inBoot outBoot-- where- inBoot = replaceExtension inFile "hs-boot"- outBoot = replaceExtension outFile "hs-boot"-- inFile = normalise (inBaseDir </> inRelativeFile)- outFile = normalise (outBaseDir </> outRelativeFile)---- --------------------------------------------------------------- * known preprocessors--- --------------------------------------------------------------ppGreenCard :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppGreenCard _ lbi _- = PreProcessor {- platformIndependent = False,- runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->- runDbProgram verbosity greencardProgram (withPrograms lbi)- (["-tffi", "-o" ++ outFile, inFile])- }---- This one is useful for preprocessors that can't handle literate source.--- We also need a way to chain preprocessors.-ppUnlit :: PreProcessor-ppUnlit =- PreProcessor {- platformIndependent = True,- runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->- withUTF8FileContents inFile $ \contents ->- either (writeUTF8File outFile) (die' verbosity) (unlit inFile contents)- }--ppCpp :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppCpp = ppCpp' []--ppCpp' :: [String] -> BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppCpp' extraArgs bi lbi clbi =- case compilerFlavor (compiler lbi) of- GHC -> ppGhcCpp ghcProgram (const True) args bi lbi clbi- GHCJS -> ppGhcCpp ghcjsProgram (const True) args bi lbi clbi- _ -> ppCpphs args bi lbi clbi- where cppArgs = getCppOptions bi lbi- args = cppArgs ++ extraArgs--ppGhcCpp :: Program -> (Version -> Bool)- -> [String] -> BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppGhcCpp program xHs extraArgs _bi lbi clbi =- PreProcessor {- platformIndependent = False,- runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity -> do- (prog, version, _) <- requireProgramVersion verbosity- program anyVersion (withPrograms lbi)- runProgram verbosity prog $- ["-E", "-cpp"]- -- This is a bit of an ugly hack. We're going to- -- unlit the file ourselves later on if appropriate,- -- so we need GHC not to unlit it now or it'll get- -- double-unlitted. In the future we might switch to- -- using cpphs --unlit instead.- ++ (if xHs version then ["-x", "hs"] else [])- ++ [ "-optP-include", "-optP"++ (autogenComponentModulesDir lbi clbi </> cppHeaderName) ]- ++ ["-o", outFile, inFile]- ++ extraArgs- }--ppCpphs :: [String] -> BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppCpphs extraArgs _bi lbi clbi =- PreProcessor {- platformIndependent = False,- runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity -> do- (cpphsProg, cpphsVersion, _) <- requireProgramVersion verbosity- cpphsProgram anyVersion (withPrograms lbi)- runProgram verbosity cpphsProg $- ("-O" ++ outFile) : inFile- : "--noline" : "--strip"- : (if cpphsVersion >= mkVersion [1,6]- then ["--include="++ (autogenComponentModulesDir lbi clbi </> cppHeaderName)]- else [])- ++ extraArgs- }--ppHsc2hs :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppHsc2hs bi lbi clbi =- PreProcessor {- platformIndependent = False,- runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity -> do- (gccProg, _) <- requireProgram verbosity gccProgram (withPrograms lbi)- (hsc2hsProg, hsc2hsVersion, _) <- requireProgramVersion verbosity- hsc2hsProgram anyVersion (withPrograms lbi)- -- See Trac #13896 and https://github.com/haskell/cabal/issues/3122.- let isCross = hostPlatform lbi /= buildPlatform- prependCrossFlags = if isCross then ("-x":) else id- let hsc2hsSupportsResponseFiles = hsc2hsVersion >= mkVersion [0,68,4]- pureArgs = genPureArgs gccProg inFile outFile- if hsc2hsSupportsResponseFiles- then withResponseFile- verbosity- defaultTempFileOptions- (takeDirectory outFile)- "hsc2hs-response.txt"- Nothing- pureArgs- (\responseFileName ->- runProgram verbosity hsc2hsProg (prependCrossFlags ["@"++ responseFileName]))- else runProgram verbosity hsc2hsProg (prependCrossFlags pureArgs)- }- where- -- Returns a list of command line arguments that can either be passed- -- directly, or via a response file.- genPureArgs :: ConfiguredProgram -> String -> String -> [String]- genPureArgs gccProg inFile outFile =- [ "--cc=" ++ programPath gccProg- , "--ld=" ++ programPath gccProg ]-- -- Additional gcc options- ++ [ "--cflag=" ++ opt | opt <- programDefaultArgs gccProg- ++ programOverrideArgs gccProg ]- ++ [ "--lflag=" ++ opt | opt <- programDefaultArgs gccProg- ++ programOverrideArgs gccProg ]-- -- OSX frameworks:- ++ [ what ++ "=-F" ++ opt- | isOSX- , opt <- nub (concatMap Installed.frameworkDirs pkgs)- , what <- ["--cflag", "--lflag"] ]- ++ [ "--lflag=" ++ arg- | isOSX- , opt <- PD.frameworks bi ++ concatMap Installed.frameworks pkgs- , arg <- ["-framework", opt] ]-- -- Note that on ELF systems, wherever we use -L, we must also use -R- -- because presumably that -L dir is not on the normal path for the- -- system's dynamic linker. This is needed because hsc2hs works by- -- compiling a C program and then running it.-- ++ [ "--cflag=" ++ opt | opt <- platformDefines lbi ]-- -- Options from the current package:- ++ [ "--cflag=-I" ++ dir | dir <- PD.includeDirs bi ]- ++ [ "--cflag=-I" ++ buildDir lbi </> dir | dir <- PD.includeDirs bi ]- ++ [ "--cflag=" ++ opt | opt <- PD.ccOptions bi- ++ PD.cppOptions bi- -- hsc2hs uses the C ABI- -- We assume that there are only C sources- -- and C++ functions are exported via a C- -- interface and wrapped in a C source file.- -- Therefore we do not supply C++ flags- -- because there will not be C++ sources.- --- -- DO NOT add PD.cxxOptions unless this changes!- ]- ++ [ "--cflag=" ++ opt | opt <-- [ "-I" ++ autogenComponentModulesDir lbi clbi,- "-I" ++ autogenPackageModulesDir lbi,- "-include", autogenComponentModulesDir lbi clbi </> cppHeaderName ] ]- ++ [ "--lflag=-L" ++ opt | opt <- PD.extraLibDirs bi ]- ++ [ "--lflag=-Wl,-R," ++ opt | isELF- , opt <- PD.extraLibDirs bi ]- ++ [ "--lflag=-l" ++ opt | opt <- PD.extraLibs bi ]- ++ [ "--lflag=" ++ opt | opt <- PD.ldOptions bi ]-- -- Options from dependent packages- ++ [ "--cflag=" ++ opt- | pkg <- pkgs- , opt <- [ "-I" ++ opt | opt <- Installed.includeDirs pkg ]- ++ [ opt | opt <- Installed.ccOptions pkg ] ]- ++ [ "--lflag=" ++ opt- | pkg <- pkgs- , opt <- [ "-L" ++ opt | opt <- Installed.libraryDirs pkg ]- ++ [ "-Wl,-R," ++ opt | isELF- , opt <- Installed.libraryDirs pkg ]- ++ [ "-l" ++ opt | opt <- Installed.extraLibraries pkg ]- ++ [ opt | opt <- Installed.ldOptions pkg ] ]- ++ ["-o", outFile, inFile]-- hacked_index = packageHacks (installedPkgs lbi)- -- Look only at the dependencies of the current component- -- being built! This relies on 'installedPkgs' maintaining- -- 'InstalledPackageInfo' for internal deps too; see #2971.- pkgs = PackageIndex.topologicalOrder $- case PackageIndex.dependencyClosure hacked_index- (map fst (componentPackageDeps clbi)) of- Left index' -> index'- Right inf ->- error ("ppHsc2hs: broken closure: " ++ show inf)- isOSX = case buildOS of OSX -> True; _ -> False- isELF = case buildOS of OSX -> False; Windows -> False; AIX -> False; _ -> True;- packageHacks = case compilerFlavor (compiler lbi) of- GHC -> hackRtsPackage- GHCJS -> hackRtsPackage- _ -> id- -- We don't link in the actual Haskell libraries of our dependencies, so- -- the -u flags in the ldOptions of the rts package mean linking fails on- -- OS X (its ld is a tad stricter than gnu ld). Thus we remove the- -- ldOptions for GHC's rts package:- hackRtsPackage index =- case PackageIndex.lookupPackageName index (mkPackageName "rts") of- [(_, [rts])]- -> 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 -> ComponentLocalBuildInfo -> PreProcessor-ppC2hs bi lbi clbi =- PreProcessor {- platformIndependent = False,- runPreProcessor = \(inBaseDir, inRelativeFile)- (outBaseDir, outRelativeFile) verbosity -> do- (c2hsProg, _, _) <- requireProgramVersion verbosity- c2hsProgram (orLaterVersion (mkVersion [0,15]))- (withPrograms lbi)- (gccProg, _) <- requireProgram verbosity gccProgram (withPrograms lbi)- runProgram verbosity c2hsProg $-- -- Options from the current package:- [ "--cpp=" ++ programPath gccProg, "--cppopts=-E" ]- ++ [ "--cppopts=" ++ opt | opt <- getCppOptions bi lbi ]- ++ [ "--cppopts=-include" ++ (autogenComponentModulesDir lbi clbi </> cppHeaderName) ]- ++ [ "--include=" ++ outBaseDir ]-- -- Options from dependent packages- ++ [ "--cppopts=" ++ opt- | pkg <- pkgs- , opt <- [ "-I" ++ opt | opt <- Installed.includeDirs pkg ]- ++ [ opt | opt@('-':c:_) <- Installed.ccOptions pkg- -- c2hs uses the C ABI- -- We assume that there are only C sources- -- and C++ functions are exported via a C- -- interface and wrapped in a C source file.- -- Therefore we do not supply C++ flags- -- because there will not be C++ sources.- --- --- -- DO NOT add Installed.cxxOptions unless this changes!- , c `elem` "DIU" ] ]- --TODO: install .chi files for packages, so we can --include- -- those dirs here, for the dependencies-- -- input and output files- ++ [ "--output-dir=" ++ outBaseDir- , "--output=" ++ outRelativeFile- , inBaseDir </> inRelativeFile ]- }- 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---TODO: Refactor and add separate getCppOptionsForHs, getCppOptionsForCxx, & getCppOptionsForC--- instead of combining all these cases in a single function. This blind combination can--- potentially lead to compilation inconsistencies.-getCppOptions :: BuildInfo -> LocalBuildInfo -> [String]-getCppOptions bi lbi- = platformDefines lbi- ++ cppOptions bi- ++ ["-I" ++ dir | dir <- PD.includeDirs bi]- ++ [opt | opt@('-':c:_) <- PD.ccOptions bi ++ PD.cxxOptions bi, c `elem` "DIU"]--platformDefines :: LocalBuildInfo -> [String]-platformDefines lbi =- case compilerFlavor comp of- GHC ->- ["-D__GLASGOW_HASKELL__=" ++ versionInt version] ++- ["-D" ++ os ++ "_BUILD_OS=1"] ++- ["-D" ++ arch ++ "_BUILD_ARCH=1"] ++- map (\os' -> "-D" ++ os' ++ "_HOST_OS=1") osStr ++- map (\arch' -> "-D" ++ arch' ++ "_HOST_ARCH=1") archStr- GHCJS ->- compatGlasgowHaskell ++- ["-D__GHCJS__=" ++ versionInt version] ++- ["-D" ++ os ++ "_BUILD_OS=1"] ++- ["-D" ++ arch ++ "_BUILD_ARCH=1"] ++- map (\os' -> "-D" ++ os' ++ "_HOST_OS=1") osStr ++- map (\arch' -> "-D" ++ arch' ++ "_HOST_ARCH=1") archStr- HaskellSuite {} ->- ["-D__HASKELL_SUITE__"] ++- map (\os' -> "-D" ++ os' ++ "_HOST_OS=1") osStr ++- map (\arch' -> "-D" ++ arch' ++ "_HOST_ARCH=1") archStr- _ -> []- where- comp = compiler lbi- Platform hostArch hostOS = hostPlatform lbi- version = compilerVersion comp- compatGlasgowHaskell =- maybe [] (\v -> ["-D__GLASGOW_HASKELL__=" ++ versionInt v])- (compilerCompatVersion GHC comp)- -- TODO: move this into the compiler abstraction- -- FIXME: this forces GHC's crazy 4.8.2 -> 408 convention on all- -- the other compilers. Check if that's really what they want.- versionInt :: Version -> String- versionInt v = case versionNumbers v of- [] -> "1"- [n] -> show n- n1:n2:_ ->- -- 6.8.x -> 608- -- 6.10.x -> 610- let s1 = show n1- s2 = show n2- middle = case s2 of- _ : _ : _ -> ""- _ -> "0"- in s1 ++ middle ++ s2-- osStr = case hostOS of- Linux -> ["linux"]- Windows -> ["mingw32"]- OSX -> ["darwin"]- FreeBSD -> ["freebsd"]- OpenBSD -> ["openbsd"]- NetBSD -> ["netbsd"]- DragonFly -> ["dragonfly"]- Solaris -> ["solaris2"]- AIX -> ["aix"]- HPUX -> ["hpux"]- IRIX -> ["irix"]- HaLVM -> []- IOS -> ["ios"]- Android -> ["android"]- Ghcjs -> ["ghcjs"]- Hurd -> ["hurd"]- OtherOS _ -> []- archStr = case hostArch of- I386 -> ["i386"]- X86_64 -> ["x86_64"]- PPC -> ["powerpc"]- PPC64 -> ["powerpc64"]- Sparc -> ["sparc"]- Arm -> ["arm"]- AArch64 -> ["aarch64"]- Mips -> ["mips"]- SH -> []- IA64 -> ["ia64"]- S390 -> ["s390"]- Alpha -> ["alpha"]- Hppa -> ["hppa"]- Rs6000 -> ["rs6000"]- M68k -> ["m68k"]- Vax -> ["vax"]- JavaScript -> ["javascript"]- OtherArch _ -> []--ppHappy :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppHappy _ lbi _ = pp { platformIndependent = True }- where pp = standardPP lbi happyProgram (hcFlags hc)- hc = compilerFlavor (compiler lbi)- hcFlags GHC = ["-agc"]- hcFlags GHCJS = ["-agc"]- hcFlags _ = []--ppAlex :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor-ppAlex _ lbi _ = pp { platformIndependent = True }- where pp = standardPP lbi alexProgram (hcFlags hc)- hc = compilerFlavor (compiler lbi)- hcFlags GHC = ["-g"]- hcFlags GHCJS = ["-g"]- hcFlags _ = []--standardPP :: LocalBuildInfo -> Program -> [String] -> PreProcessor-standardPP lbi prog args =- PreProcessor {- platformIndependent = False,- runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->- runDbProgram verbosity prog (withPrograms lbi)- (args ++ ["-o", outFile, inFile])- }---- |Convenience function; get the suffixes of these preprocessors.-ppSuffixes :: [ PPSuffixHandler ] -> [String]-ppSuffixes = map fst---- |Standard preprocessors: GreenCard, c2hs, hsc2hs, happy, alex and cpphs.-knownSuffixHandlers :: [ PPSuffixHandler ]-knownSuffixHandlers =- [ ("gc", ppGreenCard)- , ("chs", ppC2hs)- , ("hsc", ppHsc2hs)- , ("x", ppAlex)- , ("y", ppHappy)- , ("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 :: Verbosity- -> Component- -> LocalBuildInfo- -> IO [FilePath]-preprocessExtras verbosity comp lbi = case comp of- CLib _ -> pp $ buildDir lbi- (CExe Executable { exeName = nm }) -> do- let nm' = unUnqualComponentName nm- pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"- (CFLib ForeignLib { foreignLibName = nm }) -> do- let nm' = unUnqualComponentName nm- pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"- CTest test -> do- let nm' = unUnqualComponentName $ testName test- case testInterface test of- TestSuiteExeV10 _ _ ->- pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"- TestSuiteLibV09 _ _ ->- pp $ buildDir lbi </> stubName test </> stubName test ++ "-tmp"- TestSuiteUnsupported tt ->- die' verbosity $ "No support for preprocessing test suite type " ++- prettyShow tt- CBench bm -> do- let nm' = unUnqualComponentName $ benchmarkName bm- case benchmarkInterface bm of- BenchmarkExeV10 _ _ ->- pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"- BenchmarkUnsupported tt ->- die' verbosity $ "No support for preprocessing benchmark "- ++ "type " ++ prettyShow tt- where- pp :: FilePath -> IO [FilePath]- pp dir = (map (dir </>) . filter not_sub . concat)- <$> for knownExtrasHandlers- (withLexicalCallStack (\f -> f dir))- -- TODO: This is a terrible hack to work around #3545 while we don't- -- reorganize the directory layout. Basically, for the main- -- library, we might accidentally pick up autogenerated sources for- -- our subcomponents, because they are all stored as subdirectories- -- in dist/build. This is a cheap and cheerful check to prevent- -- this from happening. It is not particularly correct; for example- -- if a user has a test suite named foobar and puts their C file in- -- foobar/foo.c, this test will incorrectly exclude it. But I- -- didn't want to break BC...- not_sub p = and [ not (pre `isPrefixOf` p) | pre <- component_dirs ]- component_dirs = component_names (localPkgDescr lbi)- -- TODO: libify me- component_names pkg_descr = fmap unUnqualComponentName $- mapMaybe (libraryNameString . libName) (subLibraries pkg_descr) ++- map exeName (executables pkg_descr) ++- map testName (testSuites pkg_descr) ++- map benchmarkName (benchmarks pkg_descr)
− Distribution/Simple/PreProcess/Unlit.hs
@@ -1,167 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.PreProcess.Unlit--- Copyright : ...------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Remove the \"literal\" markups from a Haskell source file, including--- \"@>@\", \"@\\begin{code}@\", \"@\\end{code}@\", and \"@#@\"---- This version is interesting because instead of striping comment lines, it--- turns them into "-- " style comments. This allows using haddock markup--- in literate scripts without having to use "> --" prefix.--module Distribution.Simple.PreProcess.Unlit (unlit,plain) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.Generic (safeTail, safeLast, safeInit)--import Data.List (mapAccumL)--data Classified = BirdTrack String | Blank String | Ordinary String- | Line !Int String | CPP String- | BeginCode | EndCode- -- output only:- | Error String | Comment String---- | No unliteration.-plain :: String -> String -> String-plain _ hs = hs--classify :: String -> Classified-classify ('>':s) = BirdTrack s-classify ('#':s) = case tokens s of- (line:file@('"':_:_):_) | all isDigit line- && safeLast file == Just '"'- -- this shouldn't fail as we tested for 'all isDigit'- -> Line (fromMaybe (error $ "panic! read @Int " ++ show line) $ readMaybe line) (safeTail (safeInit file)) -- TODO:eradicateNoParse- _ -> CPP s- where tokens = unfoldr $ \str -> case lex str of- (t@(_:_), str'):_ -> Just (t, str')- _ -> Nothing-classify ('\\':s)- | "begin{code}" `isPrefixOf` s = BeginCode- | "end{code}" `isPrefixOf` s = EndCode-classify s | all isSpace s = Blank s-classify s = Ordinary s---- So the weird exception for comment indenting is to make things work with--- haddock, see classifyAndCheckForBirdTracks below.-unclassify :: Bool -> Classified -> String-unclassify _ (BirdTrack s) = ' ':s-unclassify _ (Blank s) = s-unclassify _ (Ordinary s) = s-unclassify _ (Line n file) = "# " ++ show n ++ " " ++ show file-unclassify _ (CPP s) = '#':s-unclassify True (Comment "") = " --"-unclassify True (Comment s) = " -- " ++ s-unclassify False (Comment "") = "--"-unclassify False (Comment s) = "-- " ++ s-unclassify _ _ = internalError---- | 'unlit' takes a filename (for error reports), and transforms the--- given string, to eliminate the literate comments from the program text.-unlit :: FilePath -> String -> Either String String-unlit file input =- let (usesBirdTracks, classified) = classifyAndCheckForBirdTracks- . inlines- $ input- in either (Left . unlines . map (unclassify usesBirdTracks))- Right- . checkErrors- . reclassify- $ classified-- where- -- So haddock requires comments and code to align, since it treats comments- -- as following the layout rule. This is a pain for us since bird track- -- style literate code typically gets indented by two since ">" is replaced- -- by " " and people usually use one additional space of indent ie- -- "> then the code". On the other hand we cannot just go and indent all- -- the comments by two since that does not work for latex style literate- -- code. So the hacky solution we use here is that if we see any bird track- -- style code then we'll indent all comments by two, otherwise by none.- -- Of course this will not work for mixed latex/bird track .lhs files but- -- nobody does that, it's silly and specifically recommended against in the- -- H98 unlit spec.- --- classifyAndCheckForBirdTracks =- flip mapAccumL False $ \seenBirdTrack line ->- let classification = classify line- in (seenBirdTrack || isBirdTrack classification, classification)-- isBirdTrack (BirdTrack _) = True- isBirdTrack _ = False-- checkErrors ls = case [ e | Error e <- ls ] of- [] -> Left ls- (message:_) -> Right (f ++ ":" ++ show n ++ ": " ++ message)- where (f, n) = errorPos file 1 ls- errorPos f n [] = (f, n)- errorPos f n (Error _:_) = (f, n)- errorPos _ _ (Line n' f':ls) = errorPos f' n' ls- errorPos f n (_ :ls) = errorPos f (n+1) ls---- Here we model a state machine, with each state represented by--- a local function. We only have four states (well, five,--- if you count the error state), but the rules--- to transition between then are not so simple.--- Would it be simpler to have more states?------ Each state represents the type of line that was last read--- i.e. are we in a comment section, or a latex-code section,--- or a bird-code section, etc?-reclassify :: [Classified] -> [Classified]-reclassify = blank -- begin in blank state- where- latex [] = []- latex (EndCode :ls) = Blank "" : comment ls- latex (BeginCode :_ ) = [Error "\\begin{code} in code section"]- latex (BirdTrack l:ls) = Ordinary ('>':l) : latex ls- latex ( l:ls) = l : latex ls-- blank [] = []- blank (EndCode :_ ) = [Error "\\end{code} without \\begin{code}"]- blank (BeginCode :ls) = Blank "" : latex ls- blank (BirdTrack l:ls) = BirdTrack l : bird ls- blank (Ordinary l:ls) = Comment l : comment ls- blank ( l:ls) = l : blank ls-- bird [] = []- bird (EndCode :_ ) = [Error "\\end{code} without \\begin{code}"]- bird (BeginCode :ls) = Blank "" : latex ls- bird (Blank l :ls) = Blank l : blank ls- bird (Ordinary _:_ ) = [Error "program line before comment line"]- bird ( l:ls) = l : bird ls-- comment [] = []- comment (EndCode :_ ) = [Error "\\end{code} without \\begin{code}"]- comment (BeginCode :ls) = Blank "" : latex ls- comment (CPP l :ls) = CPP l : comment ls- comment (BirdTrack _:_ ) = [Error "comment line before program line"]- -- a blank line and another ordinary line following a comment- -- will be treated as continuing the comment. Otherwise it's- -- then end of the comment, with a blank line.- comment (Blank l:ls@(Ordinary _:_)) = Comment l : comment ls- comment (Blank l:ls) = Blank l : blank ls- comment (Line n f :ls) = Line n f : comment ls- comment (Ordinary l:ls) = Comment l : comment ls- comment (Comment _: _) = internalError- comment (Error _: _) = internalError---- Re-implementation of 'lines', for better efficiency (but decreased laziness).--- Also, importantly, accepts non-standard DOS and Mac line ending characters.-inlines :: String -> [String]-inlines xs = lines' xs id- where- lines' [] acc = [acc []]- lines' ('\^M':'\n':s) acc = acc [] : lines' s id -- DOS- lines' ('\^M':s) acc = acc [] : lines' s id -- MacOS- lines' ('\n':s) acc = acc [] : lines' s id -- Unix- lines' (c:s) acc = lines' s (acc . (c:))--internalError :: a-internalError = error "unlit: internal error"
− Distribution/Simple/Program.hs
@@ -1,183 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program--- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This provides an abstraction which deals with configuring and running--- programs. A 'Program' is a static notion of a known program. A--- 'ConfiguredProgram' is a 'Program' that has been found on the current--- machine and is ready to be run (possibly with some user-supplied default--- args). Configuring a program involves finding its location and if necessary--- finding its version. There is also a 'ProgramDb' type which holds--- configured and not-yet configured programs. It is the parameter to lots of--- actions elsewhere in Cabal that need to look up and run programs. If we had--- a Cabal monad, the 'ProgramDb' would probably be a reader or--- state component of it.------ The module also defines all the known built-in 'Program's and the--- 'defaultProgramDb' which contains them all.------ One nice thing about using it is that any program that is--- registered with Cabal will get some \"configure\" and \".cabal\"--- helpers like --with-foo-args --foo-path= and extra-foo-args.------ There's also good default behavior for trying to find \"foo\" in--- PATH, being able to override its location, etc.------ There's also a hook for adding programs in a Setup.lhs script. See--- hookedPrograms in 'Distribution.Simple.UserHooks'. This gives a--- hook user the ability to get the above flags and such so that they--- don't have to write all the PATH logic inside Setup.lhs.--module Distribution.Simple.Program (- -- * Program and functions for constructing them- Program(..)- , ProgramSearchPath- , ProgramSearchPathEntry(..)- , simpleProgram- , findProgramOnSearchPath- , defaultProgramSearchPath- , findProgramVersion-- -- * Configured program and related functions- , ConfiguredProgram(..)- , programPath- , ProgArg- , ProgramLocation(..)- , runProgram- , getProgramOutput- , suppressOverrideArgs-- -- * Program invocations- , ProgramInvocation(..)- , emptyProgramInvocation- , simpleProgramInvocation- , programInvocation- , runProgramInvocation- , getProgramInvocationOutput- , getProgramInvocationLBS-- -- * The collection of unconfigured and configured programs- , builtinPrograms-- -- * The collection of configured programs we can run- , ProgramDb- , defaultProgramDb- , emptyProgramDb- , restoreProgramDb- , addKnownProgram- , addKnownPrograms- , lookupKnownProgram- , knownPrograms- , getProgramSearchPath- , setProgramSearchPath- , userSpecifyPath- , userSpecifyPaths- , userMaybeSpecifyPath- , userSpecifyArgs- , userSpecifyArgss- , userSpecifiedArgs- , lookupProgram- , lookupProgramVersion- , updateProgram- , configureProgram- , configureAllKnownPrograms- , reconfigurePrograms- , requireProgram- , requireProgramVersion- , needProgram- , runDbProgram- , getDbProgramOutput-- -- * Programs that Cabal knows about- , ghcProgram- , ghcPkgProgram- , ghcjsProgram- , ghcjsPkgProgram- , hmakeProgram- , jhcProgram- , uhcProgram- , gccProgram- , arProgram- , stripProgram- , happyProgram- , alexProgram- , hsc2hsProgram- , c2hsProgram- , cpphsProgram- , hscolourProgram- , doctestProgram- , haddockProgram- , greencardProgram- , ldProgram- , tarProgram- , cppProgram- , pkgConfigProgram- , hpcProgram- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.Program.Types-import Distribution.Simple.Program.Run-import Distribution.Simple.Program.Db-import Distribution.Simple.Program.Builtin-import Distribution.Simple.Program.Find-import Distribution.Simple.Utils-import Distribution.Verbosity---- | Runs the given configured program.-runProgram :: Verbosity -- ^Verbosity- -> ConfiguredProgram -- ^The program to run- -> [ProgArg] -- ^Any /extra/ arguments to add- -> IO ()-runProgram verbosity prog args =- runProgramInvocation verbosity (programInvocation prog args)----- | Runs the given configured program and gets the output.----getProgramOutput :: Verbosity -- ^Verbosity- -> ConfiguredProgram -- ^The program to run- -> [ProgArg] -- ^Any /extra/ arguments to add- -> IO String-getProgramOutput verbosity prog args =- getProgramInvocationOutput verbosity (programInvocation prog args)----- | Looks up the given program in the program database and runs it.----runDbProgram :: Verbosity -- ^verbosity- -> Program -- ^The program to run- -> ProgramDb -- ^look up the program here- -> [ProgArg] -- ^Any /extra/ arguments to add- -> IO ()-runDbProgram verbosity prog programDb args =- case lookupProgram prog programDb of- Nothing -> die' verbosity notFound- Just configuredProg -> runProgram verbosity configuredProg args- where- notFound = "The program '" ++ programName prog- ++ "' is required but it could not be found"---- | Looks up the given program in the program database and runs it.----getDbProgramOutput :: Verbosity -- ^verbosity- -> Program -- ^The program to run- -> ProgramDb -- ^look up the program here- -> [ProgArg] -- ^Any /extra/ arguments to add- -> IO String-getDbProgramOutput verbosity prog programDb args =- case lookupProgram prog programDb of- Nothing -> die' verbosity notFound- Just configuredProg -> getProgramOutput verbosity configuredProg args- where- notFound = "The program '" ++ programName prog- ++ "' is required but it could not be found"
− Distribution/Simple/Program/Ar.hs
@@ -1,191 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE NondecreasingIndentation #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Ar--- Copyright : Duncan Coutts 2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides an library interface to the @ar@ program.--module Distribution.Simple.Program.Ar (- createArLibArchive,- multiStageProgramInvocation- ) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS8-import Distribution.Compat.CopyFile (filesEqual)-import Distribution.Simple.Compiler (arResponseFilesSupported)-import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))-import Distribution.Simple.Program- ( ProgramInvocation, arProgram, requireProgram )-import Distribution.Simple.Program.ResponseFile- ( withResponseFile )-import Distribution.Simple.Program.Run- ( programInvocation, multiStageProgramInvocation- , runProgramInvocation )-import Distribution.Simple.Setup- ( fromFlagOrDefault, configUseResponseFiles )-import Distribution.Simple.Utils- ( defaultTempFileOptions, dieWithLocation', withTempDirectory )-import Distribution.System- ( Arch(..), OS(..), Platform(..) )-import Distribution.Verbosity- ( Verbosity, deafening, verbose )-import System.Directory (doesFileExist, renameFile)-import System.FilePath ((</>), splitFileName)-import System.IO- ( Handle, IOMode(ReadWriteMode), SeekMode(AbsoluteSeek)- , hFileSize, hSeek, withBinaryFile )---- | Call @ar@ to create a library archive from a bunch of object files.----createArLibArchive :: Verbosity -> LocalBuildInfo- -> FilePath -> [FilePath] -> IO ()-createArLibArchive verbosity lbi targetPath files = do- (ar, _) <- requireProgram verbosity arProgram progDb-- let (targetDir, targetName) = splitFileName targetPath- withTempDirectory verbosity targetDir "objs" $ \ tmpDir -> do- let tmpPath = tmpDir </> targetName-- -- The args to use with "ar" are actually rather subtle and system-dependent.- -- In particular we have the following issues:- --- -- -- On OS X, "ar q" does not make an archive index. Archives with no- -- index cannot be used.- --- -- -- GNU "ar r" will not let us add duplicate objects, only "ar q" lets us- -- do that. We have duplicates because of modules like "A.M" and "B.M"- -- both make an object file "M.o" and ar does not consider the directory.- --- -- Our solution is to use "ar r" in the simple case when one call is enough.- -- When we need to call ar multiple times we use "ar q" and for the last- -- call on OSX we use "ar qs" so that it'll make the index.-- let simpleArgs = case hostOS of- OSX -> ["-r", "-s"]- _ -> ["-r"]-- initialArgs = ["-q"]- finalArgs = case hostOS of- OSX -> ["-q", "-s"]- _ -> ["-q"]-- extraArgs = verbosityOpts verbosity ++ [tmpPath]-- simple = programInvocation ar (simpleArgs ++ extraArgs)- initial = programInvocation ar (initialArgs ++ extraArgs)- middle = initial- final = programInvocation ar (finalArgs ++ extraArgs)-- oldVersionManualOverride =- fromFlagOrDefault False $ configUseResponseFiles $ configFlags lbi- responseArgumentsNotSupported =- not (arResponseFilesSupported (compiler lbi))-- invokeWithResponesFile :: FilePath -> ProgramInvocation- invokeWithResponesFile atFile =- programInvocation ar $- simpleArgs ++ extraArgs ++ ['@' : atFile]-- if oldVersionManualOverride || responseArgumentsNotSupported- then- sequence_- [ runProgramInvocation verbosity inv- | inv <- multiStageProgramInvocation- simple (initial, middle, final) files ]- else- withResponseFile verbosity defaultTempFileOptions tmpDir "ar.rsp" Nothing files $- \path -> runProgramInvocation verbosity $ invokeWithResponesFile path-- unless (hostArch == Arm -- See #1537- || hostOS == AIX) $ -- AIX uses its own "ar" format variant- wipeMetadata verbosity tmpPath- equal <- filesEqual tmpPath targetPath- unless equal $ renameFile tmpPath targetPath-- where- progDb = withPrograms lbi- Platform hostArch hostOS = hostPlatform lbi- verbosityOpts v- | v >= deafening = ["-v"]- | v >= verbose = []- | otherwise = ["-c"] -- Do not warn if library had to be created.---- | @ar@ by default includes various metadata for each object file in their--- respective headers, so the output can differ for the same inputs, making--- it difficult to avoid re-linking. GNU @ar@(1) has a deterministic mode--- (@-D@) flag that always writes zero for the mtime, UID and GID, and 0644--- for the file mode. However detecting whether @-D@ is supported seems--- rather harder than just re-implementing this feature.-wipeMetadata :: Verbosity -> FilePath -> IO ()-wipeMetadata verbosity path = do- -- Check for existence first (ReadWriteMode would create one otherwise)- exists <- doesFileExist path- unless exists $ wipeError "Temporary file disappeared"- withBinaryFile path ReadWriteMode $ \ h -> hFileSize h >>= wipeArchive h-- where- wipeError msg = dieWithLocation' verbosity path Nothing $- "Distribution.Simple.Program.Ar.wipeMetadata: " ++ msg- archLF = "!<arch>\x0a" -- global magic, 8 bytes- x60LF = "\x60\x0a" -- header magic, 2 bytes- metadata = BS.concat- [ "0 " -- mtime, 12 bytes- , "0 " -- UID, 6 bytes- , "0 " -- GID, 6 bytes- , "0644 " -- mode, 8 bytes- ]- headerSize :: Int- headerSize = 60-- -- http://en.wikipedia.org/wiki/Ar_(Unix)#File_format_details- wipeArchive :: Handle -> Integer -> IO ()- wipeArchive h archiveSize = do- global <- BS.hGet h (BS.length archLF)- unless (global == archLF) $ wipeError "Bad global header"- wipeHeader (toInteger $ BS.length archLF)-- where- wipeHeader :: Integer -> IO ()- wipeHeader offset = case compare offset archiveSize of- EQ -> return ()- GT -> wipeError (atOffset "Archive truncated")- LT -> do- header <- BS.hGet h headerSize- unless (BS.length header == headerSize) $- wipeError (atOffset "Short header")- let magic = BS.drop 58 header- unless (magic == x60LF) . wipeError . atOffset $- "Bad magic " ++ show magic ++ " in header"-- let name = BS.take 16 header- let size = BS.take 10 $ BS.drop 48 header- objSize <- case reads (BS8.unpack size) of- [(n, s)] | all isSpace s -> return n- _ -> wipeError (atOffset "Bad file size in header")-- let replacement = BS.concat [ name, metadata, size, magic ]- unless (BS.length replacement == headerSize) $- wipeError (atOffset "Something has gone terribly wrong")- hSeek h AbsoluteSeek offset- BS.hPut h replacement-- let nextHeader = offset + toInteger headerSize +- -- Odd objects are padded with an extra '\x0a'- if odd objSize then objSize + 1 else objSize- hSeek h AbsoluteSeek nextHeader- wipeHeader nextHeader-- where- atOffset msg = msg ++ " at offset " ++ show offset
− Distribution/Simple/Program/Builtin.hs
@@ -1,348 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Builtin--- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ The module defines all the known built-in 'Program's.------ Where possible we try to find their version numbers.----module Distribution.Simple.Program.Builtin (-- -- * The collection of unconfigured and configured programs- builtinPrograms,-- -- * Programs that Cabal knows about- ghcProgram,- ghcPkgProgram,- runghcProgram,- ghcjsProgram,- ghcjsPkgProgram,- hmakeProgram,- jhcProgram,- haskellSuiteProgram,- haskellSuitePkgProgram,- uhcProgram,- gccProgram,- arProgram,- stripProgram,- happyProgram,- alexProgram,- hsc2hsProgram,- c2hsProgram,- cpphsProgram,- hscolourProgram,- doctestProgram,- haddockProgram,- greencardProgram,- ldProgram,- tarProgram,- cppProgram,- pkgConfigProgram,- hpcProgram,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.Program.GHC-import Distribution.Simple.Program.Find-import Distribution.Simple.Program.Internal-import Distribution.Simple.Program.Run-import Distribution.Simple.Program.Types-import Distribution.Simple.Utils-import Distribution.Verbosity-import Distribution.Version--import qualified Data.Map as Map---- --------------------------------------------------------------- * Known programs--- ---------------------------------------------------------------- | The default list of programs.--- These programs are typically used internally to Cabal.-builtinPrograms :: [Program]-builtinPrograms =- [- -- compilers and related progs- ghcProgram- , runghcProgram- , ghcPkgProgram- , ghcjsProgram- , ghcjsPkgProgram- , haskellSuiteProgram- , haskellSuitePkgProgram- , hmakeProgram- , jhcProgram- , uhcProgram- , hpcProgram- -- preprocessors- , hscolourProgram- , doctestProgram- , haddockProgram- , happyProgram- , alexProgram- , hsc2hsProgram- , c2hsProgram- , cpphsProgram- , greencardProgram- -- platform toolchain- , gccProgram- , arProgram- , stripProgram- , ldProgram- , tarProgram- -- configuration tools- , pkgConfigProgram- ]--ghcProgram :: Program-ghcProgram = (simpleProgram "ghc") {- programFindVersion = findProgramVersion "--numeric-version" id,-- -- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/8825- -- (spurious warning on non-english locales)- programPostConf = \_verbosity ghcProg ->- do let ghcProg' = ghcProg {- programOverrideEnv = ("LANGUAGE", Just "en")- : programOverrideEnv ghcProg- }- -- Only the 7.8 branch seems to be affected. Fixed in 7.8.4.- affectedVersionRange = intersectVersionRanges- (laterVersion $ mkVersion [7,8,0])- (earlierVersion $ mkVersion [7,8,4])- return $ maybe ghcProg- (\v -> if withinRange v affectedVersionRange- then ghcProg' else ghcProg)- (programVersion ghcProg),-- programNormaliseArgs = normaliseGhcArgs- }--runghcProgram :: Program-runghcProgram = (simpleProgram "runghc") {- programFindVersion = findProgramVersion "--version" $ \str ->- case words str of- -- "runghc 7.10.3"- (_:ver:_) -> ver- _ -> ""- }--ghcPkgProgram :: Program-ghcPkgProgram = (simpleProgram "ghc-pkg") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- Invoking "ghc-pkg --version" gives a string like- -- "GHC package manager version 6.4.1"- case words str of- (_:_:_:_:ver:_) -> ver- _ -> ""- }--ghcjsProgram :: Program-ghcjsProgram = (simpleProgram "ghcjs") {- programFindVersion = findProgramVersion "--numeric-ghcjs-version" id- }---- note: version is the version number of the GHC version that ghcjs-pkg was built with-ghcjsPkgProgram :: Program-ghcjsPkgProgram = (simpleProgram "ghcjs-pkg") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- Invoking "ghcjs-pkg --version" gives a string like- -- "GHCJS package manager version 6.4.1"- case words str of- (_:_:_:_:ver:_) -> ver- _ -> ""- }--hmakeProgram :: Program-hmakeProgram = (simpleProgram "hmake") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- Invoking "hmake --version" gives a string line- -- "/usr/local/bin/hmake: 3.13 (2006-11-01)"- case words str of- (_:ver:_) -> ver- _ -> ""- }--jhcProgram :: Program-jhcProgram = (simpleProgram "jhc") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- invoking "jhc --version" gives a string like- -- "jhc 0.3.20080208 (wubgipkamcep-2)- -- compiled by ghc-6.8 on a x86_64 running linux"- case words str of- (_:ver:_) -> ver- _ -> ""- }--uhcProgram :: Program-uhcProgram = (simpleProgram "uhc") {- programFindVersion = findProgramVersion "--version-dotted" id- }--hpcProgram :: Program-hpcProgram = (simpleProgram "hpc")- {- programFindVersion = findProgramVersion "version" $ \str ->- case words str of- (_ : _ : _ : ver : _) -> ver- _ -> ""- }---- This represents a haskell-suite compiler. Of course, the compiler--- itself probably is not called "haskell-suite", so this is not a real--- program. (But we don't know statically the name of the actual compiler,--- so this is the best we can do.)------ Having this Program value serves two purposes:------ 1. We can accept options for the compiler in the form of------ --haskell-suite-option(s)=...------ 2. We can find a program later using this static id (with--- requireProgram).------ The path to the real compiler is found and recorded in the ProgramDb--- during the configure phase.-haskellSuiteProgram :: Program-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", [])- }---- 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", [])- }---happyProgram :: Program-happyProgram = (simpleProgram "happy") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- Invoking "happy --version" gives a string like- -- "Happy Version 1.16 Copyright (c) ...."- case words str of- (_:_:ver:_) -> ver- _ -> ""- }--alexProgram :: Program-alexProgram = (simpleProgram "alex") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- Invoking "alex --version" gives a string like- -- "Alex version 2.1.0, (c) 2003 Chris Dornan and Simon Marlow"- case words str of- (_:_:ver:_) -> takeWhile (\x -> isDigit x || x == '.') ver- _ -> ""- }--gccProgram :: Program-gccProgram = (simpleProgram "gcc") {- programFindVersion = findProgramVersion "-dumpversion" id- }--arProgram :: Program-arProgram = simpleProgram "ar"--stripProgram :: Program-stripProgram = (simpleProgram "strip") {- programFindVersion = \verbosity ->- findProgramVersion "--version" stripExtractVersion (lessVerbose verbosity)- }--hsc2hsProgram :: Program-hsc2hsProgram = (simpleProgram "hsc2hs") {- programFindVersion =- findProgramVersion "--version" $ \str ->- -- Invoking "hsc2hs --version" gives a string like "hsc2hs version 0.66"- case words str of- (_:_:ver:_) -> ver- _ -> ""- }--c2hsProgram :: Program-c2hsProgram = (simpleProgram "c2hs") {- programFindVersion = findProgramVersion "--numeric-version" id- }--cpphsProgram :: Program-cpphsProgram = (simpleProgram "cpphs") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- Invoking "cpphs --version" gives a string like "cpphs 1.3"- case words str of- (_:ver:_) -> ver- _ -> ""- }--hscolourProgram :: Program-hscolourProgram = (simpleProgram "hscolour") {- programFindLocation = \v p -> findProgramOnSearchPath v p "HsColour",- programFindVersion = findProgramVersion "-version" $ \str ->- -- Invoking "HsColour -version" gives a string like "HsColour 1.7"- case words str of- (_:ver:_) -> ver- _ -> ""- }---- TODO: Ensure that doctest is built against the same GHC as the one--- that's being used. Same for haddock. @phadej pointed this out.-doctestProgram :: Program-doctestProgram = (simpleProgram "doctest") {- programFindLocation = \v p -> findProgramOnSearchPath v p "doctest"- , programFindVersion = findProgramVersion "--version" $ \str ->- -- "doctest version 0.11.2"- case words str of- (_:_:ver:_) -> ver- _ -> ""- }--haddockProgram :: Program-haddockProgram = (simpleProgram "haddock") {- programFindVersion = findProgramVersion "--version" $ \str ->- -- Invoking "haddock --version" gives a string like- -- "Haddock version 0.8, (c) Simon Marlow 2006"- case words str of- (_:_:ver:_) -> takeWhile (`elem` ('.':['0'..'9'])) ver- _ -> "",-- programNormaliseArgs = \_ _ args -> args- }--greencardProgram :: Program-greencardProgram = simpleProgram "greencard"--ldProgram :: Program-ldProgram = simpleProgram "ld"--tarProgram :: Program-tarProgram = (simpleProgram "tar") {- -- See #1901. Some versions of 'tar' (OpenBSD, NetBSD, ...) don't support the- -- '--format' option.- programPostConf = \verbosity tarProg -> do- tarHelpOutput <- getProgramInvocationOutput- verbosity (programInvocation tarProg ["--help"])- -- Some versions of tar don't support '--help'.- `catchIO` (\_ -> return "")- let k = "Supports --format"- v = if ("--format" `isInfixOf` tarHelpOutput) then "YES" else "NO"- m = Map.insert k v (programProperties tarProg)- return $ tarProg { programProperties = m }- }--cppProgram :: Program-cppProgram = simpleProgram "cpp"--pkgConfigProgram :: Program-pkgConfigProgram = (simpleProgram "pkg-config") {- programFindVersion = findProgramVersion "--version" id- }
− Distribution/Simple/Program/Db.hs
@@ -1,505 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Db--- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This provides a 'ProgramDb' type which holds configured and not-yet--- configured programs. It is the parameter to lots of actions elsewhere in--- Cabal that need to look up and run programs. If we had a Cabal monad,--- the 'ProgramDb' would probably be a reader or state component of it.------ One nice thing about using it is that any program that is--- registered with Cabal will get some \"configure\" and \".cabal\"--- helpers like --with-foo-args --foo-path= and extra-foo-args.------ There's also a hook for adding programs in a Setup.lhs script. See--- hookedPrograms in 'Distribution.Simple.UserHooks'. This gives a--- hook user the ability to get the above flags and such so that they--- don't have to write all the PATH logic inside Setup.lhs.--module Distribution.Simple.Program.Db (- -- * The collection of configured programs we can run- ProgramDb,- emptyProgramDb,- defaultProgramDb,- restoreProgramDb,-- -- ** Query and manipulate the program db- addKnownProgram,- addKnownPrograms,- lookupKnownProgram,- knownPrograms,- getProgramSearchPath,- setProgramSearchPath,- modifyProgramSearchPath,- userSpecifyPath,- userSpecifyPaths,- userMaybeSpecifyPath,- userSpecifyArgs,- userSpecifyArgss,- userSpecifiedArgs,- lookupProgram,- updateProgram,- configuredPrograms,-- -- ** Query and manipulate the program db- configureProgram,- configureAllKnownPrograms,- unconfigureProgram,- lookupProgramVersion,- reconfigurePrograms,- requireProgram,- requireProgramVersion,- needProgram,-- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Pretty-import Distribution.Simple.Program.Builtin-import Distribution.Simple.Program.Find-import Distribution.Simple.Program.Types-import Distribution.Simple.Utils-import Distribution.Utils.Structured (Structure (..), Structured (..))-import Distribution.Verbosity-import Distribution.Version--import Data.Tuple (swap)--import qualified Data.Map as Map---- --------------------------------------------------------------- * Programs database--- ---------------------------------------------------------------- | The configuration is a collection of information about programs. It--- contains information both about configured programs and also about programs--- that we are yet to configure.------ The idea is that we start from a collection of unconfigured programs and one--- by one we try to configure them at which point we move them into the--- configured collection. For unconfigured programs we record not just the--- 'Program' but also any user-provided arguments and location for the program.-data ProgramDb = ProgramDb {- unconfiguredProgs :: UnconfiguredProgs,- progSearchPath :: ProgramSearchPath,- configuredProgs :: ConfiguredProgs- }- deriving (Typeable)--type UnconfiguredProgram = (Program, Maybe FilePath, [ProgArg])-type UnconfiguredProgs = Map.Map String UnconfiguredProgram-type ConfiguredProgs = Map.Map String ConfiguredProgram---emptyProgramDb :: ProgramDb-emptyProgramDb = ProgramDb Map.empty defaultProgramSearchPath Map.empty--defaultProgramDb :: ProgramDb-defaultProgramDb = restoreProgramDb builtinPrograms emptyProgramDb----- internal helpers:-updateUnconfiguredProgs :: (UnconfiguredProgs -> UnconfiguredProgs)- -> ProgramDb -> ProgramDb-updateUnconfiguredProgs update progdb =- progdb { unconfiguredProgs = update (unconfiguredProgs progdb) }--updateConfiguredProgs :: (ConfiguredProgs -> ConfiguredProgs)- -> ProgramDb -> ProgramDb-updateConfiguredProgs update progdb =- progdb { configuredProgs = update (configuredProgs progdb) }----- Read & Show instances are based on listToFM---- | 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 db = do- put (progSearchPath db)- put (configuredProgs db)-- get = do- searchpath <- get- progs <- get- return $! emptyProgramDb {- progSearchPath = searchpath,- configuredProgs = progs- }--instance Structured ProgramDb where- structure p = Nominal (typeRep p) 0 "ProgramDb"- [ structure (Proxy :: Proxy ProgramSearchPath)- , structure (Proxy :: Proxy ConfiguredProgs)- ]----- | 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.----restoreProgramDb :: [Program] -> ProgramDb -> ProgramDb-restoreProgramDb = addKnownPrograms----- ---------------------------------- Managing unconfigured programs---- | Add a known program that we may configure later----addKnownProgram :: Program -> ProgramDb -> ProgramDb-addKnownProgram prog = updateUnconfiguredProgs $- Map.insertWith combine (programName prog) (prog, Nothing, [])- where combine _ (_, path, args) = (prog, path, args)---addKnownPrograms :: [Program] -> ProgramDb -> ProgramDb-addKnownPrograms progs progdb = foldl' (flip addKnownProgram) progdb progs---lookupKnownProgram :: String -> ProgramDb -> Maybe Program-lookupKnownProgram name =- fmap (\(p,_,_)->p) . Map.lookup name . unconfiguredProgs---knownPrograms :: ProgramDb -> [(Program, Maybe ConfiguredProgram)]-knownPrograms progdb =- [ (p,p') | (p,_,_) <- Map.elems (unconfiguredProgs progdb)- , let p' = Map.lookup (programName p) (configuredProgs progdb) ]---- | Get the current 'ProgramSearchPath' used by the 'ProgramDb'.--- This is the default list of locations where programs are looked for when--- configuring them. This can be overridden for specific programs (with--- 'userSpecifyPath'), and specific known programs can modify or ignore this--- search path in their own configuration code.----getProgramSearchPath :: ProgramDb -> ProgramSearchPath-getProgramSearchPath = progSearchPath---- | Change the current 'ProgramSearchPath' used by the 'ProgramDb'.--- This will affect programs that are configured from here on, so you--- should usually set it before configuring any programs.----setProgramSearchPath :: ProgramSearchPath -> ProgramDb -> ProgramDb-setProgramSearchPath searchpath db = db { progSearchPath = searchpath }---- | Modify the current 'ProgramSearchPath' used by the 'ProgramDb'.--- This will affect programs that are configured from here on, so you--- should usually modify it before configuring any programs.----modifyProgramSearchPath :: (ProgramSearchPath -> ProgramSearchPath)- -> ProgramDb- -> ProgramDb-modifyProgramSearchPath f db =- setProgramSearchPath (f $ getProgramSearchPath db) db---- |User-specify this path. Basically override any path information--- for this program in the configuration. If it's not a known--- program ignore it.----userSpecifyPath :: String -- ^Program name- -> FilePath -- ^user-specified path to the program- -> ProgramDb -> ProgramDb-userSpecifyPath name path = updateUnconfiguredProgs $- flip Map.update name $ \(prog, _, args) -> Just (prog, Just path, args)---userMaybeSpecifyPath :: String -> Maybe FilePath- -> ProgramDb -> ProgramDb-userMaybeSpecifyPath _ Nothing progdb = progdb-userMaybeSpecifyPath name (Just path) progdb = userSpecifyPath name path progdb----- |User-specify the arguments for this program. Basically override--- any args information for this program in the configuration. If it's--- not a known program, ignore it..-userSpecifyArgs :: String -- ^Program name- -> [ProgArg] -- ^user-specified args- -> ProgramDb- -> ProgramDb-userSpecifyArgs name args' =- updateUnconfiguredProgs- (flip Map.update name $- \(prog, path, args) -> Just (prog, path, args ++ args'))- . updateConfiguredProgs- (flip Map.update name $- \prog -> Just prog { programOverrideArgs = programOverrideArgs prog- ++ args' })----- | Like 'userSpecifyPath' but for a list of progs and their paths.----userSpecifyPaths :: [(String, FilePath)]- -> ProgramDb- -> ProgramDb-userSpecifyPaths paths progdb =- foldl' (\progdb' (prog, path) -> userSpecifyPath prog path progdb') progdb paths----- | Like 'userSpecifyPath' but for a list of progs and their args.----userSpecifyArgss :: [(String, [ProgArg])]- -> ProgramDb- -> ProgramDb-userSpecifyArgss argss progdb =- foldl' (\progdb' (prog, args) -> userSpecifyArgs prog args progdb') progdb argss----- | Get the path that has been previously specified for a program, if any.----userSpecifiedPath :: Program -> ProgramDb -> Maybe FilePath-userSpecifiedPath prog =- join . fmap (\(_,p,_)->p) . Map.lookup (programName prog) . unconfiguredProgs----- | Get any extra args that have been previously specified for a program.----userSpecifiedArgs :: Program -> ProgramDb -> [ProgArg]-userSpecifiedArgs prog =- maybe [] (\(_,_,as)->as) . Map.lookup (programName prog) . unconfiguredProgs----- -------------------------------- Managing configured programs---- | Try to find a configured program-lookupProgram :: Program -> ProgramDb -> Maybe ConfiguredProgram-lookupProgram prog = Map.lookup (programName prog) . configuredProgs----- | Update a configured program in the database.-updateProgram :: ConfiguredProgram -> ProgramDb- -> ProgramDb-updateProgram prog = updateConfiguredProgs $- Map.insert (programId prog) prog----- | List all configured programs.-configuredPrograms :: ProgramDb -> [ConfiguredProgram]-configuredPrograms = Map.elems . configuredProgs---- ------------------------------ Configuring known programs---- | Try to configure a specific program. If the program is already included in--- the collection of unconfigured programs then we use any user-supplied--- location and arguments. If the program gets configured successfully it gets--- added to the configured collection.------ Note that it is not a failure if the program cannot be configured. It's only--- a failure if the user supplied a location and the program could not be found--- at that location.------ The reason for it not being a failure at this stage is that we don't know up--- front all the programs we will need, so we try to configure them all.--- To verify that a program was actually successfully configured use--- 'requireProgram'.----configureProgram :: Verbosity- -> Program- -> ProgramDb- -> IO ProgramDb-configureProgram verbosity prog progdb = do- let name = programName prog- maybeLocation <- case userSpecifiedPath prog progdb of- Nothing ->- programFindLocation prog verbosity (progSearchPath progdb)- >>= return . fmap (swap . fmap FoundOnSystem . swap)- Just path -> do- absolute <- doesExecutableExist path- if absolute- then return (Just (UserSpecified path, []))- else findProgramOnSearchPath verbosity (progSearchPath progdb) path- >>= maybe (die' verbosity 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 progdb- Just (location, triedLocations) -> do- version <- programFindVersion prog verbosity (locationPath location)- newPath <- programSearchPathAsPATHVar (progSearchPath progdb)- let configuredProg = ConfiguredProgram {- programId = name,- programVersion = version,- programDefaultArgs = [],- programOverrideArgs = userSpecifiedArgs prog progdb,- programOverrideEnv = [("PATH", Just newPath)],- programProperties = Map.empty,- programLocation = location,- programMonitorFiles = triedLocations- }- configuredProg' <- programPostConf prog verbosity configuredProg- return (updateConfiguredProgs (Map.insert name configuredProg') progdb)----- | Configure a bunch of programs using 'configureProgram'. Just a 'foldM'.----configurePrograms :: Verbosity- -> [Program]- -> ProgramDb- -> IO ProgramDb-configurePrograms verbosity progs progdb =- foldM (flip (configureProgram verbosity)) progdb progs----- | Unconfigure a program. This is basically a hack and you shouldn't--- use it, but it can be handy for making sure a 'requireProgram'--- actually reconfigures.-unconfigureProgram :: String -> ProgramDb -> ProgramDb-unconfigureProgram progname =- updateConfiguredProgs $ Map.delete progname---- | Try to configure all the known programs that have not yet been configured.----configureAllKnownPrograms :: Verbosity- -> ProgramDb- -> IO ProgramDb-configureAllKnownPrograms verbosity progdb =- configurePrograms verbosity- [ prog | (prog,_,_) <- Map.elems notYetConfigured ] progdb- where- notYetConfigured = unconfiguredProgs progdb- `Map.difference` configuredProgs progdb----- | reconfigure a bunch of programs given new user-specified args. It takes--- the same inputs as 'userSpecifyPath' and 'userSpecifyArgs' and for all progs--- with a new path it calls 'configureProgram'.----reconfigurePrograms :: Verbosity- -> [(String, FilePath)]- -> [(String, [ProgArg])]- -> ProgramDb- -> IO ProgramDb-reconfigurePrograms verbosity paths argss progdb = do- configurePrograms verbosity progs- . userSpecifyPaths paths- . userSpecifyArgss argss- $ progdb-- where- progs = catMaybes [ lookupKnownProgram name progdb | (name,_) <- paths ]----- | Check that a program is configured and available to be run.------ It raises an exception if the program could not be configured, otherwise--- it returns the configured program.----requireProgram :: Verbosity -> Program -> ProgramDb- -> IO (ConfiguredProgram, ProgramDb)-requireProgram verbosity prog progdb = do- mres <- needProgram verbosity prog progdb- case mres of- Nothing -> die' verbosity notFound- Just res -> return res- where- notFound = "The program '" ++ programName prog ++ "' is required but it could not be found."---- | Check that a program is configured and available to be run.------ It returns 'Nothing' if the program couldn't be configured,--- or is not found.------ @since 3.0.1.0-needProgram :: Verbosity -> Program -> ProgramDb- -> IO (Maybe (ConfiguredProgram, ProgramDb))-needProgram verbosity prog progdb = do-- -- If it's not already been configured, try to configure it now- progdb' <- case lookupProgram prog progdb of- Nothing -> configureProgram verbosity prog progdb- Just _ -> return progdb-- case lookupProgram prog progdb' of- Nothing -> return Nothing- Just configuredProg -> return (Just (configuredProg, progdb'))---- | Check that a program is configured and available to be run.------ Additionally check that the program version number is suitable and return--- it. For example you could require 'AnyVersion' or @'orLaterVersion'--- ('Version' [1,0] [])@------ It returns the configured program, its version number and a possibly updated--- 'ProgramDb'. If the program could not be configured or the version is--- unsuitable, it returns an error value.----lookupProgramVersion- :: Verbosity -> Program -> VersionRange -> ProgramDb- -> IO (Either String (ConfiguredProgram, Version, ProgramDb))-lookupProgramVersion verbosity prog range programDb = do-- -- If it's not already been configured, try to configure it now- programDb' <- case lookupProgram prog programDb of- Nothing -> configureProgram verbosity prog programDb- Just _ -> return programDb-- case lookupProgram prog programDb' of- Nothing -> return $! Left notFound- Just configuredProg@ConfiguredProgram { programLocation = location } ->- case programVersion configuredProg of- Just version- | withinRange version range ->- return $! Right (configuredProg, version ,programDb')- | otherwise ->- return $! Left (badVersion version location)- Nothing ->- return $! Left (unknownVersion location)-- where notFound = "The program '"- ++ programName prog ++ "'" ++ versionRequirement- ++ " is required but it could not be found."- badVersion v l = "The program '"- ++ programName prog ++ "'" ++ versionRequirement- ++ " is required but the version found at "- ++ locationPath l ++ " is version " ++ prettyShow v- unknownVersion l = "The program '"- ++ programName prog ++ "'" ++ versionRequirement- ++ " is required but the version of "- ++ locationPath l ++ " could not be determined."- versionRequirement- | isAnyVersion range = ""- | otherwise = " version " ++ prettyShow range---- | Like 'lookupProgramVersion', but raises an exception in case of error--- instead of returning 'Left errMsg'.----requireProgramVersion :: Verbosity -> Program -> VersionRange- -> ProgramDb- -> IO (ConfiguredProgram, Version, ProgramDb)-requireProgramVersion verbosity prog range programDb =- join $ either (die' verbosity) return `fmap`- lookupProgramVersion verbosity prog range programDb
− Distribution/Simple/Program/Find.hs
@@ -1,198 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Find--- Copyright : Duncan Coutts 2013------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ A somewhat extended notion of the normal program search path concept.------ Usually when finding executables we just want to look in the usual places--- using the OS's usual method for doing so. In Haskell the normal OS-specific--- method is captured by 'findExecutable'. On all common OSs that makes use of--- a @PATH@ environment variable, (though on Windows it is not just the @PATH@).------ However it is sometimes useful to be able to look in additional locations--- without having to change the process-global @PATH@ environment variable.--- So we need an extension of the usual 'findExecutable' that can look in--- additional locations, either before, after or instead of the normal OS--- locations.----module Distribution.Simple.Program.Find (- -- * Program search path- ProgramSearchPath,- ProgramSearchPathEntry(..),- defaultProgramSearchPath,- findProgramOnSearchPath,- programSearchPathAsPATHVar,- getSystemSearchPath,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Verbosity-import Distribution.Simple.Utils-import Distribution.System-import Distribution.Compat.Environment--import qualified System.Directory as Directory- ( findExecutable )-import System.FilePath as FilePath- ( (</>), (<.>), splitSearchPath, searchPathSeparator, getSearchPath- , takeDirectory )-#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--- the system default method for finding executables ('findExecutable' which--- on unix is simply looking on the @$PATH@ but on win32 is a bit more--- complicated).------ The default to use is @[ProgSearchPathDefault]@ but you can add extra dirs--- either before, after or instead of the default, e.g. here we add an extra--- dir to search after the usual ones.------ > ['ProgramSearchPathDefault', 'ProgramSearchPathDir' dir]----type ProgramSearchPath = [ProgramSearchPathEntry]-data ProgramSearchPathEntry =- ProgramSearchPathDir FilePath -- ^ A specific dir- | ProgramSearchPathDefault -- ^ The system default- deriving (Eq, Generic, Typeable)--instance Binary ProgramSearchPathEntry-instance Structured ProgramSearchPathEntry--defaultProgramSearchPath :: ProgramSearchPath-defaultProgramSearchPath = [ProgramSearchPathDefault]--findProgramOnSearchPath :: Verbosity -> ProgramSearchPath- -> FilePath -> IO (Maybe (FilePath, [FilePath]))-findProgramOnSearchPath verbosity searchpath prog = do- debug verbosity $ "Searching for " ++ prog ++ " in path."- res <- tryPathElems [] searchpath- case res of- Nothing -> debug verbosity ("Cannot find " ++ prog ++ " on the path")- Just (path, _) -> debug verbosity ("Found " ++ prog ++ " at "++ path)- return res- where- tryPathElems :: [[FilePath]] -> [ProgramSearchPathEntry]- -> IO (Maybe (FilePath, [FilePath]))- tryPathElems _ [] = return Nothing- tryPathElems tried (pe:pes) = do- res <- tryPathElem pe- case res of- (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 <- exeExtensions ]-- -- 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 <- firstJustM [ findExecutable (prog <.> ext) | ext <- exeExtensions ]- syspath <- getSystemSearchPath- case mExe of- Nothing ->- let notfoundat = [ dir </> prog | dir <- syspath ] in- return (Nothing, notfoundat)-- 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-- -- Helper for evaluating actions until the first one returns 'Just'- firstJustM :: Monad m => [m (Maybe a)] -> m (Maybe a)- firstJustM [] = return Nothing- firstJustM (ma:mas) = do- a <- ma- case a of- Just _ -> return a- Nothing -> firstJustM mas---- | 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%@.-programSearchPathAsPATHVar :: ProgramSearchPath -> IO String-programSearchPathAsPATHVar searchpath = do- ess <- traverse getEntries searchpath- return (intercalate [searchPathSeparator] (concat ess))- where- getEntries (ProgramSearchPathDir dir) = return [dir]- 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
@@ -1,851 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Distribution.Simple.Program.GHC (- GhcOptions(..),- GhcMode(..),- GhcOptimisation(..),- GhcDynLinkMode(..),- GhcProfAuto(..),-- ghcInvocation,- renderGhcOptions,-- runGHC,-- packageDbArgsDb,- normaliseGhcArgs-- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Backpack-import Distribution.Compat.Semigroup (First'(..), Last'(..), Option'(..))-import Distribution.Simple.GHC.ImplInfo-import Distribution.PackageDescription-import Distribution.ModuleName-import Distribution.Simple.Compiler-import Distribution.Simple.Flag-import Distribution.Simple.Program.Types-import Distribution.Simple.Program.Run-import Distribution.System-import Distribution.Pretty-import Distribution.Types.ComponentId-import Distribution.Types.ModuleRenaming-import Distribution.Verbosity-import Distribution.Version-import Distribution.Utils.NubList-import Language.Haskell.Extension--import Data.List (stripPrefix)-import qualified Data.Map as Map-import Data.Monoid (All(..), Any(..), Endo(..))-import qualified Data.Set as Set--normaliseGhcArgs :: Maybe Version -> PackageDescription -> [String] -> [String]-normaliseGhcArgs (Just ghcVersion) PackageDescription{..} ghcArgs- | ghcVersion `withinRange` supportedGHCVersions- = argumentFilters . filter simpleFilters . filterRtsOpts $ ghcArgs- where- supportedGHCVersions :: VersionRange- supportedGHCVersions = intersectVersionRanges- (orLaterVersion (mkVersion [8,0]))- (earlierVersion (mkVersion [9,1]))-- from :: Monoid m => [Int] -> m -> m- from version flags- | ghcVersion `withinRange` orLaterVersion (mkVersion version) = flags- | otherwise = mempty-- to :: Monoid m => [Int] -> m -> m- to version flags- | ghcVersion `withinRange` earlierVersion (mkVersion version) = flags- | otherwise = mempty-- checkGhcFlags :: forall m . Monoid m => ([String] -> m) -> m- checkGhcFlags fun = mconcat- [ fun ghcArgs- , checkComponentFlags libBuildInfo pkgLibs- , checkComponentFlags buildInfo executables- , checkComponentFlags testBuildInfo testSuites- , checkComponentFlags benchmarkBuildInfo benchmarks- ]- where- pkgLibs = maybeToList library ++ subLibraries-- checkComponentFlags :: (a -> BuildInfo) -> [a] -> m- checkComponentFlags getInfo = foldMap (checkComponent . getInfo)- where- checkComponent :: BuildInfo -> m- checkComponent = foldMap fun . filterGhcOptions . allGhcOptions-- allGhcOptions :: BuildInfo -> [(CompilerFlavor, [String])]- allGhcOptions = foldMap (perCompilerFlavorToList .)- [options, profOptions, sharedOptions, staticOptions]-- filterGhcOptions :: [(CompilerFlavor, [String])] -> [[String]]- filterGhcOptions l = [opts | (GHC, opts) <- l]-- safeToFilterWarnings :: Bool- safeToFilterWarnings = getAll $ checkGhcFlags checkWarnings- where- checkWarnings :: [String] -> All- checkWarnings = All . Set.null . foldr alter Set.empty-- alter :: String -> Set String -> Set String- alter flag = appEndo $ mconcat- [ \s -> Endo $ if s == "-Werror" then Set.insert s else id- , \s -> Endo $ if s == "-Wwarn" then const Set.empty else id- , \s -> from [8,6] . Endo $- if s == "-Werror=compat"- then Set.union compatWarningSet else id- , \s -> from [8,6] . Endo $- if s == "-Wno-error=compat"- then (`Set.difference` compatWarningSet) else id- , \s -> from [8,6] . Endo $- if s == "-Wwarn=compat"- then (`Set.difference` compatWarningSet) else id- , from [8,4] $ markFlag "-Werror=" Set.insert- , from [8,4] $ markFlag "-Wwarn=" Set.delete- , from [8,4] $ markFlag "-Wno-error=" Set.delete- ] flag-- markFlag- :: String- -> (String -> Set String -> Set String)- -> String- -> Endo (Set String)- markFlag name update flag = Endo $ case stripPrefix name flag of- Just rest | not (null rest) && rest /= "compat" -> update rest- _ -> id-- flagArgumentFilter :: [String] -> [String] -> [String]- flagArgumentFilter flags = go- where- makeFilter :: String -> String -> Option' (First' ([String] -> [String]))- makeFilter flag arg = Option' $ First' . filterRest <$> stripPrefix flag arg- where- filterRest leftOver = case dropEq leftOver of- [] -> drop 1- _ -> id-- checkFilter :: String -> Maybe ([String] -> [String])- checkFilter = fmap getFirst' . getOption' . foldMap makeFilter flags-- go :: [String] -> [String]- go [] = []- go (arg:args) = case checkFilter arg of- Just f -> go (f args)- Nothing -> arg : go args-- argumentFilters :: [String] -> [String]- argumentFilters = flagArgumentFilter- ["-ghci-script", "-H", "-interactive-print"]-- filterRtsOpts :: [String] -> [String]- filterRtsOpts = go False- where- go :: Bool -> [String] -> [String]- go _ [] = []- go _ ("+RTS":opts) = go True opts- go _ ("-RTS":opts) = go False opts- go isRTSopts (opt:opts) = addOpt $ go isRTSopts opts- where- addOpt | isRTSopts = id- | otherwise = (opt:)-- simpleFilters :: String -> Bool- simpleFilters = not . getAny . mconcat- [ flagIn simpleFlags- , Any . isPrefixOf "-ddump-"- , Any . isPrefixOf "-dsuppress-"- , Any . isPrefixOf "-dno-suppress-"- , flagIn $ invertibleFlagSet "-" ["ignore-dot-ghci"]- , flagIn . invertibleFlagSet "-f" . mconcat $- [ [ "reverse-errors", "warn-unused-binds", "break-on-error"- , "break-on-exception", "print-bind-result"- , "print-bind-contents", "print-evld-with-show"- , "implicit-import-qualified", "error-spans"- ]- , from [7,8]- [ "print-explicit-foralls" -- maybe also earlier, but GHC-7.6 doesn't have --show-options- , "print-explicit-kinds"- ]- , from [8,0]- [ "print-explicit-coercions"- , "print-explicit-runtime-reps"- , "print-equality-relations"- , "print-unicode-syntax"- , "print-expanded-synonyms"- , "print-potential-instances"- , "print-typechecker-elaboration"- ]- , from [8,2]- [ "diagnostics-show-caret", "local-ghci-history"- , "show-warning-groups", "hide-source-paths"- , "show-hole-constraints"- ]- , from [8,4] ["show-loaded-modules"]- , from [8,6] [ "ghci-leak-check", "no-it" ]- , from [8,10]- [ "defer-diagnostics" -- affects printing of diagnostics- , "keep-going" -- try harder, the build will still fail if it's erroneous- , "print-axiom-incomps" -- print more debug info for closed type families- ]- ]- , flagIn . invertibleFlagSet "-d" $ [ "ppr-case-as-let", "ppr-ticks" ]- , isOptIntFlag- , isIntFlag- , if safeToFilterWarnings- then isWarning <> (Any . ("-w"==))- else mempty- , from [8,6] $- if safeToFilterHoles- then isTypedHoleFlag- else mempty- ]-- flagIn :: Set String -> String -> Any- flagIn set flag = Any $ Set.member flag set-- isWarning :: String -> Any- isWarning = mconcat $ map ((Any .) . isPrefixOf)- ["-fwarn-", "-fno-warn-", "-W", "-Wno-"]-- simpleFlags :: Set String- simpleFlags = Set.fromList . mconcat $- [ [ "-n", "-#include", "-Rghc-timing", "-dstg-stats"- , "-dth-dec-file", "-dsource-stats", "-dverbose-core2core"- , "-dverbose-stg2stg", "-dcore-lint", "-dstg-lint", "-dcmm-lint"- , "-dasm-lint", "-dannot-lint", "-dshow-passes", "-dfaststring-stats"- , "-fno-max-relevant-binds", "-recomp", "-no-recomp", "-fforce-recomp"- , "-fno-force-recomp"- ]-- , from [8,2]- [ "-fno-max-errors", "-fdiagnostics-color=auto"- , "-fdiagnostics-color=always", "-fdiagnostics-color=never"- , "-dppr-debug", "-dno-debug-output"- ]-- , from [8,4] [ "-ddebug-output" ]- , from [8,4] $ to [8,6] [ "-fno-max-valid-substitutions" ]- , from [8,6] [ "-dhex-word-literals" ]- , from [8,8] [ "-fshow-docs-of-hole-fits", "-fno-show-docs-of-hole-fits" ]- , from [9,0] [ "-dlinear-core-lint" ]- ]-- isOptIntFlag :: String -> Any- isOptIntFlag = mconcat . map (dropIntFlag True) $ ["-v", "-j"]-- isIntFlag :: String -> Any- isIntFlag = mconcat . map (dropIntFlag False) . mconcat $- [ [ "-fmax-relevant-binds", "-ddpr-user-length", "-ddpr-cols"- , "-dtrace-level", "-fghci-hist-size" ]- , from [8,2] ["-fmax-uncovered-patterns", "-fmax-errors"]- , from [8,4] $ to [8,6] ["-fmax-valid-substitutions"]- ]-- dropIntFlag :: Bool -> String -> String -> Any- dropIntFlag isOpt flag input = Any $ case stripPrefix flag input of- Nothing -> False- Just rest | isOpt && null rest -> True- | otherwise -> case parseInt rest of- Just _ -> True- Nothing -> False- where- parseInt :: String -> Maybe Int- parseInt = readMaybe . dropEq-- dropEq :: String -> String- dropEq ('=':s) = s- dropEq s = s-- invertibleFlagSet :: String -> [String] -> Set String- invertibleFlagSet prefix flagNames =- Set.fromList $ (++) <$> [prefix, prefix ++ "no-"] <*> flagNames-- compatWarningSet :: Set String- compatWarningSet = Set.fromList $ mconcat- [ from [8,6]- [ "missing-monadfail-instances", "semigroup"- , "noncanonical-monoid-instances", "implicit-kind-vars" ]- ]-- safeToFilterHoles :: Bool- safeToFilterHoles = getAll . checkGhcFlags $- All . fromMaybe True . fmap getLast' . getOption' . foldMap notDeferred- where- notDeferred :: String -> Option' (Last' Bool)- notDeferred "-fdefer-typed-holes" = Option' . Just . Last' $ False- notDeferred "-fno-defer-typed-holes" = Option' . Just . Last' $ True- notDeferred _ = Option' Nothing-- isTypedHoleFlag :: String -> Any- isTypedHoleFlag = mconcat- [ flagIn . invertibleFlagSet "-f" $- [ "show-hole-constraints", "show-valid-substitutions"- , "show-valid-hole-fits", "sort-valid-hole-fits"- , "sort-by-size-hole-fits", "sort-by-subsumption-hole-fits"- , "abstract-refinement-hole-fits", "show-provenance-of-hole-fits"- , "show-hole-matches-of-hole-fits", "show-type-of-hole-fits"- , "show-type-app-of-hole-fits", "show-type-app-vars-of-hole-fits"- , "unclutter-valid-hole-fits"- ]- , flagIn . Set.fromList $- [ "-fno-max-valid-hole-fits", "-fno-max-refinement-hole-fits"- , "-fno-refinement-level-hole-fits" ]- , mconcat . map (dropIntFlag False) $- [ "-fmax-valid-hole-fits", "-fmax-refinement-hole-fits"- , "-frefinement-level-hole-fits" ]- ]--normaliseGhcArgs _ _ args = args---- | A structured set of GHC options/flags------ Note that options containing lists fall into two categories:------ * options that can be safely deduplicated, e.g. input modules or--- enabled extensions;--- * options that cannot be deduplicated in general without changing--- semantics, e.g. extra ghc options or linking options.-data GhcOptions = GhcOptions {-- -- | The major mode for the ghc invocation.- ghcOptMode :: Flag GhcMode,-- -- | Any extra options to pass directly to ghc. These go at the end and hence- -- override other stuff.- ghcOptExtra :: [String],-- -- | Extra default flags to pass directly to ghc. These go at the beginning- -- and so can be overridden by other stuff.- ghcOptExtraDefault :: [String],-- ------------------------ -- Inputs and outputs-- -- | The main input files; could be .hs, .hi, .c, .o, depending on mode.- ghcOptInputFiles :: NubListR FilePath,-- -- | The names of input Haskell modules, mainly for @--make@ mode.- ghcOptInputModules :: NubListR ModuleName,-- -- | Location for output file; the @ghc -o@ flag.- ghcOptOutputFile :: Flag FilePath,-- -- | Location for dynamic output file in 'GhcStaticAndDynamic' mode;- -- the @ghc -dyno@ flag.- ghcOptOutputDynFile :: Flag FilePath,-- -- | Start with an empty search path for Haskell source files;- -- the @ghc -i@ flag (@-i@ on its own with no path argument).- ghcOptSourcePathClear :: Flag Bool,-- -- | Search path for Haskell source files; the @ghc -i@ flag.- ghcOptSourcePath :: NubListR FilePath,-- -------------- -- Packages-- -- | 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 doesn't make any assumptions about the format of- -- definite unit ids, so when we are instantiating a package it- -- needs to be told explicitly what the component being instantiated- -- is. This only gets set when 'ghcOptInstantiatedWith' is non-empty- ghcOptThisComponentId :: Flag ComponentId,-- -- | How the requirements of the package being compiled are to- -- be filled. When typechecking an indefinite package, the 'OpenModule'- -- is always a 'OpenModuleVar'; otherwise, it specifies the installed module- -- that instantiates a package.- ghcOptInstantiatedWith :: [(ModuleName, OpenModule)],-- -- | No code? (But we turn on interface writing- ghcOptNoCode :: Flag Bool,-- -- | GHC package databases to use, the @ghc -package-conf@ flag.- ghcOptPackageDBs :: PackageDBStack,-- -- | The GHC packages to bring into scope when compiling,- -- the @ghc -package-id@ flags.- ghcOptPackages ::- NubListR (OpenUnitId, ModuleRenaming),-- -- | Start with a clean package set; the @ghc -hide-all-packages@ flag- ghcOptHideAllPackages :: Flag Bool,-- -- | Warn about modules, not listed in command line- ghcOptWarnMissingHomeModules :: Flag Bool,-- -- | Don't automatically link in Haskell98 etc; the @ghc- -- -no-auto-link-packages@ flag.- ghcOptNoAutoLinkPackages :: Flag Bool,-- ------------------ -- Linker stuff-- -- | Names of libraries to link in; the @ghc -l@ flag.- ghcOptLinkLibs :: [FilePath],-- -- | Search path for libraries to link in; the @ghc -L@ flag.- ghcOptLinkLibPath :: NubListR FilePath,-- -- | Options to pass through to the linker; the @ghc -optl@ flag.- ghcOptLinkOptions :: [String],-- -- | 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,-- -- | Don't link in the normal RTS @main@ entry point; the @ghc -no-hs-main@- -- flag.- ghcOptLinkNoHsMain :: Flag Bool,-- -- | Module definition files (Windows specific)- ghcOptLinkModDefFiles :: NubListR FilePath,-- --------------------- -- C and CPP stuff-- -- | Options to pass through to the C compiler; the @ghc -optc@ flag.- ghcOptCcOptions :: [String],-- -- | Options to pass through to the C++ compiler.- ghcOptCxxOptions :: [String],-- -- | Options to pass through to the Assembler.- ghcOptAsmOptions :: [String],-- -- | Options to pass through to CPP; the @ghc -optP@ flag.- ghcOptCppOptions :: [String],-- -- | Search path for CPP includes like header files; the @ghc -I@ flag.- ghcOptCppIncludePath :: NubListR FilePath,-- -- | Extra header files to include at CPP stage; the @ghc -optP-include@ flag.- ghcOptCppIncludes :: NubListR FilePath,-- -- | Extra header files to include for old-style FFI; the @ghc -#include@ flag.- ghcOptFfiIncludes :: NubListR FilePath,-- ----------------------------- -- Language and extensions-- -- | The base language; the @ghc -XHaskell98@ or @-XHaskell2010@ flag.- ghcOptLanguage :: Flag Language,-- -- | The language extensions; the @ghc -X@ flag.- ghcOptExtensions :: NubListR Extension,-- -- | A GHC version-dependent mapping of extensions to flags. This must be- -- set to be able to make use of the 'ghcOptExtensions'.- ghcOptExtensionMap :: Map Extension (Maybe CompilerFlag),-- ----------------- -- Compilation-- -- | What optimisation level to use; the @ghc -O@ flag.- ghcOptOptimisation :: Flag GhcOptimisation,-- -- | Emit debug info; the @ghc -g@ flag.- ghcOptDebugInfo :: Flag DebugInfoLevel,-- -- | 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 sections\" feature; the @ghc -split-sections@ flag.- ghcOptSplitSections :: Flag Bool,-- -- | Use the \"split object files\" feature; the @ghc -split-objs@ flag.- ghcOptSplitObjs :: Flag Bool,-- -- | Run N jobs simultaneously (if possible).- ghcOptNumJobs :: Flag (Maybe Int),-- -- | Enable coverage analysis; the @ghc -fhpc -hpcdir@ flags.- ghcOptHPCDir :: Flag FilePath,-- ----------------- -- GHCi-- -- | Extra GHCi startup scripts; the @-ghci-script@ flag- ghcOptGHCiScripts :: [FilePath],-- ------------------------- -- Redirecting outputs-- ghcOptHiSuffix :: Flag String,- ghcOptObjSuffix :: Flag String,- ghcOptDynHiSuffix :: Flag String, -- ^ only in 'GhcStaticAndDynamic' mode- ghcOptDynObjSuffix :: Flag String, -- ^ only in 'GhcStaticAndDynamic' mode- ghcOptHiDir :: Flag FilePath,- ghcOptObjDir :: Flag FilePath,- ghcOptOutputDir :: Flag FilePath,- ghcOptStubDir :: Flag FilePath,-- --------------------- -- Creating libraries-- ghcOptDynLinkMode :: Flag GhcDynLinkMode,- ghcOptStaticLib :: Flag Bool,- ghcOptShared :: Flag Bool,- ghcOptFPic :: Flag Bool,- ghcOptDylibName :: Flag String,- ghcOptRPaths :: NubListR FilePath,-- ---------------- -- Misc flags-- -- | Get GHC to be quiet or verbose with what it's doing; the @ghc -v@ flag.- ghcOptVerbosity :: Flag Verbosity,-- -- | Put the extra folders in the PATH environment variable we invoke- -- GHC with- ghcOptExtraPath :: NubListR FilePath,-- -- | Let GHC know that it is Cabal that's calling it.- -- Modifies some of the GHC error messages.- ghcOptCabal :: Flag Bool--} deriving (Show, Generic)---data GhcMode = GhcModeCompile -- ^ @ghc -c@- | GhcModeLink -- ^ @ghc@- | GhcModeMake -- ^ @ghc --make@- | GhcModeInteractive -- ^ @ghci@ \/ @ghc --interactive@- | GhcModeAbiHash -- ^ @ghc --abi-hash@--- | GhcModeDepAnalysis -- ^ @ghc -M@--- | GhcModeEvaluate -- ^ @ghc -e@- deriving (Show, Eq)--data GhcOptimisation = GhcNoOptimisation -- ^ @-O0@- | GhcNormalOptimisation -- ^ @-O@- | GhcMaximumOptimisation -- ^ @-O2@- | GhcSpecialOptimisation String -- ^ e.g. @-Odph@- deriving (Show, Eq)--data GhcDynLinkMode = GhcStaticOnly -- ^ @-static@- | GhcDynamicOnly -- ^ @-dynamic@- | 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 -> Platform -> GhcOptions- -> IO ()-runGHC verbosity ghcProg comp platform opts = do- runProgramInvocation verbosity (ghcInvocation ghcProg comp platform opts)---ghcInvocation :: ConfiguredProgram -> Compiler -> Platform -> GhcOptions- -> ProgramInvocation-ghcInvocation prog comp platform opts =- (programInvocation prog (renderGhcOptions comp platform opts)) {- progInvokePathEnv = fromNubListR (ghcOptExtraPath 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'!"- | otherwise =- concat- [ case flagToMaybe (ghcOptMode opts) of- Nothing -> []- Just GhcModeCompile -> ["-c"]- Just GhcModeLink -> []- Just GhcModeMake -> ["--make"]- Just GhcModeInteractive -> ["--interactive"]- Just GhcModeAbiHash -> ["--abi-hash"]--- Just GhcModeDepAnalysis -> ["-M"]--- Just GhcModeEvaluate -> ["-e", expr]-- , ghcOptExtraDefault opts-- , [ "-no-link" | flagBool ghcOptNoLink ]-- ---------------- -- Misc flags-- , maybe [] verbosityOpts (flagToMaybe (ghcOptVerbosity opts))-- , [ "-fbuilding-cabal-package" | flagBool ghcOptCabal ]-- ----------------- -- Compilation-- , case flagToMaybe (ghcOptOptimisation opts) of- Nothing -> []- Just GhcNoOptimisation -> ["-O0"]- Just GhcNormalOptimisation -> ["-O"]- Just GhcMaximumOptimisation -> ["-O2"]- Just (GhcSpecialOptimisation s) -> ["-O" ++ s] -- eg -Odph-- , case flagToMaybe (ghcOptDebugInfo opts) of- Nothing -> []- Just NoDebugInfo -> []- Just MinimalDebugInfo -> ["-g1"]- Just NormalDebugInfo -> ["-g2"]- Just MaximalDebugInfo -> ["-g3"]-- , [ "-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-sections" | flagBool ghcOptSplitSections ]- , [ "-split-objs" | flagBool ghcOptSplitObjs ]-- , case flagToMaybe (ghcOptHPCDir opts) of- Nothing -> []- Just hpcdir -> ["-fhpc", "-hpcdir", hpcdir]-- , if parmakeSupported comp- then case ghcOptNumJobs opts of- NoFlag -> []- Flag n -> ["-j" ++ maybe "" show n]- else []-- --------------------- -- Creating libraries-- , [ "-staticlib" | flagBool ghcOptStaticLib ]- , [ "-shared" | flagBool ghcOptShared ]- , case flagToMaybe (ghcOptDynLinkMode opts) of- Nothing -> []- Just GhcStaticOnly -> ["-static"]- Just GhcDynamicOnly -> ["-dynamic"]- Just GhcStaticAndDynamic -> ["-static", "-dynamic-too"]- , [ "-fPIC" | flagBool ghcOptFPic ]-- , concat [ ["-dylib-install-name", libname] | libname <- flag ghcOptDylibName ]-- ------------------------- -- Redirecting outputs-- , concat [ ["-osuf", suf] | suf <- flag ghcOptObjSuffix ]- , concat [ ["-hisuf", suf] | suf <- flag ghcOptHiSuffix ]- , concat [ ["-dynosuf", suf] | suf <- flag ghcOptDynObjSuffix ]- , concat [ ["-dynhisuf",suf] | suf <- flag ghcOptDynHiSuffix ]- , concat [ ["-outputdir", dir] | dir <- flag ghcOptOutputDir ]- , concat [ ["-odir", dir] | dir <- flag ghcOptObjDir ]- , concat [ ["-hidir", dir] | dir <- flag ghcOptHiDir ]- , concat [ ["-stubdir", dir] | dir <- flag ghcOptStubDir ]-- ------------------------ -- Source search path-- , [ "-i" | flagBool ghcOptSourcePathClear ]- , [ "-i" ++ dir | dir <- flags ghcOptSourcePath ]-- ---------------------- --------------------- -- CPP, C, and C++ stuff-- , [ "-I" ++ dir | dir <- flags ghcOptCppIncludePath ]- , [ "-optP" ++ opt | opt <- ghcOptCppOptions opts]- , concat [ [ "-optP-include", "-optP" ++ inc]- | inc <- flags ghcOptCppIncludes ]- , [ "-optc" ++ opt | opt <- ghcOptCcOptions opts]- , -- C++ compiler options: GHC >= 8.10 requires -optcxx, older requires -optc- let cxxflag = case compilerCompatVersion GHC comp of- Just v | v >= mkVersion [8, 10] -> "-optcxx"- _ -> "-optc"- in [ cxxflag ++ opt | opt <- ghcOptCxxOptions opts]- , [ "-opta" ++ opt | opt <- ghcOptAsmOptions opts]-- ------------------ -- Linker stuff-- , [ "-optl" ++ opt | opt <- ghcOptLinkOptions opts]- , ["-l" ++ lib | lib <- ghcOptLinkLibs opts]- , ["-L" ++ dir | dir <- flags ghcOptLinkLibPath ]- , 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]- | dir <- flags ghcOptRPaths ]- , [ modDefFile | modDefFile <- flags ghcOptLinkModDefFiles ]-- -------------- -- Packages-- , concat [ [ case () of- _ | unitIdSupported comp -> "-this-unit-id"- | packageKeySupported comp -> "-this-package-key"- | otherwise -> "-package-name"- , this_arg ]- | this_arg <- flag ghcOptThisUnitId ]-- , concat [ ["-this-component-id", prettyShow this_cid ]- | this_cid <- flag ghcOptThisComponentId ]-- , if null (ghcOptInstantiatedWith opts)- then []- else "-instantiated-with"- : intercalate "," (map (\(n,m) -> prettyShow n ++ "="- ++ prettyShow m)- (ghcOptInstantiatedWith opts))- : []-- , concat [ ["-fno-code", "-fwrite-interface"] | flagBool ghcOptNoCode ]-- , [ "-hide-all-packages" | flagBool ghcOptHideAllPackages ]- , [ "-Wmissing-home-modules" | flagBool ghcOptWarnMissingHomeModules ]- , [ "-no-auto-link-packages" | flagBool ghcOptNoAutoLinkPackages ]-- , packageDbArgs implInfo (ghcOptPackageDBs opts)-- , concat $ let space "" = ""- space xs = ' ' : xs- in [ ["-package-id", prettyShow ipkgid ++ space (prettyShow rns)]- | (ipkgid,rns) <- flags ghcOptPackages ]-- ----------------------------- -- Language and extensions-- , if supportsHaskell2010 implInfo- then [ "-X" ++ prettyShow lang | lang <- flag ghcOptLanguage ]- else []-- , [ ext'- | ext <- flags ghcOptExtensions- , ext' <- case Map.lookup ext (ghcOptExtensionMap opts) of- Just (Just arg) -> [arg]- Just Nothing -> []- Nothing ->- error $ "Distribution.Simple.Program.GHC.renderGhcOptions: "- ++ prettyShow ext ++ " not present in ghcOptExtensionMap."- ]-- ----------------- -- GHCi-- , concat [ [ "-ghci-script", script ] | script <- ghcOptGHCiScripts opts- , flagGhciScript implInfo ]-- ---------------- -- Inputs-- -- Specify the input file(s) first, so that in ghci the `main-is` module is- -- in scope instead of the first module defined in `other-modules`.- , flags ghcOptInputFiles- , [ prettyShow modu | modu <- flags ghcOptInputModules ]-- , concat [ [ "-o", out] | out <- flag ghcOptOutputFile ]- , concat [ [ "-dyno", out] | out <- flag ghcOptOutputDynFile ]-- ---------------- -- Extra-- , ghcOptExtra opts-- ]--- where- implInfo = getImplInfo comp- isOSX = os == OSX- flag flg = flagToList (flg opts)- flags flg = fromNubListR . flg $ opts- flagBool flg = fromFlagOrDefault False (flg opts)--verbosityOpts :: Verbosity -> [String]-verbosityOpts verbosity- | verbosity >= deafening = ["-v"]- | verbosity >= normal = []- | otherwise = ["-w", "-v0"]----- | 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-package-conf")- : concatMap specific dbs- _ -> ierror- where- 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://gitlab.haskell.org/ghc/ghc/-/issues/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 = gmempty- mappend = (<>)--instance Semigroup GhcOptions where- (<>) = gmappend
− Distribution/Simple/Program/HcPkg.hs
@@ -1,516 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE OverloadedStrings #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.HcPkg--- Copyright : Duncan Coutts 2009, 2013------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides an library interface to the @hc-pkg@ program.--- Currently only GHC and GHCJS have hc-pkg programs.--module Distribution.Simple.Program.HcPkg (- -- * Types- HcPkgInfo(..),- RegisterOptions(..),- defaultRegisterOptions,-- -- * Actions- init,- invoke,- register,- unregister,- recache,- expose,- hide,- dump,- describe,- list,-- -- * Program invocations- initInvocation,- registerInvocation,- unregisterInvocation,- recacheInvocation,- exposeInvocation,- hideInvocation,- dumpInvocation,- describeInvocation,- listInvocation,- ) where--import Distribution.Compat.Prelude hiding (init)-import Prelude ()--import Distribution.InstalledPackageInfo-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Simple.Compiler-import Distribution.Simple.Program.Run-import Distribution.Simple.Program.Types-import Distribution.Simple.Utils-import Distribution.Types.ComponentId-import Distribution.Types.PackageId-import Distribution.Types.UnitId-import Distribution.Verbosity--import Data.List (stripPrefix)-import System.FilePath as FilePath (isPathSeparator, joinPath, splitDirectories, splitPath, (<.>), (</>))--import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as LBS-import qualified Data.List.NonEmpty as NE-import qualified System.FilePath.Posix as FilePath.Posix---- | Information about the features and capabilities of an @hc-pkg@--- program.----data HcPkgInfo = HcPkgInfo- { hcPkgProgram :: ConfiguredProgram- , 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- , 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- , suppressFilesCheck :: Bool -- ^ supports --force-files or equivalent- }----- | Call @hc-pkg@ to initialise a package database at the location {path}.------ > hc-pkg init {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 ()-invoke hpi verbosity dbStack extraArgs =- runProgramInvocation verbosity invocation- where- args = packageDbStackOpts hpi dbStack ++ extraArgs- invocation = programInvocation (hcPkgProgram hpi) args---- | Additional variations in the behaviour for 'register'.-data RegisterOptions = RegisterOptions {- -- | Allows re-registering \/ overwriting an existing package- registerAllowOverwrite :: Bool,-- -- | Insist on the ability to register multiple instances of a- -- single version of a single package. This will fail if the @hc-pkg@- -- does not support it, see 'nativeMultiInstance' and- -- 'recacheMultiInstance'.- registerMultiInstance :: Bool,-- -- | Require that no checks are performed on the existence of package- -- files mentioned in the registration info. This must be used if- -- registering prior to putting the files in their final place. This will- -- fail if the @hc-pkg@ does not support it, see 'suppressFilesCheck'.- registerSuppressFilesCheck :: Bool- }---- | Defaults are @True@, @False@ and @False@-defaultRegisterOptions :: RegisterOptions-defaultRegisterOptions = RegisterOptions {- registerAllowOverwrite = True,- registerMultiInstance = False,- registerSuppressFilesCheck = False- }---- | Call @hc-pkg@ to register a package.------ > hc-pkg register {filename | -} [--user | --global | --package-db]----register :: HcPkgInfo -> Verbosity -> PackageDBStack- -> InstalledPackageInfo- -> RegisterOptions- -> IO ()-register hpi verbosity packagedbs pkgInfo registerOptions- | registerMultiInstance registerOptions- , not (nativeMultiInstance hpi || recacheMultiInstance hpi)- = die' verbosity $ "HcPkg.register: the compiler does not support "- ++ "registering multiple instances of packages."-- | registerSuppressFilesCheck registerOptions- , not (suppressFilesCheck hpi)- = die' verbosity $ "HcPkg.register: the compiler does not support "- ++ "suppressing checks on files."-- -- 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.- --- | registerMultiInstance registerOptions- , recacheMultiInstance hpi- = do let pkgdb = registrationPackageDB packagedbs- writeRegistrationFileDirectly verbosity hpi pkgdb pkgInfo- recache hpi verbosity pkgdb-- | otherwise- = runProgramInvocation verbosity- (registerInvocation hpi verbosity packagedbs pkgInfo registerOptions)--writeRegistrationFileDirectly :: Verbosity- -> HcPkgInfo- -> PackageDB- -> InstalledPackageInfo- -> IO ()-writeRegistrationFileDirectly verbosity hpi (SpecificPackageDB dir) pkgInfo- | supportsDirDbs hpi- = do let pkgfile = dir </> prettyShow (installedUnitId pkgInfo) <.> "conf"- writeUTF8File pkgfile (showInstalledPackageInfo pkgInfo)-- | otherwise- = die' verbosity $ "HcPkg.writeRegistrationFileDirectly: compiler does not support dir style package dbs"--writeRegistrationFileDirectly verbosity _ _ _ =- -- 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' verbosity $ "HcPkg.writeRegistrationFileDirectly: only supports SpecificPackageDB for now"----- | Call @hc-pkg@ to unregister a package------ > hc-pkg unregister [pkgid] [--user | --global | --package-db]----unregister :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> IO ()-unregister hpi verbosity packagedb pkgid =- runProgramInvocation verbosity- (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]----expose :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> IO ()-expose hpi verbosity packagedb pkgid =- 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 <- getProgramInvocationLBS verbosity- (describeInvocation hpi verbosity packagedb pid)- `catchIO` \_ -> return mempty-- case parsePackages output of- Left ok -> return ok- _ -> die' verbosity $ "failed to parse output of '"- ++ programId (hcPkgProgram hpi) ++ " describe " ++ prettyShow pid ++ "'"---- | Call @hc-pkg@ to hide a package.------ > hc-pkg hide [pkgid] [--user | --global | --package-db]----hide :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> IO ()-hide hpi verbosity packagedb pkgid =- runProgramInvocation verbosity- (hideInvocation hpi verbosity packagedb pkgid)----- | Call @hc-pkg@ to get all the details of all the packages in the given--- package database.----dump :: HcPkgInfo -> Verbosity -> PackageDB -> IO [InstalledPackageInfo]-dump hpi verbosity packagedb = do-- output <- getProgramInvocationLBS verbosity- (dumpInvocation hpi verbosity packagedb)- `catchIO` \e -> die' verbosity $ programId (hcPkgProgram hpi) ++ " dump failed: "- ++ displayException e-- case parsePackages output of- Left ok -> return ok- _ -> die' verbosity $ "failed to parse output of '"- ++ programId (hcPkgProgram hpi) ++ " dump'"---parsePackages :: LBS.ByteString -> Either [InstalledPackageInfo] [String]-parsePackages lbs0 =- case traverse parseInstalledPackageInfo $ splitPkgs lbs0 of- Right ok -> Left [ setUnitId . maybe id mungePackagePaths (pkgRoot pkg) $ pkg | (_, pkg) <- ok ]- Left msgs -> Right (NE.toList msgs)- where- splitPkgs :: LBS.ByteString -> [BS.ByteString]- splitPkgs = checkEmpty . doSplit- where- -- Handle the case of there being no packages at all.- checkEmpty [s] | BS.all isSpace8 s = []- checkEmpty ss = ss-- isSpace8 :: Word8 -> Bool- isSpace8 9 = True -- '\t'- isSpace8 10 = True -- '\n'- isSpace8 13 = True -- '\r'- isSpace8 32 = True -- ' '- isSpace8 _ = False-- doSplit :: LBS.ByteString -> [BS.ByteString]- doSplit lbs = go (LBS.findIndices (\w -> w == 10 || w == 13) lbs)- where- go :: [Int64] -> [BS.ByteString]- go [] = [ LBS.toStrict lbs ]- go (idx:idxs) =- let (pfx, sfx) = LBS.splitAt idx lbs- in case foldr (<|>) Nothing $ map (`lbsStripPrefix` sfx) separators of- Just sfx' -> LBS.toStrict pfx : doSplit sfx'- Nothing -> go idxs-- separators :: [LBS.ByteString]- separators = ["\n---\n", "\r\n---\r\n", "\r---\r"]--lbsStripPrefix :: LBS.ByteString -> LBS.ByteString -> Maybe LBS.ByteString-#if MIN_VERSION_bytestring(0,10,8)-lbsStripPrefix pfx lbs = LBS.stripPrefix pfx lbs-#else-lbsStripPrefix pfx lbs- | LBS.isPrefixOf pfx lbs = Just (LBS.drop (LBS.length pfx) lbs)- | otherwise = Nothing-#endif---mungePackagePaths :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo--- Perform path/URL variable substitution as per the Cabal ${pkgroot} spec--- (http://www.haskell.org/pipermail/libraries/2009-May/011772.html)--- Paths/URLs can be relative to ${pkgroot} or ${pkgrooturl}.--- The "pkgroot" is the directory containing the package database.-mungePackagePaths pkgroot pkginfo =- pkginfo {- importDirs = mungePaths (importDirs pkginfo),- includeDirs = mungePaths (includeDirs pkginfo),- libraryDirs = mungePaths (libraryDirs pkginfo),- libraryDynDirs = mungePaths (libraryDynDirs pkginfo),- frameworkDirs = mungePaths (frameworkDirs pkginfo),- haddockInterfaces = mungePaths (haddockInterfaces pkginfo),- haddockHTMLs = mungeUrls (haddockHTMLs pkginfo)- }- where- mungePaths = map mungePath- mungeUrls = map mungeUrl-- mungePath p = case stripVarPrefix "${pkgroot}" p of- Just p' -> pkgroot </> p'- Nothing -> p-- mungeUrl p = case stripVarPrefix "${pkgrooturl}" p of- Just p' -> toUrlPath pkgroot p'- Nothing -> p-- toUrlPath r p = "file:///"- -- URLs always use posix style '/' separators:- ++ FilePath.Posix.joinPath (r : FilePath.splitDirectories p)-- stripVarPrefix var p =- case splitPath p of- (root:path') -> case stripPrefix var root of- Just [sep] | isPathSeparator sep -> Just (joinPath path')- _ -> Nothing- _ -> Nothing----- 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.--- NB: Internal libraries not supported.-setUnitId :: InstalledPackageInfo -> InstalledPackageInfo-setUnitId pkginfo@InstalledPackageInfo {- installedUnitId = uid,- sourcePackageId = pid- } | unUnitId uid == ""- = pkginfo {- installedUnitId = mkLegacyUnitId pid,- installedComponentId_ = mkComponentId (prettyShow pid)- }-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 'UnitId', just--- the source 'PackageId' which is not necessarily unique in any package db.----list :: HcPkgInfo -> Verbosity -> PackageDB- -> IO [PackageId]-list hpi verbosity packagedb = do-- output <- getProgramInvocationOutput verbosity- (listInvocation hpi verbosity packagedb)- `catchIO` \_ -> die' verbosity $ programId (hcPkgProgram hpi) ++ " list failed"-- case parsePackageIds output of- Just ok -> return ok- _ -> die' verbosity $ "failed to parse output of '"- ++ programId (hcPkgProgram hpi) ++ " list'"-- where- parsePackageIds = traverse simpleParsec . words------------------------------- The program invocations-----initInvocation :: HcPkgInfo -> Verbosity -> FilePath -> ProgramInvocation-initInvocation hpi verbosity path =- programInvocation (hcPkgProgram hpi) args- where- args = ["init", path]- ++ verbosityOpts hpi verbosity--registerInvocation- :: HcPkgInfo -> Verbosity -> PackageDBStack- -> InstalledPackageInfo- -> RegisterOptions- -> ProgramInvocation-registerInvocation hpi verbosity packagedbs pkgInfo registerOptions =- (programInvocation (hcPkgProgram hpi) (args "-")) {- progInvokeInput = Just $ IODataText $ showInstalledPackageInfo pkgInfo,- progInvokeInputEncoding = IOEncodingUTF8- }- where- cmdname- | registerAllowOverwrite registerOptions = "update"- | registerMultiInstance registerOptions = "update"- | otherwise = "register"-- args file = [cmdname, file]- ++ packageDbStackOpts hpi packagedbs- ++ [ "--enable-multi-instance"- | registerMultiInstance registerOptions ]- ++ [ "--force-files"- | registerSuppressFilesCheck registerOptions ]- ++ verbosityOpts hpi verbosity--unregisterInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId- -> ProgramInvocation-unregisterInvocation hpi verbosity packagedb pkgid =- programInvocation (hcPkgProgram hpi) $- ["unregister", packageDbOpts hpi packagedb, prettyShow pkgid]- ++ 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 =- programInvocation (hcPkgProgram hpi) $- ["expose", packageDbOpts hpi packagedb, prettyShow pkgid]- ++ verbosityOpts hpi verbosity--describeInvocation :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId- -> ProgramInvocation-describeInvocation hpi verbosity packagedbs pkgid =- programInvocation (hcPkgProgram hpi) $- ["describe", prettyShow pkgid]- ++ packageDbStackOpts hpi packagedbs- ++ verbosityOpts hpi verbosity--hideInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId- -> ProgramInvocation-hideInvocation hpi verbosity packagedb pkgid =- programInvocation (hcPkgProgram hpi) $- ["hide", packageDbOpts hpi packagedb, prettyShow pkgid]- ++ verbosityOpts hpi verbosity---dumpInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> ProgramInvocation-dumpInvocation hpi _verbosity packagedb =- (programInvocation (hcPkgProgram hpi) args) {- progInvokeOutputEncoding = IOEncodingUTF8- }- where- args = ["dump", packageDbOpts hpi packagedb]- ++ verbosityOpts hpi silent- -- We use verbosity level 'silent' because it is important that we- -- do not contaminate the output with info/debug messages.--listInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> ProgramInvocation-listInvocation hpi _verbosity packagedb =- (programInvocation (hcPkgProgram hpi) args) {- progInvokeOutputEncoding = IOEncodingUTF8- }- where- args = ["list", "--simple-output", packageDbOpts hpi packagedb]- ++ verbosityOpts hpi silent- -- We use verbosity level 'silent' because it is important that we- -- do not contaminate the output with info/debug messages.---packageDbStackOpts :: HcPkgInfo -> PackageDBStack -> [String]-packageDbStackOpts hpi dbstack- | noPkgDbStack hpi = [packageDbOpts hpi (registrationPackageDB dbstack)]- | otherwise = case dbstack of- (GlobalPackageDB:UserPackageDB:dbs) -> "--global"- : "--user"- : map specific dbs- (GlobalPackageDB:dbs) -> "--global"- : ("--no-user-" ++ packageDbFlag hpi)- : map specific dbs- _ -> ierror- where- specific (SpecificPackageDB db) = "--" ++ packageDbFlag hpi ++ "=" ++ db- specific _ = ierror- ierror :: a- ierror = error ("internal error: unexpected package db stack: " ++ show dbstack)--packageDbFlag :: HcPkgInfo -> String-packageDbFlag hpi- | flagPackageConf hpi- = "package-conf"- | otherwise- = "package-db"--packageDbOpts :: HcPkgInfo -> PackageDB -> String-packageDbOpts _ GlobalPackageDB = "--global"-packageDbOpts _ UserPackageDB = "--user"-packageDbOpts hpi (SpecificPackageDB db) = "--" ++ packageDbFlag hpi ++ "=" ++ db--verbosityOpts :: HcPkgInfo -> Verbosity -> [String]-verbosityOpts hpi v- | noVerboseFlag hpi- = []- | v >= deafening = ["-v2"]- | v == silent = ["-v0"]- | otherwise = []
− Distribution/Simple/Program/Hpc.hs
@@ -1,110 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Hpc--- Copyright : Thomas Tuegel 2011------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides an library interface to the @hpc@ program.--module Distribution.Simple.Program.Hpc- ( markup- , union- ) where--import Prelude ()-import Distribution.Compat.Prelude--import System.Directory (makeRelativeToCurrentDirectory)--import Distribution.ModuleName-import Distribution.Simple.Program.Run-import Distribution.Simple.Program.Types-import Distribution.Pretty-import Distribution.Simple.Utils-import Distribution.Verbosity-import Distribution.Version---- | Invoke hpc with the given parameters.------ Prior to HPC version 0.7 (packaged with GHC 7.8), hpc did not handle--- multiple .mix paths correctly, so we print a warning, and only pass it the--- first path in the list. This means that e.g. test suites that import their--- library as a dependency can still work, but those that include the library--- modules directly (in other-modules) don't.-markup :: ConfiguredProgram- -> Version- -> Verbosity- -> FilePath -- ^ Path to .tix file- -> [FilePath] -- ^ Paths to .mix file directories- -> FilePath -- ^ Path where html output should be located- -> [ModuleName] -- ^ List of modules to exclude from report- -> IO ()-markup hpc hpcVer verbosity tixFile hpcDirs destDir excluded = do- hpcDirs' <- if withinRange hpcVer (orLaterVersion version07)- then return hpcDirs- else do- warn verbosity $ "Your version of HPC (" ++ prettyShow hpcVer- ++ ") does not properly handle multiple search paths. "- ++ "Coverage report generation may fail unexpectedly. These "- ++ "issues are addressed in version 0.7 or later (GHC 7.8 or "- ++ "later)."- ++ if null droppedDirs- then ""- else " The following search paths have been abandoned: "- ++ show droppedDirs- return passedDirs-- -- Prior to GHC 8.0, hpc assumes all .mix paths are relative.- hpcDirs'' <- traverse makeRelativeToCurrentDirectory hpcDirs'-- runProgramInvocation verbosity- (markupInvocation hpc tixFile hpcDirs'' destDir excluded)- where- version07 = mkVersion [0, 7]- (passedDirs, droppedDirs) = splitAt 1 hpcDirs--markupInvocation :: ConfiguredProgram- -> FilePath -- ^ Path to .tix file- -> [FilePath] -- ^ Paths to .mix file directories- -> FilePath -- ^ Path where html output should be- -- located- -> [ModuleName] -- ^ List of modules to exclude from- -- report- -> ProgramInvocation-markupInvocation hpc tixFile hpcDirs destDir excluded =- let args = [ "markup", tixFile- , "--destdir=" ++ destDir- ]- ++ map ("--hpcdir=" ++) hpcDirs- ++ ["--exclude=" ++ prettyShow moduleName- | moduleName <- excluded ]- in programInvocation hpc args--union :: ConfiguredProgram- -> Verbosity- -> [FilePath] -- ^ Paths to .tix files- -> FilePath -- ^ Path to resultant .tix file- -> [ModuleName] -- ^ List of modules to exclude from union- -> IO ()-union hpc verbosity tixFiles outFile excluded =- runProgramInvocation verbosity- (unionInvocation hpc tixFiles outFile excluded)--unionInvocation :: ConfiguredProgram- -> [FilePath] -- ^ Paths to .tix files- -> FilePath -- ^ Path to resultant .tix file- -> [ModuleName] -- ^ List of modules to exclude from union- -> ProgramInvocation-unionInvocation hpc tixFiles outFile excluded =- programInvocation hpc $ concat- [ ["sum", "--union"]- , tixFiles- , ["--output=" ++ outFile]- , ["--exclude=" ++ prettyShow moduleName- | moduleName <- excluded ]- ]
− Distribution/Simple/Program/Internal.hs
@@ -1,47 +0,0 @@--------------------------------------------------------------------------------- |--- 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 Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.Generic(safeTail)---- | 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) ((safeTail 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/Ld.hs
@@ -1,92 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Ld--- Copyright : Duncan Coutts 2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides an library interface to the @ld@ linker program.--module Distribution.Simple.Program.Ld (- combineObjectFiles,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.Compiler (arResponseFilesSupported)-import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))-import Distribution.Simple.Program.ResponseFile- ( withResponseFile )-import Distribution.Simple.Program.Run- ( ProgramInvocation, programInvocation, multiStageProgramInvocation- , runProgramInvocation )-import Distribution.Simple.Program.Types- ( ConfiguredProgram(..) )-import Distribution.Simple.Setup- ( fromFlagOrDefault, configUseResponseFiles )-import Distribution.Simple.Utils- ( defaultTempFileOptions )-import Distribution.Verbosity- ( Verbosity )--import System.Directory- ( renameFile )-import System.FilePath- ( (<.>), takeDirectory )---- | Call @ld -r@ to link a bunch of object files together.----combineObjectFiles :: Verbosity -> LocalBuildInfo -> ConfiguredProgram- -> FilePath -> [FilePath] -> IO ()-combineObjectFiles verbosity lbi ld target files = do-- -- Unlike "ar", the "ld" tool is not designed to be used with xargs. That is,- -- if we have more object files than fit on a single command line then we- -- have a slight problem. What we have to do is link files in batches into- -- a temp object file and then include that one in the next batch.-- let simpleArgs = ["-r", "-o", target]-- initialArgs = ["-r", "-o", target]- middleArgs = ["-r", "-o", target, tmpfile]- finalArgs = middleArgs-- simple = programInvocation ld simpleArgs- initial = programInvocation ld initialArgs- middle = programInvocation ld middleArgs- final = programInvocation ld finalArgs-- targetDir = takeDirectory target-- invokeWithResponesFile :: FilePath -> ProgramInvocation- invokeWithResponesFile atFile =- programInvocation ld $ simpleArgs ++ ['@' : atFile]-- oldVersionManualOverride =- fromFlagOrDefault False $ configUseResponseFiles $ configFlags lbi- -- Whether ghc's ar supports response files is a good proxy for- -- whether ghc's ld supports them as well.- responseArgumentsNotSupported =- not (arResponseFilesSupported (compiler lbi))-- if oldVersionManualOverride || responseArgumentsNotSupported- then- run $ multiStageProgramInvocation simple (initial, middle, final) files- else- withResponseFile verbosity defaultTempFileOptions targetDir "ld.rsp" Nothing files $- \path -> runProgramInvocation verbosity $ invokeWithResponesFile path-- where- tmpfile = target <.> "tmp" -- perhaps should use a proper temp file-- run :: [ProgramInvocation] -> IO ()- run [] = return ()- run [inv] = runProgramInvocation verbosity inv- run (inv:invs) = do runProgramInvocation verbosity inv- renameFile target tmpfile- run invs
− Distribution/Simple/Program/ResponseFile.hs
@@ -1,60 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.ResponseFile--- Copyright : (c) Sergey Vinokurov 2017--- License : BSD3-style------ Maintainer : cabal-devel@haskell.org--- Created : 23 July 2017-------------------------------------------------------------------------------module Distribution.Simple.Program.ResponseFile (withResponseFile) where--import Prelude ()-import System.IO (TextEncoding, hSetEncoding, hPutStr, hClose)--import Distribution.Compat.Prelude-import Distribution.Simple.Utils (TempFileOptions, withTempFileEx, debug)-import Distribution.Verbosity--withResponseFile- :: Verbosity- -> TempFileOptions- -> FilePath -- ^ Working directory to create response file in.- -> FilePath -- ^ Template for response file name.- -> Maybe TextEncoding -- ^ Encoding to use for response file contents.- -> [String] -- ^ Arguments to put into response file.- -> (FilePath -> IO a)- -> IO a-withResponseFile verbosity tmpFileOpts workDir fileNameTemplate encoding arguments f =- withTempFileEx tmpFileOpts workDir fileNameTemplate $ \responseFileName hf -> do- traverse_ (hSetEncoding hf) encoding- let responseContents = unlines $ map escapeResponseFileArg arguments- hPutStr hf responseContents- hClose hf- debug verbosity $ responseFileName ++ " contents: <<<"- debug verbosity responseContents- debug verbosity $ ">>> " ++ responseFileName- f responseFileName---- Support a gcc-like response file syntax. Each separate--- argument and its possible parameter(s), will be separated in the--- response file by an actual newline; all other whitespace,--- single quotes, double quotes, and the character used for escaping--- (backslash) are escaped. The called program will need to do a similar--- inverse operation to de-escape and re-constitute the argument list.-escapeResponseFileArg :: String -> String-escapeResponseFileArg = reverse . foldl' escape []- where- escape :: String -> Char -> String- escape cs c =- case c of- '\\' -> c:'\\':cs- '\'' -> c:'\\':cs- '"' -> c:'\\':cs- _ | isSpace c -> c:'\\':cs- | otherwise -> c:cs--
− Distribution/Simple/Program/Run.hs
@@ -1,297 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Run--- Copyright : Duncan Coutts 2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides a data type for program invocations and functions to--- run them.--module Distribution.Simple.Program.Run (- ProgramInvocation(..),- IOEncoding(..),- emptyProgramInvocation,- simpleProgramInvocation,- programInvocation,- multiStageProgramInvocation,-- runProgramInvocation,- getProgramInvocationOutput,- getProgramInvocationLBS,- getProgramInvocationOutputAndErrors,-- getEffectiveEnvironment,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Compat.Environment-import Distribution.Simple.Program.Types-import Distribution.Simple.Utils-import Distribution.Utils.Generic-import Distribution.Verbosity--import System.FilePath (searchPathSeparator)--import qualified Data.ByteString.Lazy as LBS-import qualified Data.Map as Map---- | Represents a specific invocation of a specific program.------ This is used as an intermediate type between deciding how to call a program--- and actually doing it. This provides the opportunity to the caller to--- adjust how the program will be called. These invocations can either be run--- directly or turned into shell or batch scripts.----data ProgramInvocation = ProgramInvocation {- progInvokePath :: FilePath,- progInvokeArgs :: [String],- progInvokeEnv :: [(String, Maybe String)],- -- Extra paths to add to PATH- progInvokePathEnv :: [FilePath],- progInvokeCwd :: Maybe FilePath,- progInvokeInput :: Maybe IOData,- progInvokeInputEncoding :: IOEncoding, -- ^ TODO: remove this, make user decide when constructing 'progInvokeInput'.- progInvokeOutputEncoding :: IOEncoding- }--data IOEncoding = IOEncodingText -- locale mode text- | IOEncodingUTF8 -- always utf8--encodeToIOData :: IOEncoding -> IOData -> IOData-encodeToIOData _ iod@(IODataBinary _) = iod-encodeToIOData IOEncodingText iod@(IODataText _) = iod-encodeToIOData IOEncodingUTF8 (IODataText str) = IODataBinary (toUTF8LBS str)--emptyProgramInvocation :: ProgramInvocation-emptyProgramInvocation =- ProgramInvocation {- progInvokePath = "",- progInvokeArgs = [],- progInvokeEnv = [],- progInvokePathEnv = [],- progInvokeCwd = Nothing,- progInvokeInput = Nothing,- progInvokeInputEncoding = IOEncodingText,- progInvokeOutputEncoding = IOEncodingText- }--simpleProgramInvocation :: FilePath -> [String] -> ProgramInvocation-simpleProgramInvocation path args =- emptyProgramInvocation {- progInvokePath = path,- progInvokeArgs = args- }--programInvocation :: ConfiguredProgram -> [String] -> ProgramInvocation-programInvocation prog args =- emptyProgramInvocation {- progInvokePath = programPath prog,- progInvokeArgs = programDefaultArgs prog- ++ args- ++ programOverrideArgs prog,- progInvokeEnv = programOverrideEnv prog- }---runProgramInvocation :: Verbosity -> ProgramInvocation -> IO ()-runProgramInvocation verbosity- ProgramInvocation {- progInvokePath = path,- progInvokeArgs = args,- progInvokeEnv = [],- progInvokePathEnv = [],- progInvokeCwd = Nothing,- progInvokeInput = Nothing- } =- rawSystemExit verbosity path args--runProgramInvocation verbosity- ProgramInvocation {- progInvokePath = path,- progInvokeArgs = args,- progInvokeEnv = envOverrides,- progInvokePathEnv = extraPath,- progInvokeCwd = mcwd,- progInvokeInput = Nothing- } = do- pathOverride <- getExtraPathEnv envOverrides extraPath- menv <- getEffectiveEnvironment (envOverrides ++ pathOverride)- exitCode <- rawSystemIOWithEnv verbosity- path args- mcwd menv- Nothing Nothing Nothing- when (exitCode /= ExitSuccess) $- exitWith exitCode--runProgramInvocation verbosity- ProgramInvocation {- progInvokePath = path,- progInvokeArgs = args,- progInvokeEnv = envOverrides,- progInvokePathEnv = extraPath,- progInvokeCwd = mcwd,- progInvokeInput = Just inputStr,- progInvokeInputEncoding = encoding- } = do- pathOverride <- getExtraPathEnv envOverrides extraPath- menv <- getEffectiveEnvironment (envOverrides ++ pathOverride)- (_, errors, exitCode) <- rawSystemStdInOut verbosity- path args- mcwd menv- (Just input) IODataModeBinary- when (exitCode /= ExitSuccess) $- die' verbosity $ "'" ++ path ++ "' exited with an error:\n" ++ errors- where- input = encodeToIOData encoding inputStr--getProgramInvocationOutput :: Verbosity -> ProgramInvocation -> IO String-getProgramInvocationOutput verbosity inv = do- (output, errors, exitCode) <- getProgramInvocationOutputAndErrors verbosity inv- when (exitCode /= ExitSuccess) $- die' verbosity $ "'" ++ progInvokePath inv ++ "' exited with an error:\n" ++ errors- return output--getProgramInvocationLBS :: Verbosity -> ProgramInvocation -> IO LBS.ByteString-getProgramInvocationLBS verbosity inv = do- (output, errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeBinary- when (exitCode /= ExitSuccess) $- die' verbosity $ "'" ++ progInvokePath inv ++ "' exited with an error:\n" ++ errors- return output--getProgramInvocationOutputAndErrors :: Verbosity -> ProgramInvocation- -> IO (String, String, ExitCode)-getProgramInvocationOutputAndErrors verbosity inv = case progInvokeOutputEncoding inv of- IOEncodingText -> do- (output, errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeText- return (output, errors, exitCode)- IOEncodingUTF8 -> do- (output', errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeBinary- return (normaliseLineEndings (fromUTF8LBS output'), errors, exitCode)--getProgramInvocationIODataAndErrors- :: KnownIODataMode mode => Verbosity -> ProgramInvocation -> IODataMode mode- -> IO (mode, String, ExitCode)-getProgramInvocationIODataAndErrors- verbosity- ProgramInvocation- { progInvokePath = path- , progInvokeArgs = args- , progInvokeEnv = envOverrides- , progInvokePathEnv = extraPath- , progInvokeCwd = mcwd- , progInvokeInput = minputStr- , progInvokeInputEncoding = encoding- }- mode = do- pathOverride <- getExtraPathEnv envOverrides extraPath- menv <- getEffectiveEnvironment (envOverrides ++ pathOverride)- rawSystemStdInOut verbosity path args mcwd menv input mode- where- input = encodeToIOData encoding <$> minputStr--getExtraPathEnv :: [(String, Maybe String)] -> [FilePath] -> IO [(String, Maybe String)]-getExtraPathEnv _ [] = return []-getExtraPathEnv env extras = do- mb_path <- case lookup "PATH" env of- Just x -> return x- Nothing -> lookupEnv "PATH"- let extra = intercalate [searchPathSeparator] extras- path' = case mb_path of- Nothing -> extra- Just path -> extra ++ searchPathSeparator : path- return [("PATH", Just path')]---- | Return the current environment extended with the given overrides.--- If an entry is specified twice in @overrides@, the second entry takes--- precedence.----getEffectiveEnvironment :: [(String, Maybe String)]- -> IO (Maybe [(String, String)])-getEffectiveEnvironment [] = return Nothing-getEffectiveEnvironment overrides =- fmap (Just . Map.toList . apply overrides . Map.fromList) getEnvironment- where- apply os env = foldl' (flip update) env os- update (var, Nothing) = Map.delete var- update (var, Just val) = Map.insert var val---- | Like the unix xargs program. Useful for when we've got very long command--- lines that might overflow an OS limit on command line length and so you--- need to invoke a command multiple times to get all the args in.------ It takes four template invocations corresponding to the simple, initial,--- middle and last invocations. If the number of args given is small enough--- that we can get away with just a single invocation then the simple one is--- used:------ > $ simple args------ If the number of args given means that we need to use multiple invocations--- then the templates for the initial, middle and last invocations are used:------ > $ initial args_0--- > $ middle args_1--- > $ middle args_2--- > ...--- > $ final args_n----multiStageProgramInvocation- :: ProgramInvocation- -> (ProgramInvocation, ProgramInvocation, ProgramInvocation)- -> [String]- -> [ProgramInvocation]-multiStageProgramInvocation simple (initial, middle, final) args =-- let argSize inv = length (progInvokePath inv)- + foldl' (\s a -> length a + 1 + s) 1 (progInvokeArgs inv)- fixedArgSize = maximum (map argSize [simple, initial, middle, final])- chunkSize = maxCommandLineSize - fixedArgSize-- in case splitChunks chunkSize args of- [] -> [ simple ]-- [c] -> [ simple `appendArgs` c ]-- (c:c2:cs) | (xs, x) <- unsnocNE (c2:|cs) ->- [ initial `appendArgs` c ]- ++ [ middle `appendArgs` c'| c' <- xs ]- ++ [ final `appendArgs` x ]-- where- appendArgs :: ProgramInvocation -> [String] -> ProgramInvocation- inv `appendArgs` as = inv { progInvokeArgs = progInvokeArgs inv ++ as }-- splitChunks :: Int -> [[a]] -> [[[a]]]- splitChunks len = unfoldr $ \s ->- if null s then Nothing- else Just (chunk len s)-- chunk :: Int -> [[a]] -> ([[a]], [[a]])- chunk len (s:_) | length s >= len = error toolong- chunk len ss = chunk' [] len ss-- chunk' :: [[a]] -> Int -> [[a]] -> ([[a]], [[a]])- chunk' acc len (s:ss)- | len' < len = chunk' (s:acc) (len-len'-1) ss- where len' = length s- chunk' acc _ ss = (reverse acc, ss)-- toolong = "multiStageProgramInvocation: a single program arg is larger "- ++ "than the maximum command line length!"-----FIXME: discover this at configure time or runtime on unix--- The value is 32k on Windows and posix specifies a minimum of 4k--- but all sensible unixes use more than 4k.--- we could use getSysVar ArgumentLimit but that's in the unix lib----maxCommandLineSize :: Int-maxCommandLineSize = 30 * 1024
− Distribution/Simple/Program/Script.hs
@@ -1,114 +0,0 @@-{-# LANGUAGE GADTs #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Script--- Copyright : Duncan Coutts 2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides an library interface to the @hc-pkg@ program.--- Currently only GHC and LHC have hc-pkg programs.--module Distribution.Simple.Program.Script (-- invocationAsSystemScript,- invocationAsShellScript,- invocationAsBatchFile,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.Program.Run-import Distribution.Simple.Utils-import Distribution.System---- | Generate a system script, either POSIX shell script or Windows batch file--- as appropriate for the given system.----invocationAsSystemScript :: OS -> ProgramInvocation -> String-invocationAsSystemScript Windows = invocationAsBatchFile-invocationAsSystemScript _ = invocationAsShellScript----- | Generate a POSIX shell script that invokes a program.----invocationAsShellScript :: ProgramInvocation -> String-invocationAsShellScript- ProgramInvocation {- progInvokePath = path,- progInvokeArgs = args,- progInvokeEnv = envExtra,- progInvokeCwd = mcwd,- progInvokeInput = minput- } = unlines $- [ "#!/bin/sh" ]- ++ concatMap setEnv envExtra- ++ [ "cd " ++ quote cwd | cwd <- maybeToList mcwd ]- ++ [ (case minput of- Nothing -> ""- Just input -> "echo " ++ quote (iodataToText input) ++ " | ")- ++ unwords (map quote $ path : args) ++ " \"$@\""]-- where- setEnv (var, Nothing) = ["unset " ++ var, "export " ++ var]- setEnv (var, Just val) = ["export " ++ var ++ "=" ++ quote val]-- quote :: String -> String- quote s = "'" ++ escape s ++ "'"-- escape [] = []- escape ('\'':cs) = "'\\''" ++ escape cs- escape (c :cs) = c : escape cs--iodataToText :: IOData -> String-iodataToText (IODataText str) = str-iodataToText (IODataBinary lbs) = fromUTF8LBS lbs----- | Generate a Windows batch file that invokes a program.----invocationAsBatchFile :: ProgramInvocation -> String-invocationAsBatchFile- ProgramInvocation {- progInvokePath = path,- progInvokeArgs = args,- progInvokeEnv = envExtra,- progInvokeCwd = mcwd,- progInvokeInput = minput- } = unlines $- [ "@echo off" ]- ++ map setEnv envExtra- ++ [ "cd \"" ++ cwd ++ "\"" | cwd <- maybeToList mcwd ]- ++ case minput of- Nothing ->- [ path ++ concatMap (' ':) args ]-- Just input ->- [ "(" ]- ++ [ "echo " ++ escape line | line <- lines $ iodataToText input ]- ++ [ ") | "- ++ "\"" ++ path ++ "\""- ++ concatMap (\arg -> ' ':quote arg) args ]-- where- setEnv (var, Nothing) = "set " ++ var ++ "="- setEnv (var, Just val) = "set " ++ var ++ "=" ++ escape val-- quote :: String -> String- quote s = "\"" ++ escapeQ s ++ "\""-- escapeQ [] = []- escapeQ ('"':cs) = "\"\"\"" ++ escapeQ cs- escapeQ (c :cs) = c : escapeQ cs-- escape [] = []- escape ('|':cs) = "^|" ++ escape cs- escape ('<':cs) = "^<" ++ escape cs- escape ('>':cs) = "^>" ++ escape cs- escape ('&':cs) = "^&" ++ escape cs- escape ('(':cs) = "^(" ++ escape cs- escape (')':cs) = "^)" ++ escape cs- escape ('^':cs) = "^^" ++ escape cs- escape (c :cs) = c : escape cs
− Distribution/Simple/Program/Strip.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Strip------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module provides an library interface to the @strip@ program.--module Distribution.Simple.Program.Strip (stripLib, stripExe)- where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Simple.Program-import Distribution.Simple.Utils-import Distribution.System-import Distribution.Verbosity-import Distribution.Version--import System.FilePath (takeBaseName)--runStrip :: Verbosity -> ProgramDb -> FilePath -> [String] -> IO ()-runStrip verbosity progDb path args =- case lookupProgram stripProgram progDb of- Just strip -> runProgram verbosity strip (args ++ [path])- Nothing -> unless (buildOS == Windows) $- -- Don't bother warning on windows, we don't expect them to- -- have the strip program anyway.- warn verbosity $ "Unable to strip executable or library '"- ++ (takeBaseName path)- ++ "' (missing the 'strip' program)"--stripExe :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()-stripExe verbosity (Platform _arch os) progdb path =- runStrip verbosity progdb path args- where- args = case os of- OSX -> ["-x"] -- By default, stripping the ghc binary on at least- -- some OS X installations causes:- -- HSbase-3.0.o: unknown symbol `_environ'"- -- The -x flag fixes that.- _ -> []--stripLib :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()-stripLib verbosity (Platform arch os) progdb path = do- case os of- 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- -- #1784.- return()- Linux | arch == I386 ->- -- Versions of 'strip' on 32-bit Linux older than 2.18 are- -- broken. See #2339.- let okVersion = orLaterVersion (mkVersion [2,18])- in case programVersion =<< lookupProgram stripProgram progdb of- Just v | withinRange v okVersion ->- runStrip verbosity progdb path args- _ -> warn verbosity $ "Unable to strip library '"- ++ (takeBaseName path)- ++ "' (version of 'strip' too old; "- ++ "requires >= 2.18 on 32-bit Linux)"- _ -> runStrip verbosity progdb path args- where- args = ["--strip-unneeded"]
− Distribution/Simple/Program/Types.hs
@@ -1,190 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE DeriveDataTypeable #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Program.Types--- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This provides an abstraction which deals with configuring and running--- programs. A 'Program' is a static notion of a known program. A--- 'ConfiguredProgram' is a 'Program' that has been found on the current--- machine and is ready to be run (possibly with some user-supplied default--- args). Configuring a program involves finding its location and if necessary--- finding its version. There's reasonable default behavior for trying to find--- \"foo\" in PATH, being able to override its location, etc.----module Distribution.Simple.Program.Types (- -- * Program and functions for constructing them- Program(..),- ProgramSearchPath,- ProgramSearchPathEntry(..),- simpleProgram,-- -- * Configured program and related functions- ConfiguredProgram(..),- programPath,- suppressOverrideArgs,- ProgArg,- ProgramLocation(..),- simpleConfiguredProgram,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.PackageDescription-import Distribution.Simple.Program.Find-import Distribution.Version-import Distribution.Verbosity--import qualified Data.Map as Map---- | Represents a program which can be configured.------ Note: rather than constructing this directly, start with 'simpleProgram' and--- override any extra fields.----data Program = Program {- -- | The simple name of the program, eg. ghc- programName :: String,-- -- | A function to search for the program if its location was not- -- specified by the user. Usually this will just be a call to- -- 'findProgramOnSearchPath'.- --- -- 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, [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.- programFindVersion :: Verbosity -> FilePath -> IO (Maybe Version),-- -- | A function to do any additional configuration after we have- -- located the program (and perhaps identified its version). For example- -- it could add args, or environment vars.- programPostConf :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram,- -- | A function that filters any arguments that don't impact the output- -- from a commandline. Used to limit the volatility of dependency hashes- -- when using new-build.- programNormaliseArgs :: Maybe Version -> PackageDescription -> [String] -> [String]- }-instance Show Program where- show (Program name _ _ _ _) = "Program: " ++ name--type ProgArg = String---- | Represents a program which has been configured and is thus ready to be run.------ These are usually made by configuring a 'Program', but if you have to--- construct one directly then start with 'simpleConfiguredProgram' and--- override any extra fields.----data ConfiguredProgram = ConfiguredProgram {- -- | Just the name again- programId :: String,-- -- | The version of this program, if it is known.- programVersion :: Maybe Version,-- -- | Default command-line args for this program.- -- These flags will appear first on the command line, so they can be- -- overridden by subsequent flags.- programDefaultArgs :: [String],-- -- | Override command-line args for this program.- -- These flags will appear last on the command line, so they override- -- all earlier flags.- programOverrideArgs :: [String],-- -- | Override environment variables for this program.- -- These env vars will extend\/override the prevailing environment of- -- the current to form the environment for the new process.- programOverrideEnv :: [(String, Maybe String)],-- -- | A key-value map listing various properties of the program, useful- -- for feature detection. Populated during the configuration step, key- -- names depend on the specific program.- programProperties :: Map.Map String String,-- -- | Location of the program. eg. @\/usr\/bin\/ghc-6.4@- 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, Typeable)--instance Binary ConfiguredProgram-instance Structured ConfiguredProgram---- | Where a program was found. Also tells us whether it's specified by user or--- not. This includes not just the path, but the program as well.-data ProgramLocation- = UserSpecified { locationPath :: FilePath }- -- ^The user gave the path to this program,- -- eg. --ghc-path=\/usr\/bin\/ghc-6.6- | FoundOnSystem { locationPath :: FilePath }- -- ^The program was found automatically.- deriving (Eq, Generic, Read, Show, Typeable)--instance Binary ProgramLocation-instance Structured ProgramLocation---- | The full path of a configured program.-programPath :: ConfiguredProgram -> FilePath-programPath = locationPath . programLocation---- | Suppress any extra arguments added by the user.-suppressOverrideArgs :: ConfiguredProgram -> ConfiguredProgram-suppressOverrideArgs prog = prog { programOverrideArgs = [] }---- | Make a simple named program.------ By default we'll just search for it in the path and not try to find the--- version name. You can override these behaviours if necessary, eg:------ > (simpleProgram "foo") { programFindLocation = ... , programFindVersion ... }----simpleProgram :: String -> Program-simpleProgram name = Program {- programName = name,- programFindLocation = \v p -> findProgramOnSearchPath v p name,- programFindVersion = \_ _ -> return Nothing,- programPostConf = \_ p -> return p,- programNormaliseArgs = \_ _ -> id- }---- | Make a simple 'ConfiguredProgram'.------ > simpleConfiguredProgram "foo" (FoundOnSystem path)----simpleConfiguredProgram :: String -> ProgramLocation -> ConfiguredProgram-simpleConfiguredProgram name loc = ConfiguredProgram {- programId = name,- programVersion = Nothing,- programDefaultArgs = [],- programOverrideArgs = [],- programOverrideEnv = [],- programProperties = Map.empty,- programLocation = loc,- programMonitorFiles = [] -- did not look in any other locations- }
− Distribution/Simple/Register.hs
@@ -1,595 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Register--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module deals with registering and unregistering packages. There are a--- couple ways it can do this, one is to do it directly. Another is to generate--- a script that can be run later to do it. The idea here being that the user--- is shielded from the details of what command to use for package registration--- for a particular compiler. In practice this aspect was not especially--- popular so we also provide a way to simply generate the package registration--- file which then must be manually passed to @ghc-pkg@. It is possible to--- generate registration information for where the package is to be installed,--- or alternatively to register the package in place in the build tree. The--- latter is occasionally handy, and will become more important when we try to--- build multi-package systems.------ This module does not delegate anything to the per-compiler modules but just--- mixes it all in this module, which is rather unsatisfactory. The script--- generation and the unregister feature are not well used or tested.--module Distribution.Simple.Register (- register,- unregister,-- internalPackageDBPath,-- initPackageDB,- doesPackageDBExist,- createPackageDB,- deletePackageDB,-- abiHash,- invokeHcPkg,- registerPackage,- HcPkg.RegisterOptions(..),- HcPkg.defaultRegisterOptions,- generateRegistrationInfo,- inplaceInstalledPackageInfo,- absoluteInstalledPackageInfo,- generalInstalledPackageInfo,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.TargetInfo-import Distribution.Types.LocalBuildInfo-import Distribution.Types.ComponentLocalBuildInfo--import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.BuildPaths-import Distribution.Simple.BuildTarget--import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS-import qualified Distribution.Simple.UHC as UHC-import qualified Distribution.Simple.HaskellSuite as HaskellSuite-import qualified Distribution.Simple.PackageIndex as Index--import Distribution.Backpack.DescribeUnitId-import Distribution.Simple.Compiler-import Distribution.Simple.Program-import Distribution.Simple.Program.Script-import qualified Distribution.Simple.Program.HcPkg as HcPkg-import Distribution.Simple.Setup-import Distribution.PackageDescription-import Distribution.Package-import Distribution.License (licenseToSPDX, licenseFromSPDX)-import qualified Distribution.InstalledPackageInfo as IPI-import Distribution.InstalledPackageInfo (InstalledPackageInfo)-import Distribution.Simple.Utils-import Distribution.Utils.MapAccum-import Distribution.System-import Distribution.Pretty-import Distribution.Verbosity as Verbosity-import Distribution.Version-import Distribution.Compat.Graph (IsNode(nodeKey))--import System.FilePath ((</>), (<.>), isAbsolute)-import System.Directory--import qualified Data.ByteString.Lazy.Char8 as BS.Char8---- -------------------------------------------------------------------------------- Registration--register :: PackageDescription -> LocalBuildInfo- -> RegisterFlags -- ^Install in the user's database?; verbose- -> IO ()-register pkg_descr lbi0 flags =- -- Duncan originally asked for us to not register/install files- -- when there was no public library. But with per-component- -- configure, we legitimately need to install internal libraries- -- so that we can get them. So just unconditionally install.- doRegister- where- doRegister = do- targets <- readTargetInfos verbosity pkg_descr lbi0 (regArgs flags)-- -- It's important to register in build order, because ghc-pkg- -- will complain if a dependency is not registered.- let componentsToRegister- = neededTargetsInBuildOrder' pkg_descr lbi0 (map nodeKey targets)-- (_, ipi_mbs) <-- mapAccumM `flip` installedPkgs lbi0 `flip` componentsToRegister $ \index tgt ->- case targetComponent tgt of- CLib lib -> do- let clbi = targetCLBI tgt- lbi = lbi0 { installedPkgs = index }- ipi <- generateOne pkg_descr lib lbi clbi flags- return (Index.insert ipi index, Just ipi)- _ -> return (index, Nothing)-- registerAll pkg_descr lbi0 flags (catMaybes ipi_mbs)- where- verbosity = fromFlag (regVerbosity flags)--generateOne :: PackageDescription -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo- -> RegisterFlags- -> IO InstalledPackageInfo-generateOne pkg lib lbi clbi regFlags- = do- absPackageDBs <- absolutePackageDBPaths packageDbs- installedPkgInfo <- generateRegistrationInfo- verbosity pkg lib lbi clbi inplace reloc distPref- (registrationPackageDB absPackageDBs)- info verbosity (IPI.showInstalledPackageInfo installedPkgInfo)- return installedPkgInfo- where- inplace = fromFlag (regInPlace regFlags)- reloc = relocatable lbi- -- FIXME: there's really no guarantee this will work.- -- registering into a totally different db stack can- -- fail if dependencies cannot be satisfied.- packageDbs = nub $ withPackageDB lbi- ++ maybeToList (flagToMaybe (regPackageDB regFlags))- distPref = fromFlag (regDistPref regFlags)- verbosity = fromFlag (regVerbosity regFlags)--registerAll :: PackageDescription -> LocalBuildInfo -> RegisterFlags- -> [InstalledPackageInfo]- -> IO ()-registerAll pkg lbi regFlags ipis- = do- when (fromFlag (regPrintId regFlags)) $ do- for_ ipis $ \installedPkgInfo ->- -- Only print the public library's IPI- when (packageId installedPkgInfo == packageId pkg- && IPI.sourceLibName installedPkgInfo == LMainLibName) $- putStrLn (prettyShow (IPI.installedUnitId installedPkgInfo))-- -- Three different modes:- case () of- _ | modeGenerateRegFile -> writeRegistrationFileOrDirectory- | modeGenerateRegScript -> writeRegisterScript- | otherwise -> do- for_ ipis $ \ipi -> do- setupMessage' verbosity "Registering" (packageId pkg)- (CLibName (IPI.sourceLibName ipi))- (Just (IPI.instantiatedWith ipi))- registerPackage verbosity (compiler lbi) (withPrograms lbi)- packageDbs ipi HcPkg.defaultRegisterOptions-- where- modeGenerateRegFile = isJust (flagToMaybe (regGenPkgConf regFlags))- regFile = fromMaybe (prettyShow (packageId pkg) <.> "conf")- (fromFlag (regGenPkgConf regFlags))-- modeGenerateRegScript = fromFlag (regGenScript regFlags)-- -- FIXME: there's really no guarantee this will work.- -- registering into a totally different db stack can- -- fail if dependencies cannot be satisfied.- packageDbs = nub $ withPackageDB lbi- ++ maybeToList (flagToMaybe (regPackageDB regFlags))- verbosity = fromFlag (regVerbosity regFlags)-- writeRegistrationFileOrDirectory = do- -- Handles overwriting both directory and file- deletePackageDB regFile- case ipis of- [installedPkgInfo] -> do- info verbosity ("Creating package registration file: " ++ regFile)- writeUTF8File regFile (IPI.showInstalledPackageInfo installedPkgInfo)- _ -> do- info verbosity ("Creating package registration directory: " ++ regFile)- createDirectory regFile- let num_ipis = length ipis- lpad m xs = replicate (m - length ys) '0' ++ ys- where ys = take m xs- number i = lpad (length (show num_ipis)) (show i)- for_ (zip ([1..] :: [Int]) ipis) $ \(i, installedPkgInfo) ->- writeUTF8File (regFile </> (number i ++ "-" ++ prettyShow (IPI.installedUnitId installedPkgInfo)))- (IPI.showInstalledPackageInfo installedPkgInfo)-- writeRegisterScript =- case compilerFlavor (compiler lbi) of- UHC -> notice verbosity "Registration scripts not needed for uhc"- _ -> withHcPkg verbosity- "Registration scripts are not implemented for this compiler"- (compiler lbi) (withPrograms lbi)- (writeHcPkgRegisterScript verbosity ipis packageDbs)---generateRegistrationInfo :: Verbosity- -> PackageDescription- -> Library- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> Bool- -> Bool- -> FilePath- -> PackageDB- -> IO InstalledPackageInfo-generateRegistrationInfo verbosity pkg lib lbi clbi inplace reloc distPref packageDb = do- --TODO: eliminate pwd!- pwd <- getCurrentDirectory-- installedPkgInfo <-- if inplace- -- NB: With an inplace installation, the user may run './Setup- -- build' to update the library files, without reregistering.- -- In this case, it is critical that the ABI hash not flip.- then return (inplaceInstalledPackageInfo pwd distPref- pkg (mkAbiHash "inplace") lib lbi clbi)- else do- abi_hash <- abiHash verbosity pkg distPref lbi lib clbi- if reloc- then relocRegistrationInfo verbosity- pkg lib lbi clbi abi_hash packageDb- else return (absoluteInstalledPackageInfo- pkg abi_hash lib lbi clbi)--- return installedPkgInfo---- | Compute the 'AbiHash' of a library that we built inplace.-abiHash :: Verbosity- -> PackageDescription- -> FilePath- -> LocalBuildInfo- -> Library- -> ComponentLocalBuildInfo- -> IO AbiHash-abiHash verbosity pkg distPref lbi lib clbi =- case compilerFlavor comp of- GHC -> do- fmap mkAbiHash $ GHC.libAbiHash verbosity pkg lbi' lib clbi- GHCJS -> do- fmap mkAbiHash $ GHCJS.libAbiHash verbosity pkg lbi' lib clbi- _ -> return (mkAbiHash "")- where- comp = compiler lbi- lbi' = lbi {- withPackageDB = withPackageDB lbi- ++ [SpecificPackageDB (internalPackageDBPath lbi distPref)]- }--relocRegistrationInfo :: Verbosity- -> PackageDescription- -> Library- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> AbiHash- -> PackageDB- -> IO InstalledPackageInfo-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 abi_hash lib lbi clbi fs)- _ -> die' verbosity- "Distribution.Simple.Register.relocRegistrationInfo: \- \not implemented for this compiler"--initPackageDB :: Verbosity -> Compiler -> ProgramDb -> FilePath -> IO ()-initPackageDB verbosity comp progdb dbPath =- createPackageDB verbosity comp progdb False dbPath---- | Create an empty package DB at the specified location.-createPackageDB :: Verbosity -> Compiler -> ProgramDb -> 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- UHC -> return ()- HaskellSuite _ -> HaskellSuite.initPackageDB verbosity progdb dbPath- _ -> die' verbosity $- "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 -> ProgramDb -> PackageDBStack- -> [String] -> IO ()-invokeHcPkg verbosity comp progdb dbStack extraArgs =- withHcPkg verbosity "invokeHcPkg" comp progdb- (\hpi -> HcPkg.invoke hpi verbosity dbStack extraArgs)--withHcPkg :: Verbosity -> String -> Compiler -> ProgramDb- -> (HcPkg.HcPkgInfo -> IO a) -> IO a-withHcPkg verbosity name comp progdb f =- case compilerFlavor comp of- GHC -> f (GHC.hcPkgInfo progdb)- GHCJS -> f (GHCJS.hcPkgInfo progdb)- _ -> die' verbosity ("Distribution.Simple.Register." ++ name ++ ":\- \not implemented for this compiler")--registerPackage :: Verbosity- -> Compiler- -> ProgramDb- -> PackageDBStack- -> InstalledPackageInfo- -> HcPkg.RegisterOptions- -> IO ()-registerPackage verbosity comp progdb packageDbs installedPkgInfo registerOptions =- case compilerFlavor comp of- GHC -> GHC.registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions- GHCJS -> GHCJS.registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions- HaskellSuite {} ->- HaskellSuite.registerPackage verbosity progdb packageDbs installedPkgInfo- _ | HcPkg.registerMultiInstance registerOptions- -> die' verbosity "Registering multiple package instances is not yet supported for this compiler"- UHC -> UHC.registerPackage verbosity comp progdb packageDbs installedPkgInfo- _ -> die' verbosity "Registering is not implemented for this compiler"--writeHcPkgRegisterScript :: Verbosity- -> [InstalledPackageInfo]- -> PackageDBStack- -> HcPkg.HcPkgInfo- -> IO ()-writeHcPkgRegisterScript verbosity ipis packageDbs hpi = do- let genScript installedPkgInfo =- let invocation = HcPkg.registerInvocation hpi Verbosity.normal- packageDbs installedPkgInfo- HcPkg.defaultRegisterOptions- in invocationAsSystemScript buildOS invocation- scripts = map genScript ipis- -- TODO: Do something more robust here- regScript = unlines scripts-- info verbosity ("Creating package registration script: " ++ regScriptFileName)- writeUTF8File regScriptFileName regScript- setFileExecutable regScriptFileName--regScriptFileName :: FilePath-regScriptFileName = case buildOS of- Windows -> "register.bat"- _ -> "register.sh"----- -------------------------------------------------------------------------------- Making the InstalledPackageInfo---- | Construct 'InstalledPackageInfo' for a library in a package, given a set--- of installation directories.----generalInstalledPackageInfo- :: ([FilePath] -> [FilePath]) -- ^ Translate relative include dir paths to- -- absolute paths.- -> PackageDescription- -> AbiHash- -> Library- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> InstallDirs FilePath- -> InstalledPackageInfo-generalInstalledPackageInfo adjustRelIncDirs pkg abi_hash lib lbi clbi installDirs =- IPI.InstalledPackageInfo {- IPI.sourcePackageId = packageId pkg,- IPI.installedUnitId = componentUnitId clbi,- IPI.installedComponentId_ = componentComponentId clbi,- IPI.instantiatedWith = componentInstantiatedWith clbi,- IPI.sourceLibName = libName lib,- IPI.compatPackageKey = componentCompatPackageKey clbi,- -- If GHC >= 8.4 we register with SDPX, otherwise with legacy license- IPI.license =- if ghc84- then Left $ either id licenseToSPDX $ licenseRaw pkg- else Right $ either licenseFromSPDX id $ licenseRaw pkg,- IPI.copyright = copyright pkg,- IPI.maintainer = maintainer pkg,- IPI.author = author pkg,- IPI.stability = stability pkg,- IPI.homepage = homepage pkg,- IPI.pkgUrl = pkgUrl pkg,- IPI.synopsis = synopsis pkg,- IPI.description = description pkg,- IPI.category = category pkg,- IPI.abiHash = abi_hash,- IPI.indefinite = componentIsIndefinite clbi,- IPI.exposed = libExposed lib,- IPI.exposedModules = componentExposedModules clbi- -- add virtual modules into the list of exposed modules for the- -- package database as well.- ++ map (\name -> IPI.ExposedModule name Nothing) (virtualModules bi),- IPI.hiddenModules = otherModules bi,- IPI.trusted = IPI.trusted IPI.emptyInstalledPackageInfo,- IPI.importDirs = [ libdir installDirs | hasModules ],- IPI.libraryDirs = libdirs,- IPI.libraryDynDirs = dynlibdirs,- IPI.dataDir = datadir installDirs,- IPI.hsLibraries = (if hasLibrary- then [getHSLibraryName (componentUnitId clbi)]- else []) ++ extraBundledLibs bi,- IPI.extraLibraries = extraLibs bi,- IPI.extraGHCiLibraries = extraGHCiLibs bi,- IPI.includeDirs = absinc ++ adjustRelIncDirs relinc,- IPI.includes = includes bi,- IPI.depends = depends,- IPI.abiDepends = [], -- due to #5465- IPI.ccOptions = [], -- Note. NOT ccOptions bi!- -- We don't want cc-options to be propagated- -- to C compilations in other packages.- IPI.cxxOptions = [], -- Also. NOT cxxOptions bi!- IPI.ldOptions = ldOptions bi,- IPI.frameworks = frameworks bi,- IPI.frameworkDirs = extraFrameworkDirs bi,- IPI.haddockInterfaces = [haddockdir installDirs </> haddockName pkg],- IPI.haddockHTMLs = [htmldir installDirs],- IPI.pkgRoot = Nothing,- IPI.libVisibility = libVisibility lib- }- where- ghc84 = case compilerId $ compiler lbi of- CompilerId GHC v -> v >= mkVersion [8, 4]- _ -> False-- bi = libBuildInfo lib- --TODO: unclear what the root cause of the- -- duplication is, but we nub it here for now:- depends = ordNub $ map fst (componentPackageDeps clbi)- (absinc, relinc) = partition isAbsolute (includeDirs bi)- hasModules = not $ null (allLibModules lib clbi)- comp = compiler lbi- hasLibrary = (hasModules || not (null (cSources bi))- || not (null (asmSources bi))- || not (null (cmmSources bi))- || not (null (cxxSources bi))- || (not (null (jsSources bi)) &&- compilerFlavor comp == GHCJS))- && not (componentIsIndefinite clbi)- (libdirs, dynlibdirs)- | not hasLibrary- = (extraLibDirs bi, [])- -- the dynamic-library-dirs defaults to the library-dirs if not specified,- -- so this works whether the dynamic-library-dirs field is supported or not-- | libraryDynDirSupported comp- = (libdir installDirs : extraLibDirs bi,- dynlibdir installDirs : extraLibDirs bi)-- | otherwise- = (libdir installDirs : dynlibdir installDirs : extraLibDirs bi, [])- -- the compiler doesn't understand the dynamic-library-dirs field so we- -- add the dyn directory to the "normal" list in the library-dirs field---- | Construct 'InstalledPackageInfo' for a library that is in place in the--- build tree.------ This function knows about the layout of in place packages.----inplaceInstalledPackageInfo :: FilePath -- ^ top of the build tree- -> FilePath -- ^ location of the dist tree- -> PackageDescription- -> AbiHash- -> Library- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> InstalledPackageInfo-inplaceInstalledPackageInfo inplaceDir distPref pkg abi_hash lib lbi clbi =- generalInstalledPackageInfo adjustRelativeIncludeDirs- pkg abi_hash lib lbi clbi installDirs- where- adjustRelativeIncludeDirs = concatMap $ \d ->- [ inplaceDir </> d -- local include-dir- , inplaceDir </> libTargetDir </> d -- autogen include-dir- ]- libTargetDir = componentBuildDir lbi clbi- installDirs =- (absoluteComponentInstallDirs pkg lbi (componentUnitId clbi) NoCopyDest) {- libdir = inplaceDir </> libTargetDir,- dynlibdir = inplaceDir </> libTargetDir,- datadir = inplaceDir </> dataDir pkg,- docdir = inplaceDocdir,- htmldir = inplaceHtmldir,- haddockdir = inplaceHtmldir- }- inplaceDocdir = inplaceDir </> distPref </> "doc"- inplaceHtmldir = inplaceDocdir </> "html" </> prettyShow (packageName pkg)----- | Construct 'InstalledPackageInfo' for the final install location of a--- library package.------ This function knows about the layout of installed packages.----absoluteInstalledPackageInfo :: PackageDescription- -> AbiHash- -> Library- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> InstalledPackageInfo-absoluteInstalledPackageInfo pkg abi_hash lib lbi clbi =- generalInstalledPackageInfo adjustReativeIncludeDirs- 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.- adjustReativeIncludeDirs _- | null (installIncludes bi) = []- | otherwise = [includedir installDirs]- bi = libBuildInfo lib- installDirs = absoluteComponentInstallDirs pkg lbi (componentUnitId clbi) NoCopyDest---relocatableInstalledPackageInfo :: PackageDescription- -> AbiHash- -> Library- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> FilePath- -> InstalledPackageInfo-relocatableInstalledPackageInfo pkg abi_hash lib lbi clbi pkgroot =- generalInstalledPackageInfo adjustReativeIncludeDirs- 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.- adjustReativeIncludeDirs _- | null (installIncludes bi) = []- | otherwise = [includedir installDirs]- bi = libBuildInfo lib-- installDirs = fmap (("${pkgroot}" </>) . shortRelativePath pkgroot)- $ absoluteComponentInstallDirs pkg lbi (componentUnitId clbi) NoCopyDest---- -------------------------------------------------------------------------------- Unregistration--unregister :: PackageDescription -> LocalBuildInfo -> RegisterFlags -> IO ()-unregister pkg lbi regFlags = do- let pkgid = packageId pkg- genScript = fromFlag (regGenScript regFlags)- verbosity = fromFlag (regVerbosity regFlags)- packageDb = fromFlagOrDefault (registrationPackageDB (withPackageDB lbi))- (regPackageDB regFlags)- unreg hpi =- let invocation = HcPkg.unregisterInvocation- hpi Verbosity.normal packageDb pkgid- in if genScript- then writeFileAtomic unregScriptFileName- (BS.Char8.pack $ invocationAsSystemScript buildOS invocation)- else runProgramInvocation verbosity invocation- setupMessage verbosity "Unregistering" pkgid- withHcPkg verbosity "unregistering is only implemented for GHC and GHCJS"- (compiler lbi) (withPrograms lbi) unreg--unregScriptFileName :: FilePath-unregScriptFileName = case buildOS of- Windows -> "unregister.bat"- _ -> "unregister.sh"--internalPackageDBPath :: LocalBuildInfo -> FilePath -> FilePath-internalPackageDBPath lbi distPref =- case compilerFlavor (compiler lbi) of- UHC -> UHC.inplacePackageDbPath lbi- _ -> distPref </> "package.conf.inplace"
− Distribution/Simple/Setup.hs
@@ -1,2411 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Setup--- Copyright : Isaac Jones 2003-2004--- Duncan Coutts 2007--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is a big module, but not very complicated. The code is very regular--- and repetitive. It defines the command line interface for all the Cabal--- commands. For each command (like @configure@, @build@ etc) it defines a type--- that holds all the flags, the default set of flags and a 'CommandUI' that--- maps command line flags to and from the corresponding flags type.------ All the flags types are instances of 'Monoid', see--- <http://www.haskell.org/pipermail/cabal-devel/2007-December/001509.html>--- for an explanation.------ The types defined here get used in the front end and especially in--- @cabal-install@ which has to do quite a bit of manipulating sets of command--- line flags.------ This is actually relatively nice, it works quite well. The main change it--- needs is to unify it with the code for managing sets of fields that can be--- read and written from files. This would allow us to save configure flags in--- config files.--module Distribution.Simple.Setup (-- GlobalFlags(..), emptyGlobalFlags, defaultGlobalFlags, globalCommand,- ConfigFlags(..), emptyConfigFlags, defaultConfigFlags, configureCommand,- configPrograms,- configAbsolutePaths, readPackageDbList, showPackageDbList,- CopyFlags(..), emptyCopyFlags, defaultCopyFlags, copyCommand,- InstallFlags(..), emptyInstallFlags, defaultInstallFlags, installCommand,- DoctestFlags(..), emptyDoctestFlags, defaultDoctestFlags, doctestCommand,- HaddockTarget(..),- HaddockFlags(..), emptyHaddockFlags, defaultHaddockFlags, haddockCommand,- HscolourFlags(..), emptyHscolourFlags, defaultHscolourFlags, hscolourCommand,- BuildFlags(..), emptyBuildFlags, defaultBuildFlags, buildCommand,- ShowBuildInfoFlags(..), defaultShowBuildFlags, showBuildInfoCommand,- ReplFlags(..), defaultReplFlags, replCommand,- CleanFlags(..), emptyCleanFlags, defaultCleanFlags, cleanCommand,- RegisterFlags(..), emptyRegisterFlags, defaultRegisterFlags, registerCommand,- unregisterCommand,- SDistFlags(..), emptySDistFlags, defaultSDistFlags, sdistCommand,- TestFlags(..), emptyTestFlags, defaultTestFlags, testCommand,- TestShowDetails(..),- BenchmarkFlags(..), emptyBenchmarkFlags,- defaultBenchmarkFlags, benchmarkCommand,- CopyDest(..),- configureArgs, configureOptions, configureCCompiler, configureLinker,- buildOptions, haddockOptions, installDirsOptions,- testOptions', benchmarkOptions',- programDbOptions, programDbPaths',- programFlagsDescription,- replOptions,- splitArgs,-- defaultDistPref, optionDistPref,-- Flag(..),- toFlag,- fromFlag,- fromFlagOrDefault,- flagToMaybe,- flagToList,- maybeToFlag,- BooleanFlag(..),- boolOpt, boolOpt', trueArg, falseArg,- optionVerbosity, optionNumJobs) where--import Prelude ()-import Distribution.Compat.Prelude hiding (get)--import Distribution.Compiler-import Distribution.ReadE-import Distribution.Parsec-import Distribution.Pretty-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp-import Distribution.ModuleName-import Distribution.PackageDescription-import Distribution.Simple.Command hiding (boolOpt, boolOpt')-import qualified Distribution.Simple.Command as Command-import Distribution.Simple.Compiler-import Distribution.Simple.Flag-import Distribution.Simple.Utils-import Distribution.Simple.Program-import Distribution.Simple.InstallDirs-import Distribution.Verbosity-import Distribution.Utils.NubList-import Distribution.Types.ComponentId-import Distribution.Types.GivenComponent-import Distribution.Types.Module-import Distribution.Types.PackageVersionConstraint--import Distribution.Compat.Stack-import Distribution.Compat.Semigroup (Last' (..), Option' (..))---- FIXME Not sure where this should live-defaultDistPref :: FilePath-defaultDistPref = "dist"---- --------------------------------------------------------------- * Global flags--- ---------------------------------------------------------------- In fact since individual flags types are monoids and these are just sets of--- flags then they are also monoids pointwise. This turns out to be really--- useful. The mempty is the set of empty flags and mappend allows us to--- override specific flags. For example we can start with default flags and--- override with the ones we get from a file or the command line, or both.---- | Flags that apply at the top level, not to any sub-command.-data GlobalFlags = GlobalFlags {- globalVersion :: Flag Bool,- globalNumericVersion :: Flag Bool- } deriving (Generic, Typeable)--defaultGlobalFlags :: GlobalFlags-defaultGlobalFlags = GlobalFlags {- globalVersion = Flag False,- globalNumericVersion = Flag False- }--globalCommand :: [Command action] -> CommandUI GlobalFlags-globalCommand commands = CommandUI- { commandName = ""- , commandSynopsis = ""- , commandUsage = \pname ->- "This Setup program uses the Haskell Cabal Infrastructure.\n"- ++ "See http://www.haskell.org/cabal/ for more information.\n"- ++ "\n"- ++ "Usage: " ++ pname ++ " [GLOBAL FLAGS] [COMMAND [FLAGS]]\n"- , commandDescription = Just $ \pname ->- let- commands' = commands ++ [commandAddAction helpCommandUI undefined]- cmdDescs = getNormalCommandDescriptions commands'- maxlen = maximum $ [length name | (name, _) <- cmdDescs]- align str = str ++ replicate (maxlen - length str) ' '- in- "Commands:\n"- ++ unlines [ " " ++ align name ++ " " ++ descr- | (name, descr) <- cmdDescs ]- ++ "\n"- ++ "For more information about a command use\n"- ++ " " ++ pname ++ " COMMAND --help\n\n"- ++ "Typical steps for installing Cabal packages:\n"- ++ concat [ " " ++ pname ++ " " ++ x ++ "\n"- | x <- ["configure", "build", "install"]]- , commandNotes = Nothing- , commandDefaultFlags = defaultGlobalFlags- , commandOptions = \_ ->- [option ['V'] ["version"]- "Print version information"- globalVersion (\v flags -> flags { globalVersion = v })- trueArg- ,option [] ["numeric-version"]- "Print just the version number"- globalNumericVersion (\v flags -> flags { globalNumericVersion = v })- trueArg- ]- }--emptyGlobalFlags :: GlobalFlags-emptyGlobalFlags = mempty--instance Monoid GlobalFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup GlobalFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Config flags--- ---------------------------------------------------------------- | Flags to @configure@ command.------ IMPORTANT: every time a new flag is added, 'D.C.Setup.filterConfigureFlags'--- should be updated.--- IMPORTANT: every time a new flag is added, it should be added to the Eq instance-data ConfigFlags = ConfigFlags {- -- This is the same hack as in 'buildArgs' and 'copyArgs'.- -- TODO: Stop using this eventually when 'UserHooks' gets changed- configArgs :: [String],-- --FIXME: the configPrograms is only here to pass info through to configure- -- because the type of configure is constrained by the UserHooks.- -- when we change UserHooks next we should pass the initial- -- ProgramDb directly and not via ConfigFlags- configPrograms_ :: Option' (Last' ProgramDb), -- ^All programs that- -- @cabal@ may run-- configProgramPaths :: [(String, FilePath)], -- ^user specified programs paths- configProgramArgs :: [(String, [String])], -- ^user specified programs args- configProgramPathExtra :: NubList FilePath, -- ^Extend the $PATH- configHcFlavor :: Flag CompilerFlavor, -- ^The \"flavor\" of the- -- compiler, e.g. GHC.- configHcPath :: Flag FilePath, -- ^given compiler location- configHcPkg :: Flag FilePath, -- ^given hc-pkg location- configVanillaLib :: Flag Bool, -- ^Enable vanilla library- configProfLib :: Flag Bool, -- ^Enable profiling in the library- configSharedLib :: Flag Bool, -- ^Build shared library- configStaticLib :: Flag Bool, -- ^Build static library- configDynExe :: Flag Bool, -- ^Enable dynamic linking of the- -- executables.- configFullyStaticExe :: Flag Bool, -- ^Enable fully static linking of the- -- 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.- configProgSuffix :: Flag PathTemplate, -- ^Installed executable suffix.- configInstallDirs :: InstallDirs (Flag PathTemplate), -- ^Installation- -- 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- configCID :: Flag ComponentId, -- ^ explicit CID to be used- configDeterministic :: Flag Bool, -- ^ be as deterministic as possible- -- (e.g., invariant over GHC, database,- -- etc). Used by the test suite-- configDistPref :: Flag FilePath, -- ^"dist" prefix- configCabalFilePath :: Flag FilePath, -- ^ Cabal file to use- configVerbosity :: Flag Verbosity, -- ^verbosity level- configUserInstall :: Flag Bool, -- ^The --user\/--global flag- configPackageDBs :: [Maybe PackageDB], -- ^Which package DBs to use- configGHCiLib :: Flag Bool, -- ^Enable compiling library for GHCi- configSplitSections :: Flag Bool, -- ^Enable -split-sections with GHC- configSplitObjs :: Flag Bool, -- ^Enable -split-objs with GHC- configStripExes :: Flag Bool, -- ^Enable executable stripping- configStripLibs :: Flag Bool, -- ^Enable library stripping- configConstraints :: [PackageVersionConstraint], -- ^Additional constraints for- -- dependencies.- configDependencies :: [GivenComponent],- -- ^The packages depended on.- configInstantiateWith :: [(ModuleName, Module)],- -- ^ The requested Backpack instantiation. If empty, either this- -- package does not use Backpack, or we just want to typecheck- -- the indefinite package.- configConfigurationsFlags :: FlagAssignment,- configTests :: Flag Bool, -- ^Enable test suite compilation- configBenchmarks :: Flag Bool, -- ^Enable benchmark compilation- configCoverage :: Flag Bool, -- ^Enable program coverage- configLibCoverage :: Flag Bool, -- ^Enable program coverage (deprecated)- configExactConfiguration :: Flag Bool,- -- ^All direct dependencies and flags are provided on the command line by- -- the user via the '--dependency' and '--flags' options.- 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.- configUseResponseFiles :: Flag Bool,- -- ^ Whether to use response files at all. They're used for such tools- -- as haddock, or ld.- configAllowDependingOnPrivateLibs :: Flag Bool- -- ^ Allow depending on private sublibraries. This is used by external- -- tools (like cabal-install) so they can add multiple-public-libraries- -- compatibility to older ghcs by checking visibility externally.- }- deriving (Generic, Read, Show, Typeable)--instance Binary ConfigFlags-instance Structured ConfigFlags---- | More convenient version of 'configPrograms'. Results in an--- 'error' if internal invariant is violated.-configPrograms :: WithCallStack (ConfigFlags -> ProgramDb)-configPrograms = fromMaybe (error "FIXME: remove configPrograms") . fmap getLast'- . getOption' . configPrograms_--instance Eq ConfigFlags where- (==) a b =- -- configPrograms skipped: not user specified, has no Eq instance- equal configProgramPaths- && equal configProgramArgs- && equal configProgramPathExtra- && equal configHcFlavor- && equal configHcPath- && equal configHcPkg- && equal configVanillaLib- && equal configProfLib- && equal configSharedLib- && equal configStaticLib- && equal configDynExe- && equal configFullyStaticExe- && equal configProfExe- && equal configProf- && equal configProfDetail- && equal configProfLibDetail- && equal configConfigureArgs- && equal configOptimization- && equal configProgPrefix- && equal configProgSuffix- && equal configInstallDirs- && equal configScratchDir- && equal configExtraLibDirs- && equal configExtraIncludeDirs- && equal configIPID- && equal configDeterministic- && equal configDistPref- && equal configVerbosity- && equal configUserInstall- && equal configPackageDBs- && equal configGHCiLib- && equal configSplitSections- && equal configSplitObjs- && equal configStripExes- && equal configStripLibs- && equal configConstraints- && equal configDependencies- && equal configConfigurationsFlags- && equal configTests- && equal configBenchmarks- && equal configCoverage- && equal configLibCoverage- && equal configExactConfiguration- && equal configFlagError- && equal configRelocatable- && equal configDebugInfo- && equal configUseResponseFiles- where- equal f = on (==) f a b--configAbsolutePaths :: ConfigFlags -> IO ConfigFlags-configAbsolutePaths f =- (\v -> f { configPackageDBs = v })- `liftM` traverse (maybe (return Nothing) (liftM Just . absolutePackageDBPath))- (configPackageDBs f)--defaultConfigFlags :: ProgramDb -> ConfigFlags-defaultConfigFlags progDb = emptyConfigFlags {- configArgs = [],- configPrograms_ = Option' (Just (Last' progDb)),- configHcFlavor = maybe NoFlag Flag defaultCompilerFlavor,- configVanillaLib = Flag True,- configProfLib = NoFlag,- configSharedLib = NoFlag,- configStaticLib = NoFlag,- configDynExe = Flag False,- configFullyStaticExe = Flag False,- configProfExe = NoFlag,- configProf = NoFlag,- configProfDetail = NoFlag,- configProfLibDetail= NoFlag,- configOptimization = Flag NormalOptimisation,- configProgPrefix = Flag (toPathTemplate ""),- configProgSuffix = Flag (toPathTemplate ""),- configDistPref = NoFlag,- configCabalFilePath = NoFlag,- configVerbosity = Flag normal,- configUserInstall = Flag False, --TODO: reverse this-#if defined(mingw32_HOST_OS)- -- See #1589.- configGHCiLib = Flag True,-#else- configGHCiLib = NoFlag,-#endif- configSplitSections = Flag False,- configSplitObjs = Flag False, -- takes longer, so turn off by default- configStripExes = NoFlag,- configStripLibs = NoFlag,- configTests = Flag False,- configBenchmarks = Flag False,- configCoverage = Flag False,- configLibCoverage = NoFlag,- configExactConfiguration = Flag False,- configFlagError = NoFlag,- configRelocatable = Flag False,- configDebugInfo = Flag NoDebugInfo,- configUseResponseFiles = NoFlag- }--configureCommand :: ProgramDb -> CommandUI ConfigFlags-configureCommand progDb = CommandUI- { commandName = "configure"- , commandSynopsis = "Prepare to build the package."- , commandDescription = Just $ \_ -> wrapText $- "Configure how the package is built by setting "- ++ "package (and other) flags.\n"- ++ "\n"- ++ "The configuration affects several other commands, "- ++ "including build, test, bench, run, repl.\n"- , commandNotes = Just $ \_pname -> programFlagsDescription progDb- , commandUsage = \pname ->- "Usage: " ++ pname ++ " configure [FLAGS]\n"- , commandDefaultFlags = defaultConfigFlags progDb- , commandOptions = \showOrParseArgs ->- configureOptions showOrParseArgs- ++ programDbPaths progDb showOrParseArgs- configProgramPaths (\v fs -> fs { configProgramPaths = v })- ++ programDbOption progDb showOrParseArgs- configProgramArgs (\v fs -> fs { configProgramArgs = v })- ++ programDbOptions progDb showOrParseArgs- configProgramArgs (\v fs -> fs { configProgramArgs = v })- }---- | Inverse to 'dispModSubstEntry'.-parsecModSubstEntry :: ParsecParser (ModuleName, Module)-parsecModSubstEntry = do- k <- parsec- _ <- P.char '='- v <- parsec- return (k, v)---- | Pretty-print a single entry of a module substitution.-dispModSubstEntry :: (ModuleName, Module) -> Disp.Doc-dispModSubstEntry (k, v) = pretty k <<>> Disp.char '=' <<>> pretty v--configureOptions :: ShowOrParseArgs -> [OptionField ConfigFlags]-configureOptions showOrParseArgs =- [optionVerbosity configVerbosity- (\v flags -> flags { configVerbosity = v })- ,optionDistPref- configDistPref (\d flags -> flags { configDistPref = d })- showOrParseArgs-- ,option [] ["compiler"] "compiler"- configHcFlavor (\v flags -> flags { configHcFlavor = v })- (choiceOpt [ (Flag GHC, ("g", ["ghc"]), "compile with GHC")- , (Flag GHCJS, ([] , ["ghcjs"]), "compile with GHCJS")- , (Flag UHC, ([] , ["uhc"]), "compile with UHC")- -- "haskell-suite" compiler id string will be replaced- -- by a more specific one during the configure stage- , (Flag (HaskellSuite "haskell-suite"), ([] , ["haskell-suite"]),- "compile with a haskell-suite compiler")])-- ,option "" ["cabal-file"]- "use this Cabal file"- configCabalFilePath (\v flags -> flags { configCabalFilePath = v })- (reqArgFlag "PATH")-- ,option "w" ["with-compiler"]- "give the path to a particular compiler"- configHcPath (\v flags -> flags { configHcPath = v })- (reqArgFlag "PATH")-- ,option "" ["with-hc-pkg"]- "give the path to the package tool"- configHcPkg (\v flags -> flags { configHcPkg = v })- (reqArgFlag "PATH")- ]- ++ map liftInstallDirs installDirsOptions- ++ [option "" ["program-prefix"]- "prefix to be applied to installed executables"- configProgPrefix- (\v flags -> flags { configProgPrefix = v })- (reqPathTemplateArgFlag "PREFIX")-- ,option "" ["program-suffix"]- "suffix to be applied to installed executables"- configProgSuffix (\v flags -> flags { configProgSuffix = v } )- (reqPathTemplateArgFlag "SUFFIX")-- ,option "" ["library-vanilla"]- "Vanilla libraries"- configVanillaLib (\v flags -> flags { configVanillaLib = v })- (boolOpt [] [])-- ,option "p" ["library-profiling"]- "Library profiling"- configProfLib (\v flags -> flags { configProfLib = v })- (boolOpt "p" [])-- ,option "" ["shared"]- "Shared library"- configSharedLib (\v flags -> flags { configSharedLib = v })- (boolOpt [] [])-- ,option "" ["static"]- "Static library"- configStaticLib (\v flags -> flags { configStaticLib = v })- (boolOpt [] [])-- ,option "" ["executable-dynamic"]- "Executable dynamic linking"- configDynExe (\v flags -> flags { configDynExe = v })- (boolOpt [] [])-- ,option "" ["executable-static"]- "Executable fully static linking"- configFullyStaticExe (\v flags -> flags { configFullyStaticExe = v })- (boolOpt [] [])-- ,option "" ["profiling"]- "Executable and library profiling"- configProf (\v flags -> flags { configProf = v })- (boolOpt [] [])-- ,option "" ["executable-profiling"]- "Executable profiling (DEPRECATED)"- 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)- (\f -> case f of- Flag NoOptimisation -> []- Flag NormalOptimisation -> [Nothing]- Flag MaximumOptimisation -> [Just "2"]- _ -> [])- "O" ["enable-optimization","enable-optimisation"]- "Build with optimization (n is 0--2, default is 1)",- noArg (Flag NoOptimisation) []- ["disable-optimization","disable-optimisation"]- "Build without optimization"- ]-- ,multiOption "debug-info"- configDebugInfo (\v flags -> flags { configDebugInfo = v })- [optArg' "n" (Flag . flagToDebugInfoLevel)- (\f -> case f of- Flag NoDebugInfo -> []- Flag MinimalDebugInfo -> [Just "1"]- Flag NormalDebugInfo -> [Nothing]- Flag MaximalDebugInfo -> [Just "3"]- _ -> [])- "" ["enable-debug-info"]- "Emit debug info (n is 0--3, default is 0)",- noArg (Flag NoDebugInfo) []- ["disable-debug-info"]- "Don't emit debug info"- ]-- ,option "" ["library-for-ghci"]- "compile library for use with GHCi"- configGHCiLib (\v flags -> flags { configGHCiLib = v })- (boolOpt [] [])-- ,option "" ["split-sections"]- "compile library code such that unneeded definitions can be dropped from the final executable (GHC 7.8+)"- configSplitSections (\v flags -> flags { configSplitSections = v })- (boolOpt [] [])-- ,option "" ["split-objs"]- "split library into smaller objects to reduce binary sizes (GHC 6.6+)"- configSplitObjs (\v flags -> flags { configSplitObjs = v })- (boolOpt [] [])-- ,option "" ["executable-stripping"]- "strip executables upon installation to reduce binary sizes"- configStripExes (\v flags -> flags { configStripExes = v })- (boolOpt [] [])-- ,option "" ["library-stripping"]- "strip libraries upon installation to reduce binary sizes"- configStripLibs (\v flags -> flags { configStripLibs = v })- (boolOpt [] [])-- ,option "" ["configure-option"]- "Extra option for configure"- configConfigureArgs (\v flags -> flags { configConfigureArgs = v })- (reqArg' "OPT" (\x -> [x]) id)-- ,option "" ["user-install"]- "doing a per-user installation"- configUserInstall (\v flags -> flags { configUserInstall = v })- (boolOpt' ([],["user"]) ([], ["global"]))-- ,option "" ["package-db"]- ( "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)-- ,option "f" ["flags"]- "Force values for the given flags in Cabal conditionals in the .cabal file. E.g., --flags=\"debug -usebytestrings\" forces the flag \"debug\" to true and \"usebytestrings\" to false."- configConfigurationsFlags (\v flags -> flags { configConfigurationsFlags = v })- (reqArg "FLAGS"- (parsecToReadE (\err -> "Invalid flag assignment: " ++ err) legacyParsecFlagAssignment)- legacyShowFlagAssignment')-- ,option "" ["extra-include-dirs"]- "A list of directories to search for header files"- configExtraIncludeDirs (\v flags -> flags {configExtraIncludeDirs = v})- (reqArg' "PATH" (\x -> [x]) id)-- ,option "" ["deterministic"]- "Try to be as deterministic as possible (used by the test suite)"- configDeterministic (\v flags -> flags {configDeterministic = v})- (boolOpt [] [])-- ,option "" ["ipid"]- "Installed package ID to compile this package as"- configIPID (\v flags -> flags {configIPID = v})- (reqArgFlag "IPID")-- ,option "" ["cid"]- "Installed component ID to compile this component as"- (fmap prettyShow . configCID) (\v flags -> flags {configCID = fmap mkComponentId v})- (reqArgFlag "CID")-- ,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})- (reqArg' "PATH" (\x -> toNubList [x]) fromNubList)-- ,option "" ["constraint"]- "A list of additional constraints on the dependencies."- configConstraints (\v flags -> flags { configConstraints = v})- (reqArg "DEPENDENCY"- (parsecToReadE (const "dependency expected") ((\x -> [x]) `fmap` parsec))- (map prettyShow))-- ,option "" ["dependency"]- "A list of exact dependencies. E.g., --dependency=\"void=void-0.5.8-177d5cdf20962d0581fe2e4932a6c309\""- configDependencies (\v flags -> flags { configDependencies = v})- (reqArg "NAME[:COMPONENT_NAME]=CID"- (parsecToReadE (const "dependency expected") ((\x -> [x]) `fmap` parsecGivenComponent))- (map (\(GivenComponent pn cn cid) ->- prettyShow pn- ++ case cn of LMainLibName -> ""- LSubLibName n -> ":" ++ prettyShow n- ++ "=" ++ prettyShow cid)))-- ,option "" ["instantiate-with"]- "A mapping of signature names to concrete module instantiations."- configInstantiateWith (\v flags -> flags { configInstantiateWith = v })- (reqArg "NAME=MOD"- (parsecToReadE ("Cannot parse module substitution: " ++) (fmap (:[]) parsecModSubstEntry))- (map (Disp.renderStyle defaultStyle . dispModSubstEntry)))-- ,option "" ["tests"]- "dependency checking and compilation for test suites listed in the package description file."- configTests (\v flags -> flags { configTests = v })- (boolOpt [] [])-- ,option "" ["coverage"]- "build package with Haskell Program Coverage. (GHC only)"- configCoverage (\v flags -> flags { configCoverage = v })- (boolOpt [] [])-- ,option "" ["library-coverage"]- "build package with Haskell Program Coverage. (GHC only) (DEPRECATED)"- configLibCoverage (\v flags -> flags { configLibCoverage = v })- (boolOpt [] [])-- ,option "" ["exact-configuration"]- "All direct dependencies and flags are provided on the command line."- configExactConfiguration- (\v flags -> flags { configExactConfiguration = v })- trueArg-- ,option "" ["benchmarks"]- "dependency checking and compilation for benchmarks listed in the package description file."- configBenchmarks (\v flags -> flags { configBenchmarks = v })- (boolOpt [] [])-- ,option "" ["relocatable"]- "building a package that is relocatable. (GHC only)"- configRelocatable (\v flags -> flags { configRelocatable = v})- (boolOpt [] [])-- ,option "" ["response-files"]- "enable workaround for old versions of programs like \"ar\" that do not support @file arguments"- configUseResponseFiles- (\v flags -> flags { configUseResponseFiles = v })- (boolOpt' ([], ["disable-response-files"]) ([], []))-- ,option "" ["allow-depending-on-private-libs"]- ( "Allow depending on private libraries. "- ++ "If set, the library visibility check MUST be done externally." )- configAllowDependingOnPrivateLibs- (\v flags -> flags { configAllowDependingOnPrivateLibs = v })- trueArg- ]- where- liftInstallDirs =- liftOption configInstallDirs (\v flags -> flags { configInstallDirs = v })-- reqPathTemplateArgFlag title _sf _lf d get set =- reqArgFlag title _sf _lf d- (fmap fromPathTemplate . get) (set . fmap toPathTemplate)--readPackageDbList :: String -> [Maybe PackageDB]-readPackageDbList "clear" = [Nothing]-readPackageDbList "global" = [Just GlobalPackageDB]-readPackageDbList "user" = [Just UserPackageDB]-readPackageDbList other = [Just (SpecificPackageDB other)]--showPackageDbList :: [Maybe PackageDB] -> [String]-showPackageDbList = map showPackageDb- where- showPackageDb Nothing = "clear"- showPackageDb (Just GlobalPackageDB) = "global"- showPackageDb (Just UserPackageDB) = "user"- showPackageDb (Just (SpecificPackageDB db)) = db--showProfDetailLevelFlag :: Flag ProfDetailLevel -> [String]-showProfDetailLevelFlag NoFlag = []-showProfDetailLevelFlag (Flag dl) = [showProfDetailLevel dl]--parsecGivenComponent :: ParsecParser GivenComponent-parsecGivenComponent = do- pn <- parsec- ln <- P.option LMainLibName $ do- _ <- P.char ':'- ucn <- parsec- return $ if unUnqualComponentName ucn == unPackageName pn- then LMainLibName- else LSubLibName ucn- _ <- P.char '='- cid <- parsec- return $ GivenComponent pn ln cid--installDirsOptions :: [OptionField (InstallDirs (Flag PathTemplate))]-installDirsOptions =- [ option "" ["prefix"]- "bake this prefix in preparation of installation"- prefix (\v flags -> flags { prefix = v })- installDirArg-- , option "" ["bindir"]- "installation directory for executables"- bindir (\v flags -> flags { bindir = v })- installDirArg-- , option "" ["libdir"]- "installation directory for libraries"- libdir (\v flags -> flags { libdir = v })- installDirArg-- , option "" ["libsubdir"]- "subdirectory of libdir in which libs are installed"- libsubdir (\v flags -> flags { libsubdir = v })- installDirArg-- , option "" ["dynlibdir"]- "installation directory for dynamic libraries"- dynlibdir (\v flags -> flags { dynlibdir = v })- installDirArg-- , option "" ["libexecdir"]- "installation directory for program executables"- libexecdir (\v flags -> flags { libexecdir = v })- installDirArg-- , option "" ["libexecsubdir"]- "subdirectory of libexecdir in which private executables are installed"- libexecsubdir (\v flags -> flags { libexecsubdir = v })- installDirArg-- , option "" ["datadir"]- "installation directory for read-only data"- datadir (\v flags -> flags { datadir = v })- installDirArg-- , option "" ["datasubdir"]- "subdirectory of datadir in which data files are installed"- datasubdir (\v flags -> flags { datasubdir = v })- installDirArg-- , option "" ["docdir"]- "installation directory for documentation"- docdir (\v flags -> flags { docdir = v })- installDirArg-- , option "" ["htmldir"]- "installation directory for HTML documentation"- htmldir (\v flags -> flags { htmldir = v })- installDirArg-- , option "" ["haddockdir"]- "installation directory for haddock interfaces"- haddockdir (\v flags -> flags { haddockdir = v })- installDirArg-- , option "" ["sysconfdir"]- "installation directory for configuration files"- sysconfdir (\v flags -> flags { sysconfdir = v })- installDirArg- ]- where- installDirArg _sf _lf d get set =- reqArgFlag "DIR" _sf _lf d- (fmap fromPathTemplate . get) (set . fmap toPathTemplate)--emptyConfigFlags :: ConfigFlags-emptyConfigFlags = mempty--instance Monoid ConfigFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup ConfigFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Copy flags--- ---------------------------------------------------------------- | Flags to @copy@: (destdir, copy-prefix (backwards compat), verbosity)-data CopyFlags = CopyFlags {- copyDest :: Flag CopyDest,- copyDistPref :: Flag FilePath,- copyVerbosity :: Flag Verbosity,- -- This is the same hack as in 'buildArgs'. But I (ezyang) don't- -- think it's a hack, it's the right way to make hooks more robust- -- TODO: Stop using this eventually when 'UserHooks' gets changed- copyArgs :: [String],- copyCabalFilePath :: Flag FilePath- }- deriving (Show, Generic)--defaultCopyFlags :: CopyFlags-defaultCopyFlags = CopyFlags {- copyDest = Flag NoCopyDest,- copyDistPref = NoFlag,- copyVerbosity = Flag normal,- copyArgs = [],- copyCabalFilePath = mempty- }--copyCommand :: CommandUI CopyFlags-copyCommand = CommandUI- { commandName = "copy"- , commandSynopsis = "Copy the files of all/specific components to install locations."- , commandDescription = Just $ \_ -> wrapText $- "Components encompass executables and libraries. "- ++ "Does not call register, and allows a prefix at install time. "- ++ "Without the --destdir flag, configure determines location.\n"- , commandNotes = Just $ \pname ->- "Examples:\n"- ++ " " ++ pname ++ " copy "- ++ " All the components in the package\n"- ++ " " ++ pname ++ " copy foo "- ++ " A component (i.e. lib, exe, test suite)"- , commandUsage = usageAlternatives "copy" $- [ "[FLAGS]"- , "COMPONENTS [FLAGS]"- ]- , commandDefaultFlags = defaultCopyFlags- , commandOptions = \showOrParseArgs -> case showOrParseArgs of- ShowArgs -> filter ((`notElem` ["target-package-db"])- . optionName) $ copyOptions ShowArgs- ParseArgs -> copyOptions ParseArgs-}--copyOptions :: ShowOrParseArgs -> [OptionField CopyFlags]-copyOptions showOrParseArgs =- [optionVerbosity copyVerbosity (\v flags -> flags { copyVerbosity = v })-- ,optionDistPref- copyDistPref (\d flags -> flags { copyDistPref = d })- showOrParseArgs-- ,option "" ["destdir"]- "directory to copy files to, prepended to installation directories"- copyDest (\v flags -> case copyDest flags of- Flag (CopyToDb _) -> error "Use either 'destdir' or 'target-package-db'."- _ -> flags { copyDest = v })- (reqArg "DIR" (succeedReadE (Flag . CopyTo))- (\f -> case f of Flag (CopyTo p) -> [p]; _ -> []))-- ,option "" ["target-package-db"]- "package database to copy files into. Required when using ${pkgroot} prefix."- copyDest (\v flags -> case copyDest flags of- NoFlag -> flags { copyDest = v }- Flag NoCopyDest -> flags { copyDest = v }- _ -> error "Use either 'destdir' or 'target-package-db'.")- (reqArg "DATABASE" (succeedReadE (Flag . CopyToDb))- (\f -> case f of Flag (CopyToDb p) -> [p]; _ -> []))- ]--emptyCopyFlags :: CopyFlags-emptyCopyFlags = mempty--instance Monoid CopyFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup CopyFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Install flags--- ---------------------------------------------------------------- | Flags to @install@: (package db, verbosity)-data InstallFlags = InstallFlags {- installPackageDB :: Flag PackageDB,- installDest :: Flag CopyDest,- installDistPref :: Flag FilePath,- installUseWrapper :: Flag Bool,- installInPlace :: Flag Bool,- installVerbosity :: Flag Verbosity,- -- this is only here, because we can not- -- change the hooks API.- installCabalFilePath :: Flag FilePath- }- deriving (Show, Generic)--defaultInstallFlags :: InstallFlags-defaultInstallFlags = InstallFlags {- installPackageDB = NoFlag,- installDest = Flag NoCopyDest,- installDistPref = NoFlag,- installUseWrapper = Flag False,- installInPlace = Flag False,- installVerbosity = Flag normal,- installCabalFilePath = mempty- }--installCommand :: CommandUI InstallFlags-installCommand = CommandUI- { commandName = "install"- , commandSynopsis =- "Copy the files into the install locations. Run register."- , commandDescription = Just $ \_ -> wrapText $- "Unlike the copy command, install calls the register command."- ++ "If you want to install into a location that is not what was"- ++ "specified in the configure step, use the copy command.\n"- , commandNotes = Nothing- , commandUsage = \pname ->- "Usage: " ++ pname ++ " install [FLAGS]\n"- , commandDefaultFlags = defaultInstallFlags- , commandOptions = \showOrParseArgs -> case showOrParseArgs of- ShowArgs -> filter ((`notElem` ["target-package-db"])- . optionName) $ installOptions ShowArgs- ParseArgs -> installOptions ParseArgs- }--installOptions :: ShowOrParseArgs -> [OptionField InstallFlags]-installOptions showOrParseArgs =- [optionVerbosity installVerbosity (\v flags -> flags { installVerbosity = v })- ,optionDistPref- installDistPref (\d flags -> flags { installDistPref = d })- showOrParseArgs-- ,option "" ["inplace"]- "install the package in the install subdirectory of the dist prefix, so it can be used without being installed"- installInPlace (\v flags -> flags { installInPlace = v })- trueArg-- ,option "" ["shell-wrappers"]- "using shell script wrappers around executables"- installUseWrapper (\v flags -> flags { installUseWrapper = v })- (boolOpt [] [])-- ,option "" ["package-db"] ""- installPackageDB (\v flags -> flags { installPackageDB = v })- (choiceOpt [ (Flag UserPackageDB, ([],["user"]),- "upon configuration register this package in the user's local package database")- , (Flag GlobalPackageDB, ([],["global"]),- "(default) upon configuration register this package in the system-wide package database")])- ,option "" ["target-package-db"]- "package database to install into. Required when using ${pkgroot} prefix."- installDest (\v flags -> flags { installDest = v })- (reqArg "DATABASE" (succeedReadE (Flag . CopyToDb))- (\f -> case f of Flag (CopyToDb p) -> [p]; _ -> []))- ]--emptyInstallFlags :: InstallFlags-emptyInstallFlags = mempty--instance Monoid InstallFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup InstallFlags where- (<>) = gmappend---- --------------------------------------------------------------- * SDist flags--- ---------------------------------------------------------------- | Flags to @sdist@: (snapshot, verbosity)-data SDistFlags = SDistFlags {- sDistSnapshot :: Flag Bool,- sDistDirectory :: Flag FilePath,- sDistDistPref :: Flag FilePath,- sDistListSources :: Flag FilePath,- sDistVerbosity :: Flag Verbosity- }- deriving (Show, Generic, Typeable)--defaultSDistFlags :: SDistFlags-defaultSDistFlags = SDistFlags {- sDistSnapshot = Flag False,- sDistDirectory = mempty,- sDistDistPref = NoFlag,- sDistListSources = mempty,- sDistVerbosity = Flag normal- }--sdistCommand :: CommandUI SDistFlags-sdistCommand = CommandUI- { commandName = "sdist"- , commandSynopsis =- "Generate a source distribution file (.tar.gz)."- , commandDescription = Nothing- , commandNotes = Nothing- , commandUsage = \pname ->- "Usage: " ++ pname ++ " sdist [FLAGS]\n"- , commandDefaultFlags = defaultSDistFlags- , commandOptions = \showOrParseArgs ->- [optionVerbosity sDistVerbosity (\v flags -> flags { sDistVerbosity = v })- ,optionDistPref- sDistDistPref (\d flags -> flags { sDistDistPref = d })- showOrParseArgs-- ,option "" ["list-sources"]- "Just write a list of the package's sources to a file"- sDistListSources (\v flags -> flags { sDistListSources = v })- (reqArgFlag "FILE")-- ,option "" ["snapshot"]- "Produce a snapshot source distribution"- sDistSnapshot (\v flags -> flags { sDistSnapshot = v })- trueArg-- ,option "" ["output-directory"]- ("Generate a source distribution in the given directory, "- ++ "without creating a tarball")- sDistDirectory (\v flags -> flags { sDistDirectory = v })- (reqArgFlag "DIR")- ]- }--emptySDistFlags :: SDistFlags-emptySDistFlags = mempty--instance Monoid SDistFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup SDistFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Register flags--- ---------------------------------------------------------------- | Flags to @register@ and @unregister@: (user package, gen-script,--- in-place, verbosity)-data RegisterFlags = RegisterFlags {- regPackageDB :: Flag PackageDB,- regGenScript :: Flag Bool,- regGenPkgConf :: Flag (Maybe FilePath),- regInPlace :: Flag Bool,- regDistPref :: Flag FilePath,- regPrintId :: Flag Bool,- regVerbosity :: Flag Verbosity,- -- Same as in 'buildArgs' and 'copyArgs'- regArgs :: [String],- regCabalFilePath :: Flag FilePath- }- deriving (Show, Generic, Typeable)--defaultRegisterFlags :: RegisterFlags-defaultRegisterFlags = RegisterFlags {- regPackageDB = NoFlag,- regGenScript = Flag False,- regGenPkgConf = NoFlag,- regInPlace = Flag False,- regDistPref = NoFlag,- regPrintId = Flag False,- regArgs = [],- regCabalFilePath = mempty,- regVerbosity = Flag normal- }--registerCommand :: CommandUI RegisterFlags-registerCommand = CommandUI- { commandName = "register"- , commandSynopsis =- "Register this package with the compiler."- , commandDescription = Nothing- , commandNotes = Nothing- , commandUsage = \pname ->- "Usage: " ++ pname ++ " register [FLAGS]\n"- , commandDefaultFlags = defaultRegisterFlags- , commandOptions = \showOrParseArgs ->- [optionVerbosity regVerbosity (\v flags -> flags { regVerbosity = v })- ,optionDistPref- regDistPref (\d flags -> flags { regDistPref = d })- showOrParseArgs-- ,option "" ["packageDB"] ""- regPackageDB (\v flags -> flags { regPackageDB = v })- (choiceOpt [ (Flag UserPackageDB, ([],["user"]),- "upon registration, register this package in the user's local package database")- , (Flag GlobalPackageDB, ([],["global"]),- "(default)upon registration, register this package in the system-wide package database")])-- ,option "" ["inplace"]- "register the package in the build location, so it can be used without being installed"- regInPlace (\v flags -> flags { regInPlace = v })- trueArg-- ,option "" ["gen-script"]- "instead of registering, generate a script to register later"- regGenScript (\v flags -> flags { regGenScript = v })- trueArg-- ,option "" ["gen-pkg-config"]- "instead of registering, generate a package registration file/directory"- regGenPkgConf (\v flags -> flags { regGenPkgConf = v })- (optArg' "PKG" Flag flagToList)-- ,option "" ["print-ipid"]- "print the installed package ID calculated for this package"- regPrintId (\v flags -> flags { regPrintId = v })- trueArg- ]- }--unregisterCommand :: CommandUI RegisterFlags-unregisterCommand = CommandUI- { commandName = "unregister"- , commandSynopsis =- "Unregister this package with the compiler."- , commandDescription = Nothing- , commandNotes = Nothing- , commandUsage = \pname ->- "Usage: " ++ pname ++ " unregister [FLAGS]\n"- , commandDefaultFlags = defaultRegisterFlags- , commandOptions = \showOrParseArgs ->- [optionVerbosity regVerbosity (\v flags -> flags { regVerbosity = v })- ,optionDistPref- regDistPref (\d flags -> flags { regDistPref = d })- showOrParseArgs-- ,option "" ["user"] ""- regPackageDB (\v flags -> flags { regPackageDB = v })- (choiceOpt [ (Flag UserPackageDB, ([],["user"]),- "unregister this package in the user's local package database")- , (Flag GlobalPackageDB, ([],["global"]),- "(default) unregister this package in the system-wide package database")])-- ,option "" ["gen-script"]- "Instead of performing the unregister command, generate a script to unregister later"- regGenScript (\v flags -> flags { regGenScript = v })- trueArg- ]- }--emptyRegisterFlags :: RegisterFlags-emptyRegisterFlags = mempty--instance Monoid RegisterFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup RegisterFlags where- (<>) = gmappend---- --------------------------------------------------------------- * HsColour flags--- --------------------------------------------------------------data HscolourFlags = HscolourFlags {- hscolourCSS :: Flag FilePath,- hscolourExecutables :: Flag Bool,- hscolourTestSuites :: Flag Bool,- hscolourBenchmarks :: Flag Bool,- hscolourForeignLibs :: Flag Bool,- hscolourDistPref :: Flag FilePath,- hscolourVerbosity :: Flag Verbosity,- hscolourCabalFilePath :: Flag FilePath- }- deriving (Show, Generic, Typeable)--emptyHscolourFlags :: HscolourFlags-emptyHscolourFlags = mempty--defaultHscolourFlags :: HscolourFlags-defaultHscolourFlags = HscolourFlags {- hscolourCSS = NoFlag,- hscolourExecutables = Flag False,- hscolourTestSuites = Flag False,- hscolourBenchmarks = Flag False,- hscolourDistPref = NoFlag,- hscolourForeignLibs = Flag False,- hscolourVerbosity = Flag normal,- hscolourCabalFilePath = mempty- }--instance Monoid HscolourFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup HscolourFlags where- (<>) = gmappend--hscolourCommand :: CommandUI HscolourFlags-hscolourCommand = CommandUI- { commandName = "hscolour"- , commandSynopsis =- "Generate HsColour colourised code, in HTML format."- , commandDescription = Just (\_ -> "Requires the hscolour program.\n")- , commandNotes = Just $ \_ ->- "Deprecated in favour of 'cabal haddock --hyperlink-source'."- , commandUsage = \pname ->- "Usage: " ++ pname ++ " hscolour [FLAGS]\n"- , commandDefaultFlags = defaultHscolourFlags- , commandOptions = \showOrParseArgs ->- [optionVerbosity hscolourVerbosity- (\v flags -> flags { hscolourVerbosity = v })- ,optionDistPref- hscolourDistPref (\d flags -> flags { hscolourDistPref = d })- showOrParseArgs-- ,option "" ["executables"]- "Run hscolour for Executables targets"- hscolourExecutables (\v flags -> flags { hscolourExecutables = v })- trueArg-- ,option "" ["tests"]- "Run hscolour for Test Suite targets"- hscolourTestSuites (\v flags -> flags { hscolourTestSuites = v })- trueArg-- ,option "" ["benchmarks"]- "Run hscolour for Benchmark targets"- hscolourBenchmarks (\v flags -> flags { hscolourBenchmarks = v })- trueArg-- ,option "" ["foreign-libraries"]- "Run hscolour for Foreign Library targets"- hscolourForeignLibs (\v flags -> flags { hscolourForeignLibs = v })- trueArg-- ,option "" ["all"]- "Run hscolour for all targets"- (\f -> allFlags [ hscolourExecutables f- , hscolourTestSuites f- , hscolourBenchmarks f- , hscolourForeignLibs f- ])- (\v flags -> flags { hscolourExecutables = v- , hscolourTestSuites = v- , hscolourBenchmarks = v- , hscolourForeignLibs = v- })- trueArg-- ,option "" ["css"]- "Use a cascading style sheet"- hscolourCSS (\v flags -> flags { hscolourCSS = v })- (reqArgFlag "PATH")- ]- }---- --------------------------------------------------------------- * Doctest flags--- --------------------------------------------------------------data DoctestFlags = DoctestFlags {- doctestProgramPaths :: [(String, FilePath)],- doctestProgramArgs :: [(String, [String])],- doctestDistPref :: Flag FilePath,- doctestVerbosity :: Flag Verbosity- }- deriving (Show, Generic, Typeable)--defaultDoctestFlags :: DoctestFlags-defaultDoctestFlags = DoctestFlags {- doctestProgramPaths = mempty,- doctestProgramArgs = [],- doctestDistPref = NoFlag,- doctestVerbosity = Flag normal- }--doctestCommand :: CommandUI DoctestFlags-doctestCommand = CommandUI- { commandName = "doctest"- , commandSynopsis = "Run doctest tests."- , commandDescription = Just $ \_ ->- "Requires the program doctest, version 0.12.\n"- , commandNotes = Nothing- , commandUsage = \pname ->- "Usage: " ++ pname ++ " doctest [FLAGS]\n"- , commandDefaultFlags = defaultDoctestFlags- , commandOptions = \showOrParseArgs ->- doctestOptions showOrParseArgs- ++ programDbPaths progDb ParseArgs- doctestProgramPaths (\v flags -> flags { doctestProgramPaths = v })- ++ programDbOption progDb showOrParseArgs- doctestProgramArgs (\v fs -> fs { doctestProgramArgs = v })- ++ programDbOptions progDb ParseArgs- doctestProgramArgs (\v flags -> flags { doctestProgramArgs = v })- }- where- progDb = addKnownProgram doctestProgram- emptyProgramDb--doctestOptions :: ShowOrParseArgs -> [OptionField DoctestFlags]-doctestOptions showOrParseArgs =- [optionVerbosity doctestVerbosity- (\v flags -> flags { doctestVerbosity = v })- ,optionDistPref- doctestDistPref (\d flags -> flags { doctestDistPref = d })- showOrParseArgs- ]--emptyDoctestFlags :: DoctestFlags-emptyDoctestFlags = mempty--instance Monoid DoctestFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup DoctestFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Haddock flags--- ----------------------------------------------------------------- | When we build haddock documentation, there are two cases:------ 1. We build haddocks only for the current development version,--- intended for local use and not for distribution. In this case,--- we store the generated documentation in @<dist>/doc/html/<package name>@.------ 2. We build haddocks for intended for uploading them to hackage.--- In this case, we need to follow the layout that hackage expects--- from documentation tarballs, and we might also want to use different--- flags than for development builds, so in this case we store the generated--- documentation in @<dist>/doc/html/<package id>-docs@.-data HaddockTarget = ForHackage | ForDevelopment deriving (Eq, Show, Generic, Typeable)--instance Binary HaddockTarget-instance Structured HaddockTarget--instance Pretty HaddockTarget where- pretty ForHackage = Disp.text "for-hackage"- pretty ForDevelopment = Disp.text "for-development"--instance Parsec HaddockTarget where- parsec = P.choice [ P.try $ P.string "for-hackage" >> return ForHackage- , P.string "for-development" >> return ForDevelopment]--data HaddockFlags = HaddockFlags {- haddockProgramPaths :: [(String, FilePath)],- haddockProgramArgs :: [(String, [String])],- haddockHoogle :: Flag Bool,- haddockHtml :: Flag Bool,- haddockHtmlLocation :: Flag String,- haddockForHackage :: Flag HaddockTarget,- haddockExecutables :: Flag Bool,- haddockTestSuites :: Flag Bool,- haddockBenchmarks :: Flag Bool,- haddockForeignLibs :: Flag Bool,- haddockInternal :: Flag Bool,- haddockCss :: Flag FilePath,- haddockLinkedSource :: Flag Bool,- haddockQuickJump :: Flag Bool,- haddockHscolourCss :: Flag FilePath,- haddockContents :: Flag PathTemplate,- haddockDistPref :: Flag FilePath,- haddockKeepTempFiles:: Flag Bool,- haddockVerbosity :: Flag Verbosity,- haddockCabalFilePath :: Flag FilePath,- haddockArgs :: [String]- }- deriving (Show, Generic, Typeable)--defaultHaddockFlags :: HaddockFlags-defaultHaddockFlags = HaddockFlags {- haddockProgramPaths = mempty,- haddockProgramArgs = [],- haddockHoogle = Flag False,- haddockHtml = Flag False,- haddockHtmlLocation = NoFlag,- haddockForHackage = NoFlag,- haddockExecutables = Flag False,- haddockTestSuites = Flag False,- haddockBenchmarks = Flag False,- haddockForeignLibs = Flag False,- haddockInternal = Flag False,- haddockCss = NoFlag,- haddockLinkedSource = Flag False,- haddockQuickJump = Flag False,- haddockHscolourCss = NoFlag,- haddockContents = NoFlag,- haddockDistPref = NoFlag,- haddockKeepTempFiles= Flag False,- haddockVerbosity = Flag normal,- haddockCabalFilePath = mempty,- haddockArgs = mempty- }--haddockCommand :: CommandUI HaddockFlags-haddockCommand = CommandUI- { commandName = "haddock"- , commandSynopsis = "Generate Haddock HTML documentation."- , commandDescription = Just $ \_ ->- "Requires the program haddock, version 2.x.\n"- , commandNotes = Nothing- , commandUsage = usageAlternatives "haddock" $- [ "[FLAGS]"- , "COMPONENTS [FLAGS]"- ]- , commandDefaultFlags = defaultHaddockFlags- , commandOptions = \showOrParseArgs ->- haddockOptions showOrParseArgs- ++ programDbPaths progDb ParseArgs- haddockProgramPaths (\v flags -> flags { haddockProgramPaths = v})- ++ programDbOption progDb showOrParseArgs- haddockProgramArgs (\v fs -> fs { haddockProgramArgs = v })- ++ programDbOptions progDb ParseArgs- haddockProgramArgs (\v flags -> flags { haddockProgramArgs = v})- }- where- progDb = addKnownProgram haddockProgram- $ addKnownProgram ghcProgram- $ emptyProgramDb--haddockOptions :: ShowOrParseArgs -> [OptionField HaddockFlags]-haddockOptions showOrParseArgs =- [optionVerbosity haddockVerbosity- (\v flags -> flags { haddockVerbosity = v })- ,optionDistPref- haddockDistPref (\d flags -> flags { haddockDistPref = d })- showOrParseArgs-- ,option "" ["keep-temp-files"]- "Keep temporary files"- haddockKeepTempFiles (\b flags -> flags { haddockKeepTempFiles = b })- trueArg-- ,option "" ["hoogle"]- "Generate a hoogle database"- haddockHoogle (\v flags -> flags { haddockHoogle = v })- trueArg-- ,option "" ["html"]- "Generate HTML documentation (the default)"- haddockHtml (\v flags -> flags { haddockHtml = v })- trueArg-- ,option "" ["html-location"]- "Location of HTML documentation for pre-requisite packages"- 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 })- (noArg (Flag ForHackage))-- ,option "" ["executables"]- "Run haddock for Executables targets"- haddockExecutables (\v flags -> flags { haddockExecutables = v })- trueArg-- ,option "" ["tests"]- "Run haddock for Test Suite targets"- haddockTestSuites (\v flags -> flags { haddockTestSuites = v })- trueArg-- ,option "" ["benchmarks"]- "Run haddock for Benchmark targets"- haddockBenchmarks (\v flags -> flags { haddockBenchmarks = v })- trueArg-- ,option "" ["foreign-libraries"]- "Run haddock for Foreign Library targets"- haddockForeignLibs (\v flags -> flags { haddockForeignLibs = v })- trueArg-- ,option "" ["all"]- "Run haddock for all targets"- (\f -> allFlags [ haddockExecutables f- , haddockTestSuites f- , haddockBenchmarks f- , haddockForeignLibs f- ])- (\v flags -> flags { haddockExecutables = v- , haddockTestSuites = v- , haddockBenchmarks = v- , haddockForeignLibs = v- })- trueArg-- ,option "" ["internal"]- "Run haddock for internal modules and include all symbols"- haddockInternal (\v flags -> flags { haddockInternal = v })- trueArg-- ,option "" ["css"]- "Use PATH as the haddock stylesheet"- haddockCss (\v flags -> flags { haddockCss = v })- (reqArgFlag "PATH")-- ,option "" ["hyperlink-source","hyperlink-sources","hyperlinked-source"]- "Hyperlink the documentation to the source code"- haddockLinkedSource (\v flags -> flags { haddockLinkedSource = v })- trueArg-- ,option "" ["quickjump"]- "Generate an index for interactive documentation navigation"- haddockQuickJump (\v flags -> flags { haddockQuickJump = v })- trueArg-- ,option "" ["hscolour-css"]- "Use PATH as the HsColour stylesheet"- haddockHscolourCss (\v flags -> flags { haddockHscolourCss = v })- (reqArgFlag "PATH")-- ,option "" ["contents-location"]- "Bake URL in as the location for the contents page"- haddockContents (\v flags -> flags { haddockContents = v })- (reqArg' "URL"- (toFlag . toPathTemplate)- (flagToList . fmap fromPathTemplate))- ]--emptyHaddockFlags :: HaddockFlags-emptyHaddockFlags = mempty--instance Monoid HaddockFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup HaddockFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Clean flags--- --------------------------------------------------------------data CleanFlags = CleanFlags {- cleanSaveConf :: Flag Bool,- cleanDistPref :: Flag FilePath,- cleanVerbosity :: Flag Verbosity,- cleanCabalFilePath :: Flag FilePath- }- deriving (Show, Generic, Typeable)--defaultCleanFlags :: CleanFlags-defaultCleanFlags = CleanFlags {- cleanSaveConf = Flag False,- cleanDistPref = NoFlag,- cleanVerbosity = Flag normal,- cleanCabalFilePath = mempty- }--cleanCommand :: CommandUI CleanFlags-cleanCommand = CommandUI- { commandName = "clean"- , commandSynopsis = "Clean up after a build."- , commandDescription = Just $ \_ ->- "Removes .hi, .o, preprocessed sources, etc.\n"- , commandNotes = Nothing- , commandUsage = \pname ->- "Usage: " ++ pname ++ " clean [FLAGS]\n"- , commandDefaultFlags = defaultCleanFlags- , commandOptions = \showOrParseArgs ->- [optionVerbosity cleanVerbosity (\v flags -> flags { cleanVerbosity = v })- ,optionDistPref- cleanDistPref (\d flags -> flags { cleanDistPref = d })- showOrParseArgs-- ,option "s" ["save-configure"]- "Do not remove the configuration file (dist/setup-config) during cleaning. Saves need to reconfigure."- cleanSaveConf (\v flags -> flags { cleanSaveConf = v })- trueArg- ]- }--emptyCleanFlags :: CleanFlags-emptyCleanFlags = mempty--instance Monoid CleanFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup CleanFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Build flags--- --------------------------------------------------------------data BuildFlags = BuildFlags {- buildProgramPaths :: [(String, FilePath)],- buildProgramArgs :: [(String, [String])],- buildDistPref :: Flag FilePath,- buildVerbosity :: Flag Verbosity,- buildNumJobs :: Flag (Maybe Int),- -- TODO: this one should not be here, it's just that the silly- -- UserHooks stop us from passing extra info in other ways- buildArgs :: [String],- buildCabalFilePath :: Flag FilePath- }- deriving (Read, Show, Generic, Typeable)--defaultBuildFlags :: BuildFlags-defaultBuildFlags = BuildFlags {- buildProgramPaths = mempty,- buildProgramArgs = [],- buildDistPref = mempty,- buildVerbosity = Flag normal,- buildNumJobs = mempty,- buildArgs = [],- buildCabalFilePath = mempty- }--buildCommand :: ProgramDb -> CommandUI BuildFlags-buildCommand progDb = CommandUI- { commandName = "build"- , commandSynopsis = "Compile all/specific components."- , commandDescription = Just $ \_ -> wrapText $- "Components encompass executables, tests, and benchmarks.\n"- ++ "\n"- ++ "Affected by configuration options, see `configure`.\n"- , commandNotes = Just $ \pname ->- "Examples:\n"- ++ " " ++ pname ++ " build "- ++ " All the components in the package\n"- ++ " " ++ pname ++ " build foo "- ++ " A component (i.e. lib, exe, test suite)\n\n"- ++ programFlagsDescription progDb---TODO: re-enable once we have support for module/file targets--- ++ " " ++ pname ++ " build Foo.Bar "--- ++ " A module\n"--- ++ " " ++ pname ++ " build Foo/Bar.hs"--- ++ " A file\n\n"--- ++ "If a target is ambiguous it can be qualified with the component "--- ++ "name, e.g.\n"--- ++ " " ++ pname ++ " build foo:Foo.Bar\n"--- ++ " " ++ pname ++ " build testsuite1:Foo/Bar.hs\n"- , commandUsage = usageAlternatives "build" $- [ "[FLAGS]"- , "COMPONENTS [FLAGS]"- ]- , commandDefaultFlags = defaultBuildFlags- , commandOptions = \showOrParseArgs ->- [ optionVerbosity- buildVerbosity (\v flags -> flags { buildVerbosity = v })-- , optionDistPref- buildDistPref (\d flags -> flags { buildDistPref = d }) showOrParseArgs- ]- ++ buildOptions progDb showOrParseArgs- }--buildOptions :: ProgramDb -> ShowOrParseArgs- -> [OptionField BuildFlags]-buildOptions progDb showOrParseArgs =- [ optionNumJobs- buildNumJobs (\v flags -> flags { buildNumJobs = v })- ]-- ++ programDbPaths progDb showOrParseArgs- buildProgramPaths (\v flags -> flags { buildProgramPaths = v})-- ++ programDbOption progDb showOrParseArgs- buildProgramArgs (\v fs -> fs { buildProgramArgs = v })-- ++ programDbOptions progDb showOrParseArgs- buildProgramArgs (\v flags -> flags { buildProgramArgs = v})--emptyBuildFlags :: BuildFlags-emptyBuildFlags = mempty--instance Monoid BuildFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup BuildFlags where- (<>) = gmappend---- --------------------------------------------------------------- * REPL Flags--- --------------------------------------------------------------data ReplFlags = ReplFlags {- replProgramPaths :: [(String, FilePath)],- replProgramArgs :: [(String, [String])],- replDistPref :: Flag FilePath,- replVerbosity :: Flag Verbosity,- replReload :: Flag Bool,- replReplOptions :: [String]- }- deriving (Show, Generic, Typeable)--defaultReplFlags :: ReplFlags-defaultReplFlags = ReplFlags {- replProgramPaths = mempty,- replProgramArgs = [],- replDistPref = NoFlag,- replVerbosity = Flag normal,- replReload = Flag False,- replReplOptions = []- }--instance Monoid ReplFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup ReplFlags where- (<>) = gmappend--replCommand :: ProgramDb -> CommandUI ReplFlags-replCommand progDb = CommandUI- { commandName = "repl"- , commandSynopsis =- "Open an interpreter session for the given component."- , commandDescription = Just $ \pname -> wrapText $- "If the current directory contains no package, ignores COMPONENT "- ++ "parameters and opens an interactive interpreter session; if a "- ++ "sandbox is present, its package database will be used.\n"- ++ "\n"- ++ "Otherwise, (re)configures with the given or default flags, and "- ++ "loads the interpreter with the relevant modules. For executables, "- ++ "tests and benchmarks, loads the main module (and its "- ++ "dependencies); for libraries all exposed/other modules.\n"- ++ "\n"- ++ "The default component is the library itself, or the executable "- ++ "if that is the only component.\n"- ++ "\n"- ++ "Support for loading specific modules is planned but not "- ++ "implemented yet. For certain scenarios, `" ++ pname- ++ " exec -- ghci :l Foo` may be used instead. Note that `exec` will "- ++ "not (re)configure and you will have to specify the location of "- ++ "other modules, if required.\n"-- , commandNotes = Just $ \pname ->- "Examples:\n"- ++ " " ++ pname ++ " repl "- ++ " The first component in the package\n"- ++ " " ++ pname ++ " repl foo "- ++ " A named component (i.e. lib, exe, test suite)\n"- ++ " " ++ pname ++ " repl --repl-options=\"-lstdc++\""- ++ " Specifying flags for interpreter\n"---TODO: re-enable once we have support for module/file targets--- ++ " " ++ pname ++ " repl Foo.Bar "--- ++ " A module\n"--- ++ " " ++ pname ++ " repl Foo/Bar.hs"--- ++ " A file\n\n"--- ++ "If a target is ambiguous it can be qualified with the component "--- ++ "name, e.g.\n"--- ++ " " ++ pname ++ " repl foo:Foo.Bar\n"--- ++ " " ++ pname ++ " repl testsuite1:Foo/Bar.hs\n"- , commandUsage = \pname -> "Usage: " ++ pname ++ " repl [COMPONENT] [FLAGS]\n"- , commandDefaultFlags = defaultReplFlags- , commandOptions = \showOrParseArgs ->- optionVerbosity replVerbosity (\v flags -> flags { replVerbosity = v })- : optionDistPref- replDistPref (\d flags -> flags { replDistPref = d })- showOrParseArgs-- : programDbPaths progDb showOrParseArgs- replProgramPaths (\v flags -> flags { replProgramPaths = v})-- ++ programDbOption progDb showOrParseArgs- replProgramArgs (\v flags -> flags { replProgramArgs = v})-- ++ programDbOptions progDb showOrParseArgs- replProgramArgs (\v flags -> flags { replProgramArgs = v})-- ++ case showOrParseArgs of- ParseArgs ->- [ option "" ["reload"]- "Used from within an interpreter to update files."- replReload (\v flags -> flags { replReload = v })- trueArg- ]- _ -> []- ++ map liftReplOption (replOptions showOrParseArgs)- }- where- liftReplOption = liftOption replReplOptions (\v flags -> flags { replReplOptions = v })--replOptions :: ShowOrParseArgs -> [OptionField [String]]-replOptions _ = [ option [] ["repl-options"] "use this option for the repl" id- const (reqArg "FLAG" (succeedReadE (:[])) id) ]---- --------------------------------------------------------------- * Test flags--- --------------------------------------------------------------data TestShowDetails = Never | Failures | Always | Streaming | Direct- deriving (Eq, Ord, Enum, Bounded, Generic, Show, Typeable)--instance Binary TestShowDetails-instance Structured TestShowDetails--knownTestShowDetails :: [TestShowDetails]-knownTestShowDetails = [minBound..maxBound]--instance Pretty TestShowDetails where- pretty = Disp.text . lowercase . show--instance Parsec TestShowDetails where- parsec = maybe (fail "invalid TestShowDetails") return . classify =<< ident- where- ident = P.munch1 (\c -> isAlpha c || c == '_' || c == '-')- classify str = lookup (lowercase str) enumMap- enumMap :: [(String, TestShowDetails)]- enumMap = [ (prettyShow x, x)- | x <- knownTestShowDetails ]----TODO: do we need this instance?-instance Monoid TestShowDetails where- mempty = Never- mappend = (<>)--instance Semigroup TestShowDetails where- a <> b = if a < b then b else a--data TestFlags = TestFlags {- testDistPref :: Flag FilePath,- testVerbosity :: Flag Verbosity,- testHumanLog :: Flag PathTemplate,- testMachineLog :: Flag PathTemplate,- testShowDetails :: Flag TestShowDetails,- testKeepTix :: Flag Bool,- testWrapper :: Flag FilePath,- testFailWhenNoTestSuites :: Flag Bool,- -- TODO: think about if/how options are passed to test exes- testOptions :: [PathTemplate]- } deriving (Show, Generic, Typeable)--defaultTestFlags :: TestFlags-defaultTestFlags = TestFlags {- testDistPref = NoFlag,- testVerbosity = Flag normal,- testHumanLog = toFlag $ toPathTemplate $ "$pkgid-$test-suite.log",- testMachineLog = toFlag $ toPathTemplate $ "$pkgid.log",- testShowDetails = toFlag Failures,- testKeepTix = toFlag False,- testWrapper = NoFlag,- testFailWhenNoTestSuites = toFlag False,- testOptions = []- }--testCommand :: CommandUI TestFlags-testCommand = CommandUI- { commandName = "test"- , commandSynopsis =- "Run all/specific tests in the test suite."- , commandDescription = Just $ \pname -> wrapText $- "If necessary (re)configures with `--enable-tests` flag and builds"- ++ " the test suite.\n"- ++ "\n"- ++ "Remember that the tests' dependencies must be installed if there"- ++ " are additional ones; e.g. with `" ++ pname- ++ " install --only-dependencies --enable-tests`.\n"- ++ "\n"- ++ "By defining UserHooks in a custom Setup.hs, the package can"- ++ " define actions to be executed before and after running tests.\n"- , commandNotes = Nothing- , commandUsage = usageAlternatives "test"- [ "[FLAGS]"- , "TESTCOMPONENTS [FLAGS]"- ]- , commandDefaultFlags = defaultTestFlags- , commandOptions = testOptions'- }--testOptions' :: ShowOrParseArgs -> [OptionField TestFlags]-testOptions' showOrParseArgs =- [ optionVerbosity testVerbosity (\v flags -> flags { testVerbosity = v })- , optionDistPref- testDistPref (\d flags -> flags { testDistPref = d })- showOrParseArgs- , option [] ["log"]- ("Log all test suite results to file (name template can use "- ++ "$pkgid, $compiler, $os, $arch, $test-suite, $result)")- testHumanLog (\v flags -> flags { testHumanLog = v })- (reqArg' "TEMPLATE"- (toFlag . toPathTemplate)- (flagToList . fmap fromPathTemplate))- , option [] ["machine-log"]- ("Produce a machine-readable log file (name template can use "- ++ "$pkgid, $compiler, $os, $arch, $result)")- testMachineLog (\v flags -> flags { testMachineLog = v })- (reqArg' "TEMPLATE"- (toFlag . toPathTemplate)- (flagToList . fmap fromPathTemplate))- , option [] ["show-details"]- ("'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."- ++ "'direct': send results of test cases in real time; no log file.")- testShowDetails (\v flags -> flags { testShowDetails = v })- (reqArg "FILTER"- (parsecToReadE (\_ -> "--show-details flag expects one of "- ++ intercalate ", "- (map prettyShow knownTestShowDetails))- (fmap toFlag parsec))- (flagToList . fmap prettyShow))- , option [] ["keep-tix-files"]- "keep .tix files for HPC between test runs"- testKeepTix (\v flags -> flags { testKeepTix = v})- trueArg- , option [] ["test-wrapper"]- "Run test through a wrapper."- testWrapper (\v flags -> flags { testWrapper = v })- (reqArg' "FILE" (toFlag :: FilePath -> Flag FilePath)- (flagToList :: Flag FilePath -> [FilePath]))- , option [] ["fail-when-no-test-suites"]- ("Exit with failure when no test suites are found.")- testFailWhenNoTestSuites (\v flags -> flags { testFailWhenNoTestSuites = v})- trueArg- , option [] ["test-options"]- ("give extra options to test executables "- ++ "(name templates can use $pkgid, $compiler, "- ++ "$os, $arch, $test-suite)")- testOptions (\v flags -> flags { testOptions = v })- (reqArg' "TEMPLATES" (map toPathTemplate . splitArgs)- (const []))- , option [] ["test-option"]- ("give extra option to test executables "- ++ "(no need to quote options containing spaces, "- ++ "name template can use $pkgid, $compiler, "- ++ "$os, $arch, $test-suite)")- testOptions (\v flags -> flags { testOptions = v })- (reqArg' "TEMPLATE" (\x -> [toPathTemplate x])- (map fromPathTemplate))- ]--emptyTestFlags :: TestFlags-emptyTestFlags = mempty--instance Monoid TestFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup TestFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Benchmark flags--- --------------------------------------------------------------data BenchmarkFlags = BenchmarkFlags {- benchmarkDistPref :: Flag FilePath,- benchmarkVerbosity :: Flag Verbosity,- benchmarkOptions :: [PathTemplate]- } deriving (Show, Generic, Typeable)--defaultBenchmarkFlags :: BenchmarkFlags-defaultBenchmarkFlags = BenchmarkFlags {- benchmarkDistPref = NoFlag,- benchmarkVerbosity = Flag normal,- benchmarkOptions = []- }--benchmarkCommand :: CommandUI BenchmarkFlags-benchmarkCommand = CommandUI- { commandName = "bench"- , commandSynopsis =- "Run all/specific benchmarks."- , commandDescription = Just $ \pname -> wrapText $- "If necessary (re)configures with `--enable-benchmarks` flag and"- ++ " builds the benchmarks.\n"- ++ "\n"- ++ "Remember that the benchmarks' dependencies must be installed if"- ++ " there are additional ones; e.g. with `" ++ pname- ++ " install --only-dependencies --enable-benchmarks`.\n"- ++ "\n"- ++ "By defining UserHooks in a custom Setup.hs, the package can"- ++ " define actions to be executed before and after running"- ++ " benchmarks.\n"- , commandNotes = Nothing- , commandUsage = usageAlternatives "bench"- [ "[FLAGS]"- , "BENCHCOMPONENTS [FLAGS]"- ]- , commandDefaultFlags = defaultBenchmarkFlags- , commandOptions = benchmarkOptions'- }--benchmarkOptions' :: ShowOrParseArgs -> [OptionField BenchmarkFlags]-benchmarkOptions' showOrParseArgs =- [ optionVerbosity benchmarkVerbosity- (\v flags -> flags { benchmarkVerbosity = v })- , optionDistPref- benchmarkDistPref (\d flags -> flags { benchmarkDistPref = d })- showOrParseArgs- , option [] ["benchmark-options"]- ("give extra options to benchmark executables "- ++ "(name templates can use $pkgid, $compiler, "- ++ "$os, $arch, $benchmark)")- benchmarkOptions (\v flags -> flags { benchmarkOptions = v })- (reqArg' "TEMPLATES" (map toPathTemplate . splitArgs)- (const []))- , option [] ["benchmark-option"]- ("give extra option to benchmark executables "- ++ "(no need to quote options containing spaces, "- ++ "name template can use $pkgid, $compiler, "- ++ "$os, $arch, $benchmark)")- benchmarkOptions (\v flags -> flags { benchmarkOptions = v })- (reqArg' "TEMPLATE" (\x -> [toPathTemplate x])- (map fromPathTemplate))- ]--emptyBenchmarkFlags :: BenchmarkFlags-emptyBenchmarkFlags = mempty--instance Monoid BenchmarkFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup BenchmarkFlags where- (<>) = gmappend---- --------------------------------------------------------------- * Shared options utils--- --------------------------------------------------------------programFlagsDescription :: ProgramDb -> String-programFlagsDescription progDb =- "The flags --with-PROG and --PROG-option(s) can be used with"- ++ " the following programs:"- ++ (concatMap (\line -> "\n " ++ unwords line) . wrapLine 77 . sort)- [ programName prog | (prog, _) <- knownPrograms progDb ]- ++ "\n"---- | For each known program @PROG@ in 'progDb', produce a @with-PROG@--- 'OptionField'.-programDbPaths- :: ProgramDb- -> ShowOrParseArgs- -> (flags -> [(String, FilePath)])- -> ([(String, FilePath)] -> (flags -> flags))- -> [OptionField flags]-programDbPaths progDb showOrParseArgs get set =- programDbPaths' ("with-" ++) progDb showOrParseArgs get set---- | Like 'programDbPaths', but allows to customise the option name.-programDbPaths'- :: (String -> String)- -> ProgramDb- -> ShowOrParseArgs- -> (flags -> [(String, FilePath)])- -> ([(String, FilePath)] -> (flags -> flags))- -> [OptionField flags]-programDbPaths' mkName progDb showOrParseArgs get set =- case showOrParseArgs of- -- we don't want a verbose help text list so we just show a generic one:- ShowArgs -> [withProgramPath "PROG"]- ParseArgs -> map (withProgramPath . programName . fst)- (knownPrograms progDb)- where- withProgramPath prog =- option "" [mkName prog]- ("give the path to " ++ prog)- get set- (reqArg' "PATH" (\path -> [(prog, path)])- (\progPaths -> [ path | (prog', path) <- progPaths, prog==prog' ]))---- | For each known program @PROG@ in 'progDb', produce a @PROG-option@--- 'OptionField'.-programDbOption- :: ProgramDb- -> ShowOrParseArgs- -> (flags -> [(String, [String])])- -> ([(String, [String])] -> (flags -> flags))- -> [OptionField flags]-programDbOption progDb showOrParseArgs get set =- case showOrParseArgs of- -- we don't want a verbose help text list so we just show a generic one:- ShowArgs -> [programOption "PROG"]- ParseArgs -> map (programOption . programName . fst)- (knownPrograms progDb)- where- programOption prog =- option "" [prog ++ "-option"]- ("give an extra option to " ++ prog ++- " (no need to quote options containing spaces)")- get set- (reqArg' "OPT" (\arg -> [(prog, [arg])])- (\progArgs -> concat [ args- | (prog', args) <- progArgs, prog==prog' ]))----- | For each known program @PROG@ in 'progDb', produce a @PROG-options@--- 'OptionField'.-programDbOptions- :: ProgramDb- -> ShowOrParseArgs- -> (flags -> [(String, [String])])- -> ([(String, [String])] -> (flags -> flags))- -> [OptionField flags]-programDbOptions progDb showOrParseArgs get set =- case showOrParseArgs of- -- we don't want a verbose help text list so we just show a generic one:- ShowArgs -> [programOptions "PROG"]- ParseArgs -> map (programOptions . programName . fst)- (knownPrograms progDb)- where- programOptions prog =- option "" [prog ++ "-options"]- ("give extra options to " ++ prog)- get set- (reqArg' "OPTS" (\args -> [(prog, splitArgs args)]) (const []))---- --------------------------------------------------------------- * GetOpt Utils--- --------------------------------------------------------------boolOpt :: SFlags -> SFlags- -> MkOptDescr (a -> Flag Bool) (Flag Bool -> a -> a) a-boolOpt = Command.boolOpt flagToMaybe Flag--boolOpt' :: OptFlags -> OptFlags- -> MkOptDescr (a -> Flag Bool) (Flag Bool -> a -> a) a-boolOpt' = Command.boolOpt' flagToMaybe Flag--trueArg, falseArg :: MkOptDescr (a -> Flag Bool) (Flag Bool -> a -> a) a-trueArg sfT lfT = boolOpt' (sfT, lfT) ([], []) sfT lfT-falseArg sfF lfF = boolOpt' ([], []) (sfF, lfF) sfF lfF--reqArgFlag :: ArgPlaceHolder -> SFlags -> LFlags -> Description ->- (b -> Flag String) -> (Flag String -> b -> b) -> OptDescr b-reqArgFlag ad = reqArg ad (succeedReadE Flag) flagToList--optionDistPref :: (flags -> Flag FilePath)- -> (Flag FilePath -> flags -> flags)- -> ShowOrParseArgs- -> OptionField flags-optionDistPref get set = \showOrParseArgs ->- option "" (distPrefFlagName showOrParseArgs)- ( "The directory where Cabal puts generated build files "- ++ "(default " ++ defaultDistPref ++ ")")- get set- (reqArgFlag "DIR")- where- distPrefFlagName ShowArgs = ["builddir"]- distPrefFlagName ParseArgs = ["builddir", "distdir", "distpref"]--optionVerbosity :: (flags -> Flag Verbosity)- -> (Flag Verbosity -> flags -> flags)- -> OptionField flags-optionVerbosity get set =- option "v" ["verbose"]- "Control verbosity (n is 0--3, default verbosity level is 1)"- get set- (optArg "n" (fmap Flag flagToVerbosity)- (Flag verbose) -- default Value if no n is given- (fmap (Just . showForCabal) . flagToList))--optionNumJobs :: (flags -> Flag (Maybe Int))- -> (Flag (Maybe Int) -> flags -> flags)- -> OptionField flags-optionNumJobs get set =- option "j" ["jobs"]- "Run NUM jobs simultaneously (or '$ncpus' if no NUM is given)."- get set- (optArg "NUM" (fmap Flag numJobsParser)- (Flag Nothing)- (map (Just . maybe "$ncpus" show) . flagToList))- where- numJobsParser :: ReadE (Maybe Int)- numJobsParser = ReadE $ \s ->- case s of- "$ncpus" -> Right Nothing- _ -> case reads s of- [(n, "")]- | n < 1 -> Left "The number of jobs should be 1 or more."- | otherwise -> Right (Just n)- _ -> Left "The jobs value should be a number or '$ncpus'"----- --------------------------------------------------------------- * show-build-info command flags--- --------------------------------------------------------------data ShowBuildInfoFlags = ShowBuildInfoFlags- { buildInfoBuildFlags :: BuildFlags- , buildInfoOutputFile :: Maybe FilePath- } deriving (Show, Typeable)--defaultShowBuildFlags :: ShowBuildInfoFlags-defaultShowBuildFlags =- ShowBuildInfoFlags- { buildInfoBuildFlags = defaultBuildFlags- , buildInfoOutputFile = Nothing- }--showBuildInfoCommand :: ProgramDb -> CommandUI ShowBuildInfoFlags-showBuildInfoCommand progDb = CommandUI- { commandName = "show-build-info"- , commandSynopsis = "Emit details about how a package would be built."- , commandDescription = Just $ \_ -> wrapText $- "Components encompass executables, tests, and benchmarks.\n"- ++ "\n"- ++ "Affected by configuration options, see `configure`.\n"- , commandNotes = Just $ \pname ->- "Examples:\n"- ++ " " ++ pname ++ " show-build-info "- ++ " All the components in the package\n"- ++ " " ++ pname ++ " show-build-info foo "- ++ " A component (i.e. lib, exe, test suite)\n\n"- ++ programFlagsDescription progDb---TODO: re-enable once we have support for module/file targets--- ++ " " ++ pname ++ " show-build-info Foo.Bar "--- ++ " A module\n"--- ++ " " ++ pname ++ " show-build-info Foo/Bar.hs"--- ++ " A file\n\n"--- ++ "If a target is ambiguous it can be qualified with the component "--- ++ "name, e.g.\n"--- ++ " " ++ pname ++ " show-build-info foo:Foo.Bar\n"--- ++ " " ++ pname ++ " show-build-info testsuite1:Foo/Bar.hs\n"- , commandUsage = usageAlternatives "show-build-info" $- [ "[FLAGS]"- , "COMPONENTS [FLAGS]"- ]- , commandDefaultFlags = defaultShowBuildFlags- , commandOptions = \showOrParseArgs ->- parseBuildFlagsForShowBuildInfoFlags showOrParseArgs progDb- ++- [ option [] ["buildinfo-json-output"]- "Write the result to the given file instead of stdout"- buildInfoOutputFile (\pf flags -> flags { buildInfoOutputFile = pf })- (reqArg' "FILE" Just (maybe [] pure))- ]-- }--parseBuildFlagsForShowBuildInfoFlags :: ShowOrParseArgs -> ProgramDb -> [OptionField ShowBuildInfoFlags]-parseBuildFlagsForShowBuildInfoFlags showOrParseArgs progDb =- map- (liftOption- buildInfoBuildFlags- (\bf flags -> flags { buildInfoBuildFlags = bf } )- )- buildFlags- where- buildFlags = buildOptions progDb showOrParseArgs- ++- [ optionVerbosity- buildVerbosity (\v flags -> flags { buildVerbosity = v })-- , optionDistPref- buildDistPref (\d flags -> flags { buildDistPref = d }) showOrParseArgs- ]---- --------------------------------------------------------------- * Other Utils--- ---------------------------------------------------------------- | Arguments to pass to a @configure@ script, e.g. generated by--- @autoconf@.-configureArgs :: Bool -> ConfigFlags -> [String]-configureArgs bcHack flags- = hc_flag- ++ optFlag "with-hc-pkg" configHcPkg- ++ optFlag' "prefix" prefix- ++ optFlag' "bindir" bindir- ++ optFlag' "libdir" libdir- ++ optFlag' "libexecdir" libexecdir- ++ optFlag' "datadir" datadir- ++ optFlag' "sysconfdir" sysconfdir- ++ configConfigureArgs flags- where- hc_flag = case (configHcFlavor flags, configHcPath flags) of- (_, Flag hc_path) -> [hc_flag_name ++ hc_path]- (Flag hc, NoFlag) -> [hc_flag_name ++ prettyShow hc]- (NoFlag,NoFlag) -> []- hc_flag_name- --TODO kill off thic bc hack when defaultUserHooks is removed.- | bcHack = "--with-hc="- | otherwise = "--with-compiler="- optFlag name config_field = case config_field flags of- Flag p -> ["--" ++ name ++ "=" ++ p]- NoFlag -> []- optFlag' name config_field = optFlag name (fmap fromPathTemplate- . config_field- . configInstallDirs)--configureCCompiler :: Verbosity -> ProgramDb- -> IO (FilePath, [String])-configureCCompiler verbosity progdb = configureProg verbosity progdb gccProgram--configureLinker :: Verbosity -> ProgramDb -> IO (FilePath, [String])-configureLinker verbosity progdb = configureProg verbosity progdb ldProgram--configureProg :: Verbosity -> ProgramDb -> Program- -> IO (FilePath, [String])-configureProg verbosity programDb prog = do- (p, _) <- requireProgram verbosity prog programDb- let pInv = programInvocation p []- return (progInvokePath pInv, progInvokeArgs pInv)---- | Helper function to split a string into a list of arguments.--- It's supposed to handle quoted things sensibly, eg:------ > splitArgs "--foo=\"C:/Program Files/Bar/" --baz"--- > = ["--foo=C:/Program Files/Bar", "--baz"]------ > splitArgs "\"-DMSGSTR=\\\"foo bar\\\"\" --baz"--- > = ["-DMSGSTR=\"foo bar\"","--baz"]----splitArgs :: String -> [String]-splitArgs = space []- where- space :: String -> String -> [String]- space w [] = word w []- space w ( c :s)- | isSpace c = word w (space [] s)- space w ('"':s) = string w s- space w s = nonstring w s-- string :: String -> String -> [String]- string w [] = word w []- string w ('"':s) = space w s- string w ('\\':'"':s) = string ('"':w) s- string w ( c :s) = string (c:w) s-- nonstring :: String -> String -> [String]- nonstring w [] = word w []- nonstring w ('"':s) = string w s- nonstring w ( c :s) = space (c:w) s-- word [] s = s- word w s = reverse w : s---- The test cases kinda have to be rewritten from the ground up... :/---hunitTests :: [Test]---hunitTests =--- let m = [("ghc", GHC), ("nhc98", NHC), ("hugs", Hugs)]--- (flags, commands', unkFlags, ers)--- = getOpt Permute options ["configure", "foobar", "--prefix=/foo", "--ghc", "--nhc98", "--hugs", "--with-compiler=/comp", "--unknown1", "--unknown2", "--install-prefix=/foo", "--user", "--global"]--- in [TestLabel "very basic option parsing" $ TestList [--- "getOpt flags" ~: "failed" ~:--- [Prefix "/foo", GhcFlag, NhcFlag, HugsFlag,--- WithCompiler "/comp", InstPrefix "/foo", UserFlag, GlobalFlag]--- ~=? flags,--- "getOpt commands" ~: "failed" ~: ["configure", "foobar"] ~=? commands',--- "getOpt unknown opts" ~: "failed" ~:--- ["--unknown1", "--unknown2"] ~=? unkFlags,--- "getOpt errors" ~: "failed" ~: [] ~=? ers],------ TestLabel "test location of various compilers" $ TestList--- ["configure parsing for prefix and compiler flag" ~: "failed" ~:--- (Right (ConfigCmd (Just comp, Nothing, Just "/usr/local"), []))--- ~=? (parseArgs ["--prefix=/usr/local", "--"++name, "configure"])--- | (name, comp) <- m],------ TestLabel "find the package tool" $ TestList--- ["configure parsing for prefix comp flag, withcompiler" ~: "failed" ~:--- (Right (ConfigCmd (Just comp, Just "/foo/comp", Just "/usr/local"), []))--- ~=? (parseArgs ["--prefix=/usr/local", "--"++name,--- "--with-compiler=/foo/comp", "configure"])--- | (name, comp) <- m],------ TestLabel "simpler commands" $ TestList--- [flag ~: "failed" ~: (Right (flagCmd, [])) ~=? (parseArgs [flag])--- | (flag, flagCmd) <- [("build", BuildCmd),--- ("install", InstallCmd Nothing False),--- ("sdist", SDistCmd),--- ("register", RegisterCmd False)]--- ]--- ]--{- Testing ideas:- * IO to look for hugs and hugs-pkg (which hugs, etc)- * quickCheck to test permutations of arguments- * what other options can we over-ride with a command-line flag?--}
− Distribution/Simple/ShowBuildInfo.hs
@@ -1,161 +0,0 @@--- |--- This module defines a simple JSON-based format for exporting basic--- information about a Cabal package and the compiler configuration Cabal--- would use to build it. This can be produced with the--- @cabal new-show-build-info@ command.--------- This format is intended for consumption by external tooling and should--- therefore be rather stable. Moreover, this allows tooling users to avoid--- linking against Cabal. This is an important advantage as direct API usage--- tends to be rather fragile in the presence of user-initiated upgrades of--- Cabal.------ Below is an example of the output this module produces,------ @--- { "cabal-version": "1.23.0.0",--- "compiler": {--- "flavour": "GHC",--- "compiler-id": "ghc-7.10.2",--- "path": "/usr/bin/ghc",--- },--- "components": [--- { "type": "lib",--- "name": "lib:Cabal",--- "compiler-args":--- ["-O", "-XHaskell98", "-Wall",--- "-package-id", "parallel-3.2.0.6-b79c38c5c25fff77f3ea7271851879eb"]--- "modules": ["Project.ModA", "Project.ModB", "Paths_project"],--- "src-files": [],--- "src-dirs": ["src"]--- }--- ]--- }--- @------ The @cabal-version@ property provides the version of the Cabal library--- which generated the output. The @compiler@ property gives some basic--- information about the compiler Cabal would use to compile the package.------ The @components@ property gives a list of the Cabal 'Component's defined by--- the package. Each has,------ * @type@: the type of the component (one of @lib@, @exe@,--- @test@, @bench@, or @flib@)--- * @name@: a string serving to uniquely identify the component within the--- package.--- * @compiler-args@: the command-line arguments Cabal would pass to the--- compiler to compile the component--- * @modules@: the modules belonging to the component--- * @src-dirs@: a list of directories where the modules might be found--- * @src-files@: any other Haskell sources needed by the component------ Note: At the moment this is only supported when using the GHC compiler.-----module Distribution.Simple.ShowBuildInfo (mkBuildInfo) where--import Distribution.Compat.Prelude-import Prelude ()--import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.Program.GHC as GHC--import Distribution.PackageDescription-import Distribution.Compiler-import Distribution.Verbosity-import Distribution.Simple.Compiler-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.Program-import Distribution.Simple.Setup-import Distribution.Simple.Utils (cabalVersion)-import Distribution.Simple.Utils.Json-import Distribution.Types.TargetInfo-import Distribution.Text-import Distribution.Pretty---- | Construct a JSON document describing the build information for a--- package.-mkBuildInfo- :: PackageDescription -- ^ Mostly information from the .cabal file- -> LocalBuildInfo -- ^ Configuration information- -> BuildFlags -- ^ Flags that the user passed to build- -> [TargetInfo]- -> Json-mkBuildInfo pkg_descr lbi _flags targetsToBuild = info- where- targetToNameAndLBI target =- (componentLocalName $ targetCLBI target, targetCLBI target)- componentsToBuild = map targetToNameAndLBI targetsToBuild- (.=) :: String -> Json -> (String, Json)- k .= v = (k, v)-- info = JsonObject- [ "cabal-version" .= JsonString (display cabalVersion)- , "compiler" .= mkCompilerInfo- , "components" .= JsonArray (map mkComponentInfo componentsToBuild)- ]-- mkCompilerInfo = JsonObject- [ "flavour" .= JsonString (prettyShow $ compilerFlavor $ compiler lbi)- , "compiler-id" .= JsonString (showCompilerId $ compiler lbi)- , "path" .= path- ]- where- path = maybe JsonNull (JsonString . programPath)- $ (flavorToProgram . compilerFlavor $ compiler lbi)- >>= flip lookupProgram (withPrograms lbi)-- flavorToProgram :: CompilerFlavor -> Maybe Program- flavorToProgram GHC = Just ghcProgram- flavorToProgram GHCJS = Just ghcjsProgram- flavorToProgram UHC = Just uhcProgram- flavorToProgram JHC = Just jhcProgram- flavorToProgram _ = Nothing-- mkComponentInfo (name, clbi) = JsonObject- [ "type" .= JsonString compType- , "name" .= JsonString (prettyShow name)- , "unit-id" .= JsonString (prettyShow $ componentUnitId clbi)- , "compiler-args" .= JsonArray (map JsonString $ getCompilerArgs bi lbi clbi)- , "modules" .= JsonArray (map (JsonString . display) modules)- , "src-files" .= JsonArray (map JsonString sourceFiles)- , "src-dirs" .= JsonArray (map JsonString $ hsSourceDirs bi)- ]- where- bi = componentBuildInfo comp- comp = fromMaybe (error $ "mkBuildInfo: no component " ++ prettyShow name) $ lookupComponent pkg_descr name- compType = case comp of- CLib _ -> "lib"- CExe _ -> "exe"- CTest _ -> "test"- CBench _ -> "bench"- CFLib _ -> "flib"- modules = case comp of- CLib lib -> explicitLibModules lib- CExe exe -> exeModules exe- _ -> []- sourceFiles = case comp of- CLib _ -> []- CExe exe -> [modulePath exe]- _ -> []---- | Get the command-line arguments that would be passed--- to the compiler to build the given component.-getCompilerArgs- :: BuildInfo- -> LocalBuildInfo- -> ComponentLocalBuildInfo- -> [String]-getCompilerArgs bi lbi clbi =- case compilerFlavor $ compiler lbi of- GHC -> ghc- GHCJS -> ghc- c -> error $ "ShowBuildInfo.getCompilerArgs: Don't know how to get "++- "build arguments for compiler "++show c- where- -- This is absolutely awful- ghc = GHC.renderGhcOptions (compiler lbi) (hostPlatform lbi) baseOpts- where- baseOpts = GHC.componentGhcOptions normal lbi bi clbi (buildDir lbi)
− Distribution/Simple/SrcDist.hs
@@ -1,517 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.SrcDist--- Copyright : Simon Marlow 2004--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This handles the @sdist@ command. The module exports an 'sdist' action but--- also some of the phases that make it up so that other tools can use just the--- bits they need. In particular the preparation of the tree of files to go--- into the source tarball is separated from actually building the source--- tarball.------ The 'createArchive' action uses the external @tar@ program and assumes that--- it accepts the @-z@ flag. Neither of these assumptions are valid on Windows.--- The 'sdist' action now also does some distribution QA checks.---- NOTE: FIX: we don't have a great way of testing this module, since--- we can't easily look inside a tarball once its created.--module Distribution.Simple.SrcDist (- -- * The top level action- sdist,-- -- ** Parts of 'sdist'- printPackageProblems,- prepareTree,- createArchive,-- -- ** Snapshots- prepareSnapshotTree,- snapshotPackage,- snapshotVersion,- dateToSnapshotNumber,-- -- * Extracting the source files- listPackageSources,- listPackageSourcesWithDie,-- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.PackageDescription-import Distribution.PackageDescription.Check hiding (doesFileExist)-import Distribution.Package-import Distribution.ModuleName-import qualified Distribution.ModuleName as ModuleName-import Distribution.Version-import Distribution.Simple.Configure (findDistPrefOrDefault)-import Distribution.Simple.Glob-import Distribution.Simple.Utils-import Distribution.Simple.Setup-import Distribution.Simple.PreProcess-import Distribution.Simple.BuildPaths-import Distribution.Simple.Program-import Distribution.Pretty-import Distribution.Verbosity--import qualified Data.Map as Map-import Data.Time (UTCTime, getCurrentTime, toGregorian, utctDay)-import System.Directory ( doesFileExist )-import System.IO (IOMode(WriteMode), hPutStrLn, withFile)-import System.FilePath ((</>), (<.>), dropExtension, isRelative)---- |Create a source distribution.-sdist :: PackageDescription -- ^ information from the tarball- -> SDistFlags -- ^ verbosity & snapshot- -> (FilePath -> FilePath) -- ^ build prefix (temp dir)- -> [PPSuffixHandler] -- ^ extra preprocessors (includes suffixes)- -> IO ()-sdist pkg flags mkTmpDir pps = do-- distPref <- findDistPrefOrDefault $ sDistDistPref flags- let targetPref = distPref- tmpTargetDir = mkTmpDir distPref-- -- When given --list-sources, just output the list of sources to a file.- case sDistListSources flags of- Flag path -> withFile path WriteMode $ \outHandle -> do- ordinary <- listPackageSources verbosity "." pkg pps- traverse_ (hPutStrLn outHandle) ordinary- notice verbosity $ "List of package sources written to file '" ++ path ++ "'"-- NoFlag -> do- -- do some QA- printPackageProblems verbosity pkg-- date <- getCurrentTime- let pkg' | snapshot = snapshotPackage date pkg- | otherwise = pkg-- case flagToMaybe (sDistDirectory flags) of- Just targetDir -> do- generateSourceDir targetDir pkg'- info verbosity $ "Source directory created: " ++ targetDir-- Nothing -> do- createDirectoryIfMissingVerbose verbosity True tmpTargetDir- withTempDirectory verbosity tmpTargetDir "sdist." $ \tmpDir -> do- let targetDir = tmpDir </> tarBallName pkg'- generateSourceDir targetDir pkg'- targzFile <- createArchive verbosity pkg' tmpDir targetPref- notice verbosity $ "Source tarball created: " ++ targzFile-- where- generateSourceDir :: FilePath -> PackageDescription -> IO ()- generateSourceDir targetDir pkg' = do- setupMessage verbosity "Building source dist for" (packageId pkg')- prepareTree verbosity pkg' targetDir pps- when snapshot $- overwriteSnapshotPackageDesc verbosity pkg' targetDir-- verbosity = fromFlag (sDistVerbosity flags)- snapshot = fromFlag (sDistSnapshot flags)---- | List all source files of a package.------ Since @Cabal-3.4@ returns a single list. There shouldn't be any--- executable files, they are hardly portable.--- -listPackageSources- :: Verbosity -- ^ verbosity- -> FilePath -- ^ directory with cabal file- -> PackageDescription -- ^ info from the cabal file- -> [PPSuffixHandler] -- ^ extra preprocessors (include suffixes)- -> IO [FilePath] -- ^ relative paths-listPackageSources verbosity cwd pkg_descr0 pps = do- -- Call helpers that actually do all work.- listPackageSources' verbosity die' cwd pkg_descr pps- where- pkg_descr = filterAutogenModules pkg_descr0---- | A variant of 'listPackageSources' with configurable 'die'.------ /Note:/ may still 'die' directly. For example on missing include file.------ Since @3.4.0.0-listPackageSourcesWithDie- :: Verbosity -- ^ verbosity- -> (Verbosity -> String -> IO [FilePath]) -- ^ 'die'' alternative- -> FilePath -- ^ directory with cabal file- -> PackageDescription -- ^ info from the cabal file- -> [PPSuffixHandler] -- ^ extra preprocessors (include suffixes)- -> IO [FilePath] -- ^ relative paths-listPackageSourcesWithDie verbosity rip cwd pkg_descr0 pps = do- -- Call helpers that actually do all work.- listPackageSources' verbosity rip cwd pkg_descr pps- where- pkg_descr = filterAutogenModules pkg_descr0---listPackageSources'- :: Verbosity- -> (Verbosity -> String -> IO [FilePath])- -> FilePath- -> PackageDescription- -> [PPSuffixHandler]- -> IO [FilePath]-listPackageSources' verbosity rip cwd pkg_descr pps =- fmap concat . sequenceA $- [- -- Library sources.- fmap concat- . withAllLib $ \Library {- exposedModules = modules,- signatures = sigs,- libBuildInfo = libBi- } ->- allSourcesBuildInfo verbosity rip cwd libBi pps (modules ++ sigs)-- -- Executables sources.- , fmap concat- . withAllExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do- biSrcs <- allSourcesBuildInfo verbosity rip cwd exeBi pps []- mainSrc <- findMainExeFile verbosity cwd exeBi pps mainPath- return (mainSrc:biSrcs)-- -- Foreign library sources- , fmap concat- . withAllFLib $ \flib@(ForeignLib { foreignLibBuildInfo = flibBi }) -> do- biSrcs <- allSourcesBuildInfo verbosity rip cwd flibBi pps []- defFiles <- traverse (findModDefFile verbosity cwd flibBi pps)- (foreignLibModDefFile flib)- return (defFiles ++ biSrcs)-- -- Test suites sources.- , fmap concat- . withAllTest $ \t -> do- let bi = testBuildInfo t- case testInterface t of- TestSuiteExeV10 _ mainPath -> do- biSrcs <- allSourcesBuildInfo verbosity rip cwd bi pps []- srcMainFile <- findMainExeFile verbosity cwd bi pps mainPath- return (srcMainFile:biSrcs)- TestSuiteLibV09 _ m ->- allSourcesBuildInfo verbosity rip cwd bi pps [m]- TestSuiteUnsupported tp ->- rip verbosity $ "Unsupported test suite type: " ++ show tp-- -- Benchmarks sources.- , fmap concat- . withAllBenchmark $ \bm -> do- let bi = benchmarkBuildInfo bm- case benchmarkInterface bm of- BenchmarkExeV10 _ mainPath -> do- biSrcs <- allSourcesBuildInfo verbosity rip cwd bi pps []- srcMainFile <- findMainExeFile verbosity cwd bi pps mainPath- return (srcMainFile:biSrcs)- BenchmarkUnsupported tp ->- rip verbosity $ "Unsupported benchmark type: " ++ show tp-- -- Data files.- , fmap concat- . for (dataFiles pkg_descr) $ \filename -> do- let srcDataDirRaw = dataDir pkg_descr- srcDataDir | null srcDataDirRaw = "."- | otherwise = srcDataDirRaw- matchDirFileGlob verbosity (specVersion pkg_descr) cwd (srcDataDir </> filename)-- -- Extra source files.- , fmap concat . for (extraSrcFiles pkg_descr) $ \fpath ->- matchDirFileGlob verbosity (specVersion pkg_descr) cwd fpath-- -- Extra doc files.- , fmap concat- . for (extraDocFiles pkg_descr) $ \ filename ->- matchDirFileGlob verbosity (specVersion pkg_descr) cwd filename-- -- License file(s).- , return (licenseFiles pkg_descr)-- -- Install-include files, without autogen-include files- , fmap concat- . withAllLib $ \ l -> do- let lbi = libBuildInfo l- incls = filter (`notElem` autogenIncludes lbi) (installIncludes lbi)- relincdirs = "." : filter isRelative (includeDirs lbi)- traverse (fmap snd . findIncludeFile verbosity cwd relincdirs) incls-- -- Setup script, if it exists.- , fmap (maybe [] (\f -> [f])) $ findSetupFile cwd-- -- The .cabal file itself.- , fmap (\d -> [d]) (tryFindPackageDescCwd verbosity cwd ".")-- ]- where- -- We have to deal with all libs and executables, so we have local- -- versions of these functions that ignore the 'buildable' attribute:- withAllLib action = traverse action (allLibraries pkg_descr)- withAllFLib action = traverse action (foreignLibs pkg_descr)- withAllExe action = traverse action (executables pkg_descr)- withAllTest action = traverse action (testSuites pkg_descr)- withAllBenchmark action = traverse action (benchmarks pkg_descr)----- |Prepare a directory tree of source files.-prepareTree :: Verbosity -- ^verbosity- -> PackageDescription -- ^info from the cabal file- -> FilePath -- ^source tree to populate- -> [PPSuffixHandler] -- ^extra preprocessors (includes suffixes)- -> IO ()-prepareTree verbosity pkg_descr0 targetDir pps = do- ordinary <- listPackageSources verbosity "." pkg_descr pps- installOrdinaryFiles verbosity targetDir (zip (repeat []) ordinary)- maybeCreateDefaultSetupScript targetDir- where- pkg_descr = filterAutogenModules pkg_descr0---- | Find the setup script file, if it exists.-findSetupFile :: FilePath -> IO (Maybe FilePath)-findSetupFile targetDir = do- hsExists <- doesFileExist (targetDir </> setupHs)- lhsExists <- doesFileExist (targetDir </> setupLhs)- if hsExists- then return (Just setupHs)- else if lhsExists- then return (Just setupLhs)- else return Nothing- where- setupHs = "Setup.hs"- setupLhs = "Setup.lhs"---- | Create a default setup script in the target directory, if it doesn't exist.-maybeCreateDefaultSetupScript :: FilePath -> IO ()-maybeCreateDefaultSetupScript targetDir = do- mSetupFile <- findSetupFile targetDir- case mSetupFile of- Just _setupFile -> return ()- Nothing -> do- writeUTF8File (targetDir </> "Setup.hs") $ unlines [- "import Distribution.Simple",- "main = defaultMain"]---- | Find the main executable file.-findMainExeFile- :: Verbosity- -> FilePath -- ^ cwd- -> BuildInfo- -> [PPSuffixHandler]- -> FilePath -- ^ main-is- -> IO FilePath-findMainExeFile verbosity cwd exeBi pps mainPath = do- ppFile <- findFileCwdWithExtension cwd (ppSuffixes pps) (hsSourceDirs exeBi)- (dropExtension mainPath)- case ppFile of- Nothing -> findFileCwd verbosity cwd (hsSourceDirs exeBi) mainPath- Just pp -> return pp---- | Find a module definition file------ TODO: I don't know if this is right-findModDefFile- :: Verbosity -> FilePath -> BuildInfo -> [PPSuffixHandler] -> FilePath -> IO FilePath-findModDefFile verbosity cwd flibBi _pps modDefPath =- findFileCwd verbosity cwd (".":hsSourceDirs flibBi) modDefPath---- | Given a list of include paths, try to find the include file named--- @f@. Return the name of the file and the full path, or exit with error if--- there's no such file.-findIncludeFile :: Verbosity -> FilePath -> [FilePath] -> String -> IO (String, FilePath)-findIncludeFile verbosity _ [] f = die' verbosity ("can't find include file " ++ f)-findIncludeFile verbosity cwd (d:ds) f = do- let path = (d </> f)- b <- doesFileExist (cwd </> path)- if b then return (f,path) else findIncludeFile verbosity cwd ds f---- | Remove the auto-generated modules (like 'Paths_*') from 'exposed-modules' --- and 'other-modules'.-filterAutogenModules :: PackageDescription -> PackageDescription-filterAutogenModules pkg_descr0 = mapLib filterAutogenModuleLib $- mapAllBuildInfo filterAutogenModuleBI pkg_descr0- where- mapLib f pkg = pkg { library = fmap f (library pkg)- , subLibraries = map f (subLibraries pkg) }- filterAutogenModuleLib lib = lib {- exposedModules = filter (filterFunction (libBuildInfo lib)) (exposedModules lib)- }- filterAutogenModuleBI bi = bi {- otherModules = filter (filterFunction bi) (otherModules bi)- }- pathsModule = autogenPathsModuleName pkg_descr0- filterFunction bi = \mn ->- mn /= pathsModule- && not (mn `elem` autogenModules bi)---- | Prepare a directory tree of source files for a snapshot version.--- It is expected that the appropriate snapshot version has already been set--- in the package description, eg using 'snapshotPackage' or 'snapshotVersion'.----prepareSnapshotTree- :: Verbosity -- ^verbosity- -> PackageDescription -- ^info from the cabal file- -> FilePath -- ^source tree to populate- -> [PPSuffixHandler] -- ^extra preprocessors (includes suffixes)- -> IO ()-prepareSnapshotTree verbosity pkg targetDir pps = do- prepareTree verbosity pkg targetDir pps- overwriteSnapshotPackageDesc verbosity pkg targetDir--overwriteSnapshotPackageDesc :: Verbosity -- ^verbosity- -> PackageDescription -- ^info from the cabal file- -> FilePath -- ^source tree- -> IO ()-overwriteSnapshotPackageDesc verbosity pkg targetDir = do- -- We could just writePackageDescription targetDescFile pkg_descr,- -- but that would lose comments and formatting.- descFile <- defaultPackageDesc verbosity- withUTF8FileContents descFile $- writeUTF8File (targetDir </> descFile)- . unlines . map (replaceVersion (packageVersion pkg)) . lines-- where- replaceVersion :: Version -> String -> String- replaceVersion version line- | "version:" `isPrefixOf` map toLower line- = "version: " ++ prettyShow version- | otherwise = line---- | Modifies a 'PackageDescription' by appending a snapshot number--- corresponding to the given date.----snapshotPackage :: UTCTime -> PackageDescription -> PackageDescription-snapshotPackage date pkg =- pkg {- package = pkgid { pkgVersion = snapshotVersion date (pkgVersion pkgid) }- }- where pkgid = packageId pkg---- | Modifies a 'Version' by appending a snapshot number corresponding--- to the given date.----snapshotVersion :: UTCTime -> Version -> Version-snapshotVersion date = alterVersion (++ [dateToSnapshotNumber date])---- | Given a date produce a corresponding integer representation.--- For example given a date @18/03/2008@ produce the number @20080318@.----dateToSnapshotNumber :: UTCTime -> Int-dateToSnapshotNumber date = case toGregorian (utctDay date) of- (year, month, day) ->- fromIntegral year * 10000- + month * 100- + day---- | Create an archive from a tree of source files, and clean up the tree.-createArchive- :: Verbosity -- ^ verbosity- -> PackageDescription -- ^ info from cabal file- -> FilePath -- ^ source tree to archive- -> FilePath -- ^ name of archive to create- -> IO FilePath-createArchive verbosity pkg_descr tmpDir targetPref = do- let tarBallFilePath = targetPref </> tarBallName pkg_descr <.> "tar.gz"- (tarProg, _) <- requireProgram verbosity tarProgram defaultProgramDb- let formatOptSupported = maybe False (== "YES") $- Map.lookup "Supports --format"- (programProperties tarProg)- runProgram verbosity tarProg $- -- Hmm: I could well be skating on thinner ice here by using the -C option- -- (=> seems to be supported at least by GNU and *BSD tar) [The- -- prev. solution used pipes and sub-command sequences to set up the paths- -- correctly, which is problematic in a Windows setting.]- ["-czf", tarBallFilePath, "-C", tmpDir]- ++ (if formatOptSupported then ["--format", "ustar"] else [])- ++ [tarBallName pkg_descr]- return tarBallFilePath---- | Given a buildinfo, return the names of all source files.-allSourcesBuildInfo- :: Verbosity- -> (Verbosity -> String -> IO [FilePath])- -> FilePath -- ^ cwd- -> BuildInfo- -> [PPSuffixHandler] -- ^ Extra preprocessors- -> [ModuleName] -- ^ Exposed modules- -> IO [FilePath]-allSourcesBuildInfo verbosity rip cwd bi pps modules = do- let searchDirs = hsSourceDirs bi- sources <- fmap concat $ sequenceA $- [ let file = ModuleName.toFilePath module_- -- NB: *Not* findFileWithExtension, because the same source- -- file may show up in multiple paths due to a conditional;- -- we need to package all of them. See #367.- in findAllFilesCwdWithExtension cwd suffixes searchDirs file- >>= nonEmpty (notFound module_) return- | module_ <- modules ++ otherModules bi ]- bootFiles <- sequenceA- [ let file = ModuleName.toFilePath module_- fileExts = ["hs-boot", "lhs-boot"]- in findFileCwdWithExtension cwd fileExts (hsSourceDirs bi) file- | module_ <- modules ++ otherModules bi ]-- return $ sources ++ catMaybes bootFiles ++ cSources bi ++ cxxSources bi ++- cmmSources bi ++ asmSources bi ++ jsSources bi-- where- nonEmpty x _ [] = x- nonEmpty _ f xs = f xs- suffixes = ppSuffixes pps ++ ["hs", "lhs", "hsig", "lhsig"]-- notFound :: ModuleName -> IO [FilePath]- notFound m = rip verbosity $ "Error: Could not find module: " ++ prettyShow m- ++ " with any suffix: " ++ show suffixes ++ ". If the module "- ++ "is autogenerated it should be added to 'autogen-modules'."----- | Note: must be called with the CWD set to the directory containing--- the '.cabal' file.-printPackageProblems :: Verbosity -> PackageDescription -> IO ()-printPackageProblems verbosity pkg_descr = do- ioChecks <- checkPackageFiles verbosity pkg_descr "."- let pureChecks = checkConfiguredPackage pkg_descr- isDistError (PackageDistSuspicious _) = False- isDistError (PackageDistSuspiciousWarn _) = False- isDistError _ = True- (errors, warnings) = partition isDistError (pureChecks ++ ioChecks)- unless (null errors) $- notice verbosity $ "Distribution quality errors:\n"- ++ unlines (map explanation errors)- unless (null warnings) $- notice verbosity $ "Distribution quality warnings:\n"- ++ unlines (map explanation warnings)- unless (null errors) $- notice verbosity- "Note: the public hackage server would reject this package."------------------------------------------------------------------ | The name of the tarball without extension----tarBallName :: PackageDescription -> String-tarBallName = prettyShow . packageId--mapAllBuildInfo :: (BuildInfo -> BuildInfo)- -> (PackageDescription -> PackageDescription)-mapAllBuildInfo f pkg = pkg {- library = fmap mapLibBi (library pkg),- subLibraries = fmap mapLibBi (subLibraries pkg),- foreignLibs = fmap mapFLibBi (foreignLibs pkg),- executables = fmap mapExeBi (executables pkg),- testSuites = fmap mapTestBi (testSuites pkg),- benchmarks = fmap mapBenchBi (benchmarks pkg)- }- where- mapLibBi lib = lib { libBuildInfo = f (libBuildInfo lib) }- mapFLibBi flib = flib { foreignLibBuildInfo = f (foreignLibBuildInfo flib) }- mapExeBi exe = exe { buildInfo = f (buildInfo exe) }- mapTestBi tst = tst { testBuildInfo = f (testBuildInfo tst) }- mapBenchBi bm = bm { benchmarkBuildInfo = f (benchmarkBuildInfo bm) }
− Distribution/Simple/Test.hs
@@ -1,136 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Test--- Copyright : Thomas Tuegel 2010--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This is the entry point into testing a built package. It performs the--- \"@.\/setup test@\" action. It runs test suites designated in the package--- description and reports on the results.--module Distribution.Simple.Test- ( test- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.UnqualComponentName-import qualified Distribution.PackageDescription as PD-import Distribution.Simple.Compiler-import Distribution.Simple.Hpc-import Distribution.Simple.InstallDirs-import qualified Distribution.Simple.LocalBuildInfo as LBI-import qualified Distribution.Types.LocalBuildInfo as LBI-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-import Distribution.TestSuite-import Distribution.Pretty--import System.Directory- ( createDirectoryIfMissing, doesFileExist, getDirectoryContents- , removeFile )-import System.FilePath ( (</>) )---- |Perform the \"@.\/setup test@\" action.-test :: Args -- ^positional command-line arguments- -> PD.PackageDescription -- ^information from the .cabal file- -> LBI.LocalBuildInfo -- ^information from the configure step- -> TestFlags -- ^flags sent to test- -> IO ()-test args pkg_descr lbi flags = do- let verbosity = fromFlag $ testVerbosity flags- machineTemplate = fromFlag $ testMachineLog flags- distPref = fromFlag $ testDistPref flags- testLogDir = distPref </> "test"- testNames = args- pkgTests = PD.testSuites pkg_descr- enabledTests = LBI.enabledTestLBIs pkg_descr lbi-- doTest :: ((PD.TestSuite, LBI.ComponentLocalBuildInfo),- Maybe TestSuiteLog) -> IO TestSuiteLog- doTest ((suite, clbi), _) =- case PD.testInterface suite of- PD.TestSuiteExeV10 _ _ ->- ExeV10.runTest pkg_descr lbi clbi flags suite-- PD.TestSuiteLibV09 _ _ ->- LibV09.runTest pkg_descr lbi clbi flags suite-- _ -> return TestSuiteLog- { testSuiteName = PD.testName suite- , testLogs = TestLog- { testName = unUnqualComponentName $ PD.testName suite- , testOptionsReturned = []- , testResult =- Error $ "No support for running test suite type: "- ++ show (pretty $ PD.testType suite)- }- , logFile = ""- }-- unless (PD.hasTests pkg_descr) $ do- notice verbosity "Package has no test suites."- exitSuccess-- when (PD.hasTests pkg_descr && null enabledTests) $- die' verbosity $- "No test suites enabled. Did you remember to configure with "- ++ "\'--enable-tests\'?"-- testsToRun <- case testNames of- [] -> return $ zip enabledTests $ repeat Nothing- names -> for names $ \tName ->- let testMap = zip enabledNames enabledTests- enabledNames = map (PD.testName . fst) enabledTests- allNames = map PD.testName pkgTests- tCompName = mkUnqualComponentName tName- in case lookup tCompName testMap of- Just t -> return (t, Nothing)- _ | tCompName `elem` allNames ->- die' verbosity $ "Package configured with test suite "- ++ tName ++ " disabled."- | otherwise -> die' verbosity $ "no such test: " ++ tName-- createDirectoryIfMissing True testLogDir-- -- Delete ordinary files from test log directory.- getDirectoryContents testLogDir- >>= filterM doesFileExist . map (testLogDir </>)- >>= traverse_ removeFile-- let totalSuites = length testsToRun- notice verbosity $ "Running " ++ show totalSuites ++ " test suites..."- suites <- traverse doTest testsToRun- let packageLog = (localPackageLog pkg_descr lbi) { testSuites = suites }- packageLogFile = (</>) testLogDir- $ packageLogPath machineTemplate pkg_descr lbi- allOk <- summarizePackage verbosity packageLog- writeFile packageLogFile $ show packageLog-- when (LBI.testCoverage lbi) $- markupPackage verbosity lbi distPref (prettyShow $ PD.package pkg_descr) $- map (fst . fst) testsToRun-- unless allOk exitFailure--packageLogPath :: PathTemplate- -> PD.PackageDescription- -> LBI.LocalBuildInfo- -> FilePath-packageLogPath template pkg_descr lbi =- fromPathTemplate $ substPathTemplate env template- where- env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.localUnitId lbi)- (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)
− Distribution/Simple/Test/ExeV10.hs
@@ -1,188 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--module Distribution.Simple.Test.ExeV10- ( runTest- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.UnqualComponentName-import Distribution.Compat.CreatePipe-import Distribution.Compat.Environment-import qualified Distribution.PackageDescription as PD-import Distribution.Simple.Build.PathsModule-import Distribution.Simple.BuildPaths-import Distribution.Simple.Compiler-import Distribution.Simple.Hpc-import Distribution.Simple.InstallDirs-import qualified Distribution.Simple.LocalBuildInfo as LBI-import qualified Distribution.Types.LocalBuildInfo as LBI-import Distribution.Simple.Setup-import Distribution.Simple.Test.Log-import Distribution.Simple.Utils-import Distribution.System-import Distribution.TestSuite-import Distribution.Pretty-import Distribution.Verbosity--import System.Directory- ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist- , getCurrentDirectory, removeDirectoryRecursive )-import System.FilePath ( (</>), (<.>) )-import System.IO ( stdout, stderr )--import qualified Data.ByteString.Lazy as LBS--runTest :: PD.PackageDescription- -> LBI.LocalBuildInfo- -> LBI.ComponentLocalBuildInfo- -> TestFlags- -> PD.TestSuite- -> IO TestSuiteLog-runTest pkg_descr lbi clbi flags suite = do- let isCoverageEnabled = LBI.testCoverage lbi- way = guessWay lbi- tixDir_ = tixDir distPref way testName'-- pwd <- getCurrentDirectory- existingEnv <- getEnvironment-- let cmd = LBI.buildDir lbi </> testName'- </> testName' <.> exeExtension (LBI.hostPlatform lbi)- -- Check that the test executable exists.- exists <- doesFileExist cmd- unless exists $ die' verbosity $ "Error: Could not find test program \"" ++ cmd- ++ "\". Did you build the package first?"-- -- Remove old .tix files if appropriate.- unless (fromFlag $ testKeepTix flags) $ do- exists' <- doesDirectoryExist tixDir_- when exists' $ removeDirectoryRecursive tixDir_-- -- Create directory for HPC files.- createDirectoryIfMissing True tixDir_-- -- Write summary notices indicating start of test suite- notice verbosity $ summarizeSuiteStart $ testName'--- -- Run the test executable- let opts = map (testOption pkg_descr lbi suite)- (testOptions flags)- dataDirPath = pwd </> PD.dataDir pkg_descr- tixFile = pwd </> tixFilePath distPref way (testName')- pkgPathEnv = (pkgPathEnvVar pkg_descr "datadir", dataDirPath)- : existingEnv- shellEnv = [("HPCTIXFILE", tixFile) | isCoverageEnabled] ++ pkgPathEnv-- -- Add (DY)LD_LIBRARY_PATH if needed- shellEnv' <- if LBI.withDynExe lbi- then do let (Platform _ os) = LBI.hostPlatform lbi- paths <- LBI.depLibraryPaths True False lbi clbi- return (addLibraryPath os paths shellEnv)- else return shellEnv-- -- Output logger- (wOut, wErr, getLogText) <- case details of- Direct -> return (stdout, stderr, return LBS.empty)- _ -> do- (rOut, wOut) <- createPipe-- return $ (,,) wOut wOut $ do- -- Read test executables' output- logText <- LBS.hGetContents rOut-- -- '--show-details=streaming': print the log output in another thread- when (details == Streaming) $ LBS.putStr logText-- -- drain the output.- evaluate (force logText)-- (exit, logText) <- case testWrapper flags of- Flag path -> rawSystemIOWithEnvAndAction- verbosity path (cmd:opts) Nothing (Just shellEnv')- getLogText- -- these handles are automatically closed- Nothing (Just wOut) (Just wErr)-- NoFlag -> rawSystemIOWithEnvAndAction- verbosity cmd opts Nothing (Just shellEnv')- getLogText- -- these handles are automatically closed- Nothing (Just wOut) (Just wErr)-- -- Generate TestSuiteLog from executable exit code and a machine-- -- readable test log.- let suiteLog = buildLog exit-- -- Write summary notice to log file indicating start of test suite- appendFile (logFile suiteLog) $ summarizeSuiteStart $ testName'-- -- Append contents of temporary log file to the final human-- -- readable log file- LBS.appendFile (logFile suiteLog) logText-- -- Write end-of-suite summary notice to log file- appendFile (logFile suiteLog) $ summarizeSuiteFinish suiteLog-- -- 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 == Always ||- details == Failures && not (suitePassed $ testLogs suiteLog))- -- verbosity overrides show-details- && verbosity >= normal- whenPrinting $ do- LBS.putStr logText- putChar '\n'-- -- Write summary notice to terminal indicating end of test suite- notice verbosity $ summarizeSuiteFinish suiteLog-- when isCoverageEnabled $- markupTest verbosity lbi distPref (prettyShow $ PD.package pkg_descr) suite-- return suiteLog- where- testName' = unUnqualComponentName $ PD.testName suite-- distPref = fromFlag $ testDistPref flags- verbosity = fromFlag $ testVerbosity flags- details = fromFlag $ testShowDetails flags- testLogDir = distPref </> "test"-- buildLog exit =- let r = case exit of- ExitSuccess -> Pass- ExitFailure c -> Fail $ "exit code: " ++ show c- --n = unUnqualComponentName $ PD.testName suite- l = TestLog- { testName = testName'- , testOptionsReturned = []- , testResult = r- }- in TestSuiteLog- { testSuiteName = PD.testName suite- , testLogs = l- , logFile =- testLogDir- </> testSuiteLogPath (fromFlag $ testHumanLog flags)- pkg_descr lbi testName' l- }---- TODO: This is abusing the notion of a 'PathTemplate'. The result isn't--- necessarily a path.-testOption :: PD.PackageDescription- -> LBI.LocalBuildInfo- -> PD.TestSuite- -> PathTemplate- -> String-testOption pkg_descr lbi suite template =- fromPathTemplate $ substPathTemplate env template- where- env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.localUnitId lbi)- (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++- [(TestSuiteNameVar, toPathTemplate $ unUnqualComponentName $ PD.testName suite)]
− Distribution/Simple/Test/LibV09.hs
@@ -1,287 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--module Distribution.Simple.Test.LibV09- ( runTest- -- Test stub- , simpleTestStub- , stubFilePath, stubMain, stubName, stubWriteLog- , writeSimpleTestStub- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Types.UnqualComponentName--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-import Distribution.Simple.BuildPaths-import Distribution.Simple.Compiler-import Distribution.Simple.Hpc-import Distribution.Simple.InstallDirs-import qualified Distribution.Simple.LocalBuildInfo as LBI-import qualified Distribution.Types.LocalBuildInfo as LBI-import Distribution.Simple.Setup-import Distribution.Simple.Test.Log-import Distribution.Simple.Utils-import Distribution.System-import Distribution.TestSuite-import Distribution.Pretty-import Distribution.Verbosity--import qualified Control.Exception as CE-import qualified Data.ByteString.Lazy as LBS-import System.Directory- ( createDirectoryIfMissing, canonicalizePath- , doesDirectoryExist, doesFileExist- , getCurrentDirectory, removeDirectoryRecursive, removeFile- , setCurrentDirectory )-import System.FilePath ( (</>), (<.>) )-import System.IO ( hClose, hPutStr )-import System.Process (StdStream(..), waitForProcess)--runTest :: PD.PackageDescription- -> LBI.LocalBuildInfo- -> LBI.ComponentLocalBuildInfo- -> TestFlags- -> PD.TestSuite- -> IO TestSuiteLog-runTest pkg_descr lbi clbi flags suite = do- let isCoverageEnabled = LBI.testCoverage lbi- way = guessWay lbi-- pwd <- getCurrentDirectory- existingEnv <- getEnvironment-- let cmd = LBI.buildDir lbi </> stubName suite- </> stubName suite <.> exeExtension (LBI.hostPlatform lbi)- -- Check that the test executable exists.- exists <- doesFileExist cmd- unless exists $- die' verbosity $ "Error: Could not find test program \"" ++ cmd- ++ "\". Did you build the package first?"-- -- Remove old .tix files if appropriate.- unless (fromFlag $ testKeepTix flags) $ do- let tDir = tixDir distPref way testName'- exists' <- doesDirectoryExist tDir- when exists' $ removeDirectoryRecursive tDir-- -- Create directory for HPC files.- createDirectoryIfMissing True $ tixDir distPref way testName'-- -- Write summary notices indicating start of test suite- notice verbosity $ summarizeSuiteStart testName'-- suiteLog <- CE.bracket openCabalTemp deleteIfExists $ \tempLog -> do-- -- TODO: this setup is broken,- -- if the test output is too big, we will deadlock.- (rOut, wOut) <- createPipe-- -- Run test executable- (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 testName'- pkgPathEnv = (pkgPathEnvVar pkg_descr "datadir", dataDirPath)- : existingEnv- shellEnv = [("HPCTIXFILE", tixFile) | isCoverageEnabled]- ++ pkgPathEnv- -- Add (DY)LD_LIBRARY_PATH if needed- shellEnv' <-- if LBI.withDynExe lbi- then do- let (Platform _ os) = LBI.hostPlatform lbi- paths <- LBI.depLibraryPaths True False lbi clbi- cpath <- canonicalizePath $ LBI.componentBuildDir lbi clbi- return (addLibraryPath os (cpath : paths) shellEnv)- else return shellEnv- case testWrapper flags of- Flag path -> createProcessWithEnv verbosity path (cmd:opts) Nothing (Just shellEnv')- -- these handles are closed automatically- CreatePipe (UseHandle wOut) (UseHandle wOut)-- NoFlag -> 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 <- LBS.hGetContents rOut- -- Force the IO manager to drain the test output pipe- _ <- evaluate (force logText)-- exitcode <- waitForProcess process- unless (exitcode == ExitSuccess) $ do- debug verbosity $ cmd ++ " returned " ++ show exitcode-- -- Generate final log file name- let finalLogName l = testLogDir- </> testSuiteLogPath- (fromFlag $ testHumanLog flags) pkg_descr lbi- (unUnqualComponentName $ testSuiteName l) (testLogs l)- -- Generate TestSuiteLog from executable exit code and a machine-- -- readable test log- suiteLog <- fmap (\s -> (\l -> l { logFile = finalLogName l })- . fromMaybe (error $ "panic! read @TestSuiteLog " ++ show s) $ readMaybe s) -- TODO: eradicateNoParse- $ readFile tempLog-- -- Write summary notice to log file indicating start of test suite- appendFile (logFile suiteLog) $ summarizeSuiteStart testName'-- LBS.appendFile (logFile suiteLog) logText-- -- Write end-of-suite summary notice to log file- appendFile (logFile suiteLog) $ summarizeSuiteFinish suiteLog-- -- Show the contents of the human-readable log file on the terminal- -- if there is a failure and/or detailed output is requested- let details = fromFlag $ testShowDetails flags- whenPrinting = when $ (details > Never)- && (not (suitePassed $ testLogs suiteLog) || details == Always)- && verbosity >= normal- whenPrinting $ do- LBS.putStr logText- putChar '\n'-- return suiteLog-- -- Write summary notice to terminal indicating end of test suite- notice verbosity $ summarizeSuiteFinish suiteLog-- when isCoverageEnabled $- markupTest verbosity lbi distPref (prettyShow $ PD.package pkg_descr) suite-- return suiteLog- where- testName' = unUnqualComponentName $ PD.testName suite-- deleteIfExists file = do- exists <- doesFileExist file- when exists $ removeFile file-- testLogDir = distPref </> "test"- openCabalTemp = do- (f, h) <- openTempFile testLogDir $ "cabal-test-" <.> "log"- hClose h >> return f-- distPref = fromFlag $ testDistPref flags- verbosity = fromFlag $ testVerbosity flags---- TODO: This is abusing the notion of a 'PathTemplate'. The result isn't--- necessarily a path.-testOption :: PD.PackageDescription- -> LBI.LocalBuildInfo- -> PD.TestSuite- -> PathTemplate- -> String-testOption pkg_descr lbi suite template =- fromPathTemplate $ substPathTemplate env template- where- env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.localUnitId lbi)- (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++- [(TestSuiteNameVar, toPathTemplate $ unUnqualComponentName $ PD.testName suite)]---- Test stub -------------- | The name of the stub executable associated with a library 'TestSuite'.-stubName :: PD.TestSuite -> FilePath-stubName t = unUnqualComponentName (PD.testName t) ++ "Stub"---- | The filename of the source file for the stub executable associated with a--- library 'TestSuite'.-stubFilePath :: PD.TestSuite -> FilePath-stubFilePath t = stubName t <.> "hs"---- | Write the source file for a library 'TestSuite' stub executable.-writeSimpleTestStub :: PD.TestSuite -- ^ library 'TestSuite' for which a stub- -- is being created- -> FilePath -- ^ path to directory where stub source- -- should be located- -> IO ()-writeSimpleTestStub t dir = do- createDirectoryIfMissing True dir- let filename = dir </> stubFilePath t- m = case PD.testInterface t of- PD.TestSuiteLibV09 _ m' -> m'- _ -> error "writeSimpleTestStub: invalid TestSuite passed"- writeFile filename $ simpleTestStub m---- | Source code for library test suite stub executable-simpleTestStub :: ModuleName -> String-simpleTestStub m = unlines- [ "module Main ( main ) where"- , "import Distribution.Simple.Test.LibV09 ( stubMain )"- , "import " ++ show (pretty m) ++ " ( tests )"- , "main :: IO ()"- , "main = stubMain tests"- ]---- | Main function for test stubs. Once, it was written directly into the stub,--- but minimizing the amount of code actually in the stub maximizes the number--- of detectable errors when Cabal is compiled.-stubMain :: IO [Test] -> IO ()-stubMain tests = do- (f, n) <- fmap (\s -> fromMaybe (error $ "panic! read " ++ show s) $ readMaybe s) getContents -- TODO: eradicateNoParse- dir <- getCurrentDirectory- results <- (tests >>= stubRunTests) `CE.catch` errHandler- setCurrentDirectory dir- stubWriteLog f n results- where- errHandler :: CE.SomeException -> IO TestLogs- errHandler e = case CE.fromException e of- Just CE.UserInterrupt -> CE.throwIO e- _ -> return $ TestLog { testName = "Cabal test suite exception",- testOptionsReturned = [],- testResult = Error $ show e }---- | The test runner used in library "TestSuite" stub executables. Runs a list--- of 'Test's. An executable calling this function is meant to be invoked as--- the child of a Cabal process during @.\/setup test@. A 'TestSuiteLog',--- provided by Cabal, is read from the standard input; it supplies the name of--- the test suite and the location of the machine-readable test suite log file.--- Human-readable log information is written to the standard output for capture--- by the calling Cabal process.-stubRunTests :: [Test] -> IO TestLogs-stubRunTests tests = do- logs <- traverse stubRunTests' tests- return $ GroupLogs "Default" logs- where- stubRunTests' (Test t) = do- l <- run t >>= finish- summarizeTest normal Always l- return l- where- finish (Finished result) =- return TestLog- { testName = name t- , testOptionsReturned = defaultOptions t- , testResult = result- }- finish (Progress _ next) = next >>= finish- stubRunTests' g@(Group {}) = do- logs <- traverse stubRunTests' $ groupTests g- return $ GroupLogs (groupName g) logs- stubRunTests' (ExtraOptions _ t) = stubRunTests' t- maybeDefaultOption opt =- maybe Nothing (\d -> Just (optionName opt, d)) $ optionDefault opt- defaultOptions testInst = mapMaybe maybeDefaultOption $ options testInst---- | From a test stub, write the 'TestSuiteLog' to temporary file for the calling--- Cabal process to read.-stubWriteLog :: FilePath -> UnqualComponentName -> TestLogs -> IO ()-stubWriteLog f n logs = do- let testLog = TestSuiteLog { testSuiteName = n, testLogs = logs, logFile = f }- writeFile (logFile testLog) $ show testLog- when (suiteError logs) $ exitWith $ ExitFailure 2- when (suiteFailed logs) $ exitWith $ ExitFailure 1- exitSuccess
− Distribution/Simple/Test/Log.hs
@@ -1,166 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--module Distribution.Simple.Test.Log- ( PackageLog(..)- , TestLogs(..)- , TestSuiteLog(..)- , countTestResults- , localPackageLog- , summarizePackage- , summarizeSuiteFinish, summarizeSuiteStart- , summarizeTest- , suiteError, suiteFailed, suitePassed- , testSuiteLogPath- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Package-import Distribution.Types.UnqualComponentName-import qualified Distribution.PackageDescription as PD-import Distribution.Simple.Compiler-import Distribution.Simple.InstallDirs-import qualified Distribution.Simple.LocalBuildInfo as LBI-import Distribution.Simple.Setup-import Distribution.Simple.Utils-import Distribution.System-import Distribution.TestSuite-import Distribution.Verbosity-import Distribution.Pretty--import qualified Prelude (foldl1)---- | Logs all test results for a package, broken down first by test suite and--- then by test case.-data PackageLog = PackageLog- { package :: PackageId- , compiler :: CompilerId- , platform :: Platform- , testSuites :: [TestSuiteLog]- }- deriving (Read, Show, Eq)---- | A 'PackageLog' with package and platform information specified.-localPackageLog :: PD.PackageDescription -> LBI.LocalBuildInfo -> PackageLog-localPackageLog pkg_descr lbi = PackageLog- { package = PD.package pkg_descr- , compiler = compilerId $ LBI.compiler lbi- , platform = LBI.hostPlatform lbi- , testSuites = []- }---- | Logs test suite results, itemized by test case.-data TestSuiteLog = TestSuiteLog- { testSuiteName :: UnqualComponentName- , testLogs :: TestLogs- , logFile :: FilePath -- path to human-readable log file- }- deriving (Read, Show, Eq)--data TestLogs- = TestLog- { testName :: String- , testOptionsReturned :: Options- , testResult :: Result- }- | GroupLogs String [TestLogs]- deriving (Read, Show, Eq)---- | Count the number of pass, fail, and error test results in a 'TestLogs'--- tree.-countTestResults :: TestLogs- -> (Int, Int, Int) -- ^ Passes, fails, and errors,- -- respectively.-countTestResults = go (0, 0, 0)- where- go (p, f, e) (TestLog { testResult = r }) =- case r of- Pass -> (p + 1, f, e)- Fail _ -> (p, f + 1, e)- Error _ -> (p, f, e + 1)- go (p, f, e) (GroupLogs _ ts) = foldl go (p, f, e) ts---- | From a 'TestSuiteLog', determine if the test suite passed.-suitePassed :: TestLogs -> Bool-suitePassed l =- case countTestResults l of- (_, 0, 0) -> True- _ -> False---- | From a 'TestSuiteLog', determine if the test suite failed.-suiteFailed :: TestLogs -> Bool-suiteFailed l =- case countTestResults l of- (_, 0, _) -> False- _ -> True---- | From a 'TestSuiteLog', determine if the test suite encountered errors.-suiteError :: TestLogs -> Bool-suiteError l =- case countTestResults l of- (_, _, 0) -> False- _ -> True--resultString :: TestLogs -> String-resultString l | suiteError l = "error"- | suiteFailed l = "fail"- | otherwise = "pass"--testSuiteLogPath :: PathTemplate- -> PD.PackageDescription- -> LBI.LocalBuildInfo- -> String -- ^ test suite name- -> TestLogs -- ^ test suite results- -> FilePath-testSuiteLogPath template pkg_descr lbi test_name result =- fromPathTemplate $ substPathTemplate env template- where- env = initialPathTemplateEnv- (PD.package pkg_descr) (LBI.localUnitId lbi)- (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)- ++ [ (TestSuiteNameVar, toPathTemplate test_name)- , (TestSuiteResultVar, toPathTemplate $ resultString result)- ]---- | Print a summary to the console after all test suites have been run--- indicating the number of successful test suites and cases. Returns 'True' if--- all test suites passed and 'False' otherwise.-summarizePackage :: Verbosity -> PackageLog -> IO Bool-summarizePackage verbosity packageLog = do- let counts = map (countTestResults . testLogs) $ testSuites packageLog- (passed, failed, errors) = Prelude.foldl1 addTriple counts- totalCases = passed + failed + errors- passedSuites = length- $ filter (suitePassed . testLogs)- $ testSuites packageLog- totalSuites = length $ testSuites packageLog- notice verbosity $ show passedSuites ++ " of " ++ show totalSuites- ++ " test suites (" ++ show passed ++ " of "- ++ show totalCases ++ " test cases) passed."- return $! passedSuites == totalSuites- where- addTriple (p1, f1, e1) (p2, f2, e2) = (p1 + p2, f1 + f2, e1 + e2)---- | Print a summary of a single test case's result to the console, suppressing--- output for certain verbosity or test filter levels.-summarizeTest :: Verbosity -> TestShowDetails -> TestLogs -> IO ()-summarizeTest _ _ (GroupLogs {}) = return ()-summarizeTest verbosity details t =- when shouldPrint $ notice verbosity $ "Test case " ++ testName t- ++ ": " ++ show (testResult t)- where shouldPrint = (details > Never) && (notPassed || details == Always)- notPassed = testResult t /= Pass---- | Print a summary of the test suite's results on the console, suppressing--- output for certain verbosity or test filter levels.-summarizeSuiteFinish :: TestSuiteLog -> String-summarizeSuiteFinish testLog = unlines- [ "Test suite " ++ prettyShow (testSuiteName testLog) ++ ": " ++ resStr- , "Test suite logged to: " ++ logFile testLog- ]- where resStr = map toUpper (resultString $ testLogs testLog)--summarizeSuiteStart :: String -> String-summarizeSuiteStart n = "Test suite " ++ n ++ ": RUNNING...\n"
− Distribution/Simple/UHC.hs
@@ -1,295 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.UHC--- Copyright : Andres Loeh 2009--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module contains most of the UHC-specific code for configuring, building--- and installing packages.------ Thanks to the authors of the other implementation-specific files, in--- particular to Isaac Jones, Duncan Coutts and Henning Thielemann, for--- inspiration on how to design this module.--module Distribution.Simple.UHC (- configure, getInstalledPackages,- buildLib, buildExe, installLib, registerPackage, inplacePackageDbPath- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.InstalledPackageInfo-import Distribution.Package hiding (installedUnitId)-import Distribution.PackageDescription-import Distribution.Simple.BuildPaths-import Distribution.Simple.Compiler-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.PackageIndex-import Distribution.Simple.Program-import Distribution.Simple.Utils-import Distribution.Pretty-import Distribution.Parsec-import Distribution.Types.MungedPackageId-import Distribution.Verbosity-import Distribution.Version-import Distribution.System-import Language.Haskell.Extension--import qualified Data.Map as Map ( empty )-import System.Directory-import System.FilePath---- -------------------------------------------------------------------------------- Configuring--configure :: Verbosity -> Maybe FilePath -> Maybe FilePath- -> ProgramDb -> IO (Compiler, Maybe Platform, ProgramDb)-configure verbosity hcPath _hcPkgPath progdb = do-- (_uhcProg, uhcVersion, progdb') <-- requireProgramVersion verbosity uhcProgram- (orLaterVersion (mkVersion [1,0,2]))- (userMaybeSpecifyPath "uhc" hcPath progdb)-- let comp = Compiler {- compilerId = CompilerId UHC uhcVersion,- compilerAbiTag = NoAbiTag,- compilerCompat = [],- compilerLanguages = uhcLanguages,- compilerExtensions = uhcLanguageExtensions,- compilerProperties = Map.empty- }- compPlatform = Nothing- return (comp, compPlatform, progdb')--uhcLanguages :: [(Language, CompilerFlag)]-uhcLanguages = [(Haskell98, "")]---- | The flags for the supported extensions.-uhcLanguageExtensions :: [(Extension, Maybe CompilerFlag)]-uhcLanguageExtensions =- let doFlag (f, (enable, disable)) = [(EnableExtension f, enable),- (DisableExtension f, disable)]- alwaysOn = (Nothing, Nothing{- wrong -})- in concatMap doFlag- [(CPP, (Just "--cpp", Nothing{- wrong -})),- (PolymorphicComponents, alwaysOn),- (ExistentialQuantification, alwaysOn),- (ForeignFunctionInterface, alwaysOn),- (UndecidableInstances, alwaysOn),- (MultiParamTypeClasses, alwaysOn),- (Rank2Types, alwaysOn),- (PatternSignatures, alwaysOn),- (EmptyDataDecls, alwaysOn),- (ImplicitPrelude, (Nothing, Just "--no-prelude"{- wrong -})),- (TypeOperators, alwaysOn),- (OverlappingInstances, alwaysOn),- (FlexibleInstances, alwaysOn)]--getInstalledPackages :: Verbosity -> Compiler -> PackageDBStack -> ProgramDb- -> IO InstalledPackageIndex-getInstalledPackages verbosity comp packagedbs progdb = do- let compilerid = compilerId comp- systemPkgDir <- getGlobalPackageDir verbosity progdb- userPkgDir <- getUserPackageDir- let pkgDirs = nub (concatMap (packageDbPaths userPkgDir systemPkgDir) packagedbs)- -- putStrLn $ "pkgdirs: " ++ show pkgDirs- pkgs <- liftM (map addBuiltinVersions . concat) $- traverse (\ d -> getDirectoryContents d >>= filterM (isPkgDir (prettyShow compilerid) d))- pkgDirs- -- putStrLn $ "pkgs: " ++ show pkgs- let iPkgs =- map mkInstalledPackageInfo $- concatMap parsePackage $- pkgs- -- putStrLn $ "installed pkgs: " ++ show iPkgs- return (fromList iPkgs)--getGlobalPackageDir :: Verbosity -> ProgramDb -> IO FilePath-getGlobalPackageDir verbosity progdb = do- output <- getDbProgramOutput verbosity- uhcProgram progdb ["--meta-pkgdir-system"]- -- we need to trim because pkgdir contains an extra newline at the end- let pkgdir = trimEnd output- return pkgdir- where- trimEnd = reverse . dropWhile isSpace . reverse--getUserPackageDir :: IO FilePath-getUserPackageDir = do- homeDir <- getHomeDirectory- return $ homeDir </> ".cabal" </> "lib" -- TODO: determine in some other way--packageDbPaths :: FilePath -> FilePath -> PackageDB -> [FilePath]-packageDbPaths user system db =- case db of- GlobalPackageDB -> [ system ]- UserPackageDB -> [ user ]- SpecificPackageDB path -> [ path ]---- | Hack to add version numbers to UHC-built-in packages. This should sooner or--- later be fixed on the UHC side.-addBuiltinVersions :: String -> String-{--addBuiltinVersions "uhcbase" = "uhcbase-1.0"-addBuiltinVersions "base" = "base-3.0"-addBuiltinVersions "array" = "array-0.2"--}-addBuiltinVersions xs = xs---- | Name of the installed package config file.-installedPkgConfig :: String-installedPkgConfig = "installed-pkg-config"---- | Check if a certain dir contains a valid package. Currently, we are--- looking only for the presence of an installed package configuration.--- TODO: Actually make use of the information provided in the file.-isPkgDir :: String -> String -> String -> IO Bool-isPkgDir _ _ ('.' : _) = return False -- ignore files starting with a .-isPkgDir c dir xs = do- let candidate = dir </> uhcPackageDir xs c- -- putStrLn $ "trying: " ++ candidate- doesFileExist (candidate </> installedPkgConfig)--parsePackage :: String -> [PackageId]-parsePackage = toList . simpleParsec---- | Create a trivial package info from a directory name.-mkInstalledPackageInfo :: PackageId -> InstalledPackageInfo-mkInstalledPackageInfo p = emptyInstalledPackageInfo- { installedUnitId = mkLegacyUnitId p,- sourcePackageId = p }----- -------------------------------------------------------------------------------- Building--buildLib :: Verbosity -> PackageDescription -> LocalBuildInfo- -> Library -> ComponentLocalBuildInfo -> IO ()-buildLib verbosity pkg_descr lbi lib clbi = do-- systemPkgDir <- getGlobalPackageDir verbosity (withPrograms lbi)- userPkgDir <- getUserPackageDir- let runUhcProg = runDbProgram verbosity uhcProgram (withPrograms lbi)- let uhcArgs = -- set package name- ["--pkg-build=" ++ prettyShow (packageId pkg_descr)]- -- common flags lib/exe- ++ constructUHCCmdLine userPkgDir systemPkgDir- lbi (libBuildInfo lib) clbi- (buildDir lbi) verbosity- -- source files- -- suboptimal: UHC does not understand module names, so- -- we replace periods by path separators- ++ map (map (\ c -> if c == '.' then pathSeparator else c))- (map prettyShow (allLibModules lib clbi))-- runUhcProg uhcArgs-- return ()--buildExe :: Verbosity -> PackageDescription -> LocalBuildInfo- -> Executable -> ComponentLocalBuildInfo -> IO ()-buildExe verbosity _pkg_descr lbi exe clbi = do- systemPkgDir <- getGlobalPackageDir verbosity (withPrograms lbi)- userPkgDir <- getUserPackageDir- let runUhcProg = runDbProgram verbosity uhcProgram (withPrograms lbi)- let uhcArgs = -- common flags lib/exe- constructUHCCmdLine userPkgDir systemPkgDir- lbi (buildInfo exe) clbi- (buildDir lbi) verbosity- -- output file- ++ ["--output", buildDir lbi </> prettyShow (exeName exe)]- -- main source module- ++ [modulePath exe]- runUhcProg uhcArgs--constructUHCCmdLine :: FilePath -> FilePath- -> LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo- -> FilePath -> Verbosity -> [String]-constructUHCCmdLine user system lbi bi clbi odir verbosity =- -- verbosity- (if verbosity >= deafening then ["-v4"]- else if verbosity >= normal then []- else ["-v0"])- ++ hcOptions UHC bi- -- flags for language extensions- ++ languageToFlags (compiler lbi) (defaultLanguage bi)- ++ extensionsToFlags (compiler lbi) (usedExtensions bi)- -- packages- ++ ["--hide-all-packages"]- ++ uhcPackageDbOptions user system (withPackageDB lbi)- ++ ["--package=uhcbase"]- ++ ["--package=" ++ prettyShow (mungedName pkgid) | (_, pkgid) <- componentPackageDeps clbi ]- -- search paths- ++ ["-i" ++ odir]- ++ ["-i" ++ l | l <- nub (hsSourceDirs bi)]- ++ ["-i" ++ autogenComponentModulesDir lbi clbi]- ++ ["-i" ++ autogenPackageModulesDir lbi]- -- cpp options- ++ ["--optP=" ++ opt | opt <- cppOptions bi]- -- output path- ++ ["--odir=" ++ odir]- -- optimization- ++ (case withOptimization lbi of- NoOptimisation -> ["-O0"]- NormalOptimisation -> ["-O1"]- MaximumOptimisation -> ["-O2"])--uhcPackageDbOptions :: FilePath -> FilePath -> PackageDBStack -> [String]-uhcPackageDbOptions user system db = map (\ x -> "--pkg-searchpath=" ++ x)- (concatMap (packageDbPaths user system) db)---- -------------------------------------------------------------------------------- Installation--installLib :: Verbosity -> LocalBuildInfo- -> FilePath -> FilePath -> FilePath- -> PackageDescription -> Library -> ComponentLocalBuildInfo -> IO ()-installLib verbosity _lbi targetDir _dynlibTargetDir builtDir pkg _library _clbi = do- -- putStrLn $ "dest: " ++ targetDir- -- putStrLn $ "built: " ++ builtDir- installDirectoryContents verbosity (builtDir </> prettyShow (packageId pkg)) targetDir---- currently hard-coded UHC code generator and variant to use-uhcTarget, uhcTargetVariant :: String-uhcTarget = "bc"-uhcTargetVariant = "plain"---- root directory for a package in UHC-uhcPackageDir :: String -> String -> FilePath-uhcPackageSubDir :: String -> FilePath-uhcPackageDir pkgid compilerid = pkgid </> uhcPackageSubDir compilerid-uhcPackageSubDir compilerid = compilerid </> uhcTarget </> uhcTargetVariant---- -------------------------------------------------------------------------------- Registering--registerPackage- :: Verbosity- -> Compiler- -> ProgramDb- -> PackageDBStack- -> InstalledPackageInfo- -> IO ()-registerPackage verbosity comp progdb packageDbs installedPkgInfo = do- dbdir <- case registrationPackageDB packageDbs of- GlobalPackageDB -> getGlobalPackageDir verbosity progdb- UserPackageDB -> getUserPackageDir- SpecificPackageDB dir -> return dir- let pkgdir = dbdir </> uhcPackageDir (prettyShow pkgid) (prettyShow compilerid)- createDirectoryIfMissingVerbose verbosity True pkgdir- writeUTF8File (pkgdir </> installedPkgConfig)- (showInstalledPackageInfo installedPkgInfo)- where- pkgid = sourcePackageId installedPkgInfo- compilerid = compilerId comp--inplacePackageDbPath :: LocalBuildInfo -> FilePath-inplacePackageDbPath lbi = buildDir lbi
− Distribution/Simple/UserHooks.hs
@@ -1,207 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.UserHooks--- Copyright : Isaac Jones 2003-2005--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This defines the API that @Setup.hs@ scripts can use to customise the way--- the build works. This module just defines the 'UserHooks' type. The--- predefined sets of hooks that implement the @Simple@, @Make@ and @Configure@--- build systems are defined in "Distribution.Simple". The 'UserHooks' is a big--- record of functions. There are 3 for each action, a pre, post and the action--- itself. There are few other miscellaneous hooks, ones to extend the set of--- programs and preprocessors and one to override the function used to read the--- @.cabal@ file.------ This hooks type is widely agreed to not be the right solution. Partly this--- is because changes to it usually break custom @Setup.hs@ files and yet many--- internal code changes do require changes to the hooks. For example we cannot--- pass any extra parameters to most of the functions that implement the--- various phases because it would involve changing the types of the--- corresponding hook. At some point it will have to be replaced.--module Distribution.Simple.UserHooks (- UserHooks(..), Args,- emptyUserHooks,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.PackageDescription-import Distribution.Simple.Program-import Distribution.Simple.Command-import Distribution.Simple.PreProcess-import Distribution.Simple.Setup-import Distribution.Simple.LocalBuildInfo--type Args = [String]---- | Hooks allow authors to add specific functionality before and after a--- command is run, and also to specify additional preprocessors.------ * WARNING: The hooks interface is under rather constant flux as we try to--- understand users needs. Setup files that depend on this interface may--- break in future releases.-data UserHooks = UserHooks {-- -- | Read the description file- readDesc :: IO (Maybe GenericPackageDescription),- -- | Custom preprocessors in addition to and overriding 'knownSuffixHandlers'.- hookedPreProcessors :: [ PPSuffixHandler ],- -- | These programs are detected at configure time. Arguments for them are- -- added to the configure command.- hookedPrograms :: [Program],-- -- |Hook to run before configure command- preConf :: Args -> ConfigFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during configure.- confHook :: (GenericPackageDescription, HookedBuildInfo)- -> ConfigFlags -> IO LocalBuildInfo,- -- |Hook to run after configure command- postConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before build command. Second arg indicates verbosity level.- preBuild :: Args -> BuildFlags -> IO HookedBuildInfo,-- -- |Over-ride this hook to get different behavior during build.- buildHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO (),- -- |Hook to run after build command. Second arg indicates verbosity level.- postBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before repl command. Second arg indicates verbosity level.- preRepl :: Args -> ReplFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during interpretation.- replHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO (),- -- |Hook to run after repl command. Second arg indicates verbosity level.- postRepl :: Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before clean command. Second arg indicates verbosity level.- preClean :: Args -> CleanFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during clean.- cleanHook :: PackageDescription -> () -> UserHooks -> CleanFlags -> IO (),- -- |Hook to run after clean command. Second arg indicates verbosity level.- postClean :: Args -> CleanFlags -> PackageDescription -> () -> IO (),-- -- |Hook to run before copy command- preCopy :: Args -> CopyFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during copy.- copyHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO (),- -- |Hook to run after copy command- postCopy :: Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before install command- preInst :: Args -> InstallFlags -> IO HookedBuildInfo,-- -- |Over-ride this hook to get different behavior during install.- instHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO (),- -- |Hook to run after install command. postInst should be run- -- on the target, not on the build machine.- postInst :: Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before register command- preReg :: Args -> RegisterFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during registration.- regHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO (),- -- |Hook to run after register command- postReg :: Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before unregister command- preUnreg :: Args -> RegisterFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during unregistration.- unregHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO (),- -- |Hook to run after unregister command- postUnreg :: Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before hscolour command. Second arg indicates verbosity level.- preHscolour :: Args -> HscolourFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during hscolour.- hscolourHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO (),- -- |Hook to run after hscolour command. Second arg indicates verbosity level.- postHscolour :: Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before doctest command. Second arg indicates verbosity level.- preDoctest :: Args -> DoctestFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during doctest.- doctestHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> DoctestFlags -> IO (),- -- |Hook to run after doctest command. Second arg indicates verbosity level.- postDoctest :: Args -> DoctestFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before haddock command. Second arg indicates verbosity level.- preHaddock :: Args -> HaddockFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during haddock.- haddockHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO (),- -- |Hook to run after haddock command. Second arg indicates verbosity level.- postHaddock :: Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before test command.- preTest :: Args -> TestFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during test.- testHook :: Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO (),- -- |Hook to run after test command.- postTest :: Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO (),-- -- |Hook to run before bench command.- preBench :: Args -> BenchmarkFlags -> IO HookedBuildInfo,- -- |Over-ride this hook to get different behavior during bench.- benchHook :: Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO (),- -- |Hook to run after bench command.- postBench :: Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()- }---- |Empty 'UserHooks' which do nothing.-emptyUserHooks :: UserHooks-emptyUserHooks- = UserHooks {- readDesc = return Nothing,- hookedPreProcessors = [],- hookedPrograms = [],- preConf = rn',- confHook = (\_ _ -> return (error "No local build info generated during configure. Over-ride empty configure hook.")),- postConf = ru,- preBuild = rn',- buildHook = ru,- postBuild = ru,- preRepl = \_ _ -> return emptyHookedBuildInfo,- replHook = \_ _ _ _ _ -> return (),- postRepl = ru,- preClean = rn,- cleanHook = ru,- postClean = ru,- preCopy = rn',- copyHook = ru,- postCopy = ru,- preInst = rn,- instHook = ru,- postInst = ru,- preReg = rn',- regHook = ru,- postReg = ru,- preUnreg = rn,- unregHook = ru,- postUnreg = ru,- preHscolour = rn,- hscolourHook = ru,- postHscolour = ru,- preDoctest = rn,- doctestHook = ru,- postDoctest = ru,- preHaddock = rn',- haddockHook = ru,- postHaddock = ru,- preTest = rn',- testHook = \_ -> ru,- postTest = ru,- preBench = rn',- benchHook = \_ -> ru,- postBench = ru- }- where rn args _ = noExtraFlags args >> return emptyHookedBuildInfo- rn' _ _ = return emptyHookedBuildInfo- ru _ _ _ _ = return ()
− Distribution/Simple/Utils.hs
@@ -1,1609 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE BangPatterns #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Utils--- Copyright : Isaac Jones, Simon Marlow 2003-2004--- License : BSD3--- portions Copyright (c) 2007, Galois Inc.------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ A large and somewhat miscellaneous collection of utility functions used--- throughout the rest of the Cabal lib and in other tools that use the Cabal--- lib like @cabal-install@. It has a very simple set of logging actions. It--- has low level functions for running programs, a bunch of wrappers for--- various directory and file functions that do extra logging.--module Distribution.Simple.Utils (- cabalVersion,-- -- * logging and errors- dieNoVerbosity,- die', dieWithLocation',- dieNoWrap,- topHandler, topHandlerWith,- warn,- notice, noticeNoWrap, noticeDoc,- setupMessage,- info, infoNoWrap,- debug, debugNoWrap,- chattyTry,- annotateIO,- printRawCommandAndArgs, printRawCommandAndArgsAndEnv,- withOutputMarker,-- -- * exceptions- handleDoesNotExist,-- -- * running programs- rawSystemExit,- rawSystemExitCode,- rawSystemExitWithEnv,- rawSystemStdout,- rawSystemStdInOut,- rawSystemIOWithEnv,- rawSystemIOWithEnvAndAction,- createProcessWithEnv,- maybeExit,- xargs,- findProgramVersion,-- -- ** 'IOData' re-export- --- -- These types are re-exported from- -- "Distribution.Utils.IOData" for convience as they're- -- exposed in the API of 'rawSystemStdInOut'- IOData(..),- KnownIODataMode (..),- IODataMode (..),-- -- * copying files- createDirectoryIfMissingVerbose,- copyFileVerbose,- copyFiles,- copyFileTo,-- -- * installing files- installOrdinaryFile,- installExecutableFile,- installMaybeExecutableFile,- installOrdinaryFiles,- installExecutableFiles,- installMaybeExecutableFiles,- installDirectoryContents,- copyDirectoryRecursive,-- -- * File permissions- doesExecutableExist,- setFileOrdinary,- setFileExecutable,-- -- * file names- currentDir,- shortRelativePath,- dropExeExtension,- exeExtensions,-- -- * finding files- findFileEx,- findFileCwd,- findFirstFile,- findFileWithExtension,- findFileCwdWithExtension,- findFileWithExtension',- findAllFilesWithExtension,- findAllFilesCwdWithExtension,- findModuleFileEx,- findModuleFilesEx,- getDirectoryContentsRecursive,-- -- * environment variables- isInSearchPath,- addLibraryPath,-- -- * modification time- moreRecentFile,- existsAndIsMoreRecentThan,-- -- * temp files and dirs- TempFileOptions(..), defaultTempFileOptions,- withTempFile, withTempFileEx,- withTempDirectory, withTempDirectoryEx,- createTempDirectory,-- -- * .cabal and .buildinfo files- defaultPackageDesc,- findPackageDesc,- findPackageDescCwd,- tryFindPackageDesc,- tryFindPackageDescCwd,- findHookedPackageDesc,-- -- * reading and writing files safely- withFileContents,- writeFileAtomic,- rewriteFileEx,- rewriteFileLBS,-- -- * Unicode- fromUTF8BS,- fromUTF8LBS,- toUTF8BS,- toUTF8LBS,- readUTF8File,- withUTF8FileContents,- writeUTF8File,- normaliseLineEndings,-- -- * BOM- ignoreBOM,-- -- * generic utils- dropWhileEndLE,- takeWhileEndLE,- equating,- comparing,- isInfixOf,- intercalate,- lowercase,- listUnion,- listUnionRight,- ordNub,- ordNubBy,- ordNubRight,- safeHead,- safeTail,- safeLast,- safeInit,- unintersperse,- wrapText,- wrapLine,-- -- * FilePath stuff- isAbsoluteOnAnyPlatform,- isRelativeOnAnyPlatform,-- -- * Deprecated functions- findFile,- findModuleFile,- findModuleFiles,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Utils.Generic-import Distribution.Utils.IOData (IOData(..), IODataMode (..), KnownIODataMode (..))-import qualified Distribution.Utils.IOData as IOData-import Distribution.ModuleName as ModuleName-import Distribution.System-import Distribution.Version-import Distribution.Compat.Async-import Distribution.Compat.CopyFile-import Distribution.Compat.Internal.TempFile-import Distribution.Compat.FilePath as FilePath-import Distribution.Compat.Stack-import Distribution.Verbosity-import Distribution.Types.PackageId--#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 Distribution.Pretty-import Distribution.Parsec--import Data.Typeable- ( cast )-import qualified Data.ByteString.Lazy as BS--import System.Directory- ( Permissions(executable), getDirectoryContents, getPermissions- , doesDirectoryExist, doesFileExist, removeFile- , getModificationTime, createDirectory, removeDirectoryRecursive )-import System.Environment- ( getProgName )-import System.FilePath as FilePath- ( normalise, (</>), (<.>)- , getSearchPath, joinPath, takeDirectory, splitExtension- , splitDirectories, searchPathSeparator )-import System.IO- ( Handle, hSetBinaryMode, hGetContents, stderr, stdout, hPutStr, hFlush- , hClose, hSetBuffering, BufferMode(..), hPutStrLn )-import System.IO.Error-import System.IO.Unsafe- ( unsafeInterleaveIO )-import qualified Control.Exception as Exception--import Foreign.C.Error (Errno (..), ePIPE)-import Data.Time.Clock.POSIX (getPOSIXTime, POSIXTime)-import Numeric (showFFloat)-import Distribution.Compat.Process (createProcess, rawSystem, runInteractiveProcess)-import System.Process- ( ProcessHandle- , showCommandForUser, waitForProcess)-import qualified System.Process as Process-import qualified GHC.IO.Exception as GHC--import qualified Text.PrettyPrint as Disp---- We only get our own version number when we're building with ourselves-cabalVersion :: Version-#if defined(BOOTSTRAPPED_CABAL)-cabalVersion = mkVersion' Paths_Cabal.version-#elif defined(CABAL_VERSION)-cabalVersion = mkVersion [CABAL_VERSION]-#else-cabalVersion = mkVersion [3,0] --used when bootstrapping-#endif---- ------------------------------------------------------------------------------- Exception and logging utils---- Cabal's logging infrastructure has a few constraints:------ * We must make all logging formatting and emissions decisions based--- on the 'Verbosity' parameter, which is the only parameter that is--- plumbed to enough call-sites to actually be used for this matter.--- (One of Cabal's "big mistakes" is to have never have defined a--- monad of its own.)------ * When we 'die', we must raise an IOError. This a backwards--- compatibility consideration, because that's what we've raised--- previously, and if we change to any other exception type,--- exception handlers which match on IOError will no longer work.--- One case where it is known we rely on IOError being catchable--- is 'readPkgConfigDb' in cabal-install; there may be other--- user code that also assumes this.------ * The 'topHandler' does not know what 'Verbosity' is, because--- it gets called before we've done command line parsing (where--- the 'Verbosity' parameter would come from).------ This leads to two big architectural choices:------ * Although naively we might imagine 'Verbosity' to be a simple--- enumeration type, actually it is a full-on abstract data type--- that may contain arbitrarily complex information. At the--- moment, it is fully representable as a string, but we might--- eventually also use verbosity to let users register their--- own logging handler.------ * When we call 'die', we perform all the formatting and addition--- of extra information we need, and then ship this in the IOError--- to the top-level handler. Here are alternate designs that--- don't work:------ a) Ship the unformatted info to the handler. This doesn't--- work because at the point the handler gets the message,--- we've lost call stacks, and even if we did, we don't have access--- to 'Verbosity' to decide whether or not to render it.------ b) Print the information at the 'die' site, then raise an--- error. This means that if the exception is subsequently--- caught by a handler, we will still have emitted the output,--- which is not the correct behavior.------ For the top-level handler to "know" that an error message--- contains one of these fully formatted packets, we set a sentinel--- in one of IOError's extra fields. This is handled by--- 'ioeSetVerbatim' and 'ioeGetVerbatim'.-----dieNoVerbosity :: String -> IO a-dieNoVerbosity msg- = ioError (userError msg)- where- _ = callStack -- TODO: Attach CallStack to exception---- | Tag an 'IOError' whose error string should be output to the screen--- verbatim.-ioeSetVerbatim :: IOError -> IOError-ioeSetVerbatim e = ioeSetLocation e "dieVerbatim"---- | Check if an 'IOError' should be output verbatim to screen.-ioeGetVerbatim :: IOError -> Bool-ioeGetVerbatim e = ioeGetLocation e == "dieVerbatim"---- | Create a 'userError' whose error text will be output verbatim-verbatimUserError :: String -> IOError-verbatimUserError = ioeSetVerbatim . userError--dieWithLocation' :: Verbosity -> FilePath -> Maybe Int -> String -> IO a-dieWithLocation' verbosity filename mb_lineno msg = withFrozenCallStack $ do- ts <- getPOSIXTime- pname <- getProgName- ioError . verbatimUserError- . withMetadata ts AlwaysMark VerboseTrace verbosity- . wrapTextVerbosity verbosity- $ pname ++ ": " ++- filename ++ (case mb_lineno of- Just lineno -> ":" ++ show lineno- Nothing -> "") ++- ": " ++ msg--die' :: Verbosity -> String -> IO a-die' verbosity msg = withFrozenCallStack $ do- ts <- getPOSIXTime- pname <- getProgName- ioError . verbatimUserError- . withMetadata ts AlwaysMark VerboseTrace verbosity- . wrapTextVerbosity verbosity- $ pname ++ ": " ++ msg--dieNoWrap :: Verbosity -> String -> IO a-dieNoWrap verbosity msg = withFrozenCallStack $ do- -- TODO: should this have program name or not?- ts <- getPOSIXTime- ioError . verbatimUserError- . withMetadata ts AlwaysMark VerboseTrace verbosity- $ msg---- | Given a block of IO code that may raise an exception, annotate--- it with the metadata from the current scope. Use this as close--- to external code that raises IO exceptions as possible, since--- this function unconditionally wraps the error message with a trace--- (so it is NOT idempotent.)-annotateIO :: Verbosity -> IO a -> IO a-annotateIO verbosity act = do- ts <- getPOSIXTime- modifyIOError (f ts) act- where- f ts ioe = ioeSetErrorString ioe- . withMetadata ts NeverMark VerboseTrace verbosity- $ ioeGetErrorString ioe---{-# NOINLINE topHandlerWith #-}-topHandlerWith :: forall a. (Exception.SomeException -> IO a) -> IO a -> IO a-topHandlerWith cont prog = do- -- By default, stderr to a terminal device is NoBuffering. But this- -- is *really slow*- hSetBuffering stderr LineBuffering- Exception.catches prog [- Exception.Handler rethrowAsyncExceptions- , Exception.Handler rethrowExitStatus- , Exception.Handler handle- ]- where- -- Let async exceptions rise to the top for the default top-handler- rethrowAsyncExceptions :: Exception.AsyncException -> IO a- rethrowAsyncExceptions a = throwIO a-- -- 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 (message pname se)- cont se-- message :: String -> Exception.SomeException -> String- message pname (Exception.SomeException se) =- case cast se :: Maybe Exception.IOException of- Just ioe- | ioeGetVerbatim ioe ->- -- Use the message verbatim- ioeGetErrorString ioe ++ "\n"- | isUserError ioe ->- let file = case ioeGetFileName ioe of- Nothing -> ""- Just path -> path ++ location ++ ": "- location = case ioeGetLocation ioe of- l@(n:_) | isDigit n -> ':' : l- _ -> ""- detail = ioeGetErrorString ioe- in wrapText (pname ++ ": " ++ file ++ detail)- _ ->- displaySomeException se ++ "\n"---- | BC wrapper around 'Exception.displayException'.-displaySomeException :: Exception.Exception e => e -> String-displaySomeException se =-#if __GLASGOW_HASKELL__ < 710- show se-#else- Exception.displayException se-#endif--topHandler :: IO a -> IO a-topHandler prog = topHandlerWith (const $ exitWith (ExitFailure 1)) prog--verbosityHandle :: Verbosity -> Handle-verbosityHandle verbosity- | isVerboseStderr verbosity = stderr- | otherwise = stdout---- | Non fatal conditions that may be indicative of an error or problem.------ We display these at the 'normal' verbosity level.----warn :: Verbosity -> String -> IO ()-warn verbosity msg = withFrozenCallStack $ do- when (verbosity >= normal) $ do- ts <- getPOSIXTime- hFlush stdout- hPutStr stderr . withMetadata ts NormalMark FlagTrace verbosity- . wrapTextVerbosity verbosity- $ "Warning: " ++ msg---- | Useful status messages.------ We display these at the 'normal' verbosity level.------ This is for the ordinary helpful status messages that users see. Just--- enough information to know that things are working but not floods of detail.----notice :: Verbosity -> String -> IO ()-notice verbosity msg = withFrozenCallStack $ do- when (verbosity >= normal) $ do- let h = verbosityHandle verbosity- ts <- getPOSIXTime- hPutStr h- $ withMetadata ts NormalMark FlagTrace verbosity- $ wrapTextVerbosity verbosity- $ msg---- | Display a message at 'normal' verbosity level, but without--- wrapping.----noticeNoWrap :: Verbosity -> String -> IO ()-noticeNoWrap verbosity msg = withFrozenCallStack $ do- when (verbosity >= normal) $ do- let h = verbosityHandle verbosity- ts <- getPOSIXTime- hPutStr h . withMetadata ts NormalMark FlagTrace verbosity $ msg---- | Pretty-print a 'Disp.Doc' status message at 'normal' verbosity--- level. Use this if you need fancy formatting.----noticeDoc :: Verbosity -> Disp.Doc -> IO ()-noticeDoc verbosity msg = withFrozenCallStack $ do- when (verbosity >= normal) $ do- let h = verbosityHandle verbosity- ts <- getPOSIXTime- hPutStr h- $ withMetadata ts NormalMark FlagTrace verbosity- $ Disp.renderStyle defaultStyle- $ msg---- | Display a "setup status message". Prefer using setupMessage'--- if possible.----setupMessage :: Verbosity -> String -> PackageIdentifier -> IO ()-setupMessage verbosity msg pkgid = withFrozenCallStack $ do- noticeNoWrap verbosity (msg ++ ' ': prettyShow pkgid ++ "...")---- | More detail on the operation of some action.------ We display these messages when the verbosity level is 'verbose'----info :: Verbosity -> String -> IO ()-info verbosity msg = withFrozenCallStack $- when (verbosity >= verbose) $ do- let h = verbosityHandle verbosity- ts <- getPOSIXTime- hPutStr h- $ withMetadata ts NeverMark FlagTrace verbosity- $ wrapTextVerbosity verbosity- $ msg--infoNoWrap :: Verbosity -> String -> IO ()-infoNoWrap verbosity msg = withFrozenCallStack $- when (verbosity >= verbose) $ do- let h = verbosityHandle verbosity- ts <- getPOSIXTime- hPutStr h- $ withMetadata ts NeverMark FlagTrace verbosity- $ msg---- | Detailed internal debugging information------ We display these messages when the verbosity level is 'deafening'----debug :: Verbosity -> String -> IO ()-debug verbosity msg = withFrozenCallStack $- when (verbosity >= deafening) $ do- let h = verbosityHandle verbosity- ts <- getPOSIXTime- hPutStr h $ withMetadata ts NeverMark FlagTrace verbosity- $ wrapTextVerbosity verbosity- $ msg- -- ensure that we don't lose output if we segfault/infinite loop- hFlush stdout---- | A variant of 'debug' that doesn't perform the automatic line--- wrapping. Produces better output in some cases.-debugNoWrap :: Verbosity -> String -> IO ()-debugNoWrap verbosity msg = withFrozenCallStack $- when (verbosity >= deafening) $ do- let h = verbosityHandle verbosity- ts <- getPOSIXTime- hPutStr h- $ withMetadata ts NeverMark FlagTrace verbosity- $ msg- -- ensure that we don't lose output if we segfault/infinite loop- hFlush stdout---- | Perform an IO action, catching any IO exceptions and printing an error--- if one occurs.-chattyTry :: String -- ^ a description of the action we were attempting- -> IO () -- ^ the action itself- -> IO ()-chattyTry desc action =- catchIO action $ \exception ->- hPutStrLn stderr $ "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---- | Wraps text unless the @+nowrap@ verbosity flag is active-wrapTextVerbosity :: Verbosity -> String -> String-wrapTextVerbosity verb- | isVerboseNoWrap verb = withTrailingNewline- | otherwise = withTrailingNewline . wrapText----- | Prepends a timestamp if @+timestamp@ verbosity flag is set------ This is used by 'withMetadata'----withTimestamp :: Verbosity -> POSIXTime -> String -> String-withTimestamp v ts msg- | isVerboseTimestamp v = msg'- | otherwise = msg -- no-op- where- msg' = case lines msg of- [] -> tsstr "\n"- l1:rest -> unlines (tsstr (' ':l1) : map (contpfx++) rest)-- -- format timestamp to be prepended to first line with msec precision- tsstr = showFFloat (Just 3) (realToFrac ts :: Double)-- -- continuation prefix for subsequent lines of msg- contpfx = replicate (length (tsstr " ")) ' '---- | Wrap output with a marker if @+markoutput@ verbosity flag is set.------ NB: Why is markoutput done with start/end markers, and not prefixes?--- Markers are more convenient to add (if we want to add prefixes,--- we have to 'lines' and then 'map'; here's it's just some--- concatenates). Note that even in the prefix case, we can't--- guarantee that the markers are unambiguous, because some of--- Cabal's output comes straight from external programs, where--- we don't have the ability to interpose on the output.------ This is used by 'withMetadata'----withOutputMarker :: Verbosity -> String -> String-withOutputMarker v xs | not (isVerboseMarkOutput v) = xs-withOutputMarker _ "" = "" -- Minor optimization, don't mark uselessly-withOutputMarker _ xs =- "-----BEGIN CABAL OUTPUT-----\n" ++- withTrailingNewline xs ++- "-----END CABAL OUTPUT-----\n"---- | Append a trailing newline to a string if it does not--- already have a trailing newline.----withTrailingNewline :: String -> String-withTrailingNewline "" = ""-withTrailingNewline (x:xs) = x : go x xs- where- go _ (c:cs) = c : go c cs- go '\n' "" = ""- go _ "" = "\n"---- | Prepend a call-site and/or call-stack based on Verbosity----withCallStackPrefix :: WithCallStack (TraceWhen -> Verbosity -> String -> String)-withCallStackPrefix tracer verbosity s = withFrozenCallStack $- (if isVerboseCallSite verbosity- then parentSrcLocPrefix ++- -- Hack: need a newline before starting output marker :(- if isVerboseMarkOutput verbosity- then "\n"- else ""- else "") ++- (case traceWhen verbosity tracer of- Just pre -> pre ++ prettyCallStack callStack ++ "\n"- Nothing -> "") ++- s---- | When should we emit the call stack? We always emit--- for internal errors, emit the trace for errors when we--- are in verbose mode, and otherwise only emit it if--- explicitly asked for using the @+callstack@ verbosity--- flag. (At the moment, 'AlwaysTrace' is not used.----data TraceWhen- = AlwaysTrace- | VerboseTrace- | FlagTrace- deriving (Eq)---- | Determine if we should emit a call stack.--- If we trace, it also emits any prefix we should append.-traceWhen :: Verbosity -> TraceWhen -> Maybe String-traceWhen _ AlwaysTrace = Just ""-traceWhen v VerboseTrace | v >= verbose = Just ""-traceWhen v FlagTrace | isVerboseCallStack v = Just "----\n"-traceWhen _ _ = Nothing---- | When should we output the marker? Things like 'die'--- always get marked, but a 'NormalMark' will only be--- output if we're not a quiet verbosity.----data MarkWhen = AlwaysMark | NormalMark | NeverMark---- | Add all necessary metadata to a logging message----withMetadata :: WithCallStack (POSIXTime -> MarkWhen -> TraceWhen -> Verbosity -> String -> String)-withMetadata ts marker tracer verbosity x = withFrozenCallStack $- -- NB: order matters. Output marker first because we- -- don't want to capture call stacks.- withTrailingNewline- . withCallStackPrefix tracer verbosity- . (case marker of- AlwaysMark -> withOutputMarker verbosity- NormalMark | not (isVerboseQuiet verbosity)- -> withOutputMarker verbosity- | otherwise- -> id- NeverMark -> id)- -- Clear out any existing markers- . clearMarkers- . withTimestamp verbosity ts- $ x--clearMarkers :: String -> String-clearMarkers s = unlines . filter isMarker $ lines s- where- isMarker "-----BEGIN CABAL OUTPUT-----" = False- isMarker "-----END CABAL OUTPUT-----" = False- isMarker _ = True---- -------------------------------------------------------------------------------- rawSystem variants-maybeExit :: IO ExitCode -> IO ()-maybeExit cmd = do- res <- cmd- unless (res == ExitSuccess) $ exitWith res----printRawCommandAndArgs :: Verbosity -> FilePath -> [String] -> IO ()-printRawCommandAndArgs verbosity path args = withFrozenCallStack $- printRawCommandAndArgsAndEnv verbosity path args Nothing Nothing--printRawCommandAndArgsAndEnv :: Verbosity- -> FilePath- -> [String]- -> Maybe FilePath- -> Maybe [(String, String)]- -> IO ()-printRawCommandAndArgsAndEnv verbosity path args mcwd menv = do- case menv of- Just env -> debugNoWrap verbosity ("Environment: " ++ show env)- Nothing -> return ()- case mcwd of- Just cwd -> debugNoWrap verbosity ("Working directory: " ++ show cwd)- Nothing -> return ()- infoNoWrap verbosity (showCommandForUser path args)---- Exit with the same exit code if the subcommand fails-rawSystemExit :: Verbosity -> FilePath -> [String] -> IO ()-rawSystemExit verbosity path args = withFrozenCallStack $ do- printRawCommandAndArgs verbosity path args- hFlush stdout- exitcode <- rawSystem path args- unless (exitcode == ExitSuccess) $ do- debug verbosity $ path ++ " returned " ++ show exitcode- exitWith exitcode--rawSystemExitCode :: Verbosity -> FilePath -> [String] -> IO ExitCode-rawSystemExitCode verbosity path args = withFrozenCallStack $ do- printRawCommandAndArgs verbosity path args- hFlush stdout- exitcode <- rawSystem path args- unless (exitcode == ExitSuccess) $ do- debug verbosity $ path ++ " returned " ++ show exitcode- return exitcode--rawSystemExitWithEnv :: Verbosity- -> FilePath- -> [String]- -> [(String, String)]- -> IO ()-rawSystemExitWithEnv verbosity path args env = withFrozenCallStack $ do- printRawCommandAndArgsAndEnv verbosity path args Nothing (Just env)- hFlush stdout- (_,_,_,ph) <- createProcess $- (Process.proc path args) { Process.env = (Just env)-#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-#endif-#endif- }- exitcode <- waitForProcess ph- unless (exitcode == ExitSuccess) $ do- debug verbosity $ path ++ " returned " ++ show exitcode- exitWith exitcode---- Closes the passed in handles before returning.-rawSystemIOWithEnv :: Verbosity- -> FilePath- -> [String]- -> Maybe FilePath -- ^ New working dir or inherit- -> Maybe [(String, String)] -- ^ New environment or inherit- -> Maybe Handle -- ^ stdin- -> Maybe Handle -- ^ stdout- -> Maybe Handle -- ^ stderr- -> IO ExitCode-rawSystemIOWithEnv verbosity path args mcwd menv inp out err = withFrozenCallStack $ 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--rawSystemIOWithEnvAndAction- :: Verbosity- -> FilePath- -> [String]- -> Maybe FilePath -- ^ New working dir or inherit- -> Maybe [(String, String)] -- ^ New environment or inherit- -> IO a -- ^ action to perform after process is created, but before 'waitForProcess'.- -> Maybe Handle -- ^ stdin- -> Maybe Handle -- ^ stdout- -> Maybe Handle -- ^ stderr- -> IO (ExitCode, a)-rawSystemIOWithEnvAndAction verbosity path args mcwd menv action inp out err = withFrozenCallStack $ do- (_,_,_,ph) <- createProcessWithEnv verbosity path args mcwd menv- (mbToStd inp) (mbToStd out) (mbToStd err)- a <- action- exitcode <- waitForProcess ph- unless (exitcode == ExitSuccess) $ do- debug verbosity $ path ++ " returned " ++ show exitcode- return (exitcode, a)- 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 = withFrozenCallStack $ do- printRawCommandAndArgsAndEnv verbosity path args mcwd menv- hFlush stdout- (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-#endif-#endif- }- return (inp', out', err', ph)---- | Run a command and return its output.------ The output is assumed to be text in the locale encoding.----rawSystemStdout :: forall mode. KnownIODataMode mode => Verbosity -> FilePath -> [String] -> IO mode-rawSystemStdout verbosity path args = withFrozenCallStack $ do- (output, errors, exitCode) <- rawSystemStdInOut verbosity path args- Nothing Nothing Nothing (IOData.iodataMode :: IODataMode mode)- when (exitCode /= ExitSuccess) $- die' verbosity errors- return output---- | Run a command and return its output, errors and exit status. Optionally--- also supply some input. Also provides control over whether the binary/text--- mode of the input and output.----rawSystemStdInOut :: KnownIODataMode mode- => Verbosity- -> FilePath -- ^ Program location- -> [String] -- ^ Arguments- -> Maybe FilePath -- ^ New working dir or inherit- -> Maybe [(String, String)] -- ^ New environment or inherit- -> Maybe IOData -- ^ input text and binary mode- -> IODataMode mode -- ^ iodata mode, acts as proxy- -> IO (mode, String, ExitCode) -- ^ output, errors, exit-rawSystemStdInOut verbosity path args mcwd menv input _ = withFrozenCallStack $ do- printRawCommandAndArgs verbosity path args-- Exception.bracket- (runInteractiveProcess path args mcwd menv)- (\(inh,outh,errh,_) -> hClose inh >> hClose outh >> hClose errh)- $ \(inh,outh,errh,pid) -> do-- -- output mode depends on what the caller wants- -- but the errors are always assumed to be text (in the current locale)- hSetBinaryMode errh False-- -- fork off a couple threads to pull on the stderr and stdout- -- so if the process writes to stderr we do not block.-- withAsyncNF (hGetContents errh) $ \errA -> withAsyncNF (IOData.hGetIODataContents outh) $ \outA -> do- -- push all the input, if any- ignoreSigPipe $ case input of- Nothing -> hClose inh- Just inputData -> IOData.hPutContents inh inputData-- -- wait for both to finish- mberr1 <- waitCatch outA- mberr2 <- waitCatch errA-- -- wait for the program to terminate- exitcode <- waitForProcess pid-- -- get the stderr, so it can be added to error message- err <- reportOutputIOError mberr2-- unless (exitcode == ExitSuccess) $- debug verbosity $ path ++ " returned " ++ show exitcode- ++ if null err then "" else- " with error message:\n" ++ err- ++ case input of- Nothing -> ""- Just d | IOData.null d -> ""- Just (IODataText inp) -> "\nstdin input:\n" ++ inp- Just (IODataBinary inp) -> "\nstdin input (binary):\n" ++ show inp-- -- Check if we hit an exception while consuming the output- -- (e.g. a text decoding error)- out <- reportOutputIOError mberr1-- return (out, err, exitcode)- where- reportOutputIOError :: Either Exception.SomeException a -> IO a- reportOutputIOError (Right x) = return x- reportOutputIOError (Left exc) = case fromException exc of- Just ioe -> throwIO (ioeSetFileName ioe ("output of " ++ path))- Nothing -> throwIO exc-- ignoreSigPipe :: IO () -> IO ()- ignoreSigPipe = Exception.handle $ \e -> case e of- GHC.IOError { GHC.ioe_type = GHC.ResourceVanished, GHC.ioe_errno = Just ioe }- | Errno ioe == ePIPE -> return ()- _ -> throwIO e---- | Look for a program and try to find it's version number. It can accept--- either an absolute path or the name of a program binary, in which case we--- will look for the program on the path.----findProgramVersion :: String -- ^ version args- -> (String -> String) -- ^ function to select version- -- number from program output- -> Verbosity- -> FilePath -- ^ location- -> IO (Maybe Version)-findProgramVersion versionArg selectVersion verbosity path = withFrozenCallStack $ do- str <- rawSystemStdout verbosity path [versionArg]- `catchIO` (\_ -> return "")- `catchExit` (\_ -> return "")- let version :: Maybe Version- version = simpleParsec (selectVersion str)- case version of- Nothing -> warn verbosity $ "cannot determine version of " ++ path- ++ " :\n" ++ show str- Just v -> debug verbosity $ path ++ " is version " ++ prettyShow v- return version----- | Like the Unix xargs program. Useful for when we've got very long command--- lines that might overflow an OS limit on command line length and so you--- need to invoke a command multiple times to get all the args in.------ Use it with either of the rawSystem variants above. For example:------ > xargs (32*1024) (rawSystemExit verbosity) prog fixedArgs bigArgs----xargs :: Int -> ([String] -> IO ())- -> [String] -> [String] -> IO ()-xargs maxSize rawSystemFun fixedArgs bigArgs =- let fixedArgSize = sum (map length fixedArgs) + length fixedArgs- chunkSize = maxSize - fixedArgSize- in traverse_ (rawSystemFun . (fixedArgs ++)) (chunks chunkSize bigArgs)-- where chunks len = unfoldr $ \s ->- if null s then Nothing- else Just (chunk [] len s)-- chunk acc _ [] = (reverse acc,[])- chunk acc len (s:ss)- | len' < len = chunk (s:acc) (len-len'-1) ss- | otherwise = (reverse acc, s:ss)- where len' = length s---- --------------------------------------------------------------- * File Utilities--- --------------------------------------------------------------------------------- Finding files---{-# DEPRECATED findFile "Use findFileEx instead. This symbol will be removed in Cabal 3.2 (est. December 2019)" #-}-findFile :: [FilePath] -- ^search locations- -> FilePath -- ^File Name- -> IO FilePath-findFile = findFileEx normal---- | Find a file by looking in a search path. The file path must match exactly.------ @since 3.4.0.0-findFileCwd- :: Verbosity- -> FilePath -- ^ cwd- -> [FilePath] -- ^ relative search location- -> FilePath -- ^ File Name- -> IO FilePath-findFileCwd verbosity cwd searchPath fileName =- findFirstFile (cwd </>)- [ path </> fileName- | path <- nub searchPath]- >>= maybe (die' verbosity $ fileName ++ " doesn't exist") return---- | Find a file by looking in a search path. The file path must match exactly.----findFileEx :: Verbosity- -> [FilePath] -- ^search locations- -> FilePath -- ^File Name- -> IO FilePath-findFileEx verbosity searchPath fileName =- findFirstFile id- [ path </> fileName- | path <- nub searchPath]- >>= maybe (die' verbosity $ fileName ++ " doesn't exist") return---- | Find a file by looking in a search path with one of a list of possible--- file extensions. The file base name should be given and it will be tried--- with each of the extensions in each element of the search path.----findFileWithExtension :: [String]- -> [FilePath]- -> FilePath- -> IO (Maybe FilePath)-findFileWithExtension extensions searchPath baseName =- findFirstFile id- [ path </> baseName <.> ext- | path <- nub searchPath- , ext <- nub extensions ]---- | @since 3.4.0.0-findFileCwdWithExtension- :: FilePath- -> [String]- -> [FilePath]- -> FilePath- -> IO (Maybe FilePath)-findFileCwdWithExtension cwd extensions searchPath baseName =- findFirstFile (cwd </>)- [ path </> baseName <.> ext- | path <- nub searchPath- , ext <- nub extensions ]---- | @since 3.4.0.0-findAllFilesCwdWithExtension- :: FilePath -- ^ cwd- -> [String] -- ^ extensions- -> [FilePath] -- ^ relative search locations- -> FilePath -- ^ basename- -> IO [FilePath]-findAllFilesCwdWithExtension cwd extensions searchPath basename =- findAllFiles (cwd </>)- [ path </> basename <.> ext- | 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.----findFileWithExtension' :: [String]- -> [FilePath]- -> FilePath- -> IO (Maybe (FilePath, FilePath))-findFileWithExtension' extensions searchPath baseName =- findFirstFile (uncurry (</>))- [ (path, baseName <.> ext)- | path <- nub searchPath- , ext <- nub extensions ]--findFirstFile :: (a -> FilePath) -> [a] -> IO (Maybe a)-findFirstFile file = findFirst- where findFirst [] = return Nothing- findFirst (x:xs) = do exists <- doesFileExist (file x)- if exists- then return (Just x)- else findFirst xs--findAllFiles :: (a -> FilePath) -> [a] -> IO [a]-findAllFiles file = filterM (doesFileExist . file)---{-# DEPRECATED findModuleFiles "Use findModuleFilesEx instead. This symbol will be removed in Cabal 3.2 (est. December 2019)" #-}-findModuleFiles :: [FilePath] -- ^ build prefix (location of objects)- -> [String] -- ^ search suffixes- -> [ModuleName] -- ^ modules- -> IO [(FilePath, FilePath)]-findModuleFiles = findModuleFilesEx normal---- | Finds the files corresponding to a list of Haskell module names.------ As 'findModuleFile' but for a list of module names.----findModuleFilesEx :: Verbosity- -> [FilePath] -- ^ build prefix (location of objects)- -> [String] -- ^ search suffixes- -> [ModuleName] -- ^ modules- -> IO [(FilePath, FilePath)]-findModuleFilesEx verbosity searchPath extensions moduleNames =- traverse (findModuleFileEx verbosity searchPath extensions) moduleNames--{-# DEPRECATED findModuleFile "Use findModuleFileEx instead. This symbol will be removed in Cabal 3.2 (est. December 2019)" #-}-findModuleFile :: [FilePath] -- ^ build prefix (location of objects)- -> [String] -- ^ search suffixes- -> ModuleName -- ^ module- -> IO (FilePath, FilePath)-findModuleFile = findModuleFileEx normal---- | Find the file corresponding to a Haskell module name.------ This is similar to 'findFileWithExtension'' but specialised to a module--- name. The function fails if the file corresponding to the module is missing.----findModuleFileEx :: Verbosity- -> [FilePath] -- ^ build prefix (location of objects)- -> [String] -- ^ search suffixes- -> ModuleName -- ^ module- -> IO (FilePath, FilePath)-findModuleFileEx verbosity searchPath extensions mod_name =- maybe notFound return- =<< findFileWithExtension' extensions searchPath- (ModuleName.toFilePath mod_name)- where- notFound = die' verbosity $- "Error: Could not find module: " ++ prettyShow mod_name- ++ " with any suffix: " ++ show extensions- ++ " in the search path: " ++ show searchPath---- | List all the files in a directory and all subdirectories.------ The order places files in sub-directories after all the files in their--- parent directories. The list is generated lazily so is not well defined if--- the source directory structure changes before the list is used.----getDirectoryContentsRecursive :: FilePath -> IO [FilePath]-getDirectoryContentsRecursive topdir = recurseDirectories [""]- where- recurseDirectories :: [FilePath] -> IO [FilePath]- recurseDirectories [] = return []- recurseDirectories (dir:dirs) = unsafeInterleaveIO $ do- (files, dirs') <- collect [] [] =<< getDirectoryContents (topdir </> dir)- files' <- recurseDirectories (dirs' ++ dirs)- return (files ++ files')-- where- collect files dirs' [] = return (reverse files- ,reverse dirs')- collect files dirs' (entry:entries) | ignore entry- = collect files dirs' entries- collect files dirs' (entry:entries) = do- let dirEntry = dir </> entry- isDirectory <- doesDirectoryExist (topdir </> dirEntry)- if isDirectory- then collect files (dirEntry:dirs') entries- else collect (dirEntry:files) dirs' entries-- ignore ['.'] = True- ignore ['.', '.'] = True- ignore _ = False----------------------------- Environment variables---- | Is this directory in the system search path?-isInSearchPath :: FilePath -> IO Bool-isInSearchPath path = fmap (elem path) getSearchPath--addLibraryPath :: OS- -> [FilePath]- -> [(String,String)]- -> [(String,String)]-addLibraryPath os paths = addEnv- where- pathsString = intercalate [searchPathSeparator] paths- ldPath = case os of- OSX -> "DYLD_LIBRARY_PATH"- _ -> "LD_LIBRARY_PATH"-- addEnv [] = [(ldPath,pathsString)]- addEnv ((key,value):xs)- | key == ldPath =- if null value- then (key,pathsString):xs- else (key,value ++ (searchPathSeparator:pathsString)):xs- | otherwise = (key,value):addEnv xs------------------------- Modification time---- | Compare the modification times of two files to see if the first is newer--- than the second. The first file must exist but the second need not.--- The expected use case is when the second file is generated using the first.--- In this use case, if the result is True then the second file is out of date.----moreRecentFile :: FilePath -> FilePath -> IO Bool-moreRecentFile a b = do- exists <- doesFileExist b- if not exists- then return True- else do tb <- getModificationTime b- ta <- getModificationTime a- return (ta > tb)---- | Like 'moreRecentFile', but also checks that the first file exists.-existsAndIsMoreRecentThan :: FilePath -> FilePath -> IO Bool-existsAndIsMoreRecentThan a b = do- exists <- doesFileExist a- if not exists- then return False- else a `moreRecentFile` b--------------------------------------------- Copying and installing files and dirs---- | Same as 'createDirectoryIfMissing' but logs at higher verbosity levels.----createDirectoryIfMissingVerbose :: Verbosity- -> Bool -- ^ Create its parents too?- -> FilePath- -> IO ()-createDirectoryIfMissingVerbose verbosity create_parents path0- | create_parents = withFrozenCallStack $ createDirs (parents path0)- | otherwise = withFrozenCallStack $ createDirs (take 1 (parents path0))- where- parents = reverse . scanl1 (</>) . splitDirectories . normalise-- createDirs [] = return ()- createDirs (dir:[]) = createDir dir throwIO- createDirs (dir:dirs) =- createDir dir $ \_ -> do- createDirs dirs- createDir dir throwIO-- createDir :: FilePath -> (IOException -> IO ()) -> IO ()- createDir dir notExistHandler = do- r <- tryIO $ createDirectoryVerbose verbosity dir- case (r :: Either IOException ()) of- Right () -> return ()- Left e- | isDoesNotExistError e -> notExistHandler e- -- createDirectory (and indeed POSIX mkdir) does not distinguish- -- between a dir already existing and a file already existing. So we- -- check for it here. Unfortunately there is a slight race condition- -- here, but we think it is benign. It could report an exception in- -- the case that the dir did exist but another process deletes the- -- directory and creates a file in its place before we can check- -- that the directory did indeed exist.- | isAlreadyExistsError e -> (do- isDir <- doesDirectoryExist dir- unless isDir $ throwIO e- ) `catchIO` ((\_ -> return ()) :: IOException -> IO ())- | otherwise -> throwIO e--createDirectoryVerbose :: Verbosity -> FilePath -> IO ()-createDirectoryVerbose verbosity dir = withFrozenCallStack $ do- info verbosity $ "creating " ++ dir- createDirectory dir- setDirOrdinary dir---- | Copies a file without copying file permissions. The target file is created--- with default permissions. Any existing target file is replaced.------ At higher verbosity levels it logs an info message.----copyFileVerbose :: Verbosity -> FilePath -> FilePath -> IO ()-copyFileVerbose verbosity src dest = withFrozenCallStack $ do- info verbosity ("copy " ++ src ++ " to " ++ dest)- copyFile src dest---- | Install an ordinary file. This is like a file copy but the permissions--- are set appropriately for an installed file. On Unix it is \"-rw-r--r--\"--- while on Windows it uses the default permissions for the target directory.----installOrdinaryFile :: Verbosity -> FilePath -> FilePath -> IO ()-installOrdinaryFile verbosity src dest = withFrozenCallStack $ do- info verbosity ("Installing " ++ src ++ " to " ++ dest)- copyOrdinaryFile src dest---- | Install an executable file. This is like a file copy but the permissions--- are set appropriately for an installed file. On Unix it is \"-rwxr-xr-x\"--- while on Windows it uses the default permissions for the target directory.----installExecutableFile :: Verbosity -> FilePath -> FilePath -> IO ()-installExecutableFile verbosity src dest = withFrozenCallStack $ do- info verbosity ("Installing executable " ++ src ++ " to " ++ dest)- copyExecutableFile src dest---- | Install a file that may or not be executable, preserving permissions.-installMaybeExecutableFile :: Verbosity -> FilePath -> FilePath -> IO ()-installMaybeExecutableFile verbosity src dest = withFrozenCallStack $ do- perms <- getPermissions src- if (executable perms) --only checks user x bit- then installExecutableFile verbosity src dest- else installOrdinaryFile verbosity src dest---- | Given a relative path to a file, copy it to the given directory, preserving--- the relative path and creating the parent directories if needed.-copyFileTo :: Verbosity -> FilePath -> FilePath -> IO ()-copyFileTo verbosity dir file = withFrozenCallStack $ do- let targetFile = dir </> file- createDirectoryIfMissingVerbose verbosity True (takeDirectory targetFile)- installOrdinaryFile verbosity file targetFile---- | Common implementation of 'copyFiles', 'installOrdinaryFiles',--- 'installExecutableFiles' and 'installMaybeExecutableFiles'.-copyFilesWith :: (Verbosity -> FilePath -> FilePath -> IO ())- -> Verbosity -> FilePath -> [(FilePath, FilePath)] -> IO ()-copyFilesWith doCopy verbosity targetDir srcFiles = withFrozenCallStack $ do-- -- Create parent directories for everything- let dirs = map (targetDir </>) . nub . map (takeDirectory . snd) $ srcFiles- traverse_ (createDirectoryIfMissingVerbose verbosity True) dirs-- -- Copy all the files- sequence_ [ let src = srcBase </> srcFile- dest = targetDir </> srcFile- in doCopy verbosity src dest- | (srcBase, srcFile) <- srcFiles ]---- | Copies a bunch of files to a target directory, preserving the directory--- structure in the target location. The target directories are created if they--- do not exist.------ The files are identified by a pair of base directory and a path relative to--- that base. It is only the relative part that is preserved in the--- destination.------ For example:------ > copyFiles normal "dist/src"--- > [("", "src/Foo.hs"), ("dist/build/", "src/Bar.hs")]------ This would copy \"src\/Foo.hs\" to \"dist\/src\/src\/Foo.hs\" and--- copy \"dist\/build\/src\/Bar.hs\" to \"dist\/src\/src\/Bar.hs\".------ This operation is not atomic. Any IO failure during the copy (including any--- missing source files) leaves the target in an unknown state so it is best to--- use it with a freshly created directory so that it can be simply deleted if--- anything goes wrong.----copyFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)] -> IO ()-copyFiles v fp fs = withFrozenCallStack (copyFilesWith copyFileVerbose v fp fs)---- | This is like 'copyFiles' but uses 'installOrdinaryFile'.----installOrdinaryFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)] -> IO ()-installOrdinaryFiles v fp fs = withFrozenCallStack (copyFilesWith installOrdinaryFile v fp fs)---- | This is like 'copyFiles' but uses 'installExecutableFile'.----installExecutableFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)]- -> IO ()-installExecutableFiles v fp fs = withFrozenCallStack (copyFilesWith installExecutableFile v fp fs)---- | This is like 'copyFiles' but uses 'installMaybeExecutableFile'.----installMaybeExecutableFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)]- -> IO ()-installMaybeExecutableFiles v fp fs = withFrozenCallStack (copyFilesWith installMaybeExecutableFile v fp fs)---- | This installs all the files in a directory to a target location,--- preserving the directory layout. All the files are assumed to be ordinary--- rather than executable files.----installDirectoryContents :: Verbosity -> FilePath -> FilePath -> IO ()-installDirectoryContents verbosity srcDir destDir = withFrozenCallStack $ do- info verbosity ("copy directory '" ++ srcDir ++ "' to '" ++ destDir ++ "'.")- srcFiles <- getDirectoryContentsRecursive srcDir- installOrdinaryFiles verbosity destDir [ (srcDir, f) | f <- srcFiles ]---- | Recursively copy the contents of one directory to another path.-copyDirectoryRecursive :: Verbosity -> FilePath -> FilePath -> IO ()-copyDirectoryRecursive verbosity srcDir destDir = withFrozenCallStack $ do- info verbosity ("copy directory '" ++ srcDir ++ "' to '" ++ destDir ++ "'.")- srcFiles <- getDirectoryContentsRecursive srcDir- copyFilesWith (const copyFile) verbosity destDir [ (srcDir, f)- | f <- srcFiles ]------------------------ File permissions---- | Like 'doesFileExist', but also checks that the file is executable.-doesExecutableExist :: FilePath -> IO Bool-doesExecutableExist f = do- exists <- doesFileExist f- if exists- then do perms <- getPermissions f- return (executable perms)- else return False-------------------------------- Temporary files and dirs---- | Advanced options for 'withTempFile' and 'withTempDirectory'.-data TempFileOptions = TempFileOptions {- optKeepTempFiles :: Bool -- ^ Keep temporary files?- }--defaultTempFileOptions :: TempFileOptions-defaultTempFileOptions = TempFileOptions { optKeepTempFiles = False }---- | Use a temporary filename that doesn't already exist.----withTempFile :: FilePath -- ^ Temp dir to create the file in- -> String -- ^ File name template. See 'openTempFile'.- -> (FilePath -> Handle -> IO a) -> IO a-withTempFile tmpDir template action =- withTempFileEx defaultTempFileOptions tmpDir template action---- | A version of 'withTempFile' that additionally takes a 'TempFileOptions'--- argument.-withTempFileEx :: TempFileOptions- -> FilePath -- ^ Temp dir to create the file in- -> String -- ^ File name template. See 'openTempFile'.- -> (FilePath -> Handle -> IO a) -> IO a-withTempFileEx opts tmpDir template action =- Exception.bracket- (openTempFile tmpDir template)- (\(name, handle) -> do hClose handle- unless (optKeepTempFiles opts) $- handleDoesNotExist () . removeFile $ name)- (withLexicalCallStack (\x -> uncurry action x))---- | Create and use a temporary directory.------ Creates a new temporary directory inside the given directory, making use--- of the template. The temp directory is deleted after use. For example:------ > withTempDirectory verbosity "src" "sdist." $ \tmpDir -> do ...------ The @tmpDir@ will be a new subdirectory of the given directory, e.g.--- @src/sdist.342@.----withTempDirectory :: Verbosity -> FilePath -> String -> (FilePath -> IO a) -> IO a-withTempDirectory verbosity targetDir template f = withFrozenCallStack $- withTempDirectoryEx verbosity defaultTempFileOptions targetDir template- (withLexicalCallStack (\x -> f x))---- | A version of 'withTempDirectory' that additionally takes a--- 'TempFileOptions' argument.-withTempDirectoryEx :: Verbosity -> TempFileOptions- -> FilePath -> String -> (FilePath -> IO a) -> IO a-withTempDirectoryEx _verbosity opts targetDir template f = withFrozenCallStack $- Exception.bracket- (createTempDirectory targetDir template)- (unless (optKeepTempFiles opts)- . handleDoesNotExist () . removeDirectoryRecursive)- (withLexicalCallStack (\x -> f x))---------------------------------------- Safely reading and writing files---- | Write a file but only if it would have new content. If we would be writing--- the same as the existing content then leave the file as is so that we do not--- update the file's modification time.------ NB: Before Cabal-3.0 the file content was assumed to be--- ASCII-representable. Since Cabal-3.0 the file is assumed to be--- UTF-8 encoded.-rewriteFileEx :: Verbosity -> FilePath -> String -> IO ()-rewriteFileEx verbosity path =- rewriteFileLBS verbosity path . toUTF8LBS---- | Same as `rewriteFileEx` but for 'ByteString's.-rewriteFileLBS :: Verbosity -> FilePath -> BS.ByteString -> IO ()-rewriteFileLBS verbosity path newContent =- flip catchIO mightNotExist $ do- existingContent <- annotateIO verbosity $ BS.readFile path- _ <- evaluate (BS.length existingContent)- unless (existingContent == newContent) $- annotateIO verbosity $- writeFileAtomic path newContent- where- mightNotExist e | isDoesNotExistError e- = annotateIO verbosity $ writeFileAtomic path newContent- | otherwise- = ioError e----- | The path name that represents the current directory.--- In Unix, it's @\".\"@, but this is system-specific.--- (E.g. AmigaOS uses the empty string @\"\"@ for the current directory.)-currentDir :: FilePath-currentDir = "."--shortRelativePath :: FilePath -> FilePath -> FilePath-shortRelativePath from to =- case dropCommonPrefix (splitDirectories from) (splitDirectories to) of- (stuff, path) -> joinPath (map (const "..") stuff ++ path)- where- dropCommonPrefix :: Eq a => [a] -> [a] -> ([a],[a])- dropCommonPrefix (x:xs) (y:ys)- | 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 =- -- System.FilePath's extension handling functions are horribly- -- inconsistent, consider:- --- -- isExtensionOf "" "foo" == False but- -- isExtensionOf "" "foo." == True.- --- -- On the other hand stripExtension doesn't remove the empty extension:- --- -- stripExtension "" "foo." == Just "foo."- --- -- Since by "" in exeExtensions we mean 'no extension' anyways we can- -- just always ignore it here.- let exts = [ ext | ext <- exeExtensions, ext /= "" ] in- fromMaybe filepath $ do- ext <- find (`FilePath.isExtensionOf` filepath) exts- ext `FilePath.stripExtension` filepath---- | List of possible executable file extensions on the current build--- 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--- ---------------------------------------------------------------- | Package description file (/pkgname/@.cabal@)-defaultPackageDesc :: Verbosity -> IO FilePath-defaultPackageDesc verbosity = tryFindPackageDesc verbosity currentDir---- |Find a package description file in the given directory. Looks for--- @.cabal@ files.-findPackageDesc :: FilePath -- ^Where to look- -> IO (Either String FilePath) -- ^<pkgname>.cabal-findPackageDesc = findPackageDescCwd "."---- | @since 3.4.0.0-findPackageDescCwd- :: FilePath -- ^ project root- -> FilePath -- ^ relative directory- -> IO (Either String FilePath) -- ^ <pkgname>.cabal relative to the project root-findPackageDescCwd cwd dir- = do files <- getDirectoryContents (cwd </> 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 . snd)- [ (dir </> file, cwd </> dir </> file)- | file <- files- , let (name, ext) = splitExtension file- , not (null name) && ext == ".cabal" ]- case map fst cabalFiles of- [] -> return (Left noDesc)- [cabalFile] -> return (Right cabalFile)- multiple -> return (Left $ 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---- |Like 'findPackageDesc', but calls 'die' in case of error.-tryFindPackageDesc :: Verbosity -> FilePath -> IO FilePath-tryFindPackageDesc verbosity dir =- either (die' verbosity) return =<< findPackageDesc dir---- | Like 'findPackageDescCwd', but calls 'die' in case of error.------ @since 3.4.0.0-tryFindPackageDescCwd :: Verbosity -> FilePath -> FilePath -> IO FilePath-tryFindPackageDescCwd verbosity cwd dir =- either (die' verbosity) return =<< findPackageDescCwd cwd dir---- |Find auxiliary package information in the given directory.--- Looks for @.buildinfo@ files.-findHookedPackageDesc- :: Verbosity- -> FilePath -- ^Directory to search- -> IO (Maybe FilePath) -- ^/dir/@\/@/pkgname/@.buildinfo@, if present-findHookedPackageDesc verbosity dir = do- files <- getDirectoryContents dir- buildInfoFiles <- filterM doesFileExist- [ dir </> file- | file <- files- , let (name, ext) = splitExtension file- , not (null name) && ext == buildInfoExt ]- case buildInfoFiles of- [] -> return Nothing- [f] -> return (Just f)- _ -> die' verbosity ("Multiple files with extension " ++ buildInfoExt)--buildInfoExt :: String-buildInfoExt = ".buildinfo"
− Distribution/Simple/Utils/Json.hs
@@ -1,46 +0,0 @@--- | Utility json lib for Cabal--- TODO: Remove it again.-module Distribution.Simple.Utils.Json- ( Json(..)- , renderJson- ) where--data Json = JsonArray [Json]- | JsonBool !Bool- | JsonNull- | JsonNumber !Int- | JsonObject [(String, Json)]- | JsonString !String--renderJson :: Json -> ShowS-renderJson (JsonArray objs) =- surround "[" "]" $ intercalate "," $ map renderJson objs-renderJson (JsonBool True) = showString "true"-renderJson (JsonBool False) = showString "false"-renderJson JsonNull = showString "null"-renderJson (JsonNumber n) = shows n-renderJson (JsonObject attrs) =- surround "{" "}" $ intercalate "," $ map render attrs- where- render (k,v) = (surround "\"" "\"" $ showString' k) . showString ":" . renderJson v-renderJson (JsonString s) = surround "\"" "\"" $ showString' s--surround :: String -> String -> ShowS -> ShowS-surround begin end middle = showString begin . middle . showString end--showString' :: String -> ShowS-showString' xs = showStringWorker xs- where- showStringWorker :: String -> ShowS- showStringWorker ('\"':as) = showString "\\\"" . showStringWorker as- showStringWorker ('\\':as) = showString "\\\\" . showStringWorker as- showStringWorker ('\'':as) = showString "\\\'" . showStringWorker as- showStringWorker (x:as) = showString [x] . showStringWorker as- showStringWorker [] = showString ""--intercalate :: String -> [ShowS] -> ShowS-intercalate sep = go- where- go [] = id- go [x] = x- go (x:xs) = x . showString' sep . go xs
− Distribution/System.hs
@@ -1,275 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}---------------------------------------------------------------------------------- |--- Module : Distribution.System--- Copyright : Duncan Coutts 2007-2008------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Cabal often needs to do slightly different things on specific platforms. You--- 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 \"mingw32\"). So to make it--- more consistent and easy to use we have an 'OS' enumeration.----module Distribution.System (- -- * Operating System- OS(..),- buildOS,-- -- * Machine Architecture- Arch(..),- buildArch,-- -- * Platform is a pair of arch and OS- Platform(..),- buildPlatform,- platformFromTriple,-- -- * Internal- knownOSs,- knownArches,-- -- * Classification- ClassificationStrictness (..),- classifyOS,- classifyArch,- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Control.Applicative (liftA2)--import qualified System.Info (os, arch)-import Distribution.Utils.Generic (lowercase)--import Distribution.Parsec-import Distribution.Pretty--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | How strict to be when classifying strings into the 'OS' and 'Arch' enums.------ The reason we have multiple ways to do the classification is because there--- are two situations where we need to do it.------ For parsing OS and arch names in .cabal files we really want everyone to be--- referring to the same or arch by the same name. Variety is not a virtue--- in this case. We don't mind about case though.------ For the System.Info.os\/arch different Haskell implementations use different--- names for the same or\/arch. Also they tend to distinguish versions of an--- OS\/arch which we just don't care about.------ The 'Compat' classification allows us to recognise aliases that are already--- in common use but it allows us to distinguish them from the canonical name--- which enables us to warn about such deprecated aliases.----data ClassificationStrictness = Permissive | Compat | Strict---- --------------------------------------------------------------- * Operating System--- ---------------------------------------------------------------- | These are the known OS names: Linux, Windows, OSX--- ,FreeBSD, OpenBSD, NetBSD, DragonFly--- ,Solaris, AIX, HPUX, IRIX--- ,HaLVM ,Hurd ,IOS, Android,Ghcjs------ The following aliases can also be used:,--- * Windows aliases: mingw32, win32, cygwin32--- * OSX alias: darwin--- * Hurd alias: gnu--- * FreeBSD alias: kfreebsdgnu--- * Solaris alias: solaris2----data OS = Linux | Windows | OSX -- tier 1 desktop OSs- | FreeBSD | OpenBSD | NetBSD -- other free Unix OSs- | DragonFly- | Solaris | AIX | HPUX | IRIX -- ageing Unix OSs- | HaLVM -- bare metal / VMs / hypervisors- | Hurd -- GNU's microkernel- | IOS | Android -- mobile OSs- | Ghcjs- | OtherOS String- deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)--instance Binary OS-instance Structured OS-instance NFData OS where rnf = genericRnf--knownOSs :: [OS]-knownOSs = [Linux, Windows, OSX- ,FreeBSD, OpenBSD, NetBSD, DragonFly- ,Solaris, AIX, HPUX, IRIX- ,HaLVM- ,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"]-osAliases Compat Solaris = ["solaris2"]-osAliases Permissive Android = ["linux-android", "linux-androideabi", "linux-androideabihf"]-osAliases Compat Android = ["linux-android"]-osAliases _ _ = []--instance Pretty OS where- pretty (OtherOS name) = Disp.text name- pretty other = Disp.text (lowercase (show other))--instance Parsec OS where- parsec = classifyOS Compat <$> parsecIdent----classifyOS :: ClassificationStrictness -> String -> OS-classifyOS strictness s =- fromMaybe (OtherOS s) $ lookup (lowercase s) osMap- where- osMap = [ (name, os)- | os <- knownOSs- , name <- prettyShow os : osAliases strictness os ]--buildOS :: OS-buildOS = classifyOS Permissive System.Info.os---- --------------------------------------------------------------- * Machine Architecture--- ---------------------------------------------------------------- | These are the known Arches: I386, X86_64, PPC, PPC64, Sparc,--- Arm, AArch64, Mips, SH, IA64, S39, Alpha, Hppa, Rs6000, M68k,--- Vax, and JavaScript.------ The following aliases can also be used:--- * PPC alias: powerpc--- * PPC64 alias : powerpc64, powerpc64le--- * Sparc aliases: sparc64, sun4--- * Mips aliases: mipsel, mipseb--- * Arm aliases: armeb, armel--- * AArch64 aliases: arm64----data Arch = I386 | X86_64 | PPC | PPC64 | Sparc- | Arm | AArch64 | Mips | SH- | IA64 | S390- | Alpha | Hppa | Rs6000- | M68k | Vax- | JavaScript- | OtherArch String- deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)--instance Binary Arch-instance Structured Arch-instance NFData Arch where rnf = genericRnf--knownArches :: [Arch]-knownArches = [I386, X86_64, PPC, PPC64, Sparc- ,Arm, AArch64, Mips, SH- ,IA64, S390- ,Alpha, Hppa, Rs6000- ,M68k, Vax- ,JavaScript]--archAliases :: ClassificationStrictness -> Arch -> [String]-archAliases Strict _ = []-archAliases Compat _ = []-archAliases _ PPC = ["powerpc"]-archAliases _ PPC64 = ["powerpc64", "powerpc64le"]-archAliases _ Sparc = ["sparc64", "sun4"]-archAliases _ Mips = ["mipsel", "mipseb"]-archAliases _ Arm = ["armeb", "armel"]-archAliases _ AArch64 = ["arm64"]-archAliases _ _ = []--instance Pretty Arch where- pretty (OtherArch name) = Disp.text name- pretty other = Disp.text (lowercase (show other))--instance Parsec Arch where- parsec = classifyArch Strict <$> parsecIdent--classifyArch :: ClassificationStrictness -> String -> Arch-classifyArch strictness s =- fromMaybe (OtherArch s) $ lookup (lowercase s) archMap- where- archMap = [ (name, arch)- | arch <- knownArches- , name <- prettyShow arch : archAliases strictness arch ]--buildArch :: Arch-buildArch = classifyArch Permissive System.Info.arch---- --------------------------------------------------------------- * Platform--- --------------------------------------------------------------data Platform = Platform Arch OS- deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)--instance Binary Platform-instance Structured Platform-instance NFData Platform where rnf = genericRnf--instance Pretty Platform where- pretty (Platform arch os) = pretty arch <<>> Disp.char '-' <<>> pretty os--instance Parsec Platform where- -- 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.- parsec = do- arch <- parsecDashlessArch- _ <- P.char '-'- os <- parsec- return (Platform arch os)- where- parsecDashlessArch = classifyArch Strict <$> dashlessIdent-- dashlessIdent = liftA2 (:) firstChar rest- where- firstChar = P.satisfy isAlpha- rest = P.munch (\c -> isAlphaNum c || c == '_')---- | The platform Cabal was compiled on. In most cases,--- @LocalBuildInfo.hostPlatform@ should be used instead (the platform we're--- targeting).-buildPlatform :: Platform-buildPlatform = Platform buildArch buildOS---- Utils:--parsecIdent :: CabalParsing m => m String-parsecIdent = (:) <$> firstChar <*> rest- where- firstChar = P.satisfy isAlpha- rest = P.munch (\c -> isAlphaNum c || c == '_' || c == '-')--platformFromTriple :: String -> Maybe Platform-platformFromTriple triple =- either (const Nothing) Just $ explicitEitherParsec parseTriple triple- where parseWord = P.munch1 (\c -> isAlphaNum c || c == '_')- parseTriple = do- arch <- fmap (classifyArch Permissive) parseWord- _ <- P.char '-'- _ <- parseWord -- Skip vendor- _ <- P.char '-'- os <- fmap (classifyOS Permissive) parsecIdent -- OS may have hyphens, like- -- 'nto-qnx'- return $ Platform arch os
− Distribution/TestSuite.hs
@@ -1,102 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.TestSuite--- Copyright : Thomas Tuegel 2010--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This module defines the detailed test suite interface which makes it--- possible to expose individual tests to Cabal or other test agents.--module Distribution.TestSuite- ( TestInstance(..)- , OptionDescr(..)- , OptionType(..)- , Test(..)- , Options- , Progress(..)- , Result(..)- , testGroup- ) where--import Prelude ()-import Distribution.Compat.Prelude--data TestInstance = TestInstance- { run :: IO Progress -- ^ Perform the test.- , name :: String -- ^ A name for the test, unique within a- -- test suite.- , tags :: [String] -- ^ Users can select groups of tests by- -- their tags.- , options :: [OptionDescr] -- ^ Descriptions of the options recognized- -- by this test.- , setOption :: String -> String -> Either String TestInstance- -- ^ Try to set the named option to the given value. Returns an error- -- message if the option is not supported or the value could not be- -- correctly parsed; otherwise, a 'TestInstance' with the option set to- -- the given value is returned.- }--data OptionDescr = OptionDescr- { optionName :: String- , optionDescription :: String -- ^ A human-readable description of the- -- option to guide the user setting it.- , optionType :: OptionType- , optionDefault :: Maybe String- }- deriving (Eq, Read, Show)--data OptionType- = OptionFile- { optionFileMustExist :: Bool- , optionFileIsDir :: Bool- , optionFileExtensions :: [String]- }- | OptionString- { optionStringMultiline :: Bool- }- | OptionNumber- { optionNumberIsInt :: Bool- , optionNumberBounds :: (Maybe String, Maybe String)- }- | OptionBool- | OptionEnum [String]- | OptionSet [String]- | OptionRngSeed- deriving (Eq, Read, Show)--data Test- = Test TestInstance- | Group- { groupName :: String- , concurrently :: Bool- -- ^ If true, then children of this group may be run in parallel.- -- Note that this setting is not inherited by children. In- -- particular, consider a group F with "concurrently = False" that- -- has some children, including a group T with "concurrently =- -- True". The children of group T may be run concurrently with each- -- other, as long as none are run at the same time as any of the- -- direct children of group F.- , groupTests :: [Test]- }- | ExtraOptions [OptionDescr] Test--type Options = [(String, String)]--data Progress = Finished Result- | Progress String (IO Progress)--data Result = Pass- | Fail String- | Error String- deriving (Eq, Read, Show)---- | Create a named group of tests, which are assumed to be safe to run in--- parallel.-testGroup :: String -> [Test] -> Test-testGroup n ts = Group { groupName = n, concurrently = True, groupTests = ts }
− Distribution/Text.hs
@@ -1,12 +0,0 @@--- Since @3.0@ this is a compat module.-module Distribution.Text (display, simpleParse) where-{- {-# DEPRECATED "Use Distribution.Parsec or Distribution.Pretty" #-} -}--import Distribution.Pretty-import Distribution.Parsec--display :: Pretty a => a -> String-display = prettyShow--simpleParse :: Parsec a => String -> Maybe a-simpleParse = simpleParsec
− Distribution/Types/AbiDependency.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.AbiDependency where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty--import qualified Distribution.Compat.CharParsing as P-import qualified Distribution.Package as Package-import qualified Text.PrettyPrint as Disp---- | An ABI dependency is a dependency on a library which also--- records the ABI hash ('abiHash') of the library it depends--- on.------ The primary utility of this is to enable an extra sanity when--- GHC loads libraries: it can check if the dependency has a matching--- ABI and if not, refuse to load this library. This information--- is critical if we are shadowing libraries; differences in the--- ABI hash let us know what packages get shadowed by the new version--- of a package.-data AbiDependency = AbiDependency {- depUnitId :: Package.UnitId,- depAbiHash :: Package.AbiHash- }- deriving (Eq, Generic, Read, Show, Typeable)--instance Pretty AbiDependency where- pretty (AbiDependency uid abi) =- pretty uid <<>> Disp.char '=' <<>> pretty abi--instance Parsec AbiDependency where- parsec = do- uid <- parsec- _ <- P.char '='- abi <- parsec- return (AbiDependency uid abi)--instance Binary AbiDependency-instance Structured AbiDependency-instance NFData AbiDependency where rnf = genericRnf
− Distribution/Types/AbiHash.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Distribution.Types.AbiHash- ( AbiHash, unAbiHash, mkAbiHash- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.ShortText--import qualified Distribution.Compat.CharParsing as P-import Distribution.Pretty-import Distribution.Parsec--import Text.PrettyPrint (text)---- | ABI Hashes------ Use 'mkAbiHash' and 'unAbiHash' to convert from/to a--- 'String'.------ This type is opaque since @Cabal-2.0@------ @since 2.0.0.2-newtype AbiHash = AbiHash ShortText- deriving (Eq, Show, Read, Generic, Typeable)---- | Construct a 'AbiHash' from a 'String'------ 'mkAbiHash' is the inverse to 'unAbiHash'------ Note: No validations are performed to ensure that the resulting--- 'AbiHash' is valid------ @since 2.0.0.2-unAbiHash :: AbiHash -> String-unAbiHash (AbiHash h) = fromShortText h---- | Convert 'AbiHash' to 'String'------ @since 2.0.0.2-mkAbiHash :: String -> AbiHash-mkAbiHash = AbiHash . toShortText---- | 'mkAbiHash'------ @since 2.0.0.2-instance IsString AbiHash where- fromString = mkAbiHash--instance Binary AbiHash-instance Structured AbiHash-instance NFData AbiHash where rnf = genericRnf--instance Pretty AbiHash where- pretty = text . unAbiHash--instance Parsec AbiHash where- parsec = fmap mkAbiHash (P.munch isAlphaNum)
− Distribution/Types/AnnotatedId.hs
@@ -1,34 +0,0 @@-module Distribution.Types.AnnotatedId (- AnnotatedId(..)-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Package-import Distribution.Types.ComponentName---- | An 'AnnotatedId' is a 'ComponentId', 'UnitId', etc.--- which is annotated with some other useful information--- that is useful for printing to users, etc.------ Invariant: if ann_id x == ann_id y, then ann_pid x == ann_pid y--- and ann_cname x == ann_cname y-data AnnotatedId id = AnnotatedId {- ann_pid :: PackageId,- ann_cname :: ComponentName,- ann_id :: id- }- deriving (Show)--instance Eq id => Eq (AnnotatedId id) where- x == y = ann_id x == ann_id y--instance Ord id => Ord (AnnotatedId id) where- compare x y = compare (ann_id x) (ann_id y)--instance Package (AnnotatedId id) where- packageId = ann_pid--instance Functor AnnotatedId where- fmap f (AnnotatedId pid cn x) = AnnotatedId pid cn (f x)
− Distribution/Types/Benchmark.hs
@@ -1,77 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.Benchmark (- Benchmark(..),- emptyBenchmark,- benchmarkType,- benchmarkModules,- benchmarkModulesAutogen-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.BuildInfo-import Distribution.Types.BenchmarkType-import Distribution.Types.BenchmarkInterface-import Distribution.Types.UnqualComponentName--import Distribution.ModuleName--import qualified Distribution.Types.BuildInfo.Lens as L---- | A \"benchmark\" stanza in a cabal file.----data Benchmark = Benchmark {- benchmarkName :: UnqualComponentName,- benchmarkInterface :: BenchmarkInterface,- benchmarkBuildInfo :: BuildInfo- }- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Binary Benchmark-instance Structured Benchmark-instance NFData Benchmark where rnf = genericRnf--instance L.HasBuildInfo Benchmark where- buildInfo f (Benchmark x1 x2 x3) = fmap (\y1 -> Benchmark x1 x2 y1) (f x3)--instance Monoid Benchmark where- mempty = Benchmark {- benchmarkName = mempty,- benchmarkInterface = mempty,- benchmarkBuildInfo = mempty- }- mappend = (<>)--instance Semigroup Benchmark where- a <> b = Benchmark {- benchmarkName = combine' benchmarkName,- benchmarkInterface = combine benchmarkInterface,- benchmarkBuildInfo = combine benchmarkBuildInfo- }- where combine field = field a `mappend` field b- combine' field = case ( unUnqualComponentName $ field a- , unUnqualComponentName $ field b) of- ("", _) -> field b- (_, "") -> field a- (x, y) -> error $ "Ambiguous values for test field: '"- ++ x ++ "' and '" ++ y ++ "'"--emptyBenchmark :: Benchmark-emptyBenchmark = mempty--benchmarkType :: Benchmark -> BenchmarkType-benchmarkType benchmark = case benchmarkInterface benchmark of- BenchmarkExeV10 ver _ -> BenchmarkTypeExe ver- BenchmarkUnsupported benchmarktype -> benchmarktype---- | Get all the module names from a benchmark.-benchmarkModules :: Benchmark -> [ModuleName]-benchmarkModules benchmark = otherModules (benchmarkBuildInfo benchmark)---- | Get all the auto generated module names from a benchmark.--- This are a subset of 'benchmarkModules'.-benchmarkModulesAutogen :: Benchmark -> [ModuleName]-benchmarkModulesAutogen benchmark = autogenModules (benchmarkBuildInfo benchmark)
− Distribution/Types/Benchmark/Lens.hs
@@ -1,27 +0,0 @@-module Distribution.Types.Benchmark.Lens (- Benchmark,- module Distribution.Types.Benchmark.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.Benchmark (Benchmark)-import Distribution.Types.BenchmarkInterface (BenchmarkInterface)-import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.UnqualComponentName (UnqualComponentName)--import qualified Distribution.Types.Benchmark as T--benchmarkName :: Lens' Benchmark UnqualComponentName-benchmarkName f s = fmap (\x -> s { T.benchmarkName = x }) (f (T.benchmarkName s))-{-# INLINE benchmarkName #-}--benchmarkInterface :: Lens' Benchmark BenchmarkInterface-benchmarkInterface f s = fmap (\x -> s { T.benchmarkInterface = x }) (f (T.benchmarkInterface s))-{-# INLINE benchmarkInterface #-}--benchmarkBuildInfo :: Lens' Benchmark BuildInfo-benchmarkBuildInfo f s = fmap (\x -> s { T.benchmarkBuildInfo = x }) (f (T.benchmarkBuildInfo s))-{-# INLINE benchmarkBuildInfo #-}
− Distribution/Types/BenchmarkInterface.hs
@@ -1,46 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.BenchmarkInterface (- BenchmarkInterface(..),-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.BenchmarkType-import Distribution.Version---- | The benchmark interfaces that are currently defined. Each--- benchmark must specify which interface it supports.------ More interfaces may be defined in future, either new revisions or--- totally new interfaces.----data BenchmarkInterface =-- -- | Benchmark interface \"exitcode-stdio-1.0\". The benchmark- -- takes the form of an executable. It returns a zero exit code- -- for success, non-zero for failure. The stdout and stderr- -- channels may be logged. It takes no command line parameters- -- and nothing on stdin.- --- BenchmarkExeV10 Version FilePath-- -- | A benchmark that does not conform to one of the above- -- interfaces for the given reason (e.g. unknown benchmark type).- --- | BenchmarkUnsupported BenchmarkType- deriving (Eq, Generic, Read, Show, Typeable, Data)--instance Binary BenchmarkInterface-instance Structured BenchmarkInterface-instance NFData BenchmarkInterface where rnf = genericRnf--instance Monoid BenchmarkInterface where- mempty = BenchmarkUnsupported (BenchmarkTypeUnknown mempty nullVersion)- mappend = (<>)--instance Semigroup BenchmarkInterface where- a <> (BenchmarkUnsupported _) = a- _ <> b = b
− Distribution/Types/BenchmarkType.hs
@@ -1,40 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--module Distribution.Types.BenchmarkType (- BenchmarkType(..),- knownBenchmarkTypes,-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Version-import Text.PrettyPrint (char, text)---- | The \"benchmark-type\" field in the benchmark stanza.----data BenchmarkType = BenchmarkTypeExe Version- -- ^ \"type: exitcode-stdio-x.y\"- | BenchmarkTypeUnknown String Version- -- ^ Some unknown benchmark type e.g. \"type: foo\"- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Binary BenchmarkType-instance Structured BenchmarkType-instance NFData BenchmarkType where rnf = genericRnf--knownBenchmarkTypes :: [BenchmarkType]-knownBenchmarkTypes = [ BenchmarkTypeExe (mkVersion [1,0]) ]--instance Pretty BenchmarkType where- pretty (BenchmarkTypeExe ver) = text "exitcode-stdio-" <<>> pretty ver- pretty (BenchmarkTypeUnknown name ver) = text name <<>> char '-' <<>> pretty ver--instance Parsec BenchmarkType where- parsec = parsecStandard $ \ver name -> case name of- "exitcode-stdio" -> BenchmarkTypeExe ver- _ -> BenchmarkTypeUnknown name ver
− Distribution/Types/BuildInfo.hs
@@ -1,262 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.BuildInfo (- BuildInfo(..),-- emptyBuildInfo,- allLanguages,- allExtensions,- usedExtensions,- usesTemplateHaskellOrQQ,-- hcOptions,- hcProfOptions,- hcSharedOptions,- hcStaticOptions,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.Mixin-import Distribution.Types.Dependency-import Distribution.Types.ExeDependency-import Distribution.Types.LegacyExeDependency-import Distribution.Types.PkgconfigDependency--import Distribution.ModuleName-import Distribution.Compiler-import Language.Haskell.Extension---- Consider refactoring into executable and library versions.-data BuildInfo = BuildInfo {- -- | component is buildable here- buildable :: Bool,- -- | Tools needed to build this bit.- --- -- This is a legacy field that 'buildToolDepends' largely supersedes.- --- -- Unless use are very sure what you are doing, use the functions in- -- "Distribution.Simple.BuildToolDepends" rather than accessing this- -- field directly.- buildTools :: [LegacyExeDependency],- -- | Haskell tools needed to build this bit- --- -- This field is better than 'buildTools' because it allows one to- -- precisely specify an executable in a package.- --- -- Unless use are very sure what you are doing, use the functions in- -- "Distribution.Simple.BuildToolDepends" rather than accessing this- -- field directly.- buildToolDepends :: [ExeDependency],- cppOptions :: [String], -- ^ options for pre-processing Haskell code- asmOptions :: [String], -- ^ options for assmebler- cmmOptions :: [String], -- ^ options for C-- compiler- ccOptions :: [String], -- ^ options for C compiler- cxxOptions :: [String], -- ^ options for C++ compiler- ldOptions :: [String], -- ^ options for linker- pkgconfigDepends :: [PkgconfigDependency], -- ^ pkg-config packages that are used- frameworks :: [String], -- ^support frameworks for Mac OS X- extraFrameworkDirs:: [String], -- ^ extra locations to find frameworks.- asmSources :: [FilePath], -- ^ Assembly files.- cmmSources :: [FilePath], -- ^ C-- files.- cSources :: [FilePath],- cxxSources :: [FilePath],- jsSources :: [FilePath],- hsSourceDirs :: [FilePath], -- ^ where to look for the Haskell module hierarchy- otherModules :: [ModuleName], -- ^ non-exposed or non-main modules- virtualModules :: [ModuleName], -- ^ exposed modules that do not have a source file (e.g. @GHC.Prim@ from @ghc-prim@ package)- autogenModules :: [ModuleName], -- ^ not present on sdist, Paths_* or user-generated with a custom Setup.hs-- defaultLanguage :: Maybe Language,-- ^ language used when not explicitly specified- otherLanguages :: [Language], -- ^ other languages used within the package- defaultExtensions :: [Extension], -- ^ language extensions used by all modules- otherExtensions :: [Extension], -- ^ other language extensions used within the package- oldExtensions :: [Extension], -- ^ the old extensions field, treated same as 'defaultExtensions'-- extraLibs :: [String], -- ^ what libraries to link with when compiling a program that uses your package- extraGHCiLibs :: [String], -- ^ if present, overrides extraLibs when package is loaded with GHCi.- extraBundledLibs :: [String], -- ^ if present, adds libs to hs-libraries, which become part of the package.- -- Example: the Cffi library shipping with the rts, alognside the HSrts-1.0.a,.o,...- -- Example 2: a library that is being built by a foreing tool (e.g. rust)- -- and copied and registered together with this library. The- -- logic on how this library is built will have to be encoded in a- -- custom Setup for now. Otherwise cabal would need to lear how to- -- call arbitrary library builders.- extraLibFlavours :: [String], -- ^ Hidden Flag. This set of strings, will be appended to all libraries when- -- copying. E.g. [libHS<name>_<flavour> | flavour <- extraLibFlavours]. This- -- should only be needed in very specific cases, e.g. the `rts` package, where- -- there are multiple copies of slightly differently built libs.- extraDynLibFlavours :: [String], -- ^ Hidden Flag. This set of strings will be appended to all /dynamic/- -- libraries when copying. This is particularly useful with the `rts` package,- -- where we want different dynamic flavours of the RTS library to be installed.- extraLibDirs :: [String],- includeDirs :: [FilePath], -- ^directories to find .h files- includes :: [FilePath], -- ^ The .h files to be found in includeDirs- autogenIncludes :: [FilePath], -- ^ The .h files to be generated (e.g. by @autoconf@)- installIncludes :: [FilePath], -- ^ .h files to install with the package- options :: PerCompilerFlavor [String],- profOptions :: PerCompilerFlavor [String],- sharedOptions :: PerCompilerFlavor [String],- staticOptions :: PerCompilerFlavor [String],- customFieldsBI :: [(String,String)], -- ^Custom fields starting- -- with x-, stored in a- -- simple assoc-list.- targetBuildDepends :: [Dependency], -- ^ Dependencies specific to a library or executable target- mixins :: [Mixin]- }- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Binary BuildInfo-instance Structured BuildInfo-instance NFData BuildInfo where rnf = genericRnf--instance Monoid BuildInfo where- mempty = BuildInfo {- buildable = True,- buildTools = [],- buildToolDepends = [],- cppOptions = [],- asmOptions = [],- cmmOptions = [],- ccOptions = [],- cxxOptions = [],- ldOptions = [],- pkgconfigDepends = [],- frameworks = [],- extraFrameworkDirs = [],- asmSources = [],- cmmSources = [],- cSources = [],- cxxSources = [],- jsSources = [],- hsSourceDirs = [],- otherModules = [],- virtualModules = [],- autogenModules = [],- defaultLanguage = Nothing,- otherLanguages = [],- defaultExtensions = [],- otherExtensions = [],- oldExtensions = [],- extraLibs = [],- extraGHCiLibs = [],- extraBundledLibs = [],- extraLibFlavours = [],- extraDynLibFlavours = [],- extraLibDirs = [],- includeDirs = [],- includes = [],- autogenIncludes = [],- installIncludes = [],- options = mempty,- profOptions = mempty,- sharedOptions = mempty,- staticOptions = mempty,- customFieldsBI = [],- targetBuildDepends = [],- mixins = []- }- mappend = (<>)--instance Semigroup BuildInfo where- a <> b = BuildInfo {- buildable = buildable a && buildable b,- buildTools = combine buildTools,- buildToolDepends = combine buildToolDepends,- cppOptions = combine cppOptions,- asmOptions = combine asmOptions,- cmmOptions = combine cmmOptions,- ccOptions = combine ccOptions,- cxxOptions = combine cxxOptions,- ldOptions = combine ldOptions,- pkgconfigDepends = combine pkgconfigDepends,- frameworks = combineNub frameworks,- extraFrameworkDirs = combineNub extraFrameworkDirs,- asmSources = combineNub asmSources,- cmmSources = combineNub cmmSources,- cSources = combineNub cSources,- cxxSources = combineNub cxxSources,- jsSources = combineNub jsSources,- hsSourceDirs = combineNub hsSourceDirs,- otherModules = combineNub otherModules,- virtualModules = combineNub virtualModules,- autogenModules = combineNub autogenModules,- defaultLanguage = combineMby defaultLanguage,- otherLanguages = combineNub otherLanguages,- defaultExtensions = combineNub defaultExtensions,- otherExtensions = combineNub otherExtensions,- oldExtensions = combineNub oldExtensions,- extraLibs = combine extraLibs,- extraGHCiLibs = combine extraGHCiLibs,- extraBundledLibs = combine extraBundledLibs,- extraLibFlavours = combine extraLibFlavours,- extraDynLibFlavours = combine extraDynLibFlavours,- extraLibDirs = combineNub extraLibDirs,- includeDirs = combineNub includeDirs,- includes = combineNub includes,- autogenIncludes = combineNub autogenIncludes,- installIncludes = combineNub installIncludes,- options = combine options,- profOptions = combine profOptions,- sharedOptions = combine sharedOptions,- staticOptions = combine staticOptions,- customFieldsBI = combine customFieldsBI,- targetBuildDepends = combineNub targetBuildDepends,- mixins = combine mixins- }- where- combine field = field a `mappend` field b- combineNub field = nub (combine field)- combineMby field = field b `mplus` field a--emptyBuildInfo :: BuildInfo-emptyBuildInfo = mempty---- | The 'Language's used by this component----allLanguages :: BuildInfo -> [Language]-allLanguages bi = maybeToList (defaultLanguage bi)- ++ otherLanguages bi---- | The 'Extension's that are used somewhere by this component----allExtensions :: BuildInfo -> [Extension]-allExtensions bi = usedExtensions bi- ++ otherExtensions bi---- | The 'Extensions' that are used by all modules in this component----usedExtensions :: BuildInfo -> [Extension]-usedExtensions bi = oldExtensions bi- ++ defaultExtensions bi---- | Whether any modules in this component use Template Haskell or--- Quasi Quotes-usesTemplateHaskellOrQQ :: BuildInfo -> Bool-usesTemplateHaskellOrQQ bi = any p (allExtensions bi)- where- p ex = ex `elem`- [EnableExtension TemplateHaskell, EnableExtension QuasiQuotes]---- |Select options for a particular Haskell compiler.-hcOptions :: CompilerFlavor -> BuildInfo -> [String]-hcOptions = lookupHcOptions options--hcProfOptions :: CompilerFlavor -> BuildInfo -> [String]-hcProfOptions = lookupHcOptions profOptions--hcSharedOptions :: CompilerFlavor -> BuildInfo -> [String]-hcSharedOptions = lookupHcOptions sharedOptions--hcStaticOptions :: CompilerFlavor -> BuildInfo -> [String]-hcStaticOptions = lookupHcOptions staticOptions--lookupHcOptions :: (BuildInfo -> PerCompilerFlavor [String])- -> CompilerFlavor -> BuildInfo -> [String]-lookupHcOptions f hc bi = case f bi of- PerCompilerFlavor ghc ghcjs- | hc == GHC -> ghc- | hc == GHCJS -> ghcjs- | otherwise -> mempty
− Distribution/Types/BuildInfo/Lens.hs
@@ -1,334 +0,0 @@-module Distribution.Types.BuildInfo.Lens (- BuildInfo,- HasBuildInfo (..),- HasBuildInfos (..),- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Compat.Lens--import Distribution.Compiler (PerCompilerFlavor)-import Distribution.ModuleName (ModuleName)-import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.Dependency (Dependency)-import Distribution.Types.ExeDependency (ExeDependency)-import Distribution.Types.LegacyExeDependency (LegacyExeDependency)-import Distribution.Types.Mixin (Mixin)-import Distribution.Types.PkgconfigDependency (PkgconfigDependency)-import Language.Haskell.Extension (Extension, Language)--import qualified Distribution.Types.BuildInfo as T---- | Classy lenses for 'BuildInfo'.-class HasBuildInfo a where- buildInfo :: Lens' a BuildInfo-- buildable :: Lens' a Bool- buildable = buildInfo . buildable- {-# INLINE buildable #-}-- buildTools :: Lens' a [LegacyExeDependency]- buildTools = buildInfo . buildTools- {-# INLINE buildTools #-}-- buildToolDepends :: Lens' a [ExeDependency]- buildToolDepends = buildInfo . buildToolDepends- {-# INLINE buildToolDepends #-}-- cppOptions :: Lens' a [String]- cppOptions = buildInfo . cppOptions- {-# INLINE cppOptions #-}-- asmOptions :: Lens' a [String]- asmOptions = buildInfo . asmOptions- {-# INLINE asmOptions #-}-- cmmOptions :: Lens' a [String]- cmmOptions = buildInfo . cmmOptions- {-# INLINE cmmOptions #-}-- ccOptions :: Lens' a [String]- ccOptions = buildInfo . ccOptions- {-# INLINE ccOptions #-}-- cxxOptions :: Lens' a [String]- cxxOptions = buildInfo . cxxOptions- {-# INLINE cxxOptions #-}-- ldOptions :: Lens' a [String]- ldOptions = buildInfo . ldOptions- {-# INLINE ldOptions #-}-- pkgconfigDepends :: Lens' a [PkgconfigDependency]- pkgconfigDepends = buildInfo . pkgconfigDepends- {-# INLINE pkgconfigDepends #-}-- frameworks :: Lens' a [String]- frameworks = buildInfo . frameworks- {-# INLINE frameworks #-}-- extraFrameworkDirs :: Lens' a [String]- extraFrameworkDirs = buildInfo . extraFrameworkDirs- {-# INLINE extraFrameworkDirs #-}-- asmSources :: Lens' a [FilePath]- asmSources = buildInfo . asmSources- {-# INLINE asmSources #-}-- cmmSources :: Lens' a [FilePath]- cmmSources = buildInfo . cmmSources- {-# INLINE cmmSources #-}-- cSources :: Lens' a [FilePath]- cSources = buildInfo . cSources- {-# INLINE cSources #-}-- cxxSources :: Lens' a [FilePath]- cxxSources = buildInfo . cxxSources- {-# INLINE cxxSources #-}-- jsSources :: Lens' a [FilePath]- jsSources = buildInfo . jsSources- {-# INLINE jsSources #-}-- hsSourceDirs :: Lens' a [FilePath]- hsSourceDirs = buildInfo . hsSourceDirs- {-# INLINE hsSourceDirs #-}-- otherModules :: Lens' a [ModuleName]- otherModules = buildInfo . otherModules- {-# INLINE otherModules #-}-- virtualModules :: Lens' a [ModuleName]- virtualModules = buildInfo . virtualModules- {-# INLINE virtualModules #-}-- autogenModules :: Lens' a [ModuleName]- autogenModules = buildInfo . autogenModules- {-# INLINE autogenModules #-}-- defaultLanguage :: Lens' a (Maybe Language)- defaultLanguage = buildInfo . defaultLanguage- {-# INLINE defaultLanguage #-}-- otherLanguages :: Lens' a [Language]- otherLanguages = buildInfo . otherLanguages- {-# INLINE otherLanguages #-}-- defaultExtensions :: Lens' a [Extension]- defaultExtensions = buildInfo . defaultExtensions- {-# INLINE defaultExtensions #-}-- otherExtensions :: Lens' a [Extension]- otherExtensions = buildInfo . otherExtensions- {-# INLINE otherExtensions #-}-- oldExtensions :: Lens' a [Extension]- oldExtensions = buildInfo . oldExtensions- {-# INLINE oldExtensions #-}-- extraLibs :: Lens' a [String]- extraLibs = buildInfo . extraLibs- {-# INLINE extraLibs #-}-- extraGHCiLibs :: Lens' a [String]- extraGHCiLibs = buildInfo . extraGHCiLibs- {-# INLINE extraGHCiLibs #-}-- extraBundledLibs :: Lens' a [String]- extraBundledLibs = buildInfo . extraBundledLibs- {-# INLINE extraBundledLibs #-}-- extraLibFlavours :: Lens' a [String]- extraLibFlavours = buildInfo . extraLibFlavours- {-# INLINE extraLibFlavours #-}-- extraDynLibFlavours :: Lens' a [String]- extraDynLibFlavours = buildInfo . extraDynLibFlavours- {-# INLINE extraDynLibFlavours #-}-- extraLibDirs :: Lens' a [String]- extraLibDirs = buildInfo . extraLibDirs- {-# INLINE extraLibDirs #-}-- includeDirs :: Lens' a [FilePath]- includeDirs = buildInfo . includeDirs- {-# INLINE includeDirs #-}-- includes :: Lens' a [FilePath]- includes = buildInfo . includes- {-# INLINE includes #-}-- autogenIncludes :: Lens' a [FilePath]- autogenIncludes = buildInfo . autogenIncludes- {-# INLINE autogenIncludes #-}-- installIncludes :: Lens' a [FilePath]- installIncludes = buildInfo . installIncludes- {-# INLINE installIncludes #-}-- options :: Lens' a (PerCompilerFlavor [String])- options = buildInfo . options- {-# INLINE options #-}-- profOptions :: Lens' a (PerCompilerFlavor [String])- profOptions = buildInfo . profOptions- {-# INLINE profOptions #-}-- sharedOptions :: Lens' a (PerCompilerFlavor [String])- sharedOptions = buildInfo . sharedOptions- {-# INLINE sharedOptions #-}-- staticOptions :: Lens' a (PerCompilerFlavor [String])- staticOptions = buildInfo . staticOptions- {-# INLINE staticOptions #-}-- customFieldsBI :: Lens' a [(String,String)]- customFieldsBI = buildInfo . customFieldsBI- {-# INLINE customFieldsBI #-}-- targetBuildDepends :: Lens' a [Dependency]- targetBuildDepends = buildInfo . targetBuildDepends- {-# INLINE targetBuildDepends #-}-- mixins :: Lens' a [Mixin]- mixins = buildInfo . mixins- {-# INLINE mixins #-}---instance HasBuildInfo BuildInfo where- buildInfo = id- {-# INLINE buildInfo #-}-- buildable f s = fmap (\x -> s { T.buildable = x }) (f (T.buildable s))- {-# INLINE buildable #-}-- buildTools f s = fmap (\x -> s { T.buildTools = x }) (f (T.buildTools s))- {-# INLINE buildTools #-}-- buildToolDepends f s = fmap (\x -> s { T.buildToolDepends = x }) (f (T.buildToolDepends s))- {-# INLINE buildToolDepends #-}-- cppOptions f s = fmap (\x -> s { T.cppOptions = x }) (f (T.cppOptions s))- {-# INLINE cppOptions #-}-- asmOptions f s = fmap (\x -> s { T.asmOptions = x }) (f (T.asmOptions s))- {-# INLINE asmOptions #-}-- cmmOptions f s = fmap (\x -> s { T.cmmOptions = x }) (f (T.cmmOptions s))- {-# INLINE cmmOptions #-}-- ccOptions f s = fmap (\x -> s { T.ccOptions = x }) (f (T.ccOptions s))- {-# INLINE ccOptions #-}-- cxxOptions f s = fmap (\x -> s { T.cxxOptions = x }) (f (T.cxxOptions s))- {-# INLINE cxxOptions #-}-- ldOptions f s = fmap (\x -> s { T.ldOptions = x }) (f (T.ldOptions s))- {-# INLINE ldOptions #-}-- pkgconfigDepends f s = fmap (\x -> s { T.pkgconfigDepends = x }) (f (T.pkgconfigDepends s))- {-# INLINE pkgconfigDepends #-}-- frameworks f s = fmap (\x -> s { T.frameworks = x }) (f (T.frameworks s))- {-# INLINE frameworks #-}-- extraFrameworkDirs f s = fmap (\x -> s { T.extraFrameworkDirs = x }) (f (T.extraFrameworkDirs s))- {-# INLINE extraFrameworkDirs #-}-- asmSources f s = fmap (\x -> s { T.asmSources = x }) (f (T.asmSources s))- {-# INLINE asmSources #-}-- cmmSources f s = fmap (\x -> s { T.cmmSources = x }) (f (T.cmmSources s))- {-# INLINE cmmSources #-}-- cSources f s = fmap (\x -> s { T.cSources = x }) (f (T.cSources s))- {-# INLINE cSources #-}-- cxxSources f s = fmap (\x -> s { T.cSources = x }) (f (T.cxxSources s))- {-# INLINE cxxSources #-}-- jsSources f s = fmap (\x -> s { T.jsSources = x }) (f (T.jsSources s))- {-# INLINE jsSources #-}-- hsSourceDirs f s = fmap (\x -> s { T.hsSourceDirs = x }) (f (T.hsSourceDirs s))- {-# INLINE hsSourceDirs #-}-- otherModules f s = fmap (\x -> s { T.otherModules = x }) (f (T.otherModules s))- {-# INLINE otherModules #-}-- virtualModules f s = fmap (\x -> s { T.virtualModules = x }) (f (T.virtualModules s))- {-# INLINE virtualModules #-}-- autogenModules f s = fmap (\x -> s { T.autogenModules = x }) (f (T.autogenModules s))- {-# INLINE autogenModules #-}-- defaultLanguage f s = fmap (\x -> s { T.defaultLanguage = x }) (f (T.defaultLanguage s))- {-# INLINE defaultLanguage #-}-- otherLanguages f s = fmap (\x -> s { T.otherLanguages = x }) (f (T.otherLanguages s))- {-# INLINE otherLanguages #-}-- defaultExtensions f s = fmap (\x -> s { T.defaultExtensions = x }) (f (T.defaultExtensions s))- {-# INLINE defaultExtensions #-}-- otherExtensions f s = fmap (\x -> s { T.otherExtensions = x }) (f (T.otherExtensions s))- {-# INLINE otherExtensions #-}-- oldExtensions f s = fmap (\x -> s { T.oldExtensions = x }) (f (T.oldExtensions s))- {-# INLINE oldExtensions #-}-- extraLibs f s = fmap (\x -> s { T.extraLibs = x }) (f (T.extraLibs s))- {-# INLINE extraLibs #-}-- extraGHCiLibs f s = fmap (\x -> s { T.extraGHCiLibs = x }) (f (T.extraGHCiLibs s))- {-# INLINE extraGHCiLibs #-}-- extraBundledLibs f s = fmap (\x -> s { T.extraBundledLibs = x }) (f (T.extraBundledLibs s))- {-# INLINE extraBundledLibs #-}-- extraLibFlavours f s = fmap (\x -> s { T.extraLibFlavours = x }) (f (T.extraLibFlavours s))- {-# INLINE extraLibFlavours #-}-- extraDynLibFlavours f s = fmap (\x -> s { T.extraDynLibFlavours = x}) (f (T.extraDynLibFlavours s))- {-# INLINE extraDynLibFlavours #-}-- extraLibDirs f s = fmap (\x -> s { T.extraLibDirs = x }) (f (T.extraLibDirs s))- {-# INLINE extraLibDirs #-}-- includeDirs f s = fmap (\x -> s { T.includeDirs = x }) (f (T.includeDirs s))- {-# INLINE includeDirs #-}-- includes f s = fmap (\x -> s { T.includes = x }) (f (T.includes s))- {-# INLINE includes #-}-- autogenIncludes f s = fmap (\x -> s { T.autogenIncludes = x }) (f (T.autogenIncludes s))- {-# INLINE autogenIncludes #-}-- installIncludes f s = fmap (\x -> s { T.installIncludes = x }) (f (T.installIncludes s))- {-# INLINE installIncludes #-}-- options f s = fmap (\x -> s { T.options = x }) (f (T.options s))- {-# INLINE options #-}-- profOptions f s = fmap (\x -> s { T.profOptions = x }) (f (T.profOptions s))- {-# INLINE profOptions #-}-- sharedOptions f s = fmap (\x -> s { T.sharedOptions = x }) (f (T.sharedOptions s))- {-# INLINE sharedOptions #-}-- staticOptions f s = fmap (\x -> s { T.staticOptions = x }) (f (T.staticOptions s))- {-# INLINE staticOptions #-}-- customFieldsBI f s = fmap (\x -> s { T.customFieldsBI = x }) (f (T.customFieldsBI s))- {-# INLINE customFieldsBI #-}-- targetBuildDepends f s = fmap (\x -> s { T.targetBuildDepends = x }) (f (T.targetBuildDepends s))- {-# INLINE targetBuildDepends #-}-- mixins f s = fmap (\x -> s { T.mixins = x }) (f (T.mixins s))- {-# INLINE mixins #-}--class HasBuildInfos a where- traverseBuildInfos :: Traversal' a BuildInfo
− Distribution/Types/BuildType.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--module Distribution.Types.BuildType (- BuildType(..),- knownBuildTypes,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.CabalSpecVersion (CabalSpecVersion (..))-import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | The type of build system used by this package.-data BuildType- = Simple -- ^ calls @Distribution.Simple.defaultMain@- | Configure -- ^ calls @Distribution.Simple.defaultMainWithHooks defaultUserHooks@,- -- which invokes @configure@ to generate additional build- -- information used by later phases.- | Make -- ^ calls @Distribution.Make.defaultMain@- | Custom -- ^ uses user-supplied @Setup.hs@ or @Setup.lhs@ (default)- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Binary BuildType-instance Structured BuildType-instance NFData BuildType where rnf = genericRnf--knownBuildTypes :: [BuildType]-knownBuildTypes = [Simple, Configure, Make, Custom]--instance Pretty BuildType where- pretty = Disp.text . show--instance Parsec BuildType where- parsec = do- name <- P.munch1 isAlphaNum- case name of- "Simple" -> return Simple- "Configure" -> return Configure- "Custom" -> return Custom- "Make" -> return Make- "Default" -> do- v <- askCabalSpecVersion- if v <= CabalSpecV1_18 -- oldest version needing this, based on hackage-tests- then do- parsecWarning PWTBuildTypeDefault "build-type: Default is parsed as Custom for legacy reasons. See https://github.com/haskell/cabal/issues/5020"- return Custom- else fail ("unknown build-type: '" ++ name ++ "'")- _ -> fail ("unknown build-type: '" ++ name ++ "'")
− Distribution/Types/Component.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.Component (- Component(..),- foldComponent,- componentBuildInfo,- componentBuildable,- componentName,- partitionComponents,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.Library-import Distribution.Types.ForeignLib-import Distribution.Types.Executable-import Distribution.Types.TestSuite-import Distribution.Types.Benchmark--import Distribution.Types.ComponentName-import Distribution.Types.BuildInfo--import qualified Distribution.Types.BuildInfo.Lens as L--data Component = CLib Library- | CFLib ForeignLib- | CExe Executable- | CTest TestSuite- | CBench Benchmark- deriving (Show, Eq, Read)--instance Semigroup Component where- CLib l <> CLib l' = CLib (l <> l')- CFLib l <> CFLib l' = CFLib (l <> l')- CExe e <> CExe e' = CExe (e <> e')- CTest t <> CTest t' = CTest (t <> t')- CBench b <> CBench b' = CBench (b <> b')- _ <> _ = error "Cannot merge Component"--instance L.HasBuildInfo Component where- buildInfo f (CLib l) = CLib <$> L.buildInfo f l- buildInfo f (CFLib l) = CFLib <$> L.buildInfo f l- buildInfo f (CExe e) = CExe <$> L.buildInfo f e- buildInfo f (CTest t) = CTest <$> L.buildInfo f t- buildInfo f (CBench b) = CBench <$> L.buildInfo f b--foldComponent :: (Library -> a)- -> (ForeignLib -> a)- -> (Executable -> a)- -> (TestSuite -> a)- -> (Benchmark -> a)- -> Component- -> a-foldComponent f _ _ _ _ (CLib lib) = f lib-foldComponent _ f _ _ _ (CFLib flib)= f flib-foldComponent _ _ f _ _ (CExe exe) = f exe-foldComponent _ _ _ f _ (CTest tst) = f tst-foldComponent _ _ _ _ f (CBench bch) = f bch--componentBuildInfo :: Component -> BuildInfo-componentBuildInfo =- foldComponent libBuildInfo foreignLibBuildInfo buildInfo testBuildInfo benchmarkBuildInfo---- | Is a component buildable (i.e., not marked with @buildable: False@)?--- See also this note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".------ @since 2.0.0.2----componentBuildable :: Component -> Bool-componentBuildable = buildable . componentBuildInfo--componentName :: Component -> ComponentName-componentName =- foldComponent (CLibName . libName)- (CFLibName . foreignLibName)- (CExeName . exeName)- (CTestName . testName)- (CBenchName . benchmarkName)--partitionComponents- :: [Component]- -> ([Library], [ForeignLib], [Executable], [TestSuite], [Benchmark])-partitionComponents = foldr (foldComponent fa fb fc fd fe) ([],[],[],[],[])- where- fa x ~(a,b,c,d,e) = (x:a,b,c,d,e)- fb x ~(a,b,c,d,e) = (a,x:b,c,d,e)- fc x ~(a,b,c,d,e) = (a,b,x:c,d,e)- fd x ~(a,b,c,d,e) = (a,b,c,x:d,e)- fe x ~(a,b,c,d,e) = (a,b,c,d,x:e)
− Distribution/Types/ComponentId.hs
@@ -1,69 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Distribution.Types.ComponentId- ( ComponentId, unComponentId, mkComponentId- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.ShortText--import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint (text)---- | A 'ComponentId' uniquely identifies the transitive source--- code closure of a component (i.e. libraries, executables).------ For non-Backpack components, this corresponds one to one with--- the 'UnitId', which serves as the basis for install paths,--- linker symbols, etc.------ Use 'mkComponentId' and 'unComponentId' to convert from/to a--- 'String'.------ This type is opaque since @Cabal-2.0@------ @since 2.0.0.2-newtype ComponentId = ComponentId ShortText- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)---- | Construct a 'ComponentId' from a 'String'------ 'mkComponentId' is the inverse to 'unComponentId'------ Note: No validations are performed to ensure that the resulting--- 'ComponentId' is valid------ @since 2.0.0.2-mkComponentId :: String -> ComponentId-mkComponentId = ComponentId . toShortText---- | Convert 'ComponentId' to 'String'------ @since 2.0.0.2-unComponentId :: ComponentId -> String-unComponentId (ComponentId s) = fromShortText s---- | 'mkComponentId'------ @since 2.0.0.2-instance IsString ComponentId where- fromString = mkComponentId--instance Binary ComponentId-instance Structured ComponentId--instance Pretty ComponentId where- pretty = text . unComponentId--instance Parsec ComponentId where- parsec = mkComponentId `fmap` P.munch1 abi_char- where abi_char c = isAlphaNum c || c `elem` "-_."--instance NFData ComponentId where- rnf = rnf . unComponentId
− Distribution/Types/ComponentInclude.hs
@@ -1,32 +0,0 @@-module Distribution.Types.ComponentInclude (- ComponentInclude(..),- ci_id,- ci_pkgid,- ci_cname-) where--import Distribution.Types.PackageId-import Distribution.Types.ComponentName-import Distribution.Types.AnnotatedId---- Once ci_id is refined to an 'OpenUnitId' or 'DefUnitId',--- the 'includeRequiresRn' is not so useful (because it--- includes the requirements renaming that is no longer--- needed); use 'ci_prov_renaming' instead.-data ComponentInclude id rn = ComponentInclude {- ci_ann_id :: AnnotatedId id,- ci_renaming :: rn,- -- | Did this come from an entry in @mixins@, or- -- was implicitly generated by @build-depends@?- ci_implicit :: Bool- }--ci_id :: ComponentInclude id rn -> id-ci_id = ann_id . ci_ann_id--ci_pkgid :: ComponentInclude id rn -> PackageId-ci_pkgid = ann_pid . ci_ann_id---- | This should always return 'CLibName' or 'CSubLibName'-ci_cname :: ComponentInclude id rn -> ComponentName-ci_cname = ann_cname . ci_ann_id
− Distribution/Types/ComponentLocalBuildInfo.hs
@@ -1,129 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE TypeFamilies #-}--module Distribution.Types.ComponentLocalBuildInfo (- ComponentLocalBuildInfo(..),- componentIsIndefinite,- maybeComponentInstantiatedWith,- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.ModuleName--import Distribution.Backpack-import Distribution.Compat.Graph-import Distribution.Types.ComponentId-import Distribution.Types.MungedPackageId-import Distribution.Types.UnitId-import Distribution.Types.ComponentName-import Distribution.Types.MungedPackageName-import Distribution.Types.ModuleRenaming--import qualified Distribution.InstalledPackageInfo as Installed---- | The first five fields are common across all algebraic variants.-data ComponentLocalBuildInfo- = LibComponentLocalBuildInfo {- -- | It would be very convenient to store the literal Library here,- -- but if we do that, it will get serialized (via the Binary)- -- instance twice. So instead we just provide the ComponentName,- -- which can be used to find the Component in the- -- PackageDescription. NB: eventually, this will NOT uniquely- -- identify the ComponentLocalBuildInfo.- componentLocalName :: ComponentName,- -- | The computed 'ComponentId' of this component.- componentComponentId :: ComponentId,- -- | The computed 'UnitId' which uniquely identifies this- -- component. Might be hashed.- componentUnitId :: UnitId,- -- | Is this an indefinite component (i.e. has unfilled holes)?- componentIsIndefinite_ :: Bool,- -- | How the component was instantiated- componentInstantiatedWith :: [(ModuleName, OpenModule)],- -- | Resolved internal and external package dependencies for this component.- -- 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 :: [(UnitId, MungedPackageId)],- -- | The set of packages that are brought into scope during- -- compilation, including a 'ModuleRenaming' which may used- -- to hide or rename modules. This is what gets translated into- -- @-package-id@ arguments. This is a modernized version of- -- 'componentPackageDeps', which is kept around for BC purposes.- componentIncludes :: [(OpenUnitId, ModuleRenaming)],- componentExeDeps :: [UnitId],- -- | The internal dependencies which induce a graph on the- -- 'ComponentLocalBuildInfo' of this package. This does NOT- -- coincide with 'componentPackageDeps' because it ALSO records- -- 'build-tool' dependencies on executables. Maybe one day- -- @cabal-install@ will also handle these correctly too!- componentInternalDeps :: [UnitId],- -- | Compatibility "package key" that we pass to older versions of GHC.- componentCompatPackageKey :: String,- -- | Compatibility "package name" that we register this component as.- componentCompatPackageName :: MungedPackageName,- -- | A list of exposed modules (either defined in this component,- -- or reexported from another component.)- componentExposedModules :: [Installed.ExposedModule],- -- | Convenience field, specifying whether or not this is the- -- "public library" that has the same name as the package.- componentIsPublic :: Bool- }- -- TODO: refactor all these duplicates- | FLibComponentLocalBuildInfo {- componentLocalName :: ComponentName,- componentComponentId :: ComponentId,- componentUnitId :: UnitId,- componentPackageDeps :: [(UnitId, MungedPackageId)],- componentIncludes :: [(OpenUnitId, ModuleRenaming)],- componentExeDeps :: [UnitId],- componentInternalDeps :: [UnitId]- }- | ExeComponentLocalBuildInfo {- componentLocalName :: ComponentName,- componentComponentId :: ComponentId,- componentUnitId :: UnitId,- componentPackageDeps :: [(UnitId, MungedPackageId)],- componentIncludes :: [(OpenUnitId, ModuleRenaming)],- componentExeDeps :: [UnitId],- componentInternalDeps :: [UnitId]- }- | TestComponentLocalBuildInfo {- componentLocalName :: ComponentName,- componentComponentId :: ComponentId,- componentUnitId :: UnitId,- componentPackageDeps :: [(UnitId, MungedPackageId)],- componentIncludes :: [(OpenUnitId, ModuleRenaming)],- componentExeDeps :: [UnitId],- componentInternalDeps :: [UnitId]-- }- | BenchComponentLocalBuildInfo {- componentLocalName :: ComponentName,- componentComponentId :: ComponentId,- componentUnitId :: UnitId,- componentPackageDeps :: [(UnitId, MungedPackageId)],- componentIncludes :: [(OpenUnitId, ModuleRenaming)],- componentExeDeps :: [UnitId],- componentInternalDeps :: [UnitId]- }- deriving (Generic, Read, Show, Typeable)--instance Binary ComponentLocalBuildInfo-instance Structured ComponentLocalBuildInfo--instance IsNode ComponentLocalBuildInfo where- type Key ComponentLocalBuildInfo = UnitId- nodeKey = componentUnitId- nodeNeighbors = componentInternalDeps--componentIsIndefinite :: ComponentLocalBuildInfo -> Bool-componentIsIndefinite LibComponentLocalBuildInfo{ componentIsIndefinite_ = b } = b-componentIsIndefinite _ = False--maybeComponentInstantiatedWith :: ComponentLocalBuildInfo -> Maybe [(ModuleName, OpenModule)]-maybeComponentInstantiatedWith- LibComponentLocalBuildInfo { componentInstantiatedWith = insts } = Just insts-maybeComponentInstantiatedWith _ = Nothing
− Distribution/Types/ComponentName.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.ComponentName (- ComponentName(..),- showComponentName,- componentNameStanza,- componentNameString,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.UnqualComponentName-import Distribution.Types.LibraryName-import Distribution.Pretty-import Distribution.Parsec--import qualified Text.PrettyPrint as Disp-import qualified Distribution.Compat.CharParsing as P---- Libraries live in a separate namespace, so must distinguish-data ComponentName = CLibName LibraryName- | CFLibName UnqualComponentName- | CExeName UnqualComponentName- | CTestName UnqualComponentName- | CBenchName UnqualComponentName- deriving (Eq, Generic, Ord, Read, Show, Typeable)--instance Binary ComponentName-instance Structured ComponentName---- Build-target-ish syntax-instance Pretty ComponentName where- pretty (CLibName lib) = prettyLibraryNameComponent lib- pretty (CFLibName str) = Disp.text "flib:" <<>> pretty str- pretty (CExeName str) = Disp.text "exe:" <<>> pretty str- pretty (CTestName str) = Disp.text "test:" <<>> pretty str- pretty (CBenchName str) = Disp.text "bench:" <<>> pretty str--instance Parsec ComponentName where- -- note: this works as lib/flib/... all start with different character!- parsec = parseComposite <|> parseLib- where- parseLib = CLibName <$> parsecLibraryNameComponent- parseComposite = do- ctor <- P.choice- [ P.string "flib:" >> return CFLibName- , P.string "exe:" >> return CExeName- , P.string "bench:" >> return CBenchName- , P.string "test:" >> return CTestName- ]- ctor <$> parsec--showComponentName :: ComponentName -> String-showComponentName (CLibName lib) = showLibraryName lib-showComponentName (CFLibName name) = "foreign library '" ++ prettyShow name ++ "'"-showComponentName (CExeName name) = "executable '" ++ prettyShow name ++ "'"-showComponentName (CTestName name) = "test suite '" ++ prettyShow name ++ "'"-showComponentName (CBenchName name) = "benchmark '" ++ prettyShow name ++ "'"--componentNameStanza :: ComponentName -> String-componentNameStanza (CLibName lib) = libraryNameStanza lib-componentNameStanza (CFLibName name) = "foreign-library " ++ prettyShow name-componentNameStanza (CExeName name) = "executable " ++ prettyShow name-componentNameStanza (CTestName name) = "test-suite " ++ prettyShow name-componentNameStanza (CBenchName name) = "benchmark " ++ prettyShow name---- | This gets the underlying unqualified component name. In fact, it is--- guaranteed to uniquely identify a component, returning--- @Nothing@ if the 'ComponentName' was for the public--- library.-componentNameString :: ComponentName -> Maybe UnqualComponentName-componentNameString (CLibName lib) = libraryNameString lib-componentNameString (CFLibName n) = Just n-componentNameString (CExeName n) = Just n-componentNameString (CTestName n) = Just n-componentNameString (CBenchName n) = Just n
− Distribution/Types/ComponentRequestedSpec.hs
@@ -1,127 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.ComponentRequestedSpec (- -- $buildable_vs_enabled_components-- ComponentRequestedSpec(..),- ComponentDisabledReason(..),-- defaultComponentRequestedSpec,- componentNameRequested,-- componentEnabled,- componentDisabledReason,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.Component -- TODO: maybe remove me?-import Distribution.Types.ComponentName--import Distribution.Pretty (prettyShow)---- $buildable_vs_enabled_components--- #buildable_vs_enabled_components#------ = Note: Buildable versus requested versus enabled components--- What's the difference between a buildable component (ala--- 'componentBuildable'), a requested component--- (ala 'componentNameRequested'), and an enabled component (ala--- 'componentEnabled')?------ A component is __buildable__ if, after resolving flags and--- conditionals, there is no @buildable: False@ property in it.--- This is a /static/ property that arises from the--- Cabal file and the package description flattening; once we have--- a 'PackageDescription' buildability is known.------ A component is __requested__ if a user specified, via a--- the flags and arguments passed to configure, that it should be--- built. E.g., @--enable-tests@ or @--enable-benchmarks@ request--- all tests and benchmarks, if they are provided. What is requested--- can be read off directly from 'ComponentRequestedSpec'. A requested--- component is not always buildable; e.g., a user may @--enable-tests@--- but one of the test suites may have @buildable: False@.------ A component is __enabled__ if it is BOTH buildable--- and requested. Once we have a 'LocalBuildInfo', whether or not a--- component is enabled is known.------ Generally speaking, most Cabal API code cares if a component--- is enabled. (For example, if you want to run a preprocessor on each--- component prior to building them, you want to run this on each--- /enabled/ component.)------ Note that post-configuration, you will generally not see a--- non-buildable 'Component'. This is because 'flattenPD' will drop--- any such components from 'PackageDescription'. See #3858 for--- an example where this causes problems.---- | Describes what components are enabled by user-interaction.--- See also this note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".------ @since 2.0.0.2-data ComponentRequestedSpec- = ComponentRequestedSpec { testsRequested :: Bool- , benchmarksRequested :: Bool }- | OneComponentRequestedSpec ComponentName- deriving (Generic, Read, Show, Eq, Typeable)--instance Binary ComponentRequestedSpec-instance Structured ComponentRequestedSpec---- | The default set of enabled components. Historically tests and--- benchmarks are NOT enabled by default.------ @since 2.0.0.2-defaultComponentRequestedSpec :: ComponentRequestedSpec-defaultComponentRequestedSpec = ComponentRequestedSpec False False---- | Is this component enabled? See also this note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".------ @since 2.0.0.2-componentEnabled :: ComponentRequestedSpec -> Component -> Bool-componentEnabled enabled = isNothing . componentDisabledReason enabled---- | Is this component name enabled? See also this note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".------ @since 2.0.0.2-componentNameRequested :: ComponentRequestedSpec -> ComponentName -> Bool-componentNameRequested enabled = isNothing . componentNameNotRequestedReason enabled---- | Is this component disabled, and if so, why?------ @since 2.0.0.2-componentDisabledReason :: ComponentRequestedSpec -> Component- -> Maybe ComponentDisabledReason-componentDisabledReason enabled comp- | not (componentBuildable comp) = Just DisabledComponent- | otherwise = componentNameNotRequestedReason enabled (componentName comp)---- | Is this component name disabled, and if so, why?------ @since 2.0.0.2-componentNameNotRequestedReason :: ComponentRequestedSpec -> ComponentName- -> Maybe ComponentDisabledReason-componentNameNotRequestedReason- ComponentRequestedSpec{ testsRequested = False } (CTestName _)- = Just DisabledAllTests-componentNameNotRequestedReason- ComponentRequestedSpec{ benchmarksRequested = False } (CBenchName _)- = Just DisabledAllBenchmarks-componentNameNotRequestedReason ComponentRequestedSpec{} _ = Nothing-componentNameNotRequestedReason (OneComponentRequestedSpec cname) c- | c == cname = Nothing- | otherwise = Just (DisabledAllButOne (prettyShow cname))---- | A reason explaining why a component is disabled.------ @since 2.0.0.2-data ComponentDisabledReason = DisabledComponent- | DisabledAllTests- | DisabledAllBenchmarks- | DisabledAllButOne String
− Distribution/Types/CondTree.hs
@@ -1,181 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Distribution.Types.CondTree (- CondTree(..),- CondBranch(..),- condIfThen,- condIfThenElse,- mapCondTree,- mapTreeConstrs,- mapTreeConds,- mapTreeData,- traverseCondTreeV,- traverseCondBranchV,- traverseCondTreeC,- traverseCondBranchC,- extractCondition,- simplifyCondTree,- ignoreConditions,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.Condition--import qualified Distribution.Compat.Lens as L----- | A 'CondTree' is used to represent the conditional structure of--- a Cabal file, reflecting a syntax element subject to constraints,--- and then any number of sub-elements which may be enabled subject--- to some condition. Both @a@ and @c@ are usually 'Monoid's.------ To be more concrete, consider the following fragment of a @Cabal@--- file:------ @--- build-depends: base >= 4.0--- if flag(extra)--- build-depends: base >= 4.2--- @------ One way to represent this is to have @'CondTree' 'ConfVar'--- ['Dependency'] 'BuildInfo'@. Here, 'condTreeData' represents--- the actual fields which are not behind any conditional, while--- 'condTreeComponents' recursively records any further fields--- which are behind a conditional. 'condTreeConstraints' records--- the constraints (in this case, @base >= 4.0@) which would--- be applied if you use this syntax; in general, this is--- derived off of 'targetBuildInfo' (perhaps a good refactoring--- would be to convert this into an opaque type, with a smart--- constructor that pre-computes the dependencies.)----data CondTree v c a = CondNode- { condTreeData :: a- , condTreeConstraints :: c- , condTreeComponents :: [CondBranch v c a]- }- deriving (Show, Eq, Typeable, Data, Generic, Functor, Foldable, Traversable)--instance (Binary v, Binary c, Binary a) => Binary (CondTree v c a)-instance (Structured v, Structured c, Structured a) => Structured (CondTree v c a)-instance (NFData v, NFData c, NFData a) => NFData (CondTree v c a) where rnf = genericRnf---- | A 'CondBranch' represents a conditional branch, e.g., @if--- flag(foo)@ on some syntax @a@. It also has an optional false--- branch.----data CondBranch v c a = CondBranch- { condBranchCondition :: Condition v- , condBranchIfTrue :: CondTree v c a- , condBranchIfFalse :: Maybe (CondTree v c a)- }- deriving (Show, Eq, Typeable, Data, Generic, Functor, Traversable)---- This instance is written by hand because GHC 8.0.1/8.0.2 infinite--- loops when trying to derive it with optimizations. See--- https://gitlab.haskell.org/ghc/ghc/-/issues/13056-instance Foldable (CondBranch v c) where- foldMap f (CondBranch _ c Nothing) = foldMap f c- foldMap f (CondBranch _ c (Just a)) = foldMap f c `mappend` foldMap f a--instance (Binary v, Binary c, Binary a) => Binary (CondBranch v c a)-instance (Structured v, Structured c, Structured a) => Structured (CondBranch v c a)-instance (NFData v, NFData c, NFData a) => NFData (CondBranch v c a) where rnf = genericRnf--condIfThen :: Condition v -> CondTree v c a -> CondBranch v c a-condIfThen c t = CondBranch c t Nothing--condIfThenElse :: Condition v -> CondTree v c a -> CondTree v c a -> CondBranch v c a-condIfThenElse c t e = CondBranch c t (Just e)--mapCondTree :: (a -> b) -> (c -> d) -> (Condition v -> Condition w)- -> CondTree v c a -> CondTree w d b-mapCondTree fa fc fcnd (CondNode a c ifs) =- CondNode (fa a) (fc c) (map g ifs)- where- g (CondBranch cnd t me)- = CondBranch (fcnd cnd)- (mapCondTree fa fc fcnd t)- (fmap (mapCondTree fa fc fcnd) me)--mapTreeConstrs :: (c -> d) -> CondTree v c a -> CondTree v d a-mapTreeConstrs f = mapCondTree id f id--mapTreeConds :: (Condition v -> Condition w) -> CondTree v c a -> CondTree w c a-mapTreeConds f = mapCondTree id id f--mapTreeData :: (a -> b) -> CondTree v c a -> CondTree v c b-mapTreeData f = mapCondTree f id id---- | @@Traversal@@ for the variables-traverseCondTreeV :: L.Traversal (CondTree v c a) (CondTree w c a) v w-traverseCondTreeV f (CondNode a c ifs) =- CondNode a c <$> traverse (traverseCondBranchV f) ifs---- | @@Traversal@@ for the variables-traverseCondBranchV :: L.Traversal (CondBranch v c a) (CondBranch w c a) v w-traverseCondBranchV f (CondBranch cnd t me) = CondBranch- <$> traverse f cnd- <*> traverseCondTreeV f t- <*> traverse (traverseCondTreeV f) me---- | @@Traversal@@ for the aggregated constraints-traverseCondTreeC :: L.Traversal (CondTree v c a) (CondTree v d a) c d-traverseCondTreeC f (CondNode a c ifs) =- CondNode a <$> f c <*> traverse (traverseCondBranchC f) ifs---- | @@Traversal@@ for the aggregated constraints-traverseCondBranchC :: L.Traversal (CondBranch v c a) (CondBranch v d a) c d-traverseCondBranchC f (CondBranch cnd t me) = CondBranch cnd- <$> traverseCondTreeC f t- <*> traverse (traverseCondTreeC f) me----- | Extract the condition matched by the given predicate from a cond tree.------ We use this mainly for extracting buildable conditions (see the Note in--- Distribution.PackageDescription.Configuration), 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 (CondBranch 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---- | Flattens a CondTree using a partial flag assignment. When a condition--- cannot be evaluated, both branches are ignored.-simplifyCondTree :: (Semigroup a, Semigroup d) =>- (v -> Either v Bool)- -> CondTree v d a- -> (d, a)-simplifyCondTree env (CondNode a d ifs) =- foldl (<>) (d, a) $ mapMaybe simplifyIf ifs- where- simplifyIf (CondBranch cnd t me) =- case simplifyCondition cnd env of- (Lit True, _) -> Just $ simplifyCondTree env t- (Lit False, _) -> fmap (simplifyCondTree env) me- _ -> Nothing---- | Flatten a CondTree. This will resolve the CondTree by taking all--- possible paths into account. Note that since branches represent exclusive--- choices this may not result in a \"sane\" result.-ignoreConditions :: (Semigroup a, Semigroup c) => CondTree v c a -> (a, c)-ignoreConditions (CondNode a c ifs) = foldl (<>) (a, c) $ concatMap f ifs- where f (CondBranch _ t me) = ignoreConditions t- : maybeToList (fmap ignoreConditions me)
− Distribution/Types/Condition.hs
@@ -1,135 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.Condition (- Condition(..),- cNot,- cAnd,- cOr,- simplifyCondition,-) where--import Prelude ()-import Distribution.Compat.Prelude---- | 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, 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 = 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` 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 = 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 = (<>)--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)-instance Structured c => Structured (Condition c)-instance NFData c => NFData (Condition c) where rnf = genericRnf---- | Simplify the condition and return its free variables.-simplifyCondition :: Condition c- -> (c -> Either d Bool) -- ^ (partial) variable assignment- -> (Condition d, [d])-simplifyCondition cond i = fv . walk $ cond- where- walk cnd = case cnd of- Var v -> either Var Lit (i v)- Lit b -> Lit b- CNot c -> case walk c of- Lit True -> Lit False- Lit False -> Lit True- c' -> CNot c'- COr c d -> case (walk c, walk d) of- (Lit False, d') -> d'- (Lit True, _) -> Lit True- (c', Lit False) -> c'- (_, Lit True) -> Lit True- (c',d') -> COr c' d'- CAnd c d -> case (walk c, walk d) of- (Lit False, _) -> Lit False- (Lit True, d') -> d'- (_, Lit False) -> Lit False- (c', Lit True) -> c'- (c',d') -> CAnd c' d'- -- gather free vars- fv c = (c, fv' c)- fv' c = case c of- Var v -> [v]- Lit _ -> []- CNot c' -> fv' c'- COr c1 c2 -> fv' c1 ++ fv' c2- CAnd c1 c2 -> fv' c1 ++ fv' c2
− Distribution/Types/ConfVar.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.ConfVar (- ConfVar(..),- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.Flag-import Distribution.Types.VersionRange-import Distribution.Compiler-import Distribution.System---- | A @ConfVar@ represents the variable type used.-data ConfVar = OS OS- | Arch Arch- | PackageFlag FlagName- | Impl CompilerFlavor VersionRange- deriving (Eq, Show, Typeable, Data, Generic)--instance Binary ConfVar-instance Structured ConfVar--instance NFData ConfVar where rnf = genericRnf
− Distribution/Types/Dependency.hs
@@ -1,179 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.Dependency- ( Dependency(..)- , mkDependency- , depPkgName- , depVerRange- , depLibraries- , simplifyDependency- , mainLibSet- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.VersionRange (isAnyVersionLight)-import Distribution.Version (VersionRange, anyVersion, simplifyVersionRange)--import Distribution.CabalSpecVersion-import Distribution.Compat.CharParsing (char, spaces)-import Distribution.Compat.Parsing (between, option)-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.LibraryName-import Distribution.Types.PackageName-import Distribution.Types.UnqualComponentName--import qualified Distribution.Compat.NonEmptySet as NES-import qualified Text.PrettyPrint as PP---- | Describes a dependency on a source package (API)------ /Invariant:/ package name does not appear as 'LSubLibName' in--- set of library names.----data Dependency = Dependency- PackageName- VersionRange- (NonEmptySet LibraryName)- -- ^ The set of libraries required from the package.- -- Only the selected libraries will be built.- -- It does not affect the cabal-install solver yet.- deriving (Generic, Read, Show, Eq, Typeable, Data)--depPkgName :: Dependency -> PackageName-depPkgName (Dependency pn _ _) = pn--depVerRange :: Dependency -> VersionRange-depVerRange (Dependency _ vr _) = vr--depLibraries :: Dependency -> NonEmptySet LibraryName-depLibraries (Dependency _ _ cs) = cs---- | Smart constructor of 'Dependency'.------ If 'PackageName' is appears as 'LSubLibName' in a set of sublibraries,--- it is automatically converted to 'LMainLibName'.------ @since 3.4.0.0----mkDependency :: PackageName -> VersionRange -> NonEmptySet LibraryName -> Dependency-mkDependency pn vr lb = Dependency pn vr (NES.map conv lb)- where- pn' = packageNameToUnqualComponentName pn-- conv l@LMainLibName = l- conv l@(LSubLibName ln) | ln == pn' = LMainLibName- | otherwise = l--instance Binary Dependency-instance Structured Dependency-instance NFData Dependency where rnf = genericRnf---- |------ >>> prettyShow $ Dependency "pkg" anyVersion mainLibSet--- "pkg"------ >>> prettyShow $ Dependency "pkg" anyVersion $ NES.insert (LSubLibName "sublib") mainLibSet--- "pkg:{pkg, sublib}"------ >>> prettyShow $ Dependency "pkg" anyVersion $ NES.singleton (LSubLibName "sublib")--- "pkg:sublib"------ >>> prettyShow $ Dependency "pkg" anyVersion $ NES.insert (LSubLibName "sublib-b") $ NES.singleton (LSubLibName "sublib-a")--- "pkg:{sublib-a, sublib-b}"----instance Pretty Dependency where- pretty (Dependency name ver sublibs) = withSubLibs (pretty name) <+> pver- where- -- TODO: change to isAnyVersion after #6736- pver | isAnyVersionLight ver = PP.empty- | otherwise = pretty ver-- withSubLibs doc = case NES.toList sublibs of- [LMainLibName] -> doc- [LSubLibName uq] -> doc <<>> PP.colon <<>> pretty uq- _ -> doc <<>> PP.colon <<>> PP.braces prettySublibs-- prettySublibs = PP.hsep $ PP.punctuate PP.comma $ prettySublib <$> NES.toList sublibs-- prettySublib LMainLibName = PP.text $ unPackageName name- prettySublib (LSubLibName un) = PP.text $ unUnqualComponentName un---- |------ >>> simpleParsec "mylib:sub" :: Maybe Dependency--- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub") :| [])))------ >>> simpleParsec "mylib:{sub1,sub2}" :: Maybe Dependency--- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))------ >>> simpleParsec "mylib:{ sub1 , sub2 }" :: Maybe Dependency--- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))------ >>> simpleParsec "mylib:{ sub1 , sub2 } ^>= 42" :: Maybe Dependency--- Just (Dependency (PackageName "mylib") (MajorBoundVersion (mkVersion [42])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))------ >>> simpleParsec "mylib:{ } ^>= 42" :: Maybe Dependency--- Nothing------ >>> traverse_ print (map simpleParsec ["mylib:mylib", "mylib:{mylib}", "mylib:{mylib,sublib}" ] :: [Maybe Dependency])--- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [])))--- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [])))--- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [LSubLibName (UnqualComponentName "sublib")])))------ Spaces around colon are not allowed:------ >>> map simpleParsec ["mylib: sub", "mylib :sub", "mylib: {sub1,sub2}", "mylib :{sub1,sub2}"] :: [Maybe Dependency]--- [Nothing,Nothing,Nothing,Nothing]------ Sublibrary syntax is accepted since @cabal-version: 3.0@------ >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe Dependency]--- [Nothing,Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub") :| [])))]----instance Parsec Dependency where- parsec = do- name <- parsec-- libs <- option mainLibSet $ do- _ <- char ':'- versionGuardMultilibs- parsecWarning PWTExperimental "colon specifier is experimental feature (issue #5660)"- NES.singleton <$> parseLib <|> parseMultipleLibs-- spaces -- https://github.com/haskell/cabal/issues/5846-- ver <- parsec <|> pure anyVersion- return $ mkDependency name ver libs- where- parseLib = LSubLibName <$> parsec- parseMultipleLibs = between- (char '{' *> spaces)- (spaces *> char '}')- (NES.fromNonEmpty <$> parsecCommaNonEmpty parseLib)--versionGuardMultilibs :: CabalParsing m => m ()-versionGuardMultilibs = do- csv <- askCabalSpecVersion- when (csv < CabalSpecV3_0) $ fail $ unwords- [ "Sublibrary dependency syntax used."- , "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."- , "Alternatively, if you are depending on an internal library, you can write"- , "directly the library name as it were a package."- ]---- | Library set with main library.------ @since 3.4.0.0-mainLibSet :: NonEmptySet LibraryName-mainLibSet = NES.singleton LMainLibName---- | Simplify the 'VersionRange' expression in a 'Dependency'.--- See 'simplifyVersionRange'.----simplifyDependency :: Dependency -> Dependency-simplifyDependency (Dependency name range comps) =- Dependency name (simplifyVersionRange range) comps
− Distribution/Types/DependencyMap.hs
@@ -1,57 +0,0 @@-module Distribution.Types.DependencyMap (- DependencyMap,- toDepMap,- fromDepMap,- constrainBy,-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.Dependency-import Distribution.Types.LibraryName-import Distribution.Types.PackageName-import Distribution.Types.PackageVersionConstraint-import Distribution.Version--import qualified Data.Map.Lazy as Map---- | 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, NonEmptySet LibraryName) }- deriving (Show, Read)--instance Monoid DependencyMap where- mempty = DependencyMap Map.empty- mappend = (<>)--instance Semigroup DependencyMap where- (DependencyMap a) <> (DependencyMap b) =- DependencyMap (Map.unionWith intersectVersionRangesAndJoinComponents a b)--intersectVersionRangesAndJoinComponents :: (VersionRange, NonEmptySet LibraryName)- -> (VersionRange, NonEmptySet LibraryName)- -> (VersionRange, NonEmptySet LibraryName)-intersectVersionRangesAndJoinComponents (va, ca) (vb, cb) =- (intersectVersionRanges va vb, ca <> cb)--toDepMap :: [Dependency] -> DependencyMap-toDepMap ds =- DependencyMap $ Map.fromListWith intersectVersionRangesAndJoinComponents [ (p,(vr,cs)) | Dependency p vr cs <- ds ]--fromDepMap :: DependencyMap -> [Dependency]-fromDepMap m = [ Dependency p vr cs | (p,(vr,cs)) <- Map.toList (unDependencyMap m) ]---- Apply extra constraints to a dependency map.--- Combines dependencies where the result will only contain keys from the left--- (first) map. If a key also exists in the right map, both constraints will--- be intersected.-constrainBy- :: DependencyMap- -> [PackageVersionConstraint]- -> DependencyMap-constrainBy = foldl' tightenConstraint where- tightenConstraint (DependencyMap l) (PackageVersionConstraint pn vr) = DependencyMap $- case Map.lookup pn l of- Nothing -> l- Just (vr', cs) -> Map.insert pn (intersectVersionRanges vr' vr, cs) l
− Distribution/Types/ExeDependency.hs
@@ -1,71 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.ExeDependency- ( ExeDependency(..)- , qualifiedExeName- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.ComponentName-import Distribution.Types.PackageName-import Distribution.Types.UnqualComponentName-import Distribution.Version (VersionRange, anyVersion, isAnyVersion)--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as PP---- | Describes a dependency on an executable from a package----data ExeDependency = ExeDependency- PackageName- UnqualComponentName -- name of executable component of package- VersionRange- deriving (Generic, Read, Show, Eq, Typeable, Data)--instance Binary ExeDependency-instance Structured ExeDependency-instance NFData ExeDependency where rnf = genericRnf--instance Pretty ExeDependency where- pretty (ExeDependency name exe ver) =- pretty name <<>> PP.colon <<>> pretty exe PP.<+> pver- where- pver | isAnyVersion ver = PP.empty- | otherwise = pretty ver---- | ------ Examples------ >>> simpleParsec "happy:happy" :: Maybe ExeDependency--- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [0])))------ >>> simpleParsec "happy:happy >= 1.19.12" :: Maybe ExeDependency--- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [1,19,12])))------ >>> simpleParsec "happy:happy>=1.19.12" :: Maybe ExeDependency--- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [1,19,12])))------ >>> simpleParsec "happy : happy >= 1.19.12" :: Maybe ExeDependency--- Nothing------ >>> simpleParsec "happy: happy >= 1.19.12" :: Maybe ExeDependency--- Nothing------ >>> simpleParsec "happy :happy >= 1.19.12" :: Maybe ExeDependency--- Nothing----instance Parsec ExeDependency where- parsec = do- name <- parsec- _ <- P.char ':'- exe <- lexemeParsec- ver <- parsec <|> pure anyVersion- return (ExeDependency name exe ver)--qualifiedExeName :: ExeDependency -> ComponentName-qualifiedExeName (ExeDependency _ ucn _) = CExeName ucn
− Distribution/Types/Executable.hs
@@ -1,65 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.Executable (- Executable(..),- emptyExecutable,- exeModules,- exeModulesAutogen-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.BuildInfo-import Distribution.Types.UnqualComponentName-import Distribution.Types.ExecutableScope-import Distribution.ModuleName--import qualified Distribution.Types.BuildInfo.Lens as L--data Executable = Executable {- exeName :: UnqualComponentName,- modulePath :: FilePath,- exeScope :: ExecutableScope,- buildInfo :: BuildInfo- }- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance L.HasBuildInfo Executable where- buildInfo f l = (\x -> l { buildInfo = x }) <$> f (buildInfo l)--instance Binary Executable-instance Structured Executable-instance NFData Executable where rnf = genericRnf--instance Monoid Executable where- mempty = gmempty- mappend = (<>)--instance Semigroup Executable where- a <> b = Executable{- exeName = combine' exeName,- modulePath = combine modulePath,- exeScope = combine exeScope,- buildInfo = combine buildInfo- }- where combine field = field a `mappend` field b- combine' field = case ( unUnqualComponentName $ field a- , unUnqualComponentName $ field b) of- ("", _) -> field b- (_, "") -> field a- (x, y) -> error $ "Ambiguous values for executable field: '"- ++ x ++ "' and '" ++ y ++ "'"--emptyExecutable :: Executable-emptyExecutable = mempty---- | Get all the module names from an exe-exeModules :: Executable -> [ModuleName]-exeModules exe = otherModules (buildInfo exe)---- | Get all the auto generated module names from an exe--- This are a subset of 'exeModules'.-exeModulesAutogen :: Executable -> [ModuleName]-exeModulesAutogen exe = autogenModules (buildInfo exe)
− Distribution/Types/Executable/Lens.hs
@@ -1,31 +0,0 @@-module Distribution.Types.Executable.Lens (- Executable,- module Distribution.Types.Executable.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.Executable (Executable)-import Distribution.Types.ExecutableScope (ExecutableScope)-import Distribution.Types.UnqualComponentName (UnqualComponentName)--import qualified Distribution.Types.Executable as T--exeName :: Lens' Executable UnqualComponentName-exeName f s = fmap (\x -> s { T.exeName = x }) (f (T.exeName s))-{-# INLINE exeName #-}--modulePath :: Lens' Executable String-modulePath f s = fmap (\x -> s { T.modulePath = x }) (f (T.modulePath s))-{-# INLINE modulePath #-}--exeScope :: Lens' Executable ExecutableScope-exeScope f s = fmap (\x -> s { T.exeScope = x }) (f (T.exeScope s))-{-# INLINE exeScope #-}--exeBuildInfo :: Lens' Executable BuildInfo-exeBuildInfo f s = fmap (\x -> s { T.buildInfo = x }) (f (T.buildInfo s))-{-# INLINE exeBuildInfo #-}
− Distribution/Types/ExecutableScope.hs
@@ -1,43 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--module Distribution.Types.ExecutableScope (- ExecutableScope(..),-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp--data ExecutableScope = ExecutablePublic- | ExecutablePrivate- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Pretty ExecutableScope where- pretty ExecutablePublic = Disp.text "public"- pretty ExecutablePrivate = Disp.text "private"--instance Parsec ExecutableScope where- parsec = P.try pub <|> pri where- pub = ExecutablePublic <$ P.string "public"- pri = ExecutablePrivate <$ P.string "private"--instance Binary ExecutableScope-instance Structured ExecutableScope-instance NFData ExecutableScope where rnf = genericRnf---- | 'Any' like semigroup, where 'ExecutablePrivate' is 'Any True'-instance Semigroup ExecutableScope where- ExecutablePublic <> x = x- x@ExecutablePrivate <> _ = x---- | 'mempty' = 'ExecutablePublic'-instance Monoid ExecutableScope where- mempty = ExecutablePublic- mappend = (<>)
− Distribution/Types/ExposedModule.hs
@@ -1,45 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.ExposedModule where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Backpack-import Distribution.ModuleName-import Distribution.Parsec-import Distribution.Pretty--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp--data ExposedModule- = ExposedModule {- exposedName :: ModuleName,- exposedReexport :: Maybe OpenModule- }- deriving (Eq, Generic, Read, Show, Typeable)--instance Pretty ExposedModule where- pretty (ExposedModule m reexport) =- Disp.hsep [ pretty m- , case reexport of- Just m' -> Disp.hsep [Disp.text "from", pretty m']- Nothing -> Disp.empty- ]--instance Parsec ExposedModule where- parsec = do- m <- parsecMaybeQuoted parsec- P.spaces-- reexport <- P.optional $ do- _ <- P.string "from"- P.skipSpaces1- parsec-- return (ExposedModule m reexport)--instance Binary ExposedModule-instance Structured ExposedModule-instance NFData ExposedModule where rnf = genericRnf
− Distribution/Types/Flag.hs
@@ -1,346 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Distribution.Types.Flag (- -- * Package flag- PackageFlag(..),- emptyFlag,- -- * Flag name- FlagName,- mkFlagName,- unFlagName,- -- * Flag assignment- FlagAssignment,- mkFlagAssignment,- unFlagAssignment,- lookupFlagAssignment,- insertFlagAssignment,- diffFlagAssignment,- findDuplicateFlagAssignments,- nullFlagAssignment,- showFlagValue,- dispFlagAssignment,- showFlagAssignment,- parsecFlagAssignment,- parsecFlagAssignmentNonEmpty,- -- ** Legacy formats- legacyShowFlagAssignment,- legacyShowFlagAssignment',- legacyParsecFlagAssignment,- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.ShortText-import Distribution.Utils.Generic (lowercase)--import Distribution.Parsec-import Distribution.Pretty--import qualified Data.Map as Map-import qualified Text.PrettyPrint as Disp-import qualified Distribution.Compat.CharParsing as P---- -------------------------------------------------------------------------------- The Flag' type---- | 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.-data PackageFlag = MkPackageFlag- { flagName :: FlagName- , flagDescription :: String- , flagDefault :: Bool- , flagManual :: Bool- }- deriving (Show, Eq, Typeable, Data, Generic)--instance Binary PackageFlag-instance Structured PackageFlag-instance NFData PackageFlag where rnf = genericRnf---- | A 'PackageFlag' initialized with default parameters.-emptyFlag :: FlagName -> PackageFlag-emptyFlag name = MkPackageFlag- { flagName = name- , flagDescription = ""- , flagDefault = True- , flagManual = False- }---- | A 'FlagName' is the name of a user-defined configuration flag------ Use 'mkFlagName' and 'unFlagName' to convert from/to a 'String'.------ This type is opaque since @Cabal-2.0@------ @since 2.0.0.2-newtype FlagName = FlagName ShortText- deriving (Eq, Generic, Ord, Show, Read, Typeable, Data, NFData)---- | Construct a 'FlagName' from a 'String'------ 'mkFlagName' is the inverse to 'unFlagName'------ Note: No validations are performed to ensure that the resulting--- 'FlagName' is valid------ @since 2.0.0.2-mkFlagName :: String -> FlagName-mkFlagName = FlagName . toShortText---- | 'mkFlagName'------ @since 2.0.0.2-instance IsString FlagName where- fromString = mkFlagName---- | Convert 'FlagName' to 'String'------ @since 2.0.0.2-unFlagName :: FlagName -> String-unFlagName (FlagName s) = fromShortText s--instance Binary FlagName-instance Structured FlagName--instance Pretty FlagName where- pretty = Disp.text . unFlagName--instance Parsec FlagName where- -- Note: we don't check that FlagName doesn't have leading dash,- -- cabal check will do that.- parsec = mkFlagName . lowercase <$> parsec'- where- parsec' = (:) <$> lead <*> rest- lead = P.satisfy (\c -> isAlphaNum c || c == '_')- rest = P.munch (\c -> isAlphaNum c || c == '_' || c == '-')---- | A 'FlagAssignment' is a total or partial mapping of 'FlagName's to--- 'Bool' flag values. It represents the flags chosen by the user or--- discovered during configuration. For example @--flags=foo --flags=-bar@--- becomes @[("foo", True), ("bar", False)]@------ TODO: Why we record the multiplicity of the flag?----newtype FlagAssignment- = FlagAssignment { getFlagAssignment :: Map.Map FlagName (Int, Bool) }- deriving (Binary, Generic, NFData, Typeable)--instance Structured FlagAssignment--instance Eq FlagAssignment where- (==) (FlagAssignment m1) (FlagAssignment m2)- = fmap snd m1 == fmap snd m2--instance Ord FlagAssignment where- compare (FlagAssignment m1) (FlagAssignment m2)- = fmap snd m1 `compare` fmap snd m2---- | Combines pairs of values contained in the 'FlagAssignment' Map.------ The last flag specified takes precedence, and we record the number--- of times we have seen the flag.----combineFlagValues :: (Int, Bool) -> (Int, Bool) -> (Int, Bool)-combineFlagValues (c1, _) (c2, b2) = (c1 + c2, b2)---- The 'Semigroup' instance currently is right-biased.------ If duplicate flags are specified, we want the last flag specified to--- take precedence and we want to know how many times the flag has been--- specified so that we have the option of warning the user about--- supplying duplicate flags.-instance Semigroup FlagAssignment where- (<>) (FlagAssignment m1) (FlagAssignment m2)- = FlagAssignment (Map.unionWith combineFlagValues m1 m2)--instance Monoid FlagAssignment where- mempty = FlagAssignment Map.empty- mappend = (<>)---- | Construct a 'FlagAssignment' from a list of flag/value pairs.------ If duplicate flags occur in the input list, the later entries--- in the list will take precedence.------ @since 2.2.0-mkFlagAssignment :: [(FlagName, Bool)] -> FlagAssignment-mkFlagAssignment =- FlagAssignment .- Map.fromListWith (flip combineFlagValues) . fmap (fmap (\b -> (1, b)))---- | Deconstruct a 'FlagAssignment' into a list of flag/value pairs.------ @ 'null' ('findDuplicateFlagAssignments' fa) ==> ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @------ @since 2.2.0-unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]-unFlagAssignment = fmap (fmap snd) . Map.toList . getFlagAssignment---- | Test whether 'FlagAssignment' is empty.------ @since 2.2.0-nullFlagAssignment :: FlagAssignment -> Bool-nullFlagAssignment = Map.null . getFlagAssignment---- | Lookup the value for a flag------ Returns 'Nothing' if the flag isn't contained in the 'FlagAssignment'.------ @since 2.2.0-lookupFlagAssignment :: FlagName -> FlagAssignment -> Maybe Bool-lookupFlagAssignment fn = fmap snd . Map.lookup fn . getFlagAssignment---- | Insert or update the boolean value of a flag.------ If the flag is already present in the 'FlagAssigment', the--- value will be updated and the fact that multiple values have--- been provided for that flag will be recorded so that a--- warning can be generated later on.------ @since 2.2.0-insertFlagAssignment :: FlagName -> Bool -> FlagAssignment -> FlagAssignment--- TODO: this currently just shadows prior values for an existing--- flag; rather than enforcing uniqueness at construction, it's--- verified later on via `D.C.Dependency.configuredPackageProblems`-insertFlagAssignment flag val =- FlagAssignment .- Map.insertWith (flip combineFlagValues) flag (1, val) . getFlagAssignment---- | Remove all flag-assignments from the first 'FlagAssignment' that--- are contained in the second 'FlagAssignment'------ NB/TODO: This currently only removes flag assignments which also--- match the value assignment! We should review the code which uses--- this operation to figure out if this it's not enough to only--- compare the flagnames without the values.------ @since 2.2.0-diffFlagAssignment :: FlagAssignment -> FlagAssignment -> FlagAssignment-diffFlagAssignment fa1 fa2 = FlagAssignment- (Map.difference (getFlagAssignment fa1) (getFlagAssignment fa2))---- | Find the 'FlagName's that have been listed more than once.------ @since 2.2.0-findDuplicateFlagAssignments :: FlagAssignment -> [FlagName]-findDuplicateFlagAssignments =- Map.keys . Map.filter ((> 1) . fst) . getFlagAssignment---- | @since 2.2.0-instance Read FlagAssignment where- readsPrec p s = [ (FlagAssignment x, rest) | (x,rest) <- readsPrec p s ]---- | @since 2.2.0-instance Show FlagAssignment where- showsPrec p (FlagAssignment xs) = showsPrec p xs---- | String representation of a flag-value pair.-showFlagValue :: (FlagName, Bool) -> String-showFlagValue (f, True) = '+' : unFlagName f-showFlagValue (f, False) = '-' : unFlagName f---- | @since 3.4.0.0-instance Pretty FlagAssignment where- pretty = dispFlagAssignment---- |------ >>> simpleParsec "" :: Maybe FlagAssignment--- Just (fromList [])------ >>> simpleParsec "+foo -bar" :: Maybe FlagAssignment--- Just (fromList [(FlagName "bar",(1,False)),(FlagName "foo",(1,True))])------ >>> simpleParsec "-none -any" :: Maybe FlagAssignment--- Just (fromList [(FlagName "any",(1,False)),(FlagName "none",(1,False))])------ >>> simpleParsec "+foo -foo +foo +foo" :: Maybe FlagAssignment--- Just (fromList [(FlagName "foo",(4,True))])------ >>> simpleParsec "+foo -bar baz" :: Maybe FlagAssignment--- Nothing------ @since 3.4.0.0----instance Parsec FlagAssignment where- parsec = parsecFlagAssignment---- | Pretty-prints a flag assignment.-dispFlagAssignment :: FlagAssignment -> Disp.Doc-dispFlagAssignment = Disp.hsep . map (Disp.text . showFlagValue) . unFlagAssignment---- | Parses a flag assignment.-parsecFlagAssignment :: CabalParsing m => m FlagAssignment-parsecFlagAssignment = mkFlagAssignment <$>- P.sepBy (onFlag <|> offFlag) P.skipSpaces1- where- onFlag = do- _ <- P.char '+'- f <- parsec- return (f, True)- offFlag = do- _ <- P.char '-'- f <- parsec- return (f, False)---- | Parse a non-empty flag assignment------ The flags have to explicitly start with minus or plus.------ @since 3.4.0.0-parsecFlagAssignmentNonEmpty :: CabalParsing m => m FlagAssignment-parsecFlagAssignmentNonEmpty = mkFlagAssignment . toList <$>- P.sepByNonEmpty (onFlag <|> offFlag) P.skipSpaces1- where- onFlag = do- _ <- P.char '+'- f <- parsec- return (f, True)- offFlag = do- _ <- P.char '-'- f <- parsec- return (f, False)---- | Show flag assignment.------ @since 3.4.0.0-showFlagAssignment :: FlagAssignment -> String-showFlagAssignment = prettyShow . dispFlagAssignment------------------------------------------------------------------------------------ Legacy: without requiring +------------------------------------------------------------------------------------ | We need this as far as we support custom setups older than 2.2.0.0------ @since 3.4.0.0-legacyShowFlagAssignment :: FlagAssignment -> String-legacyShowFlagAssignment =- prettyShow . Disp.hsep . map Disp.text . legacyShowFlagAssignment'---- | @since 3.4.0.0-legacyShowFlagAssignment' :: FlagAssignment -> [String]-legacyShowFlagAssignment' = map legacyShowFlagValue . unFlagAssignment---- | @since 3.4.0.0-legacyShowFlagValue :: (FlagName, Bool) -> String-legacyShowFlagValue (f, True) = unFlagName f-legacyShowFlagValue (f, False) = '-' : unFlagName f---- |--- We need this as far as we support custom setups older than 2.2.0.0------ @since 3.4.0.0-legacyParsecFlagAssignment :: CabalParsing m => m FlagAssignment-legacyParsecFlagAssignment = mkFlagAssignment <$>- P.sepBy (onFlag <|> offFlag) P.skipSpaces1- where- onFlag = do- _ <- P.optional (P.char '+')- f <- parsec- return (f, True)- offFlag = do- _ <- P.char '-'- f <- parsec- return (f, False)
− Distribution/Types/ForeignLib.hs
@@ -1,199 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.ForeignLib(- ForeignLib(..),- emptyForeignLib,- foreignLibModules,- foreignLibIsShared,- foreignLibVersion,-- LibVersionInfo,- mkLibVersionInfo,- libVersionInfoCRA,- libVersionNumber,- libVersionNumberShow,- libVersionMajor-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.ModuleName-import Distribution.Parsec-import Distribution.Pretty-import Distribution.System-import Distribution.Types.BuildInfo-import Distribution.Types.ForeignLibOption-import Distribution.Types.ForeignLibType-import Distribution.Types.UnqualComponentName-import Distribution.Version--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp-import qualified Text.Read as Read--import qualified Distribution.Types.BuildInfo.Lens as L---- | A foreign library stanza is like a library stanza, except that--- the built code is intended for consumption by a non-Haskell client.-data ForeignLib = ForeignLib {- -- | Name of the foreign library- foreignLibName :: UnqualComponentName- -- | What kind of foreign library is this (static or dynamic).- , foreignLibType :: ForeignLibType- -- | What options apply to this foreign library (e.g., are we- -- merging in all foreign dependencies.)- , foreignLibOptions :: [ForeignLibOption]- -- | Build information for this foreign library.- , foreignLibBuildInfo :: BuildInfo- -- | Libtool-style version-info data to compute library version.- -- Refer to the libtool documentation on the- -- current:revision:age versioning scheme.- , foreignLibVersionInfo :: Maybe LibVersionInfo- -- | Linux library version- , foreignLibVersionLinux :: Maybe Version-- -- | (Windows-specific) module definition files- --- -- This is a list rather than a maybe field so that we can flatten- -- the condition trees (for instance, when creating an sdist)- , foreignLibModDefFile :: [FilePath]- }- deriving (Generic, Show, Read, Eq, Typeable, Data)--data LibVersionInfo = LibVersionInfo Int Int Int deriving (Data, Eq, Generic, Typeable)--instance Ord LibVersionInfo where- LibVersionInfo c r _ `compare` LibVersionInfo c' r' _ =- case c `compare` c' of- EQ -> r `compare` r'- e -> e--instance Show LibVersionInfo where- showsPrec d (LibVersionInfo c r a) = showParen (d > 10)- $ showString "mkLibVersionInfo "- . showsPrec 11 (c,r,a)--instance Read LibVersionInfo where- readPrec = Read.parens $ do- Read.Ident "mkLibVersionInfo" <- Read.lexP- t <- Read.step Read.readPrec- return (mkLibVersionInfo t)--instance Binary LibVersionInfo-instance Structured LibVersionInfo-instance NFData LibVersionInfo where rnf = genericRnf--instance Pretty LibVersionInfo where- pretty (LibVersionInfo c r a)- = Disp.hcat $ Disp.punctuate (Disp.char ':') $ map Disp.int [c,r,a]--instance Parsec LibVersionInfo where- parsec = do- c <- P.integral- (r, a) <- P.option (0,0) $ do- _ <- P.char ':'- r <- P.integral- a <- P.option 0 $ do- _ <- P.char ':'- P.integral- return (r,a)- return $ mkLibVersionInfo (c,r,a)---- | Construct 'LibVersionInfo' from @(current, revision, age)@--- numbers.------ For instance, @mkLibVersionInfo (3,0,0)@ constructs a--- 'LibVersionInfo' representing the version-info @3:0:0@.------ All version components must be non-negative.-mkLibVersionInfo :: (Int, Int, Int) -> LibVersionInfo-mkLibVersionInfo (c,r,a) = LibVersionInfo c r a---- | From a given 'LibVersionInfo', extract the @(current, revision,--- age)@ numbers.-libVersionInfoCRA :: LibVersionInfo -> (Int, Int, Int)-libVersionInfoCRA (LibVersionInfo c r a) = (c,r,a)---- | Given a version-info field, produce a @major.minor.build@ version-libVersionNumber :: LibVersionInfo -> (Int, Int, Int)-libVersionNumber (LibVersionInfo c r a) = (c-a , a , r)---- | Given a version-info field, return @"major.minor.build"@ as a--- 'String'-libVersionNumberShow :: LibVersionInfo -> String-libVersionNumberShow v =- let (major, minor, build) = libVersionNumber v- in show major ++ "." ++ show minor ++ "." ++ show build---- | Return the @major@ version of a version-info field.-libVersionMajor :: LibVersionInfo -> Int-libVersionMajor (LibVersionInfo c _ a) = c-a--instance L.HasBuildInfo ForeignLib where- buildInfo f l = (\x -> l { foreignLibBuildInfo = x }) <$> f (foreignLibBuildInfo l)--instance Binary ForeignLib-instance Structured ForeignLib-instance NFData ForeignLib where rnf = genericRnf--instance Semigroup ForeignLib where- a <> b = ForeignLib {- foreignLibName = combine' foreignLibName- , foreignLibType = combine foreignLibType- , foreignLibOptions = combine foreignLibOptions- , foreignLibBuildInfo = combine foreignLibBuildInfo- , foreignLibVersionInfo = combine'' foreignLibVersionInfo- , foreignLibVersionLinux = combine'' foreignLibVersionLinux- , foreignLibModDefFile = combine foreignLibModDefFile- }- where combine field = field a `mappend` field b- combine' field = case ( unUnqualComponentName $ field a- , unUnqualComponentName $ field b) of- ("", _) -> field b- (_, "") -> field a- (x, y) -> error $ "Ambiguous values for executable field: '"- ++ x ++ "' and '" ++ y ++ "'"- combine'' field = field b--instance Monoid ForeignLib where- mempty = ForeignLib {- foreignLibName = mempty- , foreignLibType = ForeignLibTypeUnknown- , foreignLibOptions = []- , foreignLibBuildInfo = mempty- , foreignLibVersionInfo = Nothing- , foreignLibVersionLinux = Nothing- , foreignLibModDefFile = []- }- mappend = (<>)---- | An empty foreign library.-emptyForeignLib :: ForeignLib-emptyForeignLib = mempty---- | Modules defined by a foreign library.-foreignLibModules :: ForeignLib -> [ModuleName]-foreignLibModules = otherModules . foreignLibBuildInfo---- | Is the foreign library shared?-foreignLibIsShared :: ForeignLib -> Bool-foreignLibIsShared = foreignLibTypeIsShared . foreignLibType---- | Get a version number for a foreign library.--- If we're on Linux, and a Linux version is specified, use that.--- If we're on Linux, and libtool-style version-info is specified, translate--- that field into appropriate version numbers.--- Otherwise, this feature is unsupported so we don't return any version data.-foreignLibVersion :: ForeignLib -> OS -> [Int]-foreignLibVersion flib Linux =- case foreignLibVersionLinux flib of- Just v -> versionNumbers v- Nothing ->- case foreignLibVersionInfo flib of- Just v' ->- let (major, minor, build) = libVersionNumber v'- in [major, minor, build]- Nothing -> []-foreignLibVersion _ _ = []
− Distribution/Types/ForeignLib/Lens.hs
@@ -1,45 +0,0 @@-module Distribution.Types.ForeignLib.Lens (- ForeignLib,- module Distribution.Types.ForeignLib.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.ForeignLib (ForeignLib, LibVersionInfo)-import Distribution.Types.ForeignLibOption (ForeignLibOption)-import Distribution.Types.ForeignLibType (ForeignLibType)-import Distribution.Types.UnqualComponentName (UnqualComponentName)-import Distribution.Version (Version)--import qualified Distribution.Types.ForeignLib as T--foreignLibName :: Lens' ForeignLib UnqualComponentName-foreignLibName f s = fmap (\x -> s { T.foreignLibName = x }) (f (T.foreignLibName s))-{-# INLINE foreignLibName #-}--foreignLibType :: Lens' ForeignLib ForeignLibType-foreignLibType f s = fmap (\x -> s { T.foreignLibType = x }) (f (T.foreignLibType s))-{-# INLINE foreignLibType #-}--foreignLibOptions :: Lens' ForeignLib [ForeignLibOption]-foreignLibOptions f s = fmap (\x -> s { T.foreignLibOptions = x }) (f (T.foreignLibOptions s))-{-# INLINE foreignLibOptions #-}--foreignLibBuildInfo :: Lens' ForeignLib BuildInfo-foreignLibBuildInfo f s = fmap (\x -> s { T.foreignLibBuildInfo = x }) (f (T.foreignLibBuildInfo s))-{-# INLINE foreignLibBuildInfo #-}--foreignLibVersionInfo :: Lens' ForeignLib (Maybe LibVersionInfo)-foreignLibVersionInfo f s = fmap (\x -> s { T.foreignLibVersionInfo = x }) (f (T.foreignLibVersionInfo s))-{-# INLINE foreignLibVersionInfo #-}--foreignLibVersionLinux :: Lens' ForeignLib (Maybe Version)-foreignLibVersionLinux f s = fmap (\x -> s { T.foreignLibVersionLinux = x }) (f (T.foreignLibVersionLinux s))-{-# INLINE foreignLibVersionLinux #-}--foreignLibModDefFile :: Lens' ForeignLib [FilePath]-foreignLibModDefFile f s = fmap (\x -> s { T.foreignLibModDefFile = x }) (f (T.foreignLibModDefFile s))-{-# INLINE foreignLibModDefFile #-}
− Distribution/Types/ForeignLibOption.hs
@@ -1,39 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--module Distribution.Types.ForeignLibOption(- ForeignLibOption(..)-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp--data ForeignLibOption =- -- | Merge in all dependent libraries (i.e., use- -- @ghc -shared -static@ rather than just record- -- the dependencies, ala @ghc -shared -dynamic@).- -- This option is compulsory on Windows and unsupported- -- on other platforms.- ForeignLibStandalone- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Pretty ForeignLibOption where- pretty ForeignLibStandalone = Disp.text "standalone"--instance Parsec ForeignLibOption where- parsec = do- name <- P.munch1 (\c -> isAlphaNum c || c == '-')- case name of- "standalone" -> return ForeignLibStandalone- _ -> fail "unrecognized foreign-library option"--instance Binary ForeignLibOption-instance Structured ForeignLibOption-instance NFData ForeignLibOption where rnf = genericRnf
− Distribution/Types/ForeignLibType.hs
@@ -1,69 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--module Distribution.Types.ForeignLibType(- ForeignLibType(..),- knownForeignLibTypes,- foreignLibTypeIsShared,-) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.PackageDescription.Utils--import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | What kind of foreign library is to be built?-data ForeignLibType =- -- | A native shared library (@.so@ on Linux, @.dylib@ on OSX, or- -- @.dll@ on Windows).- ForeignLibNativeShared- -- | A native static library (not currently supported.)- | ForeignLibNativeStatic- -- TODO: Maybe this should record a string?- | ForeignLibTypeUnknown- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Pretty ForeignLibType where- pretty ForeignLibNativeShared = Disp.text "native-shared"- pretty ForeignLibNativeStatic = Disp.text "native-static"- pretty ForeignLibTypeUnknown = Disp.text "unknown"--instance Parsec ForeignLibType where- parsec = do- name <- P.munch1 (\c -> isAlphaNum c || c == '-')- return $ case name of- "native-shared" -> ForeignLibNativeShared- "native-static" -> ForeignLibNativeStatic- _ -> ForeignLibTypeUnknown--instance Binary ForeignLibType-instance Structured ForeignLibType-instance NFData ForeignLibType where rnf = genericRnf--instance Semigroup ForeignLibType where- ForeignLibTypeUnknown <> b = b- a <> ForeignLibTypeUnknown = a- _ <> _ = error "Ambiguous foreign library type"--instance Monoid ForeignLibType where- mempty = ForeignLibTypeUnknown- mappend = (<>)--knownForeignLibTypes :: [ForeignLibType]-knownForeignLibTypes = [- ForeignLibNativeShared- , ForeignLibNativeStatic- ]--foreignLibTypeIsShared :: ForeignLibType -> Bool-foreignLibTypeIsShared t =- case t of- ForeignLibNativeShared -> True- ForeignLibNativeStatic -> False- ForeignLibTypeUnknown -> cabalBug "Unknown foreign library type"
− Distribution/Types/GenericPackageDescription.hs
@@ -1,105 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Distribution.Types.GenericPackageDescription (- GenericPackageDescription(..),- emptyGenericPackageDescription,-) where--import Prelude ()-import Distribution.Compat.Prelude---- lens-import Distribution.Compat.Lens as L-import qualified Distribution.Types.BuildInfo.Lens as L--import Distribution.Types.PackageDescription--import Distribution.Types.Benchmark-import Distribution.Types.CondTree-import Distribution.Types.ConfVar-import Distribution.Types.Dependency-import Distribution.Types.Executable-import Distribution.Types.Flag-import Distribution.Types.ForeignLib-import Distribution.Types.Library-import Distribution.Types.TestSuite-import Distribution.Types.UnqualComponentName-import Distribution.Package-import Distribution.Version---- ------------------------------------------------------------------------------ The 'GenericPackageDescription' type--data GenericPackageDescription =- GenericPackageDescription- { packageDescription :: PackageDescription- , gpdScannedVersion :: Maybe Version- -- ^ This is a version as specified in source.- -- We populate this field in index reading for dummy GPDs,- -- only when GPD reading failed, but scanning haven't.- --- -- Cabal-the-library never produces GPDs with Just as gpdScannedVersion.- --- -- Perfectly, PackageIndex should have sum type, so we don't need to- -- have dummy GPDs.- , genPackageFlags :: [PackageFlag]- , condLibrary :: Maybe (CondTree ConfVar [Dependency] Library)- , condSubLibraries :: [( UnqualComponentName- , CondTree ConfVar [Dependency] Library )]- , condForeignLibs :: [( UnqualComponentName- , CondTree ConfVar [Dependency] ForeignLib )]- , condExecutables :: [( UnqualComponentName- , CondTree ConfVar [Dependency] Executable )]- , condTestSuites :: [( UnqualComponentName- , CondTree ConfVar [Dependency] TestSuite )]- , condBenchmarks :: [( UnqualComponentName- , CondTree ConfVar [Dependency] Benchmark )]- }- deriving (Show, Eq, Typeable, Data, Generic)--instance Package GenericPackageDescription where- packageId = packageId . packageDescription--instance Binary GenericPackageDescription-instance Structured GenericPackageDescription-instance NFData GenericPackageDescription where rnf = genericRnf--emptyGenericPackageDescription :: GenericPackageDescription-emptyGenericPackageDescription = GenericPackageDescription emptyPackageDescription Nothing [] Nothing [] [] [] [] []---- -------------------------------------------------------------------------------- Traversal Instances--instance L.HasBuildInfos GenericPackageDescription where- traverseBuildInfos f (GenericPackageDescription p v a1 x1 x2 x3 x4 x5 x6) =- GenericPackageDescription- <$> L.traverseBuildInfos f p- <*> pure v- <*> pure a1- <*> (traverse . traverseCondTreeBuildInfo) f x1- <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x2- <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x3- <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x4- <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x5- <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x6- where---- We use this traversal to keep [Dependency] field in CondTree up to date.-traverseCondTreeBuildInfo- :: forall f comp v. (Applicative f, L.HasBuildInfo comp)- => LensLike' f (CondTree v [Dependency] comp) L.BuildInfo-traverseCondTreeBuildInfo g = node where- mkCondNode :: comp -> [CondBranch v [Dependency] comp] -> CondTree v [Dependency] comp- mkCondNode comp branches = CondNode comp (view L.targetBuildDepends comp) branches-- node (CondNode comp _ branches) = mkCondNode- <$> L.buildInfo g comp- <*> traverse branch branches-- branch (CondBranch v x y) = CondBranch v- <$> node x- <*> traverse node y
− Distribution/Types/GenericPackageDescription/Lens.hs
@@ -1,131 +0,0 @@-{-# LANGUAGE Rank2Types #-}-module Distribution.Types.GenericPackageDescription.Lens (- GenericPackageDescription,- PackageFlag,- FlagName,- ConfVar (..),- module Distribution.Types.GenericPackageDescription.Lens,- ) where--import Prelude()-import Distribution.Compat.Prelude-import Distribution.Compat.Lens--import qualified Distribution.Types.GenericPackageDescription as T---- We import types from their packages, so we can remove unused imports--- and have wider inter-module dependency graph-import Distribution.Types.CondTree (CondTree)-import Distribution.Types.Dependency (Dependency)-import Distribution.Types.Executable (Executable)-import Distribution.Types.PackageDescription (PackageDescription)-import Distribution.Types.Benchmark (Benchmark)-import Distribution.Types.ForeignLib (ForeignLib)-import Distribution.Types.GenericPackageDescription (GenericPackageDescription(GenericPackageDescription) )-import Distribution.Types.Flag (PackageFlag(MkPackageFlag), FlagName)-import Distribution.Types.ConfVar (ConfVar (..))-import Distribution.Types.Library (Library)-import Distribution.Types.TestSuite (TestSuite)-import Distribution.Types.UnqualComponentName (UnqualComponentName)-import Distribution.System (Arch, OS)-import Distribution.Compiler (CompilerFlavor)-import Distribution.Version (Version, VersionRange)------------------------------------------------------------------------------------ GenericPackageDescription----------------------------------------------------------------------------------packageDescription :: Lens' GenericPackageDescription PackageDescription-packageDescription f s = fmap (\x -> s { T.packageDescription = x }) (f (T.packageDescription s))-{-# INLINE packageDescription #-}--gpdScannedVersion :: Lens' GenericPackageDescription (Maybe Version)-gpdScannedVersion f s = fmap (\x -> s { T.gpdScannedVersion = x }) (f (T.gpdScannedVersion s))-{-# INLINE gpdScannedVersion #-}--genPackageFlags :: Lens' GenericPackageDescription [PackageFlag]-genPackageFlags f s = fmap (\x -> s { T.genPackageFlags = x }) (f (T.genPackageFlags s))-{-# INLINE genPackageFlags #-}--condLibrary :: Lens' GenericPackageDescription (Maybe (CondTree ConfVar [Dependency] Library))-condLibrary f s = fmap (\x -> s { T.condLibrary = x }) (f (T.condLibrary s))-{-# INLINE condLibrary #-}--condSubLibraries :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] Library))]-condSubLibraries f s = fmap (\x -> s { T.condSubLibraries = x }) (f (T.condSubLibraries s))-{-# INLINE condSubLibraries #-}--condForeignLibs :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] ForeignLib))]-condForeignLibs f s = fmap (\x -> s { T.condForeignLibs = x }) (f (T.condForeignLibs s))-{-# INLINE condForeignLibs #-}--condExecutables :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] Executable))]-condExecutables f s = fmap (\x -> s { T.condExecutables = x }) (f (T.condExecutables s))-{-# INLINE condExecutables #-}--condTestSuites :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] TestSuite))]-condTestSuites f s = fmap (\x -> s { T.condTestSuites = x }) (f (T.condTestSuites s))-{-# INLINE condTestSuites #-}--condBenchmarks :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] Benchmark))]-condBenchmarks f s = fmap (\x -> s { T.condBenchmarks = x }) (f (T.condBenchmarks s))-{-# INLINE condBenchmarks #-}--allCondTrees- :: Applicative f- => (forall a. CondTree ConfVar [Dependency] a- -> f (CondTree ConfVar [Dependency] a))- -> GenericPackageDescription- -> f GenericPackageDescription-allCondTrees f (GenericPackageDescription p v a1 x1 x2 x3 x4 x5 x6) =- GenericPackageDescription- <$> pure p- <*> pure v- <*> pure a1- <*> traverse f x1- <*> (traverse . _2) f x2- <*> (traverse . _2) f x3- <*> (traverse . _2) f x4- <*> (traverse . _2) f x5- <*> (traverse . _2) f x6------------------------------------------------------------------------------------- Flag----------------------------------------------------------------------------------flagName :: Lens' PackageFlag FlagName-flagName f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag y1 x2 x3 x4) (f x1)-{-# INLINE flagName #-}--flagDescription :: Lens' PackageFlag String-flagDescription f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 y1 x3 x4) (f x2)-{-# INLINE flagDescription #-}--flagDefault :: Lens' PackageFlag Bool-flagDefault f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 x2 y1 x4) (f x3)-{-# INLINE flagDefault #-}--flagManual :: Lens' PackageFlag Bool-flagManual f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 x2 x3 y1) (f x4)-{-# INLINE flagManual #-}------------------------------------------------------------------------------------ ConfVar----------------------------------------------------------------------------------_OS :: Traversal' ConfVar OS-_OS f (OS os) = OS <$> f os-_OS _ x = pure x--_Arch :: Traversal' ConfVar Arch-_Arch f (Arch arch) = Arch <$> f arch-_Arch _ x = pure x--_PackageFlag :: Traversal' ConfVar FlagName-_PackageFlag f (PackageFlag flag) = PackageFlag <$> f flag-_PackageFlag _ x = pure x--_Impl :: Traversal' ConfVar (CompilerFlavor, VersionRange)-_Impl f (Impl cf vr) = uncurry Impl <$> f (cf, vr)-_Impl _ x = pure x
− Distribution/Types/GivenComponent.hs
@@ -1,28 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.GivenComponent (- GivenComponent(..)-) where--import Distribution.Compat.Prelude--import Distribution.Types.ComponentId-import Distribution.Types.LibraryName-import Distribution.Types.PackageName---- | A 'GivenComponent' represents a library depended on and explicitly--- specified by the user/client with @--dependency@------ It enables Cabal to know which 'ComponentId' to associate with a library------ @since 2.3.0.0-data GivenComponent =- GivenComponent- { givenComponentPackage :: PackageName- , givenComponentName :: LibraryName -- --dependency is for libraries- -- only, not for any component- , givenComponentId :: ComponentId }- deriving (Generic, Read, Show, Eq, Typeable)--instance Binary GivenComponent-instance Structured GivenComponent
− Distribution/Types/HookedBuildInfo.hs
@@ -1,66 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.HookedBuildInfo (- HookedBuildInfo,- emptyHookedBuildInfo,- ) where---- import Distribution.Compat.Prelude-import Distribution.Types.BuildInfo-import Distribution.Types.UnqualComponentName---- | 'HookedBuildInfo' is mechanism that hooks can use to--- override the 'BuildInfo's inside packages. One example--- use-case (which is used in core libraries today) is as--- a way of passing flags which are computed by a configure--- script into Cabal. In this case, the autoconf build type adds--- hooks to read in a textual 'HookedBuildInfo' format prior--- to doing any operations.------ Quite honestly, this mechanism is a massive hack since we shouldn't--- be editing the 'PackageDescription' data structure (it's easy--- to assume that this data structure shouldn't change and--- run into bugs, see for example 1c20a6328579af9e37677d507e2e9836ef70ab9d).--- But it's a bit convenient, because there isn't another data--- structure that allows adding extra 'BuildInfo' style things.------ In any case, a lot of care has to be taken to make sure the--- 'HookedBuildInfo' is applied to the 'PackageDescription'. In--- general this process occurs in "Distribution.Simple", which is--- responsible for orchestrating the hooks mechanism. The--- general strategy:------ 1. We run the pre-hook, which produces a 'HookedBuildInfo'--- (e.g., in the Autoconf case, it reads it out from a file).--- 2. We sanity-check the hooked build info with--- 'sanityCheckHookedBuildInfo'.--- 3. We update our 'PackageDescription' (either freshly read--- or cached from 'LocalBuildInfo') with 'updatePackageDescription'.------ In principle, we are also supposed to update the copy of--- the 'PackageDescription' stored in 'LocalBuildInfo'--- at 'localPkgDescr'. Unfortunately, in practice, there--- are lots of Custom setup scripts which fail to update--- 'localPkgDescr' so you really shouldn't rely on it.--- It's not DEPRECATED because there are legitimate uses--- for it, but... yeah. Sharp knife. See--- <https://github.com/haskell/cabal/issues/3606>--- for more information on the issue.------ It is not well-specified whether or not a 'HookedBuildInfo' applied--- at configure time is persistent to the 'LocalBuildInfo'. The--- fact that 'HookedBuildInfo' is passed to 'confHook' MIGHT SUGGEST--- that the 'HookedBuildInfo' is applied at this time, but actually--- since 9317b67e6122ab14e53f81b573bd0ecb388eca5a it has been ONLY used--- to create a modified package description that we check for problems:--- it is never actually saved to the LBI. Since 'HookedBuildInfo' is--- applied monoidally to the existing build infos (and it is not an--- idempotent monoid), it could break things to save it, since we--- are obligated to apply any new 'HookedBuildInfo' and then we'd--- get the effect twice. But this does mean we have to re-apply--- it every time. Hey, it's more flexibility.-type HookedBuildInfo = (Maybe BuildInfo, [(UnqualComponentName, BuildInfo)])--emptyHookedBuildInfo :: HookedBuildInfo-emptyHookedBuildInfo = (Nothing, [])
− Distribution/Types/IncludeRenaming.hs
@@ -1,68 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.IncludeRenaming (- IncludeRenaming(..),- defaultIncludeRenaming,- isDefaultIncludeRenaming,-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.ModuleRenaming--import qualified Distribution.Compat.CharParsing as P-import Distribution.Parsec-import Distribution.Pretty-import Text.PrettyPrint (text)-import qualified Text.PrettyPrint as Disp---- ------------------------------------------------------------------------------ Module renaming---- | A renaming on an include: (provides renaming, requires renaming)-data IncludeRenaming- = IncludeRenaming {- includeProvidesRn :: ModuleRenaming,- includeRequiresRn :: ModuleRenaming- }- deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)--instance Binary IncludeRenaming-instance Structured IncludeRenaming--instance NFData IncludeRenaming where rnf = genericRnf---- | The 'defaultIncludeRenaming' applied when you only @build-depends@--- on a package.-defaultIncludeRenaming :: IncludeRenaming-defaultIncludeRenaming = IncludeRenaming defaultRenaming defaultRenaming---- | Is an 'IncludeRenaming' the default one?-isDefaultIncludeRenaming :: IncludeRenaming -> Bool-isDefaultIncludeRenaming (IncludeRenaming p r) = isDefaultRenaming p && isDefaultRenaming r--instance Pretty IncludeRenaming where- pretty (IncludeRenaming prov_rn req_rn) =- pretty prov_rn- <+> (if isDefaultRenaming req_rn- then Disp.empty- else text "requires" <+> pretty req_rn)--instance Parsec IncludeRenaming where- parsec = do- prov_rn <- parsec- req_rn <- P.option defaultRenaming $ P.try $ do- P.spaces -- no need to be space- _ <- P.string "requires"- P.spaces- parsec- -- Requirements don't really care if they're mentioned- -- or not (since you can't thin a requirement.) But- -- we have a little hack in Configure to combine- -- the provisions and requirements together before passing- -- them to GHC, and so the most neutral choice for a requirement- -- is for the "with" field to be False, so we correctly- -- thin provisions.- return (IncludeRenaming prov_rn req_rn)
− Distribution/Types/InstalledPackageInfo.hs
@@ -1,173 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE OverloadedStrings #-}-module Distribution.Types.InstalledPackageInfo (- InstalledPackageInfo (..),- emptyInstalledPackageInfo,- mungedPackageId,- mungedPackageName,- AbiDependency (..),- ExposedModule (..),- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Backpack-import Distribution.Compat.Graph (IsNode (..))-import Distribution.License-import Distribution.ModuleName-import Distribution.Package hiding (installedUnitId)-import Distribution.Types.AbiDependency-import Distribution.Types.ExposedModule-import Distribution.Types.LibraryName-import Distribution.Types.LibraryVisibility-import Distribution.Types.MungedPackageId-import Distribution.Types.MungedPackageName-import Distribution.Version (nullVersion)-import Distribution.Utils.ShortText (ShortText)--import qualified Distribution.Package as Package-import qualified Distribution.SPDX as SPDX---- -------------------------------------------------------------------------------- The InstalledPackageInfo type---- 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 (sourcePackageId, installedUnitId) are- -- exactly the same as PackageDescription- sourcePackageId :: PackageId,- sourceLibName :: LibraryName,- installedComponentId_ :: ComponentId,- libVisibility :: LibraryVisibility,- installedUnitId :: UnitId,- -- INVARIANT: if this package is definite, OpenModule's- -- OpenUnitId directly records UnitId. If it is- -- indefinite, OpenModule is always an OpenModuleVar- -- with the same ModuleName as the key.- instantiatedWith :: [(ModuleName, OpenModule)],- compatPackageKey :: String,- license :: Either SPDX.License License,- copyright :: !ShortText,- maintainer :: !ShortText,- author :: !ShortText,- stability :: !ShortText,- homepage :: !ShortText,- pkgUrl :: !ShortText,- synopsis :: !ShortText,- description :: !ShortText,- category :: !ShortText,- -- these parts are required by an installed package only:- abiHash :: AbiHash,- indefinite :: Bool,- exposed :: Bool,- -- INVARIANT: if the package is definite, OpenModule's- -- OpenUnitId directly records UnitId.- exposedModules :: [ExposedModule],- hiddenModules :: [ModuleName],- trusted :: Bool,- importDirs :: [FilePath],- libraryDirs :: [FilePath],- libraryDynDirs :: [FilePath], -- ^ overrides 'libraryDirs'- dataDir :: FilePath,- hsLibraries :: [String],- extraLibraries :: [String],- extraGHCiLibraries:: [String], -- overrides extraLibraries for GHCi- includeDirs :: [FilePath],- includes :: [String],- -- INVARIANT: if the package is definite, UnitId is NOT- -- a ComponentId of an indefinite package- depends :: [UnitId],- abiDepends :: [AbiDependency],- ccOptions :: [String],- cxxOptions :: [String],- ldOptions :: [String],- frameworkDirs :: [FilePath],- frameworks :: [String],- haddockInterfaces :: [FilePath],- haddockHTMLs :: [FilePath],- pkgRoot :: Maybe FilePath- }- deriving (Eq, Generic, Typeable, Read, Show)--instance Binary InstalledPackageInfo-instance Structured InstalledPackageInfo--instance NFData InstalledPackageInfo where rnf = genericRnf--instance Package.HasMungedPackageId InstalledPackageInfo where- mungedId = mungedPackageId--instance Package.Package InstalledPackageInfo where- packageId = sourcePackageId--instance Package.HasUnitId InstalledPackageInfo where- installedUnitId = installedUnitId--instance Package.PackageInstalled InstalledPackageInfo where- installedDepends = depends--instance IsNode InstalledPackageInfo where- type Key InstalledPackageInfo = UnitId- nodeKey = installedUnitId- nodeNeighbors = depends--mungedPackageId :: InstalledPackageInfo -> MungedPackageId-mungedPackageId ipi =- MungedPackageId (mungedPackageName ipi) (packageVersion ipi)---- | Returns the munged package name, which we write into @name@ for--- compatibility with old versions of GHC.-mungedPackageName :: InstalledPackageInfo -> MungedPackageName-mungedPackageName ipi = MungedPackageName (packageName ipi) (sourceLibName ipi)--emptyInstalledPackageInfo :: InstalledPackageInfo-emptyInstalledPackageInfo- = InstalledPackageInfo {- sourcePackageId = PackageIdentifier (mkPackageName "") nullVersion,- sourceLibName = LMainLibName,- installedComponentId_ = mkComponentId "",- installedUnitId = mkUnitId "",- instantiatedWith = [],- compatPackageKey = "",- license = Left SPDX.NONE,- copyright = "",- maintainer = "",- author = "",- stability = "",- homepage = "",- pkgUrl = "",- synopsis = "",- description = "",- category = "",- abiHash = mkAbiHash "",- indefinite = False,- exposed = False,- exposedModules = [],- hiddenModules = [],- trusted = False,- importDirs = [],- libraryDirs = [],- libraryDynDirs = [],- dataDir = "",- hsLibraries = [],- extraLibraries = [],- extraGHCiLibraries= [],- includeDirs = [],- includes = [],- depends = [],- abiDepends = [],- ccOptions = [],- cxxOptions = [],- ldOptions = [],- frameworkDirs = [],- frameworks = [],- haddockInterfaces = [],- haddockHTMLs = [],- pkgRoot = Nothing,- libVisibility = LibraryVisibilityPrivate- }
− Distribution/Types/InstalledPackageInfo/FieldGrammar.hs
@@ -1,317 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-module Distribution.Types.InstalledPackageInfo.FieldGrammar (- ipiFieldGrammar,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Backpack-import Distribution.CabalSpecVersion-import Distribution.Compat.Lens (Lens', (&), (.~))-import Distribution.Compat.Newtype-import Distribution.FieldGrammar-import Distribution.FieldGrammar.FieldDescrs-import Distribution.License-import Distribution.ModuleName-import Distribution.Package-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.LibraryName-import Distribution.Types.LibraryVisibility-import Distribution.Types.MungedPackageName-import Distribution.Types.UnqualComponentName-import Distribution.Version--import qualified Data.Char as Char-import qualified Data.Map as Map-import qualified Distribution.Compat.CharParsing as P-import qualified Distribution.SPDX as SPDX-import qualified Text.PrettyPrint as Disp--import Distribution.Types.InstalledPackageInfo--import qualified Distribution.Types.InstalledPackageInfo.Lens as L-import qualified Distribution.Types.PackageId.Lens as L---- Note: GHC goes nuts and inlines everything,--- One can see e.g. in -ddump-simpl-stats:------ 34886 KnownBranch--- 8197 wild1_ixF0------ https://gitlab.haskell.org/ghc/ghc/-/issues/13253 might be the cause.------ The workaround is to prevent GHC optimising the code:-infixl 4 <@>-(<@>) :: Applicative f => f (a -> b) -> f a -> f b-f <@> x = f <*> x-{-# NOINLINE (<@>) #-}--ipiFieldGrammar- :: ( FieldGrammar c g, Applicative (g InstalledPackageInfo), Applicative (g Basic)- , c (Identity AbiHash)- , c (Identity LibraryVisibility)- , c (Identity PackageName)- , c (Identity UnitId)- , c (Identity UnqualComponentName)- , c (List FSep (Identity AbiDependency) AbiDependency)- , c (List FSep (Identity UnitId) UnitId)- , c (List FSep (MQuoted ModuleName) ModuleName)- , c (List FSep FilePathNT String)- , c (List FSep Token String)- , c (MQuoted MungedPackageName)- , c (MQuoted Version)- , c CompatPackageKey- , c ExposedModules- , c InstWith- , c SpecLicenseLenient- )- => g InstalledPackageInfo InstalledPackageInfo-ipiFieldGrammar = mkInstalledPackageInfo- -- Deprecated fields- <$> monoidalFieldAla "hugs-options" (alaList' FSep Token) unitedList- --- https://github.com/haskell/cabal/commit/40f3601e17024f07e0da8e64d3dd390177ce908b- ^^^ deprecatedSince CabalSpecV1_22 "hugs isn't supported anymore"- -- Very basic fields: name, version, package-name, lib-name and visibility- <@> blurFieldGrammar basic basicFieldGrammar- -- Basic fields- <@> optionalFieldDef "id" L.installedUnitId (mkUnitId "")- <@> optionalFieldDefAla "instantiated-with" InstWith L.instantiatedWith []- <@> optionalFieldDefAla "key" CompatPackageKey L.compatPackageKey ""- <@> optionalFieldDefAla "license" SpecLicenseLenient L.license (Left SPDX.NONE)- <@> freeTextFieldDefST "copyright" L.copyright- <@> freeTextFieldDefST "maintainer" L.maintainer- <@> freeTextFieldDefST "author" L.author- <@> freeTextFieldDefST "stability" L.stability- <@> freeTextFieldDefST "homepage" L.homepage- <@> freeTextFieldDefST "package-url" L.pkgUrl- <@> freeTextFieldDefST "synopsis" L.synopsis- <@> freeTextFieldDefST "description" L.description- <@> freeTextFieldDefST "category" L.category- -- Installed fields- <@> optionalFieldDef "abi" L.abiHash (mkAbiHash "")- <@> booleanFieldDef "indefinite" L.indefinite False- <@> booleanFieldDef "exposed" L.exposed False- <@> monoidalFieldAla "exposed-modules" ExposedModules L.exposedModules- <@> monoidalFieldAla "hidden-modules" (alaList' FSep MQuoted) L.hiddenModules- <@> booleanFieldDef "trusted" L.trusted False- <@> monoidalFieldAla "import-dirs" (alaList' FSep FilePathNT) L.importDirs- <@> monoidalFieldAla "library-dirs" (alaList' FSep FilePathNT) L.libraryDirs- <@> monoidalFieldAla "dynamic-library-dirs" (alaList' FSep FilePathNT) L.libraryDynDirs- <@> optionalFieldDefAla "data-dir" FilePathNT L.dataDir ""- <@> monoidalFieldAla "hs-libraries" (alaList' FSep Token) L.hsLibraries- <@> monoidalFieldAla "extra-libraries" (alaList' FSep Token) L.extraLibraries- <@> monoidalFieldAla "extra-ghci-libraries" (alaList' FSep Token) L.extraGHCiLibraries- <@> monoidalFieldAla "include-dirs" (alaList' FSep FilePathNT) L.includeDirs- <@> monoidalFieldAla "includes" (alaList' FSep FilePathNT) L.includes- <@> monoidalFieldAla "depends" (alaList FSep) L.depends- <@> monoidalFieldAla "abi-depends" (alaList FSep) L.abiDepends- <@> monoidalFieldAla "cc-options" (alaList' FSep Token) L.ccOptions- <@> monoidalFieldAla "cxx-options" (alaList' FSep Token) L.cxxOptions- <@> monoidalFieldAla "ld-options" (alaList' FSep Token) L.ldOptions- <@> monoidalFieldAla "framework-dirs" (alaList' FSep FilePathNT) L.frameworkDirs- <@> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks- <@> monoidalFieldAla "haddock-interfaces" (alaList' FSep FilePathNT) L.haddockInterfaces- <@> monoidalFieldAla "haddock-html" (alaList' FSep FilePathNT) L.haddockHTMLs- <@> optionalFieldAla "pkgroot" FilePathNT L.pkgRoot- where- mkInstalledPackageInfo _ Basic {..} = InstalledPackageInfo- -- _basicPkgName is not used- -- setMaybePackageId says it can be no-op.- (PackageIdentifier pn _basicVersion)- (combineLibraryName ln _basicLibName)- (mkComponentId "") -- installedComponentId_, not in use- _basicLibVisibility- where- MungedPackageName pn ln = _basicName-{-# SPECIALIZE ipiFieldGrammar :: FieldDescrs InstalledPackageInfo InstalledPackageInfo #-}-{-# SPECIALIZE ipiFieldGrammar :: ParsecFieldGrammar InstalledPackageInfo InstalledPackageInfo #-}-{-# SPECIALIZE ipiFieldGrammar :: PrettyFieldGrammar InstalledPackageInfo InstalledPackageInfo #-}---- (forall b. [b]) ~ ()-unitedList :: Lens' a [b]-unitedList f s = s <$ f []------------------------------------------------------------------------------------ Helper functions------------------------------------------------------------------------------------ | Combine 'LibraryName'. in parsing we prefer value coming--- from munged @name@ field over the @lib-name@.------ /Should/ be irrelevant.-combineLibraryName :: LibraryName -> LibraryName -> LibraryName-combineLibraryName l@(LSubLibName _) _ = l-combineLibraryName _ l = l---- To maintain backwards-compatibility, we accept both comma/non-comma--- separated variants of this field. You SHOULD use the comma syntax if you--- use any new functions, although actually it's unambiguous due to a quirk--- of the fact that modules must start with capital letters.--showExposedModules :: [ExposedModule] -> Disp.Doc-showExposedModules xs- | all isExposedModule xs = Disp.fsep (map pretty xs)- | otherwise = Disp.fsep (Disp.punctuate Disp.comma (map pretty xs))- where isExposedModule (ExposedModule _ Nothing) = True- isExposedModule _ = False---- | Setter for the @package-name@ field. It should be acceptable for this--- to be a no-op.-setMaybePackageName :: Maybe PackageName -> InstalledPackageInfo -> InstalledPackageInfo-setMaybePackageName Nothing ipi = ipi-setMaybePackageName (Just pn) ipi = ipi- { sourcePackageId = (sourcePackageId ipi) {pkgName=pn}- }--setMungedPackageName :: MungedPackageName -> InstalledPackageInfo -> InstalledPackageInfo-setMungedPackageName (MungedPackageName pn ln) ipi = ipi- { sourcePackageId = (sourcePackageId ipi) {pkgName=pn}- , sourceLibName = ln- }----- | Returns @Just@ if the @name@ field of the IPI record would not contain---- the package name verbatim. This helps us avoid writing @package-name@---- when it's redundant.-maybePackageName :: InstalledPackageInfo -> Maybe PackageName-maybePackageName ipi = case sourceLibName ipi of- LMainLibName -> Nothing- LSubLibName _ -> Just (packageName ipi)------------------------------------------------------------------------------------ Auxiliary types----------------------------------------------------------------------------------newtype ExposedModules = ExposedModules { getExposedModules :: [ExposedModule] }--instance Newtype [ExposedModule] ExposedModules--instance Parsec ExposedModules where- parsec = ExposedModules <$> parsecOptCommaList parsec--instance Pretty ExposedModules where- pretty = showExposedModules . getExposedModules--newtype CompatPackageKey = CompatPackageKey { getCompatPackageKey :: String }--instance Newtype String CompatPackageKey--instance Pretty CompatPackageKey where- pretty = Disp.text . getCompatPackageKey--instance Parsec CompatPackageKey where- parsec = CompatPackageKey <$> P.munch1 uid_char where- uid_char c = Char.isAlphaNum c || c `elem` ("-_.=[],:<>+" :: String)--newtype InstWith = InstWith { getInstWith :: [(ModuleName,OpenModule)] }--instance Newtype [(ModuleName, OpenModule)] InstWith--instance Pretty InstWith where- pretty = dispOpenModuleSubst . Map.fromList . getInstWith--instance Parsec InstWith where- parsec = InstWith . Map.toList <$> parsecOpenModuleSubst---- | SPDX License expression or legacy license. Lenient parser, accepts either.-newtype SpecLicenseLenient = SpecLicenseLenient { getSpecLicenseLenient :: Either SPDX.License License }--instance Newtype (Either SPDX.License License) SpecLicenseLenient--instance Parsec SpecLicenseLenient where- parsec = fmap SpecLicenseLenient $ Left <$> P.try parsec <|> Right <$> parsec--instance Pretty SpecLicenseLenient where- pretty = either pretty pretty . getSpecLicenseLenient------------------------------------------------------------------------------------ Basic fields------------------------------------------------------------------------------------ | This type is used to mangle fields as--- in serialised textual representation--- to the actual 'InstalledPackageInfo' fields.-data Basic = Basic- { _basicName :: MungedPackageName- , _basicVersion :: Version- , _basicPkgName :: Maybe PackageName- , _basicLibName :: LibraryName- , _basicLibVisibility :: LibraryVisibility- }--basic :: Lens' InstalledPackageInfo Basic-basic f ipi = g <$> f b- where- b = Basic- (mungedPackageName ipi)- (packageVersion ipi)- (maybePackageName ipi)- (sourceLibName ipi)- (libVisibility ipi)-- g (Basic n v pn ln lv) = ipi- & setMungedPackageName n- & L.sourcePackageId . L.pkgVersion .~ v- & setMaybePackageName pn- & L.sourceLibName .~ ln- & L.libVisibility .~ lv--basicName :: Lens' Basic MungedPackageName-basicName f b = (\x -> b { _basicName = x }) <$> f (_basicName b)-{-# INLINE basicName #-}--basicVersion :: Lens' Basic Version-basicVersion f b = (\x -> b { _basicVersion = x }) <$> f (_basicVersion b)-{-# INLINE basicVersion #-}--basicPkgName :: Lens' Basic (Maybe PackageName)-basicPkgName f b = (\x -> b { _basicPkgName = x }) <$> f (_basicPkgName b)-{-# INLINE basicPkgName #-}--basicLibName :: Lens' Basic (Maybe UnqualComponentName)-basicLibName f b = (\x -> b { _basicLibName = maybeToLibraryName x }) <$>- f (libraryNameString (_basicLibName b))-{-# INLINE basicLibName #-}--basicLibVisibility :: Lens' Basic LibraryVisibility-basicLibVisibility f b = (\x -> b { _basicLibVisibility = x }) <$>- f (_basicLibVisibility b)-{-# INLINE basicLibVisibility #-}--basicFieldGrammar- :: ( FieldGrammar c g, Applicative (g Basic)- , c (Identity LibraryVisibility)- , c (Identity PackageName)- , c (Identity UnqualComponentName)- , c (MQuoted MungedPackageName)- , c (MQuoted Version)- )- => g Basic Basic-basicFieldGrammar = mkBasic- <$> optionalFieldDefAla "name" MQuoted basicName (mungedPackageName emptyInstalledPackageInfo)- <*> optionalFieldDefAla "version" MQuoted basicVersion nullVersion- <*> optionalField "package-name" basicPkgName- <*> optionalField "lib-name" basicLibName- <*> optionalFieldDef "visibility" basicLibVisibility LibraryVisibilityPrivate- where- mkBasic n v pn ln lv = Basic n v pn ln' lv'- where- ln' = maybe LMainLibName LSubLibName ln- -- Older GHCs (<8.8) always report installed libraries as private- -- because their ghc-pkg builds with an older Cabal.- -- So we always set LibraryVisibilityPublic for main (unnamed) libs.- -- This can be removed once we stop supporting GHC<8.8, at the- -- condition that we keep marking main libraries as public when- -- registering them.- lv' = if- let MungedPackageName _ mln = n in- -- We need to check both because on ghc<8.2 ln' will always- -- be LMainLibName- ln' == LMainLibName && mln == LMainLibName- then LibraryVisibilityPublic- else lv
− Distribution/Types/InstalledPackageInfo/Lens.hs
@@ -1,190 +0,0 @@-module Distribution.Types.InstalledPackageInfo.Lens (- InstalledPackageInfo,- module Distribution.Types.InstalledPackageInfo.Lens- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Backpack (OpenModule)-import Distribution.License (License)-import Distribution.ModuleName (ModuleName)-import Distribution.Package (AbiHash, ComponentId, PackageIdentifier, UnitId)-import Distribution.Types.InstalledPackageInfo (AbiDependency, ExposedModule, InstalledPackageInfo)-import Distribution.Types.LibraryName (LibraryName)-import Distribution.Types.LibraryVisibility (LibraryVisibility)-import Distribution.Utils.ShortText (ShortText)---import qualified Distribution.SPDX as SPDX-import qualified Distribution.Types.InstalledPackageInfo as T--sourcePackageId :: Lens' InstalledPackageInfo PackageIdentifier-sourcePackageId f s = fmap (\x -> s { T.sourcePackageId = x }) (f (T.sourcePackageId s))-{-# INLINE sourcePackageId #-}--installedUnitId :: Lens' InstalledPackageInfo UnitId-installedUnitId f s = fmap (\x -> s { T.installedUnitId = x }) (f (T.installedUnitId s))-{-# INLINE installedUnitId #-}--installedComponentId_ :: Lens' InstalledPackageInfo ComponentId-installedComponentId_ f s = fmap (\x -> s { T.installedComponentId_ = x }) (f (T.installedComponentId_ s))-{-# INLINE installedComponentId_ #-}--instantiatedWith :: Lens' InstalledPackageInfo [(ModuleName,OpenModule)]-instantiatedWith f s = fmap (\x -> s { T.instantiatedWith = x }) (f (T.instantiatedWith s))-{-# INLINE instantiatedWith #-}--sourceLibName :: Lens' InstalledPackageInfo LibraryName-sourceLibName f s = fmap (\x -> s { T.sourceLibName = x }) (f (T.sourceLibName s))-{-# INLINE sourceLibName #-}--compatPackageKey :: Lens' InstalledPackageInfo String-compatPackageKey f s = fmap (\x -> s { T.compatPackageKey = x }) (f (T.compatPackageKey s))-{-# INLINE compatPackageKey #-}--license :: Lens' InstalledPackageInfo (Either SPDX.License License)-license f s = fmap (\x -> s { T.license = x }) (f (T.license s))-{-# INLINE license #-}--copyright :: Lens' InstalledPackageInfo ShortText-copyright f s = fmap (\x -> s { T.copyright = x }) (f (T.copyright s))-{-# INLINE copyright #-}--maintainer :: Lens' InstalledPackageInfo ShortText-maintainer f s = fmap (\x -> s { T.maintainer = x }) (f (T.maintainer s))-{-# INLINE maintainer #-}--author :: Lens' InstalledPackageInfo ShortText-author f s = fmap (\x -> s { T.author = x }) (f (T.author s))-{-# INLINE author #-}--stability :: Lens' InstalledPackageInfo ShortText-stability f s = fmap (\x -> s { T.stability = x }) (f (T.stability s))-{-# INLINE stability #-}--homepage :: Lens' InstalledPackageInfo ShortText-homepage f s = fmap (\x -> s { T.homepage = x }) (f (T.homepage s))-{-# INLINE homepage #-}--pkgUrl :: Lens' InstalledPackageInfo ShortText-pkgUrl f s = fmap (\x -> s { T.pkgUrl = x }) (f (T.pkgUrl s))-{-# INLINE pkgUrl #-}--synopsis :: Lens' InstalledPackageInfo ShortText-synopsis f s = fmap (\x -> s { T.synopsis = x }) (f (T.synopsis s))-{-# INLINE synopsis #-}--description :: Lens' InstalledPackageInfo ShortText-description f s = fmap (\x -> s { T.description = x }) (f (T.description s))-{-# INLINE description #-}--category :: Lens' InstalledPackageInfo ShortText-category f s = fmap (\x -> s { T.category = x }) (f (T.category s))-{-# INLINE category #-}--abiHash :: Lens' InstalledPackageInfo AbiHash-abiHash f s = fmap (\x -> s { T.abiHash = x }) (f (T.abiHash s))-{-# INLINE abiHash #-}--indefinite :: Lens' InstalledPackageInfo Bool-indefinite f s = fmap (\x -> s { T.indefinite = x }) (f (T.indefinite s))-{-# INLINE indefinite #-}--exposed :: Lens' InstalledPackageInfo Bool-exposed f s = fmap (\x -> s { T.exposed = x }) (f (T.exposed s))-{-# INLINE exposed #-}--exposedModules :: Lens' InstalledPackageInfo [ExposedModule]-exposedModules f s = fmap (\x -> s { T.exposedModules = x }) (f (T.exposedModules s))-{-# INLINE exposedModules #-}--hiddenModules :: Lens' InstalledPackageInfo [ModuleName]-hiddenModules f s = fmap (\x -> s { T.hiddenModules = x }) (f (T.hiddenModules s))-{-# INLINE hiddenModules #-}--trusted :: Lens' InstalledPackageInfo Bool-trusted f s = fmap (\x -> s { T.trusted = x }) (f (T.trusted s))-{-# INLINE trusted #-}--importDirs :: Lens' InstalledPackageInfo [FilePath]-importDirs f s = fmap (\x -> s { T.importDirs = x }) (f (T.importDirs s))-{-# INLINE importDirs #-}--libraryDirs :: Lens' InstalledPackageInfo [FilePath]-libraryDirs f s = fmap (\x -> s { T.libraryDirs = x }) (f (T.libraryDirs s))-{-# INLINE libraryDirs #-}--libraryDynDirs :: Lens' InstalledPackageInfo [FilePath]-libraryDynDirs f s = fmap (\x -> s { T.libraryDynDirs = x }) (f (T.libraryDynDirs s))-{-# INLINE libraryDynDirs #-}--dataDir :: Lens' InstalledPackageInfo FilePath-dataDir f s = fmap (\x -> s { T.dataDir = x }) (f (T.dataDir s))-{-# INLINE dataDir #-}--hsLibraries :: Lens' InstalledPackageInfo [String]-hsLibraries f s = fmap (\x -> s { T.hsLibraries = x }) (f (T.hsLibraries s))-{-# INLINE hsLibraries #-}--extraLibraries :: Lens' InstalledPackageInfo [String]-extraLibraries f s = fmap (\x -> s { T.extraLibraries = x }) (f (T.extraLibraries s))-{-# INLINE extraLibraries #-}--extraGHCiLibraries :: Lens' InstalledPackageInfo [String]-extraGHCiLibraries f s = fmap (\x -> s { T.extraGHCiLibraries = x }) (f (T.extraGHCiLibraries s))-{-# INLINE extraGHCiLibraries #-}--includeDirs :: Lens' InstalledPackageInfo [FilePath]-includeDirs f s = fmap (\x -> s { T.includeDirs = x }) (f (T.includeDirs s))-{-# INLINE includeDirs #-}--includes :: Lens' InstalledPackageInfo [String]-includes f s = fmap (\x -> s { T.includes = x }) (f (T.includes s))-{-# INLINE includes #-}--depends :: Lens' InstalledPackageInfo [UnitId]-depends f s = fmap (\x -> s { T.depends = x }) (f (T.depends s))-{-# INLINE depends #-}--abiDepends :: Lens' InstalledPackageInfo [AbiDependency]-abiDepends f s = fmap (\x -> s { T.abiDepends = x }) (f (T.abiDepends s))-{-# INLINE abiDepends #-}--ccOptions :: Lens' InstalledPackageInfo [String]-ccOptions f s = fmap (\x -> s { T.ccOptions = x }) (f (T.ccOptions s))-{-# INLINE ccOptions #-}--cxxOptions :: Lens' InstalledPackageInfo [String]-cxxOptions f s = fmap (\x -> s { T.cxxOptions = x }) (f (T.cxxOptions s))-{-# INLINE cxxOptions #-}--ldOptions :: Lens' InstalledPackageInfo [String]-ldOptions f s = fmap (\x -> s { T.ldOptions = x }) (f (T.ldOptions s))-{-# INLINE ldOptions #-}--frameworkDirs :: Lens' InstalledPackageInfo [FilePath]-frameworkDirs f s = fmap (\x -> s { T.frameworkDirs = x }) (f (T.frameworkDirs s))-{-# INLINE frameworkDirs #-}--frameworks :: Lens' InstalledPackageInfo [String]-frameworks f s = fmap (\x -> s { T.frameworks = x }) (f (T.frameworks s))-{-# INLINE frameworks #-}--haddockInterfaces :: Lens' InstalledPackageInfo [FilePath]-haddockInterfaces f s = fmap (\x -> s { T.haddockInterfaces = x }) (f (T.haddockInterfaces s))-{-# INLINE haddockInterfaces #-}--haddockHTMLs :: Lens' InstalledPackageInfo [FilePath]-haddockHTMLs f s = fmap (\x -> s { T.haddockHTMLs = x }) (f (T.haddockHTMLs s))-{-# INLINE haddockHTMLs #-}--pkgRoot :: Lens' InstalledPackageInfo (Maybe FilePath)-pkgRoot f s = fmap (\x -> s { T.pkgRoot = x }) (f (T.pkgRoot s))-{-# INLINE pkgRoot #-}--libVisibility :: Lens' InstalledPackageInfo LibraryVisibility-libVisibility f s = fmap (\x -> s { T.libVisibility = x }) (f (T.libVisibility s))-{-# INLINE libVisibility #-}-
− Distribution/Types/LegacyExeDependency.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.LegacyExeDependency- ( LegacyExeDependency(..)- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Version (VersionRange, anyVersion)--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | Describes a legacy `build-tools`-style dependency on an executable------ It is "legacy" because we do not know what the build-tool referred to. It--- could refer to a pkg-config executable (PkgconfigName), or an internal--- executable (UnqualComponentName). Thus the name is stringly typed.------ @since 2.0.0.2-data LegacyExeDependency = LegacyExeDependency- String- VersionRange- deriving (Generic, Read, Show, Eq, Typeable, Data)--instance Binary LegacyExeDependency-instance Structured LegacyExeDependency-instance NFData LegacyExeDependency where rnf = genericRnf--instance Pretty LegacyExeDependency where- pretty (LegacyExeDependency name ver) =- Disp.text name <+> pretty ver--instance Parsec LegacyExeDependency where- parsec = do- name <- parsecMaybeQuoted nameP- P.spaces- verRange <- parsecMaybeQuoted parsec <|> pure anyVersion- pure $ LegacyExeDependency name verRange- where- nameP = intercalate "-" <$> toList <$> P.sepByNonEmpty component (P.char '-')- component = do- cs <- P.munch1 (\c -> isAlphaNum c || c == '+' || c == '_')- if all isDigit cs then fail "invalid component" else return cs
− Distribution/Types/Lens.hs
@@ -1,25 +0,0 @@-module Distribution.Types.Lens (- module Distribution.Types.Benchmark.Lens,- module Distribution.Types.BuildInfo.Lens,- module Distribution.Types.Executable.Lens,- module Distribution.Types.ForeignLib.Lens,- module Distribution.Types.GenericPackageDescription.Lens,- module Distribution.Types.Library.Lens,- module Distribution.Types.PackageDescription.Lens,- module Distribution.Types.PackageId.Lens,- module Distribution.Types.SetupBuildInfo.Lens,- module Distribution.Types.SourceRepo.Lens,- module Distribution.Types.TestSuite.Lens,- ) where--import Distribution.Types.Benchmark.Lens-import Distribution.Types.BuildInfo.Lens-import Distribution.Types.Executable.Lens-import Distribution.Types.ForeignLib.Lens-import Distribution.Types.GenericPackageDescription.Lens-import Distribution.Types.Library.Lens-import Distribution.Types.PackageDescription.Lens-import Distribution.Types.PackageId.Lens-import Distribution.Types.SetupBuildInfo.Lens-import Distribution.Types.SourceRepo.Lens-import Distribution.Types.TestSuite.Lens
− Distribution/Types/Library.hs
@@ -1,96 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.Library (- Library(..),- emptyLibrary,- explicitLibModules,- libModulesAutogen,-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.ModuleName-import Distribution.Types.BuildInfo-import Distribution.Types.LibraryVisibility-import Distribution.Types.ModuleReexport-import Distribution.Types.LibraryName--import qualified Distribution.Types.BuildInfo.Lens as L--data Library = Library- { libName :: LibraryName- , exposedModules :: [ModuleName]- , reexportedModules :: [ModuleReexport]- , signatures :: [ModuleName] -- ^ What sigs need implementations?- , libExposed :: Bool -- ^ Is the lib to be exposed by default? (i.e. whether its modules available in GHCi for example)- , libVisibility :: LibraryVisibility -- ^ Whether this multilib can be dependent from outside.- , libBuildInfo :: BuildInfo- }- deriving (Generic, Show, Eq, Read, Typeable, Data)--instance L.HasBuildInfo Library where- buildInfo f l = (\x -> l { libBuildInfo = x }) <$> f (libBuildInfo l)--instance Binary Library-instance Structured Library-instance NFData Library where rnf = genericRnf--emptyLibrary :: Library-emptyLibrary = Library- { libName = LMainLibName- , exposedModules = mempty- , reexportedModules = mempty- , signatures = mempty- , libExposed = True- , libVisibility = mempty- , libBuildInfo = mempty- }---- | This instance is not good.------ We need it for 'PackageDescription.Configuration.addBuildableCondition'.--- More correct method would be some kind of "create empty clone".------ More concretely, 'addBuildableCondition' will make `libVisibility = False`--- libraries when `buildable: false`. This may cause problems.----instance Monoid Library where- mempty = emptyLibrary- mappend = (<>)--instance Semigroup Library where- a <> b = Library- { libName = combineLibraryName (libName a) (libName b)- , exposedModules = combine exposedModules- , reexportedModules = combine reexportedModules- , signatures = combine signatures- , libExposed = libExposed a && libExposed b -- so False propagates- , libVisibility = combine libVisibility- , libBuildInfo = combine libBuildInfo- }- where combine field = field a `mappend` field b---- | Get all the module names from the library (exposed and internal modules)--- which are explicitly listed in the package description which would--- need to be compiled. (This does not include reexports, which--- do not need to be compiled.) This may not include all modules for which--- GHC generated interface files (i.e., implicit modules.)-explicitLibModules :: Library -> [ModuleName]-explicitLibModules lib = exposedModules lib- ++ otherModules (libBuildInfo lib)- ++ signatures lib---- | Get all the auto generated module names from the library, exposed or not.--- This are a subset of 'libModules'.-libModulesAutogen :: Library -> [ModuleName]-libModulesAutogen lib = autogenModules (libBuildInfo lib)---- | Combine 'LibraryName'. in parsing we prefer value coming--- from munged @name@ field over the @lib-name@.------ /Should/ be irrelevant.-combineLibraryName :: LibraryName -> LibraryName -> LibraryName-combineLibraryName l@(LSubLibName _) _ = l-combineLibraryName _ l = l
− Distribution/Types/Library/Lens.hs
@@ -1,45 +0,0 @@-module Distribution.Types.Library.Lens (- Library,- module Distribution.Types.Library.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.ModuleName (ModuleName)-import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.Library (Library)-import Distribution.Types.LibraryName (LibraryName)-import Distribution.Types.LibraryVisibility (LibraryVisibility)-import Distribution.Types.ModuleReexport (ModuleReexport)--import qualified Distribution.Types.Library as T--libName :: Lens' Library LibraryName-libName f s = fmap (\x -> s { T.libName = x }) (f (T.libName s))-{-# INLINE libName #-}--exposedModules :: Lens' Library [ModuleName]-exposedModules f s = fmap (\x -> s { T.exposedModules = x }) (f (T.exposedModules s))-{-# INLINE exposedModules #-}--reexportedModules :: Lens' Library [ModuleReexport]-reexportedModules f s = fmap (\x -> s { T.reexportedModules = x }) (f (T.reexportedModules s))-{-# INLINE reexportedModules #-}--signatures :: Lens' Library [ModuleName]-signatures f s = fmap (\x -> s { T.signatures = x }) (f (T.signatures s))-{-# INLINE signatures #-}--libExposed :: Lens' Library Bool-libExposed f s = fmap (\x -> s { T.libExposed = x }) (f (T.libExposed s))-{-# INLINE libExposed #-}--libVisibility :: Lens' Library LibraryVisibility-libVisibility f s = fmap (\x -> s { T.libVisibility = x }) (f (T.libVisibility s))-{-# INLINE libVisibility #-}--libBuildInfo :: Lens' Library BuildInfo-libBuildInfo f s = fmap (\x -> s { T.libBuildInfo = x }) (f (T.libBuildInfo s))-{-# INLINE libBuildInfo #-}
− Distribution/Types/LibraryName.hs
@@ -1,73 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.LibraryName (- LibraryName(..),- defaultLibName,- maybeToLibraryName,- showLibraryName,- libraryNameStanza,- libraryNameString,- -- * Pretty & Parse- prettyLibraryNameComponent,- parsecLibraryNameComponent,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.UnqualComponentName-import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp--data LibraryName = LMainLibName- | LSubLibName UnqualComponentName- deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)--instance Binary LibraryName-instance Structured LibraryName-instance NFData LibraryName where rnf = genericRnf---- | Pretty print 'LibraryName' in build-target-ish syntax.------ /Note:/ there are no 'Pretty' or 'Parsec' instances,--- as there's other way to represent 'LibraryName', namely as bare--- 'UnqualComponentName'. -prettyLibraryNameComponent :: LibraryName -> Disp.Doc-prettyLibraryNameComponent LMainLibName = Disp.text "lib"-prettyLibraryNameComponent (LSubLibName str) = Disp.text "lib:" <<>> pretty str--parsecLibraryNameComponent :: CabalParsing m => m LibraryName-parsecLibraryNameComponent = do- _ <- P.string "lib"- parseComposite <|> parseSingle- where- parseSingle = return LMainLibName- parseComposite = do- _ <- P.char ':'- LSubLibName <$> parsec--defaultLibName :: LibraryName-defaultLibName = LMainLibName--showLibraryName :: LibraryName -> String-showLibraryName LMainLibName = "library"-showLibraryName (LSubLibName name) = "library '" ++ prettyShow name ++ "'"--libraryNameStanza :: LibraryName -> String-libraryNameStanza LMainLibName = "library"-libraryNameStanza (LSubLibName name) = "library " ++ prettyShow name--libraryNameString :: LibraryName -> Maybe UnqualComponentName-libraryNameString LMainLibName = Nothing-libraryNameString (LSubLibName n) = Just n---- | Convert the 'UnqualComponentName' of a library into a--- 'LibraryName'.-maybeToLibraryName :: Maybe UnqualComponentName -> LibraryName-maybeToLibraryName Nothing = LMainLibName-maybeToLibraryName (Just n) = LSubLibName n-
− Distribution/Types/LibraryVisibility.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--module Distribution.Types.LibraryVisibility(- LibraryVisibility(..),-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | Multi-lib visibility------ @since 3.0.0.0----data LibraryVisibility- -- | Can be depenendent from other packages- = LibraryVisibilityPublic- -- | Internal library, default- | LibraryVisibilityPrivate- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Pretty LibraryVisibility where- pretty LibraryVisibilityPublic = Disp.text "public"- pretty LibraryVisibilityPrivate = Disp.text "private"--instance Parsec LibraryVisibility where- parsec = do- name <- P.munch1 isAlpha- parsecWarning PWTExperimental "visibility is experimental feature (issue #5660)"- case name of- "public" -> return LibraryVisibilityPublic- "private" -> return LibraryVisibilityPrivate- _ -> fail $ "Unknown visibility: " ++ name--instance Binary LibraryVisibility-instance Structured LibraryVisibility-instance NFData LibraryVisibility where rnf = genericRnf--instance Semigroup LibraryVisibility where- LibraryVisibilityPrivate <> LibraryVisibilityPrivate = LibraryVisibilityPrivate- _ <> _ = LibraryVisibilityPublic--instance Monoid LibraryVisibility where- mempty = LibraryVisibilityPrivate- mappend = (<>)
− Distribution/Types/LocalBuildInfo.hs
@@ -1,304 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}--module Distribution.Types.LocalBuildInfo (- -- * The type-- LocalBuildInfo(..),-- -- * Convenience accessors-- localComponentId,- localUnitId,- localCompatPackageKey,- localPackage,-- -- * Build targets of the 'LocalBuildInfo'.-- componentNameCLBIs,-- -- NB: the primes mean that they take a 'PackageDescription'- -- which may not match 'localPkgDescr' in 'LocalBuildInfo'.- -- More logical types would drop this argument, but- -- at the moment, this is the ONLY supported function, because- -- 'localPkgDescr' is not guaranteed to match. At some point- -- we will fix it and then we can use the (free) unprimed- -- namespace for the correct commands.- --- -- See https://github.com/haskell/cabal/issues/3606 for more- -- details.-- componentNameTargets',- unitIdTarget',- allTargetsInBuildOrder',- withAllTargetsInBuildOrder',- neededTargetsInBuildOrder',- withNeededTargetsInBuildOrder',- testCoverage,-- -- * Functions you SHOULD NOT USE (yet), but are defined here to- -- prevent someone from accidentally defining them-- componentNameTargets,- unitIdTarget,- allTargetsInBuildOrder,- withAllTargetsInBuildOrder,- neededTargetsInBuildOrder,- withNeededTargetsInBuildOrder,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.PackageDescription-import Distribution.Types.ComponentLocalBuildInfo-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.ComponentId-import Distribution.Types.PackageId-import Distribution.Types.UnitId-import Distribution.Types.TargetInfo--import Distribution.Simple.InstallDirs hiding (absoluteInstallDirs,- prefixRelativeInstallDirs,- substPathTemplate, )-import Distribution.Simple.Program-import Distribution.PackageDescription-import Distribution.Simple.Compiler-import Distribution.Simple.PackageIndex-import Distribution.Simple.Setup-import Distribution.System-import Distribution.Pretty--import Distribution.Compat.Graph (Graph)-import qualified Distribution.Compat.Graph as Graph-import qualified Data.Map as Map---- | Data cached after configuration step. See also--- 'Distribution.Simple.Setup.ConfigFlags'.-data LocalBuildInfo = LocalBuildInfo {- 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- componentEnabledSpec :: ComponentRequestedSpec,- -- ^ What components were enabled during configuration, and why.- extraConfigArgs :: [String],- -- ^ Extra args on the command line for the configuration step.- -- Needed to re-run configuration when .cabal is out of date- installDirTemplates :: InstallDirTemplates,- -- ^ The installation directories for the various different- -- kinds of files- --TODO: inplaceDirTemplates :: InstallDirs FilePath- compiler :: Compiler,- -- ^ The compiler we're building with- hostPlatform :: Platform,- -- ^ The platform we're building for- buildDir :: FilePath,- -- ^ Where to build the package.- cabalFilePath :: Maybe FilePath,- -- ^ Path to the cabal file, if given during configuration.- componentGraph :: Graph ComponentLocalBuildInfo,- -- ^ All the components to build, ordered by topological- -- sort, and with their INTERNAL dependencies over the- -- intrapackage dependency graph.- -- TODO: this is assumed to be short; otherwise we want- -- some sort of ordered map.- componentNameMap :: Map ComponentName [ComponentLocalBuildInfo],- -- ^ A map from component name to all matching- -- components. These coincide with 'componentGraph'- installedPkgs :: InstalledPackageIndex,- -- ^ All the info about the installed packages that the- -- current package depends on (directly or indirectly).- -- The copy saved on disk does NOT include internal- -- dependencies (because we just don't have enough- -- information at this point to have an- -- 'InstalledPackageInfo' for an internal dep), but we- -- will often update it with the internal dependencies;- -- see for example 'Distribution.Simple.Build.build'.- -- (This admonition doesn't apply for per-component builds.)- pkgDescrFile :: Maybe FilePath,- -- ^ the filename containing the .cabal file, if available- localPkgDescr :: PackageDescription,- -- ^ WARNING WARNING WARNING Be VERY careful about using- -- this function; we haven't deprecated it but using it- -- could introduce subtle bugs related to- -- 'HookedBuildInfo'.- --- -- In principle, this is supposed to contain the- -- resolved package description, that does not contain- -- any conditionals. However, it MAY NOT contain- -- the description with a 'HookedBuildInfo' applied- -- to it; see 'HookedBuildInfo' for the whole sordid saga.- -- As much as possible, Cabal library should avoid using- -- this parameter.- withPrograms :: ProgramDb, -- ^Location and args for all programs- withPackageDB :: PackageDBStack, -- ^What package database to use, global\/user- withVanillaLib:: Bool, -- ^Whether to build normal libs.- withProfLib :: Bool, -- ^Whether to build profiling versions of libs.- withSharedLib :: Bool, -- ^Whether to build shared versions of libs.- withStaticLib :: Bool, -- ^Whether to build static versions of libs (with all other libs rolled in)- withDynExe :: Bool, -- ^Whether to link executables dynamically- withFullyStaticExe :: Bool, -- ^Whether to link executables fully statically- 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.- splitSections :: Bool, -- ^Use -split-sections with GHC, if available- splitObjs :: Bool, -- ^Use -split-objs with GHC, if available- stripExes :: Bool, -- ^Whether to strip executables during install- stripLibs :: Bool, -- ^Whether to strip libraries during install- exeCoverage :: Bool, -- ^Whether to enable executable program coverage- libCoverage :: Bool, -- ^Whether to enable library program coverage- progPrefix :: PathTemplate, -- ^Prefix to be prepended to installed executables- progSuffix :: PathTemplate, -- ^Suffix to be appended to installed executables- relocatable :: Bool -- ^Whether to build a relocatable package- } deriving (Generic, Read, Show, Typeable)--instance Binary LocalBuildInfo-instance Structured LocalBuildInfo------------------------------------------------------------------------------------ Accessor functions---- TODO: Get rid of these functions, as much as possible. They are--- a bit useful in some cases, but you should be very careful!---- | Extract the 'ComponentId' from the public 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 componentNameCLBIs lbi (CLibName LMainLibName) of- [LibComponentLocalBuildInfo { componentComponentId = cid }]- -> cid- _ -> mkComponentId (prettyShow (localPackage lbi))---- | Extract the 'PackageIdentifier' of a 'LocalBuildInfo'.--- This is a "safe" use of 'localPkgDescr'-localPackage :: LocalBuildInfo -> PackageId-localPackage lbi = package (localPkgDescr lbi)---- | 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 =- case componentNameCLBIs lbi (CLibName LMainLibName) of- [LibComponentLocalBuildInfo { componentUnitId = uid }]- -> uid- _ -> mkLegacyUnitId $ localPackage lbi---- | Extract the compatibility package key from the public library component of a--- 'LocalBuildInfo' if it exists, or make a fake package key based--- on the package ID.-localCompatPackageKey :: LocalBuildInfo -> String-localCompatPackageKey lbi =- case componentNameCLBIs lbi (CLibName LMainLibName) of- [LibComponentLocalBuildInfo { componentCompatPackageKey = pk }]- -> pk- _ -> prettyShow (localPackage lbi)---- | Convenience function to generate a default 'TargetInfo' from a--- 'ComponentLocalBuildInfo'. The idea is to call this once, and then--- use 'TargetInfo' everywhere else. Private to this module.-mkTargetInfo :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> TargetInfo-mkTargetInfo pkg_descr _lbi clbi =- TargetInfo {- targetCLBI = clbi,- -- NB: @pkg_descr@, not @localPkgDescr lbi@!- targetComponent = getComponent pkg_descr- (componentLocalName clbi)- }---- | Return all 'TargetInfo's associated with 'ComponentName'.--- In the presence of Backpack there may be more than one!--- Has a prime because it takes a 'PackageDescription' argument--- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.-componentNameTargets' :: PackageDescription -> LocalBuildInfo -> ComponentName -> [TargetInfo]-componentNameTargets' pkg_descr lbi cname =- case Map.lookup cname (componentNameMap lbi) of- Just clbis -> map (mkTargetInfo pkg_descr lbi) clbis- Nothing -> []--unitIdTarget' :: PackageDescription -> LocalBuildInfo -> UnitId -> Maybe TargetInfo-unitIdTarget' pkg_descr lbi uid =- case Graph.lookup uid (componentGraph lbi) of- Just clbi -> Just (mkTargetInfo pkg_descr lbi clbi)- Nothing -> Nothing---- | Return all 'ComponentLocalBuildInfo's associated with 'ComponentName'.--- In the presence of Backpack there may be more than one!-componentNameCLBIs :: LocalBuildInfo -> ComponentName -> [ComponentLocalBuildInfo]-componentNameCLBIs lbi cname =- case Map.lookup cname (componentNameMap lbi) of- Just clbis -> clbis- Nothing -> []---- TODO: Maybe cache topsort (Graph can do this)---- | Return the list of default 'TargetInfo's associated with a--- configured package, in the order they need to be built.--- Has a prime because it takes a 'PackageDescription' argument--- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.-allTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> [TargetInfo]-allTargetsInBuildOrder' pkg_descr lbi- = map (mkTargetInfo pkg_descr lbi) (Graph.revTopSort (componentGraph lbi))---- | Execute @f@ for every 'TargetInfo' in the package, respecting the--- build dependency order. (TODO: We should use Shake!)--- Has a prime because it takes a 'PackageDescription' argument--- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.-withAllTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> (TargetInfo -> IO ()) -> IO ()-withAllTargetsInBuildOrder' pkg_descr lbi f- = sequence_ [ f target | target <- allTargetsInBuildOrder' pkg_descr lbi ]---- | Return the list of all targets needed to build the @uids@, in--- the order they need to be built.--- Has a prime because it takes a 'PackageDescription' argument--- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.-neededTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> [UnitId] -> [TargetInfo]-neededTargetsInBuildOrder' pkg_descr lbi uids =- case Graph.closure (componentGraph lbi) uids of- Nothing -> error $ "localBuildPlan: missing uids " ++ intercalate ", " (map prettyShow uids)- Just clos -> map (mkTargetInfo pkg_descr lbi) (Graph.revTopSort (Graph.fromDistinctList clos))---- | Execute @f@ for every 'TargetInfo' needed to build @uid@s, respecting--- the build dependency order.--- Has a prime because it takes a 'PackageDescription' argument--- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.-withNeededTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> [UnitId] -> (TargetInfo -> IO ()) -> IO ()-withNeededTargetsInBuildOrder' pkg_descr lbi uids f- = sequence_ [ f target | target <- neededTargetsInBuildOrder' pkg_descr lbi uids ]---- | Is coverage enabled for test suites? In practice, this requires library--- and executable profiling to be enabled.-testCoverage :: LocalBuildInfo -> Bool-testCoverage lbi = exeCoverage lbi && libCoverage lbi------------------------------------------------------------------------------------ Stub functions to prevent someone from accidentally defining them--{-# WARNING componentNameTargets, unitIdTarget, allTargetsInBuildOrder, withAllTargetsInBuildOrder, neededTargetsInBuildOrder, withNeededTargetsInBuildOrder "By using this function, you may be introducing a bug where you retrieve a 'Component' which does not have 'HookedBuildInfo' applied to it. See the documentation for 'HookedBuildInfo' for an explanation of the issue. If you have a 'PakcageDescription' handy (NOT from the 'LocalBuildInfo'), try using the primed version of the function, which takes it as an extra argument." #-}--componentNameTargets :: LocalBuildInfo -> ComponentName -> [TargetInfo]-componentNameTargets lbi = componentNameTargets' (localPkgDescr lbi) lbi--unitIdTarget :: LocalBuildInfo -> UnitId -> Maybe TargetInfo-unitIdTarget lbi = unitIdTarget' (localPkgDescr lbi) lbi--allTargetsInBuildOrder :: LocalBuildInfo -> [TargetInfo]-allTargetsInBuildOrder lbi = allTargetsInBuildOrder' (localPkgDescr lbi) lbi--withAllTargetsInBuildOrder :: LocalBuildInfo -> (TargetInfo -> IO ()) -> IO ()-withAllTargetsInBuildOrder lbi = withAllTargetsInBuildOrder' (localPkgDescr lbi) lbi--neededTargetsInBuildOrder :: LocalBuildInfo -> [UnitId] -> [TargetInfo]-neededTargetsInBuildOrder lbi = neededTargetsInBuildOrder' (localPkgDescr lbi) lbi--withNeededTargetsInBuildOrder :: LocalBuildInfo -> [UnitId] -> (TargetInfo -> IO ()) -> IO ()-withNeededTargetsInBuildOrder lbi = withNeededTargetsInBuildOrder' (localPkgDescr lbi) lbi
− Distribution/Types/Mixin.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.Mixin (- Mixin(..),- mkMixin,- normaliseMixin,-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.IncludeRenaming-import Distribution.Types.LibraryName-import Distribution.Types.PackageName-import Distribution.Types.UnqualComponentName--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as PP---- |------ /Invariant:/ if 'mixinLibraryName' is 'LSubLibName', it's not--- the same as 'mixinPackageName'. In other words,--- the same invariant as 'Dependency' has.----data Mixin = Mixin { mixinPackageName :: PackageName- , mixinLibraryName :: LibraryName- , mixinIncludeRenaming :: IncludeRenaming }- deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)--instance Binary Mixin-instance Structured Mixin--instance NFData Mixin where rnf = genericRnf--instance Pretty Mixin where- pretty (Mixin pn LMainLibName incl) = pretty pn <+> pretty incl- pretty (Mixin pn (LSubLibName ln) incl) = pretty pn <<>> PP.colon <<>> pretty ln <+> pretty incl---- |------ >>> simpleParsec "mylib" :: Maybe Mixin--- Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})------ >>> simpleParsec "thatlib:sublib" :: Maybe Mixin--- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LSubLibName (UnqualComponentName "sublib"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})------ >>> simpleParsec "thatlib:thatlib" :: Maybe Mixin--- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})------ Sublibrary syntax is accepted since @cabal-version: 3.4@.------ >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV3_0, CabalSpecV3_4] :: [Maybe Mixin]--- [Nothing,Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LSubLibName (UnqualComponentName "sub"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})]----instance Parsec Mixin where- parsec = do- pn <- parsec- ln <- P.option LMainLibName $ do- _ <- P.char ':'- versionGuardMultilibs- parsecWarning PWTExperimental "colon specifier is experimental feature (issue #5660)"- LSubLibName <$> parsec- P.spaces- incl <- parsec- return (mkMixin pn ln incl)- where--versionGuardMultilibs :: CabalParsing m => m ()-versionGuardMultilibs = do- csv <- askCabalSpecVersion- when (csv < CabalSpecV3_4) $ fail $ unwords- [ "Sublibrary mixin syntax used."- , "To use this syntax the package needs to specify at least 'cabal-version: 3.4'."- ]---- | Smart constructor of 'Mixin', enforces invariant.--- --- @since 3.4.0.0-mkMixin :: PackageName -> LibraryName -> IncludeRenaming -> Mixin-mkMixin pn (LSubLibName uqn) incl- | packageNameToUnqualComponentName pn == uqn- = Mixin pn LMainLibName incl-mkMixin pn ln incl- = Mixin pn ln incl---- | Restore invariant-normaliseMixin :: Mixin -> Mixin-normaliseMixin (Mixin pn ln incl) = mkMixin pn ln incl
− Distribution/Types/Module.hs
@@ -1,46 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Distribution.Types.Module- ( Module(..)- ) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp-import Distribution.Pretty-import Distribution.Parsec-import Distribution.Types.UnitId-import Distribution.ModuleName---- | A module identity uniquely identifies a Haskell module by--- qualifying a 'ModuleName' with the 'UnitId' which defined--- it. This type distinguishes between two packages--- which provide a module with the same name, or a module--- from the same package compiled with different dependencies.--- There are a few cases where Cabal needs to know about--- module identities, e.g., when writing out reexported modules in--- the 'InstalledPackageInfo'.-data Module =- Module DefUnitId ModuleName- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)--instance Binary Module-instance Structured Module--instance Pretty Module where- pretty (Module uid mod_name) =- pretty uid <<>> Disp.text ":" <<>> pretty mod_name--instance Parsec Module where- parsec = do- uid <- parsec- _ <- P.char ':'- mod_name <- parsec- return (Module uid mod_name)--instance NFData Module where- rnf (Module uid mod_name) = rnf uid `seq` rnf mod_name
− Distribution/Types/ModuleReexport.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.ModuleReexport (- ModuleReexport(..)-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.ModuleName-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.PackageName--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- -------------------------------------------------------------------------------- Module re-exports--data ModuleReexport = ModuleReexport {- moduleReexportOriginalPackage :: Maybe PackageName,- moduleReexportOriginalName :: ModuleName,- moduleReexportName :: ModuleName- }- deriving (Eq, Generic, Read, Show, Typeable, Data)--instance Binary ModuleReexport-instance Structured ModuleReexport-instance NFData ModuleReexport where rnf = genericRnf--instance Pretty ModuleReexport where- pretty (ModuleReexport mpkgname origname newname) =- maybe Disp.empty (\pkgname -> pretty pkgname <<>> Disp.char ':') mpkgname- <<>> pretty origname- <+> if newname == origname- then Disp.empty- else Disp.text "as" <+> pretty newname--instance Parsec ModuleReexport where- parsec = do- mpkgname <- P.optional (P.try $ parsec <* P.char ':')- origname <- parsec- newname <- P.option origname $ P.try $ do- P.spaces- _ <- P.string "as"- P.spaces- parsec- return (ModuleReexport mpkgname origname newname)
− Distribution/Types/ModuleRenaming.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE RankNTypes #-}--module Distribution.Types.ModuleRenaming (- ModuleRenaming(..),- interpModuleRenaming,- defaultRenaming,- isDefaultRenaming,-) where--import Distribution.CabalSpecVersion-import Distribution.Compat.Prelude hiding (empty)-import Prelude ()--import Distribution.ModuleName-import Distribution.Parsec-import Distribution.Pretty--import qualified Data.Map as Map-import qualified Data.Set as Set-import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint (hsep, parens, punctuate, text, comma)---- | Renaming applied to the modules provided by a package.--- The boolean indicates whether or not to also include all of the--- original names of modules. Thus, @ModuleRenaming False []@ is--- "don't expose any modules, and @ModuleRenaming True [("Data.Bool", "Bool")]@--- is, "expose all modules, but also expose @Data.Bool@ as @Bool@".--- If a renaming is omitted you get the 'DefaultRenaming'.------ (NB: This is a list not a map so that we can preserve order.)----data ModuleRenaming- -- | A module renaming/thinning; e.g., @(A as B, C as C)@- -- brings @B@ and @C@ into scope.- = ModuleRenaming [(ModuleName, ModuleName)]- -- | The default renaming, bringing all exported modules- -- into scope.- | DefaultRenaming- -- | Hiding renaming, e.g., @hiding (A, B)@, bringing all- -- exported modules into scope except the hidden ones.- | HidingRenaming [ModuleName]- deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)---- | Interpret a 'ModuleRenaming' as a partial map from 'ModuleName'--- to 'ModuleName'. For efficiency, you should partially apply it--- with 'ModuleRenaming' and then reuse it.-interpModuleRenaming :: ModuleRenaming -> ModuleName -> Maybe ModuleName-interpModuleRenaming DefaultRenaming = Just-interpModuleRenaming (ModuleRenaming rns) =- let m = Map.fromList rns- in \k -> Map.lookup k m-interpModuleRenaming (HidingRenaming hs) =- let s = Set.fromList hs- in \k -> if k `Set.member` s then Nothing else Just k---- | The default renaming, if something is specified in @build-depends@--- only.-defaultRenaming :: ModuleRenaming-defaultRenaming = DefaultRenaming---- | Tests if its the default renaming; we can use a more compact syntax--- in 'Distribution.Types.IncludeRenaming.IncludeRenaming' in this case.-isDefaultRenaming :: ModuleRenaming -> Bool-isDefaultRenaming DefaultRenaming = True-isDefaultRenaming _ = False----instance Binary ModuleRenaming where-instance Structured ModuleRenaming where--instance NFData ModuleRenaming where rnf = genericRnf---- NB: parentheses are mandatory, because later we may extend this syntax--- to allow "hiding (A, B)" or other modifier words.-instance Pretty ModuleRenaming where- pretty DefaultRenaming = mempty- pretty (HidingRenaming hides)- = text "hiding" <+> parens (hsep (punctuate comma (map pretty hides)))- pretty (ModuleRenaming rns)- = parens . hsep $ punctuate comma (map dispEntry rns)- where dispEntry (orig, new)- | orig == new = pretty orig- | otherwise = pretty orig <+> text "as" <+> pretty new--instance Parsec ModuleRenaming where- parsec = do- csv <- askCabalSpecVersion- if csv >= CabalSpecV3_0- then moduleRenamingParsec parensLax lexemeParsec- else moduleRenamingParsec parensStrict parsec- where- -- For cabal spec versions < 3.0 white spaces were not skipped- -- after the '(' and ')' tokens in the mixin field. This- -- parser checks the cabal file version and does the correct- -- skipping of spaces.- parensLax p = P.between (P.char '(' >> P.spaces) (P.char ')' >> P.spaces) p- parensStrict p = P.between (P.char '(' >> warnSpaces) (P.char ')') p-- warnSpaces = P.optional $- P.space *> fail "space after parenthesis, use cabal-version: 3.0 or higher"--moduleRenamingParsec- :: CabalParsing m- => (forall a. m a -> m a) -- ^ between parens- -> m ModuleName -- ^ module name parser- -> m ModuleRenaming-moduleRenamingParsec bp mn =- -- NB: try not necessary as the first token is obvious- P.choice [ parseRename, parseHiding, return DefaultRenaming ]- where- cma = P.char ',' >> P.spaces- parseRename = do- rns <- bp parseList- P.spaces- return (ModuleRenaming rns)- parseHiding = do- _ <- P.string "hiding"- P.spaces -- space isn't strictly required as next is an open paren- hides <- bp (P.sepBy mn cma)- return (HidingRenaming hides)- parseList =- P.sepBy parseEntry cma- parseEntry = do- orig <- parsec- P.spaces- P.option (orig, orig) $ do- _ <- P.string "as"- P.skipSpaces1 -- require space after "as"- new <- parsec- P.spaces- return (orig, new)
− Distribution/Types/MungedPackageId.hs
@@ -1,83 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.MungedPackageId- ( MungedPackageId(..)- , computeCompatPackageId- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.LibraryName-import Distribution.Types.MungedPackageName-import Distribution.Types.PackageId-import Distribution.Version (Version, nullVersion)--import qualified Text.PrettyPrint as Disp---- | A simple pair of a 'MungedPackageName' and 'Version'. 'MungedPackageName' is to--- 'MungedPackageId' as 'PackageName' is to 'PackageId'. See 'MungedPackageName' for more--- info.-data MungedPackageId- = MungedPackageId {- -- | The combined package and component name. see documentation for- -- 'MungedPackageName'.- mungedName :: MungedPackageName,- -- | The version of this package / component, eg 1.2- mungedVersion :: Version- }- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)--instance Binary MungedPackageId-instance Structured MungedPackageId---- |------ >>> prettyShow $ MungedPackageId (MungedPackageName "servant" LMainLibName) (mkVersion [1,2,3])--- "servant-1.2.3"------ >>> prettyShow $ MungedPackageId (MungedPackageName "servant" (LSubLibName "lackey")) (mkVersion [0,1,2])--- "z-servant-z-lackey-0.1.2"----instance Pretty MungedPackageId where- pretty (MungedPackageId n v)- | v == nullVersion = pretty n -- if no version, don't show version.- | otherwise = pretty n <<>> Disp.char '-' <<>> pretty v---- |------ >>> simpleParsec "foo-bar-0" :: Maybe MungedPackageId--- Just (MungedPackageId {mungedName = MungedPackageName (PackageName "foo-bar") LMainLibName, mungedVersion = mkVersion [0]})------ >>> simpleParsec "foo-bar" :: Maybe MungedPackageId--- Just (MungedPackageId {mungedName = MungedPackageName (PackageName "foo-bar") LMainLibName, mungedVersion = mkVersion []})------ >>> simpleParsec "z-foo-bar-z-baz-0" :: Maybe MungedPackageId--- Just (MungedPackageId {mungedName = MungedPackageName (PackageName "foo-bar") (LSubLibName (UnqualComponentName "baz")), mungedVersion = mkVersion [0]})------ >>> simpleParsec "foo-bar-0-0" :: Maybe MungedPackageId--- Nothing------ >>> simpleParsec "foo-bar.0" :: Maybe MungedPackageId--- Nothing------ >>> simpleParsec "foo-bar.4-2" :: Maybe MungedPackageId--- Nothing----instance Parsec MungedPackageId where- parsec = do- PackageIdentifier pn v <- parsec- return $ MungedPackageId (decodeCompatPackageName pn) v--instance NFData MungedPackageId where- rnf (MungedPackageId name version) = rnf name `seq` rnf version--computeCompatPackageId :: PackageId -> LibraryName -> MungedPackageId-computeCompatPackageId (PackageIdentifier pn vr) ln =- MungedPackageId (MungedPackageName pn ln) vr---- $setup--- >>> :seti -XOverloadedStrings--- >>> import Distribution.Types.Version
− Distribution/Types/MungedPackageName.hs
@@ -1,157 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.MungedPackageName- ( MungedPackageName (..)- , decodeCompatPackageName- , encodeCompatPackageName- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.LibraryName-import Distribution.Types.PackageName-import Distribution.Types.UnqualComponentName--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | A combination of a package and component name used in various legacy--- interfaces, chiefly bundled with a version as 'MungedPackageId'. It's generally--- better to use a 'UnitId' to opaquely refer to some compilation/packing unit,--- but that doesn't always work, e.g. where a "name" is needed, in which case--- this can be used as a fallback.------ Use 'mkMungedPackageName' and 'unMungedPackageName' to convert from/to a 'String'.------ In @3.0.0.0@ representation was changed from opaque (string) to semantic representation.------ @since 2.0.0.2----data MungedPackageName = MungedPackageName !PackageName !LibraryName- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)--instance Binary MungedPackageName-instance Structured MungedPackageName-instance NFData MungedPackageName where rnf = genericRnf---- | Computes the package name for a library. If this is the public--- library, it will just be the original package name; otherwise,--- it will be a munged package name recording the original package--- name as well as the name of the internal library.------ A lot of tooling in the Haskell ecosystem assumes that if something--- is installed to the package database with the package name 'foo',--- then it actually is an entry for the (only public) library in package--- 'foo'. With internal packages, this is not necessarily true:--- a public library as well as arbitrarily many internal libraries may--- come from the same package. To prevent tools from getting confused--- in this case, the package name of these internal libraries is munged--- so that they do not conflict the public library proper. A particular--- case where this matters is ghc-pkg: if we don't munge the package--- name, the inplace registration will OVERRIDE a different internal--- library.------ We munge into a reserved namespace, "z-", and encode both the--- component name and the package name of an internal library using the--- following format:------ compat-pkg-name ::= "z-" package-name "-z-" library-name------ where package-name and library-name have "-" ( "z" + ) "-"--- segments encoded by adding an extra "z".------ When we have the public library, the compat-pkg-name is just the--- package-name, no surprises there!------ >>> prettyShow $ MungedPackageName "servant" LMainLibName--- "servant"------ >>> prettyShow $ MungedPackageName "servant" (LSubLibName "lackey")--- "z-servant-z-lackey"----instance Pretty MungedPackageName where- -- First handle the cases where we can just use the original 'PackageName'.- -- This is for the PRIMARY library, and it is non-Backpack, or the- -- indefinite package for us.- pretty = Disp.text . encodeCompatPackageName'---- |------ >>> simpleParsec "servant" :: Maybe MungedPackageName--- Just (MungedPackageName (PackageName "servant") LMainLibName)------ >>> simpleParsec "z-servant-z-lackey" :: Maybe MungedPackageName--- Just (MungedPackageName (PackageName "servant") (LSubLibName (UnqualComponentName "lackey")))------ >>> simpleParsec "z-servant-zz" :: Maybe MungedPackageName--- Just (MungedPackageName (PackageName "z-servant-zz") LMainLibName)----instance Parsec MungedPackageName where- parsec = decodeCompatPackageName' <$> parsecUnqualComponentName------------------------------------------------------------------------------------ ZDashCode conversions------------------------------------------------------------------------------------ | Intended for internal use only------ >>> decodeCompatPackageName "z-servant-z-lackey"--- MungedPackageName (PackageName "servant") (LSubLibName (UnqualComponentName "lackey"))----decodeCompatPackageName :: PackageName -> MungedPackageName-decodeCompatPackageName = decodeCompatPackageName' . unPackageName---- | Intended for internal use only------ >>> encodeCompatPackageName $ MungedPackageName "servant" (LSubLibName "lackey")--- PackageName "z-servant-z-lackey"------ This is used in @cabal-install@ in the Solver.--- May become obsolete as solver moves to per-component solving.----encodeCompatPackageName :: MungedPackageName -> PackageName-encodeCompatPackageName = mkPackageName . encodeCompatPackageName'--decodeCompatPackageName' :: String -> MungedPackageName-decodeCompatPackageName' m =- case m of- 'z':'-':rest | Right [pn, cn] <- explicitEitherParsec parseZDashCode rest- -> MungedPackageName (mkPackageName pn) (LSubLibName (mkUnqualComponentName cn))- s -> MungedPackageName (mkPackageName s) LMainLibName--encodeCompatPackageName' :: MungedPackageName -> String-encodeCompatPackageName' (MungedPackageName pn LMainLibName) = unPackageName pn-encodeCompatPackageName' (MungedPackageName pn (LSubLibName uqn)) =- "z-" ++ zdashcode (unPackageName pn) ++- "-z-" ++ zdashcode (unUnqualComponentName uqn)--zdashcode :: String -> String-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)--parseZDashCode :: CabalParsing m => m [String]-parseZDashCode = do- ns <- toList <$> P.sepByNonEmpty (some (P.satisfy (/= '-'))) (P.char '-')- return (go ns)- where- go ns = case break (=="z") ns of- (_, []) -> [paste ns]- (as, "z":bs) -> paste as : go bs- _ -> error "parseZDashCode: go"- unZ :: String -> String- unZ "" = error "parseZDashCode: unZ"- unZ r@('z':zs) | all (=='z') zs = zs- | otherwise = r- unZ r = r- paste :: [String] -> String- paste = intercalate "-" . map unZ---- $setup--- >>> :seti -XOverloadedStrings
− Distribution/Types/PackageDescription.hs
@@ -1,456 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Types.PackageDescription--- Copyright : Isaac Jones 2003-2005--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ This defines the data structure for the @.cabal@ file format. There are--- several parts to this structure. It has top level info and then 'Library',--- 'Executable', 'TestSuite', and 'Benchmark' sections each of which have--- associated 'BuildInfo' data that's used to build the library, exe, test, or--- benchmark. To further complicate things there is both a 'PackageDescription'--- and a 'GenericPackageDescription'. This distinction relates to cabal--- configurations. When we initially read a @.cabal@ file we get a--- 'GenericPackageDescription' which has all the conditional sections.--- Before actually building a package we have to decide--- on each conditional. Once we've done that we get a 'PackageDescription'.--- It was done this way initially to avoid breaking too much stuff when the--- feature was introduced. It could probably do with being rationalised at some--- point to make it simpler.--module Distribution.Types.PackageDescription (- PackageDescription(..),- license,- license',- buildType,- emptyPackageDescription,- hasPublicLib,- hasLibs,- allLibraries,- withLib,- hasExes,- withExe,- hasTests,- withTest,- hasBenchmarks,- withBenchmark,- hasForeignLibs,- withForeignLib,- allBuildInfo,- enabledBuildInfos,- allBuildDepends,- enabledBuildDepends,- updatePackageDescription,- pkgComponents,- pkgBuildableComponents,- enabledComponents,- lookupComponent,- getComponent,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Control.Monad ((<=<))---- lens-import qualified Distribution.Types.BuildInfo.Lens as L-import Distribution.Types.Library-import Distribution.Types.TestSuite-import Distribution.Types.Executable-import Distribution.Types.Benchmark-import Distribution.Types.ForeignLib--import Distribution.Types.Component-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.Dependency-import Distribution.Types.PackageId-import Distribution.Types.ComponentName-import Distribution.Types.PackageName-import Distribution.Types.UnqualComponentName-import Distribution.Types.SetupBuildInfo-import Distribution.Types.BuildInfo-import Distribution.Types.BuildType-import Distribution.Types.SourceRepo-import Distribution.Types.HookedBuildInfo--import Distribution.CabalSpecVersion-import Distribution.Compiler-import Distribution.License-import Distribution.Package-import Distribution.Version-import Distribution.Utils.ShortText--import qualified Distribution.SPDX as SPDX---- -------------------------------------------------------------------------------- The PackageDescription type---- | This data type is the internal representation of the file @pkg.cabal@.--- It contains two kinds of information about the package: information--- which is needed for all packages, such as the package name and version, and--- information which is needed for the simple build system only, such as--- the compiler options and library name.----data PackageDescription- = PackageDescription {- -- the following are required by all packages:-- -- | The version of the Cabal spec that this package description uses.- specVersion :: CabalSpecVersion,- package :: PackageIdentifier,- licenseRaw :: Either SPDX.License License,- licenseFiles :: [FilePath],- copyright :: !ShortText,- maintainer :: !ShortText,- author :: !ShortText,- stability :: !ShortText,- testedWith :: [(CompilerFlavor,VersionRange)],- homepage :: !ShortText,- pkgUrl :: !ShortText,- bugReports :: !ShortText,- sourceRepos :: [SourceRepo],- synopsis :: !ShortText, -- ^A one-line summary of this package- description :: !ShortText, -- ^A more verbose description of this package- category :: !ShortText,- customFieldsPD :: [(String,String)], -- ^Custom fields starting- -- with x-, stored in a- -- simple assoc-list.-- -- | The original @build-type@ value as parsed from the- -- @.cabal@ file without defaulting. See also 'buildType'.- --- -- @since 2.2- buildTypeRaw :: Maybe BuildType,- setupBuildInfo :: Maybe SetupBuildInfo,- -- components- library :: Maybe Library,- subLibraries :: [Library],- executables :: [Executable],- foreignLibs :: [ForeignLib],- testSuites :: [TestSuite],- benchmarks :: [Benchmark],- -- files- dataFiles :: [FilePath],- dataDir :: FilePath,- extraSrcFiles :: [FilePath],- extraTmpFiles :: [FilePath],- extraDocFiles :: [FilePath]- }- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Binary PackageDescription-instance Structured PackageDescription--instance NFData PackageDescription where rnf = genericRnf--instance Package PackageDescription where- packageId = package---- | The SPDX 'LicenseExpression' of the package.------ @since 2.2.0.0-license :: PackageDescription -> SPDX.License-license = license' . licenseRaw---- | See 'license'.------ @since 2.2.0.0-license' :: Either SPDX.License License -> SPDX.License-license' = either id licenseToSPDX---- | The effective @build-type@ after applying defaulting rules.------ The original @build-type@ value parsed is stored in the--- 'buildTypeRaw' field. However, the @build-type@ field is optional--- and can therefore be empty in which case we need to compute the--- /effective/ @build-type@. This function implements the following--- defaulting rules:------ * For @cabal-version:2.0@ and below, default to the @Custom@--- build-type unconditionally.------ * Otherwise, if a @custom-setup@ stanza is defined, default to--- the @Custom@ build-type; else default to @Simple@ build-type.------ @since 2.2-buildType :: PackageDescription -> BuildType-buildType pkg- | specVersion pkg >= CabalSpecV2_2- = fromMaybe newDefault (buildTypeRaw pkg)- | otherwise -- cabal-version < 2.1- = fromMaybe Custom (buildTypeRaw pkg)- where- newDefault | isNothing (setupBuildInfo pkg) = Simple- | otherwise = Custom--emptyPackageDescription :: PackageDescription-emptyPackageDescription- = PackageDescription {- package = PackageIdentifier (mkPackageName "")- nullVersion,- licenseRaw = Right UnspecifiedLicense, -- TODO:- licenseFiles = [],- specVersion = CabalSpecV1_0,- buildTypeRaw = Nothing,- copyright = mempty,- maintainer = mempty,- author = mempty,- stability = mempty,- testedWith = [],- homepage = mempty,- pkgUrl = mempty,- bugReports = mempty,- sourceRepos = [],- synopsis = mempty,- description = mempty,- category = mempty,- customFieldsPD = [],- setupBuildInfo = Nothing,- library = Nothing,- subLibraries = [],- foreignLibs = [],- executables = [],- testSuites = [],- benchmarks = [],- dataFiles = [],- dataDir = ".",- extraSrcFiles = [],- extraTmpFiles = [],- extraDocFiles = []- }---- ------------------------------------------------------------------------------ The Library type---- | Does this package have a buildable PUBLIC library?-hasPublicLib :: PackageDescription -> Bool-hasPublicLib p =- case library p of- Just lib -> buildable (libBuildInfo lib)- Nothing -> False---- | Does this package have any libraries?-hasLibs :: PackageDescription -> Bool-hasLibs p = any (buildable . libBuildInfo) (allLibraries p)--allLibraries :: PackageDescription -> [Library]-allLibraries p = maybeToList (library p) ++ subLibraries p---- | If the package description has a buildable library section,--- call the given function with the library build info as argument.--- You probably want 'withLibLBI' if you have a 'LocalBuildInfo',--- see the note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"--- for more information.-withLib :: PackageDescription -> (Library -> IO ()) -> IO ()-withLib pkg_descr f =- sequence_ [f lib | lib <- allLibraries pkg_descr, buildable (libBuildInfo lib)]---- ------------------------------------------------------------------------------ The Executable type---- |does this package have any executables?-hasExes :: PackageDescription -> Bool-hasExes p = any (buildable . buildInfo) (executables p)---- | Perform the action on each buildable 'Executable' in the package--- description. You probably want 'withExeLBI' if you have a--- 'LocalBuildInfo', see the note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"--- for more information.-withExe :: PackageDescription -> (Executable -> IO ()) -> IO ()-withExe pkg_descr f =- sequence_ [f exe | exe <- executables pkg_descr, buildable (buildInfo exe)]---- ------------------------------------------------------------------------------ The TestSuite type---- | Does this package have any test suites?-hasTests :: PackageDescription -> Bool-hasTests = any (buildable . testBuildInfo) . testSuites---- | Perform an action on each buildable 'TestSuite' in a package.--- You probably want 'withTestLBI' if you have a 'LocalBuildInfo', see the note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"--- for more information.--withTest :: PackageDescription -> (TestSuite -> IO ()) -> IO ()-withTest pkg_descr f =- sequence_ [ f test | test <- testSuites pkg_descr, buildable (testBuildInfo test) ]---- ------------------------------------------------------------------------------ The Benchmark type---- | Does this package have any benchmarks?-hasBenchmarks :: PackageDescription -> Bool-hasBenchmarks = any (buildable . benchmarkBuildInfo) . benchmarks---- | Perform an action on each buildable 'Benchmark' in a package.--- You probably want 'withBenchLBI' if you have a 'LocalBuildInfo', see the note in--- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"--- for more information.--withBenchmark :: PackageDescription -> (Benchmark -> IO ()) -> IO ()-withBenchmark pkg_descr f =- sequence_ [f bench | bench <- benchmarks pkg_descr, buildable (benchmarkBuildInfo bench)]---- ------------------------------------------------------------------------------ The ForeignLib type---- | Does this package have any foreign libraries?-hasForeignLibs :: PackageDescription -> Bool-hasForeignLibs p = any (buildable . foreignLibBuildInfo) (foreignLibs p)---- | Perform the action on each buildable 'ForeignLib' in the package--- description.-withForeignLib :: PackageDescription -> (ForeignLib -> IO ()) -> IO ()-withForeignLib pkg_descr f =- sequence_ [ f flib- | flib <- foreignLibs pkg_descr- , buildable (foreignLibBuildInfo flib)- ]---- ------------------------------------------------------------------------------ The BuildInfo type---- | All 'BuildInfo' in the 'PackageDescription':--- libraries, executables, test-suites and benchmarks.------ Useful for implementing package checks.-allBuildInfo :: PackageDescription -> [BuildInfo]-allBuildInfo pkg_descr = [ bi | lib <- allLibraries pkg_descr- , let bi = libBuildInfo lib ]- ++ [ bi | flib <- foreignLibs pkg_descr- , let bi = foreignLibBuildInfo flib ]- ++ [ bi | exe <- executables pkg_descr- , let bi = buildInfo exe ]- ++ [ bi | tst <- testSuites pkg_descr- , let bi = testBuildInfo tst ]- ++ [ bi | tst <- benchmarks pkg_descr- , let bi = benchmarkBuildInfo tst ]---- | Return all of the 'BuildInfo's of enabled components, i.e., all of--- the ones that would be built if you run @./Setup build@.-enabledBuildInfos :: PackageDescription -> ComponentRequestedSpec -> [BuildInfo]-enabledBuildInfos pkg enabled =- [ componentBuildInfo comp- | comp <- enabledComponents pkg enabled ]----- --------------------------------------------------------------- * Utils--- ---------------------------------------------------------------- | Get the combined build-depends entries of all components.-allBuildDepends :: PackageDescription -> [Dependency]-allBuildDepends = targetBuildDepends <=< allBuildInfo---- | Get the combined build-depends entries of all enabled components, per the--- given request spec.-enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [Dependency]-enabledBuildDepends spec pd = targetBuildDepends =<< enabledBuildInfos spec pd---updatePackageDescription :: HookedBuildInfo -> PackageDescription -> PackageDescription-updatePackageDescription (mb_lib_bi, exe_bi) p- = p{ executables = updateExecutables exe_bi (executables p)- , library = updateLibrary mb_lib_bi (library p) }- where- updateLibrary :: Maybe BuildInfo -> Maybe Library -> Maybe Library- updateLibrary (Just bi) (Just lib) = Just (lib{libBuildInfo = bi `mappend` libBuildInfo lib})- updateLibrary Nothing mb_lib = mb_lib- updateLibrary (Just _) Nothing = Nothing-- updateExecutables :: [(UnqualComponentName, BuildInfo)] -- ^[(exeName, new buildinfo)]- -> [Executable] -- ^list of executables to update- -> [Executable] -- ^list with exeNames updated- updateExecutables exe_bi' executables' = foldr updateExecutable executables' exe_bi'-- updateExecutable :: (UnqualComponentName, BuildInfo) -- ^(exeName, new buildinfo)- -> [Executable] -- ^list of executables to update- -> [Executable] -- ^list with exeName updated- updateExecutable _ [] = []- updateExecutable exe_bi'@(name,bi) (exe:exes)- | exeName exe == name = exe{buildInfo = bi `mappend` buildInfo exe} : exes- | otherwise = exe : updateExecutable exe_bi' exes---- -------------------------------------------------------------------------------- Source-representation of buildable components---- | All the components in the package.----pkgComponents :: PackageDescription -> [Component]-pkgComponents pkg =- [ CLib lib | lib <- allLibraries pkg ]- ++ [ CFLib flib | flib <- foreignLibs pkg ]- ++ [ CExe exe | exe <- executables pkg ]- ++ [ CTest tst | tst <- testSuites pkg ]- ++ [ CBench bm | bm <- benchmarks pkg ]---- | A list of all components in the package that are buildable,--- i.e., were not marked with @buildable: False@. This does NOT--- indicate if we are actually going to build the component,--- see 'enabledComponents' instead.------ @since 2.0.0.2----pkgBuildableComponents :: PackageDescription -> [Component]-pkgBuildableComponents = filter componentBuildable . pkgComponents---- | A list of all components in the package that are enabled.------ @since 2.0.0.2----enabledComponents :: PackageDescription -> ComponentRequestedSpec -> [Component]-enabledComponents pkg enabled = filter (componentEnabled enabled) $ pkgBuildableComponents pkg--lookupComponent :: PackageDescription -> ComponentName -> Maybe Component-lookupComponent pkg (CLibName name) =- fmap CLib $ find ((name ==) . libName) (allLibraries pkg)-lookupComponent pkg (CFLibName name) =- fmap CFLib $ find ((name ==) . foreignLibName) (foreignLibs pkg)-lookupComponent pkg (CExeName name) =- fmap CExe $ find ((name ==) . exeName) (executables pkg)-lookupComponent pkg (CTestName name) =- fmap CTest $ find ((name ==) . testName) (testSuites pkg)-lookupComponent pkg (CBenchName name) =- fmap CBench $ find ((name ==) . benchmarkName) (benchmarks pkg)--getComponent :: PackageDescription -> ComponentName -> Component-getComponent pkg cname =- case lookupComponent pkg cname of- Just cpnt -> cpnt- Nothing -> missingComponent- where- missingComponent =- error $ "internal error: the package description contains no "- ++ "component corresponding to " ++ show cname---- -------------------------------------------------------------------------------- Traversal Instances--instance L.HasBuildInfos PackageDescription where- traverseBuildInfos f (PackageDescription a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19- x1 x2 x3 x4 x5 x6- a20 a21 a22 a23 a24) =- PackageDescription a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19- <$> (traverse . L.buildInfo) f x1 -- library- <*> (traverse . L.buildInfo) f x2 -- sub libraries- <*> (traverse . L.buildInfo) f x3 -- executables- <*> (traverse . L.buildInfo) f x4 -- foreign libs- <*> (traverse . L.buildInfo) f x5 -- test suites- <*> (traverse . L.buildInfo) f x6 -- benchmarks- <*> pure a20 -- data files- <*> pure a21 -- data dir- <*> pure a22 -- extra src files- <*> pure a23 -- extra temp files- <*> pure a24 -- extra doc files
− Distribution/Types/PackageDescription/Lens.hs
@@ -1,220 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-module Distribution.Types.PackageDescription.Lens (- PackageDescription,- module Distribution.Types.PackageDescription.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.CabalSpecVersion (CabalSpecVersion)-import Distribution.Compiler (CompilerFlavor)-import Distribution.License (License)-import Distribution.ModuleName (ModuleName)-import Distribution.Types.Benchmark (Benchmark, benchmarkModules)-import Distribution.Types.Benchmark.Lens (benchmarkBuildInfo, benchmarkName)-import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.BuildType (BuildType)-import Distribution.Types.ComponentName (ComponentName (..))-import Distribution.Types.Executable (Executable, exeModules)-import Distribution.Types.Executable.Lens (exeBuildInfo, exeName)-import Distribution.Types.ForeignLib (ForeignLib, foreignLibModules)-import Distribution.Types.ForeignLib.Lens (foreignLibBuildInfo, foreignLibName)-import Distribution.Types.Library (Library, explicitLibModules)-import Distribution.Types.Library.Lens (libBuildInfo, libName)-import Distribution.Types.PackageDescription (PackageDescription)-import Distribution.Types.PackageId (PackageIdentifier)-import Distribution.Types.SetupBuildInfo (SetupBuildInfo)-import Distribution.Types.SourceRepo (SourceRepo)-import Distribution.Types.TestSuite (TestSuite, testModules)-import Distribution.Types.TestSuite.Lens (testBuildInfo, testName)-import Distribution.Utils.ShortText (ShortText)-import Distribution.Version (VersionRange)--import qualified Distribution.SPDX as SPDX-import qualified Distribution.Types.PackageDescription as T--package :: Lens' PackageDescription PackageIdentifier-package f s = fmap (\x -> s { T.package = x }) (f (T.package s))-{-# INLINE package #-}--licenseRaw :: Lens' PackageDescription (Either SPDX.License License)-licenseRaw f s = fmap (\x -> s { T.licenseRaw = x }) (f (T.licenseRaw s))-{-# INLINE licenseRaw #-}--licenseFiles :: Lens' PackageDescription [FilePath]-licenseFiles f s = fmap (\x -> s { T.licenseFiles = x }) (f (T.licenseFiles s))-{-# INLINE licenseFiles #-}--copyright :: Lens' PackageDescription ShortText-copyright f s = fmap (\x -> s { T.copyright = x }) (f (T.copyright s))-{-# INLINE copyright #-}--maintainer :: Lens' PackageDescription ShortText-maintainer f s = fmap (\x -> s { T.maintainer = x }) (f (T.maintainer s))-{-# INLINE maintainer #-}--author :: Lens' PackageDescription ShortText-author f s = fmap (\x -> s { T.author = x }) (f (T.author s))-{-# INLINE author #-}--stability :: Lens' PackageDescription ShortText-stability f s = fmap (\x -> s { T.stability = x }) (f (T.stability s))-{-# INLINE stability #-}--testedWith :: Lens' PackageDescription [(CompilerFlavor,VersionRange)]-testedWith f s = fmap (\x -> s { T.testedWith = x }) (f (T.testedWith s))-{-# INLINE testedWith #-}--homepage :: Lens' PackageDescription ShortText-homepage f s = fmap (\x -> s { T.homepage = x }) (f (T.homepage s))-{-# INLINE homepage #-}--pkgUrl :: Lens' PackageDescription ShortText-pkgUrl f s = fmap (\x -> s { T.pkgUrl = x }) (f (T.pkgUrl s))-{-# INLINE pkgUrl #-}--bugReports :: Lens' PackageDescription ShortText-bugReports f s = fmap (\x -> s { T.bugReports = x }) (f (T.bugReports s))-{-# INLINE bugReports #-}--sourceRepos :: Lens' PackageDescription [SourceRepo]-sourceRepos f s = fmap (\x -> s { T.sourceRepos = x }) (f (T.sourceRepos s))-{-# INLINE sourceRepos #-}--synopsis :: Lens' PackageDescription ShortText-synopsis f s = fmap (\x -> s { T.synopsis = x }) (f (T.synopsis s))-{-# INLINE synopsis #-}--description :: Lens' PackageDescription ShortText-description f s = fmap (\x -> s { T.description = x }) (f (T.description s))-{-# INLINE description #-}--category :: Lens' PackageDescription ShortText-category f s = fmap (\x -> s { T.category = x }) (f (T.category s))-{-# INLINE category #-}--customFieldsPD :: Lens' PackageDescription [(String,String)]-customFieldsPD f s = fmap (\x -> s { T.customFieldsPD = x }) (f (T.customFieldsPD s))-{-# INLINE customFieldsPD #-}--specVersion :: Lens' PackageDescription CabalSpecVersion-specVersion f s = fmap (\x -> s { T.specVersion = x }) (f (T.specVersion s))-{-# INLINE specVersion #-}--buildTypeRaw :: Lens' PackageDescription (Maybe BuildType)-buildTypeRaw f s = fmap (\x -> s { T.buildTypeRaw = x }) (f (T.buildTypeRaw s))-{-# INLINE buildTypeRaw #-}--setupBuildInfo :: Lens' PackageDescription (Maybe SetupBuildInfo)-setupBuildInfo f s = fmap (\x -> s { T.setupBuildInfo = x }) (f (T.setupBuildInfo s))-{-# INLINE setupBuildInfo #-}--library :: Lens' PackageDescription (Maybe Library)-library f s = fmap (\x -> s { T.library = x }) (f (T.library s))-{-# INLINE library #-}--subLibraries :: Lens' PackageDescription [Library]-subLibraries f s = fmap (\x -> s { T.subLibraries = x }) (f (T.subLibraries s))-{-# INLINE subLibraries #-}--executables :: Lens' PackageDescription [Executable]-executables f s = fmap (\x -> s { T.executables = x }) (f (T.executables s))-{-# INLINE executables #-}--foreignLibs :: Lens' PackageDescription [ForeignLib]-foreignLibs f s = fmap (\x -> s { T.foreignLibs = x }) (f (T.foreignLibs s))-{-# INLINE foreignLibs #-}--testSuites :: Lens' PackageDescription [TestSuite]-testSuites f s = fmap (\x -> s { T.testSuites = x }) (f (T.testSuites s))-{-# INLINE testSuites #-}--benchmarks :: Lens' PackageDescription [Benchmark]-benchmarks f s = fmap (\x -> s { T.benchmarks = x }) (f (T.benchmarks s))-{-# INLINE benchmarks #-}--dataFiles :: Lens' PackageDescription [FilePath]-dataFiles f s = fmap (\x -> s { T.dataFiles = x }) (f (T.dataFiles s))-{-# INLINE dataFiles #-}--dataDir :: Lens' PackageDescription FilePath-dataDir f s = fmap (\x -> s { T.dataDir = x }) (f (T.dataDir s))-{-# INLINE dataDir #-}--extraSrcFiles :: Lens' PackageDescription [String]-extraSrcFiles f s = fmap (\x -> s { T.extraSrcFiles = x }) (f (T.extraSrcFiles s))-{-# INLINE extraSrcFiles #-}--extraTmpFiles :: Lens' PackageDescription [String]-extraTmpFiles f s = fmap (\x -> s { T.extraTmpFiles = x }) (f (T.extraTmpFiles s))-{-# INLINE extraTmpFiles #-}--extraDocFiles :: Lens' PackageDescription [String]-extraDocFiles f s = fmap (\x -> s { T.extraDocFiles = x }) (f (T.extraDocFiles s))-{-# INLINE extraDocFiles #-}---- | @since 3.0.0.0-allLibraries :: Traversal' PackageDescription Library-allLibraries f pd = mk <$> traverse f (T.library pd) <*> traverse f (T.subLibraries pd)- where- mk l ls = pd { T.library = l, T.subLibraries = ls }---- | @since 2.4-componentModules :: Monoid r => ComponentName -> Getting r PackageDescription [ModuleName]-componentModules cname = case cname of- CLibName name ->- componentModules' name allLibraries libName explicitLibModules- CFLibName name ->- componentModules' name (foreignLibs . traverse) foreignLibName foreignLibModules- CExeName name ->- componentModules' name (executables . traverse) exeName exeModules- CTestName name ->- componentModules' name (testSuites . traverse) testName testModules- CBenchName name ->- componentModules' name (benchmarks . traverse) benchmarkName benchmarkModules- where- componentModules'- :: (Eq name, Monoid r)- => name- -> Traversal' PackageDescription a- -> Lens' a name- -> (a -> [ModuleName])- -> Getting r PackageDescription [ModuleName]- componentModules' name pdL nameL modules =- pdL- . filtered ((== name) . view nameL)- . getting modules-- filtered :: (a -> Bool) -> Traversal' a a- filtered p f s = if p s then f s else pure s---- | @since 2.4-componentBuildInfo :: ComponentName -> Traversal' PackageDescription BuildInfo-componentBuildInfo cname = case cname of- CLibName name ->- componentBuildInfo' name allLibraries libName libBuildInfo- CFLibName name ->- componentBuildInfo' name (foreignLibs . traverse) foreignLibName foreignLibBuildInfo- CExeName name ->- componentBuildInfo' name (executables . traverse) exeName exeBuildInfo- CTestName name ->- componentBuildInfo' name (testSuites . traverse) testName testBuildInfo- CBenchName name ->- componentBuildInfo' name (benchmarks . traverse) benchmarkName benchmarkBuildInfo- where- componentBuildInfo' :: Eq name- => name- -> Traversal' PackageDescription a- -> Lens' a name- -> Traversal' a BuildInfo- -> Traversal' PackageDescription BuildInfo- componentBuildInfo' name pdL nameL biL =- pdL- . filtered ((== name) . view nameL)- . biL-- filtered :: (a -> Bool) -> Traversal' a a- filtered p f s = if p s then f s else pure s
− Distribution/Types/PackageId.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.PackageId- ( PackageIdentifier(..)- , PackageId- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec (Parsec (..), simpleParsec)-import Distribution.Pretty-import Distribution.Types.PackageName-import Distribution.Version (Version, nullVersion)--import qualified Data.List.NonEmpty as NE-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | Type alias so we can use the shorter name PackageId.-type PackageId = PackageIdentifier---- | The name and version of a package.-data PackageIdentifier- = PackageIdentifier {- pkgName :: PackageName, -- ^The name of this package, eg. foo- pkgVersion :: Version -- ^the version of this package, eg 1.2- }- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)--instance Binary PackageIdentifier-instance Structured PackageIdentifier--instance Pretty PackageIdentifier where- pretty (PackageIdentifier n v)- | v == nullVersion = pretty n -- if no version, don't show version.- | otherwise = pretty n <<>> Disp.char '-' <<>> pretty v---- |------ >>> simpleParsec "foo-bar-0" :: Maybe PackageIdentifier--- Just (PackageIdentifier {pkgName = PackageName "foo-bar", pkgVersion = mkVersion [0]})------ >>> simpleParsec "foo-bar" :: Maybe PackageIdentifier--- Just (PackageIdentifier {pkgName = PackageName "foo-bar", pkgVersion = mkVersion []})------ /Note:/ Stricter than 'Text' instance------ >>> simpleParsec "foo-bar-0-0" :: Maybe PackageIdentifier--- Nothing------ >>> simpleParsec "foo-bar.0" :: Maybe PackageIdentifier--- Nothing------ >>> simpleParsec "foo-bar.4-2" :: Maybe PackageIdentifier--- Nothing------ >>> simpleParsec "1.2.3" :: Maybe PackageIdentifier--- Nothing----instance Parsec PackageIdentifier where- parsec = do- xs' <- P.sepByNonEmpty component (P.char '-')- (v, xs) <- case simpleParsec (NE.last xs') of- Nothing -> return (nullVersion, toList xs') -- all components are version- Just v -> return (v, NE.init xs')- if not (null xs) && all (\c -> all (/= '.') c && not (all isDigit c)) xs- then return $ PackageIdentifier (mkPackageName (intercalate "-" xs)) v- else fail "all digits or a dot in a portion of package name"- where- component = P.munch1 (\c -> isAlphaNum c || c == '.')--instance NFData PackageIdentifier where- rnf (PackageIdentifier name version) = rnf name `seq` rnf version
− Distribution/Types/PackageId/Lens.hs
@@ -1,22 +0,0 @@-module Distribution.Types.PackageId.Lens (- PackageIdentifier,- module Distribution.Types.PackageId.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.PackageId (PackageIdentifier)-import Distribution.Types.PackageName (PackageName)-import Distribution.Version (Version)--import qualified Distribution.Types.PackageId as T--pkgName :: Lens' PackageIdentifier PackageName-pkgName f s = fmap (\x -> s { T.pkgName = x }) (f (T.pkgName s))-{-# INLINE pkgName #-}--pkgVersion :: Lens' PackageIdentifier Version-pkgVersion f s = fmap (\x -> s { T.pkgVersion = x }) (f (T.pkgVersion s))-{-# INLINE pkgVersion #-}
− Distribution/Types/PackageName.hs
@@ -1,73 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.PackageName- ( PackageName- , unPackageName, mkPackageName- , unPackageNameST, mkPackageNameST- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.ShortText--import qualified Text.PrettyPrint as Disp-import Distribution.Pretty-import Distribution.Parsec---- | A package name.------ Use 'mkPackageName' and 'unPackageName' to convert from/to a--- 'String'.------ This type is opaque since @Cabal-2.0@------ @since 2.0.0.2-newtype PackageName = PackageName ShortText- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)---- | Convert 'PackageName' to 'String'-unPackageName :: PackageName -> String-unPackageName (PackageName s) = fromShortText s---- | @since 3.4.0.0-unPackageNameST :: PackageName -> ShortText-unPackageNameST (PackageName s) = s---- | Construct a 'PackageName' from a 'String'------ 'mkPackageName' is the inverse to 'unPackageName'------ Note: No validations are performed to ensure that the resulting--- 'PackageName' is valid------ @since 2.0.0.2-mkPackageName :: String -> PackageName-mkPackageName = PackageName . toShortText---- | Construct a 'PackageName' from a 'ShortText'------ Note: No validations are performed to ensure that the resulting--- 'PackageName' is valid------ @since 3.4.0.0-mkPackageNameST :: ShortText -> PackageName-mkPackageNameST = PackageName---- | 'mkPackageName'------ @since 2.0.0.2-instance IsString PackageName where- fromString = mkPackageName--instance Binary PackageName-instance Structured PackageName--instance Pretty PackageName where- pretty = Disp.text . unPackageName--instance Parsec PackageName where- parsec = mkPackageName <$> parsecUnqualComponentName--instance NFData PackageName where- rnf (PackageName pkg) = rnf pkg
− Distribution/Types/PackageName/Magic.hs
@@ -1,20 +0,0 @@--- | Magic 'PackageName's.------ @since 3.0.0.0-module Distribution.Types.PackageName.Magic where--import Distribution.Types.PackageId-import Distribution.Types.PackageName-import Distribution.Types.Version---- | Used as a placeholder in "Distribution.Backpack.ReadyComponent"-nonExistentPackageThisIsCabalBug :: PackageName-nonExistentPackageThisIsCabalBug = mkPackageName "nonexistent-package-this-is-a-cabal-bug"---- | Used by @cabal new-repl@ and @cabal new-run@-fakePackageName :: PackageName-fakePackageName = mkPackageName "fake-package"---- | 'fakePackageName' with 'version0'.-fakePackageId :: PackageId-fakePackageId = PackageIdentifier fakePackageName version0
− Distribution/Types/PackageVersionConstraint.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.PackageVersionConstraint (- PackageVersionConstraint(..),- thisPackageVersionConstraint,- simplifyPackageVersionConstraint,-) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.PackageId-import Distribution.Types.PackageName-import Distribution.Types.Version-import Distribution.Types.VersionRange.Internal-import Distribution.Version (simplifyVersionRange)--import qualified Distribution.Compat.CharParsing as P---- | A version constraint on a package. Different from 'ExeDependency' and--- 'Dependency' since it does not specify the need for a component, not even--- the main library.--- There are a few places in the codebase where 'Dependency' was used where--- 'PackageVersionConstraint' is not used instead (#5570).-data PackageVersionConstraint = PackageVersionConstraint PackageName VersionRange- deriving (Generic, Read, Show, Eq, Typeable, Data)--instance Binary PackageVersionConstraint-instance Structured PackageVersionConstraint-instance NFData PackageVersionConstraint where rnf = genericRnf--instance Pretty PackageVersionConstraint where- -- Cannot do: PackageVersionConstraint have to be parseable- -- as Dependency, due roundtrip problems. (e.g. talking to old ./Setup).- --- -- pretty (PackageVersionConstraint name (ThisVersion ver)) =- -- pretty (PackageIdentifier name ver)- pretty (PackageVersionConstraint name ver) =- pretty name <+> pretty ver---- |------ >>> simpleParsec "foo" :: Maybe PackageVersionConstraint--- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [0])))------ >>> simpleParsec "foo >=2.0" :: Maybe PackageVersionConstraint--- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [2,0])))------ >>> simpleParsec "foo-2.0" :: Maybe PackageVersionConstraint--- Just (PackageVersionConstraint (PackageName "foo") (ThisVersion (mkVersion [2,0])))----instance Parsec PackageVersionConstraint where- parsec = do- PackageIdentifier name ver <- parsec- if ver == nullVersion- then do- P.spaces- vr <- parsec <|> return anyVersion- P.spaces- return (PackageVersionConstraint name vr)- else- pure (PackageVersionConstraint name (thisVersion ver))---- | @since 3.4.0.0-thisPackageVersionConstraint :: PackageIdentifier -> PackageVersionConstraint-thisPackageVersionConstraint (PackageIdentifier pn vr) =- PackageVersionConstraint pn (thisVersion vr)---- | @since 3.4.0.0-simplifyPackageVersionConstraint :: PackageVersionConstraint -> PackageVersionConstraint-simplifyPackageVersionConstraint (PackageVersionConstraint pn vr) =- PackageVersionConstraint pn (simplifyVersionRange vr)
− Distribution/Types/PkgconfigDependency.hs
@@ -1,39 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.PkgconfigDependency- ( PkgconfigDependency(..)- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.PkgconfigName-import Distribution.Types.PkgconfigVersionRange--import Distribution.Parsec-import Distribution.Pretty--import qualified Distribution.Compat.CharParsing as P---- | Describes a dependency on a pkg-config library------ @since 2.0.0.2-data PkgconfigDependency = PkgconfigDependency- PkgconfigName- PkgconfigVersionRange- deriving (Generic, Read, Show, Eq, Typeable, Data)--instance Binary PkgconfigDependency-instance Structured PkgconfigDependency-instance NFData PkgconfigDependency where rnf = genericRnf--instance Pretty PkgconfigDependency where- pretty (PkgconfigDependency name PcAnyVersion) = pretty name- pretty (PkgconfigDependency name ver) = pretty name <+> pretty ver--instance Parsec PkgconfigDependency where- parsec = do- name <- parsec- P.spaces- verRange <- parsec <|> pure anyPkgconfigVersion- pure $ PkgconfigDependency name verRange
− Distribution/Types/PkgconfigName.hs
@@ -1,68 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.PkgconfigName- ( PkgconfigName, unPkgconfigName, mkPkgconfigName- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.ShortText--import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- | A pkg-config library name------ This is parsed as any valid argument to the pkg-config utility.------ @since 2.0.0.2-newtype PkgconfigName = PkgconfigName ShortText- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)---- | Convert 'PkgconfigName' to 'String'------ @since 2.0.0.2-unPkgconfigName :: PkgconfigName -> String-unPkgconfigName (PkgconfigName s) = fromShortText s---- | Construct a 'PkgconfigName' from a 'String'------ 'mkPkgconfigName' is the inverse to 'unPkgconfigName'------ Note: No validations are performed to ensure that the resulting--- 'PkgconfigName' is valid------ @since 2.0.0.2-mkPkgconfigName :: String -> PkgconfigName-mkPkgconfigName = PkgconfigName . toShortText---- | 'mkPkgconfigName'------ @since 2.0.0.2-instance IsString PkgconfigName where- fromString = mkPkgconfigName--instance Binary PkgconfigName-instance Structured PkgconfigName---- pkg-config allows versions and other letters in package names, eg--- "gtk+-2.0" is a valid pkg-config package _name_. It then has a package--- version number like 2.10.13-instance Pretty PkgconfigName where- pretty = Disp.text . unPkgconfigName--instance Parsec PkgconfigName where- parsec = mkPkgconfigName <$> P.munch1 isNameChar where- -- https://gitlab.haskell.org/ghc/ghc/issues/17752- isNameChar '-' = True- isNameChar '_' = True- isNameChar '.' = True- isNameChar '+' = True- isNameChar c = isAlphaNum c--instance NFData PkgconfigName where- rnf (PkgconfigName pkg) = rnf pkg
− Distribution/Types/PkgconfigVersion.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--- @since 3.0-module Distribution.Types.PkgconfigVersion (- PkgconfigVersion (..),- rpmvercmp,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Utils.Generic (isAsciiAlphaNum)--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS8-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as PP---- | @pkg-config@ versions.------ In fact, this can be arbitrary 'BS.ByteString',--- but 'Parsec' instance is a little pickier.------ @since 3.0-newtype PkgconfigVersion = PkgconfigVersion BS.ByteString- deriving (Generic, Read, Show, Typeable, Data)--instance Eq PkgconfigVersion where- PkgconfigVersion a == PkgconfigVersion b = rpmvercmp a b == EQ--instance Ord PkgconfigVersion where- PkgconfigVersion a `compare` PkgconfigVersion b = rpmvercmp a b--instance Binary PkgconfigVersion-instance Structured PkgconfigVersion-instance NFData PkgconfigVersion where rnf = genericRnf--instance Pretty PkgconfigVersion where- pretty (PkgconfigVersion bs) = PP.text (BS8.unpack bs)---- |------ >>> simpleParsec "1.0.2n" :: Maybe PkgconfigVersion--- Just (PkgconfigVersion "1.0.2n")------ >>> simpleParsec "0.3.5+ds" :: Maybe PkgconfigVersion--- Nothing----instance Parsec PkgconfigVersion where- parsec = PkgconfigVersion . BS8.pack <$> P.munch1 predicate where- predicate c = isAsciiAlphaNum c || c == '.' || c == '-'------------------------------------------------------------------------------------ rmpvercmp - pure Haskell implementation------------------------------------------------------------------------------------ | Compare two version strings as @pkg-config@ would compare them.------ @since 3.0-rpmvercmp :: BS.ByteString -> BS.ByteString -> Ordering-rpmvercmp a b = go0 (BS.unpack a) (BS.unpack b)- where- go0 :: [Word8] -> [Word8] -> Ordering- -- if there is _any_ trailing "garbage", it seems to affect result- -- https://github.com/haskell/cabal/issues/6805- go0 [] [] = EQ- go0 [] _ = LT- go0 _ [] = GT- go0 xs ys = go1 (dropNonAlnum8 xs) (dropNonAlnum8 ys)-- go1 :: [Word8] -> [Word8] -> Ordering- go1 [] [] = EQ- go1 [] _ = LT- go1 _ [] = GT- go1 xs@(x:_) ys- | isDigit8 x =- let (xs1, xs2) = span isDigit8 xs- (ys1, ys2) = span isDigit8 ys- -- numeric segments are always newer than alpha segments- in if null ys1- then GT- else compareInt xs1 ys1 <> go0 xs2 ys2-- -- isAlpha- | otherwise =- let (xs1, xs2) = span isAlpha8 xs- (ys1, ys2) = span isAlpha8 ys- in if null ys1- then LT- else compareStr xs1 ys1 <> go0 xs2 ys2---- compare as numbers-compareInt :: [Word8] -> [Word8] -> Ordering-compareInt xs ys =- -- whichever number has more digits wins- compare (length xs') (length ys') <>- -- equal length: use per character compare, "strcmp"- compare xs' ys'- where- -- drop leading zeros- xs' = dropWhile (== 0x30) xs- ys' = dropWhile (== 0x30) ys---- strcmp-compareStr :: [Word8] -> [Word8] -> Ordering-compareStr = compare--dropNonAlnum8 :: [Word8] -> [Word8]-dropNonAlnum8 = dropWhile (\w -> not (isDigit8 w || isAlpha8 w))--isDigit8 :: Word8 -> Bool-isDigit8 w = 0x30 <= w && w <= 0x39--isAlpha8 :: Word8 -> Bool-isAlpha8 w = (0x41 <= w && w <= 0x5A) || (0x61 <= w && w <= 0x7A)--
− Distribution/Types/PkgconfigVersionRange.hs
@@ -1,161 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.PkgconfigVersionRange (- PkgconfigVersionRange (..),- anyPkgconfigVersion,- isAnyPkgconfigVersion,- withinPkgconfigVersionRange,- -- * Internal- versionToPkgconfigVersion,- versionRangeToPkgconfigVersionRange,- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.PkgconfigVersion-import Distribution.Types.Version-import Distribution.Types.VersionInterval-import Distribution.Types.VersionRange--import qualified Data.ByteString.Char8 as BS8-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as PP---- | @since 3.0-data PkgconfigVersionRange- = PcAnyVersion- | PcThisVersion PkgconfigVersion -- = version- | PcLaterVersion PkgconfigVersion -- > version (NB. not >=)- | PcEarlierVersion PkgconfigVersion -- < version- | PcOrLaterVersion PkgconfigVersion -- >= version- | PcOrEarlierVersion PkgconfigVersion -- =< version- | PcUnionVersionRanges PkgconfigVersionRange PkgconfigVersionRange- | PcIntersectVersionRanges PkgconfigVersionRange PkgconfigVersionRange- deriving (Generic, Read, Show, Eq, Typeable, Data)--instance Binary PkgconfigVersionRange-instance Structured PkgconfigVersionRange-instance NFData PkgconfigVersionRange where rnf = genericRnf--instance Pretty PkgconfigVersionRange where- pretty = pp 0 where- pp :: Int -> PkgconfigVersionRange -> PP.Doc- pp _ PcAnyVersion = PP.text "-any"- pp _ (PcThisVersion v) = PP.text "==" <<>> pretty v- pp _ (PcLaterVersion v) = PP.text ">" <<>> pretty v- pp _ (PcEarlierVersion v) = PP.text "<" <<>> pretty v- pp _ (PcOrLaterVersion v) = PP.text ">=" <<>> pretty v- pp _ (PcOrEarlierVersion v) = PP.text "<=" <<>> pretty v-- pp d (PcUnionVersionRanges v u) = parens (d >= 1) $- pp 1 v PP.<+> PP.text "||" PP.<+> pp 0 u- pp d (PcIntersectVersionRanges v u) = parens (d >= 2) $- pp 2 v PP.<+> PP.text "&&" PP.<+> pp 1 u-- parens True = PP.parens- parens False = id--instance Parsec PkgconfigVersionRange where- -- note: the wildcard is used in some places, e.g- -- http://hackage.haskell.org/package/bindings-libzip-0.10.1/bindings-libzip.cabal- --- -- however, in the presence of alphanumerics etc. lax version parser,- -- wildcard is ill-specified-- parsec = do- csv <- askCabalSpecVersion- if csv >= CabalSpecV3_0- then pkgconfigParser- else versionRangeToPkgconfigVersionRange <$> versionRangeParser P.integral csv---- "modern" parser of @pkg-config@ package versions.-pkgconfigParser :: CabalParsing m => m PkgconfigVersionRange-pkgconfigParser = P.spaces >> expr where- -- every parser here eats trailing space- expr = do- ts <- term `P.sepByNonEmpty` (P.string "||" >> P.spaces)- return $ foldr1 PcUnionVersionRanges ts-- term = do- fs <- factor `P.sepByNonEmpty` (P.string "&&" >> P.spaces)- return $ foldr1 PcIntersectVersionRanges fs-- factor = parens expr <|> prim-- prim = do- op <- P.munch1 isOpChar P.<?> "operator"- case op of- "-" -> anyPkgconfigVersion <$ (P.string "any" *> P.spaces)-- "==" -> afterOp PcThisVersion- ">" -> afterOp PcLaterVersion- "<" -> afterOp PcEarlierVersion- ">=" -> afterOp PcOrLaterVersion- "<=" -> afterOp PcOrEarlierVersion-- _ -> P.unexpected $ "Unknown version operator " ++ show op-- -- https://gitlab.haskell.org/ghc/ghc/issues/17752- isOpChar '<' = True- isOpChar '=' = True- isOpChar '>' = True- isOpChar '^' = True- isOpChar '-' = True- isOpChar _ = False-- afterOp f = do- P.spaces- v <- parsec- P.spaces- return (f v)-- parens = P.between- ((P.char '(' P.<?> "opening paren") >> P.spaces)- (P.char ')' >> P.spaces)--anyPkgconfigVersion :: PkgconfigVersionRange-anyPkgconfigVersion = PcAnyVersion---- | TODO: this is not precise, but used only to prettify output.-isAnyPkgconfigVersion :: PkgconfigVersionRange -> Bool-isAnyPkgconfigVersion = (== PcAnyVersion)--withinPkgconfigVersionRange :: PkgconfigVersion -> PkgconfigVersionRange -> Bool-withinPkgconfigVersionRange v = go where- go PcAnyVersion = True- go (PcThisVersion u) = v == u- go (PcLaterVersion u) = v > u- go (PcEarlierVersion u) = v < u- go (PcOrLaterVersion u) = v >= u- go (PcOrEarlierVersion u) = v <= u- go (PcUnionVersionRanges a b) = go a || go b- go (PcIntersectVersionRanges a b) = go a && go b------------------------------------------------------------------------------------ Conversion----------------------------------------------------------------------------------versionToPkgconfigVersion :: Version -> PkgconfigVersion-versionToPkgconfigVersion = PkgconfigVersion . BS8.pack . prettyShow--versionRangeToPkgconfigVersionRange :: VersionRange -> PkgconfigVersionRange-versionRangeToPkgconfigVersionRange vr- | isAnyVersion vr- = PcAnyVersion- | otherwise- = case asVersionIntervals vr of- [] -> PcEarlierVersion (PkgconfigVersion (BS8.pack "0"))- (i:is) -> foldl (\r j -> PcUnionVersionRanges r (conv j)) (conv i) is- where- conv (LowerBound v b, NoUpperBound) = convL v b- conv (LowerBound v b, UpperBound u c) = PcIntersectVersionRanges (convL v b) (convU u c)-- convL v ExclusiveBound = PcLaterVersion (versionToPkgconfigVersion v)- convL v InclusiveBound = PcOrLaterVersion (versionToPkgconfigVersion v)-- convU v ExclusiveBound = PcEarlierVersion (versionToPkgconfigVersion v)- convU v InclusiveBound = PcOrEarlierVersion (versionToPkgconfigVersion v)
− Distribution/Types/SetupBuildInfo.hs
@@ -1,41 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.SetupBuildInfo (- SetupBuildInfo(..)-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.Dependency---- ------------------------------------------------------------------------------ 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 Structured SetupBuildInfo-instance NFData SetupBuildInfo where rnf = genericRnf--instance Monoid SetupBuildInfo where- mempty = SetupBuildInfo [] False- mappend = (<>)--instance Semigroup SetupBuildInfo where- a <> b = SetupBuildInfo- (setupDepends a <> setupDepends b)- (defaultSetupDepends a || defaultSetupDepends b)
− Distribution/Types/SetupBuildInfo/Lens.hs
@@ -1,21 +0,0 @@-module Distribution.Types.SetupBuildInfo.Lens (- SetupBuildInfo,- module Distribution.Types.SetupBuildInfo.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.Dependency (Dependency)-import Distribution.Types.SetupBuildInfo (SetupBuildInfo)--import qualified Distribution.Types.SetupBuildInfo as T--setupDepends :: Lens' SetupBuildInfo [Dependency]-setupDepends f s = fmap (\x -> s { T.setupDepends = x }) (f (T.setupDepends s))-{-# INLINE setupDepends #-}--defaultSetupDepends :: Lens' SetupBuildInfo Bool-defaultSetupDepends f s = fmap (\x -> s { T.defaultSetupDepends = x }) (f (T.defaultSetupDepends s))-{-# INLINE defaultSetupDepends #-}
− Distribution/Types/SourceRepo.hs
@@ -1,201 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.SourceRepo (- SourceRepo(..),- RepoKind(..),- RepoType(..),- KnownRepoType (..),- knownRepoTypes,- emptySourceRepo,- classifyRepoType,- classifyRepoKind,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Utils.Generic (lowercase)--import Distribution.Pretty-import Distribution.Parsec--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp-import qualified Data.Map.Strict as M---- --------------------------------------------------------------- * Source repos--- ---------------------------------------------------------------- | Information about the source revision control system for a package.------ When specifying a repo it is useful to know the meaning or intention of the--- information as doing so enables automation. There are two obvious common--- purposes: one is to find the repo for the latest development version, the--- other is to find the repo for this specific release. The 'ReopKind'--- specifies which one we mean (or another custom one).------ A package can specify one or the other kind or both. Most will specify just--- a head repo but some may want to specify a repo to reconstruct the sources--- for this package release.------ The required information is the 'RepoType' which tells us if it's using--- 'Darcs', 'Git' for example. The 'repoLocation' and other details are--- interpreted according to the repo type.----data SourceRepo = SourceRepo {- -- | The kind of repo. This field is required.- repoKind :: RepoKind,-- -- | The type of the source repository system for this repo, eg 'Darcs' or- -- 'Git'. This field is required.- repoType :: Maybe RepoType,-- -- | The location of the repository. For most 'RepoType's this is a URL.- -- This field is required.- repoLocation :: Maybe String,-- -- | 'CVS' can put multiple \"modules\" on one server and requires a- -- module name in addition to the location to identify a particular repo.- -- Logically this is part of the location but unfortunately has to be- -- specified separately. This field is required for the 'CVS' 'RepoType' and- -- should not be given otherwise.- repoModule :: Maybe String,-- -- | The name or identifier of the branch, if any. Many source control- -- systems have the notion of multiple branches in a repo that exist in the- -- same location. For example 'Git' and 'CVS' use this while systems like- -- 'Darcs' use different locations for different branches. This field is- -- optional but should be used if necessary to identify the sources,- -- especially for the 'RepoThis' repo kind.- repoBranch :: Maybe String,-- -- | The tag identify a particular state of the repository. This should be- -- given for the 'RepoThis' repo kind and not for 'RepoHead' kind.- --- repoTag :: Maybe String,-- -- | Some repositories contain multiple projects in different subdirectories- -- This field specifies the subdirectory where this packages sources can be- -- found, eg the subdirectory containing the @.cabal@ file. It is interpreted- -- relative to the root of the repository. This field is optional. If not- -- given the default is \".\" ie no subdirectory.- repoSubdir :: Maybe FilePath-}- deriving (Eq, Ord, Generic, Read, Show, Typeable, Data)--emptySourceRepo :: RepoKind -> SourceRepo-emptySourceRepo kind = SourceRepo- { repoKind = kind- , repoType = Nothing- , repoLocation = Nothing- , repoModule = Nothing- , repoBranch = Nothing- , repoTag = Nothing- , repoSubdir = Nothing- }--instance Binary SourceRepo-instance Structured SourceRepo-instance NFData SourceRepo where rnf = genericRnf---- | What this repo info is for, what it represents.----data RepoKind =- -- | The repository for the \"head\" or development version of the project.- -- This repo is where we should track the latest development activity or- -- the usual repo people should get to contribute patches.- RepoHead-- -- | The repository containing the sources for this exact package version- -- or release. For this kind of repo a tag should be given to give enough- -- information to re-create the exact sources.- | RepoThis-- | RepoKindUnknown String- deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)--instance Binary RepoKind-instance Structured RepoKind-instance NFData RepoKind where rnf = genericRnf---- | An enumeration of common source control systems. The fields used in the--- 'SourceRepo' depend on the type of repo. The tools and methods used to--- obtain and track the repo depend on the repo type.----data KnownRepoType = Darcs | Git | SVN | CVS- | Mercurial | GnuArch | Bazaar | Monotone- | Pijul -- ^ @since 3.4.0.0- deriving (Eq, Generic, Ord, Read, Show, Typeable, Data, Enum, Bounded)--instance Binary KnownRepoType-instance Structured KnownRepoType-instance NFData KnownRepoType where rnf = genericRnf--instance Parsec KnownRepoType where- parsec = do- str <- P.munch1 isIdent- maybe- (P.unexpected $ "Could not parse KnownRepoType from " ++ str)- return- (M.lookup str knownRepoTypeMap)--instance Pretty KnownRepoType where- pretty = Disp.text . lowercase . show--data RepoType = KnownRepoType KnownRepoType- | OtherRepoType String- deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)--instance Binary RepoType-instance Structured RepoType-instance NFData RepoType where rnf = genericRnf--knownRepoTypes :: [KnownRepoType]-knownRepoTypes = [minBound .. maxBound]--repoTypeAliases :: KnownRepoType -> [String]-repoTypeAliases Bazaar = ["bzr"]-repoTypeAliases Mercurial = ["hg"]-repoTypeAliases GnuArch = ["arch"]-repoTypeAliases _ = []--instance Pretty RepoKind where- pretty RepoHead = Disp.text "head"- pretty RepoThis = Disp.text "this"- pretty (RepoKindUnknown other) = Disp.text other--instance Parsec RepoKind where- parsec = classifyRepoKind <$> P.munch1 isIdent--classifyRepoKind :: String -> RepoKind-classifyRepoKind name = case lowercase name of- "head" -> RepoHead- "this" -> RepoThis- _ -> RepoKindUnknown name--instance Parsec RepoType where- parsec = classifyRepoType <$> P.munch1 isIdent--instance Pretty RepoType where- pretty (OtherRepoType other) = Disp.text other- pretty (KnownRepoType t) = pretty t--classifyRepoType :: String -> RepoType-classifyRepoType s =- maybe- (OtherRepoType s)- KnownRepoType- (M.lookup (lowercase s) knownRepoTypeMap)--knownRepoTypeMap :: Map String KnownRepoType-knownRepoTypeMap =- M.fromList- [ (name, repoType')- | repoType' <- knownRepoTypes- , name <- prettyShow repoType' : repoTypeAliases repoType'- ]--isIdent :: Char -> Bool-isIdent c = isAlphaNum c || c == '_' || c == '-'
− Distribution/Types/SourceRepo/Lens.hs
@@ -1,39 +0,0 @@-module Distribution.Types.SourceRepo.Lens (- T.SourceRepo,- module Distribution.Types.SourceRepo.Lens,- ) where--import Prelude()-import Distribution.Compat.Prelude-import Distribution.Compat.Lens--import Distribution.Types.SourceRepo (SourceRepo, RepoKind, RepoType)-import qualified Distribution.Types.SourceRepo as T--repoKind :: Lens' SourceRepo RepoKind-repoKind f s = fmap (\x -> s { T.repoKind = x }) (f (T.repoKind s))-{-# INLINE repoKind #-}--repoType :: Lens' SourceRepo (Maybe RepoType)-repoType f s = fmap (\x -> s { T.repoType = x }) (f (T.repoType s))-{-# INLINE repoType #-}--repoLocation :: Lens' SourceRepo (Maybe String)-repoLocation f s = fmap (\x -> s { T.repoLocation = x }) (f (T.repoLocation s))-{-# INLINE repoLocation #-}--repoModule :: Lens' SourceRepo (Maybe String)-repoModule f s = fmap (\x -> s { T.repoModule = x }) (f (T.repoModule s))-{-# INLINE repoModule #-}--repoBranch :: Lens' SourceRepo (Maybe String)-repoBranch f s = fmap (\x -> s { T.repoBranch = x }) (f (T.repoBranch s))-{-# INLINE repoBranch #-}--repoTag :: Lens' SourceRepo (Maybe String)-repoTag f s = fmap (\x -> s { T.repoTag = x }) (f (T.repoTag s))-{-# INLINE repoTag #-}--repoSubdir :: Lens' SourceRepo (Maybe FilePath)-repoSubdir f s = fmap (\x -> s { T.repoSubdir = x }) (f (T.repoSubdir s))-{-# INLINE repoSubdir #-}
− Distribution/Types/TargetInfo.hs
@@ -1,33 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Distribution.Types.TargetInfo (- TargetInfo(..)-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.ComponentLocalBuildInfo-import Distribution.Types.Component-import Distribution.Types.UnitId--import Distribution.Compat.Graph (IsNode(..))---- | The 'TargetInfo' contains all the information necessary to build a--- specific target (e.g., component/module/file) in a package. In--- principle, one can get the 'Component' from a--- 'ComponentLocalBuildInfo' and 'LocalBuildInfo', but it is much more--- convenient to have the component in hand.-data TargetInfo = TargetInfo {- targetCLBI :: ComponentLocalBuildInfo,- targetComponent :: Component- -- TODO: BuildTargets supporting parsing these is dumb,- -- we don't have support for compiling single modules or- -- file paths. Accommodating it now is premature- -- generalization. Figure it out later.- -- targetSub :: Maybe (Either ModuleName FilePath)- }--instance IsNode TargetInfo where- type Key TargetInfo = UnitId- nodeKey = nodeKey . targetCLBI- nodeNeighbors = nodeNeighbors . targetCLBI
− Distribution/Types/TestSuite.hs
@@ -1,83 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.TestSuite (- TestSuite(..),- emptyTestSuite,- testType,- testModules,- testModulesAutogen-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.BuildInfo-import Distribution.Types.TestType-import Distribution.Types.TestSuiteInterface-import Distribution.Types.UnqualComponentName--import Distribution.ModuleName--import qualified Distribution.Types.BuildInfo.Lens as L---- | A \"test-suite\" stanza in a cabal file.----data TestSuite = TestSuite {- testName :: UnqualComponentName,- testInterface :: TestSuiteInterface,- testBuildInfo :: BuildInfo- }- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance L.HasBuildInfo TestSuite where- buildInfo f l = (\x -> l { testBuildInfo = x }) <$> f (testBuildInfo l)--instance Binary TestSuite-instance Structured TestSuite--instance NFData TestSuite where rnf = genericRnf--instance Monoid TestSuite where- mempty = TestSuite {- testName = mempty,- testInterface = mempty,- testBuildInfo = mempty- }- mappend = (<>)--instance Semigroup TestSuite where- a <> b = TestSuite {- testName = combine' testName,- testInterface = combine testInterface,- testBuildInfo = combine testBuildInfo- }- where combine field = field a `mappend` field b- combine' field = case ( unUnqualComponentName $ field a- , unUnqualComponentName $ field b) of- ("", _) -> field b- (_, "") -> field a- (x, y) -> error $ "Ambiguous values for test field: '"- ++ x ++ "' and '" ++ y ++ "'"--emptyTestSuite :: TestSuite-emptyTestSuite = mempty---testType :: TestSuite -> TestType-testType test = case testInterface test of- TestSuiteExeV10 ver _ -> TestTypeExe ver- TestSuiteLibV09 ver _ -> TestTypeLib ver- TestSuiteUnsupported testtype -> testtype---- | Get all the module names from a test suite.-testModules :: TestSuite -> [ModuleName]-testModules test = (case testInterface test of- TestSuiteLibV09 _ m -> [m]- _ -> [])- ++ otherModules (testBuildInfo test)---- | Get all the auto generated module names from a test suite.--- This are a subset of 'testModules'.-testModulesAutogen :: TestSuite -> [ModuleName]-testModulesAutogen test = autogenModules (testBuildInfo test)
− Distribution/Types/TestSuite/Lens.hs
@@ -1,27 +0,0 @@-module Distribution.Types.TestSuite.Lens (- TestSuite,- module Distribution.Types.TestSuite.Lens,- ) where--import Distribution.Compat.Lens-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.TestSuite (TestSuite)-import Distribution.Types.TestSuiteInterface (TestSuiteInterface)-import Distribution.Types.UnqualComponentName (UnqualComponentName)--import qualified Distribution.Types.TestSuite as T--testName :: Lens' TestSuite UnqualComponentName-testName f s = fmap (\x -> s { T.testName = x }) (f (T.testName s))-{-# INLINE testName #-}--testInterface :: Lens' TestSuite TestSuiteInterface-testInterface f s = fmap (\x -> s { T.testInterface = x }) (f (T.testInterface s))-{-# INLINE testInterface #-}--testBuildInfo :: Lens' TestSuite BuildInfo-testBuildInfo f s = fmap (\x -> s { T.testBuildInfo = x }) (f (T.testBuildInfo s))-{-# INLINE testBuildInfo #-}
− Distribution/Types/TestSuiteInterface.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Distribution.Types.TestSuiteInterface (- TestSuiteInterface(..),-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Types.TestType-import Distribution.ModuleName-import Distribution.Version---- | The test suite interfaces that are currently defined. Each test suite must--- specify which interface it supports.------ More interfaces may be defined in future, either new revisions or totally--- new interfaces.----data TestSuiteInterface =-- -- | Test interface \"exitcode-stdio-1.0\". The test-suite takes the form- -- of an executable. It returns a zero exit code for success, non-zero for- -- failure. The stdout and stderr channels may be logged. It takes no- -- command line parameters and nothing on stdin.- --- TestSuiteExeV10 Version FilePath-- -- | Test interface \"detailed-0.9\". The test-suite takes the form of a- -- library containing a designated module that exports \"tests :: [Test]\".- --- | TestSuiteLibV09 Version ModuleName-- -- | A test suite that does not conform to one of the above interfaces for- -- the given reason (e.g. unknown test type).- --- | TestSuiteUnsupported TestType- deriving (Eq, Generic, Read, Show, Typeable, Data)--instance Binary TestSuiteInterface-instance Structured TestSuiteInterface--instance NFData TestSuiteInterface where rnf = genericRnf--instance Monoid TestSuiteInterface where- mempty = TestSuiteUnsupported (TestTypeUnknown mempty nullVersion)- mappend = (<>)--instance Semigroup TestSuiteInterface where- a <> (TestSuiteUnsupported _) = a- _ <> b = b
− Distribution/Types/TestType.hs
@@ -1,43 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}--module Distribution.Types.TestType (- TestType(..),- knownTestTypes,-) where--import Distribution.Compat.Prelude-import Distribution.Version-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Text.PrettyPrint (char, text)---- | The \"test-type\" field in the test suite stanza.----data TestType = TestTypeExe Version -- ^ \"type: exitcode-stdio-x.y\"- | TestTypeLib Version -- ^ \"type: detailed-x.y\"- | TestTypeUnknown String Version -- ^ Some unknown test type e.g. \"type: foo\"- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Binary TestType-instance Structured TestType--instance NFData TestType where rnf = genericRnf--knownTestTypes :: [TestType]-knownTestTypes = [ TestTypeExe (mkVersion [1,0])- , TestTypeLib (mkVersion [0,9]) ]--instance Pretty TestType where- pretty (TestTypeExe ver) = text "exitcode-stdio-" <<>> pretty ver- pretty (TestTypeLib ver) = text "detailed-" <<>> pretty ver- pretty (TestTypeUnknown name ver) = text name <<>> char '-' <<>> pretty ver--instance Parsec TestType where- parsec = parsecStandard $ \ver name -> case name of- "exitcode-stdio" -> TestTypeExe ver- "detailed" -> TestTypeLib ver- _ -> TestTypeUnknown name ver
− Distribution/Types/UnitId.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE FlexibleContexts #-}--module Distribution.Types.UnitId- ( UnitId, unUnitId, mkUnitId- , DefUnitId- , unsafeMkDefUnitId- , unDefUnitId- , newSimpleUnitId- , mkLegacyUnitId- , getHSLibraryName- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.ShortText--import qualified Distribution.Compat.CharParsing as P-import Distribution.Pretty-import Distribution.Parsec-import Distribution.Types.ComponentId-import Distribution.Types.PackageId--import Text.PrettyPrint (text)---- | A unit identifier identifies a (possibly instantiated)--- package/component that can be installed the installed package--- database. There are several types of components that can be--- installed:------ * A traditional library with no holes, so that 'unitIdHash'--- is @Nothing@. In the absence of Backpack, 'UnitId'--- is the same as a 'ComponentId'.------ * An indefinite, Backpack library with holes. In this case,--- 'unitIdHash' is still @Nothing@, but in the install,--- there are only interfaces, no compiled objects.------ * An instantiated Backpack library with all the holes--- filled in. 'unitIdHash' is a @Just@ a hash of the--- instantiating mapping.------ A unit is a component plus the additional information on how the--- holes are filled in. Thus there is a one to many relationship: for a--- particular component there are many different ways of filling in the--- holes, and each different combination is a unit (and has a separate--- 'UnitId').------ 'UnitId' is distinct from 'OpenUnitId', in that it is always--- installed, whereas 'OpenUnitId' are intermediate unit identities--- that arise during mixin linking, and don't necessarily correspond--- to any actually installed unit. Since the mapping is not actually--- recorded in a 'UnitId', you can't actually substitute over them--- (but you can substitute over 'OpenUnitId'). See also--- "Distribution.Backpack.FullUnitId" for a mechanism for expanding an--- instantiated 'UnitId' to retrieve its mapping.------ Backwards compatibility note: if you need to get the string--- representation of a UnitId to pass, e.g., as a @-package-id@--- flag, use the 'display' function, which will work on all--- versions of Cabal.----newtype UnitId = UnitId ShortText- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, NFData)--instance Binary UnitId-instance Structured UnitId---- | The textual format for 'UnitId' coincides with the format--- GHC accepts for @-package-id@.----instance Pretty UnitId where- pretty = text . unUnitId---- | The textual format for 'UnitId' coincides with the format--- GHC accepts for @-package-id@.----instance Parsec UnitId where- parsec = mkUnitId <$> P.munch1 isUnitChar where- -- https://gitlab.haskell.org/ghc/ghc/issues/17752- isUnitChar '-' = True- isUnitChar '_' = True- isUnitChar '.' = True- isUnitChar '+' = True- isUnitChar c = isAlphaNum c---- | If you need backwards compatibility, consider using 'display'--- instead, which is supported by all versions of Cabal.----unUnitId :: UnitId -> String-unUnitId (UnitId s) = fromShortText s--mkUnitId :: String -> UnitId-mkUnitId = UnitId . toShortText---- | 'mkUnitId'------ @since 2.0.0.2-instance IsString UnitId where- fromString = mkUnitId---- | Create a unit identity with no associated hash directly--- from a 'ComponentId'.-newSimpleUnitId :: ComponentId -> UnitId-newSimpleUnitId = mkUnitId . unComponentId---- | Make an old-style UnitId from a package identifier.--- Assumed to be for the public library-mkLegacyUnitId :: PackageId -> UnitId-mkLegacyUnitId = newSimpleUnitId . mkComponentId . prettyShow---- | Returns library name prefixed with HS, suitable for filenames-getHSLibraryName :: UnitId -> String-getHSLibraryName uid = "HS" ++ prettyShow uid---- | A 'UnitId' for a definite package. The 'DefUnitId' invariant says--- that a 'UnitId' identified this way is definite; i.e., it has no--- unfilled holes.-newtype DefUnitId = DefUnitId { unDefUnitId :: UnitId }- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, Binary, NFData, Pretty)--instance Structured DefUnitId---- Workaround for a GHC 8.0.1 bug, see--- https://github.com/haskell/cabal/issues/4793#issuecomment-334258288-instance Parsec DefUnitId where- parsec = DefUnitId <$> parsec---- | Unsafely create a 'DefUnitId' from a 'UnitId'. Your responsibility--- is to ensure that the 'DefUnitId' invariant holds.-unsafeMkDefUnitId :: UnitId -> DefUnitId-unsafeMkDefUnitId = DefUnitId
− Distribution/Types/UnqualComponentName.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Distribution.Types.UnqualComponentName- ( UnqualComponentName, unUnqualComponentName, unUnqualComponentNameST, mkUnqualComponentName- , packageNameToUnqualComponentName, unqualComponentNameToPackageName- ) where--import Distribution.Compat.Prelude-import Distribution.Utils.ShortText-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty-import Distribution.Types.PackageName---- | An unqualified component name, for any kind of component.------ This is distinguished from a 'ComponentName' and 'ComponentId'. The former--- also states which of a library, executable, etc the name refers too. The--- later uniquely identifiers a component and its closure.------ @since 2.0.0.2-newtype UnqualComponentName = UnqualComponentName ShortText- deriving (Generic, Read, Show, Eq, Ord, Typeable, Data,- Semigroup, Monoid) -- TODO: bad enabler of bad monoids---- | Convert 'UnqualComponentName' to 'String'------ @since 2.0.0.2-unUnqualComponentName :: UnqualComponentName -> String-unUnqualComponentName (UnqualComponentName s) = fromShortText s---- | @since 3.4.0.0-unUnqualComponentNameST :: UnqualComponentName -> ShortText-unUnqualComponentNameST (UnqualComponentName s) = s---- | Construct a 'UnqualComponentName' from a 'String'------ 'mkUnqualComponentName' is the inverse to 'unUnqualComponentName'------ Note: No validations are performed to ensure that the resulting--- 'UnqualComponentName' is valid------ @since 2.0.0.2-mkUnqualComponentName :: String -> UnqualComponentName-mkUnqualComponentName = UnqualComponentName . toShortText---- | 'mkUnqualComponentName'------ @since 2.0.0.2-instance IsString UnqualComponentName where- fromString = mkUnqualComponentName--instance Binary UnqualComponentName-instance Structured UnqualComponentName--instance Pretty UnqualComponentName where- pretty = showToken . unUnqualComponentName--instance Parsec UnqualComponentName where- parsec = mkUnqualComponentName <$> parsecUnqualComponentName--instance NFData UnqualComponentName where- rnf (UnqualComponentName pkg) = rnf pkg---- TODO avoid String round trip with these PackageName <->--- UnqualComponentName converters.---- | Converts a package name to an unqualified component name------ Useful in legacy situations where a package name may refer to an internal--- component, if one is defined with that name.------ 2018-12-21: These "legacy" situations are not legacy.--- We can @build-depends@ on the internal library. However--- Now dependency contains @Set LibraryName@, and we should use that.------ @since 2.0.0.2-packageNameToUnqualComponentName :: PackageName -> UnqualComponentName-packageNameToUnqualComponentName = UnqualComponentName . unPackageNameST---- | Converts an unqualified component name to a package name------ `packageNameToUnqualComponentName` is the inverse of--- `unqualComponentNameToPackageName`.------ Useful in legacy situations where a package name may refer to an internal--- component, if one is defined with that name.------ @since 2.0.0.2-unqualComponentNameToPackageName :: UnqualComponentName -> PackageName-unqualComponentNameToPackageName = mkPackageNameST . unUnqualComponentNameST
− Distribution/Types/Version.hs
@@ -1,242 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.Version (- -- * Package versions- Version,- mkVersion,- mkVersion',- versionNumbers,- nullVersion,- alterVersion,- version0,-- -- * Internal- validVersion,- versionDigitParser,- ) where--import Data.Bits (shiftL, shiftR, (.&.), (.|.))-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Parsec-import Distribution.Pretty--import qualified Data.Version as Base-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp-import qualified Text.Read as Read---- | A 'Version' represents the version of a software entity.------ Instances of 'Eq' and 'Ord' are provided, which gives exact--- equality and lexicographic ordering of the version number--- components (i.e. 2.1 > 2.0, 1.2.3 > 1.2.2, etc.).------ This type is opaque and distinct from the 'Base.Version' type in--- "Data.Version" since @Cabal-2.0@. The difference extends to the--- 'Binary' instance using a different (and more compact) encoding.------ @since 2.0.0.2-data Version = PV0 {-# UNPACK #-} !Word64- | PV1 !Int [Int]- -- NOTE: If a version fits into the packed Word64- -- representation (i.e. at most four version components- -- which all fall into the [0..0xfffe] range), then PV0- -- MUST be used. This is essential for the 'Eq' instance- -- to work.- deriving (Data,Eq,Generic,Typeable)--instance Ord Version where- compare (PV0 x) (PV0 y) = compare x y- compare (PV1 x xs) (PV1 y ys) = case compare x y of- EQ -> compare xs ys- c -> c- compare (PV0 w) (PV1 y ys) = case compare x y of- EQ -> compare [x2,x3,x4] ys- c -> c- where- x = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1- x2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1- x3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1- x4 = fromIntegral (w .&. 0xffff) - 1- compare (PV1 x xs) (PV0 w) = case compare x y of- EQ -> compare xs [y2,y3,y4]- c -> c- where- y = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1- y2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1- y3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1- y4 = fromIntegral (w .&. 0xffff) - 1--instance Show Version where- showsPrec d v = showParen (d > 10)- $ showString "mkVersion "- . showsPrec 11 (versionNumbers v)--instance Read Version where- readPrec = Read.parens $ do- Read.Ident "mkVersion" <- Read.lexP- v <- Read.step Read.readPrec- return (mkVersion v)--instance Binary Version-instance Structured Version--instance NFData Version where- rnf (PV0 _) = ()- rnf (PV1 _ ns) = rnf ns--instance Pretty Version where- pretty ver- = Disp.hcat (Disp.punctuate (Disp.char '.')- (map Disp.int $ versionNumbers ver))--instance Parsec Version where- parsec = mkVersion <$> toList <$> P.sepByNonEmpty versionDigitParser (P.char '.') <* tags- where- tags = do- ts <- many $ P.char '-' *> some (P.satisfy isAlphaNum)- case ts of- [] -> pure ()- (_ : _) -> parsecWarning PWTVersionTag "version with tags"---- | An integral without leading zeroes.------ @since 3.0-versionDigitParser :: CabalParsing m => m Int-versionDigitParser = (some d >>= toNumber) P.<?> "version digit (integral without leading zeroes)"- where- toNumber :: CabalParsing m => [Int] -> m Int- toNumber [0] = return 0- toNumber (0:_) = P.unexpected "Version digit with leading zero"- toNumber xs- -- 10^9 = 1000000000- -- 2^30 = 1073741824- --- -- GHC Int is at least 32 bits, so 2^31-1 is the 'maxBound'.- | length xs > 9 = P.unexpected "At most 9 numbers are allowed per version number part"- | otherwise = return $ foldl' (\a b -> a * 10 + b) 0 xs-- d :: P.CharParsing m => m Int- d = f <$> P.satisfyRange '0' '9'- f c = ord c - ord '0'---- | Construct 'Version' from list of version number components.------ For instance, @mkVersion [3,2,1]@ constructs a 'Version'--- representing the version @3.2.1@.------ All version components must be non-negative. @mkVersion []@--- currently represents the special /null/ version; see also 'nullVersion'.------ @since 2.0.0.2-mkVersion :: [Int] -> Version--- TODO: add validity check; disallow 'mkVersion []' (we have--- 'nullVersion' for that)-mkVersion [] = nullVersion-mkVersion (v1:[])- | inWord16VerRep1 v1 = PV0 (mkWord64VerRep1 v1)- | otherwise = PV1 v1 []- where- inWord16VerRep1 x1 = inWord16 (x1 .|. (x1+1))- mkWord64VerRep1 y1 = mkWord64VerRep (y1+1) 0 0 0--mkVersion (v1:vs@(v2:[]))- | inWord16VerRep2 v1 v2 = PV0 (mkWord64VerRep2 v1 v2)- | otherwise = PV1 v1 vs- where- inWord16VerRep2 x1 x2 = inWord16 (x1 .|. (x1+1)- .|. x2 .|. (x2+1))- mkWord64VerRep2 y1 y2 = mkWord64VerRep (y1+1) (y2+1) 0 0--mkVersion (v1:vs@(v2:v3:[]))- | inWord16VerRep3 v1 v2 v3 = PV0 (mkWord64VerRep3 v1 v2 v3)- | otherwise = PV1 v1 vs- where- inWord16VerRep3 x1 x2 x3 = inWord16 (x1 .|. (x1+1)- .|. x2 .|. (x2+1)- .|. x3 .|. (x3+1))- mkWord64VerRep3 y1 y2 y3 = mkWord64VerRep (y1+1) (y2+1) (y3+1) 0--mkVersion (v1:vs@(v2:v3:v4:[]))- | inWord16VerRep4 v1 v2 v3 v4 = PV0 (mkWord64VerRep4 v1 v2 v3 v4)- | otherwise = PV1 v1 vs- where- inWord16VerRep4 x1 x2 x3 x4 = inWord16 (x1 .|. (x1+1)- .|. x2 .|. (x2+1)- .|. x3 .|. (x3+1)- .|. x4 .|. (x4+1))- mkWord64VerRep4 y1 y2 y3 y4 = mkWord64VerRep (y1+1) (y2+1) (y3+1) (y4+1)--mkVersion (v1:vs) = PV1 v1 vs---- | Version 0. A lower bound of 'Version'.------ @since 2.2-version0 :: Version-version0 = mkVersion [0]--{-# INLINE mkWord64VerRep #-}-mkWord64VerRep :: Int -> Int -> Int -> Int -> Word64-mkWord64VerRep v1 v2 v3 v4 =- (fromIntegral v1 `shiftL` 48)- .|. (fromIntegral v2 `shiftL` 32)- .|. (fromIntegral v3 `shiftL` 16)- .|. fromIntegral v4--{-# INLINE inWord16 #-}-inWord16 :: Int -> Bool-inWord16 x = (fromIntegral x :: Word) <= 0xffff---- | Variant of 'mkVersion' which converts a "Data.Version"--- 'Base.Version' into Cabal's 'Version' type.------ @since 2.0.0.2-mkVersion' :: Base.Version -> Version-mkVersion' = mkVersion . Base.versionBranch---- | Unpack 'Version' into list of version number components.------ This is the inverse to 'mkVersion', so the following holds:------ > (versionNumbers . mkVersion) vs == vs------ @since 2.0.0.2-versionNumbers :: Version -> [Int]-versionNumbers (PV1 n ns) = n:ns-versionNumbers (PV0 w)- | v1 < 0 = []- | v2 < 0 = [v1]- | v3 < 0 = [v1,v2]- | v4 < 0 = [v1,v2,v3]- | otherwise = [v1,v2,v3,v4]- where- v1 = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1- v2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1- v3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1- v4 = fromIntegral (w .&. 0xffff) - 1----- | Constant representing the special /null/ 'Version'------ The 'nullVersion' compares (via 'Ord') as less than every proper--- 'Version' value.------ @since 2.0.0.2-nullVersion :: Version--- TODO: at some point, 'mkVersion' may disallow creating /null/--- 'Version's-nullVersion = PV0 0---- | Apply function to list of version number components------ > alterVersion f == mkVersion . f . versionNumbers------ @since 2.0.0.2-alterVersion :: ([Int] -> [Int]) -> Version -> Version-alterVersion f = mkVersion . f . versionNumbers---- internal helper-validVersion :: Version -> Bool-validVersion v = v /= nullVersion && all (>=0) (versionNumbers v)
− Distribution/Types/VersionInterval.hs
@@ -1,364 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-module Distribution.Types.VersionInterval (- -- * Version intervals- VersionIntervals,- toVersionIntervals,- fromVersionIntervals,- withinIntervals,- versionIntervals,- mkVersionIntervals,- unionVersionIntervals,- intersectVersionIntervals,- invertVersionIntervals,- relaxLastInterval,- relaxHeadInterval,-- -- * Version intervals view- asVersionIntervals,- VersionInterval,- LowerBound(..),- UpperBound(..),- Bound(..),- ) where--import Prelude ()-import Distribution.Compat.Prelude-import Control.Exception (assert)--import Distribution.Types.Version-import Distribution.Types.VersionRange.Internal---- NonEmpty-import qualified Prelude (foldr1)------------------------------------------------------------------------------------ VersionRange------------------------------------------------------------------------------------ | View a 'VersionRange' as a union of intervals.------ This provides a canonical view of the semantics of a 'VersionRange' as--- opposed to the syntax of the expression used to define it. For the syntactic--- view use 'foldVersionRange'.------ Each interval is non-empty. The sequence is in increasing order and no--- intervals overlap or touch. Therefore only the first and last can be--- unbounded. The sequence can be empty if the range is empty--- (e.g. a range expression like @< 1 && > 2@).------ Other checks are trivial to implement using this view. For example:------ > isNoVersion vr | [] <- asVersionIntervals vr = True--- > | otherwise = False------ > isSpecificVersion vr--- > | [(LowerBound v InclusiveBound--- > ,UpperBound v' InclusiveBound)] <- asVersionIntervals vr--- > , v == v' = Just v--- > | otherwise = Nothing----asVersionIntervals :: VersionRange -> [VersionInterval]-asVersionIntervals = versionIntervals . toVersionIntervals------------------------------------------------------------------------------------- VersionInterval------------------------------------------------------------------------------------ | A complementary representation of a 'VersionRange'. Instead of a boolean--- version predicate it uses an increasing sequence of non-overlapping,--- non-empty intervals.------ The key point is that this representation gives a canonical representation--- for the semantics of 'VersionRange's. This makes it easier to check things--- like whether a version range is empty, covers all versions, or requires a--- certain minimum or maximum version. It also makes it easy to check equality--- or containment. It also makes it easier to identify \'simple\' version--- predicates for translation into foreign packaging systems that do not--- support complex version range expressions.----newtype VersionIntervals = VersionIntervals [VersionInterval]- deriving (Eq, Show, Typeable)---- | Inspect the list of version intervals.----versionIntervals :: VersionIntervals -> [VersionInterval]-versionIntervals (VersionIntervals is) = is--type VersionInterval = (LowerBound, UpperBound)-data LowerBound = LowerBound Version !Bound deriving (Eq, Show)-data UpperBound = NoUpperBound | UpperBound Version !Bound deriving (Eq, Show)-data Bound = ExclusiveBound | InclusiveBound deriving (Eq, Show)--minLowerBound :: LowerBound-minLowerBound = LowerBound (mkVersion [0]) InclusiveBound--isVersion0 :: Version -> Bool-isVersion0 = (==) version0--instance Ord LowerBound where- LowerBound ver bound <= LowerBound ver' bound' = case compare ver ver' of- LT -> True- EQ -> not (bound == ExclusiveBound && bound' == InclusiveBound)- GT -> False--instance Ord UpperBound where- _ <= NoUpperBound = True- NoUpperBound <= UpperBound _ _ = False- UpperBound ver bound <= UpperBound ver' bound' = case compare ver ver' of- LT -> True- EQ -> not (bound == InclusiveBound && bound' == ExclusiveBound)- GT -> False--invariant :: VersionIntervals -> Bool-invariant (VersionIntervals intervals) = all validInterval intervals- && all doesNotTouch' adjacentIntervals- where- doesNotTouch' :: (VersionInterval, VersionInterval) -> Bool- doesNotTouch' ((_,u), (l',_)) = doesNotTouch u l'-- adjacentIntervals :: [(VersionInterval, VersionInterval)]- adjacentIntervals = case intervals of- [] -> []- (_:tl) -> zip intervals tl--checkInvariant :: VersionIntervals -> VersionIntervals-checkInvariant is = assert (invariant is) is---- | Directly construct a 'VersionIntervals' from a list of intervals.------ In @Cabal-2.2@ the 'Maybe' is dropped from the result type.----mkVersionIntervals :: [VersionInterval] -> VersionIntervals-mkVersionIntervals intervals- | invariant (VersionIntervals intervals) = VersionIntervals intervals- | otherwise- = checkInvariant- . foldl' (flip insertInterval) (VersionIntervals [])- . filter validInterval- $ intervals--insertInterval :: VersionInterval -> VersionIntervals -> VersionIntervals-insertInterval i is = unionVersionIntervals (VersionIntervals [i]) is--validInterval :: (LowerBound, UpperBound) -> Bool-validInterval i@(l, u) = validLower l && validUpper u && nonEmpty i- where- validLower (LowerBound v _) = validVersion v- validUpper NoUpperBound = True- validUpper (UpperBound v _) = validVersion v---- Check an interval is non-empty----nonEmpty :: VersionInterval -> Bool-nonEmpty (_, NoUpperBound ) = True-nonEmpty (LowerBound l lb, UpperBound u ub) =- (l < u) || (l == u && lb == InclusiveBound && ub == InclusiveBound)---- Check an upper bound does not intersect, or even touch a lower bound:------ ---| or ---) but not ---] or ---) or ---]--- |--- (--- (--- [--- [-------doesNotTouch :: UpperBound -> LowerBound -> Bool-doesNotTouch NoUpperBound _ = False-doesNotTouch (UpperBound u ub) (LowerBound l lb) =- u < l- || (u == l && ub == ExclusiveBound && lb == ExclusiveBound)---- | Check an upper bound does not intersect a lower bound:------ ---| or ---) or ---] or ---) but not ---]--- |--- (--- (--- [--- [-------doesNotIntersect :: UpperBound -> LowerBound -> Bool-doesNotIntersect NoUpperBound _ = False-doesNotIntersect (UpperBound u ub) (LowerBound l lb) =- u < l- || (u == l && not (ub == InclusiveBound && lb == InclusiveBound))---- | Test if a version falls within the version intervals.------ It exists mostly for completeness and testing. It satisfies the following--- properties:------ > withinIntervals v (toVersionIntervals vr) = withinRange v vr--- > withinIntervals v ivs = withinRange v (fromVersionIntervals ivs)----withinIntervals :: Version -> VersionIntervals -> Bool-withinIntervals v (VersionIntervals intervals) = any withinInterval intervals- where- withinInterval (lowerBound, upperBound) = withinLower lowerBound- && withinUpper upperBound- withinLower (LowerBound v' ExclusiveBound) = v' < v- withinLower (LowerBound v' InclusiveBound) = v' <= v-- withinUpper NoUpperBound = True- withinUpper (UpperBound v' ExclusiveBound) = v' > v- withinUpper (UpperBound v' InclusiveBound) = v' >= v---- | Convert a 'VersionRange' to a sequence of version intervals.----toVersionIntervals :: VersionRange -> VersionIntervals-toVersionIntervals = cataVersionRange alg where- alg (ThisVersionF v) = chkIvl (LowerBound v InclusiveBound, UpperBound v InclusiveBound)- alg (LaterVersionF v) = chkIvl (LowerBound v ExclusiveBound, NoUpperBound)- alg (OrLaterVersionF v) = chkIvl (LowerBound v InclusiveBound, NoUpperBound)- alg (EarlierVersionF v)- | isVersion0 v = VersionIntervals []- | otherwise = chkIvl (minLowerBound, UpperBound v ExclusiveBound)- alg (OrEarlierVersionF v) = chkIvl (minLowerBound, UpperBound v InclusiveBound)- alg (MajorBoundVersionF v) = chkIvl (LowerBound v InclusiveBound, UpperBound (majorUpperBound v) ExclusiveBound)- alg (UnionVersionRangesF v1 v2) = unionVersionIntervals v1 v2- alg (IntersectVersionRangesF v1 v2) = intersectVersionIntervals v1 v2-- chkIvl interval = checkInvariant (VersionIntervals [interval])---- | Convert a 'VersionIntervals' value back into a 'VersionRange' expression--- representing the version intervals.----fromVersionIntervals :: VersionIntervals -> VersionRange-fromVersionIntervals (VersionIntervals []) = noVersion-fromVersionIntervals (VersionIntervals intervals) =- Prelude.foldr1 unionVersionRanges [ interval l u | (l, u) <- intervals ]-- where- interval (LowerBound v InclusiveBound)- (UpperBound v' InclusiveBound) | v == v'- = thisVersion v- interval l u = lowerBound l `intersectVersionRanges'` upperBound u-- lowerBound (LowerBound v InclusiveBound)- | isVersion0 v = Nothing- | otherwise = Just (orLaterVersion v)- lowerBound (LowerBound v ExclusiveBound) = Just (laterVersion v)-- upperBound NoUpperBound = Nothing- upperBound (UpperBound v InclusiveBound) = Just (orEarlierVersion v)- upperBound (UpperBound v ExclusiveBound) = Just (earlierVersion v)-- intersectVersionRanges' Nothing Nothing = anyVersion- intersectVersionRanges' (Just vr) Nothing = vr- intersectVersionRanges' Nothing (Just vr) = vr- intersectVersionRanges' (Just vr) (Just vr') = intersectVersionRanges vr vr'--unionVersionIntervals :: VersionIntervals -> VersionIntervals- -> VersionIntervals-unionVersionIntervals (VersionIntervals is0) (VersionIntervals is'0) =- checkInvariant (VersionIntervals (union is0 is'0))- where- union is [] = is- union [] is' = is'- union (i:is) (i':is') = case unionInterval i i' of- Left Nothing -> i : union is (i' :is')- Left (Just i'') -> union is (i'':is')- Right Nothing -> i' : union (i :is) is'- Right (Just i'') -> union (i'':is) is'--unionInterval :: VersionInterval -> VersionInterval- -> Either (Maybe VersionInterval) (Maybe VersionInterval)-unionInterval (lower , upper ) (lower', upper')-- -- Non-intersecting intervals with the left interval ending first- | upper `doesNotTouch` lower' = Left Nothing-- -- Non-intersecting intervals with the right interval first- | upper' `doesNotTouch` lower = Right Nothing-- -- Complete or partial overlap, with the left interval ending first- | upper <= upper' = lowerBound `seq`- Left (Just (lowerBound, upper'))-- -- Complete or partial overlap, with the left interval ending first- | otherwise = lowerBound `seq`- Right (Just (lowerBound, upper))- where- lowerBound = min lower lower'--intersectVersionIntervals :: VersionIntervals -> VersionIntervals- -> VersionIntervals-intersectVersionIntervals (VersionIntervals is0) (VersionIntervals is'0) =- checkInvariant (VersionIntervals (intersect is0 is'0))- where- intersect _ [] = []- intersect [] _ = []- intersect (i:is) (i':is') = case intersectInterval i i' of- Left Nothing -> intersect is (i':is')- Left (Just i'') -> i'' : intersect is (i':is')- Right Nothing -> intersect (i:is) is'- Right (Just i'') -> i'' : intersect (i:is) is'--intersectInterval :: VersionInterval -> VersionInterval- -> Either (Maybe VersionInterval) (Maybe VersionInterval)-intersectInterval (lower , upper ) (lower', upper')-- -- Non-intersecting intervals with the left interval ending first- | upper `doesNotIntersect` lower' = Left Nothing-- -- Non-intersecting intervals with the right interval first- | upper' `doesNotIntersect` lower = Right Nothing-- -- Complete or partial overlap, with the left interval ending first- | upper <= upper' = lowerBound `seq`- Left (Just (lowerBound, upper))-- -- Complete or partial overlap, with the right interval ending first- | otherwise = lowerBound `seq`- Right (Just (lowerBound, upper'))- 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 (mkVersion [0]) InclusiveBound---relaxLastInterval :: VersionIntervals -> VersionIntervals-relaxLastInterval (VersionIntervals xs) = VersionIntervals (relaxLastInterval' xs)- where- relaxLastInterval' [] = []- relaxLastInterval' [(l,_)] = [(l, NoUpperBound)]- relaxLastInterval' (i:is) = i : relaxLastInterval' is--relaxHeadInterval :: VersionIntervals -> VersionIntervals-relaxHeadInterval (VersionIntervals xs) = VersionIntervals (relaxHeadInterval' xs)- where- relaxHeadInterval' [] = []- relaxHeadInterval' ((_,u):is) = (minLowerBound,u) : is
− Distribution/Types/VersionRange.hs
@@ -1,180 +0,0 @@-module Distribution.Types.VersionRange (- -- * Version ranges- VersionRange,-- -- ** Constructing- anyVersion, noVersion,- thisVersion, notThisVersion,- laterVersion, earlierVersion,- orLaterVersion, orEarlierVersion,- unionVersionRanges, intersectVersionRanges,- withinVersion,- majorBoundVersion,-- -- ** Inspection- --- -- See "Distribution.Version" for more utilities.- withinRange,- foldVersionRange,- normaliseVersionRange,- stripParensVersionRange,- hasUpperBound,- hasLowerBound,-- -- ** Cata & ana- VersionRangeF (..),- cataVersionRange,- anaVersionRange,- hyloVersionRange,- projectVersionRange,- embedVersionRange,-- -- ** Utilities- isAnyVersion,- isAnyVersionLight,- wildcardUpperBound,- majorUpperBound,- isWildcardRange,- versionRangeParser,- ) where--import Distribution.Compat.Prelude-import Distribution.Types.Version-import Distribution.Types.VersionInterval-import Distribution.Types.VersionRange.Internal-import Prelude ()---- | Fold over the basic syntactic structure of a 'VersionRange'.------ This provides a syntactic view of the expression defining the version range.--- The syntactic sugar @\">= v\"@, @\"<= v\"@ and @\"== v.*\"@ is presented--- in terms of the other basic syntax.------ For a semantic view use 'asVersionIntervals'.----foldVersionRange :: a -- ^ @\"-any\"@ version- -> (Version -> a) -- ^ @\"== v\"@- -> (Version -> a) -- ^ @\"> v\"@- -> (Version -> a) -- ^ @\"< v\"@- -> (a -> a -> a) -- ^ @\"_ || _\"@ union- -> (a -> a -> a) -- ^ @\"_ && _\"@ intersection- -> VersionRange -> a-foldVersionRange _any this later earlier union intersect = fold- where- fold = cataVersionRange alg-- alg (ThisVersionF v) = this v- alg (LaterVersionF v) = later v- alg (OrLaterVersionF v) = union (this v) (later v)- alg (EarlierVersionF v) = earlier v- alg (OrEarlierVersionF v) = union (this v) (earlier v)- alg (MajorBoundVersionF v) = fold (majorBound v)- alg (UnionVersionRangesF v1 v2) = union v1 v2- alg (IntersectVersionRangesF v1 v2) = intersect v1 v2-- majorBound v = intersectVersionRanges- (orLaterVersion v)- (earlierVersion (majorUpperBound v))---- | Normalise 'VersionRange'.------ In particular collapse @(== v || > v)@ into @>= v@, and so on.-normaliseVersionRange :: VersionRange -> VersionRange-normaliseVersionRange = hyloVersionRange embed projectVersionRange- where- -- == v || > v, > v || == v ==> >= v- embed (UnionVersionRangesF (ThisVersion v) (LaterVersion v')) | v == v' =- orLaterVersion v- embed (UnionVersionRangesF (LaterVersion v) (ThisVersion v')) | v == v' =- orLaterVersion v-- -- == v || < v, < v || == v ==> <= v- embed (UnionVersionRangesF (ThisVersion v) (EarlierVersion v')) | v == v' =- orEarlierVersion v- embed (UnionVersionRangesF (EarlierVersion v) (ThisVersion v')) | v == v' =- orEarlierVersion v-- -- otherwise embed normally- embed vr = embedVersionRange vr---- | Remove 'VersionRangeParens' constructors.------ Since version 3.4 this function is 'id', there aren't 'VersionRangeParens' constructor in 'VersionRange' anymore.------ @since 2.2-stripParensVersionRange :: VersionRange -> VersionRange-stripParensVersionRange = id---- | Does this version fall within the given range?------ This is the evaluation function for the 'VersionRange' type.----withinRange :: Version -> VersionRange -> Bool-withinRange v = foldVersionRange- True- (\v' -> v == v')- (\v' -> v > v')- (\v' -> v < v')- (||)- (&&)---- | Does this 'VersionRange' place any restriction on the 'Version' or is it--- in fact equivalent to 'AnyVersion'.------ Note this is a semantic check, not simply a syntactic check. So for example--- the following is @True@ (for all @v@).------ > isAnyVersion (EarlierVersion v `UnionVersionRanges` orLaterVersion v)----isAnyVersion :: VersionRange -> Bool-isAnyVersion vr = case asVersionIntervals vr of- [(LowerBound v InclusiveBound, NoUpperBound)] -> v == version0- _ -> False---- A fast and non-precise version of 'isAnyVersion',--- returns 'True' only for @>= 0@ 'VersionRange's.------ /Do not use/. The "VersionIntervals don't destroy MajorBoundVersion"--- https://github.com/haskell/cabal/pull/6736 pull-request--- will change 'simplifyVersionRange' to properly preserve semantics.--- Then we can use it to normalise 'VersionRange's in tests.----isAnyVersionLight :: VersionRange -> Bool-isAnyVersionLight (OrLaterVersion v) = v == version0-isAnyVersionLight _vr = False--------------------------------- Wildcard range utilities------isWildcardRange :: Version -> Version -> Bool-isWildcardRange ver1 ver2 = check (versionNumbers ver1) (versionNumbers ver2)- where check (n:[]) (m:[]) | n+1 == m = True- check (n:ns) (m:ms) | n == m = check ns ms- check _ _ = False---- | 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)- (&&) (||)
− Distribution/Types/VersionRange/Internal.hs
@@ -1,526 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}---- | The only purpose of this module is to prevent the export of--- 'VersionRange' constructors from--- 'Distribution.Types.VersionRange'. To avoid creating orphan--- instances, a lot of related code had to be moved here too.--module Distribution.Types.VersionRange.Internal- ( VersionRange(..)- , anyVersion, noVersion- , thisVersion, notThisVersion- , laterVersion, earlierVersion- , orLaterVersion, orEarlierVersion- , unionVersionRanges, intersectVersionRanges- , withinVersion- , majorBoundVersion-- , VersionRangeF(..)- , projectVersionRange- , embedVersionRange- , cataVersionRange- , anaVersionRange- , hyloVersionRange- , versionRangeParser-- , majorUpperBound- , wildcardUpperBound- ) where--import Distribution.Compat.Prelude-import Distribution.Types.Version-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Utils.Generic (unsnoc)--import qualified Distribution.Compat.CharParsing as P-import qualified Distribution.Compat.DList as DList-import qualified Text.PrettyPrint as Disp--data VersionRange- = ThisVersion Version -- = version- | LaterVersion Version -- > version (NB. not >=)- | OrLaterVersion Version -- >= version- | EarlierVersion Version -- < version- | OrEarlierVersion Version -- <= version- | MajorBoundVersion Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1)- | UnionVersionRanges VersionRange VersionRange- | IntersectVersionRanges VersionRange VersionRange- deriving ( Data, Eq, Generic, Read, Show, Typeable )--instance Binary VersionRange-instance Structured VersionRange-instance NFData VersionRange where rnf = genericRnf---- | The version range @-any@. That is, a version range containing all--- versions.------ > withinRange v anyVersion = True----anyVersion :: VersionRange-anyVersion = OrLaterVersion (mkVersion [0])---- | The empty version range, that is a version range containing no versions.------ This can be constructed using any unsatisfiable version range expression,--- for example @< 0@.------ > withinRange v noVersion = False----noVersion :: VersionRange-noVersion = EarlierVersion (mkVersion [0])---- | The version range @== v@------ > withinRange v' (thisVersion v) = v' == v----thisVersion :: Version -> VersionRange-thisVersion = ThisVersion---- | The version range @< v || > v@------ > withinRange v' (notThisVersion v) = v' /= v----notThisVersion :: Version -> VersionRange-notThisVersion v = UnionVersionRanges (EarlierVersion v) (LaterVersion v)---- | The version range @> v@------ > withinRange v' (laterVersion v) = v' > v----laterVersion :: Version -> VersionRange-laterVersion = LaterVersion---- | The version range @>= v@------ > withinRange v' (orLaterVersion v) = v' >= v----orLaterVersion :: Version -> VersionRange-orLaterVersion = OrLaterVersion---- | The version range @< v@------ > withinRange v' (earlierVersion v) = v' < v----earlierVersion :: Version -> VersionRange-earlierVersion = EarlierVersion---- | The version range @<= v@------ > withinRange v' (orEarlierVersion v) = v' <= v----orEarlierVersion :: Version -> VersionRange-orEarlierVersion = OrEarlierVersion---- | The version range @vr1 || vr2@------ > withinRange v' (unionVersionRanges vr1 vr2)--- > = withinRange v' vr1 || withinRange v' vr2----unionVersionRanges :: VersionRange -> VersionRange -> VersionRange-unionVersionRanges = UnionVersionRanges---- | The version range @vr1 && vr2@------ > withinRange v' (intersectVersionRanges vr1 vr2)--- > = withinRange v' vr1 && withinRange v' vr2----intersectVersionRanges :: VersionRange -> VersionRange -> VersionRange-intersectVersionRanges = IntersectVersionRanges---- | The version range @== v.*@.------ For example, for version @1.2@, the version range @== 1.2.*@ is the same as--- @>= 1.2 && < 1.3@------ > withinRange v' (laterVersion v) = v' >= v && v' < upper v--- > where--- > upper (Version lower t) = Version (init lower ++ [last lower + 1]) t----withinVersion :: Version -> VersionRange-withinVersion v = intersectVersionRanges- (orLaterVersion v)- (earlierVersion (wildcardUpperBound v))---- | The version range @^>= v@.------ For example, for version @1.2.3.4@, the version range @^>= 1.2.3.4@--- is the same as @>= 1.2.3.4 && < 1.3@.------ Note that @^>= 1@ is equivalent to @>= 1 && < 1.1@.------ @since 2.0.0.2-majorBoundVersion :: Version -> VersionRange-majorBoundVersion = MajorBoundVersion----- | F-Algebra of 'VersionRange'. See 'cataVersionRange'.------ @since 2.2-data VersionRangeF a- = ThisVersionF Version -- = version- | LaterVersionF Version -- > version (NB. not >=)- | OrLaterVersionF Version -- >= version- | EarlierVersionF Version -- < version- | OrEarlierVersionF Version -- <= version- | MajorBoundVersionF Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1)- | UnionVersionRangesF a a- | IntersectVersionRangesF a a- deriving ( Data, Eq, Generic, Read, Show, Typeable- , Functor, Foldable, Traversable )---- | @since 2.2-projectVersionRange :: VersionRange -> VersionRangeF VersionRange-projectVersionRange (ThisVersion v) = ThisVersionF v-projectVersionRange (LaterVersion v) = LaterVersionF v-projectVersionRange (OrLaterVersion v) = OrLaterVersionF v-projectVersionRange (EarlierVersion v) = EarlierVersionF v-projectVersionRange (OrEarlierVersion v) = OrEarlierVersionF v-projectVersionRange (MajorBoundVersion v) = MajorBoundVersionF v-projectVersionRange (UnionVersionRanges a b) = UnionVersionRangesF a b-projectVersionRange (IntersectVersionRanges a b) = IntersectVersionRangesF a b---- | Fold 'VersionRange'.------ @since 2.2-cataVersionRange :: (VersionRangeF a -> a) -> VersionRange -> a-cataVersionRange f = c where c = f . fmap c . projectVersionRange---- | @since 2.2-embedVersionRange :: VersionRangeF VersionRange -> VersionRange-embedVersionRange (ThisVersionF v) = ThisVersion v-embedVersionRange (LaterVersionF v) = LaterVersion v-embedVersionRange (OrLaterVersionF v) = OrLaterVersion v-embedVersionRange (EarlierVersionF v) = EarlierVersion v-embedVersionRange (OrEarlierVersionF v) = OrEarlierVersion v-embedVersionRange (MajorBoundVersionF v) = MajorBoundVersion v-embedVersionRange (UnionVersionRangesF a b) = UnionVersionRanges a b-embedVersionRange (IntersectVersionRangesF a b) = IntersectVersionRanges a b---- | Unfold 'VersionRange'.------ @since 2.2-anaVersionRange :: (a -> VersionRangeF a) -> a -> VersionRange-anaVersionRange g = a where a = embedVersionRange . fmap a . g---- | Refold 'VersionRange'------ @since 2.2-hyloVersionRange :: (VersionRangeF VersionRange -> VersionRange)- -> (VersionRange -> VersionRangeF VersionRange)- -> VersionRange -> VersionRange-hyloVersionRange f g = h where h = f . fmap h . g------------------------------------------------------------------------------------ Parsec & Pretty------------------------------------------------------------------------------------ |------ >>> fmap pretty (simpleParsec' CabalSpecV1_6 "== 3.2.*" :: Maybe VersionRange)--- Just >=3.2 && <3.3------ >>> fmap (prettyVersioned CabalSpecV1_6) (simpleParsec' CabalSpecV1_6 "== 3.2.*" :: Maybe VersionRange)--- Just ==3.2.*------ >>> fmap pretty (simpleParsec' CabalSpecV1_6 "-any" :: Maybe VersionRange)--- Just >=0------ >>> fmap (prettyVersioned CabalSpecV1_6) (simpleParsec' CabalSpecV1_6 "-any" :: Maybe VersionRange)--- Just >=0----instance Pretty VersionRange where- pretty = prettyVersioned cabalSpecLatest-- prettyVersioned csv- | csv > CabalSpecV1_6 = prettyVersionRange- | otherwise = prettyVersionRange16--prettyVersionRange :: VersionRange -> Disp.Doc-prettyVersionRange vr = cataVersionRange alg vr 0- where- alg :: VersionRangeF (Int -> Disp.Doc) -> Int -> Disp.Doc- alg (ThisVersionF v) _ = Disp.text "==" <<>> pretty v- alg (LaterVersionF v) _ = Disp.text ">" <<>> pretty v- alg (OrLaterVersionF v) _ = Disp.text ">=" <<>> pretty v- alg (EarlierVersionF v) _ = Disp.text "<" <<>> pretty v- alg (OrEarlierVersionF v) _ = Disp.text "<=" <<>> pretty v- alg (MajorBoundVersionF v) _ = Disp.text "^>=" <<>> pretty v- alg (UnionVersionRangesF r1 r2) d = parens (d > 0)- $ r1 1 <+> Disp.text "||" <+> r2 0- alg (IntersectVersionRangesF r1 r2) d = parens (d > 1)- $ r1 2 <+> Disp.text "&&" <+> r2 1-- parens True = Disp.parens- parens False = id---- | Don't use && and || operators. If possible.-prettyVersionRange16 :: VersionRange -> Disp.Doc-prettyVersionRange16 (IntersectVersionRanges (OrLaterVersion v) (EarlierVersion u))- | u == wildcardUpperBound v- = Disp.text "==" <<>> dispWild v- where- dispWild ver =- Disp.hcat (Disp.punctuate (Disp.char '.')- (map Disp.int $ versionNumbers ver))- <<>> Disp.text ".*"--prettyVersionRange16 vr = prettyVersionRange vr---- |------ >>> simpleParsec "^>= 3.4" :: Maybe VersionRange--- Just (MajorBoundVersion (mkVersion [3,4]))------ Small history:------ @-any@ and @-none@ removed in 3.4--- Use @>=0@ and @<0@ instead.------ >>> map (`simpleParsec'` "-none") [CabalSpecV3_0, CabalSpecV3_4] :: [Maybe VersionRange]--- [Just (EarlierVersion (mkVersion [0])),Nothing]------ Set operations are introduced in 3.0------ >>> map (`simpleParsec'` "^>= { 1.2 , 1.3 }") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe VersionRange]--- [Nothing,Just (UnionVersionRanges (MajorBoundVersion (mkVersion [1,2])) (MajorBoundVersion (mkVersion [1,3])))]------ @^>=@ is introduced in 2.0------ >>> map (`simpleParsec'` "^>=1.2") [CabalSpecV1_24, CabalSpecV2_0] :: [Maybe VersionRange]--- [Nothing,Just (MajorBoundVersion (mkVersion [1,2]))]------ @-none@ is introduced in 1.22------ >>> map (`simpleParsec'` "-none") [CabalSpecV1_20, CabalSpecV1_22] :: [Maybe VersionRange]--- [Nothing,Just (EarlierVersion (mkVersion [0]))]------ Operators are introduced in 1.8. Issues only a warning.------ >>> map (`simpleParsecW'` "== 1 || ==2") [CabalSpecV1_6, CabalSpecV1_8] :: [Maybe VersionRange]--- [Nothing,Just (UnionVersionRanges (ThisVersion (mkVersion [1])) (ThisVersion (mkVersion [2])))]------ Wild-version ranges are introduced in 1.6. Issues only a warning.------ >>> map (`simpleParsecW'` "== 1.2.*") [CabalSpecV1_4, CabalSpecV1_6] :: [Maybe VersionRange]--- [Nothing,Just (IntersectVersionRanges (OrLaterVersion (mkVersion [1,2])) (EarlierVersion (mkVersion [1,3])))]----instance Parsec VersionRange where- parsec = askCabalSpecVersion >>= versionRangeParser versionDigitParser---- | 'VersionRange' parser parametrised by version digit parser------ - 'versionDigitParser' is used for all 'VersionRange'.--- - 'P.integral' is used for backward-compat @pkgconfig-depends@--- versions, 'PkgConfigVersionRange'.------ @since 3.0-versionRangeParser :: forall m. CabalParsing m => m Int -> CabalSpecVersion -> m VersionRange-versionRangeParser digitParser csv = expr- where- expr = do P.spaces- t <- term- P.spaces- (do _ <- P.string "||"- checkOp- P.spaces- e <- expr- return (unionVersionRanges t e)- <|>- return t)- term = do f <- factor- P.spaces- (do _ <- P.string "&&"- checkOp- P.spaces- t <- term- return (intersectVersionRanges f t)- <|>- return f)- factor = parens expr <|> prim-- prim = do- op <- P.munch1 isOpChar P.<?> "operator"- case op of- "-" -> anyVersion <$ P.string "any" <|> P.string "none" *> noVersion'-- "==" -> do- P.spaces- (do (wild, v) <- verOrWild- checkWild wild- pure $ (if wild then withinVersion else thisVersion) v- <|>- (verSet' thisVersion =<< verSet))-- "^>=" -> do- P.spaces- (do (wild, v) <- verOrWild- when wild $ P.unexpected $- "wild-card version after ^>= operator"- majorBoundVersion' v- <|>- (verSet' majorBoundVersion =<< verSet))-- _ -> do- P.spaces- (wild, v) <- verOrWild- when wild $ P.unexpected $- "wild-card version after non-== operator: " ++ show op- case op of- ">=" -> pure $ orLaterVersion v- "<" -> pure $ earlierVersion v- "<=" -> pure $ orEarlierVersion v- ">" -> pure $ laterVersion v- _ -> fail $ "Unknown version operator " ++ show op-- -- Cannot be warning- -- On 2020-03-16 there was around 27400 files on Hackage failing to parse due this- -- For example https://hackage.haskell.org/package/haxr-3000.0.0/haxr.cabal- --- checkOp = when (csv < CabalSpecV1_8) $- parsecWarning PWTVersionOperator $ unwords- [ "version operators used."- , "To use version operators the package needs to specify at least 'cabal-version: >= 1.8'."- ]-- -- Cannot be warning- -- On 2020-03-16 there was 46 files on Hackage failing to parse due this- -- For example https://hackage.haskell.org/package/derive-0.1.2/derive.cabal- --- checkWild False = pure ()- checkWild True = when (csv < CabalSpecV1_6) $- parsecWarning PWTVersionWildcard $ unwords- [ "Wildcard syntax used."- , "To use version wildcards the package needs to specify at least 'cabal-version: >= 1.6'."- ]-- -- https://gitlab.haskell.org/ghc/ghc/issues/17752- isOpChar '<' = True- isOpChar '=' = True- isOpChar '>' = True- isOpChar '^' = True- isOpChar '-' = csv < CabalSpecV3_4- -- https://github.com/haskell/cabal/issues/6589- -- Unfortunately we have must not consume the dash,- -- as otherwise following parts may not be parsed.- --- -- i.e. we cannot fail here with good error.- isOpChar _ = False-- -- -none version range is available since 1.22- noVersion' =- if csv >= CabalSpecV1_22- then pure noVersion- else fail $ unwords- [ "-none version range used."- , "To use this syntax the package needs to specify at least 'cabal-version: 1.22'."- , "Alternatively, if broader compatibility is important then use"- , "<0 or other empty range."- ]-- -- ^>= is available since 2.0- majorBoundVersion' v =- if csv >= CabalSpecV2_0- then pure $ majorBoundVersion v- else fail $ unwords- [ "major bounded version syntax (caret, ^>=) used."- , "To use this syntax the package need to specify at least 'cabal-version: 2.0'."- , "Alternatively, if broader compatibility is important then use:"- , prettyShow $ eliminateMajorBoundSyntax $ majorBoundVersion v- ]- where- eliminateMajorBoundSyntax = hyloVersionRange embed projectVersionRange- embed (MajorBoundVersionF u) = intersectVersionRanges- (orLaterVersion u) (earlierVersion (majorUpperBound u))- embed vr = embedVersionRange vr-- -- version set notation (e.g. "== { 0.0.1.0, 0.0.2.0, 0.1.0.0 }")- verSet' op vs =- if csv >= CabalSpecV3_0- then pure $ foldr1 unionVersionRanges (fmap op vs)- else fail $ unwords- [ "version set syntax used."- , "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."- , "Alternatively, if broader compatibility is important then use"- , "a series of single version constraints joined with the || operator:"- , prettyShow (foldr1 unionVersionRanges (fmap op vs))- ]-- verSet :: CabalParsing m => m (NonEmpty Version)- verSet = do- _ <- P.char '{'- P.spaces- vs <- P.sepByNonEmpty (verPlain <* P.spaces) (P.char ',' *> P.spaces)- _ <- P.char '}'- pure vs-- -- a plain version without tags or wildcards- verPlain :: CabalParsing m => m Version- verPlain = mkVersion <$> toList <$> P.sepByNonEmpty digitParser (P.char '.')-- -- either wildcard or normal version- verOrWild :: CabalParsing m => m (Bool, Version)- verOrWild = do- x <- digitParser- verLoop (DList.singleton x)-- -- trailing: wildcard (.y.*) or normal version (optional tags) (.y.z-tag)- verLoop :: CabalParsing m => DList.DList Int -> m (Bool, Version)- verLoop acc = verLoop' acc- <|> (tags *> pure (False, mkVersion (DList.toList acc)))-- verLoop' :: CabalParsing m => DList.DList Int -> m (Bool, Version)- verLoop' acc = do- _ <- P.char '.'- let digit = digitParser >>= verLoop . DList.snoc acc- let wild = (True, mkVersion (DList.toList acc)) <$ P.char '*'- digit <|> wild-- parens p = P.between- ((P.char '(' P.<?> "opening paren") >> P.spaces)- (P.char ')' >> P.spaces)- $ do- a <- p- P.spaces- return a-- tags :: CabalParsing m => m ()- tags = do- ts <- many $ P.char '-' *> some (P.satisfy isAlphaNum)- case ts of- [] -> pure ()- (_ : _) -> parsecWarning PWTVersionTag "version with tags"---------------------------------- Wildcard range utilities------- | Compute next greater major version to be used as upper bound------ Example: @0.4.1@ produces the version @0.5@ which then can be used--- to construct a range @>= 0.4.1 && < 0.5@------ @since 2.2-majorUpperBound :: Version -> Version-majorUpperBound = alterVersion $ \numbers -> case numbers of- [] -> [0,1] -- should not happen- [m1] -> [m1,1] -- e.g. version '1'- (m1:m2:_) -> [m1,m2+1]---- | @since 2.2-wildcardUpperBound :: Version -> Version-wildcardUpperBound = alterVersion $- \lowerBound -> case unsnoc lowerBound of- Nothing -> []- Just (xs, x) -> xs ++ [x + 1]
− Distribution/Utils/Base62.hs
@@ -1,22 +0,0 @@---- | Implementation of base-62 encoding, which we use when computing hashes--- for fully instantiated unit ids.-module Distribution.Utils.Base62 (hashToBase62) where--import GHC.Fingerprint ( Fingerprint(..), fingerprintString )-import Numeric ( showIntAtBase )-import Data.Char ( chr )---- | Hash a string using GHC's fingerprinting algorithm (a 128-bit--- MD5 hash) and then encode the resulting hash in base 62.-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-
− Distribution/Utils/Generic.hs
@@ -1,576 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE BangPatterns #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Simple.Utils--- Copyright : Isaac Jones, Simon Marlow 2003-2004--- License : BSD3--- portions Copyright (c) 2007, Galois Inc.------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ A large and somewhat miscellaneous collection of utility functions used--- throughout the rest of the Cabal lib and in other tools that use the Cabal--- lib like @cabal-install@. It has a very simple set of logging actions. It--- has low level functions for running programs, a bunch of wrappers for--- various directory and file functions that do extra logging.--module Distribution.Utils.Generic (- -- * reading and writing files safely- withFileContents,- writeFileAtomic,-- -- * Unicode-- -- ** Conversions- fromUTF8BS,- fromUTF8LBS,-- toUTF8BS,- toUTF8LBS,-- validateUTF8,-- -- ** File I/O- readUTF8File,- withUTF8FileContents,- writeUTF8File,-- -- ** BOM- ignoreBOM,-- -- ** Misc- normaliseLineEndings,-- -- * generic utils- dropWhileEndLE,- takeWhileEndLE,- equating,- comparing,- isInfixOf,- intercalate,- lowercase,- isAscii,- isAsciiAlpha,- isAsciiAlphaNum,- listUnion,- listUnionRight,- ordNub,- ordNubBy,- ordNubRight,- safeHead,- safeTail,- safeLast,- safeInit,- unintersperse,- wrapText,- wrapLine,- unfoldrM,- spanMaybe,- breakMaybe,- unsnoc,- unsnocNE,-- -- * Triples- fstOf3,- sndOf3,- trdOf3,-- -- * FilePath stuff- isAbsoluteOnAnyPlatform,- isRelativeOnAnyPlatform,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Utils.String--import Data.Bits ((.&.), (.|.), shiftL)-import Data.List- ( isInfixOf )-import qualified Data.Set as Set-import qualified Data.ByteString as SBS-import qualified Data.ByteString.Lazy as LBS--import System.Directory- ( removeFile, renameFile )-import System.FilePath- ( (<.>), splitFileName )-import System.IO- ( withFile, withBinaryFile- , openBinaryTempFileWithDefaultPermissions- , IOMode(ReadMode), hGetContents, hClose )-import qualified Control.Exception as Exception---- -------------------------------------------------------------------------------- Helper functions---- | Wraps text to the default line width. Existing newlines are preserved.-wrapText :: String -> String-wrapText = unlines- . map (intercalate "\n"- . map unwords- . wrapLine 79- . words)- . lines---- | Wraps a list of words to a list of lines of words of a particular width.-wrapLine :: Int -> [String] -> [[String]]-wrapLine width = wrap 0 []- where wrap :: Int -> [String] -> [String] -> [[String]]- wrap 0 [] (w:ws)- | length w + 1 > width- = wrap (length w) [w] ws- wrap col line (w:ws)- | col + length w + 1 > width- = reverse line : wrap 0 [] (w:ws)- wrap col line (w:ws)- = let col' = col + length w + 1- in wrap col' (w:line) ws- wrap _ [] [] = []- wrap _ line [] = [reverse line]---------------------------------------- Safely reading and writing files---- | Gets the contents of a file, but guarantee that it gets closed.------ The file is read lazily but if it is not fully consumed by the action then--- the remaining input is truncated and the file is closed.----withFileContents :: FilePath -> (String -> IO a) -> IO a-withFileContents name action =- withFile name ReadMode- (\hnd -> hGetContents hnd >>= action)---- | Writes a file atomically.------ The file is either written successfully or an IO exception is raised and--- the original file is left unchanged.------ On windows it is not possible to delete a file that is open by a process.--- This case will give an IO exception but the atomic property is not affected.----writeFileAtomic :: FilePath -> LBS.ByteString -> IO ()-writeFileAtomic targetPath content = do- let (targetDir, targetFile) = splitFileName targetPath- Exception.bracketOnError- (openBinaryTempFileWithDefaultPermissions targetDir $ targetFile <.> "tmp")- (\(tmpPath, handle) -> hClose handle >> removeFile tmpPath)- (\(tmpPath, handle) -> do- LBS.hPut handle content- hClose handle- renameFile tmpPath targetPath)---- --------------------------------------------------------------- * Unicode stuff--- ---------------------------------------------------------------- | Decode 'String' from UTF8-encoded 'BS.ByteString'------ Invalid data in the UTF8 stream (this includes code-points @U+D800@--- through @U+DFFF@) will be decoded as the replacement character (@U+FFFD@).----fromUTF8BS :: SBS.ByteString -> String-fromUTF8BS = decodeStringUtf8 . SBS.unpack---- | Variant of 'fromUTF8BS' for lazy 'BS.ByteString's----fromUTF8LBS :: LBS.ByteString -> String-fromUTF8LBS = decodeStringUtf8 . LBS.unpack---- | Encode 'String' to UTF8-encoded 'SBS.ByteString'------ Code-points in the @U+D800@-@U+DFFF@ range will be encoded--- as the replacement character (i.e. @U+FFFD@).----toUTF8BS :: String -> SBS.ByteString-toUTF8BS = SBS.pack . encodeStringUtf8---- | Variant of 'toUTF8BS' for lazy 'BS.ByteString's----toUTF8LBS :: String -> LBS.ByteString-toUTF8LBS = LBS.pack . encodeStringUtf8---- | Check that strict 'ByteString' is valid UTF8. Returns 'Just offset' if it's not.-validateUTF8 :: SBS.ByteString -> Maybe Int-validateUTF8 = go 0 where- go off bs = case SBS.uncons bs of- Nothing -> Nothing- Just (c, bs')- | c <= 0x7F -> go (off + 1) bs'- | c <= 0xBF -> Just off- | c <= 0xDF -> twoBytes off c bs'- | c <= 0xEF -> moreBytes off 3 0x800 bs' (fromIntegral $ c .&. 0xF)- | c <= 0xF7 -> moreBytes off 4 0x10000 bs' (fromIntegral $ c .&. 0x7)- | c <= 0xFB -> moreBytes off 5 0x200000 bs' (fromIntegral $ c .&. 0x3)- | c <= 0xFD -> moreBytes off 6 0x4000000 bs' (fromIntegral $ c .&. 0x1)- | otherwise -> Just off-- twoBytes off c0 bs = case SBS.uncons bs of- Nothing -> Just off- Just (c1, bs')- | c1 .&. 0xC0 == 0x80 ->- if d >= (0x80 :: Int)- then go (off + 2) bs'- else Just off- | otherwise -> Just off- where- d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6) .|. fromIntegral (c1 .&. 0x3F)-- moreBytes :: Int -> Int -> Int -> SBS.ByteString -> Int -> Maybe Int- moreBytes off 1 overlong cs' acc- | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc- = go (off + 1) cs'-- | otherwise- = Just off-- moreBytes off byteCount overlong bs acc = case SBS.uncons bs of- Just (cn, bs') | cn .&. 0xC0 == 0x80 ->- moreBytes (off + 1) (byteCount-1) overlong bs' ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)- _ -> Just off- ---- | Ignore a Unicode byte order mark (BOM) at the beginning of the input----ignoreBOM :: String -> String-ignoreBOM ('\xFEFF':string) = string-ignoreBOM string = string---- | Reads a UTF8 encoded text file as a Unicode String------ Reads lazily using ordinary 'readFile'.----readUTF8File :: FilePath -> IO String-readUTF8File f = (ignoreBOM . fromUTF8LBS) <$> LBS.readFile f---- | Reads a UTF8 encoded text file as a Unicode String------ Same behaviour as 'withFileContents'.----withUTF8FileContents :: FilePath -> (String -> IO a) -> IO a-withUTF8FileContents name action =- withBinaryFile name ReadMode- (\hnd -> LBS.hGetContents hnd >>= action . ignoreBOM . fromUTF8LBS)---- | Writes a Unicode String as a UTF8 encoded text file.------ Uses 'writeFileAtomic', so provides the same guarantees.----writeUTF8File :: FilePath -> String -> IO ()-writeUTF8File path = writeFileAtomic path . toUTF8LBS---- | Fix different systems silly line ending conventions-normaliseLineEndings :: String -> String-normaliseLineEndings [] = []-normaliseLineEndings ('\r':'\n':s) = '\n' : normaliseLineEndings s -- windows-normaliseLineEndings ('\r':s) = '\n' : normaliseLineEndings s -- old OS X-normaliseLineEndings ( c :s) = c : normaliseLineEndings s---- --------------------------------------------------------------- * Common utils--- ---------------------------------------------------------------- | @dropWhileEndLE p@ is equivalent to @reverse . dropWhile p . reverse@, but--- quite a bit faster. The difference between "Data.List.dropWhileEnd" and this--- version is that the one in "Data.List" is strict in elements, but spine-lazy,--- while this one is spine-strict but lazy in elements. That's what @LE@ stands--- for - "lazy in elements".------ Example:------ >>> safeTail $ Data.List.dropWhileEnd (<3) [undefined, 5, 4, 3, 2, 1]--- *** Exception: Prelude.undefined--- ...------ >>> safeTail $ dropWhileEndLE (<3) [undefined, 5, 4, 3, 2, 1]--- [5,4,3]------ >>> take 3 $ Data.List.dropWhileEnd (<3) [5, 4, 3, 2, 1, undefined]--- [5,4,3]------ >>> take 3 $ dropWhileEndLE (<3) [5, 4, 3, 2, 1, undefined]--- *** Exception: Prelude.undefined--- ...----dropWhileEndLE :: (a -> Bool) -> [a] -> [a]-dropWhileEndLE p = foldr (\x r -> if null r && p x then [] else x:r) []---- | @takeWhileEndLE p@ is equivalent to @reverse . takeWhile p . reverse@, but--- is usually faster (as well as being easier to read).-takeWhileEndLE :: (a -> Bool) -> [a] -> [a]-takeWhileEndLE p = fst . foldr go ([], False)- where- go x (rest, done)- | not done && p x = (x:rest, False)- | otherwise = (rest, True)---- | Like 'Data.List.nub', but has @O(n log n)@ complexity instead of--- @O(n^2)@. Code for 'ordNub' and 'listUnion' taken from Niklas Hambüchen's--- <http://github.com/nh2/haskell-ordnub ordnub> package.-ordNub :: Ord a => [a] -> [a]-ordNub = ordNubBy id---- | Like 'ordNub' and 'Data.List.nubBy'. Selects a key for each element and--- takes the nub based on that key.-ordNubBy :: Ord b => (a -> b) -> [a] -> [a]-ordNubBy f l = go Set.empty l- where- go !_ [] = []- go !s (x:xs)- | y `Set.member` s = go s xs- | otherwise = let !s' = Set.insert y s- in x : go s' xs- where- y = f x---- | Like "Data.List.union", but has @O(n log n)@ complexity instead of--- @O(n^2)@.-listUnion :: (Ord a) => [a] -> [a] -> [a]-listUnion a b = a ++ ordNub (filter (`Set.notMember` aSet) b)- where- aSet = Set.fromList a---- | A right-biased version of 'ordNub'.------ Example:------ >>> ordNub [1,2,1] :: [Int]--- [1,2]------ >>> ordNubRight [1,2,1] :: [Int]--- [2,1]----ordNubRight :: (Ord a) => [a] -> [a]-ordNubRight = fst . foldr go ([], Set.empty)- where- go x p@(l, s) = if x `Set.member` s then p- else (x:l, Set.insert x s)---- | A right-biased version of 'listUnion'.------ Example:------ >>> listUnion [1,2,3,4,3] [2,1,1]--- [1,2,3,4,3]------ >>> listUnionRight [1,2,3,4,3] [2,1,1]--- [4,3,2,1,1]----listUnionRight :: (Ord a) => [a] -> [a] -> [a]-listUnionRight a b = ordNubRight (filter (`Set.notMember` bSet) a) ++ b- where- bSet = Set.fromList b---- | A total variant of 'head'.------ @since 3.2.0.0-safeHead :: [a] -> Maybe a-safeHead [] = Nothing-safeHead (x:_) = Just x---- | A total variant of 'tail'.------ @since 3.2.0.0-safeTail :: [a] -> [a]-safeTail [] = []-safeTail (_:xs) = xs---- | A total variant of 'last'.------ @since 3.2.0.0-safeLast :: [a] -> Maybe a-safeLast [] = Nothing-safeLast (x:xs) = Just (foldl (\_ a -> a) x xs)---- | A total variant of 'init'.------ @since 3.2.0.0-safeInit :: [a] -> [a]-safeInit [] = []-safeInit [_] = []-safeInit (x:xs) = x : safeInit xs--equating :: Eq a => (b -> a) -> b -> b -> Bool-equating p x y = p x == p y---- | Lower case string------ >>> lowercase "Foobar"--- "foobar"-lowercase :: String -> String-lowercase = map toLower---- | Ascii characters-isAscii :: Char -> Bool-isAscii c = fromEnum c < 0x80---- | Ascii letters.-isAsciiAlpha :: Char -> Bool-isAsciiAlpha c = ('a' <= c && c <= 'z')- || ('A' <= c && c <= 'Z')---- | Ascii letters and digits.------ >>> isAsciiAlphaNum 'a'--- True------ >>> isAsciiAlphaNum 'ä'--- False----isAsciiAlphaNum :: Char -> Bool-isAsciiAlphaNum c = isAscii c && isAlphaNum c--unintersperse :: Char -> String -> [String]-unintersperse mark = unfoldr unintersperse1 where- unintersperse1 str- | null str = Nothing- | otherwise =- let (this, rest) = break (== mark) str in- Just (this, safeTail rest)---- | Like 'break', but with 'Maybe' predicate------ >>> breakMaybe (readMaybe :: String -> Maybe Int) ["foo", "bar", "1", "2", "quu"]--- (["foo","bar"],Just (1,["2","quu"]))------ >>> breakMaybe (readMaybe :: String -> Maybe Int) ["foo", "bar"]--- (["foo","bar"],Nothing)------ @since 2.2----breakMaybe :: (a -> Maybe b) -> [a] -> ([a], Maybe (b, [a]))-breakMaybe f = go id where- go !acc [] = (acc [], Nothing)- go !acc (x:xs) = case f x of- Nothing -> go (acc . (x:)) xs- Just b -> (acc [], Just (b, xs))---- | Like 'span' but with 'Maybe' predicate------ >>> spanMaybe listToMaybe [[1,2],[3],[],[4,5],[6,7]]--- ([1,3],[[],[4,5],[6,7]])------ >>> spanMaybe (readMaybe :: String -> Maybe Int) ["1", "2", "foo"]--- ([1,2],["foo"])------ @since 2.2----spanMaybe :: (a -> Maybe b) -> [a] -> ([b],[a])-spanMaybe _ xs@[] = ([], xs)-spanMaybe p xs@(x:xs') = case p x of- Just y -> let (ys, zs) = spanMaybe p xs' in (y : ys, zs)- Nothing -> ([], xs)---- | 'unfoldr' with monadic action.------ >>> take 5 $ unfoldrM (\b r -> Just (r + b, b + 1)) (1 :: Int) 2--- [3,4,5,6,7]------ @since 2.2----unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> m [a]-unfoldrM f = go where- go b = do- m <- f b- case m of- Nothing -> return []- Just (a, b') -> liftM (a :) (go b')---- | The opposite of 'snoc', which is the reverse of 'cons'------ Example:------ >>> unsnoc [1, 2, 3]--- Just ([1,2],3)------ >>> unsnoc []--- Nothing------ @since 3.2.0.0----unsnoc :: [a] -> Maybe ([a], a)-unsnoc [] = Nothing-unsnoc (x:xs) = Just (unsnocNE (x :| xs))---- | Like 'unsnoc', but for 'NonEmpty' so without the 'Maybe'------ Example:------ >>> unsnocNE (1 :| [2, 3])--- ([1,2],3)------ >>> unsnocNE (1 :| [])--- ([],1)------ @since 3.2.0.0----unsnocNE :: NonEmpty a -> ([a], a)-unsnocNE (x:|xs) = go x xs where- go y [] = ([], y)- go y (z:zs) = let ~(ws, w) = go z zs in (y : ws, w)------------------------------------------------------------------------------------ Triples------------------------------------------------------------------------------------ | @since 3.4.0.0-fstOf3 :: (a,b,c) -> a-fstOf3 (a,_,_) = a---- | @since 3.4.0.0-sndOf3 :: (a,b,c) -> b-sndOf3 (_,b,_) = b---- | @since 3.4.0.0-trdOf3 :: (a,b,c) -> c-trdOf3 (_,_,c) = c---- --------------------------------------------------------------- * FilePath stuff--- ---------------------------------------------------------------- | 'isAbsoluteOnAnyPlatform' and 'isRelativeOnAnyPlatform' are like--- 'System.FilePath.isAbsolute' and 'System.FilePath.isRelative' but have--- platform independent heuristics.--- The System.FilePath exists in two versions, Windows and Posix. The two--- versions don't agree on what is a relative path and we don't know if we're--- given Windows or Posix paths.--- This results in false positives when running on Posix and inspecting--- Windows paths, like the hackage server does.--- System.FilePath.Posix.isAbsolute \"C:\\hello\" == False--- System.FilePath.Windows.isAbsolute \"/hello\" == False--- This means that we would treat paths that start with \"/\" to be absolute.--- On Posix they are indeed absolute, while on Windows they are not.------ The portable versions should be used when we might deal with paths that--- are from another OS than the host OS. For example, the Hackage Server--- deals with both Windows and Posix paths while performing the--- PackageDescription checks. In contrast, when we run 'cabal configure' we--- do expect the paths to be correct for our OS and we should not have to use--- the platform independent heuristics.-isAbsoluteOnAnyPlatform :: FilePath -> Bool--- C:\\directory-isAbsoluteOnAnyPlatform (drive:':':'\\':_) = isAlpha drive-isAbsoluteOnAnyPlatform (drive:':':'/':_) = isAlpha drive--- UNC-isAbsoluteOnAnyPlatform ('\\':'\\':_) = True--- Posix root-isAbsoluteOnAnyPlatform ('/':_) = True-isAbsoluteOnAnyPlatform _ = False---- | @isRelativeOnAnyPlatform = not . 'isAbsoluteOnAnyPlatform'@-isRelativeOnAnyPlatform :: FilePath -> Bool-isRelativeOnAnyPlatform = not . isAbsoluteOnAnyPlatform---- $setup--- >>> import Data.Maybe--- >>> import Text.Read
− Distribution/Utils/IOData.hs
@@ -1,92 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE RankNTypes #-}--- | @since 2.2.0-module Distribution.Utils.IOData- ( -- * 'IOData' & 'IODataMode' type- IOData (..)- , IODataMode (..)- , KnownIODataMode (..)- , withIOData- , null- , hPutContents- ) where--import qualified Data.ByteString.Lazy as LBS-import Distribution.Compat.Prelude hiding (null)-import qualified Prelude-import qualified System.IO---- | Represents either textual or binary data passed via I/O functions--- which support binary/text mode------ @since 2.2-data IOData- = IODataText String- -- ^ How Text gets encoded is usually locale-dependent.- | IODataBinary LBS.ByteString- -- ^ Raw binary which gets read/written in binary mode.--withIOData :: IOData -> (forall mode. IODataMode mode -> mode -> r) -> r-withIOData (IODataText str) k = k IODataModeText str-withIOData (IODataBinary lbs) k = k IODataModeBinary lbs---- | Test whether 'IOData' is empty-null :: IOData -> Bool-null (IODataText s) = Prelude.null s-null (IODataBinary b) = LBS.null b--instance NFData IOData where- rnf (IODataText s) = rnf s- rnf (IODataBinary lbs) = rnf lbs---- | @since 2.2-class NFData mode => KnownIODataMode mode where- -- | 'IOData' Wrapper for 'System.IO.hGetContents'- --- -- __Note__: This operation uses lazy I/O. Use 'NFData' to force all- -- data to be read and consequently the internal file handle to be- -- closed.- --- hGetIODataContents :: System.IO.Handle -> Prelude.IO mode-- toIOData :: mode -> IOData- iodataMode :: IODataMode mode---- | @since 3.2-data IODataMode mode where- IODataModeText :: IODataMode String- IODataModeBinary :: IODataMode LBS.ByteString--instance a ~ Char => KnownIODataMode [a] where- hGetIODataContents h = do- System.IO.hSetBinaryMode h False- System.IO.hGetContents h-- toIOData = IODataText- iodataMode = IODataModeText--instance KnownIODataMode LBS.ByteString where- hGetIODataContents h = do- System.IO.hSetBinaryMode h True- LBS.hGetContents h-- toIOData = IODataBinary- iodataMode = IODataModeBinary---- | 'IOData' Wrapper for 'System.IO.hPutStr' and 'System.IO.hClose'------ This is the dual operation ot 'hGetIODataContents',--- and consequently the handle is closed with `hClose`.------ /Note:/ this performs lazy-IO.------ @since 2.2-hPutContents :: System.IO.Handle -> IOData -> Prelude.IO ()-hPutContents h (IODataText c) = do- System.IO.hSetBinaryMode h False- System.IO.hPutStr h c- System.IO.hClose h-hPutContents h (IODataBinary c) = do- System.IO.hSetBinaryMode h True- LBS.hPutStr h c- System.IO.hClose h
− Distribution/Utils/LogProgress.hs
@@ -1,89 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE FlexibleContexts #-}-module Distribution.Utils.LogProgress (- LogProgress,- runLogProgress,- warnProgress,- infoProgress,- dieProgress,- addProgressCtx,-) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.Utils.Progress-import Distribution.Verbosity-import Distribution.Simple.Utils-import Text.PrettyPrint--type CtxMsg = Doc-type LogMsg = Doc-type ErrMsg = Doc--data LogEnv = LogEnv {- le_verbosity :: Verbosity,- le_context :: [CtxMsg]- }---- | The 'Progress' monad with specialized logging and--- error messages.-newtype LogProgress a = LogProgress { unLogProgress :: LogEnv -> Progress LogMsg ErrMsg a }--instance Functor LogProgress where- fmap f (LogProgress m) = LogProgress (fmap (fmap f) m)--instance Applicative LogProgress where- pure x = LogProgress (pure (pure x))- LogProgress f <*> LogProgress x = LogProgress $ \r -> f r `ap` x r--instance Monad LogProgress where- return = pure- LogProgress m >>= f = LogProgress $ \r -> m r >>= \x -> unLogProgress (f x) r---- | Run 'LogProgress', outputting traces according to 'Verbosity',--- 'die' if there is an error.-runLogProgress :: Verbosity -> LogProgress a -> IO a-runLogProgress verbosity (LogProgress m) =- foldProgress step_fn fail_fn return (m env)- where- env = LogEnv {- le_verbosity = verbosity,- le_context = []- }- step_fn :: LogMsg -> IO a -> IO a- step_fn doc go = do- putStrLn (render doc)- go- fail_fn :: Doc -> IO a- fail_fn doc = do- dieNoWrap verbosity (render doc)---- | Output a warning trace message in 'LogProgress'.-warnProgress :: Doc -> LogProgress ()-warnProgress s = LogProgress $ \env ->- when (le_verbosity env >= normal) $- stepProgress $- hang (text "Warning:") 4 (formatMsg (le_context env) s)---- | Output an informational trace message in 'LogProgress'.-infoProgress :: Doc -> LogProgress ()-infoProgress s = LogProgress $ \env ->- when (le_verbosity env >= verbose) $- stepProgress s---- | Fail the computation with an error message.-dieProgress :: Doc -> LogProgress a-dieProgress s = LogProgress $ \env ->- failProgress $- hang (text "Error:") 4 (formatMsg (le_context env) s)---- | Format a message with context. (Something simple for now.)-formatMsg :: [CtxMsg] -> Doc -> Doc-formatMsg ctx doc = doc $$ vcat ctx---- | Add a message to the error/warning context.-addProgressCtx :: CtxMsg -> LogProgress a -> LogProgress a-addProgressCtx s (LogProgress m) = LogProgress $ \env ->- m env { le_context = s : le_context env }
− Distribution/Utils/MD5.hs
@@ -1,79 +0,0 @@-module Distribution.Utils.MD5 (- MD5,- showMD5,- md5,- -- * Helpers- md5FromInteger,- -- * Binary- binaryPutMD5,- binaryGetMD5,- ) where--import Data.Binary (Get, Put)-import Data.Binary.Get (getWord64le)-import Data.Binary.Put (putWord64le)-import Data.Bits (complement, shiftR, (.&.))-import Foreign.Ptr (castPtr)-import GHC.Fingerprint (Fingerprint (..), fingerprintData)-import Numeric (showHex)-import System.IO.Unsafe (unsafeDupablePerformIO)--import qualified Data.ByteString as BS-import qualified Data.ByteString.Unsafe as BS--type MD5 = Fingerprint---- | Show 'MD5' in human readable form------ >>> showMD5 (Fingerprint 123 456)--- "000000000000007b00000000000001c8"------ >>> showMD5 $ md5 $ BS.pack [0..127]--- "37eff01866ba3f538421b30b7cbefcac"------ @since 3.2.0.0-showMD5 :: MD5 -> String-showMD5 (Fingerprint a b) = pad a' ++ pad b' where- a' = showHex a ""- b' = showHex b ""- pad s = replicate (16 - length s) '0' ++ s---- | @since 3.2.0.0-md5 :: BS.ByteString -> MD5-md5 bs = unsafeDupablePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, len) ->- fingerprintData (castPtr ptr) len---- | @since 3.2.0.0-binaryPutMD5 :: MD5 -> Put-binaryPutMD5 (Fingerprint a b) = do- putWord64le a- putWord64le b---- | @since 3.2.0.0-binaryGetMD5 :: Get MD5-binaryGetMD5 = do- a <- getWord64le- b <- getWord64le- return (Fingerprint a b)---- |------ >>> showMD5 $ md5FromInteger 0x37eff01866ba3f538421b30b7cbefcac--- "37eff01866ba3f538421b30b7cbefcac"------ Note: the input is truncated:------ >>> showMD5 $ md5FromInteger 0x1230000037eff01866ba3f538421b30b7cbefcac--- "37eff01866ba3f538421b30b7cbefcac"------ Yet, negative numbers are not a problem...------ >>> showMD5 $ md5FromInteger (-1)--- "ffffffffffffffffffffffffffffffff"------ @since 3.4.0.0-md5FromInteger :: Integer -> MD5-md5FromInteger i = Fingerprint hi lo where- mask = complement 0- lo = mask .&. fromInteger i- hi = mask .&. fromInteger (i `shiftR` 64)
− Distribution/Utils/MapAccum.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE CPP #-}-module Distribution.Utils.MapAccum (mapAccumM) where--import Distribution.Compat.Prelude-import Prelude ()---- Like StateT but with return tuple swapped-newtype StateM s m a = StateM { runStateM :: s -> m (s, a) }--instance Functor m => Functor (StateM s m) where- fmap f (StateM x) = StateM $ \s -> fmap (\(s', a) -> (s', f a)) (x s)--instance-#if __GLASGOW_HASKELL__ < 709- (Functor m, Monad m)-#else- Monad m-#endif- => Applicative (StateM s m) where- pure x = StateM $ \s -> return (s, x)- StateM f <*> StateM x = StateM $ \s -> do (s', f') <- f s- (s'', x') <- x s'- return (s'', f' x')---- | Monadic variant of 'mapAccumL'.-mapAccumM ::-#if __GLASGOW_HASKELL__ < 709- (Functor m, Monad m, Traversable t)-#else- (Monad m, Traversable t)-#endif- => (a -> b -> m (a, c)) -> a -> t b -> m (a, t c)-mapAccumM f s t = runStateM (traverse (\x -> StateM (\s' -> f s' x)) t) s-
− Distribution/Utils/NubList.hs
@@ -1,108 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE ScopedTypeVariables #-}-module Distribution.Utils.NubList- ( NubList -- opaque- , toNubList -- smart construtor- , fromNubList- , overNubList-- , NubListR- , toNubListR- , fromNubListR- , overNubListR- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Distribution.Simple.Utils--import qualified Text.Read as R---- | NubList : A de-duplicated list that maintains the original order.-newtype NubList a =- NubList { fromNubList :: [a] }- deriving (Eq, Generic, Typeable)---- NubList assumes that nub retains the list order while removing duplicate--- elements (keeping the first occurrence). Documentation for "Data.List.nub"--- does not specifically state that ordering is maintained so we will add a test--- for that to the test suite.---- | Smart constructor for the NubList type.-toNubList :: Ord a => [a] -> NubList a-toNubList list = NubList $ ordNub list---- | Lift a function over lists to a function over NubLists.-overNubList :: Ord a => ([a] -> [a]) -> NubList a -> NubList a-overNubList f (NubList list) = toNubList . f $ list---- | Monoid operations on NubLists.--- For a valid Monoid instance we need to satistfy the required monoid laws;--- identity, associativity and closure.------ Identity : by inspection:--- mempty `mappend` NubList xs == NubList xs `mappend` mempty------ Associativity : by inspection:--- (NubList xs `mappend` NubList ys) `mappend` NubList zs--- == NubList xs `mappend` (NubList ys `mappend` NubList zs)------ Closure : appending two lists of type a and removing duplicates obviously--- does not change the type.--instance Ord a => Monoid (NubList a) where- mempty = NubList []- mappend = (<>)--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--instance (Ord a, Read a) => Read (NubList a) where- readPrec = readNubList toNubList---- | Helper used by NubList/NubListR's Read instances.-readNubList :: (Read a) => ([a] -> l a) -> R.ReadPrec (l a)-readNubList listToL = R.parens . R.prec 10 $ fmap listToL R.readPrec---- | Binary instance for 'NubList a' is the same as for '[a]'. For 'put', we--- just pull off constructor and put the list. For 'get', we get the list and--- make a 'NubList' out of it using 'toNubList'.-instance (Ord a, Binary a) => Binary (NubList a) where- put (NubList l) = put l- get = fmap toNubList get--instance Structured a => Structured (NubList a)---- | NubListR : A right-biased version of 'NubList'. That is @toNubListR--- ["-XNoFoo", "-XFoo", "-XNoFoo"]@ will result in @["-XFoo", "-XNoFoo"]@,--- unlike the normal 'NubList', which is left-biased. Built on top of--- 'ordNubRight' and 'listUnionRight'.-newtype NubListR a =- NubListR { fromNubListR :: [a] }- deriving Eq---- | Smart constructor for the NubListR type.-toNubListR :: Ord a => [a] -> NubListR a-toNubListR list = NubListR $ ordNubRight list---- | Lift a function over lists to a function over NubListRs.-overNubListR :: Ord a => ([a] -> [a]) -> NubListR a -> NubListR a-overNubListR f (NubListR list) = toNubListR . f $ list--instance Ord a => Monoid (NubListR a) where- mempty = NubListR []- mappend = (<>)--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--instance (Ord a, Read a) => Read (NubListR a) where- readPrec = readNubList toNubListR
− Distribution/Utils/Progress.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveFunctor #-}--- Note: This module was copied from cabal-install.---- | A progress monad, which we use to report failure and logging from--- otherwise pure code.-module Distribution.Utils.Progress- ( Progress- , stepProgress- , failProgress- , foldProgress- ) where--import Prelude ()-import Distribution.Compat.Prelude--import qualified Data.Monoid as Mon----- | A type to represent the unfolding of an expensive long running--- calculation that may fail (or maybe not expensive, but complicated!)--- We may get intermediate steps before the final--- result which may be used to indicate progress and\/or logging messages.------ TODO: Apply Codensity to avoid left-associativity problem.--- See http://comonad.com/reader/2011/free-monads-for-less/ and--- http://blog.ezyang.com/2012/01/problem-set-the-codensity-transformation/----data Progress step fail done = Step step (Progress step fail done)- | Fail fail- | Done done- deriving (Functor)---- | Emit a step and then continue.----stepProgress :: step -> Progress step fail ()-stepProgress step = Step step (Done ())---- | Fail the computation.-failProgress :: fail -> Progress step fail done-failProgress err = Fail err---- | Consume a 'Progress' calculation. Much like 'foldr' for lists but with two--- base cases, one for a final result and one for failure.------ Eg to convert into a simple 'Either' result use:------ > foldProgress (flip const) Left Right----foldProgress :: (step -> a -> a) -> (fail -> a) -> (done -> a)- -> Progress step fail done -> a-foldProgress step err done = fold- where fold (Step s p) = step s (fold p)- fold (Fail f) = err f- fold (Done r) = done r--instance Monad (Progress step fail) where- return = pure- p >>= f = foldProgress Step Fail f p--instance Applicative (Progress step fail) where- pure a = Done a- p <*> x = foldProgress Step Fail (flip fmap x) p--instance Monoid fail => Alternative (Progress step fail) where- empty = Fail Mon.mempty- p <|> q = foldProgress Step (const q) Done p
− Distribution/Utils/ShortText.hs
@@ -1,159 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}---- | Compact representation of short 'Strings'------ This module is designed to be import qualifeid------ @--- import Distribution.Utils.ShortText (ShortText)--- import qualified Distribution.Utils.ShortText as ShortText--- @-module Distribution.Utils.ShortText- ( -- * 'ShortText' type- ShortText- , toShortText- , fromShortText- , unsafeFromUTF8BS-- -- * Operations- , null- , length-- -- * internal utilities- , decodeStringUtf8- , encodeStringUtf8- ) where--import Distribution.Compat.Prelude hiding (length, null)-import Prelude ()--import Distribution.Utils.String (decodeStringUtf8, encodeStringUtf8)-import Distribution.Utils.Structured (Structured (..), nominalStructure)--#if defined(MIN_VERSION_bytestring)-# if MIN_VERSION_bytestring(0,10,4)-# define HAVE_SHORTBYTESTRING 1-# endif-#endif---- Hack for GHC bootstrapping------ Currently (as of GHC 8.1), GHC bootstraps Cabal by building--- binary and Cabal in one giant ghc --make command. This--- means no MIN_VERSION_binary macro is available.------ We could try to cleverly figure something out in this case,--- but there is a better plan: just use the unoptimized version--- of the Binary instance. We're not going to use it for anything--- real in any case.------ WARNING: Don't use MIN_VERSION_binary to smooth over a BC-break!----#ifndef MIN_VERSION_binary-#define MIN_VERSION_binary(x, y, z) 0-#endif--import qualified Data.ByteString as BS-import qualified Data.List as List--#if HAVE_SHORTBYTESTRING-import qualified Data.ByteString.Short as BS.Short-#else-import Distribution.Utils.Generic (fromUTF8BS)-#endif---- | Construct 'ShortText' from 'String'-toShortText :: String -> ShortText---- | Convert 'ShortText' to 'String'-fromShortText :: ShortText -> String---- | Convert from UTF-8 encoded strict 'ByteString'.------ @since 3.2.0.0-unsafeFromUTF8BS :: BS.ByteString -> ShortText---- | Text whether 'ShortText' is empty.------ @since 3.2.0.0-null :: ShortText -> Bool---- | Compact representation of short 'Strings'------ The data is stored internally as UTF8 in an--- 'BS.Short.ShortByteString' when compiled against @bytestring >=--- 0.10.4@, and otherwise the fallback is to use plain old non-compat--- '[Char]'.------ Note: This type is for internal uses (such as e.g. 'PackageName')--- and shall not be exposed in Cabal's API------ @since 2.0.0.2-#if HAVE_SHORTBYTESTRING-newtype ShortText = ST { unST :: BS.Short.ShortByteString }- deriving (Eq,Ord,Generic,Data,Typeable)--# if MIN_VERSION_binary(0,8,1)-instance Binary ShortText where- put = put . unST- get = fmap ST get-# else-instance Binary ShortText where- put = put . BS.Short.fromShort . unST- get = fmap (ST . BS.Short.toShort) get-# endif---toShortText = ST . BS.Short.pack . encodeStringUtf8--fromShortText = decodeStringUtf8 . BS.Short.unpack . unST--unsafeFromUTF8BS = ST . BS.Short.toShort--null = BS.Short.null . unST-#else-newtype ShortText = ST { unST :: String }- deriving (Eq,Ord,Generic,Data,Typeable)--instance Binary ShortText where- put = put . encodeStringUtf8 . unST- get = fmap (ST . decodeStringUtf8) get--toShortText = ST--fromShortText = unST--unsafeFromUTF8BS = ST . fromUTF8BS--null = List.null . unST-#endif--instance Structured ShortText where structure = nominalStructure--instance NFData ShortText where- rnf = rnf . unST--instance Show ShortText where- show = show . fromShortText--instance Read ShortText where- readsPrec p = map (first toShortText) . readsPrec p--instance Semigroup ShortText where- ST a <> ST b = ST (mappend a b)--instance Monoid ShortText where- mempty = ST mempty- mappend = (<>)--instance IsString ShortText where- fromString = toShortText---- | /O(n)/. Length in characters. /Slow/ as converts to string.------ @since 3.2.0.0-length :: ShortText -> Int-length = List.length . fromShortText--- Note: avoid using it, we use it @cabal check@ implementation, where it's ok.
− Distribution/Utils/String.hs
@@ -1,93 +0,0 @@-module Distribution.Utils.String- ( -- * Encode to/from UTF8- decodeStringUtf8- , encodeStringUtf8- ) where--import Data.Word-import Data.Bits-import Data.Char (chr,ord)---- | Decode 'String' from UTF8-encoded octets.------ Invalid data in the UTF8 stream (this includes code-points @U+D800@--- through @U+DFFF@) will be decoded as the replacement character (@U+FFFD@).------ See also 'encodeStringUtf8'-decodeStringUtf8 :: [Word8] -> String-decodeStringUtf8 = go- where- go :: [Word8] -> String- go [] = []- go (c : cs)- | c <= 0x7F = chr (fromIntegral c) : go cs- | c <= 0xBF = replacementChar : go cs- | c <= 0xDF = twoBytes c cs- | c <= 0xEF = moreBytes 3 0x800 cs (fromIntegral $ c .&. 0xF)- | c <= 0xF7 = moreBytes 4 0x10000 cs (fromIntegral $ c .&. 0x7)- | c <= 0xFB = moreBytes 5 0x200000 cs (fromIntegral $ c .&. 0x3)- | c <= 0xFD = moreBytes 6 0x4000000 cs (fromIntegral $ c .&. 0x1)- | otherwise = replacementChar : go cs-- twoBytes :: Word8 -> [Word8] -> String- twoBytes c0 (c1:cs')- | c1 .&. 0xC0 == 0x80- = let d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6)- .|. fromIntegral (c1 .&. 0x3F)- in if d >= 0x80- then chr d : go cs'- else replacementChar : go cs'- twoBytes _ cs' = replacementChar : go cs'-- moreBytes :: Int -> Int -> [Word8] -> Int -> [Char]- moreBytes 1 overlong cs' acc- | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc- = chr acc : go cs'-- | otherwise- = replacementChar : go cs'-- moreBytes byteCount overlong (cn:cs') acc- | cn .&. 0xC0 == 0x80- = moreBytes (byteCount-1) overlong cs'- ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)-- moreBytes _ _ cs' _- = replacementChar : go cs'-- replacementChar = '\xfffd'----- | Encode 'String' to a list of UTF8-encoded octets------ Code-points in the @U+D800@-@U+DFFF@ range will be encoded--- as the replacement character (i.e. @U+FFFD@).------ See also 'decodeUtf8'-encodeStringUtf8 :: String -> [Word8]-encodeStringUtf8 [] = []-encodeStringUtf8 (c:cs)- | c <= '\x07F' = w8- : encodeStringUtf8 cs- | c <= '\x7FF' = (0xC0 .|. w8ShiftR 6 )- : (0x80 .|. (w8 .&. 0x3F))- : encodeStringUtf8 cs- | c <= '\xD7FF'= (0xE0 .|. w8ShiftR 12 )- : (0x80 .|. (w8ShiftR 6 .&. 0x3F))- : (0x80 .|. (w8 .&. 0x3F))- : encodeStringUtf8 cs- | c <= '\xDFFF'= 0xEF : 0xBF : 0xBD -- U+FFFD- : encodeStringUtf8 cs- | c <= '\xFFFF'= (0xE0 .|. w8ShiftR 12 )- : (0x80 .|. (w8ShiftR 6 .&. 0x3F))- : (0x80 .|. (w8 .&. 0x3F))- : encodeStringUtf8 cs- | otherwise = (0xf0 .|. w8ShiftR 18 )- : (0x80 .|. (w8ShiftR 12 .&. 0x3F))- : (0x80 .|. (w8ShiftR 6 .&. 0x3F))- : (0x80 .|. (w8 .&. 0x3F))- : encodeStringUtf8 cs- where- w8 = fromIntegral (ord c) :: Word8- w8ShiftR :: Int -> Word8- w8ShiftR = fromIntegral . shiftR (ord c)
− Distribution/Utils/Structured.hs
@@ -1,476 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-#if __GLASGOW_HASKELL__ >= 711-{-# LANGUAGE PatternSynonyms #-}-#endif-#if __GLASGOW_HASKELL__ >= 800-{-# LANGUAGE TypeInType #-}-#endif--- |------ Copyright: (c) 2019 Oleg Grenrus------ Structurally tag binary serialisaton stream.--- Useful when most 'Binary' instances are 'Generic' derived.------ Say you have a data type------ @--- data Record = Record--- { _recordFields :: HM.HashMap Text (Integer, ByteString)--- , _recordEnabled :: Bool--- }--- deriving (Eq, Show, Generic)------ instance 'Binary' Record--- instance 'Structured' Record--- @------ then you can serialise and deserialise @Record@ values with a structure tag by simply------ @--- 'structuredEncode' record :: 'LBS.ByteString'--- 'structuredDecode' lbs :: IO Record--- @------ If structure of @Record@ changes in between, deserialisation will fail early.------ Technically, 'Structured' is not related to 'Binary', and may--- be useful in other uses.----module Distribution.Utils.Structured (- -- * Encoding and decoding- -- | These functions operate like @binary@'s counterparts,- -- but the serialised version has a structure hash in front.- structuredEncode,- structuredEncodeFile,- structuredDecode,- structuredDecodeOrFailIO,- structuredDecodeFileOrFail,- -- * Structured class- Structured (structure),- MD5,- structureHash,- structureBuilder,- genericStructure,- GStructured,- nominalStructure,- containerStructure,- -- * Structure type- Structure (..),- TypeName,- ConstructorName,- TypeVersion,- SopStructure,- hashStructure,- typeVersion,- typeName,- ) where--import Data.Int (Int16, Int32, Int64, Int8)-import Data.List.NonEmpty (NonEmpty)-import Data.Proxy (Proxy (..))-import Data.Ratio (Ratio)-import Data.Word (Word, Word16, Word32, Word64, Word8)--import qualified Control.Monad.Trans.State.Strict as State--import Control.Exception (ErrorCall (..), catch, evaluate)--import GHC.Generics--import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as LBS-#if MIN_VERSION_bytestring(0,10,4)-import qualified Data.ByteString.Builder as Builder-#else-import qualified Data.ByteString.Lazy.Builder as Builder-#endif-import qualified Data.IntMap as IM-import qualified Data.IntSet as IS-import qualified Data.Map as Map-import qualified Data.Sequence as Seq-import qualified Data.Set as Set-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import qualified Data.Time as Time-import qualified Distribution.Compat.Binary as Binary--#ifdef MIN_VERSION_aeson-import qualified Data.Aeson as Aeson-#endif--#if __GLASGOW_HASKELL__ >= 800-import Data.Kind (Type)-#else-#define Type *-#endif--import Distribution.Compat.Typeable (Typeable, TypeRep, typeRep)-import Distribution.Utils.MD5--import Data.Monoid (mconcat)--import qualified Data.Semigroup-import qualified Data.Foldable--#if !MIN_VERSION_base(4,8,0)-import Control.Applicative (pure)-import Data.Traversable (traverse)-#endif--#if !MIN_VERSION_base(4,7,0)-import Data.Typeable (Typeable1, typeOf1)-#endif------------------------------------------------------------------------------------- Types----------------------------------------------------------------------------------type TypeName = String-type ConstructorName = String---- | A sematic version of a data type. Usually 0.-type TypeVersion = Word32---- | Structure of a datatype.------ It can be infinite, as far as 'TypeRep's involved are finite.--- (e.g. polymorphic recursion might cause troubles).----data Structure- = Nominal !TypeRep !TypeVersion TypeName [Structure] -- ^ nominal, yet can be parametrised by other structures.- | Newtype !TypeRep !TypeVersion TypeName Structure -- ^ a newtype wrapper- | Structure !TypeRep !TypeVersion TypeName SopStructure -- ^ sum-of-products structure- deriving (Eq, Ord, Show, Generic)--type SopStructure = [(ConstructorName, [Structure])]---- | A MD5 hash digest of 'Structure'.-hashStructure :: Structure -> MD5-hashStructure = md5 . LBS.toStrict . Builder.toLazyByteString . structureBuilder---- | A van-Laarhoven lens into 'TypeVersion' of 'Structure'------ @--- 'typeVersion' :: Lens' 'Structure' 'TypeVersion'--- @-typeVersion :: Functor f => (TypeVersion -> f TypeVersion) -> Structure -> f Structure-typeVersion f (Nominal t v n s) = fmap (\v' -> Nominal t v' n s) (f v)-typeVersion f (Newtype t v n s) = fmap (\v' -> Newtype t v' n s) (f v)-typeVersion f (Structure t v n s) = fmap (\v' -> Structure t v' n s) (f v)---- | A van-Laarhoven lens into 'TypeName' of 'Structure'------ @--- 'typeName' :: Lens' 'Structure' 'TypeName'--- @-typeName :: Functor f => (TypeName -> f TypeName) -> Structure -> f Structure-typeName f (Nominal t v n s) = fmap (\n' -> Nominal t v n' s) (f n)-typeName f (Newtype t v n s) = fmap (\n' -> Newtype t v n' s) (f n)-typeName f (Structure t v n s) = fmap (\n' -> Structure t v n' s) (f n)------------------------------------------------------------------------------------ Builder------------------------------------------------------------------------------------ | Flatten 'Structure' into something we can calculate hash of.------ As 'Structure' can be potentially infinite. For mutually recursive types,--- we keep track of 'TypeRep's, and put just 'TypeRep' name when it's occurred--- another time.-structureBuilder :: Structure -> Builder.Builder-structureBuilder s0 = State.evalState (go s0) Map.empty where- go :: Structure -> State.State (Map.Map String (NonEmpty TypeRep)) Builder.Builder- go (Nominal t v n s) = withTypeRep t $ do- s' <- traverse go s- return $ mconcat $ Builder.word8 1 : Builder.word32LE v : Builder.stringUtf8 n : s'-- go (Newtype t v n s) = withTypeRep t $ do- s' <- go s- return $ mconcat [Builder.word8 2, Builder.word32LE v, Builder.stringUtf8 n, s']-- go (Structure t v n s) = withTypeRep t $ do- s' <- goSop s- return $ mconcat [Builder.word8 3, Builder.word32LE v, Builder.stringUtf8 n, s']-- withTypeRep t k = do- acc <- State.get- case insert t acc of- Nothing -> return $ mconcat [ Builder.word8 0, Builder.stringUtf8 (show t) ]- Just acc' -> do- State.put acc'- k -- goSop :: SopStructure -> State.State (Map.Map String (NonEmpty TypeRep)) Builder.Builder- goSop sop = do- parts <- traverse part sop- return $ mconcat parts-- part (cn, s) = do- s' <- traverse go s- return $ Data.Monoid.mconcat [ Builder.stringUtf8 cn, mconcat s' ]-- insert :: TypeRep -> Map.Map String (NonEmpty TypeRep) -> Maybe (Map.Map String (NonEmpty TypeRep))- insert tr m = case Map.lookup trShown m of- Nothing -> inserted- Just ne | tr `Data.Foldable.elem` ne -> Nothing- | otherwise -> inserted- where- inserted = Just (Map.insertWith (Data.Semigroup.<>) trShown (pure tr) m)- trShown = show tr------------------------------------------------------------------------------------ Classes------------------------------------------------------------------------------------ | Class of types with a known 'Structure'.------ For regular data types 'Structured' can be derived generically.------ @--- data Record = Record { a :: Int, b :: Bool, c :: [Char] } deriving ('Generic')--- instance 'Structured' Record--- @------ @since 3.2.0.0----class Typeable a => Structured a where- structure :: Proxy a -> Structure- default structure :: (Generic a, GStructured (Rep a)) => Proxy a -> Structure- structure = genericStructure-- -- This member is hidden. It's there to precalc- structureHash' :: Tagged a MD5- structureHash' = Tagged (hashStructure (structure (Proxy :: Proxy a)))---- private Tagged-newtype Tagged a b = Tagged { untag :: b }---- | Semantically @'hashStructure' . 'structure'@.-structureHash :: forall a. Structured a => Proxy a -> MD5-structureHash _ = untag (structureHash' :: Tagged a MD5)------------------------------------------------------------------------------------ Functions------------------------------------------------------------------------------------ | Structured 'Binary.encode'.--- Encode a value to using binary serialisation to a lazy 'LBS.ByteString'.--- Encoding starts with 16 byte large structure hash.-structuredEncode- :: forall a. (Binary.Binary a, Structured a)- => a -> LBS.ByteString-structuredEncode x = Binary.encode (Tag :: Tag a, x)---- | Lazily serialise a value to a file-structuredEncodeFile :: (Binary.Binary a, Structured a) => FilePath -> a -> IO ()-structuredEncodeFile f = LBS.writeFile f . structuredEncode---- | Structured 'Binary.decode'.--- Decode a value from a lazy 'LBS.ByteString', reconstructing the original structure.--- Throws pure exception on invalid inputs.-structuredDecode- :: forall a. (Binary.Binary a, Structured a)- => LBS.ByteString -> a-structuredDecode lbs = snd (Binary.decode lbs :: (Tag a, a))--structuredDecodeOrFailIO :: (Binary.Binary a, Structured a) => LBS.ByteString -> IO (Either String a)-structuredDecodeOrFailIO bs =- catch (evaluate (structuredDecode bs) >>= return . Right) handler- where-#if MIN_VERSION_base(4,9,0)- handler (ErrorCallWithLocation str _) = return $ Left str-#else- handler (ErrorCall str) = return $ Left str-#endif---- | Lazily reconstruct a value previously written to a file.-structuredDecodeFileOrFail :: (Binary.Binary a, Structured a) => FilePath -> IO (Either String a)-structuredDecodeFileOrFail f = structuredDecodeOrFailIO =<< LBS.readFile f------------------------------------------------------------------------------------ Helper data----------------------------------------------------------------------------------data Tag a = Tag--instance Structured a => Binary.Binary (Tag a) where- get = do- actual <- binaryGetMD5- if actual == expected- then return Tag- else fail $ concat- [ "Non-matching structured hashes: "- , showMD5 actual- , "; expected: "- , showMD5 expected- ]- where- expected = untag (structureHash' :: Tagged a MD5)-- put _ = binaryPutMD5 expected- where- expected = untag (structureHash' :: Tagged a MD5)------------------------------------------------------------------------------------ Smart constructors------------------------------------------------------------------------------------ | Use 'Typeable' to infer name-nominalStructure :: Typeable a => Proxy a -> Structure-nominalStructure p = Nominal tr 0 (show tr) [] where- tr = typeRep p--#if MIN_VERSION_base(4,7,0)-containerStructure :: forall f a. (Typeable f, Structured a) => Proxy (f a) -> Structure-containerStructure _ = Nominal faTypeRep 0 (show fTypeRep)- [ structure (Proxy :: Proxy a)- ]- where- fTypeRep = typeRep (Proxy :: Proxy f)- faTypeRep = typeRep (Proxy :: Proxy (f a))--#else-containerStructure :: forall f a. (Typeable1 f, Structured a) => Proxy (f a) -> Structure-containerStructure _ = Nominal faTypeRep 0 (show fTypeRep)- [ structure (Proxy :: Proxy a)- ]- where- fTypeRep = typeOf1 (undefined :: f ())- faTypeRep = typeRep (Proxy :: Proxy (f a))-#endif------------------------------------------------------------------------------------ Generic------------------------------------------------------------------------------------ | Derive 'structure' genrically.-genericStructure :: forall a. (Typeable a, Generic a, GStructured (Rep a)) => Proxy a -> Structure-genericStructure _ = gstructured (typeRep (Proxy :: Proxy a)) (Proxy :: Proxy (Rep a)) 0---- | Used to implement 'genericStructure'.-class GStructured (f :: Type -> Type) where- gstructured :: TypeRep -> Proxy f -> TypeVersion -> Structure--instance (i ~ D, Datatype c, GStructuredSum f) => GStructured (M1 i c f) where- gstructured tr _ v = case sop of-#if MIN_VERSION_base(4,7,0)- [(_, [s])] | isNewtype p -> Newtype tr v name s-#endif- _ -> Structure tr v name sop- where- p = undefined :: M1 i c f ()- name = datatypeName p- sop = gstructuredSum (Proxy :: Proxy f) []--class GStructuredSum (f :: Type -> Type) where- gstructuredSum :: Proxy f -> SopStructure -> SopStructure--instance (i ~ C, Constructor c, GStructuredProd f) => GStructuredSum (M1 i c f) where- gstructuredSum _ xs = (name, prod) : xs- where- name = conName (undefined :: M1 i c f ())- prod = gstructuredProd (Proxy :: Proxy f) []--instance (GStructuredSum f, GStructuredSum g) => GStructuredSum (f :+: g) where- gstructuredSum _ xs- = gstructuredSum (Proxy :: Proxy f)- $ gstructuredSum (Proxy :: Proxy g) xs--instance GStructuredSum V1 where- gstructuredSum _ = id--class GStructuredProd (f :: Type -> Type) where- gstructuredProd :: Proxy f -> [Structure] -> [Structure]--instance (i ~ S, GStructuredProd f) => GStructuredProd (M1 i c f) where- gstructuredProd _ = gstructuredProd (Proxy :: Proxy f)--instance Structured c => GStructuredProd (K1 i c) where- gstructuredProd _ xs = structure (Proxy :: Proxy c) : xs--instance GStructuredProd U1 where- gstructuredProd _ = id--instance (GStructuredProd f, GStructuredProd g) => GStructuredProd (f :*: g) where- gstructuredProd _ xs- = gstructuredProd (Proxy :: Proxy f)- $ gstructuredProd (Proxy :: Proxy g) xs------------------------------------------------------------------------------------ instances----------------------------------------------------------------------------------instance Structured ()-instance Structured Bool-instance Structured Ordering--instance Structured Char where structure = nominalStructure-instance Structured Int where structure = nominalStructure-instance Structured Integer where structure = nominalStructure--instance Structured Data.Word.Word where structure = nominalStructure--instance Structured Int8 where structure = nominalStructure-instance Structured Int16 where structure = nominalStructure-instance Structured Int32 where structure = nominalStructure-instance Structured Int64 where structure = nominalStructure--instance Structured Word8 where structure = nominalStructure-instance Structured Word16 where structure = nominalStructure-instance Structured Word32 where structure = nominalStructure-instance Structured Word64 where structure = nominalStructure--instance Structured Float where structure = nominalStructure-instance Structured Double where structure = nominalStructure--instance Structured a => Structured (Maybe a)-instance (Structured a, Structured b) => Structured (Either a b)-instance Structured a => Structured (Ratio a) where structure = containerStructure-instance Structured a => Structured [a] where structure = containerStructure-instance Structured a => Structured (NonEmpty a) where structure = containerStructure--instance (Structured a1, Structured a2) => Structured (a1, a2)-instance (Structured a1, Structured a2, Structured a3) => Structured (a1, a2, a3)-instance (Structured a1, Structured a2, Structured a3, Structured a4) => Structured (a1, a2, a3, a4)-instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5) => Structured (a1, a2, a3, a4, a5)-instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5, Structured a6) => Structured (a1, a2, a3, a4, a5, a6)-instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5, Structured a6, Structured a7) => Structured (a1, a2, a3, a4, a5, a6, a7)--instance Structured BS.ByteString where structure = nominalStructure-instance Structured LBS.ByteString where structure = nominalStructure--instance Structured T.Text where structure = nominalStructure-instance Structured LT.Text where structure = nominalStructure--instance (Structured k, Structured v) => Structured (Map.Map k v) where structure _ = Nominal (typeRep (Proxy :: Proxy (Map.Map k v))) 0 "Map" [ structure (Proxy :: Proxy k), structure (Proxy :: Proxy v) ]-instance (Structured k) => Structured (Set.Set k) where structure = containerStructure-instance (Structured v) => Structured (IM.IntMap v) where structure = containerStructure-instance Structured IS.IntSet where structure = nominalStructure-instance (Structured v) => Structured (Seq.Seq v) where structure = containerStructure--instance Structured Time.UTCTime where structure = nominalStructure-instance Structured Time.DiffTime where structure = nominalStructure-instance Structured Time.UniversalTime where structure = nominalStructure-instance Structured Time.NominalDiffTime where structure = nominalStructure-instance Structured Time.Day where structure = nominalStructure-instance Structured Time.TimeZone where structure = nominalStructure-instance Structured Time.TimeOfDay where structure = nominalStructure-instance Structured Time.LocalTime where structure = nominalStructure---- Proxy isn't Typeable in base-4.8 / base---- #if __GLASGOW_HASKELL__ >= 800--- instance (Typeable k, Typeable (a :: k)) => Structured (Proxy a)--- #else--- instance (Typeable a) => Structured (Proxy a) where--- structure p = Structure (typeRep p) 0 "Proxy" [("Proxy",[])]--- #endif
− Distribution/Utils/UnionFind.hs
@@ -1,102 +0,0 @@-{-# LANGUAGE NondecreasingIndentation #-}--- | A simple mutable union-find data structure.------ It is used in a unification algorithm for backpack mix-in linking.------ This implementation is based off of the one in \"The Essence of ML Type--- Inference\". (N.B. the union-find package is also based off of this.)----module Distribution.Utils.UnionFind (- Point,- fresh,- find,- union,- equivalent,-) where--import Data.STRef-import Control.Monad-import Control.Monad.ST---- | A variable which can be unified; alternately, this can be thought--- of as an equivalence class with a distinguished representative.-newtype Point s a = Point (STRef s (Link s a))- deriving (Eq)---- | Mutable write to a 'Point'-writePoint :: Point s a -> Link s a -> ST s ()-writePoint (Point v) = writeSTRef v---- | Read the current value of 'Point'.-readPoint :: Point s a -> ST s (Link s a)-readPoint (Point v) = readSTRef v---- | The internal data structure for a 'Point', which either records--- the representative element of an equivalence class, or a link to--- the 'Point' that actually stores the representative type.-data Link s a- -- NB: it is too bad we can't say STRef Int#; the weights remain boxed- = Info {-# UNPACK #-} !(STRef s Int) {-# UNPACK #-} !(STRef s a)- | Link {-# UNPACK #-} !(Point s a)---- | Create a fresh equivalence class with one element.-fresh :: a -> ST s (Point s a)-fresh desc = do- weight <- newSTRef 1- descriptor <- newSTRef desc- Point `fmap` newSTRef (Info weight descriptor)---- | Flatten any chains of links, returning a 'Point'--- which points directly to the canonical representation.-repr :: Point s a -> ST s (Point s a)-repr point = readPoint point >>= \r ->- case r of- Link point' -> do- point'' <- repr point'- when (point'' /= point') $ do- writePoint point =<< readPoint point'- return point''- Info _ _ -> return point---- | Return the canonical element of an equivalence--- class 'Point'.-find :: Point s a -> ST s a-find point =- -- Optimize length 0 and 1 case at expense of- -- general case- readPoint point >>= \r ->- case r of- Info _ d_ref -> readSTRef d_ref- Link point' -> readPoint point' >>= \r' ->- case r' of- Info _ d_ref -> readSTRef d_ref- Link _ -> repr point >>= find---- | Unify two equivalence classes, so that they share--- a canonical element. Keeps the descriptor of point2.-union :: Point s a -> Point s a -> ST s ()-union refpoint1 refpoint2 = do- point1 <- repr refpoint1- point2 <- repr refpoint2- when (point1 /= point2) $ do- l1 <- readPoint point1- l2 <- readPoint point2- case (l1, l2) of- (Info wref1 dref1, Info wref2 dref2) -> do- weight1 <- readSTRef wref1- weight2 <- readSTRef wref2- -- Should be able to optimize the == case separately- if weight1 >= weight2- then do- writePoint point2 (Link point1)- -- The weight calculation here seems a bit dodgy- writeSTRef wref1 (weight1 + weight2)- writeSTRef dref1 =<< readSTRef dref2- else do- writePoint point1 (Link point2)- writeSTRef wref2 (weight1 + weight2)- _ -> error "UnionFind.union: repr invariant broken"---- | Test if two points are in the same equivalence class.-equivalent :: Point s a -> Point s a -> ST s Bool-equivalent point1 point2 = liftM2 (==) (repr point1) (repr point2)
− Distribution/Verbosity.hs
@@ -1,345 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}---------------------------------------------------------------------------------- |--- Module : Distribution.Verbosity--- Copyright : Ian Lynagh 2007--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ A 'Verbosity' type with associated utilities.------ There are 4 standard verbosity levels from 'silent', 'normal',--- 'verbose' up to 'deafening'. This is used for deciding what logging--- messages to print.------ Verbosity also is equipped with some internal settings which can be--- used to control at a fine granularity the verbosity of specific--- settings (e.g., so that you can trace only particular things you--- are interested in.) It's important to note that the instances--- for 'Verbosity' assume that this does not exist.---- Verbosity for Cabal functions.--module Distribution.Verbosity (- -- * Verbosity- Verbosity,- silent, normal, verbose, deafening,- moreVerbose, lessVerbose, isVerboseQuiet,- intToVerbosity, flagToVerbosity,- showForCabal, showForGHC,- verboseNoFlags, verboseHasFlags,- modifyVerbosity,-- -- * Call stacks- verboseCallSite, verboseCallStack,- isVerboseCallSite, isVerboseCallStack,-- -- * Output markets- verboseMarkOutput, isVerboseMarkOutput,- verboseUnmarkOutput,-- -- * line-wrapping- verboseNoWrap, isVerboseNoWrap,-- -- * timestamps- verboseTimestamp, isVerboseTimestamp,- verboseNoTimestamp,-- -- * Stderr- verboseStderr, isVerboseStderr,- verboseNoStderr,- ) where--import Prelude ()-import Distribution.Compat.Prelude--import Distribution.ReadE--import Data.List (elemIndex)-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Verbosity.Internal-import Distribution.Utils.Generic (isAsciiAlpha)--import qualified Data.Set as Set-import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as PP--data Verbosity = Verbosity {- vLevel :: VerbosityLevel,- vFlags :: Set VerbosityFlag,- vQuiet :: Bool- } deriving (Generic, Show, Read, Typeable)--mkVerbosity :: VerbosityLevel -> Verbosity-mkVerbosity l = Verbosity { vLevel = l, vFlags = Set.empty, vQuiet = False }--instance Eq Verbosity where- x == y = vLevel x == vLevel y--instance Ord Verbosity where- compare x y = compare (vLevel x) (vLevel y)--instance Enum Verbosity where- toEnum = mkVerbosity . toEnum- fromEnum = fromEnum . vLevel--instance Bounded Verbosity where- minBound = mkVerbosity minBound- maxBound = mkVerbosity maxBound--instance Binary Verbosity-instance Structured Verbosity---- We shouldn't print /anything/ unless an error occurs in silent mode-silent :: Verbosity-silent = mkVerbosity Silent---- Print stuff we want to see by default-normal :: Verbosity-normal = mkVerbosity Normal---- Be more verbose about what's going on-verbose :: Verbosity-verbose = mkVerbosity Verbose---- Not only are we verbose ourselves (perhaps even noisier than when--- being "verbose"), but we tell everything we run to be verbose too-deafening :: Verbosity-deafening = mkVerbosity Deafening--moreVerbose :: Verbosity -> Verbosity-moreVerbose v =- case vLevel v of- Silent -> v -- silent should stay silent- Normal -> v { vLevel = Verbose }- Verbose -> v { vLevel = Deafening }- Deafening -> v--lessVerbose :: Verbosity -> Verbosity-lessVerbose v =- verboseQuiet $- case vLevel v of- Deafening -> v -- deafening stays deafening- Verbose -> v { vLevel = Normal }- Normal -> v { vLevel = Silent }- Silent -> v---- | Combinator for transforming verbosity level while retaining the--- original hidden state.------ For instance, the following property holds------ prop> isVerboseNoWrap (modifyVerbosity (max verbose) v) == isVerboseNoWrap v------ __Note__: you can use @modifyVerbosity (const v1) v0@ to overwrite--- @v1@'s flags with @v0@'s flags.------ @since 2.0.1.0-modifyVerbosity :: (Verbosity -> Verbosity) -> Verbosity -> Verbosity-modifyVerbosity f v = v { vLevel = vLevel (f v) }--intToVerbosity :: Int -> Maybe Verbosity-intToVerbosity 0 = Just (mkVerbosity Silent)-intToVerbosity 1 = Just (mkVerbosity Normal)-intToVerbosity 2 = Just (mkVerbosity Verbose)-intToVerbosity 3 = Just (mkVerbosity Deafening)-intToVerbosity _ = Nothing---- | Parser verbosity------ >>> explicitEitherParsec parsecVerbosity "normal"--- Right (Verbosity {vLevel = Normal, vFlags = fromList [], vQuiet = False})------ >>> explicitEitherParsec parsecVerbosity "normal+nowrap "--- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap], vQuiet = False})------ >>> explicitEitherParsec parsecVerbosity "normal+nowrap +markoutput"--- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})------ >>> explicitEitherParsec parsecVerbosity "normal +nowrap +markoutput"--- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})------ >>> explicitEitherParsec parsecVerbosity "normal+nowrap+markoutput"--- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})------ >>> explicitEitherParsec parsecVerbosity "deafening+nowrap+stdout+stderr+callsite+callstack"--- Right (Verbosity {vLevel = Deafening, vFlags = fromList [VCallStack,VCallSite,VNoWrap,VStderr], vQuiet = False})------ /Note:/ this parser will eat trailing spaces.----instance Parsec Verbosity where- parsec = parsecVerbosity--instance Pretty Verbosity where- pretty = PP.text . showForCabal--parsecVerbosity :: CabalParsing m => m Verbosity-parsecVerbosity = parseIntVerbosity <|> parseStringVerbosity- where- parseIntVerbosity = do- i <- P.integral- case intToVerbosity i of- Just v -> return v- Nothing -> P.unexpected $ "Bad integral verbosity: " ++ show i ++ ". Valid values are 0..3"-- parseStringVerbosity = do- level <- parseVerbosityLevel- _ <- P.spaces- flags <- many (parseFlag <* P.spaces)- return $ foldl' (flip ($)) (mkVerbosity level) flags-- parseVerbosityLevel = do- token <- P.munch1 isAsciiAlpha- case token of- "silent" -> return Silent- "normal" -> return Normal- "verbose" -> return Verbose- "debug" -> return Deafening- "deafening" -> return Deafening- _ -> P.unexpected $ "Bad verbosity level: " ++ token- parseFlag = do- _ <- P.char '+'- token <- P.munch1 isAsciiAlpha- case token of- "callsite" -> return verboseCallSite- "callstack" -> return verboseCallStack- "nowrap" -> return verboseNoWrap- "markoutput" -> return verboseMarkOutput- "timestamp" -> return verboseTimestamp- "stderr" -> return verboseStderr- "stdout" -> return verboseNoStderr- _ -> P.unexpected $ "Bad verbosity flag: " ++ token--flagToVerbosity :: ReadE Verbosity-flagToVerbosity = parsecToReadE id parsecVerbosity--showForCabal :: Verbosity -> String-showForCabal v- | Set.null (vFlags v)- = maybe (error "unknown verbosity") show $- elemIndex v [silent,normal,verbose,deafening]- | otherwise- = unwords- $ showLevel (vLevel v)- : concatMap showFlag (Set.toList (vFlags v))- where- showLevel Silent = "silent"- showLevel Normal = "normal"- showLevel Verbose = "verbose"- showLevel Deafening = "debug"-- showFlag VCallSite = ["+callsite"]- showFlag VCallStack = ["+callstack"]- showFlag VNoWrap = ["+nowrap"]- showFlag VMarkOutput = ["+markoutput"]- showFlag VTimestamp = ["+timestamp"]- showFlag VStderr = ["+stderr"]--showForGHC :: Verbosity -> String-showForGHC v = maybe (error "unknown verbosity") show $- elemIndex v [silent,normal,__,verbose,deafening]- where __ = silent -- this will be always ignored by elemIndex---- | Turn on verbose call-site printing when we log.-verboseCallSite :: Verbosity -> Verbosity-verboseCallSite = verboseFlag VCallSite---- | Turn on verbose call-stack printing when we log.-verboseCallStack :: Verbosity -> Verbosity-verboseCallStack = verboseFlag VCallStack---- | Turn on @-----BEGIN CABAL OUTPUT-----@ markers for output--- from Cabal (as opposed to GHC, or system dependent).-verboseMarkOutput :: Verbosity -> Verbosity-verboseMarkOutput = verboseFlag VMarkOutput---- | Turn off marking; useful for suppressing nondeterministic output.-verboseUnmarkOutput :: Verbosity -> Verbosity-verboseUnmarkOutput = verboseNoFlag VMarkOutput---- | Disable line-wrapping for log messages.-verboseNoWrap :: Verbosity -> Verbosity-verboseNoWrap = verboseFlag VNoWrap---- | Mark the verbosity as quiet-verboseQuiet :: Verbosity -> Verbosity-verboseQuiet v = v { vQuiet = True }---- | Turn on timestamps for log messages.-verboseTimestamp :: Verbosity -> Verbosity-verboseTimestamp = verboseFlag VTimestamp---- | Turn off timestamps for log messages.-verboseNoTimestamp :: Verbosity -> Verbosity-verboseNoTimestamp = verboseNoFlag VTimestamp---- | Turn on timestamps for log messages.------ @since 3.4.0.0-verboseStderr :: Verbosity -> Verbosity-verboseStderr = verboseFlag VStderr---- | Turn off timestamps for log messages.------ @since 3.4.0.0-verboseNoStderr :: Verbosity -> Verbosity-verboseNoStderr = verboseNoFlag VStderr---- | Helper function for flag enabling functions-verboseFlag :: VerbosityFlag -> (Verbosity -> Verbosity)-verboseFlag flag v = v { vFlags = Set.insert flag (vFlags v) }---- | Helper function for flag disabling functions-verboseNoFlag :: VerbosityFlag -> (Verbosity -> Verbosity)-verboseNoFlag flag v = v { vFlags = Set.delete flag (vFlags v) }---- | Turn off all flags-verboseNoFlags :: Verbosity -> Verbosity-verboseNoFlags v = v { vFlags = Set.empty }--verboseHasFlags :: Verbosity -> Bool-verboseHasFlags = not . Set.null . vFlags---- | Test if we should output call sites when we log.-isVerboseCallSite :: Verbosity -> Bool-isVerboseCallSite = isVerboseFlag VCallSite---- | Test if we should output call stacks when we log.-isVerboseCallStack :: Verbosity -> Bool-isVerboseCallStack = isVerboseFlag VCallStack---- | Test if we should output markets.-isVerboseMarkOutput :: Verbosity -> Bool-isVerboseMarkOutput = isVerboseFlag VMarkOutput---- | Test if line-wrapping is disabled for log messages.-isVerboseNoWrap :: Verbosity -> Bool-isVerboseNoWrap = isVerboseFlag VNoWrap---- | Test if we had called 'lessVerbose' on the verbosity-isVerboseQuiet :: Verbosity -> Bool-isVerboseQuiet = vQuiet---- | Test if we should output timestamps when we log.-isVerboseTimestamp :: Verbosity -> Bool-isVerboseTimestamp = isVerboseFlag VTimestamp---- | Test if we should output to stderr when we log.------ @since 3.4.0.0-isVerboseStderr :: Verbosity -> Bool-isVerboseStderr = isVerboseFlag VStderr---- | Helper function for flag testing functions.-isVerboseFlag :: VerbosityFlag -> Verbosity -> Bool-isVerboseFlag flag = (Set.member flag) . vFlags---- $setup--- >>> import Test.QuickCheck (Arbitrary (..), arbitraryBoundedEnum)--- >>> instance Arbitrary VerbosityLevel where arbitrary = arbitraryBoundedEnum--- >>> instance Arbitrary Verbosity where arbitrary = fmap mkVerbosity arbitrary
− Distribution/Verbosity/Internal.hs
@@ -1,27 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.Verbosity.Internal- ( VerbosityLevel(..)- , VerbosityFlag(..)- ) where--import Prelude ()-import Distribution.Compat.Prelude--data VerbosityLevel = Silent | Normal | Verbose | Deafening- deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable)--instance Binary VerbosityLevel-instance Structured VerbosityLevel--data VerbosityFlag- = VCallStack- | VCallSite- | VNoWrap- | VMarkOutput- | VTimestamp- | VStderr -- ^ @since 3.4.0.0- deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable)--instance Binary VerbosityFlag-instance Structured VerbosityFlag
− Distribution/Version.hs
@@ -1,178 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Version--- Copyright : Isaac Jones, Simon Marlow 2003-2004--- Duncan Coutts 2008--- License : BSD3------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ Exports the 'Version' type along with a parser and pretty printer. A version--- is something like @\"1.3.3\"@. It also defines the 'VersionRange' data--- types. Version ranges are like @\">= 1.2 && < 2\"@.--module Distribution.Version (- -- * Package versions- Version,- version0,- mkVersion,- mkVersion',- versionNumbers,- nullVersion,- alterVersion,-- -- * Version ranges- VersionRange,-- -- ** Constructing- anyVersion, noVersion,- thisVersion, notThisVersion,- laterVersion, earlierVersion,- orLaterVersion, orEarlierVersion,- unionVersionRanges, intersectVersionRanges,- differenceVersionRanges,- invertVersionRange,- withinVersion,- majorBoundVersion,-- -- ** Inspection- withinRange,- isAnyVersion,- isNoVersion,- isSpecificVersion,- simplifyVersionRange,- foldVersionRange,- normaliseVersionRange,- stripParensVersionRange,- hasUpperBound,- hasLowerBound,-- -- ** Cata & ana- VersionRangeF (..),- cataVersionRange,- anaVersionRange,- hyloVersionRange,- projectVersionRange,- embedVersionRange,-- -- ** Utilities- wildcardUpperBound,- majorUpperBound,-- -- ** Modification- removeUpperBound,- removeLowerBound,-- -- * Version intervals view- asVersionIntervals,- VersionInterval,- LowerBound(..),- UpperBound(..),- Bound(..),-- -- ** 'VersionIntervals' abstract type- -- | The 'VersionIntervals' type and the accompanying functions are exposed- -- primarily for completeness and testing purposes. In practice- -- 'asVersionIntervals' is the main function to use to- -- view a 'VersionRange' as a bunch of 'VersionInterval's.- --- VersionIntervals,- toVersionIntervals,- fromVersionIntervals,- withinIntervals,- versionIntervals,- mkVersionIntervals,- unionVersionIntervals,- intersectVersionIntervals,- invertVersionIntervals-- ) where--import Distribution.Types.Version-import Distribution.Types.VersionRange-import Distribution.Types.VersionInterval------------------------------------------------------------------------------------ Utilities on VersionRange requiring VersionInterval------------------------------------------------------------------------------------ | This is the converse of 'isAnyVersion'. It check if the version range is--- empty, if there is no possible version that satisfies the version range.------ For example this is @True@ (for all @v@):------ > isNoVersion (EarlierVersion v `IntersectVersionRanges` LaterVersion v)----isNoVersion :: VersionRange -> Bool-isNoVersion vr = case asVersionIntervals vr of- [] -> True- _ -> False---- | Is this version range in fact just a specific version?------ For example the version range @\">= 3 && <= 3\"@ contains only the version--- @3@.----isSpecificVersion :: VersionRange -> Maybe Version-isSpecificVersion vr = case asVersionIntervals vr of- [(LowerBound v InclusiveBound- ,UpperBound v' InclusiveBound)]- | v == v' -> Just v- _ -> Nothing---- | Simplify a 'VersionRange' expression. For non-empty version ranges--- this produces a canonical form. Empty or inconsistent version ranges--- are left as-is because that provides more information.------ If you need a canonical form use--- @fromVersionIntervals . toVersionIntervals@------ It satisfies the following properties:------ > withinRange v (simplifyVersionRange r) = withinRange v r------ > withinRange v r = withinRange v r'--- > ==> simplifyVersionRange r = simplifyVersionRange r'--- > || isNoVersion r--- > || isNoVersion r'----simplifyVersionRange :: VersionRange -> VersionRange-simplifyVersionRange vr- -- If the version range is inconsistent then we just return the- -- original since that has more information than ">1 && < 1", which- -- is the canonical inconsistent version range.- | null (versionIntervals vi) = vr- | otherwise = fromVersionIntervals vi- where- vi = toVersionIntervals vr---- | The difference of two version ranges------ > withinRange v' (differenceVersionRanges vr1 vr2)--- > = withinRange v' vr1 && not (withinRange v' vr2)------ @since 1.24.1.0-differenceVersionRanges :: VersionRange -> VersionRange -> VersionRange-differenceVersionRanges vr1 vr2 =- intersectVersionRanges vr1 (invertVersionRange vr2)---- | The inverse of a version range------ > withinRange v' (invertVersionRange vr)--- > = not (withinRange v' vr)----invertVersionRange :: VersionRange -> VersionRange-invertVersionRange =- fromVersionIntervals . invertVersionIntervals . toVersionIntervals---- | Given a version range, remove the highest upper bound. Example: @(>= 1 && <--- 3) || (>= 4 && < 5)@ is converted to @(>= 1 && < 3) || (>= 4)@.-removeUpperBound :: VersionRange -> VersionRange-removeUpperBound = fromVersionIntervals . relaxLastInterval . toVersionIntervals---- | Given a version range, remove the lowest lower bound.--- Example: @(>= 1 && < 3) || (>= 4 && < 5)@ is converted to--- @(>= 0 && < 3) || (>= 4 && < 5)@.-removeLowerBound :: VersionRange -> VersionRange-removeLowerBound = fromVersionIntervals . relaxHeadInterval . toVersionIntervals
− Distribution/ZinzaPrelude.hs
@@ -1,43 +0,0 @@--- | A small prelude used in @zinza@ generated--- template modules.-module Distribution.ZinzaPrelude (- Writer,- execWriter,- tell,- -- * Re-exports- forM_,- Generic,- PackageName,- Version,- prettyShow- ) where--import Distribution.Compat.Prelude-import Prelude ()--import Control.Monad (forM_)-import Distribution.Pretty (prettyShow)-import Distribution.Types.PackageName (PackageName)-import Distribution.Types.Version (Version)--newtype Writer a = W { unW :: ShowS -> (ShowS, a) }--instance Functor Writer where- fmap = liftM--instance Applicative Writer where- pure x = W $ \ss -> (ss, x)- (<*>) = ap--instance Monad Writer where- return = pure- m >>= k = W $ \s1 ->- let (s2, x) = unW m s1- in unW (k x) s2- {-# INLINE (>>=) #-}--execWriter :: Writer a -> String-execWriter w = fst (unW w id) ""--tell :: String -> Writer ()-tell s = W $ \s' -> (s' . showString s, ())
− Language/Haskell/Extension.hs
@@ -1,919 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}---------------------------------------------------------------------------------- |--- Module : Language.Haskell.Extension--- Copyright : Isaac Jones 2003-2004--- License : BSD3------ Maintainer : libraries@haskell.org--- Portability : portable------ Haskell language dialects and extensions--module Language.Haskell.Extension (- Language(..),- knownLanguages,- classifyLanguage,-- Extension(..),- KnownExtension(..),- deprecatedExtensions,- classifyExtension,- ) where--import qualified Prelude (head)-import Distribution.Compat.Prelude--import Data.Array (Array, accumArray, bounds, Ix(inRange), (!))--import Distribution.Parsec-import Distribution.Pretty--import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp---- --------------------------------------------------------------- * Language--- ---------------------------------------------------------------- | This represents a Haskell language dialect.------ Language 'Extension's are interpreted relative to one of these base--- languages.----data Language =-- -- | The Haskell 98 language as defined by the Haskell 98 report.- -- <http://haskell.org/onlinereport/>- Haskell98-- -- | The Haskell 2010 language as defined by the Haskell 2010 report.- -- <http://www.haskell.org/onlinereport/haskell2010>- | Haskell2010-- -- | An unknown language, identified by its name.- | UnknownLanguage String- deriving (Generic, Show, Read, Eq, Typeable, Data)--instance Binary Language-instance Structured Language--instance NFData Language where rnf = genericRnf--knownLanguages :: [Language]-knownLanguages = [Haskell98, Haskell2010]--instance Pretty Language where- pretty (UnknownLanguage other) = Disp.text other- pretty other = Disp.text (show other)--instance Parsec Language where- parsec = classifyLanguage <$> P.munch1 isAlphaNum--classifyLanguage :: String -> Language-classifyLanguage = \str -> case lookup str langTable of- Just lang -> lang- Nothing -> UnknownLanguage str- where- langTable = [ (show lang, lang)- | lang <- knownLanguages ]---- --------------------------------------------------------------- * Extension--- ---------------------------------------------------------------- Note: if you add a new 'KnownExtension':------ * also add it to the Distribution.Simple.X.languageExtensions lists--- (where X is each compiler: GHC, UHC, HaskellSuite)------ | This represents language extensions beyond a base 'Language' definition--- (such as 'Haskell98') that are supported by some implementations, usually--- in some special mode.------ Where applicable, references are given to an implementation's--- official documentation.--data Extension =- -- | Enable a known extension- EnableExtension KnownExtension-- -- | Disable a known extension- | DisableExtension KnownExtension-- -- | An unknown extension, identified by the name of its @LANGUAGE@- -- pragma.- | UnknownExtension String-- deriving (Generic, Show, Read, Eq, Ord, Typeable, Data)--instance Binary Extension-instance Structured Extension--instance NFData Extension where rnf = genericRnf--data KnownExtension =-- -- | Allow overlapping class instances, provided there is a unique- -- most specific instance for each use.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XOverlappingInstances>- OverlappingInstances-- -- | Ignore structural rules guaranteeing the termination of class- -- instance resolution. Termination is guaranteed by a fixed-depth- -- recursion stack, and compilation may fail if this depth is- -- exceeded.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XUndecidableInstances>- | UndecidableInstances-- -- | Implies 'OverlappingInstances'. Allow the implementation to- -- choose an instance even when it is possible that further- -- instantiation of types will lead to a more specific instance- -- being applicable.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XIncoherentInstances>- | IncoherentInstances-- -- | /(deprecated)/ Deprecated in favour of 'RecursiveDo'.- --- -- Old description: Allow recursive bindings in @do@ blocks, using- -- the @rec@ keyword. See also 'RecursiveDo'.- | DoRec-- -- | Allow recursive bindings in @do@ blocks, using the @rec@- -- keyword, or @mdo@, a variant of @do@.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRecursiveDo>- | RecursiveDo-- -- | Provide syntax for writing list comprehensions which iterate- -- over several lists together, like the 'zipWith' family of- -- functions.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XParallelListComp>- | ParallelListComp-- -- | Allow multiple parameters in a type class.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMultiParamTypeClasses>- | MultiParamTypeClasses-- -- | Enable the dreaded monomorphism restriction.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNoMonomorphismRestriction>- | MonomorphismRestriction-- -- | Allow a specification attached to a multi-parameter type class- -- which indicates that some parameters are entirely determined by- -- others. The implementation will check that this property holds- -- for the declared instances, and will use this property to reduce- -- ambiguity in instance resolution.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XFunctionalDependencies>- | FunctionalDependencies-- -- | /(deprecated)/ A synonym for 'RankNTypes'.- --- -- Old description: Like 'RankNTypes' but does not allow a- -- higher-rank type to itself appear on the left of a function- -- arrow.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRank2Types>- | Rank2Types-- -- | Allow a universally-quantified type to occur on the left of a- -- function arrow.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRankNTypes>- | RankNTypes-- -- | /(deprecated)/ A synonym for 'RankNTypes'.- --- -- Old description: Allow data constructors to have polymorphic- -- arguments. Unlike 'RankNTypes', does not allow this for ordinary- -- functions.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#arbitrary-rank-polymorphism>- | PolymorphicComponents-- -- | Allow existentially-quantified data constructors.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XExistentialQuantification>- | ExistentialQuantification-- -- | Cause a type variable in a signature, which has an explicit- -- @forall@ quantifier, to scope over the definition of the- -- accompanying value declaration.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XScopedTypeVariables>- | ScopedTypeVariables-- -- | Deprecated, use 'ScopedTypeVariables' instead.- | PatternSignatures-- -- | Enable implicit function parameters with dynamic scope.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XImplicitParams>- | ImplicitParams-- -- | Relax some restrictions on the form of the context of a type- -- signature.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XFlexibleContexts>- | FlexibleContexts-- -- | Relax some restrictions on the form of the context of an- -- instance declaration.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XFlexibleInstances>- | FlexibleInstances-- -- | Allow data type declarations with no constructors.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XEmptyDataDecls>- | EmptyDataDecls-- -- | Run the C preprocessor on Haskell source code.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#language-pragma>- | CPP-- -- | Allow an explicit kind signature giving the kind of types over- -- which a type variable ranges.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XKindSignatures>- | KindSignatures-- -- | Enable a form of pattern which forces evaluation before an- -- attempted match, and a form of strict @let@/@where@ binding.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XBangPatterns>- | BangPatterns-- -- | Allow type synonyms in instance heads.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTypeSynonymInstances>- | TypeSynonymInstances-- -- | Enable Template Haskell, a system for compile-time- -- metaprogramming.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTemplateHaskell>- | TemplateHaskell-- -- | Enable the Foreign Function Interface. In GHC, implements the- -- standard Haskell 98 Foreign Function Interface Addendum, plus- -- some GHC-specific extensions.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#language-pragma>- | ForeignFunctionInterface-- -- | Enable arrow notation.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XArrows>- | Arrows-- -- | /(deprecated)/ Enable generic type classes, with default instances defined in- -- terms of the algebraic structure of a type.- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#generic-classes>- | Generics-- -- | Enable the implicit importing of the module "Prelude". When- -- disabled, when desugaring certain built-in syntax into ordinary- -- identifiers, use whatever is in scope rather than the "Prelude"- -- -- version.- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#rebindable-syntax-and-the-implicit-prelude-import>- | ImplicitPrelude-- -- | Enable syntax for implicitly binding local names corresponding- -- to the field names of a record. Puns bind specific names, unlike- -- 'RecordWildCards'.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNamedFieldPuns>- | NamedFieldPuns-- -- | Enable a form of guard which matches a pattern and binds- -- variables.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPatternGuards>- | PatternGuards-- -- | Allow a type declared with @newtype@ to use @deriving@ for any- -- class with an instance for the underlying type.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XGeneralizedNewtypeDeriving>- | GeneralizedNewtypeDeriving-- -- Synonym for GeneralizedNewtypeDeriving added in GHC 8.6.1.- | GeneralisedNewtypeDeriving-- -- | Enable the \"Trex\" extensible records system.- --- -- * <http://haskell.org/hugs/pages/users_guide/hugs-only.html#TREX>- | ExtensibleRecords-- -- | Enable type synonyms which are transparent in some definitions- -- and opaque elsewhere, as a way of implementing abstract- -- datatypes.- --- -- * <http://haskell.org/hugs/pages/users_guide/restricted-synonyms.html>- | RestrictedTypeSynonyms-- -- | Enable an alternate syntax for string literals,- -- with string templating.- --- -- * <http://haskell.org/hugs/pages/users_guide/here-documents.html>- | HereDocuments-- -- | Allow the character @#@ as a postfix modifier on identifiers.- -- Also enables literal syntax for unboxed values.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMagicHash>- | MagicHash-- -- | Allow data types and type synonyms which are indexed by types,- -- i.e. ad-hoc polymorphism for types.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTypeFamilies>- | TypeFamilies-- -- | Allow a standalone declaration which invokes the type class- -- @deriving@ mechanism.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XStandaloneDeriving>- | StandaloneDeriving-- -- | Allow certain Unicode characters to stand for certain ASCII- -- character sequences, e.g. keywords and punctuation.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XUnicodeSyntax>- | UnicodeSyntax-- -- | Allow the use of unboxed types as foreign types, e.g. in- -- @foreign import@ and @foreign export@.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#language-options>- | UnliftedFFITypes-- -- | Enable interruptible FFI.- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/ffi-chap.html#interruptible-foreign-calls>- | InterruptibleFFI-- -- | Allow use of CAPI FFI calling convention (@foreign import capi@).- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/ffi-chap.html#the-capi-calling-convention>- | CApiFFI-- -- | Defer validity checking of types until after expanding type- -- synonyms, relaxing the constraints on how synonyms may be used.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XLiberalTypeSynonyms>- | LiberalTypeSynonyms-- -- | Allow the name of a type constructor, type class, or type- -- variable to be an infix operator.- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTypeOperators>- | TypeOperators-- -- | Enable syntax for implicitly binding local names corresponding- -- to the field names of a record. A wildcard binds all unmentioned- -- names, unlike 'NamedFieldPuns'.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRecordWildCards>- | RecordWildCards-- -- | Deprecated, use 'NamedFieldPuns' instead.- | RecordPuns-- -- | Allow a record field name to be disambiguated by the type of- -- the record it's in.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDisambiguateRecordFields>- | DisambiguateRecordFields-- -- | Enable traditional record syntax (as supported by Haskell 98)- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#traditional-record-syntax>- | TraditionalRecordSyntax-- -- | Enable overloading of string literals using a type class, much- -- like integer literals.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XOverloadedStrings>- | OverloadedStrings-- -- | Enable generalized algebraic data types, in which type- -- variables may be instantiated on a per-constructor basis. Implies- -- 'GADTSyntax'.- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#generalised-algebraic-data-types-gadts>- | GADTs-- -- | Enable GADT syntax for declaring ordinary algebraic datatypes.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XGADTSyntax>- | GADTSyntax-- -- | /(deprecated)/ Has no effect.- --- -- Old description: Make pattern bindings monomorphic.- --- -- * <https://downloads.haskell.org/~ghc/7.6.3/docs/html/users_guide/monomorphism.html>- | MonoPatBinds-- -- | Relax the requirements on mutually-recursive polymorphic- -- functions.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRelaxedPolyRec>- | RelaxedPolyRec-- -- | Allow default instantiation of polymorphic types in more- -- situations.- --- -- * <http://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#type-defaulting-in-ghci>- | ExtendedDefaultRules-- -- | Enable unboxed tuples.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XUnboxedTuples>- | UnboxedTuples-- -- | Enable @deriving@ for classes 'Data.Typeable.Typeable' and- -- 'Data.Generics.Data'.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveDataTypeable>- | DeriveDataTypeable-- -- | Enable @deriving@ for 'GHC.Generics.Generic' and 'GHC.Generics.Generic1'.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveGeneric>- | DeriveGeneric-- -- | Enable support for default signatures.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDefaultSignatures>- | DefaultSignatures-- -- | Allow type signatures to be specified in instance declarations.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XInstanceSigs>- | InstanceSigs-- -- | Allow a class method's type to place additional constraints on- -- a class type variable.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XConstrainedClassMethods>- | ConstrainedClassMethods-- -- | Allow imports to be qualified by the package name the module is- -- intended to be imported from, e.g.- --- -- > import "network" Network.Socket- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPackageImports>- | PackageImports-- -- | /(deprecated)/ Allow a type variable to be instantiated at a- -- polymorphic type.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XImpredicativeTypes>- | ImpredicativeTypes-- -- | /(deprecated)/ Change the syntax for qualified infix operators.- --- -- * <http://www.haskell.org/ghc/docs/6.12.3/html/users_guide/syntax-extns.html#new-qualified-operators>- | NewQualifiedOperators-- -- | Relax the interpretation of left operator sections to allow- -- unary postfix operators.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPostfixOperators>- | PostfixOperators-- -- | Enable quasi-quotation, a mechanism for defining new concrete- -- syntax for expressions and patterns.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XQuasiQuotes>- | QuasiQuotes-- -- | Enable generalized list comprehensions, supporting operations- -- such as sorting and grouping.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTransformListComp>- | TransformListComp-- -- | Enable monad comprehensions, which generalise the list- -- comprehension syntax to work for any monad.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMonadComprehensions>- | MonadComprehensions-- -- | Enable view patterns, which match a value by applying a- -- function and matching on the result.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XViewPatterns>- | ViewPatterns-- -- | Allow concrete XML syntax to be used in expressions and patterns,- -- as per the Haskell Server Pages extension language:- -- <http://www.haskell.org/haskellwiki/HSP>. The ideas behind it are- -- discussed in the paper \"Haskell Server Pages through Dynamic Loading\"- -- by Niklas Broberg, from Haskell Workshop '05.- | XmlSyntax-- -- | Allow regular pattern matching over lists, as discussed in the- -- paper \"Regular Expression Patterns\" by Niklas Broberg, Andreas Farre- -- and Josef Svenningsson, from ICFP '04.- | RegularPatterns-- -- | Enable the use of tuple sections, e.g. @(, True)@ desugars into- -- @\x -> (x, True)@.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTupleSections>- | TupleSections-- -- | Allow GHC primops, written in C--, to be imported into a Haskell- -- file.- | GHCForeignImportPrim-- -- | Support for patterns of the form @n + k@, where @k@ is an- -- integer literal.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNPlusKPatterns>- | NPlusKPatterns-- -- | Improve the layout rule when @if@ expressions are used in a @do@- -- block.- | DoAndIfThenElse-- -- | Enable support for multi-way @if@-expressions.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMultiWayIf>- | MultiWayIf-- -- | Enable support lambda-@case@ expressions.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XLambdaCase>- | LambdaCase-- -- | Makes much of the Haskell sugar be desugared into calls to the- -- function with a particular name that is in scope.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRebindableSyntax>- | RebindableSyntax-- -- | Make @forall@ a keyword in types, which can be used to give the- -- generalisation explicitly.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XExplicitForAll>- | ExplicitForAll-- -- | Allow contexts to be put on datatypes, e.g. the @Eq a@ in- -- @data Eq a => Set a = NilSet | ConsSet a (Set a)@.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDatatypeContexts>- | DatatypeContexts-- -- | Local (@let@ and @where@) bindings are monomorphic.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMonoLocalBinds>- | MonoLocalBinds-- -- | Enable @deriving@ for the 'Data.Functor.Functor' class.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveFunctor>- | DeriveFunctor-- -- | Enable @deriving@ for the 'Data.Traversable.Traversable' class.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveTraversable>- | DeriveTraversable-- -- | Enable @deriving@ for the 'Data.Foldable.Foldable' class.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveFoldable>- | DeriveFoldable-- -- | Enable non-decreasing indentation for @do@ blocks.- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/bugs.html#context-free-syntax>- | NondecreasingIndentation-- -- | Allow imports to be qualified with a safe keyword that requires- -- the imported module be trusted as according to the Safe Haskell- -- definition of trust.- --- -- > import safe Network.Socket- --- -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#safe-imports>- | SafeImports-- -- | Compile a module in the Safe, Safe Haskell mode -- a restricted- -- form of the Haskell language to ensure type safety.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/safe_haskell.html#ghc-flag--XSafe>- | Safe-- -- | Compile a module in the Trustworthy, Safe Haskell mode -- no- -- restrictions apply but the module is marked as trusted as long as- -- the package the module resides in is trusted.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/safe_haskell.html#ghc-flag--XTrustworthy>- | Trustworthy-- -- | Compile a module in the Unsafe, Safe Haskell mode so that- -- modules compiled using Safe, Safe Haskell mode can't import it.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/safe_haskell.html#ghc-flag--XUnsafe>- | Unsafe-- -- | Allow type class/implicit parameter/equality constraints to be- -- used as types with the special kind constraint. Also generalise- -- the @(ctxt => ty)@ syntax so that any type of kind constraint can- -- occur before the arrow.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XConstraintKinds>- | ConstraintKinds-- -- | Enable kind polymorphism.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPolyKinds>- | PolyKinds-- -- | Enable datatype promotion.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDataKinds>- | DataKinds-- -- | Enable parallel arrays syntax (@[:@, @:]@) for /Data Parallel Haskell/.- --- -- * <http://www.haskell.org/haskellwiki/GHC/Data_Parallel_Haskell>- | ParallelArrays-- -- | Enable explicit role annotations, like in (@type role Foo representational representational@).- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRoleAnnotations>- | RoleAnnotations-- -- | Enable overloading of list literals, arithmetic sequences and- -- list patterns using the 'IsList' type class.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XOverloadedLists>- | OverloadedLists-- -- | Enable case expressions that have no alternatives. Also applies to lambda-case expressions if they are enabled.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XEmptyCase>- | EmptyCase-- -- | /(deprecated)/ Deprecated in favour of 'DeriveDataTypeable'.- --- -- Old description: Triggers the generation of derived 'Typeable'- -- instances for every datatype and type class declaration.- --- -- * <https://haskell.org/ghc/docs/7.8.4/html/users_guide/deriving.html#auto-derive-typeable>- | AutoDeriveTypeable-- -- | Desugars negative literals directly (without using negate).- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNegativeLiterals>- | NegativeLiterals-- -- | Allow the use of binary integer literal syntax (e.g. @0b11001001@ to denote @201@).- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XBinaryLiterals>- | BinaryLiterals-- -- | Allow the use of floating literal syntax for all instances of 'Num', including 'Int' and 'Integer'.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNumDecimals>- | NumDecimals-- -- | Enable support for type classes with no type parameter.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNullaryTypeClasses>- | NullaryTypeClasses-- -- | Enable explicit namespaces in module import/export lists.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XExplicitNamespaces>- | ExplicitNamespaces-- -- | Allow the user to write ambiguous types, and the type inference engine to infer them.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XAllowAmbiguousTypes>- | AllowAmbiguousTypes-- -- | Enable @foreign import javascript@.- | JavaScriptFFI-- -- | Allow giving names to and abstracting over patterns.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPatternSynonyms>- | PatternSynonyms-- -- | Allow anonymous placeholders (underscore) inside type signatures. The- -- type inference engine will generate a message describing the type inferred- -- at the hole's location.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPartialTypeSignatures>- | PartialTypeSignatures-- -- | Allow named placeholders written with a leading underscore inside type- -- signatures. Wildcards with the same name unify to the same type.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNamedWildCards>- | NamedWildCards-- -- | Enable @deriving@ for any class.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveAnyClass>- | DeriveAnyClass-- -- | Enable @deriving@ for the 'Language.Haskell.TH.Syntax.Lift' class.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveLift>- | DeriveLift-- -- | Enable support for 'static pointers' (and the @static@- -- keyword) to refer to globally stable names, even across- -- different programs.- --- -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XStaticPointers>- | 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 @~@.- --- -- * <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#ghc-flag--XStrictData>- | 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@.- --- -- * <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#ghc-flag--XStrict>- | 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 undecidable) 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 quoting.- | TemplateHaskellQuotes-- -- | Allows use of the @#label@ syntax.- | OverloadedLabels-- -- | Allow functional dependency annotations on type families to declare them- -- as injective.- | TypeFamilyDependencies-- -- | Allow multiple @deriving@ clauses, each optionally qualified with a- -- /strategy/.- | DerivingStrategies-- -- | Enable deriving instances via types of the same runtime representation.- -- Implies 'DerivingStrategies'.- | DerivingVia-- -- | Enable the use of unboxed sum syntax.- | UnboxedSums-- -- | Allow use of hexadecimal literal notation for floating-point values.- | HexFloatLiterals-- -- | Allow @do@ blocks etc. in argument position.- | BlockArguments-- -- | Allow use of underscores in numeric literals.- | NumericUnderscores-- -- | Allow @forall@ in constraints.- | QuantifiedConstraints-- -- | Have @*@ refer to @Type@.- | StarIsType-- -- | Liberalises deriving to provide instances for empty data types.- --- -- * <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#deriving-instances-for-empty-data-types>- | EmptyDataDeriving-- -- | Enable detection of complete user-supplied kind signatures.- | CUSKs-- -- | Allows the syntax @import M qualified@.- | ImportQualifiedPost-- -- | Allow the use of standalone kind signatures.- | StandaloneKindSignatures-- -- | Enable unlifted newtypes.- | UnliftedNewtypes-- -- | Use whitespace to determine whether the minus sign stands for negation or subtraction.- | LexicalNegation-- -- | Enable qualified do-notation desugaring.- | QualifiedDo-- -- | Enable linear types.- | LinearTypes-- deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable, Data)--instance Binary KnownExtension-instance Structured KnownExtension--instance NFData KnownExtension where rnf = genericRnf---- | Extensions that have been deprecated, possibly paired with another--- extension that replaces it.----deprecatedExtensions :: [(Extension, Maybe Extension)]-deprecatedExtensions =- [ (EnableExtension RecordPuns, Just (EnableExtension NamedFieldPuns))- , (EnableExtension PatternSignatures, Just (EnableExtension ScopedTypeVariables))- ]--- NOTE: when adding deprecated extensions that have new alternatives--- we must be careful to make sure that the deprecation messages are--- valid. We must not recommend aliases that cannot be used with older--- compilers, perhaps by adding support in Cabal to translate the new--- name to the old one for older compilers. Otherwise we are in danger--- of the scenario in ticket #689.--instance Pretty Extension where- pretty (UnknownExtension other) = Disp.text other- pretty (EnableExtension ke) = Disp.text (show ke)- pretty (DisableExtension ke) = Disp.text ("No" ++ show ke)--instance Parsec Extension where- parsec = classifyExtension <$> P.munch1 isAlphaNum--instance Pretty KnownExtension where- pretty ke = Disp.text (show ke)--classifyExtension :: String -> Extension-classifyExtension string- = case classifyKnownExtension string of- Just ext -> EnableExtension ext- Nothing ->- case string of- 'N':'o':string' ->- case classifyKnownExtension string' of- Just ext -> DisableExtension ext- Nothing -> UnknownExtension string- _ -> UnknownExtension string---- | 'read' for 'KnownExtension's is really really slow so for the Text--- instance--- what we do is make a simple table indexed off the first letter in the--- extension name. The extension names actually cover the range @'A'-'Z'@--- pretty densely and the biggest bucket is 7 so it's not too bad. We just do--- a linear search within each bucket.------ This gives an order of magnitude improvement in parsing speed, and it'll--- also allow us to do case insensitive matches in future if we prefer.----classifyKnownExtension :: String -> Maybe KnownExtension-classifyKnownExtension "" = Nothing-classifyKnownExtension string@(c : _)- | inRange (bounds knownExtensionTable) c- = lookup string (knownExtensionTable ! c)- | otherwise = Nothing--knownExtensionTable :: Array Char [(String, KnownExtension)]-knownExtensionTable =- accumArray (flip (:)) [] ('A', 'Z')- [ (Prelude.head str, (str, extension)) -- assume KnownExtension's Show returns a non-empty string- | extension <- [toEnum 0 ..]- , let str = show extension ]
README.md view
@@ -8,108 +8,6 @@ [cabal-install]: ../cabal-install/README.md -Installing the Cabal library-============================--If you already have the `cabal` program------------------------------------------In this case run:-- $ cabal install--However, if you do not have an existing version of the `cabal` program,-you first must install the Cabal library. To avoid this bootstrapping-problem, you can install the Cabal library directly as described below.---Installing as a user (no root or administrator access)--------------------------------------------------------- ghc -threaded --make Setup- ./Setup configure --user- ./Setup build- ./Setup install--Note the use of the `--user` flag at the configure step.--Compiling 'Setup' rather than using `runghc Setup` is much faster and-works on Windows. For all packages other than Cabal itself, it is fine-to use `runghc`.--This will install into `$HOME/.cabal/` on Unix and into-`Documents and Settings\$User\Application Data\cabal\` on Windows.-If you want to install elsewhere, use the `--prefix=` flag at the-configure step.---Installing as root or Administrator-------------------------------------- ghc -threaded --make Setup- ./Setup configure- ./Setup build- sudo ./Setup install--Compiling Setup rather than using `runghc Setup` is much faster and-works on Windows. For all packages other than Cabal itself, it is fine-to use `runghc`.--This will install into `/usr/local` on Unix, and on Windows it will-install into `$ProgramFiles/Haskell`. If you want to install elsewhere,-use the `--prefix=` flag at the configure step.---Using older versions of GHC and Cabal-======================================--It is recommended that you leave any pre-existing version of Cabal-installed. In particular, it is *essential* you keep the version that-came with GHC itself, since other installed packages require it (for-instance, the "ghc" API package).--Prior to GHC 6.4.2, however, GHC did not deal particularly well with-having multiple versions of packages installed at once. So if you are-using GHC 6.4.1 or older and you have an older version of Cabal-installed, you should probably remove it by running:-- $ ghc-pkg unregister Cabal--or, if you had Cabal installed only for your user account, run:-- $ ghc-pkg unregister Cabal --user--The `filepath` dependency-=========================--Cabal uses the [filepath] package, so it must be installed first.-GHC version 6.6.1 and later come with `filepath`, however, earlier-versions do not by default. If you do not already have `filepath`,-you need to install it. You can use any existing version of Cabal to do-that. If you have neither Cabal nor `filepath`, it is slightly-harder but still possible.--Unpack Cabal and `filepath` into separate directories. For example:-- tar -xzf filepath-1.1.0.0.tar.gz- tar -xzf Cabal-1.6.0.0.tar.gz-- # rename to make the following instructions simpler:- mv filepath-1.1.0.0/ filepath/- mv Cabal-1.6.0.0/ Cabal/-- cd Cabal- ghc -i../filepath -cpp --make Setup.hs -o ../filepath/setup- cd ../filepath/- ./setup configure --user- ./setup build- ./setup install--This installs `filepath` so that you can install Cabal with the normal-method.--[filepath]: http://hackage.haskell.org/package/filepath- More information ================
− doc/README.md
@@ -1,121 +0,0 @@-Cabal documentation-===================--### Where to read it-These docs will be built and deployed whenever a release is made,-and can be read at: https://www.haskell.org/cabal/users-guide/--In addition, the docs are taken directly from git and hosted at:-http://cabal.readthedocs.io/---### How to build it--Building the documentation requires Python 3 be installed-* `> cd Cabal`-* `> make clean users-guide`-* Python on Mac OS X dislikes `LC_CTYPE=UTF-8`, unset the env var in-terminal preferences and instead set `LC_ALL=en_US.UTF-8` or something--### Caveats, for newcomers to RST from MD-RST does not allow you to skip section levels when nesting, like MD-does.-So, you cannot have--```- Section heading- ===============-- Some unimportant block- """"""""""""""""""""""-```-- instead you need to observe order and either promote your block:--```- Section heading- ===============-- Some not quite so important block- ----------------------------------```-- or introduce more subsections:--```- Section heading- ===============-- Subsection- ------------ Subsubsection- ^^^^^^^^^^^^^-- Some unimportant block- """"""""""""""""""""""-```--* RST simply parses a file and interprets headings to indicate the- start of a new block,- * at the level implied by the header's *adornment*, if the adornment was- previously encountered in this file,- * at one level deeper than the previous block, otherwise.-- This means that a lot of confusion can arise when people use- different adornments to signify the same depth in different files.-- To eliminate this confusion, please stick to the adornment order- recommended by the Sphinx team:--```- ####- Part- ####-- *******- Chapter- *******-- Section- =======-- Subsection- ------------ Subsubsection- ^^^^^^^^^^^^^-- Paragraph- """""""""-```--* The Read-The-Docs stylesheet does not support multiple top-level- sections in a file that is linked to from the top-most TOC (in- `index.rst`). It will mess up the sidebar.- E.g. you cannot link to a `cabal.rst` with sections "Introduction",- "Using Cabal", "Epilogue" from `index.rst`.-- One solution is to have a single section, e.g. "All About Cabal", in- `cabal.rst` and make the other blocks subsections of that.-- Another solution is to link via an indirection, e.g. create- `all-about-cabal.rst`, where you include `cabal.rst` using the- `.. toctree::` command and then link to `all-about-cabal.rst` from- `index.rst`.- This will effectively "push down" all blocks by one layer and solve- the problem without having to change `cabal.rst`.---* We use [`extlinks`](http://www.sphinx-doc.org/en/stable/ext/extlinks.html)- to shorten links to commonly referred resources (wiki, issue trackers).-- E.g. you can use the more convenient short syntax-- :issue:`123`-- which is expanded into a hyperlink-- `#123 <https://github.com/haskell/cabal/issues/123>`__-- See `conf.py` for list of currently defined link shorteners.
− doc/bugs-and-stability.rst
@@ -1,6 +0,0 @@-Reporting Bugs and Stability of Cabal Interfaces-================================================--.. toctree::- misc-
− doc/concepts-and-development.rst
@@ -1,7 +0,0 @@-Package Concepts and Development-================================--.. toctree::- :maxdepth: 2-- developing-packages
− doc/conf.py
@@ -1,223 +0,0 @@-# -*- coding: utf-8 -*--#-# GHC Users Guide documentation build configuration file-#-# This file is execfile()d with the current directory set to its-# containing dir.-#-import sys-import os-import sphinx_rtd_theme--# Support for :base-ref:, etc.-sys.path.insert(0, os.path.abspath('.'))-import cabaldomain--version = "3.4.0.0"--extensions = ['sphinx.ext.extlinks', 'sphinx.ext.todo']--templates_path = ['_templates']-source_suffix = '.rst'-source_encoding = 'utf-8-sig'-master_doc = 'index'--# extlinks -- see http://www.sphinx-doc.org/en/stable/ext/extlinks.html-extlinks = {- 'issue': ('https://github.com/haskell/cabal/issues/%s', '#'),-- 'ghc-wiki': ('https://gitlab.haskell.org/ghc/ghc/-/wikis/%s', ''),- 'ghc-ticket': ('https://gitlab.haskell.org/ghc/ghc/-/issues/%s', 'GHC #'),-- 'hackage-pkg': ('http://hackage.haskell.org/package/%s', ''),-}--# General information about the project.-project = u'Cabal'-copyright = u'2003-2020, Cabal Team'-# N.B. version comes from ghc_config-release = version # The full version, including alpha/beta/rc tags.--# Syntax highlighting-highlight_language = 'cabal'-#pygments_style = 'tango'--primary_domain = 'cabal'--# List of patterns, relative to source directory, that match files and-# directories to ignore when looking for source files.-exclude_patterns = ['.build', "*.gen.rst"]--# -- Options for HTML output -----------------------------------------------# on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org-on_rtd = os.environ.get('READTHEDOCS', None) == 'True'--if not on_rtd: # only import and set the theme if we're building docs locally- import sphinx_rtd_theme- html_theme = 'sphinx_rtd_theme'- html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]--# The name for this set of Sphinx documents. If None, it defaults to-# "<project> v<release> documentation".-html_title = "Cabal {} User's Guide".format(release)-html_short_title = "Cabal %s User's Guide" % release-html_logo = 'images/Cabal-dark.png'-html_static_path = ['images']-# Convert quotes and dashes to typographically correct entities-html_use_smartypants = True-html_show_copyright = True-html_context = {- 'source_url_prefix': "https://github.com/haskell/cabal/tree/master/Cabal/doc/",- "display_github": True,- "github_host": "github.com",- "github_user": "haskell",- "github_repo": 'cabal',- "github_version": "master/",- "conf_py_path": "Cabal/doc/",- "source_suffix": '.rst',-}---# If true, an OpenSearch description file will be output, and all pages will-# contain a <link> tag referring to it. The value of this option must be the-# base URL from which the finished HTML is served.-#html_use_opensearch = ''--# This is the file name suffix for HTML files (e.g. ".xhtml").-#html_file_suffix = None--# Output file base name for HTML help builder.-htmlhelp_basename = 'CabalUsersGuide'--# MathJax to use SVG rendering by default-mathjax_path = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS-MML_SVG'---# -- Options for LaTeX output -----------------------------------------------latex_elements = {- 'inputenc': '',- 'utf8extra': '',- 'preamble': r'''-\usepackage{fontspec}-\usepackage{makeidx}-\setsansfont{DejaVu Sans}-\setromanfont{DejaVu Serif}-\setmonofont{DejaVu Sans Mono}-''',-}--# Grouping the document tree into LaTeX files. List of tuples-# (source start file, target name, title,-# author, documentclass [howto, manual, or own class]).-latex_documents = [- ('index', 'users_guide.tex', u'GHC Users Guide Documentation',- u'GHC Team', 'manual'),-]--# The name of an image file (relative to this directory) to place at the top of-# the title page.-#latex_logo = 'images/logo.pdf'-latex_logo = 'images/Cabal-dark.png'--# If true, show page references after internal links.-latex_show_pagerefs = True--# http://www.sphinx-doc.org/en/master/usage/extensions/todo.html-todo_include_todos = True--# -- Options for manual page output -----------------------------------------# One entry per manual page. List of tuples-# (source start file, name, description, authors, manual section).-man_pages = [- ('cabal', 'cabal', 'The Haskell Cabal', 'The Cabal Team', 1)-]--# If true, show URL addresses after external links.-#man_show_urls = False---# -- Options for Texinfo output ---------------------------------------------# Grouping the document tree into Texinfo files. List of tuples-# (source start file, target name, title, author,-# dir menu entry, description, category)-texinfo_documents = [- ('index', 'CabalUsersGuide', u'Cabal Users Guide',- u'Cabal Team', 'CabalUsersGuide', 'The Haskell Cabal.',- 'Compilers'),-]--from sphinx import addnodes-from docutils import nodes--def parse_ghci_cmd(env, sig, signode):- name = sig.split(';')[0]- sig = sig.replace(';', '')- signode += addnodes.desc_name(name, sig)- return name--def parse_flag(env, sig, signode):- import re- names = []- for i, flag in enumerate(sig.split(',')):- flag = flag.strip()- sep = '='- parts = flag.split('=')- if len(parts) == 1:- sep=' '- parts = flag.split()- if len(parts) == 0: continue-- name = parts[0]- names.append(name)- sig = sep + ' '.join(parts[1:])- sig = re.sub(r'<([-a-zA-Z ]+)>', r'⟨\1⟩', sig)- if i > 0:- signode += addnodes.desc_name(', ', ', ')- signode += addnodes.desc_name(name, name)- if len(sig) > 0:- signode += addnodes.desc_addname(sig, sig)-- return names[0]--def setup(app):- from sphinx.util.docfields import Field, TypedField-- increase_python_stack()-- # the :ghci-cmd: directive used in ghci.rst- app.add_object_type('ghci-cmd', 'ghci-cmd',- parse_node=parse_ghci_cmd,- objname='GHCi command',- indextemplate='pair: %s; GHCi command')-- app.add_object_type('ghc-flag', 'ghc-flag',- objname='GHC command-line option',- parse_node=parse_flag,- indextemplate='pair: %s; GHC option',- doc_field_types=[- Field('since', label='Introduced in GHC version', names=['since']),- Field('default', label='Default value', names=['default']),- Field('static')- ])-- app.add_object_type('rts-flag', 'rts-flag',- objname='runtime system command-line option',- parse_node=parse_flag,- indextemplate='pair: %s; RTS option',- doc_field_types=[- Field('since', label='Introduced in GHC version', names=['since']),- ])-- cabaldomain.setup(app)--def increase_python_stack():- # Workaround sphinx-build recursion limit overflow:- # pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)- # RuntimeError: maximum recursion depth exceeded while pickling an object- #- # Default python allows recursion depth of 1000 calls.- sys.setrecursionlimit(10000)
− doc/config-and-install.rst
@@ -1,5 +0,0 @@-Configuration and Installing Packages-=====================================--.. toctree::- installing-packages
− doc/developing-packages.rst
@@ -1,488 +0,0 @@-Quickstart-==========--.. TIP::- If this is your first time using `cabal` you should check out the `Getting Started guide <getting-started.html>`__.--Let's assume we have created a project directory and already have a-Haskell module or two.--Every project needs a name, we'll call this example "proglet".--.. highlight:: console--::-- $ cd proglet/- $ ls- Proglet.hs--It is assumed that (apart from external dependencies) all the files that-make up a package live under a common project root directory. This-simple example has all the project files in one directory, but most-packages will use one or more subdirectories.--To turn this into a Cabal package we need two extra files in the-project's root directory:--- ``proglet.cabal``: containing package metadata and build information.--- ``Setup.hs``: usually containing a few standardized lines of code,- but can be customized if necessary.--We can create both files manually or we can use ``cabal init`` to create-them for us.--Using "cabal init"---------------------The ``cabal init --interactive`` command is interactive. If we answer-"no" to using the "sensible defaults" it asks a number of questions.--::-- $ cabal init --interactive- Should I generate a simple project with sensible defaults? [default: y] n- What does the package build:- 1) Executable- 2) Library- 3) Library and Executable- Your choice?- ...--One of the important questions is whether the package contains a library-and/or an executable. Libraries are collections of Haskell modules that-can be re-used by other Haskell libraries and programs, while executables-are standalone programs.--For the moment these are the only choices. For more complex packages-(e.g. a library and multiple executables or test suites) the ``.cabal``-file can be edited afterwards.--After you make your selection (executable; library; or: library-and executable) cabal asks us a number of questions starting with-which version of the cabal specification to use, our package's name-(for example, "proglet"), and our package's version.--It also asks questions about various other bits of package metadata. For-a package that you never intend to distribute to others, these fields-can be left blank.--Finally, ``cabal init --interactive`` creates the initial ``proglet.cabal``-and ``Setup.hs`` files, and depending on your choice of license, a-``LICENSE`` file as well.--::-- Generating LICENSE...- Generating Setup.hs...- Generating proglet.cabal...-- You may want to edit the .cabal file and add a Description field.--At this stage the ``proglet.cabal`` is not quite complete and before you-are able to build the package you will need to edit the file and add-some build information about the library or executable.--Editing the .cabal file--------------------------.. highlight:: cabal--Load up the ``.cabal`` file in a text editor. The first part of the-``.cabal`` file has the package metadata and towards the end of the file-you will find the :pkg-section:`executable` or :pkg-section:`library` section.--You will see that the fields that have yet to be filled in are commented-out. Cabal files use "``--``" Haskell-style comment syntax. (Note that-comments are only allowed on lines on their own. Trailing comments on-other lines are not allowed because they could be confused with program-options.)--If you selected earlier to create a library package then your ``.cabal``-file will have a section that looks like this:--::-- library- exposed-modules: Proglet- -- other-modules:- -- build-depends:--Alternatively, if you selected an executable then there will be a-section like:--::-- executable proglet- -- main-is:- -- other-modules:- -- build-depends:--The build information fields listed (but commented out) are just the few-most important and common fields. There are many others that are covered-later in this chapter.--Most of the build information fields are the same between libraries and-executables. The difference is that libraries have a number of "exposed"-modules that make up the public interface of the library, while-executables have a file containing a ``Main`` module.--The name of a library always matches the name of the package, so it is-not specified in the library section. Executables often follow the name-of the package too, but this is not required and the name is given-explicitly.--Modules included in the package----------------------------------For a library, ``cabal init`` looks in the project directory for files-that look like Haskell modules and adds all the modules to the-:pkg-field:`library:exposed-modules` field. For modules that do not form part-of your package's public interface, you can move those modules to the-:pkg-field:`other-modules` field. Either way, all modules in the library need-to be listed.--For an executable, ``cabal init`` does not try to guess which file-contains your program's ``Main`` module. You will need to fill in the-:pkg-field:`executable:main-is` field with the file name of your program's-``Main`` module (including ``.hs`` or ``.lhs`` extension). Other modules-included in the executable should be listed in the :pkg-field:`other-modules`-field.--Modules imported from other packages---------------------------------------While your library or executable may include a number of modules, it-almost certainly also imports a number of external modules from the-standard libraries or other pre-packaged libraries. (These other-libraries are of course just Cabal packages that contain a library.)--You have to list all of the library packages that your library or-executable imports modules from. Or to put it another way: you have to-list all the other packages that your package depends on.--For example, suppose the example ``Proglet`` module imports the module-``Data.Map``. The ``Data.Map`` module comes from the ``containers``-package, so we must list it:--::-- library- exposed-modules: Proglet- other-modules:- build-depends: containers, base == 4.*--In addition, almost every package also depends on the ``base`` library-package because it exports the standard ``Prelude`` module plus other-basic modules like ``Data.List``.--You will notice that we have listed ``base == 4.*``. This gives a-constraint on the version of the base package that our package will work-with. The most common kinds of constraints are:--- ``pkgname >= n``-- ``pkgname ^>= n`` (since Cabal 2.0)-- ``pkgname >= n && < m``-- ``pkgname == n.*`` (since Cabal 1.6)--The last is just shorthand, for example ``base == 4.*`` means exactly-the same thing as ``base >= 4 && < 5``. Please refer to the documentation-on the :pkg-field:`build-depends` field for more information.--Also, you can factor out shared ``build-depends`` (and other fields such-as ``ghc-options``) into a ``common`` stanza which you can ``import`` in-your libraries and executable sections. For example:--::-- common shared-properties- default-language: Haskell2010- build-depends:- base == 4.*- ghc-options:- -Wall-- library- import: shared-properties- exposed-modules:- Proglet--Note that the ``import`` **must** be the first thing in the stanza. For more-information see the :ref:`common-stanzas` section.--Building the package-----------------------For simple packages that's it! We can now try configuring and building-the package:--.. code-block:: console-- $ cabal configure- $ cabal build--Assuming those two steps worked then you can also install the package:--.. code-block:: console-- $ cabal install--For libraries this makes them available for use in GHCi or to be used by-other packages. For executables it installs the program so that you can-run it (though you may first need to adjust your system's ``$PATH``).--Next steps-------------What we have covered so far should be enough for very simple packages-that you use on your own system.--The next few sections cover more details needed for more complex-packages and details needed for distributing packages to other people.--The previous chapter covers building and installing packages -- your own-packages or ones developed by other people.--Package concepts-================--Before diving into the details of writing packages it helps to-understand a bit about packages in the Haskell world and the particular-approach that Cabal takes.--The point of packages------------------------Packages are a mechanism for organising and distributing code. Packages-are particularly suited for "programming in the large", that is building-big systems by using and re-using code written by different people at-different times.--People organise code into packages based on functionality and-dependencies. Social factors are also important: most packages have a-single author, or a relatively small team of authors.--Packages are also used for distribution: the idea is that a package can-be created in one place and be moved to a different computer and be-usable in that different environment. There are a surprising number of-details that have to be got right for this to work, and a good package-system helps to simplify this process and make it reliable.--Packages come in two main flavours: libraries of reusable code, and-complete programs. Libraries present a code interface, an API, while-programs can be run directly. In the Haskell world, library packages-expose a set of Haskell modules as their public interface. Cabal-packages can contain a library or executables or both.--Some programming languages have packages as a builtin language concept.-For example in Java, a package provides a local namespace for types and-other definitions. In the Haskell world, packages are not a part of the-language itself. Haskell programs consist of a number of modules, and-packages just provide a way to partition the modules into sets of-related functionality. Thus the choice of module names in Haskell is-still important, even when using packages.--Package names and versions-----------------------------All packages have a name, e.g. "HUnit". Package names are assumed to be-unique. Cabal package names may contain letters, numbers and hyphens,-but not spaces and may also not contain a hyphened section consisting of-only numbers. The namespace for Cabal packages is flat, not-hierarchical.--Packages also have a version, e.g "1.1". This matches the typical way in-which packages are developed. Strictly speaking, each version of a-package is independent, but usually they are very similar. Cabal package-versions follow the conventional numeric style, consisting of a sequence-of digits such as "1.0.1" or "2.0". There are a range of common-conventions for "versioning" packages, that is giving some meaning to-the version number in terms of changes in the package, such as-e.g. `SemVer <http://semver.org>`__; however, for packages intended to be-distributed via Hackage Haskell's `Package Versioning Policy <https://pvp.haskell.org/>`_ applies-(see also the `PVP/SemVer FAQ section <https://pvp.haskell.org/faq/#semver>`__).--The combination of package name and version is called the *package ID*-and is written with a hyphen to separate the name and version, e.g.-"HUnit-1.1".--For Cabal packages, the combination of the package name and version-*uniquely* identifies each package. Or to put it another way: two-packages with the same name and version are considered to *be* the same.--Strictly speaking, the package ID only identifies each Cabal *source*-package; the same Cabal source package can be configured and built in-different ways. There is a separate installed package ID that uniquely-identifies each installed package instance. Most of the time however,-users need not be aware of this detail.--Kinds of package: Cabal vs GHC vs system-------------------------------------------It can be slightly confusing at first because there are various-different notions of package floating around. Fortunately the details-are not very complicated.--Cabal packages- Cabal packages are really source packages. That is they contain- Haskell (and sometimes C) source code.-- Cabal packages can be compiled to produce GHC packages. They can- also be translated into operating system packages.--GHC packages- This is GHC's view on packages. GHC only cares about library- packages, not executables. Library packages have to be registered- with GHC for them to be available in GHCi or to be used when- compiling other programs or packages.-- The low-level tool ``ghc-pkg`` is used to register GHC packages and- to get information on what packages are currently registered.-- You never need to make GHC packages manually. When you build and- install a Cabal package containing a library then it gets registered- with GHC automatically.-- Haskell implementations other than GHC have essentially the same- concept of registered packages. For the most part, Cabal hides the- slight differences.--Operating system packages- On operating systems like Linux and Mac OS X, the system has a- specific notion of a package and there are tools for installing and- managing packages.-- The Cabal package format is designed to allow Cabal packages to be- translated, mostly-automatically, into operating system packages.- They are usually translated 1:1, that is a single Cabal package- becomes a single system package.-- It is also possible to make Windows installers from Cabal packages,- though this is typically done for a program together with all of its- library dependencies, rather than packaging each library separately.--Unit of distribution-----------------------The Cabal package is the unit of distribution. What this means is that-each Cabal package can be distributed on its own in source or binary-form. Of course there may be dependencies between packages, but there is-usually a degree of flexibility in which versions of packages can work-together so distributing them independently makes sense.--It is perhaps easiest to see what being "the unit of distribution"-means by contrast to an alternative approach. Many projects are made up-of several interdependent packages and during development these might-all be kept under one common directory tree and be built and tested-together. When it comes to distribution however, rather than-distributing them all together in a single tarball, it is required that-they each be distributed independently in their own tarballs.--Cabal's approach is to say that if you can specify a dependency on a-package then that package should be able to be distributed-independently. Or to put it the other way round, if you want to-distribute it as a single unit, then it should be a single package.--Explicit dependencies and automatic package management---------------------------------------------------------Cabal takes the approach that all packages dependencies are specified-explicitly and specified in a declarative way. The point is to enable-automatic package management. This means tools like ``cabal`` can-resolve dependencies and install a package plus all of its dependencies-automatically. Alternatively, it is possible to mechanically (or mostly-mechanically) translate Cabal packages into system packages and let the-system package manager install dependencies automatically.--It is important to track dependencies accurately so that packages can-reliably be moved from one system to another system and still be able to-build it there. Cabal is therefore relatively strict about specifying-dependencies. For example Cabal's default build system will not even let-code build if it tries to import a module from a package that isn't-listed in the ``.cabal`` file, even if that package is actually-installed. This helps to ensure that there are no "untracked-dependencies" that could cause the code to fail to build on some other-system.--The explicit dependency approach is in contrast to the traditional-"./configure" approach where instead of specifying dependencies-declaratively, the ``./configure`` script checks if the dependencies are-present on the system. Some manual work is required to transform a-``./configure`` based package into a Linux distribution package (or-similar). This conversion work is usually done by people other than the-package author(s). The practical effect of this is that only the most-popular packages will benefit from automatic package management.-Instead, Cabal forces the original author to specify the dependencies-but the advantage is that every package can benefit from automatic-package management.--The "./configure" approach tends to encourage packages that adapt-themselves to the environment in which they are built, for example by-disabling optional features so that they can continue to work when a-particular dependency is not available. This approach makes sense in a-world where installing additional dependencies is a tiresome manual-process and so minimising dependencies is important. The automatic-package management view is that packages should just declare what they-need and the package manager will take responsibility for ensuring that-all the dependencies are installed.--Sometimes of course optional features and optional dependencies do make-sense. Cabal packages can have optional features and varying-dependencies. These conditional dependencies are still specified in a-declarative way however and remain compatible with automatic package-management. The need to remain compatible with automatic package-management means that Cabal's conditional dependencies system is a bit-less flexible than with the "./configure" approach.--.. note::- `GNU autoconf places restrictions on paths, including the- path that the user builds a package from.- <https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions>`_- Package authors using ``build-type: configure`` should be aware of- these restrictions; because users may be unexpectedly constrained and- face mysterious errors, it is recommended that ``build-type: configure``- is only used where strictly necessary.--Portability--------------One of the purposes of Cabal is to make it easier to build packages on-different platforms (operating systems and CPU architectures), with-different compiler versions and indeed even with different Haskell-implementations. (Yes, there are Haskell implementations other than-GHC!)--Cabal provides abstractions of features present in different Haskell-implementations and wherever possible it is best to take advantage of-these to increase portability. Where necessary however it is possible to-use specific features of specific implementations.--For example a package author can list in the package's ``.cabal`` what-language extensions the code uses. This allows Cabal to figure out if-the language extension is supported by the Haskell implementation that-the user picks. Additionally, certain language extensions such as-Template Haskell require special handling from the build system and by-listing the extension it provides the build system with enough-information to do the right thing.--Another similar example is linking with foreign libraries. Rather than-specifying GHC flags directly, the package author can list the libraries-that are needed and the build system will take care of using the right-flags for the compiler. Additionally this makes it easier for tools to-discover what system C libraries a package needs, which is useful for-tracking dependencies on system libraries (e.g. when translating into-Linux distribution packages).--In fact both of these examples fall into the category of explicitly-specifying dependencies. Not all dependencies are other Cabal packages.-Foreign libraries are clearly another kind of dependency. It's also-possible to think of language extensions as dependencies: the package-depends on a Haskell implementation that supports all those extensions.--Where compiler-specific options are needed however, there is an "escape-hatch" available. The developer can specify implementation-specific-options and more generally there is a configuration mechanism to-customise many aspects of how a package is built depending on the-Haskell implementation, the operating system, computer architecture and-user-specified configuration flags.
− doc/file-format-changelog.rst
@@ -1,236 +0,0 @@-.. _spec-history:--==================================================- Package Description Format Specification History-==================================================--:ref:`pkg-desc` need to specify the version of the-specification they need to be interpreted in via the-:pkg-field:`cabal-version` declaration. The following list describes-changes that occurred in each version of the cabal specification-relative to the respective preceding *published* version.--.. note::-- The sequence of specification version numbers is *not*- contiguous because it's synchronised with the version of the- ``Cabal`` library. As a consequence, only *even* versions are- considered proper published versions of the specification as *odd*- versions of the ``Cabal`` library denote unreleased development- branches which have no stability guarantee.--``cabal-version: 3.4``--------------------------* License fields use identifiers from SPDX License List version- ``3.9 2020-05-15``--* Dependencies to sublibraries have to be specified explicitly,- even for current package.- This way you can have an internal library with the same- name as some external dependency.--* Remove ``-any`` and ``-none`` syntax for version ranges- Use ``>=0`` and ``<0`` respectively.--* :pkg-field:`default-language` is optional.- The Default value is to use the compiler's default language.--* :pkg-field:`mixins` field allow specifying a sublibrary.--``cabal-version: 3.0``-------------------------* Added the :pkg-field:`extra-dynamic-library-flavours` field to specify non-trivial- variants of dynamic flavours. It is :pkg-field:`extra-library-flavours` but for- shared libraries. Mainly useful for GHC's RTS library.--* Free text fields (e.g. :pkg-field:`description`) preserve empty lines- and indentation. In other words, you don't need to add dots for blank lines.--* License fields use identifiers from SPDX License List version- ``3.6 2019-07-10``--* Remove deprecated ``hs-source-dir``, :pkg-field:`extensions` and- :pkg-field:`build-tools` fields.--* Common stanzas are now allowed also in the beginning of conditional- sections. In other words, the following is valid-- ::-- library- import deps-- if flag(foo)- import foo-deps--* Allow redundant leading or trailing commas in package fields with- optional commas, such as :pkg-field:`library:exposed-modules`--* Require fields with optional commas to consistently omit or place- commas between elements.--* Changed the behavior of :pkg-field:`extra-bundled-libraries` field. The naming convention- of dynamic library files (e.g. generated by a custom build script) has- changed. For library names prefixed with "C", the dynamic library file- name(s) must be of the form `lib<library-name>.<dyn-library-extension>*`- instead of the old `libC<library-name>-ghc<ghc-flavour><ghc-version>.<dyn-library-extension>`--* New set-notation syntax for ``==`` and ``^>=`` operators, see- :pkg-field:`build-depends` field documentation for examples.--* Allow more whitespace in :pkg-field:`mixins` field--* Wildcards are disallowed in :pkg-field:`pkgconfig-depends`,- Yet the pkgconfig format is relaxed to accept e.g. versions like ``1.1.0h``.--* New :pkg-field:`autogen-includes` for specifying :pkg-field:`install-includes`- which are autogenerated (e.g. by a ``configure`` script).--* New :pkg-field:`asm-sources` and :pkg-field:`asm-options` fields- added for supporting bundled foreign routines implemented in- assembler.--* New :pkg-field:`cmm-sources` and :pkg-field:`cmm-options` fields- added for supporting bundled foreign primops implemented in- C--.--``cabal-version: 2.4``-------------------------* Wildcard matching has been expanded. All previous wildcard- expressions are still valid; some will match strictly more files- than before. Specifically:-- * Double-star (``**``) wildcards are now accepted for recursive- matching immediately before the final slash; they must be followed- by a filename wildcard (e.g., ``foo/**/*.html`` is valid;- ``foo/**/bar/*.html`` and ``foo/**/**/*.html``,- ``foo/**/bar.html`` are all invalid). As ``**`` was an error in- globs before, this does not affect any existing ``.cabal`` files- that previously worked.-- * Wildcards now match when the pattern's extensions form a suffix of- the candidate file's extension, rather than requiring strict- equality (e.g., previously ``*.html`` did not match- ``foo.en.html``, but now it does).--* License fields use identifiers from SPDX License List version- ``3.2 2018-07-10``---``cabal-version: 2.2``-------------------------* New :pkg-section:`common` stanzas and :pkg-field:`import`- pseudo-field added.--* New :pkg-field:`library:virtual-modules` field added.--* New :pkg-field:`cxx-sources` and :pkg-field:`cxx-options` fields- added for suppporting bundled foreign routines implemented in C++.--* New :pkg-field:`extra-bundled-libraries` field for specifying- additional custom library objects to be installed.--* Extended ``if`` control structure with support for ``elif`` keyword.--* Changed default rules of :pkg-field:`build-type` field to infer- "build-type:" for "Simple"/"Custom" automatically.--* :pkg-field:`license` field syntax changed to require SPDX- expression syntax (using SPDX license list version ``3.0 2017-12-28``).--* Allow redundant leading or trailing commas in package fields (which- require commas) such as :pkg-field:`build-depends`.---``cabal-version: 2.0``-------------------------* New :pkg-field:`library:signatures` and :pkg-field:`mixins` fields- added for supporting Backpack_.--* New :pkg-field:`build-tool-depends` field added for adding- build-time dependencies of executable components.--* New :pkg-field:`custom-setup:autogen-modules` field added for declaring modules- which are generated at build time.--* Support for new PVP_ caret-style version operator (``^>=``) added to- :pkg-field:`build-depends`.--* Add support for new :pkg-section:`foreign-library` stanza.--* Add support for :ref:`internal library stanzas <sublibs>`.--* New CPP Macro ``CURRENT_PACKAGE_VERSION``.--``cabal-version: 1.24``--------------------------* New :pkg-section:`custom-setup` stanza and- :pkg-field:`custom-setup:setup-depends` field added for specifying dependencies- of custom ``Setup.hs`` scripts.--* CPP Macros ``VERSION_$pkgname`` and ``MIN_VERSION_$pkgname`` are now- also generated for the current package.--* New CPP Macros ``CURRENT_COMPONENT_ID`` and ``CURRENT_PACKAGE_KEY``.--* New :pkg-field:`extra-framework-dirs` field added for specifying- extra locations to find OS X frameworks.--``cabal-version: 1.22``--------------------------* New :pkg-field:`library:reexported-modules` field.--* Support for ``-none`` version constraint added to- :pkg-field:`build-depends`.--* New :pkg-field:`license` type ``ISC`` added.--``cabal-version: 1.20``--------------------------* Add support for new :pkg-field:`license-files` field for declaring- multiple license documents.--* New CPP Macro ``MIN_TOOL_VERSION_$buildtool``.--* New :pkg-field:`license` types ``BSD2`` and ``MPL-2.0`` added.--``cabal-version: 1.18``--------------------------* Add support for new :pkg-field:`extra-doc-files` field for- specifying extra file assets referenced by the Haddock- documentation.--* New :pkg-field:`license` type ``AGPL`` and ``AGPL-3`` added.--* Add support for specifying a C/C++/obj-C source file in- :pkg-field:`executable:main-is` field.--* Add ``getSysconfDir`` operation to ``Paths_`` API.--``cabal-version: 1.16``--------------------------.. todo::-- this needs to be researched; there were only few changes between- 1.12 and 1.18;--``cabal-version: 1.12``--------------------------* Change syntax of :pkg-field:`cabal-version` to support the new recommended- ``cabal-version: x.y`` style----.. include:: references.inc
− doc/images/Cabal-dark.png
binary file changed (7086 → absent bytes)
− doc/index.rst
@@ -1,21 +0,0 @@--Welcome to the Cabal User Guide-===============================--.. toctree::- :maxdepth: 2- :numbered:-- getting-started- intro- config-and-install- concepts-and-development- nix-local-build-overview- cabal-commands- cabal-package- cabal-project- setup-commands- file-format-changelog- buildinfo-fields-reference- bugs-and-stability- nix-integration
− doc/installing-packages.rst
@@ -1,247 +0,0 @@-Configuration-=============--.. highlight:: cabal--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--.. code-block:: console-- $ cabal user-config update--You can change the location of the global configuration file by specifying-either ``--config-file=FILE`` on the command line or by setting the-``CABAL_CONFIG`` environment variable.--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``.--Environment variables------------------------Various environment variables affect ``cabal-install``.--``CABAL_CONFIG``- The variable to find global configuration file.--``CABAL_DIR``- Default content directory for ``cabal-install`` files.- Default value is ``getAppUserDataDirectory "cabal"``, which is- ``$HOME/.cabal`` on unix systems and ``%APPDATA%\cabal`` in Windows.-- .. note::-- The CABAL_DIR might be dropped in the future, when- ``cabal-install`` starts to use XDG Directory specification.--``CABAL_BUILDDIR``- The override for default ``dist`` build directory.- Note, the nix-style builds build directory (``dist-newstyle``)- is not affected by this environment variable.--Configuration file discovery-^^^^^^^^^^^^^^^^^^^^^^^^^^^^--1. If ``$CABAL_CONFIG`` is set use it,-2. otherwise if ``$CABAL_DIR`` is set use ``$CABAL_DIR/config``-3. otherwise use ``getAppUserDirectory "cabal"``--If the configuration file doesn't exist ``cabal-install``-will generate the default one, with directories based on-``$CABAL_DIR`` (if set) or ``getAppUserDirectory "cabal"`` prefix.--.. note:-- If ``$CABAL_CONFIG`` is set, but the file doesn't exist,- one will be generated with ``$CABAL_DIR`` or ``getAppUserDirectory "cabal"``- based prefixes. In other words not the prefixes based on a- directory part of ``$CABAL_CONFIG`` path.--Repository specification---------------------------An important part of the configuration is 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-:cfg-field:`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) 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 tampered 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/haskell/hackage-security.--Local no-index repositories-^^^^^^^^^^^^^^^^^^^^^^^^^^^--It's possible to use a directory of `.tar.gz` package files as a local package-repository.--::-- repository my-local-repository- url: file+noindex:///absolute/path/to/directory--``cabal`` will construct the index automatically from the-``package-name-version.tar.gz`` files in the directory, and will use optional-corresponding ``package-name-version.cabal`` files as new revisions.--For example, if ``/absolute/path/to/directory`` looks like-::-- /absolute/path/to/directory/- foo-0.1.0.0.tar.gz- bar-0.2.0.0.tar.gz- bar-0.2.0.0.cabal--then ``cabal`` will create an index with two packages:--- ``foo-0.1.0.0`` using the source and ``.cabal`` file inside- ``foo-0.1.0.0.tar.gz``-- ``bar-0.2.0.0`` using the source inside ``bar-0.2.0.0.tar.gz``- and ``bar-0.2.0.0.cabal``--The index is cached inside the given directory. If the directory is not-writable, you can append ``#shared-cache`` fragment to the URI,-then the cache will be stored inside the :cfg-field:`remote-repo-cache` directory.-The part of the path will be used to determine the cache key part.--.. note::- ``cabal-install`` creates a ``.cache`` file, and will aggressively use- its contents if it exists. Therefore if you change the contents of- the directory, remember to wipe the cache too.--.. note::- The URI scheme ``file:`` is interpreted as a remote repository,- as described in the previous sections, thus requiring manual construction- of ``01-index.tar`` file.--Legacy repositories-^^^^^^^^^^^^^^^^^^^--Currently ``cabal`` supports single kind of “legacy” repositories.-It 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: 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/``.--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-pkg:`hackage-repo-tool`-can be used to create and manage such repositories.--.. _installing-packages:--Building and installing packages-================================--To be written--Installing packages from Hackage-----------------------------------The ``cabal`` tool also can download, configure, build and install a-`Hackage`_ package and all of its-dependencies in a single step. To do this, run:--::-- $ cabal install [PACKAGE...]--To browse the list of available packages, visit the `Hackage`_ web site.--.. _Hackage: https://hackage.haskell.org/
− doc/intro.rst
@@ -1,200 +0,0 @@-.. highlight:: console--Cabal is the standard package system for-Haskell_ software. It helps people to-configure, build and install Haskell software and to distribute it-easily to other users and developers.--There is a command line tool called ``cabal`` for working with Cabal-packages. It helps with installing existing packages and also helps-people developing their own packages. It can be used to work with local-packages or to install packages from online package archives, including-automatically installing dependencies. By default it is configured to-use Hackage_ which is Haskell's central-package archive that contains thousands of libraries and applications in-the Cabal package format.--Introduction-============--Cabal is a package system for Haskell software. The point of a package-system is to enable software developers and users to easily distribute,-use and reuse software. A package system makes it easier for developers-to get their software into the hands of users. Equally importantly, it-makes it easier for software developers to be able to reuse software-components written by other developers.--Packaging systems deal with packages and with Cabal we call them *Cabal-packages*. The Cabal package is the unit of distribution. Every Cabal-package has a name and a version number which are used to identify the-package, e.g. ``filepath-1.0``.--Cabal packages can depend on other Cabal packages. There are tools to-enable automated package management. This means it is possible for-developers and users to install a package plus all of the other Cabal-packages that it depends on. It also means that it is practical to make-very modular systems using lots of packages that reuse code written by-many developers.--Cabal packages are source based and are typically (but not necessarily)-portable to many platforms and Haskell implementations. The Cabal-package format is designed to make it possible to translate into other-formats, including binary packages for various systems.--When distributed, Cabal packages use the standard compressed tarball-format, with the file extension ``.tar.gz``, e.g.-``filepath-1.0.tar.gz``.--Note that packages are not part of the Haskell language, rather they are-a feature provided by the combination of Cabal and GHC (and several-other Haskell implementations).--A tool for working with packages-----------------------------------There is a command line tool, called "``cabal``", that users and-developers can use to build and install Cabal packages. It can be used-for both local packages and for packages available remotely over the-network. It can automatically install Cabal packages plus any other-Cabal packages they depend on.--Developers can use the tool with packages in local directories, e.g.--::-- $ cd foo/- $ cabal install--While working on a package in a local directory, developers can run the-individual steps to configure and build, and also generate documentation-and run test suites and benchmarks.--It is also possible to install several local packages at once, e.g.--::-- $ cabal install foo/ bar/--Developers and users can use the tool to install packages from remote-Cabal package archives. By default, the ``cabal`` tool is configured to-use the central Haskell package archive called-Hackage_ but it is possible to use it-with any other suitable archive.--::-- $ cabal install xmonad--This will install the ``xmonad`` package plus all of its dependencies.--In addition to packages that have been published in an archive,-developers can install packages from local or remote tarball files, for-example--::-- $ cabal install foo-1.0.tar.gz- $ cabal install http://example.com/foo-1.0.tar.gz--Cabal provides a number of ways for a user to customise how and where a-package is installed. They can decide where a package will be installed,-which Haskell implementation to use and whether to build optimised code-or build with the ability to profile code. It is not expected that users-will have to modify any of the information in the ``.cabal`` file.--For full details, see the section on `building and installing-packages <installing-packages.html>`__.--Note that ``cabal`` is not the only tool for working with Cabal-packages. Due to the standardised format and a library for reading-``.cabal`` files, there are several other special-purpose tools.--What's in a package----------------------A Cabal package consists of:--- Haskell software, including libraries, executables and tests-- metadata about the package in a standard human and machine readable- format (the "``.cabal``" file)-- a standard interface to build the package (the "``Setup.hs``" file)--The ``.cabal`` file contains information about the package, supplied by-the package author. In particular it lists the other Cabal packages that-the package depends on.--For full details on what goes in the ``.cabal`` and ``Setup.hs`` files,-and for all the other features provided by the build system, see the-section on `developing packages <developing-packages.html>`__.--Cabal featureset-------------------Cabal and its associated tools and websites covers:--- a software build system-- software configuration-- packaging for distribution-- automated package management-- - natively using the ``cabal`` command line tool; or- - by translation into native package formats such as RPM or deb--- web and local Cabal package archives-- - central Hackage website with 1000's of Cabal packages--Some parts of the system can be used without others. In particular the-built-in build system for simple packages is optional: it is possible to-use custom build systems.--Similar systems------------------The Cabal system is roughly comparable with the system of Python Eggs,-Ruby Gems or Perl distributions. Each system has a notion of-distributable packages, and has tools to manage the process of-distributing and installing packages.--Hackage is an online archive of Cabal packages. It is roughly comparable-to CPAN but with rather fewer packages (around 5,000 vs 28,000).--Cabal is often compared with autoconf and automake and there is some-overlap in functionality. The most obvious similarity is that the-command line interface for actually configuring and building packages-follows the same steps and has many of the same configuration-parameters.--::-- $ ./configure --prefix=...- $ make- $ make install--compared to--::-- $ cabal configure --prefix=...- $ cabal build- $ cabal install--Cabal's build system for simple packages is considerably less flexible-than make/automake, but has builtin knowledge of how to build Haskell-code and requires very little manual configuration. Cabal's simple build-system is also portable to Windows, without needing a Unix-like-environment such as cygwin/mingwin.--Compared to autoconf, Cabal takes a somewhat different approach to-package configuration. Cabal's approach is designed for automated-package management. Instead of having a configure script that tests for-whether dependencies are available, Cabal packages specify their-dependencies. There is some scope for optional and conditional-dependencies. By having package authors specify dependencies it makes it-possible for tools to install a package and all of its dependencies-automatically. It also makes it possible to translate (in a-mostly-automatically way) into another package format like RPM or deb-which also have automatic dependency resolution.---.. include:: references.inc
− doc/misc.rst
@@ -1,103 +0,0 @@-Reporting bugs and deficiencies-===============================--Please report any flaws or feature requests in the `bug-tracker <https://github.com/haskell/cabal/issues>`__.--For general discussion or queries email the libraries mailing list-libraries@haskell.org. There is also a development mailing list-cabal-devel@haskell.org.--Stability of Cabal interfaces-=============================--The Cabal library and related infrastructure is still under active-development. New features are being added and limitations and bugs are-being fixed. This requires internal changes and often user visible-changes as well. We therefore cannot promise complete future-proof-stability, at least not without halting all development work.--This section documents the aspects of the Cabal interface that we can-promise to keep stable and which bits are subject to change.--Cabal file format--------------------This is backwards compatible and mostly forwards compatible. New fields-can be added without breaking older versions of Cabal. Fields can be-deprecated without breaking older packages.--Command-line interface-------------------------Very Stable Command-line interfaces-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- ``./setup configure``-- ``--prefix``-- ``--user``-- ``--ghc``, ``--uhc``-- ``--verbose``-- ``--prefix``--- ``./setup build``-- ``./setup install``-- ``./setup register``-- ``./setup copy``--Stable Command-line interfaces-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--Unstable command-line-~~~~~~~~~~~~~~~~~~~~~--Functions and Types----------------------The Cabal library follows the `Package Versioning Policy`_.-This means that within a stable major release, for example 1.2.x, there-will be no incompatible API changes. But minor versions increments, for-example 1.2.3, indicate compatible API additions.--The Package Versioning Policy does not require any API guarantees-between major releases, for example between 1.2.x and 1.4.x. In practice-of course not everything changes between major releases. Some parts of-the API are more prone to change than others. The rest of this section-gives some informal advice on what level of API stability you can expect-between major releases.--Very Stable API-~~~~~~~~~~~~~~~--- ``defaultMain``--- ``defaultMainWithHooks defaultUserHooks``--But regular ``defaultMainWithHooks`` isn't stable since ``UserHooks``-changes.--Semi-stable API-~~~~~~~~~~~~~~~--- ``UserHooks`` The hooks API will change in the future--- ``Distribution.*`` is mostly declarative information about packages- and is somewhat stable.--Unstable API-~~~~~~~~~~~~--Everything under ``Distribution.Simple.*`` has no stability guarantee.--Hackage----------The index format is a partly stable interface. It consists of a tar.gz-file that contains directories with ``.cabal`` files in. In future it-may contain more kinds of files so do not assume every file is a-``.cabal`` file. Incompatible revisions to the format would involve-bumping the name of the index file, i.e., ``00-index.tar.gz``,-``01-index.tar.gz`` etc.---.. include:: references.inc
− doc/nix-local-build-overview.rst
@@ -1,45 +0,0 @@-Nix-style Local Builds-======================--.. _nix-style-builds:--Nix-style local builds are a new build system implementation inspired by Nix.-The Nix-style local build system is commonly called "v2-build" for short-after the ``cabal v2-*`` family of commands that control it. However, those-names are only temporary now that Nix-style local builds have become the-default. For those who do not wish to use the new-functionality, the classic project style will not be removed immediately,-but these legacy commands will require the usage of the ``v1-`` prefix as of-Cabal 3.0 and will be removed in a future release. For a future-proof-way to use these commands in a script or tutorial that anticipates the-possibility of another UI paradigm being devised in the future, there-are also ``v2-`` prefixed versions that will reference the same functionality-until such a point as it is completely removed from Cabal.--Nix-style local builds combine the best of non-sandboxed and sandboxed Cabal:--1. Like sandboxed Cabal previously, we build sets of independent local- packages deterministically and independent of any global state.- v2-build will never tell you that it can't build your package- because it would result in a "dangerous reinstall." Given a- particular state of the Hackage index, your build is completely- reproducible. For example, you no longer need to compile packages- with profiling ahead of time; just request profiling and v2-build- will rebuild all its dependencies with profiling automatically.--2. Like non-sandboxed Cabal today, builds of external packages are- cached in ``~/.cabal/store``, so that a package can be built once,- and then reused anywhere else it is also used. No need to continually- rebuild dependencies whenever you make a new sandbox: dependencies- which can be shared, are shared.--Nix-style local builds were first released as beta in cabal-install 1.24.-They currently work with all versions of GHC supported by that release: GHC 7.0 and later.--Some features described in this manual are not implemented. If you need-them, please give us a shout and we'll prioritize accordingly.----.. toctree::- nix-local-build
− doc/nix-local-build.rst
@@ -1,264 +0,0 @@-.. highlight:: console--Quickstart-==========--Suppose that you are in a directory containing a single Cabal package-which you wish to build (if you haven't set up a package yet check-out `developing packages <developing-packages.html>`__ for-instructions). You can configure and build it using Nix-style-local builds with this command (configuring is not necessary):--::-- $ cabal v2-build--To open a GHCi shell with this package, use this command:--::-- $ cabal v2-repl--To run an executable defined in this package, use this command:--::-- $ cabal v2-run <executable name> [executable args]--Developing multiple packages-------------------------------Many Cabal projects involve multiple packages which need to be built-together. To build multiple Cabal packages, you need to first create a-``cabal.project`` file which declares where all the local package-directories live. For example, in the Cabal repository, there is a root-directory with a folder per package, e.g., the folders ``Cabal`` and-``cabal-install``. The ``cabal.project`` file specifies each folder as-part of the project:--.. code-block:: cabal-- packages: Cabal/- cabal-install/--The expectation is that a ``cabal.project`` is checked into your source-control, to be used by all developers of a project. If you need to make-local changes, they can be placed in ``cabal.project.local`` (which-should not be checked in.)--Then, to build every component of every package, from the top-level-directory, run the command: (using cabal-install-2.0 or greater.)--::-- $ cabal v2-build all--To build a specific package, you can either run ``v2-build`` from the-directory of the package in question:--::-- $ cd cabal-install- $ cabal v2-build--or you can pass the name of the package as an argument to-``cabal v2-build`` (this works in any subdirectory of the project):--::-- $ cabal v2-build cabal-install--You can also specify a specific component of the package to build. For-example, to build a test suite named ``package-tests``, use the command:--::-- $ cabal v2-build package-tests--Targets can be qualified with package names. So to request-``package-tests`` *from* the ``Cabal`` package, use-``Cabal:package-tests``.--Unlike sandboxes, there is no need to setup a sandbox or ``add-source``-projects; just check in ``cabal.project`` to your repository and-``v2-build`` will just work.--Cookbook-========--How can I profile my library/application?--------------------------------------------Create or edit your ``cabal.project.local``, adding the following-line::-- profiling: True--Now, ``cabal v2-build`` will automatically build all libraries and-executables with profiling. You can fine-tune the profiling settings-for each package using :cfg-field:`profiling-detail`::-- package p- profiling-detail: toplevel-functions--Alternately, you can call ``cabal v2-build --enable-profiling`` to-temporarily build with profiling.--How it works-============--Local versus external packages---------------------------------One of the primary innovations of Nix-style local builds is the-distinction between local packages, which users edit and recompile and-must be built per-project, versus external packages, which can be cached-across projects. To be more precise:--1. A **local package** is one that is listed explicitly in the- ``packages``, ``optional-packages`` or ``extra-packages`` field of a- project. Usually, these refer to packages whose source code lives- directly in a folder in your project. But you can list an- arbitrary Hackage package in :cfg-field:`packages`- to force it to be treated as local.--Local packages, as well as the external packages (below) which depend on-them, are built **inplace**, meaning that they are always built-specifically for the project and are not installed globally. Inplace-packages are not cached and not given unique hashes, which makes them-suitable for packages which you want to edit and recompile.--2. An **external package** is any package which is not listed in the- ``packages`` field. The source code for external packages is usually- retrieved from Hackage.--When an external package does not depend on an inplace package, it can-be built and installed to a **global** store, which can be shared across-projects. These build products are identified by a hash based on all of-the inputs which influence the compilation of a package (flags,-dependency selection, etc.). Just as in Nix, these hashes uniquely-identify the result of a build; if we compute this identifier and we-find that we already have this ID built, we can just use the already-built version.--The global package store is ``~/.cabal/store`` (configurable via-global `store-dir` option); if you need to clear your store for-whatever reason (e.g., to reclaim disk space or because the global-store is corrupted), deleting this directory is safe (``v2-build``-will just rebuild everything it needs on its next invocation).--This split motivates some of the UI choices for Nix-style local build-commands. For example, flags passed to ``cabal v2-build`` are only-applied to *local* packages, so that adding a flag to-``cabal v2-build`` doesn't necessitate a rebuild of *every* transitive-dependency in the global package store.--In cabal-install 2.0 and above, Nix-style local builds also take advantage of a-new Cabal library feature, `per-component-builds <https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst>`__,-where each component of a package is configured and built separately.-This can massively speed up rebuilds of packages with lots of components-(e.g., a package that defines multiple executables), as only one-executable needs to be rebuilt. Packages that use Custom setup scripts-are not currently built on a per-component basis.--Where are my build products?-------------------------------A major deficiency in the current implementation of v2-build is that-there is no programmatic way to access the location of build products.-The location of the build products is intended to be an internal-implementation detail of v2-build, but we also understand that many-unimplemented features can only be reasonably worked around by-accessing build products directly.--The location where build products can be found varies depending on the-version of cabal-install:--- In cabal-install-1.24, the dist directory for a package ``p-0.1`` is- stored in ``dist-newstyle/build/p-0.1``. For example, if you built an- executable or test suite named ``pexe``, it would be located at- ``dist-newstyle/build/p-0.1/build/pexe/pexe``.--- In cabal-install-2.0, the dist directory for a package ``p-0.1``- defining a library built with GHC 8.0.1 on 64-bit Linux is- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1``. When- per-component builds are enabled (any non-Custom package), a- subcomponent like an executable or test suite named ``pexe`` will be- stored at- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe``; thus,- the full path of the executable is- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe/build/pexe/pexe``- (you can see why we want this to be an implementation detail!)--- In cabal-install-2.2 and above, the ``/c/`` part of the above path- is replaced with one of ``/l/``, ``/x/``, ``/f/``, ``/t/``, or- ``/b/``, depending on the type of component (sublibrary,- executable, foreign library, test suite, or benchmark- respectively). So the full path to an executable named ``pexe``- compiled with GHC 8.0.1 on a 64-bit Linux is now- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/x/pexe/build/pexe/pexe``;- for a benchmark named ``pbench`` it now is- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/b/pbench/build/pbench/pbench``;---The paths are a bit longer in 2.0 and above but the benefit is that you can-transparently have multiple builds with different versions of GHC. We-plan to add the ability to create aliases for certain build-configurations, and more convenient paths to access particularly useful-build products like executables.--Caching----------Nix-style local builds sport a robust caching system which helps to reduce-the time it takes to execute a rebuild cycle. While the details of how-``cabal-install`` does caching are an implementation detail and may-change in the future, knowing what gets cached is helpful for-understanding the performance characteristics of invocations to-``v2-build``. The cached intermediate results are stored in-``dist-newstyle/cache``; this folder can be safely deleted to clear the-cache.--The following intermediate results are cached in the following files in-this folder (the most important two are first):--``solver-plan`` (binary)- The result of calling the dependency solver, assuming that the- Hackage index, local ``cabal.project`` file, and local ``cabal``- files are unmodified. (Notably, we do NOT have to dependency solve- again if new build products are stored in the global store; the- invocation of the dependency solver is independent of what is- already available in the store.)-``source-hashes`` (binary)- The hashes of all local source files. When all local source files of- a local package are unchanged, ``cabal v2-build`` will skip- invoking ``setup build`` entirely (saving us from a possibly- expensive call to ``ghc --make``). The full list of source files- participating in compilation is determined using- ``cabal sdist --list-only``. Thus if you do not list all your- source files in a Cabal file, Cabal may fail to recompile when you- edit them.-``config`` (same format as ``cabal.project``)- The full project configuration, merged from ``cabal.project`` (and- friends) as well as the command line arguments.-``compiler`` (binary)- The configuration of the compiler being used to build the project.-``improved-plan`` (binary)- Like ``solver-plan``, but with all non-inplace packages improved- into pre-existing copies from the store.-``plan.json`` (JSON)- A JSON serialization of the computed install plan intended- for integrating ``cabal`` with external tooling.- The `cabal-plan <http://hackage.haskell.org/package/cabal-plan>`__- package provides a library for parsing ``plan.json`` files into a- Haskell data structure as well as an example tool showing possible- applications.-- .. todo::-- Document JSON schema (including version history of schema)---Note that every package also has a local cache managed by the Cabal-build system, e.g., in ``$distdir/cache``.
− doc/references.inc
@@ -1,26 +0,0 @@-.. -*- rst -*-- This file contains commonly used link-references- See also "extlinks" in conf.py--.. _`Package Versioning Policy`:-.. _PVP: http://pvp.haskell.org/--.. _Hackage: http://hackage.haskell.org/--.. _Haskell: http://www.haskell.org/--.. _Haddock: http://www.haskell.org/haddock/--.. _Alex: http://www.haskell.org/alex/--.. _Happy: http://www.haskell.org/happy/--.. _Hoogle: http://www.haskell.org/hoogle/--.. _HsColour: http://www.cs.york.ac.uk/fp/darcs/hscolour/--.. _cpphs: http://projects.haskell.org/cpphs/--.. _ABNF: https://tools.ietf.org/html/rfc5234--.. _Backpack: https://gitlab.haskell.org/ghc/ghc/-/wikis/backpack
+ src/Distribution/Backpack.hs view
@@ -0,0 +1,269 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}++-- | This module defines the core data types for Backpack. For more+-- details, see:+--+-- <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>++module Distribution.Backpack (+ -- * OpenUnitId+ OpenUnitId(..),+ openUnitIdFreeHoles,+ mkOpenUnitId,++ -- * DefUnitId+ DefUnitId,+ unDefUnitId,+ mkDefUnitId,++ -- * OpenModule+ OpenModule(..),+ openModuleFreeHoles,++ -- * OpenModuleSubst+ OpenModuleSubst,+ dispOpenModuleSubst,+ dispOpenModuleSubstEntry,+ parsecOpenModuleSubst,+ parsecOpenModuleSubstEntry,+ openModuleSubstFreeHoles,++ -- * Conversions to 'UnitId'+ abstractUnitId,+ hashModuleSubst,+) where++import Distribution.Compat.Prelude hiding (mod)+import Distribution.Parsec+import Distribution.Pretty+import Prelude ()+import Text.PrettyPrint (hcat)++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++import Distribution.ModuleName+import Distribution.Types.ComponentId+import Distribution.Types.Module+import Distribution.Types.UnitId+import Distribution.Utils.Base62++import qualified Data.Map as Map+import qualified Data.Set as Set++-----------------------------------------------------------------------+-- OpenUnitId++-- | An 'OpenUnitId' describes a (possibly partially) instantiated+-- Backpack component, with a description of how the holes are filled+-- in. Unlike 'OpenUnitId', the 'ModuleSubst' is kept in a structured+-- form that allows for substitution (which fills in holes.) This form+-- of unit cannot be installed. It must first be converted to a+-- 'UnitId'.+--+-- In the absence of Backpack, there are no holes to fill, so any such+-- component always has an empty module substitution; thus we can lossly+-- represent it as an 'OpenUnitId uid'.+--+-- For a source component using Backpack, however, there is more+-- structure as components may be parametrized over some signatures, and+-- these \"holes\" may be partially or wholly filled.+--+-- OpenUnitId plays an important role when we are mix-in linking,+-- and is recorded to the installed packaged database for indefinite+-- packages; however, for compiled packages that are fully instantiated,+-- we instantiate 'OpenUnitId' into 'UnitId'.+--+-- For more details see the Backpack spec+-- <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+--++data OpenUnitId+ -- | Identifies a component which may have some unfilled holes;+ -- specifying its 'ComponentId' and its 'OpenModuleSubst'.+ -- TODO: Invariant that 'OpenModuleSubst' is non-empty?+ -- See also the Text instance.+ = IndefFullUnitId ComponentId OpenModuleSubst+ -- | Identifies a fully instantiated component, which has+ -- been compiled and abbreviated as a hash. The embedded 'UnitId'+ -- MUST NOT be for an indefinite component; an 'OpenUnitId'+ -- is guaranteed not to have any holes.+ | DefiniteUnitId DefUnitId+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)+-- TODO: cache holes?++instance Binary OpenUnitId+instance Structured OpenUnitId +instance NFData OpenUnitId where+ rnf (IndefFullUnitId cid subst) = rnf cid `seq` rnf subst+ rnf (DefiniteUnitId uid) = rnf uid++instance Pretty OpenUnitId where+ pretty (IndefFullUnitId cid insts)+ -- TODO: arguably a smart constructor to enforce invariant would be+ -- better+ | Map.null insts = pretty cid+ | otherwise = pretty cid <<>> Disp.brackets (dispOpenModuleSubst insts)+ pretty (DefiniteUnitId uid) = pretty uid++-- |+--+-- >>> eitherParsec "foobar" :: Either String OpenUnitId+--Right (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "foobar"}))+--+-- >>> eitherParsec "foo[Str=text-1.2.3:Data.Text.Text]" :: Either String OpenUnitId+-- Right (IndefFullUnitId (ComponentId "foo") (fromList [(ModuleName "Str",OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "text-1.2.3"})) (ModuleName "Data.Text.Text"))]))+--+instance Parsec OpenUnitId where+ parsec = P.try parseOpenUnitId <|> fmap DefiniteUnitId parsec+ where+ parseOpenUnitId = do+ cid <- parsec+ insts <- P.between (P.char '[') (P.char ']')+ parsecOpenModuleSubst+ return (IndefFullUnitId cid insts)++-- | Get the set of holes ('ModuleVar') embedded in a 'UnitId'.+openUnitIdFreeHoles :: OpenUnitId -> Set ModuleName+openUnitIdFreeHoles (IndefFullUnitId _ insts) = openModuleSubstFreeHoles insts+openUnitIdFreeHoles _ = Set.empty++-- | Safe constructor from a UnitId. The only way to do this safely+-- is if the instantiation is provided.+mkOpenUnitId :: UnitId -> ComponentId -> OpenModuleSubst -> OpenUnitId+mkOpenUnitId uid cid insts =+ if Set.null (openModuleSubstFreeHoles insts)+ then DefiniteUnitId (unsafeMkDefUnitId uid) -- invariant holds!+ else IndefFullUnitId cid insts++-----------------------------------------------------------------------+-- DefUnitId++-- | Create a 'DefUnitId' from a 'ComponentId' and an instantiation+-- with no holes.+mkDefUnitId :: ComponentId -> Map ModuleName Module -> DefUnitId+mkDefUnitId cid insts =+ unsafeMkDefUnitId (mkUnitId+ (unComponentId cid ++ maybe "" ("+"++) (hashModuleSubst insts)))+ -- impose invariant!++-----------------------------------------------------------------------+-- OpenModule++-- | Unlike a 'Module', an 'OpenModule' is either an ordinary+-- module from some unit, OR an 'OpenModuleVar', representing a+-- hole that needs to be filled in. Substitutions are over+-- module variables.+data OpenModule+ = OpenModule OpenUnitId ModuleName+ | OpenModuleVar ModuleName+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++instance Binary OpenModule+instance Structured OpenModule++instance NFData OpenModule where+ rnf (OpenModule uid mod_name) = rnf uid `seq` rnf mod_name+ rnf (OpenModuleVar mod_name) = rnf mod_name++instance Pretty OpenModule where+ pretty (OpenModule uid mod_name) =+ hcat [pretty uid, Disp.text ":", pretty mod_name]+ pretty (OpenModuleVar mod_name) =+ hcat [Disp.char '<', pretty mod_name, Disp.char '>']++-- |+--+-- >>> eitherParsec "Includes2-0.1.0.0-inplace-mysql:Database.MySQL" :: Either String OpenModule+-- Right (OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "Includes2-0.1.0.0-inplace-mysql"})) (ModuleName "Database.MySQL"))+--+instance Parsec OpenModule where+ parsec = parsecModuleVar <|> parsecOpenModule+ where+ parsecOpenModule = do+ uid <- parsec+ _ <- P.char ':'+ mod_name <- parsec+ return (OpenModule uid mod_name)++ parsecModuleVar = do+ _ <- P.char '<'+ mod_name <- parsec+ _ <- P.char '>'+ return (OpenModuleVar mod_name)++-- | Get the set of holes ('ModuleVar') embedded in a 'Module'.+openModuleFreeHoles :: OpenModule -> Set ModuleName+openModuleFreeHoles (OpenModuleVar mod_name) = Set.singleton mod_name+openModuleFreeHoles (OpenModule uid _n) = openUnitIdFreeHoles uid++-----------------------------------------------------------------------+-- OpenModuleSubst++-- | An explicit substitution on modules.+--+-- NB: These substitutions are NOT idempotent, for example, a+-- valid substitution is (A -> B, B -> A).+type OpenModuleSubst = Map ModuleName OpenModule++-- | Pretty-print the entries of a module substitution, suitable+-- for embedding into a 'OpenUnitId' or passing to GHC via @--instantiate-with@.+dispOpenModuleSubst :: OpenModuleSubst -> Disp.Doc+dispOpenModuleSubst subst+ = Disp.hcat+ . Disp.punctuate Disp.comma+ $ map dispOpenModuleSubstEntry (Map.toAscList subst)++-- | Pretty-print a single entry of a module substitution.+dispOpenModuleSubstEntry :: (ModuleName, OpenModule) -> Disp.Doc+dispOpenModuleSubstEntry (k, v) = pretty k <<>> Disp.char '=' <<>> pretty v++-- | Inverse to 'dispModSubst'.+--+-- @since 2.2+parsecOpenModuleSubst :: CabalParsing m => m OpenModuleSubst+parsecOpenModuleSubst = fmap Map.fromList+ . flip P.sepBy (P.char ',')+ $ parsecOpenModuleSubstEntry++-- | Inverse to 'dispModSubstEntry'.+--+-- @since 2.2+parsecOpenModuleSubstEntry :: CabalParsing m => m (ModuleName, OpenModule)+parsecOpenModuleSubstEntry =+ do k <- parsec+ _ <- P.char '='+ v <- parsec+ return (k, v)++-- | Get the set of holes ('ModuleVar') embedded in a 'OpenModuleSubst'.+-- This is NOT the domain of the substitution.+openModuleSubstFreeHoles :: OpenModuleSubst -> Set ModuleName+openModuleSubstFreeHoles insts = Set.unions (map openModuleFreeHoles (Map.elems insts))++-----------------------------------------------------------------------+-- Conversions to UnitId++-- | When typechecking, we don't demand that a freshly instantiated+-- 'IndefFullUnitId' be compiled; instead, we just depend on the+-- installed indefinite unit installed at the 'ComponentId'.+abstractUnitId :: OpenUnitId -> UnitId+abstractUnitId (DefiniteUnitId def_uid) = unDefUnitId def_uid+abstractUnitId (IndefFullUnitId cid _) = newSimpleUnitId cid++-- | Take a module substitution and hash it into a string suitable for+-- 'UnitId'. Note that since this takes 'Module', not 'OpenModule',+-- you are responsible for recursively converting 'OpenModule'+-- into 'Module'. See also "Distribution.Backpack.ReadyComponent".+hashModuleSubst :: Map ModuleName Module -> Maybe String+hashModuleSubst subst+ | Map.null subst = Nothing+ | otherwise =+ Just . hashToBase62 $+ concat [ prettyShow mod_name ++ "=" ++ prettyShow m ++ "\n"+ | (mod_name, m) <- Map.toList subst]
+ src/Distribution/Backpack/ComponentsGraph.hs view
@@ -0,0 +1,97 @@+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.ComponentsGraph (+ ComponentsGraph,+ ComponentsWithDeps,+ mkComponentsGraph,+ componentsGraphToList,+ dispComponentsWithDeps,+ componentCycleMsg+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Package+import Distribution.PackageDescription+import Distribution.Simple.BuildToolDepends+import Distribution.Simple.LocalBuildInfo+import Distribution.Types.ComponentRequestedSpec+import Distribution.Compat.Graph (Graph, Node(..))+import qualified Distribution.Compat.Graph as Graph+import qualified Distribution.Compat.NonEmptySet as NES+import Distribution.Utils.Generic++import Distribution.Pretty (pretty)+import Text.PrettyPrint++------------------------------------------------------------------------------+-- Components graph+------------------------------------------------------------------------------++-- | A graph of source-level components by their source-level+-- dependencies+--+type ComponentsGraph = Graph (Node ComponentName Component)++-- | A list of components associated with the source level+-- dependencies between them.+--+type ComponentsWithDeps = [(Component, [ComponentName])]++-- | Pretty-print 'ComponentsWithDeps'.+--+dispComponentsWithDeps :: ComponentsWithDeps -> Doc+dispComponentsWithDeps graph =+ vcat [ hang (text "component" <+> pretty (componentName c)) 4+ (vcat [ text "dependency" <+> pretty cdep | cdep <- cdeps ])+ | (c, cdeps) <- graph ]++-- | Create a 'Graph' of 'Component', or report a cycle if there is a+-- problem.+--+mkComponentsGraph :: ComponentRequestedSpec+ -> PackageDescription+ -> Either [ComponentName] ComponentsGraph+mkComponentsGraph enabled pkg_descr =+ let g = Graph.fromDistinctList+ [ N c (componentName c) (componentDeps c)+ | c <- pkgBuildableComponents pkg_descr+ , componentEnabled enabled c ]+ in case Graph.cycles g of+ [] -> Right g+ ccycles -> Left [ componentName c | N c _ _ <- concat ccycles ]+ where+ -- The dependencies for the given component+ componentDeps component =+ toolDependencies ++ libDependencies+ where+ bi = componentBuildInfo component++ toolDependencies = CExeName <$> getAllInternalToolDependencies pkg_descr bi++ libDependencies = do+ Dependency pkgname _ lns <- targetBuildDepends bi+ guard (pkgname == packageName pkg_descr)++ ln <- NES.toList lns+ return (CLibName ln)++-- | Given the package description and a 'PackageDescription' (used+-- to determine if a package name is internal or not), sort the+-- components in dependency order (fewest dependencies first). This is+-- NOT necessarily the build order (although it is in the absence of+-- Backpack.)+--+componentsGraphToList :: ComponentsGraph+ -> ComponentsWithDeps+componentsGraphToList =+ map (\(N c _ cs) -> (c, cs)) . Graph.revTopSort++-- | Error message when there is a cycle; takes the SCC of components.+componentCycleMsg :: PackageIdentifier -> [ComponentName] -> Doc+componentCycleMsg pn cnames =+ text "Components in the package" <+> pretty pn <+> text "depend on each other in a cyclic way:"+ $$+ text (intercalate " depends on "+ [ "'" ++ showComponentName cname ++ "'"+ | cname <- cnames ++ maybeToList (safeHead cnames) ])
+ src/Distribution/Backpack/Configure.hs view
@@ -0,0 +1,359 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoMonoLocalBinds #-}+{-# LANGUAGE NondecreasingIndentation #-}++-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+--+-- WARNING: The contents of this module are HIGHLY experimental.+-- We may refactor it under you.+module Distribution.Backpack.Configure (+ configureComponentLocalBuildInfos,+) where++import Prelude ()+import Distribution.Compat.Prelude hiding ((<>))++import Distribution.Backpack+import Distribution.Backpack.FullUnitId+import Distribution.Backpack.PreExistingComponent+import Distribution.Backpack.ConfiguredComponent+import Distribution.Backpack.LinkedComponent+import Distribution.Backpack.ReadyComponent+import Distribution.Backpack.ComponentsGraph+import Distribution.Backpack.Id++import Distribution.Simple.Compiler+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+import Distribution.ModuleName+import Distribution.Simple.Setup as Setup+import Distribution.Simple.LocalBuildInfo+import Distribution.Types.AnnotatedId+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.ComponentInclude+import Distribution.Types.MungedPackageName+import Distribution.Verbosity+import qualified Distribution.Compat.Graph as Graph+import Distribution.Compat.Graph (Graph, IsNode(..))+import Distribution.Utils.LogProgress++import Data.Either+ ( lefts )+import qualified Data.Set as Set+import qualified Data.Map as Map+import Distribution.Pretty+import Text.PrettyPrint++------------------------------------------------------------------------------+-- Pipeline+------------------------------------------------------------------------------++configureComponentLocalBuildInfos+ :: Verbosity+ -> Bool -- use_external_internal_deps+ -> ComponentRequestedSpec+ -> Bool -- deterministic+ -> Flag String -- configIPID+ -> Flag ComponentId -- configCID+ -> PackageDescription+ -> [PreExistingComponent]+ -> FlagAssignment -- configConfigurationsFlags+ -> [(ModuleName, Module)] -- configInstantiateWith+ -> InstalledPackageIndex+ -> Compiler+ -> LogProgress ([ComponentLocalBuildInfo], InstalledPackageIndex)+configureComponentLocalBuildInfos+ verbosity use_external_internal_deps enabled deterministic ipid_flag cid_flag pkg_descr+ prePkgDeps flagAssignment instantiate_with installedPackageSet comp = do+ -- NB: In single component mode, this returns a *single* component.+ -- In this graph, the graph is NOT closed.+ graph0 <- case mkComponentsGraph enabled pkg_descr of+ Left ccycle -> dieProgress (componentCycleMsg (package pkg_descr) ccycle)+ Right g -> return (componentsGraphToList g)+ infoProgress $ hang (text "Source component graph:") 4+ (dispComponentsWithDeps graph0)++ let conf_pkg_map = Map.fromListWith Map.union+ [(pc_pkgname pkg,+ Map.singleton (pc_compname pkg)+ (AnnotatedId {+ ann_id = pc_cid pkg,+ ann_pid = packageId pkg,+ ann_cname = pc_compname pkg+ }))+ | pkg <- prePkgDeps]+ graph1 <- toConfiguredComponents use_external_internal_deps+ flagAssignment+ deterministic ipid_flag cid_flag pkg_descr+ conf_pkg_map (map fst graph0)+ infoProgress $ hang (text "Configured component graph:") 4+ (vcat (map dispConfiguredComponent graph1))++ let shape_pkg_map = Map.fromList+ [ (pc_cid pkg, (pc_open_uid pkg, pc_shape pkg))+ | pkg <- prePkgDeps]+ uid_lookup def_uid+ | Just pkg <- PackageIndex.lookupUnitId installedPackageSet uid+ = FullUnitId (Installed.installedComponentId pkg)+ (Map.fromList (Installed.instantiatedWith pkg))+ | otherwise = error ("uid_lookup: " ++ prettyShow uid)+ where uid = unDefUnitId def_uid+ graph2 <- toLinkedComponents verbosity uid_lookup+ (package pkg_descr) shape_pkg_map graph1++ infoProgress $+ hang (text "Linked component graph:") 4+ (vcat (map dispLinkedComponent graph2))++ let pid_map = Map.fromList $+ [ (pc_uid pkg, pc_munged_id pkg)+ | pkg <- prePkgDeps] +++ [ (Installed.installedUnitId pkg, mungedId pkg)+ | (_, Module uid _) <- instantiate_with+ , Just pkg <- [PackageIndex.lookupUnitId+ installedPackageSet (unDefUnitId uid)] ]+ subst = Map.fromList instantiate_with+ graph3 = toReadyComponents pid_map subst graph2+ graph4 = Graph.revTopSort (Graph.fromDistinctList graph3)++ infoProgress $ hang (text "Ready component graph:") 4+ (vcat (map dispReadyComponent graph4))++ toComponentLocalBuildInfos comp installedPackageSet pkg_descr prePkgDeps graph4++------------------------------------------------------------------------------+-- ComponentLocalBuildInfo+------------------------------------------------------------------------------++toComponentLocalBuildInfos+ :: Compiler+ -> InstalledPackageIndex -- FULL set+ -> PackageDescription+ -> [PreExistingComponent] -- external package deps+ -> [ReadyComponent]+ -> LogProgress ([ComponentLocalBuildInfo],+ InstalledPackageIndex) -- only relevant packages+toComponentLocalBuildInfos+ comp installedPackageSet pkg_descr externalPkgDeps graph = do+ -- Check and make sure that every instantiated component exists.+ -- We have to do this now, because prior to linking/instantiating+ -- we don't actually know what the full set of 'UnitId's we need+ -- are.+ let -- TODO: This is actually a bit questionable performance-wise,+ -- since we will pay for the ALL installed packages even if+ -- they are not related to what we are building. This was true+ -- in the old configure code.+ external_graph :: Graph (Either InstalledPackageInfo ReadyComponent)+ external_graph = Graph.fromDistinctList+ . map Left+ $ PackageIndex.allPackages installedPackageSet+ internal_graph :: Graph (Either InstalledPackageInfo ReadyComponent)+ internal_graph = Graph.fromDistinctList+ . map Right+ $ graph+ combined_graph = Graph.unionRight external_graph internal_graph+ local_graph = fromMaybe (error "toComponentLocalBuildInfos: closure returned Nothing")+ $ Graph.closure combined_graph (map nodeKey graph)+ -- The database of transitively reachable installed packages that the+ -- external components the package (as a whole) depends on. This will be+ -- used in several ways:+ --+ -- * We'll use it to do a consistency check so we're not depending+ -- on multiple versions of the same package (TODO: someday relax+ -- this for private dependencies.) See right below.+ --+ -- * We'll pass it on in the LocalBuildInfo, where preprocessors+ -- and other things will incorrectly use it to determine what+ -- the include paths and everything should be.+ --+ packageDependsIndex = PackageIndex.fromList (lefts local_graph)+ fullIndex = Graph.fromDistinctList local_graph+ case Graph.broken fullIndex of+ [] -> return ()+ broken ->+ -- TODO: ppr this+ dieProgress . text $+ "The following packages are broken because other"+ ++ " packages they depend on are missing. These broken "+ ++ "packages must be rebuilt before they can be used.\n"+ -- TODO: Undupe.+ ++ unlines [ "installed package "+ ++ prettyShow (packageId pkg)+ ++ " is broken due to missing package "+ ++ intercalate ", " (map prettyShow deps)+ | (Left pkg, deps) <- broken ]+ ++ unlines [ "planned package "+ ++ prettyShow (packageId pkg)+ ++ " is broken due to missing package "+ ++ intercalate ", " (map prettyShow deps)+ | (Right pkg, deps) <- broken ]++ -- In this section, we'd like to look at the 'packageDependsIndex'+ -- and see if we've picked multiple versions of the same+ -- installed package (this is bad, because it means you might+ -- get an error could not match foo-0.1:Type with foo-0.2:Type).+ --+ -- What is pseudoTopPkg for? I have no idea. It was used+ -- in the very original commit which introduced checking for+ -- inconsistencies 5115bb2be4e13841ea07dc9166b9d9afa5f0d012,+ -- and then moved out of PackageIndex and put here later.+ -- TODO: Try this code without it...+ --+ -- TODO: Move this into a helper function+ --+ -- TODO: This is probably wrong for Backpack+ let pseudoTopPkg :: InstalledPackageInfo+ pseudoTopPkg = emptyInstalledPackageInfo {+ Installed.installedUnitId = mkLegacyUnitId (packageId pkg_descr),+ Installed.sourcePackageId = packageId pkg_descr,+ Installed.depends = map pc_uid externalPkgDeps+ }+ case PackageIndex.dependencyInconsistencies+ . PackageIndex.insert pseudoTopPkg+ $ packageDependsIndex of+ [] -> return ()+ inconsistencies ->+ warnProgress $+ hang (text "This package indirectly depends on multiple versions of the same" <+>+ text "package. This is very likely to cause a compile failure.") 2+ (vcat [ text "package" <+> pretty (packageName user) <+>+ parens (pretty (installedUnitId user)) <+> text "requires" <+>+ pretty inst+ | (_dep_key, insts) <- inconsistencies+ , (inst, users) <- insts+ , user <- users ])+ let clbis = mkLinkedComponentsLocalBuildInfo comp graph+ -- forM clbis $ \(clbi,deps) -> info verbosity $ "UNIT" ++ hashUnitId (componentUnitId clbi) ++ "\n" ++ intercalate "\n" (map hashUnitId deps)+ return (clbis, packageDependsIndex)++-- Build ComponentLocalBuildInfo for each component we are going+-- to build.+--+-- This conversion is lossy; we lose some invariants from ReadyComponent+mkLinkedComponentsLocalBuildInfo+ :: Compiler+ -> [ReadyComponent]+ -> [ComponentLocalBuildInfo]+mkLinkedComponentsLocalBuildInfo comp rcs = map go rcs+ where+ internalUnits = Set.fromList (map rc_uid rcs)+ isInternal x = Set.member x internalUnits+ go rc =+ case rc_component rc of+ CLib lib ->+ let convModuleExport (modname', (Module uid modname))+ | this_uid == unDefUnitId uid+ , modname' == modname+ = Installed.ExposedModule modname' Nothing+ | otherwise+ = Installed.ExposedModule modname'+ (Just (OpenModule (DefiniteUnitId uid) modname))+ convOpenModuleExport (modname', modu@(OpenModule uid modname))+ | uid == this_open_uid+ , modname' == modname+ = Installed.ExposedModule modname' Nothing+ | otherwise+ = Installed.ExposedModule modname' (Just modu)+ convOpenModuleExport (_, OpenModuleVar _)+ = error "convOpenModuleExport: top-level modvar"+ exports =+ -- Loses invariants+ case rc_i rc of+ Left indefc -> map convOpenModuleExport+ $ Map.toList (indefc_provides indefc)+ Right instc -> map convModuleExport+ $ Map.toList (instc_provides instc)+ insts =+ case rc_i rc of+ Left indefc -> [ (m, OpenModuleVar m) | m <- indefc_requires indefc ]+ Right instc -> [ (m, OpenModule (DefiniteUnitId uid') m')+ | (m, Module uid' m') <- instc_insts instc ]++ compat_name = MungedPackageName (packageName rc) (libName lib)+ compat_key = computeCompatPackageKey comp compat_name (packageVersion rc) this_uid++ in LibComponentLocalBuildInfo {+ componentPackageDeps = cpds,+ componentUnitId = this_uid,+ componentComponentId = this_cid,+ componentInstantiatedWith = insts,+ componentIsIndefinite_ = is_indefinite,+ componentLocalName = cname,+ componentInternalDeps = internal_deps,+ componentExeDeps = exe_deps,+ componentIncludes = includes,+ componentExposedModules = exports,+ componentIsPublic = rc_public rc,+ componentCompatPackageKey = compat_key,+ componentCompatPackageName = compat_name+ }+ CFLib _ ->+ FLibComponentLocalBuildInfo {+ componentUnitId = this_uid,+ componentComponentId = this_cid,+ componentLocalName = cname,+ componentPackageDeps = cpds,+ componentExeDeps = exe_deps,+ componentInternalDeps = internal_deps,+ componentIncludes = includes+ }+ CExe _ ->+ ExeComponentLocalBuildInfo {+ componentUnitId = this_uid,+ componentComponentId = this_cid,+ componentLocalName = cname,+ componentPackageDeps = cpds,+ componentExeDeps = exe_deps,+ componentInternalDeps = internal_deps,+ componentIncludes = includes+ }+ CTest _ ->+ TestComponentLocalBuildInfo {+ componentUnitId = this_uid,+ componentComponentId = this_cid,+ componentLocalName = cname,+ componentPackageDeps = cpds,+ componentExeDeps = exe_deps,+ componentInternalDeps = internal_deps,+ componentIncludes = includes+ }+ CBench _ ->+ BenchComponentLocalBuildInfo {+ componentUnitId = this_uid,+ componentComponentId = this_cid,+ componentLocalName = cname,+ componentPackageDeps = cpds,+ componentExeDeps = exe_deps,+ componentInternalDeps = internal_deps,+ componentIncludes = includes+ }+ where+ this_uid = rc_uid rc+ this_open_uid = rc_open_uid rc+ this_cid = rc_cid rc+ cname = componentName (rc_component rc)+ cpds = rc_depends rc+ exe_deps = map ann_id $ rc_exe_deps rc+ is_indefinite =+ case rc_i rc of+ Left _ -> True+ Right _ -> False+ includes =+ map (\ci -> (ci_id ci, ci_renaming ci)) $+ case rc_i rc of+ Left indefc ->+ indefc_includes indefc+ Right instc ->+ map (\ci -> ci { ci_ann_id = fmap DefiniteUnitId (ci_ann_id ci) })+ (instc_includes instc)+ internal_deps = filter isInternal (nodeNeighbors rc)
+ src/Distribution/Backpack/ConfiguredComponent.hs view
@@ -0,0 +1,308 @@+{-# LANGUAGE PatternGuards #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.ConfiguredComponent (+ ConfiguredComponent(..),+ cc_name,+ cc_cid,+ cc_pkgid,+ toConfiguredComponent,+ toConfiguredComponents,+ dispConfiguredComponent,++ ConfiguredComponentMap,+ extendConfiguredComponentMap,++ -- TODO: Should go somewhere else+ newPackageDepsBehaviour+) where++import Prelude ()+import Distribution.Compat.Prelude hiding ((<>))++import Distribution.Backpack.Id++import Distribution.CabalSpecVersion+import Distribution.Types.AnnotatedId+import Distribution.Types.Dependency+import Distribution.Types.ExeDependency+import Distribution.Types.IncludeRenaming+import Distribution.Types.ComponentId+import Distribution.Types.PackageId+import Distribution.Types.PackageName+import Distribution.Types.Mixin+import Distribution.Types.ComponentName+import Distribution.Types.LibraryName+import Distribution.Types.ComponentInclude+import Distribution.Package+import Distribution.PackageDescription+import Distribution.Simple.BuildToolDepends+import Distribution.Simple.Setup as Setup+import Distribution.Simple.LocalBuildInfo+import Distribution.Utils.LogProgress+import Distribution.Utils.MapAccum+import Distribution.Utils.Generic++import Control.Monad+import qualified Data.Set as Set+import qualified Distribution.Compat.NonEmptySet as NonEmptySet+import qualified Data.Map as Map+import Distribution.Pretty+import Text.PrettyPrint (Doc, hang, text, vcat, hsep, quotes, ($$))+import qualified Text.PrettyPrint as PP++-- | A configured component, we know exactly what its 'ComponentId' is,+-- and the 'ComponentId's of the things it depends on.+data ConfiguredComponent+ = ConfiguredComponent {+ -- | Unique identifier of component, plus extra useful info.+ cc_ann_id :: AnnotatedId ComponentId,+ -- | The fragment of syntax from the Cabal file describing this+ -- component.+ cc_component :: Component,+ -- | Is this the public library component of the package?+ -- (If we invoke Setup with an instantiation, this is the+ -- component the instantiation applies to.)+ -- Note that in one-component configure mode, this is+ -- always True, because any component is the "public" one.)+ cc_public :: Bool,+ -- | Dependencies on executables from @build-tools@ and+ -- @build-tool-depends@.+ cc_exe_deps :: [AnnotatedId ComponentId],+ -- | The mixins of this package, including both explicit (from+ -- the @mixins@ field) and implicit (from @build-depends@). Not+ -- mix-in linked yet; component configuration only looks at+ -- 'ComponentId's.+ cc_includes :: [ComponentInclude ComponentId IncludeRenaming]+ }+++-- | Uniquely identifies a configured component.+cc_cid :: ConfiguredComponent -> ComponentId+cc_cid = ann_id . cc_ann_id++-- | The package this component came from.+cc_pkgid :: ConfiguredComponent -> PackageId+cc_pkgid = ann_pid . cc_ann_id++-- | The 'ComponentName' of a component; this uniquely identifies+-- a fragment of syntax within a specified Cabal file describing the+-- component.+cc_name :: ConfiguredComponent -> ComponentName+cc_name = ann_cname . cc_ann_id++-- | Pretty-print a 'ConfiguredComponent'.+dispConfiguredComponent :: ConfiguredComponent -> Doc+dispConfiguredComponent cc =+ hang (text "component" <+> pretty (cc_cid cc)) 4+ (vcat [ hsep $ [ text "include"+ , pretty (ci_id incl), pretty (ci_renaming incl) ]+ | incl <- cc_includes cc+ ])++-- | Construct a 'ConfiguredComponent', given that the 'ComponentId'+-- and library/executable dependencies are known. The primary+-- work this does is handling implicit @backpack-include@ fields.+mkConfiguredComponent+ :: PackageDescription+ -> ComponentId+ -> [AnnotatedId ComponentId] -- lib deps+ -> [AnnotatedId ComponentId] -- exe deps+ -> Component+ -> LogProgress ConfiguredComponent+mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do+ -- Resolve each @mixins@ into the actual dependency+ -- from @lib_deps@.+ explicit_includes <- forM (mixins bi) $ \(Mixin pn ln rns) -> do+ aid <- case Map.lookup (pn, CLibName ln) deps_map of+ Nothing ->+ dieProgress $+ text "Mix-in refers to non-existent library" <+>+ quotes (pretty pn <<>> prettyLN ln) $$+ text "(did you forget to add the package to build-depends?)"+ Just r -> return r+ return ComponentInclude {+ ci_ann_id = aid,+ ci_renaming = rns,+ ci_implicit = False+ }++ -- Any @build-depends@ which is not explicitly mentioned in+ -- @backpack-include@ is converted into an "implicit" include.+ let used_explicitly = Set.fromList (map ci_id explicit_includes)+ implicit_includes+ = map (\aid -> ComponentInclude {+ ci_ann_id = aid,+ ci_renaming = defaultIncludeRenaming,+ ci_implicit = True+ })+ $ filter (flip Set.notMember used_explicitly . ann_id) lib_deps++ return ConfiguredComponent {+ cc_ann_id = AnnotatedId {+ ann_id = this_cid,+ ann_pid = package pkg_descr,+ ann_cname = componentName component+ },+ cc_component = component,+ cc_public = is_public,+ cc_exe_deps = exe_deps,+ cc_includes = explicit_includes ++ implicit_includes+ }+ where+ bi :: BuildInfo+ bi = componentBuildInfo component++ prettyLN :: LibraryName -> Doc+ prettyLN LMainLibName = PP.empty+ prettyLN (LSubLibName n) = PP.colon <<>> pretty n++ deps_map :: Map (PackageName, ComponentName) (AnnotatedId ComponentId)+ deps_map = Map.fromList [ ((packageName dep, ann_cname dep), dep)+ | dep <- lib_deps ]++ is_public = componentName component == CLibName LMainLibName++type ConfiguredComponentMap =+ Map PackageName (Map ComponentName (AnnotatedId ComponentId))++toConfiguredComponent+ :: PackageDescription+ -> ComponentId+ -> ConfiguredComponentMap+ -> ConfiguredComponentMap+ -> Component+ -> LogProgress ConfiguredComponent+toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do+ lib_deps <-+ if newPackageDepsBehaviour pkg_descr+ then fmap concat $ forM (targetBuildDepends bi) $+ \(Dependency name _ sublibs) -> do+ pkg <- case Map.lookup name lib_dep_map of+ Nothing ->+ dieProgress $+ text "Dependency on unbuildable" <+>+ text "package" <+> pretty name+ Just p -> return p+ -- Return all library components+ forM (NonEmptySet.toList sublibs) $ \lib ->+ let comp = CLibName lib in+ case Map.lookup comp pkg of+ Nothing ->+ dieProgress $+ text "Dependency on unbuildable" <+>+ text (showLibraryName lib) <+>+ text "from" <+> pretty name+ Just v -> return v+ else return old_style_lib_deps+ mkConfiguredComponent+ pkg_descr this_cid+ lib_deps exe_deps component+ where+ bi = componentBuildInfo component+ -- lib_dep_map contains a mix of internal and external deps.+ -- We want all the public libraries (dep_cn == CLibName)+ -- of all external deps (dep /= pn). Note that this+ -- excludes the public library of the current package:+ -- this is not supported by old-style deps behavior+ -- because it would imply a cyclic dependency for the+ -- library itself.+ old_style_lib_deps = [ e+ | (pn, comp_map) <- Map.toList lib_dep_map+ , pn /= packageName pkg_descr+ , (cn, e) <- Map.toList comp_map+ , cn == CLibName LMainLibName ]+ -- We have to nub here, because 'getAllToolDependencies' may return+ -- duplicates (see #4986). (NB: This is not needed for lib_deps,+ -- since those elaborate into includes, for which there explicitly+ -- may be multiple instances of a package)+ exe_deps = ordNub $+ [ exe+ | ExeDependency pn cn _ <- getAllToolDependencies pkg_descr bi+ -- The error suppression here is important, because in general+ -- we won't know about external dependencies (e.g., 'happy')+ -- which the package is attempting to use (those deps are only+ -- fed in when cabal-install uses this codepath.)+ -- TODO: Let cabal-install request errors here+ , Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup pn exe_dep_map]+ ]++-- | Also computes the 'ComponentId', and sets cc_public if necessary.+-- This is Cabal-only; cabal-install won't use this.+toConfiguredComponent'+ :: Bool -- use_external_internal_deps+ -> FlagAssignment+ -> PackageDescription+ -> Bool -- deterministic+ -> Flag String -- configIPID (todo: remove me)+ -> Flag ComponentId -- configCID+ -> ConfiguredComponentMap+ -> Component+ -> LogProgress ConfiguredComponent+toConfiguredComponent' use_external_internal_deps flags+ pkg_descr deterministic ipid_flag cid_flag+ dep_map component = do+ cc <- toConfiguredComponent+ pkg_descr this_cid+ dep_map dep_map component+ return $ if use_external_internal_deps+ then cc { cc_public = True }+ else cc+ where+ -- TODO: pass component names to it too!+ this_cid = computeComponentId deterministic ipid_flag cid_flag+ (package pkg_descr) (componentName component) (Just (deps, flags))+ deps = [ ann_id aid | m <- Map.elems dep_map+ , aid <- Map.elems m ]++extendConfiguredComponentMap+ :: ConfiguredComponent+ -> ConfiguredComponentMap+ -> ConfiguredComponentMap+extendConfiguredComponentMap cc =+ Map.insertWith Map.union+ (pkgName (cc_pkgid cc))+ (Map.singleton (cc_name cc) (cc_ann_id cc))++-- Compute the 'ComponentId's for a graph of 'Component's. The+-- list of internal components must be topologically sorted+-- based on internal package dependencies, so that any internal+-- dependency points to an entry earlier in the list.+--+-- TODO: This function currently restricts the input configured components to+-- one version per package, by using the type ConfiguredComponentMap. It cannot+-- be used to configure a component that depends on one version of a package for+-- a library and another version for a build-tool.+toConfiguredComponents+ :: Bool -- use_external_internal_deps+ -> FlagAssignment+ -> Bool -- deterministic+ -> Flag String -- configIPID+ -> Flag ComponentId -- configCID+ -> PackageDescription+ -> ConfiguredComponentMap+ -> [Component]+ -> LogProgress [ConfiguredComponent]+toConfiguredComponents+ use_external_internal_deps flags deterministic ipid_flag cid_flag pkg_descr+ dep_map comps+ = fmap snd (mapAccumM go dep_map comps)+ where+ go m component = do+ cc <- toConfiguredComponent'+ use_external_internal_deps flags pkg_descr+ deterministic ipid_flag cid_flag+ m component+ return (extendConfiguredComponentMap cc m, cc)++newPackageDepsBehaviourMinVersion :: CabalSpecVersion+newPackageDepsBehaviourMinVersion = CabalSpecV1_8+++-- 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
+ src/Distribution/Backpack/DescribeUnitId.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE Rank2Types #-}+module Distribution.Backpack.DescribeUnitId where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Compat.Stack+import Distribution.ModuleName+import Distribution.Pretty+import Distribution.Simple.Utils+import Distribution.Types.ComponentName+import Distribution.Types.PackageId+import Distribution.Verbosity++import Text.PrettyPrint++-- Unit identifiers have a well defined, machine-readable format,+-- but this format isn't very user-friendly for users. This+-- module defines some functions for solving common rendering+-- problems one has for displaying these.+--+-- There are three basic problems we tackle:+--+-- - Users don't want to see pkg-0.5-inplace-libname,+-- they want to see "library 'libname' from 'pkg-0.5'"+--+-- - Users don't want to see the raw component identifier, which+-- usually contains a wordy hash that doesn't matter.+--+-- - Users don't want to see a hash of the instantiation: they+-- want to see the actual instantiation, and they want it in+-- interpretable form.+--++-- | Print a Setup message stating (1) what operation we are doing,+-- for (2) which component (with enough details to uniquely identify+-- the build in question.)+--+setupMessage' :: Pretty a => Verbosity+ -> String -- ^ Operation being done (capitalized), on:+ -> PackageIdentifier -- ^ Package+ -> ComponentName -- ^ Component name+ -> Maybe [(ModuleName, a)] -- ^ Instantiation, if available.+ -- Polymorphic to take+ -- 'OpenModule' or 'Module'+ -> IO ()+setupMessage' verbosity msg pkgid cname mb_insts = withFrozenCallStack $ do+ noticeDoc verbosity $+ case mb_insts of+ Just insts | not (null insts) ->+ hang (msg_doc <+> text "instantiated with") 2+ (vcat [ pretty k <+> text "=" <+> pretty v+ | (k,v) <- insts ]) $$+ for_doc+ _ ->+ msg_doc <+> for_doc++ where+ msg_doc = text msg <+> text (showComponentName cname)+ for_doc = text "for" <+> pretty pkgid <<>> text ".."
+ src/Distribution/Backpack/FullUnitId.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Backpack.FullUnitId (+ FullUnitId(..),+ FullDb,+ expandOpenUnitId,+ expandUnitId+) where++import Distribution.Backpack+import Distribution.Types.ComponentId+import Distribution.Compat.Prelude++-- Unlike OpenUnitId, which could direct to a UnitId.+data FullUnitId = FullUnitId ComponentId OpenModuleSubst+ deriving (Show, Generic)++type FullDb = DefUnitId -> FullUnitId++expandOpenUnitId :: FullDb -> OpenUnitId -> FullUnitId+expandOpenUnitId _db (IndefFullUnitId cid subst)+ = FullUnitId cid subst+expandOpenUnitId db (DefiniteUnitId uid)+ = expandUnitId db uid++expandUnitId :: FullDb -> DefUnitId -> FullUnitId+expandUnitId db uid = db uid
+ src/Distribution/Backpack/Id.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE PatternGuards #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.Id(+ computeComponentId,+ computeCompatPackageKey,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.UnqualComponentName+import Distribution.Simple.Compiler+import Distribution.PackageDescription+import Distribution.Simple.Setup as Setup+import qualified Distribution.Simple.InstallDirs as InstallDirs+import Distribution.Simple.LocalBuildInfo+import Distribution.Types.ComponentId+import Distribution.Types.UnitId+import Distribution.Types.MungedPackageName+import Distribution.Utils.Base62+import Distribution.Version++import Distribution.Pretty+ ( prettyShow )+import Distribution.Parsec ( simpleParsec )++-- | 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+ :: Bool -- deterministic mode+ -> Flag String+ -> Flag ComponentId+ -> PackageIdentifier+ -> ComponentName+ -- This is used by cabal-install's legacy codepath+ -> Maybe ([ComponentId], FlagAssignment)+ -> ComponentId+computeComponentId deterministic mb_ipid mb_cid pid cname mb_details =+ -- 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_suffix+ | Just (dep_ipids, flags) <- mb_details+ = "-" ++ hashToBase62+ -- For safety, include the package + version here+ -- for GHC 7.10, where just the hash is used as+ -- the package key+ ( prettyShow pid+ ++ show dep_ipids+ ++ show flags )+ | otherwise = ""+ generated_base = prettyShow pid ++ hash_suffix+ explicit_base cid0 = fromPathTemplate (InstallDirs.substPathTemplate env+ (toPathTemplate cid0))+ -- Hack to reuse install dirs machinery+ -- NB: no real IPID available at this point+ where env = packageTemplateEnv pid (mkUnitId "")+ actual_base = case mb_ipid of+ Flag ipid0 -> explicit_base ipid0+ NoFlag | deterministic -> prettyShow pid+ | otherwise -> generated_base+ in case mb_cid of+ Flag cid -> cid+ NoFlag -> mkComponentId $ actual_base+ ++ (case componentNameString cname of+ Nothing -> ""+ Just s -> "-" ++ unUnqualComponentName s)++-- | 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:+--+-- * We use the *compatibility* package name and version. For+-- public libraries this is just the package identifier; for+-- internal libraries, it's something like "z-pkgname-z-libname-0.1".+-- See 'computeCompatPackageName' for more details.+--+-- 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+ -> MungedPackageName+ -> Version+ -> UnitId+ -> String+computeCompatPackageKey comp pkg_name pkg_version uid+ | not (packageKeySupported comp || unitIdSupported comp)+ = prettyShow pkg_name ++ "-" ++ prettyShow pkg_version+ | not (unifiedIPIDRequired comp) =+ let str = unUnitId uid -- assume no Backpack support+ mb_verbatim_key+ = case simpleParsec 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 | prettyShow 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 fromMaybe rehashed_key (mb_verbatim_key `mplus` mb_truncated_key)+ | otherwise = prettyShow uid
+ src/Distribution/Backpack/LinkedComponent.hs view
@@ -0,0 +1,396 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.LinkedComponent (+ LinkedComponent(..),+ lc_insts,+ lc_uid,+ lc_cid,+ lc_pkgid,+ toLinkedComponent,+ toLinkedComponents,+ dispLinkedComponent,+ LinkedComponentMap,+ extendLinkedComponentMap,+) where++import Prelude ()+import Distribution.Compat.Prelude hiding ((<>))++import Distribution.Backpack+import Distribution.Backpack.FullUnitId+import Distribution.Backpack.ConfiguredComponent+import Distribution.Backpack.ModuleShape+import Distribution.Backpack.PreModuleShape+import Distribution.Backpack.ModuleScope+import Distribution.Backpack.UnifyM+import Distribution.Backpack.MixLink+import Distribution.Utils.MapAccum++import Distribution.Types.AnnotatedId+import Distribution.Types.ComponentName+import Distribution.Types.ModuleReexport+import Distribution.Types.ModuleRenaming+import Distribution.Types.IncludeRenaming+import Distribution.Types.ComponentInclude+import Distribution.Types.ComponentId+import Distribution.Types.PackageId+import Distribution.Package+import Distribution.PackageDescription+import Distribution.ModuleName+import Distribution.Simple.LocalBuildInfo+import Distribution.Verbosity+import Distribution.Utils.LogProgress++import qualified Data.Set as Set+import qualified Data.Map as Map+import Distribution.Pretty (pretty)+import Text.PrettyPrint (Doc, hang, text, vcat, ($+$), hsep, quotes)++-- | A linked component is a component that has been mix-in linked, at+-- which point we have determined how all the dependencies of the+-- component are explicitly instantiated (in the form of an OpenUnitId).+-- 'ConfiguredComponent' is mix-in linked into 'LinkedComponent', which+-- is then instantiated into 'ReadyComponent'.+data LinkedComponent+ = LinkedComponent {+ -- | Uniquely identifies linked component+ lc_ann_id :: AnnotatedId ComponentId,+ -- | Corresponds to 'cc_component'.+ lc_component :: Component,+ -- | @build-tools@ and @build-tool-depends@ dependencies.+ -- Corresponds to 'cc_exe_deps'.+ lc_exe_deps :: [AnnotatedId OpenUnitId],+ -- | Is this the public library of a package? Corresponds to+ -- 'cc_public'.+ lc_public :: Bool,+ -- | Corresponds to 'cc_includes', but (1) this does not contain+ -- includes of signature packages (packages with no exports),+ -- and (2) the 'ModuleRenaming' for requirements (stored in+ -- 'IncludeRenaming') has been removed, as it is reflected in+ -- 'OpenUnitId'.)+ lc_includes :: [ComponentInclude OpenUnitId ModuleRenaming],+ -- | Like 'lc_includes', but this specifies includes on+ -- signature packages which have no exports.+ lc_sig_includes :: [ComponentInclude OpenUnitId ModuleRenaming],+ -- | The module shape computed by mix-in linking. This is+ -- newly computed from 'ConfiguredComponent'+ lc_shape :: ModuleShape+ }++-- | Uniquely identifies a 'LinkedComponent'. Corresponds to+-- 'cc_cid'.+lc_cid :: LinkedComponent -> ComponentId+lc_cid = ann_id . lc_ann_id++-- | Corresponds to 'cc_pkgid'.+lc_pkgid :: LinkedComponent -> PackageId+lc_pkgid = ann_pid . lc_ann_id++-- | The 'OpenUnitId' of this component in the "default" instantiation.+-- See also 'lc_insts'. 'LinkedComponent's cannot be instantiated+-- (e.g., there is no 'ModSubst' instance for them).+lc_uid :: LinkedComponent -> OpenUnitId+lc_uid lc = IndefFullUnitId (lc_cid lc) . Map.fromList $ lc_insts lc++-- | The instantiation of 'lc_uid'; this always has the invariant+-- that it is a mapping from a module name @A@ to @<A>@ (the hole A).+lc_insts :: LinkedComponent -> [(ModuleName, OpenModule)]+lc_insts lc = [ (req, OpenModuleVar req)+ | req <- Set.toList (modShapeRequires (lc_shape lc)) ]++dispLinkedComponent :: LinkedComponent -> Doc+dispLinkedComponent lc =+ hang (text "unit" <+> pretty (lc_uid lc)) 4 $+ vcat [ text "include" <+> pretty (ci_id incl) <+> pretty (ci_renaming incl)+ | incl <- lc_includes lc ]+ $+$+ vcat [ text "signature include" <+> pretty (ci_id incl)+ | incl <- lc_sig_includes lc ]+ $+$ dispOpenModuleSubst (modShapeProvides (lc_shape lc))++instance Package LinkedComponent where+ packageId = lc_pkgid++toLinkedComponent+ :: Verbosity+ -> FullDb+ -> PackageId+ -> LinkedComponentMap+ -> ConfiguredComponent+ -> LogProgress LinkedComponent+toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {+ cc_ann_id = aid@AnnotatedId { ann_id = this_cid },+ cc_component = component,+ cc_exe_deps = exe_deps,+ cc_public = is_public,+ cc_includes = cid_includes+ } = do+ let+ -- The explicitly specified requirements, provisions and+ -- reexports from the Cabal file. These are only non-empty for+ -- libraries; everything else is trivial.+ (src_reqs :: [ModuleName],+ src_provs :: [ModuleName],+ src_reexports :: [ModuleReexport]) =+ case component of+ CLib lib -> (signatures lib,+ exposedModules lib,+ reexportedModules lib)+ _ -> ([], [], [])+ src_hidden = otherModules (componentBuildInfo component)++ -- Take each included ComponentId and resolve it into an+ -- *unlinked* unit identity. We will use unification (relying+ -- on the ModuleShape) to resolve these into linked identities.+ unlinked_includes :: [ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming]+ unlinked_includes = [ ComponentInclude (fmap lookupUid dep_aid) rns i+ | ComponentInclude dep_aid rns i <- cid_includes ]++ lookupUid :: ComponentId -> (OpenUnitId, ModuleShape)+ lookupUid cid = fromMaybe (error "linkComponent: lookupUid")+ (Map.lookup cid pkg_map)++ let orErr (Right x) = return x+ orErr (Left [err]) = dieProgress err+ orErr (Left errs) = do+ dieProgress (vcat (intersperse (text "") -- double newline!+ [ hang (text "-") 2 err | err <- errs]))++ -- Pre-shaping+ let pre_shape = mixLinkPreModuleShape $+ PreModuleShape {+ preModShapeProvides = Set.fromList (src_provs ++ src_hidden),+ preModShapeRequires = Set.fromList src_reqs+ } : [ renamePreModuleShape (toPreModuleShape sh) rns+ | ComponentInclude (AnnotatedId { ann_id = (_, sh) }) rns _ <- unlinked_includes ]+ reqs = preModShapeRequires pre_shape+ insts = [ (req, OpenModuleVar req)+ | req <- Set.toList reqs ]+ this_uid = IndefFullUnitId this_cid . Map.fromList $ insts++ -- OK, actually do unification+ -- TODO: the unification monad might return errors, in which+ -- case we have to deal. Use monadic bind for now.+ (linked_shape0 :: ModuleScope,+ linked_includes0 :: [ComponentInclude OpenUnitId ModuleRenaming],+ linked_sig_includes0 :: [ComponentInclude OpenUnitId ModuleRenaming])+ <- orErr $ runUnifyM verbosity this_cid db $ do+ -- The unification monad is implemented using mutable+ -- references. Thus, we must convert our *pure* data+ -- structures into mutable ones to perform unification.++ let convertMod :: (ModuleName -> ModuleSource) -> ModuleName -> UnifyM s (ModuleScopeU s)+ convertMod from m = do+ m_u <- convertModule (OpenModule this_uid m)+ return (Map.singleton m [WithSource (from m) m_u], Map.empty)+ -- Handle 'exposed-modules'+ exposed_mod_shapes_u <- traverse (convertMod FromExposedModules) src_provs+ -- Handle 'other-modules'+ other_mod_shapes_u <- traverse (convertMod FromOtherModules) src_hidden++ -- Handle 'signatures'+ let convertReq :: ModuleName -> UnifyM s (ModuleScopeU s)+ convertReq req = do+ req_u <- convertModule (OpenModuleVar req)+ return (Map.empty, Map.singleton req [WithSource (FromSignatures req) req_u])+ req_shapes_u <- traverse convertReq src_reqs++ -- Handle 'mixins'+ (incl_shapes_u, all_includes_u) <- fmap unzip (traverse convertInclude unlinked_includes)++ failIfErrs -- Prevent error cascade+ -- Mix-in link everything! mixLink is the real workhorse.+ shape_u <- mixLink $ exposed_mod_shapes_u+ ++ other_mod_shapes_u+ ++ req_shapes_u+ ++ incl_shapes_u++ -- src_reqs_u <- traverse convertReq src_reqs+ -- Read out all the final results by converting back+ -- into a pure representation.+ let convertIncludeU (ComponentInclude dep_aid rns i) = do+ uid <- convertUnitIdU (ann_id dep_aid)+ return (ComponentInclude {+ ci_ann_id = dep_aid { ann_id = uid },+ ci_renaming = rns,+ ci_implicit = i+ })+ shape <- convertModuleScopeU shape_u+ let (includes_u, sig_includes_u) = partitionEithers all_includes_u+ incls <- traverse convertIncludeU includes_u+ sig_incls <- traverse convertIncludeU sig_includes_u+ return (shape, incls, sig_incls)++ let isNotLib (CLib _) = False+ isNotLib _ = True+ when (not (Set.null reqs) && isNotLib component) $+ dieProgress $+ hang (text "Non-library component has unfilled requirements:")+ 4 (vcat [pretty req | req <- Set.toList reqs])++ -- NB: do NOT include hidden modules here: GHC 7.10's ghc-pkg+ -- won't allow it (since someone could directly synthesize+ -- an 'InstalledPackageInfo' that violates abstraction.)+ -- Though, maybe it should be relaxed?+ let src_hidden_set = Set.fromList src_hidden+ linked_shape = linked_shape0 {+ modScopeProvides =+ -- Would rather use withoutKeys but need BC+ Map.filterWithKey+ (\k _ -> not (k `Set.member` src_hidden_set))+ (modScopeProvides linked_shape0)+ }++ -- OK, compute the reexports+ -- TODO: This code reports the errors for reexports one reexport at+ -- a time. Better to collect them all up and report them all at+ -- once.+ let hdl :: [Either Doc a] -> LogProgress [a]+ hdl es =+ case partitionEithers es of+ ([], rs) -> return rs+ (ls, _) ->+ dieProgress $+ hang (text "Problem with module re-exports:") 2+ (vcat [hang (text "-") 2 l | l <- ls])+ reexports_list <- hdl . (flip map) src_reexports $ \reex@(ModuleReexport mb_pn from to) -> do+ case Map.lookup from (modScopeProvides linked_shape) of+ Just cands@(x0:xs0) -> do+ -- Make sure there is at least one candidate+ (x, xs) <-+ case mb_pn of+ Just pn ->+ let matches_pn (FromMixins pn' _ _) = pn == pn'+ matches_pn (FromBuildDepends pn' _) = pn == pn'+ matches_pn (FromExposedModules _) = pn == packageName this_pid+ matches_pn (FromOtherModules _) = pn == packageName this_pid+ matches_pn (FromSignatures _) = pn == packageName this_pid+ in case filter (matches_pn . getSource) cands of+ (x1:xs1) -> return (x1, xs1)+ _ -> Left (brokenReexportMsg reex)+ Nothing -> return (x0, xs0)+ -- Test that all the candidates are consistent+ case filter (\x' -> unWithSource x /= unWithSource x') xs of+ [] -> return ()+ _ -> Left $ ambiguousReexportMsg reex x xs+ return (to, unWithSource x)+ _ ->+ Left (brokenReexportMsg reex)++ -- TODO: maybe check this earlier; it's syntactically obvious.+ let build_reexports m (k, v)+ | Map.member k m =+ dieProgress $ hsep+ [ text "Module name ", pretty k, text " is exported multiple times." ]+ | otherwise = return (Map.insert k v m)+ provs <- foldM build_reexports Map.empty $+ -- TODO: doublecheck we have checked for+ -- src_provs duplicates already!+ [ (mod_name, OpenModule this_uid mod_name) | mod_name <- src_provs ] +++ reexports_list++ let final_linked_shape = ModuleShape provs (Map.keysSet (modScopeRequires linked_shape))++ -- See Note Note [Signature package special case]+ let (linked_includes, linked_sig_includes)+ | Set.null reqs = (linked_includes0 ++ linked_sig_includes0, [])+ | otherwise = (linked_includes0, linked_sig_includes0)++ return $ LinkedComponent {+ lc_ann_id = aid,+ lc_component = component,+ lc_public = is_public,+ -- These must be executables+ lc_exe_deps = map (fmap (\cid -> IndefFullUnitId cid Map.empty)) exe_deps,+ lc_shape = final_linked_shape,+ lc_includes = linked_includes,+ lc_sig_includes = linked_sig_includes+ }++-- Note [Signature package special case]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Suppose we have p-indef, which depends on str-sig and inherits+-- the hole from that signature package. When we instantiate p-indef,+-- it's a bit pointless to also go ahead and build str-sig, because+-- str-sig cannot possibly have contributed any code to the package+-- in question. Furthermore, because the signature was inherited to+-- p-indef, if we test matching against p-indef, we also have tested+-- matching against p-sig. In fact, skipping p-sig is *mandatory*,+-- because p-indef may have thinned it (so that an implementation may+-- match p-indef but not p-sig.)+--+-- However, suppose that we have a package which mixes together str-sig+-- and str-bytestring, with the intent of *checking* that str-sig is+-- implemented by str-bytestring. Here, it's quite important to+-- build an instantiated str-sig, since that is the only way we will+-- actually end up testing if the matching works. Note that this+-- admonition only applies if the package has NO requirements; if it+-- has any requirements, we will typecheck it as an indefinite+-- package, at which point the signature includes will be passed to+-- GHC who will in turn actually do the checking to make sure they+-- are instantiated correctly.++-- Handle mix-in linking for components. In the absence of Backpack,+-- every ComponentId gets converted into a UnitId by way of SimpleUnitId.+toLinkedComponents+ :: Verbosity+ -> FullDb+ -> PackageId+ -> LinkedComponentMap+ -> [ConfiguredComponent]+ -> LogProgress [LinkedComponent]+toLinkedComponents verbosity db this_pid lc_map0 comps+ = fmap snd (mapAccumM go lc_map0 comps)+ where+ go :: Map ComponentId (OpenUnitId, ModuleShape)+ -> ConfiguredComponent+ -> LogProgress (Map ComponentId (OpenUnitId, ModuleShape), LinkedComponent)+ go lc_map cc = do+ lc <- addProgressCtx (text "In the stanza" <+> text (componentNameStanza (cc_name cc))) $+ toLinkedComponent verbosity db this_pid lc_map cc+ return (extendLinkedComponentMap lc lc_map, lc)++type LinkedComponentMap = Map ComponentId (OpenUnitId, ModuleShape)++extendLinkedComponentMap :: LinkedComponent+ -> LinkedComponentMap+ -> LinkedComponentMap+extendLinkedComponentMap lc m =+ Map.insert (lc_cid lc) (lc_uid lc, lc_shape lc) m++brokenReexportMsg :: ModuleReexport -> Doc+brokenReexportMsg (ModuleReexport (Just pn) from _to) =+ vcat [ text "The package" <+> quotes (pretty pn)+ , text "does not export a module" <+> quotes (pretty from) ]+brokenReexportMsg (ModuleReexport Nothing from _to) =+ vcat [ text "The module" <+> quotes (pretty from)+ , text "is not exported by any suitable package."+ , text "It occurs in neither the 'exposed-modules' of this package,"+ , text "nor any of its 'build-depends' dependencies." ]++ambiguousReexportMsg :: ModuleReexport -> ModuleWithSource -> [ModuleWithSource] -> Doc+ambiguousReexportMsg (ModuleReexport mb_pn from _to) y1 ys =+ vcat [ text "Ambiguous reexport" <+> quotes (pretty from)+ , hang (text "It could refer to either:") 2+ (vcat (msg : msgs))+ , help_msg mb_pn ]+ where+ msg = text " " <+> displayModuleWithSource y1+ msgs = [text "or" <+> displayModuleWithSource y | y <- ys]+ help_msg Nothing =+ -- TODO: This advice doesn't help if the ambiguous exports+ -- come from a package named the same thing+ vcat [ text "The ambiguity can be resolved by qualifying the"+ , text "re-export with a package name."+ , text "The syntax is 'packagename:ModuleName [as NewName]'." ]+ -- Qualifying won't help that much.+ help_msg (Just _) =+ vcat [ text "The ambiguity can be resolved by using the"+ , text "mixins field to rename one of the module"+ , text "names differently." ]+ displayModuleWithSource y+ = vcat [ quotes (pretty (unWithSource y))+ , text "brought into scope by" <+>+ dispModuleSource (getSource y)+ ]
+ src/Distribution/Backpack/MixLink.hs view
@@ -0,0 +1,185 @@+{-# LANGUAGE NondecreasingIndentation #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.MixLink (+ mixLink,+) where++import Prelude ()+import Distribution.Compat.Prelude hiding (mod)++import Distribution.Backpack+import Distribution.Backpack.UnifyM+import Distribution.Backpack.FullUnitId+import Distribution.Backpack.ModuleScope++import qualified Distribution.Utils.UnionFind as UnionFind+import Distribution.ModuleName+import Distribution.Pretty+import Distribution.Types.ComponentId++import Text.PrettyPrint+import Control.Monad+import qualified Data.Map as Map+import qualified Data.Foldable as F++-----------------------------------------------------------------------+-- Linking++-- | Given to scopes of provisions and requirements, link them together.+mixLink :: [ModuleScopeU s] -> UnifyM s (ModuleScopeU s)+mixLink scopes = do+ let provs = Map.unionsWith (++) (map fst scopes)+ -- Invariant: any identically named holes refer to same mutable cell+ reqs = Map.unionsWith (++) (map snd scopes)+ filled = Map.intersectionWithKey linkProvision provs reqs+ F.sequenceA_ filled+ let remaining = Map.difference reqs filled+ return (provs, remaining)++-- | Link a list of possibly provided modules to a single+-- requirement. This applies a side-condition that all+-- of the provided modules at the same name are *actually*+-- the same module.+linkProvision :: ModuleName+ -> [ModuleWithSourceU s] -- provs+ -> [ModuleWithSourceU s] -- reqs+ -> UnifyM s [ModuleWithSourceU s]+linkProvision mod_name ret@(prov:provs) (req:reqs) = do+ -- TODO: coalesce all the non-unifying modules together+ forM_ provs $ \prov' -> do+ -- Careful: read it out BEFORE unifying, because the+ -- unification algorithm preemptively unifies modules+ mod <- convertModuleU (unWithSource prov)+ mod' <- convertModuleU (unWithSource prov')+ r <- unify prov prov'+ case r of+ Just () -> return ()+ Nothing -> do+ addErr $+ text "Ambiguous module" <+> quotes (pretty mod_name) $$+ text "It could refer to" <+>+ ( text " " <+> (quotes (pretty mod) $$ in_scope_by (getSource prov)) $$+ text "or" <+> (quotes (pretty mod') $$ in_scope_by (getSource prov')) ) $$+ link_doc+ mod <- convertModuleU (unWithSource prov)+ req_mod <- convertModuleU (unWithSource req)+ self_cid <- fmap unify_self_cid getUnifEnv+ case mod of+ OpenModule (IndefFullUnitId cid _) _+ | cid == self_cid -> addErr $+ text "Cannot instantiate requirement" <+> quotes (pretty mod_name) <+>+ in_scope_by (getSource req) $$+ text "with locally defined module" <+> in_scope_by (getSource prov) $$+ text "as this would create a cyclic dependency, which GHC does not support." $$+ text "Try moving this module to a separate library, e.g.," $$+ text "create a new stanza: library 'sublib'."+ _ -> return ()+ r <- unify prov req+ case r of+ Just () -> return ()+ Nothing -> do+ -- TODO: Record and report WHERE the bad constraint came from+ addErr $ text "Could not instantiate requirement" <+> quotes (pretty mod_name) $$+ nest 4 (text "Expected:" <+> pretty mod $$+ text "Actual: " <+> pretty req_mod) $$+ parens (text "This can occur if an exposed module of" <+>+ text "a libraries shares a name with another module.") $$+ link_doc+ return ret+ where+ unify s1 s2 = tryM $ addErrContext short_link_doc+ $ unifyModule (unWithSource s1) (unWithSource s2)+ in_scope_by s = text "brought into scope by" <+> dispModuleSource s+ short_link_doc = text "While filling requirement" <+> quotes (pretty mod_name)+ link_doc = text "While filling requirements of" <+> reqs_doc+ reqs_doc+ | null reqs = dispModuleSource (getSource req)+ | otherwise = ( text " " <+> dispModuleSource (getSource req) $$+ vcat [ text "and" <+> dispModuleSource (getSource r) | r <- reqs])+linkProvision _ _ _ = error "linkProvision"++++-----------------------------------------------------------------------+-- The unification algorithm++-- This is based off of https://gist.github.com/amnn/559551517d020dbb6588+-- which is a translation from Huet's thesis.++unifyUnitId :: UnitIdU s -> UnitIdU s -> UnifyM s ()+unifyUnitId uid1_u uid2_u+ | uid1_u == uid2_u = return ()+ | otherwise = do+ xuid1 <- liftST $ UnionFind.find uid1_u+ xuid2 <- liftST $ UnionFind.find uid2_u+ case (xuid1, xuid2) of+ (UnitIdThunkU u1, UnitIdThunkU u2)+ | u1 == u2 -> return ()+ | otherwise ->+ failWith $ hang (text "Couldn't match unit IDs:") 4+ (text " " <+> pretty u1 $$+ text "and" <+> pretty u2)+ (UnitIdThunkU uid1, UnitIdU _ cid2 insts2)+ -> unifyThunkWith cid2 insts2 uid2_u uid1 uid1_u+ (UnitIdU _ cid1 insts1, UnitIdThunkU uid2)+ -> unifyThunkWith cid1 insts1 uid1_u uid2 uid2_u+ (UnitIdU _ cid1 insts1, UnitIdU _ cid2 insts2)+ -> unifyInner cid1 insts1 uid1_u cid2 insts2 uid2_u++unifyThunkWith :: ComponentId+ -> Map ModuleName (ModuleU s)+ -> UnitIdU s+ -> DefUnitId+ -> UnitIdU s+ -> UnifyM s ()+unifyThunkWith cid1 insts1 uid1_u uid2 uid2_u = do+ db <- fmap unify_db getUnifEnv+ let FullUnitId cid2 insts2' = expandUnitId db uid2+ insts2 <- convertModuleSubst insts2'+ unifyInner cid1 insts1 uid1_u cid2 insts2 uid2_u++unifyInner :: ComponentId+ -> Map ModuleName (ModuleU s)+ -> UnitIdU s+ -> ComponentId+ -> Map ModuleName (ModuleU s)+ -> UnitIdU s+ -> UnifyM s ()+unifyInner cid1 insts1 uid1_u cid2 insts2 uid2_u = do+ when (cid1 /= cid2) $+ -- TODO: if we had a package identifier, could be an+ -- easier to understand error message.+ failWith $+ hang (text "Couldn't match component IDs:") 4+ (text " " <+> pretty cid1 $$+ text "and" <+> pretty cid2)+ -- The KEY STEP which makes this a Huet-style unification+ -- algorithm. (Also a payoff of using union-find.)+ -- We can build infinite unit IDs this way, which is necessary+ -- for support mutual recursion. NB: union keeps the SECOND+ -- descriptor, so we always arrange for a UnitIdThunkU to live+ -- there.+ liftST $ UnionFind.union uid1_u uid2_u+ F.sequenceA_ $ Map.intersectionWith unifyModule insts1 insts2++-- | Imperatively unify two modules.+unifyModule :: ModuleU s -> ModuleU s -> UnifyM s ()+unifyModule mod1_u mod2_u+ | mod1_u == mod2_u = return ()+ | otherwise = do+ mod1 <- liftST $ UnionFind.find mod1_u+ mod2 <- liftST $ UnionFind.find mod2_u+ case (mod1, mod2) of+ (ModuleVarU _, _) -> liftST $ UnionFind.union mod1_u mod2_u+ (_, ModuleVarU _) -> liftST $ UnionFind.union mod2_u mod1_u+ (ModuleU uid1 mod_name1, ModuleU uid2 mod_name2) -> do+ when (mod_name1 /= mod_name2) $+ failWith $+ hang (text "Cannot match module names") 4 $+ text " " <+> pretty mod_name1 $$+ text "and" <+> pretty mod_name2+ -- NB: this is not actually necessary (because we'll+ -- detect loops eventually in 'unifyUnitId'), but it+ -- seems harmless enough+ liftST $ UnionFind.union mod1_u mod2_u+ unifyUnitId uid1 uid2
+ src/Distribution/Backpack/ModSubst.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PatternGuards #-}++-- | A type class 'ModSubst' for objects which can have 'ModuleSubst'+-- applied to them.+--+-- See also <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>++module Distribution.Backpack.ModSubst (+ ModSubst(..),+) where++import Prelude ()+import Distribution.Compat.Prelude hiding (mod)++import Distribution.Backpack+import Distribution.ModuleName++import qualified Data.Map as Map+import qualified Data.Set as Set++-- | Applying module substitutions to semantic objects.+class ModSubst a where+ -- In notation, substitution is postfix, which implies+ -- putting it on the right hand side, but for partial+ -- application it's more convenient to have it on the left+ -- hand side.+ modSubst :: OpenModuleSubst -> a -> a++instance ModSubst OpenModule where+ modSubst subst (OpenModule cid mod_name) = OpenModule (modSubst subst cid) mod_name+ modSubst subst mod@(OpenModuleVar mod_name)+ | Just mod' <- Map.lookup mod_name subst = mod'+ | otherwise = mod++instance ModSubst OpenUnitId where+ modSubst subst (IndefFullUnitId cid insts) = IndefFullUnitId cid (modSubst subst insts)+ modSubst _subst uid = uid++instance ModSubst (Set ModuleName) where+ modSubst subst reqs+ = Set.union (Set.difference reqs (Map.keysSet subst))+ (openModuleSubstFreeHoles subst)++-- Substitutions are functorial. NB: this means that+-- there is an @instance 'ModSubst' 'ModuleSubst'@!+instance ModSubst a => ModSubst (Map k a) where+ modSubst subst = fmap (modSubst subst)+instance ModSubst a => ModSubst [a] where+ modSubst subst = fmap (modSubst subst)+instance ModSubst a => ModSubst (k, a) where+ modSubst subst (x,y) = (x, modSubst subst y)
+ src/Distribution/Backpack/ModuleScope.hs view
@@ -0,0 +1,132 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DeriveFoldable #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.ModuleScope (+ -- * Module scopes+ ModuleScope(..),+ ModuleProvides,+ ModuleRequires,+ ModuleSource(..),+ dispModuleSource,+ WithSource(..),+ unWithSource,+ getSource,+ ModuleWithSource,+ emptyModuleScope,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.ModuleName+import Distribution.Types.IncludeRenaming+import Distribution.Types.PackageName+import Distribution.Types.ComponentName+import Distribution.Types.LibraryName+import Distribution.Pretty++import Distribution.Backpack+import Distribution.Backpack.ModSubst++import qualified Data.Map as Map+import Text.PrettyPrint+++-----------------------------------------------------------------------+-- Module scopes++-- Why is ModuleProvides so complicated? The basic problem is that+-- we want to support this:+--+-- package p where+-- include q (A)+-- include r (A)+-- module B where+-- import "q" A+-- import "r" A+--+-- Specifically, in Cabal today it is NOT an error have two modules in+-- scope with the same identifier. So we need to preserve this for+-- Backpack. The modification is that an ambiguous module name is+-- OK... as long as it is NOT used to fill a requirement!+--+-- So as a first try, we might try deferring unifying provisions that+-- are being glommed together, and check for equality after the fact.+-- But this doesn't work, because what if a multi-module provision+-- is used to fill a requirement?! So you do the equality test+-- IMMEDIATELY before a requirement fill happens... or never at all.+--+-- Alternate strategy: go ahead and unify, and then if it is revealed+-- that some requirements got filled "out-of-thin-air", error.+++-- | A 'ModuleScope' describes the modules and requirements that+-- are in-scope as we are processing a Cabal package. Unlike+-- a 'ModuleShape', there may be multiple modules in scope at+-- the same 'ModuleName'; this is only an error if we attempt+-- to use those modules to fill a requirement. A 'ModuleScope'+-- can influence the 'ModuleShape' via a reexport.+data ModuleScope = ModuleScope {+ modScopeProvides :: ModuleProvides,+ modScopeRequires :: ModuleRequires+ }++-- | An empty 'ModuleScope'.+emptyModuleScope :: ModuleScope+emptyModuleScope = ModuleScope Map.empty Map.empty++-- | Every 'Module' in scope at a 'ModuleName' is annotated with+-- the 'PackageName' it comes from.+type ModuleProvides = Map ModuleName [ModuleWithSource]+-- | INVARIANT: entries for ModuleName m, have msrc_module is OpenModuleVar m+type ModuleRequires = Map ModuleName [ModuleWithSource]+-- TODO: consider newtping the two types above.++-- | Description of where a module participating in mixin linking came+-- from.+data ModuleSource+ = FromMixins PackageName ComponentName IncludeRenaming+ | FromBuildDepends PackageName ComponentName+ | FromExposedModules ModuleName+ | FromOtherModules ModuleName+ | FromSignatures ModuleName+-- We don't have line numbers, but if we did, we'd want to record that+-- too++-- TODO: Deduplicate this with Distribution.Backpack.UnifyM.ci_msg+dispModuleSource :: ModuleSource -> Doc+dispModuleSource (FromMixins pn cn incls)+ = text "mixins:" <+> dispComponent pn cn <+> pretty incls+dispModuleSource (FromBuildDepends pn cn)+ = text "build-depends:" <+> dispComponent pn cn+dispModuleSource (FromExposedModules m)+ = text "exposed-modules:" <+> pretty m+dispModuleSource (FromOtherModules m)+ = text "other-modules:" <+> pretty m+dispModuleSource (FromSignatures m)+ = text "signatures:" <+> pretty m++-- Dependency+dispComponent :: PackageName -> ComponentName -> Doc+dispComponent pn cn =+ -- NB: This syntax isn't quite the source syntax, but it+ -- should be clear enough. To do source syntax, we'd+ -- need to know what the package we're linking is.+ case cn of+ CLibName LMainLibName -> pretty pn+ CLibName (LSubLibName ucn) -> pretty pn <<>> colon <<>> pretty ucn+ -- Case below shouldn't happen+ _ -> pretty pn <+> parens (pretty cn)++-- | An 'OpenModule', annotated with where it came from in a Cabal file.+data WithSource a = WithSource ModuleSource a+ deriving (Functor, Foldable, Traversable)+unWithSource :: WithSource a -> a+unWithSource (WithSource _ x) = x+getSource :: WithSource a -> ModuleSource+getSource (WithSource s _) = s+type ModuleWithSource = WithSource OpenModule++instance ModSubst a => ModSubst (WithSource a) where+ modSubst subst (WithSource s m) = WithSource s (modSubst subst m)
+ src/Distribution/Backpack/ModuleShape.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.ModuleShape (+ -- * Module shapes+ ModuleShape(..),+ emptyModuleShape,+ shapeInstalledPackage,+) where++import Prelude ()+import Distribution.Compat.Prelude hiding (mod)++import Distribution.ModuleName+import Distribution.InstalledPackageInfo as IPI++import Distribution.Backpack.ModSubst+import Distribution.Backpack++import qualified Data.Map as Map+import qualified Data.Set as Set++-----------------------------------------------------------------------+-- Module shapes++-- | A 'ModuleShape' describes the provisions and requirements of+-- a library. We can extract a 'ModuleShape' from an+-- 'InstalledPackageInfo'.+data ModuleShape = ModuleShape {+ modShapeProvides :: OpenModuleSubst,+ modShapeRequires :: Set ModuleName+ }+ deriving (Eq, Show, Generic, Typeable)++instance Binary ModuleShape+instance Structured ModuleShape++instance ModSubst ModuleShape where+ modSubst subst (ModuleShape provs reqs)+ = ModuleShape (modSubst subst provs) (modSubst subst reqs)++-- | The default module shape, with no provisions and no requirements.+emptyModuleShape :: ModuleShape+emptyModuleShape = ModuleShape Map.empty Set.empty++-- Food for thought: suppose we apply the Merkel tree optimization.+-- Imagine this situation:+--+-- component p+-- signature H+-- module P+-- component h+-- module H+-- component a+-- signature P+-- module A+-- component q(P)+-- include p+-- include h+-- component r+-- include q (P)+-- include p (P) requires (H)+-- include h (H)+-- include a (A) requires (P)+--+-- Component r should not have any conflicts, since after mix-in linking+-- the two P imports will end up being the same, so we can properly+-- instantiate it. But to know that q's P is p:P instantiated with h:H,+-- we have to be able to expand its unit id. Maybe we can expand it+-- lazily but in some cases it will need to be expanded.+--+-- FWIW, the way that GHC handles this is by improving unit IDs as+-- soon as it sees an improved one in the package database. This+-- is a bit disgusting.+shapeInstalledPackage :: IPI.InstalledPackageInfo -> ModuleShape+shapeInstalledPackage ipi = ModuleShape (Map.fromList provs) reqs+ where+ uid = installedOpenUnitId ipi+ provs = map shapeExposedModule (IPI.exposedModules ipi)+ reqs = requiredSignatures ipi+ shapeExposedModule (IPI.ExposedModule mod_name Nothing)+ = (mod_name, OpenModule uid mod_name)+ shapeExposedModule (IPI.ExposedModule mod_name (Just mod))+ = (mod_name, mod)
+ src/Distribution/Backpack/PreExistingComponent.hs view
@@ -0,0 +1,67 @@+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.PreExistingComponent (+ PreExistingComponent(..),+ ipiToPreExistingComponent,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Backpack.ModuleShape+import Distribution.Backpack+import Distribution.Types.ComponentId+import Distribution.Types.MungedPackageId+import Distribution.Types.PackageId+import Distribution.Types.UnitId+import Distribution.Types.ComponentName+import Distribution.Types.PackageName+import Distribution.Package++import qualified Data.Map as Map+import qualified Distribution.InstalledPackageInfo as Installed+import Distribution.InstalledPackageInfo (InstalledPackageInfo)++-- | Stripped down version of 'LinkedComponent' for things+-- we don't need to know how to build.+data PreExistingComponent+ = PreExistingComponent {+ -- | The actual name of the package. This may DISAGREE with 'pc_pkgid'+ -- for internal dependencies: e.g., an internal component @lib@ may be+ -- munged to @z-pkg-z-lib@, but we still want to use it when we see+ -- @lib@ in @build-depends@+ pc_pkgname :: PackageName,+ -- | The actual name of the component.+ pc_compname :: ComponentName,+ pc_munged_id :: MungedPackageId,+ pc_uid :: UnitId,+ pc_cid :: ComponentId,+ pc_open_uid :: OpenUnitId,+ pc_shape :: ModuleShape+ }++-- | Convert an 'InstalledPackageInfo' into a 'PreExistingComponent',+-- which was brought into scope under the 'PackageName' (important for+-- a package qualified reference.)+ipiToPreExistingComponent :: InstalledPackageInfo -> PreExistingComponent+ipiToPreExistingComponent ipi =+ PreExistingComponent {+ pc_pkgname = packageName ipi,+ pc_compname = CLibName $ Installed.sourceLibName ipi,+ pc_munged_id = mungedId ipi,+ pc_uid = Installed.installedUnitId ipi,+ pc_cid = Installed.installedComponentId ipi,+ pc_open_uid =+ IndefFullUnitId (Installed.installedComponentId ipi)+ (Map.fromList (Installed.instantiatedWith ipi)),+ pc_shape = shapeInstalledPackage ipi+ }++instance HasMungedPackageId PreExistingComponent where+ mungedId = pc_munged_id++instance Package PreExistingComponent where+ packageId pec = PackageIdentifier (pc_pkgname pec) v+ where MungedPackageId _ v = pc_munged_id pec++instance HasUnitId PreExistingComponent where+ installedUnitId = pc_uid
+ src/Distribution/Backpack/PreModuleShape.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Backpack.PreModuleShape (+ PreModuleShape(..),+ toPreModuleShape,+ renamePreModuleShape,+ mixLinkPreModuleShape,+) where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Data.Set as Set+import qualified Data.Map as Map++import Distribution.Backpack.ModuleShape+import Distribution.Types.IncludeRenaming+import Distribution.Types.ModuleRenaming+import Distribution.ModuleName++data PreModuleShape = PreModuleShape {+ preModShapeProvides :: Set ModuleName,+ preModShapeRequires :: Set ModuleName+ }+ deriving (Eq, Show, Generic)++toPreModuleShape :: ModuleShape -> PreModuleShape+toPreModuleShape (ModuleShape provs reqs) = PreModuleShape (Map.keysSet provs) reqs++renamePreModuleShape :: PreModuleShape -> IncludeRenaming -> PreModuleShape+renamePreModuleShape (PreModuleShape provs reqs) (IncludeRenaming prov_rn req_rn) =+ PreModuleShape+ (Set.fromList (mapMaybe prov_fn (Set.toList provs)))+ (Set.map req_fn reqs)+ where+ prov_fn = interpModuleRenaming prov_rn+ req_fn k = fromMaybe k (interpModuleRenaming req_rn k)++mixLinkPreModuleShape :: [PreModuleShape] -> PreModuleShape+mixLinkPreModuleShape shapes = PreModuleShape provs (Set.difference reqs provs)+ where+ provs = Set.unions (map preModShapeProvides shapes)+ reqs = Set.unions (map preModShapeRequires shapes)
+ src/Distribution/Backpack/ReadyComponent.hs view
@@ -0,0 +1,376 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE PatternGuards #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.ReadyComponent (+ ReadyComponent(..),+ InstantiatedComponent(..),+ IndefiniteComponent(..),+ rc_depends,+ rc_uid,+ rc_pkgid,+ dispReadyComponent,+ toReadyComponents,+) where++import Prelude ()+import Distribution.Compat.Prelude hiding ((<>))++import Distribution.Backpack+import Distribution.Backpack.LinkedComponent+import Distribution.Backpack.ModuleShape++import Distribution.Types.AnnotatedId+import Distribution.Types.ModuleRenaming+import Distribution.Types.Component+import Distribution.Types.ComponentInclude+import Distribution.Types.ComponentId+import Distribution.Types.ComponentName+import Distribution.Types.PackageId+import Distribution.Types.PackageName.Magic+import Distribution.Types.UnitId+import Distribution.Compat.Graph (IsNode(..))+import Distribution.Types.Module+import Distribution.Types.MungedPackageId+import Distribution.Types.MungedPackageName+import Distribution.Types.Library+import Distribution.Types.LibraryName++import Distribution.ModuleName+import Distribution.Package+import Distribution.Simple.Utils++import Control.Monad+import Text.PrettyPrint+import qualified Data.Map as Map+import qualified Data.Set as Set++import Distribution.Version+import Distribution.Pretty++-- | A 'ReadyComponent' is one that we can actually generate build+-- products for. We have a ready component for the typecheck-only+-- products of every indefinite package, as well as a ready component+-- for every way these packages can be fully instantiated.+--+data ReadyComponent+ = ReadyComponent {+ rc_ann_id :: AnnotatedId UnitId,+ -- | The 'OpenUnitId' for this package. At the moment, this+ -- is used in only one case, which is to determine if an+ -- export is of a module from this library (indefinite+ -- libraries record these exports as 'OpenModule');+ -- 'rc_open_uid' can be conveniently used to test for+ -- equality, whereas 'UnitId' cannot always be used in this+ -- case.+ rc_open_uid :: OpenUnitId,+ -- | Corresponds to 'lc_cid'. Invariant: if 'rc_open_uid'+ -- records a 'ComponentId', it coincides with this one.+ rc_cid :: ComponentId,+ -- | Corresponds to 'lc_component'.+ rc_component :: Component,+ -- | Corresponds to 'lc_exe_deps'.+ -- Build-tools don't participate in mix-in linking.+ -- (but what if they could?)+ rc_exe_deps :: [AnnotatedId UnitId],+ -- | Corresponds to 'lc_public'.+ rc_public :: Bool,+ -- | Extra metadata depending on whether or not this is an+ -- indefinite library (typechecked only) or an instantiated+ -- component (can be compiled).+ rc_i :: Either IndefiniteComponent InstantiatedComponent+ }++-- | The final, string 'UnitId' that will uniquely identify+-- the compilation products of this component.+rc_uid :: ReadyComponent -> UnitId+rc_uid = ann_id . rc_ann_id++-- | Corresponds to 'lc_pkgid'.+rc_pkgid :: ReadyComponent -> PackageId+rc_pkgid = ann_pid . rc_ann_id++-- | An 'InstantiatedComponent' is a library which is fully instantiated+-- (or, possibly, has no requirements at all.)+data InstantiatedComponent+ = InstantiatedComponent {+ -- | How this library was instantiated.+ instc_insts :: [(ModuleName, Module)],+ -- | Dependencies induced by 'instc_insts'. These are recorded+ -- here because there isn't a convenient way otherwise to get+ -- the 'PackageId' we need to fill 'componentPackageDeps' as needed.+ instc_insts_deps :: [(UnitId, MungedPackageId)],+ -- | The modules exported/reexported by this library.+ instc_provides :: Map ModuleName Module,+ -- | The dependencies which need to be passed to the compiler+ -- to bring modules into scope. These always refer to installed+ -- fully instantiated libraries.+ instc_includes :: [ComponentInclude DefUnitId ModuleRenaming]+ }++-- | An 'IndefiniteComponent' is a library with requirements+-- which we will typecheck only.+data IndefiniteComponent+ = IndefiniteComponent {+ -- | The requirements of the library.+ indefc_requires :: [ModuleName],+ -- | The modules exported/reexported by this library.+ indefc_provides :: Map ModuleName OpenModule,+ -- | The dependencies which need to be passed to the compiler+ -- to bring modules into scope. These are 'OpenUnitId' because+ -- these may refer to partially instantiated libraries.+ indefc_includes :: [ComponentInclude OpenUnitId ModuleRenaming]+ }++-- | Compute the dependencies of a 'ReadyComponent' that should+-- be recorded in the @depends@ field of 'InstalledPackageInfo'.+rc_depends :: ReadyComponent -> [(UnitId, MungedPackageId)]+rc_depends rc = ordNub $+ case rc_i rc of+ Left indefc ->+ map (\ci -> (abstractUnitId $ ci_id ci, toMungedPackageId ci))+ (indefc_includes indefc)+ Right instc ->+ map (\ci -> (unDefUnitId $ ci_id ci, toMungedPackageId ci))+ (instc_includes instc)+ ++ instc_insts_deps instc+ where+ toMungedPackageId :: Pretty id => ComponentInclude id rn -> MungedPackageId+ toMungedPackageId ci =+ computeCompatPackageId+ (ci_pkgid ci)+ (case ci_cname ci of+ CLibName name -> name+ _ -> error $ prettyShow (rc_cid rc) +++ " depends on non-library " ++ prettyShow (ci_id ci))++-- | Get the 'MungedPackageId' of a 'ReadyComponent' IF it is+-- a library.+rc_munged_id :: ReadyComponent -> MungedPackageId+rc_munged_id rc =+ computeCompatPackageId+ (rc_pkgid rc)+ (case rc_component rc of+ CLib lib -> libName lib+ _ -> error "rc_munged_id: not library")++instance Package ReadyComponent where+ packageId = rc_pkgid++instance HasUnitId ReadyComponent where+ installedUnitId = rc_uid++instance IsNode ReadyComponent where+ type Key ReadyComponent = UnitId+ nodeKey = rc_uid+ nodeNeighbors rc =+ (case rc_i rc of+ Right inst | [] <- instc_insts inst+ -> []+ | otherwise+ -> [newSimpleUnitId (rc_cid rc)]+ _ -> []) +++ ordNub (map fst (rc_depends rc)) +++ map ann_id (rc_exe_deps rc)++dispReadyComponent :: ReadyComponent -> Doc+dispReadyComponent rc =+ hang (text (case rc_i rc of+ Left _ -> "indefinite"+ Right _ -> "definite")+ <+> pretty (nodeKey rc)+ {- <+> dispModSubst (Map.fromList (lc_insts lc)) -} ) 4 $+ vcat [ text "depends" <+> pretty uid+ | uid <- nodeNeighbors rc ]++-- | The state of 'InstM'; a mapping from 'UnitId's to their+-- ready component, or @Nothing@ if its an external+-- component which we don't know how to build.+type InstS = Map UnitId (Maybe ReadyComponent)++-- | A state monad for doing instantiations (can't use actual+-- State because that would be an extra dependency.)+newtype InstM a = InstM { runInstM :: InstS -> (a, InstS) }++instance Functor InstM where+ fmap f (InstM m) = InstM $ \s -> let (x, s') = m s+ in (f x, s')++instance Applicative InstM where+ pure a = InstM $ \s -> (a, s)+ InstM f <*> InstM x = InstM $ \s -> let (f', s') = f s+ (x', s'') = x s'+ in (f' x', s'')++instance Monad InstM where+ return = pure+ InstM m >>= f = InstM $ \s -> let (x, s') = m s+ in runInstM (f x) s'++-- | Given a list of 'LinkedComponent's, expand the module graph+-- so that we have an instantiated graph containing all of the+-- instantiated components we need to build.+--+-- Instantiation intuitively follows the following algorithm:+--+-- instantiate a definite unit id p[S]:+-- recursively instantiate each module M in S+-- recursively instantiate modules exported by this unit+-- recursively instantiate dependencies substituted by S+--+-- The implementation is a bit more involved to memoize instantiation+-- if we have done it already.+--+-- We also call 'improveUnitId' during this process, so that fully+-- instantiated components are given 'HashedUnitId'.+--+toReadyComponents+ :: Map UnitId MungedPackageId+ -> Map ModuleName Module -- subst for the public component+ -> [LinkedComponent]+ -> [ReadyComponent]+toReadyComponents pid_map subst0 comps+ = catMaybes (Map.elems ready_map)+ where+ cmap = Map.fromList [ (lc_cid lc, lc) | lc <- comps ]++ instantiateUnitId :: ComponentId -> Map ModuleName Module+ -> InstM DefUnitId+ instantiateUnitId cid insts = InstM $ \s ->+ case Map.lookup uid s of+ Nothing ->+ -- Knot tied+ let (r, s') = runInstM (instantiateComponent uid cid insts)+ (Map.insert uid r s)+ in (def_uid, Map.insert uid r s')+ Just _ -> (def_uid, s)+ where+ -- The mkDefUnitId here indicates that we assume+ -- that Cabal handles unit id hash allocation.+ -- Good thing about hashing here: map is only on string.+ -- Bad thing: have to repeatedly hash.+ def_uid = mkDefUnitId cid insts+ uid = unDefUnitId def_uid++ instantiateComponent+ :: UnitId -> ComponentId -> Map ModuleName Module+ -> InstM (Maybe ReadyComponent)+ instantiateComponent uid cid insts+ | Just lc <- Map.lookup cid cmap = do+ provides <- traverse (substModule insts) (modShapeProvides (lc_shape lc))+ -- NB: lc_sig_includes is omitted here, because we don't+ -- need them to build+ includes <- forM (lc_includes lc) $ \ci -> do+ uid' <- substUnitId insts (ci_id ci)+ return ci { ci_ann_id = fmap (const uid') (ci_ann_id ci) }+ exe_deps <- traverse (substExeDep insts) (lc_exe_deps lc)+ s <- InstM $ \s -> (s, s)+ let getDep (Module dep_def_uid _)+ | let dep_uid = unDefUnitId dep_def_uid+ -- Lose DefUnitId invariant for rc_depends+ = [(dep_uid,+ fromMaybe err_pid $+ Map.lookup dep_uid pid_map <|>+ fmap rc_munged_id (join (Map.lookup dep_uid s)))]+ where+ err_pid = MungedPackageId+ (MungedPackageName nonExistentPackageThisIsCabalBug LMainLibName)+ (mkVersion [0])+ instc = InstantiatedComponent {+ instc_insts = Map.toList insts,+ instc_insts_deps = concatMap getDep (Map.elems insts),+ instc_provides = provides,+ instc_includes = includes+ -- NB: there is no dependency on the+ -- indefinite version of this instantiated package here,+ -- as (1) it doesn't go in depends in the+ -- IPI: it's not a run time dep, and (2)+ -- we don't have to tell GHC about it, it+ -- will match up the ComponentId+ -- automatically+ }+ return $ Just ReadyComponent {+ rc_ann_id = (lc_ann_id lc) { ann_id = uid },+ rc_open_uid = DefiniteUnitId (unsafeMkDefUnitId uid),+ rc_cid = lc_cid lc,+ rc_component = lc_component lc,+ rc_exe_deps = exe_deps,+ rc_public = lc_public lc,+ rc_i = Right instc+ }+ | otherwise = return Nothing++ substUnitId :: Map ModuleName Module -> OpenUnitId -> InstM DefUnitId+ substUnitId _ (DefiniteUnitId uid) =+ return uid+ substUnitId subst (IndefFullUnitId cid insts) = do+ insts' <- substSubst subst insts+ instantiateUnitId cid insts'++ -- NB: NOT composition+ substSubst :: Map ModuleName Module+ -> Map ModuleName OpenModule+ -> InstM (Map ModuleName Module)+ substSubst subst insts = traverse (substModule subst) insts++ substModule :: Map ModuleName Module -> OpenModule -> InstM Module+ substModule subst (OpenModuleVar mod_name)+ | Just m <- Map.lookup mod_name subst = return m+ | otherwise = error "substModule: non-closing substitution"+ substModule subst (OpenModule uid mod_name) = do+ uid' <- substUnitId subst uid+ return (Module uid' mod_name)++ substExeDep :: Map ModuleName Module+ -> AnnotatedId OpenUnitId -> InstM (AnnotatedId UnitId)+ substExeDep insts exe_aid = do+ exe_uid' <- substUnitId insts (ann_id exe_aid)+ return exe_aid { ann_id = unDefUnitId exe_uid' }++ indefiniteUnitId :: ComponentId -> InstM UnitId+ indefiniteUnitId cid = do+ let uid = newSimpleUnitId cid+ r <- indefiniteComponent uid cid+ InstM $ \s -> (uid, Map.insert uid r s)++ indefiniteComponent :: UnitId -> ComponentId -> InstM (Maybe ReadyComponent)+ indefiniteComponent uid cid+ | Just lc <- Map.lookup cid cmap = do+ -- We're going to process includes, in case some of them+ -- are fully definite even without any substitution. We+ -- want to build those too; see #5634.+ inst_includes <- forM (lc_includes lc) $ \ci ->+ if Set.null (openUnitIdFreeHoles (ci_id ci))+ then do uid' <- substUnitId Map.empty (ci_id ci)+ return $ ci { ci_ann_id = fmap (const (DefiniteUnitId uid')) (ci_ann_id ci) }+ else return ci+ exe_deps <- traverse (substExeDep Map.empty) (lc_exe_deps lc)+ let indefc = IndefiniteComponent {+ indefc_requires = map fst (lc_insts lc),+ indefc_provides = modShapeProvides (lc_shape lc),+ indefc_includes = inst_includes ++ lc_sig_includes lc+ }+ return $ Just ReadyComponent {+ rc_ann_id = (lc_ann_id lc) { ann_id = uid },+ rc_cid = lc_cid lc,+ rc_open_uid = lc_uid lc,+ rc_component = lc_component lc,+ -- It's always fully built+ rc_exe_deps = exe_deps,+ rc_public = lc_public lc,+ rc_i = Left indefc+ }+ | otherwise = return Nothing++ ready_map = snd $ runInstM work Map.empty++ work+ -- Top-level instantiation per subst0+ | not (Map.null subst0)+ , [lc] <- filter lc_public (Map.elems cmap)+ = do _ <- instantiateUnitId (lc_cid lc) subst0+ return ()+ | otherwise+ = forM_ (Map.elems cmap) $ \lc ->+ if null (lc_insts lc)+ then instantiateUnitId (lc_cid lc) Map.empty >> return ()+ else indefiniteUnitId (lc_cid lc) >> return ()
+ src/Distribution/Backpack/UnifyM.hs view
@@ -0,0 +1,625 @@+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>+module Distribution.Backpack.UnifyM (+ -- * Unification monad+ UnifyM,+ runUnifyM,+ failWith,+ addErr,+ failIfErrs,+ tryM,+ addErrContext,+ addErrContextM,+ liftST,++ UnifEnv(..),+ getUnifEnv,++ -- * Modules and unit IDs+ ModuleU,+ ModuleU'(..),+ convertModule,+ convertModuleU,++ UnitIdU,+ UnitIdU'(..),+ convertUnitId,+ convertUnitIdU,++ ModuleSubstU,+ convertModuleSubstU,+ convertModuleSubst,++ ModuleScopeU,+ emptyModuleScopeU,+ convertModuleScopeU,++ ModuleWithSourceU,++ convertInclude,+ convertModuleProvides,+ convertModuleProvidesU,++) where++import Prelude ()+import Distribution.Compat.Prelude hiding (mod)++import Distribution.Backpack.ModuleShape+import Distribution.Backpack.ModuleScope+import Distribution.Backpack.ModSubst+import Distribution.Backpack.FullUnitId+import Distribution.Backpack++import qualified Distribution.Utils.UnionFind as UnionFind+import Distribution.ModuleName+import Distribution.Package+import Distribution.PackageDescription+import Distribution.Pretty+import Distribution.Types.ComponentInclude+import Distribution.Types.AnnotatedId+import Distribution.Verbosity++import Data.STRef+import Data.Traversable+import Control.Monad.ST+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import Text.PrettyPrint++-- TODO: more detailed trace output on high verbosity would probably+-- be appreciated by users debugging unification errors. Collect+-- some good examples!++data ErrMsg = ErrMsg {+ err_msg :: Doc,+ err_ctx :: [Doc]+ }+type MsgDoc = Doc++renderErrMsg :: ErrMsg -> MsgDoc+renderErrMsg ErrMsg { err_msg = msg, err_ctx = ctx } =+ msg $$ vcat ctx++-- | The unification monad, this monad encapsulates imperative+-- unification.+newtype UnifyM s a = UnifyM { unUnifyM :: UnifEnv s -> ST s (Maybe a) }++-- | Run a computation in the unification monad.+runUnifyM :: Verbosity -> ComponentId -> FullDb -> (forall s. UnifyM s a) -> Either [MsgDoc] a+runUnifyM verbosity self_cid db m+ = runST $ do i <- newSTRef 0+ hmap <- newSTRef Map.empty+ errs <- newSTRef []+ mb_r <- unUnifyM m UnifEnv {+ unify_uniq = i,+ unify_reqs = hmap,+ unify_self_cid = self_cid,+ unify_verbosity = verbosity,+ unify_ctx = [],+ unify_db = db,+ unify_errs = errs }+ final_errs <- readSTRef errs+ case mb_r of+ Just x | null final_errs -> return (Right x)+ _ -> return (Left (map renderErrMsg (reverse final_errs)))+-- NB: GHC 7.6 throws a hissy fit if you pattern match on 'm'.++type ErrCtx s = MsgDoc++-- | The unification environment.+data UnifEnv s = UnifEnv {+ -- | A supply of unique integers to label 'UnitIdU'+ -- cells. This is used to determine loops in unit+ -- identifiers (which can happen with mutual recursion.)+ unify_uniq :: UnifRef s UnitIdUnique,+ -- | The set of requirements in scope. When+ -- a provision is brought into scope, we unify with+ -- the requirement at the same module name to fill it.+ -- This mapping grows monotonically.+ unify_reqs :: UnifRef s (Map ModuleName (ModuleU s)),+ -- | Component id of the unit we're linking. We use this+ -- to detect if we fill a requirement with a local module,+ -- which in principle should be OK but is not currently+ -- supported by GHC.+ unify_self_cid :: ComponentId,+ -- | How verbose the error message should be+ unify_verbosity :: Verbosity,+ -- | The error reporting context+ unify_ctx :: [ErrCtx s],+ -- | The package index for expanding unit identifiers+ unify_db :: FullDb,+ -- | Accumulated errors+ unify_errs :: UnifRef s [ErrMsg]+ }++instance Functor (UnifyM s) where+ fmap f (UnifyM m) = UnifyM (fmap (fmap (fmap f)) m)++instance Applicative (UnifyM s) where+ pure = UnifyM . pure . pure . pure+ UnifyM f <*> UnifyM x = UnifyM $ \r -> do+ f' <- f r+ case f' of+ Nothing -> return Nothing+ Just f'' -> do+ x' <- x r+ case x' of+ Nothing -> return Nothing+ Just x'' -> return (Just (f'' x''))++instance Monad (UnifyM s) where+ return = pure+ UnifyM m >>= f = UnifyM $ \r -> do+ x <- m r+ case x of+ Nothing -> return Nothing+ Just x' -> unUnifyM (f x') r++-- | Lift a computation from 'ST' monad to 'UnifyM' monad.+-- Internal use only.+liftST :: ST s a -> UnifyM s a+liftST m = UnifyM $ \_ -> fmap Just m++addErr :: MsgDoc -> UnifyM s ()+addErr msg = do+ env <- getUnifEnv+ let err = ErrMsg {+ err_msg = msg,+ err_ctx = unify_ctx env+ }+ liftST $ modifySTRef (unify_errs env) (\errs -> err:errs)++failWith :: MsgDoc -> UnifyM s a+failWith msg = do+ addErr msg+ failM++failM :: UnifyM s a+failM = UnifyM $ \_ -> return Nothing++failIfErrs :: UnifyM s ()+failIfErrs = do+ env <- getUnifEnv+ errs <- liftST $ readSTRef (unify_errs env)+ when (not (null errs)) failM++tryM :: UnifyM s a -> UnifyM s (Maybe a)+tryM m =+ UnifyM (\env -> do+ mb_r <- unUnifyM m env+ return (Just mb_r))++{-+otherFail :: ErrMsg -> UnifyM s a+otherFail s = UnifyM $ \_ -> return (Left s)++unifyFail :: ErrMsg -> UnifyM s a+unifyFail err = do+ env <- getUnifEnv+ msg <- case unify_ctx env of+ Nothing -> return (text "Unspecified unification error:" <+> err)+ Just (ctx, mod1, mod2)+ | unify_verbosity env > normal+ -> do mod1' <- convertModuleU mod1+ mod2' <- convertModuleU mod2+ let extra = " (was unifying " ++ display mod1'+ ++ " and " ++ display mod2' ++ ")"+ return (ctx ++ err ++ extra)+ | otherwise+ -> return (ctx ++ err ++ " (for more information, pass -v flag)")+ UnifyM $ \_ -> return (Left msg)+-}++-- | A convenient alias for mutable references in the unification monad.+type UnifRef s a = STRef s a++-- | Imperatively read a 'UnifRef'.+readUnifRef :: UnifRef s a -> UnifyM s a+readUnifRef = liftST . readSTRef++-- | Imperatively write a 'UnifRef'.+writeUnifRef :: UnifRef s a -> a -> UnifyM s ()+writeUnifRef x = liftST . writeSTRef x++-- | Get the current unification environment.+getUnifEnv :: UnifyM s (UnifEnv s)+getUnifEnv = UnifyM $ \r -> return (return r)++-- | Add a fixed message to the error context.+addErrContext :: Doc -> UnifyM s a -> UnifyM s a+addErrContext ctx m = addErrContextM ctx m++-- | Add a message to the error context. It may make monadic queries.+addErrContextM :: ErrCtx s -> UnifyM s a -> UnifyM s a+addErrContextM ctx m =+ UnifyM $ \r -> unUnifyM m r { unify_ctx = ctx : unify_ctx r }+++-----------------------------------------------------------------------+-- The "unifiable" variants of the data types+--+-- In order to properly do unification over infinite trees, we+-- need to union find over 'Module's and 'UnitId's. The pure+-- representation is ill-equipped to do this, so we convert+-- from the pure representation into one which is indirected+-- through union-find. 'ModuleU' handles hole variables;+-- 'UnitIdU' handles mu-binders.++-- | Contents of a mutable 'ModuleU' reference.+data ModuleU' s+ = ModuleU (UnitIdU s) ModuleName+ | ModuleVarU ModuleName++-- | Contents of a mutable 'UnitIdU' reference.+data UnitIdU' s+ = UnitIdU UnitIdUnique ComponentId (Map ModuleName (ModuleU s))+ | UnitIdThunkU DefUnitId++-- | A mutable version of 'Module' which can be imperatively unified.+type ModuleU s = UnionFind.Point s (ModuleU' s)++-- | A mutable version of 'UnitId' which can be imperatively unified.+type UnitIdU s = UnionFind.Point s (UnitIdU' s)++-- | An integer for uniquely labeling 'UnitIdU' nodes. We need+-- these labels in order to efficiently serialize 'UnitIdU's into+-- 'UnitId's (we use the label to check if any parent is the+-- node in question, and if so insert a deBruijn index instead.)+-- These labels must be unique across all 'UnitId's/'Module's which+-- participate in unification!+type UnitIdUnique = Int+++-----------------------------------------------------------------------+-- Conversion to the unifiable data types++-- An environment for tracking the mu-bindings in scope.+-- The invariant for a state @(m, i)@ is that [0..i] are+-- keys of @m@; in fact, the @i-k@th entry is the @k@th+-- de Bruijn index (this saves us from having to shift as+-- we enter mu-binders.)+type MuEnv s = (IntMap (UnitIdU s), Int)++extendMuEnv :: MuEnv s -> UnitIdU s -> MuEnv s+extendMuEnv (m, i) x =+ (IntMap.insert (i + 1) x m, i + 1)++{-+lookupMuEnv :: MuEnv s -> Int {- de Bruijn index -} -> UnitIdU s+lookupMuEnv (m, i) k =+ case IntMap.lookup (i - k) m of+ -- Technically a user can trigger this by giving us a+ -- bad 'UnitId', so handle this better.+ Nothing -> error "lookupMuEnv: out of bounds (malformed de Bruijn index)"+ Just v -> v+-}++emptyMuEnv :: MuEnv s+emptyMuEnv = (IntMap.empty, -1)++-- The workhorse functions. These share an environment:+-- * @UnifRef s UnitIdUnique@ - the unique label supply for 'UnitIdU' nodes+-- * @UnifRef s (Map ModuleName moduleU)@ - the (lazily initialized)+-- environment containing the implicitly universally quantified+-- @hole:A@ binders.+-- * @MuEnv@ - the environment for mu-binders.++convertUnitId' :: MuEnv s+ -> OpenUnitId+ -> UnifyM s (UnitIdU s)+-- TODO: this could be more lazy if we know there are no internal+-- references+convertUnitId' _ (DefiniteUnitId uid) =+ liftST $ UnionFind.fresh (UnitIdThunkU uid)+convertUnitId' stk (IndefFullUnitId cid insts) = do+ fs <- fmap unify_uniq getUnifEnv+ x <- liftST $ UnionFind.fresh (error "convertUnitId") -- tie the knot later+ insts_u <- for insts $ convertModule' (extendMuEnv stk x)+ u <- readUnifRef fs+ writeUnifRef fs (u+1)+ y <- liftST $ UnionFind.fresh (UnitIdU u cid insts_u)+ liftST $ UnionFind.union x y+ return y+-- convertUnitId' stk (UnitIdVar i) = return (lookupMuEnv stk i)++convertModule' :: MuEnv s+ -> OpenModule -> UnifyM s (ModuleU s)+convertModule' _stk (OpenModuleVar mod_name) = do+ hmap <- fmap unify_reqs getUnifEnv+ hm <- readUnifRef hmap+ case Map.lookup mod_name hm of+ Nothing -> do mod <- liftST $ UnionFind.fresh (ModuleVarU mod_name)+ writeUnifRef hmap (Map.insert mod_name mod hm)+ return mod+ Just mod -> return mod+convertModule' stk (OpenModule uid mod_name) = do+ uid_u <- convertUnitId' stk uid+ liftST $ UnionFind.fresh (ModuleU uid_u mod_name)++convertUnitId :: OpenUnitId -> UnifyM s (UnitIdU s)+convertUnitId = convertUnitId' emptyMuEnv++convertModule :: OpenModule -> UnifyM s (ModuleU s)+convertModule = convertModule' emptyMuEnv++++-----------------------------------------------------------------------+-- Substitutions++-- | The mutable counterpart of a 'ModuleSubst' (not defined here).+type ModuleSubstU s = Map ModuleName (ModuleU s)++-- | Conversion of 'ModuleSubst' to 'ModuleSubstU'+convertModuleSubst :: Map ModuleName OpenModule -> UnifyM s (Map ModuleName (ModuleU s))+convertModuleSubst = traverse convertModule++-- | Conversion of 'ModuleSubstU' to 'ModuleSubst'+convertModuleSubstU :: ModuleSubstU s -> UnifyM s OpenModuleSubst+convertModuleSubstU = traverse convertModuleU++-----------------------------------------------------------------------+-- Conversion from the unifiable data types++-- An environment for tracking candidates for adding a mu-binding.+-- The invariant for a state @(m, i)@, is that if we encounter a node+-- labeled @k@ such that @m[k -> v]@, then we can replace this+-- node with the de Bruijn index @i-v@ referring to an enclosing+-- mu-binder; furthermore, @range(m) = [0..i]@.+type MooEnv = (IntMap Int, Int)++emptyMooEnv :: MooEnv+emptyMooEnv = (IntMap.empty, -1)++extendMooEnv :: MooEnv -> UnitIdUnique -> MooEnv+extendMooEnv (m, i) k = (IntMap.insert k (i + 1) m, i + 1)++lookupMooEnv :: MooEnv -> UnitIdUnique -> Maybe Int+lookupMooEnv (m, i) k =+ case IntMap.lookup k m of+ Nothing -> Nothing+ Just v -> Just (i-v) -- de Bruijn indexize++-- The workhorse functions++convertUnitIdU' :: MooEnv -> UnitIdU s -> UnifyM s OpenUnitId+convertUnitIdU' stk uid_u = do+ x <- liftST $ UnionFind.find uid_u+ case x of+ UnitIdThunkU uid -> return (DefiniteUnitId uid)+ UnitIdU u cid insts_u ->+ case lookupMooEnv stk u of+ Just _i ->+ failWith (text "Unsupported mutually recursive unit identifier")+ -- return (UnitIdVar i)+ Nothing -> do+ insts <- for insts_u $ convertModuleU' (extendMooEnv stk u)+ return (IndefFullUnitId cid insts)++convertModuleU' :: MooEnv -> ModuleU s -> UnifyM s OpenModule+convertModuleU' stk mod_u = do+ mod <- liftST $ UnionFind.find mod_u+ case mod of+ ModuleVarU mod_name -> return (OpenModuleVar mod_name)+ ModuleU uid_u mod_name -> do+ uid <- convertUnitIdU' stk uid_u+ return (OpenModule uid mod_name)++-- Helper functions++convertUnitIdU :: UnitIdU s -> UnifyM s OpenUnitId+convertUnitIdU = convertUnitIdU' emptyMooEnv++convertModuleU :: ModuleU s -> UnifyM s OpenModule+convertModuleU = convertModuleU' emptyMooEnv++-- | An empty 'ModuleScopeU'.+emptyModuleScopeU :: ModuleScopeU s+emptyModuleScopeU = (Map.empty, Map.empty)+++-- | The mutable counterpart of 'ModuleScope'.+type ModuleScopeU s = (ModuleProvidesU s, ModuleRequiresU s)+-- | The mutable counterpart of 'ModuleProvides'+type ModuleProvidesU s = Map ModuleName [ModuleWithSourceU s]+type ModuleRequiresU s = ModuleProvidesU s+type ModuleWithSourceU s = WithSource (ModuleU s)++-- TODO: Deduplicate this with Distribution.Backpack.MixLink.dispSource+ci_msg :: ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming -> Doc+ci_msg ci+ | ci_implicit ci = text "build-depends:" <+> pp_pn+ | otherwise = text "mixins:" <+> pp_pn <+> pretty (ci_renaming ci)+ where+ pn = pkgName (ci_pkgid ci)+ pp_pn =+ case ci_cname ci of+ CLibName LMainLibName -> pretty pn+ CLibName (LSubLibName cn) -> pretty pn <<>> colon <<>> pretty cn+ -- Shouldn't happen+ cn -> pretty pn <+> parens (pretty cn)++-- | Convert a 'ModuleShape' into a 'ModuleScopeU', so we can do+-- unification on it.+convertInclude+ :: ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming+ -> UnifyM s (ModuleScopeU s,+ Either (ComponentInclude (UnitIdU s) ModuleRenaming) {- normal -}+ (ComponentInclude (UnitIdU s) ModuleRenaming) {- sig -})+convertInclude ci@(ComponentInclude {+ ci_ann_id = AnnotatedId {+ ann_id = (uid, ModuleShape provs reqs),+ ann_pid = pid,+ ann_cname = compname+ },+ ci_renaming = incl@(IncludeRenaming prov_rns req_rns),+ ci_implicit = implicit+ }) = addErrContext (text "In" <+> ci_msg ci) $ do+ let pn = packageName pid+ the_source | implicit+ = FromBuildDepends pn compname+ | otherwise+ = FromMixins pn compname incl+ source = WithSource the_source++ -- Suppose our package has two requirements A and B, and+ -- we include it with @requires (A as X)@+ -- There are three closely related things we compute based+ -- off of @reqs@ and @reqs_rns@:+ --+ -- 1. The requirement renaming (A -> X)+ -- 2. The requirement substitution (A -> <X>, B -> <B>)++ -- Requirement renaming. This is read straight off the syntax:+ --+ -- [nothing] ==> [empty]+ -- requires (B as Y) ==> B -> Y+ --+ -- Requirement renamings are NOT injective: if two requirements+ -- are mapped to the same name, the intent is to merge them+ -- together. But they are *functions*, so @B as X, B as Y@ is+ -- illegal.++ req_rename_list <-+ case req_rns of+ DefaultRenaming -> return []+ HidingRenaming _ -> do+ -- Not valid here for requires!+ addErr $ text "Unsupported syntax" <+>+ quotes (text "requires hiding (...)")+ return []+ ModuleRenaming rns -> return rns++ let req_rename_listmap :: Map ModuleName [ModuleName]+ req_rename_listmap =+ Map.fromListWith (++) [ (k,[v]) | (k,v) <- req_rename_list ]+ req_rename <- sequenceA . flip Map.mapWithKey req_rename_listmap $ \k vs0 ->+ case vs0 of+ [] -> error "req_rename"+ [v] -> return v+ v:vs -> do addErr $+ text "Conflicting renamings of requirement" <+> quotes (pretty k) $$+ text "Renamed to: " <+> vcat (map pretty (v:vs))+ return v++ let req_rename_fn k = case Map.lookup k req_rename of+ Nothing -> k+ Just v -> v++ -- Requirement substitution.+ --+ -- A -> X ==> A -> <X>+ let req_subst = fmap OpenModuleVar req_rename++ uid_u <- convertUnitId (modSubst req_subst uid)++ -- Requirement mapping. This is just taking the range of the+ -- requirement substitution, and making a mapping so that it is+ -- convenient to merge things together. It INCLUDES the implicit+ -- mappings.+ --+ -- A -> X ==> X -> <X>, B -> <B>+ reqs_u <- convertModuleRequires . Map.fromList $+ [ (k, [source (OpenModuleVar k)])+ | k <- map req_rename_fn (Set.toList reqs)+ ]++ -- Report errors if there were unused renamings+ let leftover = Map.keysSet req_rename `Set.difference` reqs+ unless (Set.null leftover) $+ addErr $+ hang (text "The" <+> text (showComponentName compname) <+>+ text "from package" <+> quotes (pretty pid)+ <+> text "does not require:") 4+ (vcat (map pretty (Set.toList leftover)))++ -- Provision computation is more complex.+ -- For example, if we have:+ --+ -- include p (A as X) requires (B as Y)+ -- where A -> q[B=<B>]:A+ --+ -- Then we need:+ --+ -- X -> [("p", q[B=<B>]:A)]+ --+ -- There are a bunch of clever ways to present the algorithm+ -- but here is the simple one:+ --+ -- 1. If we have a default renaming, apply req_subst+ -- to provs and use that.+ --+ -- 2. Otherwise, build a map by successively looking+ -- up the referenced modules in the renaming in provs.+ --+ -- Importantly, overlapping rename targets get accumulated+ -- together. It's not an (immediate) error.+ (pre_prov_scope, prov_rns') <-+ case prov_rns of+ DefaultRenaming -> return (Map.toList provs, prov_rns)+ HidingRenaming hides ->+ let hides_set = Set.fromList hides+ in let r = [ (k,v)+ | (k,v) <- Map.toList provs+ , not (k `Set.member` hides_set) ]+ -- GHC doesn't understand hiding, so expand it out!+ in return (r, ModuleRenaming (map ((\x -> (x,x)).fst) r))+ ModuleRenaming rns -> do+ r <- sequence+ [ case Map.lookup from provs of+ Just m -> return (to, m)+ Nothing -> failWith $+ text "Package" <+> quotes (pretty pid) <+>+ text "does not expose the module" <+> quotes (pretty from)+ | (from, to) <- rns ]+ return (r, prov_rns)+ let prov_scope = modSubst req_subst+ $ Map.fromListWith (++)+ [ (k, [source v])+ | (k, v) <- pre_prov_scope ]++ provs_u <- convertModuleProvides prov_scope++ -- TODO: Assert that provs_u is empty if provs was empty+ return ((provs_u, reqs_u),+ -- NB: We test that requirements is not null so that+ -- users can create packages with zero module exports+ -- that cause some C library to linked in, etc.+ (if Map.null provs && not (Set.null reqs)+ then Right -- is sig+ else Left) (ComponentInclude {+ ci_ann_id = AnnotatedId {+ ann_id = uid_u,+ ann_pid = pid,+ ann_cname = compname+ },+ ci_renaming = prov_rns',+ ci_implicit = ci_implicit ci+ }))++-- | Convert a 'ModuleScopeU' to a 'ModuleScope'.+convertModuleScopeU :: ModuleScopeU s -> UnifyM s ModuleScope+convertModuleScopeU (provs_u, reqs_u) = do+ provs <- convertModuleProvidesU provs_u+ reqs <- convertModuleRequiresU reqs_u+ -- TODO: Test that the requirements are still free. If they+ -- are not, they got unified, and that's dodgy at best.+ return (ModuleScope provs reqs)++-- | Convert a 'ModuleProvides' to a 'ModuleProvidesU'+convertModuleProvides :: ModuleProvides -> UnifyM s (ModuleProvidesU s)+convertModuleProvides = traverse (traverse (traverse convertModule))++-- | Convert a 'ModuleProvidesU' to a 'ModuleProvides'+convertModuleProvidesU :: ModuleProvidesU s -> UnifyM s ModuleProvides+convertModuleProvidesU = traverse (traverse (traverse convertModuleU))++convertModuleRequires :: ModuleRequires -> UnifyM s (ModuleRequiresU s)+convertModuleRequires = convertModuleProvides++convertModuleRequiresU :: ModuleRequiresU s -> UnifyM s ModuleRequires+convertModuleRequiresU = convertModuleProvidesU
+ src/Distribution/CabalSpecVersion.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.CabalSpecVersion where++import Prelude ()+import Distribution.Compat.Prelude++-- | Different Cabal-the-spec versions.+--+-- We branch based on this at least in the parser.+--+data CabalSpecVersion+ = CabalSpecV1_0 -- ^ this is older than 'CabalSpecV1_2'+ | CabalSpecV1_2 -- ^ new syntax (sections)+ | CabalSpecV1_4+ | CabalSpecV1_6+ | CabalSpecV1_8+ | CabalSpecV1_10+ | CabalSpecV1_12+ -- 1.16 -- 1.14: no changes+ | CabalSpecV1_18+ | CabalSpecV1_20+ | CabalSpecV1_22+ | CabalSpecV1_24+ | CabalSpecV2_0+ | CabalSpecV2_2+ | CabalSpecV2_4+ | CabalSpecV3_0+ -- 3.2: no changes+ | CabalSpecV3_4+ | CabalSpecV3_6+ deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data, Generic)++instance Binary CabalSpecVersion+instance Structured CabalSpecVersion+instance NFData CabalSpecVersion where rnf = genericRnf++-- | Show cabal spec version, but not the way in the .cabal files+--+-- @since 3.0.0.0+showCabalSpecVersion :: CabalSpecVersion -> String+showCabalSpecVersion CabalSpecV3_6 = "3.6"+showCabalSpecVersion CabalSpecV3_4 = "3.4"+showCabalSpecVersion CabalSpecV3_0 = "3.0"+showCabalSpecVersion CabalSpecV2_4 = "2.4"+showCabalSpecVersion CabalSpecV2_2 = "2.2"+showCabalSpecVersion CabalSpecV2_0 = "2.0"+showCabalSpecVersion CabalSpecV1_24 = "1.24"+showCabalSpecVersion CabalSpecV1_22 = "1.22"+showCabalSpecVersion CabalSpecV1_20 = "1.20"+showCabalSpecVersion CabalSpecV1_18 = "1.18"+showCabalSpecVersion CabalSpecV1_12 = "1.12"+showCabalSpecVersion CabalSpecV1_10 = "1.10"+showCabalSpecVersion CabalSpecV1_8 = "1.8"+showCabalSpecVersion CabalSpecV1_6 = "1.6"+showCabalSpecVersion CabalSpecV1_4 = "1.4"+showCabalSpecVersion CabalSpecV1_2 = "1.2"+showCabalSpecVersion CabalSpecV1_0 = "1.0"++cabalSpecLatest :: CabalSpecVersion+cabalSpecLatest = CabalSpecV3_6++-- | Parse 'CabalSpecVersion' from version digits.+--+-- It may fail if for recent versions the version is not exact.+--+cabalSpecFromVersionDigits :: [Int] -> Maybe CabalSpecVersion+cabalSpecFromVersionDigits v+ | v == [3,6] = Just CabalSpecV3_6+ | v == [3,4] = Just CabalSpecV3_4+ | v == [3,0] = Just CabalSpecV3_0+ | v == [2,4] = Just CabalSpecV2_4+ | v == [2,2] = Just CabalSpecV2_2+ | v == [2,0] = Just CabalSpecV2_0+ | v >= [1,25] = Nothing+ | v >= [1,23] = Just CabalSpecV1_24+ | v >= [1,21] = Just CabalSpecV1_22+ | v >= [1,19] = Just CabalSpecV1_20+ | v >= [1,17] = Just CabalSpecV1_18+ | v >= [1,11] = Just CabalSpecV1_12+ | v >= [1,9] = Just CabalSpecV1_10+ | v >= [1,7] = Just CabalSpecV1_8+ | v >= [1,5] = Just CabalSpecV1_6+ | v >= [1,3] = Just CabalSpecV1_4+ | v >= [1,1] = Just CabalSpecV1_2+ | otherwise = Just CabalSpecV1_0++-- | @since 3.4.0.0+cabalSpecToVersionDigits :: CabalSpecVersion -> [Int]+cabalSpecToVersionDigits CabalSpecV3_6 = [3,6]+cabalSpecToVersionDigits CabalSpecV3_4 = [3,4]+cabalSpecToVersionDigits CabalSpecV3_0 = [3,0]+cabalSpecToVersionDigits CabalSpecV2_4 = [2,4]+cabalSpecToVersionDigits CabalSpecV2_2 = [2,2]+cabalSpecToVersionDigits CabalSpecV2_0 = [2,0]+cabalSpecToVersionDigits CabalSpecV1_24 = [1,24]+cabalSpecToVersionDigits CabalSpecV1_22 = [1,22]+cabalSpecToVersionDigits CabalSpecV1_20 = [1,20]+cabalSpecToVersionDigits CabalSpecV1_18 = [1,18]+cabalSpecToVersionDigits CabalSpecV1_12 = [1,12]+cabalSpecToVersionDigits CabalSpecV1_10 = [1,10]+cabalSpecToVersionDigits CabalSpecV1_8 = [1,8]+cabalSpecToVersionDigits CabalSpecV1_6 = [1,6]+cabalSpecToVersionDigits CabalSpecV1_4 = [1,4]+cabalSpecToVersionDigits CabalSpecV1_2 = [1,2]+cabalSpecToVersionDigits CabalSpecV1_0 = [1,0]++-- | What is the minimum Cabal library version which knows how handle+-- this spec version.+--+-- /Note:/ this is a point where we could decouple cabal-spec and Cabal+-- versions, if we ever want that.+--+-- >>> cabalSpecMinimumLibraryVersion CabalSpecV3_0+-- [2,5]+--+-- >>> cabalSpecMinimumLibraryVersion CabalSpecV2_4+-- [2,3]+--+-- @since 3.4.0.0+cabalSpecMinimumLibraryVersion :: CabalSpecVersion -> [Int]+cabalSpecMinimumLibraryVersion CabalSpecV1_0 = [1,0]+cabalSpecMinimumLibraryVersion csv = case cabalSpecToVersionDigits (pred csv) of+ [x,y] -> [x, y+1]+ xs -> xs++specHasCommonStanzas :: CabalSpecVersion -> HasCommonStanzas+specHasCommonStanzas v =+ if v >= CabalSpecV2_2+ then HasCommonStanzas+ else NoCommonStanzas++specHasElif :: CabalSpecVersion -> HasElif+specHasElif v = + if v >= CabalSpecV2_2+ then HasElif+ else NoElif++-------------------------------------------------------------------------------+-- Booleans+-------------------------------------------------------------------------------++-- IDEA: make some kind of tagged booleans?+data HasElif = HasElif | NoElif+ deriving (Eq, Show)++data HasCommonStanzas = HasCommonStanzas | NoCommonStanzas+ deriving (Eq, Show)++data HasGlobstar = HasGlobstar | NoGlobstar
+ src/Distribution/Compat/Async.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+-- | 'Async', yet using 'MVar's.+--+-- Adopted from @async@ library+-- Copyright (c) 2012, Simon Marlow+-- Licensed under BSD-3-Clause+--+-- @since 3.2.0.0+--+module Distribution.Compat.Async (+ AsyncM,+ withAsync, waitCatch,+ wait, asyncThreadId,+ cancel, uninterruptibleCancel, AsyncCancelled (..),+ -- * Cabal extras+ withAsyncNF,+ ) where++import Control.Concurrent (ThreadId, forkIO)+import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar)+import Control.DeepSeq (NFData, force)+import Control.Exception+ (BlockedIndefinitelyOnMVar (..), Exception (..), SomeException (..), catch, evaluate, mask, throwIO, throwTo, try, uninterruptibleMask_)+import Control.Monad (void)+import Data.Typeable (Typeable)+import GHC.Exts (inline)++#if MIN_VERSION_base(4,7,0)+import Control.Exception (asyncExceptionFromException, asyncExceptionToException)+#endif++-- | Async, but based on 'MVar', as we don't depend on @stm@.+data AsyncM a = Async+ { asyncThreadId :: {-# UNPACK #-} !ThreadId+ -- ^ Returns the 'ThreadId' of the thread running+ -- the given 'Async'.+ , _asyncMVar :: MVar (Either SomeException a)+ }++-- | Spawn an asynchronous action in a separate thread, and pass its+-- @Async@ handle to the supplied function. When the function returns+-- or throws an exception, 'uninterruptibleCancel' is called on the @Async@.+--+-- > withAsync action inner = mask $ \restore -> do+-- > a <- async (restore action)+-- > restore (inner a) `finally` uninterruptibleCancel a+--+-- This is a useful variant of 'async' that ensures an @Async@ is+-- never left running unintentionally.+--+-- Note: a reference to the child thread is kept alive until the call+-- to `withAsync` returns, so nesting many `withAsync` calls requires+-- linear memory.+--+withAsync :: IO a -> (AsyncM a -> IO b) -> IO b+withAsync = inline withAsyncUsing forkIO++withAsyncNF :: NFData a => IO a -> (AsyncM a -> IO b) -> IO b+withAsyncNF m = inline withAsyncUsing forkIO (m >>= evaluateNF) where+ evaluateNF = evaluate . force++withAsyncUsing :: (IO () -> IO ThreadId) -> IO a -> (AsyncM a -> IO b) -> IO b+-- The bracket version works, but is slow. We can do better by+-- hand-coding it:+withAsyncUsing doFork = \action inner -> do+ var <- newEmptyMVar+ mask $ \restore -> do+ t <- doFork $ try (restore action) >>= putMVar var+ let a = Async t var+ r <- restore (inner a) `catchAll` \e -> do+ uninterruptibleCancel a+ throwIO e+ uninterruptibleCancel a+ return r++-- | Wait for an asynchronous action to complete, and return its+-- value. If the asynchronous action threw an exception, then the+-- exception is re-thrown by 'wait'.+--+-- > wait = atomically . waitSTM+--+{-# INLINE wait #-}+wait :: AsyncM a -> IO a+wait a = do+ res <- waitCatch a+ case res of+ Left (SomeException e) -> throwIO e+ Right x -> return x++-- | Wait for an asynchronous action to complete, and return either+-- @Left e@ if the action raised an exception @e@, or @Right a@ if it+-- returned a value @a@.+--+-- > waitCatch = atomically . waitCatchSTM+--+{-# INLINE waitCatch #-}+waitCatch :: AsyncM a -> IO (Either SomeException a)+waitCatch (Async _ var) = tryAgain (readMVar var)+ where+ -- See: https://github.com/simonmar/async/issues/14+ tryAgain f = f `catch` \BlockedIndefinitelyOnMVar -> f++catchAll :: IO a -> (SomeException -> IO a) -> IO a+catchAll = catch++-- | Cancel an asynchronous action by throwing the @AsyncCancelled@+-- exception to it, and waiting for the `Async` thread to quit.+-- Has no effect if the 'Async' has already completed.+--+-- > cancel a = throwTo (asyncThreadId a) AsyncCancelled <* waitCatch a+--+-- Note that 'cancel' will not terminate until the thread the 'Async'+-- refers to has terminated. This means that 'cancel' will block for+-- as long said thread blocks when receiving an asynchronous exception.+--+-- For example, it could block if:+--+-- * It's executing a foreign call, and thus cannot receive the asynchronous+-- exception;+-- * It's executing some cleanup handler after having received the exception,+-- and the handler is blocking.+{-# INLINE cancel #-}+cancel :: AsyncM a -> IO ()+cancel a@(Async t _) = do+ throwTo t AsyncCancelled+ void (waitCatch a)++-- | The exception thrown by `cancel` to terminate a thread.+data AsyncCancelled = AsyncCancelled+ deriving (Show, Eq+ , Typeable+ )++instance Exception AsyncCancelled where+#if MIN_VERSION_base(4,7,0)+ -- wraps in SomeAsyncException+ -- See https://github.com/ghc/ghc/commit/756a970eacbb6a19230ee3ba57e24999e4157b09+ fromException = asyncExceptionFromException+ toException = asyncExceptionToException+#endif++-- | Cancel an asynchronous action+--+-- This is a variant of `cancel`, but it is not interruptible.+{-# INLINE uninterruptibleCancel #-}+uninterruptibleCancel :: AsyncM a -> IO ()+uninterruptibleCancel = uninterruptibleMask_ . cancel
+ src/Distribution/Compat/Binary.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 711+{-# LANGUAGE PatternSynonyms #-}+#endif++#ifndef MIN_VERSION_binary+#define MIN_VERSION_binary(x, y, z) 0+#endif++module Distribution.Compat.Binary+ ( decodeOrFailIO+ , decodeFileOrFail'+#if __GLASGOW_HASKELL__ >= 708 || MIN_VERSION_binary(0,7,0)+ , module Data.Binary+#else+ , Binary(..)+ , decode, encode, encodeFile+#endif+ ) where++import Control.Exception (ErrorCall (..), catch, evaluate)+import Data.ByteString.Lazy (ByteString)++#if __GLASGOW_HASKELL__ >= 708 || MIN_VERSION_binary(0,7,0)++import Data.Binary++-- | Lazily reconstruct a value previously written to a file.+decodeFileOrFail' :: Binary a => FilePath -> IO (Either String a)+decodeFileOrFail' f = either (Left . snd) Right `fmap` decodeFileOrFail f++#else++import Data.Binary.Get+import Data.Binary.Put+import qualified Data.ByteString.Lazy as BSL++import Distribution.Compat.Binary.Class+import Distribution.Compat.Binary.Generic ()++-- | Decode a value from a lazy ByteString, reconstructing the+-- original structure.+--+decode :: Binary a => ByteString -> a+decode = runGet get++-- | Encode a value using binary serialisation to a lazy ByteString.+--+encode :: Binary a => a -> ByteString+encode = runPut . put+{-# INLINE encode #-}++-- | Lazily reconstruct a value previously written to a file.+decodeFileOrFail' :: Binary a => FilePath -> IO (Either String a)+decodeFileOrFail' f = decodeOrFailIO =<< BSL.readFile f++-- | Lazily serialise a value to a file+encodeFile :: Binary a => FilePath -> a -> IO ()+encodeFile f = BSL.writeFile f . encode++#endif++decodeOrFailIO :: Binary a => ByteString -> IO (Either String a)+decodeOrFailIO bs =+ catch (evaluate (decode bs) >>= return . Right) handler+ where+#if MIN_VERSION_base(4,9,0)+ handler (ErrorCallWithLocation str _) = return $ Left str+#else+ handler (ErrorCall str) = return $ Left str+#endif
+ src/Distribution/Compat/Binary/Class.hs view
@@ -0,0 +1,519 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE DefaultSignatures #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.Binary.Class+-- Copyright : Lennart Kolmodin+-- License : BSD3-style (see LICENSE)+--+-- Maintainer : Lennart Kolmodin <kolmodin@gmail.com>+-- Stability : unstable+-- Portability : portable to Hugs and GHC. Requires the FFI and some flexible instances+--+-- Typeclass and instances for binary serialization.+--+-----------------------------------------------------------------------------++module Distribution.Compat.Binary.Class (++ -- * The Binary class+ Binary(..)++ -- * Support for generics+ , GBinary(..)++ ) where++import Data.Word++import Data.Binary.Put+import Data.Binary.Get++import Control.Applicative ((<$>), (<*>), (*>))+import Foreign++import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as L++import Data.Char (chr,ord)+import Data.List (unfoldr)+import Data.Foldable (traverse_)++-- And needed for the instances:+import qualified Data.ByteString as B+import qualified Data.Map as Map+import qualified Data.Set as Set+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.Ratio as R++import qualified Data.Tree as T++import Data.Array.Unboxed++import GHC.Generics++import qualified Data.Sequence as Seq+import qualified Data.Foldable as Fold++------------------------------------------------------------------------++class GBinary f where+ gput :: f t -> Put+ gget :: Get (f t)++-- | The 'Binary' class provides 'put' and 'get', methods to encode and+-- decode a Haskell value to a lazy 'ByteString'. It mirrors the 'Read' and+-- 'Show' classes for textual representation of Haskell types, and is+-- suitable for serialising Haskell values to disk, over the network.+--+-- For decoding and generating simple external binary formats (e.g. C+-- structures), Binary may be used, but in general is not suitable+-- for complex protocols. Instead use the 'Put' and 'Get' primitives+-- directly.+--+-- Instances of Binary should satisfy the following property:+--+-- > decode . encode == id+--+-- That is, the 'get' and 'put' methods should be the inverse of each+-- other. A range of instances are provided for basic Haskell types.+--+class Binary t where+ -- | Encode a value in the Put monad.+ put :: t -> Put+ -- | Decode a value in the Get monad+ get :: Get t++ default put :: (Generic t, GBinary (Rep t)) => t -> Put+ put = gput . from++ default get :: (Generic t, GBinary (Rep t)) => Get t+ get = to `fmap` gget++------------------------------------------------------------------------+-- Simple instances++-- The () type need never be written to disk: values of singleton type+-- can be reconstructed from the type alone+instance Binary () where+ put () = return ()+ get = return ()++-- Bools are encoded as a byte in the range 0 .. 1+instance Binary Bool where+ put = putWord8 . fromIntegral . fromEnum+ get = fmap (toEnum . fromIntegral) getWord8++-- Values of type 'Ordering' are encoded as a byte in the range 0 .. 2+instance Binary Ordering where+ put = putWord8 . fromIntegral . fromEnum+ get = fmap (toEnum . fromIntegral) getWord8++------------------------------------------------------------------------+-- Words and Ints++-- Words8s are written as bytes+instance Binary Word8 where+ put = putWord8+ get = getWord8++-- Words16s are written as 2 bytes in big-endian (network) order+instance Binary Word16 where+ put = putWord16be+ get = getWord16be++-- Words32s are written as 4 bytes in big-endian (network) order+instance Binary Word32 where+ put = putWord32be+ get = getWord32be++-- Words64s are written as 8 bytes in big-endian (network) order+instance Binary Word64 where+ put = putWord64be+ get = getWord64be++-- Int8s are written as a single byte.+instance Binary Int8 where+ put i = put (fromIntegral i :: Word8)+ get = fmap fromIntegral (get :: Get Word8)++-- Int16s are written as a 2 bytes in big endian format+instance Binary Int16 where+ put i = put (fromIntegral i :: Word16)+ get = fmap fromIntegral (get :: Get Word16)++-- Int32s are written as a 4 bytes in big endian format+instance Binary Int32 where+ put i = put (fromIntegral i :: Word32)+ get = fmap fromIntegral (get :: Get Word32)++-- Int64s are written as a 4 bytes in big endian format+instance Binary Int64 where+ put i = put (fromIntegral i :: Word64)+ get = fmap fromIntegral (get :: Get Word64)++------------------------------------------------------------------------++-- Words are are written as Word64s, that is, 8 bytes in big endian format+instance Binary Word where+ put i = put (fromIntegral i :: Word64)+ get = fmap fromIntegral (get :: Get Word64)++-- Ints are are written as Int64s, that is, 8 bytes in big endian format+instance Binary Int where+ put i = put (fromIntegral i :: Int64)+ get = fmap fromIntegral (get :: Get Int64)++------------------------------------------------------------------------+--+-- Portable, and pretty efficient, serialisation of Integer+--++-- Fixed-size type for a subset of Integer+type SmallInt = Int32++-- Integers are encoded in two ways: if they fit inside a SmallInt,+-- they're written as a byte tag, and that value. If the Integer value+-- is too large to fit in a SmallInt, it is written as a byte array,+-- along with a sign and length field.++instance Binary Integer where++ {-# INLINE put #-}+ put n | n >= lo && n <= hi = do+ putWord8 0+ put (fromIntegral n :: SmallInt) -- fast path+ where+ lo = fromIntegral (minBound :: SmallInt) :: Integer+ hi = fromIntegral (maxBound :: SmallInt) :: Integer++ put n = do+ putWord8 1+ put sign+ put (unroll (abs n)) -- unroll the bytes+ where+ sign = fromIntegral (signum n) :: Word8++ {-# INLINE get #-}+ get = do+ tag <- get :: Get Word8+ case tag of+ 0 -> fmap fromIntegral (get :: Get SmallInt)+ _ -> do sign <- get+ bytes <- get+ let v = roll bytes+ return $! if sign == (1 :: Word8) then v else - v++--+-- Fold and unfold an Integer to and from a list of its bytes+--+unroll :: Integer -> [Word8]+unroll = unfoldr step+ where+ step 0 = Nothing+ step i = Just (fromIntegral i, i `shiftR` 8)++roll :: [Word8] -> Integer+roll = foldr unstep 0+ where+ unstep b a = a `shiftL` 8 .|. fromIntegral b++{-++--+-- An efficient, raw serialisation for Integer (GHC only)+--++-- TODO This instance is not architecture portable. GMP stores numbers as+-- arrays of machine sized words, so the byte format is not portable across+-- architectures with different endianness and word size.++import Data.ByteString.Base (toForeignPtr,unsafePackAddress, memcpy)+import GHC.Base hiding (ord, chr)+import GHC.Prim+import GHC.Ptr (Ptr(..))+import GHC.IOBase (IO(..))++instance Binary Integer where+ put (S# i) = putWord8 0 *> put (I# i)+ put (J# s ba) = do+ putWord8 1+ put (I# s)+ put (BA ba)++ get = do+ b <- getWord8+ case b of+ 0 -> do (I# i#) <- get+ return (S# i#)+ _ -> do (I# s#) <- get+ (BA a#) <- get+ return (J# s# a#)++instance Binary ByteArray where++ -- Pretty safe.+ put (BA ba) =+ let sz = sizeofByteArray# ba -- (primitive) in *bytes*+ addr = byteArrayContents# ba+ bs = unsafePackAddress (I# sz) addr+ in put bs -- write as a ByteString. easy, yay!++ -- Pretty scary. Should be quick though+ get = do+ (fp, off, n@(I# sz)) <- fmap toForeignPtr get -- so decode a ByteString+ assert (off == 0) $ return $ unsafePerformIO $ do+ (MBA arr) <- newByteArray sz -- and copy it into a ByteArray#+ let to = byteArrayContents# (unsafeCoerce# arr) -- urk, is this safe?+ withForeignPtr fp $ \from -> memcpy (Ptr to) from (fromIntegral n)+ freezeByteArray arr++-- wrapper for ByteArray#+data ByteArray = BA {-# UNPACK #-} !ByteArray#+data MBA = MBA {-# UNPACK #-} !(MutableByteArray# RealWorld)++newByteArray :: Int# -> IO MBA+newByteArray sz = IO $ \s ->+ case newPinnedByteArray# sz s of { (# s', arr #) ->+ (# s', MBA arr #) }++freezeByteArray :: MutableByteArray# RealWorld -> IO ByteArray+freezeByteArray arr = IO $ \s ->+ case unsafeFreezeByteArray# arr s of { (# s', arr' #) ->+ (# s', BA arr' #) }++-}++instance (Binary a,Integral a) => Binary (R.Ratio a) where+ put r = put (R.numerator r) *> put (R.denominator r)+ get = (R.%) <$> get <*> get++------------------------------------------------------------------------++-- Char is serialised as UTF-8+instance Binary Char where+ put a | c <= 0x7f = put (fromIntegral c :: Word8)+ | c <= 0x7ff = do put (0xc0 .|. y)+ put (0x80 .|. z)+ | c <= 0xffff = do put (0xe0 .|. x)+ put (0x80 .|. y)+ put (0x80 .|. z)+ | c <= 0x10ffff = do put (0xf0 .|. w)+ put (0x80 .|. x)+ put (0x80 .|. y)+ put (0x80 .|. z)+ | otherwise = error "Not a valid Unicode code point"+ where+ c = ord a+ z, y, x, w :: Word8+ z = fromIntegral (c .&. 0x3f)+ y = fromIntegral (shiftR c 6 .&. 0x3f)+ x = fromIntegral (shiftR c 12 .&. 0x3f)+ w = fromIntegral (shiftR c 18 .&. 0x7)++ get = do+ let getByte = fmap (fromIntegral :: Word8 -> Int) get+ shiftL6 = flip shiftL 6 :: Int -> Int+ w <- getByte+ r <- case () of+ _ | w < 0x80 -> return w+ | w < 0xe0 -> do+ x <- fmap (xor 0x80) getByte+ return (x .|. shiftL6 (xor 0xc0 w))+ | w < 0xf0 -> do+ x <- fmap (xor 0x80) getByte+ y <- fmap (xor 0x80) getByte+ return (y .|. shiftL6 (x .|. shiftL6+ (xor 0xe0 w)))+ | otherwise -> do+ x <- fmap (xor 0x80) getByte+ y <- fmap (xor 0x80) getByte+ z <- fmap (xor 0x80) getByte+ return (z .|. shiftL6 (y .|. shiftL6+ (x .|. shiftL6 (xor 0xf0 w))))+ return $! chr r++------------------------------------------------------------------------+-- Instances for the first few tuples++instance (Binary a, Binary b) => Binary (a,b) where+ put (a,b) = put a *> put b+ get = (,) <$> get <*> get++instance (Binary a, Binary b, Binary c) => Binary (a,b,c) where+ put (a,b,c) = put a *> put b *> put c+ get = (,,) <$> get <*> get <*> get++instance (Binary a, Binary b, Binary c, Binary d) => Binary (a,b,c,d) where+ put (a,b,c,d) = put a *> put b *> put c *> put d+ get = (,,,) <$> get <*> get <*> get <*> get++instance (Binary a, Binary b, Binary c, Binary d, Binary e) => Binary (a,b,c,d,e) where+ put (a,b,c,d,e) = put a *> put b *> put c *> put d *> put e+ get = (,,,,) <$> get <*> get <*> get <*> get <*> get++--+-- and now just recurse:+--++instance (Binary a, Binary b, Binary c, Binary d, Binary e, Binary f)+ => Binary (a,b,c,d,e,f) where+ put (a,b,c,d,e,f) = put (a,(b,c,d,e,f))+ get = do (a,(b,c,d,e,f)) <- get ; return (a,b,c,d,e,f)++instance (Binary a, Binary b, Binary c, Binary d, Binary e, Binary f, Binary g)+ => Binary (a,b,c,d,e,f,g) where+ put (a,b,c,d,e,f,g) = put (a,(b,c,d,e,f,g))+ get = do (a,(b,c,d,e,f,g)) <- get ; return (a,b,c,d,e,f,g)++instance (Binary a, Binary b, Binary c, Binary d, Binary e,+ Binary f, Binary g, Binary h)+ => Binary (a,b,c,d,e,f,g,h) where+ put (a,b,c,d,e,f,g,h) = put (a,(b,c,d,e,f,g,h))+ get = do (a,(b,c,d,e,f,g,h)) <- get ; return (a,b,c,d,e,f,g,h)++instance (Binary a, Binary b, Binary c, Binary d, Binary e,+ Binary f, Binary g, Binary h, Binary i)+ => Binary (a,b,c,d,e,f,g,h,i) where+ put (a,b,c,d,e,f,g,h,i) = put (a,(b,c,d,e,f,g,h,i))+ get = do (a,(b,c,d,e,f,g,h,i)) <- get ; return (a,b,c,d,e,f,g,h,i)++instance (Binary a, Binary b, Binary c, Binary d, Binary e,+ Binary f, Binary g, Binary h, Binary i, Binary j)+ => Binary (a,b,c,d,e,f,g,h,i,j) where+ put (a,b,c,d,e,f,g,h,i,j) = put (a,(b,c,d,e,f,g,h,i,j))+ get = do (a,(b,c,d,e,f,g,h,i,j)) <- get ; return (a,b,c,d,e,f,g,h,i,j)++------------------------------------------------------------------------+-- Container types++instance Binary a => Binary [a] where+ put l = put (length l) *> traverse_ put l+ get = do n <- get :: Get Int+ getMany n++-- | 'getMany n' get 'n' elements in order, without blowing the stack.+getMany :: Binary a => Int -> Get [a]+getMany n = go [] n+ where+ go xs 0 = return $! reverse xs+ go xs i = do x <- get+ -- we must seq x to avoid stack overflows due to laziness in+ -- (>>=)+ x `seq` go (x:xs) (i-1)+{-# INLINE getMany #-}++instance (Binary a) => Binary (Maybe a) where+ put Nothing = putWord8 0+ put (Just x) = putWord8 1 *> put x+ get = do+ w <- getWord8+ case w of+ 0 -> return Nothing+ _ -> fmap Just get++instance (Binary a, Binary b) => Binary (Either a b) where+ put (Left a) = putWord8 0 *> put a+ put (Right b) = putWord8 1 *> put b+ get = do+ w <- getWord8+ case w of+ 0 -> fmap Left get+ _ -> fmap Right get++------------------------------------------------------------------------+-- ByteStrings (have specially efficient instances)++instance Binary B.ByteString where+ put bs = do put (B.length bs)+ putByteString bs+ get = get >>= getByteString++--+-- Using old versions of fps, this is a type synonym, and non portable+--+-- Requires 'flexible instances'+--+instance Binary ByteString where+ put bs = do put (fromIntegral (L.length bs) :: Int)+ putLazyByteString bs+ get = get >>= getLazyByteString++------------------------------------------------------------------------+-- Maps and Sets++instance (Binary a) => Binary (Set.Set a) where+ put s = put (Set.size s) *> traverse_ put (Set.toAscList s)+ get = fmap Set.fromDistinctAscList get++instance (Binary k, Binary e) => Binary (Map.Map k e) where+ put m = put (Map.size m) *> traverse_ put (Map.toAscList m)+ get = fmap Map.fromDistinctAscList get++instance Binary IntSet.IntSet where+ put s = put (IntSet.size s) *> traverse_ put (IntSet.toAscList s)+ get = fmap IntSet.fromDistinctAscList get++instance (Binary e) => Binary (IntMap.IntMap e) where+ put m = put (IntMap.size m) *> traverse_ put (IntMap.toAscList m)+ get = fmap IntMap.fromDistinctAscList get++------------------------------------------------------------------------+-- Queues and Sequences++instance (Binary e) => Binary (Seq.Seq e) where+ put s = put (Seq.length s) *> Fold.traverse_ put s+ get = do n <- get :: Get Int+ rep Seq.empty n get+ where rep xs 0 _ = return $! xs+ rep xs n g = xs `seq` n `seq` do+ x <- g+ rep (xs Seq.|> x) (n-1) g++------------------------------------------------------------------------+-- Floating point++instance Binary Double where+ put d = put (decodeFloat d)+ get = encodeFloat <$> get <*> get++instance Binary Float where+ put f = put (decodeFloat f)+ get = encodeFloat <$> get <*> get++------------------------------------------------------------------------+-- Trees++instance (Binary e) => Binary (T.Tree e) where+ put (T.Node r s) = put r *> put s+ get = T.Node <$> get <*> get++------------------------------------------------------------------------+-- Arrays++instance (Binary i, Ix i, Binary e) => Binary (Array i e) where+ put a = do+ put (bounds a)+ put (rangeSize $ bounds a) -- write the length+ traverse_ put (elems a) -- now the elems.+ get = do+ bs <- get+ n <- get -- read the length+ xs <- getMany n -- now the elems.+ return (listArray bs xs)++--+-- The IArray UArray e constraint is non portable. Requires flexible instances+--+instance (Binary i, Ix i, Binary e, IArray UArray e) => Binary (UArray i e) where+ put a = do+ put (bounds a)+ put (rangeSize $ bounds a) -- now write the length+ traverse_ put (elems a)+ get = do+ bs <- get+ n <- get+ xs <- getMany n+ return (listArray bs xs)
+ src/Distribution/Compat/Binary/Generic.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, KindSignatures,+ ScopedTypeVariables, Trustworthy, TypeOperators, TypeSynonymInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.Binary.Generic+-- Copyright : Bryan O'Sullivan+-- License : BSD3-style (see LICENSE)+--+-- Maintainer : Bryan O'Sullivan <bos@serpentine.com>+-- Stability : unstable+-- Portability : Only works with GHC 7.2 and newer+--+-- Instances for supporting GHC generics.+--+-----------------------------------------------------------------------------+module Distribution.Compat.Binary.Generic+ (+ ) where++import Control.Applicative+import Distribution.Compat.Binary.Class+import Data.Binary.Get+import Data.Binary.Put+import Data.Bits+import Data.Word+import GHC.Generics++-- Type without constructors+instance GBinary V1 where+ gput _ = return ()+ gget = return undefined++-- Constructor without arguments+instance GBinary U1 where+ gput U1 = return ()+ gget = return U1++-- Product: constructor with parameters+instance (GBinary a, GBinary b) => GBinary (a :*: b) where+ gput (x :*: y) = gput x >> gput y+ gget = (:*:) <$> gget <*> gget++-- Metadata (constructor name, etc)+instance GBinary a => GBinary (M1 i c a) where+ gput = gput . unM1+ gget = M1 <$> gget++-- Constants, additional parameters, and rank-1 recursion+instance Binary a => GBinary (K1 i a) where+ gput = put . unK1+ gget = K1 <$> get++-- Borrowed from the cereal package.++-- The following GBinary instance for sums has support for serializing+-- types with up to 2^64-1 constructors. It will use the minimal+-- number of bytes needed to encode the constructor. For example when+-- a type has 2^8 constructors or less it will use a single byte to+-- encode the constructor. If it has 2^16 constructors or less it will+-- use two bytes, and so on till 2^64-1.++#define GUARD(WORD) (size - 1) <= fromIntegral (maxBound :: WORD)+#define PUTSUM(WORD) GUARD(WORD) = putSum (0 :: WORD) (fromIntegral size)+#define GETSUM(WORD) GUARD(WORD) = (get :: Get WORD) >>= checkGetSum (fromIntegral size)++instance ( GSum a, GSum b+ , GBinary a, GBinary b+ , SumSize a, SumSize b) => GBinary (a :+: b) where+ gput | PUTSUM(Word8) | PUTSUM(Word16) | PUTSUM(Word32) | PUTSUM(Word64)+ | otherwise = sizeError "encode" size+ where+ size = unTagged (sumSize :: Tagged (a :+: b) Word64)++ gget | GETSUM(Word8) | GETSUM(Word16) | GETSUM(Word32) | GETSUM(Word64)+ | otherwise = sizeError "decode" size+ where+ size = unTagged (sumSize :: Tagged (a :+: b) Word64)++sizeError :: Show size => String -> size -> error+sizeError s size =+ error $ "Can't " ++ s ++ " a type with " ++ show size ++ " constructors"++------------------------------------------------------------------------++checkGetSum :: (Ord word, Num word, Bits word, GSum f)+ => word -> word -> Get (f a)+checkGetSum size code | code < size = getSum code size+ | otherwise = fail "Unknown encoding for constructor"+{-# INLINE checkGetSum #-}++class GSum f where+ getSum :: (Ord word, Num word, Bits word) => word -> word -> Get (f a)+ putSum :: (Num w, Bits w, Binary w) => w -> w -> f a -> Put++instance (GSum a, GSum b, GBinary a, GBinary b) => GSum (a :+: b) where+ getSum !code !size | code < sizeL = L1 <$> getSum code sizeL+ | otherwise = R1 <$> getSum (code - sizeL) sizeR+ where+ sizeL = size `shiftR` 1+ sizeR = size - sizeL++ putSum !code !size s = case s of+ L1 x -> putSum code sizeL x+ R1 x -> putSum (code + sizeL) sizeR x+ where+ sizeL = size `shiftR` 1+ sizeR = size - sizeL++instance GBinary a => GSum (C1 c a) where+ getSum _ _ = gget++ putSum !code _ x = put code *> gput x++------------------------------------------------------------------------++class SumSize f where+ sumSize :: Tagged f Word64++newtype Tagged (s :: * -> *) b = Tagged {unTagged :: b}++instance (SumSize a, SumSize b) => SumSize (a :+: b) where+ sumSize = Tagged $ unTagged (sumSize :: Tagged a Word64) ++ unTagged (sumSize :: Tagged b Word64)++instance SumSize (C1 c a) where+ sumSize = Tagged 1
+ src/Distribution/Compat/CharParsing.hs view
@@ -0,0 +1,357 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -fspec-constr -fspec-constr-count=8 #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.CharParsing+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable+--+-- Parsers for character streams+--+-- Originally in @parsers@ package.+--+-----------------------------------------------------------------------------+module Distribution.Compat.CharParsing+ (+ -- * Combinators+ oneOf -- :: CharParsing m => [Char] -> m Char+ , noneOf -- :: CharParsing m => [Char] -> m Char+ , spaces -- :: CharParsing m => m ()+ , space -- :: CharParsing m => m Char+ , newline -- :: CharParsing m => m Char+ , tab -- :: CharParsing m => m Char+ , upper -- :: CharParsing m => m Char+ , lower -- :: CharParsing m => m Char+ , alphaNum -- :: CharParsing m => m Char+ , letter -- :: CharParsing m => m Char+ , digit -- :: CharParsing m => m Char+ , hexDigit -- :: CharParsing m => m Char+ , octDigit -- :: CharParsing m => m Char+ , satisfyRange -- :: CharParsing m => Char -> Char -> m Char+ -- * Class+ , CharParsing(..)+ -- * Cabal additions+ , integral+ , signedIntegral+ , munch1+ , munch+ , skipSpaces1+ , module Distribution.Compat.Parsing+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.State.Lazy as Lazy+import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Reader (ReaderT (..))+import Control.Monad.Trans.Identity (IdentityT (..))+import Data.Char+import Data.Text (Text, unpack)++import qualified Text.Parsec as Parsec++import Distribution.Compat.Parsing++-- | @oneOf cs@ succeeds if the current character is in the supplied+-- list of characters @cs@. Returns the parsed character. See also+-- 'satisfy'.+--+-- > vowel = oneOf "aeiou"+oneOf :: CharParsing m => [Char] -> m Char+oneOf xs = satisfy (\c -> c `elem` xs)+{-# INLINE oneOf #-}++-- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current+-- character is /not/ in the supplied list of characters @cs@. Returns the+-- parsed character.+--+-- > consonant = noneOf "aeiou"+noneOf :: CharParsing m => [Char] -> m Char+noneOf xs = satisfy (\c -> c `notElem` xs)+{-# INLINE noneOf #-}++-- | Skips /zero/ or more white space characters. See also 'skipMany'.+spaces :: CharParsing m => m ()+spaces = skipMany space <?> "white space"+{-# INLINE spaces #-}++-- | Parses a white space character (any character which satisfies 'isSpace')+-- Returns the parsed character.+space :: CharParsing m => m Char+space = satisfy isSpace <?> "space"+{-# INLINE space #-}++-- | Parses a newline character (\'\\n\'). Returns a newline character.+newline :: CharParsing m => m Char+newline = char '\n' <?> "new-line"+{-# INLINE newline #-}++-- | Parses a tab character (\'\\t\'). Returns a tab character.+tab :: CharParsing m => m Char+tab = char '\t' <?> "tab"+{-# INLINE tab #-}++-- | Parses an upper case letter. Returns the parsed character.+upper :: CharParsing m => m Char+upper = satisfy isUpper <?> "uppercase letter"+{-# INLINE upper #-}++-- | Parses a lower case character. Returns the parsed character.+lower :: CharParsing m => m Char+lower = satisfy isLower <?> "lowercase letter"+{-# INLINE lower #-}++-- | Parses a letter or digit. Returns the parsed character.+alphaNum :: CharParsing m => m Char+alphaNum = satisfy isAlphaNum <?> "letter or digit"+{-# INLINE alphaNum #-}++-- | Parses a letter (an upper case or lower case character). Returns the+-- parsed character.+letter :: CharParsing m => m Char+letter = satisfy isAlpha <?> "letter"+{-# INLINE letter #-}++-- | Parses a digit. Returns the parsed character.+digit :: CharParsing m => m Char+digit = satisfy isDigit <?> "digit"+{-# INLINE digit #-}++-- | Parses a hexadecimal digit (a digit or a letter between \'a\' and+-- \'f\' or \'A\' and \'F\'). Returns the parsed character.+hexDigit :: CharParsing m => m Char+hexDigit = satisfy isHexDigit <?> "hexadecimal digit"+{-# INLINE hexDigit #-}++-- | Parses an octal digit (a character between \'0\' and \'7\'). Returns+-- the parsed character.+octDigit :: CharParsing m => m Char+octDigit = satisfy isOctDigit <?> "octal digit"+{-# INLINE octDigit #-}++satisfyRange :: CharParsing m => Char -> Char -> m Char+satisfyRange a z = satisfy (\c -> c >= a && c <= z)+{-# INLINE satisfyRange #-}++-- | Additional functionality needed to parse character streams.+class Parsing m => CharParsing m where+ -- | Parse a single character of the input, with UTF-8 decoding+ satisfy :: (Char -> Bool) -> m Char++ -- | @char c@ parses a single character @c@. Returns the parsed+ -- character (i.e. @c@).+ --+ -- /e.g./+ --+ -- @semiColon = 'char' ';'@+ char :: Char -> m Char+ char c = satisfy (c ==) <?> show [c]+ {-# INLINE char #-}++ -- | @notChar c@ parses any single character other than @c@. Returns the parsed+ -- character.+ notChar :: Char -> m Char+ notChar c = satisfy (c /=)+ {-# INLINE notChar #-}++ -- | This parser succeeds for any character. Returns the parsed character.+ anyChar :: m Char+ anyChar = satisfy (const True)+ {-# INLINE anyChar #-}++ -- | @string s@ parses a sequence of characters given by @s@. Returns+ -- the parsed string (i.e. @s@).+ --+ -- > divOrMod = string "div"+ -- > <|> string "mod"+ string :: String -> m String+ string s = s <$ try (traverse_ char s) <?> show s+ {-# INLINE string #-}++ -- | @text t@ parses a sequence of characters determined by the text @t@ Returns+ -- the parsed text fragment (i.e. @t@).+ --+ -- Using @OverloadedStrings@:+ --+ -- > divOrMod = text "div"+ -- > <|> text "mod"+ text :: Text -> m Text+ text t = t <$ string (unpack t)+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m) => CharParsing (Lazy.StateT s m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m) => CharParsing (Strict.StateT s m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m) => CharParsing (ReaderT e m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Strict.WriterT w m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Lazy.WriterT w m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Lazy.RWST r w s m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Strict.RWST r w s m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance (CharParsing m, MonadPlus m) => CharParsing (IdentityT m) where+ satisfy = lift . satisfy+ {-# INLINE satisfy #-}+ char = lift . char+ {-# INLINE char #-}+ notChar = lift . notChar+ {-# INLINE notChar #-}+ anyChar = lift anyChar+ {-# INLINE anyChar #-}+ string = lift . string+ {-# INLINE string #-}+ text = lift . text+ {-# INLINE text #-}++instance Parsec.Stream s m Char => CharParsing (Parsec.ParsecT s u m) where+ satisfy = Parsec.satisfy+ char = Parsec.char+ notChar c = Parsec.satisfy (/= c)+ anyChar = Parsec.anyChar+ string = Parsec.string++-------------------------------------------------------------------------------+-- Our additions+-------------------------------------------------------------------------------++integral :: (CharParsing m, Integral a) => m a+integral = toNumber <$> some d <?> "integral"+ where+ toNumber = foldl' (\a b -> a * 10 + b) 0+ d = f <$> satisfyRange '0' '9'+ f '0' = 0+ f '1' = 1+ f '2' = 2+ f '3' = 3+ f '4' = 4+ f '5' = 5+ f '6' = 6+ f '7' = 7+ f '8' = 8+ f '9' = 9+ f _ = error "panic! integral"+{-# INLINE integral #-}++-- | Accepts negative (starting with @-@) and positive (without sign) integral+-- numbers.+-- +-- @since 3.4.0.0+signedIntegral :: (CharParsing m, Integral a) => m a+signedIntegral = negate <$ char '-' <*> integral <|> integral+{-# INLINE signedIntegral #-}++-- | Greedily munch characters while predicate holds.+-- Require at least one character.+munch1 :: CharParsing m => (Char -> Bool) -> m String+munch1 = some . satisfy+{-# INLINE munch1 #-}++-- | Greedely munch characters while predicate holds.+-- Always succeeds.+munch :: CharParsing m => (Char -> Bool) -> m String+munch = many . satisfy+{-# INLINE munch #-}++skipSpaces1 :: CharParsing m => m ()+skipSpaces1 = skipSome space+{-# INLINE skipSpaces1 #-}
+ src/Distribution/Compat/CopyFile.hs view
@@ -0,0 +1,250 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_HADDOCK hide #-}+module Distribution.Compat.CopyFile (+ copyFile,+ copyFileChanged,+ filesEqual,+ copyOrdinaryFile,+ copyExecutableFile,+ setFileOrdinary,+ setFileExecutable,+ setDirOrdinary,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++#ifndef mingw32_HOST_OS+import Distribution.Compat.Internal.TempFile++import Control.Exception+ ( bracketOnError )+import qualified Data.ByteString.Lazy as BSL+import System.IO.Error+ ( ioeSetLocation )+import System.Directory+ ( doesFileExist, renameFile, removeFile )+import System.FilePath+ ( takeDirectory )+import System.IO+ ( IOMode(ReadMode), hClose, hGetBuf, hPutBuf, hFileSize+ , withBinaryFile )+import Foreign+ ( allocaBytes )++import System.Posix.Types+ ( FileMode )+import System.Posix.Internals+ ( c_chmod, withFilePath )+import Foreign.C+ ( throwErrnoPathIfMinus1_ )++#else /* else mingw32_HOST_OS */++import qualified Data.ByteString.Lazy as BSL+import System.IO.Error+ ( ioeSetLocation )+import System.Directory+ ( doesFileExist )+import System.FilePath+ ( addTrailingPathSeparator+ , hasTrailingPathSeparator+ , isPathSeparator+ , isRelative+ , joinDrive+ , joinPath+ , pathSeparator+ , pathSeparators+ , splitDirectories+ , splitDrive+ )+import System.IO+ ( IOMode(ReadMode), hFileSize+ , withBinaryFile )++import qualified System.Win32.File as Win32 ( copyFile )+#endif /* mingw32_HOST_OS */++copyOrdinaryFile, copyExecutableFile :: FilePath -> FilePath -> IO ()+copyOrdinaryFile src dest = copyFile src dest >> setFileOrdinary dest+copyExecutableFile src dest = copyFile src dest >> setFileExecutable dest++setFileOrdinary, setFileExecutable, setDirOrdinary :: FilePath -> IO ()+#ifndef mingw32_HOST_OS+setFileOrdinary path = setFileMode path 0o644 -- file perms -rw-r--r--+setFileExecutable path = setFileMode path 0o755 -- file perms -rwxr-xr-x++setFileMode :: FilePath -> FileMode -> IO ()+setFileMode name m =+ withFilePath name $ \s -> do+ throwErrnoPathIfMinus1_ "setFileMode" name (c_chmod s m)+#else+setFileOrdinary _ = return ()+setFileExecutable _ = return ()+#endif+-- This happens to be true on Unix and currently on Windows too:+setDirOrdinary = setFileExecutable++-- | Copies a file to a new destination.+-- Often you should use `copyFileChanged` instead.+copyFile :: FilePath -> FilePath -> IO ()+copyFile fromFPath toFPath =+ copy+ `catchIO` (\ioe -> throwIO (ioeSetLocation ioe "copyFile"))+ where+#ifndef mingw32_HOST_OS+ copy = withBinaryFile fromFPath ReadMode $ \hFrom ->+ bracketOnError openTmp cleanTmp $ \(tmpFPath, hTmp) ->+ do allocaBytes bufferSize $ copyContents hFrom hTmp+ hClose hTmp+ renameFile tmpFPath toFPath+ openTmp = openBinaryTempFile (takeDirectory toFPath) ".copyFile.tmp"+ cleanTmp (tmpFPath, hTmp) = do+ hClose hTmp `catchIO` \_ -> return ()+ removeFile tmpFPath `catchIO` \_ -> return ()+ bufferSize = 4096++ copyContents hFrom hTo buffer = do+ count <- hGetBuf hFrom buffer bufferSize+ when (count > 0) $ do+ hPutBuf hTo buffer count+ copyContents hFrom hTo buffer+#else+ copy = Win32.copyFile (toExtendedLengthPath fromFPath)+ (toExtendedLengthPath toFPath)+ False++-- NOTE: Shamelessly lifted from System.Directory.Internal.Windows++-- | Add the @"\\\\?\\"@ prefix if necessary or possible. The path remains+-- unchanged if the prefix is not added. This function can sometimes be used+-- to bypass the @MAX_PATH@ length restriction in Windows API calls.+--+-- See Note [Path normalization].+toExtendedLengthPath :: FilePath -> FilePath+toExtendedLengthPath path+ | isRelative path = path+ | otherwise =+ case normalisedPath of+ '\\' : '?' : '?' : '\\' : _ -> normalisedPath+ '\\' : '\\' : '?' : '\\' : _ -> normalisedPath+ '\\' : '\\' : '.' : '\\' : _ -> normalisedPath+ '\\' : subpath@('\\' : _) -> "\\\\?\\UNC" <> subpath+ _ -> "\\\\?\\" <> normalisedPath+ where normalisedPath = simplifyWindows path++-- | Similar to 'normalise' but:+--+-- * empty paths stay empty,+-- * parent dirs (@..@) are expanded, and+-- * paths starting with @\\\\?\\@ are preserved.+--+-- The goal is to preserve the meaning of paths better than 'normalise'.+--+-- Note [Path normalization]+-- 'normalise' doesn't simplify path names but will convert / into \\+-- this would normally not be a problem as once the path hits the RTS we would+-- have simplified the path then. However since we're calling the WIn32 API+-- directly we have to do the simplification before the call. Without this the+-- path Z:// would become Z:\\\\ and when converted to a device path the path+-- becomes \\?\Z:\\\\ which is an invalid path.+--+-- This is not a bug in normalise as it explicitly states that it won't simplify+-- a FilePath.+simplifyWindows :: FilePath -> FilePath+simplifyWindows "" = ""+simplifyWindows path =+ case drive' of+ "\\\\?\\" -> drive' <> subpath+ _ -> simplifiedPath+ where+ simplifiedPath = joinDrive drive' subpath'+ (drive, subpath) = splitDrive path+ drive' = upperDrive (normaliseTrailingSep (normalisePathSeps drive))+ subpath' = appendSep . avoidEmpty . prependSep . joinPath .+ stripPardirs . expandDots . skipSeps .+ splitDirectories $ subpath++ upperDrive d = case d of+ c : ':' : s | isAlpha c && all isPathSeparator s -> toUpper c : ':' : s+ _ -> d+ skipSeps = filter (not . (`elem` (pure <$> pathSeparators)))+ stripPardirs | pathIsAbsolute || subpathIsAbsolute = dropWhile (== "..")+ | otherwise = id+ prependSep | subpathIsAbsolute = (pathSeparator :)+ | otherwise = id+ avoidEmpty | not pathIsAbsolute+ && (null drive || hasTrailingPathSep) -- prefer "C:" over "C:."+ = emptyToCurDir+ | otherwise = id+ appendSep p | hasTrailingPathSep+ && not (pathIsAbsolute && null p)+ = addTrailingPathSeparator p+ | otherwise = p+ pathIsAbsolute = not (isRelative path)+ subpathIsAbsolute = any isPathSeparator (take 1 subpath)+ hasTrailingPathSep = hasTrailingPathSeparator subpath++-- | Given a list of path segments, expand @.@ and @..@. The path segments+-- must not contain path separators.+expandDots :: [FilePath] -> [FilePath]+expandDots = reverse . go []+ where+ go ys' xs' =+ case xs' of+ [] -> ys'+ x : xs ->+ case x of+ "." -> go ys' xs+ ".." ->+ case ys' of+ [] -> go (x : ys') xs+ ".." : _ -> go (x : ys') xs+ _ : ys -> go ys xs+ _ -> go (x : ys') xs++-- | Convert to the right kind of slashes.+normalisePathSeps :: FilePath -> FilePath+normalisePathSeps p = (\ c -> if isPathSeparator c then pathSeparator else c) <$> p++-- | Remove redundant trailing slashes and pick the right kind of slash.+normaliseTrailingSep :: FilePath -> FilePath+normaliseTrailingSep path = do+ let path' = reverse path+ let (sep, path'') = span isPathSeparator path'+ let addSep = if null sep then id else (pathSeparator :)+ reverse (addSep path'')++-- | Convert empty paths to the current directory, otherwise leave it+-- unchanged.+emptyToCurDir :: FilePath -> FilePath+emptyToCurDir "" = "."+emptyToCurDir path = path+#endif /* mingw32_HOST_OS */++-- | Like `copyFile`, but does not touch the target if source and destination+-- are already byte-identical. This is recommended as it is useful for+-- time-stamp based recompilation avoidance.+copyFileChanged :: FilePath -> FilePath -> IO ()+copyFileChanged src dest = do+ equal <- filesEqual src dest+ unless equal $ copyFile src dest++-- | Checks if two files are byte-identical.+-- Returns False if either of the files do not exist or if files+-- are of different size.+filesEqual :: FilePath -> FilePath -> IO Bool+filesEqual f1 f2 = do+ ex1 <- doesFileExist f1+ ex2 <- doesFileExist f2+ if not (ex1 && ex2) then return False else+ withBinaryFile f1 ReadMode $ \h1 ->+ withBinaryFile f2 ReadMode $ \h2 -> do+ s1 <- hFileSize h1+ s2 <- hFileSize h2+ if s1 /= s2+ then return False+ else do+ c1 <- BSL.hGetContents h1+ c2 <- BSL.hGetContents h2+ return $! c1 == c2
+ src/Distribution/Compat/CreatePipe.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++module Distribution.Compat.CreatePipe (createPipe) where++#if MIN_VERSION_process(1,2,1)+import System.Process (createPipe)+#else+import System.IO (Handle, hSetBinaryMode)++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Compat.Stack++-- The mingw32_HOST_OS CPP macro is GHC-specific+#ifdef mingw32_HOST_OS+import qualified Prelude+import Control.Exception (onException)+import Foreign.C.Error (throwErrnoIfMinus1_)+import Foreign.C.Types (CInt(..), CUInt(..))+import Foreign.Ptr (Ptr)+import Foreign.Marshal.Array (allocaArray)+import Foreign.Storable (peek, peekElemOff)+import GHC.IO.FD (mkFD)+import GHC.IO.Device (IODeviceType(Stream))+import GHC.IO.Handle.FD (mkHandleFromFD)+import System.IO (IOMode(ReadMode, WriteMode))+#elif defined ghcjs_HOST_OS+#else+import System.Posix.IO (fdToHandle)+import qualified System.Posix.IO as Posix+#endif++createPipe :: IO (Handle, Handle)+-- The mingw32_HOST_OS CPP macro is GHC-specific+#ifdef mingw32_HOST_OS+createPipe = do+ (readfd, writefd) <- allocaArray 2 $ \ pfds -> do+ throwErrnoIfMinus1_ "_pipe" $ c__pipe pfds 2 ({- _O_BINARY -} 32768)+ readfd <- peek pfds+ writefd <- peekElemOff pfds 1+ return (readfd, writefd)+ (do readh <- fdToHandle readfd ReadMode+ writeh <- fdToHandle writefd WriteMode+ hSetBinaryMode readh True+ hSetBinaryMode writeh True+ return (readh, writeh)) `onException` (close readfd >> close writefd)+ where+ fdToHandle :: CInt -> IOMode -> IO Handle+ fdToHandle fd mode = do+ (fd', deviceType) <- mkFD fd mode (Just (Stream, 0, 0)) False False+ mkHandleFromFD fd' deviceType "" mode False Nothing++ close :: CInt -> IO ()+ close = throwErrnoIfMinus1_ "_close" . c__close+ where _ = callStack -- TODO: attach call stack to exception++ _ = callStack -- TODO: attach call stack to exceptions++foreign import ccall "io.h _pipe" c__pipe ::+ Ptr CInt -> CUInt -> CInt -> Prelude.IO CInt++foreign import ccall "io.h _close" c__close ::+ CInt -> Prelude.IO CInt+#elif defined ghcjs_HOST_OS+createPipe = error "createPipe"+ where+ _ = callStack+#else+createPipe = do+ (readfd, writefd) <- Posix.createPipe+ readh <- fdToHandle readfd+ writeh <- fdToHandle writefd+ hSetBinaryMode readh True+ hSetBinaryMode writeh True+ return (readh, writeh)+ where+ _ = callStack+#endif+#endif
+ src/Distribution/Compat/DList.hs view
@@ -0,0 +1,53 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.DList+-- Copyright : (c) Ben Gamari 2015-2019+-- License : BSD3+--+-- Maintainer : cabal-dev@haskell.org+-- Stability : experimental+-- Portability : portable+--+-- A very simple difference list.+module Distribution.Compat.DList (+ DList,+ runDList,+ empty,+ singleton,+ fromList,+ toList,+ snoc,+) where++import Prelude ()+import Distribution.Compat.Prelude hiding (toList, empty)++-- | Difference list.+newtype DList a = DList ([a] -> [a])++runDList :: DList a -> [a]+runDList (DList run) = run []++-- | Make 'DList' containing single element.+singleton :: a -> DList a+singleton a = DList (a:)++-- | @since 3.4.0.0+empty :: DList a+empty = DList id++fromList :: [a] -> DList a+fromList as = DList (as ++)++toList :: DList a -> [a]+toList = runDList++snoc :: DList a -> a -> DList a+snoc xs x = xs <> singleton x++instance Monoid (DList a) where+ mempty = empty+ mappend = (<>)++instance Semigroup (DList a) where+ DList a <> DList b = DList (a . b)
+ src/Distribution/Compat/Directory.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE CPP #-}++module Distribution.Compat.Directory+( listDirectory+, makeAbsolute+, doesPathExist+) where++#if MIN_VERSION_directory(1,2,7)+import System.Directory as Dir hiding (doesPathExist)+import System.Directory (doesPathExist)+#else+import System.Directory as Dir+#endif+#if !MIN_VERSION_directory(1,2,2)+import System.FilePath as Path+#endif++#if !MIN_VERSION_directory(1,2,5)++listDirectory :: FilePath -> IO [FilePath]+listDirectory path =+ filter f `fmap` Dir.getDirectoryContents path+ where f filename = filename /= "." && filename /= ".."++#endif++#if !MIN_VERSION_directory(1,2,2)++makeAbsolute :: FilePath -> IO FilePath+makeAbsolute p | Path.isAbsolute p = return p+ | otherwise = do+ cwd <- Dir.getCurrentDirectory+ return $ cwd </> p++#endif++#if !MIN_VERSION_directory(1,2,7)++doesPathExist :: FilePath -> IO Bool+doesPathExist path = do+ -- not using Applicative, as this way we can do less IO+ e <- doesDirectoryExist path+ if e+ then return True+ else doesFileExist path++#endif+
+ src/Distribution/Compat/Environment.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# OPTIONS_HADDOCK hide #-}++module Distribution.Compat.Environment+ ( getEnvironment, lookupEnv, setEnv, unsetEnv )+ where++import Prelude ()+import qualified Prelude+import Distribution.Compat.Prelude++#ifndef mingw32_HOST_OS+#if __GLASGOW_HASKELL__ < 708+import Foreign.C.Error (throwErrnoIf_)+#endif+#endif++import qualified System.Environment as System+import System.Environment (lookupEnv)+#if __GLASGOW_HASKELL__ >= 708+import System.Environment (unsetEnv)+#endif++import Distribution.Compat.Stack++#ifdef mingw32_HOST_OS+import Foreign.C+#if __GLASGOW_HASKELL__ < 708+import Foreign.Ptr (nullPtr)+#endif+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+-- On Windows, the names of environment variables are case-insensitive, but are+-- often given in mixed-case (e.g. "PATH" is "Path"), so we have to normalise+-- them.+getEnvironment = fmap upcaseVars System.getEnvironment+ where+ upcaseVars = map upcaseVar+ upcaseVar (var, val) = (map toUpper var, val)+#else+getEnvironment = System.getEnvironment+#endif++-- | @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_ = 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")+ where+ _ = callStack -- TODO: attach CallStack to exception++# 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 -> Prelude.IO Bool+#else+setEnv_ key value = do+ withFilePath key $ \ keyP ->+ withFilePath value $ \ valueP ->+ throwErrnoIfMinus1_ "setenv" $+ c_setenv keyP valueP (fromIntegral (fromEnum True))+ where+ _ = callStack -- TODO: attach CallStack to exception++foreign import ccall unsafe "setenv"+ c_setenv :: CString -> CString -> CInt -> Prelude.IO CInt+#endif /* mingw32_HOST_OS */++#if __GLASGOW_HASKELL__ < 708++-- | @unsetEnv name@ removes the specified environment variable from the+-- environment of the current process.+--+-- Throws `Control.Exception.IOException` if @name@ is the empty string or+-- contains an equals sign.+--+-- @since 4.7.0.0+unsetEnv :: String -> IO ()+#ifdef mingw32_HOST_OS+unsetEnv key = withCWString key $ \k -> do+ success <- c_SetEnvironmentVariable k nullPtr+ unless success $ do+ -- We consider unsetting an environment variable that does not exist not as+ -- an error, hence we ignore eRROR_ENVVAR_NOT_FOUND.+ err <- c_GetLastError+ unless (err == eRROR_ENVVAR_NOT_FOUND) $ do+ throwGetLastError "unsetEnv"++eRROR_ENVVAR_NOT_FOUND :: DWORD+eRROR_ENVVAR_NOT_FOUND = 203++foreign import WINDOWS_CCONV unsafe "windows.h GetLastError"+ c_GetLastError:: IO DWORD+#else+unsetEnv key = withFilePath key (throwErrnoIf_ (/= 0) "unsetEnv" . c_unsetenv)+#if __GLASGOW_HASKELL__ > 706+foreign import ccall unsafe "__hsbase_unsetenv" c_unsetenv :: CString -> Prelude.IO CInt+#else+-- HACK: We hope very hard that !UNSETENV_RETURNS_VOID+foreign import ccall unsafe "unsetenv" c_unsetenv :: CString -> Prelude.IO CInt+#endif+#endif++#endif
+ src/Distribution/Compat/Exception.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE CPP #-}+module Distribution.Compat.Exception (+ catchIO,+ catchExit,+ tryIO,+ displayException,+ ) where++#ifdef MIN_VERSION_base+#define MINVER_base_48 MIN_VERSION_base(4,8,0)+#else+#define MINVER_base_48 (__GLASGOW_HASKELL__ >= 710)+#endif++import System.Exit+import qualified Control.Exception as Exception++#if MINVER_base_48+import Control.Exception (displayException)+#endif++-- | Try 'IOException'.+tryIO :: IO a -> IO (Either Exception.IOException a)+tryIO = Exception.try++-- | Catch 'IOException'.+catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a+catchIO = Exception.catch++-- | Catch 'ExitCode'+catchExit :: IO a -> (ExitCode -> IO a) -> IO a+catchExit = Exception.catch++#if !MINVER_base_48+displayException :: Exception.Exception e => e -> String+displayException = show+#endif
+ src/Distribution/Compat/FilePath.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE CPP #-}++{-# OPTIONS_GHC -fno-warn-unused-imports #-}++module Distribution.Compat.FilePath+( isExtensionOf+, stripExtension+) where++import Data.List ( isSuffixOf, stripPrefix )+import System.FilePath++#if !MIN_VERSION_filepath(1,4,2)+isExtensionOf :: String -> FilePath -> Bool+isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions+isExtensionOf ext = isSuffixOf ('.':ext) . takeExtensions+#endif++#if !MIN_VERSION_filepath(1,4,1)+stripExtension :: String -> FilePath -> Maybe FilePath+stripExtension [] path = Just path+stripExtension ext@(x:_) path = stripSuffix dotExt path+ where+ dotExt = if isExtSeparator x then ext else '.':ext+ stripSuffix :: Eq a => [a] -> [a] -> Maybe [a]+ stripSuffix xs ys = fmap reverse $ stripPrefix (reverse xs) (reverse ys)+#endif
+ src/Distribution/Compat/GetShortPathName.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE CPP #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.GetShortPathName+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : Windows-only+--+-- Win32 API 'GetShortPathName' function.++module Distribution.Compat.GetShortPathName ( getShortPathName )+ where++import Prelude ()+import Distribution.Compat.Prelude++#ifdef mingw32_HOST_OS++import qualified Prelude+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 -> Prelude.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.+--+-- From MS's GetShortPathName docs:+--+-- Passing NULL for [the second] parameter and zero for cchBuffer+-- will always return the required buffer size for a+-- specified lpszLongPath.+--+getShortPathName :: FilePath -> IO FilePath+getShortPathName path =+ Win32.withTString path $ \c_path -> do+ c_len <- Win32.failIfZero "GetShortPathName #1 failed!" $+ c_GetShortPathName c_path Win32.nullPtr 0+ let arr_len = fromIntegral c_len+ allocaArray arr_len $ \c_out -> do+ void $ Win32.failIfZero "GetShortPathName #2 failed!" $+ c_GetShortPathName c_path c_out c_len+ Win32.peekTString c_out++#else++getShortPathName :: FilePath -> IO FilePath+getShortPathName path = return path++#endif
+ src/Distribution/Compat/Graph.hs view
@@ -0,0 +1,408 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.Graph+-- Copyright : (c) Edward Z. Yang 2016+-- License : BSD3+--+-- Maintainer : cabal-dev@haskell.org+-- Stability : experimental+-- Portability : portable+--+-- A data type representing directed graphs, backed by "Data.Graph".+-- It is strict in the node type.+--+-- This is an alternative interface to "Data.Graph". In this interface,+-- nodes (identified by the 'IsNode' type class) are associated with a+-- key and record the keys of their neighbors. This interface is more+-- convenient than 'Data.Graph.Graph', which requires vertices to be+-- explicitly handled by integer indexes.+--+-- The current implementation has somewhat peculiar performance+-- characteristics. The asymptotics of all map-like operations mirror+-- their counterparts in "Data.Map". However, to perform a graph+-- operation, we first must build the "Data.Graph" representation, an+-- operation that takes /O(V + E log V)/. However, this operation can+-- be amortized across all queries on that particular graph.+--+-- Some nodes may be broken, i.e., refer to neighbors which are not+-- stored in the graph. In our graph algorithms, we transparently+-- ignore such edges; however, you can easily query for the broken+-- vertices of a graph using 'broken' (and should, e.g., to ensure that+-- a closure of a graph is well-formed.) It's possible to take a closed+-- subset of a broken graph and get a well-formed graph.+--+-----------------------------------------------------------------------------++module Distribution.Compat.Graph (+ -- * Graph type+ Graph,+ IsNode(..),+ -- * Query+ null,+ size,+ member,+ lookup,+ -- * Construction+ empty,+ insert,+ deleteKey,+ deleteLookup,+ -- * Combine+ unionLeft,+ unionRight,+ -- * Graph algorithms+ stronglyConnComp,+ SCC(..),+ cycles,+ broken,+ neighbors,+ revNeighbors,+ closure,+ revClosure,+ topSort,+ revTopSort,+ -- * Conversions+ -- ** Maps+ toMap,+ -- ** Lists+ fromDistinctList,+ toList,+ keys,+ -- ** Sets+ keysSet,+ -- ** Graphs+ toGraph,+ -- * Node type+ Node(..),+ nodeValue,+) where++import Distribution.Compat.Prelude hiding (empty, lookup, null, toList)+import Prelude ()++import Data.Array ((!))+import Data.Graph (SCC (..))+import Distribution.Utils.Structured (Structure (..), Structured (..))++import qualified Data.Array as Array+import qualified Data.Foldable as Foldable+import qualified Data.Graph as G+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import qualified Data.Tree as Tree+import qualified Distribution.Compat.Prelude as Prelude++-- | A graph of nodes @a@. The nodes are expected to have instance+-- of class 'IsNode'.+data Graph a+ = Graph {+ graphMap :: !(Map (Key a) a),+ -- Lazily cached graph representation+ graphForward :: G.Graph,+ graphAdjoint :: G.Graph,+ graphVertexToNode :: G.Vertex -> a,+ graphKeyToVertex :: Key a -> Maybe G.Vertex,+ graphBroken :: [(a, [Key a])]+ }+ deriving (Typeable)++-- NB: Not a Functor! (or Traversable), because you need+-- to restrict Key a ~ Key b. We provide our own mapping+-- functions.++-- General strategy is most operations are deferred to the+-- Map representation.++instance Show a => Show (Graph a) where+ show = show . toList++instance (IsNode a, Read a, Show (Key a)) => Read (Graph a) where+ readsPrec d s = map (\(a,r) -> (fromDistinctList a, r)) (readsPrec d s)++instance (IsNode a, Binary a, Show (Key a)) => Binary (Graph a) where+ put x = put (toList x)+ get = fmap fromDistinctList get++instance Structured a => Structured (Graph a) where+ structure p = Nominal (typeRep p) 0 "Graph" [structure (Proxy :: Proxy a)]++instance (Eq (Key a), Eq a) => Eq (Graph a) where+ g1 == g2 = graphMap g1 == graphMap g2++instance Foldable.Foldable Graph where+ fold = Foldable.fold . graphMap+ foldr f z = Foldable.foldr f z . graphMap+ foldl f z = Foldable.foldl f z . graphMap+ foldMap f = Foldable.foldMap f . graphMap+ foldl' f z = Foldable.foldl' f z . graphMap+ foldr' f z = Foldable.foldr' f z . graphMap+#ifdef MIN_VERSION_base+#if MIN_VERSION_base(4,8,0)+ length = Foldable.length . graphMap+ null = Foldable.null . graphMap+ toList = Foldable.toList . graphMap+ elem x = Foldable.elem x . graphMap+ maximum = Foldable.maximum . graphMap+ minimum = Foldable.minimum . graphMap+ sum = Foldable.sum . graphMap+ product = Foldable.product . graphMap+#endif+#endif++instance (NFData a, NFData (Key a)) => NFData (Graph a) where+ rnf Graph {+ graphMap = m,+ graphForward = gf,+ graphAdjoint = ga,+ graphVertexToNode = vtn,+ graphKeyToVertex = ktv,+ graphBroken = b+ } = gf `seq` ga `seq` vtn `seq` ktv `seq` b `seq` rnf m++-- TODO: Data instance?++-- | The 'IsNode' class is used for datatypes which represent directed+-- graph nodes. A node of type @a@ is associated with some unique key of+-- type @'Key' a@; given a node we can determine its key ('nodeKey')+-- and the keys of its neighbors ('nodeNeighbors').+class Ord (Key a) => IsNode a where+ type Key a+ nodeKey :: a -> Key a+ nodeNeighbors :: a -> [Key a]++instance (IsNode a, IsNode b, Key a ~ Key b) => IsNode (Either a b) where+ type Key (Either a b) = Key a+ nodeKey (Left x) = nodeKey x+ nodeKey (Right x) = nodeKey x+ nodeNeighbors (Left x) = nodeNeighbors x+ nodeNeighbors (Right x) = nodeNeighbors x++-- | A simple, trivial data type which admits an 'IsNode' instance.+data Node k a = N a k [k]+ deriving (Show, Eq)++-- | Get the value from a 'Node'.+nodeValue :: Node k a -> a+nodeValue (N a _ _) = a++instance Functor (Node k) where+ fmap f (N a k ks) = N (f a) k ks++instance Ord k => IsNode (Node k a) where+ type Key (Node k a) = k+ nodeKey (N _ k _) = k+ nodeNeighbors (N _ _ ks) = ks++-- TODO: Maybe introduce a typeclass for items which just+-- keys (so, Key associated type, and nodeKey method). But+-- I didn't need it here, so I didn't introduce it.++-- Query++-- | /O(1)/. Is the graph empty?+null :: Graph a -> Bool+null = Map.null . toMap++-- | /O(1)/. The number of nodes in the graph.+size :: Graph a -> Int+size = Map.size . toMap++-- | /O(log V)/. Check if the key is in the graph.+member :: IsNode a => Key a -> Graph a -> Bool+member k g = Map.member k (toMap g)++-- | /O(log V)/. Lookup the node at a key in the graph.+lookup :: IsNode a => Key a -> Graph a -> Maybe a+lookup k g = Map.lookup k (toMap g)++-- Construction++-- | /O(1)/. The empty graph.+empty :: IsNode a => Graph a+empty = fromMap Map.empty++-- | /O(log V)/. Insert a node into a graph.+insert :: IsNode a => a -> Graph a -> Graph a+insert !n g = fromMap (Map.insert (nodeKey n) n (toMap g))++-- | /O(log V)/. Delete the node at a key from the graph.+deleteKey :: IsNode a => Key a -> Graph a -> Graph a+deleteKey k g = fromMap (Map.delete k (toMap g))++-- | /O(log V)/. Lookup and delete. This function returns the deleted+-- value if it existed.+deleteLookup :: IsNode a => Key a -> Graph a -> (Maybe a, Graph a)+deleteLookup k g =+ let (r, m') = Map.updateLookupWithKey (\_ _ -> Nothing) k (toMap g)+ in (r, fromMap m')++-- Combining++-- | /O(V + V')/. Right-biased union, preferring entries+-- from the second map when conflicts occur.+-- @'nodeKey' x = 'nodeKey' (f x)@.+unionRight :: IsNode a => Graph a -> Graph a -> Graph a+unionRight g g' = fromMap (Map.union (toMap g') (toMap g))++-- | /O(V + V')/. Left-biased union, preferring entries from+-- the first map when conflicts occur.+unionLeft :: IsNode a => Graph a -> Graph a -> Graph a+unionLeft = flip unionRight++-- Graph-like operations++-- | /Ω(V + E)/. Compute the strongly connected components of a graph.+-- Requires amortized construction of graph.+stronglyConnComp :: Graph a -> [SCC a]+stronglyConnComp g = map decode forest+ where+ forest = G.scc (graphForward g)+ decode (Tree.Node v [])+ | mentions_itself v = CyclicSCC [graphVertexToNode g v]+ | otherwise = AcyclicSCC (graphVertexToNode g v)+ decode other = CyclicSCC (dec other [])+ where dec (Tree.Node v ts) vs+ = graphVertexToNode g v : foldr dec vs ts+ mentions_itself v = v `elem` (graphForward g ! v)+-- Implementation copied from 'stronglyConnCompR' in 'Data.Graph'.++-- | /Ω(V + E)/. Compute the cycles of a graph.+-- Requires amortized construction of graph.+cycles :: Graph a -> [[a]]+cycles g = [ vs | CyclicSCC vs <- stronglyConnComp g ]++-- | /O(1)/. Return a list of nodes paired with their broken+-- neighbors (i.e., neighbor keys which are not in the graph).+-- Requires amortized construction of graph.+broken :: Graph a -> [(a, [Key a])]+broken g = graphBroken g++-- | Lookup the immediate neighbors from a key in the graph.+-- Requires amortized construction of graph.+neighbors :: Graph a -> Key a -> Maybe [a]+neighbors g k = do+ v <- graphKeyToVertex g k+ return (map (graphVertexToNode g) (graphForward g ! v))++-- | Lookup the immediate reverse neighbors from a key in the graph.+-- Requires amortized construction of graph.+revNeighbors :: Graph a -> Key a -> Maybe [a]+revNeighbors g k = do+ v <- graphKeyToVertex g k+ return (map (graphVertexToNode g) (graphAdjoint g ! v))++-- | Compute the subgraph which is the closure of some set of keys.+-- Returns @Nothing@ if one (or more) keys are not present in+-- the graph.+-- Requires amortized construction of graph.+closure :: Graph a -> [Key a] -> Maybe [a]+closure g ks = do+ vs <- traverse (graphKeyToVertex g) ks+ return (decodeVertexForest g (G.dfs (graphForward g) vs))++-- | Compute the reverse closure of a graph from some set+-- of keys. Returns @Nothing@ if one (or more) keys are not present in+-- the graph.+-- Requires amortized construction of graph.+revClosure :: Graph a -> [Key a] -> Maybe [a]+revClosure g ks = do+ vs <- traverse (graphKeyToVertex g) ks+ return (decodeVertexForest g (G.dfs (graphAdjoint g) vs))++flattenForest :: Tree.Forest a -> [a]+flattenForest = concatMap Tree.flatten++decodeVertexForest :: Graph a -> Tree.Forest G.Vertex -> [a]+decodeVertexForest g = map (graphVertexToNode g) . flattenForest++-- | Topologically sort the nodes of a graph.+-- Requires amortized construction of graph.+topSort :: Graph a -> [a]+topSort g = map (graphVertexToNode g) $ G.topSort (graphForward g)++-- | Reverse topologically sort the nodes of a graph.+-- Requires amortized construction of graph.+revTopSort :: Graph a -> [a]+revTopSort g = map (graphVertexToNode g) $ G.topSort (graphAdjoint g)++-- Conversions++-- | /O(1)/. Convert a map from keys to nodes into a graph.+-- The map must satisfy the invariant that+-- @'fromMap' m == 'fromList' ('Data.Map.elems' m)@;+-- if you can't fulfill this invariant use @'fromList' ('Data.Map.elems' m)@+-- instead. The values of the map are assumed to already+-- be in WHNF.+fromMap :: IsNode a => Map (Key a) a -> Graph a+fromMap m+ = Graph { graphMap = m+ -- These are lazily computed!+ , graphForward = g+ , graphAdjoint = G.transposeG g+ , graphVertexToNode = vertex_to_node+ , graphKeyToVertex = key_to_vertex+ , graphBroken = broke+ }+ where+ try_key_to_vertex k = maybe (Left k) Right (key_to_vertex k)++ (brokenEdges, edges)+ = unzip+ $ [ partitionEithers (map try_key_to_vertex (nodeNeighbors n))+ | n <- ns ]+ broke = filter (not . Prelude.null . snd) (zip ns brokenEdges)++ g = Array.listArray bounds edges++ ns = Map.elems m -- sorted ascending+ vertices = zip (map nodeKey ns) [0..]+ vertex_map = Map.fromAscList vertices+ key_to_vertex k = Map.lookup k vertex_map++ vertex_to_node vertex = nodeTable ! vertex++ nodeTable = Array.listArray bounds ns+ bounds = (0, Map.size m - 1)++-- | /O(V log V)/. Convert a list of nodes (with distinct keys) into a graph.+fromDistinctList :: (IsNode a, Show (Key a)) => [a] -> Graph a+fromDistinctList = fromMap+ . Map.fromListWith (\_ -> duplicateError)+ . map (\n -> n `seq` (nodeKey n, n))+ where+ duplicateError n = error $ "Graph.fromDistinctList: duplicate key: "+ ++ show (nodeKey n)++-- Map-like operations++-- | /O(V)/. Convert a graph into a list of nodes.+toList :: Graph a -> [a]+toList g = Map.elems (toMap g)++-- | /O(V)/. Convert a graph into a list of keys.+keys :: Graph a -> [Key a]+keys g = Map.keys (toMap g)++-- | /O(V)/. Convert a graph into a set of keys.+keysSet :: Graph a -> Set.Set (Key a)+keysSet g = Map.keysSet (toMap g)++-- | /O(1)/. Convert a graph into a map from keys to nodes.+-- The resulting map @m@ is guaranteed to have the property that+-- @'Prelude.all' (\(k,n) -> k == 'nodeKey' n) ('Data.Map.toList' m)@.+toMap :: Graph a -> Map (Key a) a+toMap = graphMap++-- Graph-like operations++-- | /O(1)/. Convert a graph into a 'Data.Graph.Graph'.+-- Requires amortized construction of graph.+toGraph :: Graph a -> (G.Graph, G.Vertex -> a, Key a -> Maybe G.Vertex)+toGraph g = (graphForward g, graphVertexToNode g, graphKeyToVertex g)
+ src/Distribution/Compat/Internal/TempFile.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_HADDOCK hide #-}+module Distribution.Compat.Internal.TempFile (+ openTempFile,+ openBinaryTempFile,+ openNewBinaryFile,+ createTempDirectory,+ ) where++import Distribution.Compat.Exception++import System.FilePath ((</>))++import System.IO (Handle, openTempFile, openBinaryTempFile)+#if defined(__IO_MANAGER_WINIO__)+import System.IO (openBinaryTempFileWithDefaultPermissions)+#else+import Control.Exception (onException)+import Data.Bits ((.|.))+import Foreign.C (CInt, eEXIST, getErrno, errnoToIOError)+import GHC.IO.Handle.FD (fdToHandle)+import System.Posix.Internals (c_open, c_close, o_EXCL, o_BINARY, withFilePath,+ o_CREAT, o_RDWR, o_NONBLOCK, o_NOCTTY)+#endif++import System.Posix.Internals (c_getpid)+import System.IO.Error (isAlreadyExistsError)++#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: This file should probably be removed.++-- This is a copy/paste of the openBinaryTempFile definition, but+-- it uses 666 rather than 600 for the permissions. Newer versions+-- of base have a new function with this behavior which we use on+-- Windows when the new IO manager is used.+openNewBinaryFile :: FilePath -> String -> IO (FilePath, Handle)+openNewBinaryFile dir template = do+ -- This method can't be used under WINIO. Also the current implementation has+ -- thread safety issues depending on which GHC is used. On newer GHC's let's+ -- use the built in one.+#if defined(__IO_MANAGER_WINIO__)+ openBinaryTempFileWithDefaultPermissions dir template+#else+ 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: 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++-- FIXME: Should use System.FilePath library+pathSeparator :: Char+#ifdef mingw32_HOST_OS+pathSeparator = '\\'+#else+pathSeparator = '/'+#endif+-- /* __IO_MANAGER_WINIO__ */+#endif++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
+ src/Distribution/Compat/Lens.hs view
@@ -0,0 +1,262 @@+{-# LANGUAGE RankNTypes #-}+-- | This module provides very basic lens functionality, without extra dependencies.+--+-- For the documentation of the combinators see <http://hackage.haskell.org/package/lens lens> package.+-- This module uses the same vocabulary.+module Distribution.Compat.Lens (+ -- * Types+ Lens,+ Lens',+ Traversal,+ Traversal',+ -- ** LensLike+ LensLike,+ LensLike',+ -- ** rank-1 types+ Getting,+ AGetter,+ ASetter,+ ALens,+ ALens',+ -- * Getter+ view,+ use,+ getting,+ -- * Setter+ set,+ over,+ -- * Fold+ toDListOf,+ toListOf,+ toSetOf,+ -- * Lens+ cloneLens,+ aview,+ -- * Common lenses+ _1, _2,+ -- * Operators+ (&),+ (^.),+ (.~), (?~), (%~),+ (.=), (?=), (%=),+ (^#),+ (#~), (#%~),+ -- * Internal Comonads+ Pretext (..),+ -- * Cabal developer info+ -- $development+ ) where++import Prelude()+import Distribution.Compat.Prelude++import Control.Monad.State.Class (MonadState (..), gets, modify)++import qualified Distribution.Compat.DList as DList+import qualified Data.Set as Set++-------------------------------------------------------------------------------+-- Types+-------------------------------------------------------------------------------++type LensLike f s t a b = (a -> f b) -> s -> f t+type LensLike' f s a = (a -> f a) -> s -> f s++type Lens s t a b = forall f. Functor f => LensLike f s t a b+type Traversal s t a b = forall f. Applicative f => LensLike f s t a b++type Lens' s a = Lens s s a a+type Traversal' s a = Traversal s s a a++type Getting r s a = LensLike (Const r) s s a a++type AGetter s a = LensLike (Const a) s s a a -- this doesn't exist in 'lens'+type ASetter s t a b = LensLike Identity s t a b+type ALens s t a b = LensLike (Pretext a b) s t a b++type ALens' s a = ALens s s a a++-------------------------------------------------------------------------------+-- Getter+-------------------------------------------------------------------------------++view :: Getting a s a -> s -> a+view l s = getConst (l Const s)+{-# INLINE view #-}++use :: MonadState s m => Getting a s a -> m a+use l = gets (view l)+{-# INLINE use #-}++-- | @since 2.4+--+-- >>> (3 :: Int) ^. getting (+2) . getting show+-- "5"+getting :: (s -> a) -> Getting r s a+getting k f = Const . getConst . f . k+{-# INLINE getting #-}++-------------------------------------------------------------------------------+-- Setter+-------------------------------------------------------------------------------++set :: ASetter s t a b -> b -> s -> t+set l x = over l (const x)++over :: ASetter s t a b -> (a -> b) -> s -> t+over l f s = runIdentity (l (\x -> Identity (f x)) s)++-------------------------------------------------------------------------------+-- Fold+-------------------------------------------------------------------------------++toDListOf :: Getting (DList.DList a) s a -> s -> DList.DList a+toDListOf l s = getConst (l (\x -> Const (DList.singleton x)) s)++toListOf :: Getting (DList.DList a) s a -> s -> [a]+toListOf l = DList.runDList . toDListOf l++toSetOf :: Getting (Set.Set a) s a -> s -> Set.Set a+toSetOf l s = getConst (l (\x -> Const (Set.singleton x)) s)++-------------------------------------------------------------------------------+-- Lens+-------------------------------------------------------------------------------++aview :: ALens s t a b -> s -> a+aview l = pretextPos . l pretextSell+{-# INLINE aview #-}++{-+lens :: (s -> a) -> (s -> a -> s) -> Lens' s a+lens sa sbt afb s = sbt s <$> afb (sa s)+-}++-------------------------------------------------------------------------------+-- Common+-------------------------------------------------------------------------------++_1 :: Lens (a, c) (b, c) a b+_1 f (a, c) = flip (,) c <$> f a++_2 :: Lens (c, a) (c, b) a b+_2 f (c, a) = (,) c <$> f a++-------------------------------------------------------------------------------+-- Operators+-------------------------------------------------------------------------------++-- | '&' is a reverse application operator+(&) :: a -> (a -> b) -> b+(&) = flip ($)+{-# INLINE (&) #-}+infixl 1 &++infixl 8 ^., ^#+infixr 4 .~, %~, ?~+infixr 4 #~, #%~+infixr 4 .=, %=, ?=++(^.) :: s -> Getting a s a -> a+s ^. l = getConst (l Const s)+{-# INLINE (^.) #-}++(.~) :: ASetter s t a b -> b -> s -> t+(.~) = set+{-# INLINE (.~) #-}++(?~) :: ASetter s t a (Maybe b) -> b -> s -> t+l ?~ b = set l (Just b)+{-# INLINE (?~) #-}++(%~) :: ASetter s t a b -> (a -> b) -> s -> t+(%~) = over+{-# INLINE (%~) #-}++(.=) :: MonadState s m => ASetter s s a b -> b -> m ()+l .= b = modify (l .~ b)+{-# INLINE (.=) #-}++(?=) :: MonadState s m => ASetter s s a (Maybe b) -> b -> m ()+l ?= b = modify (l ?~ b)+{-# INLINE (?=) #-}++(%=) :: MonadState s m => ASetter s s a b -> (a -> b) -> m ()+l %= f = modify (l %~ f)+{-# INLINE (%=) #-}++(^#) :: s -> ALens s t a b -> a+s ^# l = aview l s++(#~) :: ALens s t a b -> b -> s -> t+(#~) l b s = pretextPeek b (l pretextSell s)+{-# INLINE (#~) #-}++(#%~) :: ALens s t a b -> (a -> b) -> s -> t+(#%~) l f s = pretextPeeks f (l pretextSell s)+{-# INLINE (#%~) #-}++pretextSell :: a -> Pretext a b b+pretextSell a = Pretext (\afb -> afb a)+{-# INLINE pretextSell #-}++pretextPeeks :: (a -> b) -> Pretext a b t -> t+pretextPeeks f (Pretext m) = runIdentity $ m (\x -> Identity (f x))+{-# INLINE pretextPeeks #-}++pretextPeek :: b -> Pretext a b t -> t+pretextPeek b (Pretext m) = runIdentity $ m (\_ -> Identity b)+{-# INLINE pretextPeek #-}++pretextPos :: Pretext a b t -> a+pretextPos (Pretext m) = getConst (m Const)+{-# INLINE pretextPos #-}++cloneLens :: Functor f => ALens s t a b -> LensLike f s t a b+cloneLens l f s = runPretext (l pretextSell s) f+{-# INLINE cloneLens #-}++-------------------------------------------------------------------------------+-- Comonads+-------------------------------------------------------------------------------++-- | @lens@ variant is also parametrised by profunctor.+data Pretext a b t = Pretext { runPretext :: forall f. Functor f => (a -> f b) -> f t }++instance Functor (Pretext a b) where+ fmap f (Pretext pretext) = Pretext (\afb -> fmap f (pretext afb))++-------------------------------------------------------------------------------+-- Documentation+-------------------------------------------------------------------------------++-- $development+--+-- We cannot depend on @template-haskell@, because Cabal is a boot library.+-- This fact makes defining optics a manual task. Here is a small recipe to+-- make the process less tedious.+--+-- First start a repl+--+-- > cabal new-repl Cabal:hackage-tests+--+-- Because @--extra-package@ isn't yet implemented, we use a test-suite+-- with @generics-sop@ dependency.+--+-- In the repl, we load a helper script:+--+-- > :l ../generics-sop-lens.hs+--+-- Now we are set up to derive lenses!+--+-- > :m +Distribution.Types.SourceRepo+-- > putStr $ genericLenses (Proxy :: Proxy SourceRepo)+--+-- @+-- repoKind :: Lens' SourceRepo RepoKind+-- repoKind f s = fmap (\\x -> s { T.repoKind = x }) (f (T.repoKind s))+-- \{-# INLINE repoKind #-\}+-- ...+-- @+--+-- /Note:/ You may need to adjust type-aliases, e.g. `String` to `FilePath`.
+ src/Distribution/Compat/MonadFail.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE CPP #-}++-- | Compatibility layer for "Control.Monad.Fail"+module Distribution.Compat.MonadFail ( Control.Monad.Fail.MonadFail(fail) ) where+import Control.Monad.Fail
+ src/Distribution/Compat/Newtype.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+-- | Per Conor McBride, the 'Newtype' typeclass represents the packing and+-- unpacking of a newtype, and allows you to operatate under that newtype with+-- functions such as 'ala'.+module Distribution.Compat.Newtype (+ Newtype (..),+ ala,+ alaf,+ pack',+ unpack',+ ) where++import Data.Functor.Identity (Identity (..))+import Data.Monoid (Sum (..), Product (..), Endo (..))++#if MIN_VERSION_base(4,7,0)+import Data.Coerce (coerce, Coercible)+#else+import Unsafe.Coerce (unsafeCoerce)+#endif++-- | The @FunctionalDependencies@ version of 'Newtype' type-class.+--+-- Since Cabal-3.0 class arguments are in a different order than in @newtype@ package.+-- This change is to allow usage with @DeriveAnyClass@ (and @DerivingStrategies@, in GHC-8.2).+-- Unfortunately one has to repeat inner type.+--+-- @+-- newtype New = New Old+-- deriving anyclass (Newtype Old)+-- @+--+-- Another approach would be to use @TypeFamilies@ (and possibly+-- compute inner type using "GHC.Generics"), but we think @FunctionalDependencies@+-- version gives cleaner type signatures.+--+class Newtype o n | n -> o where+ pack :: o -> n+#if MIN_VERSION_base(4,7,0)+ default pack :: Coercible o n => o -> n+ pack = coerce+#else+ default pack :: o -> n+ pack = unsafeCoerce+#endif++ unpack :: n -> o+#if MIN_VERSION_base(4,7,0)+ default unpack :: Coercible n o => n -> o+ unpack = coerce+#else+ default unpack :: n -> o+ unpack = unsafeCoerce+#endif++instance Newtype a (Identity a)+instance Newtype a (Sum a)+instance Newtype a (Product a)+instance Newtype (a -> a) (Endo a)++-- |+--+-- >>> ala Sum foldMap [1, 2, 3, 4 :: Int]+-- 10+--+-- /Note:/ the user supplied function for the newtype is /ignored/.+--+-- >>> ala (Sum . (+1)) foldMap [1, 2, 3, 4 :: Int]+-- 10+ala :: (Newtype o n, Newtype o' n') => (o -> n) -> ((o -> n) -> b -> n') -> (b -> o')+ala pa hof = alaf pa hof id++-- |+--+-- >>> alaf Sum foldMap length ["cabal", "install"]+-- 12+--+-- /Note:/ as with 'ala', the user supplied function for the newtype is /ignored/.+alaf :: (Newtype o n, Newtype o' n') => (o -> n) -> ((a -> n) -> b -> n') -> (a -> o) -> (b -> o')+alaf _ hof f = unpack . hof (pack . f)++-- | Variant of 'pack', which takes a phantom type.+pack' :: Newtype o n => (o -> n) -> o -> n+pack' _ = pack++-- | Variant of 'unpack', which takes a phantom type.+unpack' :: Newtype o n => (o -> n) -> n -> o+unpack' _ = unpack
+ src/Distribution/Compat/NonEmptySet.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+module Distribution.Compat.NonEmptySet (+ NonEmptySet,+ -- * Construction+ singleton,+ -- * Insertion+ insert,+ -- * Deletion+ delete,+ -- * Conversions+ toNonEmpty,+ fromNonEmpty,+ toList,+ toSet,+ -- * Query+ member,+ -- * Map+ map,+) where++import Prelude (Bool (..), Eq, Maybe (..), Ord (..), Read, Show (..), String, error, otherwise, return, showParen, showString, ($), (++), (.))++import Control.DeepSeq (NFData (..))+import Data.Data (Data)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Semigroup (Semigroup (..))+import Data.Typeable (Typeable)++import qualified Data.Foldable as F+import qualified Data.Set as Set++import Distribution.Compat.Binary (Binary (..))+import Distribution.Utils.Structured++#if MIN_VERSION_binary(0,6,0)+import Control.Applicative (empty)+#else+import Control.Monad (fail)+#endif++-- | @since 3.4.0.0+newtype NonEmptySet a = NES (Set.Set a)+ deriving (Eq, Ord, Typeable, Data, Read)++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++instance Show a => Show (NonEmptySet a) where+ showsPrec d s = showParen (d > 10)+ $ showString "fromNonEmpty "+ . showsPrec 11 (toNonEmpty s)++instance Binary a => Binary (NonEmptySet a) where+ put (NES s) = put s+ get = do+ xs <- get+ if Set.null xs+#if MIN_VERSION_binary(0,6,0)+ then empty+#else+ then fail "NonEmptySet: empty"+#endif+ else return (NES xs)++instance Structured a => Structured (NonEmptySet a) where+ structure = containerStructure++instance NFData a => NFData (NonEmptySet a) where+ rnf (NES x) = rnf x++-- | Note: there aren't @Monoid@ instance.+instance Ord a => Semigroup (NonEmptySet a) where+ NES x <> NES y = NES (Set.union x y)++instance F.Foldable NonEmptySet where+ foldMap f (NES s) = F.foldMap f s+ foldr f z (NES s) = F.foldr f z s++#if MIN_VERSION_base(4,8,0)+ toList = toList+ null _ = False+ length (NES s) = F.length s+#endif++-------------------------------------------------------------------------------+-- Constructors+-------------------------------------------------------------------------------++singleton :: a -> NonEmptySet a+singleton = NES . Set.singleton++-------------------------------------------------------------------------------+-- Insertion+-------------------------------------------------------------------------------++insert :: Ord a => a -> NonEmptySet a -> NonEmptySet a+insert x (NES xs) = NES (Set.insert x xs)++-------------------------------------------------------------------------------+-- Deletion+-------------------------------------------------------------------------------++delete :: Ord a => a -> NonEmptySet a -> Maybe (NonEmptySet a)+delete x (NES xs)+ | Set.null res = Nothing+ | otherwise = Just (NES xs)+ where+ res = Set.delete x xs++-------------------------------------------------------------------------------+-- Conversions+-------------------------------------------------------------------------------++fromNonEmpty :: Ord a => NonEmpty a -> NonEmptySet a+fromNonEmpty (x :| xs) = NES (Set.fromList (x : xs))++toNonEmpty :: NonEmptySet a -> NonEmpty a+toNonEmpty (NES s) = case Set.toList s of+ [] -> panic "toNonEmpty"+ x:xs -> x :| xs++toList :: NonEmptySet a -> [a]+toList (NES s) = Set.toList s++toSet :: NonEmptySet a -> Set.Set a+toSet (NES s) = s++-------------------------------------------------------------------------------+-- Query+-------------------------------------------------------------------------------++member :: Ord a => a -> NonEmptySet a -> Bool+member x (NES xs) = Set.member x xs++-------------------------------------------------------------------------------+-- Map+-------------------------------------------------------------------------------++map+ :: ( Ord b+#if !MIN_VERSION_containers(0,5,2)+ , Ord a+#endif+ )+ => (a -> b) -> NonEmptySet a -> NonEmptySet b+map f (NES x) = NES (Set.map f x)++-------------------------------------------------------------------------------+-- Internal+-------------------------------------------------------------------------------++panic :: String -> a+panic msg = error $ "NonEmptySet invariant violated: " ++ msg
+ src/Distribution/Compat/Parsing.hs view
@@ -0,0 +1,362 @@+{-# LANGUAGE GADTs, UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.Parsing+-- Copyright : (c) Edward Kmett 2011-2012+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable+--+-- Alternative parser combinators.+--+-- Originally in @parsers@ package.+--+-----------------------------------------------------------------------------+module Distribution.Compat.Parsing+ (+ -- * Parsing Combinators+ choice+ , option+ , optional -- from Control.Applicative, parsec optionMaybe+ , skipOptional -- parsec optional+ , between+ , some -- from Control.Applicative, parsec many1+ , many -- from Control.Applicative+ , sepBy+ , sepByNonEmpty+ , sepEndByNonEmpty+ , sepEndBy+ , endByNonEmpty+ , endBy+ , count+ , chainl+ , chainr+ , chainl1+ , chainr1+ , manyTill+ -- * Parsing Class+ , Parsing(..)+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Control.Applicative ((<**>), optional)+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.State.Lazy as Lazy+import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Reader (ReaderT (..))+import Control.Monad.Trans.Identity (IdentityT (..))+import Data.Foldable (asum)++import qualified Data.List.NonEmpty as NE+import qualified Text.Parsec as Parsec++-- | @choice ps@ tries to apply the parsers in the list @ps@ in order,+-- until one of them succeeds. Returns the value of the succeeding+-- parser.+choice :: Alternative m => [m a] -> m a+choice = asum+{-# INLINE choice #-}++-- | @option x p@ tries to apply parser @p@. If @p@ fails without+-- consuming input, it returns the value @x@, otherwise the value+-- returned by @p@.+--+-- > priority = option 0 (digitToInt <$> digit)+option :: Alternative m => a -> m a -> m a+option x p = p <|> pure x+{-# INLINE option #-}++-- | @skipOptional p@ tries to apply parser @p@. It will parse @p@ or nothing.+-- It only fails if @p@ fails after consuming input. It discards the result+-- of @p@. (Plays the role of parsec's optional, which conflicts with Applicative's optional)+skipOptional :: Alternative m => m a -> m ()+skipOptional p = (() <$ p) <|> pure ()+{-# INLINE skipOptional #-}++-- | @between open close p@ parses @open@, followed by @p@ and @close@.+-- Returns the value returned by @p@.+--+-- > braces = between (symbol "{") (symbol "}")+between :: Applicative m => m bra -> m ket -> m a -> m a+between bra ket p = bra *> p <* ket+{-# INLINE between #-}++-- | @sepBy p sep@ parses /zero/ or more occurrences of @p@, separated+-- by @sep@. Returns a list of values returned by @p@.+--+-- > commaSep p = p `sepBy` (symbol ",")+sepBy :: Alternative m => m a -> m sep -> m [a]+sepBy p sep = toList <$> sepByNonEmpty p sep <|> pure []+{-# INLINE sepBy #-}++-- | @sepByNonEmpty p sep@ parses /one/ or more occurrences of @p@, separated+-- by @sep@. Returns a non-empty list of values returned by @p@.+sepByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)+sepByNonEmpty p sep = (:|) <$> p <*> many (sep *> p)+{-# INLINE sepByNonEmpty #-}++-- | @sepEndByNonEmpty p sep@ parses /one/ or more occurrences of @p@,+-- separated and optionally ended by @sep@. Returns a non-empty list of values+-- returned by @p@.+sepEndByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)+sepEndByNonEmpty p sep = (:|) <$> p <*> ((sep *> sepEndBy p sep) <|> pure [])++-- | @sepEndBy p sep@ parses /zero/ or more occurrences of @p@,+-- separated and optionally ended by @sep@, ie. haskell style+-- statements. Returns a list of values returned by @p@.+--+-- > haskellStatements = haskellStatement `sepEndBy` semi+sepEndBy :: Alternative m => m a -> m sep -> m [a]+sepEndBy p sep = toList <$> sepEndByNonEmpty p sep <|> pure []+{-# INLINE sepEndBy #-}++-- | @endByNonEmpty p sep@ parses /one/ or more occurrences of @p@, separated+-- and ended by @sep@. Returns a non-empty list of values returned by @p@.+endByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)+endByNonEmpty p sep = NE.some1 (p <* sep)+{-# INLINE endByNonEmpty #-}++-- | @endBy p sep@ parses /zero/ or more occurrences of @p@, separated+-- and ended by @sep@. Returns a list of values returned by @p@.+--+-- > cStatements = cStatement `endBy` semi+endBy :: Alternative m => m a -> m sep -> m [a]+endBy p sep = many (p <* sep)+{-# INLINE endBy #-}++-- | @count n p@ parses @n@ occurrences of @p@. If @n@ is smaller or+-- equal to zero, the parser equals to @return []@. Returns a list of+-- @n@ values returned by @p@.+count :: Applicative m => Int -> m a -> m [a]+count n p | n <= 0 = pure []+ | otherwise = sequenceA (replicate n p)+{-# INLINE count #-}++-- | @chainr p op x@ parses /zero/ or more occurrences of @p@,+-- separated by @op@ Returns a value obtained by a /right/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@. If there are no occurrences of @p@, the value @x@ is+-- returned.+chainr :: Alternative m => m a -> m (a -> a -> a) -> a -> m a+chainr p op x = chainr1 p op <|> pure x+{-# INLINE chainr #-}++-- | @chainl p op x@ parses /zero/ or more occurrences of @p@,+-- separated by @op@. Returns a value obtained by a /left/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@. If there are zero occurrences of @p@, the value @x@ is+-- returned.+chainl :: Alternative m => m a -> m (a -> a -> a) -> a -> m a+chainl p op x = chainl1 p op <|> pure x+{-# INLINE chainl #-}++-- | @chainl1 p op x@ parses /one/ or more occurrences of @p@,+-- separated by @op@ Returns a value obtained by a /left/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@. . This parser can for example be used to eliminate left+-- recursion which typically occurs in expression grammars.+--+-- > expr = term `chainl1` addop+-- > term = factor `chainl1` mulop+-- > factor = parens expr <|> integer+-- >+-- > mulop = (*) <$ symbol "*"+-- > <|> div <$ symbol "/"+-- >+-- > addop = (+) <$ symbol "+"+-- > <|> (-) <$ symbol "-"+chainl1 :: Alternative m => m a -> m (a -> a -> a) -> m a+chainl1 p op = scan where+ scan = p <**> rst+ rst = (\f y g x -> g (f x y)) <$> op <*> p <*> rst <|> pure id+{-# INLINE chainl1 #-}++-- | @chainr1 p op x@ parses /one/ or more occurrences of @p@,+-- separated by @op@ Returns a value obtained by a /right/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@.+chainr1 :: Alternative m => m a -> m (a -> a -> a) -> m a+chainr1 p op = scan where+ scan = p <**> rst+ rst = (flip <$> op <*> scan) <|> pure id+{-# INLINE chainr1 #-}++-- | @manyTill p end@ applies parser @p@ /zero/ or more times until+-- parser @end@ succeeds. Returns the list of values returned by @p@.+-- This parser can be used to scan comments:+--+-- > simpleComment = do{ string "<!--"+-- > ; manyTill anyChar (try (string "-->"))+-- > }+--+-- Note the overlapping parsers @anyChar@ and @string \"-->\"@, and+-- therefore the use of the 'try' combinator.+manyTill :: Alternative m => m a -> m end -> m [a]+manyTill p end = go where go = ([] <$ end) <|> ((:) <$> p <*> go)+{-# INLINE manyTill #-}++infixr 0 <?>++-- | Additional functionality needed to describe parsers independent of input type.+class Alternative m => Parsing m where+ -- | Take a parser that may consume input, and on failure, go back to+ -- where we started and fail as if we didn't consume input.+ try :: m a -> m a++ -- | Give a parser a name+ (<?>) :: m a -> String -> m a++ -- | A version of many that discards its input. Specialized because it+ -- can often be implemented more cheaply.+ skipMany :: m a -> m ()+ skipMany p = () <$ many p+ {-# INLINE skipMany #-}++ -- | @skipSome p@ applies the parser @p@ /one/ or more times, skipping+ -- its result. (aka skipMany1 in parsec)+ skipSome :: m a -> m ()+ skipSome p = p *> skipMany p+ {-# INLINE skipSome #-}++ -- | Used to emit an error on an unexpected token+ unexpected :: String -> m a++ -- | This parser only succeeds at the end of the input. This is not a+ -- primitive parser but it is defined using 'notFollowedBy'.+ --+ -- > eof = notFollowedBy anyChar <?> "end of input"+ eof :: m ()++ -- | @notFollowedBy p@ only succeeds when parser @p@ fails. This parser+ -- does not consume any input. This parser can be used to implement the+ -- \'longest match\' rule. For example, when recognizing keywords (for+ -- example @let@), we want to make sure that a keyword is not followed+ -- by a legal identifier character, in which case the keyword is+ -- actually an identifier (for example @lets@). We can program this+ -- behaviour as follows:+ --+ -- > keywordLet = try $ string "let" <* notFollowedBy alphaNum+ notFollowedBy :: Show a => m a -> m ()++instance (Parsing m, MonadPlus m) => Parsing (Lazy.StateT s m) where+ try (Lazy.StateT m) = Lazy.StateT $ try . m+ {-# INLINE try #-}+ Lazy.StateT m <?> l = Lazy.StateT $ \s -> m s <?> l+ {-# INLINE (<?>) #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (Lazy.StateT m) = Lazy.StateT+ $ \s -> notFollowedBy (fst <$> m s) >> return ((),s)+ {-# INLINE notFollowedBy #-}++instance (Parsing m, MonadPlus m) => Parsing (Strict.StateT s m) where+ try (Strict.StateT m) = Strict.StateT $ try . m+ {-# INLINE try #-}+ Strict.StateT m <?> l = Strict.StateT $ \s -> m s <?> l+ {-# INLINE (<?>) #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (Strict.StateT m) = Strict.StateT+ $ \s -> notFollowedBy (fst <$> m s) >> return ((),s)+ {-# INLINE notFollowedBy #-}++instance (Parsing m, MonadPlus m) => Parsing (ReaderT e m) where+ try (ReaderT m) = ReaderT $ try . m+ {-# INLINE try #-}+ ReaderT m <?> l = ReaderT $ \e -> m e <?> l+ {-# INLINE (<?>) #-}+ skipMany (ReaderT m) = ReaderT $ skipMany . m+ {-# INLINE skipMany #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (ReaderT m) = ReaderT $ notFollowedBy . m+ {-# INLINE notFollowedBy #-}++instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Strict.WriterT w m) where+ try (Strict.WriterT m) = Strict.WriterT $ try m+ {-# INLINE try #-}+ Strict.WriterT m <?> l = Strict.WriterT (m <?> l)+ {-# INLINE (<?>) #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (Strict.WriterT m) = Strict.WriterT+ $ notFollowedBy (fst <$> m) >>= \x -> return (x, mempty)+ {-# INLINE notFollowedBy #-}++instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Lazy.WriterT w m) where+ try (Lazy.WriterT m) = Lazy.WriterT $ try m+ {-# INLINE try #-}+ Lazy.WriterT m <?> l = Lazy.WriterT (m <?> l)+ {-# INLINE (<?>) #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (Lazy.WriterT m) = Lazy.WriterT+ $ notFollowedBy (fst <$> m) >>= \x -> return (x, mempty)+ {-# INLINE notFollowedBy #-}++instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Lazy.RWST r w s m) where+ try (Lazy.RWST m) = Lazy.RWST $ \r s -> try (m r s)+ {-# INLINE try #-}+ Lazy.RWST m <?> l = Lazy.RWST $ \r s -> m r s <?> l+ {-# INLINE (<?>) #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (Lazy.RWST m) = Lazy.RWST+ $ \r s -> notFollowedBy ((\(a,_,_) -> a) <$> m r s) >>= \x -> return (x, s, mempty)+ {-# INLINE notFollowedBy #-}++instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Strict.RWST r w s m) where+ try (Strict.RWST m) = Strict.RWST $ \r s -> try (m r s)+ {-# INLINE try #-}+ Strict.RWST m <?> l = Strict.RWST $ \r s -> m r s <?> l+ {-# INLINE (<?>) #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (Strict.RWST m) = Strict.RWST+ $ \r s -> notFollowedBy ((\(a,_,_) -> a) <$> m r s) >>= \x -> return (x, s, mempty)+ {-# INLINE notFollowedBy #-}++instance (Parsing m, Monad m) => Parsing (IdentityT m) where+ try = IdentityT . try . runIdentityT+ {-# INLINE try #-}+ IdentityT m <?> l = IdentityT (m <?> l)+ {-# INLINE (<?>) #-}+ skipMany = IdentityT . skipMany . runIdentityT+ {-# INLINE skipMany #-}+ unexpected = lift . unexpected+ {-# INLINE unexpected #-}+ eof = lift eof+ {-# INLINE eof #-}+ notFollowedBy (IdentityT m) = IdentityT $ notFollowedBy m+ {-# INLINE notFollowedBy #-}++instance (Parsec.Stream s m t, Show t) => Parsing (Parsec.ParsecT s u m) where+ try = Parsec.try+ (<?>) = (Parsec.<?>)+ skipMany = Parsec.skipMany+ skipSome = Parsec.skipMany1+ unexpected = Parsec.unexpected+ eof = Parsec.eof+ notFollowedBy = Parsec.notFollowedBy
+ src/Distribution/Compat/Prelude.hs view
@@ -0,0 +1,316 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeOperators #-}++#ifdef MIN_VERSION_base+#define MINVER_base_411 MIN_VERSION_base(4,11,0)+#define MINVER_base_48 MIN_VERSION_base(4,8,0)+#define MINVER_base_47 MIN_VERSION_base(4,7,0)+#else+#define MINVER_base_411 (__GLASGOW_HASKELL__ >= 804)+#define MINVER_base_48 (__GLASGOW_HASKELL__ >= 710)+#define MINVER_base_47 (__GLASGOW_HASKELL__ >= 708)+#endif++-- | This module does two things:+--+-- * Acts as a compatibility layer, like @base-compat@.+--+-- * Provides commonly used imports.+module Distribution.Compat.Prelude (+ -- * Prelude+ --+ -- Prelude is re-exported, following is hidden:+ module BasePrelude,++#if !MINVER_base_48+ -- * base 4.8 shim+ Applicative(..), (<$), (<$>),+ Monoid(..),+#endif++ -- * Common type-classes+ Semigroup (..),+ gmappend, gmempty,+ Typeable, TypeRep, typeRep,+ Data,+ Generic,+ NFData (..), genericRnf,+ Binary (..),+ Structured,+ Alternative (..),+ MonadPlus (..),+ IsString (..),++ -- * Some types+ Map,+ Set,+ NonEmptySet,+ Identity (..),+ Proxy (..),+ Const (..),+ Void,++ -- * Data.Either+ partitionEithers,++ -- * Data.Maybe+ catMaybes, mapMaybe,+ fromMaybe,+ maybeToList, listToMaybe,+ isNothing, isJust,++ -- * Data.List+ unfoldr,+ isPrefixOf, isSuffixOf,+ intercalate, intersperse,+ sort, sortBy,+ nub, nubBy,+ partition,++ -- * Data.List.NonEmpty+ NonEmpty((:|)), nonEmpty, foldl1, foldr1,+ head, tail, last, init,++ -- * Data.Foldable+ Foldable, foldMap, foldr,+ null, length,+ find, foldl',+ traverse_, for_,+ any, all,+ toList,++ -- * Data.Traversable+ Traversable, traverse, sequenceA,+ for,++ -- * Data.Function+ on,++ -- * Data.Ord+ comparing,++ -- * Control.Arrow+ first,++ -- * Control.Monad+ liftM, liftM2,+ unless, when,+ ap, void,+ foldM, filterM,+ join, guard,++ -- * Control.Exception+ catch, throwIO, evaluate,+ Exception (..), IOException, SomeException (..),+#if !MINVER_base_48+ displayException,+#endif+ tryIO, catchIO, catchExit,++ -- * Control.DeepSeq+ deepseq, force,++ -- * Data.Char+ isSpace, isDigit, isUpper, isAlpha, isAlphaNum,+ chr, ord,+ toLower, toUpper,++ -- * Data.Void+ absurd, vacuous,++ -- * Data.Word & Data.Int+ Word,+ Word8, Word16, Word32, Word64,+ Int8, Int16, Int32, Int64,++ -- * Text.PrettyPrint+ (<<>>), (Disp.<+>),++ -- * System.Exit+ ExitCode (..),+ exitWith, exitSuccess, exitFailure,++ -- * Text.Read+ readMaybe,++ -- * Debug.Trace (as deprecated functions)+ trace, traceShow, traceShowId,+ ) where++-- We also could hide few partial function+import Prelude as BasePrelude hiding+ ( mapM, mapM_, sequence, null, length, foldr, any, all, head, tail, last, init+ -- partial functions+ , read+ , foldr1, foldl1+#if MINVER_base_411+ -- As of base 4.11.0.0 Prelude exports part of Semigroup(..).+ -- Hide this so we instead rely on Distribution.Compat.Semigroup.+ , Semigroup(..)+#endif+#if MINVER_base_48+ , Word+ -- We hide them, as we import only some members+ , Traversable, traverse, sequenceA+ , Foldable, foldMap+#endif+ )++-- AMP+#if !MINVER_base_48+import Control.Applicative (Applicative (..), (<$), (<$>))+import Data.Foldable (toList)+import Distribution.Compat.Semigroup (Monoid (..))+#else+import Data.Foldable (Foldable (toList), length, null)+#endif++import Data.Foldable (Foldable (foldMap, foldr), all, any, find, foldl', for_, traverse_)+import Data.Traversable (Traversable (sequenceA, traverse), for)++import qualified Data.Foldable++-- Extra exports+import Control.Applicative (Alternative (..))+import Control.Applicative (Const (..))+import Control.Arrow (first)+import Control.DeepSeq (NFData (..), deepseq, force)+import Control.Exception (Exception (..), IOException, SomeException (..), catch, evaluate, throwIO)+import Control.Monad (MonadPlus (..), ap, filterM, foldM, guard, join, liftM, liftM2, unless, void, when)+import Data.Char (chr, isAlpha, isAlphaNum, isDigit, isSpace, isUpper, ord, toLower, toUpper)+import Data.Data (Data)+import Data.Either (partitionEithers)+import Data.Function (on)+import Data.Functor.Identity (Identity (..))+import Data.Int (Int16, Int32, Int64, Int8)+import Data.List (intercalate, intersperse, isPrefixOf, isSuffixOf, nub, nubBy, partition, sort, sortBy, unfoldr)+import Data.List.NonEmpty (NonEmpty ((:|)), nonEmpty, head, init, last, tail)+import Data.Map (Map)+import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, listToMaybe, mapMaybe, maybeToList)+import Data.Ord (comparing)+import Data.Proxy (Proxy (..))+import Data.Set (Set)+import Data.String (IsString (..))+import Data.Void (Void, absurd, vacuous)+import Data.Word (Word, Word16, Word32, Word64, Word8)+import Distribution.Compat.Binary (Binary (..))+import Distribution.Compat.Semigroup (Semigroup (..), gmappend, gmempty)+import Distribution.Compat.Typeable (TypeRep, Typeable, typeRep)+import GHC.Generics ((:*:) ((:*:)), (:+:) (L1, R1), Generic, K1 (unK1), M1 (unM1), Rep (..), U1 (U1), V1)+import System.Exit (ExitCode (..), exitFailure, exitSuccess, exitWith)+import Text.Read (readMaybe)++import qualified Text.PrettyPrint as Disp++import Distribution.Compat.Exception+import Distribution.Compat.NonEmptySet (NonEmptySet)+import Distribution.Utils.Structured (Structured)++import qualified Debug.Trace++-- | New name for 'Text.PrettyPrint.<>'+(<<>>) :: Disp.Doc -> Disp.Doc -> Disp.Doc+(<<>>) = (Disp.<>)++#if !MINVER_base_48+-- | Test whether the structure is empty. The default implementation is+-- optimized for structures that are similar to cons-lists, because there+-- is no general way to do better.+null :: Foldable t => t a -> Bool+null = foldr (\_ _ -> False) True++-- | Returns the size/length of a finite structure as an 'Int'. The+-- default implementation is optimized for structures that are similar to+-- cons-lists, because there is no general way to do better.+length :: Foldable t => t a -> Int+length = foldl' (\c _ -> c+1) 0+#endif+++-- | "GHC.Generics"-based 'rnf' implementation+--+-- This is needed in order to support @deepseq < 1.4@ which didn't+-- have a 'Generic'-based default 'rnf' implementation yet.+--+-- In order to define instances, use e.g.+--+-- > instance NFData MyType where rnf = genericRnf+--+-- The implementation has been taken from @deepseq-1.4.2@'s default+-- 'rnf' implementation.+genericRnf :: (Generic a, GNFData (Rep a)) => a -> ()+genericRnf = grnf . from++-- | Hidden internal type-class+class GNFData f where+ grnf :: f a -> ()++instance GNFData V1 where+ grnf = error "Control.DeepSeq.rnf: uninhabited type"++instance GNFData U1 where+ grnf U1 = ()++instance NFData a => GNFData (K1 i a) where+ grnf = rnf . unK1+ {-# INLINEABLE grnf #-}++instance GNFData a => GNFData (M1 i c a) where+ grnf = grnf . unM1+ {-# INLINEABLE grnf #-}++instance (GNFData a, GNFData b) => GNFData (a :*: b) where+ grnf (x :*: y) = grnf x `seq` grnf y+ {-# INLINEABLE grnf #-}++instance (GNFData a, GNFData b) => GNFData (a :+: b) where+ grnf (L1 x) = grnf x+ grnf (R1 x) = grnf x+ {-# INLINEABLE grnf #-}+++-- TODO: if we want foldr1/foldl1 to work on more than NonEmpty, we+-- can define a local typeclass 'Foldable1', e.g.+--+-- @+-- class Foldable f => Foldable1 f+--+-- instance Foldable1 NonEmpty+--+-- foldr1 :: Foldable1 t => (a -> a -> a) -> t a -> a+-- foldr1 = Data.Foldable.foldr1+--+-- foldl1 :: Foldable1 t => (a -> a -> a) -> t a -> a+-- foldl1 = Data.Foldable.foldl1+-- @+--++{-# INLINE foldr1 #-}+foldr1 :: (a -> a -> a) -> NonEmpty a -> a+foldr1 = Data.Foldable.foldr1++{-# INLINE foldl1 #-}+foldl1 :: (a -> a -> a) -> NonEmpty a -> a+foldl1 = Data.Foldable.foldl1++-------------------------------------------------------------------------------+-- Trace+-------------------------------------------------------------------------------++-- Functions from Debug.Trace+-- but with DEPRECATED pragma, so -Werror will scream on them.++trace :: String -> a -> a+trace = Debug.Trace.trace+{-# DEPRECATED trace "Don't leave me in the code" #-}++traceShowId :: Show a => a -> a+traceShowId x = Debug.Trace.traceShow x x+{-# DEPRECATED traceShowId "Don't leave me in the code" #-}++traceShow :: Show a => a -> b -> b+traceShow = Debug.Trace.traceShow+{-# DEPRECATED traceShow "Don't leave me in the code" #-}
+ src/Distribution/Compat/Prelude/Internal.hs view
@@ -0,0 +1,14 @@+-- | This module re-exports the non-exposed+-- "Distribution.Compat.Prelude" module for+-- reuse by @cabal-install@'s+-- "Distribution.Client.Compat.Prelude" module.+--+-- It is highly discouraged to rely on this module+-- for @Setup.hs@ scripts since its API is /not/+-- stable.+module Distribution.Compat.Prelude.Internal+ {-# WARNING "This modules' API is not stable. Use at your own risk, or better yet, use @base-compat@!" #-}+ ( module Distribution.Compat.Prelude+ ) where++import Distribution.Compat.Prelude
+ src/Distribution/Compat/Process.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE CPP #-}+module Distribution.Compat.Process (+ -- * Redefined functions+ createProcess,+ runInteractiveProcess,+ rawSystem,+ -- * Additions+ enableProcessJobs,+ ) where++import System.Exit (ExitCode (..))+import System.IO (Handle)++import System.Process (CreateProcess, ProcessHandle)+import qualified System.Process as Process++#if MIN_VERSION_process(1,2,0)+import System.Process (waitForProcess)+#endif++-------------------------------------------------------------------------------+-- enableProcessJobs+-------------------------------------------------------------------------------++-- | Enable process jobs to ensure accurate determination of process completion+-- in the presence of @exec(3)@ on Windows.+--+-- Unfortunately the process job support is badly broken in @process@ releases+-- prior to 1.6.9, so we disable it in these versions, despite the fact that+-- this means we may see sporatic build failures without jobs.+enableProcessJobs :: CreateProcess -> CreateProcess+#ifdef MIN_VERSION_process+#if MIN_VERSION_process(1,6,9)+enableProcessJobs cp = cp {Process.use_process_jobs = True}+#else+enableProcessJobs cp = cp+#endif+#else+enableProcessJobs cp = cp+#endif++-------------------------------------------------------------------------------+-- process redefinitions+-------------------------------------------------------------------------------++-- | 'System.Process.createProcess' with process jobs enabled when appropriate.+-- See 'enableProcessJobs'.+createProcess :: CreateProcess+ -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)+createProcess = Process.createProcess . enableProcessJobs++-- | 'System.Process.rawSystem' with process jobs enabled when appropriate.+-- See 'enableProcessJobs'.+rawSystem :: String -> [String] -> IO ExitCode+rawSystem cmd args = do+#if MIN_VERSION_process(1,2,0)+ (_,_,_,p) <- createProcess (Process.proc cmd args) { Process.delegate_ctlc = True }+ waitForProcess p+#else+ -- With very old 'process', just do its rawSystem+ Process.rawSystem cmd args+#endif++-- | 'System.Process.runInteractiveProcess' with process jobs enabled when+-- appropriate. See 'enableProcessJobs'.+runInteractiveProcess+ :: FilePath -- ^ Filename of the executable (see 'RawCommand' for details)+ -> [String] -- ^ Arguments to pass to the executable+ -> Maybe FilePath -- ^ Optional path to the working directory+ -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit)+ -> IO (Handle,Handle,Handle,ProcessHandle)+runInteractiveProcess cmd args mb_cwd mb_env = do+ (mb_in, mb_out, mb_err, p) <-+ createProcess (Process.proc cmd args)+ { Process.std_in = Process.CreatePipe,+ Process.std_out = Process.CreatePipe,+ Process.std_err = Process.CreatePipe,+ Process.env = mb_env,+ Process.cwd = mb_cwd }+ return (fromJust mb_in, fromJust mb_out, fromJust mb_err, p)+ where+ fromJust = maybe (error "runInteractiveProcess: fromJust") id
+ src/Distribution/Compat/ResponseFile.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE CPP, RankNTypes, FlexibleContexts #-}++-- Compatibility layer for GHC.ResponseFile+-- Implementation from base 4.12.0 is used.+-- http://hackage.haskell.org/package/base-4.12.0.0/src/LICENSE+module Distribution.Compat.ResponseFile (expandResponse) where++import Distribution.Compat.Prelude+import Prelude ()++import System.FilePath+import System.IO (hPutStrLn, stderr)+import System.IO.Error++#if MIN_VERSION_base(4,12,0)+import GHC.ResponseFile (unescapeArgs)+#else++unescapeArgs :: String -> [String]+unescapeArgs = filter (not . null) . unescape++data Quoting = NoneQ | SngQ | DblQ++unescape :: String -> [String]+unescape args = reverse . map reverse $ go args NoneQ False [] []+ where+ -- n.b., the order of these cases matters; these are cribbed from gcc+ -- case 1: end of input+ go [] _q _bs a as = a:as+ -- case 2: back-slash escape in progress+ go (c:cs) q True a as = go cs q False (c:a) as+ -- case 3: no back-slash escape in progress, but got a back-slash+ go (c:cs) q False a as+ | '\\' == c = go cs q True a as+ -- case 4: single-quote escaping in progress+ go (c:cs) SngQ False a as+ | '\'' == c = go cs NoneQ False a as+ | otherwise = go cs SngQ False (c:a) as+ -- case 5: double-quote escaping in progress+ go (c:cs) DblQ False a as+ | '"' == c = go cs NoneQ False a as+ | otherwise = go cs DblQ False (c:a) as+ -- case 6: no escaping is in progress+ go (c:cs) NoneQ False a as+ | isSpace c = go cs NoneQ False [] (a:as)+ | '\'' == c = go cs SngQ False a as+ | '"' == c = go cs DblQ False a as+ | otherwise = go cs NoneQ False (c:a) as++#endif++expandResponse :: [String] -> IO [String]+expandResponse = go recursionLimit "."+ where+ recursionLimit = 100++ go :: Int -> FilePath -> [String] -> IO [String]+ go n dir+ | n >= 0 = fmap concat . traverse (expand n dir)+ | otherwise = const $ hPutStrLn stderr "Error: response file recursion limit exceeded." >> exitFailure++ expand :: Int -> FilePath -> String -> IO [String]+ expand n dir arg@('@':f) = readRecursively n (dir </> f) `catchIOError` (const $ print "?" >> return [arg])+ expand _n _dir x = return [x]++ readRecursively :: Int -> FilePath -> IO [String]+ readRecursively n f = go (n - 1) (takeDirectory f) =<< unescapeArgs <$> readFile f
+ src/Distribution/Compat/Semigroup.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeOperators #-}++-- | Compatibility layer for "Data.Semigroup"+module Distribution.Compat.Semigroup+ ( Semigroup((<>))+ , Mon.Monoid(..)+ , All(..)+ , Any(..)++ , First'(..)+ , Last'(..)++ , Option'(..)++ , gmappend+ , gmempty+ ) where++import Distribution.Compat.Binary (Binary)+import Distribution.Utils.Structured (Structured)+import Data.Typeable (Typeable)++import GHC.Generics+-- Data.Semigroup is available since GHC 8.0/base-4.9 in `base`+-- for older GHC/base, it's provided by `semigroups`+import Data.Semigroup+import qualified Data.Monoid as Mon+++-- | A copy of 'Data.Semigroup.First'.+newtype First' a = First' { getFirst' :: a }+ deriving (Eq, Ord, Show)++instance Semigroup (First' a) where+ a <> _ = a++-- | A copy of 'Data.Semigroup.Last'.+newtype Last' a = Last' { getLast' :: a }+ deriving (Eq, Ord, Read, Show, Generic, Binary, Typeable)++instance Structured a => Structured (Last' a)++instance Semigroup (Last' a) where+ _ <> b = b++instance Functor Last' where+ fmap f (Last' x) = Last' (f x)++-- | A wrapper around 'Maybe', providing the 'Semigroup' and 'Monoid' instances+-- implemented for 'Maybe' since @base-4.11@.+newtype Option' a = Option' { getOption' :: Maybe a }+ deriving (Eq, Ord, Read, Show, Binary, Generic, Functor, Typeable)++instance Structured a => Structured (Option' a)++instance Semigroup a => Semigroup (Option' a) where+ Option' (Just a) <> Option' (Just b) = Option' (Just (a <> b))+ Option' Nothing <> b = b+ a <> Option' Nothing = a++instance Semigroup a => Monoid (Option' a) where+ mempty = Option' 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'
+ src/Distribution/Compat/SnocList.hs view
@@ -0,0 +1,33 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compat.SnocList+-- License : BSD3+--+-- Maintainer : cabal-dev@haskell.org+-- Stability : experimental+-- Portability : portable+--+-- A very reversed list. Has efficient `snoc`+module Distribution.Compat.SnocList (+ SnocList,+ runSnocList,+ snoc,+) where++import Prelude ()+import Distribution.Compat.Prelude++newtype SnocList a = SnocList [a]++snoc :: SnocList a -> a -> SnocList a+snoc (SnocList xs) x = SnocList (x : xs)++runSnocList :: SnocList a -> [a]+runSnocList (SnocList xs) = reverse xs++instance Semigroup (SnocList a) where+ SnocList xs <> SnocList ys = SnocList (ys <> xs)++instance Monoid (SnocList a) where+ mempty = SnocList []+ mappend = (<>)
+ src/Distribution/Compat/Stack.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ImplicitParams #-}+module Distribution.Compat.Stack (+ WithCallStack,+ CallStack,+ annotateCallStackIO,+ withFrozenCallStack,+ withLexicalCallStack,+ callStack,+ prettyCallStack,+ parentSrcLocPrefix+) where++import System.IO.Error++#ifdef MIN_VERSION_base+#if MIN_VERSION_base(4,8,1)+#define GHC_STACK_SUPPORTED 1+#endif+#endif++#ifdef GHC_STACK_SUPPORTED+import GHC.Stack+#endif++#ifdef GHC_STACK_SUPPORTED++#if MIN_VERSION_base(4,9,0)+type WithCallStack a = HasCallStack => a+#elif MIN_VERSION_base(4,8,1)+type WithCallStack a = (?callStack :: CallStack) => a+#endif++#if !MIN_VERSION_base(4,9,0)+-- NB: Can't say WithCallStack (WithCallStack a -> a);+-- Haskell doesn't support this kind of implicit parameter!+-- See https://mail.haskell.org/pipermail/ghc-devs/2016-January/011096.html+-- Since this function doesn't do anything, it's OK to+-- give it a less good type.+withFrozenCallStack :: WithCallStack (a -> a)+withFrozenCallStack x = x++callStack :: (?callStack :: CallStack) => CallStack+callStack = ?callStack++prettyCallStack :: CallStack -> String+prettyCallStack = showCallStack+#endif++-- | Give the *parent* of the person who invoked this;+-- so it's most suitable for being called from a utility function.+-- You probably want to call this using 'withFrozenCallStack'; otherwise+-- it's not very useful. We didn't implement this for base-4.8.1+-- because we cannot rely on freezing to have taken place.+--+parentSrcLocPrefix :: WithCallStack String+#if MIN_VERSION_base(4,9,0)+parentSrcLocPrefix =+ case getCallStack callStack of+ (_:(_, loc):_) -> showLoc loc+ [(_, loc)] -> showLoc loc+ [] -> error "parentSrcLocPrefix: empty call stack"+ where+ showLoc loc =+ srcLocFile loc ++ ":" ++ show (srcLocStartLine loc) ++ ": "+#else+parentSrcLocPrefix = "Call sites not available with base < 4.9.0.0 (GHC 8.0): "+#endif++-- Yeah, this uses skivvy implementation details.+withLexicalCallStack :: (a -> WithCallStack (IO b)) -> WithCallStack (a -> IO b)+withLexicalCallStack f =+ let stk = ?callStack+ in \x -> let ?callStack = stk in f x++#else++data CallStack = CallStack+ deriving (Eq, Show)++type WithCallStack a = a++withFrozenCallStack :: a -> a+withFrozenCallStack x = x++callStack :: CallStack+callStack = CallStack++prettyCallStack :: CallStack -> String+prettyCallStack _ = "Call stacks not available with base < 4.8.1.0 (GHC 7.10)"++parentSrcLocPrefix :: String+parentSrcLocPrefix = "Call sites not available with base < 4.9.0.0 (GHC 8.0): "++withLexicalCallStack :: (a -> IO b) -> a -> IO b+withLexicalCallStack f = f++#endif++-- | This function is for when you *really* want to add a call+-- stack to raised IO, but you don't have a+-- 'Distribution.Verbosity.Verbosity' so you can't use+-- 'Distribution.Simple.Utils.annotateIO'. If you have a 'Verbosity',+-- please use that function instead.+annotateCallStackIO :: WithCallStack (IO a -> IO a)+annotateCallStackIO = modifyIOError f+ where+ f ioe = ioeSetErrorString ioe+ . wrapCallStack+ $ ioeGetErrorString ioe+ wrapCallStack s =+ prettyCallStack callStack ++ "\n" ++ s
+ src/Distribution/Compat/Time.hs view
@@ -0,0 +1,194 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Distribution.Compat.Time+ ( ModTime(..) -- Needed for testing+ , getModTime, getFileAge, getCurTime+ , posixSecondsToModTime+ , calibrateMtimeChangeDelay )+ where++import Prelude ()+import Distribution.Compat.Prelude++import System.Directory ( getModificationTime )++import Distribution.Simple.Utils ( withTempDirectory )+import Distribution.Verbosity ( silent )++import System.FilePath++import Data.Time.Clock.POSIX ( POSIXTime, getPOSIXTime )+import Data.Time ( diffUTCTime, getCurrentTime )+import Data.Time.Clock.POSIX ( posixDayLength )+++#if defined mingw32_HOST_OS++import qualified Prelude+import Data.Bits ((.|.), unsafeShiftL)+#if MIN_VERSION_base(4,7,0)+import Data.Bits (finiteBitSize)+#else+import Data.Bits (bitSize)+#endif++import Foreign ( allocaBytes, peekByteOff )+import System.IO.Error ( mkIOError, doesNotExistErrorType )+import System.Win32.Types ( BOOL, DWORD, LPCTSTR, LPVOID, withTString )++#else++import System.Posix.Files ( FileStatus, getFileStatus )++#if MIN_VERSION_unix(2,6,0)+import System.Posix.Files ( modificationTimeHiRes )+#else+import System.Posix.Files ( modificationTime )+#endif++#endif++-- | An opaque type representing a file's modification time, represented+-- internally as a 64-bit unsigned integer in the Windows UTC format.+newtype ModTime = ModTime Word64+ deriving (Binary, Generic, Bounded, Eq, Ord, Typeable)++instance Structured ModTime++instance Show ModTime where+ show (ModTime x) = show x++instance Read ModTime where+ readsPrec p str = map (first ModTime) (readsPrec p str)++-- | Return modification time of the given file. Works around the low clock+-- resolution problem that 'getModificationTime' has on GHC < 7.8.+--+-- This is a modified version of the code originally written for Shake by Neil+-- Mitchell. See module Development.Shake.FileInfo.+getModTime :: FilePath -> IO ModTime++#if defined mingw32_HOST_OS++-- Directly against the Win32 API.+getModTime path = allocaBytes size_WIN32_FILE_ATTRIBUTE_DATA $ \info -> do+ res <- getFileAttributesEx path info+ if not res+ then do+ let err = mkIOError doesNotExistErrorType+ "Distribution.Compat.Time.getModTime"+ Nothing (Just path)+ ioError err+ else do+ dwLow <- peekByteOff info+ index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwLowDateTime+ dwHigh <- peekByteOff info+ index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwHighDateTime+#if MIN_VERSION_base(4,7,0)+ let qwTime =+ (fromIntegral (dwHigh :: DWORD) `unsafeShiftL` finiteBitSize dwHigh)+ .|. (fromIntegral (dwLow :: DWORD))+#else+ let qwTime =+ (fromIntegral (dwHigh :: DWORD) `unsafeShiftL` bitSize dwHigh)+ .|. (fromIntegral (dwLow :: DWORD))+#endif+ return $! ModTime (qwTime :: Word64)++#ifdef x86_64_HOST_ARCH+#define CALLCONV ccall+#else+#define CALLCONV stdcall+#endif++foreign import CALLCONV "windows.h GetFileAttributesExW"+ c_getFileAttributesEx :: LPCTSTR -> Int32 -> LPVOID -> Prelude.IO BOOL++getFileAttributesEx :: String -> LPVOID -> IO BOOL+getFileAttributesEx path lpFileInformation =+ withTString path $ \c_path ->+ c_getFileAttributesEx c_path getFileExInfoStandard lpFileInformation++getFileExInfoStandard :: Int32+getFileExInfoStandard = 0++size_WIN32_FILE_ATTRIBUTE_DATA :: Int+size_WIN32_FILE_ATTRIBUTE_DATA = 36++index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwLowDateTime :: Int+index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwLowDateTime = 20++index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwHighDateTime :: Int+index_WIN32_FILE_ATTRIBUTE_DATA_ftLastWriteTime_dwHighDateTime = 24++#else++-- Directly against the unix library.+getModTime path = do+ st <- getFileStatus path+ return $! (extractFileTime st)++extractFileTime :: FileStatus -> ModTime+extractFileTime x = posixTimeToModTime (modificationTimeHiRes x)++#endif++windowsTick, secToUnixEpoch :: Word64+windowsTick = 10000000+secToUnixEpoch = 11644473600++-- | Convert POSIX seconds to ModTime.+posixSecondsToModTime :: Int64 -> ModTime+posixSecondsToModTime s =+ ModTime $ ((fromIntegral s :: Word64) + secToUnixEpoch) * windowsTick++-- | Convert 'POSIXTime' to 'ModTime'.+posixTimeToModTime :: POSIXTime -> ModTime+posixTimeToModTime p = ModTime $ (ceiling $ p * 1e7) -- 100 ns precision+ + (secToUnixEpoch * windowsTick)++-- | Return age of given file in days.+getFileAge :: FilePath -> IO Double+getFileAge file = do+ t0 <- getModificationTime file+ t1 <- getCurrentTime+ return $ realToFrac (t1 `diffUTCTime` t0) / realToFrac posixDayLength++-- | Return the current time as 'ModTime'.+getCurTime :: IO ModTime+getCurTime = posixTimeToModTime `fmap` getPOSIXTime -- Uses 'gettimeofday'.++-- | Based on code written by Neil Mitchell for Shake. See+-- 'sleepFileTimeCalibrate' in 'Test.Type'. Returns a pair+-- of microsecond values: first, the maximum delay seen, and the+-- recommended delay to use before testing for file modification change.+-- The returned delay is never smaller+-- than 10 ms, but never larger than 1 second.+calibrateMtimeChangeDelay :: IO (Int, Int)+calibrateMtimeChangeDelay =+ withTempDirectory silent "." "calibration-" $ \dir -> do+ let fileName = dir </> "probe"+ mtimes <- for [1..25] $ \(i::Int) -> time $ do+ writeFile fileName $ show i+ t0 <- getModTime fileName+ let spin j = do+ writeFile fileName $ show (i,j)+ t1 <- getModTime fileName+ unless (t0 < t1) (spin $ j + 1)+ spin (0::Int)+ let mtimeChange = maximum mtimes+ mtimeChange' = min 1000000 $ (max 10000 mtimeChange) * 2+ return (mtimeChange, mtimeChange')+ where+ time :: IO () -> IO Int+ time act = do+ t0 <- getCurrentTime+ act+ t1 <- getCurrentTime+ return . ceiling $! (t1 `diffUTCTime` t0) * 1e6 -- microseconds
+ src/Distribution/Compat/Typeable.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Distribution.Compat.Typeable (+ Typeable,+ TypeRep,+ typeRep,+ ) where++#if MIN_VERSION_base(4,7,0)+import Data.Typeable (Typeable, TypeRep, typeRep)+#else+import Data.Typeable (Typeable, TypeRep, typeOf)+#endif++#if !MIN_VERSION_base(4,7,0)+typeRep :: forall a proxy. Typeable a => proxy a -> TypeRep+typeRep _ = typeOf (undefined :: a)+#endif
+ src/Distribution/Compiler.hs view
@@ -0,0 +1,223 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Compiler+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This has an enumeration of the various compilers that Cabal knows about. It+-- also specifies the default compiler. Sadly you'll often see code that does+-- case analysis on this compiler flavour enumeration like:+--+-- > case compilerFlavor comp of+-- > GHC -> GHC.getInstalledPackages verbosity packageDb progdb+--+-- Obviously it would be better to use the proper 'Compiler' abstraction+-- because that would keep all the compiler-specific code together.+-- Unfortunately we cannot make this change yet without breaking the+-- 'UserHooks' api, which would break all custom @Setup.hs@ files, so for the+-- moment we just have to live with this deficiency. If you're interested, see+-- ticket #57.++module Distribution.Compiler (+ -- * Compiler flavor+ CompilerFlavor(..),+ buildCompilerId,+ buildCompilerFlavor,+ defaultCompilerFlavor,+ classifyCompilerFlavor,+ knownCompilerFlavors,++ -- * Per compiler flavor+ PerCompilerFlavor (..),+ perCompilerFlavorToList,++ -- * Compiler id+ CompilerId(..),++ -- * Compiler info+ CompilerInfo(..),+ unknownCompilerInfo,+ AbiTag(..), abiTagString+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Language.Haskell.Extension++import Distribution.Version (Version, mkVersion', nullVersion)++import qualified System.Info (compilerName, compilerVersion)+import Distribution.Parsec (Parsec (..))+import Distribution.Pretty (Pretty (..), prettyShow)+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++data CompilerFlavor =+ GHC | GHCJS | NHC | YHC | Hugs | HBC | Helium | JHC | LHC | UHC | Eta+ | HaskellSuite String -- string is the id of the actual compiler+ | OtherCompiler String+ deriving (Generic, Show, Read, Eq, Ord, Typeable, Data)++instance Binary CompilerFlavor+instance Structured CompilerFlavor+instance NFData CompilerFlavor where rnf = genericRnf++knownCompilerFlavors :: [CompilerFlavor]+knownCompilerFlavors =+ [GHC, GHCJS, NHC, YHC, Hugs, HBC, Helium, JHC, LHC, UHC, Eta]++instance Pretty CompilerFlavor where+ pretty (OtherCompiler name) = Disp.text name+ pretty (HaskellSuite name) = Disp.text name+ pretty NHC = Disp.text "nhc98"+ pretty other = Disp.text (lowercase (show other))++instance Parsec CompilerFlavor where+ parsec = classifyCompilerFlavor <$> component+ where+ component = do+ cs <- P.munch1 isAlphaNum+ if all isDigit cs then fail "all digits compiler name" else return cs++classifyCompilerFlavor :: String -> CompilerFlavor+classifyCompilerFlavor s =+ fromMaybe (OtherCompiler s) $ lookup (lowercase s) compilerMap+ where+ compilerMap = [ (lowercase (prettyShow compiler), compiler)+ | compiler <- knownCompilerFlavors ]++buildCompilerFlavor :: CompilerFlavor+buildCompilerFlavor = classifyCompilerFlavor System.Info.compilerName++buildCompilerVersion :: Version+buildCompilerVersion = mkVersion' System.Info.compilerVersion++buildCompilerId :: CompilerId+buildCompilerId = CompilerId buildCompilerFlavor buildCompilerVersion++-- | The default compiler flavour to pick when compiling stuff. This defaults+-- to the compiler used to build the Cabal lib.+--+-- However if it's not a recognised compiler then it's 'Nothing' and the user+-- will have to specify which compiler they want.+--+defaultCompilerFlavor :: Maybe CompilerFlavor+defaultCompilerFlavor = case buildCompilerFlavor of+ OtherCompiler _ -> Nothing+ _ -> Just buildCompilerFlavor++-------------------------------------------------------------------------------+-- Per compiler data+-------------------------------------------------------------------------------++-- | 'PerCompilerFlavor' carries only info per GHC and GHCJS+--+-- Cabal parses only @ghc-options@ and @ghcjs-options@, others are omitted.+--+data PerCompilerFlavor v = PerCompilerFlavor v v+ deriving (Generic, Show, Read, Eq, Typeable, Data, Functor, Foldable+ , Traversable)++instance Binary a => Binary (PerCompilerFlavor a)+instance Structured a => Structured (PerCompilerFlavor a)+instance NFData a => NFData (PerCompilerFlavor a)++perCompilerFlavorToList :: PerCompilerFlavor v -> [(CompilerFlavor, v)]+perCompilerFlavorToList (PerCompilerFlavor a b) = [(GHC, a), (GHCJS, b)]++instance Semigroup a => Semigroup (PerCompilerFlavor a) where+ PerCompilerFlavor a b <> PerCompilerFlavor a' b' = PerCompilerFlavor+ (a <> a') (b <> b')++instance (Semigroup a, Monoid a) => Monoid (PerCompilerFlavor a) where+ mempty = PerCompilerFlavor mempty mempty+ mappend = (<>)++-- ------------------------------------------------------------+-- * Compiler Id+-- ------------------------------------------------------------++data CompilerId = CompilerId CompilerFlavor Version+ deriving (Eq, Generic, Ord, Read, Show, Typeable)++instance Binary CompilerId+instance Structured CompilerId+instance NFData CompilerId where rnf = genericRnf++instance Pretty CompilerId where+ pretty (CompilerId f v)+ | v == nullVersion = pretty f+ | otherwise = pretty f <<>> Disp.char '-' <<>> pretty v++instance Parsec CompilerId where+ parsec = do+ flavour <- parsec+ version <- (P.char '-' >> parsec) <|> return nullVersion+ return (CompilerId flavour version)++lowercase :: String -> String+lowercase = map toLower++-- ------------------------------------------------------------+-- * Compiler Info+-- ------------------------------------------------------------++-- | Compiler information used for resolving configurations. Some+-- fields can be set to Nothing to indicate that the information is+-- unknown.++data CompilerInfo = CompilerInfo {+ compilerInfoId :: CompilerId,+ -- ^ Compiler flavour and version.+ compilerInfoAbiTag :: AbiTag,+ -- ^ Tag for distinguishing incompatible ABI's on the same+ -- architecture/os.+ compilerInfoCompat :: Maybe [CompilerId],+ -- ^ Other implementations that this compiler claims to be+ -- compatible with, if known.+ compilerInfoLanguages :: Maybe [Language],+ -- ^ Supported language standards, if known.+ compilerInfoExtensions :: Maybe [Extension]+ -- ^ Supported extensions, if known.+ }+ deriving (Generic, Show, Read)++instance Binary CompilerInfo++data AbiTag+ = NoAbiTag+ | AbiTag String+ deriving (Eq, Generic, Show, Read, Typeable)++instance Binary AbiTag+instance Structured AbiTag++instance Pretty AbiTag where+ pretty NoAbiTag = Disp.empty+ pretty (AbiTag tag) = Disp.text tag++instance Parsec AbiTag where+ parsec = do+ tag <- P.munch (\c -> isAlphaNum c || c == '_')+ if null tag then return NoAbiTag else return (AbiTag tag)++abiTagString :: AbiTag -> String+abiTagString NoAbiTag = ""+abiTagString (AbiTag tag) = tag++-- | Make a CompilerInfo of which only the known information is its CompilerId,+-- its AbiTag and that it does not claim to be compatible with other+-- compiler id's.+unknownCompilerInfo :: CompilerId -> AbiTag -> CompilerInfo+unknownCompilerInfo compilerId abiTag =+ CompilerInfo compilerId abiTag (Just []) Nothing Nothing
+ src/Distribution/FieldGrammar.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | This module provides a way to specify a grammar of @.cabal@ -like files.+module Distribution.FieldGrammar (+ -- * Field grammar type+ FieldGrammar (..),+ uniqueField,+ optionalField,+ optionalFieldDef,+ monoidalField,+ -- * Concrete grammar implementations+ ParsecFieldGrammar,+ ParsecFieldGrammar',+ parseFieldGrammar,+ fieldGrammarKnownFieldList,+ PrettyFieldGrammar,+ PrettyFieldGrammar',+ prettyFieldGrammar,+ -- * Auxlilary+ (^^^),+ Section(..),+ Fields,+ partitionFields,+ takeFields,+ runFieldParser,+ runFieldParser',+ defaultFreeTextFieldDefST,+ -- * Newtypes+ module Distribution.FieldGrammar.Newtypes,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import qualified Data.Map.Strict as Map++import Distribution.FieldGrammar.Class+import Distribution.FieldGrammar.Newtypes+import Distribution.FieldGrammar.Parsec+import Distribution.FieldGrammar.Pretty+import Distribution.Fields.Field+import Distribution.Utils.Generic (spanMaybe)++type ParsecFieldGrammar' a = ParsecFieldGrammar a a+type PrettyFieldGrammar' a = PrettyFieldGrammar a a++infixl 5 ^^^++-- | Reverse function application which binds tighter than '<$>' and '<*>'.+-- Useful for refining grammar specification.+--+-- @+-- \<*\> 'monoidalFieldAla' "extensions" (alaList' FSep MQuoted) oldExtensions+-- ^^^ 'deprecatedSince' [1,12] "Please use 'default-extensions' or 'other-extensions' fields."+-- @+(^^^) :: a -> (a -> b) -> b+x ^^^ f = f x++-- | Partitioning state+data PS ann = PS (Fields ann) [Section ann] [[Section ann]]++-- | Partition field list into field map and groups of sections.+partitionFields :: [Field ann] -> (Fields ann, [[Section ann]])+partitionFields = finalize . foldl' f (PS mempty mempty mempty)+ where+ finalize :: PS ann -> (Fields ann, [[Section ann]])+ finalize (PS fs s ss)+ | null s = (fs, reverse ss)+ | otherwise = (fs, reverse (reverse s : ss))++ f :: PS ann -> Field ann -> PS ann+ f (PS fs s ss) (Field (Name ann name) fss) =+ PS (Map.insertWith (flip (++)) name [MkNamelessField ann fss] fs) [] ss'+ where+ ss' | null s = ss+ | otherwise = reverse s : ss+ f (PS fs s ss) (Section name sargs sfields) =+ PS fs (MkSection name sargs sfields : s) ss++-- | Take all fields from the front.+takeFields :: [Field ann] -> (Fields ann, [Field ann])+takeFields = finalize . spanMaybe match+ where+ finalize (fs, rest) = (Map.fromListWith (flip (++)) fs, rest)++ match (Field (Name ann name) fs) = Just (name, [MkNamelessField ann fs])+ match _ = Nothing
+ src/Distribution/FieldGrammar/Class.hs view
@@ -0,0 +1,205 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+#if __GLASGOW_HASKELL__ >= 800+{-# LANGUAGE UndecidableSuperClasses #-}+#else+{-# LANGUAGE UndecidableInstances #-}+#endif+module Distribution.FieldGrammar.Class (+ FieldGrammar (..),+ uniqueField,+ optionalField,+ optionalFieldDef,+ monoidalField,+ defaultFreeTextFieldDefST,+) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.CabalSpecVersion (CabalSpecVersion)+import Distribution.Compat.Newtype (Newtype)+import Distribution.FieldGrammar.Newtypes+import Distribution.Fields.Field+import Distribution.Utils.ShortText++-- | 'FieldGrammar' is parametrised by+--+-- * @s@ which is a structure we are parsing. We need this to provide prettyprinter+-- functionality+--+-- * @a@ type of the field.+--+-- /Note:/ We'd like to have @forall s. Applicative (f s)@ context.+--+class+ ( c SpecVersion, c TestedWith, c SpecLicense, c Token, c Token', c FilePathNT+ )+ => FieldGrammar c g | g -> c+ where+ -- | Unfocus, zoom out, /blur/ 'FieldGrammar'.+ blurFieldGrammar :: ALens' a b -> g b d -> g a d++ -- | Field which should be defined, exactly once.+ uniqueFieldAla+ :: (c b, Newtype a b)+ => FieldName -- ^ field name+ -> (a -> b) -- ^ 'Newtype' pack+ -> ALens' s a -- ^ lens into the field+ -> g s a++ -- | Boolean field with a default value.+ booleanFieldDef+ :: FieldName -- ^ field name+ -> ALens' s Bool -- ^ lens into the field+ -> Bool -- ^ default+ -> g s Bool++ -- | Optional field.+ optionalFieldAla+ :: (c b, Newtype a b)+ => FieldName -- ^ field name+ -> (a -> b) -- ^ 'pack'+ -> ALens' s (Maybe a) -- ^ lens into the field+ -> g s (Maybe a)++ -- | Optional field with default value.+ optionalFieldDefAla+ :: (c b, Newtype a b, Eq a)+ => FieldName -- ^ field name+ -> (a -> b) -- ^ 'Newtype' pack+ -> ALens' s a -- ^ @'Lens'' s a@: lens into the field+ -> a -- ^ default value+ -> g s a++ -- | Free text field is essentially 'optionalFieldDefAla` with @""@+ -- as the default and "accept everything" parser.+ --+ -- @since 3.0.0.0+ freeTextField+ :: FieldName+ -> ALens' s (Maybe String) -- ^ lens into the field+ -> g s (Maybe String)++ -- | Free text field is essentially 'optionalFieldDefAla` with @""@+ -- as the default and "accept everything" parser.+ --+ -- @since 3.0.0.0+ freeTextFieldDef+ :: FieldName+ -> ALens' s String -- ^ lens into the field+ -> g s String++ -- | @since 3.2.0.0+ freeTextFieldDefST+ :: FieldName+ -> ALens' s ShortText -- ^ lens into the field+ -> g s ShortText++ -- | Monoidal field.+ --+ -- Values are combined with 'mappend'.+ --+ -- /Note:/ 'optionalFieldAla' is a @monoidalField@ with 'Last' monoid.+ --+ monoidalFieldAla+ :: (c b, Monoid a, Newtype a b)+ => FieldName -- ^ field name+ -> (a -> b) -- ^ 'pack'+ -> ALens' s a -- ^ lens into the field+ -> g s a++ -- | Parser matching all fields with a name starting with a prefix.+ prefixedFields+ :: FieldName -- ^ field name prefix+ -> ALens' s [(String, String)] -- ^ lens into the field+ -> g s [(String, String)]++ -- | Known field, which we don't parse, nor pretty print.+ knownField :: FieldName -> g s ()++ -- | Field which is parsed but not pretty printed.+ hiddenField :: g s a -> g s a++ -- | Deprecated since+ deprecatedSince+ :: CabalSpecVersion -- ^ version+ -> String -- ^ deprecation message+ -> g s a+ -> g s a++ -- | Removed in. If we encounter removed field, parsing fails.+ removedIn+ :: CabalSpecVersion -- ^ version+ -> String -- ^ removal message+ -> g s a+ -> g s a++ -- | Annotate field with since spec-version.+ availableSince+ :: CabalSpecVersion -- ^ spec version+ -> a -- ^ default value+ -> g s a+ -> g s a++ -- | Annotate field with since spec-version.+ -- This is used to recognise, but warn about the field.+ -- It is used to process @other-extensions@ field.+ --+ -- Default implementation is to not warn.+ --+ -- @since 3.4.0.0+ availableSinceWarn+ :: CabalSpecVersion -- ^ spec version+ -> g s a+ -> g s a+ availableSinceWarn _ = id++-- | Field which can be defined at most once.+uniqueField+ :: (FieldGrammar c g, c (Identity a))+ => FieldName -- ^ field name+ -> ALens' s a -- ^ lens into the field+ -> g s a+uniqueField fn l = uniqueFieldAla fn Identity l++-- | Field which can be defined at most once.+optionalField+ :: (FieldGrammar c g, c (Identity a))+ => FieldName -- ^ field name+ -> ALens' s (Maybe a) -- ^ lens into the field+ -> g s (Maybe a)+optionalField fn l = optionalFieldAla fn Identity l++-- | Optional field with default value.+optionalFieldDef+ :: (FieldGrammar c g, Functor (g s), c (Identity a), Eq a)+ => FieldName -- ^ field name+ -> ALens' s a -- ^ @'Lens'' s a@: lens into the field+ -> a -- ^ default value+ -> g s a+optionalFieldDef fn l x = optionalFieldDefAla fn Identity l x++-- | Field which can be define multiple times, and the results are @mappend@ed.+monoidalField+ :: (FieldGrammar c g, c (Identity a), Monoid a)+ => FieldName -- ^ field name+ -> ALens' s a -- ^ lens into the field+ -> g s a+monoidalField fn l = monoidalFieldAla fn Identity l++-- | Default implementation for 'freeTextFieldDefST'.+defaultFreeTextFieldDefST+ :: (Functor (g s), FieldGrammar c g)+ => FieldName+ -> ALens' s ShortText -- ^ lens into the field+ -> g s ShortText+defaultFreeTextFieldDefST fn l =+ toShortText <$> freeTextFieldDef fn (cloneLens l . st)+ where+ st :: Lens' ShortText String+ st f s = toShortText <$> f (fromShortText s)
+ src/Distribution/FieldGrammar/FieldDescrs.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE UndecidableInstances #-}+module Distribution.FieldGrammar.FieldDescrs (+ FieldDescrs,+ fieldDescrPretty,+ fieldDescrParse,+ fieldDescrsToList,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Data.List (dropWhileEnd)+import Distribution.Compat.Lens (aview, cloneLens)+import Distribution.Compat.Newtype+import Distribution.FieldGrammar+import Distribution.Pretty (Pretty (..), showFreeText)++import qualified Data.Map as Map+import qualified Distribution.Compat.CharParsing as C+import qualified Distribution.Fields.Field as P+import qualified Distribution.Parsec as P+import qualified Text.PrettyPrint as Disp++-- strict pair+data SP s = SP+ { pPretty :: !(s -> Disp.Doc)+ , pParse :: !(forall m. P.CabalParsing m => s -> m s)+ }++-- | A collection of field parsers and pretty-printers.+newtype FieldDescrs s a = F { runF :: Map P.FieldName (SP s) }+ deriving (Functor)++instance Applicative (FieldDescrs s) where+ pure _ = F mempty+ f <*> x = F (mappend (runF f) (runF x))++singletonF :: P.FieldName -> (s -> Disp.Doc) -> (forall m. P.CabalParsing m => s -> m s) -> FieldDescrs s a+singletonF fn f g = F $ Map.singleton fn (SP f g)++-- | Lookup a field value pretty-printer.+fieldDescrPretty :: FieldDescrs s a -> P.FieldName -> Maybe (s -> Disp.Doc)+fieldDescrPretty (F m) fn = pPretty <$> Map.lookup fn m++-- | Lookup a field value parser.+fieldDescrParse :: P.CabalParsing m => FieldDescrs s a -> P.FieldName -> Maybe (s -> m s)+fieldDescrParse (F m) fn = (\f -> pParse f) <$> Map.lookup fn m++fieldDescrsToList+ :: P.CabalParsing m+ => FieldDescrs s a+ -> [(P.FieldName, s -> Disp.Doc, s -> m s)]+fieldDescrsToList = map mk . Map.toList . runF where+ mk (name, SP ppr parse) = (name, ppr, parse)++-- | /Note:/ default values are printed.+instance FieldGrammar ParsecPretty FieldDescrs where+ blurFieldGrammar l (F m) = F (fmap blur m) where+ blur (SP f g) = SP (f . aview l) (cloneLens l g)++ booleanFieldDef fn l _def = singletonF fn f g where+ f s = Disp.text (show (aview l s))+ g s = cloneLens l (const P.parsec) s+ -- Note: eta expansion is needed for RankNTypes type-checking to work.++ uniqueFieldAla fn _pack l = singletonF fn f g where+ f s = pretty (pack' _pack (aview l s))+ g s = cloneLens l (const (unpack' _pack <$> P.parsec)) s++ optionalFieldAla fn _pack l = singletonF fn f g where+ f s = maybe mempty (pretty . pack' _pack) (aview l s)+ g s = cloneLens l (const (Just . unpack' _pack <$> P.parsec)) s++ optionalFieldDefAla fn _pack l _def = singletonF fn f g where+ f s = pretty (pack' _pack (aview l s))+ g s = cloneLens l (const (unpack' _pack <$> P.parsec)) s++ freeTextField fn l = singletonF fn f g where+ f s = maybe mempty showFreeText (aview l s)+ g s = cloneLens l (const (Just <$> parsecFreeText)) s++ freeTextFieldDef fn l = singletonF fn f g where+ f s = showFreeText (aview l s)+ g s = cloneLens l (const parsecFreeText) s++ freeTextFieldDefST = defaultFreeTextFieldDefST++ monoidalFieldAla fn _pack l = singletonF fn f g where+ f s = pretty (pack' _pack (aview l s))+ g s = cloneLens l (\x -> mappend x . unpack' _pack <$> P.parsec) s++ prefixedFields _fnPfx _l = F mempty+ knownField _ = pure ()+ deprecatedSince _ _ x = x+ removedIn _ _ x = x+ availableSince _ _ = id+ hiddenField _ = F mempty++parsecFreeText :: P.CabalParsing m => m String+parsecFreeText = dropDotLines <$ C.spaces <*> many C.anyChar+ where+ -- Example package with dot lines+ -- http://hackage.haskell.org/package/copilot-cbmc-0.1/copilot-cbmc.cabal+ dropDotLines "." = "."+ dropDotLines x = intercalate "\n" . map dotToEmpty . lines $ x++ dotToEmpty x | trim' x == "." = ""+ dotToEmpty x = trim x++ trim' :: String -> String+ trim' = dropWhileEnd (`elem` (" \t" :: String))++ trim :: String -> String+ trim = dropWhile isSpace . dropWhileEnd isSpace++class (P.Parsec a, Pretty a) => ParsecPretty a+instance (P.Parsec a, Pretty a) => ParsecPretty a
+ src/Distribution/FieldGrammar/Newtypes.hs view
@@ -0,0 +1,392 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | This module provides @newtype@ wrappers to be used with "Distribution.FieldGrammar".+module Distribution.FieldGrammar.Newtypes (+ -- * List+ alaList,+ alaList',+ -- ** Modifiers+ CommaVCat (..),+ CommaFSep (..),+ VCat (..),+ FSep (..),+ NoCommaFSep (..),+ Sep (..),+ -- ** Type+ List,+ -- ** Set+ alaSet,+ alaSet',+ Set',+ -- ** NonEmpty+ alaNonEmpty,+ alaNonEmpty',+ NonEmpty',+ -- * Version & License+ SpecVersion (..),+ TestedWith (..),+ SpecLicense (..),+ -- * Identifiers+ Token (..),+ Token' (..),+ MQuoted (..),+ FilePathNT (..),+ ) where++import Distribution.Compat.Newtype+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.CabalSpecVersion+import Distribution.Compiler (CompilerFlavor)+import Distribution.License (License)+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Version+ (LowerBound (..), Version, VersionInterval (..), VersionRange, VersionRangeF (..), anyVersion, asVersionIntervals, cataVersionRange, mkVersion,+ version0, versionNumbers)+import Text.PrettyPrint (Doc, comma, fsep, punctuate, text, vcat)++import qualified Data.List.NonEmpty as NE+import qualified Data.Set as Set+import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.SPDX as SPDX++-- | Vertical list with commas. Displayed with 'vcat'+data CommaVCat = CommaVCat++-- | Paragraph fill list with commas. Displayed with 'fsep'+data CommaFSep = CommaFSep++-- | Vertical list with optional commas. Displayed with 'vcat'.+data VCat = VCat++-- | Paragraph fill list with optional commas. Displayed with 'fsep'.+data FSep = FSep++-- | Paragraph fill list without commas. Displayed with 'fsep'.+data NoCommaFSep = NoCommaFSep++class Sep sep where+ prettySep :: Proxy sep -> [Doc] -> Doc++ parseSep :: CabalParsing m => Proxy sep -> m a -> m [a]+ parseSepNE :: CabalParsing m => Proxy sep -> m a -> m (NonEmpty a)++instance Sep CommaVCat where+ prettySep _ = vcat . punctuate comma+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p+ parseSepNE _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2 then parsecLeadingCommaNonEmpty p else parsecCommaNonEmpty p+instance Sep CommaFSep where+ prettySep _ = fsep . punctuate comma+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p+ parseSepNE _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2 then parsecLeadingCommaNonEmpty p else parsecCommaNonEmpty p+instance Sep VCat where+ prettySep _ = vcat+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p+ parseSepNE _ p = NE.some1 (p <* P.spaces)+instance Sep FSep where+ prettySep _ = fsep+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p+ parseSepNE _ p = NE.some1 (p <* P.spaces)+instance Sep NoCommaFSep where+ prettySep _ = fsep+ parseSep _ p = many (p <* P.spaces)+ parseSepNE _ p = NE.some1 (p <* P.spaces)++-- | List separated with optional commas. Displayed with @sep@, arguments of+-- type @a@ are parsed and pretty-printed as @b@.+newtype List sep b a = List { _getList :: [a] }++-- | 'alaList' and 'alaList'' are simply 'List', with additional phantom+-- arguments to constrain the resulting type+--+-- >>> :t alaList VCat+-- alaList VCat :: [a] -> List VCat (Identity a) a+--+-- >>> :t alaList' FSep Token+-- alaList' FSep Token :: [String] -> List FSep Token String+--+alaList :: sep -> [a] -> List sep (Identity a) a+alaList _ = List++-- | More general version of 'alaList'.+alaList' :: sep -> (a -> b) -> [a] -> List sep b a+alaList' _ _ = List++instance Newtype [a] (List sep wrapper a)++instance (Newtype a b, Sep sep, Parsec b) => Parsec (List sep b a) where+ parsec = pack . map (unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) parsec++instance (Newtype a b, Sep sep, Pretty b) => Pretty (List sep b a) where+ pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . unpack++--+-- | Like 'List', but for 'Set'.+--+-- @since 3.2.0.0+newtype Set' sep b a = Set' { _getSet :: Set a }++-- | 'alaSet' and 'alaSet'' are simply 'Set'' constructor, with additional phantom+-- arguments to constrain the resulting type+--+-- >>> :t alaSet VCat+-- alaSet VCat :: Set a -> Set' VCat (Identity a) a+--+-- >>> :t alaSet' FSep Token+-- alaSet' FSep Token :: Set String -> Set' FSep Token String+--+-- >>> unpack' (alaSet' FSep Token) <$> eitherParsec "foo bar foo"+-- Right (fromList ["bar","foo"])+--+-- @since 3.2.0.0+alaSet :: sep -> Set a -> Set' sep (Identity a) a+alaSet _ = Set'++-- | More general version of 'alaSet'.+--+-- @since 3.2.0.0+alaSet' :: sep -> (a -> b) -> Set a -> Set' sep b a+alaSet' _ _ = Set'++instance Newtype (Set a) (Set' sep wrapper a)++instance (Newtype a b, Ord a, Sep sep, Parsec b) => Parsec (Set' sep b a) where+ parsec = pack . Set.fromList . map (unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) parsec++instance (Newtype a b, Sep sep, Pretty b) => Pretty (Set' sep b a) where+ pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . Set.toList . unpack++--+-- | Like 'List', but for 'NonEmpty'.+--+-- @since 3.2.0.0+newtype NonEmpty' sep b a = NonEmpty' { _getNonEmpty :: NonEmpty a }++-- | 'alaNonEmpty' and 'alaNonEmpty'' are simply 'NonEmpty'' constructor, with additional phantom+-- arguments to constrain the resulting type+--+-- >>> :t alaNonEmpty VCat+-- alaNonEmpty VCat :: NonEmpty a -> NonEmpty' VCat (Identity a) a+--+-- >>> unpack' (alaNonEmpty' FSep Token) <$> eitherParsec "foo bar foo"+-- Right ("foo" :| ["bar","foo"])+--+-- @since 3.2.0.0+alaNonEmpty :: sep -> NonEmpty a -> NonEmpty' sep (Identity a) a+alaNonEmpty _ = NonEmpty'++-- | More general version of 'alaNonEmpty'.+--+-- @since 3.2.0.0+alaNonEmpty' :: sep -> (a -> b) -> NonEmpty a -> NonEmpty' sep b a+alaNonEmpty' _ _ = NonEmpty'++instance Newtype (NonEmpty a) (NonEmpty' sep wrapper a)++instance (Newtype a b, Sep sep, Parsec b) => Parsec (NonEmpty' sep b a) where+ parsec = pack . fmap (unpack :: b -> a) <$> parseSepNE (Proxy :: Proxy sep) parsec++instance (Newtype a b, Sep sep, Pretty b) => Pretty (NonEmpty' sep b a) where+ pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . NE.toList . unpack++-------------------------------------------------------------------------------+-- Identifiers+-------------------------------------------------------------------------------++-- | Haskell string or @[^ ,]+@+newtype Token = Token { getToken :: String }++instance Newtype String Token++instance Parsec Token where+ parsec = pack <$> parsecToken++instance Pretty Token where+ pretty = showToken . unpack++-- | Haskell string or @[^ ]+@+newtype Token' = Token' { getToken' :: String }++instance Newtype String Token'++instance Parsec Token' where+ parsec = pack <$> parsecToken'++instance Pretty Token' where+ pretty = showToken . unpack++-- | Either @"quoted"@ or @un-quoted@.+newtype MQuoted a = MQuoted { getMQuoted :: a }++instance Newtype a (MQuoted a)++instance Parsec a => Parsec (MQuoted a) where+ parsec = pack <$> parsecMaybeQuoted parsec++instance Pretty a => Pretty (MQuoted a) where+ pretty = pretty . unpack++-- | Filepath are parsed as 'Token'.+newtype FilePathNT = FilePathNT { getFilePathNT :: String }++instance Newtype String FilePathNT++instance Parsec FilePathNT where+ parsec = do+ token <- parsecToken+ if null token+ then P.unexpected "empty FilePath"+ else return (FilePathNT token)++instance Pretty FilePathNT where+ pretty = showFilePath . unpack++-------------------------------------------------------------------------------+-- SpecVersion+-------------------------------------------------------------------------------++-- | Version range or just version, i.e. @cabal-version@ field.+--+-- There are few things to consider:+--+-- * Starting with 2.2 the cabal-version field should be the first field in the+-- file and only exact version is accepted. Therefore if we get e.g.+-- @>= 2.2@, we fail.+-- See <https://github.com/haskell/cabal/issues/4899>+--+-- We have this newtype, as writing Parsec and Pretty instances+-- for CabalSpecVersion would cause cycle in modules:+-- Version -> CabalSpecVersion -> Parsec -> ...+--+newtype SpecVersion = SpecVersion { getSpecVersion :: CabalSpecVersion }+ deriving (Eq, Show) -- instances needed for tests++instance Newtype CabalSpecVersion SpecVersion++instance Parsec SpecVersion where+ parsec = do+ e <- parsecSpecVersion+ let ver :: Version+ ver = either id specVersionFromRange e++ digits :: [Int]+ digits = versionNumbers ver++ case cabalSpecFromVersionDigits digits of+ Nothing -> fail $ "Unknown cabal spec version specified: " ++ prettyShow ver+ Just csv -> do+ -- Check some warnings:+ case e of+ -- example: cabal-version: 1.10+ -- should be cabal-version: >=1.10+ Left _v | csv < CabalSpecV1_12 -> parsecWarning PWTSpecVersion $ concat+ [ "With 1.10 or earlier, the 'cabal-version' field must use "+ , "range syntax rather than a simple version number. Use "+ , "'cabal-version: >= " ++ prettyShow ver ++ "'."+ ]++ -- example: cabal-version: >=1.12+ -- should be cabal-version: 1.12+ Right _vr | csv >= CabalSpecV1_12 -> parsecWarning PWTSpecVersion $ concat+ [ "Packages with 'cabal-version: 1.12' or later should specify a "+ , "specific version of the Cabal spec of the form "+ , "'cabal-version: x.y'. "+ , "Use 'cabal-version: " ++ prettyShow ver ++ "'."+ ]++ -- example: cabal-version: >=1.10 && <1.12+ -- should be cabal-version: >=1.10+ Right vr | csv < CabalSpecV1_12+ , not (simpleSpecVersionRangeSyntax vr) -> parsecWarning PWTSpecVersion $ concat+ [ "It is recommended that the 'cabal-version' field only specify a "+ , "version range of the form '>= x.y' for older cabal versions. Use "+ , "'cabal-version: >= " ++ prettyShow ver ++ "'. "+ , "Tools based on Cabal 1.10 and later will ignore upper bounds."+ ]++ -- otherwise no warnings+ _ -> pure ()++ return (pack csv)+ where+ parsecSpecVersion = Left <$> parsec <|> Right <$> range++ range = do+ vr <- parsec+ if specVersionFromRange vr >= mkVersion [2,1]+ then fail "cabal-version higher than 2.2 cannot be specified as a range. See https://github.com/haskell/cabal/issues/4899"+ else return vr++ specVersionFromRange :: VersionRange -> Version+ specVersionFromRange versionRange = case asVersionIntervals versionRange of+ [] -> version0+ VersionInterval (LowerBound version _) _ : _ -> version++ simpleSpecVersionRangeSyntax = cataVersionRange alg where+ alg (OrLaterVersionF _) = True+ alg _ = False+++instance Pretty SpecVersion where+ pretty (SpecVersion csv)+ | csv >= CabalSpecV1_12 = text (showCabalSpecVersion csv)+ | otherwise = text ">=" <<>> text (showCabalSpecVersion csv)++-------------------------------------------------------------------------------+-- SpecLicense+-------------------------------------------------------------------------------++-- | SPDX License expression or legacy license+newtype SpecLicense = SpecLicense { getSpecLicense :: Either SPDX.License License }++instance Newtype (Either SPDX.License License) SpecLicense++instance Parsec SpecLicense where+ parsec = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2+ then SpecLicense . Left <$> parsec+ else SpecLicense . Right <$> parsec++instance Pretty SpecLicense where+ pretty = either pretty pretty . unpack++-------------------------------------------------------------------------------+-- TestedWith+-------------------------------------------------------------------------------++-- | Version range or just version+newtype TestedWith = TestedWith { getTestedWith :: (CompilerFlavor, VersionRange) }++instance Newtype (CompilerFlavor, VersionRange) TestedWith++instance Parsec TestedWith where+ parsec = pack <$> parsecTestedWith++instance Pretty TestedWith where+ pretty x = case unpack x of+ (compiler, vr) -> pretty compiler <+> pretty vr++parsecTestedWith :: CabalParsing m => m (CompilerFlavor, VersionRange)+parsecTestedWith = do+ name <- lexemeParsec+ ver <- parsec <|> pure anyVersion+ return (name, ver)
+ src/Distribution/FieldGrammar/Parsec.hs view
@@ -0,0 +1,439 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | This module provides a 'FieldGrammarParser', one way to parse+-- @.cabal@ -like files.+--+-- Fields can be specified multiple times in the .cabal files. The order of+-- such entries is important, but the mutual ordering of different fields is+-- not.Also conditional sections are considered after non-conditional data.+-- The example of this silent-commutation quirk is the fact that+--+-- @+-- buildable: True+-- if os(linux)+-- buildable: False+-- @+--+-- and+--+-- @+-- if os(linux)+-- buildable: False+-- buildable: True+-- @+--+-- behave the same! This is the limitation of 'GeneralPackageDescription'+-- structure.+--+-- So we transform the list of fields @['Field' ann]@ into+-- a map of grouped ordinary fields and a list of lists of sections:+-- @'Fields' ann = 'Map' 'FieldName' ['NamelessField' ann]@ and @[['Section' ann]]@.+--+-- We need list of list of sections, because we need to distinguish situations+-- where there are fields in between. For example+--+-- @+-- if flag(bytestring-lt-0_10_4)+-- build-depends: bytestring < 0.10.4+--+-- default-language: Haskell2020+--+-- else+-- build-depends: bytestring >= 0.10.4+--+-- @+--+-- is obviously invalid specification.+--+-- We can parse 'Fields' like we parse @aeson@ objects, yet we use+-- slightly higher-level API, so we can process unspecified fields,+-- to report unknown fields and save custom @x-fields@.+--+module Distribution.FieldGrammar.Parsec (+ ParsecFieldGrammar,+ parseFieldGrammar,+ fieldGrammarKnownFieldList,+ -- * Auxiliary+ Fields,+ NamelessField (..),+ namelessFieldAnn,+ Section (..),+ runFieldParser,+ runFieldParser',+ fieldLinesToStream,+ ) where++import Data.List (dropWhileEnd)+import Distribution.Compat.Newtype+import Distribution.Compat.Prelude+import Distribution.Simple.Utils (fromUTF8BS)+import Prelude ()++import qualified Data.ByteString as BS+import qualified Data.List.NonEmpty as NE+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import qualified Distribution.Utils.ShortText as ShortText+import qualified Text.Parsec as P+import qualified Text.Parsec.Error as P++import Distribution.CabalSpecVersion+import Distribution.FieldGrammar.Class+import Distribution.Fields.Field+import Distribution.Fields.ParseResult+import Distribution.Parsec+import Distribution.Parsec.FieldLineStream+import Distribution.Parsec.Position (positionCol, positionRow)++-------------------------------------------------------------------------------+-- Auxiliary types+-------------------------------------------------------------------------------++type Fields ann = Map FieldName [NamelessField ann]++-- | Single field, without name, but with its annotation.+data NamelessField ann = MkNamelessField !ann [FieldLine ann]+ deriving (Eq, Show, Functor)++namelessFieldAnn :: NamelessField ann -> ann+namelessFieldAnn (MkNamelessField ann _) = ann++-- | The 'Section' constructor of 'Field'.+data Section ann = MkSection !(Name ann) [SectionArg ann] [Field ann]+ deriving (Eq, Show, Functor)++-------------------------------------------------------------------------------+-- ParsecFieldGrammar+-------------------------------------------------------------------------------++data ParsecFieldGrammar s a = ParsecFG+ { fieldGrammarKnownFields :: !(Set FieldName)+ , fieldGrammarKnownPrefixes :: !(Set FieldName)+ , fieldGrammarParser :: !(CabalSpecVersion -> Fields Position -> ParseResult a)+ }+ deriving (Functor)++parseFieldGrammar :: CabalSpecVersion -> Fields Position -> ParsecFieldGrammar s a -> ParseResult a+parseFieldGrammar v fields grammar = do+ for_ (Map.toList (Map.filterWithKey isUnknownField fields)) $ \(name, nfields) ->+ for_ nfields $ \(MkNamelessField pos _) ->+ parseWarning pos PWTUnknownField $ "Unknown field: " ++ show name+ -- TODO: fields allowed in this section++ -- parse+ fieldGrammarParser grammar v fields++ where+ isUnknownField k _ = not $+ k `Set.member` fieldGrammarKnownFields grammar+ || any (`BS.isPrefixOf` k) (fieldGrammarKnownPrefixes grammar)++fieldGrammarKnownFieldList :: ParsecFieldGrammar s a -> [FieldName]+fieldGrammarKnownFieldList = Set.toList . fieldGrammarKnownFields++instance Applicative (ParsecFieldGrammar s) where+ pure x = ParsecFG mempty mempty (\_ _ -> pure x)+ {-# INLINE pure #-}++ ParsecFG f f' f'' <*> ParsecFG x x' x'' = ParsecFG+ (mappend f x)+ (mappend f' x')+ (\v fields -> f'' v fields <*> x'' v fields)+ {-# INLINE (<*>) #-}++warnMultipleSingularFields :: FieldName -> [NamelessField Position] -> ParseResult ()+warnMultipleSingularFields _ [] = pure ()+warnMultipleSingularFields fn (x : xs) = do+ let pos = namelessFieldAnn x+ poss = map namelessFieldAnn xs+ parseWarning pos PWTMultipleSingularField $+ "The field " <> show fn <> " is specified more than once at positions " ++ intercalate ", " (map showPos (pos : poss))++instance FieldGrammar Parsec ParsecFieldGrammar where+ blurFieldGrammar _ (ParsecFG s s' parser) = ParsecFG s s' parser++ uniqueFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser+ where+ parser v fields = case Map.lookup fn fields of+ Nothing -> parseFatalFailure zeroPos $ show fn ++ " field missing"+ Just [] -> parseFatalFailure zeroPos $ show fn ++ " field missing"+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls) =+ unpack' _pack <$> runFieldParser pos parsec v fls++ booleanFieldDef fn _extract def = ParsecFG (Set.singleton fn) Set.empty parser+ where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure def+ Just [] -> pure def+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls) = runFieldParser pos parsec v fls++ optionalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser+ where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure Nothing+ Just [] -> pure Nothing+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls)+ | null fls = pure Nothing+ | otherwise = Just . unpack' _pack <$> runFieldParser pos parsec v fls++ optionalFieldDefAla fn _pack _extract def = ParsecFG (Set.singleton fn) Set.empty parser+ where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure def+ Just [] -> pure def+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls)+ | null fls = pure def+ | otherwise = unpack' _pack <$> runFieldParser pos parsec v fls++ freeTextField fn _ = ParsecFG (Set.singleton fn) Set.empty parser where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure Nothing+ Just [] -> pure Nothing+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls)+ | null fls = pure Nothing+ | v >= CabalSpecV3_0 = pure (Just (fieldlinesToFreeText3 pos fls))+ | otherwise = pure (Just (fieldlinesToFreeText fls))++ freeTextFieldDef fn _ = ParsecFG (Set.singleton fn) Set.empty parser where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure ""+ Just [] -> pure ""+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls)+ | null fls = pure ""+ | v >= CabalSpecV3_0 = pure (fieldlinesToFreeText3 pos fls)+ | otherwise = pure (fieldlinesToFreeText fls)++ -- freeTextFieldDefST = defaultFreeTextFieldDefST+ freeTextFieldDefST fn _ = ParsecFG (Set.singleton fn) Set.empty parser where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure mempty+ Just [] -> pure mempty+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls) = case fls of+ [] -> pure mempty+ [FieldLine _ bs] -> pure (ShortText.unsafeFromUTF8BS bs)+ _ | v >= CabalSpecV3_0 -> pure (ShortText.toShortText $ fieldlinesToFreeText3 pos fls)+ | otherwise -> pure (ShortText.toShortText $ fieldlinesToFreeText fls)++ monoidalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser+ where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure mempty+ Just xs -> foldMap (unpack' _pack) <$> traverse (parseOne v) xs++ parseOne v (MkNamelessField pos fls) = runFieldParser pos parsec v fls++ prefixedFields fnPfx _extract = ParsecFG mempty (Set.singleton fnPfx) (\_ fs -> pure (parser fs))+ where+ parser :: Fields Position -> [(String, String)]+ parser values = reorder $ concatMap convert $ filter match $ Map.toList values++ match (fn, _) = fnPfx `BS.isPrefixOf` fn+ convert (fn, fields) =+ [ (pos, (fromUTF8BS fn, trim $ fromUTF8BS $ fieldlinesToBS fls))+ | MkNamelessField pos fls <- fields+ ]+ -- hack: recover the order of prefixed fields+ reorder = map snd . sortBy (comparing fst)+ trim :: String -> String+ trim = dropWhile isSpace . dropWhileEnd isSpace++ availableSince vs def (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'+ where+ parser' v values+ | v >= vs = parser v values+ | otherwise = do+ let unknownFields = Map.intersection values $ Map.fromSet (const ()) names+ for_ (Map.toList unknownFields) $ \(name, fields) ->+ for_ fields $ \(MkNamelessField pos _) ->+ parseWarning pos PWTUnknownField $+ "The field " <> show name <> " is available only since the Cabal specification version " ++ showCabalSpecVersion vs ++ ". This field will be ignored."++ pure def++ availableSinceWarn vs (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'+ where+ parser' v values+ | v >= vs = parser v values+ | otherwise = do+ let unknownFields = Map.intersection values $ Map.fromSet (const ()) names+ for_ (Map.toList unknownFields) $ \(name, fields) ->+ for_ fields $ \(MkNamelessField pos _) ->+ parseWarning pos PWTUnknownField $+ "The field " <> show name <> " is available only since the Cabal specification version " ++ showCabalSpecVersion vs ++ "."++ parser v values+++ -- todo we know about this field+ deprecatedSince vs msg (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'+ where+ parser' v values+ | v >= vs = do+ let deprecatedFields = Map.intersection values $ Map.fromSet (const ()) names+ for_ (Map.toList deprecatedFields) $ \(name, fields) ->+ for_ fields $ \(MkNamelessField pos _) ->+ parseWarning pos PWTDeprecatedField $+ "The field " <> show name <> " is deprecated in the Cabal specification version " ++ showCabalSpecVersion vs ++ ". " ++ msg++ parser v values++ | otherwise = parser v values++ removedIn vs msg (ParsecFG names prefixes parser) = ParsecFG names prefixes parser' where+ parser' v values+ | v >= vs = do+ let msg' = if null msg then "" else ' ' : msg+ let unknownFields = Map.intersection values $ Map.fromSet (const ()) names+ let namePos =+ [ (name, pos)+ | (name, fields) <- Map.toList unknownFields+ , MkNamelessField pos _ <- fields+ ]++ let makeMsg name = "The field " <> show name <> " is removed in the Cabal specification version " ++ showCabalSpecVersion vs ++ "." ++ msg'++ case namePos of+ -- no fields => proceed (with empty values, to be sure)+ [] -> parser v mempty++ -- if there's single field: fail fatally with it+ ((name, pos) : rest) -> do+ for_ rest $ \(name', pos') -> parseFailure pos' $ makeMsg name'+ parseFatalFailure pos $ makeMsg name++ | otherwise = parser v values++ knownField fn = ParsecFG (Set.singleton fn) Set.empty (\_ _ -> pure ())++ hiddenField = id++-------------------------------------------------------------------------------+-- Parsec+-------------------------------------------------------------------------------++runFieldParser' :: [Position] -> ParsecParser a -> CabalSpecVersion -> FieldLineStream -> ParseResult a+runFieldParser' inputPoss p v str = case P.runParser p' [] "<field>" str of+ Right (pok, ws) -> do+ traverse_ (\(PWarning t pos w) -> parseWarning (mapPosition pos) t w) ws+ pure pok+ Left err -> do+ let ppos = P.errorPos err+ let epos = mapPosition $ Position (P.sourceLine ppos) (P.sourceColumn ppos)++ let msg = P.showErrorMessages+ "or" "unknown parse error" "expecting" "unexpected" "end of input"+ (P.errorMessages err)+ parseFatalFailure epos $ msg ++ "\n"+ where+ p' = (,) <$ P.spaces <*> unPP p v <* P.spaces <* P.eof <*> P.getState++ -- Positions start from 1:1, not 0:0+ mapPosition (Position prow pcol) = go (prow - 1) inputPoss where+ go _ [] = zeroPos+ go _ [Position row col] = Position row (col + pcol - 1)+ go n (Position row col:_) | n <= 0 = Position row (col + pcol - 1)+ go n (_:ps) = go (n - 1) ps++runFieldParser :: Position -> ParsecParser a -> CabalSpecVersion -> [FieldLine Position] -> ParseResult a+runFieldParser pp p v ls = runFieldParser' poss p v (fieldLinesToStream ls)+ where+ poss = map (\(FieldLine pos _) -> pos) ls ++ [pp] -- add "default" position++fieldlinesToBS :: [FieldLine ann] -> BS.ByteString+fieldlinesToBS = BS.intercalate "\n" . map (\(FieldLine _ bs) -> bs)++-- Example package with dot lines+-- http://hackage.haskell.org/package/copilot-cbmc-0.1/copilot-cbmc.cabal+fieldlinesToFreeText :: [FieldLine ann] -> String+fieldlinesToFreeText [FieldLine _ "."] = "."+fieldlinesToFreeText fls = intercalate "\n" (map go fls)+ where+ go (FieldLine _ bs)+ | s == "." = ""+ | otherwise = s+ where+ s = trim (fromUTF8BS bs)++ trim :: String -> String+ trim = dropWhile isSpace . dropWhileEnd isSpace++fieldlinesToFreeText3 :: Position -> [FieldLine Position] -> String+fieldlinesToFreeText3 _ [] = ""+fieldlinesToFreeText3 _ [FieldLine _ bs] = fromUTF8BS bs+fieldlinesToFreeText3 pos (FieldLine pos1 bs1 : fls2@(FieldLine pos2 _ : _))+ -- if first line is on the same line with field name:+ -- the indentation level is either+ -- 1. the indentation of left most line in rest fields+ -- 2. the indentation of the first line+ -- whichever is leftmost+ | positionRow pos == positionRow pos1 = concat+ $ fromUTF8BS bs1+ : mealy (mk mcol1) pos1 fls2++ -- otherwise, also indent the first line+ | otherwise = concat+ $ replicate (positionCol pos1 - mcol2) ' '+ : fromUTF8BS bs1+ : mealy (mk mcol2) pos1 fls2++ where+ mcol1 = foldl' (\a b -> min a $ positionCol $ fieldLineAnn b) (min (positionCol pos1) (positionCol pos2)) fls2+ mcol2 = foldl' (\a b -> min a $ positionCol $ fieldLineAnn b) (positionCol pos1) fls2++ mk :: Int -> Position -> FieldLine Position -> (Position, String)+ mk col p (FieldLine q bs) =+ ( q+ , replicate newlines '\n'+ ++ replicate indent ' '+ ++ fromUTF8BS bs+ )+ where+ newlines = positionRow q - positionRow p+ indent = positionCol q - col++mealy :: (s -> a -> (s, b)) -> s -> [a] -> [b]+mealy f = go where+ go _ [] = []+ go s (x : xs) = let ~(s', y) = f s x in y : go s' xs++fieldLinesToStream :: [FieldLine ann] -> FieldLineStream+fieldLinesToStream [] = fieldLineStreamEnd+fieldLinesToStream [FieldLine _ bs] = FLSLast bs+fieldLinesToStream (FieldLine _ bs : fs) = FLSCons bs (fieldLinesToStream fs)
+ src/Distribution/FieldGrammar/Pretty.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module Distribution.FieldGrammar.Pretty (+ PrettyFieldGrammar,+ prettyFieldGrammar,+ ) where++import Distribution.CabalSpecVersion+import Distribution.Compat.Lens+import Distribution.Compat.Newtype+import Distribution.Compat.Prelude+import Distribution.Fields.Field (FieldName)+import Distribution.Fields.Pretty (PrettyField (..))+import Distribution.Pretty (Pretty (..), showFreeText, showFreeTextV3)+import Distribution.Simple.Utils (toUTF8BS)+import Prelude ()+import Text.PrettyPrint (Doc)+import qualified Text.PrettyPrint as PP++import Distribution.FieldGrammar.Class++newtype PrettyFieldGrammar s a = PrettyFG+ { fieldGrammarPretty :: CabalSpecVersion -> s -> [PrettyField ()]+ }+ deriving (Functor)++instance Applicative (PrettyFieldGrammar s) where+ pure _ = PrettyFG (\_ _ -> mempty)+ PrettyFG f <*> PrettyFG x = PrettyFG (\v s -> f v s <> x v s)++-- | We can use 'PrettyFieldGrammar' to pp print the @s@.+--+-- /Note:/ there is not trailing @($+$ text "")@.+prettyFieldGrammar :: CabalSpecVersion -> PrettyFieldGrammar s a -> s -> [PrettyField ()]+prettyFieldGrammar = flip fieldGrammarPretty++instance FieldGrammar Pretty PrettyFieldGrammar where+ blurFieldGrammar f (PrettyFG pp) = PrettyFG (\v -> pp v . aview f)++ uniqueFieldAla fn _pack l = PrettyFG $ \_v s ->+ ppField fn (pretty (pack' _pack (aview l s)))++ booleanFieldDef fn l def = PrettyFG pp+ where+ pp _v s+ | b == def = mempty+ | otherwise = ppField fn (PP.text (show b))+ where+ b = aview l s++ optionalFieldAla fn _pack l = PrettyFG pp+ where+ pp v s = case aview l s of+ Nothing -> mempty+ Just a -> ppField fn (prettyVersioned v (pack' _pack a))++ optionalFieldDefAla fn _pack l def = PrettyFG pp+ where+ pp v s+ | x == def = mempty+ | otherwise = ppField fn (prettyVersioned v (pack' _pack x))+ where+ x = aview l s++ freeTextField fn l = PrettyFG pp where+ pp v s = maybe mempty (ppField fn . showFT) (aview l s) where+ showFT | v >= CabalSpecV3_0 = showFreeTextV3+ | otherwise = showFreeText++ -- it's ok to just show, as showFreeText of empty string is empty.+ freeTextFieldDef fn l = PrettyFG pp where+ pp v s = ppField fn (showFT (aview l s)) where+ showFT | v >= CabalSpecV3_0 = showFreeTextV3+ | otherwise = showFreeText++ freeTextFieldDefST = defaultFreeTextFieldDefST++ monoidalFieldAla fn _pack l = PrettyFG pp+ where+ pp v s = ppField fn (prettyVersioned v (pack' _pack (aview l s)))++ prefixedFields _fnPfx l = PrettyFG (\_ -> pp . aview l)+ where+ pp xs =+ -- always print the field, even its Doc is empty.+ -- i.e. don't use ppField+ [ PrettyField () (toUTF8BS n) $ PP.vcat $ map PP.text $ lines s+ | (n, s) <- xs+ -- fnPfx `isPrefixOf` n+ ]++ knownField _ = pure ()+ deprecatedSince _ _ x = x+ -- TODO: as PrettyFieldGrammar isn't aware of cabal-version: we output the field+ -- this doesn't affect roundtrip as `removedIn` fields cannot be parsed+ -- so invalid documents can be only manually constructed.+ removedIn _ _ x = x+ availableSince _ _ = id+ hiddenField _ = PrettyFG (\_ -> mempty)++ppField :: FieldName -> Doc -> [PrettyField ()]+ppField name fielddoc+ | PP.isEmpty fielddoc = []+ | otherwise = [ PrettyField () name fielddoc ]
+ src/Distribution/Fields.hs view
@@ -0,0 +1,42 @@+-- | Utilitiies to work with @.cabal@ like file structure.+module Distribution.Fields (+ -- * Types+ Field(..),+ Name(..),+ FieldLine(..),+ SectionArg(..),+ FieldName,+ -- * Grammar and parsing+ --+ -- See "Distribution.Fields.Parser" for grammar.+ readFields,+ readFields',+ -- ** ParseResult+ ParseResult,+ runParseResult,+ parseString,+ parseWarning,+ parseWarnings,+ parseFailure,+ parseFatalFailure,+ -- ** Warnings+ PWarnType (..),+ PWarning (..),+ showPWarning,+ -- ** Errors+ PError (..),+ showPError,+ -- * Pretty printing+ PrettyField (..),+ showFields,+ -- ** Transformation from Field+ genericFromParsecFields,+ fromParsecFields,+ ) where++import Distribution.Fields.Field+import Distribution.Fields.Parser+import Distribution.Fields.ParseResult+import Distribution.Fields.Pretty+import Distribution.Parsec.Error+import Distribution.Parsec.Warning
+ src/Distribution/Fields/ConfVar.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE OverloadedStrings #-}+module Distribution.Fields.ConfVar (parseConditionConfVar) where++import Distribution.Compat.CharParsing (char, integral)+import Distribution.Compat.Prelude+import Distribution.Fields.Field (SectionArg (..))+import Distribution.Fields.ParseResult+import Distribution.Parsec (Parsec (..), Position (..), runParsecParser)+import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS)+import Distribution.Types.Condition+import Distribution.Types.ConfVar (ConfVar (..))+import Distribution.Version+ (anyVersion, earlierVersion, intersectVersionRanges, laterVersion, majorBoundVersion,+ mkVersion, noVersion, orEarlierVersion, orLaterVersion, thisVersion, unionVersionRanges,+ withinVersion)+import Prelude ()++import qualified Text.Parsec as P+import qualified Text.Parsec.Error as P++-- | Parse @'Condition' 'ConfVar'@ from section arguments provided by parsec+-- based outline parser.+parseConditionConfVar :: [SectionArg Position] -> ParseResult (Condition ConfVar)+parseConditionConfVar args =+ -- The name of the input file is irrelevant, as we reformat the error message.+ case P.runParser (parser <* P.eof) () "<condition>" args of+ Right x -> pure x+ Left err -> do+ -- Mangle the position to the actual one+ let ppos = P.errorPos err+ let epos = Position (P.sourceLine ppos) (P.sourceColumn ppos)+ let msg = P.showErrorMessages+ "or" "unknown parse error" "expecting" "unexpected" "end of input"+ (P.errorMessages err)+ parseFailure epos msg+ pure $ Lit True++type Parser = P.Parsec [SectionArg Position] ()++sepByNonEmpty :: Parser a -> Parser sep -> Parser (NonEmpty a)+sepByNonEmpty p sep = (:|) <$> p <*> many (sep *> p)++parser :: Parser (Condition ConfVar)+parser = condOr+ where+ condOr = sepByNonEmpty condAnd (oper "||") >>= return . foldl1 COr+ condAnd = sepByNonEmpty cond (oper "&&") >>= return . foldl1 CAnd+ cond = P.choice+ [ boolLiteral, parens condOr, notCond, osCond, archCond, flagCond, implCond ]++ notCond = CNot <$ oper "!" <*> cond++ boolLiteral = Lit <$> boolLiteral'+ osCond = Var . OS <$ string "os" <*> parens fromParsec+ flagCond = Var . PackageFlag <$ string "flag" <*> parens fromParsec+ archCond = Var . Arch <$ string "arch" <*> parens fromParsec+ implCond = Var <$ string "impl" <*> parens implCond'++ implCond' = Impl+ <$> fromParsec+ <*> P.option anyVersion versionRange++ version = fromParsec+ versionStar = mkVersion <$> fromParsec' versionStar' <* oper "*"+ versionStar' = some (integral <* char '.')++ versionRange = expr+ where+ expr = foldl1 unionVersionRanges <$> sepByNonEmpty term (oper "||")+ term = foldl1 intersectVersionRanges <$> sepByNonEmpty factor (oper "&&")++ factor = P.choice+ $ parens expr+ : parseAnyVersion+ : parseNoVersion+ : parseWildcardRange+ : map parseRangeOp rangeOps++ parseAnyVersion = anyVersion <$ string "-any"+ parseNoVersion = noVersion <$ string "-none"++ parseWildcardRange = P.try $ withinVersion <$ oper "==" <*> versionStar++ parseRangeOp (s,f) = P.try (f <$ oper s <*> version)+ rangeOps = [ ("<", earlierVersion),+ ("<=", orEarlierVersion),+ (">", laterVersion),+ (">=", orLaterVersion),+ ("^>=", majorBoundVersion),+ ("==", thisVersion) ]++ -- Number token can have many dots in it: SecArgNum (Position 65 15) "7.6.1"+ identBS = tokenPrim $ \t -> case t of+ SecArgName _ s -> Just s+ _ -> Nothing++ boolLiteral' = tokenPrim $ \t -> case t of+ SecArgName _ s+ | s == "True" -> Just True+ | s == "true" -> Just True+ | s == "False" -> Just False+ | s == "false" -> Just False+ _ -> Nothing++ string s = tokenPrim $ \t -> case t of+ SecArgName _ s' | s == s' -> Just ()+ _ -> Nothing++ oper o = tokenPrim $ \t -> case t of+ SecArgOther _ o' | o == o' -> Just ()+ _ -> Nothing++ parens = P.between (oper "(") (oper ")")++ tokenPrim = P.tokenPrim prettySectionArg updatePosition+ -- TODO: check where the errors are reported+ updatePosition x _ _ = x+ prettySectionArg = show++ fromParsec :: Parsec a => Parser a+ fromParsec = fromParsec' parsec++ fromParsec' p = do+ bs <- identBS+ let fls = fieldLineStreamFromBS bs+ either (fail . show) pure (runParsecParser p "<fromParsec'>" fls)
+ src/Distribution/Fields/Field.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+-- | Cabal-like file AST types: 'Field', 'Section' etc+--+-- These types are parametrized by an annotation.+module Distribution.Fields.Field (+ -- * Cabal file+ Field (..),+ fieldName,+ fieldAnn,+ fieldUniverse,+ FieldLine (..),+ fieldLineAnn,+ fieldLineBS,+ SectionArg (..),+ sectionArgAnn,+ -- * Name+ FieldName,+ Name (..),+ mkName,+ getName,+ nameAnn,+ -- * Conversions to String+ sectionArgsToString,+ fieldLinesToString,+ ) where++import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as B+import qualified Data.Char as Char+import Distribution.Compat.Prelude+import Distribution.Pretty (showTokenStr)+import Distribution.Simple.Utils (fromUTF8BS)+import Prelude ()+++-------------------------------------------------------------------------------+-- Cabal file+-------------------------------------------------------------------------------++-- | A Cabal-like file consists of a series of fields (@foo: bar@) and sections (@library ...@).+data Field ann+ = Field !(Name ann) [FieldLine ann]+ | Section !(Name ann) [SectionArg ann] [Field ann]+ deriving (Eq, Show, Functor, Foldable, Traversable)++-- | Section of field name+fieldName :: Field ann -> Name ann+fieldName (Field n _ ) = n+fieldName (Section n _ _) = n++fieldAnn :: Field ann -> ann+fieldAnn = nameAnn . fieldName++-- | All transitive descendants of 'Field', including itself.+--+-- /Note:/ the resulting list is never empty.+--+fieldUniverse :: Field ann -> [Field ann]+fieldUniverse f@(Section _ _ fs) = f : concatMap fieldUniverse fs+fieldUniverse f@(Field _ _) = [f]++-- | A line of text representing the value of a field from a Cabal file.+-- A field may contain multiple lines.+--+-- /Invariant:/ 'ByteString' has no newlines.+data FieldLine ann = FieldLine !ann !ByteString+ deriving (Eq, Show, Functor, Foldable, Traversable)++-- | @since 3.0.0.0+fieldLineAnn :: FieldLine ann -> ann+fieldLineAnn (FieldLine ann _) = ann++-- | @since 3.0.0.0+fieldLineBS :: FieldLine ann -> ByteString+fieldLineBS (FieldLine _ bs) = bs++-- | Section arguments, e.g. name of the library+data SectionArg ann+ = SecArgName !ann !ByteString+ -- ^ identifier, or something which looks like number. Also many dot numbers, i.e. "7.6.3"+ | SecArgStr !ann !ByteString+ -- ^ quoted string+ | SecArgOther !ann !ByteString+ -- ^ everything else, mm. operators (e.g. in if-section conditionals)+ deriving (Eq, Show, Functor, Foldable, Traversable)++-- | Extract annotation from 'SectionArg'.+sectionArgAnn :: SectionArg ann -> ann+sectionArgAnn (SecArgName ann _) = ann+sectionArgAnn (SecArgStr ann _) = ann+sectionArgAnn (SecArgOther ann _) = ann++-------------------------------------------------------------------------------+-- Name+-------------------------------------------------------------------------------++type FieldName = ByteString++-- | A field name.+--+-- /Invariant/: 'ByteString' is lower-case ASCII.+data Name ann = Name !ann !FieldName+ deriving (Eq, Show, Functor, Foldable, Traversable)++mkName :: ann -> FieldName -> Name ann+mkName ann bs = Name ann (B.map Char.toLower bs)++getName :: Name ann -> FieldName+getName (Name _ bs) = bs++nameAnn :: Name ann -> ann+nameAnn (Name ann _) = ann++-------------------------------------------------------------------------------+-- To Strings+-------------------------------------------------------------------------------++-- |+--+-- @since 3.6.0.0+sectionArgsToString :: [SectionArg ann] -> String+sectionArgsToString = unwords . map toStr where+ toStr :: SectionArg ann -> String+ toStr (SecArgName _ bs) = showTokenStr (fromUTF8BS bs)+ toStr (SecArgStr _ bs) = showTokenStr (fromUTF8BS bs)+ toStr (SecArgOther _ bs) = fromUTF8BS bs++-- | Convert @['FieldLine']@ into String.+--+-- /Note:/ this doesn't preserve indentation or empty lines,+-- as the annotations (e.g. positions) are ignored.+--+-- @since 3.6.0.0+fieldLinesToString :: [FieldLine ann] -> String+fieldLinesToString =+ -- intercalate to avoid trailing newline.+ intercalate "\n" . map toStr+ where+ toStr (FieldLine _ bs) = fromUTF8BS bs
+ src/Distribution/Fields/Lexer.hs view
@@ -0,0 +1,496 @@+{-# OPTIONS_GHC -fno-warn-unused-binds -fno-warn-missing-signatures #-}+{-# LANGUAGE CPP,MagicHash #-}+{-# LINE 1 "templates/Lexer.x" #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Fields.Lexer+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Lexer for the cabal files.+{-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-}+#ifdef CABAL_PARSEC_DEBUG+{-# LANGUAGE PatternGuards #-}+#endif+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Distribution.Fields.Lexer+ (ltest, lexToken, Token(..), LToken(..)+ ,bol_section, in_section, in_field_layout, in_field_braces+ ,mkLexState) where++-- [Note: boostrapping parsec parser]+--+-- We manually produce the `Lexer.hs` file from `boot/Lexer.x` (make lexer)+-- because boostrapping cabal-install would be otherwise tricky.+-- Alex is (atm) tricky package to build, cabal-install has some magic+-- to move bundled generated files in place, so rather we don't depend+-- on it before we can build it ourselves.+-- Therefore there is one thing less to worry in bootstrap.sh, which is a win.+--+-- See also https://github.com/haskell/cabal/issues/4633+--++import Prelude ()+import qualified Prelude as Prelude+import Distribution.Compat.Prelude++import Distribution.Fields.LexerMonad+import Distribution.Parsec.Position (Position (..), incPos, retPos)+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B.Char8+import qualified Data.Word as Word++#ifdef CABAL_PARSEC_DEBUG+import Debug.Trace+import qualified Data.Vector as V+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Encoding.Error as T+#endif++#if __GLASGOW_HASKELL__ >= 603+#include "ghcconfig.h"+#elif defined(__GLASGOW_HASKELL__)+#include "config.h"+#endif+#if __GLASGOW_HASKELL__ >= 503+import Data.Array+#else+import Array+#endif+#if __GLASGOW_HASKELL__ >= 503+import Data.Array.Base (unsafeAt)+import GHC.Exts+#else+import GlaExts+#endif+alex_tab_size :: Int+alex_tab_size = 8+alex_base :: AlexAddr+alex_base = AlexA#+ "\x12\xff\xff\xff\xf9\xff\xff\xff\xfb\xff\xff\xff\x01\x00\x00\x00\x2f\x00\x00\x00\x50\x00\x00\x00\xd0\x00\x00\x00\x48\xff\xff\xff\xdc\xff\xff\xff\x51\xff\xff\xff\x6d\xff\xff\xff\x6f\xff\xff\xff\x50\x01\x00\x00\x74\x01\x00\x00\x70\xff\xff\xff\x68\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\xa3\x01\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6a\x00\x00\x00\xd1\x01\x00\x00\xfb\x01\x00\x00\x7b\x02\x00\x00\xfb\x02\x00\x00\x00\x00\x00\x00\x7b\x03\x00\x00\x7d\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x6d\x00\x00\x00\x6b\x00\x00\x00\xfc\x03\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x6f\x00\x00\x00\x1c\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00"#++alex_table :: AlexAddr+alex_table = AlexA#+ "\x00\x00\x09\x00\x0f\x00\x11\x00\x02\x00\x11\x00\x12\x00\x00\x00\x12\x00\x13\x00\x03\x00\x11\x00\x07\x00\x10\x00\x12\x00\x25\x00\x14\x00\x11\x00\x10\x00\x11\x00\x14\x00\x11\x00\x12\x00\x23\x00\x12\x00\x0f\x00\x28\x00\x02\x00\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x08\x00\x10\x00\x00\x00\x14\x00\x00\x00\x00\x00\x08\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2a\x00\x2e\x00\xff\xff\xff\xff\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x26\x00\x28\x00\xff\xff\xff\xff\x29\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x26\x00\x0f\x00\x11\x00\x17\x00\x26\x00\x12\x00\x25\x00\x11\x00\x2a\x00\x00\x00\x12\x00\x00\x00\x15\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x17\x00\x26\x00\x00\x00\x25\x00\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2c\x00\x00\x00\x2d\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0e\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x17\x00\x23\x00\xff\xff\xff\xff\x24\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x17\x00\x1e\x00\x0d\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x1f\x00\x1f\x00\x1e\x00\x1e\x00\x1e\x00\x19\x00\x1a\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x1f\x00\x1e\x00\x1f\x00\x1e\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x21\x00\x1e\x00\x22\x00\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x1d\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1e\x00\xff\xff\x1e\x00\x1e\x00\x1e\x00\x1e\x00\xff\xff\xff\xff\xff\xff\x1e\x00\x1e\x00\x1e\x00\x18\x00\x1a\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1e\x00\xff\xff\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\xff\xff\xff\xff\x1e\x00\x1e\x00\x1e\x00\x1a\x00\x1a\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x1e\x00\xff\xff\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x1c\x00\x1e\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\xff\xff\x1e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#++alex_check :: AlexAddr+alex_check = AlexA#+ "\xff\xff\xef\x00\x09\x00\x0a\x00\x09\x00\x0a\x00\x0d\x00\xbf\x00\x0d\x00\x2d\x00\x09\x00\x0a\x00\xbb\x00\xa0\x00\x0d\x00\xa0\x00\xa0\x00\x0a\x00\x09\x00\x0a\x00\x09\x00\x0a\x00\x0d\x00\x0a\x00\x0d\x00\x20\x00\x0a\x00\x20\x00\x0a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\x2d\x00\x20\x00\xff\xff\x20\x00\xff\xff\xff\xff\x2d\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x09\x00\x0a\x00\x09\x00\x09\x00\x0d\x00\x09\x00\x0a\x00\x09\x00\xff\xff\x0d\x00\xff\xff\x7b\x00\xff\xff\x7d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x20\x00\x20\x00\xff\xff\x20\x00\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x2d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\xff\xff\x7d\x00\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\xff\xff\xc2\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\xff\xff\xc2\x00\xff\xff\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xc2\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x22\x00\xff\xff\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x22\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x5c\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x5c\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\xff\xff\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x7f\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\xff\xff\xff\xff\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3a\x00\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5b\x00\x5c\x00\x5d\x00\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\x22\x00\x21\x00\xff\xff\x23\x00\x24\x00\x25\x00\x26\x00\xff\xff\xff\xff\xff\xff\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x5c\x00\xff\xff\x5c\x00\xff\xff\x5e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7c\x00\x7f\x00\x7e\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\xff\xff\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\xff\xff\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7b\x00\xff\xff\x7d\x00\xff\xff\x7f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#++alex_deflt :: AlexAddr+alex_deflt = AlexA#+ "\xff\xff\xff\xff\xff\xff\xff\xff\x2b\x00\x27\x00\x1b\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x13\x00\xff\xff\xff\xff\xff\xff\xff\xff\x18\x00\x1b\x00\x1b\x00\x1b\x00\xff\xff\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\x2b\x00\xff\xff\xff\xff\xff\xff\xff\xff"#++alex_accept = listArray (0 :: Int, 47)+ [ AlexAcc 29+ , AlexAcc 28+ , AlexAcc 27+ , AlexAcc 26+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAccNone+ , AlexAcc 25+ , AlexAcc 24+ , AlexAccSkip+ , AlexAcc 23+ , AlexAcc 22+ , AlexAcc 21+ , AlexAccSkip+ , AlexAccSkip+ , AlexAcc 20+ , AlexAcc 19+ , AlexAcc 18+ , AlexAcc 17+ , AlexAcc 16+ , AlexAcc 15+ , AlexAcc 14+ , AlexAcc 13+ , AlexAcc 12+ , AlexAcc 11+ , AlexAcc 10+ , AlexAcc 9+ , AlexAcc 8+ , AlexAccSkip+ , AlexAcc 7+ , AlexAcc 6+ , AlexAcc 5+ , AlexAccSkip+ , AlexAcc 4+ , AlexAcc 3+ , AlexAcc 2+ , AlexAcc 1+ , AlexAcc 0+ ]++alex_actions = array (0 :: Int, 30)+ [ (29,alex_action_0)+ , (28,alex_action_20)+ , (27,alex_action_16)+ , (26,alex_action_3)+ , (25,alex_action_1)+ , (24,alex_action_1)+ , (23,alex_action_3)+ , (22,alex_action_4)+ , (21,alex_action_5)+ , (20,alex_action_8)+ , (19,alex_action_8)+ , (18,alex_action_8)+ , (17,alex_action_9)+ , (16,alex_action_9)+ , (15,alex_action_10)+ , (14,alex_action_11)+ , (13,alex_action_12)+ , (12,alex_action_13)+ , (11,alex_action_14)+ , (10,alex_action_15)+ , (9,alex_action_15)+ , (8,alex_action_16)+ , (7,alex_action_18)+ , (6,alex_action_19)+ , (5,alex_action_19)+ , (4,alex_action_22)+ , (3,alex_action_23)+ , (2,alex_action_24)+ , (1,alex_action_25)+ , (0,alex_action_25)+ ]++{-# LINE 151 "templates/Lexer.x" #-}++-- | Tokens of outer cabal file structure. Field values are treated opaquely.+data Token = TokSym !ByteString -- ^ Haskell-like identifier, number or operator+ | TokStr !ByteString -- ^ String in quotes+ | TokOther !ByteString -- ^ Operators and parens+ | Indent !Int -- ^ Indentation token+ | TokFieldLine !ByteString -- ^ Lines after @:@+ | Colon+ | OpenBrace+ | CloseBrace+ | EOF+ | LexicalError InputStream --TODO: add separate string lexical error+ deriving Show++data LToken = L !Position !Token+ deriving Show++toki :: (ByteString -> Token) -> Position -> Int -> ByteString -> Lex LToken+toki t pos len input = return $! L pos (t (B.take len input))++tok :: Token -> Position -> Int -> ByteString -> Lex LToken+tok t pos _len _input = return $! L pos t++checkLeadingWhitespace :: Int -> ByteString -> Lex Int+checkLeadingWhitespace len bs+ | B.any (== 9) (B.take len bs) = do+ addWarning LexWarningTab+ checkWhitespace len bs+ | otherwise = checkWhitespace len bs++checkWhitespace :: Int -> ByteString -> Lex Int+checkWhitespace len bs+ | B.any (== 194) (B.take len bs) = do+ addWarning LexWarningNBSP+ return $ len - B.count 194 (B.take len bs)+ | otherwise = return len++-- -----------------------------------------------------------------------------+-- The input type++type AlexInput = InputStream++alexInputPrevChar :: AlexInput -> Char+alexInputPrevChar _ = error "alexInputPrevChar not used"++alexGetByte :: AlexInput -> Maybe (Word.Word8,AlexInput)+alexGetByte = B.uncons++lexicalError :: Position -> InputStream -> Lex LToken+lexicalError pos inp = do+ setInput B.empty+ return $! L pos (LexicalError inp)++lexToken :: Lex LToken+lexToken = do+ pos <- getPos+ inp <- getInput+ st <- getStartCode+ case alexScan inp st of+ AlexEOF -> return (L pos EOF)+ AlexError inp' ->+ let !len_bytes = B.length inp - B.length inp' in+ --FIXME: we want len_chars here really+ -- need to decode utf8 up to this point+ lexicalError (incPos len_bytes pos) inp'+ AlexSkip inp' len_chars -> do+ checkPosition pos inp inp' len_chars+ adjustPos (incPos len_chars)+ setInput inp'+ lexToken+ AlexToken inp' len_chars action -> do+ checkPosition pos inp inp' len_chars+ adjustPos (incPos len_chars)+ setInput inp'+ let !len_bytes = B.length inp - B.length inp'+ t <- action pos len_bytes inp+ --traceShow t $ return tok+ return t++checkPosition :: Position -> ByteString -> ByteString -> Int -> Lex ()+#ifdef CABAL_PARSEC_DEBUG+checkPosition pos@(Position lineno colno) inp inp' len_chars = do+ text_lines <- getDbgText+ let len_bytes = B.length inp - B.length inp'+ pos_txt | lineno-1 < V.length text_lines = T.take len_chars (T.drop (colno-1) (text_lines V.! (lineno-1)))+ | otherwise = T.empty+ real_txt = B.take len_bytes inp+ when (pos_txt /= T.decodeUtf8 real_txt) $+ traceShow (pos, pos_txt, T.decodeUtf8 real_txt) $+ traceShow (take 3 (V.toList text_lines)) $ return ()+ where+ getDbgText = Lex $ \s@LexState{ dbgText = txt } -> LexResult s txt+#else+checkPosition _ _ _ _ = return ()+#endif++lexAll :: Lex [LToken]+lexAll = do+ t <- lexToken+ case t of+ L _ EOF -> return [t]+ _ -> do ts <- lexAll+ return (t : ts)++ltest :: Int -> String -> Prelude.IO ()+ltest code s =+ let (ws, xs) = execLexer (setStartCode code >> lexAll) (B.Char8.pack s)+ in traverse_ print ws >> traverse_ print xs++mkLexState :: ByteString -> LexState+mkLexState input = LexState+ { curPos = Position 1 1+ , curInput = input+ , curCode = 0+ , warnings = []+#ifdef CABAL_PARSEC_DEBUG+ , dbgText = V.fromList . lines' . T.decodeUtf8With T.lenientDecode $ input+#endif+ }++#ifdef CABAL_PARSEC_DEBUG+lines' :: T.Text -> [T.Text]+lines' s1+ | T.null s1 = []+ | otherwise = case T.break (\c -> c == '\r' || c == '\n') s1 of+ (l, s2) | Just (c,s3) <- T.uncons s2+ -> case T.uncons s3 of+ Just ('\n', s4) | c == '\r' -> l `T.snoc` '\r' `T.snoc` '\n' : lines' s4+ _ -> l `T.snoc` c : lines' s3++ | otherwise+ -> [l]+#endif++bol_field_braces,bol_field_layout,bol_section,in_field_braces,in_field_layout,in_section :: Int+bol_field_braces = 1+bol_field_layout = 2+bol_section = 3+in_field_braces = 4+in_field_layout = 5+in_section = 6+alex_action_0 = \_ len _ -> do+ when (len /= 0) $ addWarning LexWarningBOM+ setStartCode bol_section+ lexToken+ +alex_action_1 = \_pos len inp -> checkWhitespace len inp >> adjustPos retPos >> lexToken +alex_action_3 = \pos len inp -> checkLeadingWhitespace len inp >>+ if B.length inp == len+ then return (L pos EOF)+ else setStartCode in_section+ >> return (L pos (Indent len)) +alex_action_4 = tok OpenBrace +alex_action_5 = tok CloseBrace +alex_action_8 = toki TokSym +alex_action_9 = \pos len inp -> return $! L pos (TokStr (B.take (len - 2) (B.tail inp))) +alex_action_10 = toki TokOther +alex_action_11 = toki TokOther +alex_action_12 = tok Colon +alex_action_13 = tok OpenBrace +alex_action_14 = tok CloseBrace +alex_action_15 = \_ _ _ -> adjustPos retPos >> setStartCode bol_section >> lexToken +alex_action_16 = \pos len inp -> checkLeadingWhitespace len inp >>= \len' ->+ if B.length inp == len+ then return (L pos EOF)+ else setStartCode in_field_layout+ >> return (L pos (Indent len')) +alex_action_18 = toki TokFieldLine +alex_action_19 = \_ _ _ -> adjustPos retPos >> setStartCode bol_field_layout >> lexToken +alex_action_20 = \_ _ _ -> setStartCode in_field_braces >> lexToken +alex_action_22 = toki TokFieldLine +alex_action_23 = tok OpenBrace +alex_action_24 = tok CloseBrace +alex_action_25 = \_ _ _ -> adjustPos retPos >> setStartCode bol_field_braces >> lexToken +{-# LINE 1 "templates/GenericTemplate.hs" #-}+-- -----------------------------------------------------------------------------+-- ALEX TEMPLATE+--+-- This code is in the PUBLIC DOMAIN; you may copy it freely and use+-- it for any purpose whatsoever.++-- -----------------------------------------------------------------------------+-- INTERNALS and main scanner engine++-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.+#if __GLASGOW_HASKELL__ > 706+#define GTE(n,m) (tagToEnum# (n >=# m))+#define EQ(n,m) (tagToEnum# (n ==# m))+#else+#define GTE(n,m) (n >=# m)+#define EQ(n,m) (n ==# m)+#endif++data AlexAddr = AlexA# Addr#+-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.+#if __GLASGOW_HASKELL__ < 503+uncheckedShiftL# = shiftL#+#endif++{-# INLINE alexIndexInt16OffAddr #-}+alexIndexInt16OffAddr :: AlexAddr -> Int# -> Int#+alexIndexInt16OffAddr (AlexA# arr) off =+#ifdef WORDS_BIGENDIAN+ narrow16Int# i+ where+ i = word2Int# ((high `uncheckedShiftL#` 8#) `or#` low)+ high = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))+ low = int2Word# (ord# (indexCharOffAddr# arr off'))+ off' = off *# 2#+#else+#if __GLASGOW_HASKELL__ >= 901+ int16ToInt#+#endif+ (indexInt16OffAddr# arr off)+#endif++{-# INLINE alexIndexInt32OffAddr #-}+alexIndexInt32OffAddr :: AlexAddr -> Int# -> Int#+alexIndexInt32OffAddr (AlexA# arr) off =+#ifdef WORDS_BIGENDIAN+ narrow32Int# i+ where+ i = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#`+ (b2 `uncheckedShiftL#` 16#) `or#`+ (b1 `uncheckedShiftL#` 8#) `or#` b0)+ b3 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#)))+ b2 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#)))+ b1 = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))+ b0 = int2Word# (ord# (indexCharOffAddr# arr off'))+ off' = off *# 4#+#else+#if __GLASGOW_HASKELL__ >= 901+ int32ToInt#+#endif+ (indexInt32OffAddr# arr off)+#endif++#if __GLASGOW_HASKELL__ < 503+quickIndex arr i = arr ! i+#else+-- GHC >= 503, unsafeAt is available from Data.Array.Base.+quickIndex = unsafeAt+#endif++-- -----------------------------------------------------------------------------+-- Main lexing routines++data AlexReturn a+ = AlexEOF+ | AlexError !AlexInput+ | AlexSkip !AlexInput !Int+ | AlexToken !AlexInput !Int a++-- alexScan :: AlexInput -> StartCode -> AlexReturn a+alexScan input__ (I# (sc))+ = alexScanUser undefined input__ (I# (sc))++alexScanUser user__ input__ (I# (sc))+ = case alex_scan_tkn user__ input__ 0# input__ sc AlexNone of+ (AlexNone, input__') ->+ case alexGetByte input__ of+ Nothing ->++ AlexEOF+ Just _ ->++ AlexError input__'++ (AlexLastSkip input__'' len, _) ->++ AlexSkip input__'' len++ (AlexLastAcc k input__''' len, _) ->++ AlexToken input__''' len (alex_actions ! k)++-- Push the input through the DFA, remembering the most recent accepting+-- state it encountered.++alex_scan_tkn user__ orig_input len input__ s last_acc =+ input__ `seq` -- strict in the input+ let+ new_acc = (check_accs (alex_accept `quickIndex` (I# (s))))+ in+ new_acc `seq`+ case alexGetByte input__ of+ Nothing -> (new_acc, input__)+ Just (c, new_input) ->++ case fromIntegral c of { (I# (ord_c)) ->+ let+ base = alexIndexInt32OffAddr alex_base s+ offset = (base +# ord_c)+ check = alexIndexInt16OffAddr alex_check offset++ new_s = if GTE(offset,0#) && EQ(check,ord_c)+ then alexIndexInt16OffAddr alex_table offset+ else alexIndexInt16OffAddr alex_deflt s+ in+ case new_s of+ -1# -> (new_acc, input__)+ -- on an error, we want to keep the input *before* the+ -- character that failed, not after.+ _ -> alex_scan_tkn user__ orig_input (if c < 0x80 || c >= 0xC0 then (len +# 1#) else len)+ -- note that the length is increased ONLY if this is the 1st byte in a char encoding)+ new_input new_s new_acc+ }+ where+ check_accs (AlexAccNone) = last_acc+ check_accs (AlexAcc a ) = AlexLastAcc a input__ (I# (len))+ check_accs (AlexAccSkip) = AlexLastSkip input__ (I# (len))++data AlexLastAcc+ = AlexNone+ | AlexLastAcc !Int !AlexInput !Int+ | AlexLastSkip !AlexInput !Int++data AlexAcc user+ = AlexAccNone+ | AlexAcc Int+ | AlexAccSkip+
+ src/Distribution/Fields/LexerMonad.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE CPP #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Fields.LexerMonad+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+module Distribution.Fields.LexerMonad (+ InputStream,+ LexState(..),+ LexResult(..),++ Lex(..),+ execLexer,++ getPos,+ setPos,+ adjustPos,++ getInput,+ setInput,++ getStartCode,+ setStartCode,++ LexWarning(..),+ LexWarningType(..),+ addWarning,+ toPWarnings,++ ) where++import qualified Data.ByteString as B+import qualified Data.List.NonEmpty as NE+import Distribution.Compat.Prelude+import Distribution.Parsec.Position (Position (..), showPos)+import Distribution.Parsec.Warning (PWarnType (..), PWarning (..))+import Prelude ()++import qualified Data.Map.Strict as Map++#ifdef CABAL_PARSEC_DEBUG+-- testing only:+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Vector as V+#endif++-- simple state monad+newtype Lex a = Lex { unLex :: LexState -> LexResult a }++instance Functor Lex where+ fmap = liftM++instance Applicative Lex where+ pure = returnLex+ (<*>) = ap++instance Monad Lex where+ return = pure+ (>>=) = thenLex++data LexResult a = LexResult {-# UNPACK #-} !LexState a++data LexWarningType+ = LexWarningNBSP -- ^ Encountered non breaking space+ | LexWarningBOM -- ^ BOM at the start of the cabal file+ | LexWarningTab -- ^ Leading tags+ deriving (Eq, Ord, Show)++data LexWarning = LexWarning !LexWarningType+ {-# UNPACK #-} !Position+ deriving (Show)++toPWarnings :: [LexWarning] -> [PWarning]+toPWarnings+ = map (uncurry toWarning)+ . Map.toList+ . Map.fromListWith (<>)+ . map (\(LexWarning t p) -> (t, pure p))+ where+ toWarning LexWarningBOM poss =+ PWarning PWTLexBOM (NE.head poss) "Byte-order mark found at the beginning of the file"+ toWarning LexWarningNBSP poss =+ PWarning PWTLexNBSP (NE.head poss) $ "Non breaking spaces at " ++ intercalate ", " (NE.toList $ fmap showPos poss)+ toWarning LexWarningTab poss =+ PWarning PWTLexTab (NE.head poss) $ "Tabs used as indentation at " ++ intercalate ", " (NE.toList $ fmap showPos poss)++data LexState = LexState {+ curPos :: {-# UNPACK #-} !Position, -- ^ position at current input location+ curInput :: {-# UNPACK #-} !InputStream, -- ^ the current input+ curCode :: {-# UNPACK #-} !StartCode, -- ^ lexer code+ warnings :: [LexWarning]+#ifdef CABAL_PARSEC_DEBUG+ , dbgText :: V.Vector T.Text -- ^ input lines, to print pretty debug info+#endif+ } --TODO: check if we should cache the first token+ -- since it looks like parsec's uncons can be called many times on the same input++type StartCode = Int -- ^ An @alex@ lexer start code+type InputStream = B.ByteString++++-- | Execute the given lexer on the supplied input stream.+execLexer :: Lex a -> InputStream -> ([LexWarning], a)+execLexer (Lex lexer) input =+ case lexer initialState of+ LexResult LexState{ warnings = ws } result -> (ws, result)+ where+ initialState = LexState+ -- TODO: add 'startPosition'+ { curPos = Position 1 1+ , curInput = input+ , curCode = 0+ , warnings = []+#ifdef CABAL_PARSEC_DEBUG+ , dbgText = V.fromList . T.lines . T.decodeUtf8 $ input+#endif+ }++{-# INLINE returnLex #-}+returnLex :: a -> Lex a+returnLex a = Lex $ \s -> LexResult s a++{-# INLINE thenLex #-}+thenLex :: Lex a -> (a -> Lex b) -> Lex b+(Lex m) `thenLex` k = Lex $ \s -> case m s of LexResult s' a -> (unLex (k a)) s'++setPos :: Position -> Lex ()+setPos pos = Lex $ \s -> LexResult s{ curPos = pos } ()++getPos :: Lex Position+getPos = Lex $ \s@LexState{ curPos = pos } -> LexResult s pos++adjustPos :: (Position -> Position) -> Lex ()+adjustPos f = Lex $ \s@LexState{ curPos = pos } -> LexResult s{ curPos = f pos } ()++getInput :: Lex InputStream+getInput = Lex $ \s@LexState{ curInput = i } -> LexResult s i++setInput :: InputStream -> Lex ()+setInput i = Lex $ \s -> LexResult s{ curInput = i } ()++getStartCode :: Lex Int+getStartCode = Lex $ \s@LexState{ curCode = c } -> LexResult s c++setStartCode :: Int -> Lex ()+setStartCode c = Lex $ \s -> LexResult s{ curCode = c } ()++-- | Add warning at the current position+addWarning :: LexWarningType -> Lex ()+addWarning wt = Lex $ \s@LexState{ curPos = pos, warnings = ws } ->+ LexResult s{ warnings = LexWarning wt pos : ws } ()
+ src/Distribution/Fields/ParseResult.hs view
@@ -0,0 +1,196 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+-- | A parse result type for parsers from AST to Haskell types.+module Distribution.Fields.ParseResult (+ ParseResult,+ runParseResult,+ recoverWith,+ parseWarning,+ parseWarnings,+ parseFailure,+ parseFatalFailure,+ parseFatalFailure',+ getCabalSpecVersion,+ setCabalSpecVersion,+ readAndParseFile,+ parseString,+ withoutWarnings,+ ) where++import qualified Data.ByteString.Char8 as BS+import Distribution.Compat.Prelude+import Distribution.Parsec.Error (PError (..), showPError)+import Distribution.Parsec.Position (Position (..), zeroPos)+import Distribution.Parsec.Warning (PWarnType (..), PWarning (..), showPWarning)+import Distribution.Simple.Utils (die', warn)+import Distribution.Verbosity (Verbosity)+import Distribution.Version (Version)+import Prelude ()+import System.Directory (doesFileExist)++#if MIN_VERSION_base(4,10,0)+import Control.Applicative (Applicative (..))+#endif++-- | A monad with failure and accumulating errors and warnings.+newtype ParseResult a = PR+ { unPR+ :: forall r. PRState+ -> (PRState -> r) -- failure, but we were able to recover a new-style spec-version declaration+ -> (PRState -> a -> r) -- success+ -> r+ }++-- Note: we have version here, as we could get any version.+data PRState = PRState ![PWarning] ![PError] !(Maybe Version)++emptyPRState :: PRState+emptyPRState = PRState [] [] Nothing++-- | Forget 'ParseResult's warnings.+--+-- @since 3.4.0.0+withoutWarnings :: ParseResult a -> ParseResult a+withoutWarnings m = PR $ \s failure success ->+ unPR m s failure $ \ !s1 -> success (s1 `withWarningsOf` s)+ where+ withWarningsOf (PRState _ e v) (PRState w _ _) = PRState w e v++-- | Destruct a 'ParseResult' into the emitted warnings and either+-- a successful value or+-- list of errors and possibly recovered a spec-version declaration.+runParseResult :: ParseResult a -> ([PWarning], Either (Maybe Version, NonEmpty PError) a)+runParseResult pr = unPR pr emptyPRState failure success+ where+ failure (PRState warns [] v) = (warns, Left (v, PError zeroPos "panic" :| []))+ failure (PRState warns (err:errs) v) = (warns, Left (v, err :| errs)) where+ success (PRState warns [] _) x = (warns, Right x)+ -- If there are any errors, don't return the result+ success (PRState warns (err:errs) v) _ = (warns, Left (v, err :| errs))++instance Functor ParseResult where+ fmap f (PR pr) = PR $ \ !s failure success ->+ pr s failure $ \ !s' a ->+ success s' (f a)+ {-# INLINE fmap #-}++instance Applicative ParseResult where+ pure x = PR $ \ !s _ success -> success s x+ {-# INLINE pure #-}++ f <*> x = PR $ \ !s0 failure success ->+ unPR f s0 failure $ \ !s1 f' ->+ unPR x s1 failure $ \ !s2 x' ->+ success s2 (f' x')+ {-# INLINE (<*>) #-}++ x *> y = PR $ \ !s0 failure success ->+ unPR x s0 failure $ \ !s1 _ ->+ unPR y s1 failure success+ {-# INLINE (*>) #-}++ x <* y = PR $ \ !s0 failure success ->+ unPR x s0 failure $ \ !s1 x' ->+ unPR y s1 failure $ \ !s2 _ ->+ success s2 x'+ {-# INLINE (<*) #-}++#if MIN_VERSION_base(4,10,0)+ liftA2 f x y = PR $ \ !s0 failure success ->+ unPR x s0 failure $ \ !s1 x' ->+ unPR y s1 failure $ \ !s2 y' ->+ success s2 (f x' y')+ {-# INLINE liftA2 #-}+#endif++instance Monad ParseResult where+ return = pure+ (>>) = (*>)++ m >>= k = PR $ \ !s failure success ->+ unPR m s failure $ \ !s' a ->+ unPR (k a) s' failure success+ {-# INLINE (>>=) #-}++-- | "Recover" the parse result, so we can proceed parsing.+-- 'runParseResult' will still result in 'Nothing', if there are recorded errors.+recoverWith :: ParseResult a -> a -> ParseResult a+recoverWith (PR pr) x = PR $ \ !s _failure success ->+ pr s (\ !s' -> success s' x) success++-- | Set cabal spec version.+setCabalSpecVersion :: Maybe Version -> ParseResult ()+setCabalSpecVersion v = PR $ \(PRState warns errs _) _failure success ->+ success (PRState warns errs v) ()++-- | Get cabal spec version.+getCabalSpecVersion :: ParseResult (Maybe Version)+getCabalSpecVersion = PR $ \s@(PRState _ _ v) _failure success ->+ success s v++-- | Add a warning. This doesn't fail the parsing process.+parseWarning :: Position -> PWarnType -> String -> ParseResult ()+parseWarning pos t msg = PR $ \(PRState warns errs v) _failure success ->+ success (PRState (PWarning t pos msg : warns) errs v) ()++-- | Add multiple warnings at once.+parseWarnings :: [PWarning] -> ParseResult ()+parseWarnings newWarns = PR $ \(PRState warns errs v) _failure success ->+ success (PRState (newWarns ++ warns) errs v) ()++-- | Add an error, but not fail the parser yet.+--+-- For fatal failure use 'parseFatalFailure'+parseFailure :: Position -> String -> ParseResult ()+parseFailure pos msg = PR $ \(PRState warns errs v) _failure success ->+ success (PRState warns (PError pos msg : errs) v) ()++-- | Add an fatal error.+parseFatalFailure :: Position -> String -> ParseResult a+parseFatalFailure pos msg = PR $ \(PRState warns errs v) failure _success ->+ failure (PRState warns (PError pos msg : errs) v)++-- | A 'mzero'.+parseFatalFailure' :: ParseResult a+parseFatalFailure' = PR pr+ where+ pr (PRState warns [] v) failure _success = failure (PRState warns [err] v)+ pr s failure _success = failure s++ err = PError zeroPos "Unknown fatal error"++-- | Helper combinator to do parsing plumbing for files.+--+-- Given a parser and a filename, return the parse of the file,+-- after checking if the file exists.+--+-- Argument order is chosen to encourage partial application.+readAndParseFile+ :: (BS.ByteString -> ParseResult a) -- ^ File contents to final value parser+ -> Verbosity -- ^ Verbosity level+ -> FilePath -- ^ File to read+ -> IO a+readAndParseFile parser verbosity fpath = do+ exists <- doesFileExist fpath+ unless exists $+ die' verbosity $+ "Error Parsing: file \"" ++ fpath ++ "\" doesn't exist. Cannot continue."+ bs <- BS.readFile fpath+ parseString parser verbosity fpath bs++parseString+ :: (BS.ByteString -> ParseResult a) -- ^ File contents to final value parser+ -> Verbosity -- ^ Verbosity level+ -> String -- ^ File name+ -> BS.ByteString+ -> IO a+parseString parser verbosity name bs = do+ let (warnings, result) = runParseResult (parser bs)+ traverse_ (warn verbosity . showPWarning name) warnings+ case result of+ Right x -> return x+ Left (_, errors) -> do+ traverse_ (warn verbosity . showPError name) errors+ die' verbosity $ "Failed parsing \"" ++ name ++ "\"."
+ src/Distribution/Fields/Parser.hs view
@@ -0,0 +1,377 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Fields.Parser+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+module Distribution.Fields.Parser (+ -- * Types+ Field(..),+ Name(..),+ FieldLine(..),+ SectionArg(..),+ -- * Grammar and parsing+ -- $grammar+ readFields,+ readFields',+#ifdef CABAL_PARSEC_DEBUG+ -- * Internal+ parseFile,+ parseStr,+ parseBS,+#endif+ ) where++import qualified Data.ByteString.Char8 as B8+import Data.Functor.Identity+import Distribution.Compat.Prelude+import Distribution.Fields.Field+import Distribution.Fields.Lexer+import Distribution.Fields.LexerMonad+ (LexResult (..), LexState (..), LexWarning (..), unLex)+import Distribution.Parsec.Position (Position (..))+import Prelude ()+import Text.Parsec.Combinator hiding (eof, notFollowedBy)+import Text.Parsec.Error+import Text.Parsec.Pos+import Text.Parsec.Prim hiding (many, (<|>))++#ifdef CABAL_PARSEC_DEBUG+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Encoding.Error as T+#endif++-- | The 'LexState'' (with a prime) is an instance of parsec's 'Stream'+-- wrapped around lexer's 'LexState' (without a prime)+data LexState' = LexState' !LexState (LToken, LexState')++mkLexState' :: LexState -> LexState'+mkLexState' st = LexState' st+ (case unLex lexToken st of LexResult st' tok -> (tok, mkLexState' st'))++type Parser a = ParsecT LexState' () Identity a++instance Stream LexState' Identity LToken where+ uncons (LexState' _ (tok, st')) =+ case tok of+ L _ EOF -> return Nothing+ _ -> return (Just (tok, st'))++-- | Get lexer warnings accumulated so far+getLexerWarnings :: Parser [LexWarning]+getLexerWarnings = do+ LexState' (LexState { warnings = ws }) _ <- getInput+ return ws++-- | Set Alex code i.e. the mode "state" lexer is in.+setLexerMode :: Int -> Parser ()+setLexerMode code = do+ LexState' ls _ <- getInput+ setInput $! mkLexState' ls { curCode = code }++getToken :: (Token -> Maybe a) -> Parser a+getToken getTok = getTokenWithPos (\(L _ t) -> getTok t)++getTokenWithPos :: (LToken -> Maybe a) -> Parser a+getTokenWithPos getTok = tokenPrim (\(L _ t) -> describeToken t) updatePos getTok+ where+ updatePos :: SourcePos -> LToken -> LexState' -> SourcePos+ updatePos pos (L (Position col line) _) _ = newPos (sourceName pos) col line++describeToken :: Token -> String+describeToken t = case t of+ TokSym s -> "symbol " ++ show s+ TokStr s -> "string " ++ show s+ TokOther s -> "operator " ++ show s+ Indent _ -> "new line"+ TokFieldLine _ -> "field content"+ Colon -> "\":\""+ OpenBrace -> "\"{\""+ CloseBrace -> "\"}\""+-- SemiColon -> "\";\""+ EOF -> "end of file"+ LexicalError is -> "character in input " ++ show (B8.head is)++tokSym :: Parser (Name Position)+tokSym', tokStr, tokOther :: Parser (SectionArg Position)+tokIndent :: Parser Int+tokColon, tokOpenBrace, tokCloseBrace :: Parser ()+tokFieldLine :: Parser (FieldLine Position)++tokSym = getTokenWithPos $ \t -> case t of L pos (TokSym x) -> Just (mkName pos x); _ -> Nothing+tokSym' = getTokenWithPos $ \t -> case t of L pos (TokSym x) -> Just (SecArgName pos x); _ -> Nothing+tokStr = getTokenWithPos $ \t -> case t of L pos (TokStr x) -> Just (SecArgStr pos x); _ -> Nothing+tokOther = getTokenWithPos $ \t -> case t of L pos (TokOther x) -> Just (SecArgOther pos x); _ -> Nothing+tokIndent = getToken $ \t -> case t of Indent x -> Just x; _ -> Nothing+tokColon = getToken $ \t -> case t of Colon -> Just (); _ -> Nothing+tokOpenBrace = getToken $ \t -> case t of OpenBrace -> Just (); _ -> Nothing+tokCloseBrace = getToken $ \t -> case t of CloseBrace -> Just (); _ -> Nothing+tokFieldLine = getTokenWithPos $ \t -> case t of L pos (TokFieldLine s) -> Just (FieldLine pos s); _ -> Nothing++colon, openBrace, closeBrace :: Parser ()++sectionArg :: Parser (SectionArg Position)+sectionArg = tokSym' <|> tokStr <|> tokOther <?> "section parameter"++fieldSecName :: Parser (Name Position)+fieldSecName = tokSym <?> "field or section name"++colon = tokColon <?> "\":\""+openBrace = tokOpenBrace <?> "\"{\""+closeBrace = tokCloseBrace <?> "\"}\""++fieldContent :: Parser (FieldLine Position)+fieldContent = tokFieldLine <?> "field contents"++newtype IndentLevel = IndentLevel Int++zeroIndentLevel :: IndentLevel+zeroIndentLevel = IndentLevel 0++incIndentLevel :: IndentLevel -> IndentLevel+incIndentLevel (IndentLevel i) = IndentLevel (succ i)++indentOfAtLeast :: IndentLevel -> Parser IndentLevel+indentOfAtLeast (IndentLevel i) = try $ do+ j <- tokIndent+ guard (j >= i) <?> "indentation of at least " ++ show i+ return (IndentLevel j)+++newtype LexerMode = LexerMode Int++inLexerMode :: LexerMode -> Parser p -> Parser p+inLexerMode (LexerMode mode) p =+ do setLexerMode mode; x <- p; setLexerMode in_section; return x+++-----------------------+-- Cabal file grammar+--++-- $grammar+--+-- @+-- CabalStyleFile ::= SecElems+--+-- SecElems ::= SecElem* '\\n'?+-- SecElem ::= '\\n' SecElemLayout | SecElemBraces+-- SecElemLayout ::= FieldLayout | FieldBraces | SectionLayout | SectionBraces+-- SecElemBraces ::= FieldInline | FieldBraces | SectionBraces+-- FieldLayout ::= name ':' line? ('\\n' line)*+-- FieldBraces ::= name ':' '\\n'? '{' content '}'+-- FieldInline ::= name ':' content+-- SectionLayout ::= name arg* SecElems+-- SectionBraces ::= name arg* '\\n'? '{' SecElems '}'+-- @+--+-- and the same thing but left factored...+--+-- @+-- SecElems ::= SecElem*+-- SecElem ::= '\\n' name SecElemLayout+-- | name SecElemBraces+-- SecElemLayout ::= ':' FieldLayoutOrBraces+-- | arg* SectionLayoutOrBraces+-- FieldLayoutOrBraces ::= '\\n'? '{' content '}'+-- | line? ('\\n' line)*+-- SectionLayoutOrBraces ::= '\\n'? '{' SecElems '\\n'? '}'+-- | SecElems+-- SecElemBraces ::= ':' FieldInlineOrBraces+-- | arg* '\\n'? '{' SecElems '\\n'? '}'+-- FieldInlineOrBraces ::= '\\n'? '{' content '}'+-- | content+-- @+--+-- Note how we have several productions with the sequence:+--+-- > '\\n'? '{'+--+-- That is, an optional newline (and indent) followed by a @{@ token.+-- In the @SectionLayoutOrBraces@ case you can see that this makes it+-- not fully left factored (because @SecElems@ can start with a @\\n@).+-- Fully left factoring here would be ugly, and though we could use a+-- lookahead of two tokens to resolve the alternatives, we can't+-- conveniently use Parsec's 'try' here to get a lookahead of only two.+-- So instead we deal with this case in the lexer by making a line+-- where the first non-space is @{@ lex as just the @{@ token, without+-- the usual indent token. Then in the parser we can resolve everything+-- with just one token of lookahead and so without using 'try'.++-- Top level of a file using cabal syntax+--+cabalStyleFile :: Parser [Field Position]+cabalStyleFile = do es <- elements zeroIndentLevel+ eof+ return es++-- Elements that live at the top level or inside a section, ie fields+-- and sectionscontent+--+-- elements ::= element*+elements :: IndentLevel -> Parser [Field Position]+elements ilevel = many (element ilevel)++-- An individual element, ie a field or a section. These can either use+-- layout style or braces style. For layout style then it must start on+-- a line on its own (so that we know its indentation level).+--+-- element ::= '\\n' name elementInLayoutContext+-- | name elementInNonLayoutContext+element :: IndentLevel -> Parser (Field Position)+element ilevel =+ (do ilevel' <- indentOfAtLeast ilevel+ name <- fieldSecName+ elementInLayoutContext (incIndentLevel ilevel') name)+ <|> (do name <- fieldSecName+ elementInNonLayoutContext name)++-- An element (field or section) that is valid in a layout context.+-- In a layout context we can have fields and sections that themselves+-- either use layout style or that use braces style.+--+-- elementInLayoutContext ::= ':' fieldLayoutOrBraces+-- | arg* sectionLayoutOrBraces+elementInLayoutContext :: IndentLevel -> Name Position -> Parser (Field Position)+elementInLayoutContext ilevel name =+ (do colon; fieldLayoutOrBraces ilevel name)+ <|> (do args <- many sectionArg+ elems <- sectionLayoutOrBraces ilevel+ return (Section name args elems))++-- An element (field or section) that is valid in a non-layout context.+-- In a non-layout context we can have only have fields and sections that+-- themselves use braces style, or inline style fields.+--+-- elementInNonLayoutContext ::= ':' FieldInlineOrBraces+-- | arg* '\\n'? '{' elements '\\n'? '}'+elementInNonLayoutContext :: Name Position -> Parser (Field Position)+elementInNonLayoutContext name =+ (do colon; fieldInlineOrBraces name)+ <|> (do args <- many sectionArg+ openBrace+ elems <- elements zeroIndentLevel+ optional tokIndent+ closeBrace+ return (Section name args elems))++-- The body of a field, using either layout style or braces style.+--+-- fieldLayoutOrBraces ::= '\\n'? '{' content '}'+-- | line? ('\\n' line)*+fieldLayoutOrBraces :: IndentLevel -> Name Position -> Parser (Field Position)+fieldLayoutOrBraces ilevel name = braces <|> fieldLayout+ where+ braces = do+ openBrace+ ls <- inLexerMode (LexerMode in_field_braces) (many fieldContent)+ closeBrace+ return (Field name ls)+ fieldLayout = inLexerMode (LexerMode in_field_layout) $ do+ l <- optionMaybe fieldContent+ ls <- many (do _ <- indentOfAtLeast ilevel; fieldContent)+ return $ case l of+ Nothing -> Field name ls+ Just l' -> Field name (l' : ls)++-- The body of a section, using either layout style or braces style.+--+-- sectionLayoutOrBraces ::= '\\n'? '{' elements \\n? '}'+-- | elements+sectionLayoutOrBraces :: IndentLevel -> Parser [Field Position]+sectionLayoutOrBraces ilevel =+ (do openBrace+ elems <- elements zeroIndentLevel+ optional tokIndent+ closeBrace+ return elems)+ <|> (elements ilevel)++-- The body of a field, using either inline style or braces.+--+-- fieldInlineOrBraces ::= '\\n'? '{' content '}'+-- | content+fieldInlineOrBraces :: Name Position -> Parser (Field Position)+fieldInlineOrBraces name =+ (do openBrace+ ls <- inLexerMode (LexerMode in_field_braces) (many fieldContent)+ closeBrace+ return (Field name ls))+ <|> (do ls <- inLexerMode (LexerMode in_field_braces) (option [] (fmap (\l -> [l]) fieldContent))+ return (Field name ls))+++-- | Parse cabal style 'B8.ByteString' into list of 'Field's, i.e. the cabal AST.+readFields :: B8.ByteString -> Either ParseError [Field Position]+readFields s = fmap fst (readFields' s)++-- | Like 'readFields' but also return lexer warnings+readFields' :: B8.ByteString -> Either ParseError ([Field Position], [LexWarning])+readFields' s = do+ parse parser "the input" lexSt+ where+ parser = do+ fields <- cabalStyleFile+ ws <- getLexerWarnings+ pure (fields, ws)++ lexSt = mkLexState' (mkLexState s)++#ifdef CABAL_PARSEC_DEBUG+parseTest' :: Show a => Parsec LexState' () a -> SourceName -> B8.ByteString -> IO ()+parseTest' p fname s =+ case parse p fname (lexSt s) of+ Left err -> putStrLn (formatError s err)++ Right x -> print x+ where+ lexSt = mkLexState' . mkLexState++parseFile :: Show a => Parser a -> FilePath -> IO ()+parseFile p f = B8.readFile f >>= \s -> parseTest' p f s++parseStr :: Show a => Parser a -> String -> IO ()+parseStr p = parseBS p . B8.pack++parseBS :: Show a => Parser a -> B8.ByteString -> IO ()+parseBS p = parseTest' p "<input string>"++formatError :: B8.ByteString -> ParseError -> String+formatError input perr =+ unlines+ [ "Parse error "++ show (errorPos perr) ++ ":"+ , errLine+ , indicator ++ errmsg ]+ where+ pos = errorPos perr+ ls = lines' (T.decodeUtf8With T.lenientDecode input)+ errLine = T.unpack (ls !! (sourceLine pos - 1))+ indicator = replicate (sourceColumn pos) ' ' ++ "^"+ errmsg = showErrorMessages "or" "unknown parse error"+ "expecting" "unexpected" "end of file"+ (errorMessages perr)++-- | Handles windows/osx/unix line breaks uniformly+lines' :: T.Text -> [T.Text]+lines' s1+ | T.null s1 = []+ | otherwise = case T.break (\c -> c == '\r' || c == '\n') s1 of+ (l, s2) | Just (c,s3) <- T.uncons s2+ -> case T.uncons s3 of+ Just ('\n', s4) | c == '\r' -> l : lines' s4+ _ -> l : lines' s3+ | otherwise -> [l]+#endif++eof :: Parser ()+eof = notFollowedBy anyToken <?> "end of file"+ where+ notFollowedBy :: Parser LToken -> Parser ()+ notFollowedBy p = try ( (do L _ t <- try p; unexpected (describeToken t))+ <|> return ())
+ src/Distribution/Fields/Pretty.hs view
@@ -0,0 +1,176 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-}+-- | Cabal-like file AST types: 'Field', 'Section' etc,+--+-- This (intermediate) data type is used for pretty-printing.+--+-- @since 3.0.0.0+--+module Distribution.Fields.Pretty (+ -- * Fields+ PrettyField (..),+ showFields,+ showFields',+ -- * Transformation from 'P.Field'+ fromParsecFields,+ genericFromParsecFields,+ prettyFieldLines,+ prettySectionArgs,+ ) where++import Distribution.Compat.Prelude+import Distribution.Pretty (showToken)+import Prelude ()++import Distribution.Fields.Field (FieldName)+import Distribution.Simple.Utils (fromUTF8BS)++import qualified Distribution.Fields.Parser as P++import qualified Data.ByteString as BS+import qualified Text.PrettyPrint as PP++data PrettyField ann+ = PrettyField ann FieldName PP.Doc+ | PrettySection ann FieldName [PP.Doc] [PrettyField ann]+ deriving (Functor, Foldable, Traversable)++-- | Prettyprint a list of fields.+--+-- Note: the first argument should return 'String's without newlines+-- and properly prefixes (with @--@) to count as comments.+-- This unsafety is left in place so one could generate empty lines+-- between comment lines.+--+showFields :: (ann -> [String]) -> [PrettyField ann] -> String+showFields rann = showFields' rann (const id) 4++-- | 'showFields' with user specified indentation.+showFields'+ :: (ann -> [String])+ -- ^ Convert an annotation to lined to preceed the field or section.+ -> (ann -> [String] -> [String])+ -- ^ Post-process non-annotation produced lines.+ -> Int+ -- ^ Indentation level.+ -> [PrettyField ann]+ -- ^ Fields/sections to show.+ -> String+showFields' rann post n = unlines . renderFields (Opts rann indent post)+ where+ -- few hardcoded, "unrolled" variants.+ indent | n == 4 = indent4+ | n == 2 = indent2+ | otherwise = (replicate (max n 1) ' ' ++)++ indent4 :: String -> String+ indent4 [] = []+ indent4 xs = ' ' : ' ' : ' ' : ' ' : xs++ indent2 :: String -> String+ indent2 [] = []+ indent2 xs = ' ' : ' ' : xs++data Opts ann = Opts+ { _optAnnotation ::(ann -> [String])+ , _optIndent ::(String -> String)+ , _optPostprocess :: ann -> [String] -> [String]+ }++renderFields :: Opts ann -> [PrettyField ann] -> [String]+renderFields opts fields = flattenBlocks $ map (renderField opts len) fields+ where+ len = maxNameLength 0 fields++ maxNameLength !acc [] = acc+ maxNameLength !acc (PrettyField _ name _ : rest) = maxNameLength (max acc (BS.length name)) rest+ maxNameLength !acc (PrettySection {} : rest) = maxNameLength acc rest++-- | Block of lines,+-- Boolean parameter tells whether block should be surrounded by empty lines+data Block = Block Margin Margin [String]++data Margin = Margin | NoMargin+ deriving Eq++-- | Collapse margins, any margin = margin+instance Semigroup Margin where+ NoMargin <> NoMargin = NoMargin+ _ <> _ = Margin++flattenBlocks :: [Block] -> [String]+flattenBlocks = go0 where+ go0 [] = []+ go0 (Block _before after strs : blocks) = strs ++ go after blocks++ go _surr' [] = []+ go surr' (Block before after strs : blocks) = ins $ strs ++ go after blocks where+ ins | surr' <> before == Margin = ("" :)+ | otherwise = id++renderField :: Opts ann -> Int -> PrettyField ann -> Block+renderField (Opts rann indent post) fw (PrettyField ann name doc) =+ Block before after $ comments ++ post ann lines'+ where+ comments = rann ann+ before = if null comments then NoMargin else Margin++ (lines', after) = case lines narrow of+ [] -> ([ name' ++ ":" ], NoMargin)+ [singleLine] | length singleLine < 60+ -> ([ name' ++ ": " ++ replicate (fw - length name') ' ' ++ narrow ], NoMargin)+ _ -> ((name' ++ ":") : map indent (lines (PP.render doc)), Margin)++ name' = fromUTF8BS name+ narrow = PP.renderStyle narrowStyle doc++ narrowStyle :: PP.Style+ narrowStyle = PP.style { PP.lineLength = PP.lineLength PP.style - fw }++renderField opts@(Opts rann indent post) _ (PrettySection ann name args fields) = Block Margin Margin $+ rann ann+ +++ post ann [ PP.render $ PP.hsep $ PP.text (fromUTF8BS name) : args ]+ +++ (map indent $ renderFields opts fields)++-------------------------------------------------------------------------------+-- Transform from Parsec.Field+-------------------------------------------------------------------------------++genericFromParsecFields+ :: Applicative f+ => (FieldName -> [P.FieldLine ann] -> f PP.Doc) -- ^ transform field contents+ -> (FieldName -> [P.SectionArg ann] -> f [PP.Doc]) -- ^ transform section arguments+ -> [P.Field ann]+ -> f [PrettyField ann]+genericFromParsecFields f g = goMany where+ goMany = traverse go++ go (P.Field (P.Name ann name) fls) = PrettyField ann name <$> f name fls+ go (P.Section (P.Name ann name) secargs fs) = PrettySection ann name <$> g name secargs <*> goMany fs++-- | Used in 'fromParsecFields'.+prettyFieldLines :: FieldName -> [P.FieldLine ann] -> PP.Doc+prettyFieldLines _ fls = PP.vcat+ [ PP.text $ fromUTF8BS bs+ | P.FieldLine _ bs <- fls+ ]++-- | Used in 'fromParsecFields'.+prettySectionArgs :: FieldName -> [P.SectionArg ann] -> [PP.Doc]+prettySectionArgs _ = map $ \sa -> case sa of+ P.SecArgName _ bs -> showToken $ fromUTF8BS bs+ P.SecArgStr _ bs -> showToken $ fromUTF8BS bs+ P.SecArgOther _ bs -> PP.text $ fromUTF8BS bs++-- | Simple variant of 'genericFromParsecField'+fromParsecFields :: [P.Field ann] -> [PrettyField ann]+fromParsecFields = runIdentity . genericFromParsecFields+ (Identity .: prettyFieldLines)+ (Identity .: prettySectionArgs)+ where+ (.:) :: (a -> b) -> (c -> d -> a) -> (c -> d -> b)+ (f .: g) x y = f (g x y)
+ src/Distribution/GetOpt.hs view
@@ -0,0 +1,231 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.GetOpt+-- Copyright : (c) Sven Panne 2002-2005+-- License : BSD-style (see the file libraries/base/LICENSE)+--+-- Maintainer : libraries@haskell.org+-- Portability : portable+--+-- This is a fork of "System.Console.GetOpt" with the following changes:+--+-- * Treat "cabal --flag command" as "cabal command --flag" e.g.+-- "cabal -v configure" to mean "cabal configure -v" For flags that are+-- not recognised as global flags, pass them on to the sub-command. See+-- the difference in 'shortOpt'.+--+-- * Line wrapping in the 'usageInfo' output, plus a more compact+-- rendering of short options, and slightly less padding.+--+-- If you want to take on the challenge of merging this with the GetOpt+-- from the base package then go for it!+--+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE NamedFieldPuns #-}+module Distribution.GetOpt (+ -- * GetOpt+ getOpt, getOpt',+ usageInfo,+ ArgOrder(..),+ OptDescr(..),+ ArgDescr(..),++ -- * Example+ -- | See "System.Console.GetOpt" for examples+) where++import Prelude ()+import Distribution.Compat.Prelude+import System.Console.GetOpt+ ( ArgOrder(..), OptDescr(..), ArgDescr(..) )++data OptKind a -- kind of cmd line arg (internal use only):+ = Opt a -- an option+ | UnreqOpt String -- an un-recognized option+ | NonOpt String -- a non-option+ | EndOfOpts -- end-of-options marker (i.e. "--")+ | OptErr String -- something went wrong...++data OptHelp a = OptHelp {+ optNames :: a,+ optHelp :: String+ }++-- | Return a string describing the usage of a command, derived from+-- the header (first argument) and the options described by the+-- second argument.+usageInfo :: String -- header+ -> [OptDescr a] -- option descriptors+ -> String -- nicely formatted decription of options+usageInfo header optDescr = unlines (header : table)+ where+ options = flip map optDescr $ \(Option sos los ad d) ->+ OptHelp+ { optNames =+ intercalate ", " $+ map (fmtShort ad) sos +++ map (fmtLong ad) (take 1 los)+ , optHelp = d+ }++ maxOptNameWidth = 30+ descolWidth = 80 - (maxOptNameWidth + 3)++ table :: [String]+ table = do+ OptHelp{optNames, optHelp} <- options+ let wrappedHelp = wrapText descolWidth optHelp+ if length optNames >= maxOptNameWidth+ then [" " ++ optNames] +++ renderColumns [] wrappedHelp+ else renderColumns [optNames] wrappedHelp++ renderColumns :: [String] -> [String] -> [String]+ renderColumns xs ys = do+ (x, y) <- zipDefault "" "" xs ys+ return $ " " ++ padTo maxOptNameWidth x ++ " " ++ y++ padTo n x = take n (x ++ repeat ' ')++zipDefault :: a -> b -> [a] -> [b] -> [(a,b)]+zipDefault _ _ [] [] = []+zipDefault _ bd (a:as) [] = (a,bd) : map (,bd) as+zipDefault ad _ [] (b:bs) = (ad,b) : map (ad,) bs+zipDefault ad bd (a:as) (b:bs) = (a,b) : zipDefault ad bd as bs++fmtShort :: ArgDescr a -> Char -> String+fmtShort (NoArg _ ) so = "-" ++ [so]+fmtShort (ReqArg _ _) so = "-" ++ [so]+fmtShort (OptArg _ _) so = "-" ++ [so]+ -- unlike upstream GetOpt we omit the arg name for short options++fmtLong :: ArgDescr a -> String -> String+fmtLong (NoArg _ ) lo = "--" ++ lo+fmtLong (ReqArg _ ad) lo = "--" ++ lo ++ "=" ++ ad+fmtLong (OptArg _ ad) lo = "--" ++ lo ++ "[=" ++ ad ++ "]"++wrapText :: Int -> String -> [String]+wrapText width = map unwords . wrap 0 [] . words+ where wrap :: Int -> [String] -> [String] -> [[String]]+ wrap 0 [] (w:ws)+ | length w + 1 > width+ = wrap (length w) [w] ws+ wrap col line (w:ws)+ | col + length w + 1 > width+ = reverse line : wrap 0 [] (w:ws)+ wrap col line (w:ws)+ = let col' = col + length w + 1+ in wrap col' (w:line) ws+ wrap _ [] [] = []+ wrap _ line [] = [reverse line]++{-|+Process the command-line, and return the list of values that matched+(and those that didn\'t). The arguments are:++* The order requirements (see 'ArgOrder')++* The option descriptions (see 'OptDescr')++* The actual command line arguments (presumably got from+ 'System.Environment.getArgs').++'getOpt' returns a triple consisting of the option arguments, a list+of non-options, and a list of error messages.+-}+getOpt :: ArgOrder a -- non-option handling+ -> [OptDescr a] -- option descriptors+ -> [String] -- the command-line arguments+ -> ([a],[String],[String]) -- (options,non-options,error messages)+getOpt ordering optDescr args = (os,xs,es ++ map errUnrec us)+ where (os,xs,us,es) = getOpt' ordering optDescr args++{-|+This is almost the same as 'getOpt', but returns a quadruple+consisting of the option arguments, a list of non-options, a list of+unrecognized options, and a list of error messages.+-}+getOpt' :: ArgOrder a -- non-option handling+ -> [OptDescr a] -- option descriptors+ -> [String] -- the command-line arguments+ -> ([a],[String], [String] ,[String]) -- (options,non-options,unrecognized,error messages)+getOpt' _ _ [] = ([],[],[],[])+getOpt' ordering optDescr (arg:args) = procNextOpt opt ordering+ where procNextOpt (Opt o) _ = (o:os,xs,us,es)+ procNextOpt (UnreqOpt u) _ = (os,xs,u:us,es)+ procNextOpt (NonOpt x) RequireOrder = ([],x:rest,[],[])+ procNextOpt (NonOpt x) Permute = (os,x:xs,us,es)+ procNextOpt (NonOpt x) (ReturnInOrder f) = (f x :os, xs,us,es)+ procNextOpt EndOfOpts RequireOrder = ([],rest,[],[])+ procNextOpt EndOfOpts Permute = ([],rest,[],[])+ procNextOpt EndOfOpts (ReturnInOrder f) = (map f rest,[],[],[])+ procNextOpt (OptErr e) _ = (os,xs,us,e:es)++ (opt,rest) = getNext arg args optDescr+ (os,xs,us,es) = getOpt' ordering optDescr rest++-- take a look at the next cmd line arg and decide what to do with it+getNext :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])+getNext ('-':'-':[]) rest _ = (EndOfOpts,rest)+getNext ('-':'-':xs) rest optDescr = longOpt xs rest optDescr+getNext ('-': x :xs) rest optDescr = shortOpt x xs rest optDescr+getNext a rest _ = (NonOpt a,rest)++-- handle long option+longOpt :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])+longOpt ls rs optDescr = long ads arg rs+ where (opt,arg) = break (=='=') ls+ getWith p = [ o | o@(Option _ xs _ _) <- optDescr+ , isJust (find (p opt) xs)]+ exact = getWith (==)+ options = if null exact then getWith isPrefixOf else exact+ ads = [ ad | Option _ _ ad _ <- options ]+ optStr = "--" ++ opt++ long (_:_:_) _ rest = (errAmbig options optStr,rest)+ long [NoArg a ] [] rest = (Opt a,rest)+ long [NoArg _ ] ('=':_) rest = (errNoArg optStr,rest)+ long [ReqArg _ d] [] [] = (errReq d optStr,[])+ long [ReqArg f _] [] (r:rest) = (Opt (f r),rest)+ long [ReqArg f _] ('=':xs) rest = (Opt (f xs),rest)+ long [OptArg f _] [] rest = (Opt (f Nothing),rest)+ long [OptArg f _] ('=':xs) rest = (Opt (f (Just xs)),rest)+ long _ _ rest = (UnreqOpt ("--"++ls),rest)++-- handle short option+shortOpt :: Char -> String -> [String] -> [OptDescr a] -> (OptKind a,[String])+shortOpt y ys rs optDescr = short ads ys rs+ where options = [ o | o@(Option ss _ _ _) <- optDescr, s <- ss, y == s ]+ ads = [ ad | Option _ _ ad _ <- options ]+ optStr = '-':[y]++ short (_:_:_) _ rest = (errAmbig options optStr,rest)+ short (NoArg a :_) [] rest = (Opt a,rest)+ short (NoArg a :_) xs rest = (Opt a,('-':xs):rest)+ short (ReqArg _ d:_) [] [] = (errReq d optStr,[])+ short (ReqArg f _:_) [] (r:rest) = (Opt (f r),rest)+ short (ReqArg f _:_) xs rest = (Opt (f xs),rest)+ short (OptArg f _:_) [] rest = (Opt (f Nothing),rest)+ short (OptArg f _:_) xs rest = (Opt (f (Just xs)),rest)+ short [] [] rest = (UnreqOpt optStr,rest)+ short [] xs rest = (UnreqOpt (optStr++xs),rest)+ -- This is different vs upstream = (UnreqOpt optStr,('-':xs):rest)+ -- Apparently this was part of the change so that flags that are+ -- not recognised as global flags are passed on to the sub-command.+ -- But why was no equivalent change required for longOpt? So could+ -- this change go upstream?++-- miscellaneous error formatting++errAmbig :: [OptDescr a] -> String -> OptKind a+errAmbig ods optStr = OptErr (usageInfo header ods)+ where header = "option `" ++ optStr ++ "' is ambiguous; could be one of:"++errReq :: String -> String -> OptKind a+errReq d optStr = OptErr ("option `" ++ optStr ++ "' requires an argument " ++ d ++ "\n")++errUnrec :: String -> String+errUnrec optStr = "unrecognized option `" ++ optStr ++ "'\n"++errNoArg :: String -> OptKind a+errNoArg optStr = OptErr ("option `" ++ optStr ++ "' doesn't allow an argument\n")
+ src/Distribution/InstalledPackageInfo.hs view
@@ -0,0 +1,145 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.InstalledPackageInfo+-- Copyright : (c) The University of Glasgow 2004+--+-- Maintainer : libraries@haskell.org+-- Portability : portable+--+-- This is the information about an /installed/ package that+-- is communicated to the @ghc-pkg@ program in order to register+-- a package. @ghc-pkg@ now consumes this package format (as of version+-- 6.4). This is specific to GHC at the moment.+--+-- The @.cabal@ file format is for describing a package that is not yet+-- installed. It has a lot of flexibility, like conditionals and dependency+-- ranges. As such, that format is not at all suitable for describing a package+-- that has already been built and installed. By the time we get to that stage,+-- we have resolved all conditionals and resolved dependency version+-- constraints to exact versions of dependent packages. So, this module defines+-- the 'InstalledPackageInfo' data structure that contains all the info we keep+-- about an installed package. There is a parser and pretty printer. The+-- textual format is rather simpler than the @.cabal@ format: there are no+-- sections, for example.++-- This module is meant to be local-only to Distribution...++module Distribution.InstalledPackageInfo (+ InstalledPackageInfo(..),+ installedComponentId,+ installedOpenUnitId,+ sourceComponentName,+ requiredSignatures,+ ExposedModule(..),+ AbiDependency(..),+ emptyInstalledPackageInfo,+ parseInstalledPackageInfo,+ showInstalledPackageInfo,+ showFullInstalledPackageInfo,+ showInstalledPackageInfoField,+ showSimpleInstalledPackageInfoField,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Backpack+import Distribution.CabalSpecVersion (cabalSpecLatest)+import Distribution.FieldGrammar+import Distribution.FieldGrammar.FieldDescrs+import Distribution.ModuleName+import Distribution.Package hiding (installedUnitId)+import Distribution.Types.ComponentName+import Distribution.Utils.Generic (toUTF8BS)++import Data.ByteString (ByteString)++import qualified Data.Map as Map+import qualified Distribution.Fields as P+import qualified Text.PrettyPrint as Disp++import Distribution.Types.InstalledPackageInfo+import Distribution.Types.InstalledPackageInfo.FieldGrammar++-- $setup+-- >>> :set -XOverloadedStrings++installedComponentId :: InstalledPackageInfo -> ComponentId+installedComponentId ipi =+ case unComponentId (installedComponentId_ ipi) of+ "" -> mkComponentId (unUnitId (installedUnitId ipi))+ _ -> installedComponentId_ ipi++-- | Get the indefinite unit identity representing this package.+-- This IS NOT guaranteed to give you a substitution; for+-- instantiated packages you will get @DefiniteUnitId (installedUnitId ipi)@.+-- For indefinite libraries, however, you will correctly get+-- an @OpenUnitId@ with the appropriate 'OpenModuleSubst'.+installedOpenUnitId :: InstalledPackageInfo -> OpenUnitId+installedOpenUnitId ipi+ = mkOpenUnitId (installedUnitId ipi) (installedComponentId ipi) (Map.fromList (instantiatedWith ipi))++-- | Returns the set of module names which need to be filled for+-- an indefinite package, or the empty set if the package is definite.+requiredSignatures :: InstalledPackageInfo -> Set ModuleName+requiredSignatures ipi = openModuleSubstFreeHoles (Map.fromList (instantiatedWith ipi))++-- -----------------------------------------------------------------------------+-- Munging++sourceComponentName :: InstalledPackageInfo -> ComponentName+sourceComponentName = CLibName . sourceLibName++-- -----------------------------------------------------------------------------+-- Parsing++-- | Return either errors, or IPI with list of warnings+parseInstalledPackageInfo+ :: ByteString+ -> Either (NonEmpty String) ([String], InstalledPackageInfo)+parseInstalledPackageInfo s = case P.readFields s of+ Left err -> Left (show err :| [])+ Right fs -> case partitionFields fs of+ (fs', _) -> case P.runParseResult $ parseFieldGrammar cabalSpecLatest fs' ipiFieldGrammar of+ (ws, Right x) -> x `deepseq` Right (ws', x) where+ ws' = [ P.showPWarning "" w+ | w@(P.PWarning wt _ _) <- ws+ -- filter out warnings about experimental features+ , wt /= P.PWTExperimental+ ]+ (_, Left (_, errs)) -> Left errs' where+ errs' = fmap (P.showPError "") errs++-- -----------------------------------------------------------------------------+-- Pretty-printing++-- | Pretty print 'InstalledPackageInfo'.+--+-- @pkgRoot@ isn't printed, as ghc-pkg prints it manually (as GHC-8.4).+showInstalledPackageInfo :: InstalledPackageInfo -> String+showInstalledPackageInfo ipi =+ showFullInstalledPackageInfo ipi { pkgRoot = Nothing }++-- | The variant of 'showInstalledPackageInfo' which outputs @pkgroot@ field too.+showFullInstalledPackageInfo :: InstalledPackageInfo -> String+showFullInstalledPackageInfo = P.showFields (const []) . prettyFieldGrammar cabalSpecLatest ipiFieldGrammar++-- |+--+-- >>> let ipi = emptyInstalledPackageInfo { maintainer = "Tester" }+-- >>> fmap ($ ipi) $ showInstalledPackageInfoField "maintainer"+-- Just "maintainer: Tester"+showInstalledPackageInfoField :: String -> Maybe (InstalledPackageInfo -> String)+showInstalledPackageInfoField fn =+ fmap (\g -> Disp.render . ppField fn . g) $ fieldDescrPretty ipiFieldGrammar (toUTF8BS fn)++showSimpleInstalledPackageInfoField :: String -> Maybe (InstalledPackageInfo -> String)+showSimpleInstalledPackageInfoField fn =+ fmap (Disp.renderStyle myStyle .) $ fieldDescrPretty ipiFieldGrammar (toUTF8BS fn)+ where+ myStyle = Disp.style { Disp.mode = Disp.LeftMode }++ppField :: String -> Disp.Doc -> Disp.Doc+ppField name fielddoc+ | Disp.isEmpty fielddoc = mempty+ | otherwise = Disp.text name <<>> Disp.colon Disp.<+> fielddoc
+ src/Distribution/Lex.hs view
@@ -0,0 +1,40 @@+-----------------------------------------------------------------------------+-- |+-- 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 Prelude ()+import Distribution.Compat.Prelude+import Distribution.Compat.DList++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+
+ src/Distribution/License.hs view
@@ -0,0 +1,252 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.License+-- Description : The License data type.+-- Copyright : Isaac Jones 2003-2005+-- Duncan Coutts 2008+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Package descriptions contain fields for specifying the name of a software+-- license and the name of the file containing the text of that license. While+-- package authors may choose any license they like, Cabal provides an+-- enumeration of a small set of common free and open source software licenses.+-- This is done so that Hackage can recognise licenses, so that tools can detect+-- <https://en.wikipedia.org/wiki/License_compatibility licensing conflicts>,+-- and to deter+-- <https://en.wikipedia.org/wiki/License_proliferation license proliferation>.+--+-- It is recommended that all package authors use the @license-file@ or+-- @license-files@ fields in their package descriptions. Further information+-- about these fields can be found in the+-- <http://www.haskell.org/cabal/users-guide/developing-packages.html#package-descriptions Cabal users guide>.+--+-- = Additional resources+--+-- The following websites provide information about free and open source+-- software licenses:+--+-- * <http://www.opensource.org The Open Source Initiative (OSI)>+--+-- * <https://www.fsf.org The Free Software Foundation (FSF)>+--+-- = Disclaimer+--+-- The descriptions of software licenses provided by this documentation are+-- intended for informational purposes only and in no way constitute legal+-- advice. Please read the text of the licenses and consult a lawyer for any+-- advice regarding software licensing.++module Distribution.License (+ License(..),+ knownLicenses,+ licenseToSPDX,+ licenseFromSPDX,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Version++import qualified Distribution.Compat.CharParsing as P+import qualified Data.Map.Strict as Map+import qualified Distribution.SPDX as SPDX+import qualified Text.PrettyPrint as Disp++-- | Indicates the license under which a package's source code is released.+-- Versions of the licenses not listed here will be rejected by Hackage and+-- cause @cabal check@ to issue a warning.+data License =+ -- TODO: * remove BSD4++ -- | GNU General Public License,+ -- <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html version 2> or+ -- <https://www.gnu.org/licenses/gpl.html version 3>.+ GPL (Maybe Version)++ -- | <https://www.gnu.org/licenses/agpl.html GNU Affero General Public License, version 3>.+ | AGPL (Maybe Version)++ -- | GNU Lesser General Public License,+ -- <https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html version 2.1> or+ -- <https://www.gnu.org/licenses/lgpl.html version 3>.+ | LGPL (Maybe Version)++ -- | <http://www.opensource.org/licenses/bsd-license 2-clause BSD license>.+ | BSD2++ -- | <http://www.opensource.org/licenses/bsd-3-clause 3-clause BSD license>.+ | BSD3++ -- | <http://directory.fsf.org/wiki/License:BSD_4Clause 4-clause BSD license>.+ -- This license has not been approved by the OSI and is incompatible with+ -- the GNU GPL. It is provided for historical reasons and should be avoided.+ | BSD4++ -- | <http://www.opensource.org/licenses/MIT MIT license>.+ | MIT++ -- | <http://www.isc.org/downloads/software-support-policy/isc-license/ ISC license>+ | ISC++ -- | <https://www.mozilla.org/MPL/ Mozilla Public License, version 2.0>.+ | MPL Version++ -- | <https://www.apache.org/licenses/ Apache License, version 2.0>.+ | Apache (Maybe Version)++ -- | The author of a package disclaims any copyright to its source code and+ -- dedicates it to the public domain. This is not a software license. Please+ -- note that it is not possible to dedicate works to the public domain in+ -- every jurisdiction, nor is a work that is in the public domain in one+ -- jurisdiction necessarily in the public domain elsewhere.+ | PublicDomain++ -- | Explicitly 'All Rights Reserved', eg for proprietary software. The+ -- package may not be legally modified or redistributed by anyone but the+ -- rightsholder.+ | AllRightsReserved++ -- | No license specified which legally defaults to 'All Rights Reserved'.+ -- The package may not be legally modified or redistributed by anyone but+ -- the rightsholder.+ | UnspecifiedLicense++ -- | Any other software license.+ | OtherLicense++ -- | Indicates an erroneous license name.+ | UnknownLicense String+ deriving (Generic, Read, Show, Eq, Typeable, Data)++instance Binary License+instance Structured License+instance NFData License where rnf = genericRnf++-- | The list of all currently recognised licenses.+knownLicenses :: [License]+knownLicenses = [ GPL unversioned, GPL (version [2]), GPL (version [3])+ , LGPL unversioned, LGPL (version [2, 1]), LGPL (version [3])+ , AGPL unversioned, AGPL (version [3])+ , BSD2, BSD3, MIT, ISC+ , MPL (mkVersion [2, 0])+ , Apache unversioned, Apache (version [2, 0])+ , PublicDomain, AllRightsReserved, OtherLicense]+ where+ unversioned = Nothing+ version = Just . mkVersion++-- | Convert old 'License' to SPDX 'SPDX.License'.+-- Non-SPDX licenses are converted to 'SPDX.LicenseRef'.+--+-- @since 2.2.0.0+licenseToSPDX :: License -> SPDX.License+licenseToSPDX l = case l of+ GPL v | v == version [2] -> spdx SPDX.GPL_2_0_only+ GPL v | v == version [3] -> spdx SPDX.GPL_3_0_only+ LGPL v | v == version [2,1] -> spdx SPDX.LGPL_2_1_only+ LGPL v | v == version [3] -> spdx SPDX.LGPL_3_0_only+ AGPL v | v == version [3] -> spdx SPDX.AGPL_3_0_only+ BSD2 -> spdx SPDX.BSD_2_Clause+ BSD3 -> spdx SPDX.BSD_3_Clause+ BSD4 -> spdx SPDX.BSD_4_Clause+ MIT -> spdx SPDX.MIT+ ISC -> spdx SPDX.ISC+ MPL v | v == mkVersion [2,0] -> spdx SPDX.MPL_2_0+ Apache v | v == version [2,0] -> spdx SPDX.Apache_2_0+ AllRightsReserved -> SPDX.NONE+ UnspecifiedLicense -> SPDX.NONE+ OtherLicense -> ref (SPDX.mkLicenseRef' Nothing "OtherLicense")+ PublicDomain -> ref (SPDX.mkLicenseRef' Nothing "PublicDomain")+ UnknownLicense str -> ref (SPDX.mkLicenseRef' Nothing str)+ _ -> ref (SPDX.mkLicenseRef' Nothing $ prettyShow l)+ where+ version = Just . mkVersion+ spdx = SPDX.License . SPDX.simpleLicenseExpression+ ref r = SPDX.License $ SPDX.ELicense (SPDX.ELicenseRef r) Nothing++-- | Convert 'SPDX.License' to 'License',+--+-- This is lossy conversion. We try our best.+--+-- >>> licenseFromSPDX . licenseToSPDX $ BSD3+-- BSD3+--+-- >>> licenseFromSPDX . licenseToSPDX $ GPL (Just (mkVersion [3]))+-- GPL (Just (mkVersion [3]))+--+-- >>> licenseFromSPDX . licenseToSPDX $ PublicDomain+-- UnknownLicense "LicenseRefPublicDomain"+--+-- >>> licenseFromSPDX $ SPDX.License $ SPDX.simpleLicenseExpression SPDX.EUPL_1_1+-- UnknownLicense "EUPL-1.1"+--+-- >>> licenseFromSPDX . licenseToSPDX $ AllRightsReserved+-- AllRightsReserved+--+-- >>> licenseFromSPDX <$> simpleParsec "BSD-3-Clause OR GPL-3.0-only"+-- Just (UnknownLicense "BSD3ClauseORGPL30only")+--+-- @since 2.2.0.0+licenseFromSPDX :: SPDX.License -> License+licenseFromSPDX SPDX.NONE = AllRightsReserved+licenseFromSPDX l =+ fromMaybe (mungle $ prettyShow l) $ Map.lookup l m+ where+ m :: Map.Map SPDX.License License+ m = Map.fromList $ filter (isSimple . fst ) $+ map (\x -> (licenseToSPDX x, x)) knownLicenses++ isSimple (SPDX.License (SPDX.ELicense (SPDX.ELicenseId _) Nothing)) = True+ isSimple _ = False++ mungle name = fromMaybe (UnknownLicense (mapMaybe mangle name)) (simpleParsec name)++ mangle c+ | isAlphaNum c = Just c+ | otherwise = Nothing++instance Pretty License where+ pretty (GPL version) = Disp.text "GPL" <<>> dispOptVersion version+ pretty (LGPL version) = Disp.text "LGPL" <<>> dispOptVersion version+ pretty (AGPL version) = Disp.text "AGPL" <<>> dispOptVersion version+ pretty (MPL version) = Disp.text "MPL" <<>> dispVersion version+ pretty (Apache version) = Disp.text "Apache" <<>> dispOptVersion version+ pretty (UnknownLicense other) = Disp.text other+ pretty other = Disp.text (show other)++instance Parsec License where+ parsec = do+ name <- P.munch1 isAlphaNum+ version <- P.optional (P.char '-' *> parsec)+ return $! case (name, version :: Maybe Version) of+ ("GPL", _ ) -> GPL version+ ("LGPL", _ ) -> LGPL version+ ("AGPL", _ ) -> AGPL version+ ("BSD2", Nothing) -> BSD2+ ("BSD3", Nothing) -> BSD3+ ("BSD4", Nothing) -> BSD4+ ("ISC", Nothing) -> ISC+ ("MIT", Nothing) -> MIT+ ("MPL", Just version') -> MPL version'+ ("Apache", _ ) -> Apache version+ ("PublicDomain", Nothing) -> PublicDomain+ ("AllRightsReserved", Nothing) -> AllRightsReserved+ ("OtherLicense", Nothing) -> OtherLicense+ _ -> UnknownLicense $ name +++ maybe "" (('-':) . prettyShow) version++dispOptVersion :: Maybe Version -> Disp.Doc+dispOptVersion Nothing = Disp.empty+dispOptVersion (Just v) = dispVersion v++dispVersion :: Version -> Disp.Doc+dispVersion v = Disp.char '-' <<>> pretty v
+ src/Distribution/Make.hs view
@@ -0,0 +1,182 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Make+-- Copyright : Martin Sjögren 2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is an alternative build system that delegates everything to the @make@+-- program. All the commands just end up calling @make@ with appropriate+-- arguments. The intention was to allow preexisting packages that used+-- makefiles to be wrapped into Cabal packages. In practice essentially all+-- such packages were converted over to the \"Simple\" build system instead.+-- Consequently this module is not used much and it certainly only sees cursory+-- maintenance and no testing. Perhaps at some point we should stop pretending+-- that it works.+--+-- Uses the parsed command-line from "Distribution.Simple.Setup" in order to build+-- Haskell tools using a back-end build system based on make. Obviously we+-- assume that there is a configure script, and that after the ConfigCmd has+-- been run, there is a Makefile. Further assumptions:+--+-- [ConfigCmd] We assume the configure script accepts+-- @--with-hc@,+-- @--with-hc-pkg@,+-- @--prefix@,+-- @--bindir@,+-- @--libdir@,+-- @--libexecdir@,+-- @--datadir@.+--+-- [BuildCmd] We assume that the default Makefile target will build everything.+--+-- [InstallCmd] We assume there is an @install@ target. Note that we assume that+-- this does *not* register the package!+--+-- [CopyCmd] We assume there is a @copy@ target, and a variable @$(destdir)@.+-- The @copy@ target should probably just invoke @make install@+-- recursively (e.g. @$(MAKE) install prefix=$(destdir)\/$(prefix)+-- bindir=$(destdir)\/$(bindir)@. The reason we can\'t invoke @make+-- install@ directly here is that we don\'t know the value of @$(prefix)@.+--+-- [SDistCmd] We assume there is a @dist@ target.+--+-- [RegisterCmd] We assume there is a @register@ target and a variable @$(user)@.+--+-- [UnregisterCmd] We assume there is an @unregister@ target.+--+-- [HaddockCmd] We assume there is a @docs@ or @doc@ target.+++-- copy :+-- $(MAKE) install prefix=$(destdir)/$(prefix) \+-- bindir=$(destdir)/$(bindir) \++module Distribution.Make (+ module Distribution.Package,+ License(..), Version,+ defaultMain, defaultMainArgs+ ) where++import Prelude ()+import Distribution.Compat.Prelude++-- local+import Distribution.Package+import Distribution.Simple.Program+import Distribution.Simple.Setup+import Distribution.Simple.Command++import Distribution.Simple.Utils++import Distribution.License+import Distribution.Version+import Distribution.Pretty++import System.Environment (getArgs, getProgName)++defaultMain :: IO ()+defaultMain = getArgs >>= defaultMainArgs++defaultMainArgs :: [String] -> IO ()+defaultMainArgs = defaultMainHelper++defaultMainHelper :: [String] -> IO ()+defaultMainHelper args =+ case commandsRun (globalCommand commands) commands args of+ CommandHelp help -> printHelp help+ CommandList opts -> printOptionsList opts+ CommandErrors errs -> printErrors errs+ CommandReadyToGo (flags, commandParse) ->+ case commandParse of+ _ | fromFlag (globalVersion flags) -> printVersion+ | fromFlag (globalNumericVersion flags) -> printNumericVersion+ CommandHelp help -> printHelp help+ CommandList opts -> printOptionsList opts+ CommandErrors errs -> printErrors errs+ CommandReadyToGo action -> action++ where+ printHelp help = getProgName >>= putStr . help+ printOptionsList = putStr . unlines+ printErrors errs = do+ putStr (intercalate "\n" errs)+ exitWith (ExitFailure 1)+ printNumericVersion = putStrLn $ prettyShow cabalVersion+ printVersion = putStrLn $ "Cabal library version "+ ++ prettyShow cabalVersion++ progs = defaultProgramDb+ commands =+ [configureCommand progs `commandAddAction` configureAction+ ,buildCommand progs `commandAddAction` buildAction+ ,installCommand `commandAddAction` installAction+ ,copyCommand `commandAddAction` copyAction+ ,haddockCommand `commandAddAction` haddockAction+ ,cleanCommand `commandAddAction` cleanAction+ ,sdistCommand `commandAddAction` sdistAction+ ,registerCommand `commandAddAction` registerAction+ ,unregisterCommand `commandAddAction` unregisterAction+ ]++configureAction :: ConfigFlags -> [String] -> IO ()+configureAction flags args = do+ noExtraFlags args+ let verbosity = fromFlag (configVerbosity flags)+ rawSystemExit verbosity "sh" $+ "configure"+ : configureArgs backwardsCompatHack flags+ where backwardsCompatHack = True++copyAction :: CopyFlags -> [String] -> IO ()+copyAction flags args = do+ noExtraFlags args+ let destArgs = case fromFlag $ copyDest flags of+ NoCopyDest -> ["install"]+ CopyTo path -> ["copy", "destdir=" ++ path]+ CopyToDb _ -> error "CopyToDb not supported via Make"++ rawSystemExit (fromFlag $ copyVerbosity flags) "make" destArgs++installAction :: InstallFlags -> [String] -> IO ()+installAction flags args = do+ noExtraFlags args+ rawSystemExit (fromFlag $ installVerbosity flags) "make" ["install"]+ rawSystemExit (fromFlag $ installVerbosity flags) "make" ["register"]++haddockAction :: HaddockFlags -> [String] -> IO ()+haddockAction flags args = do+ noExtraFlags args+ rawSystemExit (fromFlag $ haddockVerbosity flags) "make" ["docs"]+ `catchIO` \_ ->+ rawSystemExit (fromFlag $ haddockVerbosity flags) "make" ["doc"]++buildAction :: BuildFlags -> [String] -> IO ()+buildAction flags args = do+ noExtraFlags args+ rawSystemExit (fromFlag $ buildVerbosity flags) "make" []++cleanAction :: CleanFlags -> [String] -> IO ()+cleanAction flags args = do+ noExtraFlags args+ rawSystemExit (fromFlag $ cleanVerbosity flags) "make" ["clean"]++sdistAction :: SDistFlags -> [String] -> IO ()+sdistAction flags args = do+ noExtraFlags args+ rawSystemExit (fromFlag $ sDistVerbosity flags) "make" ["dist"]++registerAction :: RegisterFlags -> [String] -> IO ()+registerAction flags args = do+ noExtraFlags args+ rawSystemExit (fromFlag $ regVerbosity flags) "make" ["register"]++unregisterAction :: RegisterFlags -> [String] -> IO ()+unregisterAction flags args = do+ noExtraFlags args+ rawSystemExit (fromFlag $ regVerbosity flags) "make" ["unregister"]
+ src/Distribution/ModuleName.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.ModuleName+-- Copyright : Duncan Coutts 2008+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Data type for Haskell module names.++module Distribution.ModuleName (+ ModuleName,+ fromString,+ fromComponents,+ components,+ toFilePath,+ main,+ -- * Internal+ validModuleComponent,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Utils.ShortText (ShortText, fromShortText, toShortText)+import System.FilePath (pathSeparator)++import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.Compat.DList as DList+import qualified Text.PrettyPrint as Disp++-- | A valid Haskell module name.+--+newtype ModuleName = ModuleName ShortText+ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)++unModuleName :: ModuleName -> String+unModuleName (ModuleName s) = fromShortText s++instance Binary ModuleName+instance Structured ModuleName++instance NFData ModuleName where+ rnf (ModuleName ms) = rnf ms++instance Pretty ModuleName where+ pretty = Disp.text . unModuleName++instance Parsec ModuleName where+ parsec = parsecModuleName++parsecModuleName :: forall m. CabalParsing m => m ModuleName+parsecModuleName = state0 DList.empty where+ upper :: m Char+ !upper = P.satisfy isUpper++ ch :: m Char+ !ch = P.satisfy (\c -> validModuleChar c || c == '.')++ alt :: m ModuleName -> m ModuleName -> m ModuleName+ !alt = (<|>)++ state0 :: DList.DList Char -> m ModuleName+ state0 acc = do+ c <- upper+ state1 (DList.snoc acc c)++ state1 :: DList.DList Char -> m ModuleName+ state1 acc = state1' acc `alt` return (fromString (DList.toList acc))++ state1' :: DList.DList Char -> m ModuleName+ state1' acc = do+ c <- ch+ case c of+ '.' -> state0 (DList.snoc acc c)+ _ -> state1 (DList.snoc acc c)++validModuleChar :: Char -> Bool+validModuleChar c = isAlphaNum c || c == '_' || c == '\''++validModuleComponent :: String -> Bool+validModuleComponent [] = False+validModuleComponent (c:cs) = isUpper c && all validModuleChar cs++-- | Construct a 'ModuleName' from a valid module name 'String'.+--+-- This is just a convenience function intended for valid module strings. It is+-- an error if it is used with a string that is not a valid module name. If you+-- are parsing user input then use 'Distribution.Text.simpleParse' instead.+--+instance IsString ModuleName where+ fromString = ModuleName . toShortText++-- | Construct a 'ModuleName' from valid module components, i.e. parts+-- separated by dots.+fromComponents :: [String] -> ModuleName+fromComponents comps = fromString (intercalate "." comps)+{-# DEPRECATED fromComponents "Exists for cabal-install only" #-}++-- | The module name @Main@.+--+main :: ModuleName+main = ModuleName (fromString "Main")++-- | The individual components of a hierarchical module name. For example+--+-- > components (fromString "A.B.C") = ["A", "B", "C"]+--+components :: ModuleName -> [String]+components mn = split (unModuleName mn)+ where+ split cs = case break (=='.') cs of+ (chunk,[]) -> chunk : []+ (chunk,_:rest) -> chunk : split rest++-- | Convert a module name to a file path, but without any file extension.+-- For example:+--+-- > toFilePath (fromString "A.B.C") = "A/B/C"+--+toFilePath :: ModuleName -> FilePath+toFilePath = map f . unModuleName where+ f '.' = pathSeparator+ f c = c
+ src/Distribution/Package.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Package+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Defines a package identifier along with a parser and pretty printer for it.+-- 'PackageIdentifier's consist of a name and an exact version. It also defines+-- a 'Dependency' data type. A dependency is a package name and a version+-- range, like @\"foo >= 1.2 && < 2\"@.++module Distribution.Package+ ( module Distribution.Types.AbiHash+ , module Distribution.Types.ComponentId+ , module Distribution.Types.PackageId+ , module Distribution.Types.UnitId+ , module Distribution.Types.Module+ , module Distribution.Types.PackageName+ , module Distribution.Types.PkgconfigName+ , module Distribution.Types.Dependency+ , Package(..), packageName, packageVersion+ , HasMungedPackageId(..), mungedName', mungedVersion'+ , HasUnitId(..)+ , PackageInstalled(..)+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Version+ ( Version )++import Distribution.Types.AbiHash+import Distribution.Types.ComponentId+import Distribution.Types.Dependency+import Distribution.Types.MungedPackageId+import Distribution.Types.PackageId+import Distribution.Types.UnitId+import Distribution.Types.Module+import Distribution.Types.MungedPackageName+import Distribution.Types.PackageName+import Distribution.Types.PkgconfigName++-- | Class of things that have a 'PackageIdentifier'+--+-- Types in this class are all notions of a package. This allows us to have+-- different types for the different phases that packages go though, from+-- simple name\/id, package description, configured or installed packages.+--+-- Not all kinds of packages can be uniquely identified by a+-- 'PackageIdentifier'. In particular, installed packages cannot, there may be+-- many installed instances of the same source package.+--+class Package pkg where+ packageId :: pkg -> PackageIdentifier++mungedName' :: HasMungedPackageId pkg => pkg -> MungedPackageName+mungedName' = mungedName . mungedId++mungedVersion' :: HasMungedPackageId munged => munged -> Version+mungedVersion' = mungedVersion . mungedId++class HasMungedPackageId pkg where+ mungedId :: pkg -> MungedPackageId++instance Package PackageIdentifier where+ packageId = id++packageName :: Package pkg => pkg -> PackageName+packageName = pkgName . packageId++packageVersion :: Package pkg => pkg -> Version+packageVersion = pkgVersion . packageId++instance HasMungedPackageId MungedPackageId where+ mungedId = id++-- | Packages that have an installed unit ID+class Package pkg => HasUnitId pkg where+ installedUnitId :: pkg -> UnitId++-- | 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 (HasUnitId pkg) => PackageInstalled pkg where+ installedDepends :: pkg -> [UnitId]
+ src/Distribution/PackageDescription.hs view
@@ -0,0 +1,113 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.PackageDescription+-- Copyright : Isaac Jones 2003-2005+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Backwards compatibility reexport of most things you need to know+-- about @.cabal@ files.++module Distribution.PackageDescription (+ -- * PD and GPD+ module Distribution.Types.PackageDescription,+ module Distribution.Types.GenericPackageDescription,+ -- * Components+ module Distribution.Types.ComponentName,+ -- ** Library+ module Distribution.Types.Library,+ module Distribution.Types.LibraryName,+ module Distribution.Types.LibraryVisibility,+ -- ** Executable+ module Distribution.Types.Executable,+ module Distribution.Types.ExecutableScope,+ -- ** TestSuite+ module Distribution.Types.TestSuite,+ module Distribution.Types.TestType,+ module Distribution.Types.TestSuiteInterface,+ -- ** Benchmark+ module Distribution.Types.Benchmark,+ module Distribution.Types.BenchmarkType,+ module Distribution.Types.BenchmarkInterface,+ -- ** Foreign library+ module Distribution.Types.ForeignLib,+ module Distribution.Types.ForeignLibType,+ module Distribution.Types.ForeignLibOption,+ -- * BuildInfo+ module Distribution.Types.BuildType,+ module Distribution.Types.BuildInfo,+ module Distribution.Types.HookedBuildInfo,+ module Distribution.Types.SetupBuildInfo,+ -- * Flags+ module Distribution.Types.Flag,+ -- * Identifiers+ module Distribution.Types.PackageId,+ module Distribution.Types.PackageName,+ module Distribution.Types.UnqualComponentName,+ -- * Pkgconfig+ module Distribution.Types.PkgconfigName,+ module Distribution.Types.PkgconfigVersion,+ module Distribution.Types.PkgconfigVersionRange,+ -- * Dependencies+ module Distribution.Types.Dependency,+ module Distribution.Types.ExeDependency,+ module Distribution.Types.LegacyExeDependency,+ module Distribution.Types.PkgconfigDependency,+ -- * Condition trees+ module Distribution.Types.CondTree,+ module Distribution.Types.Condition,+ module Distribution.Types.ConfVar,+ -- * Mixin+ module Distribution.Types.IncludeRenaming,+ module Distribution.Types.Mixin,+ module Distribution.Types.ModuleReexport,+ module Distribution.Types.ModuleRenaming,+ -- * Source repository+ module Distribution.Types.SourceRepo,+ ) where++import Prelude ()+--import Distribution.Compat.Prelude++import Distribution.Types.Benchmark+import Distribution.Types.BenchmarkInterface+import Distribution.Types.BenchmarkType+import Distribution.Types.BuildInfo+import Distribution.Types.BuildType+import Distribution.Types.ComponentName+import Distribution.Types.Condition+import Distribution.Types.CondTree+import Distribution.Types.ConfVar+import Distribution.Types.Dependency+import Distribution.Types.Executable+import Distribution.Types.ExecutableScope+import Distribution.Types.ExeDependency+import Distribution.Types.Flag+import Distribution.Types.ForeignLib+import Distribution.Types.ForeignLibOption+import Distribution.Types.ForeignLibType+import Distribution.Types.GenericPackageDescription+import Distribution.Types.HookedBuildInfo+import Distribution.Types.IncludeRenaming+import Distribution.Types.LegacyExeDependency+import Distribution.Types.Library+import Distribution.Types.LibraryName+import Distribution.Types.LibraryVisibility+import Distribution.Types.Mixin+import Distribution.Types.ModuleReexport+import Distribution.Types.ModuleRenaming+import Distribution.Types.PackageDescription+import Distribution.Types.PackageId+import Distribution.Types.PackageName+import Distribution.Types.PkgconfigDependency+import Distribution.Types.PkgconfigName+import Distribution.Types.PkgconfigVersion+import Distribution.Types.PkgconfigVersionRange+import Distribution.Types.SetupBuildInfo+import Distribution.Types.SourceRepo+import Distribution.Types.TestSuite+import Distribution.Types.TestSuiteInterface+import Distribution.Types.TestType+import Distribution.Types.UnqualComponentName
+ src/Distribution/PackageDescription/Check.hs view
@@ -0,0 +1,2392 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.PackageDescription.Check+-- Copyright : Lennart Kolmodin 2008+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This has code for checking for various problems in packages. There is one+-- set of checks that just looks at a 'PackageDescription' in isolation and+-- another set of checks that also looks at files in the package. Some of the+-- checks are basic sanity checks, others are portability standards that we'd+-- like to encourage. There is a 'PackageCheck' type that distinguishes the+-- different kinds of checks so we can see which ones are appropriate to report+-- in different situations. This code gets used when configuring a package when+-- we consider only basic problems. The higher standard is used when+-- preparing a source tarball and by Hackage when uploading new packages. The+-- reason for this is that we want to hold packages that are expected to be+-- distributed to a higher standard than packages that are only ever expected+-- to be used on the author's own environment.++module Distribution.PackageDescription.Check (+ -- * Package Checking+ PackageCheck(..),+ checkPackage,+ checkConfiguredPackage,++ -- ** Checking package contents+ checkPackageFiles,+ checkPackageContent,+ CheckPackageContentOps(..),+ checkPackageFileNames,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Data.List (group)+import Distribution.CabalSpecVersion+import Distribution.Compat.Lens+import Distribution.Compiler+import Distribution.License+import Distribution.Package+import Distribution.PackageDescription+import Distribution.PackageDescription.Configuration+import Distribution.Pretty (prettyShow)+import Distribution.Simple.BuildPaths (autogenPathsModuleName)+import Distribution.Simple.BuildToolDepends+import Distribution.Simple.CCompiler+import Distribution.Simple.Glob+import Distribution.Simple.Utils hiding (findPackageDesc, notice)+import Distribution.System+import Distribution.Types.ComponentRequestedSpec+import Distribution.Utils.Generic (isAscii)+import Distribution.Verbosity+import Distribution.Version+import Distribution.Utils.Path+import Language.Haskell.Extension+import System.FilePath+ (splitDirectories, splitExtension, splitPath, takeExtension, takeFileName, (<.>), (</>))++import qualified Data.ByteString.Lazy as BS+import qualified Data.Map as Map+import qualified Distribution.Compat.DList as DList+import qualified Distribution.SPDX as SPDX+import qualified System.Directory as System++import qualified System.Directory (getDirectoryContents)+import qualified System.FilePath.Windows as FilePath.Windows (isValid)++import qualified Data.Set as Set+import qualified Distribution.Utils.ShortText as ShortText++import qualified Distribution.Types.BuildInfo.Lens as L+import qualified Distribution.Types.GenericPackageDescription.Lens as L+import qualified Distribution.Types.PackageDescription.Lens as L++-- $setup+-- >>> import Control.Arrow ((&&&))++-- | Results of some kind of failed package check.+--+-- There are a range of severities, from merely dubious to totally insane.+-- All of them come with a human readable explanation. In future we may augment+-- them with more machine readable explanations, for example to help an IDE+-- suggest automatic corrections.+--+data PackageCheck =++ -- | This package description is no good. There's no way it's going to+ -- build sensibly. This should give an error at configure time.+ PackageBuildImpossible { explanation :: String }++ -- | A problem that is likely to affect building the package, or an+ -- issue that we'd like every package author to be aware of, even if+ -- the package is never distributed.+ | PackageBuildWarning { explanation :: String }++ -- | An issue that might not be a problem for the package author but+ -- might be annoying or detrimental when the package is distributed to+ -- users. We should encourage distributed packages to be free from these+ -- issues, but occasionally there are justifiable reasons so we cannot+ -- 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+ -- problems.+ | PackageDistInexcusable { explanation :: String }+ deriving (Eq, Ord)++instance Show PackageCheck where+ show notice = explanation notice++check :: Bool -> PackageCheck -> Maybe PackageCheck+check False _ = Nothing+check True pc = Just pc++checkSpecVersion :: PackageDescription -> CabalSpecVersion -> Bool -> PackageCheck+ -> Maybe PackageCheck+checkSpecVersion pkg specver cond pc+ | specVersion pkg >= specver = Nothing+ | otherwise = check cond pc++-- ------------------------------------------------------------+-- * Standard checks+-- ------------------------------------------------------------++-- | Check for common mistakes and problems in package descriptions.+--+-- This is the standard collection of checks covering all aspects except+-- for checks that require looking at files within the package. For those+-- see 'checkPackageFiles'.+--+-- It requires the 'GenericPackageDescription' and optionally a particular+-- configuration of that package. If you pass 'Nothing' then we just check+-- a version of the generic description using 'flattenPackageDescription'.+--+checkPackage :: GenericPackageDescription+ -> Maybe PackageDescription+ -> [PackageCheck]+checkPackage gpkg mpkg =+ checkConfiguredPackage pkg+ ++ checkConditionals gpkg+ ++ checkPackageVersions gpkg+ ++ checkDevelopmentOnlyFlags gpkg+ ++ checkFlagNames gpkg+ ++ checkUnusedFlags gpkg+ ++ checkUnicodeXFields gpkg+ ++ checkPathsModuleExtensions pkg+ where+ pkg = fromMaybe (flattenPackageDescription gpkg) mpkg++--TODO: make this variant go away+-- we should always know the GenericPackageDescription+checkConfiguredPackage :: PackageDescription -> [PackageCheck]+checkConfiguredPackage pkg =+ checkSanity pkg+ ++ checkFields pkg+ ++ checkLicense pkg+ ++ checkSourceRepos pkg+ ++ checkAllGhcOptions pkg+ ++ checkCCOptions pkg+ ++ checkCxxOptions pkg+ ++ checkCPPOptions pkg+ ++ checkPaths pkg+ ++ checkCabalVersion pkg+++-- ------------------------------------------------------------+-- * Basic sanity checks+-- ------------------------------------------------------------++-- | Check that this package description is sane.+--+checkSanity :: PackageDescription -> [PackageCheck]+checkSanity pkg =+ catMaybes [++ check (null . unPackageName . packageName $ pkg) $+ PackageBuildImpossible "No 'name' field."++ , check (nullVersion == packageVersion pkg) $+ PackageBuildImpossible "No 'version' field."++ , check (all ($ pkg) [ null . executables+ , null . testSuites+ , null . benchmarks+ , null . allLibraries+ , null . foreignLibs ]) $+ PackageBuildImpossible+ "No executables, libraries, tests, or benchmarks found. Nothing to do."++ , check (any (== LMainLibName) (map libName $ subLibraries pkg)) $+ PackageBuildImpossible $ "Found one or more unnamed internal libraries. "+ ++ "Only the non-internal library can have the same name as the package."++ , check (not (null duplicateNames)) $+ PackageBuildImpossible $ "Duplicate sections: "+ ++ commaSep (map unUnqualComponentName duplicateNames)+ ++ ". The name of every library, executable, test suite,"+ ++ " and benchmark section in"+ ++ " the package must be unique."++ -- NB: but it's OK for executables to have the same name!+ -- TODO shouldn't need to compare on the string level+ , check (any (== prettyShow (packageName pkg)) (prettyShow <$> subLibNames)) $+ PackageBuildImpossible $ "Illegal internal library name "+ ++ prettyShow (packageName pkg)+ ++ ". Internal libraries cannot have the same name as the package."+ ++ " Maybe you wanted a non-internal library?"+ ++ " If so, rewrite the section stanza"+ ++ " from 'library: '" ++ prettyShow (packageName pkg) ++ "' to 'library'."+ ]+ --TODO: check for name clashes case insensitively: windows file systems cannot+ --cope.++ ++ concatMap (checkLibrary pkg) (allLibraries pkg)+ ++ concatMap (checkExecutable pkg) (executables pkg)+ ++ concatMap (checkTestSuite pkg) (testSuites pkg)+ ++ concatMap (checkBenchmark pkg) (benchmarks pkg)++ where+ -- The public 'library' gets special dispensation, because it+ -- is common practice to export a library and name the executable+ -- the same as the package.+ subLibNames = mapMaybe (libraryNameString . libName) $ subLibraries pkg+ exeNames = map exeName $ executables pkg+ testNames = map testName $ testSuites pkg+ bmNames = map benchmarkName $ benchmarks pkg+ duplicateNames = dups $ subLibNames ++ exeNames ++ testNames ++ bmNames++checkLibrary :: PackageDescription -> Library -> [PackageCheck]+checkLibrary pkg lib =+ catMaybes [++ check (not (null moduleDuplicates)) $+ PackageBuildImpossible $+ "Duplicate modules in library: "+ ++ commaSep (map prettyShow moduleDuplicates)++ -- TODO: This check is bogus if a required-signature was passed through+ , check (null (explicitLibModules lib) && null (reexportedModules lib)) $+ PackageDistSuspiciousWarn $+ showLibraryName (libName lib) ++ " does not expose any modules"++ -- check use of signatures sections+ , checkVersion CabalSpecV2_0 (not (null (signatures lib))) $+ PackageDistInexcusable $+ "To use the 'signatures' field the package needs to specify "+ ++ "at least 'cabal-version: 2.0'."++ -- check that all autogen-modules appear on other-modules or exposed-modules+ , check+ (not $ and $ map (flip elem (explicitLibModules lib)) (libModulesAutogen lib)) $+ PackageBuildImpossible $+ "An 'autogen-module' is neither on 'exposed-modules' or "+ ++ "'other-modules'."++ -- check that all autogen-includes appear on includes or install-includes+ , check+ (not $ and $ map (flip elem (allExplicitIncludes lib)) (view L.autogenIncludes lib)) $+ PackageBuildImpossible $+ "An include in 'autogen-includes' is neither in 'includes' or "+ ++ "'install-includes'."+ ]++ where+ checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck+ checkVersion ver cond pc+ | specVersion pkg >= ver = Nothing+ | otherwise = check cond pc++ -- TODO: not sure if this check is always right in Backpack+ moduleDuplicates = dups (explicitLibModules lib +++ map moduleReexportName (reexportedModules lib))++allExplicitIncludes :: L.HasBuildInfo a => a -> [FilePath]+allExplicitIncludes x = view L.includes x ++ view L.installIncludes x++checkExecutable :: PackageDescription -> Executable -> [PackageCheck]+checkExecutable pkg exe =+ catMaybes [++ check (null (modulePath exe)) $+ PackageBuildImpossible $+ "No 'main-is' field found for executable " ++ prettyShow (exeName exe)++ , check (not (null (modulePath exe))+ && (not $ fileExtensionSupportedLanguage $ modulePath exe)) $+ PackageBuildImpossible $+ "The 'main-is' field must specify a '.hs' or '.lhs' file "+ ++ "(even if it is generated by a preprocessor), "+ ++ "or it may specify a C/C++/obj-C source file."++ , checkSpecVersion pkg CabalSpecV1_18+ (fileExtensionSupportedLanguage (modulePath exe)+ && takeExtension (modulePath exe) `notElem` [".hs", ".lhs"]) $+ 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'."++ , check (not (null moduleDuplicates)) $+ PackageBuildImpossible $+ "Duplicate modules in executable '" ++ prettyShow (exeName exe) ++ "': "+ ++ commaSep (map prettyShow moduleDuplicates)++ -- check that all autogen-modules appear on other-modules+ , check+ (not $ and $ map (flip elem (exeModules exe)) (exeModulesAutogen exe)) $+ PackageBuildImpossible $+ "On executable '" ++ prettyShow (exeName exe) ++ "' an 'autogen-module' is not "+ ++ "on 'other-modules'"++ -- check that all autogen-includes appear on includes+ , check+ (not $ and $ map (flip elem (view L.includes exe)) (view L.autogenIncludes exe)) $+ PackageBuildImpossible "An include in 'autogen-includes' is not in 'includes'."+ ]+ where+ moduleDuplicates = dups (exeModules exe)++checkTestSuite :: PackageDescription -> TestSuite -> [PackageCheck]+checkTestSuite pkg test =+ catMaybes [++ case testInterface test of+ TestSuiteUnsupported tt@(TestTypeUnknown _ _) -> Just $+ PackageBuildWarning $+ quote (prettyShow tt) ++ " is not a known type of test suite. "+ ++ "The known test suite types are: "+ ++ commaSep (map prettyShow knownTestTypes)++ TestSuiteUnsupported tt -> Just $+ PackageBuildWarning $+ quote (prettyShow tt) ++ " is not a supported test suite version. "+ ++ "The known test suite types are: "+ ++ commaSep (map prettyShow knownTestTypes)+ _ -> Nothing++ , check (not $ null moduleDuplicates) $+ PackageBuildImpossible $+ "Duplicate modules in test suite '" ++ prettyShow (testName test) ++ "': "+ ++ commaSep (map prettyShow moduleDuplicates)++ , check mainIsWrongExt $+ PackageBuildImpossible $+ "The 'main-is' field must specify a '.hs' or '.lhs' file "+ ++ "(even if it is generated by a preprocessor), "+ ++ "or it may specify a C/C++/obj-C source file."++ , checkSpecVersion pkg CabalSpecV1_18 (mainIsNotHsExt && not mainIsWrongExt) $+ 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'."++ -- check that all autogen-modules appear on other-modules+ , check+ (not $ and $ map (flip elem (testModules test)) (testModulesAutogen test)) $+ PackageBuildImpossible $+ "On test suite '" ++ prettyShow (testName test) ++ "' an 'autogen-module' is not "+ ++ "on 'other-modules'"++ -- check that all autogen-includes appear on includes+ , check+ (not $ and $ map (flip elem (view L.includes test)) (view L.autogenIncludes test)) $+ PackageBuildImpossible "An include in 'autogen-includes' is not in 'includes'."+ ]+ where+ moduleDuplicates = dups $ testModules test++ mainIsWrongExt = case testInterface test of+ TestSuiteExeV10 _ f -> not $ fileExtensionSupportedLanguage f+ _ -> False++ mainIsNotHsExt = case testInterface test of+ TestSuiteExeV10 _ f -> takeExtension f `notElem` [".hs", ".lhs"]+ _ -> False++checkBenchmark :: PackageDescription -> Benchmark -> [PackageCheck]+checkBenchmark _pkg bm =+ catMaybes [++ case benchmarkInterface bm of+ BenchmarkUnsupported tt@(BenchmarkTypeUnknown _ _) -> Just $+ PackageBuildWarning $+ quote (prettyShow tt) ++ " is not a known type of benchmark. "+ ++ "The known benchmark types are: "+ ++ commaSep (map prettyShow knownBenchmarkTypes)++ BenchmarkUnsupported tt -> Just $+ PackageBuildWarning $+ quote (prettyShow tt) ++ " is not a supported benchmark version. "+ ++ "The known benchmark types are: "+ ++ commaSep (map prettyShow knownBenchmarkTypes)+ _ -> Nothing++ , check (not $ null moduleDuplicates) $+ PackageBuildImpossible $+ "Duplicate modules in benchmark '" ++ prettyShow (benchmarkName bm) ++ "': "+ ++ commaSep (map prettyShow moduleDuplicates)++ , check mainIsWrongExt $+ PackageBuildImpossible $+ "The 'main-is' field must specify a '.hs' or '.lhs' file "+ ++ "(even if it is generated by a preprocessor)."++ -- check that all autogen-modules appear on other-modules+ , check+ (not $ and $ map (flip elem (benchmarkModules bm)) (benchmarkModulesAutogen bm)) $+ PackageBuildImpossible $+ "On benchmark '" ++ prettyShow (benchmarkName bm) ++ "' an 'autogen-module' is "+ ++ "not on 'other-modules'"++ -- check that all autogen-includes appear on includes+ , check+ (not $ and $ map (flip elem (view L.includes bm)) (view L.autogenIncludes bm)) $+ PackageBuildImpossible "An include in 'autogen-includes' is not in 'includes'."+ ]+ where+ moduleDuplicates = dups $ benchmarkModules bm++ mainIsWrongExt = case benchmarkInterface bm of+ BenchmarkExeV10 _ f -> takeExtension f `notElem` [".hs", ".lhs"]+ _ -> False++-- ------------------------------------------------------------+-- * Additional pure checks+-- ------------------------------------------------------------++checkFields :: PackageDescription -> [PackageCheck]+checkFields pkg =+ catMaybes [++ check (not . FilePath.Windows.isValid . prettyShow . packageName $ pkg) $+ PackageDistInexcusable $+ "Unfortunately, the package name '" ++ prettyShow (packageName pkg)+ ++ "' is one of the reserved system file names on Windows. Many tools "+ ++ "need to convert package names to file names so using this name "+ ++ "would cause problems."++ , check ((isPrefixOf "z-") . prettyShow . packageName $ pkg) $+ PackageDistInexcusable $+ "Package names with the prefix 'z-' are reserved by Cabal and "+ ++ "cannot be used."++ , check (isNothing (buildTypeRaw pkg) && specVersion pkg < CabalSpecV2_2) $+ PackageBuildWarning $+ "No 'build-type' specified. If you do not need a custom Setup.hs or "+ ++ "./configure script then use 'build-type: Simple'."++ , check (isJust (setupBuildInfo pkg) && buildType pkg /= 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)+ ++ " in 'tested-with' field."++ , check (not (null unknownLanguages)) $+ PackageBuildWarning $+ "Unknown languages: " ++ commaSep unknownLanguages++ , check (not (null unknownExtensions)) $+ PackageBuildWarning $+ "Unknown extensions: " ++ commaSep unknownExtensions++ , check (not (null languagesUsedAsExtensions)) $+ PackageBuildWarning $+ "Languages listed as extensions: "+ ++ commaSep languagesUsedAsExtensions+ ++ ". Languages must be specified in either the 'default-language' "+ ++ " or the 'other-languages' field."++ , check (not (null ourDeprecatedExtensions)) $+ PackageDistSuspicious $+ "Deprecated extensions: "+ ++ commaSep (map (quote . prettyShow . fst) ourDeprecatedExtensions)+ ++ ". " ++ unwords+ [ "Instead of '" ++ prettyShow ext+ ++ "' use '" ++ prettyShow replacement ++ "'."+ | (ext, Just replacement) <- ourDeprecatedExtensions ]++ , check (ShortText.null (category pkg)) $+ PackageDistSuspicious "No 'category' field."++ , check (ShortText.null (maintainer pkg)) $+ PackageDistSuspicious "No 'maintainer' field."++ , check (ShortText.null (synopsis pkg) && ShortText.null (description pkg)) $+ PackageDistInexcusable "No 'synopsis' or 'description' field."++ , check (ShortText.null (description pkg) && not (ShortText.null (synopsis pkg))) $+ PackageDistSuspicious "No 'description' field."++ , check (ShortText.null (synopsis pkg) && not (ShortText.null (description pkg))) $+ PackageDistSuspicious "No 'synopsis' field."++ --TODO: recommend the bug reports URL, author and homepage fields+ --TODO: recommend not using the stability field+ --TODO: recommend specifying a source repo++ , check (ShortText.length (synopsis pkg) >= 80) $+ PackageDistSuspicious+ "The 'synopsis' field is rather long (max 80 chars is recommended)."++ -- See also https://github.com/haskell/cabal/pull/3479+ , check (not (ShortText.null (description pkg))+ && ShortText.length (description pkg) <= ShortText.length (synopsis pkg)) $+ PackageDistSuspicious $+ "The 'description' field should be longer than the 'synopsis' "+ ++ "field. "+ ++ "It's useful to provide an informative 'description' to allow "+ ++ "Haskell programmers who have never heard about your package to "+ ++ "understand the purpose of your package. "+ ++ "The 'description' field content is typically shown by tooling "+ ++ "(e.g. 'cabal info', Haddock, Hackage) below the 'synopsis' which "+ ++ "serves as a headline. "+ ++ "Please refer to <https://www.haskell.org/"+ ++ "cabal/users-guide/developing-packages.html#package-properties>"+ ++ " for more details."++ -- check use of impossible constraints "tested-with: GHC== 6.10 && ==6.12"+ , check (not (null testedWithImpossibleRanges)) $+ PackageDistInexcusable $+ "Invalid 'tested-with' version range: "+ ++ commaSep (map prettyShow testedWithImpossibleRanges)+ ++ ". To indicate that you have tested a package with multiple "+ ++ "different versions of the same compiler use multiple entries, "+ ++ "for example 'tested-with: GHC==6.10.4, GHC==6.12.3' and not "+ ++ "'tested-with: GHC==6.10.4 && ==6.12.3'."++ -- for more details on why the following was commented out,+ -- check https://github.com/haskell/cabal/pull/7470#issuecomment-875878507+ -- , check (not (null depInternalLibraryWithExtraVersion)) $+ -- PackageBuildWarning $+ -- "The package has an extraneous version range for a dependency on an "+ -- ++ "internal library: "+ -- ++ commaSep (map prettyShow depInternalLibraryWithExtraVersion)+ -- ++ ". This version range includes the current package but isn't needed "+ -- ++ "as the current package's library will always be used."++ , check (not (null depInternalLibraryWithImpossibleVersion)) $+ PackageBuildImpossible $+ "The package has an impossible version range for a dependency on an "+ ++ "internal library: "+ ++ commaSep (map prettyShow depInternalLibraryWithImpossibleVersion)+ ++ ". This version range does not include the current package, and must "+ ++ "be removed as the current package's library will always be used."++ -- , check (not (null depInternalExecutableWithExtraVersion)) $+ -- PackageBuildWarning $+ -- "The package has an extraneous version range for a dependency on an "+ -- ++ "internal executable: "+ -- ++ commaSep (map prettyShow depInternalExecutableWithExtraVersion)+ -- ++ ". This version range includes the current package but isn't needed "+ -- ++ "as the current package's executable will always be used."++ , check (not (null depInternalExecutableWithImpossibleVersion)) $+ PackageBuildImpossible $+ "The package has an impossible version range for a dependency on an "+ ++ "internal executable: "+ ++ commaSep (map prettyShow depInternalExecutableWithImpossibleVersion)+ ++ ". This version range does not include the current package, and must "+ ++ "be removed as the current package's executable will always be used."++ , check (not (null depMissingInternalExecutable)) $+ PackageBuildImpossible $+ "The package depends on a missing internal executable: "+ ++ commaSep (map prettyShow depInternalExecutableWithImpossibleVersion)+ ]+ where+ unknownCompilers = [ name | (OtherCompiler name, _) <- testedWith pkg ]+ unknownLanguages = [ name | bi <- allBuildInfo pkg+ , UnknownLanguage name <- allLanguages bi ]+ unknownExtensions = [ name | bi <- allBuildInfo pkg+ , UnknownExtension name <- allExtensions bi+ , name `notElem` map prettyShow knownLanguages ]+ ourDeprecatedExtensions = nub $ catMaybes+ [ find ((==ext) . fst) deprecatedExtensions+ | bi <- allBuildInfo pkg+ , ext <- allExtensions bi ]+ languagesUsedAsExtensions =+ [ name | bi <- allBuildInfo pkg+ , UnknownExtension name <- allExtensions bi+ , name `elem` map prettyShow knownLanguages ]++ testedWithImpossibleRanges =+ [ Dependency (mkPackageName (prettyShow compiler)) vr mainLibSet+ | (compiler, vr) <- testedWith pkg+ , isNoVersion vr ]++ internalLibraries =+ map (maybe (packageName pkg) (unqualComponentNameToPackageName) . libraryNameString . libName)+ (allLibraries pkg)++ internalExecutables = map exeName $ executables pkg++ internalLibDeps =+ [ dep+ | bi <- allBuildInfo pkg+ , dep@(Dependency name _ _) <- targetBuildDepends bi+ , name `elem` internalLibraries+ ]++ internalExeDeps =+ [ dep+ | bi <- allBuildInfo pkg+ , dep <- getAllToolDependencies pkg bi+ , isInternal pkg dep+ ]++ -- depInternalLibraryWithExtraVersion =+ -- [ dep+ -- | dep@(Dependency _ versionRange _) <- internalLibDeps+ -- , not $ isAnyVersion versionRange+ -- , packageVersion pkg `withinRange` versionRange+ -- ]++ depInternalLibraryWithImpossibleVersion =+ [ dep+ | dep@(Dependency _ versionRange _) <- internalLibDeps+ , not $ packageVersion pkg `withinRange` versionRange+ ]++ -- depInternalExecutableWithExtraVersion =+ -- [ dep+ -- | dep@(ExeDependency _ _ versionRange) <- internalExeDeps+ -- , not $ isAnyVersion versionRange+ -- , packageVersion pkg `withinRange` versionRange+ -- ]++ depInternalExecutableWithImpossibleVersion =+ [ dep+ | dep@(ExeDependency _ _ versionRange) <- internalExeDeps+ , not $ packageVersion pkg `withinRange` versionRange+ ]++ depMissingInternalExecutable =+ [ dep+ | dep@(ExeDependency _ eName _) <- internalExeDeps+ , not $ eName `elem` internalExecutables+ ]+++checkLicense :: PackageDescription -> [PackageCheck]+checkLicense pkg = case licenseRaw pkg of+ Right l -> checkOldLicense pkg l+ Left l -> checkNewLicense pkg l++checkNewLicense :: PackageDescription -> SPDX.License -> [PackageCheck]+checkNewLicense _pkg lic = catMaybes+ [ check (lic == SPDX.NONE) $+ PackageDistInexcusable+ "The 'license' field is missing or is NONE."+ ]++checkOldLicense :: PackageDescription -> License -> [PackageCheck]+checkOldLicense pkg lic = catMaybes+ [ check (lic == UnspecifiedLicense) $+ PackageDistInexcusable+ "The 'license' field is missing."++ , check (lic == AllRightsReserved) $+ PackageDistSuspicious+ "The 'license' is AllRightsReserved. Is that really what you want?"++ , checkVersion CabalSpecV1_4 (lic `notElem` compatLicenses) $+ PackageDistInexcusable $+ "Unfortunately the license " ++ quote (prettyShow (license pkg))+ ++ " messes up the parser in earlier Cabal versions so you need to "+ ++ "specify 'cabal-version: >= 1.4'. Alternatively if you require "+ ++ "compatibility with earlier Cabal versions then use 'OtherLicense'."++ , case lic of+ UnknownLicense l -> Just $+ PackageBuildWarning $+ quote ("license: " ++ l) ++ " is not a recognised license. The "+ ++ "known licenses are: "+ ++ commaSep (map prettyShow knownLicenses)+ _ -> Nothing++ , check (lic == BSD4) $+ PackageDistSuspicious $+ "Using 'license: BSD4' is almost always a misunderstanding. 'BSD4' "+ ++ "refers to the old 4-clause BSD license with the advertising "+ ++ "clause. 'BSD3' refers the new 3-clause BSD license."++ , case unknownLicenseVersion (lic) of+ Just knownVersions -> Just $+ PackageDistSuspicious $+ "'license: " ++ prettyShow (lic) ++ "' is not a known "+ ++ "version of that license. The known versions are "+ ++ commaSep (map prettyShow knownVersions)+ ++ ". If this is not a mistake and you think it should be a known "+ ++ "version then please file a ticket."+ _ -> Nothing++ , check (lic `notElem` [ AllRightsReserved+ , UnspecifiedLicense, PublicDomain]+ -- AllRightsReserved and PublicDomain are not strictly+ -- licenses so don't need license files.+ && null (licenseFiles pkg)) $+ PackageDistSuspicious "A 'license-file' is not specified."+ ]+ where+ unknownLicenseVersion (GPL (Just v))+ | v `notElem` knownVersions = Just knownVersions+ where knownVersions = [ v' | GPL (Just v') <- knownLicenses ]+ unknownLicenseVersion (LGPL (Just v))+ | v `notElem` knownVersions = Just knownVersions+ where knownVersions = [ v' | LGPL (Just v') <- knownLicenses ]+ unknownLicenseVersion (AGPL (Just v))+ | v `notElem` knownVersions = Just knownVersions+ where knownVersions = [ v' | AGPL (Just v') <- knownLicenses ]+ unknownLicenseVersion (Apache (Just v))+ | v `notElem` knownVersions = Just knownVersions+ where knownVersions = [ v' | Apache (Just v') <- knownLicenses ]+ unknownLicenseVersion _ = Nothing++ checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck+ checkVersion ver cond pc+ | specVersion pkg >= ver = Nothing+ | otherwise = check cond pc++ compatLicenses = [ GPL Nothing, LGPL Nothing, AGPL Nothing, BSD3, BSD4+ , PublicDomain, AllRightsReserved+ , UnspecifiedLicense, OtherLicense ]++checkSourceRepos :: PackageDescription -> [PackageCheck]+checkSourceRepos pkg =+ catMaybes $ concat [[++ case repoKind repo of+ RepoKindUnknown kind -> Just $ PackageDistInexcusable $+ quote kind ++ " is not a recognised kind of source-repository. "+ ++ "The repo kind is usually 'head' or 'this'"+ _ -> Nothing++ , check (isNothing (repoType repo)) $+ PackageDistInexcusable+ "The source-repository 'type' is a required field."++ , check (isNothing (repoLocation repo)) $+ PackageDistInexcusable+ "The source-repository 'location' is a required field."++ , check (repoType repo == Just (KnownRepoType CVS) && isNothing (repoModule repo)) $+ PackageDistInexcusable+ "For a CVS source-repository, the 'module' is a required field."++ , check (repoKind repo == RepoThis && isNothing (repoTag repo)) $+ PackageDistInexcusable $+ "For the 'this' kind of source-repository, the 'tag' is a required "+ ++ "field. It should specify the tag corresponding to this version "+ ++ "or release of the package."++ , check (maybe False isAbsoluteOnAnyPlatform (repoSubdir repo)) $+ PackageDistInexcusable+ "The 'subdir' field of a source-repository must be a relative path."++ , check (maybe False isAbsoluteOnAnyPlatform (repoSubdir repo)) $+ PackageDistInexcusable+ "The 'subdir' field of a source-repository must be a relative path."++ , do+ subdir <- repoSubdir repo+ err <- isGoodRelativeDirectoryPath subdir+ return $ PackageDistInexcusable $+ "The 'subdir' field of a source-repository is not a good relative path: " ++ show err+ ]+ | repo <- sourceRepos pkg ]++--TODO: check location looks like a URL for some repo types.++-- | Checks GHC options from all ghc-*-options fields in the given+-- PackageDescription and reports commonly misused or non-portable flags+checkAllGhcOptions :: PackageDescription -> [PackageCheck]+checkAllGhcOptions pkg =+ checkGhcOptions "ghc-options" (hcOptions GHC) pkg+ ++ checkGhcOptions "ghc-prof-options" (hcProfOptions GHC) pkg+ ++ checkGhcOptions "ghc-shared-options" (hcSharedOptions GHC) pkg++-- | Extracts GHC options belonging to the given field from the given+-- PackageDescription using given function and checks them for commonly misused+-- or non-portable flags+checkGhcOptions :: String -> (BuildInfo -> [String]) -> PackageDescription -> [PackageCheck]+checkGhcOptions fieldName getOptions pkg =+ catMaybes [++ checkFlags ["-fasm"] $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -fasm' is unnecessary and will not work on CPU "+ ++ "architectures other than x86, x86-64, ppc or sparc."++ , checkFlags ["-fvia-C"] $+ PackageDistSuspicious $+ "'" ++ fieldName ++": -fvia-C' is usually unnecessary. If your package "+ ++ "needs -via-C for correctness rather than performance then it "+ ++ "is using the FFI incorrectly and will probably not work with GHC "+ ++ "6.10 or later."++ , checkFlags ["-fhpc"] $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -fhpc' is not necessary. Use the configure flag "+ ++ " --enable-coverage instead."++ , checkFlags ["-prof"] $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -prof' is not necessary and will lead to problems "+ ++ "when used on a library. Use the configure flag "+ ++ "--enable-library-profiling and/or --enable-profiling."++ , checkFlags ["-o"] $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -o' is not needed. "+ ++ "The output files are named automatically."++ , checkFlags ["-hide-package"] $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -hide-package' is never needed. "+ ++ "Cabal hides all packages."++ , checkFlags ["--make"] $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": --make' is never needed. Cabal uses this automatically."++ , checkFlags ["-main-is"] $+ PackageDistSuspicious $+ "'" ++ fieldName ++ ": -main-is' is not portable."++ , checkNonTestAndBenchmarkFlags ["-O0", "-Onot"] $+ PackageDistSuspicious $+ "'" ++ fieldName ++ ": -O0' is not needed. "+ ++ "Use the --disable-optimization configure flag."++ , checkTestAndBenchmarkFlags ["-O0", "-Onot"] $+ PackageDistSuspiciousWarn $+ "'" ++ fieldName ++ ": -O0' is not needed. "+ ++ "Use the --disable-optimization configure flag."++ , checkFlags [ "-O", "-O1"] $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -O' is not needed. "+ ++ "Cabal automatically adds the '-O' flag. "+ ++ "Setting it yourself interferes with the --disable-optimization flag."++ , checkFlags ["-O2"] $+ PackageDistSuspiciousWarn $+ "'" ++ fieldName ++ ": -O2' is rarely needed. "+ ++ "Check that it is giving a real benefit "+ ++ "and not just imposing longer compile times on your users."++ , checkFlags ["-split-sections"] $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -split-sections' is not needed. "+ ++ "Use the --enable-split-sections configure flag."++ , checkFlags ["-split-objs"] $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -split-objs' is not needed. "+ ++ "Use the --enable-split-objs configure flag."++ , checkFlags ["-optl-Wl,-s", "-optl-s"] $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -optl-Wl,-s' is not needed and is not portable to all"+ ++ " operating systems. Cabal 1.4 and later automatically strip"+ ++ " executables. Cabal also has a flag --disable-executable-stripping"+ ++ " which is necessary when building packages for some Linux"+ ++ " distributions and using '-optl-Wl,-s' prevents that from working."++ , checkFlags ["-fglasgow-exts"] $+ PackageDistSuspicious $+ "Instead of '" ++ fieldName ++ ": -fglasgow-exts' it is preferable to use "+ ++ "the 'extensions' field."++ , check ("-threaded" `elem` lib_ghc_options) $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -threaded' has no effect for libraries. It should "+ ++ "only be used for executables."++ , check ("-rtsopts" `elem` lib_ghc_options) $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -rtsopts' has no effect for libraries. It should "+ ++ "only be used for executables."++ , check (any (\opt -> "-with-rtsopts" `isPrefixOf` opt) lib_ghc_options) $+ PackageBuildWarning $+ "'" ++ fieldName ++ ": -with-rtsopts' has no effect for libraries. It "+ ++ "should only be used for executables."++ , checkAlternatives fieldName "extensions"+ [ (flag, prettyShow extension) | flag <- all_ghc_options+ , Just extension <- [ghcExtension flag] ]++ , checkAlternatives fieldName "extensions"+ [ (flag, extension) | flag@('-':'X':extension) <- all_ghc_options ]++ , checkAlternatives fieldName "cpp-options" $+ [ (flag, flag) | flag@('-':'D':_) <- all_ghc_options ]+ ++ [ (flag, flag) | flag@('-':'U':_) <- all_ghc_options ]++ , checkAlternatives fieldName "include-dirs"+ [ (flag, dir) | flag@('-':'I':dir) <- all_ghc_options ]++ , checkAlternatives fieldName "extra-libraries"+ [ (flag, lib) | flag@('-':'l':lib) <- all_ghc_options ]++ , checkAlternatives fieldName "extra-lib-dirs"+ [ (flag, dir) | flag@('-':'L':dir) <- all_ghc_options ]++ , checkAlternatives fieldName "frameworks"+ [ (flag, fmwk) | (flag@"-framework", fmwk) <-+ zip all_ghc_options (safeTail all_ghc_options) ]++ , checkAlternatives fieldName "extra-framework-dirs"+ [ (flag, dir) | (flag@"-framework-path", dir) <-+ zip all_ghc_options (safeTail all_ghc_options) ]+ ]++ where+ all_ghc_options = concatMap getOptions (allBuildInfo pkg)+ lib_ghc_options = concatMap (getOptions . libBuildInfo)+ (allLibraries pkg)+ test_ghc_options = concatMap (getOptions . testBuildInfo)+ (testSuites pkg)+ benchmark_ghc_options = concatMap (getOptions . benchmarkBuildInfo)+ (benchmarks pkg)+ test_and_benchmark_ghc_options = test_ghc_options +++ benchmark_ghc_options+ non_test_and_benchmark_ghc_options = concatMap getOptions+ (allBuildInfo (pkg { testSuites = []+ , benchmarks = []+ }))++ checkFlags :: [String] -> PackageCheck -> Maybe PackageCheck+ checkFlags flags = check (any (`elem` flags) all_ghc_options)++ checkTestAndBenchmarkFlags :: [String] -> PackageCheck -> Maybe PackageCheck+ checkTestAndBenchmarkFlags flags = check (any (`elem` flags) test_and_benchmark_ghc_options)++ checkNonTestAndBenchmarkFlags :: [String] -> PackageCheck -> Maybe PackageCheck+ checkNonTestAndBenchmarkFlags flags = check (any (`elem` flags) non_test_and_benchmark_ghc_options)++ ghcExtension ('-':'f':name) = case name of+ "allow-overlapping-instances" -> enable OverlappingInstances+ "no-allow-overlapping-instances" -> disable OverlappingInstances+ "th" -> enable TemplateHaskell+ "no-th" -> disable TemplateHaskell+ "ffi" -> enable ForeignFunctionInterface+ "no-ffi" -> disable ForeignFunctionInterface+ "fi" -> enable ForeignFunctionInterface+ "no-fi" -> disable ForeignFunctionInterface+ "monomorphism-restriction" -> enable MonomorphismRestriction+ "no-monomorphism-restriction" -> disable MonomorphismRestriction+ "mono-pat-binds" -> enable MonoPatBinds+ "no-mono-pat-binds" -> disable MonoPatBinds+ "allow-undecidable-instances" -> enable UndecidableInstances+ "no-allow-undecidable-instances" -> disable UndecidableInstances+ "allow-incoherent-instances" -> enable IncoherentInstances+ "no-allow-incoherent-instances" -> disable IncoherentInstances+ "arrows" -> enable Arrows+ "no-arrows" -> disable Arrows+ "generics" -> enable Generics+ "no-generics" -> disable Generics+ "implicit-prelude" -> enable ImplicitPrelude+ "no-implicit-prelude" -> disable ImplicitPrelude+ "implicit-params" -> enable ImplicitParams+ "no-implicit-params" -> disable ImplicitParams+ "bang-patterns" -> enable BangPatterns+ "no-bang-patterns" -> disable BangPatterns+ "scoped-type-variables" -> enable ScopedTypeVariables+ "no-scoped-type-variables" -> disable ScopedTypeVariables+ "extended-default-rules" -> enable ExtendedDefaultRules+ "no-extended-default-rules" -> disable ExtendedDefaultRules+ _ -> Nothing+ ghcExtension "-cpp" = enable CPP+ ghcExtension _ = Nothing++ enable e = Just (EnableExtension e)+ disable e = Just (DisableExtension e)++checkCCOptions :: PackageDescription -> [PackageCheck]+checkCCOptions = checkCLikeOptions "C" "cc-options" ccOptions++checkCxxOptions :: PackageDescription -> [PackageCheck]+checkCxxOptions = checkCLikeOptions "C++" "cxx-options" cxxOptions++checkCLikeOptions :: String -> String -> (BuildInfo -> [String]) -> PackageDescription -> [PackageCheck]+checkCLikeOptions label prefix accessor pkg =+ catMaybes [++ checkAlternatives prefix "include-dirs"+ [ (flag, dir) | flag@('-':'I':dir) <- all_cLikeOptions ]++ , checkAlternatives prefix "extra-libraries"+ [ (flag, lib) | flag@('-':'l':lib) <- all_cLikeOptions ]++ , checkAlternatives prefix "extra-lib-dirs"+ [ (flag, dir) | flag@('-':'L':dir) <- all_cLikeOptions ]++ , checkAlternatives "ld-options" "extra-libraries"+ [ (flag, lib) | flag@('-':'l':lib) <- all_ldOptions ]++ , checkAlternatives "ld-options" "extra-lib-dirs"+ [ (flag, dir) | flag@('-':'L':dir) <- all_ldOptions ]++ , checkCCFlags [ "-O", "-Os", "-O0", "-O1", "-O2", "-O3" ] $+ PackageDistSuspicious $+ "'"++prefix++": -O[n]' is generally not needed. When building with "+ ++ " optimisations Cabal automatically adds '-O2' for "++label++" code. "+ ++ "Setting it yourself interferes with the --disable-optimization flag."+ ]++ where all_cLikeOptions = [ opts | bi <- allBuildInfo pkg+ , opts <- accessor bi ]+ all_ldOptions = [ opts | bi <- allBuildInfo pkg+ , opts <- ldOptions bi ]++ checkCCFlags :: [String] -> PackageCheck -> Maybe PackageCheck+ checkCCFlags flags = check (any (`elem` flags) all_cLikeOptions)++checkCPPOptions :: PackageDescription -> [PackageCheck]+checkCPPOptions pkg = catMaybes+ [ checkAlternatives "cpp-options" "include-dirs"+ [ (flag, dir) | flag@('-':'I':dir) <- all_cppOptions ]+ ]+ +++ [ PackageBuildWarning $ "'cpp-options': " ++ opt ++ " is not portable C-preprocessor flag"+ | opt <- all_cppOptions+ -- "-I" is handled above, we allow only -DNEWSTUFF and -UOLDSTUFF+ , not $ any (`isPrefixOf` opt) ["-D", "-U", "-I" ]+ ]+ where+ all_cppOptions = [ opts | bi <- allBuildInfo pkg, opts <- cppOptions bi ]++checkAlternatives :: String -> String -> [(String, String)]+ -> Maybe PackageCheck+checkAlternatives badField goodField flags =+ check (not (null badFlags)) $+ PackageBuildWarning $+ "Instead of " ++ quote (badField ++ ": " ++ unwords badFlags)+ ++ " use " ++ quote (goodField ++ ": " ++ unwords goodFlags)++ where (badFlags, goodFlags) = unzip flags++data PathKind+ = PathKindFile+ | PathKindDirectory+ | PathKindGlob++checkPaths :: PackageDescription -> [PackageCheck]+checkPaths pkg =+ [ PackageBuildWarning $+ quote (field ++ ": " ++ path)+ ++ " is a relative path outside of the source tree. "+ ++ "This will not work when generating a tarball with 'sdist'."+ | (path, field, _) <- relPaths ++ absPaths+ , isOutsideTree path ]+ +++ [ PackageDistInexcusable $+ quote (field ++ ": " ++ path) ++ " is an absolute path."+ | (path, field, _) <- relPaths+ , isAbsoluteOnAnyPlatform path ]+ +++ [ PackageDistInexcusable $+ quote (field ++ ": " ++ path) ++ " is not good relative path: " ++ err+ | (path, field, kind) <- relPaths+ -- these are not paths, but globs...+ , err <- maybeToList $ case kind of+ PathKindFile -> isGoodRelativeFilePath path+ PathKindGlob -> isGoodRelativeGlob path+ PathKindDirectory -> isGoodRelativeDirectoryPath path+ ]+ +++ [ PackageDistInexcusable $+ quote (field ++ ": " ++ path) ++ " points inside the 'dist' "+ ++ "directory. This is not reliable because the location of this "+ ++ "directory is configurable by the user (or package manager). In "+ ++ "addition the layout of the 'dist' directory is subject to change "+ ++ "in future versions of Cabal."+ | (path, field, _) <- relPaths ++ absPaths+ , isInsideDist path ]+ +++ [ PackageDistInexcusable $+ "The 'ghc-options' contains the path '" ++ path ++ "' which points "+ ++ "inside the 'dist' directory. This is not reliable because the "+ ++ "location of this directory is configurable by the user (or package "+ ++ "manager). In addition the layout of the 'dist' directory is subject "+ ++ "to change in future versions of Cabal."+ | bi <- allBuildInfo pkg+ , (GHC, flags) <- perCompilerFlavorToList $ options bi+ , path <- flags+ , isInsideDist path ]+ +++ [ PackageDistInexcusable $+ "In the 'data-files' field: " ++ explainGlobSyntaxError pat err+ | pat <- dataFiles pkg+ , Left err <- [parseFileGlob (specVersion pkg) pat]+ ]+ +++ [ PackageDistInexcusable $+ "In the 'extra-source-files' field: " ++ explainGlobSyntaxError pat err+ | pat <- extraSrcFiles pkg+ , Left err <- [parseFileGlob (specVersion pkg) pat]+ ]+ +++ [ PackageDistInexcusable $+ "In the 'extra-doc-files' field: " ++ explainGlobSyntaxError pat err+ | pat <- extraDocFiles pkg+ , Left err <- [parseFileGlob (specVersion pkg) pat]+ ]+ where+ isOutsideTree path = case splitDirectories path of+ "..":_ -> True+ ".":"..":_ -> True+ _ -> False+ isInsideDist path = case map lowercase (splitDirectories path) of+ "dist" :_ -> True+ ".":"dist":_ -> True+ _ -> False++ -- paths that must be relative+ relPaths :: [(FilePath, String, PathKind)]+ relPaths =+ [ (path, "extra-source-files", PathKindGlob) | path <- extraSrcFiles pkg ] +++ [ (path, "extra-tmp-files", PathKindFile) | path <- extraTmpFiles pkg ] +++ [ (path, "extra-doc-files", PathKindGlob) | path <- extraDocFiles pkg ] +++ [ (path, "data-files", PathKindGlob) | path <- dataFiles pkg ] +++ [ (path, "data-dir", PathKindDirectory) | path <- [dataDir pkg]] +++ [ (path, "license-file", PathKindFile) | path <- map getSymbolicPath $ licenseFiles pkg ] +++ concat+ [ [ (path, "asm-sources", PathKindFile) | path <- asmSources bi ] +++ [ (path, "cmm-sources", PathKindFile) | path <- cmmSources bi ] +++ [ (path, "c-sources", PathKindFile) | path <- cSources bi ] +++ [ (path, "cxx-sources", PathKindFile) | path <- cxxSources bi ] +++ [ (path, "js-sources", PathKindFile) | path <- jsSources bi ] +++ [ (path, "install-includes", PathKindFile) | path <- installIncludes bi ] +++ [ (path, "hs-source-dirs", PathKindDirectory) | path <- map getSymbolicPath $ hsSourceDirs bi ]+ | bi <- allBuildInfo pkg+ ]++ -- paths that are allowed to be absolute+ absPaths :: [(FilePath, String, PathKind)]+ absPaths = concat+ [ [ (path, "includes", PathKindFile) | path <- includes bi ] +++ [ (path, "include-dirs", PathKindDirectory) | path <- includeDirs bi ] +++ [ (path, "extra-lib-dirs", PathKindDirectory) | path <- extraLibDirs bi ]+ | bi <- allBuildInfo pkg+ ]++--TODO: check sets of paths that would be interpreted differently between Unix+-- and windows, ie case-sensitive or insensitive. Things that might clash, or+-- conversely be distinguished.++--TODO: use the tar path checks on all the above paths++-- | Check that the package declares the version in the @\"cabal-version\"@+-- field correctly.+--+checkCabalVersion :: PackageDescription -> [PackageCheck]+checkCabalVersion pkg =+ catMaybes [++ -- check use of test suite sections+ checkVersion CabalSpecV1_8 (not (null $ testSuites pkg)) $+ PackageDistInexcusable $+ "The 'test-suite' section is new in Cabal 1.10. "+ ++ "Unfortunately it messes up the parser in older Cabal versions "+ ++ "so you must specify at least 'cabal-version: >= 1.8', but note "+ ++ "that only Cabal 1.10 and later can actually run such test suites."++ -- check use of default-language field+ -- note that we do not need to do an equivalent check for the+ -- other-language field since that one does not change behaviour+ , checkVersion CabalSpecV1_10 (any isJust (buildInfoField defaultLanguage)) $+ PackageBuildWarning $+ "To use the 'default-language' field the package needs to specify "+ ++ "at least 'cabal-version: >= 1.10'."++ , check (specVersion pkg >= CabalSpecV1_10 && specVersion pkg < CabalSpecV3_4+ && (any isNothing (buildInfoField defaultLanguage))) $+ PackageBuildWarning $+ "Packages using 'cabal-version: >= 1.10' and before 'cabal-version: 3.4' must specify the "+ ++ "'default-language' field for each component (e.g. Haskell98 or "+ ++ "Haskell2010). If a component uses different languages in "+ ++ "different modules then list the other ones in the "+ ++ "'other-languages' field."++ , checkVersion CabalSpecV1_18+ (not . null $ extraDocFiles pkg) $+ PackageDistInexcusable $+ "To use the 'extra-doc-files' field the package needs to specify "+ ++ "at least 'cabal-version: >= 1.18'."++ , checkVersion CabalSpecV2_0+ (not (null (subLibraries pkg))) $+ PackageDistInexcusable $+ "To use multiple 'library' sections or a named library section "+ ++ "the package needs to specify at least 'cabal-version: 2.0'."++ -- check use of reexported-modules sections+ , checkVersion CabalSpecV1_22+ (any (not.null.reexportedModules) (allLibraries pkg)) $+ PackageDistInexcusable $+ "To use the 'reexported-module' field the package needs to specify "+ ++ "at least 'cabal-version: >= 1.22'."++ -- check use of thinning and renaming+ , checkVersion CabalSpecV2_0 usesBackpackIncludes $+ PackageDistInexcusable $+ "To use the 'mixins' field the package needs to specify "+ ++ "at least 'cabal-version: 2.0'."++ -- check use of 'extra-framework-dirs' field+ , checkVersion CabalSpecV1_24 (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.24'."++ -- check use of default-extensions field+ -- don't need to do the equivalent check for other-extensions+ , checkVersion CabalSpecV1_10 (any (not . null) (buildInfoField defaultExtensions)) $+ PackageBuildWarning $+ "To use the 'default-extensions' field the package needs to specify "+ ++ "at least 'cabal-version: >= 1.10'."++ -- check use of extensions field+ , check (specVersion pkg >= CabalSpecV1_10+ && (any (not . null) (buildInfoField oldExtensions))) $+ PackageBuildWarning $+ "For packages using 'cabal-version: >= 1.10' the 'extensions' "+ ++ "field is deprecated. The new 'default-extensions' field lists "+ ++ "extensions that are used in all modules in the component, while "+ ++ "the 'other-extensions' field lists extensions that are used in "+ ++ "some modules, e.g. via the {-# LANGUAGE #-} pragma."++ , checkVersion CabalSpecV3_0 (any (not . null)+ (concatMap buildInfoField+ [ asmSources+ , cmmSources+ , extraBundledLibs+ , extraLibFlavours ])) $+ PackageDistInexcusable $+ "The use of 'asm-sources', 'cmm-sources', 'extra-bundled-libraries' "+ ++ " and 'extra-library-flavours' requires the package "+ ++ " to specify at least 'cabal-version: 3.0'."++ , checkVersion CabalSpecV3_0 (any (not . null) $ buildInfoField extraDynLibFlavours) $+ PackageDistInexcusable $+ "The use of 'extra-dynamic-library-flavours' requires the package "+ ++ " to specify at least 'cabal-version: 3.0'. The flavours are: "+ ++ commaSep [ flav+ | flavs <- buildInfoField extraDynLibFlavours+ , flav <- flavs ]++ , checkVersion CabalSpecV2_2 (any (not . null)+ (buildInfoField virtualModules)) $+ PackageDistInexcusable $+ "The use of 'virtual-modules' requires the package "+ ++ " to specify at least 'cabal-version: 2.2'."++ -- check use of "source-repository" section+ , checkVersion CabalSpecV1_6 (not (null (sourceRepos pkg))) $+ PackageDistInexcusable $+ "The 'source-repository' section is new in Cabal 1.6. "+ ++ "Unfortunately it messes up the parser in earlier Cabal versions "+ ++ "so you need to specify 'cabal-version: >= 1.6'."++ -- check for new language extensions+ , checkVersion CabalSpecV1_4 (not (null mentionedExtensionsThatNeedCabal12)) $+ PackageDistInexcusable $+ "Unfortunately the language extensions "+ ++ commaSep (map (quote . prettyShow) mentionedExtensionsThatNeedCabal12)+ ++ " break the parser in earlier Cabal versions so you need to "+ ++ "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."++ , checkVersion CabalSpecV1_4 (not (null mentionedExtensionsThatNeedCabal14)) $+ PackageDistInexcusable $+ "Unfortunately the language extensions "+ ++ commaSep (map (quote . prettyShow) mentionedExtensionsThatNeedCabal14)+ ++ " break the parser in earlier Cabal versions so you need to "+ ++ "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 >= CabalSpecV1_24+ && isNothing (setupBuildInfo pkg)+ && buildType pkg == Custom) $+ PackageBuildWarning $+ "Packages using 'cabal-version: >= 1.24' 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 < CabalSpecV1_24+ && isNothing (setupBuildInfo pkg)+ && buildType pkg == Custom) $+ PackageDistSuspiciousWarn $+ "From version 1.24 cabal supports specifying explicit dependencies "+ ++ "for Custom setup scripts. Consider using cabal-version >= 1.24 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'."++ , check (specVersion pkg >= CabalSpecV2_0+ && elem (autogenPathsModuleName pkg) allModuleNames+ && not (elem (autogenPathsModuleName pkg) allModuleNamesAutogen) ) $+ PackageDistInexcusable $+ "Packages using 'cabal-version: 2.0' and the autogenerated "+ ++ "module Paths_* must include it also on the 'autogen-modules' field "+ ++ "besides 'exposed-modules' and 'other-modules'. This specifies that "+ ++ "the module does not come with the package and is generated on "+ ++ "setup. Modules built with a custom Setup.hs script also go here "+ ++ "to ensure that commands like sdist don't fail."++ ]+ where+ -- Perform a check on packages that use a version of the spec less than+ -- the version given. This is for cases where a new Cabal version adds+ -- a new feature and we want to check that it is not used prior to that+ -- version.+ checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck+ checkVersion ver cond pc+ | specVersion pkg >= ver = Nothing+ | otherwise = check cond pc++ buildInfoField field = map field (allBuildInfo pkg)++ usesBackpackIncludes = any (not . null . mixins) (allBuildInfo pkg)++ mentionedExtensions = [ ext | bi <- allBuildInfo pkg+ , ext <- allExtensions bi ]+ mentionedExtensionsThatNeedCabal12 =+ nub (filter (`elem` compatExtensionsExtra) mentionedExtensions)++ -- As of Cabal-1.4 we can add new extensions without worrying about+ -- breaking old versions of cabal.+ mentionedExtensionsThatNeedCabal14 =+ nub (filter (`notElem` compatExtensions) mentionedExtensions)++ -- The known extensions in Cabal-1.2.3+ compatExtensions =+ map EnableExtension+ [ OverlappingInstances, UndecidableInstances, IncoherentInstances+ , RecursiveDo, ParallelListComp, MultiParamTypeClasses+ , FunctionalDependencies, Rank2Types+ , RankNTypes, PolymorphicComponents, ExistentialQuantification+ , ScopedTypeVariables, ImplicitParams, FlexibleContexts+ , FlexibleInstances, EmptyDataDecls, CPP, BangPatterns+ , TypeSynonymInstances, TemplateHaskell, ForeignFunctionInterface+ , Arrows, Generics, NamedFieldPuns, PatternGuards+ , GeneralizedNewtypeDeriving, ExtensibleRecords, RestrictedTypeSynonyms+ , HereDocuments] +++ map DisableExtension+ [MonomorphismRestriction, ImplicitPrelude] +++ compatExtensionsExtra++ -- The extra known extensions in Cabal-1.2.3 vs Cabal-1.1.6+ -- (Cabal-1.1.6 came with ghc-6.6. Cabal-1.2 came with ghc-6.8)+ compatExtensionsExtra =+ map EnableExtension+ [ KindSignatures, MagicHash, TypeFamilies, StandaloneDeriving+ , UnicodeSyntax, PatternSignatures, UnliftedFFITypes, LiberalTypeSynonyms+ , TypeOperators, RecordWildCards, RecordPuns, DisambiguateRecordFields+ , OverloadedStrings, GADTs, RelaxedPolyRec+ , ExtendedDefaultRules, UnboxedTuples, DeriveDataTypeable+ , ConstrainedClassMethods+ ] +++ map DisableExtension+ [MonoPatBinds]++ allModuleNames =+ (case library pkg of+ Nothing -> []+ (Just lib) -> explicitLibModules lib+ )+ ++ concatMap otherModules (allBuildInfo pkg)++ allModuleNamesAutogen = concatMap autogenModules (allBuildInfo pkg)++-- ------------------------------------------------------------+-- * Checks on the GenericPackageDescription+-- ------------------------------------------------------------++-- | Check the build-depends fields for any weirdness or bad practice.+--+checkPackageVersions :: GenericPackageDescription -> [PackageCheck]+checkPackageVersions pkg =+ catMaybes [++ -- Check that the version of base is bounded above.+ -- For example this bans "build-depends: base >= 3".+ -- It should probably be "build-depends: base >= 3 && < 4"+ -- which is the same as "build-depends: base == 3.*"+ check (not (boundedAbove baseDependency)) $+ PackageDistInexcusable $+ "The dependency 'build-depends: base' does not specify an upper "+ ++ "bound on the version number. Each major release of the 'base' "+ ++ "package changes the API in various ways and most packages will "+ ++ "need some changes to compile with it. The recommended practice "+ ++ "is to specify an upper bound on the version of the 'base' "+ ++ "package. This ensures your package will continue to build when a "+ ++ "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 4.5 and 4.6 then use 'build-depends: base >= 4.5 && < 4.7'."++ ]+ where+ -- TODO: What we really want to do is test if there exists any+ -- configuration in which the base version is unbounded above.+ -- However that's a bit tricky because there are many possible+ -- configurations. As a cheap easy and safe approximation we will+ -- pick a single "typical" configuration and check if that has an+ -- open upper bound. To get a typical configuration we finalise+ -- using no package index and the current platform.+ finalised = finalizePD+ mempty defaultComponentRequestedSpec (const True)+ buildPlatform+ (unknownCompilerInfo+ (CompilerId buildCompilerFlavor nullVersion)+ NoAbiTag)+ [] pkg+ baseDependency = case finalised of+ Right (pkg', _) | not (null baseDeps) ->+ foldr intersectVersionRanges anyVersion baseDeps+ where+ baseDeps =+ [ vr | Dependency pname vr _ <- allBuildDepends pkg'+ , pname == mkPackageName "base" ]++ -- Just in case finalizePD fails for any reason,+ -- or if the package doesn't depend on the base package at all,+ -- then we will just skip the check, since boundedAbove noVersion = True+ _ -> noVersion++ -- TODO: move to Distribution.Version+ boundedAbove :: VersionRange -> Bool+ boundedAbove vr = case asVersionIntervals vr of+ [] -> True -- this is the inconsistent version range.+ (x:xs) -> case last (x:|xs) of+ VersionInterval _ UpperBound {} -> True+ VersionInterval _ NoUpperBound -> False+++checkConditionals :: GenericPackageDescription -> [PackageCheck]+checkConditionals pkg =+ catMaybes [++ check (not $ null unknownOSs) $+ PackageDistInexcusable $+ "Unknown operating system name "+ ++ commaSep (map quote unknownOSs)++ , check (not $ null unknownArches) $+ PackageDistInexcusable $+ "Unknown architecture name "+ ++ commaSep (map quote unknownArches)++ , check (not $ null unknownImpls) $+ PackageDistInexcusable $+ "Unknown compiler name "+ ++ commaSep (map quote unknownImpls)+ ]+ where+ unknownOSs = [ os | OS (OtherOS os) <- conditions ]+ unknownArches = [ arch | Arch (OtherArch arch) <- conditions ]+ unknownImpls = [ impl | Impl (OtherCompiler impl) _ <- conditions ]+ conditions = concatMap fvs (maybeToList (condLibrary pkg))+ ++ concatMap (fvs . snd) (condSubLibraries pkg)+ ++ concatMap (fvs . snd) (condForeignLibs pkg)+ ++ concatMap (fvs . snd) (condExecutables pkg)+ ++ concatMap (fvs . snd) (condTestSuites pkg)+ ++ concatMap (fvs . snd) (condBenchmarks pkg)+ fvs (CondNode _ _ ifs) = concatMap compfv ifs -- free variables+ compfv (CondBranch c ct mct) = condfv c ++ fvs ct ++ maybe [] fvs mct+ condfv c = case c of+ Var v -> [v]+ Lit _ -> []+ CNot c1 -> condfv c1+ COr c1 c2 -> condfv c1 ++ condfv c2+ CAnd c1 c2 -> condfv c1 ++ condfv c2++checkFlagNames :: GenericPackageDescription -> [PackageCheck]+checkFlagNames gpd+ | null invalidFlagNames = []+ | otherwise = [ PackageDistInexcusable+ $ "Suspicious flag names: " ++ unwords invalidFlagNames ++ ". "+ ++ "To avoid ambiguity in command line interfaces, flag shouldn't "+ ++ "start with a dash. Also for better compatibility, flag names "+ ++ "shouldn't contain non-ascii characters."+ ]+ where+ invalidFlagNames =+ [ fn+ | flag <- genPackageFlags gpd+ , let fn = unFlagName (flagName flag)+ , invalidFlagName fn+ ]+ -- starts with dash+ invalidFlagName ('-':_) = True+ -- mon ascii letter+ invalidFlagName cs = any (not . isAscii) cs++checkUnusedFlags :: GenericPackageDescription -> [PackageCheck]+checkUnusedFlags gpd+ | declared == used = []+ | otherwise = [ PackageDistSuspicious+ $ "Declared and used flag sets differ: "+ ++ s declared ++ " /= " ++ s used ++ ". "+ ]+ where+ s :: Set.Set FlagName -> String+ s = commaSep . map unFlagName . Set.toList++ declared :: Set.Set FlagName+ declared = toSetOf (L.genPackageFlags . traverse . L.flagName) gpd++ used :: Set.Set FlagName+ used = mconcat+ [ toSetOf (L.condLibrary . traverse . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condSubLibraries . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condForeignLibs . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condExecutables . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condTestSuites . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condBenchmarks . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ ]++checkUnicodeXFields :: GenericPackageDescription -> [PackageCheck]+checkUnicodeXFields gpd+ | null nonAsciiXFields = []+ | otherwise = [ PackageDistInexcusable+ $ "Non ascii custom fields: " ++ unwords nonAsciiXFields ++ ". "+ ++ "For better compatibility, custom field names "+ ++ "shouldn't contain non-ascii characters."+ ]+ where+ nonAsciiXFields :: [String]+ nonAsciiXFields = [ n | (n, _) <- xfields, any (not . isAscii) n ]++ xfields :: [(String,String)]+ xfields = DList.runDList $ mconcat+ [ toDListOf (L.packageDescription . L.customFieldsPD . traverse) gpd+ , toDListOf (L.traverseBuildInfos . L.customFieldsBI . traverse) gpd+ ]++-- | cabal-version <2.2 + Paths_module + default-extensions: doesn't build.+checkPathsModuleExtensions :: PackageDescription -> [PackageCheck]+checkPathsModuleExtensions pd+ | specVersion pd >= CabalSpecV2_2 = []+ | any checkBI (allBuildInfo pd) || any checkLib (allLibraries pd)+ = return $ PackageBuildImpossible $ unwords+ [ "The package uses RebindableSyntax with OverloadedStrings or OverloadedLists"+ , "in default-extensions, and also Paths_ autogen module."+ , "That configuration is known to cause compile failures with Cabal < 2.2."+ , "To use these default-extensions with Paths_ autogen module"+ , "specify at least 'cabal-version: 2.2'."+ ]+ | otherwise = []+ where+ mn = autogenPathsModuleName pd++ checkLib :: Library -> Bool+ checkLib l = mn `elem` exposedModules l && checkExts (l ^. L.defaultExtensions)++ checkBI :: BuildInfo -> Bool+ checkBI bi =+ (mn `elem` otherModules bi || mn `elem` autogenModules bi) &&+ checkExts (bi ^. L.defaultExtensions)++ checkExts exts = rebind `elem` exts && (strings `elem` exts || lists `elem` exts)+ where+ rebind = EnableExtension RebindableSyntax+ strings = EnableExtension OverloadedStrings+ lists = EnableExtension OverloadedLists++-- | Checks GHC options from all ghc-*-options fields from the given BuildInfo+-- and reports flags that are OK during development process, but are+-- unacceptable in a distrubuted package+checkDevelopmentOnlyFlagsBuildInfo :: BuildInfo -> [PackageCheck]+checkDevelopmentOnlyFlagsBuildInfo bi =+ checkDevelopmentOnlyFlagsOptions "ghc-options" (hcOptions GHC bi)+ ++ checkDevelopmentOnlyFlagsOptions "ghc-prof-options" (hcProfOptions GHC bi)+ ++ checkDevelopmentOnlyFlagsOptions "ghc-shared-options" (hcSharedOptions GHC bi)++-- | Checks the given list of flags belonging to the given field and reports+-- flags that are OK during development process, but are unacceptable in a+-- distributed package+checkDevelopmentOnlyFlagsOptions :: String -> [String] -> [PackageCheck]+checkDevelopmentOnlyFlagsOptions fieldName ghcOptions =+ catMaybes [++ check has_WerrorWall $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -Wall -Werror' makes the package very easy to "+ ++ "break with future GHC versions because new GHC versions often "+ ++ "add new warnings. Use just '" ++ fieldName ++ ": -Wall' instead."+ ++ extraExplanation++ , check (not has_WerrorWall && has_Werror) $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -Werror' makes the package easy to "+ ++ "break with future GHC versions because new GHC versions often "+ ++ "add new warnings. "+ ++ extraExplanation++ , check (has_J) $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -j[N]' can make sense for specific user's setup,"+ ++ " but it is not appropriate for a distributed package."+ ++ extraExplanation++ , checkFlags ["-fdefer-type-errors"] $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -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")+ ghcOptions) $+ PackageDistInexcusable $+ "'" ++ fieldName ++ ": -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 $+ "'" ++ fieldName ++ ": -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` ghcOptions+ has_Wall = "-Wall" `elem` ghcOptions+ has_W = "-W" `elem` ghcOptions+ has_J = any+ (\o -> case o of+ "-j" -> True+ ('-' : 'j' : d : _) -> isDigit d+ _ -> False+ )+ ghcOptions+ checkFlags :: [String] -> PackageCheck -> Maybe PackageCheck+ checkFlags flags = check (any (`elem` flags) ghcOptions)++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 (PackageFlag 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 (PackageFlag 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 libBuildInfo . snd)+ (condSubLibraries 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+ | (CondBranch condition ifThen _) <- condTreeComponents condNode ]++ ++ concat+ [ go (condition:conditions) elseThen+ | (CondBranch condition _ (Just elseThen)) <- condTreeComponents condNode ]+++-- ------------------------------------------------------------+-- * Checks involving files in the package+-- ------------------------------------------------------------++-- | Sanity check things that requires IO. It looks at the files in the+-- package and expects to find the package unpacked in at the given file path.+--+checkPackageFiles :: Verbosity -> PackageDescription -> FilePath -> IO [PackageCheck]+checkPackageFiles verbosity pkg root = do+ contentChecks <- checkPackageContent checkFilesIO pkg+ preDistributionChecks <- checkPackageFilesPreDistribution verbosity pkg root+ -- Sort because different platforms will provide files from+ -- `getDirectoryContents` in different orders, and we'd like to be+ -- stable for test output.+ return (sort contentChecks ++ sort preDistributionChecks)+ where+ checkFilesIO = CheckPackageContentOps {+ doesFileExist = System.doesFileExist . relative,+ doesDirectoryExist = System.doesDirectoryExist . relative,+ getDirectoryContents = System.Directory.getDirectoryContents . relative,+ getFileContents = BS.readFile . relative+ }+ relative path = root </> path++-- | A record of operations needed to check the contents of packages.+-- Used by 'checkPackageContent'.+--+data CheckPackageContentOps m = CheckPackageContentOps {+ doesFileExist :: FilePath -> m Bool,+ doesDirectoryExist :: FilePath -> m Bool,+ getDirectoryContents :: FilePath -> m [FilePath],+ getFileContents :: FilePath -> m BS.ByteString+ }++-- | Sanity check things that requires looking at files in the package.+-- This is a generalised version of 'checkPackageFiles' that can work in any+-- monad for which you can provide 'CheckPackageContentOps' operations.+--+-- The point of this extra generality is to allow doing checks in some virtual+-- file system, for example a tarball in memory.+--+checkPackageContent :: (Monad m, Applicative m)+ => CheckPackageContentOps m+ -> PackageDescription+ -> m [PackageCheck]+checkPackageContent ops pkg = do+ cabalBomError <- checkCabalFileBOM ops+ cabalNameError <- checkCabalFileName ops pkg+ licenseErrors <- checkLicensesExist ops pkg+ setupError <- checkSetupExists ops pkg+ configureError <- checkConfigureExists ops pkg+ localPathErrors <- checkLocalPathsExist ops pkg+ vcsLocation <- checkMissingVcsInfo ops pkg++ return $ licenseErrors+ ++ catMaybes [cabalBomError, cabalNameError, setupError, configureError]+ ++ localPathErrors+ ++ vcsLocation++checkCabalFileBOM :: Monad m => CheckPackageContentOps m+ -> m (Maybe PackageCheck)+checkCabalFileBOM ops = do+ epdfile <- findPackageDesc ops+ case epdfile of+ -- MASSIVE HACK. If the Cabal file doesn't exist, that is+ -- a very strange situation to be in, because the driver code+ -- in 'Distribution.Setup' ought to have noticed already!+ -- But this can be an issue, see #3552 and also when+ -- --cabal-file is specified. So if you can't find the file,+ -- just don't bother with this check.+ Left _ -> return $ Nothing+ Right pdfile -> (flip check pc . BS.isPrefixOf bomUtf8)+ `liftM` (getFileContents ops pdfile)+ where pc = PackageDistInexcusable $+ pdfile ++ " starts with an Unicode byte order mark (BOM)."+ ++ " This may cause problems with older cabal versions."++ where+ bomUtf8 :: BS.ByteString+ bomUtf8 = BS.pack [0xef,0xbb,0xbf] -- U+FEFF encoded as UTF8++checkCabalFileName :: Monad m => CheckPackageContentOps m+ -> PackageDescription+ -> m (Maybe PackageCheck)+checkCabalFileName ops pkg = do+ -- findPackageDesc already takes care to detect missing/multiple+ -- .cabal files; we don't include this check in 'findPackageDesc' in+ -- order not to short-cut other checks which call 'findPackageDesc'+ epdfile <- findPackageDesc ops+ case epdfile of+ -- see "MASSIVE HACK" note in 'checkCabalFileBOM'+ Left _ -> return Nothing+ Right pdfile+ | takeFileName pdfile == expectedCabalname -> return Nothing+ | otherwise -> return $ Just $ PackageDistInexcusable $+ "The filename " ++ pdfile ++ " does not match package name " +++ "(expected: " ++ expectedCabalname ++ ")"+ where+ pkgname = unPackageName . packageName $ pkg+ expectedCabalname = pkgname <.> "cabal"+++-- |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 while checking.\n"+ ++ "Please use only one of: "+ ++ intercalate ", " l++checkLicensesExist :: (Monad m, Applicative m)+ => CheckPackageContentOps m+ -> PackageDescription+ -> m [PackageCheck]+checkLicensesExist ops pkg = do+ exists <- traverse (doesFileExist ops . getSymbolicPath) (licenseFiles pkg)+ return+ [ PackageBuildWarning $+ "The '" ++ fieldname ++ "' field refers to the file "+ ++ quote (getSymbolicPath file) ++ " which does not exist."+ | (file, False) <- zip (licenseFiles pkg) exists ]+ where+ fieldname | length (licenseFiles pkg) == 1 = "license-file"+ | otherwise = "license-files"++checkSetupExists :: Monad m => CheckPackageContentOps m+ -> PackageDescription+ -> m (Maybe PackageCheck)+checkSetupExists ops pkg = do+ let simpleBuild = buildType pkg == Simple+ hsexists <- doesFileExist ops "Setup.hs"+ lhsexists <- doesFileExist ops "Setup.lhs"+ return $ check (not simpleBuild && not hsexists && not lhsexists) $+ PackageDistInexcusable $+ "The package is missing a Setup.hs or Setup.lhs script."++checkConfigureExists :: Monad m => CheckPackageContentOps m+ -> PackageDescription+ -> m (Maybe PackageCheck)+checkConfigureExists ops pd+ | buildType pd == Configure = do+ exists <- doesFileExist ops "configure"+ return $ check (not exists) $+ PackageBuildWarning $+ "The 'build-type' is 'Configure' but there is no 'configure' script. "+ ++ "You probably need to run 'autoreconf -i' to generate it."+ | otherwise = return Nothing++checkLocalPathsExist :: Monad m => CheckPackageContentOps m+ -> PackageDescription+ -> m [PackageCheck]+checkLocalPathsExist ops pkg = do+ let dirs = [ (dir, kind)+ | 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 ]+ ++ [ (getSymbolicPath dir, "hs-source-dirs") | dir <- hsSourceDirs bi ]+ , isRelativeOnAnyPlatform dir ]+ missing <- filterM (liftM not . doesDirectoryExist ops . fst) dirs+ return [ PackageBuildWarning {+ explanation = quote (kind ++ ": " ++ dir)+ ++ " directory does not exist."+ }+ | (dir, kind) <- missing ]++checkMissingVcsInfo :: (Monad m, Applicative m)+ => CheckPackageContentOps m+ -> PackageDescription+ -> m [PackageCheck]+checkMissingVcsInfo ops pkg | null (sourceRepos pkg) = do+ vcsInUse <- liftM or $ traverse (doesDirectoryExist ops) repoDirnames+ if vcsInUse+ then return [ PackageDistSuspicious message ]+ else return []+ where+ repoDirnames = [ dirname | repo <- knownRepoTypes+ , dirname <- repoTypeDirname repo]+ message = "When distributing packages it is encouraged to specify source "+ ++ "control information in the .cabal file using one or more "+ ++ "'source-repository' sections. See the Cabal user guide for "+ ++ "details."++checkMissingVcsInfo _ _ = return []++repoTypeDirname :: KnownRepoType -> [FilePath]+repoTypeDirname Darcs = ["_darcs"]+repoTypeDirname Git = [".git"]+repoTypeDirname SVN = [".svn"]+repoTypeDirname CVS = ["CVS"]+repoTypeDirname Mercurial = [".hg"]+repoTypeDirname GnuArch = [".arch-params"]+repoTypeDirname Bazaar = [".bzr"]+repoTypeDirname Monotone = ["_MTN"]+repoTypeDirname Pijul = [".pijul"]++-- ------------------------------------------------------------+-- * Checks involving files in the package+-- ------------------------------------------------------------++-- | Check the names of all files in a package for portability problems. This+-- should be done for example when creating or validating a package tarball.+--+checkPackageFileNames :: [FilePath] -> [PackageCheck]+checkPackageFileNames 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.++checkWindowsPath :: FilePath -> Maybe PackageCheck+checkWindowsPath path =+ check (not $ FilePath.Windows.isValid path') $+ PackageDistInexcusable $+ "Unfortunately, the file " ++ quote path ++ " is not a valid file "+ ++ "name on Windows which would cause portability problems for this "+ ++ "package. Windows file names cannot contain any of the characters "+ ++ "\":*?<>|\" and there are a few reserved names including \"aux\", "+ ++ "\"nul\", \"con\", \"prn\", \"com1-9\", \"lpt1-9\" and \"clock$\"."+ where+ path' = ".\\" ++ path+ -- force a relative name to catch invalid file names like "f:oo" which+ -- otherwise parse as file "oo" in the current directory on the 'f' drive.++-- | Check a file name is valid for the portable POSIX tar format.+--+-- The POSIX tar format has a restriction on the length of file names. It is+-- unfortunately not a simple restriction like a maximum length. The exact+-- restriction is that either the whole path be 100 characters or less, or it+-- be possible to split the path on a directory separator such that the first+-- part is 155 characters or less and the second part 100 characters or less.+--+checkTarPath :: FilePath -> Maybe PackageCheck+checkTarPath path+ | length path > 255 = Just longPath+ | otherwise = case pack nameMax (reverse (splitPath path)) of+ Left err -> Just err+ Right [] -> Nothing+ Right (h:rest) -> case pack prefixMax remainder of+ Left err -> Just err+ Right [] -> Nothing+ Right (_:_) -> Just noSplit+ where+ -- drop the '/' between the name and prefix:+ remainder = safeInit h : rest++ where+ nameMax, prefixMax :: Int+ nameMax = 100+ prefixMax = 155++ pack _ [] = Left emptyName+ pack maxLen (c:cs)+ | n > maxLen = Left longName+ | otherwise = Right (pack' maxLen n cs)+ where n = length c++ pack' maxLen n (c:cs)+ | n' <= maxLen = pack' maxLen n' cs+ where n' = n + length c+ pack' _ _ cs = cs++ longPath = PackageDistInexcusable $+ "The following file name is too long to store in a portable POSIX "+ ++ "format tar archive. The maximum length is 255 ASCII characters.\n"+ ++ "The file in question is:\n " ++ path+ longName = PackageDistInexcusable $+ "The following file name is too long to store in a portable POSIX "+ ++ "format tar archive. The maximum length for the name part (including "+ ++ "extension) is 100 ASCII characters. The maximum length for any "+ ++ "individual directory component is 155.\n"+ ++ "The file in question is:\n " ++ path+ noSplit = PackageDistInexcusable $+ "The following file name is too long to store in a portable POSIX "+ ++ "format tar archive. While the total length is less than 255 ASCII "+ ++ "characters, there are unfortunately further restrictions. It has to "+ ++ "be possible to split the file path on a directory separator into "+ ++ "two parts such that the first part fits in 155 characters or less "+ ++ "and the second part fits in 100 characters or less. Basically you "+ ++ "have to make the file name or directory names shorter, or you could "+ ++ "split a long directory name into nested subdirectories with shorter "+ ++ "names.\nThe file in question is:\n " ++ path+ emptyName = PackageDistInexcusable $+ "Encountered a file with an empty name, something is very wrong! "+ ++ "Files with an empty name cannot be stored in a tar archive or in "+ ++ "standard file systems."++-- --------------------------------------------------------------+-- * Checks for missing content and other pre-distribution checks+-- --------------------------------------------------------------++-- | Similar to 'checkPackageContent', 'checkPackageFilesPreDistribution'+-- inspects the files included in the package, but is primarily looking for+-- files in the working tree that may have been missed or other similar+-- problems that can only be detected pre-distribution.+--+-- Because Hackage necessarily checks the uploaded tarball, it is too late to+-- check these on the server; these checks only make sense in the development+-- and package-creation environment. Hence we can use IO, rather than needing+-- to pass a 'CheckPackageContentOps' dictionary around.+checkPackageFilesPreDistribution :: Verbosity -> PackageDescription -> FilePath -> IO [PackageCheck]+-- Note: this really shouldn't return any 'Inexcusable' warnings,+-- because that will make us say that Hackage would reject the package.+-- But, because Hackage doesn't run these tests, that will be a lie!+checkPackageFilesPreDistribution = checkGlobFiles++-- | Discover problems with the package's wildcards.+checkGlobFiles :: Verbosity+ -> PackageDescription+ -> FilePath+ -> IO [PackageCheck]+checkGlobFiles verbosity pkg root =+ fmap concat $ for allGlobs $ \(field, dir, glob) ->+ -- Note: we just skip over parse errors here; they're reported elsewhere.+ case parseFileGlob (specVersion pkg) glob of+ Left _ -> return []+ Right parsedGlob -> do+ results <- runDirFileGlob verbosity (root </> dir) parsedGlob+ let individualWarnings = results >>= getWarning field glob+ noMatchesWarning =+ [ PackageDistSuspiciousWarn $+ "In '" ++ field ++ "': the pattern '" ++ glob ++ "' does not"+ ++ " match any files."+ | all (not . suppressesNoMatchesWarning) results+ ]+ return (noMatchesWarning ++ individualWarnings)+ where+ adjustedDataDir = if null (dataDir pkg) then "." else dataDir pkg+ allGlobs = concat+ [ (,,) "extra-source-files" "." <$> extraSrcFiles pkg+ , (,,) "extra-doc-files" "." <$> extraDocFiles pkg+ , (,,) "data-files" adjustedDataDir <$> dataFiles pkg+ ]++ -- If there's a missing directory in play, since our globs don't+ -- (currently) support disjunction, that will always mean there are no+ -- matches. The no matches error in this case is strictly less informative+ -- than the missing directory error, so sit on it.+ suppressesNoMatchesWarning (GlobMatch _) = True+ suppressesNoMatchesWarning (GlobWarnMultiDot _) = False+ suppressesNoMatchesWarning (GlobMissingDirectory _) = True++ getWarning :: String -> FilePath -> GlobResult FilePath -> [PackageCheck]+ getWarning _ _ (GlobMatch _) =+ []+ -- Before Cabal 2.4, the extensions of globs had to match the file+ -- exactly. This has been relaxed in 2.4 to allow matching only the+ -- suffix. This warning detects when pre-2.4 package descriptions are+ -- omitting files purely because of the stricter check.+ getWarning field glob (GlobWarnMultiDot file) =+ [ PackageDistSuspiciousWarn $+ "In '" ++ field ++ "': the pattern '" ++ glob ++ "' does not"+ ++ " match the file '" ++ file ++ "' because the extensions do not"+ ++ " exactly match (e.g., foo.en.html does not exactly match *.html)."+ ++ " To enable looser suffix-only matching, set 'cabal-version: 2.4' or higher."+ ]+ getWarning field glob (GlobMissingDirectory dir) =+ [ PackageDistSuspiciousWarn $+ "In '" ++ field ++ "': the pattern '" ++ glob ++ "' attempts to"+ ++ " match files in the directory '" ++ dir ++ "', but there is no"+ ++ " directory by that name."+ ]++-- ------------------------------------------------------------+-- * Utils+-- ------------------------------------------------------------++quote :: String -> String+quote s = "'" ++ s ++ "'"++commaSep :: [String] -> String+commaSep = intercalate ", "++dups :: Ord a => [a] -> [a]+dups xs = [ x | (x:_:_) <- group (sort xs) ]++fileExtensionSupportedLanguage :: FilePath -> Bool+fileExtensionSupportedLanguage path =+ isHaskell || isC+ where+ extension = takeExtension path+ isHaskell = extension `elem` [".hs", ".lhs"]+ isC = isJust (filenameCDialect extension)++-- | Whether a path is a good relative path.+--+-- >>> let test fp = putStrLn $ show (isGoodRelativeDirectoryPath fp) ++ "; " ++ show (isGoodRelativeFilePath fp)+--+-- >>> test "foo/bar/quu"+-- Nothing; Nothing+--+-- Trailing slash is not allowed for files, for directories it is ok.+--+-- >>> test "foo/"+-- Nothing; Just "trailing slash"+--+-- Leading @./@ is fine, but @.@ and @./@ are not valid files.+--+-- >>> traverse_ test [".", "./", "./foo/bar"]+-- Nothing; Just "trailing dot segment"+-- Nothing; Just "trailing slash"+-- Nothing; Nothing+--+-- Lastly, not good file nor directory cases:+--+-- >>> traverse_ test ["", "/tmp/src", "foo//bar", "foo/.", "foo/./bar", "foo/../bar", "foo*bar"]+-- Just "empty path"; Just "empty path"+-- Just "posix absolute path"; Just "posix absolute path"+-- Just "empty path segment"; Just "empty path segment"+-- Just "trailing same directory segment: ."; Just "trailing same directory segment: ."+-- Just "same directory segment: ."; Just "same directory segment: .."+-- Just "parent directory segment: .."; Just "parent directory segment: .."+-- Just "reserved character '*'"; Just "reserved character '*'"+--+-- For the last case, 'isGoodRelativeGlob' doesn't warn:+--+-- >>> traverse_ (print . isGoodRelativeGlob) ["foo/../bar", "foo*bar"]+-- Just "parent directory segment: .."+-- Nothing+--+isGoodRelativeFilePath :: FilePath -> Maybe String+isGoodRelativeFilePath = state0+ where+ -- Reserved characters+ -- https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file+ isReserved c = c `elem` "<>:\"\\/|?*"++ -- initial state+ state0 [] = Just "empty path"+ state0 (c:cs) | c == '.' = state1 cs+ | c == '/' = Just "posix absolute path"+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state3 cs++ -- after .+ state1 [] = Just "trailing dot segment"+ state1 (c:cs) | c == '.' = state4 cs+ | c == '/' = state2 cs+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state5 cs++ -- after ./+ state2 [] = Just "trailing slash"+ state2 (c:cs) | c == '.' = state3 cs+ | c == '/' = Just "empty path segment"+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state5 cs++ -- after non-first segment's .+ state3 [] = Just "trailing same directory segment: ."+ state3 (c:cs) | c == '.' = state4 cs+ | c == '/' = Just "same directory segment: .."+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state5 cs++ -- after non-first segment's ..+ state4 [] = Just "trailing parent directory segment: .."+ state4 (c:cs) | c == '.' = state5 cs+ | c == '/' = Just "parent directory segment: .."+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state5 cs++ -- in a segment which is ok.+ state5 [] = Nothing+ state5 (c:cs) | c == '.' = state3 cs+ | c == '/' = state2 cs+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state5 cs++-- | See 'isGoodRelativeFilePath'.+--+-- This is barebones function. We check whether the glob is a valid file+-- by replacing stars @*@ with @x@ses.+isGoodRelativeGlob :: FilePath -> Maybe String+isGoodRelativeGlob = isGoodRelativeFilePath . map f where+ f '*' = 'x'+ f c = c++-- | See 'isGoodRelativeFilePath'.+isGoodRelativeDirectoryPath :: FilePath -> Maybe String+isGoodRelativeDirectoryPath = state0+ where+ -- Reserved characters+ -- https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file+ isReserved c = c `elem` "<>:\"\\/|?*"++ -- initial state+ state0 [] = Just "empty path"+ state0 (c:cs) | c == '.' = state5 cs+ | c == '/' = Just "posix absolute path"+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state4 cs++ -- after ./+ state1 [] = Nothing -- "./"+ state1 (c:cs) | c == '.' = state2 cs+ | c == '/' = Just "empty path segment"+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state4 cs++ -- after non-first setgment's .+ state2 [] = Just "trailing same directory segment: ."+ state2 (c:cs) | c == '.' = state3 cs+ | c == '/' = Just "same directory segment: ."+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state4 cs++ -- after non-first segment's ..+ state3 [] = Just "trailing parent directory segment: ."+ state3 (c:cs) | c == '.' = state4 cs+ | c == '/' = Just "parent directory segment: .."+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state4 cs++ -- in a segment which is ok.+ state4 [] = Nothing+ state4 (c:cs) | c == '.' = state4 cs+ | c == '/' = state1 cs+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state4 cs++ -- after .+ state5 [] = Nothing -- "."+ state5 (c:cs) | c == '.' = state3 cs+ | c == '/' = state1 cs+ | isReserved c = Just ("reserved character " ++ show c)+ | otherwise = state4 cs++-- [Note: Good relative paths]+--+-- Using @kleene@ we can define an extended regex:+--+-- @+-- import Algebra.Lattice+-- import Kleene+-- import Kleene.ERE (ERE (..), intersections)+--+-- data C = CDot | CSlash | COtherReserved | CChar+-- deriving (Eq, Ord, Enum, Bounded, Show)+--+-- reservedR :: ERE C+-- reservedR = notChar CSlash /\ notChar COtherReserved+--+-- pathPieceR :: ERE C+-- pathPieceR = intersections+-- [ plus reservedR+-- , ERENot (string [CDot])+-- , ERENot (string [CDot,CDot])+-- ]+--+-- filePathR :: ERE C+-- filePathR = optional (string [CDot, CSlash]) <> pathPieceR <> star (char CSlash <> pathPieceR)+--+-- dirPathR :: ERE C+-- dirPathR = (char CDot \/ filePathR) <> optional (char CSlash)+--+-- plus :: ERE C -> ERE C+-- plus r = r <> star r+--+-- optional :: ERE C -> ERE C+-- optional r = mempty \/ r+-- @+--+-- Results in following state machine for @filePathR@+--+-- @+-- 0 -> \x -> if+-- | x <= CDot -> 1+-- | x <= COtherReserved -> 6+-- | otherwise -> 5+-- 1 -> \x -> if+-- | x <= CDot -> 4+-- | x <= CSlash -> 2+-- | x <= COtherReserved -> 6+-- | otherwise -> 5+-- 2 -> \x -> if+-- | x <= CDot -> 3+-- | x <= COtherReserved -> 6+-- | otherwise -> 5+-- 3 -> \x -> if+-- | x <= CDot -> 4+-- | x <= COtherReserved -> 6+-- | otherwise -> 5+-- 4 -> \x -> if+-- | x <= CDot -> 5+-- | x <= COtherReserved -> 6+-- | otherwise -> 5+-- 5+ -> \x -> if+-- | x <= CDot -> 5+-- | x <= CSlash -> 2+-- | x <= COtherReserved -> 6+-- | otherwise -> 5+-- 6 -> \_ -> 6 -- black hole+-- @+--+-- and @dirPathR@:+--+-- @+-- 0 -> \x -> if+-- | x <= CDot -> 5+-- | x <= COtherReserved -> 6+-- | otherwise -> 4+-- 1+ -> \x -> if+-- | x <= CDot -> 2+-- | x <= COtherReserved -> 6+-- | otherwise -> 4+-- 2 -> \x -> if+-- | x <= CDot -> 3+-- | x <= COtherReserved -> 6+-- | otherwise -> 4+-- 3 -> \x -> if+-- | x <= CDot -> 4+-- | x <= COtherReserved -> 6+-- | otherwise -> 4+-- 4+ -> \x -> if+-- | x <= CDot -> 4+-- | x <= CSlash -> 1+-- | x <= COtherReserved -> 6+-- | otherwise -> 4+-- 5+ -> \x -> if+-- | x <= CDot -> 3+-- | x <= CSlash -> 1+-- | x <= COtherReserved -> 6+-- | otherwise -> 4+-- 6 -> \_ -> 6 -- black hole+-- @
+ src/Distribution/PackageDescription/Configuration.hs view
@@ -0,0 +1,600 @@+-- -fno-warn-deprecations for use of Map.foldWithKey+{-# OPTIONS_GHC -fno-warn-deprecations #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.PackageDescription.Configuration+-- Copyright : Thomas Schilling, 2007+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is about the cabal configurations feature. It exports+-- 'finalizePD' and 'flattenPackageDescription' which are+-- functions for converting 'GenericPackageDescription's down to+-- 'PackageDescription's. It has code for working with the tree of conditions+-- and resolving or flattening conditions.++module Distribution.PackageDescription.Configuration (+ finalizePD,+ flattenPackageDescription,++ -- Utils+ parseCondition,+ freeVars,+ extractCondition,+ extractConditions,+ addBuildableCondition,+ mapCondTree,+ mapTreeData,+ mapTreeConds,+ mapTreeConstrs,+ transformAllBuildInfos,+ transformAllBuildDepends,+ transformAllBuildDependsN,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++-- lens+import qualified Distribution.Types.BuildInfo.Lens as L+import qualified Distribution.Types.GenericPackageDescription.Lens as L+import qualified Distribution.Types.PackageDescription.Lens as L+import qualified Distribution.Types.SetupBuildInfo.Lens as L++import Distribution.Compat.CharParsing hiding (char)+import qualified Distribution.Compat.CharParsing as P+import Distribution.Compat.Lens+import Distribution.Compiler+import Distribution.PackageDescription+import Distribution.PackageDescription.Utils+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Types.Component+import Distribution.Utils.Path+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.DependencyMap+import Distribution.Types.PackageVersionConstraint+import Distribution.Version++import qualified Data.Map.Lazy as Map+import Data.Tree (Tree (Node))++------------------------------------------------------------------------------++-- | Simplify a configuration condition using the OS and arch names. Returns+-- the names of all the flags occurring in the condition.+simplifyWithSysParams :: OS -> Arch -> CompilerInfo -> Condition ConfVar+ -> (Condition FlagName, [FlagName])+simplifyWithSysParams os arch cinfo cond = (cond', flags)+ where+ (cond', flags) = simplifyCondition cond interp+ interp (OS os') = Right $ os' == os+ interp (Arch arch') = Right $ arch' == arch+ interp (Impl comp vr)+ | matchImpl (compilerInfoId cinfo) = Right True+ | otherwise = case compilerInfoCompat cinfo of+ -- fixme: treat Nothing as unknown, rather than empty list once we+ -- support partial resolution of system parameters+ Nothing -> Right False+ Just compat -> Right (any matchImpl compat)+ where+ matchImpl (CompilerId c v) = comp == c && v `withinRange` vr+ interp (PackageFlag f) = Left f++-- TODO: Add instances and check+--+-- prop_sC_idempotent cond a o = cond' == cond''+-- where+-- cond' = simplifyCondition cond a o+-- cond'' = simplifyCondition cond' a o+--+-- prop_sC_noLits cond a o = isLit res || not (hasLits res)+-- where+-- res = simplifyCondition cond a o+-- hasLits (Lit _) = True+-- hasLits (CNot c) = hasLits c+-- hasLits (COr l r) = hasLits l || hasLits r+-- hasLits (CAnd l r) = hasLits l || hasLits r+-- hasLits _ = False+--++-- | Parse a configuration condition from a string.+parseCondition :: CabalParsing m => m (Condition ConfVar)+parseCondition = condOr+ where+ condOr = sepByNonEmpty condAnd (oper "||") >>= return . foldl1 COr+ condAnd = sepByNonEmpty cond (oper "&&")>>= return . foldl1 CAnd+ -- TODO: try?+ cond = sp >> (boolLiteral <|> inparens condOr <|> notCond <|> osCond+ <|> archCond <|> flagCond <|> implCond )+ inparens = between (P.char '(' >> sp) (sp >> P.char ')' >> sp)+ notCond = P.char '!' >> sp >> cond >>= return . CNot+ osCond = string "os" >> sp >> inparens osIdent >>= return . Var+ archCond = string "arch" >> sp >> inparens archIdent >>= return . Var+ flagCond = string "flag" >> sp >> inparens flagIdent >>= return . Var+ implCond = string "impl" >> sp >> inparens implIdent >>= return . Var+ boolLiteral = fmap Lit parsec+ archIdent = fmap Arch parsec+ osIdent = fmap OS parsec+ flagIdent = fmap (PackageFlag . mkFlagName . lowercase) (munch1 isIdentChar)+ isIdentChar c = isAlphaNum c || c == '_' || c == '-'+ oper s = sp >> string s >> sp+ sp = spaces+ implIdent = do i <- parsec+ vr <- sp >> option anyVersion parsec+ return $ Impl i vr++------------------------------------------------------------------------------++-- | Result of dependency test. Isomorphic to @Maybe d@ but renamed for+-- clarity.+data DepTestRslt d = DepOk | MissingDeps d++instance Semigroup d => Monoid (DepTestRslt d) where+ mempty = DepOk+ mappend = (<>)++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.+--+-- Returns either the missing dependencies, or a tuple containing the+-- resulting data, the associated dependencies, and the chosen flag+-- assignments.+--+-- 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:+--+-- * Rule out possible paths, by taking a look at the associated dependencies.+--+-- * Infer the required values for the conditions of these paths, and+-- calculate the required domains for the variables used in these+-- conditions. Then picking a flag assignment would be linear (I guess).+--+-- This would require some sort of SAT solving, though, thus it's not+-- implemented unless we really need it.+--+resolveWithFlags ::+ [(FlagName,[Bool])]+ -- ^ Domain for each flag name, will be tested in order.+ -> ComponentRequestedSpec+ -> OS -- ^ OS as returned by Distribution.System.buildOS+ -> Arch -- ^ Arch as returned by Distribution.System.buildArch+ -> CompilerInfo -- ^ Compiler information+ -> [PackageVersionConstraint] -- ^ Additional constraints+ -> [CondTree ConfVar [Dependency] PDTagged]+ -> ([Dependency] -> DepTestRslt [Dependency]) -- ^ Dependency test function.+ -> Either [Dependency] (TargetSet PDTagged, FlagAssignment)+ -- ^ Either the missing dependencies (error case), or a pair of+ -- (set of build targets with dependencies, chosen flag assignments)+resolveWithFlags dom enabled os arch impl constrs trees checkDeps =+ either (Left . fromDepMapUnion) Right $ explore (build mempty dom)+ where+ -- 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+ . addBuildableConditionPDTagged+ . mapTreeConds (fst . simplifyWithSysParams os arch impl))+ trees++ -- @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` constrs) .+ simplifyCondTree (env flags)+ deps = overallDependencies enabled targetSet+ in case checkDeps (fromDepMap deps) of+ DepOk | null ts -> Right (targetSet, flags)+ | otherwise -> tryAll $ map explore ts+ MissingDeps mds -> Left (toDepMapUnion mds)++ -- 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 (insertFlagAssignment 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 :: Either DepMapUnion a -> Either DepMapUnion a -> Either DepMapUnion a+ mp m@(Right _) _ = m+ mp _ m@(Right _) = m+ mp (Left xs) (Left ys) = Left (xs <> ys)++ -- `mzero'+ mz :: Either DepMapUnion a+ mz = Left (DepMapUnion Map.empty)++ env :: FlagAssignment -> FlagName -> Either FlagName Bool+ env flags flag = (maybe (Left flag) Right . lookupFlagAssignment flag) flags++-- | 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 [condIfThen c t]++-- | This is a special version of 'addBuildableCondition' for the 'PDTagged'+-- type.+--+-- It is not simply a specialisation. It is more complicated than it+-- ought to be because of the way the 'PDTagged' monoid instance works. The+-- @mempty = 'PDNull'@ forgets the component type, which has the effect of+-- completely deleting components that are not buildable.+--+-- See <https://github.com/haskell/cabal/pull/4094> for more details.+--+addBuildableConditionPDTagged :: (Eq v, Monoid c) =>+ CondTree v c PDTagged+ -> CondTree v c PDTagged+addBuildableConditionPDTagged t =+ case extractCondition (buildable . getInfo) t of+ Lit True -> t+ Lit False -> deleteConstraints t+ c -> CondNode mempty mempty [condIfThenElse c t (deleteConstraints t)]+ where+ deleteConstraints = mapTreeConstrs (const mempty)++ getInfo :: PDTagged -> BuildInfo+ getInfo (Lib l) = libBuildInfo l+ getInfo (SubComp _ c) = componentBuildInfo c+ getInfo PDNull = mempty+++-- 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 conditions matched by the given predicate from all cond trees in a+-- 'GenericPackageDescription'.+extractConditions :: (BuildInfo -> Bool) -> GenericPackageDescription+ -> [Condition ConfVar]+extractConditions f gpkg =+ concat [+ extractCondition (f . libBuildInfo) <$> maybeToList (condLibrary gpkg)+ , extractCondition (f . libBuildInfo) . snd <$> condSubLibraries gpkg+ , extractCondition (f . buildInfo) . snd <$> condExecutables gpkg+ , extractCondition (f . testBuildInfo) . snd <$> condTestSuites gpkg+ , extractCondition (f . benchmarkBuildInfo) . snd <$> condBenchmarks gpkg+ ]+++-- | A map of package constraints that combines version ranges using 'unionVersionRanges'.+newtype DepMapUnion = DepMapUnion { unDepMapUnion :: Map PackageName (VersionRange, NonEmptySet LibraryName) }++instance Semigroup DepMapUnion where+ DepMapUnion x <> DepMapUnion y = DepMapUnion $+ Map.unionWith unionVersionRanges' x y++unionVersionRanges'+ :: (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName)+unionVersionRanges' (vr, cs) (vr', cs') = (unionVersionRanges vr vr', cs <> cs')++toDepMapUnion :: [Dependency] -> DepMapUnion+toDepMapUnion ds =+ DepMapUnion $ Map.fromListWith unionVersionRanges' [ (p,(vr,cs)) | Dependency p vr cs <- ds ]+++fromDepMapUnion :: DepMapUnion -> [Dependency]+fromDepMapUnion m = [ Dependency p vr cs | (p,(vr,cs)) <- Map.toList (unDepMapUnion m) ]++freeVars :: CondTree ConfVar c a -> [FlagName]+freeVars t = [ f | PackageFlag f <- freeVars' t ]+ where+ freeVars' (CondNode _ _ ifs) = concatMap compfv ifs+ compfv (CondBranch c ct mct) = condfv c ++ freeVars' ct ++ maybe [] freeVars' mct+ condfv c = case c of+ Var v -> [v]+ Lit _ -> []+ CNot c' -> condfv c'+ COr c1 c2 -> condfv c1 ++ condfv c2+ CAnd c1 c2 -> condfv c1 ++ condfv c2+++------------------------------------------------------------------------------++-- | A set of targets with their package dependencies+newtype TargetSet a = TargetSet [(DependencyMap, a)]++-- | Combine the target-specific dependencies in a TargetSet to give the+-- dependencies for the package as a whole.+overallDependencies :: ComponentRequestedSpec -> TargetSet PDTagged -> DependencyMap+overallDependencies enabled (TargetSet targets) = mconcat depss+ where+ (depss, _) = unzip $ filter (removeDisabledSections . snd) targets+ removeDisabledSections :: PDTagged -> Bool+ -- UGH. The embedded componentName in the 'Component's here is+ -- BLANK. I don't know whose fault this is but I'll use the tag+ -- instead. -- ezyang+ removeDisabledSections (Lib _) = componentNameRequested+ enabled+ (CLibName LMainLibName)+ removeDisabledSections (SubComp t c)+ -- Do NOT use componentName+ = componentNameRequested enabled+ $ case c of+ CLib _ -> CLibName (LSubLibName t)+ CFLib _ -> CFLibName t+ CExe _ -> CExeName t+ CTest _ -> CTestName t+ CBench _ -> CBenchName t+ removeDisabledSections PDNull = True++-- | Collect up the targets in a TargetSet of tagged targets, storing the+-- dependencies as we go.+flattenTaggedTargets :: TargetSet PDTagged -> (Maybe Library, [(UnqualComponentName, Component)])+flattenTaggedTargets (TargetSet targets) = foldr untag (Nothing, []) targets where+ untag (depMap, pdTagged) accum = case (pdTagged, accum) of+ (Lib _, (Just _, _)) -> userBug "Only one library expected"+ (Lib l, (Nothing, comps)) -> (Just $ redoBD l, comps)+ (SubComp n c, (mb_lib, comps))+ | any ((== n) . fst) comps ->+ userBug $ "There exist several components with the same name: '" ++ prettyShow n ++ "'"+ | otherwise -> (mb_lib, (n, redoBD c) : comps)+ (PDNull, x) -> x -- actually this should not happen, but let's be liberal+ where+ redoBD :: L.HasBuildInfo a => a -> a+ redoBD = set L.targetBuildDepends $ fromDepMap depMap++------------------------------------------------------------------------------+-- Convert GenericPackageDescription to PackageDescription+--++data PDTagged = Lib Library+ | SubComp UnqualComponentName Component+ | PDNull+ deriving Show++instance Monoid PDTagged where+ mempty = PDNull+ mappend = (<>)++instance Semigroup PDTagged where+ PDNull <> x = x+ x <> PDNull = x+ Lib l <> Lib l' = Lib (l <> l')+ SubComp n x <> SubComp n' x' | n == n' = SubComp n (x <> x')+ _ <> _ = cabalBug "Cannot combine incompatible tags"++-- | Create a package description with all configurations resolved.+--+-- This function takes a `GenericPackageDescription` and several environment+-- parameters and tries to generate `PackageDescription` by finding a flag+-- assignment that result in satisfiable dependencies.+--+-- It takes as inputs a not necessarily complete specifications of flags+-- assignments, an optional package index as well as platform parameters. If+-- some flags are not assigned explicitly, this function will try to pick an+-- assignment that causes this function to succeed. The package index is+-- optional since on some platforms we cannot determine which packages have+-- been installed before. When no package index is supplied, every dependency+-- is assumed to be satisfiable, therefore all not explicitly assigned flags+-- will get their default values.+--+-- 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 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.+--+-- Note that this drops any stanzas which have @buildable: False@. While+-- this is arguably the right thing to do, it means we give bad error+-- messages in some situations, see #3858.+--+finalizePD ::+ FlagAssignment -- ^ Explicitly specified flag assignments+ -> ComponentRequestedSpec+ -> (Dependency -> Bool) -- ^ Is a given dependency satisfiable from the set of+ -- available packages? If this is unknown then use+ -- True.+ -> Platform -- ^ The 'Arch' and 'OS'+ -> CompilerInfo -- ^ Compiler information+ -> [PackageVersionConstraint] -- ^ Additional constraints+ -> GenericPackageDescription+ -> Either [Dependency]+ (PackageDescription, FlagAssignment)+ -- ^ Either missing dependencies or the resolved package+ -- description along with the flag assignments chosen.+finalizePD userflags enabled satisfyDep+ (Platform arch os) impl constraints+ (GenericPackageDescription pkg _ver flags mb_lib0 sub_libs0 flibs0 exes0 tests0 bms0) = do+ (targetSet, flagVals) <-+ resolveWithFlags flagChoices enabled os arch impl constraints condTrees check+ let+ (mb_lib, comps) = flattenTaggedTargets targetSet+ mb_lib' = fmap libFillInDefaults mb_lib+ comps' = flip map comps $ \(n,c) -> foldComponent+ (\l -> CLib (libFillInDefaults l) { libName = LSubLibName n+ , libExposed = False })+ (\l -> CFLib (flibFillInDefaults l) { foreignLibName = n })+ (\e -> CExe (exeFillInDefaults e) { exeName = n })+ (\t -> CTest (testFillInDefaults t) { testName = n })+ (\b -> CBench (benchFillInDefaults b) { benchmarkName = n })+ c+ (sub_libs', flibs', exes', tests', bms') = partitionComponents comps'+ return ( pkg { library = mb_lib'+ , subLibraries = sub_libs'+ , foreignLibs = flibs'+ , executables = exes'+ , testSuites = tests'+ , benchmarks = bms'+ }+ , flagVals )+ where+ -- Combine lib, exes, and tests into one list of @CondTree@s with tagged data+ condTrees = maybeToList (fmap (mapTreeData Lib) mb_lib0)+ ++ map (\(name,tree) -> mapTreeData (SubComp name . CLib) tree) sub_libs0+ ++ map (\(name,tree) -> mapTreeData (SubComp name . CFLib) tree) flibs0+ ++ map (\(name,tree) -> mapTreeData (SubComp name . CExe) tree) exes0+ ++ map (\(name,tree) -> mapTreeData (SubComp name . CTest) tree) tests0+ ++ map (\(name,tree) -> mapTreeData (SubComp name . CBench) tree) bms0++ flagChoices = map (\(MkPackageFlag n _ d manual) -> (n, d2c manual n d)) flags+ d2c manual n b = case lookupFlagAssignment n userflags of+ Just val -> [val]+ Nothing+ | manual -> [b]+ | otherwise -> [b, not b]+ --flagDefaults = map (\(n,x:_) -> (n,x)) flagChoices+ check ds = let missingDeps = filter (not . satisfyDep) ds+ in if null missingDeps+ then DepOk+ else MissingDeps missingDeps++{-+let tst_p = (CondNode [1::Int] [Distribution.Package.Dependency "a" AnyVersion] [])+let tst_p2 = (CondNode [1::Int] [Distribution.Package.Dependency "a" (EarlierVersion (Version [1,0] [])), Distribution.Package.Dependency "a" (LaterVersion (Version [2,0] []))] [])++let p_index = Distribution.Simple.PackageIndex.fromList [Distribution.Package.PackageIdentifier "a" (Version [0,5] []), Distribution.Package.PackageIdentifier "a" (Version [2,5] [])]+let look = not . null . Distribution.Simple.PackageIndex.lookupDependency p_index+let looks ds = mconcat $ map (\d -> if look d then DepOk else MissingDeps [d]) ds+resolveWithFlags [] Distribution.System.Linux Distribution.System.I386 (Distribution.Compiler.GHC,Version [6,8,2] []) [tst_p] looks ===> Right ...+resolveWithFlags [] Distribution.System.Linux Distribution.System.I386 (Distribution.Compiler.GHC,Version [6,8,2] []) [tst_p2] looks ===> Left ...+-}++-- | Flatten a generic package description by ignoring all conditions and just+-- join the field descriptors into on package description. Note, however,+-- that this may lead to inconsistent field values, since all values are+-- joined into one field, which may not be possible in the original package+-- description, due to the use of exclusive choices (if ... else ...).+--+-- TODO: One particularly tricky case is defaulting. In the original package+-- description, e.g., the source directory might either be the default or a+-- certain, explicitly set path. Since defaults are filled in only after the+-- package has been resolved and when no explicit value has been set, the+-- default path will be missing from the package description returned by this+-- function.+flattenPackageDescription :: GenericPackageDescription -> PackageDescription+flattenPackageDescription+ (GenericPackageDescription pkg _ _ mlib0 sub_libs0 flibs0 exes0 tests0 bms0) =+ pkg { library = mlib+ , subLibraries = reverse sub_libs+ , foreignLibs = reverse flibs+ , executables = reverse exes+ , testSuites = reverse tests+ , benchmarks = reverse bms+ }+ where+ mlib = f <$> mlib0+ where f lib = (libFillInDefaults . fst . ignoreConditions $ lib) { libName = LMainLibName }+ sub_libs = flattenLib <$> sub_libs0+ flibs = flattenFLib <$> flibs0+ exes = flattenExe <$> exes0+ tests = flattenTst <$> tests0+ bms = flattenBm <$> bms0+ flattenLib (n, t) = libFillInDefaults $ (fst $ ignoreConditions t)+ { libName = LSubLibName n, libExposed = False }+ flattenFLib (n, t) = flibFillInDefaults $ (fst $ ignoreConditions t)+ { foreignLibName = n }+ flattenExe (n, t) = exeFillInDefaults $ (fst $ ignoreConditions t)+ { exeName = n }+ flattenTst (n, t) = testFillInDefaults $ (fst $ ignoreConditions t)+ { testName = n }+ flattenBm (n, t) = benchFillInDefaults $ (fst $ ignoreConditions t)+ { benchmarkName = n }++-- This is in fact rather a hack. The original version just overrode the+-- default values, however, when adding conditions we had to switch to a+-- modifier-based approach. There, nothing is ever overwritten, but only+-- joined together.+--+-- This is the cleanest way i could think of, that doesn't require+-- changing all field parsing functions to return modifiers instead.+libFillInDefaults :: Library -> Library+libFillInDefaults lib@(Library { libBuildInfo = bi }) =+ lib { libBuildInfo = biFillInDefaults bi }++flibFillInDefaults :: ForeignLib -> ForeignLib+flibFillInDefaults flib@(ForeignLib { foreignLibBuildInfo = bi }) =+ flib { foreignLibBuildInfo = biFillInDefaults bi }++exeFillInDefaults :: Executable -> Executable+exeFillInDefaults exe@(Executable { buildInfo = bi }) =+ exe { buildInfo = biFillInDefaults bi }++testFillInDefaults :: TestSuite -> TestSuite+testFillInDefaults tst@(TestSuite { testBuildInfo = bi }) =+ tst { testBuildInfo = biFillInDefaults bi }++benchFillInDefaults :: Benchmark -> Benchmark+benchFillInDefaults bm@(Benchmark { benchmarkBuildInfo = bi }) =+ bm { benchmarkBuildInfo = biFillInDefaults bi }++biFillInDefaults :: BuildInfo -> BuildInfo+biFillInDefaults bi =+ if null (hsSourceDirs bi)+ then bi { hsSourceDirs = [sameDirectory] }+ 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 =+ over L.traverseBuildInfos onBuildInfo+ . over (L.packageDescription . L.setupBuildInfo . traverse) onSetupBuildInfo++-- | Walk a 'GenericPackageDescription' and apply @f@ to all nested+-- @build-depends@ fields.+transformAllBuildDepends :: (Dependency -> Dependency)+ -> GenericPackageDescription+ -> GenericPackageDescription+transformAllBuildDepends f =+ over (L.traverseBuildInfos . L.targetBuildDepends . traverse) f+ . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends . traverse) f+ -- cannot be point-free as normal because of higher rank+ . over (\f' -> L.allCondTrees $ traverseCondTreeC f') (map f)++-- | Walk a 'GenericPackageDescription' and apply @f@ to all nested+-- @build-depends@ fields.+transformAllBuildDependsN :: ([Dependency] -> [Dependency])+ -> GenericPackageDescription+ -> GenericPackageDescription+transformAllBuildDependsN f =+ over (L.traverseBuildInfos . L.targetBuildDepends) f+ . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends) f+ -- cannot be point-free as normal because of higher rank+ . over (\f' -> L.allCondTrees $ traverseCondTreeC f') f
+ src/Distribution/PackageDescription/FieldGrammar.hs view
@@ -0,0 +1,802 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+-- | 'GenericPackageDescription' Field descriptions+module Distribution.PackageDescription.FieldGrammar (+ -- * Package description+ packageDescriptionFieldGrammar,+ -- * Library+ libraryFieldGrammar,+ -- * Foreign library+ foreignLibFieldGrammar,+ -- * Executable+ executableFieldGrammar,+ -- * Test suite+ TestSuiteStanza (..),+ testSuiteFieldGrammar,+ validateTestSuite,+ unvalidateTestSuite,+ -- ** Lenses+ testStanzaTestType,+ testStanzaMainIs,+ testStanzaTestModule,+ testStanzaBuildInfo,+ -- * Benchmark+ BenchmarkStanza (..),+ benchmarkFieldGrammar,+ validateBenchmark,+ unvalidateBenchmark,+ -- * Field grammars+ formatDependencyList,+ formatExposedModules,+ formatExtraSourceFiles,+ formatHsSourceDirs,+ formatMixinList,+ formatOtherExtensions,+ formatOtherModules,+ -- ** Lenses+ benchmarkStanzaBenchmarkType,+ benchmarkStanzaMainIs,+ benchmarkStanzaBenchmarkModule,+ benchmarkStanzaBuildInfo,+ -- * Flag+ flagFieldGrammar,+ -- * Source repository+ sourceRepoFieldGrammar,+ -- * Setup build info+ setupBInfoFieldGrammar,+ -- * Component build info+ buildInfoFieldGrammar,+ ) where+++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Language.Haskell.Extension+import Prelude ()++import Distribution.CabalSpecVersion+import Distribution.Compat.Newtype (Newtype, pack', unpack')+import Distribution.Compiler (CompilerFlavor (..), PerCompilerFlavor (..))+import Distribution.FieldGrammar+import Distribution.Fields+import Distribution.ModuleName (ModuleName)+import Distribution.Package+import Distribution.PackageDescription+import Distribution.Parsec+import Distribution.Pretty (Pretty (..), prettyShow, showToken)+import Distribution.Utils.Path+import Distribution.Version (Version, VersionRange)++import qualified Data.ByteString.Char8 as BS8+import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.SPDX as SPDX+import qualified Distribution.Types.Lens as L++-------------------------------------------------------------------------------+-- PackageDescription+-------------------------------------------------------------------------------++packageDescriptionFieldGrammar+ :: ( FieldGrammar c g, Applicative (g PackageDescription), Applicative (g PackageIdentifier)+ , c (Identity BuildType)+ , c (Identity PackageName)+ , c (Identity Version)+ , c (List FSep FilePathNT String)+ , c (List FSep CompatFilePath String)+ , c (List FSep (Identity (SymbolicPath PackageDir LicenseFile)) (SymbolicPath PackageDir LicenseFile))+ , c (List FSep TestedWith (CompilerFlavor, VersionRange))+ , c (List VCat FilePathNT String)+ , c FilePathNT+ , c CompatLicenseFile+ , c CompatFilePath+ , c SpecLicense+ , c SpecVersion+ )+ => g PackageDescription PackageDescription+packageDescriptionFieldGrammar = PackageDescription+ <$> optionalFieldDefAla "cabal-version" SpecVersion L.specVersion CabalSpecV1_0+ <*> blurFieldGrammar L.package packageIdentifierGrammar+ <*> optionalFieldDefAla "license" SpecLicense L.licenseRaw (Left SPDX.NONE)+ <*> licenseFilesGrammar+ <*> freeTextFieldDefST "copyright" L.copyright+ <*> freeTextFieldDefST "maintainer" L.maintainer+ <*> freeTextFieldDefST "author" L.author+ <*> freeTextFieldDefST "stability" L.stability+ <*> monoidalFieldAla "tested-with" (alaList' FSep TestedWith) L.testedWith+ <*> freeTextFieldDefST "homepage" L.homepage+ <*> freeTextFieldDefST "package-url" L.pkgUrl+ <*> freeTextFieldDefST "bug-reports" L.bugReports+ <*> pure [] -- source-repos are stanza+ <*> freeTextFieldDefST "synopsis" L.synopsis+ <*> freeTextFieldDefST "description" L.description+ <*> freeTextFieldDefST "category" L.category+ <*> prefixedFields "x-" L.customFieldsPD+ <*> optionalField "build-type" L.buildTypeRaw+ <*> pure Nothing -- custom-setup+ -- components+ <*> pure Nothing -- lib+ <*> pure [] -- sub libs+ <*> pure [] -- executables+ <*> pure [] -- foreign libs+ <*> pure [] -- test suites+ <*> pure [] -- benchmarks+ -- * Files+ <*> monoidalFieldAla "data-files" (alaList' VCat FilePathNT) L.dataFiles+ <*> optionalFieldDefAla "data-dir" CompatFilePath L.dataDir "."+ ^^^ fmap (\x -> if null x then "." else x) -- map empty directories to "."+ <*> monoidalFieldAla "extra-source-files" formatExtraSourceFiles L.extraSrcFiles+ <*> monoidalFieldAla "extra-tmp-files" (alaList' VCat FilePathNT) L.extraTmpFiles+ <*> monoidalFieldAla "extra-doc-files" (alaList' VCat FilePathNT) L.extraDocFiles+ where+ packageIdentifierGrammar = PackageIdentifier+ <$> uniqueField "name" L.pkgName+ <*> uniqueField "version" L.pkgVersion++ licenseFilesGrammar = (++)+ -- TODO: neither field is deprecated+ -- should we pretty print license-file if there's single license file+ -- and license-files when more+ <$> monoidalFieldAla "license-file" CompatLicenseFile L.licenseFiles+ <*> monoidalFieldAla "license-files" (alaList FSep) L.licenseFiles+ ^^^ hiddenField++-------------------------------------------------------------------------------+-- Library+-------------------------------------------------------------------------------++libraryFieldGrammar+ :: ( FieldGrammar c g, Applicative (g Library), Applicative (g BuildInfo)+ , c (Identity LibraryVisibility)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List CommaVCat (Identity ModuleReexport) ModuleReexport)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir))+ , c (List VCat Token String)+ , c (MQuoted Language)+ )+ => LibraryName+ -> g Library Library+libraryFieldGrammar n = Library n+ <$> monoidalFieldAla "exposed-modules" formatExposedModules L.exposedModules+ <*> monoidalFieldAla "reexported-modules" (alaList CommaVCat) L.reexportedModules+ <*> monoidalFieldAla "signatures" (alaList' VCat MQuoted) L.signatures+ ^^^ availableSince CabalSpecV2_0 []+ <*> booleanFieldDef "exposed" L.libExposed True+ <*> visibilityField+ <*> blurFieldGrammar L.libBuildInfo buildInfoFieldGrammar+ where+ visibilityField = case n of+ -- nameless/"main" libraries are public+ LMainLibName -> pure LibraryVisibilityPublic+ -- named libraries have the field+ LSubLibName _ ->+ optionalFieldDef "visibility" L.libVisibility LibraryVisibilityPrivate+ ^^^ availableSince CabalSpecV3_0 LibraryVisibilityPrivate++{-# SPECIALIZE libraryFieldGrammar :: LibraryName -> ParsecFieldGrammar' Library #-}+{-# SPECIALIZE libraryFieldGrammar :: LibraryName -> PrettyFieldGrammar' Library #-}++-------------------------------------------------------------------------------+-- Foreign library+-------------------------------------------------------------------------------++foreignLibFieldGrammar+ :: ( FieldGrammar c g, Applicative (g ForeignLib), Applicative (g BuildInfo)+ , c (Identity ForeignLibType)+ , c (Identity LibVersionInfo)+ , c (Identity Version)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (Identity ForeignLibOption) ForeignLibOption)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir))+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String), c (List VCat Token String)+ , c (MQuoted Language)+ )+ => UnqualComponentName -> g ForeignLib ForeignLib+foreignLibFieldGrammar n = ForeignLib n+ <$> optionalFieldDef "type" L.foreignLibType ForeignLibTypeUnknown+ <*> monoidalFieldAla "options" (alaList FSep) L.foreignLibOptions+ <*> blurFieldGrammar L.foreignLibBuildInfo buildInfoFieldGrammar+ <*> optionalField "lib-version-info" L.foreignLibVersionInfo+ <*> optionalField "lib-version-linux" L.foreignLibVersionLinux+ <*> monoidalFieldAla "mod-def-file" (alaList' FSep FilePathNT) L.foreignLibModDefFile+{-# SPECIALIZE foreignLibFieldGrammar :: UnqualComponentName -> ParsecFieldGrammar' ForeignLib #-}+{-# SPECIALIZE foreignLibFieldGrammar :: UnqualComponentName -> PrettyFieldGrammar' ForeignLib #-}++-------------------------------------------------------------------------------+-- Executable+-------------------------------------------------------------------------------++executableFieldGrammar+ :: ( FieldGrammar c g, Applicative (g Executable), Applicative (g BuildInfo)+ , c (Identity ExecutableScope)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir))+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List VCat Token String)+ , c (MQuoted Language)+ )+ => UnqualComponentName -> g Executable Executable+executableFieldGrammar n = Executable n+ -- main-is is optional as conditional blocks don't have it+ <$> optionalFieldDefAla "main-is" FilePathNT L.modulePath ""+ <*> optionalFieldDef "scope" L.exeScope ExecutablePublic+ ^^^ availableSince CabalSpecV2_0 ExecutablePublic+ <*> blurFieldGrammar L.buildInfo buildInfoFieldGrammar+{-# SPECIALIZE executableFieldGrammar :: UnqualComponentName -> ParsecFieldGrammar' Executable #-}+{-# SPECIALIZE executableFieldGrammar :: UnqualComponentName -> PrettyFieldGrammar' Executable #-}++-------------------------------------------------------------------------------+-- TestSuite+-------------------------------------------------------------------------------++-- | An intermediate type just used for parsing the test-suite stanza.+-- After validation it is converted into the proper 'TestSuite' type.+data TestSuiteStanza = TestSuiteStanza+ { _testStanzaTestType :: Maybe TestType+ , _testStanzaMainIs :: Maybe FilePath+ , _testStanzaTestModule :: Maybe ModuleName+ , _testStanzaBuildInfo :: BuildInfo+ }++instance L.HasBuildInfo TestSuiteStanza where+ buildInfo = testStanzaBuildInfo++testStanzaTestType :: Lens' TestSuiteStanza (Maybe TestType)+testStanzaTestType f s = fmap (\x -> s { _testStanzaTestType = x }) (f (_testStanzaTestType s))+{-# INLINE testStanzaTestType #-}++testStanzaMainIs :: Lens' TestSuiteStanza (Maybe FilePath)+testStanzaMainIs f s = fmap (\x -> s { _testStanzaMainIs = x }) (f (_testStanzaMainIs s))+{-# INLINE testStanzaMainIs #-}++testStanzaTestModule :: Lens' TestSuiteStanza (Maybe ModuleName)+testStanzaTestModule f s = fmap (\x -> s { _testStanzaTestModule = x }) (f (_testStanzaTestModule s))+{-# INLINE testStanzaTestModule #-}++testStanzaBuildInfo :: Lens' TestSuiteStanza BuildInfo+testStanzaBuildInfo f s = fmap (\x -> s { _testStanzaBuildInfo = x }) (f (_testStanzaBuildInfo s))+{-# INLINE testStanzaBuildInfo #-}++testSuiteFieldGrammar+ :: ( FieldGrammar c g, Applicative (g TestSuiteStanza), Applicative (g BuildInfo)+ , c (Identity ModuleName)+ , c (Identity TestType)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir))+ , c (List VCat Token String)+ , c (MQuoted Language)+ )+ => g TestSuiteStanza TestSuiteStanza+testSuiteFieldGrammar = TestSuiteStanza+ <$> optionalField "type" testStanzaTestType+ <*> optionalFieldAla "main-is" FilePathNT testStanzaMainIs+ <*> optionalField "test-module" testStanzaTestModule+ <*> blurFieldGrammar testStanzaBuildInfo buildInfoFieldGrammar++validateTestSuite :: Position -> TestSuiteStanza -> ParseResult TestSuite+validateTestSuite pos stanza = case _testStanzaTestType stanza of+ Nothing -> return $+ emptyTestSuite { testBuildInfo = _testStanzaBuildInfo stanza }++ Just tt@(TestTypeUnknown _ _) ->+ pure emptyTestSuite+ { testInterface = TestSuiteUnsupported tt+ , testBuildInfo = _testStanzaBuildInfo stanza+ }++ Just tt | tt `notElem` knownTestTypes ->+ pure emptyTestSuite+ { testInterface = TestSuiteUnsupported tt+ , testBuildInfo = _testStanzaBuildInfo stanza+ }++ Just tt@(TestTypeExe ver) -> case _testStanzaMainIs stanza of+ Nothing -> do+ parseFailure pos (missingField "main-is" tt)+ pure emptyTestSuite+ Just file -> do+ when (isJust (_testStanzaTestModule stanza)) $+ parseWarning pos PWTExtraBenchmarkModule (extraField "test-module" tt)+ pure emptyTestSuite+ { testInterface = TestSuiteExeV10 ver file+ , testBuildInfo = _testStanzaBuildInfo stanza+ }++ Just tt@(TestTypeLib ver) -> case _testStanzaTestModule stanza of+ Nothing -> do+ parseFailure pos (missingField "test-module" tt)+ pure emptyTestSuite+ Just module_ -> do+ when (isJust (_testStanzaMainIs stanza)) $+ parseWarning pos PWTExtraMainIs (extraField "main-is" tt)+ pure emptyTestSuite+ { testInterface = TestSuiteLibV09 ver module_+ , testBuildInfo = _testStanzaBuildInfo stanza+ }++ where+ missingField name tt = "The '" ++ name ++ "' field is required for the "+ ++ prettyShow tt ++ " test suite type."++ extraField name tt = "The '" ++ name ++ "' field is not used for the '"+ ++ prettyShow tt ++ "' test suite type."++unvalidateTestSuite :: TestSuite -> TestSuiteStanza+unvalidateTestSuite t = TestSuiteStanza+ { _testStanzaTestType = ty+ , _testStanzaMainIs = ma+ , _testStanzaTestModule = mo+ , _testStanzaBuildInfo = testBuildInfo t+ }+ where+ (ty, ma, mo) = case testInterface t of+ TestSuiteExeV10 ver file -> (Just $ TestTypeExe ver, Just file, Nothing)+ TestSuiteLibV09 ver modu -> (Just $ TestTypeLib ver, Nothing, Just modu)+ _ -> (Nothing, Nothing, Nothing)++-------------------------------------------------------------------------------+-- Benchmark+-------------------------------------------------------------------------------++-- | An intermediate type just used for parsing the benchmark stanza.+-- After validation it is converted into the proper 'Benchmark' type.+data BenchmarkStanza = BenchmarkStanza+ { _benchmarkStanzaBenchmarkType :: Maybe BenchmarkType+ , _benchmarkStanzaMainIs :: Maybe FilePath+ , _benchmarkStanzaBenchmarkModule :: Maybe ModuleName+ , _benchmarkStanzaBuildInfo :: BuildInfo+ }++instance L.HasBuildInfo BenchmarkStanza where+ buildInfo = benchmarkStanzaBuildInfo++benchmarkStanzaBenchmarkType :: Lens' BenchmarkStanza (Maybe BenchmarkType)+benchmarkStanzaBenchmarkType f s = fmap (\x -> s { _benchmarkStanzaBenchmarkType = x }) (f (_benchmarkStanzaBenchmarkType s))+{-# INLINE benchmarkStanzaBenchmarkType #-}++benchmarkStanzaMainIs :: Lens' BenchmarkStanza (Maybe FilePath)+benchmarkStanzaMainIs f s = fmap (\x -> s { _benchmarkStanzaMainIs = x }) (f (_benchmarkStanzaMainIs s))+{-# INLINE benchmarkStanzaMainIs #-}++benchmarkStanzaBenchmarkModule :: Lens' BenchmarkStanza (Maybe ModuleName)+benchmarkStanzaBenchmarkModule f s = fmap (\x -> s { _benchmarkStanzaBenchmarkModule = x }) (f (_benchmarkStanzaBenchmarkModule s))+{-# INLINE benchmarkStanzaBenchmarkModule #-}++benchmarkStanzaBuildInfo :: Lens' BenchmarkStanza BuildInfo+benchmarkStanzaBuildInfo f s = fmap (\x -> s { _benchmarkStanzaBuildInfo = x }) (f (_benchmarkStanzaBuildInfo s))+{-# INLINE benchmarkStanzaBuildInfo #-}++benchmarkFieldGrammar+ :: ( FieldGrammar c g, Applicative (g BenchmarkStanza), Applicative (g BuildInfo)+ , c (Identity BenchmarkType)+ , c (Identity ModuleName)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir))+ , c (List VCat Token String)+ , c (MQuoted Language)+ )+ => g BenchmarkStanza BenchmarkStanza+benchmarkFieldGrammar = BenchmarkStanza+ <$> optionalField "type" benchmarkStanzaBenchmarkType+ <*> optionalFieldAla "main-is" FilePathNT benchmarkStanzaMainIs+ <*> optionalField "benchmark-module" benchmarkStanzaBenchmarkModule+ <*> blurFieldGrammar benchmarkStanzaBuildInfo buildInfoFieldGrammar++validateBenchmark :: Position -> BenchmarkStanza -> ParseResult Benchmark+validateBenchmark pos stanza = case _benchmarkStanzaBenchmarkType stanza of+ Nothing -> pure emptyBenchmark+ { benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza }++ Just tt@(BenchmarkTypeUnknown _ _) -> pure emptyBenchmark+ { benchmarkInterface = BenchmarkUnsupported tt+ , benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza+ }++ Just tt | tt `notElem` knownBenchmarkTypes -> pure emptyBenchmark+ { benchmarkInterface = BenchmarkUnsupported tt+ , benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza+ }++ Just tt@(BenchmarkTypeExe ver) -> case _benchmarkStanzaMainIs stanza of+ Nothing -> do+ parseFailure pos (missingField "main-is" tt)+ pure emptyBenchmark+ Just file -> do+ when (isJust (_benchmarkStanzaBenchmarkModule stanza)) $+ parseWarning pos PWTExtraBenchmarkModule (extraField "benchmark-module" tt)+ pure emptyBenchmark+ { benchmarkInterface = BenchmarkExeV10 ver file+ , benchmarkBuildInfo = _benchmarkStanzaBuildInfo stanza+ }++ where+ missingField name tt = "The '" ++ name ++ "' field is required for the "+ ++ prettyShow tt ++ " benchmark type."++ extraField name tt = "The '" ++ name ++ "' field is not used for the '"+ ++ prettyShow tt ++ "' benchmark type."++unvalidateBenchmark :: Benchmark -> BenchmarkStanza+unvalidateBenchmark b = BenchmarkStanza+ { _benchmarkStanzaBenchmarkType = ty+ , _benchmarkStanzaMainIs = ma+ , _benchmarkStanzaBenchmarkModule = mo+ , _benchmarkStanzaBuildInfo = benchmarkBuildInfo b+ }+ where+ (ty, ma, mo) = case benchmarkInterface b of+ BenchmarkExeV10 ver "" -> (Just $ BenchmarkTypeExe ver, Nothing, Nothing)+ BenchmarkExeV10 ver ma' -> (Just $ BenchmarkTypeExe ver, Just ma', Nothing)+ _ -> (Nothing, Nothing, Nothing)++-------------------------------------------------------------------------------+-- Build info+-------------------------------------------------------------------------------++buildInfoFieldGrammar+ :: ( FieldGrammar c g, Applicative (g BuildInfo)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir))+ , c (List VCat Token String)+ , c (MQuoted Language)+ )+ => g BuildInfo BuildInfo+buildInfoFieldGrammar = BuildInfo+ <$> booleanFieldDef "buildable" L.buildable True+ <*> monoidalFieldAla "build-tools" (alaList CommaFSep) L.buildTools+ ^^^ deprecatedSince CabalSpecV2_0+ "Please use 'build-tool-depends' field"+ ^^^ removedIn CabalSpecV3_0+ "Please use 'build-tool-depends' field."+ <*> monoidalFieldAla "build-tool-depends" (alaList CommaFSep) L.buildToolDepends+ -- {- ^^^ availableSince [2,0] [] -}+ -- here, we explicitly want to recognise build-tool-depends for all Cabal files+ -- as otherwise cabal new-build cannot really work.+ --+ -- I.e. we don't want trigger unknown field warning+ <*> monoidalFieldAla "cpp-options" (alaList' NoCommaFSep Token') L.cppOptions+ <*> monoidalFieldAla "asm-options" (alaList' NoCommaFSep Token') L.asmOptions+ ^^^ availableSince CabalSpecV3_0 []+ <*> monoidalFieldAla "cmm-options" (alaList' NoCommaFSep Token') L.cmmOptions+ ^^^ availableSince CabalSpecV3_0 []+ <*> monoidalFieldAla "cc-options" (alaList' NoCommaFSep Token') L.ccOptions+ <*> monoidalFieldAla "cxx-options" (alaList' NoCommaFSep Token') L.cxxOptions+ ^^^ availableSince CabalSpecV2_2 []+ <*> monoidalFieldAla "ld-options" (alaList' NoCommaFSep Token') L.ldOptions+ <*> monoidalFieldAla "hsc2hs-options" (alaList' NoCommaFSep Token') L.hsc2hsOptions+ ^^^ availableSince CabalSpecV3_6 []+ <*> monoidalFieldAla "pkgconfig-depends" (alaList CommaFSep) L.pkgconfigDepends+ <*> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks+ <*> monoidalFieldAla "extra-framework-dirs" (alaList' FSep FilePathNT) L.extraFrameworkDirs+ <*> monoidalFieldAla "asm-sources" (alaList' VCat FilePathNT) L.asmSources+ ^^^ availableSince CabalSpecV3_0 []+ <*> monoidalFieldAla "cmm-sources" (alaList' VCat FilePathNT) L.cmmSources+ ^^^ availableSince CabalSpecV3_0 []+ <*> monoidalFieldAla "c-sources" (alaList' VCat FilePathNT) L.cSources+ <*> monoidalFieldAla "cxx-sources" (alaList' VCat FilePathNT) L.cxxSources+ ^^^ availableSince CabalSpecV2_2 []+ <*> monoidalFieldAla "js-sources" (alaList' VCat FilePathNT) L.jsSources+ <*> hsSourceDirsGrammar+ <*> monoidalFieldAla "other-modules" formatOtherModules L.otherModules+ <*> monoidalFieldAla "virtual-modules" (alaList' VCat MQuoted) L.virtualModules+ ^^^ availableSince CabalSpecV2_2 []+ <*> monoidalFieldAla "autogen-modules" (alaList' VCat MQuoted) L.autogenModules+ ^^^ availableSince CabalSpecV2_0 []+ <*> optionalFieldAla "default-language" MQuoted L.defaultLanguage+ ^^^ availableSince CabalSpecV1_10 Nothing+ <*> monoidalFieldAla "other-languages" (alaList' FSep MQuoted) L.otherLanguages+ ^^^ availableSince CabalSpecV1_10 []+ <*> monoidalFieldAla "default-extensions" (alaList' FSep MQuoted) L.defaultExtensions+ ^^^ availableSince CabalSpecV1_10 []+ <*> monoidalFieldAla "other-extensions" formatOtherExtensions L.otherExtensions+ ^^^ availableSinceWarn CabalSpecV1_10+ <*> monoidalFieldAla "extensions" (alaList' FSep MQuoted) L.oldExtensions+ ^^^ deprecatedSince CabalSpecV1_12+ "Please use 'default-extensions' or 'other-extensions' fields."+ ^^^ removedIn CabalSpecV3_0+ "Please use 'default-extensions' or 'other-extensions' fields."+ <*> monoidalFieldAla "extra-libraries" (alaList' VCat Token) L.extraLibs+ <*> monoidalFieldAla "extra-ghci-libraries" (alaList' VCat Token) L.extraGHCiLibs+ <*> monoidalFieldAla "extra-bundled-libraries" (alaList' VCat Token) L.extraBundledLibs+ <*> monoidalFieldAla "extra-library-flavours" (alaList' VCat Token) L.extraLibFlavours+ <*> monoidalFieldAla "extra-dynamic-library-flavours" (alaList' VCat Token) L.extraDynLibFlavours+ ^^^ availableSince CabalSpecV3_0 []+ <*> monoidalFieldAla "extra-lib-dirs" (alaList' FSep FilePathNT) L.extraLibDirs+ <*> monoidalFieldAla "include-dirs" (alaList' FSep FilePathNT) L.includeDirs+ <*> monoidalFieldAla "includes" (alaList' FSep FilePathNT) L.includes+ <*> monoidalFieldAla "autogen-includes" (alaList' FSep FilePathNT) L.autogenIncludes+ ^^^ availableSince CabalSpecV3_0 []+ <*> monoidalFieldAla "install-includes" (alaList' FSep FilePathNT) L.installIncludes+ <*> optionsFieldGrammar+ <*> profOptionsFieldGrammar+ <*> sharedOptionsFieldGrammar+ <*> pure mempty -- static-options ???+ <*> prefixedFields "x-" L.customFieldsBI+ <*> monoidalFieldAla "build-depends" formatDependencyList L.targetBuildDepends+ <*> monoidalFieldAla "mixins" formatMixinList L.mixins+ ^^^ availableSince CabalSpecV2_0 []+{-# SPECIALIZE buildInfoFieldGrammar :: ParsecFieldGrammar' BuildInfo #-}+{-# SPECIALIZE buildInfoFieldGrammar :: PrettyFieldGrammar' BuildInfo #-}++hsSourceDirsGrammar+ :: ( FieldGrammar c g, Applicative (g BuildInfo)+ , c (List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir))+ )+ => g BuildInfo [SymbolicPath PackageDir SourceDir]+hsSourceDirsGrammar = (++)+ <$> monoidalFieldAla "hs-source-dirs" formatHsSourceDirs L.hsSourceDirs+ <*> monoidalFieldAla "hs-source-dir" (alaList FSep) wrongLens+ --- https://github.com/haskell/cabal/commit/49e3cdae3bdf21b017ccd42e66670ca402e22b44+ ^^^ deprecatedSince CabalSpecV1_2 "Please use 'hs-source-dirs'"+ ^^^ removedIn CabalSpecV3_0 "Please use 'hs-source-dirs' field."+ where+ -- TODO: make pretty printer aware of CabalSpecVersion+ wrongLens :: Functor f => LensLike' f BuildInfo [SymbolicPath PackageDir SourceDir]+ wrongLens f bi = (\fps -> set L.hsSourceDirs fps bi) <$> f []++optionsFieldGrammar+ :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String))+ => g BuildInfo (PerCompilerFlavor [String])+optionsFieldGrammar = PerCompilerFlavor+ <$> monoidalFieldAla "ghc-options" (alaList' NoCommaFSep Token') (extract GHC)+ <*> monoidalFieldAla "ghcjs-options" (alaList' NoCommaFSep Token') (extract GHCJS)+ -- NOTE: Hugs, NHC and JHC are not supported anymore, but these+ -- fields are kept around so that we can still parse legacy .cabal+ -- files that have them.+ <* knownField "jhc-options"+ <* knownField "hugs-options"+ <* knownField "nhc98-options"+ where+ extract :: CompilerFlavor -> ALens' BuildInfo [String]+ extract flavor = L.options . lookupLens flavor++profOptionsFieldGrammar+ :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String))+ => g BuildInfo (PerCompilerFlavor [String])+profOptionsFieldGrammar = PerCompilerFlavor+ <$> monoidalFieldAla "ghc-prof-options" (alaList' NoCommaFSep Token') (extract GHC)+ <*> monoidalFieldAla "ghcjs-prof-options" (alaList' NoCommaFSep Token') (extract GHCJS)+ where+ extract :: CompilerFlavor -> ALens' BuildInfo [String]+ extract flavor = L.profOptions . lookupLens flavor++sharedOptionsFieldGrammar+ :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String))+ => g BuildInfo (PerCompilerFlavor [String])+sharedOptionsFieldGrammar = PerCompilerFlavor+ <$> monoidalFieldAla "ghc-shared-options" (alaList' NoCommaFSep Token') (extract GHC)+ <*> monoidalFieldAla "ghcjs-shared-options" (alaList' NoCommaFSep Token') (extract GHCJS)+ where+ extract :: CompilerFlavor -> ALens' BuildInfo [String]+ extract flavor = L.sharedOptions . lookupLens flavor++lookupLens :: (Functor f, Monoid v) => CompilerFlavor -> LensLike' f (PerCompilerFlavor v) v+lookupLens k f p@(PerCompilerFlavor ghc ghcjs)+ | k == GHC = (\n -> PerCompilerFlavor n ghcjs) <$> f ghc+ | k == GHCJS = (\n -> PerCompilerFlavor ghc n) <$> f ghcjs+ | otherwise = p <$ f mempty++-------------------------------------------------------------------------------+-- Flag+-------------------------------------------------------------------------------++flagFieldGrammar+ :: (FieldGrammar c g, Applicative (g PackageFlag))+ => FlagName -> g PackageFlag PackageFlag+flagFieldGrammar name = MkPackageFlag name+ <$> freeTextFieldDef "description" L.flagDescription+ <*> booleanFieldDef "default" L.flagDefault True+ <*> booleanFieldDef "manual" L.flagManual False+{-# SPECIALIZE flagFieldGrammar :: FlagName -> ParsecFieldGrammar' PackageFlag #-}+{-# SPECIALIZE flagFieldGrammar :: FlagName -> PrettyFieldGrammar' PackageFlag #-}++-------------------------------------------------------------------------------+-- SourceRepo+-------------------------------------------------------------------------------++sourceRepoFieldGrammar+ :: (FieldGrammar c g, Applicative (g SourceRepo), c (Identity RepoType), c Token, c FilePathNT)+ => RepoKind -> g SourceRepo SourceRepo+sourceRepoFieldGrammar kind = SourceRepo kind+ <$> optionalField "type" L.repoType+ <*> freeTextField "location" L.repoLocation+ <*> optionalFieldAla "module" Token L.repoModule+ <*> optionalFieldAla "branch" Token L.repoBranch+ <*> optionalFieldAla "tag" Token L.repoTag+ <*> optionalFieldAla "subdir" FilePathNT L.repoSubdir+{-# SPECIALIZE sourceRepoFieldGrammar :: RepoKind -> ParsecFieldGrammar' SourceRepo #-}+{-# SPECIALIZE sourceRepoFieldGrammar :: RepoKind -> PrettyFieldGrammar' SourceRepo #-}++-------------------------------------------------------------------------------+-- SetupBuildInfo+-------------------------------------------------------------------------------++setupBInfoFieldGrammar+ :: (FieldGrammar c g, Functor (g SetupBuildInfo), c (List CommaVCat (Identity Dependency) Dependency))+ => Bool -> g SetupBuildInfo SetupBuildInfo+setupBInfoFieldGrammar def = flip SetupBuildInfo def+ <$> monoidalFieldAla "setup-depends" (alaList CommaVCat) L.setupDepends+{-# SPECIALIZE setupBInfoFieldGrammar :: Bool -> ParsecFieldGrammar' SetupBuildInfo #-}+{-# SPECIALIZE setupBInfoFieldGrammar :: Bool -> PrettyFieldGrammar' SetupBuildInfo #-}++-------------------------------------------------------------------------------+-- Define how field values should be formatted for 'pretty'.+-------------------------------------------------------------------------------++formatDependencyList :: [Dependency] -> List CommaVCat (Identity Dependency) Dependency+formatDependencyList = alaList CommaVCat++formatMixinList :: [Mixin] -> List CommaVCat (Identity Mixin) Mixin+formatMixinList = alaList CommaVCat++formatExtraSourceFiles :: [FilePath] -> List VCat FilePathNT FilePath+formatExtraSourceFiles = alaList' VCat FilePathNT++formatExposedModules :: [ModuleName] -> List VCat (MQuoted ModuleName) ModuleName+formatExposedModules = alaList' VCat MQuoted++formatHsSourceDirs :: [SymbolicPath PackageDir SourceDir] -> List FSep (Identity (SymbolicPath PackageDir SourceDir)) (SymbolicPath PackageDir SourceDir)+formatHsSourceDirs = alaList FSep++formatOtherExtensions :: [Extension] -> List FSep (MQuoted Extension) Extension+formatOtherExtensions = alaList' FSep MQuoted++formatOtherModules :: [ModuleName] -> List VCat (MQuoted ModuleName) ModuleName+formatOtherModules = alaList' VCat MQuoted++-------------------------------------------------------------------------------+-- newtypes+-------------------------------------------------------------------------------++-- | Compat FilePath accepts empty file path,+-- but issues a warning.+--+-- There are simply too many (~1200) package definition files+--+-- @+-- license-file: ""+-- @+--+-- and+--+-- @+-- data-dir: ""+-- @+--+-- across Hackage to outrule them completely.+-- I suspect some of them are generated (e.g. formatted) by machine.+--+newtype CompatFilePath = CompatFilePath { getCompatFilePath :: FilePath } -- TODO: Change to use SymPath++instance Newtype String CompatFilePath++instance Parsec CompatFilePath where+ parsec = do+ token <- parsecToken+ if null token+ then do+ parsecWarning PWTEmptyFilePath "empty FilePath"+ return (CompatFilePath "")+ else return (CompatFilePath token)++instance Pretty CompatFilePath where+ pretty = showToken . getCompatFilePath++newtype CompatLicenseFile = CompatLicenseFile { getCompatLicenseFile :: [SymbolicPath PackageDir LicenseFile] }++instance Newtype [SymbolicPath PackageDir LicenseFile] CompatLicenseFile++-- TODO+instance Parsec CompatLicenseFile where+ parsec = emptyToken <|> CompatLicenseFile . unpack' (alaList FSep) <$> parsec+ where+ emptyToken = P.try $ do+ token <- parsecToken+ if null token+ then return (CompatLicenseFile [])+ else P.unexpected "non-empty-token"++instance Pretty CompatLicenseFile where+ pretty = pretty . pack' (alaList FSep) . getCompatLicenseFile++-------------------------------------------------------------------------------+-- vim syntax definitions+-------------------------------------------------------------------------------++-- | '_syntaxFieldNames' and '_syntaxExtensions'+-- are for generating VIM syntax file definitions.+--+_syntaxFieldNames :: IO ()+_syntaxFieldNames = sequence_+ [ BS8.putStrLn $ " \\ " <> n+ | n <- nub $ sort $ mconcat+ [ fieldGrammarKnownFieldList packageDescriptionFieldGrammar+ , fieldGrammarKnownFieldList $ libraryFieldGrammar LMainLibName+ , fieldGrammarKnownFieldList $ executableFieldGrammar "exe"+ , fieldGrammarKnownFieldList $ foreignLibFieldGrammar "flib"+ , fieldGrammarKnownFieldList testSuiteFieldGrammar+ , fieldGrammarKnownFieldList benchmarkFieldGrammar+ , fieldGrammarKnownFieldList $ flagFieldGrammar (error "flagname")+ , fieldGrammarKnownFieldList $ sourceRepoFieldGrammar (error "repokind")+ , fieldGrammarKnownFieldList $ setupBInfoFieldGrammar True+ ]+ ]++_syntaxExtensions :: IO ()+_syntaxExtensions = sequence_+ [ putStrLn $ " \\ " <> e+ | e <- ["Safe","Trustworthy","Unsafe"]+ ++ es+ ++ map ("No"++) es+ ]+ where+ es = nub $ sort+ [ prettyShow e+ | e <- [ minBound .. maxBound ]+ , e `notElem` [Safe,Unsafe,Trustworthy]+ ]
+ src/Distribution/PackageDescription/Parsec.hs view
@@ -0,0 +1,980 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.PackageDescription.Parsec+-- Copyright : Isaac Jones 2003-2005+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This defined parsers and partial pretty printers for the @.cabal@ format.++module Distribution.PackageDescription.Parsec (+ -- * Package descriptions+ readGenericPackageDescription,+ parseGenericPackageDescription,+ parseGenericPackageDescriptionMaybe,++ -- ** Parsing+ ParseResult,+ runParseResult,++ -- * New-style spec-version+ scanSpecVersion,++ -- ** Supplementary build information+ readHookedBuildInfo,+ parseHookedBuildInfo,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Control.Monad.State.Strict (StateT, execStateT)+import Control.Monad.Trans.Class (lift)+import Distribution.CabalSpecVersion+import Distribution.Compat.Lens+import Distribution.FieldGrammar+import Distribution.FieldGrammar.Parsec (NamelessField (..))+import Distribution.Fields.ConfVar (parseConditionConfVar)+import Distribution.Fields.Field (FieldName, getName)+import Distribution.Fields.LexerMonad (LexWarning, toPWarnings)+import Distribution.Fields.Parser+import Distribution.Fields.ParseResult+import Distribution.PackageDescription+import Distribution.PackageDescription.Configuration (freeVars, transformAllBuildInfos)+import Distribution.PackageDescription.FieldGrammar+import Distribution.PackageDescription.Quirks (patchQuirks)+import Distribution.Parsec (parsec, simpleParsecBS)+import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS)+import Distribution.Parsec.Position (Position (..), zeroPos)+import Distribution.Parsec.Warning (PWarnType (..))+import Distribution.Pretty (prettyShow)+import Distribution.Simple.Utils (fromUTF8BS, toUTF8BS)+import Distribution.Utils.Generic (breakMaybe, unfoldrM, validateUTF8)+import Distribution.Verbosity (Verbosity)+import Distribution.Version (Version, mkVersion, versionNumbers)++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS8+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import qualified Distribution.Compat.Newtype as Newtype+import qualified Distribution.Compat.NonEmptySet as NES+import qualified Distribution.Types.BuildInfo.Lens as L+import qualified Distribution.Types.Executable.Lens as L+import qualified Distribution.Types.ForeignLib.Lens as L+import qualified Distribution.Types.GenericPackageDescription.Lens as L+import qualified Distribution.Types.PackageDescription.Lens as L+import qualified Distribution.Types.SetupBuildInfo.Lens as L+import qualified Text.Parsec as P++-- ---------------------------------------------------------------+-- Parsing+-- ---------------------------------------------------------------++-- | Parse the given package file.+readGenericPackageDescription :: Verbosity -> FilePath -> IO GenericPackageDescription+readGenericPackageDescription = readAndParseFile parseGenericPackageDescription++------------------------------------------------------------------------------+-- | Parses the given file into a 'GenericPackageDescription'.+--+-- In Cabal 1.2 the syntax for package descriptions was changed to a format+-- with sections and possibly indented property descriptions.+--+parseGenericPackageDescription :: BS.ByteString -> ParseResult GenericPackageDescription+parseGenericPackageDescription bs = do+ -- set scanned version+ setCabalSpecVersion ver++ csv <- case ver of+ -- if we get too new version, fail right away+ Just v -> case cabalSpecFromVersionDigits (versionNumbers v) of+ Just csv -> return (Just csv)+ Nothing -> parseFatalFailure zeroPos $+ "Unsupported cabal-version " ++ prettyShow v ++ ". See https://github.com/haskell/cabal/issues/4899."+ _ -> pure Nothing++ case readFields' bs'' of+ Right (fs, lexWarnings) -> do+ when patched $+ parseWarning zeroPos PWTQuirkyCabalFile "Legacy cabal file"+ -- UTF8 is validated in a prepass step, afterwards parsing is lenient.+ parseGenericPackageDescription' csv lexWarnings invalidUtf8 fs+ -- TODO: better marshalling of errors+ Left perr -> parseFatalFailure pos (show perr) where+ ppos = P.errorPos perr+ pos = Position (P.sourceLine ppos) (P.sourceColumn ppos)+ where+ (patched, bs') = patchQuirks bs+ ver = scanSpecVersion bs'++ invalidUtf8 = validateUTF8 bs'++ -- if there are invalid utf8 characters, we make the bytestring valid.+ bs'' = case invalidUtf8 of+ Nothing -> bs'+ Just _ -> toUTF8BS (fromUTF8BS bs')+++-- | 'Maybe' variant of 'parseGenericPackageDescription'+parseGenericPackageDescriptionMaybe :: BS.ByteString -> Maybe GenericPackageDescription+parseGenericPackageDescriptionMaybe =+ either (const Nothing) Just . snd . runParseResult . parseGenericPackageDescription++fieldlinesToBS :: [FieldLine ann] -> BS.ByteString+fieldlinesToBS = BS.intercalate "\n" . map (\(FieldLine _ bs) -> bs)++-- Monad in which sections are parsed+type SectionParser = StateT SectionS ParseResult++-- | State of section parser+data SectionS = SectionS+ { _stateGpd :: !GenericPackageDescription+ , _stateCommonStanzas :: !(Map String CondTreeBuildInfo)+ }++stateGpd :: Lens' SectionS GenericPackageDescription+stateGpd f (SectionS gpd cs) = (\x -> SectionS x cs) <$> f gpd+{-# INLINE stateGpd #-}++stateCommonStanzas :: Lens' SectionS (Map String CondTreeBuildInfo)+stateCommonStanzas f (SectionS gpd cs) = SectionS gpd <$> f cs+{-# INLINE stateCommonStanzas #-}++-- Note [Accumulating parser]+--+-- This parser has two "states":+-- * first we parse fields of PackageDescription+-- * then we parse sections (libraries, executables, etc)+parseGenericPackageDescription'+ :: Maybe CabalSpecVersion+ -> [LexWarning]+ -> Maybe Int+ -> [Field Position]+ -> ParseResult GenericPackageDescription+parseGenericPackageDescription' scannedVer lexWarnings utf8WarnPos fs = do+ parseWarnings (toPWarnings lexWarnings)+ for_ utf8WarnPos $ \pos ->+ parseWarning zeroPos PWTUTF $ "UTF8 encoding problem at byte offset " ++ show pos+ let (syntax, fs') = sectionizeFields fs+ let (fields, sectionFields) = takeFields fs'++ -- cabal-version+ specVer <- case scannedVer of+ Just v -> return v+ Nothing -> case Map.lookup "cabal-version" fields >>= safeLast of+ Nothing -> return CabalSpecV1_0+ Just (MkNamelessField pos fls) -> do+ -- version will be parsed twice, therefore we parse without warnings.+ v <- withoutWarnings $+ Newtype.unpack' SpecVersion <$>+ -- Use version with || and && but before addition of ^>= and removal of -any+ runFieldParser pos parsec CabalSpecV1_24 fls++ -- if it were at the beginning, scanner would found it+ when (v >= CabalSpecV2_2) $ parseFailure pos $+ "cabal-version should be at the beginning of the file starting with spec version 2.2. " +++ "See https://github.com/haskell/cabal/issues/4899"++ return v++ -- reset cabal version, it might not be set+ let specVer' = mkVersion (cabalSpecToVersionDigits specVer)+ setCabalSpecVersion (Just specVer')++ -- Package description+ pd <- parseFieldGrammar specVer fields packageDescriptionFieldGrammar++ -- Check that scanned and parsed versions match.+ unless (specVer == specVersion pd) $ parseFailure zeroPos $+ "Scanned and parsed cabal-versions don't match " +++ prettyShow (SpecVersion specVer) ++ " /= " ++ prettyShow (SpecVersion (specVersion pd))++ maybeWarnCabalVersion syntax pd++ -- Sections+ let gpd = emptyGenericPackageDescription+ & L.packageDescription .~ pd+ gpd1 <- view stateGpd <$> execStateT (goSections specVer sectionFields) (SectionS gpd Map.empty)++ let gpd2 = postProcessInternalDeps specVer gpd1+ checkForUndefinedFlags gpd2+ checkForUndefinedCustomSetup gpd2+ -- See nothunks test, without this deepseq we get (at least):+ -- Thunk in ThunkInfo {thunkContext = ["PackageIdentifier","PackageDescription","GenericPackageDescription"]}+ --+ -- TODO: re-benchmark, whether `deepseq` is important (both cabal-benchmarks and solver-benchmarks)+ -- TODO: remove the need for deepseq if `deepseq` in fact matters+ -- NOTE: IIRC it does affect (maximal) memory usage, which causes less GC pressure+ gpd2 `deepseq` return gpd2+ where+ safeLast :: [a] -> Maybe a+ safeLast = listToMaybe . reverse++ newSyntaxVersion :: CabalSpecVersion+ newSyntaxVersion = CabalSpecV1_2++ maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult ()+ maybeWarnCabalVersion syntax pkg+ | syntax == NewSyntax && specVersion pkg < newSyntaxVersion+ = parseWarning zeroPos PWTNewSyntax $+ "A package using section syntax must specify at least\n"+ ++ "'cabal-version: >= 1.2'."++ maybeWarnCabalVersion syntax pkg+ | syntax == OldSyntax && specVersion pkg >= newSyntaxVersion+ = parseWarning zeroPos PWTOldSyntax $+ "A package using 'cabal-version: "+ ++ prettyShow (SpecVersion (specVersion pkg))+ ++ "' must use section syntax. See the Cabal user guide for details."++ maybeWarnCabalVersion _ _ = return ()++goSections :: CabalSpecVersion -> [Field Position] -> SectionParser ()+goSections specVer = traverse_ process+ where+ process (Field (Name pos name) _) =+ lift $ parseWarning pos PWTTrailingFields $+ "Ignoring trailing fields after sections: " ++ show name+ process (Section name args secFields) =+ parseSection name args secFields++ snoc x xs = xs ++ [x]++ hasCommonStanzas = specHasCommonStanzas specVer++ -- we need signature, because this is polymorphic, but not-closed+ parseCondTree'+ :: L.HasBuildInfo a+ => ParsecFieldGrammar' a -- ^ grammar+ -> (BuildInfo -> a)+ -> Map String CondTreeBuildInfo -- ^ common stanzas+ -> [Field Position]+ -> ParseResult (CondTree ConfVar [Dependency] a)+ parseCondTree' = parseCondTreeWithCommonStanzas specVer++ parseSection :: Name Position -> [SectionArg Position] -> [Field Position] -> SectionParser ()+ parseSection (Name pos name) args fields+ | hasCommonStanzas == NoCommonStanzas, name == "common" = lift $ do+ parseWarning pos PWTUnknownSection $ "Ignoring section: common. You should set cabal-version: 2.2 or larger to use common stanzas."++ | name == "common" = do+ commonStanzas <- use stateCommonStanzas+ name' <- lift $ parseCommonName pos args+ biTree <- lift $ parseCondTree' buildInfoFieldGrammar id commonStanzas fields++ case Map.lookup name' commonStanzas of+ Nothing -> stateCommonStanzas .= Map.insert name' biTree commonStanzas+ Just _ -> lift $ parseFailure pos $+ "Duplicate common stanza: " ++ name'++ | name == "library" && null args = do+ prev <- use $ stateGpd . L.condLibrary+ when (isJust prev) $ lift $ parseFailure pos $+ "Multiple main libraries; have you forgotten to specify a name for an internal library?"++ commonStanzas <- use stateCommonStanzas+ let name'' = LMainLibName+ lib <- lift $ parseCondTree' (libraryFieldGrammar name'') (libraryFromBuildInfo name'') commonStanzas fields+ --+ -- TODO check that not set+ stateGpd . L.condLibrary ?= lib++ -- Sublibraries+ -- TODO: check cabal-version+ | name == "library" = do+ commonStanzas <- use stateCommonStanzas+ name' <- parseUnqualComponentName pos args+ let name'' = LSubLibName name'+ lib <- lift $ parseCondTree' (libraryFieldGrammar name'') (libraryFromBuildInfo name'') commonStanzas fields+ -- TODO check duplicate name here?+ stateGpd . L.condSubLibraries %= snoc (name', lib)++ -- TODO: check cabal-version+ | name == "foreign-library" = do+ commonStanzas <- use stateCommonStanzas+ name' <- parseUnqualComponentName pos args+ flib <- lift $ parseCondTree' (foreignLibFieldGrammar name') (fromBuildInfo' name') commonStanzas fields++ let hasType ts = foreignLibType ts /= foreignLibType mempty+ unless (onAllBranches hasType flib) $ lift $ parseFailure pos $ concat+ [ "Foreign library " ++ show (prettyShow name')+ , " is missing required field \"type\" or the field "+ , "is not present in all conditional branches. The "+ , "available test types are: "+ , intercalate ", " (map prettyShow knownForeignLibTypes)+ ]++ -- TODO check duplicate name here?+ stateGpd . L.condForeignLibs %= snoc (name', flib)++ | name == "executable" = do+ commonStanzas <- use stateCommonStanzas+ name' <- parseUnqualComponentName pos args+ exe <- lift $ parseCondTree' (executableFieldGrammar name') (fromBuildInfo' name') commonStanzas fields+ -- TODO check duplicate name here?+ stateGpd . L.condExecutables %= snoc (name', exe)++ | name == "test-suite" = do+ commonStanzas <- use stateCommonStanzas+ name' <- parseUnqualComponentName pos args+ testStanza <- lift $ parseCondTree' testSuiteFieldGrammar (fromBuildInfo' name') commonStanzas fields+ testSuite <- lift $ traverse (validateTestSuite pos) testStanza++ let hasType ts = testInterface ts /= testInterface mempty+ unless (onAllBranches hasType testSuite) $ lift $ parseFailure pos $ concat+ [ "Test suite " ++ show (prettyShow name')+ , " is missing required field \"type\" or the field "+ , "is not present in all conditional branches. The "+ , "available test types are: "+ , intercalate ", " (map prettyShow knownTestTypes)+ ]++ -- TODO check duplicate name here?+ stateGpd . L.condTestSuites %= snoc (name', testSuite)++ | name == "benchmark" = do+ commonStanzas <- use stateCommonStanzas+ name' <- parseUnqualComponentName pos args+ benchStanza <- lift $ parseCondTree' benchmarkFieldGrammar (fromBuildInfo' name') commonStanzas fields+ bench <- lift $ traverse (validateBenchmark pos) benchStanza++ let hasType ts = benchmarkInterface ts /= benchmarkInterface mempty+ unless (onAllBranches hasType bench) $ lift $ parseFailure pos $ concat+ [ "Benchmark " ++ show (prettyShow name')+ , " is missing required field \"type\" or the field "+ , "is not present in all conditional branches. The "+ , "available benchmark types are: "+ , intercalate ", " (map prettyShow knownBenchmarkTypes)+ ]++ -- TODO check duplicate name here?+ stateGpd . L.condBenchmarks %= snoc (name', bench)++ | name == "flag" = do+ name' <- parseNameBS pos args+ name'' <- lift $ runFieldParser' [pos] parsec specVer (fieldLineStreamFromBS name') `recoverWith` mkFlagName ""+ flag <- lift $ parseFields specVer fields (flagFieldGrammar name'')+ -- Check default flag+ stateGpd . L.genPackageFlags %= snoc flag++ | name == "custom-setup" && null args = do+ sbi <- lift $ parseFields specVer fields (setupBInfoFieldGrammar False)+ stateGpd . L.packageDescription . L.setupBuildInfo ?= sbi++ | name == "source-repository" = do+ kind <- lift $ case args of+ [SecArgName spos secName] ->+ runFieldParser' [spos] parsec specVer (fieldLineStreamFromBS secName) `recoverWith` RepoHead+ [] -> do+ parseFailure pos "'source-repository' requires exactly one argument"+ pure RepoHead+ _ -> do+ parseFailure pos $ "Invalid source-repository kind " ++ show args+ pure RepoHead++ sr <- lift $ parseFields specVer fields (sourceRepoFieldGrammar kind)+ stateGpd . L.packageDescription . L.sourceRepos %= snoc sr++ | otherwise = lift $+ parseWarning pos PWTUnknownSection $ "Ignoring section: " ++ show name++parseName :: Position -> [SectionArg Position] -> SectionParser String+parseName pos args = fromUTF8BS <$> parseNameBS pos args++parseNameBS :: Position -> [SectionArg Position] -> SectionParser BS.ByteString+-- TODO: use strict parser+parseNameBS pos args = case args of+ [SecArgName _pos secName] ->+ pure secName+ [SecArgStr _pos secName] ->+ pure secName+ [] -> do+ lift $ parseFailure pos "name required"+ pure ""+ _ -> do+ -- TODO: pretty print args+ lift $ parseFailure pos $ "Invalid name " ++ show args+ pure ""++parseCommonName :: Position -> [SectionArg Position] -> ParseResult String+parseCommonName pos args = case args of+ [SecArgName _pos secName] ->+ pure $ fromUTF8BS secName+ [SecArgStr _pos secName] ->+ pure $ fromUTF8BS secName+ [] -> do+ parseFailure pos $ "name required"+ pure ""+ _ -> do+ -- TODO: pretty print args+ parseFailure pos $ "Invalid name " ++ show args+ pure ""++-- TODO: avoid conversion to 'String'.+parseUnqualComponentName :: Position -> [SectionArg Position] -> SectionParser UnqualComponentName+parseUnqualComponentName pos args = mkUnqualComponentName <$> parseName pos args++-- | Parse a non-recursive list of fields.+parseFields+ :: CabalSpecVersion+ -> [Field Position] -- ^ fields to be parsed+ -> ParsecFieldGrammar' a+ -> ParseResult a+parseFields v fields grammar = do+ let (fs0, ss) = partitionFields fields+ traverse_ (traverse_ warnInvalidSubsection) ss+ parseFieldGrammar v fs0 grammar++warnInvalidSubsection :: Section Position -> ParseResult ()+warnInvalidSubsection (MkSection (Name pos name) _ _) =+ void $ parseFailure pos $ "invalid subsection " ++ show name++parseCondTree+ :: forall a. L.HasBuildInfo a+ => CabalSpecVersion+ -> HasElif -- ^ accept @elif@+ -> ParsecFieldGrammar' a -- ^ grammar+ -> Map String CondTreeBuildInfo -- ^ common stanzas+ -> (BuildInfo -> a) -- ^ constructor from buildInfo+ -> (a -> [Dependency]) -- ^ condition extractor+ -> [Field Position]+ -> ParseResult (CondTree ConfVar [Dependency] a)+parseCondTree v hasElif grammar commonStanzas fromBuildInfo cond = go+ where+ go fields0 = do+ (fields, endo) <-+ if v >= CabalSpecV3_0+ then processImports v fromBuildInfo commonStanzas fields0+ else traverse (warnImport v) fields0 >>= \fields1 -> return (catMaybes fields1, id)++ let (fs, ss) = partitionFields fields+ x <- parseFieldGrammar v fs grammar+ branches <- concat <$> traverse parseIfs ss+ return $ endo $ CondNode x (cond x) branches++ parseIfs :: [Section Position] -> ParseResult [CondBranch ConfVar [Dependency] a]+ parseIfs [] = return []+ parseIfs (MkSection (Name _ name) test fields : sections) | name == "if" = do+ test' <- parseConditionConfVar test+ fields' <- go fields+ (elseFields, sections') <- parseElseIfs sections+ return (CondBranch test' fields' elseFields : sections')+ parseIfs (MkSection (Name pos name) _ _ : sections) = do+ parseWarning pos PWTInvalidSubsection $ "invalid subsection " ++ show name+ parseIfs sections++ parseElseIfs+ :: [Section Position]+ -> ParseResult (Maybe (CondTree ConfVar [Dependency] a), [CondBranch ConfVar [Dependency] a])+ parseElseIfs [] = return (Nothing, [])+ parseElseIfs (MkSection (Name pos name) args fields : sections) | name == "else" = do+ unless (null args) $+ parseFailure pos $ "`else` section has section arguments " ++ show args+ elseFields <- go fields+ sections' <- parseIfs sections+ return (Just elseFields, sections')++ parseElseIfs (MkSection (Name _ name) test fields : sections) | hasElif == HasElif, name == "elif" = do+ test' <- parseConditionConfVar test+ fields' <- go fields+ (elseFields, sections') <- parseElseIfs sections+ -- we parse an empty 'Fields', to get empty value for a node+ a <- parseFieldGrammar v mempty grammar+ return (Just $ CondNode a (cond a) [CondBranch test' fields' elseFields], sections')++ parseElseIfs (MkSection (Name pos name) _ _ : sections) | name == "elif" = do+ parseWarning pos PWTInvalidSubsection $ "invalid subsection \"elif\". You should set cabal-version: 2.2 or larger to use elif-conditionals."+ (,) Nothing <$> parseIfs sections++ parseElseIfs sections = (,) Nothing <$> parseIfs sections++{- Note [Accumulating parser]++Note: Outdated a bit++In there parser, @'FieldDescr' a@ is transformed into @Map FieldName (a ->+FieldParser a)@. The weird value is used because we accumulate structure of+@a@ by folding over the fields. There are various reasons for that:++* Almost all fields are optional++* This is simple approach so declarative bi-directional format (parsing and+printing) of structure could be specified (list of @'FieldDescr' a@)++* There are surface syntax fields corresponding to single field in the file:+ @license-file@ and @license-files@++* This is quite safe approach.++When/if we re-implement the parser to support formatting preservging roundtrip+with new AST, this all need to be rewritten.+-}++-------------------------------------------------------------------------------+-- Common stanzas+-------------------------------------------------------------------------------++-- $commonStanzas+--+-- [Note: Common stanzas]+--+-- In Cabal 2.2 we support simple common stanzas:+--+-- * Commons stanzas define 'BuildInfo'+--+-- * import "fields" can only occur at top of other stanzas (think: imports)+--+-- In particular __there aren't__+--+-- * implicit stanzas+--+-- * More specific common stanzas (executable, test-suite).+--+--+-- The approach uses the fact that 'BuildInfo' is a 'Monoid':+--+-- @+-- mergeCommonStanza' :: HasBuildInfo comp => BuildInfo -> comp -> comp+-- mergeCommonStanza' bi = over L.BuildInfo (bi <>)+-- @+--+-- Real 'mergeCommonStanza' is more complicated as we have to deal with+-- conditional trees.+--+-- The approach is simple, and have good properties:+--+-- * Common stanzas are parsed exactly once, even if not-used. Thus we report errors in them.+--+type CondTreeBuildInfo = CondTree ConfVar [Dependency] BuildInfo++-- | Create @a@ from 'BuildInfo'.+-- This class is used to implement common stanza parsing.+--+-- Law: @view buildInfo . fromBuildInfo = id@+--+-- This takes name, as 'FieldGrammar's take names too.+class L.HasBuildInfo a => FromBuildInfo a where+ fromBuildInfo' :: UnqualComponentName -> BuildInfo -> a++libraryFromBuildInfo :: LibraryName -> BuildInfo -> Library+libraryFromBuildInfo n bi = emptyLibrary+ { libName = n+ , libVisibility = case n of+ LMainLibName -> LibraryVisibilityPublic+ LSubLibName _ -> LibraryVisibilityPrivate+ , libBuildInfo = bi+ }++instance FromBuildInfo BuildInfo where fromBuildInfo' _ = id+instance FromBuildInfo ForeignLib where fromBuildInfo' n bi = set L.foreignLibName n $ set L.buildInfo bi emptyForeignLib+instance FromBuildInfo Executable where fromBuildInfo' n bi = set L.exeName n $ set L.buildInfo bi emptyExecutable++instance FromBuildInfo TestSuiteStanza where+ fromBuildInfo' _ bi = TestSuiteStanza Nothing Nothing Nothing bi++instance FromBuildInfo BenchmarkStanza where+ fromBuildInfo' _ bi = BenchmarkStanza Nothing Nothing Nothing bi++parseCondTreeWithCommonStanzas+ :: forall a. L.HasBuildInfo a+ => CabalSpecVersion+ -> ParsecFieldGrammar' a -- ^ grammar+ -> (BuildInfo -> a) -- ^ construct fromBuildInfo+ -> Map String CondTreeBuildInfo -- ^ common stanzas+ -> [Field Position]+ -> ParseResult (CondTree ConfVar [Dependency] a)+parseCondTreeWithCommonStanzas v grammar fromBuildInfo commonStanzas fields = do+ (fields', endo) <- processImports v fromBuildInfo commonStanzas fields+ x <- parseCondTree v hasElif grammar commonStanzas fromBuildInfo (view L.targetBuildDepends) fields'+ return (endo x)+ where+ hasElif = specHasElif v++processImports+ :: forall a. L.HasBuildInfo a+ => CabalSpecVersion+ -> (BuildInfo -> a) -- ^ construct fromBuildInfo+ -> Map String CondTreeBuildInfo -- ^ common stanzas+ -> [Field Position]+ -> ParseResult ([Field Position], CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] a)+processImports v fromBuildInfo commonStanzas = go []+ where+ hasCommonStanzas = specHasCommonStanzas v++ getList' :: List CommaFSep Token String -> [String]+ getList' = Newtype.unpack++ go acc (Field (Name pos name) _ : fields) | name == "import", hasCommonStanzas == NoCommonStanzas = do+ parseWarning pos PWTUnknownField "Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas"+ go acc fields+ -- supported:+ go acc (Field (Name pos name) fls : fields) | name == "import" = do+ names <- getList' <$> runFieldParser pos parsec v fls+ names' <- for names $ \commonName ->+ case Map.lookup commonName commonStanzas of+ Nothing -> do+ parseFailure pos $ "Undefined common stanza imported: " ++ commonName+ pure Nothing+ Just commonTree ->+ pure (Just commonTree)++ go (acc ++ catMaybes names') fields++ -- parse actual CondTree+ go acc fields = do+ fields' <- catMaybes <$> traverse (warnImport v) fields+ pure $ (fields', \x -> foldr (mergeCommonStanza fromBuildInfo) x acc)++-- | Warn on "import" fields, also map to Maybe, so errorneous fields can be filtered+warnImport :: CabalSpecVersion -> Field Position -> ParseResult (Maybe (Field Position))+warnImport v (Field (Name pos name) _) | name == "import" = do+ if specHasCommonStanzas v == NoCommonStanzas+ then parseWarning pos PWTUnknownField "Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas"+ else parseWarning pos PWTUnknownField "Unknown field: import. Common stanza imports should be at the top of the enclosing section"+ return Nothing+warnImport _ f = pure (Just f)++mergeCommonStanza+ :: L.HasBuildInfo a+ => (BuildInfo -> a)+ -> CondTree ConfVar [Dependency] BuildInfo+ -> CondTree ConfVar [Dependency] a+ -> CondTree ConfVar [Dependency] a+mergeCommonStanza fromBuildInfo (CondNode bi _ bis) (CondNode x _ cs) =+ CondNode x' (x' ^. L.targetBuildDepends) cs'+ where+ -- new value is old value with buildInfo field _prepended_.+ x' = x & L.buildInfo %~ (bi <>)++ -- tree components are appended together.+ cs' = map (fmap fromBuildInfo) bis ++ cs++-------------------------------------------------------------------------------+-- Branches+-------------------------------------------------------------------------------++-- Check that a property holds on all branches of a condition tree+onAllBranches :: forall v c a. Monoid a => (a -> Bool) -> CondTree v c a -> Bool+onAllBranches p = go mempty+ where+ -- If the current level of the tree satisfies the property, then we are+ -- done. If not, then one of the conditional branches below the current node+ -- must satisfy it. Each node may have multiple immediate children; we only+ -- one need one to satisfy the property because the configure step uses+ -- 'mappend' to join together the results of flag resolution.+ go :: a -> CondTree v c a -> Bool+ go acc ct = let acc' = acc `mappend` condTreeData ct+ in p acc' || any (goBranch acc') (condTreeComponents ct)++ -- Both the 'true' and the 'false' block must satisfy the property.+ goBranch :: a -> CondBranch v c a -> Bool+ goBranch _ (CondBranch _ _ Nothing) = False+ goBranch acc (CondBranch _ t (Just e)) = go acc t && go acc e++-------------------------------------------------------------------------------+-- Post parsing checks+-------------------------------------------------------------------------------++-- | Check that we +--+-- * don't use undefined flags (very bad)+-- * define flags which are unused (just bad)+--+checkForUndefinedFlags :: GenericPackageDescription -> ParseResult ()+checkForUndefinedFlags gpd = do+ let definedFlags, usedFlags :: Set.Set FlagName+ definedFlags = toSetOf (L.genPackageFlags . traverse . getting flagName) gpd+ usedFlags = getConst $ L.allCondTrees f gpd++ -- Note: we can check for defined, but unused flags here too.+ unless (usedFlags `Set.isSubsetOf` definedFlags) $ parseFailure zeroPos $+ "These flags are used without having been defined: " +++ intercalate ", " [ unFlagName fn | fn <- Set.toList $ usedFlags `Set.difference` definedFlags ]+ where+ f :: CondTree ConfVar c a -> Const (Set.Set FlagName) (CondTree ConfVar c a)+ f ct = Const (Set.fromList (freeVars ct))++-- | Since @cabal-version: 1.24@ one can specify @custom-setup@.+-- Let us require it.+--+checkForUndefinedCustomSetup :: GenericPackageDescription -> ParseResult ()+checkForUndefinedCustomSetup gpd = do+ let pd = packageDescription gpd+ let csv = specVersion pd++ when (buildType pd == Custom && isNothing (setupBuildInfo pd)) $+ when (csv >= CabalSpecV1_24) $ parseFailure zeroPos $+ "Since cabal-version: 1.24 specifying custom-setup section is mandatory"++-------------------------------------------------------------------------------+-- Post processing of internal dependencies+-------------------------------------------------------------------------------++-- Note [Dependencies on sublibraries]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- This is solution to https://github.com/haskell/cabal/issues/6083+--+-- Before 'cabal-version: 3.0' we didn't have a syntax specially+-- for referring to internal libraries. Internal library names+-- shadowed the outside ones.+--+-- Since 'cabal-version: 3.0' we have ability to write+--+-- build-depends: some-package:its-sub-lib >=1.2.3+--+-- This allows us to refer also to local packages by `this-package:sublib`.+-- So since 'cabal-version: 3.4' to refer to *any*+-- sublibrary we must use the two part syntax. Here's small table:+--+-- | pre-3.4 | 3.4 and after |+-- ------------------|---------------------|-------------------------------|+-- pkg-name | may refer to sublib | always refers to external pkg |+-- pkg-name:sublib | refers to sublib | refers to sublib |+-- pkg-name:pkg-name | may refer to sublib | always refers to external pkg |+--+-- In pre-3.4 case, if a package 'this-pkg' has a sublibrary 'pkg-name',+-- all dependency definitions will refer to that sublirary.+--+-- In 3.4 and after case, 'pkg-name' will always refer to external package,+-- and to use internal library you have to say 'this-pkg:pkg-name'.+--+-- In summary, In 3.4 and after, the internal names don't shadow,+-- as there is an explicit syntax to refer to them,+-- i.e. what you write is what you get;+-- For pre-3.4 we post-process the file.+--+-- Similarly, we process mixins.+-- See https://github.com/haskell/cabal/issues/6281+--++postProcessInternalDeps :: CabalSpecVersion -> GenericPackageDescription -> GenericPackageDescription+postProcessInternalDeps specVer gpd+ | specVer >= CabalSpecV3_4 = gpd+ | otherwise = transformAllBuildInfos transformBI transformSBI gpd+ where+ transformBI :: BuildInfo -> BuildInfo+ transformBI+ = over L.targetBuildDepends (concatMap transformD)+ . over L.mixins (map transformM)++ transformSBI :: SetupBuildInfo -> SetupBuildInfo+ transformSBI = over L.setupDepends (concatMap transformD)++ transformD :: Dependency -> [Dependency]+ transformD (Dependency pn vr ln)+ | uqn `Set.member` internalLibs+ , LMainLibName `NES.member` ln+ = case NES.delete LMainLibName ln of+ Nothing -> [dep]+ Just ln' -> [dep, Dependency pn vr ln']+ where+ uqn = packageNameToUnqualComponentName pn+ dep = Dependency thisPn vr (NES.singleton (LSubLibName uqn))++ transformD d = [d]++ transformM :: Mixin -> Mixin+ transformM (Mixin pn LMainLibName incl)+ | uqn `Set.member` internalLibs+ = mkMixin thisPn (LSubLibName uqn) incl+ where+ uqn = packageNameToUnqualComponentName pn++ transformM m = m++ thisPn :: PackageName+ thisPn = pkgName (package (packageDescription gpd))++ internalLibs :: Set UnqualComponentName+ internalLibs = Set.fromList+ [ n+ | (n, _) <- condSubLibraries gpd+ ]++-------------------------------------------------------------------------------+-- Old syntax+-------------------------------------------------------------------------------++-- TODO: move to own module++-- | "Sectionize" an old-style Cabal file. A sectionized file has:+--+-- * all global fields at the beginning, followed by+--+-- * all flag declarations, followed by+--+-- * an optional library section, and an arbitrary number of executable+-- sections (in any order).+--+-- The current implementation just gathers all library-specific fields+-- in a library section and wraps all executable stanzas in an executable+-- section.+sectionizeFields :: [Field ann] -> (Syntax, [Field ann])+sectionizeFields fs = case classifyFields fs of+ Just fields -> (OldSyntax, convert fields)+ Nothing -> (NewSyntax, fs)+ where+ -- return 'Just' if all fields are simple fields+ classifyFields :: [Field ann] -> Maybe [(Name ann, [FieldLine ann])]+ classifyFields = traverse f+ where+ f (Field name fieldlines) = Just (name, fieldlines)+ f _ = Nothing++ trim = BS.dropWhile isSpace' . BS.reverse . BS.dropWhile isSpace' . BS.reverse+ isSpace' = (== 32)++ convert :: [(Name ann, [FieldLine ann])] -> [Field ann]+ convert fields =+ let+ toField (name, ls) = Field name ls+ -- "build-depends" is a local field now. To be backwards+ -- compatible, we still allow it as a global field in old-style+ -- package description files and translate it to a local field by+ -- adding it to every non-empty section+ (hdr0, exes0) = break ((=="executable") . getName . fst) fields+ (hdr, libfs0) = partition (not . (`elem` libFieldNames) . getName . fst) hdr0++ (deps, libfs) = partition ((== "build-depends") . getName . fst)+ libfs0++ exes = unfoldr toExe exes0+ toExe [] = Nothing+ toExe ((Name pos n, ls) : r)+ | n == "executable" =+ let (efs, r') = break ((== "executable") . getName . fst) r+ in Just (Section (Name pos "executable") [SecArgName pos $ trim $ fieldlinesToBS ls] (map toField $ deps ++ efs), r')+ toExe _ = error "unexpected input to 'toExe'"++ lib = case libfs of+ [] -> []+ ((Name pos _, _) : _) ->+ [Section (Name pos "library") [] (map toField $ deps ++ libfs)]++ in map toField hdr ++ lib ++ exes++-- | See 'sectionizeFields'.+data Syntax = OldSyntax | NewSyntax+ deriving (Eq, Show)++-- TODO:+libFieldNames :: [FieldName]+libFieldNames = fieldGrammarKnownFieldList (libraryFieldGrammar LMainLibName)++-------------------------------------------------------------------------------+-- Suplementary build information+-------------------------------------------------------------------------------++readHookedBuildInfo :: Verbosity -> FilePath -> IO HookedBuildInfo+readHookedBuildInfo = readAndParseFile parseHookedBuildInfo++parseHookedBuildInfo :: BS.ByteString -> ParseResult HookedBuildInfo+parseHookedBuildInfo bs = case readFields' bs of+ Right (fs, lexWarnings) -> do+ parseHookedBuildInfo' lexWarnings fs+ -- TODO: better marshalling of errors+ Left perr -> parseFatalFailure zeroPos (show perr)++parseHookedBuildInfo'+ :: [LexWarning]+ -> [Field Position]+ -> ParseResult HookedBuildInfo+parseHookedBuildInfo' lexWarnings fs = do+ parseWarnings (toPWarnings lexWarnings)+ (mLibFields, exes) <- stanzas fs+ mLib <- parseLib mLibFields+ biExes <- traverse parseExe exes+ return (mLib, biExes)+ where+ parseLib :: Fields Position -> ParseResult (Maybe BuildInfo)+ parseLib fields+ | Map.null fields = pure Nothing+ | otherwise = Just <$> parseFieldGrammar cabalSpecLatest fields buildInfoFieldGrammar++ parseExe :: (UnqualComponentName, Fields Position) -> ParseResult (UnqualComponentName, BuildInfo)+ parseExe (n, fields) = do+ bi <- parseFieldGrammar cabalSpecLatest fields buildInfoFieldGrammar+ pure (n, bi)++ stanzas :: [Field Position] -> ParseResult (Fields Position, [(UnqualComponentName, Fields Position)])+ stanzas fields = do+ let (hdr0, exes0) = breakMaybe isExecutableField fields+ hdr <- toFields hdr0+ exes <- unfoldrM (traverse toExe) exes0+ pure (hdr, exes)++ toFields :: [Field Position] -> ParseResult (Fields Position)+ toFields fields = do+ let (fields', ss) = partitionFields fields+ traverse_ (traverse_ warnInvalidSubsection) ss+ pure fields'++ toExe+ :: ([FieldLine Position], [Field Position])+ -> ParseResult ((UnqualComponentName, Fields Position), Maybe ([FieldLine Position], [Field Position]))+ toExe (fss, fields) = do+ name <- runFieldParser zeroPos parsec cabalSpecLatest fss+ let (hdr0, rest) = breakMaybe isExecutableField fields+ hdr <- toFields hdr0+ pure ((name, hdr), rest)++ isExecutableField (Field (Name _ name) fss)+ | name == "executable" = Just fss+ | otherwise = Nothing+ isExecutableField _ = Nothing++-------------------------------------------------------------------------------+-- Scan of spec version+-------------------------------------------------------------------------------++-- | Quickly scan new-style spec-version+--+-- A new-style spec-version declaration begins the .cabal file and+-- follow the following case-insensitive grammar (expressed in+-- RFC5234 ABNF):+--+-- @+-- newstyle-spec-version-decl = "cabal-version" *WS ":" *WS newstyle-pec-version *WS+--+-- spec-version = NUM "." NUM [ "." NUM ]+--+-- NUM = DIGIT0 / DIGITP 1*DIGIT0+-- DIGIT0 = %x30-39+-- DIGITP = %x31-39+-- WS = %20+-- @+--+scanSpecVersion :: BS.ByteString -> Maybe Version+scanSpecVersion bs = do+ fstline':_ <- pure (BS8.lines bs)++ -- parse <newstyle-spec-version-decl>+ -- normalise: remove all whitespace, convert to lower-case+ let fstline = BS.map toLowerW8 $ BS.filter (/= 0x20) fstline'+ ["cabal-version",vers] <- pure (BS8.split ':' fstline)++ -- parse <spec-version>+ --+ -- This is currently more tolerant regarding leading 0 digits.+ --+ ver <- simpleParsecBS vers+ guard $ case versionNumbers ver of+ [_,_] -> True+ [_,_,_] -> True+ _ -> False++ pure ver+ where+ -- | Translate ['A'..'Z'] to ['a'..'z']+ toLowerW8 :: Word8 -> Word8+ toLowerW8 w | 0x40 < w && w < 0x5b = w+0x20+ | otherwise = w
+ src/Distribution/PackageDescription/PrettyPrint.hs view
@@ -0,0 +1,282 @@+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.PackageDescription.PrettyPrint+-- Copyright : Jürgen Nicklisch-Franken 2010+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Stability : provisional+-- Portability : portable+--+-- Pretty printing for cabal files+--+-----------------------------------------------------------------------------++module Distribution.PackageDescription.PrettyPrint (+ -- * Generic package descriptions+ writeGenericPackageDescription,+ showGenericPackageDescription,+ ppGenericPackageDescription,++ -- * Package descriptions+ writePackageDescription,+ showPackageDescription,++ -- ** Supplementary build information+ writeHookedBuildInfo,+ showHookedBuildInfo,+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.CabalSpecVersion+import Distribution.Fields.Pretty+import Distribution.Compat.Lens+import Distribution.PackageDescription+import Distribution.Pretty+import Distribution.Simple.Utils (writeFileAtomic, writeUTF8File)+import Distribution.FieldGrammar (PrettyFieldGrammar', prettyFieldGrammar)+import Distribution.PackageDescription.Configuration (transformAllBuildInfos)+import Distribution.PackageDescription.FieldGrammar+ (benchmarkFieldGrammar, buildInfoFieldGrammar, executableFieldGrammar, flagFieldGrammar, foreignLibFieldGrammar, libraryFieldGrammar,+ packageDescriptionFieldGrammar, setupBInfoFieldGrammar, sourceRepoFieldGrammar, testSuiteFieldGrammar)++import qualified Distribution.PackageDescription.FieldGrammar as FG+import qualified Distribution.Types.BuildInfo.Lens as L+import qualified Distribution.Types.SetupBuildInfo.Lens as L++import Text.PrettyPrint (Doc, char, hsep, parens, text)++import qualified Data.ByteString.Lazy.Char8 as BS.Char8+import qualified Distribution.Compat.NonEmptySet as NES++-- | Writes a .cabal file from a generic package description+writeGenericPackageDescription :: FilePath -> GenericPackageDescription -> IO ()+writeGenericPackageDescription fpath pkg = writeUTF8File fpath (showGenericPackageDescription pkg)++-- | Writes a generic package description to a string+showGenericPackageDescription :: GenericPackageDescription -> String+showGenericPackageDescription gpd = showFields (const []) $ ppGenericPackageDescription v gpd+ where+ v = specVersion $ packageDescription gpd++-- | Convert a generic package description to 'PrettyField's.+ppGenericPackageDescription :: CabalSpecVersion -> GenericPackageDescription -> [PrettyField ()]+ppGenericPackageDescription v gpd0 = concat+ [ ppPackageDescription v (packageDescription gpd)+ , ppSetupBInfo v (setupBuildInfo (packageDescription gpd))+ , ppGenPackageFlags v (genPackageFlags gpd)+ , ppCondLibrary v (condLibrary gpd)+ , ppCondSubLibraries v (condSubLibraries gpd)+ , ppCondForeignLibs v (condForeignLibs gpd)+ , ppCondExecutables v (condExecutables gpd)+ , ppCondTestSuites v (condTestSuites gpd)+ , ppCondBenchmarks v (condBenchmarks gpd)+ ]+ where+ gpd = preProcessInternalDeps (specVersion (packageDescription gpd0)) gpd0+++ppPackageDescription :: CabalSpecVersion -> PackageDescription -> [PrettyField ()]+ppPackageDescription v pd =+ prettyFieldGrammar v packageDescriptionFieldGrammar pd+ ++ ppSourceRepos v (sourceRepos pd)++ppSourceRepos :: CabalSpecVersion -> [SourceRepo] -> [PrettyField ()]+ppSourceRepos = map . ppSourceRepo++ppSourceRepo :: CabalSpecVersion -> SourceRepo -> PrettyField ()+ppSourceRepo v repo = PrettySection () "source-repository" [pretty kind] $+ prettyFieldGrammar v (sourceRepoFieldGrammar kind) repo+ where+ kind = repoKind repo++ppSetupBInfo :: CabalSpecVersion -> Maybe SetupBuildInfo -> [PrettyField ()]+ppSetupBInfo _ Nothing = mempty+ppSetupBInfo v (Just sbi)+ | defaultSetupDepends sbi = mempty+ | otherwise = pure $ PrettySection () "custom-setup" [] $+ prettyFieldGrammar v (setupBInfoFieldGrammar False) sbi++ppGenPackageFlags :: CabalSpecVersion -> [PackageFlag] -> [PrettyField ()]+ppGenPackageFlags = map . ppFlag++ppFlag :: CabalSpecVersion -> PackageFlag -> PrettyField ()+ppFlag v flag@(MkPackageFlag name _ _ _) = PrettySection () "flag" [ppFlagName name] $+ prettyFieldGrammar v (flagFieldGrammar name) flag++ppCondTree2 :: CabalSpecVersion -> PrettyFieldGrammar' s -> CondTree ConfVar [Dependency] s -> [PrettyField ()]+ppCondTree2 v grammar = go+ where+ -- TODO: recognise elif opportunities+ go (CondNode it _ ifs) =+ prettyFieldGrammar v grammar it +++ concatMap ppIf ifs++ ppIf (CondBranch c thenTree Nothing)+-- | isEmpty thenDoc = mempty+ | otherwise = [ppIfCondition c thenDoc]+ where+ thenDoc = go thenTree++ ppIf (CondBranch c thenTree (Just elseTree)) =+ -- See #6193+ [ ppIfCondition c (go thenTree)+ , PrettySection () "else" [] (go elseTree)+ ]++ppCondLibrary :: CabalSpecVersion -> Maybe (CondTree ConfVar [Dependency] Library) -> [PrettyField ()]+ppCondLibrary _ Nothing = mempty+ppCondLibrary v (Just condTree) = pure $ PrettySection () "library" [] $+ ppCondTree2 v (libraryFieldGrammar LMainLibName) condTree++ppCondSubLibraries :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Library)] -> [PrettyField ()]+ppCondSubLibraries v libs =+ [ PrettySection () "library" [pretty n]+ $ ppCondTree2 v (libraryFieldGrammar $ LSubLibName n) condTree+ | (n, condTree) <- libs+ ]++ppCondForeignLibs :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)] -> [PrettyField ()]+ppCondForeignLibs v flibs =+ [ PrettySection () "foreign-library" [pretty n]+ $ ppCondTree2 v (foreignLibFieldGrammar n) condTree+ | (n, condTree) <- flibs+ ]++ppCondExecutables :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)] -> [PrettyField ()]+ppCondExecutables v exes =+ [ PrettySection () "executable" [pretty n]+ $ ppCondTree2 v (executableFieldGrammar n) condTree+ | (n, condTree) <- exes+ ]++ppCondTestSuites :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)] -> [PrettyField ()]+ppCondTestSuites v suites =+ [ PrettySection () "test-suite" [pretty n]+ $ ppCondTree2 v testSuiteFieldGrammar (fmap FG.unvalidateTestSuite condTree)+ | (n, condTree) <- suites+ ]++ppCondBenchmarks :: CabalSpecVersion -> [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)] -> [PrettyField ()]+ppCondBenchmarks v suites =+ [ PrettySection () "benchmark" [pretty n]+ $ ppCondTree2 v benchmarkFieldGrammar (fmap FG.unvalidateBenchmark condTree)+ | (n, condTree) <- suites+ ]++ppCondition :: Condition ConfVar -> Doc+ppCondition (Var x) = ppConfVar x+ppCondition (Lit b) = text (show b)+ppCondition (CNot c) = char '!' <<>> (ppCondition c)+ppCondition (COr c1 c2) = parens (hsep [ppCondition c1, text "||"+ <+> ppCondition c2])+ppCondition (CAnd c1 c2) = parens (hsep [ppCondition c1, text "&&"+ <+> ppCondition c2])+ppConfVar :: ConfVar -> Doc+ppConfVar (OS os) = text "os" <<>> parens (pretty os)+ppConfVar (Arch arch) = text "arch" <<>> parens (pretty arch)+ppConfVar (PackageFlag name) = text "flag" <<>> parens (ppFlagName name)+ppConfVar (Impl c v) = text "impl" <<>> parens (pretty c <+> pretty v)++ppFlagName :: FlagName -> Doc+ppFlagName = text . unFlagName++ppIfCondition :: Condition ConfVar -> [PrettyField ()] -> PrettyField ()+ppIfCondition c = PrettySection () "if" [ppCondition c]++-- | @since 2.0.0.2+writePackageDescription :: FilePath -> PackageDescription -> IO ()+writePackageDescription fpath pkg = writeUTF8File fpath (showPackageDescription pkg)++--TODO: make this use section syntax+-- add equivalent for GenericPackageDescription++-- | @since 2.0.0.2+showPackageDescription :: PackageDescription -> String+showPackageDescription = showGenericPackageDescription . pdToGpd++pdToGpd :: PackageDescription -> GenericPackageDescription+pdToGpd pd = GenericPackageDescription+ { packageDescription = pd+ , gpdScannedVersion = Nothing+ , genPackageFlags = []+ , condLibrary = mkCondTree <$> library pd+ , condSubLibraries = mkCondTreeL <$> subLibraries pd+ , condForeignLibs = mkCondTree' foreignLibName <$> foreignLibs pd+ , condExecutables = mkCondTree' exeName <$> executables pd+ , condTestSuites = mkCondTree' testName <$> testSuites pd+ , condBenchmarks = mkCondTree' benchmarkName <$> benchmarks pd+ }+ where+ -- We set CondTree's [Dependency] to an empty list, as it+ -- is not pretty printed anyway.+ mkCondTree x = CondNode x [] []+ mkCondTreeL l = (fromMaybe (mkUnqualComponentName "") (libraryNameString (libName l)), CondNode l [] [])++ mkCondTree'+ :: (a -> UnqualComponentName)+ -> a -> (UnqualComponentName, CondTree ConfVar [Dependency] a)+ mkCondTree' f x = (f x, CondNode x [] [])++-------------------------------------------------------------------------------+-- Internal libs+-------------------------------------------------------------------------------++-- See Note [Dependencies on sublibraries] in Distribution.PackageDescription.Parsec+--+preProcessInternalDeps :: CabalSpecVersion -> GenericPackageDescription -> GenericPackageDescription+preProcessInternalDeps specVer gpd+ | specVer >= CabalSpecV3_4 = gpd+ | otherwise = transformAllBuildInfos transformBI transformSBI gpd+ where+ transformBI :: BuildInfo -> BuildInfo+ transformBI+ = over L.targetBuildDepends (concatMap transformD)+ . over L.mixins (map transformM)++ transformSBI :: SetupBuildInfo -> SetupBuildInfo+ transformSBI = over L.setupDepends (concatMap transformD)++ transformD :: Dependency -> [Dependency]+ transformD (Dependency pn vr ln)+ | pn == thisPn+ = if LMainLibName `NES.member` ln+ then Dependency thisPn vr mainLibSet : sublibs+ else sublibs+ where+ sublibs =+ [ Dependency (unqualComponentNameToPackageName uqn) vr mainLibSet+ | LSubLibName uqn <- NES.toList ln+ ]++ transformD d = [d]++ transformM :: Mixin -> Mixin+ transformM (Mixin pn (LSubLibName uqn) inc)+ | pn == thisPn+ = mkMixin (unqualComponentNameToPackageName uqn) LMainLibName inc+ transformM m = m++ thisPn :: PackageName+ thisPn = pkgName (package (packageDescription gpd))++-------------------------------------------------------------------------------+-- HookedBuildInfo+-------------------------------------------------------------------------------++-- | @since 2.0.0.2+writeHookedBuildInfo :: FilePath -> HookedBuildInfo -> IO ()+writeHookedBuildInfo fpath = writeFileAtomic fpath . BS.Char8.pack+ . showHookedBuildInfo++-- | @since 2.0.0.2+showHookedBuildInfo :: HookedBuildInfo -> String+showHookedBuildInfo (mb_lib_bi, ex_bis) = showFields (const []) $+ maybe mempty (prettyFieldGrammar cabalSpecLatest buildInfoFieldGrammar) mb_lib_bi +++ [ PrettySection () "executable:" [pretty name]+ $ prettyFieldGrammar cabalSpecLatest buildInfoFieldGrammar bi+ | (name, bi) <- ex_bis+ ]
+ src/Distribution/PackageDescription/Quirks.hs view
@@ -0,0 +1,340 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+-- |+--+-- @since 2.2.0.0+module Distribution.PackageDescription.Quirks (patchQuirks) where++import Distribution.Compat.Prelude+import Distribution.Utils.MD5+import GHC.Fingerprint (Fingerprint (..))+import Prelude ()++import qualified Data.ByteString as BS+import qualified Data.Map as Map++-- | Patch legacy @.cabal@ file contents to allow parsec parser to accept+-- all of Hackage.+--+-- Bool part of the result tells whether the output is modified.+--+-- @since 2.2.0.0+patchQuirks :: BS.ByteString -> (Bool, BS.ByteString)+patchQuirks bs = case Map.lookup (BS.take 256 bs, md5 bs) patches of+ Nothing -> (False, bs)+ Just (post, f)+ | post /= md5 output -> (False, bs)+ | otherwise -> (True, output)+ where+ output = f bs++-- | 'patches' contains first 256 bytes, pre- and post-fingerprints and a patch function.+patches :: Map.Map (BS.ByteString, Fingerprint) (Fingerprint, BS.ByteString -> BS.ByteString)+patches = Map.fromList+ -- http://hackage.haskell.org/package/unicode-transforms-0.3.3+ -- other-modules: .+ -- ReadP assumed dot is empty line+ [ mk "-- This file has been generated from package.yaml by hpack version 0.17.0.\n--\n-- see: https://github.com/sol/hpack\n\nname: unicode-transforms\nversion: 0.3.3\nsynopsis: Unicode normalization\ndescription: Fast Unic"+ (Fingerprint 15958160436627155571 10318709190730872881)+ (Fingerprint 11008465475756725834 13815629925116264363)+ (bsRemove " other-modules:\n .\n") -- TODO: remove traling \n to test structural-diff+ -- http://hackage.haskell.org/package/DSTM-0.1.2+ -- http://hackage.haskell.org/package/DSTM-0.1.1+ -- http://hackage.haskell.org/package/DSTM-0.1+ -- Other Modules: no dash+ -- ReadP parsed as section+ , mk "Name: DSTM\nVersion: 0.1.2\nCopyright: (c) 2010, Frank Kupke\nLicense: LGPL\nLicense-File: LICENSE\nAuthor: Frank Kupke\nMaintainer: frk@informatik.uni-kiel.de\nCabal-Version: >= 1.2.3\nStability: provisional\nSynopsis: A framework for using STM within distributed "+ (Fingerprint 6919263071548559054 9050746360708965827)+ (Fingerprint 17015177514298962556 11943164891661867280)+ (bsReplace "Other modules:" "-- ")+ , mk "Name: DSTM\nVersion: 0.1.1\nCopyright: (c) 2010, Frank Kupke\nLicense: LGPL\nLicense-File: LICENSE\nAuthor: Frank Kupke\nMaintainer: frk@informatik.uni-kiel.de\nCabal-Version: >= 1.2.3\nStability: provisional\nSynopsis: A framework for using STM within distributed "+ (Fingerprint 17313105789069667153 9610429408495338584)+ (Fingerprint 17250946493484671738 17629939328766863497)+ (bsReplace "Other modules:" "-- ")+ , mk "Name: DSTM\nVersion: 0.1\nCopyright: (c) 2010, Frank Kupke\nLicense: LGPL\nLicense-File: LICENSE\nAuthor: Frank Kupke\nMaintainer: frk@informatik.uni-kiel.de\nCabal-Version: >= 1.2.3\nStability: provisional\nSynopsis: A framework for using STM within distributed sy"+ (Fingerprint 10502599650530614586 16424112934471063115)+ (Fingerprint 13562014713536696107 17899511905611879358)+ (bsReplace "Other modules:" "-- ")+ -- http://hackage.haskell.org/package/control-monad-exception-mtl-0.10.3+ , mk "name: control-monad-exception-mtl\nversion: 0.10.3\nCabal-Version: >= 1.10\nbuild-type: Simple\nlicense: PublicDomain\nauthor: Pepe Iborra\nmaintainer: pepeiborra@gmail.com\nhomepage: http://pepeiborra.github.com/control-monad-exception\nsynopsis: MTL instances f"+ (Fingerprint 18274748422558568404 4043538769550834851)+ (Fingerprint 11395257416101232635 4303318131190196308)+ (bsReplace " default- extensions:" "unknown-section")+ -- http://hackage.haskell.org/package/vacuum-opengl-0.0+ -- \DEL character+ , mk "Name: vacuum-opengl\nVersion: 0.0\nSynopsis: Visualize live Haskell data structures using vacuum, graphviz and OpenGL.\nDescription: \DELVisualize live Haskell data structures using vacuum, graphviz and OpenGL.\n "+ (Fingerprint 5946760521961682577 16933361639326309422)+ (Fingerprint 14034745101467101555 14024175957788447824)+ (bsRemove "\DEL")+ , mk "Name: vacuum-opengl\nVersion: 0.0.1\nSynopsis: Visualize live Haskell data structures using vacuum, graphviz and OpenGL.\nDescription: \DELVisualize live Haskell data structures using vacuum, graphviz and OpenGL.\n "+ (Fingerprint 10790950110330119503 1309560249972452700)+ (Fingerprint 1565743557025952928 13645502325715033593)+ (bsRemove "\DEL")+ -- http://hackage.haskell.org/package/ixset-1.0.4+ -- {- comments -}+ , mk "Name: ixset\nVersion: 1.0.4\nSynopsis: Efficient relational queries on Haskell sets.\nDescription:\n Create and query sets that are indexed by multiple indices.\nLicense: BSD3\nLicense-file: COPYING\nAut"+ (Fingerprint 11886092342440414185 4150518943472101551)+ (Fingerprint 5731367240051983879 17473925006273577821)+ (bsRemoveStarting "{-")+ -- : after section+ -- http://hackage.haskell.org/package/ds-kanren+ , mk "name: ds-kanren\nversion: 0.2.0.0\nsynopsis: A subset of the miniKanren language\ndescription:\n ds-kanren is an implementation of the <http://minikanren.org miniKanren> language.\n .\n == What's in ds-kanren?\n .\n ['dis"+ (Fingerprint 2804006762382336875 9677726932108735838)+ (Fingerprint 9830506174094917897 12812107316777006473)+ (bsReplace "Test-Suite test-unify:" "Test-Suite \"test-unify:\"" . bsReplace "Test-Suite test-list-ops:" "Test-Suite \"test-list-ops:\"")+ , mk "name: ds-kanren\nversion: 0.2.0.1\nsynopsis: A subset of the miniKanren language\ndescription:\n ds-kanren is an implementation of the <http://minikanren.org miniKanren> language.\n\nlicense: MIT\nlicense-file: "+ (Fingerprint 9130259649220396193 2155671144384738932)+ (Fingerprint 1847988234352024240 4597789823227580457)+ (bsReplace "Test-Suite test-unify:" "Test-Suite \"test-unify:\"" . bsReplace "Test-Suite test-list-ops:" "Test-Suite \"test-list-ops:\"")+ , mk "name: metric\nversion: 0.1.4\nsynopsis: Metric spaces.\nlicense: MIT\nlicense-file: LICENSE\nauthor: Vikram Verma\nmaintainer: me@vikramverma.com\ncategory: Data\nbuild-type:"+ (Fingerprint 6150019278861565482 3066802658031228162)+ (Fingerprint 9124826020564520548 15629704249829132420)+ (bsReplace "test-suite metric-tests:" "test-suite \"metric-tests:\"")+ , mk "name: metric\nversion: 0.2.0\nsynopsis: Metric spaces.\nlicense: MIT\nlicense-file: LICENSE\nauthor: Vikram Verma\nmaintainer: me@vikramverma.com\ncategory: Data\nbuild-type:"+ (Fingerprint 4639805967994715694 7859317050376284551)+ (Fingerprint 5566222290622325231 873197212916959151)+ (bsReplace "test-suite metric-tests:" "test-suite \"metric-tests:\"")+ , mk "name: phasechange\ncategory: Data\nversion: 0.1\nauthor: G\195\161bor Lehel\nmaintainer: G\195\161bor Lehel <illissius@gmail.com>\nhomepage: http://github.com/glehel/phasechange\ncopyright: Copyright (C) 2012 G\195\161bor Lehel\nlicense: "+ (Fingerprint 10546509771395401582 245508422312751943)+ (Fingerprint 5169853482576003304 7247091607933993833)+ (bsReplace "impl(ghc >= 7.4):" "erroneous-section" . bsReplace "impl(ghc >= 7.6):" "erroneous-section")+ , mk "Name: smartword\nSynopsis: Web based flash card for Word Smart I and II vocabularies\nVersion: 0.0.0.5\nHomepage: http://kyagrd.dyndns.org/~kyagrd/project/smartword/\nCategory: Web,Education\nLicense: "+ (Fingerprint 7803544783533485151 10807347873998191750)+ (Fingerprint 1665635316718752601 16212378357991151549)+ (bsReplace "build depends:" "--")+ , mk "name: shelltestrunner\n-- sync with README.md, ANNOUNCE:\nversion: 1.3\ncategory: Testing\nsynopsis: A tool for testing command-line programs.\ndescription:\n shelltestrunner is a cross-platform tool for testing command-line\n program"+ (Fingerprint 4403237110790078829 15392625961066653722)+ (Fingerprint 10218887328390239431 4644205837817510221)+ (bsReplace "other modules:" "--")+ -- &&!+ -- http://hackage.haskell.org/package/hblas-0.3.0.0+ , mk "-- Initial hblas.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP) \n-- "+ (Fingerprint 8570120150072467041 18315524331351505945)+ (Fingerprint 10838007242302656005 16026440017674974175)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP) \n-- "+ (Fingerprint 5262875856214215155 10846626274067555320)+ (Fingerprint 3022954285783401045 13395975869915955260)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP) \n-- "+ (Fingerprint 54222628930951453 5526514916844166577)+ (Fingerprint 1749630806887010665 8607076506606977549)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"+ (Fingerprint 6817250511240350300 15278852712000783849)+ (Fingerprint 15757717081429529536 15542551865099640223)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"+ (Fingerprint 8310050400349211976 201317952074418615)+ (Fingerprint 10283381191257209624 4231947623042413334)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"+ (Fingerprint 7010988292906098371 11591884496857936132)+ (Fingerprint 6158672440010710301 6419743768695725095)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further\r\n-- documentation, see http://haskell.org/cabal/users-guide/\r\n\r\n-- The name of the package.\r\nname: hblas\r\n\r\n-- The package version. See the Haskell package versioning policy (PVP)"+ (Fingerprint 2076850805659055833 16615160726215879467)+ (Fingerprint 10634706281258477722 5285812379517916984)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further\r\n-- documentation, see http://haskell.org/cabal/users-guide/\r\n\r\n-- The name of the package.\r\nname: hblas\r\n\r\n-- The package version. See the Haskell package versioning policy (PVP)"+ (Fingerprint 11850020631622781099 11956481969231030830)+ (Fingerprint 13702868780337762025 13383526367149067158)+ (bsReplace "&&!" "&& !")+ , mk "-- Initial hblas.cabal generated by cabal init. For further\n-- documentation, see http://haskell.org/cabal/users-guide/\n\n-- The name of the package.\nname: hblas\n\n-- The package version. See the Haskell package versioning policy (PVP)\n-- fo"+ (Fingerprint 13690322768477779172 19704059263540994)+ (Fingerprint 11189374824645442376 8363528115442591078)+ (bsReplace "&&!" "&& !")+ -- flag used, but not defined+ , mk "name: brainheck\nversion: 0.1.0.2\nsynopsis: Brainh*ck interpreter in haskell\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\nhomepage: https://gi"+ (Fingerprint 6910727116443152200 15401634478524888973)+ (Fingerprint 16551412117098094368 16260377389127603629)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: brainheck\r\nversion: 0.1.0.2\r\nx-revision: 1\r\nsynopsis: Brainh*ck interpreter in haskell\r\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\r\nhomepage: "+ (Fingerprint 14320987921316832277 10031098243571536929)+ (Fingerprint 7959395602414037224 13279941216182213050)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: brainheck\r\nversion: 0.1.0.2\r\nx-revision: 2\r\nsynopsis: Brainh*ck interpreter in haskell\r\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\r\nhomepage: "+ (Fingerprint 3809078390223299128 10796026010775813741)+ (Fingerprint 1127231189459220796 12088367524333209349)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: brainheck\r\nversion: 0.1.0.2\r\nx-revision: 3\r\nsynopsis: Brainh*ck interpreter in haskell\r\ndescription: Brainh*ck interpreter written in haskell and taking advantage of many prominent libraries\r\nhomepage: "+ (Fingerprint 13860013038089410950 12479824176801390651)+ (Fingerprint 4687484721703340391 8013395164515771785)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: wordchoice\nversion: 0.1.0.1\nsynopsis: Get word counts and distributions\ndescription: A command line tool to compute the word distribution from various types of document, converting to text with pandoc.\nho"+ (Fingerprint 16215911397419608203 15594928482155652475)+ (Fingerprint 15120681510314491047 2666192399775157359)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: wordchoice\r\nversion: 0.1.0.1\r\nx-revision: 1\r\nsynopsis: Get word counts and distributions\r\ndescription: A command line tool to compute the word distribution from various types of document, converting to te"+ (Fingerprint 16593139224723441188 4052919014346212001)+ (Fingerprint 3577381082410411593 11481899387780544641)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: wordchoice\nversion: 0.1.0.2\nsynopsis: Get word counts and distributions\ndescription: A command line tool to compute the word distribution from various types of document, converting to text with pandoc.\nho"+ (Fingerprint 9321301260802539374 1316392715016096607)+ (Fingerprint 3784628652257760949 12662640594755291035)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: wordchoice\r\nversion: 0.1.0.2\r\nx-revision: 1\r\nsynopsis: Get word counts and distributions\r\ndescription: A command line tool to compute the word distribution from various types of document, converting to te"+ (Fingerprint 2546901804824433337 2059732715322561176)+ (Fingerprint 8082068680348326500 615008613291421947)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: wordchoice\nversion: 0.1.0.3\nsynopsis: Get word counts and distributions\ndescription: A command line tool to compute the word distribution from various types of document, converting to text with pandoc.\nho"+ (Fingerprint 2282380737467965407 12457554753171662424)+ (Fingerprint 17324757216926991616 17172911843227482125)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: wordchoice\r\nversion: 0.1.0.3\r\nx-revision: 1\r\nsynopsis: Get word counts and distributions\r\ndescription: A command line tool to compute the word distribution from various types of document, converting to te"+ (Fingerprint 12907988890480595481 11078473638628359710)+ (Fingerprint 13246185333368731848 4663060731847518614)+ (bsReplace "flag(llvm-fast)" "False")+ , mk "name: hw-prim-bits\nversion: 0.1.0.0\nsynopsis: Primitive support for bit manipulation\ndescription: Please see README.md\nhomepage: https://github.com/githubuser/hw-prim-bits#readme\nlicense: "+ (Fingerprint 12386777729082870356 17414156731912743711)+ (Fingerprint 3452290353395041602 14102887112483033720)+ (bsReplace "flag(sse42)" "False")+ , mk "name: hw-prim-bits\nversion: 0.1.0.1\nsynopsis: Primitive support for bit manipulation\ndescription: Please see README.md\nhomepage: https://github.com/githubuser/hw-prim-bits#readme\nlicen"+ (Fingerprint 6870520675313101180 14553457351296240636)+ (Fingerprint 12481021059537696455 14711088786769892762)+ (bsReplace "flag(sse42)" "False")+ -- leading zeros in version digits+ -- https://github.com/haskell-infra/hackage-trustees/issues/128+ -- https://github.com/haskell/cabal/issues/5092+ -- https://github.com/haskell/cabal/issues/5138+ , mk "name: Sit\nversion: 0.2017.02.26\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Anonymous\nmaintainer: Anonymous\nhomepage: NONE\ncategory: Dependent"+ (Fingerprint 8458530898096910998 3228538743646501413)+ (Fingerprint 14470502514907936793 17514354054641875371)+ (bsReplace "0.2017.02.26" "0.2017.2.26")+ , mk "name: Sit\nversion: 0.2017.05.01\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Andreas Abel <andreas.abel@gu.se>\nmaintainer: Andreas Abel <andreas.abel@gu.se>\n"+ (Fingerprint 1450130849535097473 11742099607098860444)+ (Fingerprint 16679762943850814021 4253724355613883542)+ (bsReplace "0.2017.05.01" "0.2017.5.1")+ , mk "name: Sit\nversion: 0.2017.05.02\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Andreas Abel <andreas.abel@gu.se>\nmaintainer: Andreas Abel <andreas.abel@gu.se>\n"+ (Fingerprint 297248532398492441 17322625167861324800)+ (Fingerprint 634812045126693280 1755581866539318862)+ (bsReplace "0.2017.05.02" "0.2017.5.2")+ , mk "name: Sit\nversion: 0.2017.5.02\nx-revision: 1\n-- x-revision:1 see https://github.com/haskell-infra/hackage-trustees/issues/128\nbuild-type: Simple\ncabal-version: >= 1.8\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: "+ (Fingerprint 3697869560530373941 3942982281026987312)+ (Fingerprint 14344526114710295386 16386400353475114712)+ (bsReplace "0.2017.5.02" "0.2017.5.2")+ , mk "name: MiniAgda\nversion: 0.2017.02.18\nbuild-type: Simple\ncabal-version: >= 1.22\nlicense: OtherLicense\nlicense-file: LICENSE\nauthor: Andreas Abel and Karl Mehltretter\nmaintainer: Andreas Abel <andreas.abel@i"+ (Fingerprint 17167128953451088679 4300350537748753465)+ (Fingerprint 12402236925293025673 7715084875284020606)+ (bsReplace "0.2017.02.18" "0.2017.2.18")+ , mk "cabal-version:\n 2.0\nname:\n fast-downward\nversion:\n 0.1.0.0\nbuild-type:\n Simple\nsynopsis:\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\ndescription:\n @fast-downward@ is a library for modelling classical planning probl"+ (Fingerprint 11256076039027887363 6867903407496243216)+ (Fingerprint 12159816716813155434 5278015399212299853)+ (bsReplace "1.2.03.0" "1.2.3.0")+ , mk "cabal-version:\r\n 2.0\r\nname:\r\n fast-downward\r\nversion:\r\n 0.1.0.0\r\nx-revision: \r\n 1\r\nbuild-type:\r\n Simple\r\nsynopsis:\r\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\r\ndescription:\r\n @fast-downward@ is a library for mode"+ (Fingerprint 9216193973149680231 893446343655828508)+ (Fingerprint 10020169545407746427 1828336750379510675)+ (bsReplace "1.2.03.0" "1.2.3.0")+ , mk "cabal-version:\n 2.0\nname:\n fast-downward\nversion:\n 0.1.0.1\nbuild-type:\n Simple\nsynopsis:\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\ndescription:\n @fast-downward@ is a library for modelling classical planning probl"+ (Fingerprint 9899886602574848632 5980433644983783334)+ (Fingerprint 12007469255857289958 8321466548645225439)+ (bsReplace "1.2.03.0" "1.2.3.0")+ , mk "cabal-version:\n 2.0\nname:\n fast-downward\nversion:\n 0.1.1.0\nbuild-type:\n Simple\nsynopsis:\n Solve classical planning problems (STRIPS/SAS+) using Haskell & Fast Downward.\ndescription:\n @fast-downward@ is a library for modelling classical planning probl"+ (Fingerprint 12694656661460787751 1902242956706735615)+ (Fingerprint 15433152131513403849 2284712791516353264)+ (bsReplace "1.2.03.0" "1.2.3.0")+ -- 9 digits limit+ , mk "Name: SGplus\nVersion: 1.1\nSynopsis: (updated) Small geometry library for dealing with vectors and collision detection\nLicense: BSD3\nLicense-file: LICENSE\nAuthor: Neil Brown\nMaintainer: "+ (Fingerprint 17735649550442248029 11493772714725351354)+ (Fingerprint 9565458801063261772 15955773698774721052)+ (bsReplace "1000000000" "100000000")+ , mk "-- Initial control-dotdotdot.cabal generated by cabal init. For further \n-- documentation, see http://haskell.org/cabal/users-guide/\n\nname: control-dotdotdot\nversion: 0.1.0.1\nsynopsis: Haskell operator\n "+ (Fingerprint 1514257173776509942 7756050823377346485)+ (Fingerprint 14082092642045505999 18415918653404121035)+ (bsReplace "9223372036854775807" "5")+ , mk "name: data-foldapp\r\nversion: 0.1.1.0\r\nsynopsis: Fold function applications. Framework for variadic functions.\r\ndescription: Fold function applications. Framework for variadic functions.\r\nhomepage: ht"+ (Fingerprint 4511234156311243251 11701153011544112556)+ (Fingerprint 11820542702491924189 4902231447612406724)+ (bsReplace "9223372036854775807" "999" . bsReplace "9223372036854775807" "999")+ , mk "-- Initial data-list-zigzag.cabal generated by cabal init. For further \r\n-- documentation, see http://haskell.org/cabal/users-guide/\r\n\r\nname: data-list-zigzag\r\nversion: 0.1.1.1\r\nsynopsis: A list but with a balanced en"+ (Fingerprint 12475837388692175691 18053834261188158945)+ (Fingerprint 16279938253437334942 15753349540193002309)+ (bsReplace "9223372036854775807" "999")+ -- Not UTF8+ , mk "Name: nat\nVersion: 0.1\nDescription: Implementation of natural numbers and integers by a binary\n representation. The implementation is supposed to be lazy and\n "+ (Fingerprint 9222512268705577108 13085311382746579495)+ (Fingerprint 17468921266614378430 13221316288008291892)+ (bsReplace "\xf6" "\xc3\xb6")+ -- cabal-version: 2+ , mk "name: streaming-bracketed\nversion: 0.1.0.0\nsynopsis: A resource management decorator for \"streaming\". \ndescription: This package provides a decorator for the Stream type from\n the \"st"+ (Fingerprint 14670044663153191927 1427497586294143829)+ (Fingerprint 9233007756654759985 6571998449003682006)+ (bsReplace "cabal-version: 2" "cabal-version: 2.0")+ , mk "name: streaming-bracketed\nversion: 0.1.0.1\nsynopsis: A resource management decorator for \"streaming\". \ndescription: This package provides a decorator for the Stream type from\n \"stream"+ (Fingerprint 7298738862909203815 10141693276062967842)+ (Fingerprint 1349949738792220441 3593683359695349293)+ (bsReplace "cabal-version: 2" "cabal-version: 2.0")+ , mk "name: zsyntax\nversion: 0.2.0.0\ndescription: An automated theorem prover for Zsyntax, a\n logical calculus for molecular biology inspired by linear logic,\n that can be used to automatically verify biological\n"+ (Fingerprint 17812331267506881875 3005293725141563863)+ (Fingerprint 3445957263137759540 12472369104312474458)+ (bsReplace "cabal-version: 2" "cabal-version: 2.0")++ -- Empty filepath in not license-file or data-dir+ -- These have hs-source-dirs: ""+ , mk "\nname: wai-middleware-hmac-client\nversion: 0.1.0.1\nlicense: BSD3\nlicense-file: LICENSE\nauthor: Christopher Reichert\nmaintainer: creichert07@gmail.com\ncopyright: (c) 2015, Christo"+ (Fingerprint 3112606538775065787 11984607507024462091)+ (Fingerprint 6916432989977230500 6621389616675138128)+ (bsReplace "\"\"" ".")+ , mk "\nname: wai-middleware-hmac-client\nversion: 0.1.0.2\nlicense: BSD3\nlicense-file: LICENSE\nauthor: Christopher Reichert\nmaintainer: creichert07@gmail.com\ncopyright: (c) 2015, Christo"+ (Fingerprint 12566783342663020458 17562089389615949789)+ (Fingerprint 15745683452603944938 10556498036622072844)+ (bsReplace "\"\"" ".")++ -- absolute license-file+ , mk "name: reheat\nversion: 0.1.4\ncabal-version: >=1.8\nbuild-type: Simple\nlicense: GPL\nlicense-file: /home/palo/dev/haskell-workspace/playground/reheat/gpl-3.0.txt\ncopyright: GPL\nmaintainer: Ingolf Wagner <palipalo9@gmail.com>\nstability: experimental\nhomepage: h"+ (Fingerprint 9155400339287317061 14812953666990892802)+ (Fingerprint 7687053346032173923 15384472501136606592)+ (bsReplace "/home/palo/dev/haskell-workspace/playground/reheat/gpl-3.0.txt" "")+ , mk "name: reheat\nversion: 0.1.5\ncabal-version: >=1.8\nbuild-type: Simple\nlicense: GPL\nlicense-file: /home/palo/dev/haskell-workspace/playground/reheat/gpl-3.0.txt\ncopyright: GPL\nmaintainer: Ingolf Wagner <palipalo9@gmail.com>\nstability: experimental\nhomepage: h"+ (Fingerprint 2984391146441073709 11728234882049907993)+ (Fingerprint 12058479081855347701 14017937756688869826)+ (bsReplace "/home/palo/dev/haskell-workspace/playground/reheat/gpl-3.0.txt" "")+ ]+ where+ mk a b c d = ((a, b), (c, d))++-- | Helper to create entries in patches+_makePatchKey :: FilePath -> (BS.ByteString -> BS.ByteString) -> IO ()+_makePatchKey fp transform = do+ contents <- BS.readFile fp+ let output = transform contents+ let Fingerprint hi lo = md5 contents+ let Fingerprint hi' lo' = md5 output+ putStrLn+ $ showString " , mk "+ . shows (BS.take 256 contents)+ . showString "\n (Fingerprint "+ . shows hi+ . showString " "+ . shows lo+ . showString ")\n (Fingerprint "+ . shows hi'+ . showString " "+ . shows lo'+ . showString ")"+ $ ""++-------------------------------------------------------------------------------+-- Patch helpers+-------------------------------------------------------------------------------++bsRemove+ :: BS.ByteString -- ^ needle+ -> BS.ByteString -> BS.ByteString+bsRemove needle haystack = case BS.breakSubstring needle haystack of+ (h, t) -> BS.append h (BS.drop (BS.length needle) t)++bsReplace+ :: BS.ByteString -- ^ needle+ -> BS.ByteString -- ^ replacement+ -> BS.ByteString -> BS.ByteString+bsReplace needle repl haystack = case BS.breakSubstring needle haystack of+ (h, t)+ | not (BS.null t) -> BS.append h (BS.append repl (BS.drop (BS.length needle) t))+ | otherwise -> haystack++bsRemoveStarting+ :: BS.ByteString -- ^ needle+ -> BS.ByteString -> BS.ByteString+bsRemoveStarting needle haystack = case BS.breakSubstring needle haystack of+ (h, _) -> h
+ src/Distribution/PackageDescription/Utils.hs view
@@ -0,0 +1,23 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.PackageDescription.Utils+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Common utils used by modules under Distribution.PackageDescription.*.++module Distribution.PackageDescription.Utils (+ cabalBug, userBug+ ) where++-- ----------------------------------------------------------------------------+-- Exception and logging utils++userBug :: String -> a+userBug msg = error $ msg ++ ". This is a bug in your .cabal file."++cabalBug :: String -> a+cabalBug msg = error $ msg ++ ". This is possibly a bug in Cabal.\n"+ ++ "Please report it to the developers: "+ ++ "https://github.com/haskell/cabal/issues/new"
+ src/Distribution/Parsec.hs view
@@ -0,0 +1,524 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Distribution.Parsec (+ Parsec(..),+ ParsecParser (..),+ runParsecParser,+ runParsecParser',+ simpleParsec,+ simpleParsecBS,+ simpleParsec',+ simpleParsecW',+ lexemeParsec,+ eitherParsec,+ explicitEitherParsec,+ explicitEitherParsec',+ -- * CabalParsing and diagnostics+ CabalParsing (..),+ -- ** Warnings+ PWarnType (..),+ PWarning (..),+ showPWarning,+ -- ** Errors+ PError (..),+ showPError,+ -- * Position+ Position (..),+ incPos,+ retPos,+ showPos,+ zeroPos,+ -- * Utilities+ parsecToken,+ parsecToken',+ parsecFilePath,+ parsecQuoted,+ parsecMaybeQuoted,+ parsecCommaList,+ parsecCommaNonEmpty,+ parsecLeadingCommaList,+ parsecLeadingCommaNonEmpty,+ parsecOptCommaList,+ parsecLeadingOptCommaList,+ parsecStandard,+ parsecUnqualComponentName,+ ) where++import Data.ByteString (ByteString)+import Data.Char (digitToInt, intToDigit)+import Data.List (transpose)+import Distribution.CabalSpecVersion+import Distribution.Compat.Prelude+import Distribution.Parsec.Error (PError (..), showPError)+import Distribution.Parsec.FieldLineStream (FieldLineStream, fieldLineStreamFromBS, fieldLineStreamFromString)+import Distribution.Parsec.Position (Position (..), incPos, retPos, showPos, zeroPos)+import Distribution.Parsec.Warning (PWarnType (..), PWarning (..), showPWarning)+import Numeric (showIntAtBase)+import Prelude ()++import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.Compat.DList as DList+import qualified Distribution.Compat.MonadFail as Fail+import qualified Text.Parsec as Parsec++-------------------------------------------------------------------------------+-- Class+-------------------------------------------------------------------------------++-- | Class for parsing with @parsec@. Mainly used for @.cabal@ file fields.+--+-- For parsing @.cabal@ like file structure, see "Distribution.Fields".+--+class Parsec a where+ parsec :: CabalParsing m => m a++-- | Parsing class which+--+-- * can report Cabal parser warnings.+--+-- * knows @cabal-version@ we work with+--+class (P.CharParsing m, MonadPlus m, Fail.MonadFail m) => CabalParsing m where+ parsecWarning :: PWarnType -> String -> m ()++ parsecHaskellString :: m String+ parsecHaskellString = stringLiteral++ askCabalSpecVersion :: m CabalSpecVersion++-- | 'parsec' /could/ consume trailing spaces, this function /will/ consume.+lexemeParsec :: (CabalParsing m, Parsec a) => m a+lexemeParsec = parsec <* P.spaces++newtype ParsecParser a = PP { unPP+ :: CabalSpecVersion -> Parsec.Parsec FieldLineStream [PWarning] a+ }++liftParsec :: Parsec.Parsec FieldLineStream [PWarning] a -> ParsecParser a+liftParsec p = PP $ \_ -> p++instance Functor ParsecParser where+ fmap f p = PP $ \v -> fmap f (unPP p v)+ {-# INLINE fmap #-}++ x <$ p = PP $ \v -> x <$ unPP p v+ {-# INLINE (<$) #-}++instance Applicative ParsecParser where+ pure = liftParsec . pure+ {-# INLINE pure #-}++ f <*> x = PP $ \v -> unPP f v <*> unPP x v+ {-# INLINE (<*>) #-}+ f *> x = PP $ \v -> unPP f v *> unPP x v+ {-# INLINE (*>) #-}+ f <* x = PP $ \v -> unPP f v <* unPP x v+ {-# INLINE (<*) #-}++instance Alternative ParsecParser where+ empty = liftParsec empty++ a <|> b = PP $ \v -> unPP a v <|> unPP b v+ {-# INLINE (<|>) #-}++ many p = PP $ \v -> many (unPP p v)+ {-# INLINE many #-}++ some p = PP $ \v -> some (unPP p v)+ {-# INLINE some #-}++instance Monad ParsecParser where+ return = pure++ m >>= k = PP $ \v -> unPP m v >>= \x -> unPP (k x) v+ {-# INLINE (>>=) #-}+ (>>) = (*>)+ {-# INLINE (>>) #-}++#if !(MIN_VERSION_base(4,13,0))+ fail = Fail.fail+#endif++instance MonadPlus ParsecParser where+ mzero = empty+ mplus = (<|>)++instance Fail.MonadFail ParsecParser where+ fail = P.unexpected++instance P.Parsing ParsecParser where+ try p = PP $ \v -> P.try (unPP p v)+ p <?> d = PP $ \v -> unPP p v P.<?> d+ skipMany p = PP $ \v -> P.skipMany (unPP p v)+ skipSome p = PP $ \v -> P.skipSome (unPP p v)+ unexpected = liftParsec . P.unexpected+ eof = liftParsec P.eof+ notFollowedBy p = PP $ \v -> P.notFollowedBy (unPP p v)++instance P.CharParsing ParsecParser where+ satisfy = liftParsec . P.satisfy+ char = liftParsec . P.char+ notChar = liftParsec . P.notChar+ anyChar = liftParsec P.anyChar+ string = liftParsec . P.string++instance CabalParsing ParsecParser where+ parsecWarning t w = liftParsec $ do+ spos <- Parsec.getPosition+ Parsec.modifyState+ (PWarning t (Position (Parsec.sourceLine spos) (Parsec.sourceColumn spos)) w :)+ askCabalSpecVersion = PP pure++-- | Parse a 'String' with 'lexemeParsec'.+simpleParsec :: Parsec a => String -> Maybe a+simpleParsec+ = either (const Nothing) Just+ . runParsecParser lexemeParsec "<simpleParsec>"+ . fieldLineStreamFromString++-- | Like 'simpleParsec' but for 'ByteString'+simpleParsecBS :: Parsec a => ByteString -> Maybe a+simpleParsecBS+ = either (const Nothing) Just+ . runParsecParser lexemeParsec "<simpleParsec>"+ . fieldLineStreamFromBS++-- | Parse a 'String' with 'lexemeParsec' using specific 'CabalSpecVersion'.+--+-- @since 3.4.0.0+simpleParsec' :: Parsec a => CabalSpecVersion -> String -> Maybe a+simpleParsec' spec+ = either (const Nothing) Just+ . runParsecParser' spec lexemeParsec "<simpleParsec>"+ . fieldLineStreamFromString++-- | Parse a 'String' with 'lexemeParsec' using specific 'CabalSpecVersion'.+-- Fail if there are any warnings.+--+-- @since 3.4.0.0+simpleParsecW' :: Parsec a => CabalSpecVersion -> String -> Maybe a+simpleParsecW' spec+ = either (const Nothing) (\(x, ws) -> if null ws then Just x else Nothing)+ . runParsecParser' spec ((,) <$> lexemeParsec <*> liftParsec Parsec.getState) "<simpleParsec>"+ . fieldLineStreamFromString++-- | Parse a 'String' with 'lexemeParsec'.+eitherParsec :: Parsec a => String -> Either String a+eitherParsec = explicitEitherParsec parsec++-- | Parse a 'String' with given 'ParsecParser'. Trailing whitespace is accepted.+explicitEitherParsec :: ParsecParser a -> String -> Either String a+explicitEitherParsec parser+ = either (Left . show) Right+ . runParsecParser (parser <* P.spaces) "<eitherParsec>"+ . fieldLineStreamFromString++-- | Parse a 'String' with given 'ParsecParser' and 'CabalSpecVersion'. Trailing whitespace is accepted.+-- See 'explicitEitherParsec'.+--+-- @since 3.4.0.0+--+explicitEitherParsec' :: CabalSpecVersion -> ParsecParser a -> String -> Either String a+explicitEitherParsec' spec parser+ = either (Left . show) Right+ . runParsecParser' spec (parser <* P.spaces) "<eitherParsec>"+ . fieldLineStreamFromString++-- | Run 'ParsecParser' with 'cabalSpecLatest'.+runParsecParser :: ParsecParser a -> FilePath -> FieldLineStream -> Either Parsec.ParseError a+runParsecParser = runParsecParser' cabalSpecLatest++-- | Like 'runParsecParser' but lets specify 'CabalSpecVersion' used.+--+-- @since 3.0.0.0+--+runParsecParser' :: CabalSpecVersion -> ParsecParser a -> FilePath -> FieldLineStream -> Either Parsec.ParseError a+runParsecParser' v p n = Parsec.runParser (unPP p v <* P.eof) [] n++instance Parsec a => Parsec (Identity a) where+ parsec = Identity <$> parsec++instance Parsec Bool where+ parsec = P.munch1 isAlpha >>= postprocess+ where+ postprocess str+ | str == "True" = pure True+ | str == "False" = pure False+ | lstr == "true" = parsecWarning PWTBoolCase caseWarning *> pure True+ | lstr == "false" = parsecWarning PWTBoolCase caseWarning *> pure False+ | otherwise = fail $ "Not a boolean: " ++ str+ where+ lstr = map toLower str+ caseWarning =+ "Boolean values are case sensitive, use 'True' or 'False'."++-- | @[^ ,]@+parsecToken :: CabalParsing m => m String+parsecToken = parsecHaskellString <|> ((P.munch1 (\x -> not (isSpace x) && x /= ',') P.<?> "identifier" ) >>= checkNotDoubleDash)++-- | @[^ ]@+parsecToken' :: CabalParsing m => m String+parsecToken' = parsecHaskellString <|> ((P.munch1 (not . isSpace) P.<?> "token") >>= checkNotDoubleDash)++checkNotDoubleDash :: CabalParsing m => String -> m String+checkNotDoubleDash s = do+ when (s == "--") $ parsecWarning PWTDoubleDash $ unwords+ [ "Double-dash token found."+ , "Note: there are no end-of-line comments in .cabal files, only whole line comments."+ , "Use \"--\" (quoted double dash) to silence this warning, if you actually want -- token"+ ]++ return s++parsecFilePath :: CabalParsing m => m FilePath+parsecFilePath = parsecToken++-- | Parse a benchmark/test-suite types.+parsecStandard :: (CabalParsing m, Parsec ver) => (ver -> String -> a) -> m a+parsecStandard f = do+ cs <- some $ P.try (component <* P.char '-')+ ver <- parsec+ let name = map toLower (intercalate "-" cs)+ return $! f ver name+ where+ component = do+ cs <- P.munch1 isAlphaNum+ if all isDigit cs then fail "all digit component" else return cs+ -- each component must contain an alphabetic character, to avoid+ -- ambiguity in identifiers like foo-1 (the 1 is the version number).++parsecCommaList :: CabalParsing m => m a -> m [a]+parsecCommaList p = P.sepBy (p <* P.spaces) (P.char ',' *> P.spaces P.<?> "comma")++parsecCommaNonEmpty :: CabalParsing m => m a -> m (NonEmpty a)+parsecCommaNonEmpty p = P.sepByNonEmpty (p <* P.spaces) (P.char ',' *> P.spaces P.<?> "comma")++-- | Like 'parsecCommaList' but accept leading or trailing comma.+--+-- @+-- p (comma p)* -- p `sepBy` comma+-- (comma p)* -- leading comma+-- (p comma)* -- trailing comma+-- @+parsecLeadingCommaList :: CabalParsing m => m a -> m [a]+parsecLeadingCommaList p = do+ c <- P.optional comma+ case c of+ Nothing -> toList <$> P.sepEndByNonEmpty lp comma <|> pure []+ Just _ -> toList <$> P.sepByNonEmpty lp comma+ where+ lp = p <* P.spaces+ comma = P.char ',' *> P.spaces P.<?> "comma"++-- |+--+-- @since 3.4.0.0+parsecLeadingCommaNonEmpty :: CabalParsing m => m a -> m (NonEmpty a)+parsecLeadingCommaNonEmpty p = do+ c <- P.optional comma+ case c of+ Nothing -> P.sepEndByNonEmpty lp comma+ Just _ -> P.sepByNonEmpty lp comma+ where+ lp = p <* P.spaces+ comma = P.char ',' *> P.spaces P.<?> "comma"++parsecOptCommaList :: CabalParsing m => m a -> m [a]+parsecOptCommaList p = P.sepBy (p <* P.spaces) (P.optional comma)+ where+ comma = P.char ',' *> P.spaces++-- | Like 'parsecOptCommaList' but+--+-- * require all or none commas+-- * accept leading or trailing comma.+--+-- @+-- p (comma p)* -- p `sepBy` comma+-- (comma p)* -- leading comma+-- (p comma)* -- trailing comma+-- p* -- no commas: many p+-- @+--+-- @since 3.0.0.0+--+parsecLeadingOptCommaList :: CabalParsing m => m a -> m [a]+parsecLeadingOptCommaList p = do+ c <- P.optional comma+ case c of+ Nothing -> sepEndBy1Start <|> pure []+ Just _ -> toList <$> P.sepByNonEmpty lp comma+ where+ lp = p <* P.spaces+ comma = P.char ',' *> P.spaces P.<?> "comma"++ sepEndBy1Start = do+ x <- lp+ c <- P.optional comma+ case c of+ Nothing -> (x :) <$> many lp+ Just _ -> (x :) <$> P.sepEndBy lp comma++-- | Content isn't unquoted+parsecQuoted :: CabalParsing m => m a -> m a+parsecQuoted = P.between (P.char '"') (P.char '"')++-- | @parsecMaybeQuoted p = 'parsecQuoted' p <|> p@.+parsecMaybeQuoted :: CabalParsing m => m a -> m a+parsecMaybeQuoted p = parsecQuoted p <|> p++parsecUnqualComponentName :: forall m. CabalParsing m => m String+parsecUnqualComponentName = state0 DList.empty where+ --+ -- using @kleene@ package we can easily see that+ -- we need only two states to recognize+ -- unqual-component-name+ --+ -- Compare with declarative+ -- 'Distribution.FieldGrammar.Described.reUnqualComponent'.+ --+ -- @+ -- import Kleene+ -- import Kleene.Internal.Pretty+ -- import Algebra.Lattice+ -- import Data.Char+ --+ -- import qualified Data.RangeSet.Map as RSet+ --+ -- main = do+ -- -- this is an approximation, to get an idea.+ -- let component :: RE Char+ -- component = star alphaNum <> alpha <> star alphaNum+ --+ -- alphaNum = alpha \/ num+ -- alpha = unions $ map char ['a'..'z']+ -- num = unions $ map char ['0'..'9']+ --+ -- re :: RE Char+ -- re = component <> star (char '-' <> component)+ --+ -- putPretty re+ -- putPretty $ fromTM re+ -- @++ state0 :: DList.DList Char -> m String+ state0 acc = do+ c <- ch -- <|> fail ("Invalid component, after " ++ DList.toList acc)+ case () of+ _ | isDigit c -> state0 (DList.snoc acc c)+ | isAlphaNum c -> state1 (DList.snoc acc c)+ | c == '-' -> fail ("Empty component, after " ++ DList.toList acc)+ | otherwise -> fail ("Internal error, after " ++ DList.toList acc)++ state1 :: DList.DList Char -> m String+ state1 acc = state1' acc `alt` return (DList.toList acc)++ state1' :: DList.DList Char -> m String+ state1' acc = do+ c <- ch+ case () of+ _ | isAlphaNum c -> state1 (DList.snoc acc c)+ | c == '-' -> state0 (DList.snoc acc c)+ | otherwise -> fail ("Internal error, after " ++ DList.toList acc)++ ch :: m Char+ !ch = P.satisfy (\c -> isAlphaNum c || c == '-')++ alt :: m String -> m String -> m String+ !alt = (<|>)++stringLiteral :: forall m. P.CharParsing m => m String+stringLiteral = lit where+ lit :: m String+ lit = foldr (maybe id (:)) ""+ <$> P.between (P.char '"') (P.char '"' P.<?> "end of string") (many stringChar)+ P.<?> "string"++ stringChar :: m (Maybe Char)+ stringChar = Just <$> stringLetter+ <|> stringEscape+ P.<?> "string character"++ stringLetter :: m Char+ stringLetter = P.satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026'))++ stringEscape :: m (Maybe Char)+ stringEscape = P.char '\\' *> esc where+ esc :: m (Maybe Char)+ esc = Nothing <$ escapeGap+ <|> Nothing <$ escapeEmpty+ <|> Just <$> escapeCode++ escapeEmpty, escapeGap :: m Char+ escapeEmpty = P.char '&'+ escapeGap = P.skipSpaces1 *> (P.char '\\' P.<?> "end of string gap")++escapeCode :: forall m. P.CharParsing m => m Char+escapeCode = (charEsc <|> charNum <|> charAscii <|> charControl) P.<?> "escape code"+ where+ charControl, charNum :: m Char+ charControl = (\c -> toEnum (fromEnum c - fromEnum '@')) <$> (P.char '^' *> (P.upper <|> P.char '@'))+ charNum = toEnum <$> num+ where+ num :: m Int+ num = bounded 10 maxchar+ <|> (P.char 'o' *> bounded 8 maxchar)+ <|> (P.char 'x' *> bounded 16 maxchar)+ maxchar = fromEnum (maxBound :: Char)++ bounded :: Int -> Int -> m Int+ bounded base bnd = foldl' (\x d -> base * x + digitToInt d) 0+ <$> bounded' (take base thedigits) (map digitToInt $ showIntAtBase base intToDigit bnd "")+ where+ thedigits :: [m Char]+ thedigits = map P.char ['0'..'9'] ++ map P.oneOf (transpose [['A'..'F'],['a'..'f']])++ toomuch :: m a+ toomuch = P.unexpected "out-of-range numeric escape sequence"++ bounded', bounded'' :: [m Char] -> [Int] -> m [Char]+ bounded' dps@(zero:_) bds = P.skipSome zero *> ([] <$ P.notFollowedBy (P.choice dps) <|> bounded'' dps bds)+ <|> bounded'' dps bds+ bounded' [] _ = error "bounded called with base 0"+ bounded'' dps [] = [] <$ P.notFollowedBy (P.choice dps) <|> toomuch+ bounded'' dps (bd : bds) = let anyd :: m Char+ anyd = P.choice dps++ nomore :: m ()+ nomore = P.notFollowedBy anyd <|> toomuch++ (low, ex, high) = case splitAt bd dps of+ (low', ex' : high') -> (low', ex', high')+ (_, _) -> error "escapeCode: Logic error"+ in ((:) <$> P.choice low <*> atMost (length bds) anyd) <* nomore+ <|> ((:) <$> ex <*> ([] <$ nomore <|> bounded'' dps bds))+ <|> if not (null bds)+ then (:) <$> P.choice high <*> atMost (length bds - 1) anyd <* nomore+ else empty+ atMost n p | n <= 0 = pure []+ | otherwise = ((:) <$> p <*> atMost (n - 1) p) <|> pure []++ charEsc :: m Char+ charEsc = P.choice $ parseEsc <$> escMap++ parseEsc (c,code) = code <$ P.char c+ escMap = zip "abfnrtv\\\"\'" "\a\b\f\n\r\t\v\\\"\'"++ charAscii :: m Char+ charAscii = P.choice $ parseAscii <$> asciiMap++ parseAscii (asc,code) = P.try $ code <$ P.string asc+ asciiMap = zip (ascii3codes ++ ascii2codes) (ascii3 ++ ascii2)+ ascii2codes, ascii3codes :: [String]+ ascii2codes = [ "BS","HT","LF","VT","FF","CR","SO"+ , "SI","EM","FS","GS","RS","US","SP"]+ ascii3codes = ["NUL","SOH","STX","ETX","EOT","ENQ","ACK"+ ,"BEL","DLE","DC1","DC2","DC3","DC4","NAK"+ ,"SYN","ETB","CAN","SUB","ESC","DEL"]+ ascii2, ascii3 :: String+ ascii2 = "\BS\HT\LF\VT\FF\CR\SO\SI\EM\FS\GS\RS\US\SP"+ ascii3 = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK\BEL\DLE\DC1\DC2\DC3\DC4\NAK\SYN\ETB\CAN\SUB\ESC\DEL"
+ src/Distribution/Parsec/Error.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Parsec.Error (+ PError (..),+ showPError,+ ) where++import Distribution.Compat.Prelude+import Distribution.Parsec.Position+import Prelude ()+import System.FilePath (normalise)++-- | Parser error.+data PError = PError Position String+ deriving (Show, Generic)++instance Binary PError+instance NFData PError where rnf = genericRnf++showPError :: FilePath -> PError -> String+showPError fpath (PError pos msg) =+ normalise fpath ++ ":" ++ showPos pos ++ ": " ++ msg
+ src/Distribution/Parsec/FieldLineStream.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall -Werror #-}+module Distribution.Parsec.FieldLineStream (+ FieldLineStream (..),+ fieldLineStreamFromString,+ fieldLineStreamFromBS,+ fieldLineStreamEnd,+ ) where++import Data.Bits+import Data.ByteString (ByteString)+import Distribution.Compat.Prelude+import Distribution.Utils.Generic (toUTF8BS)+import Prelude ()++import qualified Data.ByteString as BS+import qualified Text.Parsec as Parsec++-- | This is essentially a lazy bytestring, but chunks are glued with newline @\'\\n\'@.+data FieldLineStream+ = FLSLast !ByteString+ | FLSCons {-# UNPACK #-} !ByteString FieldLineStream+ deriving Show++fieldLineStreamEnd :: FieldLineStream+fieldLineStreamEnd = FLSLast mempty++-- | Convert 'String' to 'FieldLineStream'.+--+-- /Note:/ inefficient!+fieldLineStreamFromString :: String -> FieldLineStream+fieldLineStreamFromString = FLSLast . toUTF8BS++fieldLineStreamFromBS :: ByteString -> FieldLineStream+fieldLineStreamFromBS = FLSLast++instance Monad m => Parsec.Stream FieldLineStream m Char where+ uncons (FLSLast bs) = return $ case BS.uncons bs of+ Nothing -> Nothing+ Just (c, bs') -> Just (unconsChar c bs' (\bs'' -> FLSLast bs'') fieldLineStreamEnd)++ uncons (FLSCons bs s) = return $ case BS.uncons bs of+ -- as lines are glued with '\n', we return '\n' here!+ Nothing -> Just ('\n', s)+ Just (c, bs') -> Just (unconsChar c bs' (\bs'' -> FLSCons bs'' s) s)++-- Based on implementation 'decodeStringUtf8'+unconsChar :: forall a. Word8 -> ByteString -> (ByteString -> a) -> a -> (Char, a)+unconsChar c0 bs0 f next+ | c0 <= 0x7F = (chr (fromIntegral c0), f bs0)+ | c0 <= 0xBF = (replacementChar, f bs0)+ | c0 <= 0xDF = twoBytes+ | c0 <= 0xEF = moreBytes 3 0x800 bs0 (fromIntegral $ c0 .&. 0xF)+ | c0 <= 0xF7 = moreBytes 4 0x10000 bs0 (fromIntegral $ c0 .&. 0x7)+ | c0 <= 0xFB = moreBytes 5 0x200000 bs0 (fromIntegral $ c0 .&. 0x3)+ | c0 <= 0xFD = moreBytes 6 0x4000000 bs0 (fromIntegral $ c0 .&. 0x1)+ | otherwise = error $ "not implemented " ++ show c0+ where+ twoBytes = case BS.uncons bs0 of+ Nothing -> (replacementChar, next)+ Just (c1, bs1)+ | c1 .&. 0xC0 == 0x80 ->+ if d >= 0x80+ then (chr d, f bs1)+ else (replacementChar, f bs1)+ | otherwise -> (replacementChar, f bs1)+ where+ d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6) .|. fromIntegral (c1 .&. 0x3F)++ moreBytes :: Int -> Int -> ByteString -> Int -> (Char, a)+ moreBytes 1 overlong bs' acc+ | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc+ = (chr acc, f bs')+ | otherwise+ = (replacementChar, f bs')++ moreBytes byteCount overlong bs' acc = case BS.uncons bs' of+ Nothing -> (replacementChar, f bs')+ Just (cn, bs1)+ | cn .&. 0xC0 == 0x80 -> moreBytes+ (byteCount-1)+ overlong+ bs1+ ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)+ | otherwise -> (replacementChar, f bs1)++replacementChar :: Char+replacementChar = '\xfffd'
+ src/Distribution/Parsec/Position.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Parsec.Position (+ Position (..),+ incPos,+ retPos,+ showPos,+ zeroPos,+ positionCol,+ positionRow,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++-- | 1-indexed row and column positions in a file.+data Position = Position+ {-# UNPACK #-} !Int -- row+ {-# UNPACK #-} !Int -- column+ deriving (Eq, Ord, Show, Generic)++instance Binary Position+instance NFData Position where rnf = genericRnf++-- | Shift position by n columns to the right.+incPos :: Int -> Position -> Position+incPos n (Position row col) = Position row (col + n)++-- | Shift position to beginning of next row.+retPos :: Position -> Position+retPos (Position row _col) = Position (row + 1) 1++showPos :: Position -> String+showPos (Position row col) = show row ++ ":" ++ show col++zeroPos :: Position+zeroPos = Position 0 0++-- | @since 3.0.0.0+positionCol :: Position -> Int+positionCol (Position _ c) = c++-- | @since 3.0.0.0+positionRow :: Position -> Int+positionRow (Position r _) = r
+ src/Distribution/Parsec/Warning.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Parsec.Warning (+ PWarning (..),+ PWarnType (..),+ showPWarning,+ ) where++import Distribution.Compat.Prelude+import Distribution.Parsec.Position+import Prelude ()+import System.FilePath (normalise)++-- | Type of parser warning. We do classify warnings.+--+-- Different application may decide not to show some, or have fatal behaviour on others+data PWarnType+ = PWTOther -- ^ Unclassified warning+ | PWTUTF -- ^ Invalid UTF encoding+ | PWTBoolCase -- ^ @true@ or @false@, not @True@ or @False@+ | PWTVersionTag -- ^ there are version with tags+ | PWTNewSyntax -- ^ New syntax used, but no @cabal-version: >= 1.2@ specified+ | PWTOldSyntax -- ^ Old syntax used, and @cabal-version >= 1.2@ specified+ | PWTDeprecatedField+ | PWTInvalidSubsection+ | PWTUnknownField+ | PWTUnknownSection+ | PWTTrailingFields+ | PWTExtraMainIs -- ^ extra main-is field+ | PWTExtraTestModule -- ^ extra test-module field+ | PWTExtraBenchmarkModule -- ^ extra benchmark-module field+ | PWTLexNBSP+ | PWTLexBOM+ | PWTLexTab+ | PWTQuirkyCabalFile -- ^ legacy cabal file that we know how to patch+ | PWTDoubleDash -- ^ Double dash token, most likely it's a mistake - it's not a comment+ | PWTMultipleSingularField -- ^ e.g. name or version should be specified only once.+ | PWTBuildTypeDefault -- ^ Workaround for derive-package having build-type: Default. See <https://github.com/haskell/cabal/issues/5020>.++ | PWTVersionOperator -- ^ Version operators used (without cabal-version: 1.8)+ | PWTVersionWildcard -- ^ Version wildcard used (without cabal-version: 1.6)++ | PWTSpecVersion -- ^ Warnings about cabal-version format.++ | PWTEmptyFilePath -- ^ Empty filepath, i.e. literally ""++ | PWTExperimental -- ^ Experimental feature+ deriving (Eq, Ord, Show, Enum, Bounded, Generic)++instance Binary PWarnType+instance NFData PWarnType where rnf = genericRnf++-- | Parser warning.+data PWarning = PWarning !PWarnType !Position String+ deriving (Show, Generic)++instance Binary PWarning+instance NFData PWarning where rnf = genericRnf++showPWarning :: FilePath -> PWarning -> String+showPWarning fpath (PWarning _ pos msg) =+ normalise fpath ++ ":" ++ showPos pos ++ ": " ++ msg
+ src/Distribution/Pretty.hs view
@@ -0,0 +1,110 @@+module Distribution.Pretty (+ Pretty (..),+ prettyShow,+ defaultStyle,+ flatStyle,+ -- * Utilities+ showFilePath,+ showToken,+ showTokenStr,+ showFreeText,+ showFreeTextV3,+ -- * Deprecated+ Separator,+ ) where++import Distribution.CabalSpecVersion+import Distribution.Compat.Prelude+import Prelude ()++import qualified Text.PrettyPrint as PP++class Pretty a where+ pretty :: a -> PP.Doc++ prettyVersioned :: CabalSpecVersion -> a -> PP.Doc+ prettyVersioned _ = pretty++-- | @since 3.4.0.0+instance Pretty PP.Doc where+ pretty = id++instance Pretty Bool where+ pretty = PP.text . show++instance Pretty Int where+ pretty = PP.text . show++instance Pretty a => Pretty (Identity a) where+ pretty = pretty . runIdentity++prettyShow :: Pretty a => a -> String+prettyShow = PP.renderStyle defaultStyle . pretty++-- | The default rendering style used in Cabal for console+-- output. It has a fixed page width and adds line breaks+-- automatically.+defaultStyle :: PP.Style+defaultStyle = PP.Style { PP.mode = PP.PageMode+ , PP.lineLength = 79+ , PP.ribbonsPerLine = 1.0+ }++-- | A style for rendering all on one line.+flatStyle :: PP.Style+flatStyle = PP.Style { PP.mode = PP.LeftMode+ , PP.lineLength = err "lineLength"+ , PP.ribbonsPerLine = err "ribbonsPerLine"+ }+ where+ err x = error ("flatStyle: tried to access " ++ x ++ " in LeftMode. " +++ "This should never happen and indicates a bug in Cabal.")++-------------------------------------------------------------------------------+-- Utilities+-------------------------------------------------------------------------------++-- TODO: remove when ReadP parser is gone.+type Separator = [PP.Doc] -> PP.Doc++showFilePath :: FilePath -> PP.Doc+showFilePath = showToken++showToken :: String -> PP.Doc+showToken = PP.text . showTokenStr++showTokenStr :: String -> String+showTokenStr str+ -- if token looks like a comment (starts with --), print it in quotes+ | "--" `isPrefixOf` str = show str+ -- also if token ends with a colon (e.g. executable name), print it in quotes+ | ":" `isSuffixOf` str = show str+ | not (any dodgy str) && not (null str) = str+ | otherwise = show str+ where+ dodgy c = isSpace c || c == ','+++-- | Pretty-print free-format text, ensuring that it is vertically aligned,+-- and with blank lines replaced by dots for correct re-parsing.+showFreeText :: String -> PP.Doc+showFreeText "" = mempty+showFreeText s = PP.vcat [ PP.text (if null l then "." else l) | l <- lines_ s ]++-- | Pretty-print free-format text.+-- Since @cabal-version: 3.0@ we don't replace blank lines with dots.+--+-- @since 3.0.0.0+showFreeTextV3 :: String -> PP.Doc+showFreeTextV3 "" = mempty+showFreeTextV3 s = PP.vcat [ PP.text l | l <- lines_ s ]++-- | 'lines_' breaks a string up into a list of strings at newline+-- characters. The resulting strings do not contain newlines.+lines_ :: String -> [String]+lines_ [] = [""]+lines_ s =+ let (l, s') = break (== '\n') s+ in l : case s' of+ [] -> []+ (_:s'') -> lines_ s''
+ src/Distribution/ReadE.hs view
@@ -0,0 +1,49 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.ReadE+-- Copyright : Jose Iborra 2008+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Simple parsing with failure++module Distribution.ReadE (+ -- * ReadE+ ReadE(..), succeedReadE, failReadE,+ -- * Projections+ readEOrFail,+ parsecToReadE,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Parsec.FieldLineStream++-- | Parser with simple error reporting+newtype ReadE a = ReadE {runReadE :: String -> Either ErrorMsg a}+type ErrorMsg = String++instance Functor ReadE where+ fmap f (ReadE p) = ReadE $ \txt -> case p txt of+ Right a -> Right (f a)+ Left err -> Left err++succeedReadE :: (String -> a) -> ReadE a+succeedReadE f = ReadE (Right . f)++failReadE :: ErrorMsg -> ReadE a+failReadE = ReadE . const . Left++readEOrFail :: ReadE a -> String -> a+readEOrFail r = either error id . runReadE r++parsecToReadE :: (String -> ErrorMsg) -> ParsecParser a -> ReadE a+parsecToReadE err p = ReadE $ \txt ->+ case runParsecParser p "<parsecToReadE>" (fieldLineStreamFromString txt) of+ Right x -> Right x+ Left _e -> Left (err txt)+-- TODO: use parsec error to make 'ErrorMsg'.
+ src/Distribution/SPDX.hs view
@@ -0,0 +1,40 @@+-- | This module implements SPDX specification version 2.1 with a version 3.0 license list.+--+-- Specification is available on <https://spdx.org/specifications>+module Distribution.SPDX (+ -- * License+ License (..),+ -- * License expression+ LicenseExpression (..),+ SimpleLicenseExpression (..),+ simpleLicenseExpression,+ -- * License identifier+ LicenseId (..),+ licenseId,+ licenseName,+ licenseIsOsiApproved,+ mkLicenseId,+ licenseIdList,+ -- * License exception+ LicenseExceptionId (..),+ licenseExceptionId,+ licenseExceptionName,+ mkLicenseExceptionId,+ licenseExceptionIdList,+ -- * License reference+ LicenseRef,+ licenseRef,+ licenseDocumentRef,+ mkLicenseRef,+ mkLicenseRef',+ -- * License list version+ LicenseListVersion (..),+ cabalSpecVersionToSPDXListVersion,+ ) where++import Distribution.SPDX.LicenseExceptionId+import Distribution.SPDX.License+import Distribution.SPDX.LicenseId+import Distribution.SPDX.LicenseExpression+import Distribution.SPDX.LicenseReference+import Distribution.SPDX.LicenseListVersion
+ src/Distribution/SPDX/License.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.SPDX.License (+ License (..),+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Pretty+import Distribution.Parsec+import Distribution.SPDX.LicenseExpression++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | Declared license.+-- See [section 3.15 of SPDX Specification 2.1](https://spdx.org/spdx-specification-21-web-version#h.1hmsyys)+--+-- /Note:/ the NOASSERTION case is omitted.+--+-- Old 'License' can be migrated using following rules:+--+-- * @AllRightsReserved@ and @UnspecifiedLicense@ to 'NONE'.+-- No license specified which legally defaults to /All Rights Reserved/.+-- The package may not be legally modified or redistributed by anyone but+-- the rightsholder.+--+-- * @OtherLicense@ can be converted to 'LicenseRef' pointing to the file+-- in the package.+--+-- * @UnknownLicense@ i.e. other licenses of the form @name-x.y@, should be+-- covered by SPDX license list, otherwise use 'LicenseRef'.+--+-- * @PublicDomain@ isn't covered. Consider using CC0.+-- See <https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files>+-- for more information.+--+data License+ = NONE+ -- ^ if the package contains no license information whatsoever; or+ | License LicenseExpression+ -- ^ A valid SPDX License Expression as defined in Appendix IV.+ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)++instance Binary License+instance Structured License++instance NFData License where+ rnf NONE = ()+ rnf (License l) = rnf l++instance Pretty License where+ pretty NONE = Disp.text "NONE"+ pretty (License l) = pretty l++-- |+-- >>> eitherParsec "BSD-3-Clause AND MIT" :: Either String License+-- Right (License (EAnd (ELicense (ELicenseId BSD_3_Clause) Nothing) (ELicense (ELicenseId MIT) Nothing)))+--+-- >>> eitherParsec "NONE" :: Either String License+-- Right NONE+--+instance Parsec License where+ parsec = NONE <$ P.try (P.string "NONE") <|> License <$> parsec
+ src/Distribution/SPDX/LicenseExceptionId.hs view
@@ -0,0 +1,316 @@+-- This file is generated. See Makefile's spdx rule+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.SPDX.LicenseExceptionId (+ LicenseExceptionId (..),+ licenseExceptionId,+ licenseExceptionName,+ mkLicenseExceptionId,+ licenseExceptionIdList,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Compat.Lens (set)+import Distribution.Pretty+import Distribution.Parsec+import Distribution.Utils.Generic (isAsciiAlphaNum)+import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion)+import Distribution.SPDX.LicenseListVersion++import qualified Data.Binary.Get as Binary+import qualified Data.Binary.Put as Binary+import qualified Data.Map.Strict as Map+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-------------------------------------------------------------------------------+-- LicenseExceptionId+-------------------------------------------------------------------------------++-- | SPDX License identifier+data LicenseExceptionId+ = DS389_exception -- ^ @389-exception@, 389 Directory Server Exception+ | Autoconf_exception_2_0 -- ^ @Autoconf-exception-2.0@, Autoconf exception 2.0+ | Autoconf_exception_3_0 -- ^ @Autoconf-exception-3.0@, Autoconf exception 3.0+ | Bison_exception_2_2 -- ^ @Bison-exception-2.2@, Bison exception 2.2+ | Bootloader_exception -- ^ @Bootloader-exception@, Bootloader Distribution Exception+ | Classpath_exception_2_0 -- ^ @Classpath-exception-2.0@, Classpath exception 2.0+ | CLISP_exception_2_0 -- ^ @CLISP-exception-2.0@, CLISP exception 2.0+ | DigiRule_FOSS_exception -- ^ @DigiRule-FOSS-exception@, DigiRule FOSS License Exception+ | ECos_exception_2_0 -- ^ @eCos-exception-2.0@, eCos exception 2.0+ | Fawkes_Runtime_exception -- ^ @Fawkes-Runtime-exception@, Fawkes Runtime Exception+ | FLTK_exception -- ^ @FLTK-exception@, FLTK exception+ | Font_exception_2_0 -- ^ @Font-exception-2.0@, Font exception 2.0+ | Freertos_exception_2_0 -- ^ @freertos-exception-2.0@, FreeRTOS Exception 2.0+ | GCC_exception_2_0 -- ^ @GCC-exception-2.0@, GCC Runtime Library exception 2.0+ | GCC_exception_3_1 -- ^ @GCC-exception-3.1@, GCC Runtime Library exception 3.1+ | Gnu_javamail_exception -- ^ @gnu-javamail-exception@, GNU JavaMail exception+ | GPL_3_0_linking_exception -- ^ @GPL-3.0-linking-exception@, GPL-3.0 Linking Exception, SPDX License List 3.9, SPDX License List 3.10+ | GPL_3_0_linking_source_exception -- ^ @GPL-3.0-linking-source-exception@, GPL-3.0 Linking Exception (with Corresponding Source), SPDX License List 3.9, SPDX License List 3.10+ | GPL_CC_1_0 -- ^ @GPL-CC-1.0@, GPL Cooperation Commitment 1.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | I2p_gpl_java_exception -- ^ @i2p-gpl-java-exception@, i2p GPL+Java Exception+ | LGPL_3_0_linking_exception -- ^ @LGPL-3.0-linking-exception@, LGPL-3.0 Linking Exception, SPDX License List 3.9, SPDX License List 3.10+ | Libtool_exception -- ^ @Libtool-exception@, Libtool Exception+ | Linux_syscall_note -- ^ @Linux-syscall-note@, Linux Syscall Note+ | LLVM_exception -- ^ @LLVM-exception@, LLVM Exception, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | LZMA_exception -- ^ @LZMA-exception@, LZMA exception+ | Mif_exception -- ^ @mif-exception@, Macros and Inline Functions Exception+ | Nokia_Qt_exception_1_1 -- ^ @Nokia-Qt-exception-1.1@, Nokia Qt LGPL exception 1.1, SPDX License List 3.0, SPDX License List 3.2+ | OCaml_LGPL_linking_exception -- ^ @OCaml-LGPL-linking-exception@, OCaml LGPL Linking Exception, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | OCCT_exception_1_0 -- ^ @OCCT-exception-1.0@, Open CASCADE Exception 1.0+ | OpenJDK_assembly_exception_1_0 -- ^ @OpenJDK-assembly-exception-1.0@, OpenJDK Assembly exception 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Openvpn_openssl_exception -- ^ @openvpn-openssl-exception@, OpenVPN OpenSSL Exception+ | PS_or_PDF_font_exception_20170817 -- ^ @PS-or-PDF-font-exception-20170817@, PS/PDF font exception (2017-08-17), SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Qt_GPL_exception_1_0 -- ^ @Qt-GPL-exception-1.0@, Qt GPL exception 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Qt_LGPL_exception_1_1 -- ^ @Qt-LGPL-exception-1.1@, Qt LGPL exception 1.1, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Qwt_exception_1_0 -- ^ @Qwt-exception-1.0@, Qwt exception 1.0+ | SHL_2_0 -- ^ @SHL-2.0@, Solderpad Hardware License v2.0, SPDX License List 3.9, SPDX License List 3.10+ | SHL_2_1 -- ^ @SHL-2.1@, Solderpad Hardware License v2.1, SPDX License List 3.9, SPDX License List 3.10+ | Swift_exception -- ^ @Swift-exception@, Swift Exception, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | U_boot_exception_2_0 -- ^ @u-boot-exception-2.0@, U-Boot exception 2.0+ | Universal_FOSS_exception_1_0 -- ^ @Universal-FOSS-exception-1.0@, Universal FOSS Exception, Version 1.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | WxWindows_exception_3_1 -- ^ @WxWindows-exception-3.1@, WxWindows Library Exception 3.1+ deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)++instance Binary LicenseExceptionId where+ put = Binary.putWord8 . fromIntegral . fromEnum+ get = do+ i <- Binary.getWord8+ if i > fromIntegral (fromEnum (maxBound :: LicenseExceptionId))+ then fail "Too large LicenseExceptionId tag"+ else return (toEnum (fromIntegral i))++-- note: remember to bump version each time the definition changes+instance Structured LicenseExceptionId where+ structure p = set typeVersion 306 $ nominalStructure p++instance Pretty LicenseExceptionId where+ pretty = Disp.text . licenseExceptionId++instance Parsec LicenseExceptionId where+ parsec = do+ n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'+ v <- askCabalSpecVersion+ maybe (fail $ "Unknown SPDX license exception identifier: " ++ n) return $+ mkLicenseExceptionId (cabalSpecVersionToSPDXListVersion v) n++instance NFData LicenseExceptionId where+ rnf l = l `seq` ()++-------------------------------------------------------------------------------+-- License Data+-------------------------------------------------------------------------------++-- | License SPDX identifier, e.g. @"BSD-3-Clause"@.+licenseExceptionId :: LicenseExceptionId -> String+licenseExceptionId DS389_exception = "389-exception"+licenseExceptionId Autoconf_exception_2_0 = "Autoconf-exception-2.0"+licenseExceptionId Autoconf_exception_3_0 = "Autoconf-exception-3.0"+licenseExceptionId Bison_exception_2_2 = "Bison-exception-2.2"+licenseExceptionId Bootloader_exception = "Bootloader-exception"+licenseExceptionId Classpath_exception_2_0 = "Classpath-exception-2.0"+licenseExceptionId CLISP_exception_2_0 = "CLISP-exception-2.0"+licenseExceptionId DigiRule_FOSS_exception = "DigiRule-FOSS-exception"+licenseExceptionId ECos_exception_2_0 = "eCos-exception-2.0"+licenseExceptionId Fawkes_Runtime_exception = "Fawkes-Runtime-exception"+licenseExceptionId FLTK_exception = "FLTK-exception"+licenseExceptionId Font_exception_2_0 = "Font-exception-2.0"+licenseExceptionId Freertos_exception_2_0 = "freertos-exception-2.0"+licenseExceptionId GCC_exception_2_0 = "GCC-exception-2.0"+licenseExceptionId GCC_exception_3_1 = "GCC-exception-3.1"+licenseExceptionId Gnu_javamail_exception = "gnu-javamail-exception"+licenseExceptionId GPL_3_0_linking_exception = "GPL-3.0-linking-exception"+licenseExceptionId GPL_3_0_linking_source_exception = "GPL-3.0-linking-source-exception"+licenseExceptionId GPL_CC_1_0 = "GPL-CC-1.0"+licenseExceptionId I2p_gpl_java_exception = "i2p-gpl-java-exception"+licenseExceptionId LGPL_3_0_linking_exception = "LGPL-3.0-linking-exception"+licenseExceptionId Libtool_exception = "Libtool-exception"+licenseExceptionId Linux_syscall_note = "Linux-syscall-note"+licenseExceptionId LLVM_exception = "LLVM-exception"+licenseExceptionId LZMA_exception = "LZMA-exception"+licenseExceptionId Mif_exception = "mif-exception"+licenseExceptionId Nokia_Qt_exception_1_1 = "Nokia-Qt-exception-1.1"+licenseExceptionId OCaml_LGPL_linking_exception = "OCaml-LGPL-linking-exception"+licenseExceptionId OCCT_exception_1_0 = "OCCT-exception-1.0"+licenseExceptionId OpenJDK_assembly_exception_1_0 = "OpenJDK-assembly-exception-1.0"+licenseExceptionId Openvpn_openssl_exception = "openvpn-openssl-exception"+licenseExceptionId PS_or_PDF_font_exception_20170817 = "PS-or-PDF-font-exception-20170817"+licenseExceptionId Qt_GPL_exception_1_0 = "Qt-GPL-exception-1.0"+licenseExceptionId Qt_LGPL_exception_1_1 = "Qt-LGPL-exception-1.1"+licenseExceptionId Qwt_exception_1_0 = "Qwt-exception-1.0"+licenseExceptionId SHL_2_0 = "SHL-2.0"+licenseExceptionId SHL_2_1 = "SHL-2.1"+licenseExceptionId Swift_exception = "Swift-exception"+licenseExceptionId U_boot_exception_2_0 = "u-boot-exception-2.0"+licenseExceptionId Universal_FOSS_exception_1_0 = "Universal-FOSS-exception-1.0"+licenseExceptionId WxWindows_exception_3_1 = "WxWindows-exception-3.1"++-- | License name, e.g. @"GNU General Public License v2.0 only"@+licenseExceptionName :: LicenseExceptionId -> String+licenseExceptionName DS389_exception = "389 Directory Server Exception"+licenseExceptionName Autoconf_exception_2_0 = "Autoconf exception 2.0"+licenseExceptionName Autoconf_exception_3_0 = "Autoconf exception 3.0"+licenseExceptionName Bison_exception_2_2 = "Bison exception 2.2"+licenseExceptionName Bootloader_exception = "Bootloader Distribution Exception"+licenseExceptionName Classpath_exception_2_0 = "Classpath exception 2.0"+licenseExceptionName CLISP_exception_2_0 = "CLISP exception 2.0"+licenseExceptionName DigiRule_FOSS_exception = "DigiRule FOSS License Exception"+licenseExceptionName ECos_exception_2_0 = "eCos exception 2.0"+licenseExceptionName Fawkes_Runtime_exception = "Fawkes Runtime Exception"+licenseExceptionName FLTK_exception = "FLTK exception"+licenseExceptionName Font_exception_2_0 = "Font exception 2.0"+licenseExceptionName Freertos_exception_2_0 = "FreeRTOS Exception 2.0"+licenseExceptionName GCC_exception_2_0 = "GCC Runtime Library exception 2.0"+licenseExceptionName GCC_exception_3_1 = "GCC Runtime Library exception 3.1"+licenseExceptionName Gnu_javamail_exception = "GNU JavaMail exception"+licenseExceptionName GPL_3_0_linking_exception = "GPL-3.0 Linking Exception"+licenseExceptionName GPL_3_0_linking_source_exception = "GPL-3.0 Linking Exception (with Corresponding Source)"+licenseExceptionName GPL_CC_1_0 = "GPL Cooperation Commitment 1.0"+licenseExceptionName I2p_gpl_java_exception = "i2p GPL+Java Exception"+licenseExceptionName LGPL_3_0_linking_exception = "LGPL-3.0 Linking Exception"+licenseExceptionName Libtool_exception = "Libtool Exception"+licenseExceptionName Linux_syscall_note = "Linux Syscall Note"+licenseExceptionName LLVM_exception = "LLVM Exception"+licenseExceptionName LZMA_exception = "LZMA exception"+licenseExceptionName Mif_exception = "Macros and Inline Functions Exception"+licenseExceptionName Nokia_Qt_exception_1_1 = "Nokia Qt LGPL exception 1.1"+licenseExceptionName OCaml_LGPL_linking_exception = "OCaml LGPL Linking Exception"+licenseExceptionName OCCT_exception_1_0 = "Open CASCADE Exception 1.0"+licenseExceptionName OpenJDK_assembly_exception_1_0 = "OpenJDK Assembly exception 1.0"+licenseExceptionName Openvpn_openssl_exception = "OpenVPN OpenSSL Exception"+licenseExceptionName PS_or_PDF_font_exception_20170817 = "PS/PDF font exception (2017-08-17)"+licenseExceptionName Qt_GPL_exception_1_0 = "Qt GPL exception 1.0"+licenseExceptionName Qt_LGPL_exception_1_1 = "Qt LGPL exception 1.1"+licenseExceptionName Qwt_exception_1_0 = "Qwt exception 1.0"+licenseExceptionName SHL_2_0 = "Solderpad Hardware License v2.0"+licenseExceptionName SHL_2_1 = "Solderpad Hardware License v2.1"+licenseExceptionName Swift_exception = "Swift Exception"+licenseExceptionName U_boot_exception_2_0 = "U-Boot exception 2.0"+licenseExceptionName Universal_FOSS_exception_1_0 = "Universal FOSS Exception, Version 1.0"+licenseExceptionName WxWindows_exception_3_1 = "WxWindows Library Exception 3.1"++-------------------------------------------------------------------------------+-- Creation+-------------------------------------------------------------------------------++licenseExceptionIdList :: LicenseListVersion -> [LicenseExceptionId]+licenseExceptionIdList LicenseListVersion_3_0 =+ [ Nokia_Qt_exception_1_1+ ]+ ++ bulkOfLicenses+licenseExceptionIdList LicenseListVersion_3_2 =+ [ LLVM_exception+ , Nokia_Qt_exception_1_1+ , OpenJDK_assembly_exception_1_0+ , PS_or_PDF_font_exception_20170817+ , Qt_GPL_exception_1_0+ , Qt_LGPL_exception_1_1+ ]+ ++ bulkOfLicenses+licenseExceptionIdList LicenseListVersion_3_6 =+ [ GPL_CC_1_0+ , LLVM_exception+ , OCaml_LGPL_linking_exception+ , OpenJDK_assembly_exception_1_0+ , PS_or_PDF_font_exception_20170817+ , Qt_GPL_exception_1_0+ , Qt_LGPL_exception_1_1+ , Swift_exception+ , Universal_FOSS_exception_1_0+ ]+ ++ bulkOfLicenses+licenseExceptionIdList LicenseListVersion_3_9 =+ [ GPL_3_0_linking_exception+ , GPL_3_0_linking_source_exception+ , GPL_CC_1_0+ , LGPL_3_0_linking_exception+ , LLVM_exception+ , OCaml_LGPL_linking_exception+ , OpenJDK_assembly_exception_1_0+ , PS_or_PDF_font_exception_20170817+ , Qt_GPL_exception_1_0+ , Qt_LGPL_exception_1_1+ , SHL_2_0+ , SHL_2_1+ , Swift_exception+ , Universal_FOSS_exception_1_0+ ]+ ++ bulkOfLicenses+licenseExceptionIdList LicenseListVersion_3_10 =+ [ GPL_3_0_linking_exception+ , GPL_3_0_linking_source_exception+ , GPL_CC_1_0+ , LGPL_3_0_linking_exception+ , LLVM_exception+ , OCaml_LGPL_linking_exception+ , OpenJDK_assembly_exception_1_0+ , PS_or_PDF_font_exception_20170817+ , Qt_GPL_exception_1_0+ , Qt_LGPL_exception_1_1+ , SHL_2_0+ , SHL_2_1+ , Swift_exception+ , Universal_FOSS_exception_1_0+ ]+ ++ bulkOfLicenses++-- | Create a 'LicenseExceptionId' from a 'String'.+mkLicenseExceptionId :: LicenseListVersion -> String -> Maybe LicenseExceptionId+mkLicenseExceptionId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0+mkLicenseExceptionId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2+mkLicenseExceptionId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6+mkLicenseExceptionId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9+mkLicenseExceptionId LicenseListVersion_3_10 s = Map.lookup s stringLookup_3_10++stringLookup_3_0 :: Map String LicenseExceptionId+stringLookup_3_0 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $+ licenseExceptionIdList LicenseListVersion_3_0++stringLookup_3_2 :: Map String LicenseExceptionId+stringLookup_3_2 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $+ licenseExceptionIdList LicenseListVersion_3_2++stringLookup_3_6 :: Map String LicenseExceptionId+stringLookup_3_6 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $+ licenseExceptionIdList LicenseListVersion_3_6++stringLookup_3_9 :: Map String LicenseExceptionId+stringLookup_3_9 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $+ licenseExceptionIdList LicenseListVersion_3_9++stringLookup_3_10 :: Map String LicenseExceptionId+stringLookup_3_10 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $+ licenseExceptionIdList LicenseListVersion_3_10++-- | License exceptions in all SPDX License lists+bulkOfLicenses :: [LicenseExceptionId]+bulkOfLicenses =+ [ DS389_exception+ , Autoconf_exception_2_0+ , Autoconf_exception_3_0+ , Bison_exception_2_2+ , Bootloader_exception+ , Classpath_exception_2_0+ , CLISP_exception_2_0+ , DigiRule_FOSS_exception+ , ECos_exception_2_0+ , Fawkes_Runtime_exception+ , FLTK_exception+ , Font_exception_2_0+ , Freertos_exception_2_0+ , GCC_exception_2_0+ , GCC_exception_3_1+ , Gnu_javamail_exception+ , I2p_gpl_java_exception+ , Libtool_exception+ , Linux_syscall_note+ , LZMA_exception+ , Mif_exception+ , OCCT_exception_1_0+ , Openvpn_openssl_exception+ , Qwt_exception_1_0+ , U_boot_exception_2_0+ , WxWindows_exception_3_1+ ]
+ src/Distribution/SPDX/LicenseExpression.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.SPDX.LicenseExpression (+ LicenseExpression (..),+ SimpleLicenseExpression (..),+ simpleLicenseExpression,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.SPDX.LicenseExceptionId+import Distribution.SPDX.LicenseId+import Distribution.SPDX.LicenseListVersion+import Distribution.SPDX.LicenseReference+import Distribution.Utils.Generic (isAsciiAlphaNum)++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | SPDX License Expression.+--+-- @+-- idstring = 1*(ALPHA \/ DIGIT \/ "-" \/ "." )+-- license id = \<short form license identifier inAppendix I.1>+-- license exception id = \<short form license exception identifier inAppendix I.2>+-- license ref = [\"DocumentRef-"1*(idstring)":"]\"LicenseRef-"1*(idstring)+--+-- simple expression = license id \/ license id"+" \/ license ref+--+-- compound expression = 1*1(simple expression \/+-- simple expression \"WITH" license exception id \/+-- compound expression \"AND" compound expression \/+-- compound expression \"OR" compound expression ) \/+-- "(" compound expression ")" )+--+-- license expression = 1*1(simple expression / compound expression)+-- @+data LicenseExpression+ = ELicense !SimpleLicenseExpression !(Maybe LicenseExceptionId)+ | EAnd !LicenseExpression !LicenseExpression+ | EOr !LicenseExpression !LicenseExpression+ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)++-- | Simple License Expressions.+data SimpleLicenseExpression+ = ELicenseId LicenseId+ -- ^ An SPDX License List Short Form Identifier. For example: @GPL-2.0-only@+ | ELicenseIdPlus LicenseId+ -- ^ An SPDX License List Short Form Identifier with a unary"+" operator suffix to represent the current version of the license or any later version. For example: @GPL-2.0+@+ | ELicenseRef LicenseRef+ -- ^ A SPDX user defined license reference: For example: @LicenseRef-23@, @LicenseRef-MIT-Style-1@, or @DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2@+ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)++simpleLicenseExpression :: LicenseId -> LicenseExpression+simpleLicenseExpression i = ELicense (ELicenseId i) Nothing++instance Binary LicenseExpression+instance Binary SimpleLicenseExpression+instance Structured SimpleLicenseExpression+instance Structured LicenseExpression++instance Pretty LicenseExpression where+ pretty = go 0+ where+ go :: Int -> LicenseExpression -> Disp.Doc+ go _ (ELicense lic exc) =+ let doc = pretty lic+ in maybe id (\e d -> d <+> Disp.text "WITH" <+> pretty e) exc doc+ go d (EAnd e1 e2) = parens (d < 0) $ go 0 e1 <+> Disp.text "AND" <+> go 0 e2+ go d (EOr e1 e2) = parens (d < 1) $ go 1 e1 <+> Disp.text "OR" <+> go 1 e2+++ parens False doc = doc+ parens True doc = Disp.parens doc++instance Pretty SimpleLicenseExpression where+ pretty (ELicenseId i) = pretty i+ pretty (ELicenseIdPlus i) = pretty i <<>> Disp.char '+'+ pretty (ELicenseRef r) = pretty r++instance Parsec SimpleLicenseExpression where+ parsec = idstring >>= simple where+ simple n+ | Just l <- "LicenseRef-" `isPrefixOfMaybe` n =+ maybe (fail $ "Incorrect LicenseRef format: " ++ n) (return . ELicenseRef) $ mkLicenseRef Nothing l+ | Just d <- "DocumentRef-" `isPrefixOfMaybe` n = do+ _ <- P.string ":LicenseRef-"+ l <- idstring+ maybe (fail $ "Incorrect LicenseRef format:" ++ n) (return . ELicenseRef) $ mkLicenseRef (Just d) l+ | otherwise = do+ v <- askCabalSpecVersion+ l <- maybe (fail $ "Unknown SPDX license identifier: '" ++ n ++ "' " ++ licenseIdMigrationMessage n) return $+ mkLicenseId (cabalSpecVersionToSPDXListVersion v) n+ orLater <- isJust <$> P.optional (P.char '+')+ if orLater+ then return (ELicenseIdPlus l)+ else return (ELicenseId l)++idstring :: P.CharParsing m => m String+idstring = P.munch1 $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'++-- returns suffix part+isPrefixOfMaybe :: Eq a => [a] -> [a] -> Maybe [a]+isPrefixOfMaybe pfx s+ | pfx `isPrefixOf` s = Just (drop (length pfx) s)+ | otherwise = Nothing++instance Parsec LicenseExpression where+ parsec = expr+ where+ expr = compoundOr++ simple = do+ s <- parsec+ exc <- exception+ return $ ELicense s exc++ exception = P.optional $ P.try (spaces1 *> P.string "WITH" *> spaces1) *> parsec++ compoundOr = do+ x <- compoundAnd+ l <- P.optional $ P.try (spaces1 *> P.string "OR" *> spaces1) *> compoundOr+ return $ maybe id (flip EOr) l x++ compoundAnd = do+ x <- compound+ l <- P.optional $ P.try (spaces1 *> P.string "AND" *> spaces1) *> compoundAnd+ return $ maybe id (flip EAnd) l x++ compound = braces <|> simple++ -- NOTE: we require that there's a space around AND & OR operators,+ -- i.e. @(MIT)AND(MIT)@ will cause parse-error.+ braces = do+ _ <- P.char '('+ _ <- P.spaces+ x <- expr+ _ <- P.char ')'+ return x++ spaces1 = P.space *> P.spaces++-- notes:+--+-- There MUST NOT be whitespace between a licenseid and any following "+". This supports easy parsing and+-- backwards compatibility. There MUST be whitespace on either side of the operator "WITH". There MUST be+-- whitespace and/or parentheses on either side of the operators "AND" and "OR".+--+-- We handle that by having greedy 'idstring' parser, so MITAND would parse as invalid license identifier.++instance NFData LicenseExpression where+ rnf (ELicense s e) = rnf s `seq` rnf e+ rnf (EAnd x y) = rnf x `seq` rnf y+ rnf (EOr x y) = rnf x `seq` rnf y++instance NFData SimpleLicenseExpression where+ rnf (ELicenseId i) = rnf i+ rnf (ELicenseIdPlus i) = rnf i+ rnf (ELicenseRef r) = rnf r
+ src/Distribution/SPDX/LicenseId.hs view
@@ -0,0 +1,2152 @@+-- This file is generated. See Makefile's spdx rule+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.SPDX.LicenseId (+ LicenseId (..),+ licenseId,+ licenseName,+ licenseIsOsiApproved,+ licenseIsFsfLibre,+ mkLicenseId,+ licenseIdList,+ -- * Helpers+ licenseIdMigrationMessage,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Compat.Lens (set)+import Distribution.Pretty+import Distribution.Parsec+import Distribution.Utils.Generic (isAsciiAlphaNum)+import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion)+import Distribution.SPDX.LicenseListVersion++import qualified Data.Binary.Get as Binary+import qualified Data.Binary.Put as Binary+import qualified Data.Map.Strict as Map+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-------------------------------------------------------------------------------+-- LicenseId+-------------------------------------------------------------------------------++-- | SPDX License identifier+data LicenseId+ = NullBSD -- ^ @0BSD@, BSD Zero Clause License+ | AAL -- ^ @AAL@, Attribution Assurance License+ | Abstyles -- ^ @Abstyles@, Abstyles License+ | Adobe_2006 -- ^ @Adobe-2006@, Adobe Systems Incorporated Source Code License Agreement+ | Adobe_Glyph -- ^ @Adobe-Glyph@, Adobe Glyph List License+ | ADSL -- ^ @ADSL@, Amazon Digital Services License+ | AFL_1_1 -- ^ @AFL-1.1@, Academic Free License v1.1+ | AFL_1_2 -- ^ @AFL-1.2@, Academic Free License v1.2+ | AFL_2_0 -- ^ @AFL-2.0@, Academic Free License v2.0+ | AFL_2_1 -- ^ @AFL-2.1@, Academic Free License v2.1+ | AFL_3_0 -- ^ @AFL-3.0@, Academic Free License v3.0+ | Afmparse -- ^ @Afmparse@, Afmparse License+ | AGPL_1_0 -- ^ @AGPL-1.0@, Affero General Public License v1.0, SPDX License List 3.0+ | AGPL_1_0_only -- ^ @AGPL-1.0-only@, Affero General Public License v1.0 only, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | AGPL_1_0_or_later -- ^ @AGPL-1.0-or-later@, Affero General Public License v1.0 or later, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | AGPL_3_0_only -- ^ @AGPL-3.0-only@, GNU Affero General Public License v3.0 only+ | AGPL_3_0_or_later -- ^ @AGPL-3.0-or-later@, GNU Affero General Public License v3.0 or later+ | Aladdin -- ^ @Aladdin@, Aladdin Free Public License+ | AMDPLPA -- ^ @AMDPLPA@, AMD's plpa_map.c License+ | AML -- ^ @AML@, Apple MIT License+ | AMPAS -- ^ @AMPAS@, Academy of Motion Picture Arts and Sciences BSD+ | ANTLR_PD -- ^ @ANTLR-PD@, ANTLR Software Rights Notice+ | Apache_1_0 -- ^ @Apache-1.0@, Apache License 1.0+ | Apache_1_1 -- ^ @Apache-1.1@, Apache License 1.1+ | Apache_2_0 -- ^ @Apache-2.0@, Apache License 2.0+ | APAFML -- ^ @APAFML@, Adobe Postscript AFM License+ | APL_1_0 -- ^ @APL-1.0@, Adaptive Public License 1.0+ | APSL_1_0 -- ^ @APSL-1.0@, Apple Public Source License 1.0+ | APSL_1_1 -- ^ @APSL-1.1@, Apple Public Source License 1.1+ | APSL_1_2 -- ^ @APSL-1.2@, Apple Public Source License 1.2+ | APSL_2_0 -- ^ @APSL-2.0@, Apple Public Source License 2.0+ | Artistic_1_0_cl8 -- ^ @Artistic-1.0-cl8@, Artistic License 1.0 w/clause 8+ | Artistic_1_0_Perl -- ^ @Artistic-1.0-Perl@, Artistic License 1.0 (Perl)+ | Artistic_1_0 -- ^ @Artistic-1.0@, Artistic License 1.0+ | Artistic_2_0 -- ^ @Artistic-2.0@, Artistic License 2.0+ | Bahyph -- ^ @Bahyph@, Bahyph License+ | Barr -- ^ @Barr@, Barr License+ | Beerware -- ^ @Beerware@, Beerware License+ | BitTorrent_1_0 -- ^ @BitTorrent-1.0@, BitTorrent Open Source License v1.0+ | BitTorrent_1_1 -- ^ @BitTorrent-1.1@, BitTorrent Open Source License v1.1+ | Blessing -- ^ @blessing@, SQLite Blessing, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | BlueOak_1_0_0 -- ^ @BlueOak-1.0.0@, Blue Oak Model License 1.0.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Borceux -- ^ @Borceux@, Borceux license+ | BSD_1_Clause -- ^ @BSD-1-Clause@, BSD 1-Clause License+ | BSD_2_Clause_FreeBSD -- ^ @BSD-2-Clause-FreeBSD@, BSD 2-Clause FreeBSD License, SPDX License List 3.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9+ | BSD_2_Clause_NetBSD -- ^ @BSD-2-Clause-NetBSD@, BSD 2-Clause NetBSD License, SPDX License List 3.0, SPDX License List 3.2, SPDX License List 3.6+ | BSD_2_Clause_Patent -- ^ @BSD-2-Clause-Patent@, BSD-2-Clause Plus Patent License+ | BSD_2_Clause_Views -- ^ @BSD-2-Clause-Views@, BSD 2-Clause with views sentence, SPDX License List 3.10+ | BSD_2_Clause -- ^ @BSD-2-Clause@, BSD 2-Clause "Simplified" License+ | BSD_3_Clause_Attribution -- ^ @BSD-3-Clause-Attribution@, BSD with attribution+ | BSD_3_Clause_Clear -- ^ @BSD-3-Clause-Clear@, BSD 3-Clause Clear License+ | BSD_3_Clause_LBNL -- ^ @BSD-3-Clause-LBNL@, Lawrence Berkeley National Labs BSD variant license+ | BSD_3_Clause_No_Nuclear_License_2014 -- ^ @BSD-3-Clause-No-Nuclear-License-2014@, BSD 3-Clause No Nuclear License 2014+ | BSD_3_Clause_No_Nuclear_License -- ^ @BSD-3-Clause-No-Nuclear-License@, BSD 3-Clause No Nuclear License+ | BSD_3_Clause_No_Nuclear_Warranty -- ^ @BSD-3-Clause-No-Nuclear-Warranty@, BSD 3-Clause No Nuclear Warranty+ | BSD_3_Clause_Open_MPI -- ^ @BSD-3-Clause-Open-MPI@, BSD 3-Clause Open MPI variant, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | BSD_3_Clause -- ^ @BSD-3-Clause@, BSD 3-Clause "New" or "Revised" License+ | BSD_4_Clause_UC -- ^ @BSD-4-Clause-UC@, BSD-4-Clause (University of California-Specific)+ | BSD_4_Clause -- ^ @BSD-4-Clause@, BSD 4-Clause "Original" or "Old" License+ | BSD_Protection -- ^ @BSD-Protection@, BSD Protection License+ | BSD_Source_Code -- ^ @BSD-Source-Code@, BSD Source Code Attribution+ | BSL_1_0 -- ^ @BSL-1.0@, Boost Software License 1.0+ | Bzip2_1_0_5 -- ^ @bzip2-1.0.5@, bzip2 and libbzip2 License v1.0.5+ | Bzip2_1_0_6 -- ^ @bzip2-1.0.6@, bzip2 and libbzip2 License v1.0.6+ | CAL_1_0_Combined_Work_Exception -- ^ @CAL-1.0-Combined-Work-Exception@, Cryptographic Autonomy License 1.0 (Combined Work Exception), SPDX License List 3.9, SPDX License List 3.10+ | CAL_1_0 -- ^ @CAL-1.0@, Cryptographic Autonomy License 1.0, SPDX License List 3.9, SPDX License List 3.10+ | Caldera -- ^ @Caldera@, Caldera License+ | CATOSL_1_1 -- ^ @CATOSL-1.1@, Computer Associates Trusted Open Source License 1.1+ | CC_BY_1_0 -- ^ @CC-BY-1.0@, Creative Commons Attribution 1.0 Generic+ | CC_BY_2_0 -- ^ @CC-BY-2.0@, Creative Commons Attribution 2.0 Generic+ | CC_BY_2_5 -- ^ @CC-BY-2.5@, Creative Commons Attribution 2.5 Generic+ | CC_BY_3_0_AT -- ^ @CC-BY-3.0-AT@, Creative Commons Attribution 3.0 Austria, SPDX License List 3.10+ | CC_BY_3_0 -- ^ @CC-BY-3.0@, Creative Commons Attribution 3.0 Unported+ | CC_BY_4_0 -- ^ @CC-BY-4.0@, Creative Commons Attribution 4.0 International+ | CC_BY_NC_1_0 -- ^ @CC-BY-NC-1.0@, Creative Commons Attribution Non Commercial 1.0 Generic+ | CC_BY_NC_2_0 -- ^ @CC-BY-NC-2.0@, Creative Commons Attribution Non Commercial 2.0 Generic+ | CC_BY_NC_2_5 -- ^ @CC-BY-NC-2.5@, Creative Commons Attribution Non Commercial 2.5 Generic+ | CC_BY_NC_3_0 -- ^ @CC-BY-NC-3.0@, Creative Commons Attribution Non Commercial 3.0 Unported+ | CC_BY_NC_4_0 -- ^ @CC-BY-NC-4.0@, Creative Commons Attribution Non Commercial 4.0 International+ | CC_BY_NC_ND_1_0 -- ^ @CC-BY-NC-ND-1.0@, Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic+ | CC_BY_NC_ND_2_0 -- ^ @CC-BY-NC-ND-2.0@, Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic+ | CC_BY_NC_ND_2_5 -- ^ @CC-BY-NC-ND-2.5@, Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic+ | CC_BY_NC_ND_3_0_IGO -- ^ @CC-BY-NC-ND-3.0-IGO@, Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO, SPDX License List 3.10+ | CC_BY_NC_ND_3_0 -- ^ @CC-BY-NC-ND-3.0@, Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported+ | CC_BY_NC_ND_4_0 -- ^ @CC-BY-NC-ND-4.0@, Creative Commons Attribution Non Commercial No Derivatives 4.0 International+ | CC_BY_NC_SA_1_0 -- ^ @CC-BY-NC-SA-1.0@, Creative Commons Attribution Non Commercial Share Alike 1.0 Generic+ | CC_BY_NC_SA_2_0 -- ^ @CC-BY-NC-SA-2.0@, Creative Commons Attribution Non Commercial Share Alike 2.0 Generic+ | CC_BY_NC_SA_2_5 -- ^ @CC-BY-NC-SA-2.5@, Creative Commons Attribution Non Commercial Share Alike 2.5 Generic+ | CC_BY_NC_SA_3_0 -- ^ @CC-BY-NC-SA-3.0@, Creative Commons Attribution Non Commercial Share Alike 3.0 Unported+ | CC_BY_NC_SA_4_0 -- ^ @CC-BY-NC-SA-4.0@, Creative Commons Attribution Non Commercial Share Alike 4.0 International+ | CC_BY_ND_1_0 -- ^ @CC-BY-ND-1.0@, Creative Commons Attribution No Derivatives 1.0 Generic+ | CC_BY_ND_2_0 -- ^ @CC-BY-ND-2.0@, Creative Commons Attribution No Derivatives 2.0 Generic+ | CC_BY_ND_2_5 -- ^ @CC-BY-ND-2.5@, Creative Commons Attribution No Derivatives 2.5 Generic+ | CC_BY_ND_3_0 -- ^ @CC-BY-ND-3.0@, Creative Commons Attribution No Derivatives 3.0 Unported+ | CC_BY_ND_4_0 -- ^ @CC-BY-ND-4.0@, Creative Commons Attribution No Derivatives 4.0 International+ | CC_BY_SA_1_0 -- ^ @CC-BY-SA-1.0@, Creative Commons Attribution Share Alike 1.0 Generic+ | CC_BY_SA_2_0 -- ^ @CC-BY-SA-2.0@, Creative Commons Attribution Share Alike 2.0 Generic+ | CC_BY_SA_2_5 -- ^ @CC-BY-SA-2.5@, Creative Commons Attribution Share Alike 2.5 Generic+ | CC_BY_SA_3_0_AT -- ^ @CC-BY-SA-3.0-AT@, Creative Commons Attribution-Share Alike 3.0 Austria, SPDX License List 3.10+ | CC_BY_SA_3_0 -- ^ @CC-BY-SA-3.0@, Creative Commons Attribution Share Alike 3.0 Unported+ | CC_BY_SA_4_0 -- ^ @CC-BY-SA-4.0@, Creative Commons Attribution Share Alike 4.0 International+ | CC_PDDC -- ^ @CC-PDDC@, Creative Commons Public Domain Dedication and Certification, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | CC0_1_0 -- ^ @CC0-1.0@, Creative Commons Zero v1.0 Universal+ | CDDL_1_0 -- ^ @CDDL-1.0@, Common Development and Distribution License 1.0+ | CDDL_1_1 -- ^ @CDDL-1.1@, Common Development and Distribution License 1.1+ | CDLA_Permissive_1_0 -- ^ @CDLA-Permissive-1.0@, Community Data License Agreement Permissive 1.0+ | CDLA_Sharing_1_0 -- ^ @CDLA-Sharing-1.0@, Community Data License Agreement Sharing 1.0+ | CECILL_1_0 -- ^ @CECILL-1.0@, CeCILL Free Software License Agreement v1.0+ | CECILL_1_1 -- ^ @CECILL-1.1@, CeCILL Free Software License Agreement v1.1+ | CECILL_2_0 -- ^ @CECILL-2.0@, CeCILL Free Software License Agreement v2.0+ | CECILL_2_1 -- ^ @CECILL-2.1@, CeCILL Free Software License Agreement v2.1+ | CECILL_B -- ^ @CECILL-B@, CeCILL-B Free Software License Agreement+ | CECILL_C -- ^ @CECILL-C@, CeCILL-C Free Software License Agreement+ | CERN_OHL_1_1 -- ^ @CERN-OHL-1.1@, CERN Open Hardware Licence v1.1, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | CERN_OHL_1_2 -- ^ @CERN-OHL-1.2@, CERN Open Hardware Licence v1.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | CERN_OHL_P_2_0 -- ^ @CERN-OHL-P-2.0@, CERN Open Hardware Licence Version 2 - Permissive, SPDX License List 3.9, SPDX License List 3.10+ | CERN_OHL_S_2_0 -- ^ @CERN-OHL-S-2.0@, CERN Open Hardware Licence Version 2 - Strongly Reciprocal, SPDX License List 3.9, SPDX License List 3.10+ | CERN_OHL_W_2_0 -- ^ @CERN-OHL-W-2.0@, CERN Open Hardware Licence Version 2 - Weakly Reciprocal, SPDX License List 3.9, SPDX License List 3.10+ | ClArtistic -- ^ @ClArtistic@, Clarified Artistic License+ | CNRI_Jython -- ^ @CNRI-Jython@, CNRI Jython License+ | CNRI_Python_GPL_Compatible -- ^ @CNRI-Python-GPL-Compatible@, CNRI Python Open Source GPL Compatible License Agreement+ | CNRI_Python -- ^ @CNRI-Python@, CNRI Python License+ | Condor_1_1 -- ^ @Condor-1.1@, Condor Public License v1.1+ | Copyleft_next_0_3_0 -- ^ @copyleft-next-0.3.0@, copyleft-next 0.3.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Copyleft_next_0_3_1 -- ^ @copyleft-next-0.3.1@, copyleft-next 0.3.1, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | CPAL_1_0 -- ^ @CPAL-1.0@, Common Public Attribution License 1.0+ | CPL_1_0 -- ^ @CPL-1.0@, Common Public License 1.0+ | CPOL_1_02 -- ^ @CPOL-1.02@, Code Project Open License 1.02+ | Crossword -- ^ @Crossword@, Crossword License+ | CrystalStacker -- ^ @CrystalStacker@, CrystalStacker License+ | CUA_OPL_1_0 -- ^ @CUA-OPL-1.0@, CUA Office Public License v1.0+ | Cube -- ^ @Cube@, Cube License+ | Curl -- ^ @curl@, curl License+ | D_FSL_1_0 -- ^ @D-FSL-1.0@, Deutsche Freie Software Lizenz+ | Diffmark -- ^ @diffmark@, diffmark license+ | DOC -- ^ @DOC@, DOC License+ | Dotseqn -- ^ @Dotseqn@, Dotseqn License+ | DSDP -- ^ @DSDP@, DSDP License+ | Dvipdfm -- ^ @dvipdfm@, dvipdfm License+ | ECL_1_0 -- ^ @ECL-1.0@, Educational Community License v1.0+ | ECL_2_0 -- ^ @ECL-2.0@, Educational Community License v2.0+ | EFL_1_0 -- ^ @EFL-1.0@, Eiffel Forum License v1.0+ | EFL_2_0 -- ^ @EFL-2.0@, Eiffel Forum License v2.0+ | EGenix -- ^ @eGenix@, eGenix.com Public License 1.1.0+ | Entessa -- ^ @Entessa@, Entessa Public License v1.0+ | EPICS -- ^ @EPICS@, EPICS Open License, SPDX License List 3.10+ | EPL_1_0 -- ^ @EPL-1.0@, Eclipse Public License 1.0+ | EPL_2_0 -- ^ @EPL-2.0@, Eclipse Public License 2.0+ | ErlPL_1_1 -- ^ @ErlPL-1.1@, Erlang Public License v1.1+ | Etalab_2_0 -- ^ @etalab-2.0@, Etalab Open License 2.0, SPDX License List 3.9, SPDX License List 3.10+ | EUDatagrid -- ^ @EUDatagrid@, EU DataGrid Software License+ | EUPL_1_0 -- ^ @EUPL-1.0@, European Union Public License 1.0+ | EUPL_1_1 -- ^ @EUPL-1.1@, European Union Public License 1.1+ | EUPL_1_2 -- ^ @EUPL-1.2@, European Union Public License 1.2+ | Eurosym -- ^ @Eurosym@, Eurosym License+ | Fair -- ^ @Fair@, Fair License+ | Frameworx_1_0 -- ^ @Frameworx-1.0@, Frameworx Open License 1.0+ | FreeImage -- ^ @FreeImage@, FreeImage Public License v1.0+ | FSFAP -- ^ @FSFAP@, FSF All Permissive License+ | FSFULLR -- ^ @FSFULLR@, FSF Unlimited License (with License Retention)+ | FSFUL -- ^ @FSFUL@, FSF Unlimited License+ | FTL -- ^ @FTL@, Freetype Project License+ | GFDL_1_1_invariants_only -- ^ @GFDL-1.1-invariants-only@, GNU Free Documentation License v1.1 only - invariants, SPDX License List 3.10+ | GFDL_1_1_invariants_or_later -- ^ @GFDL-1.1-invariants-or-later@, GNU Free Documentation License v1.1 or later - invariants, SPDX License List 3.10+ | GFDL_1_1_no_invariants_only -- ^ @GFDL-1.1-no-invariants-only@, GNU Free Documentation License v1.1 only - no invariants, SPDX License List 3.10+ | GFDL_1_1_no_invariants_or_later -- ^ @GFDL-1.1-no-invariants-or-later@, GNU Free Documentation License v1.1 or later - no invariants, SPDX License List 3.10+ | GFDL_1_1_only -- ^ @GFDL-1.1-only@, GNU Free Documentation License v1.1 only+ | GFDL_1_1_or_later -- ^ @GFDL-1.1-or-later@, GNU Free Documentation License v1.1 or later+ | GFDL_1_2_invariants_only -- ^ @GFDL-1.2-invariants-only@, GNU Free Documentation License v1.2 only - invariants, SPDX License List 3.10+ | GFDL_1_2_invariants_or_later -- ^ @GFDL-1.2-invariants-or-later@, GNU Free Documentation License v1.2 or later - invariants, SPDX License List 3.10+ | GFDL_1_2_no_invariants_only -- ^ @GFDL-1.2-no-invariants-only@, GNU Free Documentation License v1.2 only - no invariants, SPDX License List 3.10+ | GFDL_1_2_no_invariants_or_later -- ^ @GFDL-1.2-no-invariants-or-later@, GNU Free Documentation License v1.2 or later - no invariants, SPDX License List 3.10+ | GFDL_1_2_only -- ^ @GFDL-1.2-only@, GNU Free Documentation License v1.2 only+ | GFDL_1_2_or_later -- ^ @GFDL-1.2-or-later@, GNU Free Documentation License v1.2 or later+ | GFDL_1_3_invariants_only -- ^ @GFDL-1.3-invariants-only@, GNU Free Documentation License v1.3 only - invariants, SPDX License List 3.10+ | GFDL_1_3_invariants_or_later -- ^ @GFDL-1.3-invariants-or-later@, GNU Free Documentation License v1.3 or later - invariants, SPDX License List 3.10+ | GFDL_1_3_no_invariants_only -- ^ @GFDL-1.3-no-invariants-only@, GNU Free Documentation License v1.3 only - no invariants, SPDX License List 3.10+ | GFDL_1_3_no_invariants_or_later -- ^ @GFDL-1.3-no-invariants-or-later@, GNU Free Documentation License v1.3 or later - no invariants, SPDX License List 3.10+ | GFDL_1_3_only -- ^ @GFDL-1.3-only@, GNU Free Documentation License v1.3 only+ | GFDL_1_3_or_later -- ^ @GFDL-1.3-or-later@, GNU Free Documentation License v1.3 or later+ | Giftware -- ^ @Giftware@, Giftware License+ | GL2PS -- ^ @GL2PS@, GL2PS License+ | Glide -- ^ @Glide@, 3dfx Glide License+ | Glulxe -- ^ @Glulxe@, Glulxe License+ | GLWTPL -- ^ @GLWTPL@, Good Luck With That Public License, SPDX License List 3.10+ | Gnuplot -- ^ @gnuplot@, gnuplot License+ | GPL_1_0_only -- ^ @GPL-1.0-only@, GNU General Public License v1.0 only+ | GPL_1_0_or_later -- ^ @GPL-1.0-or-later@, GNU General Public License v1.0 or later+ | GPL_2_0_only -- ^ @GPL-2.0-only@, GNU General Public License v2.0 only+ | GPL_2_0_or_later -- ^ @GPL-2.0-or-later@, GNU General Public License v2.0 or later+ | GPL_3_0_only -- ^ @GPL-3.0-only@, GNU General Public License v3.0 only+ | GPL_3_0_or_later -- ^ @GPL-3.0-or-later@, GNU General Public License v3.0 or later+ | GSOAP_1_3b -- ^ @gSOAP-1.3b@, gSOAP Public License v1.3b+ | HaskellReport -- ^ @HaskellReport@, Haskell Language Report License+ | Hippocratic_2_1 -- ^ @Hippocratic-2.1@, Hippocratic License 2.1, SPDX License List 3.9, SPDX License List 3.10+ | HPND_sell_variant -- ^ @HPND-sell-variant@, Historical Permission Notice and Disclaimer - sell variant, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | HPND -- ^ @HPND@, Historical Permission Notice and Disclaimer+ | IBM_pibs -- ^ @IBM-pibs@, IBM PowerPC Initialization and Boot Software+ | ICU -- ^ @ICU@, ICU License+ | IJG -- ^ @IJG@, Independent JPEG Group License+ | ImageMagick -- ^ @ImageMagick@, ImageMagick License+ | IMatix -- ^ @iMatix@, iMatix Standard Function Library Agreement+ | Imlib2 -- ^ @Imlib2@, Imlib2 License+ | Info_ZIP -- ^ @Info-ZIP@, Info-ZIP License+ | Intel_ACPI -- ^ @Intel-ACPI@, Intel ACPI Software License Agreement+ | Intel -- ^ @Intel@, Intel Open Source License+ | Interbase_1_0 -- ^ @Interbase-1.0@, Interbase Public License v1.0+ | IPA -- ^ @IPA@, IPA Font License+ | IPL_1_0 -- ^ @IPL-1.0@, IBM Public License v1.0+ | ISC -- ^ @ISC@, ISC License+ | JasPer_2_0 -- ^ @JasPer-2.0@, JasPer License+ | JPNIC -- ^ @JPNIC@, Japan Network Information Center License, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | JSON -- ^ @JSON@, JSON License+ | LAL_1_2 -- ^ @LAL-1.2@, Licence Art Libre 1.2+ | LAL_1_3 -- ^ @LAL-1.3@, Licence Art Libre 1.3+ | Latex2e -- ^ @Latex2e@, Latex2e License+ | Leptonica -- ^ @Leptonica@, Leptonica License+ | LGPL_2_0_only -- ^ @LGPL-2.0-only@, GNU Library General Public License v2 only+ | LGPL_2_0_or_later -- ^ @LGPL-2.0-or-later@, GNU Library General Public License v2 or later+ | LGPL_2_1_only -- ^ @LGPL-2.1-only@, GNU Lesser General Public License v2.1 only+ | LGPL_2_1_or_later -- ^ @LGPL-2.1-or-later@, GNU Lesser General Public License v2.1 or later+ | LGPL_3_0_only -- ^ @LGPL-3.0-only@, GNU Lesser General Public License v3.0 only+ | LGPL_3_0_or_later -- ^ @LGPL-3.0-or-later@, GNU Lesser General Public License v3.0 or later+ | LGPLLR -- ^ @LGPLLR@, Lesser General Public License For Linguistic Resources+ | Libpng_2_0 -- ^ @libpng-2.0@, PNG Reference Library version 2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Libpng -- ^ @Libpng@, libpng License+ | Libselinux_1_0 -- ^ @libselinux-1.0@, libselinux public domain notice, SPDX License List 3.9, SPDX License List 3.10+ | Libtiff -- ^ @libtiff@, libtiff License+ | LiLiQ_P_1_1 -- ^ @LiLiQ-P-1.1@, Licence Libre du Québec – Permissive version 1.1+ | LiLiQ_R_1_1 -- ^ @LiLiQ-R-1.1@, Licence Libre du Québec – Réciprocité version 1.1+ | LiLiQ_Rplus_1_1 -- ^ @LiLiQ-Rplus-1.1@, Licence Libre du Québec – Réciprocité forte version 1.1+ | Linux_OpenIB -- ^ @Linux-OpenIB@, Linux Kernel Variant of OpenIB.org license, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | LPL_1_02 -- ^ @LPL-1.02@, Lucent Public License v1.02+ | LPL_1_0 -- ^ @LPL-1.0@, Lucent Public License Version 1.0+ | LPPL_1_0 -- ^ @LPPL-1.0@, LaTeX Project Public License v1.0+ | LPPL_1_1 -- ^ @LPPL-1.1@, LaTeX Project Public License v1.1+ | LPPL_1_2 -- ^ @LPPL-1.2@, LaTeX Project Public License v1.2+ | LPPL_1_3a -- ^ @LPPL-1.3a@, LaTeX Project Public License v1.3a+ | LPPL_1_3c -- ^ @LPPL-1.3c@, LaTeX Project Public License v1.3c+ | MakeIndex -- ^ @MakeIndex@, MakeIndex License+ | MirOS -- ^ @MirOS@, The MirOS Licence+ | MIT_0 -- ^ @MIT-0@, MIT No Attribution, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | MIT_advertising -- ^ @MIT-advertising@, Enlightenment License (e16)+ | MIT_CMU -- ^ @MIT-CMU@, CMU License+ | MIT_enna -- ^ @MIT-enna@, enna License+ | MIT_feh -- ^ @MIT-feh@, feh License+ | MITNFA -- ^ @MITNFA@, MIT +no-false-attribs license+ | MIT -- ^ @MIT@, MIT License+ | Motosoto -- ^ @Motosoto@, Motosoto License+ | Mpich2 -- ^ @mpich2@, mpich2 License+ | MPL_1_0 -- ^ @MPL-1.0@, Mozilla Public License 1.0+ | MPL_1_1 -- ^ @MPL-1.1@, Mozilla Public License 1.1+ | MPL_2_0_no_copyleft_exception -- ^ @MPL-2.0-no-copyleft-exception@, Mozilla Public License 2.0 (no copyleft exception)+ | MPL_2_0 -- ^ @MPL-2.0@, Mozilla Public License 2.0+ | MS_PL -- ^ @MS-PL@, Microsoft Public License+ | MS_RL -- ^ @MS-RL@, Microsoft Reciprocal License+ | MTLL -- ^ @MTLL@, Matrix Template Library License+ | MulanPSL_1_0 -- ^ @MulanPSL-1.0@, Mulan Permissive Software License, Version 1, SPDX License List 3.9, SPDX License List 3.10+ | MulanPSL_2_0 -- ^ @MulanPSL-2.0@, Mulan Permissive Software License, Version 2, SPDX License List 3.9, SPDX License List 3.10+ | Multics -- ^ @Multics@, Multics License+ | Mup -- ^ @Mup@, Mup License+ | NASA_1_3 -- ^ @NASA-1.3@, NASA Open Source Agreement 1.3+ | Naumen -- ^ @Naumen@, Naumen Public License+ | NBPL_1_0 -- ^ @NBPL-1.0@, Net Boolean Public License v1+ | NCGL_UK_2_0 -- ^ @NCGL-UK-2.0@, Non-Commercial Government Licence, SPDX License List 3.9, SPDX License List 3.10+ | NCSA -- ^ @NCSA@, University of Illinois/NCSA Open Source License+ | Net_SNMP -- ^ @Net-SNMP@, Net-SNMP License+ | NetCDF -- ^ @NetCDF@, NetCDF license+ | Newsletr -- ^ @Newsletr@, Newsletr License+ | NGPL -- ^ @NGPL@, Nethack General Public License+ | NIST_PD_fallback -- ^ @NIST-PD-fallback@, NIST Public Domain Notice with license fallback, SPDX License List 3.10+ | NIST_PD -- ^ @NIST-PD@, NIST Public Domain Notice, SPDX License List 3.10+ | NLOD_1_0 -- ^ @NLOD-1.0@, Norwegian Licence for Open Government Data+ | NLPL -- ^ @NLPL@, No Limit Public License+ | Nokia -- ^ @Nokia@, Nokia Open Source License+ | NOSL -- ^ @NOSL@, Netizen Open Source License+ | Noweb -- ^ @Noweb@, Noweb License+ | NPL_1_0 -- ^ @NPL-1.0@, Netscape Public License v1.0+ | NPL_1_1 -- ^ @NPL-1.1@, Netscape Public License v1.1+ | NPOSL_3_0 -- ^ @NPOSL-3.0@, Non-Profit Open Software License 3.0+ | NRL -- ^ @NRL@, NRL License+ | NTP_0 -- ^ @NTP-0@, NTP No Attribution, SPDX License List 3.9, SPDX License List 3.10+ | NTP -- ^ @NTP@, NTP License+ | O_UDA_1_0 -- ^ @O-UDA-1.0@, Open Use of Data Agreement v1.0, SPDX License List 3.9, SPDX License List 3.10+ | OCCT_PL -- ^ @OCCT-PL@, Open CASCADE Technology Public License+ | OCLC_2_0 -- ^ @OCLC-2.0@, OCLC Research Public License 2.0+ | ODbL_1_0 -- ^ @ODbL-1.0@, ODC Open Database License v1.0+ | ODC_By_1_0 -- ^ @ODC-By-1.0@, Open Data Commons Attribution License v1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | OFL_1_0_no_RFN -- ^ @OFL-1.0-no-RFN@, SIL Open Font License 1.0 with no Reserved Font Name, SPDX License List 3.9, SPDX License List 3.10+ | OFL_1_0_RFN -- ^ @OFL-1.0-RFN@, SIL Open Font License 1.0 with Reserved Font Name, SPDX License List 3.9, SPDX License List 3.10+ | OFL_1_0 -- ^ @OFL-1.0@, SIL Open Font License 1.0+ | OFL_1_1_no_RFN -- ^ @OFL-1.1-no-RFN@, SIL Open Font License 1.1 with no Reserved Font Name, SPDX License List 3.9, SPDX License List 3.10+ | OFL_1_1_RFN -- ^ @OFL-1.1-RFN@, SIL Open Font License 1.1 with Reserved Font Name, SPDX License List 3.9, SPDX License List 3.10+ | OFL_1_1 -- ^ @OFL-1.1@, SIL Open Font License 1.1+ | OGC_1_0 -- ^ @OGC-1.0@, OGC Software License, Version 1.0, SPDX License List 3.9, SPDX License List 3.10+ | OGL_Canada_2_0 -- ^ @OGL-Canada-2.0@, Open Government Licence - Canada, SPDX License List 3.9, SPDX License List 3.10+ | OGL_UK_1_0 -- ^ @OGL-UK-1.0@, Open Government Licence v1.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | OGL_UK_2_0 -- ^ @OGL-UK-2.0@, Open Government Licence v2.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | OGL_UK_3_0 -- ^ @OGL-UK-3.0@, Open Government Licence v3.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | OGTSL -- ^ @OGTSL@, Open Group Test Suite License+ | OLDAP_1_1 -- ^ @OLDAP-1.1@, Open LDAP Public License v1.1+ | OLDAP_1_2 -- ^ @OLDAP-1.2@, Open LDAP Public License v1.2+ | OLDAP_1_3 -- ^ @OLDAP-1.3@, Open LDAP Public License v1.3+ | OLDAP_1_4 -- ^ @OLDAP-1.4@, Open LDAP Public License v1.4+ | OLDAP_2_0_1 -- ^ @OLDAP-2.0.1@, Open LDAP Public License v2.0.1+ | OLDAP_2_0 -- ^ @OLDAP-2.0@, Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)+ | OLDAP_2_1 -- ^ @OLDAP-2.1@, Open LDAP Public License v2.1+ | OLDAP_2_2_1 -- ^ @OLDAP-2.2.1@, Open LDAP Public License v2.2.1+ | OLDAP_2_2_2 -- ^ @OLDAP-2.2.2@, Open LDAP Public License 2.2.2+ | OLDAP_2_2 -- ^ @OLDAP-2.2@, Open LDAP Public License v2.2+ | OLDAP_2_3 -- ^ @OLDAP-2.3@, Open LDAP Public License v2.3+ | OLDAP_2_4 -- ^ @OLDAP-2.4@, Open LDAP Public License v2.4+ | OLDAP_2_5 -- ^ @OLDAP-2.5@, Open LDAP Public License v2.5+ | OLDAP_2_6 -- ^ @OLDAP-2.6@, Open LDAP Public License v2.6+ | OLDAP_2_7 -- ^ @OLDAP-2.7@, Open LDAP Public License v2.7+ | OLDAP_2_8 -- ^ @OLDAP-2.8@, Open LDAP Public License v2.8+ | OML -- ^ @OML@, Open Market License+ | OpenSSL -- ^ @OpenSSL@, OpenSSL License+ | OPL_1_0 -- ^ @OPL-1.0@, Open Public License v1.0+ | OSET_PL_2_1 -- ^ @OSET-PL-2.1@, OSET Public License version 2.1+ | OSL_1_0 -- ^ @OSL-1.0@, Open Software License 1.0+ | OSL_1_1 -- ^ @OSL-1.1@, Open Software License 1.1+ | OSL_2_0 -- ^ @OSL-2.0@, Open Software License 2.0+ | OSL_2_1 -- ^ @OSL-2.1@, Open Software License 2.1+ | OSL_3_0 -- ^ @OSL-3.0@, Open Software License 3.0+ | Parity_6_0_0 -- ^ @Parity-6.0.0@, The Parity Public License 6.0.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Parity_7_0_0 -- ^ @Parity-7.0.0@, The Parity Public License 7.0.0, SPDX License List 3.9, SPDX License List 3.10+ | PDDL_1_0 -- ^ @PDDL-1.0@, ODC Public Domain Dedication & License 1.0+ | PHP_3_01 -- ^ @PHP-3.01@, PHP License v3.01+ | PHP_3_0 -- ^ @PHP-3.0@, PHP License v3.0+ | Plexus -- ^ @Plexus@, Plexus Classworlds License+ | PolyForm_Noncommercial_1_0_0 -- ^ @PolyForm-Noncommercial-1.0.0@, PolyForm Noncommercial License 1.0.0, SPDX License List 3.9, SPDX License List 3.10+ | PolyForm_Small_Business_1_0_0 -- ^ @PolyForm-Small-Business-1.0.0@, PolyForm Small Business License 1.0.0, SPDX License List 3.9, SPDX License List 3.10+ | PostgreSQL -- ^ @PostgreSQL@, PostgreSQL License+ | PSF_2_0 -- ^ @PSF-2.0@, Python Software Foundation License 2.0, SPDX License List 3.9, SPDX License List 3.10+ | Psfrag -- ^ @psfrag@, psfrag License+ | Psutils -- ^ @psutils@, psutils License+ | Python_2_0 -- ^ @Python-2.0@, Python License 2.0+ | Qhull -- ^ @Qhull@, Qhull License+ | QPL_1_0 -- ^ @QPL-1.0@, Q Public License 1.0+ | Rdisc -- ^ @Rdisc@, Rdisc License+ | RHeCos_1_1 -- ^ @RHeCos-1.1@, Red Hat eCos Public License v1.1+ | RPL_1_1 -- ^ @RPL-1.1@, Reciprocal Public License 1.1+ | RPL_1_5 -- ^ @RPL-1.5@, Reciprocal Public License 1.5+ | RPSL_1_0 -- ^ @RPSL-1.0@, RealNetworks Public Source License v1.0+ | RSA_MD -- ^ @RSA-MD@, RSA Message-Digest License+ | RSCPL -- ^ @RSCPL@, Ricoh Source Code Public License+ | Ruby -- ^ @Ruby@, Ruby License+ | SAX_PD -- ^ @SAX-PD@, Sax Public Domain Notice+ | Saxpath -- ^ @Saxpath@, Saxpath License+ | SCEA -- ^ @SCEA@, SCEA Shared Source License+ | Sendmail_8_23 -- ^ @Sendmail-8.23@, Sendmail License 8.23, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | Sendmail -- ^ @Sendmail@, Sendmail License+ | SGI_B_1_0 -- ^ @SGI-B-1.0@, SGI Free Software License B v1.0+ | SGI_B_1_1 -- ^ @SGI-B-1.1@, SGI Free Software License B v1.1+ | SGI_B_2_0 -- ^ @SGI-B-2.0@, SGI Free Software License B v2.0+ | SHL_0_51 -- ^ @SHL-0.51@, Solderpad Hardware License, Version 0.51, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | SHL_0_5 -- ^ @SHL-0.5@, Solderpad Hardware License v0.5, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | SimPL_2_0 -- ^ @SimPL-2.0@, Simple Public License 2.0+ | SISSL_1_2 -- ^ @SISSL-1.2@, Sun Industry Standards Source License v1.2+ | SISSL -- ^ @SISSL@, Sun Industry Standards Source License v1.1+ | Sleepycat -- ^ @Sleepycat@, Sleepycat License+ | SMLNJ -- ^ @SMLNJ@, Standard ML of New Jersey License+ | SMPPL -- ^ @SMPPL@, Secure Messaging Protocol Public License+ | SNIA -- ^ @SNIA@, SNIA Public License 1.1+ | Spencer_86 -- ^ @Spencer-86@, Spencer License 86+ | Spencer_94 -- ^ @Spencer-94@, Spencer License 94+ | Spencer_99 -- ^ @Spencer-99@, Spencer License 99+ | SPL_1_0 -- ^ @SPL-1.0@, Sun Public License v1.0+ | SSH_OpenSSH -- ^ @SSH-OpenSSH@, SSH OpenSSH license, SPDX License List 3.9, SPDX License List 3.10+ | SSH_short -- ^ @SSH-short@, SSH short notice, SPDX License List 3.9, SPDX License List 3.10+ | SSPL_1_0 -- ^ @SSPL-1.0@, Server Side Public License, v 1, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | SugarCRM_1_1_3 -- ^ @SugarCRM-1.1.3@, SugarCRM Public License v1.1.3+ | SWL -- ^ @SWL@, Scheme Widget Library (SWL) Software License Agreement+ | TAPR_OHL_1_0 -- ^ @TAPR-OHL-1.0@, TAPR Open Hardware License v1.0, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | TCL -- ^ @TCL@, TCL/TK License+ | TCP_wrappers -- ^ @TCP-wrappers@, TCP Wrappers License+ | TMate -- ^ @TMate@, TMate Open Source License+ | TORQUE_1_1 -- ^ @TORQUE-1.1@, TORQUE v2.5+ Software License v1.1+ | TOSL -- ^ @TOSL@, Trusster Open Source License+ | TU_Berlin_1_0 -- ^ @TU-Berlin-1.0@, Technische Universitaet Berlin License 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | TU_Berlin_2_0 -- ^ @TU-Berlin-2.0@, Technische Universitaet Berlin License 2.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9, SPDX License List 3.10+ | UCL_1_0 -- ^ @UCL-1.0@, Upstream Compatibility License v1.0, SPDX License List 3.9, SPDX License List 3.10+ | Unicode_DFS_2015 -- ^ @Unicode-DFS-2015@, Unicode License Agreement - Data Files and Software (2015)+ | Unicode_DFS_2016 -- ^ @Unicode-DFS-2016@, Unicode License Agreement - Data Files and Software (2016)+ | Unicode_TOU -- ^ @Unicode-TOU@, Unicode Terms of Use+ | Unlicense -- ^ @Unlicense@, The Unlicense+ | UPL_1_0 -- ^ @UPL-1.0@, Universal Permissive License v1.0+ | Vim -- ^ @Vim@, Vim License+ | VOSTROM -- ^ @VOSTROM@, VOSTROM Public License for Open Source+ | VSL_1_0 -- ^ @VSL-1.0@, Vovida Software License v1.0+ | W3C_19980720 -- ^ @W3C-19980720@, W3C Software Notice and License (1998-07-20)+ | W3C_20150513 -- ^ @W3C-20150513@, W3C Software Notice and Document License (2015-05-13)+ | W3C -- ^ @W3C@, W3C Software Notice and License (2002-12-31)+ | Watcom_1_0 -- ^ @Watcom-1.0@, Sybase Open Watcom Public License 1.0+ | Wsuipa -- ^ @Wsuipa@, Wsuipa License+ | WTFPL -- ^ @WTFPL@, Do What The F*ck You Want To Public License+ | X11 -- ^ @X11@, X11 License+ | Xerox -- ^ @Xerox@, Xerox License+ | XFree86_1_1 -- ^ @XFree86-1.1@, XFree86 License 1.1+ | Xinetd -- ^ @xinetd@, xinetd License+ | Xnet -- ^ @Xnet@, X.Net License+ | Xpp -- ^ @xpp@, XPP License+ | XSkat -- ^ @XSkat@, XSkat License+ | YPL_1_0 -- ^ @YPL-1.0@, Yahoo! Public License v1.0+ | YPL_1_1 -- ^ @YPL-1.1@, Yahoo! Public License v1.1+ | Zed -- ^ @Zed@, Zed License+ | Zend_2_0 -- ^ @Zend-2.0@, Zend License v2.0+ | Zimbra_1_3 -- ^ @Zimbra-1.3@, Zimbra Public License v1.3+ | Zimbra_1_4 -- ^ @Zimbra-1.4@, Zimbra Public License v1.4+ | Zlib_acknowledgement -- ^ @zlib-acknowledgement@, zlib/libpng License with Acknowledgement+ | Zlib -- ^ @Zlib@, zlib License+ | ZPL_1_1 -- ^ @ZPL-1.1@, Zope Public License 1.1+ | ZPL_2_0 -- ^ @ZPL-2.0@, Zope Public License 2.0+ | ZPL_2_1 -- ^ @ZPL-2.1@, Zope Public License 2.1+ deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)++instance Binary LicenseId where+ -- Word16 is encoded in big endianess+ -- https://github.com/kolmodin/binary/blob/master/src/Data/Binary/Class.hs#L220-LL227+ put = Binary.putWord16be . fromIntegral . fromEnum+ get = do+ i <- Binary.getWord16be+ if i > fromIntegral (fromEnum (maxBound :: LicenseId))+ then fail "Too large LicenseId tag"+ else return (toEnum (fromIntegral i))++-- note: remember to bump version each time the definition changes+instance Structured LicenseId where+ structure p = set typeVersion 306 $ nominalStructure p++instance Pretty LicenseId where+ pretty = Disp.text . licenseId++-- |+-- >>> eitherParsec "BSD-3-Clause" :: Either String LicenseId+-- Right BSD_3_Clause+--+-- >>> eitherParsec "BSD3" :: Either String LicenseId+-- Left "...Unknown SPDX license identifier: 'BSD3' Do you mean BSD-3-Clause?"+--+instance Parsec LicenseId where+ parsec = do+ n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'+ v <- askCabalSpecVersion+ maybe (fail $ "Unknown SPDX license identifier: '" ++ n ++ "' " ++ licenseIdMigrationMessage n) return $+ mkLicenseId (cabalSpecVersionToSPDXListVersion v) n++instance NFData LicenseId where+ rnf l = l `seq` ()++-- | Help message for migrating from non-SPDX license identifiers.+--+-- Old 'License' is almost SPDX, except for 'BSD2', 'BSD3'. This function+-- suggests SPDX variant:+--+-- >>> licenseIdMigrationMessage "BSD3"+-- "Do you mean BSD-3-Clause?"+--+-- Also 'OtherLicense', 'AllRightsReserved', and 'PublicDomain' aren't+-- valid SPDX identifiers+--+-- >>> traverse_ (print . licenseIdMigrationMessage) [ "OtherLicense", "AllRightsReserved", "PublicDomain" ]+-- "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."+-- "You can use NONE as a value of license field."+-- "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."+--+-- SPDX License list version 3.0 introduced "-only" and "-or-later" variants for GNU family of licenses.+-- See <https://spdx.org/news/news/2018/01/license-list-30-released>+-- >>> licenseIdMigrationMessage "GPL-2.0"+-- "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use GPL-2.0-only or GPL-2.0-or-later."+--+-- For other common licenses their old license format coincides with the SPDX identifiers:+--+-- >>> traverse eitherParsec ["GPL-2.0-only", "GPL-3.0-only", "LGPL-2.1-only", "MIT", "ISC", "MPL-2.0", "Apache-2.0"] :: Either String [LicenseId]+-- Right [GPL_2_0_only,GPL_3_0_only,LGPL_2_1_only,MIT,ISC,MPL_2_0,Apache_2_0]+--+licenseIdMigrationMessage :: String -> String+licenseIdMigrationMessage = go where+ go l | gnuVariant l = "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use " ++ l ++ "-only or " ++ l ++ "-or-later."+ go "BSD3" = "Do you mean BSD-3-Clause?"+ go "BSD2" = "Do you mean BSD-2-Clause?"+ go "AllRightsReserved" = "You can use NONE as a value of license field."+ go "OtherLicense" = "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."+ go "PublicDomain" = "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."++ -- otherwise, we don't know+ go _ = ""++ gnuVariant = flip elem ["GPL-2.0", "GPL-3.0", "LGPL-2.1", "LGPL-3.0", "AGPL-3.0" ]++-------------------------------------------------------------------------------+-- License Data+-------------------------------------------------------------------------------++-- | License SPDX identifier, e.g. @"BSD-3-Clause"@.+licenseId :: LicenseId -> String+licenseId NullBSD = "0BSD"+licenseId AAL = "AAL"+licenseId Abstyles = "Abstyles"+licenseId Adobe_2006 = "Adobe-2006"+licenseId Adobe_Glyph = "Adobe-Glyph"+licenseId ADSL = "ADSL"+licenseId AFL_1_1 = "AFL-1.1"+licenseId AFL_1_2 = "AFL-1.2"+licenseId AFL_2_0 = "AFL-2.0"+licenseId AFL_2_1 = "AFL-2.1"+licenseId AFL_3_0 = "AFL-3.0"+licenseId Afmparse = "Afmparse"+licenseId AGPL_1_0 = "AGPL-1.0"+licenseId AGPL_1_0_only = "AGPL-1.0-only"+licenseId AGPL_1_0_or_later = "AGPL-1.0-or-later"+licenseId AGPL_3_0_only = "AGPL-3.0-only"+licenseId AGPL_3_0_or_later = "AGPL-3.0-or-later"+licenseId Aladdin = "Aladdin"+licenseId AMDPLPA = "AMDPLPA"+licenseId AML = "AML"+licenseId AMPAS = "AMPAS"+licenseId ANTLR_PD = "ANTLR-PD"+licenseId Apache_1_0 = "Apache-1.0"+licenseId Apache_1_1 = "Apache-1.1"+licenseId Apache_2_0 = "Apache-2.0"+licenseId APAFML = "APAFML"+licenseId APL_1_0 = "APL-1.0"+licenseId APSL_1_0 = "APSL-1.0"+licenseId APSL_1_1 = "APSL-1.1"+licenseId APSL_1_2 = "APSL-1.2"+licenseId APSL_2_0 = "APSL-2.0"+licenseId Artistic_1_0_cl8 = "Artistic-1.0-cl8"+licenseId Artistic_1_0_Perl = "Artistic-1.0-Perl"+licenseId Artistic_1_0 = "Artistic-1.0"+licenseId Artistic_2_0 = "Artistic-2.0"+licenseId Bahyph = "Bahyph"+licenseId Barr = "Barr"+licenseId Beerware = "Beerware"+licenseId BitTorrent_1_0 = "BitTorrent-1.0"+licenseId BitTorrent_1_1 = "BitTorrent-1.1"+licenseId Blessing = "blessing"+licenseId BlueOak_1_0_0 = "BlueOak-1.0.0"+licenseId Borceux = "Borceux"+licenseId BSD_1_Clause = "BSD-1-Clause"+licenseId BSD_2_Clause_FreeBSD = "BSD-2-Clause-FreeBSD"+licenseId BSD_2_Clause_NetBSD = "BSD-2-Clause-NetBSD"+licenseId BSD_2_Clause_Patent = "BSD-2-Clause-Patent"+licenseId BSD_2_Clause_Views = "BSD-2-Clause-Views"+licenseId BSD_2_Clause = "BSD-2-Clause"+licenseId BSD_3_Clause_Attribution = "BSD-3-Clause-Attribution"+licenseId BSD_3_Clause_Clear = "BSD-3-Clause-Clear"+licenseId BSD_3_Clause_LBNL = "BSD-3-Clause-LBNL"+licenseId BSD_3_Clause_No_Nuclear_License_2014 = "BSD-3-Clause-No-Nuclear-License-2014"+licenseId BSD_3_Clause_No_Nuclear_License = "BSD-3-Clause-No-Nuclear-License"+licenseId BSD_3_Clause_No_Nuclear_Warranty = "BSD-3-Clause-No-Nuclear-Warranty"+licenseId BSD_3_Clause_Open_MPI = "BSD-3-Clause-Open-MPI"+licenseId BSD_3_Clause = "BSD-3-Clause"+licenseId BSD_4_Clause_UC = "BSD-4-Clause-UC"+licenseId BSD_4_Clause = "BSD-4-Clause"+licenseId BSD_Protection = "BSD-Protection"+licenseId BSD_Source_Code = "BSD-Source-Code"+licenseId BSL_1_0 = "BSL-1.0"+licenseId Bzip2_1_0_5 = "bzip2-1.0.5"+licenseId Bzip2_1_0_6 = "bzip2-1.0.6"+licenseId CAL_1_0_Combined_Work_Exception = "CAL-1.0-Combined-Work-Exception"+licenseId CAL_1_0 = "CAL-1.0"+licenseId Caldera = "Caldera"+licenseId CATOSL_1_1 = "CATOSL-1.1"+licenseId CC_BY_1_0 = "CC-BY-1.0"+licenseId CC_BY_2_0 = "CC-BY-2.0"+licenseId CC_BY_2_5 = "CC-BY-2.5"+licenseId CC_BY_3_0_AT = "CC-BY-3.0-AT"+licenseId CC_BY_3_0 = "CC-BY-3.0"+licenseId CC_BY_4_0 = "CC-BY-4.0"+licenseId CC_BY_NC_1_0 = "CC-BY-NC-1.0"+licenseId CC_BY_NC_2_0 = "CC-BY-NC-2.0"+licenseId CC_BY_NC_2_5 = "CC-BY-NC-2.5"+licenseId CC_BY_NC_3_0 = "CC-BY-NC-3.0"+licenseId CC_BY_NC_4_0 = "CC-BY-NC-4.0"+licenseId CC_BY_NC_ND_1_0 = "CC-BY-NC-ND-1.0"+licenseId CC_BY_NC_ND_2_0 = "CC-BY-NC-ND-2.0"+licenseId CC_BY_NC_ND_2_5 = "CC-BY-NC-ND-2.5"+licenseId CC_BY_NC_ND_3_0_IGO = "CC-BY-NC-ND-3.0-IGO"+licenseId CC_BY_NC_ND_3_0 = "CC-BY-NC-ND-3.0"+licenseId CC_BY_NC_ND_4_0 = "CC-BY-NC-ND-4.0"+licenseId CC_BY_NC_SA_1_0 = "CC-BY-NC-SA-1.0"+licenseId CC_BY_NC_SA_2_0 = "CC-BY-NC-SA-2.0"+licenseId CC_BY_NC_SA_2_5 = "CC-BY-NC-SA-2.5"+licenseId CC_BY_NC_SA_3_0 = "CC-BY-NC-SA-3.0"+licenseId CC_BY_NC_SA_4_0 = "CC-BY-NC-SA-4.0"+licenseId CC_BY_ND_1_0 = "CC-BY-ND-1.0"+licenseId CC_BY_ND_2_0 = "CC-BY-ND-2.0"+licenseId CC_BY_ND_2_5 = "CC-BY-ND-2.5"+licenseId CC_BY_ND_3_0 = "CC-BY-ND-3.0"+licenseId CC_BY_ND_4_0 = "CC-BY-ND-4.0"+licenseId CC_BY_SA_1_0 = "CC-BY-SA-1.0"+licenseId CC_BY_SA_2_0 = "CC-BY-SA-2.0"+licenseId CC_BY_SA_2_5 = "CC-BY-SA-2.5"+licenseId CC_BY_SA_3_0_AT = "CC-BY-SA-3.0-AT"+licenseId CC_BY_SA_3_0 = "CC-BY-SA-3.0"+licenseId CC_BY_SA_4_0 = "CC-BY-SA-4.0"+licenseId CC_PDDC = "CC-PDDC"+licenseId CC0_1_0 = "CC0-1.0"+licenseId CDDL_1_0 = "CDDL-1.0"+licenseId CDDL_1_1 = "CDDL-1.1"+licenseId CDLA_Permissive_1_0 = "CDLA-Permissive-1.0"+licenseId CDLA_Sharing_1_0 = "CDLA-Sharing-1.0"+licenseId CECILL_1_0 = "CECILL-1.0"+licenseId CECILL_1_1 = "CECILL-1.1"+licenseId CECILL_2_0 = "CECILL-2.0"+licenseId CECILL_2_1 = "CECILL-2.1"+licenseId CECILL_B = "CECILL-B"+licenseId CECILL_C = "CECILL-C"+licenseId CERN_OHL_1_1 = "CERN-OHL-1.1"+licenseId CERN_OHL_1_2 = "CERN-OHL-1.2"+licenseId CERN_OHL_P_2_0 = "CERN-OHL-P-2.0"+licenseId CERN_OHL_S_2_0 = "CERN-OHL-S-2.0"+licenseId CERN_OHL_W_2_0 = "CERN-OHL-W-2.0"+licenseId ClArtistic = "ClArtistic"+licenseId CNRI_Jython = "CNRI-Jython"+licenseId CNRI_Python_GPL_Compatible = "CNRI-Python-GPL-Compatible"+licenseId CNRI_Python = "CNRI-Python"+licenseId Condor_1_1 = "Condor-1.1"+licenseId Copyleft_next_0_3_0 = "copyleft-next-0.3.0"+licenseId Copyleft_next_0_3_1 = "copyleft-next-0.3.1"+licenseId CPAL_1_0 = "CPAL-1.0"+licenseId CPL_1_0 = "CPL-1.0"+licenseId CPOL_1_02 = "CPOL-1.02"+licenseId Crossword = "Crossword"+licenseId CrystalStacker = "CrystalStacker"+licenseId CUA_OPL_1_0 = "CUA-OPL-1.0"+licenseId Cube = "Cube"+licenseId Curl = "curl"+licenseId D_FSL_1_0 = "D-FSL-1.0"+licenseId Diffmark = "diffmark"+licenseId DOC = "DOC"+licenseId Dotseqn = "Dotseqn"+licenseId DSDP = "DSDP"+licenseId Dvipdfm = "dvipdfm"+licenseId ECL_1_0 = "ECL-1.0"+licenseId ECL_2_0 = "ECL-2.0"+licenseId EFL_1_0 = "EFL-1.0"+licenseId EFL_2_0 = "EFL-2.0"+licenseId EGenix = "eGenix"+licenseId Entessa = "Entessa"+licenseId EPICS = "EPICS"+licenseId EPL_1_0 = "EPL-1.0"+licenseId EPL_2_0 = "EPL-2.0"+licenseId ErlPL_1_1 = "ErlPL-1.1"+licenseId Etalab_2_0 = "etalab-2.0"+licenseId EUDatagrid = "EUDatagrid"+licenseId EUPL_1_0 = "EUPL-1.0"+licenseId EUPL_1_1 = "EUPL-1.1"+licenseId EUPL_1_2 = "EUPL-1.2"+licenseId Eurosym = "Eurosym"+licenseId Fair = "Fair"+licenseId Frameworx_1_0 = "Frameworx-1.0"+licenseId FreeImage = "FreeImage"+licenseId FSFAP = "FSFAP"+licenseId FSFULLR = "FSFULLR"+licenseId FSFUL = "FSFUL"+licenseId FTL = "FTL"+licenseId GFDL_1_1_invariants_only = "GFDL-1.1-invariants-only"+licenseId GFDL_1_1_invariants_or_later = "GFDL-1.1-invariants-or-later"+licenseId GFDL_1_1_no_invariants_only = "GFDL-1.1-no-invariants-only"+licenseId GFDL_1_1_no_invariants_or_later = "GFDL-1.1-no-invariants-or-later"+licenseId GFDL_1_1_only = "GFDL-1.1-only"+licenseId GFDL_1_1_or_later = "GFDL-1.1-or-later"+licenseId GFDL_1_2_invariants_only = "GFDL-1.2-invariants-only"+licenseId GFDL_1_2_invariants_or_later = "GFDL-1.2-invariants-or-later"+licenseId GFDL_1_2_no_invariants_only = "GFDL-1.2-no-invariants-only"+licenseId GFDL_1_2_no_invariants_or_later = "GFDL-1.2-no-invariants-or-later"+licenseId GFDL_1_2_only = "GFDL-1.2-only"+licenseId GFDL_1_2_or_later = "GFDL-1.2-or-later"+licenseId GFDL_1_3_invariants_only = "GFDL-1.3-invariants-only"+licenseId GFDL_1_3_invariants_or_later = "GFDL-1.3-invariants-or-later"+licenseId GFDL_1_3_no_invariants_only = "GFDL-1.3-no-invariants-only"+licenseId GFDL_1_3_no_invariants_or_later = "GFDL-1.3-no-invariants-or-later"+licenseId GFDL_1_3_only = "GFDL-1.3-only"+licenseId GFDL_1_3_or_later = "GFDL-1.3-or-later"+licenseId Giftware = "Giftware"+licenseId GL2PS = "GL2PS"+licenseId Glide = "Glide"+licenseId Glulxe = "Glulxe"+licenseId GLWTPL = "GLWTPL"+licenseId Gnuplot = "gnuplot"+licenseId GPL_1_0_only = "GPL-1.0-only"+licenseId GPL_1_0_or_later = "GPL-1.0-or-later"+licenseId GPL_2_0_only = "GPL-2.0-only"+licenseId GPL_2_0_or_later = "GPL-2.0-or-later"+licenseId GPL_3_0_only = "GPL-3.0-only"+licenseId GPL_3_0_or_later = "GPL-3.0-or-later"+licenseId GSOAP_1_3b = "gSOAP-1.3b"+licenseId HaskellReport = "HaskellReport"+licenseId Hippocratic_2_1 = "Hippocratic-2.1"+licenseId HPND_sell_variant = "HPND-sell-variant"+licenseId HPND = "HPND"+licenseId IBM_pibs = "IBM-pibs"+licenseId ICU = "ICU"+licenseId IJG = "IJG"+licenseId ImageMagick = "ImageMagick"+licenseId IMatix = "iMatix"+licenseId Imlib2 = "Imlib2"+licenseId Info_ZIP = "Info-ZIP"+licenseId Intel_ACPI = "Intel-ACPI"+licenseId Intel = "Intel"+licenseId Interbase_1_0 = "Interbase-1.0"+licenseId IPA = "IPA"+licenseId IPL_1_0 = "IPL-1.0"+licenseId ISC = "ISC"+licenseId JasPer_2_0 = "JasPer-2.0"+licenseId JPNIC = "JPNIC"+licenseId JSON = "JSON"+licenseId LAL_1_2 = "LAL-1.2"+licenseId LAL_1_3 = "LAL-1.3"+licenseId Latex2e = "Latex2e"+licenseId Leptonica = "Leptonica"+licenseId LGPL_2_0_only = "LGPL-2.0-only"+licenseId LGPL_2_0_or_later = "LGPL-2.0-or-later"+licenseId LGPL_2_1_only = "LGPL-2.1-only"+licenseId LGPL_2_1_or_later = "LGPL-2.1-or-later"+licenseId LGPL_3_0_only = "LGPL-3.0-only"+licenseId LGPL_3_0_or_later = "LGPL-3.0-or-later"+licenseId LGPLLR = "LGPLLR"+licenseId Libpng_2_0 = "libpng-2.0"+licenseId Libpng = "Libpng"+licenseId Libselinux_1_0 = "libselinux-1.0"+licenseId Libtiff = "libtiff"+licenseId LiLiQ_P_1_1 = "LiLiQ-P-1.1"+licenseId LiLiQ_R_1_1 = "LiLiQ-R-1.1"+licenseId LiLiQ_Rplus_1_1 = "LiLiQ-Rplus-1.1"+licenseId Linux_OpenIB = "Linux-OpenIB"+licenseId LPL_1_02 = "LPL-1.02"+licenseId LPL_1_0 = "LPL-1.0"+licenseId LPPL_1_0 = "LPPL-1.0"+licenseId LPPL_1_1 = "LPPL-1.1"+licenseId LPPL_1_2 = "LPPL-1.2"+licenseId LPPL_1_3a = "LPPL-1.3a"+licenseId LPPL_1_3c = "LPPL-1.3c"+licenseId MakeIndex = "MakeIndex"+licenseId MirOS = "MirOS"+licenseId MIT_0 = "MIT-0"+licenseId MIT_advertising = "MIT-advertising"+licenseId MIT_CMU = "MIT-CMU"+licenseId MIT_enna = "MIT-enna"+licenseId MIT_feh = "MIT-feh"+licenseId MITNFA = "MITNFA"+licenseId MIT = "MIT"+licenseId Motosoto = "Motosoto"+licenseId Mpich2 = "mpich2"+licenseId MPL_1_0 = "MPL-1.0"+licenseId MPL_1_1 = "MPL-1.1"+licenseId MPL_2_0_no_copyleft_exception = "MPL-2.0-no-copyleft-exception"+licenseId MPL_2_0 = "MPL-2.0"+licenseId MS_PL = "MS-PL"+licenseId MS_RL = "MS-RL"+licenseId MTLL = "MTLL"+licenseId MulanPSL_1_0 = "MulanPSL-1.0"+licenseId MulanPSL_2_0 = "MulanPSL-2.0"+licenseId Multics = "Multics"+licenseId Mup = "Mup"+licenseId NASA_1_3 = "NASA-1.3"+licenseId Naumen = "Naumen"+licenseId NBPL_1_0 = "NBPL-1.0"+licenseId NCGL_UK_2_0 = "NCGL-UK-2.0"+licenseId NCSA = "NCSA"+licenseId Net_SNMP = "Net-SNMP"+licenseId NetCDF = "NetCDF"+licenseId Newsletr = "Newsletr"+licenseId NGPL = "NGPL"+licenseId NIST_PD_fallback = "NIST-PD-fallback"+licenseId NIST_PD = "NIST-PD"+licenseId NLOD_1_0 = "NLOD-1.0"+licenseId NLPL = "NLPL"+licenseId Nokia = "Nokia"+licenseId NOSL = "NOSL"+licenseId Noweb = "Noweb"+licenseId NPL_1_0 = "NPL-1.0"+licenseId NPL_1_1 = "NPL-1.1"+licenseId NPOSL_3_0 = "NPOSL-3.0"+licenseId NRL = "NRL"+licenseId NTP_0 = "NTP-0"+licenseId NTP = "NTP"+licenseId O_UDA_1_0 = "O-UDA-1.0"+licenseId OCCT_PL = "OCCT-PL"+licenseId OCLC_2_0 = "OCLC-2.0"+licenseId ODbL_1_0 = "ODbL-1.0"+licenseId ODC_By_1_0 = "ODC-By-1.0"+licenseId OFL_1_0_no_RFN = "OFL-1.0-no-RFN"+licenseId OFL_1_0_RFN = "OFL-1.0-RFN"+licenseId OFL_1_0 = "OFL-1.0"+licenseId OFL_1_1_no_RFN = "OFL-1.1-no-RFN"+licenseId OFL_1_1_RFN = "OFL-1.1-RFN"+licenseId OFL_1_1 = "OFL-1.1"+licenseId OGC_1_0 = "OGC-1.0"+licenseId OGL_Canada_2_0 = "OGL-Canada-2.0"+licenseId OGL_UK_1_0 = "OGL-UK-1.0"+licenseId OGL_UK_2_0 = "OGL-UK-2.0"+licenseId OGL_UK_3_0 = "OGL-UK-3.0"+licenseId OGTSL = "OGTSL"+licenseId OLDAP_1_1 = "OLDAP-1.1"+licenseId OLDAP_1_2 = "OLDAP-1.2"+licenseId OLDAP_1_3 = "OLDAP-1.3"+licenseId OLDAP_1_4 = "OLDAP-1.4"+licenseId OLDAP_2_0_1 = "OLDAP-2.0.1"+licenseId OLDAP_2_0 = "OLDAP-2.0"+licenseId OLDAP_2_1 = "OLDAP-2.1"+licenseId OLDAP_2_2_1 = "OLDAP-2.2.1"+licenseId OLDAP_2_2_2 = "OLDAP-2.2.2"+licenseId OLDAP_2_2 = "OLDAP-2.2"+licenseId OLDAP_2_3 = "OLDAP-2.3"+licenseId OLDAP_2_4 = "OLDAP-2.4"+licenseId OLDAP_2_5 = "OLDAP-2.5"+licenseId OLDAP_2_6 = "OLDAP-2.6"+licenseId OLDAP_2_7 = "OLDAP-2.7"+licenseId OLDAP_2_8 = "OLDAP-2.8"+licenseId OML = "OML"+licenseId OpenSSL = "OpenSSL"+licenseId OPL_1_0 = "OPL-1.0"+licenseId OSET_PL_2_1 = "OSET-PL-2.1"+licenseId OSL_1_0 = "OSL-1.0"+licenseId OSL_1_1 = "OSL-1.1"+licenseId OSL_2_0 = "OSL-2.0"+licenseId OSL_2_1 = "OSL-2.1"+licenseId OSL_3_0 = "OSL-3.0"+licenseId Parity_6_0_0 = "Parity-6.0.0"+licenseId Parity_7_0_0 = "Parity-7.0.0"+licenseId PDDL_1_0 = "PDDL-1.0"+licenseId PHP_3_01 = "PHP-3.01"+licenseId PHP_3_0 = "PHP-3.0"+licenseId Plexus = "Plexus"+licenseId PolyForm_Noncommercial_1_0_0 = "PolyForm-Noncommercial-1.0.0"+licenseId PolyForm_Small_Business_1_0_0 = "PolyForm-Small-Business-1.0.0"+licenseId PostgreSQL = "PostgreSQL"+licenseId PSF_2_0 = "PSF-2.0"+licenseId Psfrag = "psfrag"+licenseId Psutils = "psutils"+licenseId Python_2_0 = "Python-2.0"+licenseId Qhull = "Qhull"+licenseId QPL_1_0 = "QPL-1.0"+licenseId Rdisc = "Rdisc"+licenseId RHeCos_1_1 = "RHeCos-1.1"+licenseId RPL_1_1 = "RPL-1.1"+licenseId RPL_1_5 = "RPL-1.5"+licenseId RPSL_1_0 = "RPSL-1.0"+licenseId RSA_MD = "RSA-MD"+licenseId RSCPL = "RSCPL"+licenseId Ruby = "Ruby"+licenseId SAX_PD = "SAX-PD"+licenseId Saxpath = "Saxpath"+licenseId SCEA = "SCEA"+licenseId Sendmail_8_23 = "Sendmail-8.23"+licenseId Sendmail = "Sendmail"+licenseId SGI_B_1_0 = "SGI-B-1.0"+licenseId SGI_B_1_1 = "SGI-B-1.1"+licenseId SGI_B_2_0 = "SGI-B-2.0"+licenseId SHL_0_51 = "SHL-0.51"+licenseId SHL_0_5 = "SHL-0.5"+licenseId SimPL_2_0 = "SimPL-2.0"+licenseId SISSL_1_2 = "SISSL-1.2"+licenseId SISSL = "SISSL"+licenseId Sleepycat = "Sleepycat"+licenseId SMLNJ = "SMLNJ"+licenseId SMPPL = "SMPPL"+licenseId SNIA = "SNIA"+licenseId Spencer_86 = "Spencer-86"+licenseId Spencer_94 = "Spencer-94"+licenseId Spencer_99 = "Spencer-99"+licenseId SPL_1_0 = "SPL-1.0"+licenseId SSH_OpenSSH = "SSH-OpenSSH"+licenseId SSH_short = "SSH-short"+licenseId SSPL_1_0 = "SSPL-1.0"+licenseId SugarCRM_1_1_3 = "SugarCRM-1.1.3"+licenseId SWL = "SWL"+licenseId TAPR_OHL_1_0 = "TAPR-OHL-1.0"+licenseId TCL = "TCL"+licenseId TCP_wrappers = "TCP-wrappers"+licenseId TMate = "TMate"+licenseId TORQUE_1_1 = "TORQUE-1.1"+licenseId TOSL = "TOSL"+licenseId TU_Berlin_1_0 = "TU-Berlin-1.0"+licenseId TU_Berlin_2_0 = "TU-Berlin-2.0"+licenseId UCL_1_0 = "UCL-1.0"+licenseId Unicode_DFS_2015 = "Unicode-DFS-2015"+licenseId Unicode_DFS_2016 = "Unicode-DFS-2016"+licenseId Unicode_TOU = "Unicode-TOU"+licenseId Unlicense = "Unlicense"+licenseId UPL_1_0 = "UPL-1.0"+licenseId Vim = "Vim"+licenseId VOSTROM = "VOSTROM"+licenseId VSL_1_0 = "VSL-1.0"+licenseId W3C_19980720 = "W3C-19980720"+licenseId W3C_20150513 = "W3C-20150513"+licenseId W3C = "W3C"+licenseId Watcom_1_0 = "Watcom-1.0"+licenseId Wsuipa = "Wsuipa"+licenseId WTFPL = "WTFPL"+licenseId X11 = "X11"+licenseId Xerox = "Xerox"+licenseId XFree86_1_1 = "XFree86-1.1"+licenseId Xinetd = "xinetd"+licenseId Xnet = "Xnet"+licenseId Xpp = "xpp"+licenseId XSkat = "XSkat"+licenseId YPL_1_0 = "YPL-1.0"+licenseId YPL_1_1 = "YPL-1.1"+licenseId Zed = "Zed"+licenseId Zend_2_0 = "Zend-2.0"+licenseId Zimbra_1_3 = "Zimbra-1.3"+licenseId Zimbra_1_4 = "Zimbra-1.4"+licenseId Zlib_acknowledgement = "zlib-acknowledgement"+licenseId Zlib = "Zlib"+licenseId ZPL_1_1 = "ZPL-1.1"+licenseId ZPL_2_0 = "ZPL-2.0"+licenseId ZPL_2_1 = "ZPL-2.1"++-- | License name, e.g. @"GNU General Public License v2.0 only"@+licenseName :: LicenseId -> String+licenseName NullBSD = "BSD Zero Clause License"+licenseName AAL = "Attribution Assurance License"+licenseName Abstyles = "Abstyles License"+licenseName Adobe_2006 = "Adobe Systems Incorporated Source Code License Agreement"+licenseName Adobe_Glyph = "Adobe Glyph List License"+licenseName ADSL = "Amazon Digital Services License"+licenseName AFL_1_1 = "Academic Free License v1.1"+licenseName AFL_1_2 = "Academic Free License v1.2"+licenseName AFL_2_0 = "Academic Free License v2.0"+licenseName AFL_2_1 = "Academic Free License v2.1"+licenseName AFL_3_0 = "Academic Free License v3.0"+licenseName Afmparse = "Afmparse License"+licenseName AGPL_1_0 = "Affero General Public License v1.0"+licenseName AGPL_1_0_only = "Affero General Public License v1.0 only"+licenseName AGPL_1_0_or_later = "Affero General Public License v1.0 or later"+licenseName AGPL_3_0_only = "GNU Affero General Public License v3.0 only"+licenseName AGPL_3_0_or_later = "GNU Affero General Public License v3.0 or later"+licenseName Aladdin = "Aladdin Free Public License"+licenseName AMDPLPA = "AMD's plpa_map.c License"+licenseName AML = "Apple MIT License"+licenseName AMPAS = "Academy of Motion Picture Arts and Sciences BSD"+licenseName ANTLR_PD = "ANTLR Software Rights Notice"+licenseName Apache_1_0 = "Apache License 1.0"+licenseName Apache_1_1 = "Apache License 1.1"+licenseName Apache_2_0 = "Apache License 2.0"+licenseName APAFML = "Adobe Postscript AFM License"+licenseName APL_1_0 = "Adaptive Public License 1.0"+licenseName APSL_1_0 = "Apple Public Source License 1.0"+licenseName APSL_1_1 = "Apple Public Source License 1.1"+licenseName APSL_1_2 = "Apple Public Source License 1.2"+licenseName APSL_2_0 = "Apple Public Source License 2.0"+licenseName Artistic_1_0_cl8 = "Artistic License 1.0 w/clause 8"+licenseName Artistic_1_0_Perl = "Artistic License 1.0 (Perl)"+licenseName Artistic_1_0 = "Artistic License 1.0"+licenseName Artistic_2_0 = "Artistic License 2.0"+licenseName Bahyph = "Bahyph License"+licenseName Barr = "Barr License"+licenseName Beerware = "Beerware License"+licenseName BitTorrent_1_0 = "BitTorrent Open Source License v1.0"+licenseName BitTorrent_1_1 = "BitTorrent Open Source License v1.1"+licenseName Blessing = "SQLite Blessing"+licenseName BlueOak_1_0_0 = "Blue Oak Model License 1.0.0"+licenseName Borceux = "Borceux license"+licenseName BSD_1_Clause = "BSD 1-Clause License"+licenseName BSD_2_Clause_FreeBSD = "BSD 2-Clause FreeBSD License"+licenseName BSD_2_Clause_NetBSD = "BSD 2-Clause NetBSD License"+licenseName BSD_2_Clause_Patent = "BSD-2-Clause Plus Patent License"+licenseName BSD_2_Clause_Views = "BSD 2-Clause with views sentence"+licenseName BSD_2_Clause = "BSD 2-Clause \"Simplified\" License"+licenseName BSD_3_Clause_Attribution = "BSD with attribution"+licenseName BSD_3_Clause_Clear = "BSD 3-Clause Clear License"+licenseName BSD_3_Clause_LBNL = "Lawrence Berkeley National Labs BSD variant license"+licenseName BSD_3_Clause_No_Nuclear_License_2014 = "BSD 3-Clause No Nuclear License 2014"+licenseName BSD_3_Clause_No_Nuclear_License = "BSD 3-Clause No Nuclear License"+licenseName BSD_3_Clause_No_Nuclear_Warranty = "BSD 3-Clause No Nuclear Warranty"+licenseName BSD_3_Clause_Open_MPI = "BSD 3-Clause Open MPI variant"+licenseName BSD_3_Clause = "BSD 3-Clause \"New\" or \"Revised\" License"+licenseName BSD_4_Clause_UC = "BSD-4-Clause (University of California-Specific)"+licenseName BSD_4_Clause = "BSD 4-Clause \"Original\" or \"Old\" License"+licenseName BSD_Protection = "BSD Protection License"+licenseName BSD_Source_Code = "BSD Source Code Attribution"+licenseName BSL_1_0 = "Boost Software License 1.0"+licenseName Bzip2_1_0_5 = "bzip2 and libbzip2 License v1.0.5"+licenseName Bzip2_1_0_6 = "bzip2 and libbzip2 License v1.0.6"+licenseName CAL_1_0_Combined_Work_Exception = "Cryptographic Autonomy License 1.0 (Combined Work Exception)"+licenseName CAL_1_0 = "Cryptographic Autonomy License 1.0"+licenseName Caldera = "Caldera License"+licenseName CATOSL_1_1 = "Computer Associates Trusted Open Source License 1.1"+licenseName CC_BY_1_0 = "Creative Commons Attribution 1.0 Generic"+licenseName CC_BY_2_0 = "Creative Commons Attribution 2.0 Generic"+licenseName CC_BY_2_5 = "Creative Commons Attribution 2.5 Generic"+licenseName CC_BY_3_0_AT = "Creative Commons Attribution 3.0 Austria"+licenseName CC_BY_3_0 = "Creative Commons Attribution 3.0 Unported"+licenseName CC_BY_4_0 = "Creative Commons Attribution 4.0 International"+licenseName CC_BY_NC_1_0 = "Creative Commons Attribution Non Commercial 1.0 Generic"+licenseName CC_BY_NC_2_0 = "Creative Commons Attribution Non Commercial 2.0 Generic"+licenseName CC_BY_NC_2_5 = "Creative Commons Attribution Non Commercial 2.5 Generic"+licenseName CC_BY_NC_3_0 = "Creative Commons Attribution Non Commercial 3.0 Unported"+licenseName CC_BY_NC_4_0 = "Creative Commons Attribution Non Commercial 4.0 International"+licenseName CC_BY_NC_ND_1_0 = "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic"+licenseName CC_BY_NC_ND_2_0 = "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic"+licenseName CC_BY_NC_ND_2_5 = "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic"+licenseName CC_BY_NC_ND_3_0_IGO = "Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO"+licenseName CC_BY_NC_ND_3_0 = "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported"+licenseName CC_BY_NC_ND_4_0 = "Creative Commons Attribution Non Commercial No Derivatives 4.0 International"+licenseName CC_BY_NC_SA_1_0 = "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic"+licenseName CC_BY_NC_SA_2_0 = "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic"+licenseName CC_BY_NC_SA_2_5 = "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic"+licenseName CC_BY_NC_SA_3_0 = "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported"+licenseName CC_BY_NC_SA_4_0 = "Creative Commons Attribution Non Commercial Share Alike 4.0 International"+licenseName CC_BY_ND_1_0 = "Creative Commons Attribution No Derivatives 1.0 Generic"+licenseName CC_BY_ND_2_0 = "Creative Commons Attribution No Derivatives 2.0 Generic"+licenseName CC_BY_ND_2_5 = "Creative Commons Attribution No Derivatives 2.5 Generic"+licenseName CC_BY_ND_3_0 = "Creative Commons Attribution No Derivatives 3.0 Unported"+licenseName CC_BY_ND_4_0 = "Creative Commons Attribution No Derivatives 4.0 International"+licenseName CC_BY_SA_1_0 = "Creative Commons Attribution Share Alike 1.0 Generic"+licenseName CC_BY_SA_2_0 = "Creative Commons Attribution Share Alike 2.0 Generic"+licenseName CC_BY_SA_2_5 = "Creative Commons Attribution Share Alike 2.5 Generic"+licenseName CC_BY_SA_3_0_AT = "Creative Commons Attribution-Share Alike 3.0 Austria"+licenseName CC_BY_SA_3_0 = "Creative Commons Attribution Share Alike 3.0 Unported"+licenseName CC_BY_SA_4_0 = "Creative Commons Attribution Share Alike 4.0 International"+licenseName CC_PDDC = "Creative Commons Public Domain Dedication and Certification"+licenseName CC0_1_0 = "Creative Commons Zero v1.0 Universal"+licenseName CDDL_1_0 = "Common Development and Distribution License 1.0"+licenseName CDDL_1_1 = "Common Development and Distribution License 1.1"+licenseName CDLA_Permissive_1_0 = "Community Data License Agreement Permissive 1.0"+licenseName CDLA_Sharing_1_0 = "Community Data License Agreement Sharing 1.0"+licenseName CECILL_1_0 = "CeCILL Free Software License Agreement v1.0"+licenseName CECILL_1_1 = "CeCILL Free Software License Agreement v1.1"+licenseName CECILL_2_0 = "CeCILL Free Software License Agreement v2.0"+licenseName CECILL_2_1 = "CeCILL Free Software License Agreement v2.1"+licenseName CECILL_B = "CeCILL-B Free Software License Agreement"+licenseName CECILL_C = "CeCILL-C Free Software License Agreement"+licenseName CERN_OHL_1_1 = "CERN Open Hardware Licence v1.1"+licenseName CERN_OHL_1_2 = "CERN Open Hardware Licence v1.2"+licenseName CERN_OHL_P_2_0 = "CERN Open Hardware Licence Version 2 - Permissive"+licenseName CERN_OHL_S_2_0 = "CERN Open Hardware Licence Version 2 - Strongly Reciprocal"+licenseName CERN_OHL_W_2_0 = "CERN Open Hardware Licence Version 2 - Weakly Reciprocal"+licenseName ClArtistic = "Clarified Artistic License"+licenseName CNRI_Jython = "CNRI Jython License"+licenseName CNRI_Python_GPL_Compatible = "CNRI Python Open Source GPL Compatible License Agreement"+licenseName CNRI_Python = "CNRI Python License"+licenseName Condor_1_1 = "Condor Public License v1.1"+licenseName Copyleft_next_0_3_0 = "copyleft-next 0.3.0"+licenseName Copyleft_next_0_3_1 = "copyleft-next 0.3.1"+licenseName CPAL_1_0 = "Common Public Attribution License 1.0"+licenseName CPL_1_0 = "Common Public License 1.0"+licenseName CPOL_1_02 = "Code Project Open License 1.02"+licenseName Crossword = "Crossword License"+licenseName CrystalStacker = "CrystalStacker License"+licenseName CUA_OPL_1_0 = "CUA Office Public License v1.0"+licenseName Cube = "Cube License"+licenseName Curl = "curl License"+licenseName D_FSL_1_0 = "Deutsche Freie Software Lizenz"+licenseName Diffmark = "diffmark license"+licenseName DOC = "DOC License"+licenseName Dotseqn = "Dotseqn License"+licenseName DSDP = "DSDP License"+licenseName Dvipdfm = "dvipdfm License"+licenseName ECL_1_0 = "Educational Community License v1.0"+licenseName ECL_2_0 = "Educational Community License v2.0"+licenseName EFL_1_0 = "Eiffel Forum License v1.0"+licenseName EFL_2_0 = "Eiffel Forum License v2.0"+licenseName EGenix = "eGenix.com Public License 1.1.0"+licenseName Entessa = "Entessa Public License v1.0"+licenseName EPICS = "EPICS Open License"+licenseName EPL_1_0 = "Eclipse Public License 1.0"+licenseName EPL_2_0 = "Eclipse Public License 2.0"+licenseName ErlPL_1_1 = "Erlang Public License v1.1"+licenseName Etalab_2_0 = "Etalab Open License 2.0"+licenseName EUDatagrid = "EU DataGrid Software License"+licenseName EUPL_1_0 = "European Union Public License 1.0"+licenseName EUPL_1_1 = "European Union Public License 1.1"+licenseName EUPL_1_2 = "European Union Public License 1.2"+licenseName Eurosym = "Eurosym License"+licenseName Fair = "Fair License"+licenseName Frameworx_1_0 = "Frameworx Open License 1.0"+licenseName FreeImage = "FreeImage Public License v1.0"+licenseName FSFAP = "FSF All Permissive License"+licenseName FSFULLR = "FSF Unlimited License (with License Retention)"+licenseName FSFUL = "FSF Unlimited License"+licenseName FTL = "Freetype Project License"+licenseName GFDL_1_1_invariants_only = "GNU Free Documentation License v1.1 only - invariants"+licenseName GFDL_1_1_invariants_or_later = "GNU Free Documentation License v1.1 or later - invariants"+licenseName GFDL_1_1_no_invariants_only = "GNU Free Documentation License v1.1 only - no invariants"+licenseName GFDL_1_1_no_invariants_or_later = "GNU Free Documentation License v1.1 or later - no invariants"+licenseName GFDL_1_1_only = "GNU Free Documentation License v1.1 only"+licenseName GFDL_1_1_or_later = "GNU Free Documentation License v1.1 or later"+licenseName GFDL_1_2_invariants_only = "GNU Free Documentation License v1.2 only - invariants"+licenseName GFDL_1_2_invariants_or_later = "GNU Free Documentation License v1.2 or later - invariants"+licenseName GFDL_1_2_no_invariants_only = "GNU Free Documentation License v1.2 only - no invariants"+licenseName GFDL_1_2_no_invariants_or_later = "GNU Free Documentation License v1.2 or later - no invariants"+licenseName GFDL_1_2_only = "GNU Free Documentation License v1.2 only"+licenseName GFDL_1_2_or_later = "GNU Free Documentation License v1.2 or later"+licenseName GFDL_1_3_invariants_only = "GNU Free Documentation License v1.3 only - invariants"+licenseName GFDL_1_3_invariants_or_later = "GNU Free Documentation License v1.3 or later - invariants"+licenseName GFDL_1_3_no_invariants_only = "GNU Free Documentation License v1.3 only - no invariants"+licenseName GFDL_1_3_no_invariants_or_later = "GNU Free Documentation License v1.3 or later - no invariants"+licenseName GFDL_1_3_only = "GNU Free Documentation License v1.3 only"+licenseName GFDL_1_3_or_later = "GNU Free Documentation License v1.3 or later"+licenseName Giftware = "Giftware License"+licenseName GL2PS = "GL2PS License"+licenseName Glide = "3dfx Glide License"+licenseName Glulxe = "Glulxe License"+licenseName GLWTPL = "Good Luck With That Public License"+licenseName Gnuplot = "gnuplot License"+licenseName GPL_1_0_only = "GNU General Public License v1.0 only"+licenseName GPL_1_0_or_later = "GNU General Public License v1.0 or later"+licenseName GPL_2_0_only = "GNU General Public License v2.0 only"+licenseName GPL_2_0_or_later = "GNU General Public License v2.0 or later"+licenseName GPL_3_0_only = "GNU General Public License v3.0 only"+licenseName GPL_3_0_or_later = "GNU General Public License v3.0 or later"+licenseName GSOAP_1_3b = "gSOAP Public License v1.3b"+licenseName HaskellReport = "Haskell Language Report License"+licenseName Hippocratic_2_1 = "Hippocratic License 2.1"+licenseName HPND_sell_variant = "Historical Permission Notice and Disclaimer - sell variant"+licenseName HPND = "Historical Permission Notice and Disclaimer"+licenseName IBM_pibs = "IBM PowerPC Initialization and Boot Software"+licenseName ICU = "ICU License"+licenseName IJG = "Independent JPEG Group License"+licenseName ImageMagick = "ImageMagick License"+licenseName IMatix = "iMatix Standard Function Library Agreement"+licenseName Imlib2 = "Imlib2 License"+licenseName Info_ZIP = "Info-ZIP License"+licenseName Intel_ACPI = "Intel ACPI Software License Agreement"+licenseName Intel = "Intel Open Source License"+licenseName Interbase_1_0 = "Interbase Public License v1.0"+licenseName IPA = "IPA Font License"+licenseName IPL_1_0 = "IBM Public License v1.0"+licenseName ISC = "ISC License"+licenseName JasPer_2_0 = "JasPer License"+licenseName JPNIC = "Japan Network Information Center License"+licenseName JSON = "JSON License"+licenseName LAL_1_2 = "Licence Art Libre 1.2"+licenseName LAL_1_3 = "Licence Art Libre 1.3"+licenseName Latex2e = "Latex2e License"+licenseName Leptonica = "Leptonica License"+licenseName LGPL_2_0_only = "GNU Library General Public License v2 only"+licenseName LGPL_2_0_or_later = "GNU Library General Public License v2 or later"+licenseName LGPL_2_1_only = "GNU Lesser General Public License v2.1 only"+licenseName LGPL_2_1_or_later = "GNU Lesser General Public License v2.1 or later"+licenseName LGPL_3_0_only = "GNU Lesser General Public License v3.0 only"+licenseName LGPL_3_0_or_later = "GNU Lesser General Public License v3.0 or later"+licenseName LGPLLR = "Lesser General Public License For Linguistic Resources"+licenseName Libpng_2_0 = "PNG Reference Library version 2"+licenseName Libpng = "libpng License"+licenseName Libselinux_1_0 = "libselinux public domain notice"+licenseName Libtiff = "libtiff License"+licenseName LiLiQ_P_1_1 = "Licence Libre du Qu\233bec \8211 Permissive version 1.1"+licenseName LiLiQ_R_1_1 = "Licence Libre du Qu\233bec \8211 R\233ciprocit\233 version 1.1"+licenseName LiLiQ_Rplus_1_1 = "Licence Libre du Qu\233bec \8211 R\233ciprocit\233 forte version 1.1"+licenseName Linux_OpenIB = "Linux Kernel Variant of OpenIB.org license"+licenseName LPL_1_02 = "Lucent Public License v1.02"+licenseName LPL_1_0 = "Lucent Public License Version 1.0"+licenseName LPPL_1_0 = "LaTeX Project Public License v1.0"+licenseName LPPL_1_1 = "LaTeX Project Public License v1.1"+licenseName LPPL_1_2 = "LaTeX Project Public License v1.2"+licenseName LPPL_1_3a = "LaTeX Project Public License v1.3a"+licenseName LPPL_1_3c = "LaTeX Project Public License v1.3c"+licenseName MakeIndex = "MakeIndex License"+licenseName MirOS = "The MirOS Licence"+licenseName MIT_0 = "MIT No Attribution"+licenseName MIT_advertising = "Enlightenment License (e16)"+licenseName MIT_CMU = "CMU License"+licenseName MIT_enna = "enna License"+licenseName MIT_feh = "feh License"+licenseName MITNFA = "MIT +no-false-attribs license"+licenseName MIT = "MIT License"+licenseName Motosoto = "Motosoto License"+licenseName Mpich2 = "mpich2 License"+licenseName MPL_1_0 = "Mozilla Public License 1.0"+licenseName MPL_1_1 = "Mozilla Public License 1.1"+licenseName MPL_2_0_no_copyleft_exception = "Mozilla Public License 2.0 (no copyleft exception)"+licenseName MPL_2_0 = "Mozilla Public License 2.0"+licenseName MS_PL = "Microsoft Public License"+licenseName MS_RL = "Microsoft Reciprocal License"+licenseName MTLL = "Matrix Template Library License"+licenseName MulanPSL_1_0 = "Mulan Permissive Software License, Version 1"+licenseName MulanPSL_2_0 = "Mulan Permissive Software License, Version 2"+licenseName Multics = "Multics License"+licenseName Mup = "Mup License"+licenseName NASA_1_3 = "NASA Open Source Agreement 1.3"+licenseName Naumen = "Naumen Public License"+licenseName NBPL_1_0 = "Net Boolean Public License v1"+licenseName NCGL_UK_2_0 = "Non-Commercial Government Licence"+licenseName NCSA = "University of Illinois/NCSA Open Source License"+licenseName Net_SNMP = "Net-SNMP License"+licenseName NetCDF = "NetCDF license"+licenseName Newsletr = "Newsletr License"+licenseName NGPL = "Nethack General Public License"+licenseName NIST_PD_fallback = "NIST Public Domain Notice with license fallback"+licenseName NIST_PD = "NIST Public Domain Notice"+licenseName NLOD_1_0 = "Norwegian Licence for Open Government Data"+licenseName NLPL = "No Limit Public License"+licenseName Nokia = "Nokia Open Source License"+licenseName NOSL = "Netizen Open Source License"+licenseName Noweb = "Noweb License"+licenseName NPL_1_0 = "Netscape Public License v1.0"+licenseName NPL_1_1 = "Netscape Public License v1.1"+licenseName NPOSL_3_0 = "Non-Profit Open Software License 3.0"+licenseName NRL = "NRL License"+licenseName NTP_0 = "NTP No Attribution"+licenseName NTP = "NTP License"+licenseName O_UDA_1_0 = "Open Use of Data Agreement v1.0"+licenseName OCCT_PL = "Open CASCADE Technology Public License"+licenseName OCLC_2_0 = "OCLC Research Public License 2.0"+licenseName ODbL_1_0 = "ODC Open Database License v1.0"+licenseName ODC_By_1_0 = "Open Data Commons Attribution License v1.0"+licenseName OFL_1_0_no_RFN = "SIL Open Font License 1.0 with no Reserved Font Name"+licenseName OFL_1_0_RFN = "SIL Open Font License 1.0 with Reserved Font Name"+licenseName OFL_1_0 = "SIL Open Font License 1.0"+licenseName OFL_1_1_no_RFN = "SIL Open Font License 1.1 with no Reserved Font Name"+licenseName OFL_1_1_RFN = "SIL Open Font License 1.1 with Reserved Font Name"+licenseName OFL_1_1 = "SIL Open Font License 1.1"+licenseName OGC_1_0 = "OGC Software License, Version 1.0"+licenseName OGL_Canada_2_0 = "Open Government Licence - Canada"+licenseName OGL_UK_1_0 = "Open Government Licence v1.0"+licenseName OGL_UK_2_0 = "Open Government Licence v2.0"+licenseName OGL_UK_3_0 = "Open Government Licence v3.0"+licenseName OGTSL = "Open Group Test Suite License"+licenseName OLDAP_1_1 = "Open LDAP Public License v1.1"+licenseName OLDAP_1_2 = "Open LDAP Public License v1.2"+licenseName OLDAP_1_3 = "Open LDAP Public License v1.3"+licenseName OLDAP_1_4 = "Open LDAP Public License v1.4"+licenseName OLDAP_2_0_1 = "Open LDAP Public License v2.0.1"+licenseName OLDAP_2_0 = "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)"+licenseName OLDAP_2_1 = "Open LDAP Public License v2.1"+licenseName OLDAP_2_2_1 = "Open LDAP Public License v2.2.1"+licenseName OLDAP_2_2_2 = "Open LDAP Public License 2.2.2"+licenseName OLDAP_2_2 = "Open LDAP Public License v2.2"+licenseName OLDAP_2_3 = "Open LDAP Public License v2.3"+licenseName OLDAP_2_4 = "Open LDAP Public License v2.4"+licenseName OLDAP_2_5 = "Open LDAP Public License v2.5"+licenseName OLDAP_2_6 = "Open LDAP Public License v2.6"+licenseName OLDAP_2_7 = "Open LDAP Public License v2.7"+licenseName OLDAP_2_8 = "Open LDAP Public License v2.8"+licenseName OML = "Open Market License"+licenseName OpenSSL = "OpenSSL License"+licenseName OPL_1_0 = "Open Public License v1.0"+licenseName OSET_PL_2_1 = "OSET Public License version 2.1"+licenseName OSL_1_0 = "Open Software License 1.0"+licenseName OSL_1_1 = "Open Software License 1.1"+licenseName OSL_2_0 = "Open Software License 2.0"+licenseName OSL_2_1 = "Open Software License 2.1"+licenseName OSL_3_0 = "Open Software License 3.0"+licenseName Parity_6_0_0 = "The Parity Public License 6.0.0"+licenseName Parity_7_0_0 = "The Parity Public License 7.0.0"+licenseName PDDL_1_0 = "ODC Public Domain Dedication & License 1.0"+licenseName PHP_3_01 = "PHP License v3.01"+licenseName PHP_3_0 = "PHP License v3.0"+licenseName Plexus = "Plexus Classworlds License"+licenseName PolyForm_Noncommercial_1_0_0 = "PolyForm Noncommercial License 1.0.0"+licenseName PolyForm_Small_Business_1_0_0 = "PolyForm Small Business License 1.0.0"+licenseName PostgreSQL = "PostgreSQL License"+licenseName PSF_2_0 = "Python Software Foundation License 2.0"+licenseName Psfrag = "psfrag License"+licenseName Psutils = "psutils License"+licenseName Python_2_0 = "Python License 2.0"+licenseName Qhull = "Qhull License"+licenseName QPL_1_0 = "Q Public License 1.0"+licenseName Rdisc = "Rdisc License"+licenseName RHeCos_1_1 = "Red Hat eCos Public License v1.1"+licenseName RPL_1_1 = "Reciprocal Public License 1.1"+licenseName RPL_1_5 = "Reciprocal Public License 1.5"+licenseName RPSL_1_0 = "RealNetworks Public Source License v1.0"+licenseName RSA_MD = "RSA Message-Digest License"+licenseName RSCPL = "Ricoh Source Code Public License"+licenseName Ruby = "Ruby License"+licenseName SAX_PD = "Sax Public Domain Notice"+licenseName Saxpath = "Saxpath License"+licenseName SCEA = "SCEA Shared Source License"+licenseName Sendmail_8_23 = "Sendmail License 8.23"+licenseName Sendmail = "Sendmail License"+licenseName SGI_B_1_0 = "SGI Free Software License B v1.0"+licenseName SGI_B_1_1 = "SGI Free Software License B v1.1"+licenseName SGI_B_2_0 = "SGI Free Software License B v2.0"+licenseName SHL_0_51 = "Solderpad Hardware License, Version 0.51"+licenseName SHL_0_5 = "Solderpad Hardware License v0.5"+licenseName SimPL_2_0 = "Simple Public License 2.0"+licenseName SISSL_1_2 = "Sun Industry Standards Source License v1.2"+licenseName SISSL = "Sun Industry Standards Source License v1.1"+licenseName Sleepycat = "Sleepycat License"+licenseName SMLNJ = "Standard ML of New Jersey License"+licenseName SMPPL = "Secure Messaging Protocol Public License"+licenseName SNIA = "SNIA Public License 1.1"+licenseName Spencer_86 = "Spencer License 86"+licenseName Spencer_94 = "Spencer License 94"+licenseName Spencer_99 = "Spencer License 99"+licenseName SPL_1_0 = "Sun Public License v1.0"+licenseName SSH_OpenSSH = "SSH OpenSSH license"+licenseName SSH_short = "SSH short notice"+licenseName SSPL_1_0 = "Server Side Public License, v 1"+licenseName SugarCRM_1_1_3 = "SugarCRM Public License v1.1.3"+licenseName SWL = "Scheme Widget Library (SWL) Software License Agreement"+licenseName TAPR_OHL_1_0 = "TAPR Open Hardware License v1.0"+licenseName TCL = "TCL/TK License"+licenseName TCP_wrappers = "TCP Wrappers License"+licenseName TMate = "TMate Open Source License"+licenseName TORQUE_1_1 = "TORQUE v2.5+ Software License v1.1"+licenseName TOSL = "Trusster Open Source License"+licenseName TU_Berlin_1_0 = "Technische Universitaet Berlin License 1.0"+licenseName TU_Berlin_2_0 = "Technische Universitaet Berlin License 2.0"+licenseName UCL_1_0 = "Upstream Compatibility License v1.0"+licenseName Unicode_DFS_2015 = "Unicode License Agreement - Data Files and Software (2015)"+licenseName Unicode_DFS_2016 = "Unicode License Agreement - Data Files and Software (2016)"+licenseName Unicode_TOU = "Unicode Terms of Use"+licenseName Unlicense = "The Unlicense"+licenseName UPL_1_0 = "Universal Permissive License v1.0"+licenseName Vim = "Vim License"+licenseName VOSTROM = "VOSTROM Public License for Open Source"+licenseName VSL_1_0 = "Vovida Software License v1.0"+licenseName W3C_19980720 = "W3C Software Notice and License (1998-07-20)"+licenseName W3C_20150513 = "W3C Software Notice and Document License (2015-05-13)"+licenseName W3C = "W3C Software Notice and License (2002-12-31)"+licenseName Watcom_1_0 = "Sybase Open Watcom Public License 1.0"+licenseName Wsuipa = "Wsuipa License"+licenseName WTFPL = "Do What The F*ck You Want To Public License"+licenseName X11 = "X11 License"+licenseName Xerox = "Xerox License"+licenseName XFree86_1_1 = "XFree86 License 1.1"+licenseName Xinetd = "xinetd License"+licenseName Xnet = "X.Net License"+licenseName Xpp = "XPP License"+licenseName XSkat = "XSkat License"+licenseName YPL_1_0 = "Yahoo! Public License v1.0"+licenseName YPL_1_1 = "Yahoo! Public License v1.1"+licenseName Zed = "Zed License"+licenseName Zend_2_0 = "Zend License v2.0"+licenseName Zimbra_1_3 = "Zimbra Public License v1.3"+licenseName Zimbra_1_4 = "Zimbra Public License v1.4"+licenseName Zlib_acknowledgement = "zlib/libpng License with Acknowledgement"+licenseName Zlib = "zlib License"+licenseName ZPL_1_1 = "Zope Public License 1.1"+licenseName ZPL_2_0 = "Zope Public License 2.0"+licenseName ZPL_2_1 = "Zope Public License 2.1"++-- | Whether the license is approved by Open Source Initiative (OSI).+--+-- See <https://opensource.org/licenses/alphabetical>.+licenseIsOsiApproved :: LicenseId -> Bool+licenseIsOsiApproved NullBSD = True+licenseIsOsiApproved AAL = True+licenseIsOsiApproved AFL_1_1 = True+licenseIsOsiApproved AFL_1_2 = True+licenseIsOsiApproved AFL_2_0 = True+licenseIsOsiApproved AFL_2_1 = True+licenseIsOsiApproved AFL_3_0 = True+licenseIsOsiApproved AGPL_3_0_only = True+licenseIsOsiApproved AGPL_3_0_or_later = True+licenseIsOsiApproved Apache_1_1 = True+licenseIsOsiApproved Apache_2_0 = True+licenseIsOsiApproved APL_1_0 = True+licenseIsOsiApproved APSL_1_0 = True+licenseIsOsiApproved APSL_1_1 = True+licenseIsOsiApproved APSL_1_2 = True+licenseIsOsiApproved APSL_2_0 = True+licenseIsOsiApproved Artistic_1_0_cl8 = True+licenseIsOsiApproved Artistic_1_0_Perl = True+licenseIsOsiApproved Artistic_1_0 = True+licenseIsOsiApproved Artistic_2_0 = True+licenseIsOsiApproved BSD_1_Clause = True+licenseIsOsiApproved BSD_2_Clause_Patent = True+licenseIsOsiApproved BSD_2_Clause = True+licenseIsOsiApproved BSD_3_Clause_LBNL = True+licenseIsOsiApproved BSD_3_Clause = True+licenseIsOsiApproved BSL_1_0 = True+licenseIsOsiApproved CAL_1_0_Combined_Work_Exception = True+licenseIsOsiApproved CAL_1_0 = True+licenseIsOsiApproved CATOSL_1_1 = True+licenseIsOsiApproved CDDL_1_0 = True+licenseIsOsiApproved CECILL_2_1 = True+licenseIsOsiApproved CNRI_Python = True+licenseIsOsiApproved CPAL_1_0 = True+licenseIsOsiApproved CPL_1_0 = True+licenseIsOsiApproved CUA_OPL_1_0 = True+licenseIsOsiApproved ECL_1_0 = True+licenseIsOsiApproved ECL_2_0 = True+licenseIsOsiApproved EFL_1_0 = True+licenseIsOsiApproved EFL_2_0 = True+licenseIsOsiApproved Entessa = True+licenseIsOsiApproved EPL_1_0 = True+licenseIsOsiApproved EPL_2_0 = True+licenseIsOsiApproved EUDatagrid = True+licenseIsOsiApproved EUPL_1_1 = True+licenseIsOsiApproved EUPL_1_2 = True+licenseIsOsiApproved Fair = True+licenseIsOsiApproved Frameworx_1_0 = True+licenseIsOsiApproved GPL_2_0_only = True+licenseIsOsiApproved GPL_2_0_or_later = True+licenseIsOsiApproved GPL_3_0_only = True+licenseIsOsiApproved GPL_3_0_or_later = True+licenseIsOsiApproved HPND = True+licenseIsOsiApproved Intel = True+licenseIsOsiApproved IPA = True+licenseIsOsiApproved IPL_1_0 = True+licenseIsOsiApproved ISC = True+licenseIsOsiApproved LGPL_2_0_only = True+licenseIsOsiApproved LGPL_2_0_or_later = True+licenseIsOsiApproved LGPL_2_1_only = True+licenseIsOsiApproved LGPL_2_1_or_later = True+licenseIsOsiApproved LGPL_3_0_only = True+licenseIsOsiApproved LGPL_3_0_or_later = True+licenseIsOsiApproved LiLiQ_P_1_1 = True+licenseIsOsiApproved LiLiQ_R_1_1 = True+licenseIsOsiApproved LiLiQ_Rplus_1_1 = True+licenseIsOsiApproved LPL_1_02 = True+licenseIsOsiApproved LPL_1_0 = True+licenseIsOsiApproved LPPL_1_3c = True+licenseIsOsiApproved MirOS = True+licenseIsOsiApproved MIT = True+licenseIsOsiApproved Motosoto = True+licenseIsOsiApproved MPL_1_0 = True+licenseIsOsiApproved MPL_1_1 = True+licenseIsOsiApproved MPL_2_0_no_copyleft_exception = True+licenseIsOsiApproved MPL_2_0 = True+licenseIsOsiApproved MS_PL = True+licenseIsOsiApproved MS_RL = True+licenseIsOsiApproved MulanPSL_2_0 = True+licenseIsOsiApproved Multics = True+licenseIsOsiApproved NASA_1_3 = True+licenseIsOsiApproved Naumen = True+licenseIsOsiApproved NCSA = True+licenseIsOsiApproved NGPL = True+licenseIsOsiApproved Nokia = True+licenseIsOsiApproved NPOSL_3_0 = True+licenseIsOsiApproved NTP = True+licenseIsOsiApproved OCLC_2_0 = True+licenseIsOsiApproved OFL_1_1_no_RFN = True+licenseIsOsiApproved OFL_1_1_RFN = True+licenseIsOsiApproved OFL_1_1 = True+licenseIsOsiApproved OGTSL = True+licenseIsOsiApproved OSET_PL_2_1 = True+licenseIsOsiApproved OSL_1_0 = True+licenseIsOsiApproved OSL_2_0 = True+licenseIsOsiApproved OSL_2_1 = True+licenseIsOsiApproved OSL_3_0 = True+licenseIsOsiApproved PHP_3_01 = True+licenseIsOsiApproved PHP_3_0 = True+licenseIsOsiApproved PostgreSQL = True+licenseIsOsiApproved Python_2_0 = True+licenseIsOsiApproved QPL_1_0 = True+licenseIsOsiApproved RPL_1_1 = True+licenseIsOsiApproved RPL_1_5 = True+licenseIsOsiApproved RPSL_1_0 = True+licenseIsOsiApproved RSCPL = True+licenseIsOsiApproved SimPL_2_0 = True+licenseIsOsiApproved SISSL = True+licenseIsOsiApproved Sleepycat = True+licenseIsOsiApproved SPL_1_0 = True+licenseIsOsiApproved UCL_1_0 = True+licenseIsOsiApproved Unlicense = True+licenseIsOsiApproved UPL_1_0 = True+licenseIsOsiApproved VSL_1_0 = True+licenseIsOsiApproved W3C = True+licenseIsOsiApproved Watcom_1_0 = True+licenseIsOsiApproved Xnet = True+licenseIsOsiApproved Zlib = True+licenseIsOsiApproved ZPL_2_0 = True+licenseIsOsiApproved _ = False++-- | Whether the license is considered libre by Free Software Foundation (FSF).+--+-- See <https://www.gnu.org/licenses/license-list.en.html>+--+-- @since 3.4.0.0+--+licenseIsFsfLibre :: LicenseId -> Bool+licenseIsFsfLibre AFL_1_1 = True+licenseIsFsfLibre AFL_1_2 = True+licenseIsFsfLibre AFL_2_0 = True+licenseIsFsfLibre AFL_2_1 = True+licenseIsFsfLibre AFL_3_0 = True+licenseIsFsfLibre AGPL_1_0 = True+licenseIsFsfLibre AGPL_3_0_only = True+licenseIsFsfLibre AGPL_3_0_or_later = True+licenseIsFsfLibre Apache_1_0 = True+licenseIsFsfLibre Apache_1_1 = True+licenseIsFsfLibre Apache_2_0 = True+licenseIsFsfLibre APSL_2_0 = True+licenseIsFsfLibre Artistic_2_0 = True+licenseIsFsfLibre BitTorrent_1_1 = True+licenseIsFsfLibre BSD_2_Clause_FreeBSD = True+licenseIsFsfLibre BSD_3_Clause_Clear = True+licenseIsFsfLibre BSD_3_Clause = True+licenseIsFsfLibre BSD_4_Clause = True+licenseIsFsfLibre BSL_1_0 = True+licenseIsFsfLibre CC_BY_4_0 = True+licenseIsFsfLibre CC_BY_SA_4_0 = True+licenseIsFsfLibre CC0_1_0 = True+licenseIsFsfLibre CDDL_1_0 = True+licenseIsFsfLibre CECILL_2_0 = True+licenseIsFsfLibre CECILL_B = True+licenseIsFsfLibre CECILL_C = True+licenseIsFsfLibre ClArtistic = True+licenseIsFsfLibre Condor_1_1 = True+licenseIsFsfLibre CPAL_1_0 = True+licenseIsFsfLibre CPL_1_0 = True+licenseIsFsfLibre ECL_2_0 = True+licenseIsFsfLibre EFL_2_0 = True+licenseIsFsfLibre EPL_1_0 = True+licenseIsFsfLibre EPL_2_0 = True+licenseIsFsfLibre EUDatagrid = True+licenseIsFsfLibre EUPL_1_1 = True+licenseIsFsfLibre EUPL_1_2 = True+licenseIsFsfLibre FSFAP = True+licenseIsFsfLibre FTL = True+licenseIsFsfLibre GFDL_1_1_only = True+licenseIsFsfLibre GFDL_1_1_or_later = True+licenseIsFsfLibre GFDL_1_2_only = True+licenseIsFsfLibre GFDL_1_2_or_later = True+licenseIsFsfLibre GFDL_1_3_only = True+licenseIsFsfLibre GFDL_1_3_or_later = True+licenseIsFsfLibre Gnuplot = True+licenseIsFsfLibre GPL_2_0_only = True+licenseIsFsfLibre GPL_2_0_or_later = True+licenseIsFsfLibre GPL_3_0_only = True+licenseIsFsfLibre GPL_3_0_or_later = True+licenseIsFsfLibre HPND = True+licenseIsFsfLibre IJG = True+licenseIsFsfLibre IMatix = True+licenseIsFsfLibre Imlib2 = True+licenseIsFsfLibre Intel = True+licenseIsFsfLibre IPA = True+licenseIsFsfLibre IPL_1_0 = True+licenseIsFsfLibre ISC = True+licenseIsFsfLibre LGPL_2_1_only = True+licenseIsFsfLibre LGPL_2_1_or_later = True+licenseIsFsfLibre LGPL_3_0_only = True+licenseIsFsfLibre LGPL_3_0_or_later = True+licenseIsFsfLibre LPL_1_02 = True+licenseIsFsfLibre LPPL_1_2 = True+licenseIsFsfLibre LPPL_1_3a = True+licenseIsFsfLibre MIT = True+licenseIsFsfLibre MPL_1_1 = True+licenseIsFsfLibre MPL_2_0 = True+licenseIsFsfLibre MS_PL = True+licenseIsFsfLibre MS_RL = True+licenseIsFsfLibre NCSA = True+licenseIsFsfLibre Nokia = True+licenseIsFsfLibre NOSL = True+licenseIsFsfLibre NPL_1_0 = True+licenseIsFsfLibre NPL_1_1 = True+licenseIsFsfLibre ODbL_1_0 = True+licenseIsFsfLibre OFL_1_0 = True+licenseIsFsfLibre OFL_1_1 = True+licenseIsFsfLibre OLDAP_2_3 = True+licenseIsFsfLibre OLDAP_2_7 = True+licenseIsFsfLibre OpenSSL = True+licenseIsFsfLibre OSL_1_0 = True+licenseIsFsfLibre OSL_1_1 = True+licenseIsFsfLibre OSL_2_0 = True+licenseIsFsfLibre OSL_2_1 = True+licenseIsFsfLibre OSL_3_0 = True+licenseIsFsfLibre PHP_3_01 = True+licenseIsFsfLibre Python_2_0 = True+licenseIsFsfLibre QPL_1_0 = True+licenseIsFsfLibre RPSL_1_0 = True+licenseIsFsfLibre Ruby = True+licenseIsFsfLibre SGI_B_2_0 = True+licenseIsFsfLibre SISSL = True+licenseIsFsfLibre Sleepycat = True+licenseIsFsfLibre SMLNJ = True+licenseIsFsfLibre SPL_1_0 = True+licenseIsFsfLibre Unlicense = True+licenseIsFsfLibre UPL_1_0 = True+licenseIsFsfLibre Vim = True+licenseIsFsfLibre W3C = True+licenseIsFsfLibre WTFPL = True+licenseIsFsfLibre X11 = True+licenseIsFsfLibre XFree86_1_1 = True+licenseIsFsfLibre Xinetd = True+licenseIsFsfLibre YPL_1_1 = True+licenseIsFsfLibre Zend_2_0 = True+licenseIsFsfLibre Zimbra_1_3 = True+licenseIsFsfLibre Zlib = True+licenseIsFsfLibre ZPL_2_0 = True+licenseIsFsfLibre ZPL_2_1 = True+licenseIsFsfLibre _ = False++-------------------------------------------------------------------------------+-- Creation+-------------------------------------------------------------------------------++licenseIdList :: LicenseListVersion -> [LicenseId]+licenseIdList LicenseListVersion_3_0 =+ [ AGPL_1_0+ , BSD_2_Clause_FreeBSD+ , BSD_2_Clause_NetBSD+ ]+ ++ bulkOfLicenses+licenseIdList LicenseListVersion_3_2 =+ [ AGPL_1_0_only+ , AGPL_1_0_or_later+ , BSD_2_Clause_FreeBSD+ , BSD_2_Clause_NetBSD+ , Linux_OpenIB+ , MIT_0+ , ODC_By_1_0+ , TU_Berlin_1_0+ , TU_Berlin_2_0+ ]+ ++ bulkOfLicenses+licenseIdList LicenseListVersion_3_6 =+ [ AGPL_1_0_only+ , AGPL_1_0_or_later+ , Blessing+ , BlueOak_1_0_0+ , BSD_2_Clause_FreeBSD+ , BSD_2_Clause_NetBSD+ , BSD_3_Clause_Open_MPI+ , CC_PDDC+ , CERN_OHL_1_1+ , CERN_OHL_1_2+ , Copyleft_next_0_3_0+ , Copyleft_next_0_3_1+ , HPND_sell_variant+ , JPNIC+ , Libpng_2_0+ , Linux_OpenIB+ , MIT_0+ , ODC_By_1_0+ , OGL_UK_1_0+ , OGL_UK_2_0+ , OGL_UK_3_0+ , Parity_6_0_0+ , Sendmail_8_23+ , SHL_0_51+ , SHL_0_5+ , SSPL_1_0+ , TAPR_OHL_1_0+ , TU_Berlin_1_0+ , TU_Berlin_2_0+ ]+ ++ bulkOfLicenses+licenseIdList LicenseListVersion_3_9 =+ [ AGPL_1_0_only+ , AGPL_1_0_or_later+ , Blessing+ , BlueOak_1_0_0+ , BSD_2_Clause_FreeBSD+ , BSD_3_Clause_Open_MPI+ , CAL_1_0_Combined_Work_Exception+ , CAL_1_0+ , CC_PDDC+ , CERN_OHL_1_1+ , CERN_OHL_1_2+ , CERN_OHL_P_2_0+ , CERN_OHL_S_2_0+ , CERN_OHL_W_2_0+ , Copyleft_next_0_3_0+ , Copyleft_next_0_3_1+ , Etalab_2_0+ , Hippocratic_2_1+ , HPND_sell_variant+ , JPNIC+ , Libpng_2_0+ , Libselinux_1_0+ , Linux_OpenIB+ , MIT_0+ , MulanPSL_1_0+ , MulanPSL_2_0+ , NCGL_UK_2_0+ , NTP_0+ , O_UDA_1_0+ , ODC_By_1_0+ , OFL_1_0_no_RFN+ , OFL_1_0_RFN+ , OFL_1_1_no_RFN+ , OFL_1_1_RFN+ , OGC_1_0+ , OGL_Canada_2_0+ , OGL_UK_1_0+ , OGL_UK_2_0+ , OGL_UK_3_0+ , Parity_6_0_0+ , Parity_7_0_0+ , PolyForm_Noncommercial_1_0_0+ , PolyForm_Small_Business_1_0_0+ , PSF_2_0+ , Sendmail_8_23+ , SHL_0_51+ , SHL_0_5+ , SSH_OpenSSH+ , SSH_short+ , SSPL_1_0+ , TAPR_OHL_1_0+ , TU_Berlin_1_0+ , TU_Berlin_2_0+ , UCL_1_0+ ]+ ++ bulkOfLicenses+licenseIdList LicenseListVersion_3_10 =+ [ AGPL_1_0_only+ , AGPL_1_0_or_later+ , Blessing+ , BlueOak_1_0_0+ , BSD_2_Clause_FreeBSD+ , BSD_3_Clause_Open_MPI+ , CAL_1_0_Combined_Work_Exception+ , CAL_1_0+ , CC_PDDC+ , CERN_OHL_1_1+ , CERN_OHL_1_2+ , CERN_OHL_P_2_0+ , CERN_OHL_S_2_0+ , CERN_OHL_W_2_0+ , Copyleft_next_0_3_0+ , Copyleft_next_0_3_1+ , Etalab_2_0+ , Hippocratic_2_1+ , HPND_sell_variant+ , JPNIC+ , Libpng_2_0+ , Libselinux_1_0+ , Linux_OpenIB+ , MIT_0+ , MulanPSL_1_0+ , MulanPSL_2_0+ , NCGL_UK_2_0+ , NTP_0+ , O_UDA_1_0+ , ODC_By_1_0+ , OFL_1_0_no_RFN+ , OFL_1_0_RFN+ , OFL_1_1_no_RFN+ , OFL_1_1_RFN+ , OGC_1_0+ , OGL_Canada_2_0+ , OGL_UK_1_0+ , OGL_UK_2_0+ , OGL_UK_3_0+ , Parity_6_0_0+ , Parity_7_0_0+ , PolyForm_Noncommercial_1_0_0+ , PolyForm_Small_Business_1_0_0+ , PSF_2_0+ , Sendmail_8_23+ , SHL_0_51+ , SHL_0_5+ , SSH_OpenSSH+ , SSH_short+ , SSPL_1_0+ , TAPR_OHL_1_0+ , TU_Berlin_1_0+ , TU_Berlin_2_0+ , UCL_1_0+ ]+ ++ bulkOfLicenses++-- | Create a 'LicenseId' from a 'String'.+mkLicenseId :: LicenseListVersion -> String -> Maybe LicenseId+mkLicenseId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0+mkLicenseId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2+mkLicenseId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6+mkLicenseId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9+mkLicenseId LicenseListVersion_3_10 s = Map.lookup s stringLookup_3_10++stringLookup_3_0 :: Map String LicenseId+stringLookup_3_0 = Map.fromList $ map (\i -> (licenseId i, i)) $+ licenseIdList LicenseListVersion_3_0++stringLookup_3_2 :: Map String LicenseId+stringLookup_3_2 = Map.fromList $ map (\i -> (licenseId i, i)) $+ licenseIdList LicenseListVersion_3_2++stringLookup_3_6 :: Map String LicenseId+stringLookup_3_6 = Map.fromList $ map (\i -> (licenseId i, i)) $+ licenseIdList LicenseListVersion_3_6++stringLookup_3_9 :: Map String LicenseId+stringLookup_3_9 = Map.fromList $ map (\i -> (licenseId i, i)) $+ licenseIdList LicenseListVersion_3_9++stringLookup_3_10 :: Map String LicenseId+stringLookup_3_10 = Map.fromList $ map (\i -> (licenseId i, i)) $+ licenseIdList LicenseListVersion_3_10++-- | Licenses in all SPDX License lists+bulkOfLicenses :: [LicenseId]+bulkOfLicenses =+ [ NullBSD+ , AAL+ , Abstyles+ , Adobe_2006+ , Adobe_Glyph+ , ADSL+ , AFL_1_1+ , AFL_1_2+ , AFL_2_0+ , AFL_2_1+ , AFL_3_0+ , Afmparse+ , AGPL_3_0_only+ , AGPL_3_0_or_later+ , Aladdin+ , AMDPLPA+ , AML+ , AMPAS+ , ANTLR_PD+ , Apache_1_0+ , Apache_1_1+ , Apache_2_0+ , APAFML+ , APL_1_0+ , APSL_1_0+ , APSL_1_1+ , APSL_1_2+ , APSL_2_0+ , Artistic_1_0_cl8+ , Artistic_1_0_Perl+ , Artistic_1_0+ , Artistic_2_0+ , Bahyph+ , Barr+ , Beerware+ , BitTorrent_1_0+ , BitTorrent_1_1+ , Borceux+ , BSD_1_Clause+ , BSD_2_Clause_Patent+ , BSD_2_Clause+ , BSD_3_Clause_Attribution+ , BSD_3_Clause_Clear+ , BSD_3_Clause_LBNL+ , BSD_3_Clause_No_Nuclear_License_2014+ , BSD_3_Clause_No_Nuclear_License+ , BSD_3_Clause_No_Nuclear_Warranty+ , BSD_3_Clause+ , BSD_4_Clause_UC+ , BSD_4_Clause+ , BSD_Protection+ , BSD_Source_Code+ , BSL_1_0+ , Bzip2_1_0_5+ , Bzip2_1_0_6+ , Caldera+ , CATOSL_1_1+ , CC_BY_1_0+ , CC_BY_2_0+ , CC_BY_2_5+ , CC_BY_3_0+ , CC_BY_4_0+ , CC_BY_NC_1_0+ , CC_BY_NC_2_0+ , CC_BY_NC_2_5+ , CC_BY_NC_3_0+ , CC_BY_NC_4_0+ , CC_BY_NC_ND_1_0+ , CC_BY_NC_ND_2_0+ , CC_BY_NC_ND_2_5+ , CC_BY_NC_ND_3_0+ , CC_BY_NC_ND_4_0+ , CC_BY_NC_SA_1_0+ , CC_BY_NC_SA_2_0+ , CC_BY_NC_SA_2_5+ , CC_BY_NC_SA_3_0+ , CC_BY_NC_SA_4_0+ , CC_BY_ND_1_0+ , CC_BY_ND_2_0+ , CC_BY_ND_2_5+ , CC_BY_ND_3_0+ , CC_BY_ND_4_0+ , CC_BY_SA_1_0+ , CC_BY_SA_2_0+ , CC_BY_SA_2_5+ , CC_BY_SA_3_0+ , CC_BY_SA_4_0+ , CC0_1_0+ , CDDL_1_0+ , CDDL_1_1+ , CDLA_Permissive_1_0+ , CDLA_Sharing_1_0+ , CECILL_1_0+ , CECILL_1_1+ , CECILL_2_0+ , CECILL_2_1+ , CECILL_B+ , CECILL_C+ , ClArtistic+ , CNRI_Jython+ , CNRI_Python_GPL_Compatible+ , CNRI_Python+ , Condor_1_1+ , CPAL_1_0+ , CPL_1_0+ , CPOL_1_02+ , Crossword+ , CrystalStacker+ , CUA_OPL_1_0+ , Cube+ , Curl+ , D_FSL_1_0+ , Diffmark+ , DOC+ , Dotseqn+ , DSDP+ , Dvipdfm+ , ECL_1_0+ , ECL_2_0+ , EFL_1_0+ , EFL_2_0+ , EGenix+ , Entessa+ , EPL_1_0+ , EPL_2_0+ , ErlPL_1_1+ , EUDatagrid+ , EUPL_1_0+ , EUPL_1_1+ , EUPL_1_2+ , Eurosym+ , Fair+ , Frameworx_1_0+ , FreeImage+ , FSFAP+ , FSFULLR+ , FSFUL+ , FTL+ , GFDL_1_1_only+ , GFDL_1_1_or_later+ , GFDL_1_2_only+ , GFDL_1_2_or_later+ , GFDL_1_3_only+ , GFDL_1_3_or_later+ , Giftware+ , GL2PS+ , Glide+ , Glulxe+ , Gnuplot+ , GPL_1_0_only+ , GPL_1_0_or_later+ , GPL_2_0_only+ , GPL_2_0_or_later+ , GPL_3_0_only+ , GPL_3_0_or_later+ , GSOAP_1_3b+ , HaskellReport+ , HPND+ , IBM_pibs+ , ICU+ , IJG+ , ImageMagick+ , IMatix+ , Imlib2+ , Info_ZIP+ , Intel_ACPI+ , Intel+ , Interbase_1_0+ , IPA+ , IPL_1_0+ , ISC+ , JasPer_2_0+ , JSON+ , LAL_1_2+ , LAL_1_3+ , Latex2e+ , Leptonica+ , LGPL_2_0_only+ , LGPL_2_0_or_later+ , LGPL_2_1_only+ , LGPL_2_1_or_later+ , LGPL_3_0_only+ , LGPL_3_0_or_later+ , LGPLLR+ , Libpng+ , Libtiff+ , LiLiQ_P_1_1+ , LiLiQ_R_1_1+ , LiLiQ_Rplus_1_1+ , LPL_1_02+ , LPL_1_0+ , LPPL_1_0+ , LPPL_1_1+ , LPPL_1_2+ , LPPL_1_3a+ , LPPL_1_3c+ , MakeIndex+ , MirOS+ , MIT_advertising+ , MIT_CMU+ , MIT_enna+ , MIT_feh+ , MITNFA+ , MIT+ , Motosoto+ , Mpich2+ , MPL_1_0+ , MPL_1_1+ , MPL_2_0_no_copyleft_exception+ , MPL_2_0+ , MS_PL+ , MS_RL+ , MTLL+ , Multics+ , Mup+ , NASA_1_3+ , Naumen+ , NBPL_1_0+ , NCSA+ , Net_SNMP+ , NetCDF+ , Newsletr+ , NGPL+ , NLOD_1_0+ , NLPL+ , Nokia+ , NOSL+ , Noweb+ , NPL_1_0+ , NPL_1_1+ , NPOSL_3_0+ , NRL+ , NTP+ , OCCT_PL+ , OCLC_2_0+ , ODbL_1_0+ , OFL_1_0+ , OFL_1_1+ , OGTSL+ , OLDAP_1_1+ , OLDAP_1_2+ , OLDAP_1_3+ , OLDAP_1_4+ , OLDAP_2_0_1+ , OLDAP_2_0+ , OLDAP_2_1+ , OLDAP_2_2_1+ , OLDAP_2_2_2+ , OLDAP_2_2+ , OLDAP_2_3+ , OLDAP_2_4+ , OLDAP_2_5+ , OLDAP_2_6+ , OLDAP_2_7+ , OLDAP_2_8+ , OML+ , OpenSSL+ , OPL_1_0+ , OSET_PL_2_1+ , OSL_1_0+ , OSL_1_1+ , OSL_2_0+ , OSL_2_1+ , OSL_3_0+ , PDDL_1_0+ , PHP_3_01+ , PHP_3_0+ , Plexus+ , PostgreSQL+ , Psfrag+ , Psutils+ , Python_2_0+ , Qhull+ , QPL_1_0+ , Rdisc+ , RHeCos_1_1+ , RPL_1_1+ , RPL_1_5+ , RPSL_1_0+ , RSA_MD+ , RSCPL+ , Ruby+ , SAX_PD+ , Saxpath+ , SCEA+ , Sendmail+ , SGI_B_1_0+ , SGI_B_1_1+ , SGI_B_2_0+ , SimPL_2_0+ , SISSL_1_2+ , SISSL+ , Sleepycat+ , SMLNJ+ , SMPPL+ , SNIA+ , Spencer_86+ , Spencer_94+ , Spencer_99+ , SPL_1_0+ , SugarCRM_1_1_3+ , SWL+ , TCL+ , TCP_wrappers+ , TMate+ , TORQUE_1_1+ , TOSL+ , Unicode_DFS_2015+ , Unicode_DFS_2016+ , Unicode_TOU+ , Unlicense+ , UPL_1_0+ , Vim+ , VOSTROM+ , VSL_1_0+ , W3C_19980720+ , W3C_20150513+ , W3C+ , Watcom_1_0+ , Wsuipa+ , WTFPL+ , X11+ , Xerox+ , XFree86_1_1+ , Xinetd+ , Xnet+ , Xpp+ , XSkat+ , YPL_1_0+ , YPL_1_1+ , Zed+ , Zend_2_0+ , Zimbra_1_3+ , Zimbra_1_4+ , Zlib_acknowledgement+ , Zlib+ , ZPL_1_1+ , ZPL_2_0+ , ZPL_2_1+ ]
+ src/Distribution/SPDX/LicenseListVersion.hs view
@@ -0,0 +1,22 @@+module Distribution.SPDX.LicenseListVersion (+ LicenseListVersion (..),+ cabalSpecVersionToSPDXListVersion,+ ) where++import Distribution.CabalSpecVersion++-- | SPDX License List version @Cabal@ is aware of.+data LicenseListVersion+ = LicenseListVersion_3_0+ | LicenseListVersion_3_2+ | LicenseListVersion_3_6+ | LicenseListVersion_3_9+ | LicenseListVersion_3_10+ deriving (Eq, Ord, Show, Enum, Bounded)++cabalSpecVersionToSPDXListVersion :: CabalSpecVersion -> LicenseListVersion+cabalSpecVersionToSPDXListVersion CabalSpecV3_6 = LicenseListVersion_3_10+cabalSpecVersionToSPDXListVersion CabalSpecV3_4 = LicenseListVersion_3_9+cabalSpecVersionToSPDXListVersion CabalSpecV3_0 = LicenseListVersion_3_6+cabalSpecVersionToSPDXListVersion CabalSpecV2_4 = LicenseListVersion_3_2+cabalSpecVersionToSPDXListVersion _ = LicenseListVersion_3_0
+ src/Distribution/SPDX/LicenseReference.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.SPDX.LicenseReference (+ LicenseRef,+ licenseRef,+ licenseDocumentRef,+ mkLicenseRef,+ mkLicenseRef',+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Utils.Generic (isAsciiAlphaNum)+import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | A user defined license reference denoted by @LicenseRef-[idstring]@ (for a license not on the SPDX License List);+data LicenseRef = LicenseRef+ { _lrDocument :: !(Maybe String)+ , _lrLicense :: !String+ }+ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)++-- | License reference.+licenseRef :: LicenseRef -> String+licenseRef = _lrLicense++-- | Document reference.+licenseDocumentRef :: LicenseRef -> Maybe String+licenseDocumentRef = _lrDocument++instance Binary LicenseRef+instance Structured LicenseRef++instance NFData LicenseRef where+ rnf (LicenseRef d l) = rnf d `seq` rnf l++instance Pretty LicenseRef where+ pretty (LicenseRef Nothing l) = Disp.text "LicenseRef-" <<>> Disp.text l+ pretty (LicenseRef (Just d) l) =+ Disp.text "DocumentRef-" <<>> Disp.text d <<>> Disp.char ':' <<>> Disp.text "LicenseRef-" <<>> Disp.text l++instance Parsec LicenseRef where+ parsec = name <|> doc+ where+ name = do+ _ <- P.string "LicenseRef-"+ n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'+ pure (LicenseRef Nothing n)++ doc = do+ _ <- P.string "DocumentRef-"+ d <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'+ _ <- P.char ':'+ _ <- P.string "LicenseRef-"+ n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'+ pure (LicenseRef (Just d) n)++-- | Create 'LicenseRef' from optional document ref and name.+mkLicenseRef :: Maybe String -> String -> Maybe LicenseRef+mkLicenseRef d l = do+ d' <- traverse checkIdString d+ l' <- checkIdString l+ pure (LicenseRef d' l')+ where+ checkIdString s+ | all (\c -> isAsciiAlphaNum c || c == '-' || c == '.') s = Just s+ | otherwise = Nothing++-- | Like 'mkLicenseRef' but convert invalid characters into @-@.+mkLicenseRef' :: Maybe String -> String -> LicenseRef+mkLicenseRef' d l = LicenseRef (fmap f d) (f l)+ where+ f = map g+ g c | isAsciiAlphaNum c || c == '-' || c == '.' = c+ | otherwise = '-'
+ src/Distribution/Simple.hs view
@@ -0,0 +1,818 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE LambdaCase #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple+-- Copyright : Isaac Jones 2003-2005+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is the command line front end to the Simple build system. When given+-- the parsed command-line args and package information, is able to perform+-- basic commands like configure, build, install, register, etc.+--+-- This module exports the main functions that Setup.hs scripts use. It+-- re-exports the 'UserHooks' type, the standard entry points like+-- 'defaultMain' and 'defaultMainWithHooks' and the predefined sets of+-- 'UserHooks' that custom @Setup.hs@ scripts can extend to add their own+-- behaviour.+--+-- This module isn't called \"Simple\" because it's simple. Far from+-- it. It's called \"Simple\" because it does complicated things to+-- simple software.+--+-- The original idea was that there could be different build systems that all+-- presented the same compatible command line interfaces. There is still a+-- "Distribution.Make" system but in practice no packages use it.++{-+Work around this warning:+libraries/Cabal/Distribution/Simple.hs:78:0:+ Warning: In the use of `runTests'+ (imported from Distribution.Simple.UserHooks):+ Deprecated: "Please use the new testing interface instead!"+-}+{-# OPTIONS_GHC -fno-warn-deprecations #-}++module Distribution.Simple (+ module Distribution.Package,+ module Distribution.Version,+ module Distribution.License,+ module Distribution.Simple.Compiler,+ module Language.Haskell.Extension,+ -- * Simple interface+ defaultMain, defaultMainNoRead, defaultMainArgs,+ -- * Customization+ UserHooks(..), Args,+ defaultMainWithHooks, defaultMainWithHooksArgs,+ defaultMainWithHooksNoRead, defaultMainWithHooksNoReadArgs,+ -- ** Standard sets of hooks+ simpleUserHooks,+ autoconfUserHooks,+ emptyUserHooks,+ ) where++import Control.Exception (try)++import Prelude ()+import Distribution.Compat.Prelude++-- local+import Distribution.Simple.Compiler+import Distribution.Simple.UserHooks+import Distribution.Package+import Distribution.PackageDescription+import Distribution.PackageDescription.Configuration+import Distribution.Simple.Program+import Distribution.Simple.Program.Db+import Distribution.Simple.PreProcess+import Distribution.Simple.Setup+import Distribution.Simple.Command++import Distribution.Simple.Build+import Distribution.Simple.SrcDist+import Distribution.Simple.Register++import Distribution.Simple.Configure++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+import Distribution.Utils.NubList+import Distribution.Verbosity+import Language.Haskell.Extension+import Distribution.Version+import Distribution.License+import Distribution.Pretty+import Distribution.System (buildPlatform)++-- Base+import System.Environment (getArgs, getProgName)+import System.Directory (removeFile, doesFileExist+ ,doesDirectoryExist, removeDirectoryRecursive)+import System.FilePath (searchPathSeparator, takeDirectory, (</>), splitDirectories, dropDrive)+import Distribution.Compat.ResponseFile (expandResponse)+import Distribution.Compat.Directory (makeAbsolute)+import Distribution.Compat.Environment (getEnvironment)+import Distribution.Compat.GetShortPathName (getShortPathName)++import Data.List (unionBy, (\\))++import Distribution.PackageDescription.Parsec++-- | A simple implementation of @main@ for a Cabal setup script.+-- It reads the package description file using IO, and performs the+-- action specified on the command line.+defaultMain :: IO ()+defaultMain = getArgs >>= defaultMainHelper simpleUserHooks++-- | A version of 'defaultMain' that is passed the command line+-- arguments, rather than getting them from the environment.+defaultMainArgs :: [String] -> IO ()+defaultMainArgs = defaultMainHelper simpleUserHooks++-- | A customizable version of 'defaultMain'.+defaultMainWithHooks :: UserHooks -> IO ()+defaultMainWithHooks hooks = getArgs >>= defaultMainHelper hooks++-- | A customizable version of 'defaultMain' that also takes the command+-- line arguments.+defaultMainWithHooksArgs :: UserHooks -> [String] -> IO ()+defaultMainWithHooksArgs = defaultMainHelper++-- | Like 'defaultMain', but accepts the package description as input+-- rather than using IO to read it.+defaultMainNoRead :: GenericPackageDescription -> IO ()+defaultMainNoRead = defaultMainWithHooksNoRead simpleUserHooks++-- | A customizable version of 'defaultMainNoRead'.+defaultMainWithHooksNoRead :: UserHooks -> GenericPackageDescription -> IO ()+defaultMainWithHooksNoRead hooks pkg_descr =+ getArgs >>=+ defaultMainHelper hooks { readDesc = return (Just pkg_descr) }++-- | A customizable version of 'defaultMainNoRead' that also takes the+-- command line arguments.+--+-- @since 2.2.0.0+defaultMainWithHooksNoReadArgs :: UserHooks -> GenericPackageDescription -> [String] -> IO ()+defaultMainWithHooksNoReadArgs hooks pkg_descr =+ defaultMainHelper hooks { readDesc = return (Just pkg_descr) }++defaultMainHelper :: UserHooks -> Args -> IO ()+defaultMainHelper hooks args = topHandler $ do+ args' <- expandResponse args+ case commandsRun (globalCommand commands) commands args' of+ CommandHelp help -> printHelp help+ CommandList opts -> printOptionsList opts+ CommandErrors errs -> printErrors errs+ CommandReadyToGo (flags, commandParse) ->+ case commandParse of+ _ | fromFlag (globalVersion flags) -> printVersion+ | fromFlag (globalNumericVersion flags) -> printNumericVersion+ CommandHelp help -> printHelp help+ CommandList opts -> printOptionsList opts+ CommandErrors errs -> printErrors errs+ CommandReadyToGo action -> action++ where+ printHelp help = getProgName >>= putStr . help+ printOptionsList = putStr . unlines+ printErrors errs = do+ putStr (intercalate "\n" errs)+ exitWith (ExitFailure 1)+ printNumericVersion = putStrLn $ prettyShow cabalVersion+ printVersion = putStrLn $ "Cabal library version "+ ++ prettyShow cabalVersion++ progs = addKnownPrograms (hookedPrograms hooks) defaultProgramDb+ commands =+ [configureCommand progs `commandAddAction`+ \fs as -> configureAction hooks fs as >> return ()+ ,buildCommand progs `commandAddAction` buildAction hooks+ ,showBuildInfoCommand progs `commandAddAction` showBuildInfoAction hooks+ ,replCommand progs `commandAddAction` replAction hooks+ ,installCommand `commandAddAction` installAction hooks+ ,copyCommand `commandAddAction` copyAction hooks+ ,haddockCommand `commandAddAction` haddockAction hooks+ ,cleanCommand `commandAddAction` cleanAction hooks+ ,sdistCommand `commandAddAction` sdistAction hooks+ ,hscolourCommand `commandAddAction` hscolourAction hooks+ ,registerCommand `commandAddAction` registerAction hooks+ ,unregisterCommand `commandAddAction` unregisterAction hooks+ ,testCommand `commandAddAction` testAction hooks+ ,benchmarkCommand `commandAddAction` benchAction hooks+ ]++-- | Combine the preprocessors in the given hooks with the+-- preprocessors built into cabal.+allSuffixHandlers :: UserHooks+ -> [PPSuffixHandler]+allSuffixHandlers hooks+ = overridesPP (hookedPreProcessors hooks) knownSuffixHandlers+ where+ overridesPP :: [PPSuffixHandler] -> [PPSuffixHandler] -> [PPSuffixHandler]+ overridesPP = unionBy (\x y -> fst x == fst y)++configureAction :: UserHooks -> ConfigFlags -> Args -> IO LocalBuildInfo+configureAction hooks flags args = do+ distPref <- findDistPrefOrDefault (configDistPref flags)+ let flags' = flags { configDistPref = toFlag distPref+ , configArgs = args }++ -- See docs for 'HookedBuildInfo'+ pbi <- preConf hooks args flags'++ (mb_pd_file, pkg_descr0) <- confPkgDescr hooks verbosity+ (flagToMaybe (configCabalFilePath flags))++ let epkg_descr = (pkg_descr0, pbi)++ 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++ let pkg_descr = localPkgDescr localbuildinfo+ postConf hooks args flags' pkg_descr localbuildinfo+ return localbuildinfo+ where+ verbosity = fromFlag (configVerbosity flags)++confPkgDescr :: UserHooks -> Verbosity -> Maybe FilePath+ -> IO (Maybe FilePath, GenericPackageDescription)+confPkgDescr hooks verbosity mb_path = do+ mdescr <- readDesc hooks+ case mdescr of+ Just descr -> return (Nothing, descr)+ Nothing -> do+ pdfile <- case mb_path of+ Nothing -> defaultPackageDesc verbosity+ Just path -> return path+ info verbosity "Using Parsec parser"+ descr <- readGenericPackageDescription verbosity pdfile+ return (Just pdfile, descr)++buildAction :: UserHooks -> BuildFlags -> Args -> IO ()+buildAction hooks flags args = do+ distPref <- findDistPrefOrDefault (buildDistPref flags)+ let verbosity = fromFlag $ buildVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { buildDistPref = toFlag distPref+ , buildCabalFilePath = maybeToFlag (cabalFilePath lbi)}++ progs <- reconfigurePrograms verbosity+ (buildProgramPaths flags')+ (buildProgramArgs flags')+ (withPrograms lbi)++ hookedAction verbosity preBuild buildHook postBuild+ (return lbi { withPrograms = progs })+ hooks flags' { buildArgs = args } args++showBuildInfoAction :: UserHooks -> ShowBuildInfoFlags -> Args -> IO ()+showBuildInfoAction hooks (ShowBuildInfoFlags flags fileOutput) args = do+ distPref <- findDistPrefOrDefault (buildDistPref flags)+ let verbosity = fromFlag $ buildVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { buildDistPref = toFlag distPref+ , buildCabalFilePath = maybeToFlag (cabalFilePath lbi)+ }++ progs <- reconfigurePrograms verbosity+ (buildProgramPaths flags')+ (buildProgramArgs flags')+ (withPrograms lbi)++ pbi <- preBuild hooks args flags'+ let lbi' = lbi { withPrograms = progs }+ pkg_descr0 = localPkgDescr lbi'+ pkg_descr = updatePackageDescription pbi pkg_descr0+ -- TODO: Somehow don't ignore build hook?+ buildInfoString <- showBuildInfo pkg_descr lbi' flags++ case fileOutput of+ Nothing -> putStr buildInfoString+ Just fp -> writeFile fp buildInfoString++ postBuild hooks args flags' pkg_descr lbi'++replAction :: UserHooks -> ReplFlags -> Args -> IO ()+replAction hooks flags args = do+ 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')+ (withPrograms lbi)++ -- As far as I can tell, the only reason this doesn't use+ -- 'hookedActionWithArgs' is because the arguments of 'replHook'+ -- takes the args explicitly. UGH. -- ezyang+ pbi <- preRepl hooks args flags'+ let pkg_descr0 = localPkgDescr lbi+ sanityCheckHookedBuildInfo verbosity pkg_descr0 pbi+ let pkg_descr = updatePackageDescription pbi pkg_descr0+ lbi' = lbi { withPrograms = progs+ , localPkgDescr = pkg_descr }+ 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+ distPref <- findDistPrefOrDefault (hscolourDistPref flags)+ let verbosity = fromFlag $ hscolourVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { hscolourDistPref = toFlag distPref+ , hscolourCabalFilePath = maybeToFlag (cabalFilePath lbi)}++ hookedAction verbosity preHscolour hscolourHook postHscolour+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args++haddockAction :: UserHooks -> HaddockFlags -> Args -> IO ()+haddockAction hooks flags args = do+ distPref <- findDistPrefOrDefault (haddockDistPref flags)+ let verbosity = fromFlag $ haddockVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { haddockDistPref = toFlag distPref+ , haddockCabalFilePath = maybeToFlag (cabalFilePath lbi)}++ progs <- reconfigurePrograms verbosity+ (haddockProgramPaths flags')+ (haddockProgramArgs flags')+ (withPrograms lbi)++ hookedAction verbosity preHaddock haddockHook postHaddock+ (return lbi { withPrograms = progs })+ hooks flags' { haddockArgs = args } args++cleanAction :: UserHooks -> CleanFlags -> Args -> IO ()+cleanAction hooks flags args = do+ distPref <- findDistPrefOrDefault (cleanDistPref flags)++ elbi <- tryGetBuildConfig hooks verbosity distPref+ let flags' = flags { cleanDistPref = toFlag distPref+ , cleanCabalFilePath = case elbi of+ Left _ -> mempty+ Right lbi -> maybeToFlag (cabalFilePath lbi)}++ pbi <- preClean hooks args flags'++ (_, ppd) <- confPkgDescr hooks verbosity Nothing+ -- It might seem like we are doing something clever here+ -- but we're really not: if you look at the implementation+ -- of 'clean' in the end all the package description is+ -- used for is to clear out @extra-tmp-files@. IMO,+ -- the configure script goo should go into @dist@ too!+ -- -- ezyang+ let pkg_descr0 = flattenPackageDescription ppd+ -- We don't sanity check for clean as an error+ -- here would prevent cleaning:+ --sanityCheckHookedBuildInfo verbosity 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+ distPref <- findDistPrefOrDefault (copyDistPref flags)+ let verbosity = fromFlag $ copyVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { copyDistPref = toFlag distPref+ , copyCabalFilePath = maybeToFlag (cabalFilePath lbi)}+ hookedAction verbosity preCopy copyHook postCopy+ (getBuildConfig hooks verbosity distPref)+ hooks flags' { copyArgs = args } args++installAction :: UserHooks -> InstallFlags -> Args -> IO ()+installAction hooks flags args = do+ distPref <- findDistPrefOrDefault (installDistPref flags)+ let verbosity = fromFlag $ installVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { installDistPref = toFlag distPref+ , installCabalFilePath = maybeToFlag (cabalFilePath lbi)}+ hookedAction verbosity preInst instHook postInst+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args++-- Since Cabal-3.4 UserHooks are completely ignored+sdistAction :: UserHooks -> SDistFlags -> Args -> IO ()+sdistAction _hooks flags _args = do+ (_, ppd) <- confPkgDescr emptyUserHooks verbosity Nothing+ let pkg_descr = flattenPackageDescription ppd+ sdist pkg_descr flags srcPref knownSuffixHandlers+ where+ verbosity = fromFlag (sDistVerbosity flags)++testAction :: UserHooks -> TestFlags -> Args -> IO ()+testAction hooks flags args = do+ distPref <- findDistPrefOrDefault (testDistPref flags)+ let verbosity = fromFlag $ testVerbosity flags+ flags' = flags { testDistPref = toFlag distPref }++ hookedActionWithArgs verbosity preTest testHook postTest+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args++benchAction :: UserHooks -> BenchmarkFlags -> Args -> IO ()+benchAction hooks flags args = do+ distPref <- findDistPrefOrDefault (benchmarkDistPref flags)+ let verbosity = fromFlag $ benchmarkVerbosity flags+ flags' = flags { benchmarkDistPref = toFlag distPref }+ hookedActionWithArgs verbosity preBench benchHook postBench+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args++registerAction :: UserHooks -> RegisterFlags -> Args -> IO ()+registerAction hooks flags args = do+ distPref <- findDistPrefOrDefault (regDistPref flags)+ let verbosity = fromFlag $ regVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { regDistPref = toFlag distPref+ , regCabalFilePath = maybeToFlag (cabalFilePath lbi)}+ hookedAction verbosity preReg regHook postReg+ (getBuildConfig hooks verbosity distPref)+ hooks flags' { regArgs = args } args++unregisterAction :: UserHooks -> RegisterFlags -> Args -> IO ()+unregisterAction hooks flags args = do+ distPref <- findDistPrefOrDefault (regDistPref flags)+ let verbosity = fromFlag $ regVerbosity flags+ lbi <- getBuildConfig hooks verbosity distPref+ let flags' = flags { regDistPref = toFlag distPref+ , regCabalFilePath = maybeToFlag (cabalFilePath lbi)}+ hookedAction verbosity preUnreg unregHook postUnreg+ (getBuildConfig hooks verbosity distPref)+ hooks flags' args++hookedAction+ :: Verbosity+ -> (UserHooks -> Args -> flags -> IO HookedBuildInfo)+ -> (UserHooks -> PackageDescription -> LocalBuildInfo+ -> UserHooks -> flags -> IO ())+ -> (UserHooks -> Args -> flags -> PackageDescription+ -> LocalBuildInfo -> IO ())+ -> IO LocalBuildInfo+ -> UserHooks -> flags -> Args -> IO ()+hookedAction verbosity pre_hook cmd_hook =+ hookedActionWithArgs verbosity pre_hook+ (\h _ pd lbi uh flags ->+ cmd_hook h pd lbi uh flags)++hookedActionWithArgs+ :: Verbosity+ -> (UserHooks -> Args -> flags -> IO HookedBuildInfo)+ -> (UserHooks -> Args -> PackageDescription -> LocalBuildInfo+ -> UserHooks -> flags -> IO ())+ -> (UserHooks -> Args -> flags -> PackageDescription+ -> LocalBuildInfo -> IO ())+ -> IO LocalBuildInfo+ -> UserHooks -> flags -> Args -> IO ()+hookedActionWithArgs verbosity pre_hook cmd_hook post_hook+ get_build_config hooks flags args = do+ pbi <- pre_hook hooks args flags+ lbi0 <- get_build_config+ let pkg_descr0 = localPkgDescr lbi0+ sanityCheckHookedBuildInfo verbosity pkg_descr0 pbi+ let pkg_descr = updatePackageDescription pbi pkg_descr0+ lbi = lbi0 { localPkgDescr = pkg_descr }+ cmd_hook hooks args pkg_descr lbi hooks flags+ post_hook hooks args flags pkg_descr lbi++sanityCheckHookedBuildInfo+ :: Verbosity -> PackageDescription -> HookedBuildInfo -> IO ()+sanityCheckHookedBuildInfo verbosity+ (PackageDescription { library = Nothing }) (Just _,_)+ = die' verbosity $ "The buildinfo contains info for a library, "+ ++ "but the package does not have a library."++sanityCheckHookedBuildInfo verbosity pkg_descr (_, hookExes)+ | exe1 : _ <- nonExistant+ = die' verbosity $ "The buildinfo contains info for an executable called '"+ ++ prettyShow exe1 ++ "' but the package does not have a "+ ++ "executable with that name."+ where+ pkgExeNames = nub (map exeName (executables pkg_descr))+ hookExeNames = nub (map fst hookExes)+ nonExistant = hookExeNames \\ pkgExeNames++sanityCheckHookedBuildInfo _ _ _ = return ()++-- | Try to read the 'localBuildInfoFile'+tryGetBuildConfig :: UserHooks -> Verbosity -> FilePath+ -> IO (Either ConfigStateFileError LocalBuildInfo)+tryGetBuildConfig u v = try . getBuildConfig u v+++-- | Read the 'localBuildInfoFile' or throw an exception.+getBuildConfig :: UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfo+getBuildConfig hooks verbosity distPref = do+ lbi_wo_programs <- getPersistBuildConfig distPref+ -- Restore info about unconfigured programs, since it is not serialized+ let lbi = lbi_wo_programs {+ withPrograms = restoreProgramDb+ (builtinPrograms ++ hookedPrograms hooks)+ (withPrograms lbi_wo_programs)+ }++ case pkgDescrFile lbi of+ Nothing -> return lbi+ Just pkg_descr_file -> do+ outdated <- checkPersistBuildConfigOutdated distPref pkg_descr_file+ if outdated+ then reconfigure pkg_descr_file lbi+ else return lbi++ where+ reconfigure :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo+ reconfigure pkg_descr_file lbi = do+ notice verbosity $ pkg_descr_file ++ " has been changed. "+ ++ "Re-configuring with most recently used options. "+ ++ "If this fails, please run configure manually.\n"+ let cFlags = configFlags lbi+ let cFlags' = cFlags {+ -- 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_ = fmap (restoreProgramDb+ (builtinPrograms ++ hookedPrograms hooks))+ `fmap` configPrograms_ cFlags,++ -- Use the current, not saved verbosity level:+ configVerbosity = Flag verbosity+ }+ configureAction hooks cFlags' (extraConfigArgs lbi)+++-- --------------------------------------------------------------------------+-- Cleaning++clean :: PackageDescription -> CleanFlags -> IO ()+clean pkg_descr flags = do+ let distPref = fromFlagOrDefault defaultDistPref $ cleanDistPref flags+ notice verbosity "cleaning..."++ maybeConfig <- if fromFlag (cleanSaveConf flags)+ then maybeGetPersistBuildConfig distPref+ else return Nothing++ -- remove the whole dist/ directory rather than tracking exactly what files+ -- we created in there.+ chattyTry "removing dist/" $ do+ exists <- doesDirectoryExist distPref+ when exists (removeDirectoryRecursive distPref)++ -- Any extra files the user wants to remove+ traverse_ removeFileOrDirectory (extraTmpFiles pkg_descr)++ -- If the user wanted to save the config, write it back+ traverse_ (writePersistBuildConfig distPref) maybeConfig++ where+ removeFileOrDirectory :: FilePath -> IO ()+ removeFileOrDirectory fname = do+ isDir <- doesDirectoryExist fname+ isFile <- doesFileExist fname+ if isDir then removeDirectoryRecursive fname+ else when isFile $ removeFile fname+ verbosity = fromFlag (cleanVerbosity flags)++-- --------------------------------------------------------------------------+-- Default hooks++-- | Hooks that correspond to a plain instantiation of the+-- \"simple\" build system+simpleUserHooks :: UserHooks+simpleUserHooks =+ emptyUserHooks {+ confHook = configure,+ postConf = finalChecks,+ buildHook = defaultBuildHook,+ replHook = defaultReplHook,+ copyHook = \desc lbi _ f -> install desc lbi f,+ -- 'install' has correct 'copy' behavior with params+ testHook = defaultTestHook,+ benchHook = defaultBenchHook,+ instHook = defaultInstallHook,+ cleanHook = \p _ _ f -> clean p f,+ hscolourHook = \p l h f -> hscolour p l (allSuffixHandlers h) f,+ haddockHook = \p l h f -> haddock p l (allSuffixHandlers h) f,+ regHook = defaultRegHook,+ unregHook = \p l _ f -> unregister p l f+ }+ where+ finalChecks _args flags pkg_descr lbi =+ checkForeignDeps pkg_descr lbi (lessVerbose verbosity)+ where+ verbosity = fromFlag (configVerbosity flags)++-- | Basic autoconf 'UserHooks':+--+-- * 'postConf' runs @.\/configure@, if present.+--+-- * the pre-hooks 'preBuild', 'preClean', 'preCopy', 'preInst',+-- 'preReg' and 'preUnreg' read additional build information from+-- /package/@.buildinfo@, if present.+--+-- Thus @configure@ can use local system information to generate+-- /package/@.buildinfo@ and possibly other files.++autoconfUserHooks :: UserHooks+autoconfUserHooks+ = simpleUserHooks+ {+ postConf = defaultPostConf,+ preBuild = readHookWithArgs buildVerbosity buildDistPref, -- buildCabalFilePath,+ preCopy = readHookWithArgs copyVerbosity copyDistPref,+ preClean = readHook cleanVerbosity cleanDistPref,+ preInst = readHook installVerbosity installDistPref,+ preHscolour = readHook hscolourVerbosity hscolourDistPref,+ preHaddock = readHookWithArgs haddockVerbosity haddockDistPref,+ preReg = readHook regVerbosity regDistPref,+ preUnreg = readHook regVerbosity regDistPref+ }+ where defaultPostConf :: Args -> ConfigFlags -> PackageDescription+ -> LocalBuildInfo -> IO ()+ defaultPostConf args flags pkg_descr lbi+ = do let verbosity = fromFlag (configVerbosity flags)+ baseDir lbi' = fromMaybe ""+ (takeDirectory <$> cabalFilePath lbi')+ confExists <- doesFileExist $ (baseDir lbi) </> "configure"+ if confExists+ then runConfigureScript verbosity+ backwardsCompatHack flags lbi+ else die' verbosity "configure script not found."++ pbi <- getHookedBuildInfo verbosity (buildDir lbi)+ sanityCheckHookedBuildInfo verbosity pkg_descr pbi+ let pkg_descr' = updatePackageDescription pbi pkg_descr+ lbi' = lbi { localPkgDescr = pkg_descr' }+ postConf simpleUserHooks args flags pkg_descr' lbi'++ backwardsCompatHack = False++ readHookWithArgs :: (a -> Flag Verbosity)+ -> (a -> Flag FilePath)+ -> Args -> a+ -> IO HookedBuildInfo+ readHookWithArgs get_verbosity get_dist_pref _ flags = do+ dist_dir <- findDistPrefOrDefault (get_dist_pref flags)+ getHookedBuildInfo verbosity (dist_dir </> "build")+ where+ verbosity = fromFlag (get_verbosity flags)++ readHook :: (a -> Flag Verbosity)+ -> (a -> Flag FilePath)+ -> Args -> a -> IO HookedBuildInfo+ readHook get_verbosity get_dist_pref a flags = do+ noExtraFlags a+ dist_dir <- findDistPrefOrDefault (get_dist_pref flags)+ getHookedBuildInfo verbosity (dist_dir </> "build")+ where+ verbosity = fromFlag (get_verbosity flags)++runConfigureScript :: Verbosity -> Bool -> ConfigFlags -> LocalBuildInfo+ -> IO ()+runConfigureScript verbosity backwardsCompatHack flags lbi = do+ env <- getEnvironment+ let programDb = withPrograms lbi+ (ccProg, ccFlags) <- configureCCompiler verbosity programDb+ 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+ configureFile <- makeAbsolute $+ fromMaybe "." (takeDirectory <$> cabalFilePath lbi) </> "configure"+ -- autoconf is fussy about filenames, and has a set of forbidden+ -- characters that can't appear in the build directory, etc:+ -- https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions+ --+ -- This has caused hard-to-debug failures in the past (#5368), so we+ -- detect some cases early and warn with a clear message. Windows's+ -- use of backslashes is problematic here, so we'll switch to+ -- slashes, but we do still want to fail on backslashes in POSIX+ -- paths.+ --+ -- TODO: We don't check for colons, tildes or leading dashes. We+ -- also should check the builddir's path, destdir, and all other+ -- paths as well.+ let configureFile' = intercalate "/" $ splitDirectories configureFile+ for_ badAutoconfCharacters $ \(c, cname) ->+ when (c `elem` dropDrive configureFile') $+ warn verbosity $ concat+ [ "The path to the './configure' script, '", configureFile'+ , "', contains the character '", [c], "' (", cname, ")."+ , " This may cause the script to fail with an obscure error, or for"+ , " building the package to fail later."+ ]++ 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)]+ hp = hostPlatform lbi+ maybeHostFlag = if hp == buildPlatform then [] else ["--host=" ++ show (pretty hp)]+ args' = configureFile':args ++ ["CC=" ++ ccProgShort] ++ maybeHostFlag+ 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')+ { progInvokeCwd = Just (buildDir lbi) }+ Nothing -> die' verbosity notFoundMsg+ where+ args = configureArgs backwardsCompatHack flags++ 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."++badAutoconfCharacters :: [(Char, String)]+badAutoconfCharacters =+ [ (' ', "space")+ , ('\t', "tab")+ , ('\n', "newline")+ , ('\0', "null")+ , ('"', "double quote")+ , ('#', "hash")+ , ('$', "dollar sign")+ , ('&', "ampersand")+ , ('\'', "single quote")+ , ('(', "left bracket")+ , (')', "right bracket")+ , ('*', "star")+ , (';', "semicolon")+ , ('<', "less-than sign")+ , ('=', "equals sign")+ , ('>', "greater-than sign")+ , ('?', "question mark")+ , ('[', "left square bracket")+ , ('\\', "backslash")+ , ('`', "backtick")+ , ('|', "pipe")+ ]++getHookedBuildInfo :: Verbosity -> FilePath -> IO HookedBuildInfo+getHookedBuildInfo verbosity build_dir = do+ maybe_infoFile <- findHookedPackageDesc verbosity build_dir+ case maybe_infoFile of+ Nothing -> return emptyHookedBuildInfo+ Just infoFile -> do+ info verbosity $ "Reading parameters from " ++ infoFile+ readHookedBuildInfo verbosity infoFile++defaultTestHook :: Args -> PackageDescription -> LocalBuildInfo+ -> UserHooks -> TestFlags -> IO ()+defaultTestHook args pkg_descr localbuildinfo _ flags =+ test args pkg_descr localbuildinfo flags++defaultBenchHook :: Args -> PackageDescription -> LocalBuildInfo+ -> UserHooks -> BenchmarkFlags -> IO ()+defaultBenchHook args pkg_descr localbuildinfo _ flags =+ bench args pkg_descr localbuildinfo flags++defaultInstallHook :: PackageDescription -> LocalBuildInfo+ -> UserHooks -> InstallFlags -> IO ()+defaultInstallHook pkg_descr localbuildinfo _ flags = do+ let copyFlags = defaultCopyFlags {+ copyDistPref = installDistPref flags,+ copyDest = installDest flags,+ copyVerbosity = installVerbosity flags+ }+ install pkg_descr localbuildinfo copyFlags+ let registerFlags = defaultRegisterFlags {+ regDistPref = installDistPref flags,+ regInPlace = installInPlace flags,+ regPackageDB = installPackageDB flags,+ regVerbosity = installVerbosity flags+ }+ when (hasLibs pkg_descr) $ register pkg_descr localbuildinfo registerFlags++defaultBuildHook :: PackageDescription -> LocalBuildInfo+ -> UserHooks -> BuildFlags -> IO ()+defaultBuildHook pkg_descr localbuildinfo hooks flags =+ build pkg_descr localbuildinfo flags (allSuffixHandlers hooks)++defaultReplHook :: PackageDescription -> LocalBuildInfo+ -> UserHooks -> ReplFlags -> [String] -> IO ()+defaultReplHook pkg_descr localbuildinfo hooks flags args =+ repl pkg_descr localbuildinfo flags (allSuffixHandlers hooks) args++defaultRegHook :: PackageDescription -> LocalBuildInfo+ -> UserHooks -> RegisterFlags -> IO ()+defaultRegHook pkg_descr localbuildinfo _ flags =+ if hasLibs pkg_descr+ then register pkg_descr localbuildinfo flags+ else setupMessage (fromFlag (regVerbosity flags))+ "Package contains no library to register:" (packageId pkg_descr)
+ src/Distribution/Simple/Bench.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Bench+-- Copyright : Johan Tibell 2011+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is the entry point into running the benchmarks in a built+-- package. It performs the \"@.\/setup bench@\" action. It runs+-- benchmarks designated in the package description.++module Distribution.Simple.Bench+ ( bench+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.UnqualComponentName+import qualified Distribution.PackageDescription as PD+import Distribution.Simple.BuildPaths+import Distribution.Simple.Compiler+import Distribution.Simple.InstallDirs+import qualified Distribution.Simple.LocalBuildInfo as LBI+import Distribution.Simple.Setup+import Distribution.Simple.UserHooks+import Distribution.Simple.Utils+import Distribution.Pretty++import System.Directory ( doesFileExist )+import System.FilePath ( (</>), (<.>) )++-- | Perform the \"@.\/setup bench@\" action.+bench :: Args -- ^positional command-line arguments+ -> PD.PackageDescription -- ^information from the .cabal file+ -> LBI.LocalBuildInfo -- ^information from the configure step+ -> BenchmarkFlags -- ^flags sent to benchmark+ -> IO ()+bench args pkg_descr lbi flags = do+ let verbosity = fromFlag $ benchmarkVerbosity flags+ benchmarkNames = args+ pkgBenchmarks = PD.benchmarks pkg_descr+ enabledBenchmarks = map fst (LBI.enabledBenchLBIs pkg_descr lbi)++ -- Run the benchmark+ doBench :: PD.Benchmark -> IO ExitCode+ doBench bm =+ case PD.benchmarkInterface bm of+ PD.BenchmarkExeV10 _ _ -> do+ let cmd = LBI.buildDir lbi </> name </> name <.> exeExtension (LBI.hostPlatform lbi)+ options = map (benchOption pkg_descr lbi bm) $+ benchmarkOptions flags+ -- Check that the benchmark executable exists.+ exists <- doesFileExist cmd+ unless exists $ die' verbosity $+ "Error: Could not find benchmark program \""+ ++ cmd ++ "\". Did you build the package first?"++ notice verbosity $ startMessage name+ -- This will redirect the child process+ -- stdout/stderr to the parent process.+ exitcode <- rawSystemExitCode verbosity cmd options+ notice verbosity $ finishMessage name exitcode+ return exitcode++ _ -> do+ notice verbosity $ "No support for running "+ ++ "benchmark " ++ name ++ " of type: "+ ++ prettyShow (PD.benchmarkType bm)+ exitFailure+ where name = unUnqualComponentName $ PD.benchmarkName bm++ unless (PD.hasBenchmarks pkg_descr) $ do+ notice verbosity "Package has no benchmarks."+ exitSuccess++ when (PD.hasBenchmarks pkg_descr && null enabledBenchmarks) $+ die' verbosity $ "No benchmarks enabled. Did you remember to configure with "+ ++ "\'--enable-benchmarks\'?"++ bmsToRun <- case benchmarkNames of+ [] -> return enabledBenchmarks+ names -> for names $ \bmName ->+ let benchmarkMap = zip enabledNames enabledBenchmarks+ enabledNames = map PD.benchmarkName enabledBenchmarks+ allNames = map PD.benchmarkName pkgBenchmarks+ in case lookup (mkUnqualComponentName bmName) benchmarkMap of+ Just t -> return t+ _ | mkUnqualComponentName bmName `elem` allNames ->+ die' verbosity $ "Package configured with benchmark "+ ++ bmName ++ " disabled."+ | otherwise -> die' verbosity $ "no such benchmark: " ++ bmName++ let totalBenchmarks = length bmsToRun+ notice verbosity $ "Running " ++ show totalBenchmarks ++ " benchmarks..."+ exitcodes <- traverse doBench bmsToRun+ let allOk = totalBenchmarks == length (filter (== ExitSuccess) exitcodes)+ unless allOk exitFailure+ where+ startMessage name = "Benchmark " ++ name ++ ": RUNNING...\n"+ finishMessage name exitcode = "Benchmark " ++ name ++ ": "+ ++ (case exitcode of+ ExitSuccess -> "FINISH"+ ExitFailure _ -> "ERROR")+++-- TODO: This is abusing the notion of a 'PathTemplate'. The result isn't+-- necessarily a path.+benchOption :: PD.PackageDescription+ -> LBI.LocalBuildInfo+ -> PD.Benchmark+ -> PathTemplate+ -> String+benchOption pkg_descr lbi bm template =+ fromPathTemplate $ substPathTemplate env template+ where+ env = initialPathTemplateEnv+ (PD.package pkg_descr) (LBI.localUnitId lbi)+ (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) +++ [(BenchmarkNameVar, toPathTemplate $ unUnqualComponentName $ PD.benchmarkName bm)]
+ src/Distribution/Simple/Build.hs view
@@ -0,0 +1,734 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Build+-- Copyright : Isaac Jones 2003-2005,+-- Ross Paterson 2006,+-- Duncan Coutts 2007-2008, 2012+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is the entry point to actually building the modules in a package. It+-- doesn't actually do much itself, most of the work is delegated to+-- compiler-specific actions. It does do some non-compiler specific bits like+-- running pre-processors.+--++module Distribution.Simple.Build (+ build, showBuildInfo, repl,+ startInterpreter,++ initialBuildSteps,+ createInternalPackageDB,+ componentInitialBuildSteps,+ writeAutogenFiles,+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.Generic++import Distribution.Types.ComponentLocalBuildInfo+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.Dependency+import Distribution.Types.ExecutableScope+import Distribution.Types.ForeignLib+import Distribution.Types.LibraryVisibility+import Distribution.Types.LocalBuildInfo+import Distribution.Types.MungedPackageId+import Distribution.Types.MungedPackageName+import Distribution.Types.ModuleRenaming+import Distribution.Types.TargetInfo+import Distribution.Utils.Path++import Distribution.Package+import Distribution.Backpack+import Distribution.Backpack.DescribeUnitId+import qualified Distribution.Simple.GHC as GHC+import qualified Distribution.Simple.GHCJS as GHCJS+import qualified Distribution.Simple.UHC as UHC+import qualified Distribution.Simple.HaskellSuite as HaskellSuite+import qualified Distribution.Simple.PackageIndex as Index++import Distribution.Simple.Build.Macros (generateCabalMacrosHeader)+import Distribution.Simple.Build.PathsModule (generatePathsModule)+import qualified Distribution.Simple.Program.HcPkg as HcPkg++import Distribution.Simple.Compiler+import Distribution.PackageDescription+import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.InstalledPackageInfo (InstalledPackageInfo)+import qualified Distribution.ModuleName as ModuleName++import Distribution.Simple.Setup+import Distribution.Simple.BuildTarget+import Distribution.Simple.BuildToolDepends+import Distribution.Simple.PreProcess+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.Program.Types+import Distribution.Simple.Program.Db+import Distribution.Simple.ShowBuildInfo+import Distribution.Simple.BuildPaths+import Distribution.Simple.Configure+import Distribution.Simple.Register+import Distribution.Simple.Test.LibV09+import Distribution.Simple.Utils+import Distribution.Simple.Utils.Json++import Distribution.System+import Distribution.Pretty+import Distribution.Verbosity+import Distribution.Version (thisVersion)++import Distribution.Compat.Graph (IsNode(..))++import Control.Monad+import qualified Data.Set as Set+import System.FilePath ( (</>), (<.>), takeDirectory )+import System.Directory ( getCurrentDirectory )++-- -----------------------------------------------------------------------------+-- |Build the libraries and executables in this package.++build :: PackageDescription -- ^ Mostly information from the .cabal file+ -> LocalBuildInfo -- ^ Configuration information+ -> BuildFlags -- ^ Flags that the user passed to build+ -> [ PPSuffixHandler ] -- ^ preprocessors to run before compiling+ -> IO ()+build pkg_descr lbi flags suffixes = do+ targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs flags)+ let componentsToBuild = neededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets)+ info verbosity $ "Component build order: "+ ++ intercalate ", "+ (map (showComponentName . componentLocalName . targetCLBI)+ componentsToBuild)++ when (null targets) $+ -- Only bother with this message if we're building the whole package+ setupMessage verbosity "Building" (packageId pkg_descr)++ internalPackageDB <- createInternalPackageDB verbosity lbi distPref++ (\f -> foldM_ f (installedPkgs lbi) componentsToBuild) $ \index target -> do+ let comp = targetComponent target+ clbi = targetCLBI target+ componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity+ let bi = componentBuildInfo comp+ progs' = addInternalBuildTools pkg_descr lbi bi (withPrograms lbi)+ lbi' = lbi {+ withPrograms = progs',+ withPackageDB = withPackageDB lbi ++ [internalPackageDB],+ installedPkgs = index+ }+ mb_ipi <- buildComponent verbosity (buildNumJobs flags) pkg_descr+ lbi' suffixes comp clbi distPref+ return (maybe index (Index.insert `flip` index) mb_ipi)+ return ()+ where+ distPref = fromFlag (buildDistPref flags)+ verbosity = fromFlag (buildVerbosity flags)+++showBuildInfo :: PackageDescription -- ^ Mostly information from the .cabal file+ -> LocalBuildInfo -- ^ Configuration information+ -> BuildFlags -- ^ Flags that the user passed to build+ -> IO String+showBuildInfo pkg_descr lbi flags = do+ let verbosity = fromFlag (buildVerbosity flags)+ targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs flags)+ let targetsToBuild = neededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets)+ doc = mkBuildInfo pkg_descr lbi flags targetsToBuild+ return $ renderJson doc ""+++repl :: PackageDescription -- ^ Mostly information from the .cabal file+ -> LocalBuildInfo -- ^ Configuration information+ -> ReplFlags -- ^ Flags that the user passed to build+ -> [ PPSuffixHandler ] -- ^ preprocessors to run before compiling+ -> [String]+ -> IO ()+repl pkg_descr lbi flags suffixes args = do+ let distPref = fromFlag (replDistPref flags)+ verbosity = fromFlag (replVerbosity flags)++ target <- readTargetInfos verbosity pkg_descr lbi args >>= \r -> case r of+ -- This seems DEEPLY questionable.+ [] -> case allTargetsInBuildOrder' pkg_descr lbi of+ (target:_) -> return target+ [] -> die' verbosity $ "Failed to determine target."+ [target] -> return target+ _ -> die' verbosity $ "The 'repl' command does not support multiple targets at once."+ let componentsToBuild = neededTargetsInBuildOrder' pkg_descr lbi [nodeKey target]+ debug verbosity $ "Component build order: "+ ++ intercalate ", "+ (map (showComponentName . componentLocalName . targetCLBI)+ componentsToBuild)++ internalPackageDB <- createInternalPackageDB verbosity lbi distPref++ let lbiForComponent comp lbi' =+ lbi' {+ withPackageDB = withPackageDB lbi ++ [internalPackageDB],+ withPrograms = addInternalBuildTools pkg_descr lbi'+ (componentBuildInfo comp) (withPrograms lbi')+ }++ -- build any dependent components+ sequence_+ [ do let clbi = targetCLBI subtarget+ comp = targetComponent subtarget+ lbi' = lbiForComponent comp lbi+ componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity+ buildComponent verbosity NoFlag+ pkg_descr lbi' suffixes comp clbi distPref+ | subtarget <- safeInit componentsToBuild ]++ -- REPL for target components+ let clbi = targetCLBI target+ comp = targetComponent target+ lbi' = lbiForComponent comp lbi+ replFlags = replReplOptions flags+ componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity+ replComponent replFlags verbosity pkg_descr lbi' suffixes comp clbi distPref+++-- | Start an interpreter without loading any package files.+startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform+ -> PackageDBStack -> IO ()+startInterpreter verbosity programDb comp platform packageDBs =+ case compilerFlavor comp of+ GHC -> GHC.startInterpreter verbosity programDb comp platform packageDBs+ GHCJS -> GHCJS.startInterpreter verbosity programDb comp platform packageDBs+ _ -> die' verbosity "A REPL is not supported with this compiler."++buildComponent :: Verbosity+ -> Flag (Maybe Int)+ -> PackageDescription+ -> LocalBuildInfo+ -> [PPSuffixHandler]+ -> Component+ -> ComponentLocalBuildInfo+ -> FilePath+ -> IO (Maybe InstalledPackageInfo)+buildComponent verbosity numJobs pkg_descr lbi suffixes+ comp@(CLib lib) clbi distPref = do+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ setupMessage' verbosity "Building" (packageId pkg_descr)+ (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)+ let libbi = libBuildInfo lib+ lib' = lib { libBuildInfo = flip addExtraAsmSources extras+ $ flip addExtraCmmSources extras+ $ flip addExtraCxxSources extras+ $ flip addExtraCSources extras+ $ libbi+ }++ buildLib verbosity numJobs pkg_descr lbi lib' clbi++ let oneComponentRequested (OneComponentRequestedSpec _) = True+ oneComponentRequested _ = False+ -- Don't register inplace if we're only building a single component;+ -- it's not necessary because there won't be any subsequent builds+ -- that need to tag us+ if (not (oneComponentRequested (componentEnabledSpec lbi)))+ then do+ -- 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+ installedPkgInfo = inplaceInstalledPackageInfo pwd distPref pkg_descr+ -- NB: Use a fake ABI hash to avoid+ -- needing to recompute it every build.+ (mkAbiHash "inplace") lib' lbi clbi++ debug verbosity $ "Registering inplace:\n" ++ (IPI.showInstalledPackageInfo installedPkgInfo)+ registerPackage verbosity (compiler lbi) (withPrograms lbi)+ (withPackageDB lbi) installedPkgInfo+ HcPkg.defaultRegisterOptions {+ HcPkg.registerMultiInstance = True+ }+ return (Just installedPkgInfo)+ else return Nothing++buildComponent verbosity numJobs pkg_descr lbi suffixes+ comp@(CFLib flib) clbi _distPref = do+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ setupMessage' verbosity "Building" (packageId pkg_descr)+ (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)+ buildFLib verbosity numJobs pkg_descr lbi flib clbi+ return Nothing++buildComponent verbosity numJobs pkg_descr lbi suffixes+ comp@(CExe exe) clbi _ = do+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ setupMessage' verbosity "Building" (packageId pkg_descr)+ (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)+ let ebi = buildInfo exe+ exe' = exe { buildInfo = addExtraCSources ebi extras }+ buildExe verbosity numJobs pkg_descr lbi exe' clbi+ return Nothing+++buildComponent verbosity numJobs pkg_descr lbi suffixes+ comp@(CTest test@TestSuite { testInterface = TestSuiteExeV10{} })+ clbi _distPref = do+ let exe = testSuiteExeV10AsExe test+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ setupMessage' verbosity "Building" (packageId pkg_descr)+ (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)+ let ebi = buildInfo exe+ exe' = exe { buildInfo = addExtraCSources ebi extras }+ buildExe verbosity numJobs pkg_descr lbi exe' clbi+ return Nothing+++buildComponent verbosity numJobs pkg_descr lbi0 suffixes+ comp@(CTest+ test@TestSuite { testInterface = TestSuiteLibV09{} })+ clbi -- This ComponentLocalBuildInfo corresponds to a detailed+ -- test suite and not a real component. It should not+ -- be used, except to construct the CLBIs for the+ -- library and stub executable that will actually be+ -- built.+ distPref = do+ pwd <- getCurrentDirectory+ let (pkg, lib, libClbi, lbi, ipi, exe, exeClbi) =+ testSuiteLibV09AsLibAndExe pkg_descr test clbi lbi0 distPref pwd+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ setupMessage' verbosity "Building" (packageId pkg_descr)+ (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)+ buildLib verbosity numJobs pkg lbi lib libClbi+ -- 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)+ (withPackageDB lbi) ipi+ HcPkg.defaultRegisterOptions {+ HcPkg.registerMultiInstance = True+ }+ let ebi = buildInfo exe+ -- NB: The stub executable is linked against the test-library+ -- which already contains all `other-modules`, so we need+ -- to remove those from the stub-exe's build-info+ exe' = exe { buildInfo = (addExtraCSources ebi extras) { otherModules = [] } }+ buildExe verbosity numJobs pkg_descr lbi exe' exeClbi+ return Nothing -- Can't depend on test suite+++buildComponent verbosity _ _ _ _+ (CTest TestSuite { testInterface = TestSuiteUnsupported tt })+ _ _ =+ die' verbosity $ "No support for building test suite type " ++ prettyShow tt+++buildComponent verbosity numJobs pkg_descr lbi suffixes+ comp@(CBench bm@Benchmark { benchmarkInterface = BenchmarkExeV10 {} })+ clbi _distPref = do+ let exe = benchmarkExeV10asExe bm+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ setupMessage' verbosity "Building" (packageId pkg_descr)+ (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)+ let ebi = buildInfo exe+ exe' = exe { buildInfo = addExtraCSources ebi extras }+ buildExe verbosity numJobs pkg_descr lbi exe' clbi+ return Nothing+++buildComponent verbosity _ _ _ _+ (CBench Benchmark { benchmarkInterface = BenchmarkUnsupported tt })+ _ _ =+ die' verbosity $ "No support for building benchmark type " ++ prettyShow 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+++-- | Add extra C++ sources generated by preprocessing to build+-- information.+addExtraCxxSources :: BuildInfo -> [FilePath] -> BuildInfo+addExtraCxxSources bi extras = bi { cxxSources = new }+ where new = Set.toList $ old `Set.union` exs+ old = Set.fromList $ cxxSources bi+ exs = Set.fromList extras+++-- | Add extra C-- sources generated by preprocessing to build+-- information.+addExtraCmmSources :: BuildInfo -> [FilePath] -> BuildInfo+addExtraCmmSources bi extras = bi { cmmSources = new }+ where new = Set.toList $ old `Set.union` exs+ old = Set.fromList $ cmmSources bi+ exs = Set.fromList extras+++-- | Add extra ASM sources generated by preprocessing to build+-- information.+addExtraAsmSources :: BuildInfo -> [FilePath] -> BuildInfo+addExtraAsmSources bi extras = bi { asmSources = new }+ where new = Set.toList $ old `Set.union` exs+ old = Set.fromList $ asmSources bi+ exs = Set.fromList extras+++replComponent :: [String]+ -> Verbosity+ -> PackageDescription+ -> LocalBuildInfo+ -> [PPSuffixHandler]+ -> Component+ -> ComponentLocalBuildInfo+ -> FilePath+ -> IO ()+replComponent replFlags verbosity pkg_descr lbi suffixes+ comp@(CLib lib) clbi _ = do+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ let libbi = libBuildInfo lib+ lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }+ replLib replFlags verbosity pkg_descr lbi lib' clbi++replComponent replFlags verbosity pkg_descr lbi suffixes+ comp@(CFLib flib) clbi _ = do+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ replFLib replFlags verbosity pkg_descr lbi flib clbi++replComponent replFlags verbosity pkg_descr lbi suffixes+ comp@(CExe exe) clbi _ = do+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }+ replExe replFlags verbosity pkg_descr lbi exe' clbi+++replComponent replFlags verbosity pkg_descr lbi suffixes+ comp@(CTest test@TestSuite { testInterface = TestSuiteExeV10{} })+ clbi _distPref = do+ let exe = testSuiteExeV10AsExe test+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }+ replExe replFlags verbosity pkg_descr lbi exe' clbi+++replComponent replFlags verbosity pkg_descr lbi0 suffixes+ comp@(CTest+ test@TestSuite { testInterface = TestSuiteLibV09{} })+ clbi distPref = do+ pwd <- getCurrentDirectory+ let (pkg, lib, libClbi, lbi, _, _, _) =+ testSuiteLibV09AsLibAndExe pkg_descr test clbi lbi0 distPref pwd+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ let libbi = libBuildInfo lib+ lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }+ replLib replFlags verbosity pkg lbi lib' libClbi+++replComponent _ verbosity _ _ _+ (CTest TestSuite { testInterface = TestSuiteUnsupported tt })+ _ _ =+ die' verbosity $ "No support for building test suite type " ++ prettyShow tt+++replComponent replFlags verbosity pkg_descr lbi suffixes+ comp@(CBench bm@Benchmark { benchmarkInterface = BenchmarkExeV10 {} })+ clbi _distPref = do+ let exe = benchmarkExeV10asExe bm+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ extras <- preprocessExtras verbosity comp lbi+ let ebi = buildInfo exe+ exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }+ replExe replFlags verbosity pkg_descr lbi exe' clbi+++replComponent _ verbosity _ _ _+ (CBench Benchmark { benchmarkInterface = BenchmarkUnsupported tt })+ _ _ =+ die' verbosity $ "No support for building benchmark type " ++ prettyShow tt++----------------------------------------------------+-- Shared code for buildComponent and replComponent+--++-- | Translate a exe-style 'TestSuite' component into an exe for building+testSuiteExeV10AsExe :: TestSuite -> Executable+testSuiteExeV10AsExe test@TestSuite { testInterface = TestSuiteExeV10 _ mainFile } =+ Executable {+ exeName = testName test,+ modulePath = mainFile,+ exeScope = ExecutablePublic,+ buildInfo = testBuildInfo test+ }+testSuiteExeV10AsExe TestSuite{} = error "testSuiteExeV10AsExe: wrong kind"++-- | Translate a exe-style 'Benchmark' component into an exe for building+benchmarkExeV10asExe :: Benchmark -> Executable+benchmarkExeV10asExe bm@Benchmark { benchmarkInterface = BenchmarkExeV10 _ mainFile } =+ Executable {+ exeName = benchmarkName bm,+ modulePath = mainFile,+ exeScope = ExecutablePublic,+ buildInfo = benchmarkBuildInfo bm+ }+benchmarkExeV10asExe Benchmark{} = error "benchmarkExeV10asExe: wrong kind"++-- | Translate a lib-style 'TestSuite' component into a lib + exe for building+testSuiteLibV09AsLibAndExe :: PackageDescription+ -> TestSuite+ -> ComponentLocalBuildInfo+ -> LocalBuildInfo+ -> FilePath+ -> FilePath+ -> (PackageDescription,+ Library, ComponentLocalBuildInfo,+ LocalBuildInfo,+ IPI.InstalledPackageInfo,+ Executable, ComponentLocalBuildInfo)+testSuiteLibV09AsLibAndExe pkg_descr+ test@TestSuite { testInterface = TestSuiteLibV09 _ m }+ clbi lbi distPref pwd =+ (pkg, lib, libClbi, lbi, ipi, exe, exeClbi)+ where+ bi = testBuildInfo test+ lib = Library {+ libName = LMainLibName,+ exposedModules = [ m ],+ reexportedModules = [],+ signatures = [],+ libExposed = True,+ libVisibility = LibraryVisibilityPrivate,+ libBuildInfo = bi+ }+ -- This is, like, the one place where we use a CTestName for a library.+ -- Should NOT use library name, since that could conflict!+ PackageIdentifier pkg_name pkg_ver = package pkg_descr+ -- Note: we do make internal library from the test!+ compat_name = MungedPackageName pkg_name (LSubLibName (testName test))+ compat_key = computeCompatPackageKey (compiler lbi) compat_name pkg_ver (componentUnitId clbi)+ libClbi = LibComponentLocalBuildInfo+ { componentPackageDeps = componentPackageDeps clbi+ , componentInternalDeps = componentInternalDeps clbi+ , componentIsIndefinite_ = False+ , componentExeDeps = componentExeDeps clbi+ , componentLocalName = CLibName $ LSubLibName $ testName test+ , componentIsPublic = False+ , componentIncludes = componentIncludes clbi+ , componentUnitId = componentUnitId clbi+ , componentComponentId = componentComponentId clbi+ , componentInstantiatedWith = []+ , componentCompatPackageName = compat_name+ , componentCompatPackageKey = compat_key+ , componentExposedModules = [IPI.ExposedModule m Nothing]+ }+ pkgName' = mkPackageName $ prettyShow compat_name+ pkg = pkg_descr {+ package = (package pkg_descr) { pkgName = pkgName' }+ , executables = []+ , testSuites = []+ , subLibraries = [lib]+ }+ ipi = inplaceInstalledPackageInfo pwd distPref pkg (mkAbiHash "") lib lbi libClbi+ testDir = buildDir lbi </> stubName test+ </> stubName test ++ "-tmp"+ testLibDep = Dependency+ pkgName'+ (thisVersion $ pkgVersion $ package pkg_descr)+ mainLibSet+ exe = Executable {+ exeName = mkUnqualComponentName $ stubName test,+ modulePath = stubFilePath test,+ exeScope = ExecutablePublic,+ buildInfo = (testBuildInfo test) {+ hsSourceDirs = [ unsafeMakeSymbolicPath testDir ],+ targetBuildDepends = testLibDep+ : (targetBuildDepends $ testBuildInfo test)+ }+ }+ -- | The stub executable needs a new 'ComponentLocalBuildInfo'+ -- that exposes the relevant test suite library.+ deps = (IPI.installedUnitId ipi, mungedId ipi)+ : (filter (\(_, x) -> let name = prettyShow $ mungedName x+ in name == "Cabal" || name == "base")+ (componentPackageDeps clbi))+ exeClbi = ExeComponentLocalBuildInfo {+ -- TODO: this is a hack, but as long as this is unique+ -- (doesn't clobber something) we won't run into trouble+ componentUnitId = mkUnitId (stubName test),+ componentComponentId = mkComponentId (stubName test),+ componentInternalDeps = [componentUnitId clbi],+ componentExeDeps = [],+ componentLocalName = CExeName $ mkUnqualComponentName $ stubName test,+ componentPackageDeps = deps,+ -- Assert DefUnitId invariant!+ -- Executable can't be indefinite, so dependencies must+ -- be definite packages.+ componentIncludes = zip (map (DefiniteUnitId . unsafeMkDefUnitId . fst) deps)+ (repeat defaultRenaming)+ }+testSuiteLibV09AsLibAndExe _ TestSuite{} _ _ _ _ = error "testSuiteLibV09AsLibAndExe: wrong kind"+++-- | Initialize a new package db file for libraries defined+-- internally to the package.+createInternalPackageDB :: Verbosity -> LocalBuildInfo -> FilePath+ -> IO PackageDB+createInternalPackageDB verbosity lbi distPref = do+ existsAlready <- doesPackageDBExist dbPath+ when existsAlready $ deletePackageDB dbPath+ createPackageDB verbosity (compiler lbi) (withPrograms lbi) False dbPath+ return (SpecificPackageDB dbPath)+ where+ dbPath = internalPackageDBPath lbi distPref++addInternalBuildTools :: PackageDescription -> LocalBuildInfo -> BuildInfo+ -> ProgramDb -> ProgramDb+addInternalBuildTools pkg lbi bi progs =+ foldr updateProgram progs internalBuildTools+ where+ internalBuildTools =+ [ simpleConfiguredProgram toolName' (FoundOnSystem toolLocation)+ | toolName <- getAllInternalToolDependencies pkg bi+ , let toolName' = unUnqualComponentName toolName+ , let toolLocation = buildDir lbi </> toolName' </> toolName' <.> exeExtension (hostPlatform lbi) ]+++-- TODO: build separate libs in separate dirs so that we can build+-- multiple libs, e.g. for 'LibTest' library-style test suites+buildLib :: Verbosity -> Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> Library -> ComponentLocalBuildInfo -> IO ()+buildLib verbosity numJobs pkg_descr lbi lib clbi =+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.buildLib verbosity numJobs pkg_descr lbi lib clbi+ GHCJS -> GHCJS.buildLib verbosity numJobs pkg_descr lbi lib clbi+ UHC -> UHC.buildLib verbosity pkg_descr lbi lib clbi+ HaskellSuite {} -> HaskellSuite.buildLib verbosity pkg_descr lbi lib clbi+ _ -> die' verbosity "Building is not supported with this compiler."++-- | Build a foreign library+--+-- NOTE: We assume that we already checked that we can actually build the+-- foreign library in configure.+buildFLib :: Verbosity -> Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> ForeignLib -> ComponentLocalBuildInfo -> IO ()+buildFLib verbosity numJobs pkg_descr lbi flib clbi =+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.buildFLib verbosity numJobs pkg_descr lbi flib clbi+ _ -> die' verbosity "Building is not supported with this compiler."++buildExe :: Verbosity -> Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> Executable -> ComponentLocalBuildInfo -> IO ()+buildExe verbosity numJobs pkg_descr lbi exe clbi =+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.buildExe verbosity numJobs pkg_descr lbi exe clbi+ GHCJS -> GHCJS.buildExe verbosity numJobs pkg_descr lbi exe clbi+ UHC -> UHC.buildExe verbosity pkg_descr lbi exe clbi+ _ -> die' verbosity "Building is not supported with this compiler."++replLib :: [String] -> Verbosity -> PackageDescription+ -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo+ -> IO ()+replLib replFlags verbosity pkg_descr lbi lib clbi =+ case compilerFlavor (compiler lbi) of+ -- 'cabal repl' doesn't need to support 'ghc --make -j', so we just pass+ -- NoFlag as the numJobs parameter.+ GHC -> GHC.replLib replFlags verbosity NoFlag pkg_descr lbi lib clbi+ GHCJS -> GHCJS.replLib replFlags verbosity NoFlag pkg_descr lbi lib clbi+ _ -> die' verbosity "A REPL is not supported for this compiler."++replExe :: [String] -> Verbosity -> PackageDescription+ -> LocalBuildInfo -> Executable -> ComponentLocalBuildInfo+ -> IO ()+replExe replFlags verbosity pkg_descr lbi exe clbi =+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.replExe replFlags verbosity NoFlag pkg_descr lbi exe clbi+ GHCJS -> GHCJS.replExe replFlags verbosity NoFlag pkg_descr lbi exe clbi+ _ -> die' verbosity "A REPL is not supported for this compiler."++replFLib :: [String] -> Verbosity -> PackageDescription+ -> LocalBuildInfo -> ForeignLib -> ComponentLocalBuildInfo+ -> IO ()+replFLib replFlags verbosity pkg_descr lbi exe clbi =+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.replFLib replFlags verbosity NoFlag pkg_descr lbi exe clbi+ _ -> die' verbosity "A REPL is not supported for this compiler."++-- | Runs 'componentInitialBuildSteps' on every configured component.+initialBuildSteps :: FilePath -- ^"dist" prefix+ -> PackageDescription -- ^mostly information from the .cabal file+ -> LocalBuildInfo -- ^Configuration information+ -> Verbosity -- ^The verbosity to use+ -> IO ()+initialBuildSteps distPref pkg_descr lbi verbosity =+ withAllComponentsInBuildOrder pkg_descr lbi $ \_comp clbi ->+ componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity++-- | Creates the autogenerated files for a particular configured component.+componentInitialBuildSteps :: FilePath -- ^"dist" prefix+ -> PackageDescription -- ^mostly information from the .cabal file+ -> LocalBuildInfo -- ^Configuration information+ -> ComponentLocalBuildInfo+ -> Verbosity -- ^The verbosity to use+ -> IO ()+componentInitialBuildSteps _distPref pkg_descr lbi clbi verbosity = do+ createDirectoryIfMissingVerbose verbosity True (componentBuildDir lbi clbi)++ writeAutogenFiles verbosity pkg_descr lbi clbi++-- | Generate and write out the Paths_<pkg>.hs and cabal_macros.h files+--+writeAutogenFiles :: Verbosity+ -> PackageDescription+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> IO ()+writeAutogenFiles verbosity pkg lbi clbi = do+ createDirectoryIfMissingVerbose verbosity True (autogenComponentModulesDir lbi clbi)++ let pathsModulePath = autogenComponentModulesDir lbi clbi+ </> ModuleName.toFilePath (autogenPathsModuleName pkg) <.> "hs"+ pathsModuleDir = takeDirectory pathsModulePath+ -- Ensure that the directory exists!+ createDirectoryIfMissingVerbose verbosity True pathsModuleDir+ rewriteFileEx verbosity pathsModulePath (generatePathsModule pkg lbi clbi)++ --TODO: document what we're doing here, and move it to its own function+ case clbi of+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->+ -- Write out empty hsig files for all requirements, so that GHC+ -- has a source file to look at it when it needs to typecheck+ -- a signature. It's harmless to write these out even when+ -- there is a real hsig file written by the user, since+ -- include path ordering ensures that the real hsig file+ -- will always be picked up before the autogenerated one.+ for_ (map fst insts) $ \mod_name -> do+ let sigPath = autogenComponentModulesDir lbi clbi+ </> ModuleName.toFilePath mod_name <.> "hsig"+ createDirectoryIfMissingVerbose verbosity True (takeDirectory sigPath)+ rewriteFileEx verbosity sigPath $+ "{-# OPTIONS_GHC -w #-}\n" +++ "{-# LANGUAGE NoImplicitPrelude #-}\n" +++ "signature " ++ prettyShow mod_name ++ " where"+ _ -> return ()++ let cppHeaderPath = autogenComponentModulesDir lbi clbi </> cppHeaderName+ rewriteFileEx verbosity cppHeaderPath (generateCabalMacrosHeader pkg lbi clbi)
+ src/Distribution/Simple/Build/Macros.hs view
@@ -0,0 +1,110 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Build.Macros+-- Copyright : Simon Marlow 2008+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Generate cabal_macros.h - CPP macros for package version testing+--+-- When using CPP you get+--+-- > VERSION_<package>+-- > MIN_VERSION_<package>(A,B,C)+--+-- for each /package/ in @build-depends@, which is true if the version of+-- /package/ in use is @>= A.B.C@, using the normal ordering on version+-- numbers.+--+-- TODO Figure out what to do about backpack and internal libraries. It is very+-- suspecious that this stuff works with munged package identifiers+module Distribution.Simple.Build.Macros (+ generateCabalMacrosHeader,+ generatePackageVersionMacros,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Version+import Distribution.PackageDescription+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.Program.Db+import Distribution.Simple.Program.Types+import Distribution.Types.MungedPackageId+import Distribution.Types.MungedPackageName+import Distribution.Pretty++import qualified Distribution.Simple.Build.Macros.Z as Z++-- | The contents of the @cabal_macros.h@ for the given configured package.+--+generateCabalMacrosHeader :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> String+generateCabalMacrosHeader pkg_descr lbi clbi = Z.render Z.Z+ { Z.zPackages = map mkZPackage $ package pkg_descr : map getPid (componentPackageDeps clbi)+ , Z.zTools =+ [ Z.ZTool+ { Z.ztoolName = programId prog+ , Z.ztoolVersion = ver+ , Z.ztoolX = major1+ , Z.ztoolY = major2+ , Z.ztoolZ = minor+ }+ | prog <- configuredPrograms $ withPrograms lbi+ , ver <- maybeToList (programVersion prog)+ , let (major1,major2,minor) = majorMinor ver+ ]+ , Z.zPackageKey = case clbi of+ LibComponentLocalBuildInfo{} -> componentCompatPackageKey clbi+ _ -> ""+ , Z.zComponentId = prettyShow (componentComponentId clbi)+ , Z.zPackageVersion = pkgVersion (package pkg_descr)+ , Z.zNotNull = not . null+ , Z.zManglePkgName = map fixchar . unPackageName+ , Z.zMangleStr = map fixchar+ }+ where+ getPid (_, MungedPackageId (MungedPackageName pn _) v) =+ -- NB: Drop the library name! We're just reporting package versions.+ -- This would have to be revisited if you are allowed to depend+ -- on different versions of the same package+ PackageIdentifier pn v++-- | 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+-- a configured package).+--+generatePackageVersionMacros :: Version -> [PackageId] -> String+generatePackageVersionMacros ver pkgids = Z.render Z.Z+ { Z.zPackages = map mkZPackage pkgids+ , Z.zTools = []+ , Z.zPackageKey = ""+ , Z.zComponentId = ""+ , Z.zPackageVersion = ver+ , Z.zNotNull = not . null+ , Z.zManglePkgName = map fixchar . unPackageName+ , Z.zMangleStr = map fixchar+ }++mkZPackage :: PackageId -> Z.ZPackage+mkZPackage (PackageIdentifier name ver) = Z.ZPackage+ { Z.zpkgName = name+ , Z.zpkgVersion = ver+ , Z.zpkgX = major1+ , Z.zpkgY = major2+ , Z.zpkgZ = minor+ }+ where+ (major1,major2,minor) = majorMinor ver++majorMinor :: Version -> (String, String, String)+majorMinor ver = case map show (versionNumbers ver) of+ [] -> ("0", "0", "0")+ [x] -> (x, "0", "0")+ [x,y] -> (x, y, "0")+ (x:y:z:_) -> (x, y, z)++fixchar :: Char -> Char+fixchar '-' = '_'+fixchar c = c
+ src/Distribution/Simple/Build/Macros/Z.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Simple.Build.Macros.Z (render, Z(..), ZPackage (..), ZTool (..)) where+import Distribution.ZinzaPrelude+data Z+ = Z {zPackages :: ([ZPackage]),+ zTools :: ([ZTool]),+ zPackageKey :: String,+ zComponentId :: String,+ zPackageVersion :: Version,+ zNotNull :: (String -> Bool),+ zManglePkgName :: (PackageName -> String),+ zMangleStr :: (String -> String)}+ deriving Generic+data ZPackage+ = ZPackage {zpkgName :: PackageName,+ zpkgVersion :: Version,+ zpkgX :: String,+ zpkgY :: String,+ zpkgZ :: String}+ deriving Generic+data ZTool+ = ZTool {ztoolName :: String,+ ztoolVersion :: Version,+ ztoolX :: String,+ ztoolY :: String,+ ztoolZ :: String}+ deriving Generic+render :: Z -> String+render z_root = execWriter $ do+ tell "/* DO NOT EDIT: This file is automatically generated by Cabal */\n"+ tell "\n"+ forM_ (zPackages z_root) $ \z_var0_pkg -> do+ tell "/* package "+ tell (prettyShow (zpkgName z_var0_pkg))+ tell "-"+ tell (prettyShow (zpkgVersion z_var0_pkg))+ tell " */\n"+ tell "#ifndef VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell "\n"+ tell "#define VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell " \""+ tell (prettyShow (zpkgVersion z_var0_pkg))+ tell "\"\n"+ tell "#endif /* VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell " */\n"+ tell "#ifndef MIN_VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell "\n"+ tell "#define MIN_VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell "(major1,major2,minor) (\\\n"+ tell " (major1) < "+ tell (zpkgX z_var0_pkg)+ tell " || \\\n"+ tell " (major1) == "+ tell (zpkgX z_var0_pkg)+ tell " && (major2) < "+ tell (zpkgY z_var0_pkg)+ tell " || \\\n"+ tell " (major1) == "+ tell (zpkgX z_var0_pkg)+ tell " && (major2) == "+ tell (zpkgY z_var0_pkg)+ tell " && (minor) <= "+ tell (zpkgZ z_var0_pkg)+ tell ")\n"+ tell "#endif /* MIN_VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell " */\n"+ tell "\n"+ forM_ (zTools z_root) $ \z_var1_tool -> do+ tell "/* tool "+ tell (ztoolName z_var1_tool)+ tell "-"+ tell (prettyShow (ztoolVersion z_var1_tool))+ tell " */\n"+ tell "#ifndef TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell "\n"+ tell "#define TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell " \""+ tell (prettyShow (ztoolVersion z_var1_tool))+ tell "\"\n"+ tell "#endif /* TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell " */\n"+ tell "#ifndef MIN_TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell "\n"+ tell "#define MIN_TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell "(major1,major2,minor) (\\\n"+ tell " (major1) < "+ tell (ztoolX z_var1_tool)+ tell " || \\\n"+ tell " (major1) == "+ tell (ztoolX z_var1_tool)+ tell " && (major2) < "+ tell (ztoolY z_var1_tool)+ tell " || \\\n"+ tell " (major1) == "+ tell (ztoolX z_var1_tool)+ tell " && (major2) == "+ tell (ztoolY z_var1_tool)+ tell " && (minor) <= "+ tell (ztoolZ z_var1_tool)+ tell ")\n"+ tell "#endif /* MIN_TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell " */\n"+ tell "\n"+ if (zNotNull z_root (zPackageKey z_root))+ then do+ tell "#ifndef CURRENT_PACKAGE_KEY\n"+ tell "#define CURRENT_PACKAGE_KEY \""+ tell (zPackageKey z_root)+ tell "\"\n"+ tell "#endif /* CURRENT_packageKey */\n"+ return ()+ else do+ return ()+ if (zNotNull z_root (zComponentId z_root))+ then do+ tell "#ifndef CURRENT_COMPONENT_ID\n"+ tell "#define CURRENT_COMPONENT_ID \""+ tell (zComponentId z_root)+ tell "\"\n"+ tell "#endif /* CURRENT_COMPONENT_ID */\n"+ return ()+ else do+ return ()+ tell "#ifndef CURRENT_PACKAGE_VERSION\n"+ tell "#define CURRENT_PACKAGE_VERSION \""+ tell (prettyShow (zPackageVersion z_root))+ tell "\"\n"+ tell "#endif /* CURRENT_PACKAGE_VERSION */\n"
+ src/Distribution/Simple/Build/PathsModule.hs view
@@ -0,0 +1,165 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Build.Macros+-- Copyright : Isaac Jones 2003-2005,+-- Ross Paterson 2006,+-- Duncan Coutts 2007-2008+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Generating the Paths_pkgname module.+--+-- This is a module that Cabal generates for the benefit of packages. It+-- enables them to find their version number and find any installed data files+-- at runtime. This code should probably be split off into another module.+--+module Distribution.Simple.Build.PathsModule (+ generatePathsModule, pkgPathEnvVar+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Package+import Distribution.PackageDescription+import Distribution.Simple.Compiler+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.Utils (shortRelativePath)+import Distribution.System+import Distribution.Version++import qualified Distribution.Simple.Build.PathsModule.Z as Z++-- ------------------------------------------------------------+-- * Building Paths_<pkg>.hs+-- ------------------------------------------------------------++generatePathsModule :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> String+generatePathsModule pkg_descr lbi clbi = Z.render Z.Z+ { Z.zPackageName = packageName pkg_descr+ , Z.zVersionDigits = show $ versionNumbers $ packageVersion pkg_descr+ , Z.zSupportsCpp = supports_cpp+ , Z.zSupportsNoRebindableSyntax = supports_rebindable_syntax+ , Z.zSupportsNoMissingSafeHaskellMode = supports_missing_safehaskell+ , Z.zAbsolute = absolute+ , Z.zRelocatable = relocatable lbi+ , Z.zIsWindows = isWindows+ , Z.zIsI386 = buildArch == I386+ , Z.zIsX8664 = buildArch == X86_64+ , Z.zNot = not+ , Z.zManglePkgName = showPkgName++ , Z.zPrefix = show flat_prefix+ , Z.zBindir = zBindir+ , Z.zLibdir = zLibdir+ , Z.zDynlibdir = zDynlibdir+ , Z.zDatadir = zDatadir+ , Z.zLibexecdir = zLibexecdir+ , Z.zSysconfdir = zSysconfdir+ }+ where+ supports_cpp = supports_language_pragma+ supports_rebindable_syntax = ghc_newer_than (mkVersion [7,0,1])+ supports_language_pragma = ghc_newer_than (mkVersion [6,6,1])+ supports_missing_safehaskell = ghc_newer_than (mkVersion [8,10,1])++ ghc_newer_than minVersion =+ case compilerCompatVersion GHC (compiler lbi) of+ Nothing -> False+ Just version -> version `withinRange` orLaterVersion minVersion++ -- In several cases we cannot make relocatable installations+ absolute =+ hasLibs pkg_descr -- we can only make progs relocatable+ || isNothing flat_bindirrel -- if the bin dir is an absolute path+ || not (supportsRelocatableProgs (compilerFlavor (compiler lbi)))++ -- TODO: Here, and with zIsI386 & zIs8664 we should use TARGET platform+ isWindows = case buildOS of+ Windows -> True+ _ -> False++ supportsRelocatableProgs GHC = isWindows+ supportsRelocatableProgs GHCJS = isWindows+ supportsRelocatableProgs _ = False++ cid = componentUnitId clbi++ InstallDirs+ { bindir = flat_bindir+ , libdir = flat_libdir+ , dynlibdir = flat_dynlibdir+ , datadir = flat_datadir+ , libexecdir = flat_libexecdir+ , sysconfdir = flat_sysconfdir+ , prefix = flat_prefix+ } = absoluteInstallCommandDirs pkg_descr lbi cid NoCopyDest++ InstallDirs+ { bindir = flat_bindirrel+ , libdir = flat_libdirrel+ , dynlibdir = flat_dynlibdirrel+ , datadir = flat_datadirrel+ , libexecdir = flat_libexecdirrel+ , sysconfdir = flat_sysconfdirrel+ } = prefixRelativeComponentInstallDirs (packageId pkg_descr) lbi cid++ zBindir, zLibdir, zDynlibdir, zDatadir, zLibexecdir, zSysconfdir :: String+ (zBindir, zLibdir, zDynlibdir, zDatadir, zLibexecdir, zSysconfdir)+ | relocatable lbi =+ ( show flat_bindir_reloc+ , show flat_libdir_reloc+ , show flat_dynlibdir_reloc+ , show flat_datadir_reloc+ , show flat_libexecdir_reloc+ , show flat_sysconfdir_reloc+ )+ | absolute =+ ( show flat_bindir+ , show flat_libdir+ , show flat_dynlibdir+ , show flat_datadir+ , show flat_libexecdir+ , show flat_sysconfdir+ )+ | isWindows =+ ( "maybe (error \"PathsModule.generate\") id (" ++ show flat_bindirrel ++ ")"+ , mkGetDir flat_libdir flat_libdirrel+ , mkGetDir flat_dynlibdir flat_dynlibdirrel+ , mkGetDir flat_datadir flat_datadirrel+ , mkGetDir flat_libexecdir flat_libexecdirrel+ , mkGetDir flat_sysconfdir flat_sysconfdirrel+ )+ | otherwise =+ error "panic! generatePathsModule: should never happen"++ mkGetDir :: FilePath -> Maybe FilePath -> String+ mkGetDir _ (Just dirrel) = "getPrefixDirRel " ++ show dirrel+ mkGetDir dir Nothing = "return " ++ show dir++ flat_bindir_reloc = shortRelativePath flat_prefix flat_bindir+ flat_libdir_reloc = shortRelativePath flat_prefix flat_libdir+ flat_dynlibdir_reloc = shortRelativePath flat_prefix flat_dynlibdir+ flat_datadir_reloc = shortRelativePath flat_prefix flat_datadir+ flat_libexecdir_reloc = shortRelativePath flat_prefix flat_libexecdir+ flat_sysconfdir_reloc = shortRelativePath flat_prefix flat_sysconfdir++-- | Generates the name of the environment variable controlling the path+-- component of interest.+--+-- Note: The format of these strings is part of Cabal's public API;+-- changing this function constitutes a *backwards-compatibility* break.+pkgPathEnvVar+ :: PackageDescription+ -> String -- ^ path component; one of \"bindir\", \"libdir\", -- \"datadir\", \"libexecdir\", or \"sysconfdir\"+ -> String -- ^ environment variable name+pkgPathEnvVar pkg_descr var =+ showPkgName (packageName pkg_descr) ++ "_" ++ var++showPkgName :: PackageName -> String+showPkgName = map fixchar . unPackageName++fixchar :: Char -> Char+fixchar '-' = '_'+fixchar c = c
+ src/Distribution/Simple/Build/PathsModule/Z.hs view
@@ -0,0 +1,323 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Simple.Build.PathsModule.Z (render, Z(..)) where+import Distribution.ZinzaPrelude+data Z+ = Z {zPackageName :: PackageName,+ zVersionDigits :: String,+ zSupportsCpp :: Bool,+ zSupportsNoRebindableSyntax :: Bool,+ zSupportsNoMissingSafeHaskellMode :: Bool,+ zAbsolute :: Bool,+ zRelocatable :: Bool,+ zIsWindows :: Bool,+ zIsI386 :: Bool,+ zIsX8664 :: Bool,+ zPrefix :: FilePath,+ zBindir :: FilePath,+ zLibdir :: FilePath,+ zDynlibdir :: FilePath,+ zDatadir :: FilePath,+ zLibexecdir :: FilePath,+ zSysconfdir :: FilePath,+ zNot :: (Bool -> Bool),+ zManglePkgName :: (PackageName -> String)}+ deriving Generic+render :: Z -> String+render z_root = execWriter $ do+ if (zSupportsCpp z_root)+ then do+ tell "{-# LANGUAGE CPP #-}\n"+ return ()+ else do+ return ()+ if (zSupportsNoRebindableSyntax z_root)+ then do+ tell "{-# LANGUAGE NoRebindableSyntax #-}\n"+ return ()+ else do+ return ()+ if (zNot z_root (zAbsolute z_root))+ then do+ tell "{-# LANGUAGE ForeignFunctionInterface #-}\n"+ return ()+ else do+ return ()+ tell "{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}\n"+ if (zSupportsNoMissingSafeHaskellMode z_root)+ then do+ tell "{-# OPTIONS_GHC -Wno-missing-safe-haskell-mode #-}\n"+ return ()+ else do+ return ()+ tell "module Paths_"+ tell (zManglePkgName z_root (zPackageName z_root))+ tell " (\n"+ tell " version,\n"+ tell " getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,\n"+ tell " getDataFileName, getSysconfDir\n"+ tell " ) where\n"+ tell "\n"+ if (zNot z_root (zAbsolute z_root))+ then do+ tell "import Foreign\n"+ tell "import Foreign.C\n"+ return ()+ else do+ return ()+ tell "\n"+ tell "import qualified Control.Exception as Exception\n"+ tell "import Data.Version (Version(..))\n"+ tell "import System.Environment (getEnv)\n"+ tell "import Prelude\n"+ tell "\n"+ if (zRelocatable z_root)+ then do+ tell "import System.Environment (getExecutablePath)\n"+ return ()+ else do+ return ()+ tell "\n"+ if (zSupportsCpp z_root)+ then do+ tell "#if defined(VERSION_base)\n"+ tell "\n"+ tell "#if MIN_VERSION_base(4,0,0)\n"+ tell "catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a\n"+ tell "#else\n"+ tell "catchIO :: IO a -> (Exception.Exception -> IO a) -> IO a\n"+ tell "#endif\n"+ tell "\n"+ tell "#else\n"+ tell "catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a\n"+ tell "#endif\n"+ tell "catchIO = Exception.catch\n"+ return ()+ else do+ tell "catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a\n"+ tell "catchIO = Exception.catch\n"+ return ()+ tell "\n"+ tell "version :: Version\n"+ tell "version = Version "+ tell (zVersionDigits z_root)+ tell " []\n"+ tell "\n"+ tell "getDataFileName :: FilePath -> IO FilePath\n"+ tell "getDataFileName name = do\n"+ tell " dir <- getDataDir\n"+ tell " return (dir `joinFileName` name)\n"+ tell "\n"+ tell "getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"+ tell "\n"+ tell "\n"+ if (zRelocatable z_root)+ then do+ tell "\n"+ tell "getPrefixDirReloc :: FilePath -> IO FilePath\n"+ tell "getPrefixDirReloc dirRel = do\n"+ tell " exePath <- getExecutablePath\n"+ tell " let (dir,_) = splitFileName exePath\n"+ tell " return ((dir `minusFileName` "+ tell (zBindir z_root)+ tell ") `joinFileName` dirRel)\n"+ tell "\n"+ tell "getBinDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_bindir\") (\\_ -> getPrefixDirReloc $ "+ tell (zBindir z_root)+ tell ")\n"+ tell "getLibDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_libdir\") (\\_ -> getPrefixDirReloc $ "+ tell (zLibdir z_root)+ tell ")\n"+ tell "getDynLibDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_dynlibdir\") (\\_ -> getPrefixDirReloc $ "+ tell (zDynlibdir z_root)+ tell ")\n"+ tell "getDataDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_datadir\") (\\_ -> getPrefixDirReloc $ "+ tell (zDatadir z_root)+ tell ")\n"+ tell "getLibexecDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_libexecdir\") (\\_ -> getPrefixDirReloc $ "+ tell (zLibexecdir z_root)+ tell ")\n"+ tell "getSysconfDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_sysconfdir\") (\\_ -> getPrefixDirReloc $ "+ tell (zSysconfdir z_root)+ tell ")\n"+ tell "\n"+ return ()+ else do+ if (zAbsolute z_root)+ then do+ tell "\n"+ tell "bindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath\n"+ tell "bindir = "+ tell (zBindir z_root)+ tell "\n"+ tell "libdir = "+ tell (zLibdir z_root)+ tell "\n"+ tell "dynlibdir = "+ tell (zDynlibdir z_root)+ tell "\n"+ tell "datadir = "+ tell (zDatadir z_root)+ tell "\n"+ tell "libexecdir = "+ tell (zLibexecdir z_root)+ tell "\n"+ tell "sysconfdir = "+ tell (zSysconfdir z_root)+ tell "\n"+ tell "\n"+ tell "getBinDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_bindir\") (\\_ -> return bindir)\n"+ tell "getLibDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_libdir\") (\\_ -> return libdir)\n"+ tell "getDynLibDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_dynlibdir\") (\\_ -> return dynlibdir)\n"+ tell "getDataDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_datadir\") (\\_ -> return datadir)\n"+ tell "getLibexecDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_libexecdir\") (\\_ -> return libexecdir)\n"+ tell "getSysconfDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_sysconfdir\") (\\_ -> return sysconfdir)\n"+ tell "\n"+ return ()+ else do+ if (zIsWindows z_root)+ then do+ tell "\n"+ tell "prefix :: FilePath\n"+ tell "prefix = "+ tell (zPrefix z_root)+ tell "\n"+ tell "\n"+ tell "getBinDir = getPrefixDirRel $ "+ tell (zBindir z_root)+ tell "\n"+ tell "getLibDir = "+ tell (zLibdir z_root)+ tell "\n"+ tell "getDynLibDir = "+ tell (zDynlibdir z_root)+ tell "\n"+ tell "getDataDir = catchIO (getEnv \""+ tell (zManglePkgName z_root (zPackageName z_root))+ tell "_datadir\") (\\_ -> "+ tell (zDatadir z_root)+ tell ")\n"+ tell "getLibexecDir = "+ tell (zLibexecdir z_root)+ tell "\n"+ tell "getSysconfDir = "+ tell (zSysconfdir z_root)+ tell "\n"+ tell "\n"+ tell "getPrefixDirRel :: FilePath -> IO FilePath\n"+ tell "getPrefixDirRel dirRel = try_size 2048 -- plenty, PATH_MAX is 512 under Win32.\n"+ tell " where\n"+ tell " try_size size = allocaArray (fromIntegral size) $ \\buf -> do\n"+ tell " ret <- c_GetModuleFileName nullPtr buf size\n"+ tell " case ret of\n"+ tell " 0 -> return (prefix `joinFileName` dirRel)\n"+ tell " _ | ret < size -> do\n"+ tell " exePath <- peekCWString buf\n"+ tell " let (bindir,_) = splitFileName exePath\n"+ tell " return ((bindir `minusFileName` "+ tell (zBindir z_root)+ tell ") `joinFileName` dirRel)\n"+ tell " | otherwise -> try_size (size * 2)\n"+ tell "\n"+ if (zIsI386 z_root)+ then do+ tell "foreign import stdcall unsafe \"windows.h GetModuleFileNameW\"\n"+ tell " c_GetModuleFileName :: Ptr () -> CWString -> Int32 -> IO Int32\n"+ return ()+ else do+ if (zIsX8664 z_root)+ then do+ tell "foreign import ccall unsafe \"windows.h GetModuleFileNameW\"\n"+ tell " c_GetModuleFileName :: Ptr () -> CWString -> Int32 -> IO Int32\n"+ return ()+ else do+ tell "-- win32 supported only with I386, X86_64\n"+ tell "c_GetModuleFileName :: Ptr () -> CWString -> Int32 -> IO Int32\n"+ tell "c_GetModuleFileName = _\n"+ return ()+ return ()+ tell "\n"+ return ()+ else do+ tell "\n"+ tell "notRelocAbsoluteOrWindows :: ()\n"+ tell "notRelocAbsoluteOrWindows = _\n"+ tell "\n"+ return ()+ return ()+ return ()+ tell "\n"+ tell "\n"+ if (zNot z_root (zAbsolute z_root))+ then do+ tell "minusFileName :: FilePath -> String -> FilePath\n"+ tell "minusFileName dir \"\" = dir\n"+ tell "minusFileName dir \".\" = dir\n"+ tell "minusFileName dir suffix =\n"+ tell " minusFileName (fst (splitFileName dir)) (fst (splitFileName suffix))\n"+ tell "\n"+ tell "splitFileName :: FilePath -> (String, String)\n"+ tell "splitFileName p = (reverse (path2++drive), reverse fname)\n"+ tell " where\n"+ tell " (path,drive) = case p of\n"+ tell " (c:':':p') -> (reverse p',[':',c])\n"+ tell " _ -> (reverse p ,\"\")\n"+ tell " (fname,path1) = break isPathSeparator path\n"+ tell " path2 = case path1 of\n"+ tell " [] -> \".\"\n"+ tell " [_] -> path1 -- don't remove the trailing slash if\n"+ tell " -- there is only one character\n"+ tell " (c:path') | isPathSeparator c -> path'\n"+ tell " _ -> path1\n"+ return ()+ else do+ return ()+ tell "\n"+ tell "joinFileName :: String -> String -> FilePath\n"+ tell "joinFileName \"\" fname = fname\n"+ tell "joinFileName \".\" fname = fname\n"+ tell "joinFileName dir \"\" = dir\n"+ tell "joinFileName dir fname\n"+ tell " | isPathSeparator (last dir) = dir ++ fname\n"+ tell " | otherwise = dir ++ pathSeparator : fname\n"+ tell "\n"+ tell "pathSeparator :: Char\n"+ if (zIsWindows z_root)+ then do+ tell "pathSeparator = '\\\\'\n"+ return ()+ else do+ tell "pathSeparator = '/'\n"+ return ()+ tell "\n"+ tell "isPathSeparator :: Char -> Bool\n"+ if (zIsWindows z_root)+ then do+ tell "isPathSeparator c = c == '/' || c == '\\\\'\n"+ return ()+ else do+ tell "isPathSeparator c = c == '/'\n"+ return ()
+ src/Distribution/Simple/BuildPaths.hs view
@@ -0,0 +1,257 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.BuildPaths+-- Copyright : Isaac Jones 2003-2004,+-- Duncan Coutts 2008+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- A bunch of dirs, paths and file names used for intermediate build steps.+--++module Distribution.Simple.BuildPaths (+ defaultDistPref, srcPref,+ haddockDirName, hscolourPref, haddockPref,+ autogenPackageModulesDir,+ autogenComponentModulesDir,++ autogenPathsModuleName,+ cppHeaderName,+ haddockName,++ mkGenericStaticLibName,+ mkLibName,+ mkProfLibName,+ mkGenericSharedLibName,+ mkSharedLibName,+ mkStaticLibName,+ mkGenericSharedBundledLibName,++ exeExtension,+ objExtension,+ dllExtension,+ staticLibExtension,+ -- * Source files & build directories+ getSourceFiles, getLibSourceFiles, getExeSourceFiles,+ getFLibSourceFiles, exeBuildDir, flibBuildDir,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Package+import Distribution.ModuleName as ModuleName+import Distribution.Compiler+import Distribution.PackageDescription+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.Setup+import Distribution.Pretty+import Distribution.System+import Distribution.Verbosity+import Distribution.Simple.Utils+import Distribution.Utils.Path++import Data.List (stripPrefix)+import System.FilePath ((</>), (<.>), normalise)++-- ---------------------------------------------------------------------------+-- Build directories and files++srcPref :: FilePath -> FilePath+srcPref distPref = distPref </> "src"++hscolourPref :: HaddockTarget -> FilePath -> PackageDescription -> FilePath+hscolourPref = haddockPref++-- | This is the name of the directory in which the generated haddocks+-- should be stored. It does not include the @<dist>/doc/html@ prefix.+haddockDirName :: HaddockTarget -> PackageDescription -> FilePath+haddockDirName ForDevelopment = prettyShow . packageName+haddockDirName ForHackage = (++ "-docs") . prettyShow . packageId++-- | The directory to which generated haddock documentation should be written.+haddockPref :: HaddockTarget -> FilePath -> PackageDescription -> FilePath+haddockPref haddockTarget distPref pkg_descr+ = distPref </> "doc" </> "html" </> haddockDirName haddockTarget pkg_descr++-- | The directory in which we put auto-generated modules for EVERY+-- component in the package.+autogenPackageModulesDir :: LocalBuildInfo -> String+autogenPackageModulesDir lbi = buildDir lbi </> "global-autogen"++-- | The directory in which we put auto-generated modules for a+-- particular component.+autogenComponentModulesDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> String+autogenComponentModulesDir lbi clbi = componentBuildDir lbi clbi </> "autogen"+-- NB: Look at 'checkForeignDeps' for where a simplified version of this+-- has been copy-pasted.++cppHeaderName :: String+cppHeaderName = "cabal_macros.h"++-- | The name of the auto-generated Paths_* module associated with a package+autogenPathsModuleName :: PackageDescription -> ModuleName+autogenPathsModuleName pkg_descr =+ ModuleName.fromString $+ "Paths_" ++ map fixchar (prettyShow (packageName pkg_descr))+ where fixchar '-' = '_'+ fixchar c = c++haddockName :: PackageDescription -> FilePath+haddockName pkg_descr = prettyShow (packageName pkg_descr) <.> "haddock"++-- -----------------------------------------------------------------------------+-- Source File helper++getLibSourceFiles :: Verbosity+ -> LocalBuildInfo+ -> Library+ -> ComponentLocalBuildInfo+ -> IO [(ModuleName.ModuleName, FilePath)]+getLibSourceFiles verbosity lbi lib clbi = getSourceFiles verbosity searchpaths modules+ where+ bi = libBuildInfo lib+ modules = allLibModules lib clbi+ searchpaths = componentBuildDir lbi clbi : map getSymbolicPath (hsSourceDirs bi) +++ [ autogenComponentModulesDir lbi clbi+ , autogenPackageModulesDir lbi ]++getExeSourceFiles :: Verbosity+ -> LocalBuildInfo+ -> Executable+ -> ComponentLocalBuildInfo+ -> IO [(ModuleName.ModuleName, FilePath)]+getExeSourceFiles verbosity lbi exe clbi = do+ moduleFiles <- getSourceFiles verbosity searchpaths modules+ srcMainPath <- findFileEx verbosity (map getSymbolicPath $ hsSourceDirs bi) (modulePath exe)+ return ((ModuleName.main, srcMainPath) : moduleFiles)+ where+ bi = buildInfo exe+ modules = otherModules bi+ searchpaths = autogenComponentModulesDir lbi clbi+ : autogenPackageModulesDir lbi+ : exeBuildDir lbi exe : map getSymbolicPath (hsSourceDirs bi)++getFLibSourceFiles :: Verbosity+ -> LocalBuildInfo+ -> ForeignLib+ -> ComponentLocalBuildInfo+ -> IO [(ModuleName.ModuleName, FilePath)]+getFLibSourceFiles verbosity lbi flib clbi = getSourceFiles verbosity searchpaths modules+ where+ bi = foreignLibBuildInfo flib+ modules = otherModules bi+ searchpaths = autogenComponentModulesDir lbi clbi+ : autogenPackageModulesDir lbi+ : flibBuildDir lbi flib : map getSymbolicPath (hsSourceDirs bi)++getSourceFiles :: Verbosity -> [FilePath]+ -> [ModuleName.ModuleName]+ -> IO [(ModuleName.ModuleName, FilePath)]+getSourceFiles verbosity dirs modules = flip traverse modules $ \m -> fmap ((,) m) $+ findFileWithExtension ["hs", "lhs", "hsig", "lhsig"] dirs (ModuleName.toFilePath m)+ >>= maybe (notFound m) (return . normalise)+ where+ notFound module_ = die' verbosity $ "can't find source for module " ++ prettyShow module_++-- | The directory where we put build results for an executable+exeBuildDir :: LocalBuildInfo -> Executable -> FilePath+exeBuildDir lbi exe = buildDir lbi </> nm </> nm ++ "-tmp"+ where+ nm = unUnqualComponentName $ exeName exe++-- | The directory where we put build results for a foreign library+flibBuildDir :: LocalBuildInfo -> ForeignLib -> FilePath+flibBuildDir lbi flib = buildDir lbi </> nm </> nm ++ "-tmp"+ where+ nm = unUnqualComponentName $ foreignLibName flib++-- ---------------------------------------------------------------------------+-- Library file names++-- | Create a library name for a static library from a given name.+-- Prepends @lib@ and appends the static library extension (@.a@).+mkGenericStaticLibName :: String -> String+mkGenericStaticLibName lib = "lib" ++ lib <.> "a"++mkLibName :: UnitId -> String+mkLibName lib = mkGenericStaticLibName (getHSLibraryName lib)++mkProfLibName :: UnitId -> String+mkProfLibName lib = mkGenericStaticLibName (getHSLibraryName lib ++ "_p")++-- | Create a library name for a shared library from a given name.+-- Prepends @lib@ and appends the @-\<compilerFlavour\>\<compilerVersion\>@+-- as well as the shared library extension.+mkGenericSharedLibName :: Platform -> CompilerId -> String -> String+mkGenericSharedLibName platform (CompilerId compilerFlavor compilerVersion) lib+ = mconcat [ "lib", lib, "-", comp <.> dllExtension platform ]+ where comp = prettyShow compilerFlavor ++ prettyShow compilerVersion++-- Implement proper name mangling for dynamical shared objects+-- @libHS\<packagename\>-\<compilerFlavour\>\<compilerVersion\>@+-- e.g. @libHSbase-2.1-ghc6.6.1.so@+mkSharedLibName :: Platform -> CompilerId -> UnitId -> String+mkSharedLibName platform comp lib+ = mkGenericSharedLibName platform comp (getHSLibraryName lib)++-- Static libs are named the same as shared libraries, only with+-- a different extension.+mkStaticLibName :: Platform -> CompilerId -> UnitId -> String+mkStaticLibName platform (CompilerId compilerFlavor compilerVersion) lib+ = "lib" ++ getHSLibraryName lib ++ "-" ++ comp <.> staticLibExtension platform+ where comp = prettyShow compilerFlavor ++ prettyShow compilerVersion++-- | Create a library name for a bundled shared library from a given name.+-- This matches the naming convention for shared libraries as implemented in+-- GHC's packageHsLibs function in the Packages module.+-- If the given name is prefixed with HS, then this prepends 'lib' and appends+-- the compiler flavour/version and shared library extension e.g.:+-- "HSrts-1.0" -> "libHSrts-1.0-ghc8.7.20190109.so"+-- Otherwise the given name should be prefixed with 'C', then this strips the+-- 'C', prepends 'lib' and appends the shared library extension e.g.:+-- "Cffi" -> "libffi.so"+mkGenericSharedBundledLibName :: Platform -> CompilerId -> String -> String+mkGenericSharedBundledLibName platform comp lib+ | "HS" `isPrefixOf` lib+ = mkGenericSharedLibName platform comp lib+ | Just lib' <- stripPrefix "C" lib+ = "lib" ++ lib' <.> dllExtension platform+ | otherwise+ = error ("Don't understand library name " ++ lib)++-- ------------------------------------------------------------+-- * Platform file extensions+-- ------------------------------------------------------------++-- | Default extension for executable files on the current platform.+-- (typically @\"\"@ on Unix and @\"exe\"@ on Windows or OS\/2)+exeExtension :: Platform -> String+exeExtension (Platform _arch os) = case os of+ Windows -> "exe"+ _ -> ""++-- | Extension for object files. For GHC the extension is @\"o\"@.+objExtension :: String+objExtension = "o"++-- | Extension for dynamically linked (or shared) libraries+-- (typically @\"so\"@ on Unix and @\"dll\"@ on Windows)+dllExtension :: Platform -> String+dllExtension (Platform _arch os)= case os of+ Windows -> "dll"+ OSX -> "dylib"+ _ -> "so"++-- | Extension for static libraries+--+-- TODO: Here, as well as in dllExtension, it's really the target OS that we're+-- interested in, not the build OS.+staticLibExtension :: Platform -> String+staticLibExtension (Platform _arch os) = case os of+ Windows -> "lib"+ _ -> "a"
+ src/Distribution/Simple/BuildTarget.hs view
@@ -0,0 +1,1064 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Client.BuildTargets+-- Copyright : (c) Duncan Coutts 2012+-- License : BSD-like+--+-- Maintainer : duncan@community.haskell.org+--+-- Handling for user-specified build targets+-----------------------------------------------------------------------------+module Distribution.Simple.BuildTarget (+ -- * Main interface+ readTargetInfos,+ readBuildTargets, -- in case you don't have LocalBuildInfo++ -- * Build targets+ BuildTarget(..),+ showBuildTarget,+ QualLevel(..),+ buildTargetComponentName,++ -- * Parsing user build targets+ UserBuildTarget,+ readUserBuildTargets,+ showUserBuildTarget,+ UserBuildTargetProblem(..),+ reportUserBuildTargetProblems,++ -- * Resolving build targets+ resolveBuildTargets,+ BuildTargetProblem(..),+ reportBuildTargetProblems,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.TargetInfo+import Distribution.Types.LocalBuildInfo+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.ForeignLib+import Distribution.Types.UnqualComponentName++import Distribution.Package+import Distribution.PackageDescription+import Distribution.ModuleName+import Distribution.Simple.LocalBuildInfo+import Distribution.Pretty+import Distribution.Parsec+import Distribution.Simple.Utils+import Distribution.Verbosity+import Distribution.Utils.Path++import qualified Distribution.Compat.CharParsing as P++import Control.Monad ( msum )+import Data.List ( stripPrefix, groupBy )+import qualified Data.List.NonEmpty as NE+import System.FilePath as FilePath+ ( dropExtension, normalise, splitDirectories, joinPath, splitPath+ , hasTrailingPathSeparator )+import System.Directory ( doesFileExist, doesDirectoryExist )+import qualified Data.Map as Map++-- | Take a list of 'String' build targets, and parse and validate them+-- into actual 'TargetInfo's to be built/registered/whatever.+readTargetInfos :: Verbosity -> PackageDescription -> LocalBuildInfo -> [String] -> IO [TargetInfo]+readTargetInfos verbosity pkg_descr lbi args = do+ build_targets <- readBuildTargets verbosity pkg_descr args+ checkBuildTargets verbosity pkg_descr lbi build_targets++-- ------------------------------------------------------------+-- * User build targets+-- ------------------------------------------------------------++-- | Various ways that a user may specify a build target.+--+data UserBuildTarget =++ -- | A target specified by a single name. This could be a component+ -- module or file.+ --+ -- > cabal build foo+ -- > cabal build Data.Foo+ -- > cabal build Data/Foo.hs Data/Foo.hsc+ --+ UserBuildTargetSingle String++ -- | A target specified by a qualifier and name. This could be a component+ -- name qualified by the component namespace kind, or a module or file+ -- qualified by the component name.+ --+ -- > cabal build lib:foo exe:foo+ -- > cabal build foo:Data.Foo+ -- > cabal build foo:Data/Foo.hs+ --+ | UserBuildTargetDouble String String++ -- | A fully qualified target, either a module or file qualified by a+ -- component name with the component namespace kind.+ --+ -- > cabal build lib:foo:Data/Foo.hs exe:foo:Data/Foo.hs+ -- > cabal build lib:foo:Data.Foo exe:foo:Data.Foo+ --+ | UserBuildTargetTriple String String String+ deriving (Show, Eq, Ord)+++-- ------------------------------------------------------------+-- * Resolved build targets+-- ------------------------------------------------------------++-- | A fully resolved build target.+--+data BuildTarget =++ -- | A specific component+ --+ BuildTargetComponent ComponentName++ -- | A specific module within a specific component.+ --+ | BuildTargetModule ComponentName ModuleName++ -- | A specific file within a specific component.+ --+ | BuildTargetFile ComponentName FilePath+ deriving (Eq, Show, Generic)++instance Binary BuildTarget++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 :: Verbosity -> PackageDescription -> [String] -> IO [BuildTarget]+readBuildTargets verbosity pkg targetStrs = do+ let (uproblems, utargets) = readUserBuildTargets targetStrs+ reportUserBuildTargetProblems verbosity uproblems++ utargets' <- traverse checkTargetExistsAsFile utargets++ let (bproblems, btargets) = resolveBuildTargets pkg utargets'+ reportBuildTargetProblems verbosity bproblems++ return btargets++checkTargetExistsAsFile :: UserBuildTarget -> IO (UserBuildTarget, Bool)+checkTargetExistsAsFile t = do+ fexists <- existsAsFile (fileComponentOfTarget t)+ return (t, fexists)++ where+ existsAsFile f = do+ exists <- doesFileExist f+ case splitPath f of+ (d:_) | hasTrailingPathSeparator d -> doesDirectoryExist d+ (d:_:_) | not exists -> doesDirectoryExist d+ _ -> return exists++ fileComponentOfTarget (UserBuildTargetSingle s1) = s1+ fileComponentOfTarget (UserBuildTargetDouble _ s2) = s2+ fileComponentOfTarget (UserBuildTargetTriple _ _ s3) = s3+++-- ------------------------------------------------------------+-- * Parsing user targets+-- ------------------------------------------------------------++readUserBuildTargets :: [String] -> ([UserBuildTargetProblem]+ ,[UserBuildTarget])+readUserBuildTargets = partitionEithers . map readUserBuildTarget++-- |+--+-- >>> readUserBuildTarget "comp"+-- Right (UserBuildTargetSingle "comp")+--+-- >>> readUserBuildTarget "lib:comp"+-- Right (UserBuildTargetDouble "lib" "comp")+--+-- >>> readUserBuildTarget "pkg:lib:comp"+-- Right (UserBuildTargetTriple "pkg" "lib" "comp")+--+-- >>> readUserBuildTarget "\"comp\""+-- Right (UserBuildTargetSingle "comp")+--+-- >>> readUserBuildTarget "lib:\"comp\""+-- Right (UserBuildTargetDouble "lib" "comp")+--+-- >>> readUserBuildTarget "pkg:lib:\"comp\""+-- Right (UserBuildTargetTriple "pkg" "lib" "comp")+--+-- >>> readUserBuildTarget "pkg:lib:comp:more"+-- Left (UserBuildTargetUnrecognised "pkg:lib:comp:more")+--+-- >>> readUserBuildTarget "pkg:\"lib\":comp"+-- Left (UserBuildTargetUnrecognised "pkg:\"lib\":comp")+--+readUserBuildTarget :: String -> Either UserBuildTargetProblem+ UserBuildTarget+readUserBuildTarget targetstr =+ case explicitEitherParsec parseTargetApprox targetstr of+ Left _ -> Left (UserBuildTargetUnrecognised targetstr)+ Right tgt -> Right tgt++ where+ parseTargetApprox :: CabalParsing m => m UserBuildTarget+ parseTargetApprox = do+ -- read one, two, or three tokens, where last could be "hs-string"+ ts <- tokens+ return $ case ts of+ (a, Nothing) -> UserBuildTargetSingle a+ (a, Just (b, Nothing)) -> UserBuildTargetDouble a b+ (a, Just (b, Just c)) -> UserBuildTargetTriple a b c++ tokens :: CabalParsing m => m (String, Maybe (String, Maybe String))+ tokens = (\s -> (s, Nothing)) <$> parsecHaskellString+ <|> (,) <$> token <*> P.optional (P.char ':' *> tokens2)++ tokens2 :: CabalParsing m => m (String, Maybe String)+ tokens2 = (\s -> (s, Nothing)) <$> parsecHaskellString+ <|> (,) <$> token <*> P.optional (P.char ':' *> (parsecHaskellString <|> token))++ token :: CabalParsing m => m String+ token = P.munch1 (\x -> not (isSpace x) && x /= ':')++data UserBuildTargetProblem+ = UserBuildTargetUnrecognised String+ deriving Show++reportUserBuildTargetProblems :: Verbosity -> [UserBuildTargetProblem] -> IO ()+reportUserBuildTargetProblems verbosity problems = do+ case [ target | UserBuildTargetUnrecognised target <- problems ] of+ [] -> return ()+ target ->+ die' verbosity $ unlines+ [ "Unrecognised build target '" ++ name ++ "'."+ | name <- target ]+ ++ "Examples:\n"+ ++ " - build foo -- component name "+ ++ "(library, executable, test-suite or benchmark)\n"+ ++ " - build Data.Foo -- module name\n"+ ++ " - build Data/Foo.hsc -- file name\n"+ ++ " - build lib:foo exe:foo -- component qualified by kind\n"+ ++ " - build foo:Data.Foo -- module qualified by component\n"+ ++ " - build foo:Data/Foo.hsc -- file qualified by component"++showUserBuildTarget :: UserBuildTarget -> String+showUserBuildTarget = intercalate ":" . getComponents+ where+ getComponents (UserBuildTargetSingle s1) = [s1]+ getComponents (UserBuildTargetDouble s1 s2) = [s1,s2]+ getComponents (UserBuildTargetTriple s1 s2 s3) = [s1,s2,s3]++-- | Unless you use 'QL1', this function is PARTIAL;+-- use 'showBuildTarget' instead.+showBuildTarget' :: QualLevel -> PackageId -> BuildTarget -> String+showBuildTarget' ql pkgid bt =+ showUserBuildTarget (renderBuildTarget ql bt pkgid)++-- | Unambiguously render a 'BuildTarget', so that it can+-- be parsed in all situations.+showBuildTarget :: PackageId -> BuildTarget -> String+showBuildTarget pkgid t =+ showBuildTarget' (qlBuildTarget t) pkgid t+ where+ qlBuildTarget BuildTargetComponent{} = QL2+ qlBuildTarget _ = QL3+++-- ------------------------------------------------------------+-- * Resolving user targets to build targets+-- ------------------------------------------------------------++{-+stargets =+ [ BuildTargetComponent (CExeName "foo")+ , BuildTargetModule (CExeName "foo") (mkMn "Foo")+ , BuildTargetModule (CExeName "tst") (mkMn "Foo")+ ]+ where+ mkMn :: String -> ModuleName+ mkMn = fromJust . simpleParse++ex_pkgid :: PackageIdentifier+Just ex_pkgid = simpleParse "thelib"+-}++-- | Given a bunch of user-specified targets, try to resolve what it is they+-- refer to.+--+resolveBuildTargets :: PackageDescription+ -> [(UserBuildTarget, Bool)]+ -> ([BuildTargetProblem], [BuildTarget])+resolveBuildTargets pkg = partitionEithers+ . map (uncurry (resolveBuildTarget pkg))++resolveBuildTarget :: PackageDescription -> UserBuildTarget -> Bool+ -> Either BuildTargetProblem BuildTarget+resolveBuildTarget pkg userTarget fexists =+ case findMatch (matchBuildTarget pkg userTarget fexists) of+ Unambiguous target -> Right target+ Ambiguous targets -> Left (BuildTargetAmbiguous userTarget targets')+ where targets' = disambiguateBuildTargets+ (packageId pkg)+ userTarget+ targets+ None errs -> Left (classifyMatchErrors errs)++ where+ classifyMatchErrors errs+ | Just expected' <- NE.nonEmpty expected+ = let (things, got:|_) = NE.unzip expected' in+ BuildTargetExpected userTarget (NE.toList things) got+ | not (null nosuch) = BuildTargetNoSuch userTarget nosuch+ | otherwise = error $ "resolveBuildTarget: internal error in matching"+ where+ expected = [ (thing, got) | MatchErrorExpected thing got <- errs ]+ nosuch = [ (thing, got) | MatchErrorNoSuch thing got <- errs ]+++data BuildTargetProblem+ = BuildTargetExpected UserBuildTarget [String] String+ -- ^ [expected thing] (actually got)+ | BuildTargetNoSuch UserBuildTarget [(String, String)]+ -- ^ [(no such thing, actually got)]+ | BuildTargetAmbiguous UserBuildTarget [(UserBuildTarget, BuildTarget)]+ deriving Show+++disambiguateBuildTargets :: PackageId -> UserBuildTarget -> [BuildTarget]+ -> [(UserBuildTarget, BuildTarget)]+disambiguateBuildTargets pkgid original =+ disambiguate (userTargetQualLevel original)+ where+ disambiguate ql ts+ | null amb = unamb+ | otherwise = unamb ++ disambiguate (succ ql) amb+ where+ (amb, unamb) = step ql ts++ userTargetQualLevel (UserBuildTargetSingle _ ) = QL1+ userTargetQualLevel (UserBuildTargetDouble _ _ ) = QL2+ userTargetQualLevel (UserBuildTargetTriple _ _ _) = QL3++ step :: QualLevel -> [BuildTarget]+ -> ([BuildTarget], [(UserBuildTarget, BuildTarget)])+ step ql = (\(amb, unamb) -> (map snd $ concat amb, concat unamb))+ . partition (\g -> length g > 1)+ . groupBy (equating fst)+ . sortBy (comparing fst)+ . map (\t -> (renderBuildTarget ql t pkgid, t))++data QualLevel = QL1 | QL2 | QL3+ deriving (Enum, Show)++renderBuildTarget :: QualLevel -> BuildTarget -> PackageId -> UserBuildTarget+renderBuildTarget ql target pkgid =+ case ql of+ QL1 -> UserBuildTargetSingle s1 where s1 = single target+ QL2 -> UserBuildTargetDouble s1 s2 where (s1, s2) = double target+ QL3 -> UserBuildTargetTriple s1 s2 s3 where (s1, s2, s3) = triple target++ where+ single (BuildTargetComponent cn ) = dispCName cn+ single (BuildTargetModule _ m) = prettyShow m+ single (BuildTargetFile _ f) = f++ double (BuildTargetComponent cn ) = (dispKind cn, dispCName cn)+ double (BuildTargetModule cn m) = (dispCName cn, prettyShow m)+ double (BuildTargetFile cn f) = (dispCName cn, f)++ triple (BuildTargetComponent _ ) = error "triple BuildTargetComponent"+ triple (BuildTargetModule cn m) = (dispKind cn, dispCName cn, prettyShow m)+ triple (BuildTargetFile cn f) = (dispKind cn, dispCName cn, f)++ dispCName = componentStringName pkgid+ dispKind = showComponentKindShort . componentKind++reportBuildTargetProblems :: Verbosity -> [BuildTargetProblem] -> IO ()+reportBuildTargetProblems verbosity problems = do++ case [ (t, e, g) | BuildTargetExpected t e g <- problems ] of+ [] -> return ()+ targets ->+ die' verbosity $ unlines+ [ "Unrecognised build target '" ++ showUserBuildTarget target+ ++ "'.\n"+ ++ "Expected a " ++ intercalate " or " expected+ ++ ", rather than '" ++ got ++ "'."+ | (target, expected, got) <- targets ]++ case [ (t, e) | BuildTargetNoSuch t e <- problems ] of+ [] -> return ()+ targets ->+ die' verbosity $ unlines+ [ "Unknown build target '" ++ showUserBuildTarget target+ ++ "'.\nThere is no "+ ++ intercalate " or " [ mungeThing thing ++ " '" ++ got ++ "'"+ | (thing, got) <- nosuch ] ++ "."+ | (target, nosuch) <- targets ]+ where+ mungeThing "file" = "file target"+ mungeThing thing = thing++ case [ (t, ts) | BuildTargetAmbiguous t ts <- problems ] of+ [] -> return ()+ targets ->+ die' verbosity $ unlines+ [ "Ambiguous build target '" ++ showUserBuildTarget target+ ++ "'. It could be:\n "+ ++ unlines [ " "++ showUserBuildTarget ut +++ " (" ++ showBuildTargetKind bt ++ ")"+ | (ut, bt) <- amb ]+ | (target, amb) <- targets ]++ where+ showBuildTargetKind (BuildTargetComponent _ ) = "component"+ showBuildTargetKind (BuildTargetModule _ _) = "module"+ showBuildTargetKind (BuildTargetFile _ _) = "file"+++----------------------------------+-- Top level BuildTarget matcher+--++matchBuildTarget :: PackageDescription+ -> UserBuildTarget -> Bool -> Match BuildTarget+matchBuildTarget pkg = \utarget fexists ->+ case utarget of+ UserBuildTargetSingle str1 ->+ matchBuildTarget1 cinfo str1 fexists++ UserBuildTargetDouble str1 str2 ->+ matchBuildTarget2 cinfo str1 str2 fexists++ UserBuildTargetTriple str1 str2 str3 ->+ matchBuildTarget3 cinfo str1 str2 str3 fexists+ where+ cinfo = pkgComponentInfo pkg++matchBuildTarget1 :: [ComponentInfo] -> String -> Bool -> Match BuildTarget+matchBuildTarget1 cinfo str1 fexists =+ matchComponent1 cinfo str1+ `matchPlusShadowing` matchModule1 cinfo str1+ `matchPlusShadowing` matchFile1 cinfo str1 fexists+++matchBuildTarget2 :: [ComponentInfo] -> String -> String -> Bool+ -> Match BuildTarget+matchBuildTarget2 cinfo str1 str2 fexists =+ matchComponent2 cinfo str1 str2+ `matchPlusShadowing` matchModule2 cinfo str1 str2+ `matchPlusShadowing` matchFile2 cinfo str1 str2 fexists+++matchBuildTarget3 :: [ComponentInfo] -> String -> String -> String -> Bool+ -> Match BuildTarget+matchBuildTarget3 cinfo str1 str2 str3 fexists =+ matchModule3 cinfo str1 str2 str3+ `matchPlusShadowing` matchFile3 cinfo str1 str2 str3 fexists+++data ComponentInfo = ComponentInfo {+ cinfoName :: ComponentName,+ cinfoStrName :: ComponentStringName,+ cinfoSrcDirs :: [FilePath],+ cinfoModules :: [ModuleName],+ cinfoHsFiles :: [FilePath], -- other hs files (like main.hs)+ cinfoAsmFiles:: [FilePath],+ cinfoCmmFiles:: [FilePath],+ cinfoCFiles :: [FilePath],+ cinfoCxxFiles:: [FilePath],+ cinfoJsFiles :: [FilePath]+ }++type ComponentStringName = String++pkgComponentInfo :: PackageDescription -> [ComponentInfo]+pkgComponentInfo pkg =+ [ ComponentInfo {+ cinfoName = componentName c,+ cinfoStrName = componentStringName pkg (componentName c),+ cinfoSrcDirs = map getSymbolicPath $ hsSourceDirs bi,+ cinfoModules = componentModules c,+ cinfoHsFiles = componentHsFiles c,+ cinfoAsmFiles= asmSources bi,+ cinfoCmmFiles= cmmSources bi,+ cinfoCFiles = cSources bi,+ cinfoCxxFiles= cxxSources bi,+ cinfoJsFiles = jsSources bi+ }+ | c <- pkgComponents pkg+ , let bi = componentBuildInfo c ]++componentStringName :: Package pkg => pkg -> ComponentName -> ComponentStringName+componentStringName pkg (CLibName LMainLibName ) = prettyShow (packageName pkg)+componentStringName _ (CLibName (LSubLibName name)) = unUnqualComponentName name+componentStringName _ (CFLibName name) = unUnqualComponentName name+componentStringName _ (CExeName name) = unUnqualComponentName name+componentStringName _ (CTestName name) = unUnqualComponentName name+componentStringName _ (CBenchName name) = unUnqualComponentName name++componentModules :: Component -> [ModuleName]+-- TODO: Use of 'explicitLibModules' here is a bit wrong:+-- a user could very well ask to build a specific signature+-- that was inherited from other packages. To fix this+-- we have to plumb 'LocalBuildInfo' through this code.+-- Fortunately, this is only used by 'pkgComponentInfo'+-- Please don't export this function unless you plan on fixing+-- this.+componentModules (CLib lib) = explicitLibModules lib+componentModules (CFLib flib) = foreignLibModules flib+componentModules (CExe exe) = exeModules exe+componentModules (CTest test) = testModules test+componentModules (CBench bench) = benchmarkModules bench++componentHsFiles :: Component -> [FilePath]+componentHsFiles (CExe exe) = [modulePath exe]+componentHsFiles (CTest TestSuite {+ testInterface = TestSuiteExeV10 _ mainfile+ }) = [mainfile]+componentHsFiles (CBench Benchmark {+ benchmarkInterface = BenchmarkExeV10 _ mainfile+ }) = [mainfile]+componentHsFiles _ = []++{-+ex_cs :: [ComponentInfo]+ex_cs =+ [ (mkC (CExeName "foo") ["src1", "src1/src2"] ["Foo", "Src2.Bar", "Bar"])+ , (mkC (CExeName "tst") ["src1", "test"] ["Foo"])+ ]+ where+ mkC n ds ms = ComponentInfo n (componentStringName pkgid n) ds (map mkMn ms)+ mkMn :: String -> ModuleName+ mkMn = fromJust . simpleParse+ pkgid :: PackageIdentifier+ Just pkgid = simpleParse "thelib"+-}++------------------------------+-- Matching component kinds+--++data ComponentKind = LibKind | FLibKind | ExeKind | TestKind | BenchKind+ deriving (Eq, Ord, Show, Enum, Bounded)++componentKind :: ComponentName -> ComponentKind+componentKind (CLibName _) = LibKind+componentKind (CFLibName _) = FLibKind+componentKind (CExeName _) = ExeKind+componentKind (CTestName _) = TestKind+componentKind (CBenchName _) = BenchKind++cinfoKind :: ComponentInfo -> ComponentKind+cinfoKind = componentKind . cinfoName++matchComponentKind :: String -> Match ComponentKind+matchComponentKind s+ | s `elem` ["lib", "library"] = return' LibKind+ | s `elem` ["flib", "foreign-lib", "foreign-library"] = return' FLibKind+ | s `elem` ["exe", "executable"] = return' ExeKind+ | s `elem` ["tst", "test", "test-suite"] = return' TestKind+ | s `elem` ["bench", "benchmark"] = return' BenchKind+ | otherwise = matchErrorExpected "component kind" s+ where+ return' ck = increaseConfidence >> return ck++showComponentKind :: ComponentKind -> String+showComponentKind LibKind = "library"+showComponentKind FLibKind = "foreign-library"+showComponentKind ExeKind = "executable"+showComponentKind TestKind = "test-suite"+showComponentKind BenchKind = "benchmark"++showComponentKindShort :: ComponentKind -> String+showComponentKindShort LibKind = "lib"+showComponentKindShort FLibKind = "flib"+showComponentKindShort ExeKind = "exe"+showComponentKindShort TestKind = "test"+showComponentKindShort BenchKind = "bench"++------------------------------+-- Matching component targets+--++matchComponent1 :: [ComponentInfo] -> String -> Match BuildTarget+matchComponent1 cs = \str1 -> do+ guardComponentName str1+ c <- matchComponentName cs str1+ return (BuildTargetComponent (cinfoName c))++matchComponent2 :: [ComponentInfo] -> String -> String -> Match BuildTarget+matchComponent2 cs = \str1 str2 -> do+ ckind <- matchComponentKind str1+ guardComponentName str2+ c <- matchComponentKindAndName cs ckind str2+ return (BuildTargetComponent (cinfoName c))++-- utils:++guardComponentName :: String -> Match ()+guardComponentName s+ | all validComponentChar s+ && not (null s) = increaseConfidence+ | otherwise = matchErrorExpected "component name" s+ where+ validComponentChar c = isAlphaNum c || c == '.'+ || c == '_' || c == '-' || c == '\''++matchComponentName :: [ComponentInfo] -> String -> Match ComponentInfo+matchComponentName cs str =+ orNoSuchThing "component" str+ $ increaseConfidenceFor+ $ matchInexactly caseFold+ [ (cinfoStrName c, c) | c <- cs ]+ str++matchComponentKindAndName :: [ComponentInfo] -> ComponentKind -> String+ -> Match ComponentInfo+matchComponentKindAndName cs ckind str =+ orNoSuchThing (showComponentKind ckind ++ " component") str+ $ increaseConfidenceFor+ $ matchInexactly (\(ck, cn) -> (ck, caseFold cn))+ [ ((cinfoKind c, cinfoStrName c), c) | c <- cs ]+ (ckind, str)+++------------------------------+-- Matching module targets+--++matchModule1 :: [ComponentInfo] -> String -> Match BuildTarget+matchModule1 cs = \str1 -> do+ guardModuleName str1+ nubMatchErrors $ do+ c <- tryEach cs+ let ms = cinfoModules c+ m <- matchModuleName ms str1+ return (BuildTargetModule (cinfoName c) m)++matchModule2 :: [ComponentInfo] -> String -> String -> Match BuildTarget+matchModule2 cs = \str1 str2 -> do+ guardComponentName str1+ guardModuleName str2+ c <- matchComponentName cs str1+ let ms = cinfoModules c+ m <- matchModuleName ms str2+ return (BuildTargetModule (cinfoName c) m)++matchModule3 :: [ComponentInfo] -> String -> String -> String+ -> Match BuildTarget+matchModule3 cs str1 str2 str3 = do+ ckind <- matchComponentKind str1+ guardComponentName str2+ c <- matchComponentKindAndName cs ckind str2+ guardModuleName str3+ let ms = cinfoModules c+ m <- matchModuleName ms str3+ return (BuildTargetModule (cinfoName c) m)++-- utils:++guardModuleName :: String -> Match ()+guardModuleName s+ | all validModuleChar s+ && not (null s) = increaseConfidence+ | otherwise = matchErrorExpected "module name" s+ where+ validModuleChar c = isAlphaNum c || c == '.' || c == '_' || c == '\''++matchModuleName :: [ModuleName] -> String -> Match ModuleName+matchModuleName ms str =+ orNoSuchThing "module" str+ $ increaseConfidenceFor+ $ matchInexactly caseFold+ [ (prettyShow m, m)+ | m <- ms ]+ str+++------------------------------+-- Matching file targets+--++matchFile1 :: [ComponentInfo] -> String -> Bool -> Match BuildTarget+matchFile1 cs str1 exists =+ nubMatchErrors $ do+ c <- tryEach cs+ filepath <- matchComponentFile c str1 exists+ return (BuildTargetFile (cinfoName c) filepath)+++matchFile2 :: [ComponentInfo] -> String -> String -> Bool -> Match BuildTarget+matchFile2 cs str1 str2 exists = do+ guardComponentName str1+ c <- matchComponentName cs str1+ filepath <- matchComponentFile c str2 exists+ return (BuildTargetFile (cinfoName c) filepath)+++matchFile3 :: [ComponentInfo] -> String -> String -> String -> Bool+ -> Match BuildTarget+matchFile3 cs str1 str2 str3 exists = do+ ckind <- matchComponentKind str1+ guardComponentName str2+ c <- matchComponentKindAndName cs ckind str2+ filepath <- matchComponentFile c str3 exists+ return (BuildTargetFile (cinfoName c) filepath)+++matchComponentFile :: ComponentInfo -> String -> Bool -> Match FilePath+matchComponentFile c str fexists =+ expecting "file" str $+ matchPlus+ (matchFileExists str fexists)+ (matchPlusShadowing+ (msum [ matchModuleFileRooted dirs ms str+ , matchOtherFileRooted dirs hsFiles str ])+ (msum [ matchModuleFileUnrooted ms str+ , matchOtherFileUnrooted hsFiles str+ , matchOtherFileUnrooted cFiles str+ , matchOtherFileUnrooted jsFiles str ]))+ where+ dirs = cinfoSrcDirs c+ ms = cinfoModules c+ hsFiles = cinfoHsFiles c+ cFiles = cinfoCFiles c+ jsFiles = cinfoJsFiles c+++-- utils++matchFileExists :: FilePath -> Bool -> Match a+matchFileExists _ False = mzero+matchFileExists fname True = do increaseConfidence+ matchErrorNoSuch "file" fname++matchModuleFileUnrooted :: [ModuleName] -> String -> Match FilePath+matchModuleFileUnrooted ms str = do+ let filepath = normalise str+ _ <- matchModuleFileStem ms filepath+ return filepath++matchModuleFileRooted :: [FilePath] -> [ModuleName] -> String -> Match FilePath+matchModuleFileRooted dirs ms str = nubMatches $ do+ let filepath = normalise str+ filepath' <- matchDirectoryPrefix dirs filepath+ _ <- matchModuleFileStem ms filepath'+ return filepath++matchModuleFileStem :: [ModuleName] -> FilePath -> Match ModuleName+matchModuleFileStem ms =+ increaseConfidenceFor+ . matchInexactly caseFold+ [ (toFilePath m, m) | m <- ms ]+ . dropExtension++matchOtherFileRooted :: [FilePath] -> [FilePath] -> FilePath -> Match FilePath+matchOtherFileRooted dirs fs str = do+ let filepath = normalise str+ filepath' <- matchDirectoryPrefix dirs filepath+ _ <- matchFile fs filepath'+ return filepath++matchOtherFileUnrooted :: [FilePath] -> FilePath -> Match FilePath+matchOtherFileUnrooted fs str = do+ let filepath = normalise str+ _ <- matchFile fs filepath+ return filepath++matchFile :: [FilePath] -> FilePath -> Match FilePath+matchFile fs = increaseConfidenceFor+ . matchInexactly caseFold [ (f, f) | f <- fs ]++matchDirectoryPrefix :: [FilePath] -> FilePath -> Match FilePath+matchDirectoryPrefix dirs filepath =+ exactMatches $+ catMaybes+ [ stripDirectory (normalise dir) filepath | dir <- dirs ]+ where+ stripDirectory :: FilePath -> FilePath -> Maybe FilePath+ stripDirectory dir fp =+ joinPath `fmap` stripPrefix (splitDirectories dir) (splitDirectories fp)+++------------------------------+-- Matching monad+--++-- | A matcher embodies a way to match some input as being some recognised+-- value. In particular it deals with multiple and ambiguous matches.+--+-- There are various matcher primitives ('matchExactly', 'matchInexactly'),+-- ways to combine matchers ('ambiguousWith', 'shadows') and finally we can+-- run a matcher against an input using 'findMatch'.+--++data Match a = NoMatch Confidence [MatchError]+ | ExactMatch Confidence [a]+ | InexactMatch Confidence [a]+ deriving Show++type Confidence = Int++data MatchError = MatchErrorExpected String String+ | MatchErrorNoSuch String String+ deriving (Show, Eq)+++instance Alternative Match where+ empty = mzero+ (<|>) = mplus++instance MonadPlus Match where+ mzero = matchZero+ mplus = matchPlus++matchZero :: Match a+matchZero = NoMatch 0 []++-- | Combine two matchers. Exact matches are used over inexact matches+-- but if we have multiple exact, or inexact then the we collect all the+-- ambiguous matches.+--+matchPlus :: Match a -> Match a -> Match a+matchPlus (ExactMatch d1 xs) (ExactMatch d2 xs') =+ ExactMatch (max d1 d2) (xs ++ xs')+matchPlus a@(ExactMatch _ _ ) (InexactMatch _ _ ) = a+matchPlus a@(ExactMatch _ _ ) (NoMatch _ _ ) = a+matchPlus (InexactMatch _ _ ) b@(ExactMatch _ _ ) = b+matchPlus (InexactMatch d1 xs) (InexactMatch d2 xs') =+ InexactMatch (max d1 d2) (xs ++ xs')+matchPlus a@(InexactMatch _ _ ) (NoMatch _ _ ) = a+matchPlus (NoMatch _ _ ) b@(ExactMatch _ _ ) = b+matchPlus (NoMatch _ _ ) b@(InexactMatch _ _ ) = b+matchPlus a@(NoMatch d1 ms) b@(NoMatch d2 ms')+ | d1 > d2 = a+ | d1 < d2 = b+ | otherwise = NoMatch d1 (ms ++ ms')++-- | 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.+--+matchPlusShadowing :: Match a -> Match a -> Match a+matchPlusShadowing a@(ExactMatch _ _) (ExactMatch _ _) = a+matchPlusShadowing a b = matchPlus a b++instance Functor Match where+ fmap _ (NoMatch d ms) = NoMatch d ms+ fmap f (ExactMatch d xs) = ExactMatch d (fmap f xs)+ fmap f (InexactMatch d xs) = InexactMatch d (fmap f xs)++instance Applicative Match where+ pure a = ExactMatch 0 [a]+ (<*>) = ap++instance Monad Match where+ return = pure++ NoMatch d ms >>= _ = NoMatch d ms+ ExactMatch d xs >>= f = addDepth d+ $ foldr matchPlus matchZero (map f xs)+ InexactMatch d xs >>= f = addDepth d . forceInexact+ $ foldr matchPlus matchZero (map f xs)++addDepth :: Confidence -> Match a -> Match a+addDepth d' (NoMatch d msgs) = NoMatch (d'+d) msgs+addDepth d' (ExactMatch d xs) = ExactMatch (d'+d) xs+addDepth d' (InexactMatch d xs) = InexactMatch (d'+d) xs++forceInexact :: Match a -> Match a+forceInexact (ExactMatch d ys) = InexactMatch d ys+forceInexact m = m++------------------------------+-- Various match primitives+--++matchErrorExpected, matchErrorNoSuch :: String -> String -> Match a+matchErrorExpected thing got = NoMatch 0 [MatchErrorExpected thing got]+matchErrorNoSuch thing got = NoMatch 0 [MatchErrorNoSuch thing got]++expecting :: String -> String -> Match a -> Match a+expecting thing got (NoMatch 0 _) = matchErrorExpected thing got+expecting _ _ m = m++orNoSuchThing :: String -> String -> Match a -> Match a+orNoSuchThing thing got (NoMatch 0 _) = matchErrorNoSuch thing got+orNoSuchThing _ _ m = m++increaseConfidence :: Match ()+increaseConfidence = ExactMatch 1 [()]++increaseConfidenceFor :: Match a -> Match a+increaseConfidenceFor m = m >>= \r -> increaseConfidence >> return r++nubMatches :: Eq a => Match a -> Match a+nubMatches (NoMatch d msgs) = NoMatch d msgs+nubMatches (ExactMatch d xs) = ExactMatch d (nub xs)+nubMatches (InexactMatch d xs) = InexactMatch d (nub xs)++nubMatchErrors :: Match a -> Match a+nubMatchErrors (NoMatch d msgs) = NoMatch d (nub msgs)+nubMatchErrors (ExactMatch d xs) = ExactMatch d xs+nubMatchErrors (InexactMatch d xs) = InexactMatch d xs++-- | Lift a list of matches to an exact match.+--+exactMatches, inexactMatches :: [a] -> Match a++exactMatches [] = matchZero+exactMatches xs = ExactMatch 0 xs++inexactMatches [] = matchZero+inexactMatches xs = InexactMatch 0 xs++tryEach :: [a] -> Match a+tryEach = exactMatches+++------------------------------+-- Top level match runner+--++-- | Given a matcher and a key to look up, use the matcher to find all the+-- 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 -> MaybeAmbiguous b+findMatch match =+ case match of+ NoMatch _ msgs -> None (nub msgs)+ ExactMatch _ xs -> checkAmbiguous xs+ InexactMatch _ xs -> checkAmbiguous xs+ where+ checkAmbiguous xs = case nub xs of+ [x] -> Unambiguous x+ xs' -> Ambiguous xs'++data MaybeAmbiguous a = None [MatchError] | Unambiguous a | Ambiguous [a]+ deriving Show+++------------------------------+-- Basic matchers+--++{-+-- | A primitive matcher that looks up a value in a finite 'Map'. The+-- value must match exactly.+--+matchExactly :: forall a b. Ord a => [(a, b)] -> (a -> Match b)+matchExactly xs =+ \x -> case Map.lookup x m of+ Nothing -> matchZero+ Just ys -> ExactMatch 0 ys+ where+ m :: Ord a => Map a [b]+ m = Map.fromListWith (++) [ (k,[x]) | (k,x) <- xs ]+-}++-- | A primitive matcher that looks up a value in a finite 'Map'. It checks+-- for an exact or inexact match. We get an inexact match if the match+-- is not exact, but the canonical forms match. It takes a canonicalisation+-- function for this purpose.+--+-- So for example if we used string case fold as the canonicalisation+-- function, then we would get case insensitive matching (but it will still+-- report an exact match when the case matches too).+--+matchInexactly :: (Ord a, Ord a') =>+ (a -> a') ->+ [(a, b)] -> (a -> Match b)+matchInexactly cannonicalise xs =+ \x -> case Map.lookup x m of+ Just ys -> exactMatches ys+ Nothing -> case Map.lookup (cannonicalise x) m' of+ Just ys -> inexactMatches ys+ Nothing -> matchZero+ where+ m = Map.fromListWith (++) [ (k,[x]) | (k,x) <- xs ]++ -- the map of canonicalised keys to groups of inexact matches+ m' = Map.mapKeysWith (++) cannonicalise m++++------------------------------+-- Utils+--++caseFold :: String -> String+caseFold = lowercase+++-- | Check that the given build targets are valid in the current context.+--+-- Also swizzle into a more convenient form.+--+checkBuildTargets :: Verbosity -> PackageDescription -> LocalBuildInfo -> [BuildTarget]+ -> IO [TargetInfo]+checkBuildTargets _ pkg_descr lbi [] =+ return (allTargetsInBuildOrder' pkg_descr lbi)++checkBuildTargets verbosity pkg_descr lbi targets = do++ let (enabled, disabled) =+ partitionEithers+ [ case componentDisabledReason (componentEnabledSpec lbi) comp of+ Nothing -> Left target'+ Just reason -> Right (cname, reason)+ | target <- targets+ , let target'@(cname,_) = swizzleTarget target+ , let comp = getComponent pkg_descr cname ]++ case disabled of+ [] -> return ()+ ((cname,reason):_) -> die' verbosity $ formatReason (showComponentName cname) reason++ for_ [ (c, t) | (c, Just t) <- enabled ] $ \(c, t) ->+ warn verbosity $ "Ignoring '" ++ either prettyShow id t ++ ". The whole "+ ++ showComponentName c ++ " will be processed. (Support for "+ ++ "module and file targets has not been implemented yet.)"++ -- Pick out the actual CLBIs for each of these cnames+ enabled' <- for enabled $ \(cname, _) -> do+ case componentNameTargets' pkg_descr lbi cname of+ [] -> error "checkBuildTargets: nothing enabled"+ [target] -> return target+ _targets -> error "checkBuildTargets: multiple copies enabled"++ return enabled'++ where+ swizzleTarget (BuildTargetComponent c) = (c, Nothing)+ swizzleTarget (BuildTargetModule c m) = (c, Just (Left m))+ swizzleTarget (BuildTargetFile c f) = (c, Just (Right f))++ formatReason cn DisabledComponent =+ "Cannot process the " ++ cn ++ " because the component is marked "+ ++ "as disabled in the .cabal file."+ formatReason cn DisabledAllTests =+ "Cannot process the " ++ cn ++ " because test suites are not "+ ++ "enabled. Run configure with the flag --enable-tests"+ formatReason cn DisabledAllBenchmarks =+ "Cannot process the " ++ cn ++ " because benchmarks are not "+ ++ "enabled. Re-run configure with the flag --enable-benchmarks"+ formatReason cn (DisabledAllButOne cn') =+ "Cannot process the " ++ cn ++ " because this package was "+ ++ "configured only to build " ++ cn' ++ ". Re-run configure "+ ++ "with the argument " ++ cn
+ src/Distribution/Simple/BuildToolDepends.hs view
@@ -0,0 +1,93 @@+-- |+--+-- This modules provides functions for working with both the legacy+-- "build-tools" field, and its replacement, "build-tool-depends". Prefer using+-- the functions contained to access those fields directly.+module Distribution.Simple.BuildToolDepends where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Data.Map as Map++import Distribution.Package+import Distribution.PackageDescription++-- | Desugar a "build-tools" entry into proper a executable dependency if+-- possible.+--+-- An entry can be so desguared in two cases:+--+-- 1. The name in build-tools matches a locally defined executable. The+-- executable dependency produced is on that exe in the current package.+--+-- 2. The name in build-tools matches a hard-coded set of known tools. For now,+-- the executable dependency produced is one an executable in a package of+-- the same, but the hard-coding could just as well be per-key.+--+-- The first cases matches first.+desugarBuildTool :: PackageDescription+ -> LegacyExeDependency+ -> Maybe ExeDependency+desugarBuildTool pkg led =+ if foundLocal+ then Just $ ExeDependency (packageName pkg) toolName reqVer+ else Map.lookup name whiteMap+ where+ LegacyExeDependency name reqVer = led+ toolName = mkUnqualComponentName name+ foundLocal = toolName `elem` map exeName (executables pkg)+ whitelist = [ "hscolour", "haddock", "happy", "alex", "hsc2hs", "c2hs"+ , "cpphs", "greencard", "hspec-discover"+ ]+ whiteMap = Map.fromList $ flip map whitelist $ \n ->+ (n, ExeDependency (mkPackageName n) (mkUnqualComponentName n) reqVer)++-- | Get everything from "build-tool-depends", along with entries from+-- "build-tools" that we know how to desugar.+--+-- This should almost always be used instead of just accessing the+-- `buildToolDepends` field directly.+getAllToolDependencies :: PackageDescription+ -> BuildInfo+ -> [ExeDependency]+getAllToolDependencies pkg bi =+ buildToolDepends bi ++ mapMaybe (desugarBuildTool pkg) (buildTools bi)++-- | Does the given executable dependency map to this current package?+--+-- This is a tiny function, but used in a number of places.+--+-- This function is only sound to call on `BuildInfo`s from the given package+-- description. This is because it just filters the package names of each+-- dependency, and does not check whether version bounds in fact exclude the+-- current package, or the referenced components in fact exist in the current+-- package.+--+-- This is OK because when a package is loaded, it is checked (in+-- `Distribution.Package.Check`) that dependencies matching internal components+-- do indeed have version bounds accepting the current package, and any+-- depended-on component in the current package actually exists. In fact this+-- check is performed by gathering the internal tool dependencies of each+-- component of the package according to this module, and ensuring those+-- properties on each so-gathered dependency.+--+-- version bounds and components of the package are unchecked. This is because+-- we sanitize exe deps so that the matching name implies these other+-- conditions.+isInternal :: PackageDescription -> ExeDependency -> Bool+isInternal pkg (ExeDependency n _ _) = n == packageName pkg+++-- | Get internal "build-tool-depends", along with internal "build-tools"+--+-- This is a tiny function, but used in a number of places. The same+-- restrictions that apply to `isInternal` also apply to this function.+getAllInternalToolDependencies :: PackageDescription+ -> BuildInfo+ -> [UnqualComponentName]+getAllInternalToolDependencies pkg bi =+ [ toolname+ | dep@(ExeDependency _ toolname _) <- getAllToolDependencies pkg bi+ , isInternal pkg dep+ ]
+ src/Distribution/Simple/CCompiler.hs view
@@ -0,0 +1,123 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.CCompiler+-- Copyright : 2011, Dan Knapp+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This simple package provides types and functions for interacting with+-- C compilers. Currently it's just a type enumerating extant C-like+-- languages, which we call dialects.++{-+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Isaac Jones nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -}++module Distribution.Simple.CCompiler (+ CDialect(..),+ cSourceExtensions,+ cDialectFilenameExtension,+ filenameCDialect+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import System.FilePath+ ( takeExtension )+++-- | Represents a dialect of C. The Monoid instance expresses backward+-- compatibility, in the sense that 'mappend a b' is the least inclusive+-- dialect which both 'a' and 'b' can be correctly interpreted as.+data CDialect = C+ | ObjectiveC+ | CPlusPlus+ | ObjectiveCPlusPlus+ deriving (Eq, Show)++instance Monoid CDialect where+ mempty = C+ mappend = (<>)++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,+-- not for header files.+cSourceExtensions :: [String]+cSourceExtensions = ["c", "i", "ii", "m", "mi", "mm", "M", "mii", "cc", "cp",+ "cxx", "cpp", "CPP", "c++", "C"]+++-- | Takes a dialect of C and whether code is intended to be passed through+-- the preprocessor, and returns a filename extension for containing that+-- code.+cDialectFilenameExtension :: CDialect -> Bool -> String+cDialectFilenameExtension C True = "c"+cDialectFilenameExtension C False = "i"+cDialectFilenameExtension ObjectiveC True = "m"+cDialectFilenameExtension ObjectiveC False = "mi"+cDialectFilenameExtension CPlusPlus True = "cpp"+cDialectFilenameExtension CPlusPlus False = "ii"+cDialectFilenameExtension ObjectiveCPlusPlus True = "mm"+cDialectFilenameExtension ObjectiveCPlusPlus False = "mii"+++-- | Infers from a filename's extension the dialect of C which it contains,+-- and whether it is intended to be passed through the preprocessor.+filenameCDialect :: String -> Maybe (CDialect, Bool)+filenameCDialect filename = do+ extension <- case takeExtension filename of+ '.':ext -> Just ext+ _ -> Nothing+ case extension of+ "c" -> return (C, True)+ "i" -> return (C, False)+ "ii" -> return (CPlusPlus, False)+ "m" -> return (ObjectiveC, True)+ "mi" -> return (ObjectiveC, False)+ "mm" -> return (ObjectiveCPlusPlus, True)+ "M" -> return (ObjectiveCPlusPlus, True)+ "mii" -> return (ObjectiveCPlusPlus, False)+ "cc" -> return (CPlusPlus, True)+ "cp" -> return (CPlusPlus, True)+ "cxx" -> return (CPlusPlus, True)+ "cpp" -> return (CPlusPlus, True)+ "CPP" -> return (CPlusPlus, True)+ "c++" -> return (CPlusPlus, True)+ "C" -> return (CPlusPlus, True)+ _ -> Nothing
+ src/Distribution/Simple/Command.hs view
@@ -0,0 +1,594 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Command+-- Copyright : Duncan Coutts 2007+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- 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+-- 'CommandUI' abstraction represents one of these sub-commands, with a name,+-- description, a set of flags. Commands can be associated with actions and+-- run. It handles some common stuff automatically, like the @--help@ and+-- command line completion flags. It is designed to allow other tools make+-- derived commands. This feature is used heavily in @cabal-install@.++module Distribution.Simple.Command (++ -- * Command interface+ CommandUI(..),+ commandShowOptions,+ CommandParse(..),+ commandParseArgs,+ getNormalCommandDescriptions,+ helpCommandUI,++ -- ** Constructing commands+ ShowOrParseArgs(..),+ usageDefault,+ usageAlternatives,+ mkCommandUI,+ hiddenCommand,++ -- ** Associating actions with commands+ Command,+ commandAddAction,+ noExtraFlags,++ -- ** Building lists of commands+ CommandType(..),+ CommandSpec(..),+ commandFromSpec,++ -- ** Running commands+ commandsRun,++-- * Option Fields+ OptionField(..), Name,++-- ** Constructing Option Fields+ option, multiOption,++-- ** Liftings & Projections+ liftOption, liftOptionL,++-- * Option Descriptions+ OptDescr(..), Description, SFlags, LFlags, OptFlags, ArgPlaceHolder,++-- ** OptDescr 'smart' constructors+ MkOptDescr,+ reqArg, reqArg', optArg, optArg', noArg,+ boolOpt, boolOpt', choiceOpt, choiceOptFromEnum++ ) where++import Prelude ()+import Distribution.Compat.Prelude hiding (get)++import qualified Data.Array as Array+import qualified Data.List as List+import qualified Distribution.GetOpt as GetOpt+import Distribution.ReadE+import Distribution.Simple.Utils+import Distribution.Compat.Lens (ALens', (^#), (#~))+++data CommandUI flags = CommandUI {+ -- | The name of the command as it would be entered on the command line.+ -- For example @\"build\"@.+ commandName :: String,+ -- | A short, one line description of the command to use in help texts.+ commandSynopsis :: String,+ -- | A function that maps a program name to a usage summary for this+ -- command.+ commandUsage :: String -> String,+ -- | Additional explanation of the command to use in help texts.+ commandDescription :: Maybe (String -> String),+ -- | Post-Usage notes and examples in help texts+ commandNotes :: Maybe (String -> String),+ -- | Initial \/ empty flags+ commandDefaultFlags :: flags,+ -- | All the Option fields for this command+ commandOptions :: ShowOrParseArgs -> [OptionField flags]+ }++data ShowOrParseArgs = ShowArgs | ParseArgs+type Name = String+type Description = String++-- | We usually have a data type for storing configuration values, where+-- every field stores a configuration option, and the user sets+-- the value either via command line flags or a configuration file.+-- An individual OptionField models such a field, and we usually+-- build a list of options associated to a configuration data type.+data OptionField a = OptionField {+ optionName :: Name,+ optionDescr :: [OptDescr a] }++-- | An OptionField takes one or more OptDescrs, describing the command line+-- interface for the field.+data OptDescr a = ReqArg Description OptFlags ArgPlaceHolder+ (ReadE (a->a)) (a -> [String])++ | OptArg Description OptFlags ArgPlaceHolder+ (ReadE (a->a)) (a->a) (a -> [Maybe String])++ | ChoiceOpt [(Description, OptFlags, a->a, a -> Bool)]++ | BoolOpt Description OptFlags{-True-} OptFlags{-False-}+ (Bool -> a -> a) (a-> Maybe Bool)++-- | Short command line option strings+type SFlags = [Char]+-- | Long command line option strings+type LFlags = [String]+type OptFlags = (SFlags,LFlags)+type ArgPlaceHolder = String+++-- | Create an option taking a single OptDescr.+-- No explicit Name is given for the Option, the name is the first LFlag given.+option :: SFlags -> LFlags -> Description -> get -> set -> MkOptDescr get set a+ -> OptionField a+option sf lf@(n:_) d get set arg = OptionField n [arg sf lf d get set]+option _ _ _ _ _ _ = error $ "Distribution.command.option: "+ ++ "An OptionField must have at least one LFlag"++-- | Create an option taking several OptDescrs.+-- You will have to give the flags and description individually to the+-- OptDescr constructor.+multiOption :: Name -> get -> set+ -> [get -> set -> OptDescr a] -- ^MkOptDescr constructors partially+ -- applied to flags and description.+ -> OptionField a+multiOption n get set args = OptionField n [arg get set | arg <- args]++type MkOptDescr get set a = SFlags -> LFlags -> Description -> get -> set+ -> OptDescr a++-- | Create a string-valued command line interface.+reqArg :: Monoid b => ArgPlaceHolder -> ReadE b -> (b -> [String])+ -> MkOptDescr (a -> b) (b -> a -> a) a+reqArg ad mkflag showflag sf lf d get set =+ ReqArg d (sf,lf) ad (fmap (\a b -> set (get b `mappend` a) b) mkflag)+ (showflag . get)++-- | Create a string-valued command line interface with a default value.+optArg :: Monoid b => ArgPlaceHolder -> ReadE b -> b -> (b -> [Maybe String])+ -> MkOptDescr (a -> b) (b -> a -> a) a+optArg ad mkflag def showflag sf lf d get set =+ OptArg d (sf,lf) ad (fmap (\a b -> set (get b `mappend` a) b) mkflag)+ (\b -> set (get b `mappend` def) b)+ (showflag . get)++-- | (String -> a) variant of "reqArg"+reqArg' :: Monoid b => ArgPlaceHolder -> (String -> b) -> (b -> [String])+ -> MkOptDescr (a -> b) (b -> a -> a) a+reqArg' ad mkflag showflag =+ reqArg ad (succeedReadE mkflag) showflag++-- | (String -> a) variant of "optArg"+optArg' :: 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) => 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+ -> MkOptDescr (a -> b) (b -> a -> a) a+boolOpt g s sfT sfF _sf _lf@(n:_) d get set =+ BoolOpt d (sfT, ["enable-"++n]) (sfF, ["disable-"++n]) (set.s) (g.get)+boolOpt _ _ _ _ _ _ _ _ _ = error+ "Distribution.Simple.Setup.boolOpt: unreachable"++boolOpt' :: (b -> Maybe Bool) -> (Bool -> b) -> OptFlags -> OptFlags+ -> MkOptDescr (a -> b) (b -> a -> a) a+boolOpt' g s ffT ffF _sf _lf d get set = BoolOpt d ffT ffF (set.s) (g . get)++-- | create a Choice option+choiceOpt :: Eq b => [(b,OptFlags,Description)]+ -> MkOptDescr (a -> b) (b -> a -> a) a+choiceOpt aa_ff _sf _lf _d get set = ChoiceOpt alts+ where alts = [(d,flags, set alt, (==alt) . get) | (alt,flags,d) <- aa_ff]++-- | create a Choice option out of an enumeration type.+-- As long flags, the Show output is used. As short flags, the first character+-- which does not conflict with a previous one is used.+choiceOptFromEnum :: (Bounded b, Enum b, Show b, Eq b) =>+ MkOptDescr (a -> b) (b -> a -> a) a+choiceOptFromEnum _sf _lf d get =+ choiceOpt [ (x, (sf, [map toLower $ show x]), d')+ | (x, sf) <- sflags'+ , let d' = d ++ show x]+ _sf _lf d get+ where sflags' = foldl f [] [firstOne..]+ f prev x = let prevflags = concatMap snd prev in+ prev ++ take 1 [(x, [toLower sf])+ | sf <- show x, isAlpha sf+ , toLower sf `notElem` prevflags]+ firstOne = minBound `asTypeOf` get undefined++commandGetOpts :: ShowOrParseArgs -> CommandUI flags+ -> [GetOpt.OptDescr (flags -> flags)]+commandGetOpts showOrParse command =+ concatMap viewAsGetOpt (commandOptions command showOrParse)++viewAsGetOpt :: OptionField a -> [GetOpt.OptDescr (a->a)]+viewAsGetOpt (OptionField _n aa) = concatMap optDescrToGetOpt aa+ where+ optDescrToGetOpt (ReqArg d (cs,ss) arg_desc set _) =+ [GetOpt.Option cs ss (GetOpt.ReqArg set' arg_desc) d]+ where set' = readEOrFail set+ optDescrToGetOpt (OptArg d (cs,ss) arg_desc set def _) =+ [GetOpt.Option cs ss (GetOpt.OptArg set' arg_desc) d]+ where set' Nothing = def+ set' (Just txt) = readEOrFail set txt+ optDescrToGetOpt (ChoiceOpt alts) =+ [GetOpt.Option sf lf (GetOpt.NoArg set) d | (d,(sf,lf),set,_) <- alts ]+ optDescrToGetOpt (BoolOpt d (sfT, lfT) ([], []) set _) =+ [ GetOpt.Option sfT lfT (GetOpt.NoArg (set True)) d ]+ optDescrToGetOpt (BoolOpt d ([], []) (sfF, lfF) set _) =+ [ GetOpt.Option sfF lfF (GetOpt.NoArg (set False)) d ]+ optDescrToGetOpt (BoolOpt d (sfT,lfT) (sfF, lfF) set _) =+ [ GetOpt.Option sfT lfT (GetOpt.NoArg (set True)) ("Enable " ++ d)+ , GetOpt.Option sfF lfF (GetOpt.NoArg (set False)) ("Disable " ++ d) ]++getCurrentChoice :: OptDescr a -> a -> [String]+getCurrentChoice (ChoiceOpt alts) a =+ [ lf | (_,(_sf,lf:_), _, currentChoice) <- alts, currentChoice a]++getCurrentChoice _ _ = error "Command.getChoice: expected a Choice OptDescr"+++liftOption :: (b -> a) -> (a -> (b -> b)) -> OptionField a -> OptionField b+liftOption get' set' opt =+ opt { optionDescr = liftOptDescr get' set' `map` optionDescr opt}++-- | @since 3.4.0.0+liftOptionL :: ALens' b a -> OptionField a -> OptionField b+liftOptionL l = liftOption (^# l) (l #~)+++liftOptDescr :: (b -> a) -> (a -> (b -> b)) -> OptDescr a -> OptDescr b+liftOptDescr get' set' (ChoiceOpt opts) =+ ChoiceOpt [ (d, ff, liftSet get' set' set , (get . get'))+ | (d, ff, set, get) <- opts]++liftOptDescr get' set' (OptArg d ff ad set def get) =+ OptArg d ff ad (liftSet get' set' `fmap` set)+ (liftSet get' set' def) (get . get')++liftOptDescr get' set' (ReqArg d ff ad set get) =+ ReqArg d ff ad (liftSet get' set' `fmap` set) (get . get')++liftOptDescr get' set' (BoolOpt d ffT ffF set get) =+ BoolOpt d ffT ffF (liftSet get' set' . set) (get . get')++liftSet :: (b -> a) -> (a -> (b -> b)) -> (a -> a) -> b -> b+liftSet get' set' set x = set' (set $ get' x) x++-- | Show flags in the standard long option command line format+commandShowOptions :: CommandUI flags -> flags -> [String]+commandShowOptions command v = concat+ [ showOptDescr v od | o <- commandOptions command ParseArgs+ , od <- optionDescr o]+ where+ maybePrefix [] = []+ maybePrefix (lOpt:_) = ["--" ++ lOpt]++ showOptDescr :: a -> OptDescr a -> [String]+ showOptDescr x (BoolOpt _ (_,lfTs) (_,lfFs) _ enabled)+ = case enabled x of+ Nothing -> []+ Just True -> maybePrefix lfTs+ Just False -> maybePrefix lfFs+ showOptDescr x c@ChoiceOpt{}+ = ["--" ++ val | val <- getCurrentChoice c x]+ showOptDescr x (ReqArg _ (_ssff,lf:_) _ _ showflag)+ = [ "--"++lf++"="++flag+ | flag <- showflag x ]+ showOptDescr x (OptArg _ (_ssff,lf:_) _ _ _ showflag)+ = [ case flag of+ Just s -> "--"++lf++"="++s+ Nothing -> "--"++lf+ | flag <- showflag x ]+ showOptDescr _ _+ = error "Distribution.Simple.Command.showOptDescr: unreachable"+++commandListOptions :: CommandUI flags -> [String]+commandListOptions command =+ concatMap listOption $+ addCommonFlags ShowArgs $ -- This is a slight hack, we don't want+ -- "--list-options" showing up in the+ -- list options output, so use ShowArgs+ commandGetOpts ShowArgs command+ where+ listOption (GetOpt.Option shortNames longNames _ _) =+ [ "-" ++ [name] | name <- shortNames ]+ ++ [ "--" ++ name | name <- longNames ]++-- | The help text for this command with descriptions of all the options.+commandHelp :: CommandUI flags -> String -> String+commandHelp command pname =+ commandSynopsis command+ ++ "\n\n"+ ++ commandUsage command pname+ ++ ( case commandDescription command of+ Nothing -> ""+ Just desc -> '\n': desc pname)+ ++ "\n"+ ++ ( if cname == ""+ then "Global flags:"+ else "Flags for " ++ cname ++ ":" )+ ++ ( GetOpt.usageInfo ""+ . addCommonFlags ShowArgs+ $ commandGetOpts ShowArgs command )+ ++ ( case commandNotes command of+ Nothing -> ""+ Just notes -> '\n': notes pname)+ where cname = commandName command++-- | Default "usage" documentation text for commands.+usageDefault :: String -> String -> String+usageDefault name pname =+ "Usage: " ++ pname ++ " " ++ name ++ " [FLAGS]\n\n"+ ++ "Flags for " ++ name ++ ":"++-- | Create "usage" documentation from a list of parameter+-- configurations.+usageAlternatives :: String -> [String] -> String -> String+usageAlternatives name strs pname = unlines+ [ start ++ pname ++ " " ++ name ++ " " ++ s+ | let starts = "Usage: " : repeat " or: "+ , (start, s) <- zip starts strs+ ]++-- | Make a Command from standard 'GetOpt' options.+mkCommandUI :: String -- ^ name+ -> String -- ^ synopsis+ -> [String] -- ^ usage alternatives+ -> flags -- ^ initial\/empty flags+ -> (ShowOrParseArgs -> [OptionField flags]) -- ^ options+ -> CommandUI flags+mkCommandUI name synopsis usages flags options = CommandUI+ { commandName = name+ , commandSynopsis = synopsis+ , commandDescription = Nothing+ , commandNotes = Nothing+ , commandUsage = usageAlternatives name usages+ , commandDefaultFlags = flags+ , commandOptions = options+ }++-- | Common flags that apply to every command+data CommonFlag = HelpFlag | ListOptionsFlag++commonFlags :: ShowOrParseArgs -> [GetOpt.OptDescr CommonFlag]+commonFlags showOrParseArgs = case showOrParseArgs of+ ShowArgs -> [help]+ ParseArgs -> [help, list]+ where+ help = GetOpt.Option helpShortFlags ["help"] (GetOpt.NoArg HelpFlag)+ "Show this help text"+ helpShortFlags = case showOrParseArgs of+ ShowArgs -> ['h']+ ParseArgs -> ['h', '?']+ list = GetOpt.Option [] ["list-options"] (GetOpt.NoArg ListOptionsFlag)+ "Print a list of command line flags"++addCommonFlags :: ShowOrParseArgs+ -> [GetOpt.OptDescr a]+ -> [GetOpt.OptDescr (Either CommonFlag a)]+addCommonFlags showOrParseArgs options =+ map (fmapOptDesc Left) (commonFlags showOrParseArgs)+ ++ map (fmapOptDesc Right) options+ where fmapOptDesc f (GetOpt.Option s l d m) =+ GetOpt.Option s l (fmapArgDesc f d) m+ fmapArgDesc f (GetOpt.NoArg a) = GetOpt.NoArg (f a)+ fmapArgDesc f (GetOpt.ReqArg s d) = GetOpt.ReqArg (f . s) d+ fmapArgDesc f (GetOpt.OptArg s d) = GetOpt.OptArg (f . s) d++-- | Parse a bunch of command line arguments+--+commandParseArgs :: CommandUI flags+ -> Bool -- ^ Is the command a global or subcommand?+ -> [String]+ -> CommandParse (flags -> flags, [String])+commandParseArgs command global args =+ let options = addCommonFlags ParseArgs+ $ commandGetOpts ParseArgs command+ order | global = GetOpt.RequireOrder+ | otherwise = GetOpt.Permute+ in case GetOpt.getOpt' order options args of+ (flags, _, _, _)+ | any listFlag flags -> CommandList (commandListOptions command)+ | any helpFlag flags -> CommandHelp (commandHelp command)+ where listFlag (Left ListOptionsFlag) = True; listFlag _ = False+ helpFlag (Left HelpFlag) = True; helpFlag _ = False+ (flags, opts, opts', [])+ | global || null opts' -> CommandReadyToGo (accum flags, mix opts opts')+ | otherwise -> CommandErrors (unrecognised opts')+ (_, _, _, errs) -> CommandErrors errs++ where -- Note: It is crucial to use reverse function composition here or to+ -- reverse the flags here as we want to process the flags left to right+ -- but data flow in function composition is right to left.+ accum flags = foldr (flip (.)) id [ f | Right f <- flags ]+ unrecognised opts = [ "unrecognized "+ ++ "'" ++ (commandName command) ++ "'"+ ++ " option `" ++ opt ++ "'\n"+ | opt <- opts ]+ -- For unrecognised global flags we put them in the position just after+ -- the command, if there is one. This gives us a chance to parse them+ -- as sub-command rather than global flags.+ mix [] ys = ys+ mix (x:xs) ys = x:ys++xs++data CommandParse flags = CommandHelp (String -> String)+ | CommandList [String]+ | CommandErrors [String]+ | CommandReadyToGo flags+instance Functor CommandParse where+ fmap _ (CommandHelp help) = CommandHelp help+ fmap _ (CommandList opts) = CommandList opts+ fmap _ (CommandErrors errs) = CommandErrors errs+ fmap f (CommandReadyToGo flags) = CommandReadyToGo (f flags)+++data CommandType = NormalCommand | HiddenCommand+data Command action =+ Command String String ([String] -> CommandParse action) CommandType++-- | Mark command as hidden. Hidden commands don't show up in the 'progname+-- help' or 'progname --help' output.+hiddenCommand :: Command action -> Command action+hiddenCommand (Command name synopsys f _cmdType) =+ Command name synopsys f HiddenCommand++commandAddAction :: CommandUI flags+ -> (flags -> [String] -> action)+ -> Command action+commandAddAction command action =+ Command (commandName command)+ (commandSynopsis command)+ (fmap (uncurry applyDefaultArgs) . commandParseArgs command False)+ NormalCommand++ where applyDefaultArgs mkflags args =+ let flags = mkflags (commandDefaultFlags command)+ in action flags args++commandsRun :: CommandUI a+ -> [Command action]+ -> [String]+ -> CommandParse (a, CommandParse action)+commandsRun globalCommand commands args =+ case commandParseArgs globalCommand True args of+ CommandHelp help -> CommandHelp help+ CommandList opts -> CommandList (opts ++ commandNames)+ CommandErrors errs -> CommandErrors errs+ CommandReadyToGo (mkflags, args') -> case args' of+ ("help":cmdArgs) -> handleHelpCommand cmdArgs+ (name:cmdArgs) -> case lookupCommand name of+ [Command _ _ action _]+ -> CommandReadyToGo (flags, action cmdArgs)+ _ -> CommandReadyToGo (flags, badCommand name)+ [] -> CommandReadyToGo (flags, noCommand)+ where flags = mkflags (commandDefaultFlags globalCommand)++ where+ lookupCommand cname = [ cmd | cmd@(Command cname' _ _ _) <- commands'+ , cname' == cname ]+ noCommand = CommandErrors ["no command given (try --help)\n"]++ -- Print suggested command if edit distance is < 5+ badCommand :: String -> CommandParse a+ badCommand cname =+ case eDists of+ [] -> CommandErrors [unErr]+ (s:_) -> CommandErrors [ unErr+ , "Maybe you meant `" ++ s ++ "`?\n"]+ where+ eDists = map fst . List.sortBy (comparing snd) $+ [ (cname', dist)+ | (Command cname' _ _ _) <- commands'+ , let dist = editDistance cname' cname+ , dist < 5 ]+ unErr = "unrecognised command: " ++ cname ++ " (try --help)"++ commands' = commands ++ [commandAddAction helpCommandUI undefined]+ commandNames = [ name | (Command name _ _ NormalCommand) <- commands' ]++ -- A bit of a hack: support "prog help" as a synonym of "prog --help"+ -- furthermore, support "prog help command" as "prog command --help"+ handleHelpCommand cmdArgs =+ case commandParseArgs helpCommandUI True cmdArgs of+ CommandHelp help -> CommandHelp help+ CommandList list -> CommandList (list ++ commandNames)+ CommandErrors _ -> CommandHelp globalHelp+ CommandReadyToGo (_,[]) -> CommandHelp globalHelp+ CommandReadyToGo (_,(name:cmdArgs')) ->+ case lookupCommand name of+ [Command _ _ action _] ->+ case action ("--help":cmdArgs') of+ CommandHelp help -> CommandHelp help+ CommandList _ -> CommandList []+ _ -> CommandHelp globalHelp+ _ -> badCommand name++ where globalHelp = commandHelp globalCommand++-- Levenshtein distance, from https://wiki.haskell.org/Edit_distance+-- (Author: JeanPhilippeBernardy, Simple Permissive Licence)+editDistance :: Eq a => [a] -> [a] -> Int+editDistance xs ys = table Array.! (m,n)+ where+ (m,n) = (length xs, length ys)+ x = Array.array (1,m) (zip [1..] xs)+ y = Array.array (1,n) (zip [1..] ys)++ table :: Array.Array (Int,Int) Int+ table = Array.array bnds [(ij, dist ij) | ij <- Array.range bnds]+ bnds = ((0,0),(m,n))++ dist (0,j) = j+ dist (i,0) = i+ dist (i,j) = minimum+ [ table Array.! (i-1,j) + 1+ , table Array.! (i,j-1) + 1+ , if x Array.! i == y Array.! j+ then table Array.! (i-1,j-1)+ else 1 + table Array.! (i-1,j-1)+ ]++-- | Utility function, many commands do not accept additional flags. This+-- action fails with a helpful error message if the user supplies any extra.+--+noExtraFlags :: [String] -> IO ()+noExtraFlags [] = return ()+noExtraFlags extraFlags =+ dieNoVerbosity $ "Unrecognised flags: " ++ intercalate ", " extraFlags+--TODO: eliminate this function and turn it into a variant on commandAddAction+-- instead like commandAddActionNoArgs that doesn't supply the [String]++-- | Helper function for creating globalCommand description+getNormalCommandDescriptions :: [Command action] -> [(String, String)]+getNormalCommandDescriptions cmds =+ [ (name, description)+ | Command name description _ NormalCommand <- cmds ]++helpCommandUI :: CommandUI ()+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
+ src/Distribution/Simple/Compiler.hs view
@@ -0,0 +1,453 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Compiler+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This should be a much more sophisticated abstraction than it is. Currently+-- it's just a bit of data about the compiler, like its flavour and name and+-- version. The reason it's just data is because currently it has to be in+-- 'Read' and 'Show' so it can be saved along with the 'LocalBuildInfo'. The+-- only interesting bit of info it contains is a mapping between language+-- extensions and compiler command line flags. This module also defines a+-- 'PackageDB' type which is used to refer to package databases. Most compilers+-- only know about a single global package collection but GHC has a global and+-- per-user one and it lets you create arbitrary other package databases. We do+-- not yet fully support this latter feature.++module Distribution.Simple.Compiler (+ -- * Haskell implementations+ module Distribution.Compiler,+ Compiler(..),+ showCompilerId, showCompilerIdWithAbi,+ compilerFlavor, compilerVersion,+ compilerCompatFlavor,+ compilerCompatVersion,+ compilerInfo,++ -- * Support for package databases+ PackageDB(..),+ PackageDBStack,+ registrationPackageDB,+ absolutePackageDBPaths,+ absolutePackageDBPath,++ -- * Support for optimisation levels+ OptimisationLevel(..),+ flagToOptimisationLevel,++ -- * Support for debug info levels+ DebugInfoLevel(..),+ flagToDebugInfoLevel,++ -- * Support for language extensions+ CompilerFlag,+ languageToFlags,+ unsupportedLanguages,+ extensionsToFlags,+ unsupportedExtensions,+ parmakeSupported,+ reexportedModulesSupported,+ renamingPackageFlagsSupported,+ unifiedIPIDRequired,+ packageKeySupported,+ unitIdSupported,+ coverageSupported,+ profilingSupported,+ backpackSupported,+ arResponseFilesSupported,+ libraryDynDirSupported,+ libraryVisibilitySupported,++ -- * Support for profiling detail levels+ ProfDetailLevel(..),+ knownProfDetailLevels,+ flagToProfDetailLevel,+ showProfDetailLevel,+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Pretty++import Distribution.Compiler+import Distribution.Version+import Language.Haskell.Extension+import Distribution.Simple.Utils++import qualified Data.Map as Map (lookup)+import System.Directory (canonicalizePath)++data Compiler = Compiler {+ compilerId :: CompilerId,+ -- ^ Compiler flavour and version.+ compilerAbiTag :: AbiTag,+ -- ^ Tag for distinguishing incompatible ABI's on the same+ -- architecture/os.+ compilerCompat :: [CompilerId],+ -- ^ Other implementations that this compiler claims to be+ -- compatible with.+ compilerLanguages :: [(Language, CompilerFlag)],+ -- ^ Supported language standards.+ compilerExtensions :: [(Extension, Maybe CompilerFlag)],+ -- ^ Supported extensions.+ compilerProperties :: Map String String+ -- ^ A key-value map for properties not covered by the above fields.+ }+ deriving (Eq, Generic, Typeable, Show, Read)++instance Binary Compiler+instance Structured Compiler++showCompilerId :: Compiler -> String+showCompilerId = prettyShow . compilerId++showCompilerIdWithAbi :: Compiler -> String+showCompilerIdWithAbi comp =+ prettyShow (compilerId comp) +++ case compilerAbiTag comp of+ NoAbiTag -> []+ AbiTag xs -> '-':xs++compilerFlavor :: Compiler -> CompilerFlavor+compilerFlavor = (\(CompilerId f _) -> f) . compilerId++compilerVersion :: Compiler -> Version+compilerVersion = (\(CompilerId _ v) -> v) . compilerId+++-- | Is this compiler compatible with the compiler flavour we're interested in?+--+-- For example this checks if the compiler is actually GHC or is another+-- compiler that claims to be compatible with some version of GHC, e.g. GHCJS.+--+-- > if compilerCompatFlavor GHC compiler then ... else ...+--+compilerCompatFlavor :: CompilerFlavor -> Compiler -> Bool+compilerCompatFlavor flavor comp =+ flavor == compilerFlavor comp+ || flavor `elem` [ flavor' | CompilerId flavor' _ <- compilerCompat comp ]+++-- | Is this compiler compatible with the compiler flavour we're interested in,+-- and if so what version does it claim to be compatible with.+--+-- For example this checks if the compiler is actually GHC-7.x or is another+-- compiler that claims to be compatible with some GHC-7.x version.+--+-- > case compilerCompatVersion GHC compiler of+-- > Just (Version (7:_)) -> ...+-- > _ -> ...+--+compilerCompatVersion :: CompilerFlavor -> Compiler -> Maybe Version+compilerCompatVersion flavor comp+ | compilerFlavor comp == flavor = Just (compilerVersion comp)+ | otherwise =+ listToMaybe [ v | CompilerId fl v <- compilerCompat comp, fl == flavor ]++compilerInfo :: Compiler -> CompilerInfo+compilerInfo c = CompilerInfo (compilerId c)+ (compilerAbiTag c)+ (Just . compilerCompat $ c)+ (Just . map fst . compilerLanguages $ c)+ (Just . map fst . compilerExtensions $ c)++-- ------------------------------------------------------------+-- * Package databases+-- ------------------------------------------------------------++-- |Some compilers have a notion of a database of available packages.+-- For some there is just one global db of packages, other compilers+-- support a per-user or an arbitrary db specified at some location in+-- the file system. This can be used to build isloated environments of+-- packages, for example to build a collection of related packages+-- without installing them globally.+--+data PackageDB = GlobalPackageDB+ | UserPackageDB+ | SpecificPackageDB FilePath+ deriving (Eq, Generic, Ord, Show, Read, Typeable)++instance Binary PackageDB+instance Structured PackageDB++-- | We typically get packages from several databases, and stack them+-- together. This type lets us be explicit about that stacking. For example+-- typical stacks include:+--+-- > [GlobalPackageDB]+-- > [GlobalPackageDB, UserPackageDB]+-- > [GlobalPackageDB, SpecificPackageDB "package.conf.inplace"]+--+-- Note that the 'GlobalPackageDB' is invariably at the bottom since it+-- contains the rts, base and other special compiler-specific packages.+--+-- We are not restricted to using just the above combinations. In particular+-- we can use several custom package dbs and the user package db together.+--+-- When it comes to writing, the top most (last) package is used.+--+type PackageDBStack = [PackageDB]++-- | Return the package that we should register into. This is the package db at+-- the top of the stack.+--+registrationPackageDB :: PackageDBStack -> PackageDB+registrationPackageDB dbs = case safeLast dbs of+ Nothing -> error "internal error: empty package db set"+ Just p -> p++-- | Make package paths absolute+++absolutePackageDBPaths :: PackageDBStack -> IO PackageDBStack+absolutePackageDBPaths = traverse absolutePackageDBPath++absolutePackageDBPath :: PackageDB -> IO PackageDB+absolutePackageDBPath GlobalPackageDB = return GlobalPackageDB+absolutePackageDBPath UserPackageDB = return UserPackageDB+absolutePackageDBPath (SpecificPackageDB db) =+ SpecificPackageDB `liftM` canonicalizePath db++-- ------------------------------------------------------------+-- * Optimisation levels+-- ------------------------------------------------------------++-- | Some compilers support optimising. Some have different levels.+-- For compilers that do not the level is just capped to the level+-- they do support.+--+data OptimisationLevel = NoOptimisation+ | NormalOptimisation+ | MaximumOptimisation+ deriving (Bounded, Enum, Eq, Generic, Read, Show, Typeable)++instance Binary OptimisationLevel+instance Structured OptimisationLevel++flagToOptimisationLevel :: Maybe String -> OptimisationLevel+flagToOptimisationLevel Nothing = NormalOptimisation+flagToOptimisationLevel (Just s) = case reads s of+ [(i, "")]+ | i >= fromEnum (minBound :: OptimisationLevel)+ && i <= fromEnum (maxBound :: OptimisationLevel)+ -> toEnum i+ | otherwise -> error $ "Bad optimisation level: " ++ show i+ ++ ". Valid values are 0..2"+ _ -> error $ "Can't parse optimisation level " ++ s++-- ------------------------------------------------------------+-- * Debug info levels+-- ------------------------------------------------------------++-- | Some compilers support emitting debug info. Some have different+-- levels. For compilers that do not the level is just capped to the+-- level they do support.+--+data DebugInfoLevel = NoDebugInfo+ | MinimalDebugInfo+ | NormalDebugInfo+ | MaximalDebugInfo+ deriving (Bounded, Enum, Eq, Generic, Read, Show, Typeable)++instance Binary DebugInfoLevel+instance Structured DebugInfoLevel++flagToDebugInfoLevel :: Maybe String -> DebugInfoLevel+flagToDebugInfoLevel Nothing = NormalDebugInfo+flagToDebugInfoLevel (Just s) = case reads s of+ [(i, "")]+ | i >= fromEnum (minBound :: DebugInfoLevel)+ && i <= fromEnum (maxBound :: DebugInfoLevel)+ -> toEnum i+ | otherwise -> error $ "Bad debug info level: " ++ show i+ ++ ". Valid values are 0..3"+ _ -> error $ "Can't parse debug info level " ++ s++-- ------------------------------------------------------------+-- * Languages and Extensions+-- ------------------------------------------------------------++unsupportedLanguages :: Compiler -> [Language] -> [Language]+unsupportedLanguages comp langs =+ [ lang | lang <- langs+ , isNothing (languageToFlag comp lang) ]++languageToFlags :: Compiler -> Maybe Language -> [CompilerFlag]+languageToFlags comp = filter (not . null)+ . catMaybes . map (languageToFlag comp)+ . maybe [Haskell98] (\x->[x])++languageToFlag :: Compiler -> Language -> Maybe CompilerFlag+languageToFlag comp ext = lookup ext (compilerLanguages comp)+++-- |For the given compiler, return the extensions it does not support.+unsupportedExtensions :: Compiler -> [Extension] -> [Extension]+unsupportedExtensions comp exts =+ [ ext | ext <- exts+ , isNothing (extensionToFlag' comp ext) ]++type CompilerFlag = String++-- |For the given compiler, return the flags for the supported extensions.+extensionsToFlags :: Compiler -> [Extension] -> [CompilerFlag]+extensionsToFlags comp = nub . filter (not . null)+ . catMaybes . map (extensionToFlag comp)++-- | Looks up the flag for a given extension, for a given compiler.+-- Ignores the subtlety of extensions which lack associated flags.+extensionToFlag :: Compiler -> Extension -> Maybe CompilerFlag+extensionToFlag comp ext = join (extensionToFlag' comp ext)++-- | Looks up the flag for a given extension, for a given compiler.+-- However, the extension may be valid for the compiler but not have a flag.+-- For example, NondecreasingIndentation is enabled by default on GHC 7.0.4,+-- hence it is considered a supported extension but not an accepted flag.+--+-- The outer layer of Maybe indicates whether the extensions is supported, while+-- the inner layer indicates whether it has a flag.+-- When building strings, it is often more convenient to use 'extensionToFlag',+-- which ignores the difference.+extensionToFlag' :: Compiler -> Extension -> Maybe (Maybe CompilerFlag)+extensionToFlag' comp ext = lookup ext (compilerExtensions comp)++-- | Does this compiler support parallel --make mode?+parmakeSupported :: Compiler -> Bool+parmakeSupported = ghcSupported "Support parallel --make"++-- | Does this compiler support reexported-modules?+reexportedModulesSupported :: Compiler -> Bool+reexportedModulesSupported = ghcSupported "Support reexported-modules"++-- | Does this compiler support thinning/renaming on package flags?+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"++-- | Does this compiler support Backpack?+backpackSupported :: Compiler -> Bool+backpackSupported = ghcSupported "Support Backpack"++-- | Does this compiler support a package database entry with:+-- "dynamic-library-dirs"?+libraryDynDirSupported :: Compiler -> Bool+libraryDynDirSupported comp = case compilerFlavor comp of+ GHC ->+ -- Not just v >= mkVersion [8,0,1,20161022], as there+ -- are many GHC 8.1 nightlies which don't support this.+ ((v >= mkVersion [8,0,1,20161022] && v < mkVersion [8,1]) ||+ v >= mkVersion [8,1,20161021])+ _ -> False+ where+ v = compilerVersion comp++-- | Does this compiler's "ar" command supports response file+-- arguments (i.e. @file-style arguments).+arResponseFilesSupported :: Compiler -> Bool+arResponseFilesSupported = ghcSupported "ar supports at file"++-- | Does this compiler support Haskell program coverage?+coverageSupported :: Compiler -> Bool+coverageSupported comp =+ case compilerFlavor comp of+ GHC -> True+ GHCJS -> True+ _ -> False++-- | Does this compiler support profiling?+profilingSupported :: Compiler -> Bool+profilingSupported comp =+ case compilerFlavor comp of+ GHC -> True+ GHCJS -> True+ _ -> False++-- | Does this compiler support a package database entry with:+-- "visibility"?+libraryVisibilitySupported :: Compiler -> Bool+libraryVisibilitySupported comp = case compilerFlavor comp of+ GHC -> v >= mkVersion [8,8]+ _ -> False+ where+ v = compilerVersion comp++-- | Utility function for GHC only features+ghcSupported :: String -> Compiler -> Bool+ghcSupported key comp =+ case compilerFlavor comp of+ GHC -> checkProp+ GHCJS -> checkProp+ _ -> False+ where checkProp =+ case Map.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, Typeable)++instance Binary ProfDetailLevel+instance Structured 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
+ src/Distribution/Simple/Configure.hs view
@@ -0,0 +1,2088 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# 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+ , getInternalLibraries+ , computeComponentId+ , computeCompatPackageKey+ , localBuildInfoFile+ , getInstalledPackages+ , getInstalledPackagesMonitorFiles+ , getPackageDBContents+ , configCompilerEx, configCompilerAuxEx+ , computeEffectiveProfiling+ , ccLdOptionsBuildInfo+ , checkForeignDeps+ , interpretPackageDbFlags+ , ConfigStateFileError(..)+ , tryGetConfigStateFile+ , platformDefines,+ ) where++import qualified Prelude as Unsafe (tail)+import Distribution.Compat.Prelude++import Distribution.Compiler+import Distribution.Types.IncludeRenaming+import Distribution.Utils.NubList+import Distribution.Simple.Compiler+import Distribution.Simple.PreProcess+import Distribution.Package+import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.InstalledPackageInfo (InstalledPackageInfo)+import qualified Distribution.Simple.PackageIndex as PackageIndex+import Distribution.Simple.PackageIndex (InstalledPackageIndex)+import Distribution.PackageDescription+import Distribution.PackageDescription.PrettyPrint+import Distribution.PackageDescription.Configuration+import Distribution.PackageDescription.Check hiding (doesFileExist)+import Distribution.Simple.BuildToolDepends+import Distribution.Simple.Program+import Distribution.Simple.Setup as Setup+import Distribution.Simple.BuildTarget+import Distribution.Simple.LocalBuildInfo+import Distribution.Types.PackageVersionConstraint+import Distribution.Types.LocalBuildInfo+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.GivenComponent+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Version+import Distribution.Verbosity+import qualified Distribution.Compat.Graph as Graph+import Distribution.Compat.Stack+import Distribution.Backpack.Configure+import Distribution.Backpack.DescribeUnitId+import Distribution.Backpack.PreExistingComponent+import Distribution.Backpack.ConfiguredComponent (newPackageDepsBehaviour)+import Distribution.Backpack.Id+import Distribution.Utils.LogProgress++import qualified Distribution.Simple.GHC as GHC+import qualified Distribution.Simple.GHCJS as GHCJS+import qualified Distribution.Simple.UHC as UHC+import qualified Distribution.Simple.HaskellSuite as HaskellSuite++import Control.Exception+ ( try )+import Distribution.Utils.Structured ( structuredDecodeOrFailIO, structuredEncode )+import Distribution.Compat.Directory ( listDirectory )+import Data.ByteString.Lazy ( ByteString )+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy.Char8 as BLC8+import Data.List+ ( (\\), inits, stripPrefix, intersect, dropWhileEnd )+import qualified Data.Map as Map+import System.Directory+ ( canonicalizePath, createDirectoryIfMissing, doesFileExist+ , getTemporaryDirectory, removeFile)+import System.FilePath+ ( (</>), isAbsolute, takeDirectory )+import Distribution.Compat.Directory+ ( doesPathExist )+import qualified System.Info+ ( compilerName, compilerVersion )+import System.IO+ ( hPutStrLn, hClose )+import Distribution.Pretty+ ( pretty, defaultStyle, prettyShow )+import Distribution.Parsec+ ( simpleParsec )+import Text.PrettyPrint+ ( Doc, ($+$), char, comma, hsep, nest+ , punctuate, quotes, render, renderStyle, sep, text )+import Distribution.Compat.Environment ( lookupEnv )++import qualified Data.Set as Set+import qualified Distribution.Compat.NonEmptySet as NES+++type UseExternalInternalDeps = Bool++-- | 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"+ <+> pretty oldCabal <+> "to" <+> pretty currentCabalId+ badCompiler+ | oldCompiler == currentCompilerId = mempty+ | otherwise =+ text "• the compiler changed from"+ <+> pretty oldCompiler <+> "to" <+> pretty 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])++ (cabalId, compId) <- parseHeader header++ let getStoredValue = do+ result <- structuredDecodeOrFailIO (BLC8.tail body)+ case result of+ Left _ -> throwIO ConfigStateFileNoParse+ Right x -> return x+ deferErrorIfBadVersion act+ | cabalId /= currentCabalId = do+ eResult <- try act+ throwIO $ ConfigStateFileBadVersion cabalId compId eResult+ | otherwise = act+ deferErrorIfBadVersion getStoredValue+ where+ _ = callStack -- TODO: attach call stack to exception++-- | 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, structuredEncode lbi]+ where+ pkgId = localPackage lbi++-- | Identifier of the current Cabal package.+currentCabalId :: PackageIdentifier+currentCabalId = PackageIdentifier (mkPackageName "Cabal") cabalVersion++-- | Identifier of the current compiler package.+currentCompilerId :: PackageIdentifier+currentCompilerId = PackageIdentifier (mkPackageName System.Info.compilerName)+ (mkVersion' System.Info.compilerVersion)++-- | Parse the @setup-config@ file header, returning the package identifiers+-- for Cabal and the compiler.+parseHeader :: ByteString -- ^ The file contents.+ -> IO (PackageIdentifier, PackageIdentifier)+parseHeader header = case BLC8.words header of+ ["Saved", "package", "config", "for", pkgId, "written", "by", cabalId,+ "using", compId] ->+ maybe (throwIO ConfigStateFileBadHeader) return $ do+ _ <- simpleParsec (fromUTF8LBS pkgId) :: Maybe PackageIdentifier+ cabalId' <- simpleParsec (BLC8.unpack cabalId)+ compId' <- simpleParsec (BLC8.unpack compId)+ return (cabalId', compId')+ _ -> throwIO ConfigStateFileNoHeader++-- | Generate the @setup-config@ file header.+showHeader :: PackageIdentifier -- ^ The processed package.+ -> ByteString+showHeader pkgId = BLC8.unwords+ [ "Saved", "package", "config", "for"+ , toUTF8LBS $ prettyShow pkgId+ , "written", "by"+ , BLC8.pack $ prettyShow currentCabalId+ , "using"+ , BLC8.pack $ prettyShow currentCompilerId+ ]++-- | Check that localBuildInfoFile is up-to-date with respect to the+-- .cabal file.+checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool+checkPersistBuildConfigOutdated distPref pkg_descr_file =+ 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+ -- Determine the component we are configuring, if a user specified+ -- one on the command line. We use a fake, flattened version of+ -- the package since at this point, we're not really sure what+ -- components we *can* configure. @Nothing@ means that we should+ -- configure everything (the old behavior).+ (mb_cname :: Maybe ComponentName) <- do+ let flat_pkg_descr = flattenPackageDescription pkg_descr0+ targets <- readBuildTargets verbosity flat_pkg_descr (configArgs cfg)+ -- TODO: bleat if you use the module/file syntax+ let targets' = [ cname | BuildTargetComponent cname <- targets ]+ case targets' of+ _ | null (configArgs cfg) -> return Nothing+ [cname] -> return (Just cname)+ [] -> die' verbosity "No valid component targets found"+ _ -> die' verbosity+ "Can only configure either single component or all of them"++ let use_external_internal_deps = isJust mb_cname+ case mb_cname of+ Nothing -> setupMessage verbosity "Configuring" (packageId pkg_descr0)+ Just cname -> setupMessage' verbosity "Configuring" (packageId pkg_descr0)+ cname (Just (configInstantiateWith cfg))++ -- configCID is only valid for per-component configure+ when (isJust (flagToMaybe (configCID cfg)) && isNothing mb_cname) $+ die' verbosity "--cid is only supported for per-component configure"++ checkDeprecatedFlags verbosity cfg+ checkExactConfiguration verbosity 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 :: PackageDBStack+ packageDbs+ = interpretPackageDbFlags+ (fromFlag (configUserInstall cfg))+ (configPackageDBs cfg)++ -- comp: the compiler we're building with+ -- compPlatform: the platform we're building for+ -- programDb: location and args of all programs we're+ -- building with+ (comp :: Compiler,+ compPlatform :: Platform,+ programDb :: ProgramDb)+ <- configCompilerEx+ (flagToMaybe (configHcFlavor cfg))+ (flagToMaybe (configHcPath cfg))+ (flagToMaybe (configHcPkg cfg))+ (mkProgramDb cfg (configPrograms cfg))+ (lessVerbose verbosity)++ -- The InstalledPackageIndex of all installed packages+ installedPackageSet :: InstalledPackageIndex+ <- getInstalledPackages (lessVerbose verbosity) comp+ packageDbs programDb++ -- The set of package names which are "shadowed" by internal+ -- packages, and which component they map to+ let internalPackageSet :: Set LibraryName+ internalPackageSet = getInternalLibraries pkg_descr0++ -- Make a data structure describing what components are enabled.+ let enabled :: ComponentRequestedSpec+ enabled = case mb_cname of+ Just cname -> OneComponentRequestedSpec cname+ Nothing -> ComponentRequestedSpec+ -- The flag name (@--enable-tests@) is a+ -- little bit of a misnomer, because+ -- just passing this flag won't+ -- "enable", in our internal+ -- nomenclature; it's just a request; a+ -- @buildable: False@ might make it+ -- not possible to enable.+ { testsRequested = fromFlag (configTests cfg)+ , benchmarksRequested =+ fromFlag (configBenchmarks cfg) }+ -- Some sanity checks related to enabling components.+ when (isJust mb_cname+ && (fromFlag (configTests cfg) || fromFlag (configBenchmarks cfg))) $+ die' verbosity $+ "--enable-tests/--enable-benchmarks are incompatible with" +++ " explicitly specifying a component to configure."++ -- Some sanity checks related to dynamic/static linking.+ when (fromFlag (configDynExe cfg) && fromFlag (configFullyStaticExe cfg)) $+ die' verbosity $+ "--enable-executable-dynamic and --enable-executable-static" +++ " are incompatible with each other."++ -- 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 :: [PackageVersionConstraint],+ requiredDepsMap :: Map (PackageName, ComponentName) InstalledPackageInfo)+ <- either (die' verbosity) return $+ combinedConstraints (configConstraints cfg)+ (configDependencies cfg)+ installedPackageSet++ -- pkg_descr: The resolved package description, that does not contain any+ -- conditionals, because we 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 :: PackageDescription,+ flags :: FlagAssignment)+ <- configureFinalizedPackage verbosity cfg enabled+ allConstraints+ (dependencySatisfiable+ use_external_internal_deps+ (fromFlagOrDefault False (configExactConfiguration cfg))+ (fromFlagOrDefault False (configAllowDependingOnPrivateLibs cfg))+ (packageName pkg_descr0)+ installedPackageSet+ internalPackageSet+ requiredDepsMap)+ comp+ compPlatform+ pkg_descr0++ debug verbosity $ "Finalized package description:\n"+ ++ showPackageDescription pkg_descr++ let cabalFileDir = maybe "." takeDirectory $+ flagToMaybe (configCabalFilePath cfg)+ checkCompilerProblems verbosity comp pkg_descr enabled+ checkPackageProblems verbosity cabalFileDir pkg_descr0+ (updatePackageDescription pbi pkg_descr)++ -- The list of 'InstalledPackageInfo' recording the selected+ -- dependencies 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),+ --+ -- In the presence of Backpack, these package dependencies are+ -- NOT complete: they only ever include the INDEFINITE+ -- dependencies. After we apply an instantiation, we'll get+ -- definite references which constitute extra dependencies.+ -- (Why not have cabal-install pass these in explicitly?+ -- For one it's deterministic; for two, we need to associate+ -- them with renamings which would require a far more complicated+ -- input scheme than what we have today.)+ externalPkgDeps :: [PreExistingComponent]+ <- configureDependencies+ verbosity+ use_external_internal_deps+ internalPackageSet+ installedPackageSet+ requiredDepsMap+ pkg_descr+ enabled++ -- Compute installation directory templates, based on user+ -- configuration.+ --+ -- TODO: Move this into a helper function.+ defaultDirs :: InstallDirTemplates+ <- defaultInstallDirs' use_external_internal_deps+ (compilerFlavor comp)+ (fromFlag (configUserInstall cfg))+ (hasLibs pkg_descr)+ let installDirs :: InstallDirTemplates+ installDirs = combineInstallDirs fromFlagOrDefault+ defaultDirs (configInstallDirs cfg)++ -- Check languages and extensions+ -- TODO: Move this into a helper function.+ let langlist = nub $ catMaybes $ map defaultLanguage+ (enabledBuildInfos pkg_descr enabled)+ let langs = unsupportedLanguages comp langlist+ when (not (null langs)) $+ die' verbosity $ "The package " ++ prettyShow (packageId pkg_descr0)+ ++ " requires the following languages which are not "+ ++ "supported by " ++ prettyShow (compilerId comp) ++ ": "+ ++ intercalate ", " (map prettyShow langs)+ let extlist = nub $ concatMap allExtensions+ (enabledBuildInfos pkg_descr enabled)+ let exts = unsupportedExtensions comp extlist+ when (not (null exts)) $+ die' verbosity $ "The package " ++ prettyShow (packageId pkg_descr0)+ ++ " requires the following language extensions which are not "+ ++ "supported by " ++ prettyShow (compilerId comp) ++ ": "+ ++ intercalate ", " (map prettyShow exts)++ -- Check foreign library build requirements+ let flibs = [flib | CFLib flib <- enabledComponents pkg_descr enabled]+ let unsupportedFLibs = unsupportedForeignLibs comp compPlatform flibs+ when (not (null unsupportedFLibs)) $+ die' verbosity $ "Cannot build some foreign libraries: "+ ++ intercalate "," unsupportedFLibs++ -- Configure certain external build tools, see below for which ones.+ let requiredBuildTools = do+ bi <- enabledBuildInfos pkg_descr enabled+ -- First, we collect any tool dep that we know is external. This is,+ -- in practice:+ --+ -- 1. `build-tools` entries on the whitelist+ --+ -- 2. `build-tool-depends` that aren't from the current package.+ let externBuildToolDeps =+ [ LegacyExeDependency (unUnqualComponentName eName) versionRange+ | buildTool@(ExeDependency _ eName versionRange)+ <- getAllToolDependencies pkg_descr bi+ , not $ isInternal pkg_descr buildTool ]+ -- Second, we collect any build-tools entry we don't know how to+ -- desugar. We'll never have any idea how to build them, so we just+ -- hope they are already on the PATH.+ let unknownBuildTools =+ [ buildTool+ | buildTool <- buildTools bi+ , Nothing == desugarBuildTool pkg_descr buildTool ]+ externBuildToolDeps ++ unknownBuildTools++ programDb' <-+ configureAllKnownPrograms (lessVerbose verbosity) programDb+ >>= configureRequiredPrograms verbosity requiredBuildTools++ (pkg_descr', programDb'') <-+ configurePkgconfigPackages verbosity pkg_descr programDb' enabled++ -- Compute internal component graph+ --+ -- The general idea is that we take a look at all the source level+ -- components (which may build-depends on each other) and form a graph.+ -- From there, we build a ComponentLocalBuildInfo for each of the+ -- components, which lets us actually build each component.+ -- internalPackageSet+ -- use_external_internal_deps+ (buildComponents :: [ComponentLocalBuildInfo],+ packageDependsIndex :: InstalledPackageIndex) <-+ runLogProgress verbosity $ configureComponentLocalBuildInfos+ verbosity+ use_external_internal_deps+ enabled+ (fromFlagOrDefault False (configDeterministic cfg))+ (configIPID cfg)+ (configCID cfg)+ pkg_descr+ externalPkgDeps+ (configConfigurationsFlags cfg)+ (configInstantiateWith cfg)+ installedPackageSet+ comp++ -- Decide if we're going to compile with split sections.+ split_sections :: Bool <-+ if not (fromFlag $ configSplitSections cfg)+ then return False+ else case compilerFlavor comp of+ GHC | compilerVersion comp >= mkVersion [8,0]+ -> return True+ GHCJS+ -> return True+ _ -> do warn verbosity+ ("this compiler does not support " +++ "--enable-split-sections; ignoring")+ return False++ -- Decide if we're going to compile with split objects.+ split_objs :: Bool <-+ if not (fromFlag $ configSplitObjs cfg)+ then return False+ else case compilerFlavor comp of+ _ | split_sections+ -> do warn verbosity+ ("--enable-split-sections and " +++ "--enable-split-objs are mutually" +++ "exclusive; ignoring the latter")+ return False+ GHC+ -> 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++ withStaticLib_ =+ -- build a static library (all dependent libraries rolled+ -- into a huge .a archive) via GHCs -staticlib flag.+ fromFlagOrDefault False $ configStaticLib cfg++ withDynExe_ = fromFlag $ configDynExe cfg++ withFullyStaticExe_ = fromFlag $ configFullyStaticExe 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."++ setProfLBI <- configureProfiling verbosity cfg comp++ setCoverageLBI <- configureCoverage verbosity cfg comp++++ -- Turn off library and executable stripping when `debug-info` is set+ -- to anything other than zero.+ let+ strip_libexe s f =+ let defaultStrip = fromFlagOrDefault True (f cfg)+ in case fromFlag (configDebugInfo cfg) of+ NoDebugInfo -> return defaultStrip+ _ -> case f cfg of+ Flag True -> do+ warn verbosity $ "Setting debug-info implies "+ ++ s ++ "-stripping: False"+ return False++ _ -> return False++ strip_lib <- strip_libexe "library" configStripLibs+ strip_exe <- strip_libexe "executable" configStripExes+++ let reloc = fromFlagOrDefault False $ configRelocatable cfg++ let buildComponentsMap =+ foldl' (\m clbi -> Map.insertWith (++)+ (componentLocalName clbi) [clbi] m)+ Map.empty buildComponents++ let lbi = (setCoverageLBI . setProfLBI)+ LocalBuildInfo {+ configFlags = cfg,+ flagAssignment = flags,+ componentEnabledSpec = enabled,+ extraConfigArgs = [], -- Currently configure does not+ -- take extra args, but if it+ -- did they would go here.+ installDirTemplates = installDirs,+ compiler = comp,+ hostPlatform = compPlatform,+ buildDir = buildDir,+ cabalFilePath = flagToMaybe (configCabalFilePath cfg),+ componentGraph = Graph.fromDistinctList buildComponents,+ componentNameMap = buildComponentsMap,+ installedPkgs = packageDependsIndex,+ pkgDescrFile = Nothing,+ localPkgDescr = pkg_descr',+ withPrograms = programDb'',+ withVanillaLib = fromFlag $ configVanillaLib cfg,+ withSharedLib = withSharedLib_,+ withStaticLib = withStaticLib_,+ withDynExe = withDynExe_,+ withFullyStaticExe = withFullyStaticExe_,+ withProfLib = False,+ withProfLibDetail = ProfDetailNone,+ withProfExe = False,+ withProfExeDetail = ProfDetailNone,+ withOptimization = fromFlag $ configOptimization cfg,+ withDebugInfo = fromFlag $ configDebugInfo cfg,+ withGHCiLib = fromFlagOrDefault ghciLibByDefault $+ configGHCiLib cfg,+ splitSections = split_sections,+ splitObjs = split_objs,+ stripExes = strip_exe,+ stripLibs = strip_lib,+ exeCoverage = False,+ libCoverage = False,+ withPackageDB = packageDbs,+ progPrefix = fromFlag $ configProgPrefix cfg,+ progSuffix = fromFlag $ configProgSuffix cfg,+ relocatable = reloc+ }++ when reloc (checkRelocatable verbosity pkg_descr lbi)++ -- TODO: This is not entirely correct, because the dirs may vary+ -- across libraries/executables+ let dirs = absoluteInstallDirs pkg_descr lbi NoCopyDest+ relative = prefixRelativeInstallDirs (packageId pkg_descr) lbi++ -- PKGROOT: allowing ${pkgroot} to be passed as --prefix to+ -- cabal configure, is only a hidden option. It allows packages+ -- to be relocatable with their package database. This however+ -- breaks when the Paths_* or other includes are used that+ -- contain hard coded paths. This is still an open TODO.+ --+ -- Allowing ${pkgroot} here, however requires less custom hooks+ -- in scripts that *really* want ${pkgroot}. See haskell/cabal/#4872+ unless (isAbsolute (prefix dirs)+ || "${pkgroot}" `isPrefixOf` prefix dirs) $ die' verbosity $+ "expected an absolute directory name for --prefix: " ++ prefix dirs++ when ("${pkgroot}" `isPrefixOf` prefix dirs) $+ warn verbosity $ "Using ${pkgroot} in prefix " ++ prefix dirs+ ++ " will not work if you rely on the Path_* module "+ ++ " or other hard coded paths. Cabal does not yet "+ ++ " support fully relocatable builds! "+ ++ " See #462 #2302 #2994 #3305 #3473 #3586 #3909"+ ++ " #4097 #4291 #4872"++ info verbosity $ "Using " ++ prettyShow currentCabalId+ ++ " compiled by " ++ prettyShow 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 "Executables" (bindir dirs) (bindir relative)+ dirinfo "Libraries" (libdir dirs) (libdir relative)+ dirinfo "Dynamic Libraries" (dynlibdir dirs) (dynlibdir relative)+ dirinfo "Private executables" (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 programDb'' ]++ return lbi++ where+ verbosity = fromFlag (configVerbosity cfg)++mkProgramDb :: ConfigFlags -> ProgramDb -> ProgramDb+mkProgramDb cfg initialProgramDb = programDb+ where+ programDb = userSpecifyArgss (configProgramArgs cfg)+ . userSpecifyPaths (configProgramPaths cfg)+ . setProgramSearchPath searchpath+ $ initialProgramDb+ searchpath = getProgramSearchPath initialProgramDb+ ++ 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+ :: Verbosity -> GenericPackageDescription -> ConfigFlags -> IO ()+checkExactConfiguration verbosity pkg_descr0 cfg =+ when (fromFlagOrDefault False (configExactConfiguration cfg)) $ do+ let cmdlineFlags = map fst (unFlagAssignment (configConfigurationsFlags cfg))+ allFlags = map flagName . genPackageFlags $ pkg_descr0+ diffFlags = allFlags \\ cmdlineFlags+ when (not . null $ diffFlags) $+ die' verbosity $ "'--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. finalizePD+-- does the resolution of conditionals, and it takes internalPackageSet+-- as part of its input.+getInternalLibraries :: GenericPackageDescription+ -> Set LibraryName+getInternalLibraries pkg_descr0 =+ -- TODO: some day, executables will be fair game here too!+ let pkg_descr = flattenPackageDescription pkg_descr0+ in Set.fromList (map libName (allLibraries pkg_descr))++-- | Returns true if a dependency is satisfiable. This function may+-- report a dependency satisfiable even when it is not, but not vice+-- versa. This is to be passed to finalize+dependencySatisfiable+ :: Bool -- ^ use external internal deps?+ -> Bool -- ^ exact configuration?+ -> Bool -- ^ allow depending on private libs?+ -> PackageName+ -> InstalledPackageIndex -- ^ installed set+ -> Set LibraryName -- ^ library components+ -> Map (PackageName, ComponentName) InstalledPackageInfo+ -- ^ required dependencies+ -> (Dependency -> Bool)+dependencySatisfiable+ use_external_internal_deps+ exact_config+ allow_private_deps+ pn installedPackageSet packageLibraries requiredDepsMap+ (Dependency depName vr sublibs)+ | 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,+ -- 'finalizePD' will fail.+ -- TODO: mention '--exact-configuration' in the error message+ -- when this fails?+ = if isInternalDep && not use_external_internal_deps+ -- Except for internal deps, when we're NOT per-component mode;+ -- those are just True.+ then internalDepSatisfiable+ else+ -- Backward compatibility for the old sublibrary syntax+ (sublibs == mainLibSet+ && Map.member+ (pn, CLibName $ LSubLibName $+ packageNameToUnqualComponentName depName)+ requiredDepsMap)++ || all visible sublibs++ | isInternalDep+ = if use_external_internal_deps+ -- When we are doing per-component configure, we now need to+ -- test if the internal dependency is in the index. This has+ -- DIFFERENT semantics from normal dependency satisfiability.+ then internalDepSatisfiableExternally+ -- If a 'PackageName' is defined by an internal component, the dep is+ -- satisfiable (we're going to build it ourselves)+ else internalDepSatisfiable++ | otherwise+ = depSatisfiable++ where+ -- Internal dependency is when dependency is the same as package.+ isInternalDep = pn == depName++ depSatisfiable =+ not . null $ PackageIndex.lookupDependency installedPackageSet depName vr++ internalDepSatisfiable =+ Set.isSubsetOf (NES.toSet sublibs) packageLibraries+ internalDepSatisfiableExternally =+ all (\ln -> not $ null $ PackageIndex.lookupInternalDependency installedPackageSet pn vr ln) sublibs++ -- Check whether a library exists and is visible.+ -- We don't disambiguate between dependency on non-existent or private+ -- library yet, so we just return a bool and later report a generic error.+ visible lib = maybe+ False -- Does not even exist (wasn't in the depsMap)+ (\ipi -> IPI.libVisibility ipi == LibraryVisibilityPublic+ -- If the override is enabled, the visibility does+ -- not matter (it's handled externally)+ || allow_private_deps+ -- If it's a library of the same package then it's+ -- always visible.+ -- This is only triggered when passing a component+ -- of the same package as --dependency, such as in:+ -- cabal-testsuite/PackageTests/ConfigureComponent/SubLib/setup-explicit.test.hs+ || pkgName (IPI.sourcePackageId ipi) == pn)+ maybeIPI+ where maybeIPI = Map.lookup (depName, CLibName lib) requiredDepsMap++-- | Finalize a generic package description. The workhorse is+-- 'finalizePD' but there's a bit of other nattering+-- about necessary.+--+-- TODO: what exactly is the business with @flaggedTests@ and+-- @flaggedBenchmarks@?+configureFinalizedPackage+ :: Verbosity+ -> ConfigFlags+ -> ComponentRequestedSpec+ -> [PackageVersionConstraint]+ -> (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 enabled+ allConstraints satisfies comp compPlatform pkg_descr0 = do++ (pkg_descr0', flags) <-+ case finalizePD+ (configConfigurationsFlags cfg)+ enabled+ satisfies+ compPlatform+ (compilerInfo comp)+ allConstraints+ pkg_descr0+ of Right r -> return r+ Left missing ->+ die' verbosity $ "Encountered missing or private dependencies:\n"+ ++ (render . nest 4 . sep . punctuate comma+ . map (pretty . 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'++ unless (nullFlagAssignment flags) $+ info verbosity $ "Flags chosen: "+ ++ intercalate ", " [ unFlagName fn ++ "=" ++ prettyShow value+ | (fn, value) <- unFlagAssignment flags ]++ return (pkg_descr, flags)+ where+ addExtraIncludeLibDirs pkg_descr =+ let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg+ , extraFrameworkDirs = configExtraFrameworkDirs cfg+ , includeDirs = configExtraIncludeDirs cfg}+ modifyLib l = l{ libBuildInfo = libBuildInfo l+ `mappend` extraBi }+ modifyExecutable e = e{ buildInfo = buildInfo e+ `mappend` extraBi}+ modifyForeignLib f = f{ foreignLibBuildInfo = foreignLibBuildInfo f+ `mappend` extraBi}+ modifyTestsuite t = t{ testBuildInfo = testBuildInfo t+ `mappend` extraBi}+ modifyBenchmark b = b{ benchmarkBuildInfo = benchmarkBuildInfo b+ `mappend` extraBi}+ in pkg_descr+ { library = modifyLib `fmap` library pkg_descr+ , subLibraries = modifyLib `map` subLibraries pkg_descr+ , executables = modifyExecutable `map` executables pkg_descr+ , foreignLibs = modifyForeignLib `map` foreignLibs pkg_descr+ , testSuites = modifyTestsuite `map` testSuites pkg_descr+ , benchmarks = modifyBenchmark `map` benchmarks pkg_descr+ }++-- | Check for use of Cabal features which require compiler support+checkCompilerProblems+ :: Verbosity -> Compiler -> PackageDescription -> ComponentRequestedSpec -> IO ()+checkCompilerProblems verbosity comp pkg_descr enabled = do+ unless (renamingPackageFlagsSupported comp ||+ all (all (isDefaultIncludeRenaming . mixinIncludeRenaming) . mixins)+ (enabledBuildInfos pkg_descr enabled)) $+ die' verbosity $+ "Your compiler does not support thinning and renaming on "+ ++ "package flags. To use this feature you must use "+ ++ "GHC 7.9 or later."++ when (any (not.null.reexportedModules) (allLibraries pkg_descr)+ && not (reexportedModulesSupported comp)) $+ die' verbosity $+ "Your compiler does not support module re-exports. To use "+ ++ "this feature you must use GHC 7.9 or later."++ when (any (not.null.signatures) (allLibraries pkg_descr)+ && not (backpackSupported comp)) $+ die' verbosity $+ "Your compiler does not support Backpack. To use "+ ++ "this feature you must use GHC 8.1 or later."++-- | Select dependencies for the package.+configureDependencies+ :: Verbosity+ -> UseExternalInternalDeps+ -> Set LibraryName+ -> InstalledPackageIndex -- ^ installed packages+ -> Map (PackageName, ComponentName) InstalledPackageInfo -- ^ required deps+ -> PackageDescription+ -> ComponentRequestedSpec+ -> IO [PreExistingComponent]+configureDependencies verbosity use_external_internal_deps+ packageLibraries installedPackageSet requiredDepsMap pkg_descr enableSpec = do+ let failedDeps :: [FailedDependency]+ allPkgDeps :: [ResolvedDependency]+ (failedDeps, allPkgDeps) = partitionEithers $ concat+ [ fmap (\s -> (dep, s)) <$> status+ | dep <- enabledBuildDepends pkg_descr enableSpec+ , let status = selectDependency (package pkg_descr)+ packageLibraries installedPackageSet+ requiredDepsMap use_external_internal_deps dep ]++ internalPkgDeps = [ pkgid+ | (_, InternalDependency pkgid) <- allPkgDeps ]+ -- NB: we have to SAVE the package name, because this is the only+ -- way we can be able to resolve package names in the package+ -- description.+ externalPkgDeps = [ pec+ | (_, ExternalDependency pec) <- allPkgDeps ]++ when (not (null internalPkgDeps)+ && not (newPackageDepsBehaviour pkg_descr)) $+ die' verbosity $ "The field 'build-depends: "+ ++ intercalate ", " (map (prettyShow . 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 verbosity failedDeps+ reportSelectedDependencies verbosity allPkgDeps++ return externalPkgDeps++-- | Select and apply coverage settings for the build based on the+-- 'ConfigFlags' and 'Compiler'.+configureCoverage :: Verbosity -> ConfigFlags -> Compiler+ -> IO (LocalBuildInfo -> LocalBuildInfo)+configureCoverage verbosity cfg comp = do+ let tryExeCoverage = fromFlagOrDefault False (configCoverage cfg)+ tryLibCoverage = fromFlagOrDefault tryExeCoverage+ (mappend (configCoverage cfg) (configLibCoverage cfg))+ if coverageSupported comp+ then do+ let apply lbi = lbi { libCoverage = tryLibCoverage+ , exeCoverage = tryExeCoverage+ }+ return apply+ else do+ let apply lbi = lbi { libCoverage = False+ , exeCoverage = False+ }+ when (tryExeCoverage || tryLibCoverage) $ warn verbosity+ ("The compiler " ++ showCompilerId comp ++ " does not support "+ ++ "program coverage. Program coverage has been disabled.")+ return apply++-- | Compute the effective value of the profiling flags+-- @--enable-library-profiling@ and @--enable-executable-profiling@+-- from the specified 'ConfigFlags'. This may be useful for+-- external Cabal tools which need to interact with Setup in+-- a backwards-compatible way: the most predictable mechanism+-- for enabling profiling across many legacy versions is to+-- NOT use @--enable-profiling@ and use those two flags instead.+--+-- Note that @--enable-executable-profiling@ also affects profiling+-- of benchmarks and (non-detailed) test suites.+computeEffectiveProfiling :: ConfigFlags -> (Bool {- lib -}, Bool {- exe -})+computeEffectiveProfiling cfg =+ -- 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.+ --+ -- The --profiling-detail and --library-profiling-detail flags behave+ -- similarly+ let tryExeProfiling = fromFlagOrDefault False+ (mappend (configProf cfg) (configProfExe cfg))+ tryLibProfiling = fromFlagOrDefault tryExeProfiling+ (mappend (configProf cfg) (configProfLib cfg))+ in (tryLibProfiling, tryExeProfiling)++-- | Select and apply profiling settings for the build based on the+-- 'ConfigFlags' and 'Compiler'.+configureProfiling :: Verbosity -> ConfigFlags -> Compiler+ -> IO (LocalBuildInfo -> LocalBuildInfo)+configureProfiling verbosity cfg comp = do+ let (tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling cfg++ tryExeProfileLevel = fromFlagOrDefault ProfDetailDefault+ (configProfDetail cfg)+ tryLibProfileLevel = fromFlagOrDefault ProfDetailDefault+ (mappend+ (configProfDetail cfg)+ (configProfLibDetail cfg))++ checkProfileLevel (ProfDetailOther other) = do+ warn verbosity+ ("Unknown profiling detail level '" ++ other+ ++ "', using default.\nThe profiling detail levels are: "+ ++ intercalate ", "+ [ name | (name, _, _) <- knownProfDetailLevels ])+ return ProfDetailDefault+ checkProfileLevel other = return other++ (exeProfWithoutLibProf, applyProfiling) <-+ if profilingSupported comp+ then do+ exeLevel <- checkProfileLevel tryExeProfileLevel+ libLevel <- checkProfileLevel tryLibProfileLevel+ let apply lbi = lbi { withProfLib = tryLibProfiling+ , withProfLibDetail = libLevel+ , withProfExe = tryExeProfiling+ , withProfExeDetail = exeLevel+ }+ return (tryExeProfiling && not tryLibProfiling, apply)+ else do+ let apply lbi = lbi { withProfLib = False+ , withProfLibDetail = ProfDetailNone+ , withProfExe = False+ , withProfExeDetail = ProfDetailNone+ }+ when (tryExeProfiling || tryLibProfiling) $ warn verbosity+ ("The compiler " ++ showCompilerId comp ++ " does not support "+ ++ "profiling. Profiling has been disabled.")+ return (False, apply)++ when exeProfWithoutLibProf $ warn verbosity+ ("Executables will be built with profiling, but library "+ ++ "profiling is disabled. Linking will fail if any executables "+ ++ "depend on the library.")++ return applyProfiling++-- -----------------------------------------------------------------------------+-- 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 " ++ prettyShow v++hackageUrl :: String+hackageUrl = "http://hackage.haskell.org/package/"++type ResolvedDependency = (Dependency, DependencyResolution)++data DependencyResolution+ -- | An external dependency from the package database, OR an+ -- internal dependency which we are getting from the package+ -- database.+ = ExternalDependency PreExistingComponent+ -- | An internal dependency ('PackageId' should be a library name)+ -- which we are going to have to build. (The+ -- 'PackageId' here is a hack to get a modest amount of+ -- polymorphism out of the 'Package' typeclass.)+ | InternalDependency PackageId++data FailedDependency = DependencyNotExists PackageName+ | DependencyMissingInternal PackageName LibraryName+ | DependencyNoVersion Dependency++-- | Test for a package dependency and record the version we have installed.+selectDependency :: PackageId -- ^ Package id of current package+ -> Set LibraryName -- ^ package libraries+ -> InstalledPackageIndex -- ^ Installed packages+ -> Map (PackageName, ComponentName) InstalledPackageInfo+ -- ^ Packages for which we have been given specific deps to+ -- use+ -> UseExternalInternalDeps -- ^ Are we configuring a+ -- single component?+ -> Dependency+ -> [Either FailedDependency DependencyResolution]+selectDependency pkgid internalIndex installedIndex requiredDepsMap+ use_external_internal_deps+ (Dependency dep_pkgname vr libs) =+ -- 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".+ if dep_pkgname == pn+ then+ if use_external_internal_deps+ then do_external_internal <$> NES.toList libs+ else do_internal <$> NES.toList libs+ else+ do_external_external <$> NES.toList libs+ where+ pn = packageName pkgid++ -- It's an internal library, and we're not per-component build+ do_internal lib+ | Set.member lib internalIndex+ = Right $ InternalDependency $ PackageIdentifier dep_pkgname $ packageVersion pkgid++ | otherwise+ = Left $ DependencyMissingInternal dep_pkgname lib++ -- We have to look it up externally+ do_external_external :: LibraryName -> Either FailedDependency DependencyResolution+ do_external_external lib = do+ ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of+ -- If we know the exact pkg to use, then use it.+ Just pkginstance -> Right pkginstance+ -- Otherwise we just pick an arbitrary instance of the latest version.+ Nothing -> case pickLastIPI $ PackageIndex.lookupDependency installedIndex dep_pkgname vr of+ Nothing -> Left (DependencyNotExists dep_pkgname)+ Just pkg -> Right pkg+ return $ ExternalDependency $ ipiToPreExistingComponent ipi++ do_external_internal :: LibraryName -> Either FailedDependency DependencyResolution+ do_external_internal lib = do+ ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of+ -- If we know the exact pkg to use, then use it.+ Just pkginstance -> Right pkginstance+ Nothing -> case pickLastIPI $ PackageIndex.lookupInternalDependency installedIndex pn vr lib of+ -- It's an internal library, being looked up externally+ Nothing -> Left (DependencyMissingInternal dep_pkgname lib)+ Just pkg -> Right pkg+ return $ ExternalDependency $ ipiToPreExistingComponent ipi++ pickLastIPI :: [(Version, [InstalledPackageInfo])] -> Maybe InstalledPackageInfo+ pickLastIPI pkgs = safeHead . snd . last =<< nonEmpty pkgs++reportSelectedDependencies :: Verbosity+ -> [ResolvedDependency] -> IO ()+reportSelectedDependencies verbosity deps =+ info verbosity $ unlines+ [ "Dependency " ++ prettyShow (simplifyDependency dep)+ ++ ": using " ++ prettyShow pkgid+ | (dep, resolution) <- deps+ , let pkgid = case resolution of+ ExternalDependency pkg' -> packageId pkg'+ InternalDependency pkgid' -> pkgid' ]++reportFailedDependencies :: Verbosity -> [FailedDependency] -> IO ()+reportFailedDependencies _ [] = return ()+reportFailedDependencies verbosity failed =+ die' verbosity (intercalate "\n\n" (map reportFailedDependency failed))++ where+ reportFailedDependency (DependencyNotExists pkgname) =+ "there is no version of " ++ prettyShow pkgname ++ " installed.\n"+ ++ "Perhaps you need to download and install it from\n"+ ++ hackageUrl ++ prettyShow pkgname ++ "?"++ reportFailedDependency (DependencyMissingInternal pkgname lib) =+ "internal dependency " ++ prettyShow (prettyLibraryNameComponent lib) ++ " not installed.\n"+ ++ "Perhaps you need to configure and install it first?\n"+ ++ "(This library was defined by " ++ prettyShow pkgname ++ ")"++ reportFailedDependency (DependencyNoVersion dep) =+ "cannot satisfy dependency " ++ prettyShow (simplifyDependency dep) ++ "\n"++-- | List all installed packages in the given package databases.+-- Non-existent package databases do not cause errors, they just get skipped+-- with a warning and treated as empty ones, since technically they do not+-- contain any package.+getInstalledPackages :: Verbosity -> Compiler+ -> PackageDBStack -- ^ The stack of package databases.+ -> ProgramDb+ -> IO InstalledPackageIndex+getInstalledPackages verbosity comp packageDBs progdb = do+ when (null packageDBs) $+ die' verbosity $ "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..."+ -- do not check empty packagedbs (ghc-pkg would error out)+ packageDBs' <- filterM packageDBExists packageDBs+ case compilerFlavor comp of+ GHC -> GHC.getInstalledPackages verbosity comp packageDBs' progdb+ GHCJS -> GHCJS.getInstalledPackages verbosity packageDBs' progdb+ UHC -> UHC.getInstalledPackages verbosity comp packageDBs' progdb+ HaskellSuite {} ->+ HaskellSuite.getInstalledPackages verbosity packageDBs' progdb+ flv -> die' verbosity $ "don't know how to find the installed packages for "+ ++ prettyShow flv+ where+ packageDBExists (SpecificPackageDB path) = do+ exists <- doesPathExist path+ unless exists $+ warn verbosity $ "Package db " <> path <> " does not exist yet"+ return exists+ -- Checking the user and global package dbs is more complicated and needs+ -- way more data. Also ghc-pkg won't error out unless the user/global+ -- pkgdb is overridden with an empty one, so we just don't check for them.+ packageDBExists UserPackageDB = pure True+ packageDBExists GlobalPackageDB = pure True++-- | 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 -> ProgramDb+ -> IO InstalledPackageIndex+getPackageDBContents verbosity comp packageDB progdb = do+ info verbosity "Reading installed packages..."+ case compilerFlavor comp of+ GHC -> GHC.getPackageDBContents verbosity packageDB progdb+ GHCJS -> GHCJS.getPackageDBContents verbosity packageDB progdb+ -- For other compilers, try to fall back on 'getInstalledPackages'.+ _ -> getInstalledPackages verbosity comp [packageDB] progdb+++-- | 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+ -> ProgramDb -> Platform+ -> IO [FilePath]+getInstalledPackagesMonitorFiles verbosity comp packageDBs progdb platform =+ case compilerFlavor comp of+ GHC -> GHC.getInstalledPackagesMonitorFiles+ verbosity platform progdb packageDBs+ other -> do+ warn verbosity $ "don't know how to find change monitoring files for "+ ++ "the installed package databases for " ++ prettyShow 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++-- 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+ :: [PackageVersionConstraint]+ -> [GivenComponent]+ -> InstalledPackageIndex+ -> Either String ([PackageVersionConstraint],+ Map (PackageName, ComponentName) InstalledPackageInfo)+combinedConstraints constraints dependencies installedPackages = do++ when (not (null badComponentIds)) $+ Left $ render $ text "The following package dependencies were requested"+ $+$ nest 4 (dispDependencies badComponentIds)+ $+$ text "however the given installed package instance does not exist."++ --TODO: we don't check that all dependencies are used!++ return (allConstraints, idConstraintMap)++ where+ allConstraints :: [PackageVersionConstraint]+ allConstraints = constraints+ ++ [ thisPackageVersionConstraint (packageId pkg)+ | (_, _, _, Just pkg) <- dependenciesPkgInfo ]++ idConstraintMap :: Map (PackageName, ComponentName) InstalledPackageInfo+ idConstraintMap = Map.fromList+ -- NB: do NOT use the packageName from+ -- dependenciesPkgInfo!+ [ ((pn, cname), pkg)+ | (pn, cname, _, Just pkg) <- dependenciesPkgInfo ]++ -- The dependencies along with the installed package info, if it exists+ dependenciesPkgInfo :: [(PackageName, ComponentName, ComponentId,+ Maybe InstalledPackageInfo)]+ dependenciesPkgInfo =+ [ (pkgname, CLibName lname, cid, mpkg)+ | GivenComponent pkgname lname cid <- dependencies+ , let mpkg = PackageIndex.lookupComponentId+ installedPackages cid+ ]++ -- 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.+ badComponentIds =+ [ (pkgname, cname, cid)+ | (pkgname, cname, cid, Nothing) <- dependenciesPkgInfo ]++ dispDependencies deps =+ hsep [ text "--dependency="+ <<>> quotes+ (pretty pkgname+ <<>> case cname of+ CLibName LMainLibName -> ""+ CLibName (LSubLibName n) -> ":" <<>> pretty n+ _ -> ":" <<>> pretty cname+ <<>> char '='+ <<>> pretty cid)+ | (pkgname, cname, cid) <- deps ]++-- -----------------------------------------------------------------------------+-- Configuring program dependencies++configureRequiredPrograms :: Verbosity -> [LegacyExeDependency] -> ProgramDb+ -> IO ProgramDb+configureRequiredPrograms verbosity deps progdb =+ foldM (configureRequiredProgram verbosity) progdb deps++-- | Configure a required program, ensuring that it exists in the PATH+-- (or where the user has specified the program must live) and making it+-- available for use via the 'ProgramDb' interface. If the program is+-- known (exists in the input 'ProgramDb'), we will make sure that the+-- program matches the required version; otherwise we will accept+-- any version of the program and assume that it is a simpleProgram.+configureRequiredProgram :: Verbosity -> ProgramDb -> LegacyExeDependency+ -> IO ProgramDb+configureRequiredProgram verbosity progdb+ (LegacyExeDependency progName verRange) =+ case lookupKnownProgram progName progdb of+ Nothing ->+ -- Try to configure it as a 'simpleProgram' automatically+ --+ -- There's a bit of a story behind this line. In old versions+ -- of Cabal, there were only internal build-tools dependencies. So the+ -- behavior in this case was:+ --+ -- - If a build-tool dependency was internal, don't do+ -- any checking.+ --+ -- - If it was external, call 'configureRequiredProgram' to+ -- "configure" the executable. In particular, if+ -- the program was not "known" (present in 'ProgramDb'),+ -- then we would just error. This was fine, because+ -- the only way a program could be executed from 'ProgramDb'+ -- is if some library code from Cabal actually called it,+ -- and the pre-existing Cabal code only calls known+ -- programs from 'defaultProgramDb', and so if it+ -- is calling something else, you have a Custom setup+ -- script, and in that case you are expected to register+ -- the program you want to call in the ProgramDb.+ --+ -- OK, so that was fine, until I (ezyang, in 2016) refactored+ -- Cabal to support per-component builds. In this case, what+ -- was previously an internal build-tool dependency now became+ -- an external one, and now previously "internal" dependencies+ -- are now external. But these are permitted to exist even+ -- when they are not previously configured (something that+ -- can only occur by a Custom script.)+ --+ -- So, I decided, "Fine, let's just accept these in any+ -- case." Thus this line. The alternative would have been to+ -- somehow detect when a build-tools dependency was "internal" (by+ -- looking at the unflattened package description) but this+ -- would also be incompatible with future work to support+ -- external executable dependencies: we definitely cannot+ -- assume they will be preinitialized in the 'ProgramDb'.+ configureProgram verbosity (simpleProgram progName) progdb+ 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+ (_, progdb') <- requireProgram verbosity prog progdb+ return progdb'+ | otherwise -> do+ (_, _, progdb') <- requireProgramVersion verbosity prog verRange progdb+ return progdb'++-- -----------------------------------------------------------------------------+-- Configuring pkg-config package dependencies++configurePkgconfigPackages :: Verbosity -> PackageDescription+ -> ProgramDb -> ComponentRequestedSpec+ -> IO (PackageDescription, ProgramDb)+configurePkgconfigPackages verbosity pkg_descr progdb enabled+ | null allpkgs = return (pkg_descr, progdb)+ | otherwise = do+ (_, _, progdb') <- requireProgramVersion+ (lessVerbose verbosity) pkgConfigProgram+ (orLaterVersion $ mkVersion [0,9,0]) progdb+ traverse_ requirePkg allpkgs+ mlib' <- traverse addPkgConfigBILib (library pkg_descr)+ libs' <- traverse addPkgConfigBILib (subLibraries pkg_descr)+ exes' <- traverse addPkgConfigBIExe (executables pkg_descr)+ tests' <- traverse addPkgConfigBITest (testSuites pkg_descr)+ benches' <- traverse addPkgConfigBIBench (benchmarks pkg_descr)+ let pkg_descr' = pkg_descr { library = mlib',+ subLibraries = libs', executables = exes',+ testSuites = tests', benchmarks = benches' }+ return (pkg_descr', progdb')++ where+ allpkgs = concatMap pkgconfigDepends (enabledBuildInfos pkg_descr enabled)+ pkgconfig = getDbProgramOutput (lessVerbose verbosity)+ pkgConfigProgram progdb++ requirePkg dep@(PkgconfigDependency pkgn range) = do+ version <- pkgconfig ["--modversion", pkg]+ `catchIO` (\_ -> die' verbosity notFound)+ `catchExit` (\_ -> die' verbosity notFound)+ let trim = dropWhile isSpace . dropWhileEnd isSpace+ let v = PkgconfigVersion (toUTF8BS $ trim version)+ if not (withinPkgconfigVersionRange v range)+ then die' verbosity (badVersion v)+ else 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 " ++ prettyShow v+ depSatisfied v = "Dependency " ++ prettyShow dep+ ++ ": using version " ++ prettyShow v++ versionRequirement+ | isAnyPkgconfigVersion range = ""+ | otherwise = " version " ++ prettyShow range++ pkg = unPkgconfigName pkgn++ -- 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 :: [PkgconfigDependency] -> IO BuildInfo+ pkgconfigBuildInfo [] = return mempty+ pkgconfigBuildInfo pkgdeps = do+ let pkgs = nub [ prettyShow pkg | PkgconfigDependency 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 <- getDbProgramOutput verbosity prog progdb ["--cflags"]+-- > ldflags <- getDbProgramOutput verbosity prog progdb ["--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 {+ includeDirs = map (drop 2) includeDirs',+ extraLibs = map (drop 2) extraLibs',+ extraLibDirs = map (drop 2) extraLibDirs',+ ccOptions = cflags',+ ldOptions = ldflags''+ }++-- -----------------------------------------------------------------------------+-- Determining the compiler details++configCompilerAuxEx :: ConfigFlags+ -> IO (Compiler, Platform, ProgramDb)+configCompilerAuxEx cfg = configCompilerEx (flagToMaybe $ configHcFlavor cfg)+ (flagToMaybe $ configHcPath cfg)+ (flagToMaybe $ configHcPkg cfg)+ programDb+ (fromFlag (configVerbosity cfg))+ where+ programDb = mkProgramDb cfg defaultProgramDb++configCompilerEx :: Maybe CompilerFlavor -> Maybe FilePath -> Maybe FilePath+ -> ProgramDb -> Verbosity+ -> IO (Compiler, Platform, ProgramDb)+configCompilerEx Nothing _ _ _ verbosity = die' verbosity "Unknown compiler"+configCompilerEx (Just hcFlavor) hcPath hcPkg progdb verbosity = do+ (comp, maybePlatform, programDb) <- case hcFlavor of+ GHC -> GHC.configure verbosity hcPath hcPkg progdb+ GHCJS -> GHCJS.configure verbosity hcPath hcPkg progdb+ UHC -> UHC.configure verbosity hcPath hcPkg progdb+ HaskellSuite {} -> HaskellSuite.configure verbosity hcPath hcPkg progdb+ _ -> die' verbosity "Unknown compiler"+ return (comp, fromMaybe buildPlatform maybePlatform, programDb)++-- -----------------------------------------------------------------------------+-- Testing C lib and header dependencies++-- Try to build a test C program which includes every header and links every+-- lib. If that fails, try to narrow it down by preprocessing (only) and linking+-- with individual headers and libs. If none is the obvious culprit then give a+-- generic error message.+-- TODO: produce a log file from the compiler errors, if any.+checkForeignDeps :: PackageDescription -> LocalBuildInfo -> Verbosity -> IO ()+checkForeignDeps pkg lbi verbosity =+ ifBuildsWith allHeaders (commonCcArgs ++ makeLdArgs allLibs) -- I'm feeling+ -- lucky+ (return ())+ (do missingLibs <- findMissingLibs+ missingHdr <- findOffendingHdr+ explainErrors missingHdr missingLibs)+ where+ allHeaders = collectField includes+ allLibs = collectField extraLibs++ ifBuildsWith headers args success failure = do+ checkDuplicateHeaders+ ok <- builds (makeProgram headers) args+ if ok then success else failure++ -- Ensure that there is only one header with a given name+ -- in either the generated (most likely by `configure`)+ -- build directory (e.g. `dist/build`) or in the source directory.+ --+ -- If it exists in both, we'll remove the one in the source+ -- directory, as the generated should take precedence.+ --+ -- C compilers like to prefer source local relative includes,+ -- so the search paths provided to the compiler via -I are+ -- ignored if the included file can be found relative to the+ -- including file. As such we need to take drastic measures+ -- and delete the offending file in the source directory.+ checkDuplicateHeaders = do+ let relIncDirs = filter (not . isAbsolute) (collectField includeDirs)+ isHeader = isSuffixOf ".h"+ genHeaders <- for relIncDirs $ \dir ->+ fmap (dir </>) . filter isHeader <$>+ listDirectory (buildDir lbi </> dir) `catchIO` (\_ -> return [])+ srcHeaders <- for relIncDirs $ \dir ->+ fmap (dir </>) . filter isHeader <$>+ listDirectory (baseDir lbi </> dir) `catchIO` (\_ -> return [])+ let commonHeaders = concat genHeaders `intersect` concat srcHeaders+ for_ commonHeaders $ \hdr -> do+ warn verbosity $ "Duplicate header found in "+ ++ (buildDir lbi </> hdr)+ ++ " and "+ ++ (baseDir lbi </> hdr)+ ++ "; removing "+ ++ (baseDir lbi </> hdr)+ removeFile (baseDir lbi </> hdr)++ findOffendingHdr =+ ifBuildsWith allHeaders ccArgs+ (return Nothing)+ (go . Unsafe.tail . inits $ allHeaders) -- inits always contains at least []+ where+ go [] = return Nothing -- cannot happen+ go (hdrs:hdrsInits) =+ -- Try just preprocessing first+ ifBuildsWith hdrs cppArgs+ -- If that works, try compiling too+ (ifBuildsWith hdrs ccArgs+ (go hdrsInits)+ (return . fmap Right . safeLast $ hdrs))+ (return . fmap Left . safeLast $ hdrs)+++ cppArgs = "-E":commonCppArgs -- preprocess only+ ccArgs = "-c":commonCcArgs -- don't try to link++ findMissingLibs = ifBuildsWith [] (makeLdArgs allLibs)+ (return [])+ (filterM (fmap not . libExists) allLibs)++ libExists lib = builds (makeProgram []) (makeLdArgs [lib])++ baseDir lbi' = fromMaybe "." (takeDirectory <$> cabalFilePath lbi')++ commonCppArgs = platformDefines lbi+ -- TODO: This is a massive hack, to work around the+ -- fact that the test performed here should be+ -- PER-component (c.f. the "I'm Feeling Lucky"; we+ -- should NOT be glomming everything together.)+ ++ [ "-I" ++ buildDir lbi </> "autogen" ]+ -- `configure' may generate headers in the build directory+ ++ [ "-I" ++ buildDir lbi </> dir+ | dir <- ordNub (collectField includeDirs)+ , not (isAbsolute dir)]+ -- we might also reference headers from the+ -- packages directory.+ ++ [ "-I" ++ baseDir lbi </> dir+ | dir <- ordNub (collectField includeDirs)+ , not (isAbsolute dir)]+ ++ [ "-I" ++ dir | dir <- ordNub (collectField includeDirs)+ , isAbsolute dir]+ ++ ["-I" ++ baseDir lbi]+ ++ collectField cppOptions+ ++ collectField ccOptions+ ++ [ "-I" ++ dir+ | dir <- ordNub [ dir+ | dep <- deps+ , dir <- IPI.includeDirs dep ]+ -- dedupe include dirs of dependencies+ -- to prevent quadratic blow-up+ ]+ ++ [ opt+ | dep <- deps+ , opt <- IPI.ccOptions dep ]++ commonCcArgs = commonCppArgs+ ++ collectField ccOptions+ ++ [ opt+ | dep <- deps+ , opt <- IPI.ccOptions dep ]++ commonLdArgs = [ "-L" ++ dir+ | dir <- ordNub (collectField extraLibDirs) ]+ ++ collectField ldOptions+ ++ [ "-L" ++ dir+ | dir <- ordNub [ dir+ | dep <- deps+ , dir <- IPI.libraryDirs dep ]+ ]+ --TODO: do we also need dependent packages' ld options?+ makeLdArgs libs = [ "-l"++lib | lib <- libs ] ++ commonLdArgs++ makeProgram hdrs = unlines $+ [ "#include \"" ++ hdr ++ "\"" | hdr <- hdrs ] +++ ["int main(int argc, char** argv) { return 0; }"]++ collectField f = concatMap f allBi+ allBi = enabledBuildInfos pkg (componentEnabledSpec lbi)+ deps = PackageIndex.topologicalOrder (installedPkgs lbi)++ builds program args = do+ tempDir <- getTemporaryDirectory+ withTempFile tempDir ".c" $ \cName cHnd ->+ withTempFile tempDir "" $ \oNname oHnd -> do+ hPutStrLn cHnd program+ hClose cHnd+ hClose oHnd+ _ <- getDbProgramOutput verbosity+ gccProgram (withPrograms lbi) (cName:"-o":oNname:args)+ return True+ `catchIO` (\_ -> return False)+ `catchExit` (\_ -> return False)++ explainErrors Nothing [] = return () -- should be impossible!+ explainErrors _ _+ | isNothing . lookupProgram gccProgram . withPrograms $ lbi++ = die' verbosity $ unlines+ [ "No working gcc",+ "This package depends on foreign library but we cannot "+ ++ "find a working C compiler. If you have it in a "+ ++ "non-standard location you can use the --with-gcc "+ ++ "flag to specify it." ]++ explainErrors hdr libs = die' verbosity $ unlines $+ [ if plural+ then "Missing dependencies on foreign libraries:"+ else "Missing dependency on a foreign library:"+ | missing ]+ ++ case hdr of+ Just (Left h) -> ["* Missing (or bad) header file: " ++ h ]+ _ -> []+ ++ case libs of+ [] -> []+ [lib] -> ["* Missing (or bad) C library: " ++ lib]+ _ -> ["* Missing (or bad) C libraries: " +++ intercalate ", " libs]+ ++ [if plural then messagePlural else messageSingular | missing]+ ++ case hdr of+ Just (Left _) -> [ headerCppMessage ]+ Just (Right h) -> [ (if missing then "* " else "")+ ++ "Bad header file: " ++ h+ , headerCcMessage ]+ _ -> []++ where+ plural = length libs >= 2+ -- Is there something missing? (as opposed to broken)+ missing = not (null libs)+ || case hdr of Just (Left _) -> True; _ -> False++ messageSingular =+ "This problem can usually be solved by installing the system "+ ++ "package that provides this library (you may need the "+ ++ "\"-dev\" version). If the library is already installed "+ ++ "but in a non-standard location then you can use the flags "+ ++ "--extra-include-dirs= and --extra-lib-dirs= to specify "+ ++ "where it is."+ ++ "If the library file does exist, it may contain errors that "+ ++ "are caught by the C compiler at the preprocessing stage. "+ ++ "In this case you can re-run configure with the verbosity "+ ++ "flag -v3 to see the error messages."+ messagePlural =+ "This problem can usually be solved by installing the system "+ ++ "packages that provide these libraries (you may need the "+ ++ "\"-dev\" versions). If the libraries are already installed "+ ++ "but in a non-standard location then you can use the flags "+ ++ "--extra-include-dirs= and --extra-lib-dirs= to specify "+ ++ "where they are."+ ++ "If the library files do exist, it may contain errors that "+ ++ "are caught by the C compiler at the preprocessing stage. "+ ++ "In this case you can re-run configure with the verbosity "+ ++ "flag -v3 to see the error messages."+ headerCppMessage =+ "If the header file does exist, it may contain errors that "+ ++ "are caught by the C compiler at the preprocessing stage. "+ ++ "In this case you can re-run configure with the verbosity "+ ++ "flag -v3 to see the error messages."+ headerCcMessage =+ "The header file contains a compile error. "+ ++ "You can re-run configure with the verbosity flag "+ ++ "-v3 to see the error messages from the C compiler."++-- | Output package check warnings and errors. Exit if any errors.+checkPackageProblems :: Verbosity+ -> FilePath+ -- ^ Path to the @.cabal@ file's directory+ -> GenericPackageDescription+ -> PackageDescription+ -> IO ()+checkPackageProblems verbosity dir gpkg pkg = do+ ioChecks <- checkPackageFiles verbosity pkg dir+ let pureChecks = checkPackage gpkg (Just pkg)+ errors = [ e | PackageBuildImpossible e <- pureChecks ++ ioChecks ]+ warnings = [ w | PackageBuildWarning w <- pureChecks ++ ioChecks ]+ if null errors+ then traverse_ (warn verbosity) warnings+ else die' verbosity (intercalate "\n\n" errors)++-- | Preform checks if a relocatable build is allowed+checkRelocatable :: Verbosity+ -> PackageDescription+ -> LocalBuildInfo+ -> IO ()+checkRelocatable verbosity pkg lbi+ = sequence_ [ checkOS+ , checkCompiler+ , packagePrefixRelative+ , depsPrefixRelative+ ]+ where+ -- Check if the OS support relocatable builds.+ --+ -- If you add new OS' to this list, and your OS supports dynamic libraries+ -- and RPATH, make sure you add your OS to RPATH-support list of:+ -- Distribution.Simple.GHC.getRPaths+ checkOS+ = unless (os `elem` [ OSX, Linux ])+ $ die' verbosity $ "Operating system: " ++ prettyShow os +++ ", does not support relocatable builds"+ where+ (Platform _ os) = hostPlatform lbi++ -- Check if the Compiler support relocatable builds+ checkCompiler+ = unless (compilerFlavor comp `elem` [ GHC ])+ $ die' verbosity $ "Compiler: " ++ show comp +++ ", does not support relocatable builds"+ where+ comp = compiler lbi++ -- Check if all the install dirs are relative to same prefix+ packagePrefixRelative+ = unless (relativeInstallDirs installDirs)+ $ die' verbosity $ "Installation directories are not prefix_relative:\n" +++ show installDirs+ where+ -- NB: should be good enough to check this against the default+ -- component ID, but if we wanted to be strictly correct we'd+ -- check for each ComponentId.+ installDirs = absoluteInstallDirs pkg lbi NoCopyDest+ p = prefix installDirs+ relativeInstallDirs (InstallDirs {..}) =+ all isJust+ (fmap (stripPrefix p)+ [ bindir, libdir, dynlibdir, libexecdir, includedir, datadir+ , docdir, mandir, htmldir, haddockdir, sysconfdir] )++ -- Check if the library dirs of the dependencies that are in the package+ -- database to which the package is installed are relative to the+ -- prefix of the package+ depsPrefixRelative = do+ pkgr <- GHC.pkgRoot verbosity lbi (registrationPackageDB (withPackageDB lbi))+ traverse_ (doCheck pkgr) ipkgs+ where+ doCheck pkgr ipkg+ | maybe False (== pkgr) (IPI.pkgRoot ipkg)+ = for_ (IPI.libraryDirs ipkg) $ \libdir -> do+ -- When @prefix@ is not under @pkgroot@,+ -- @shortRelativePath prefix pkgroot@ will return a path with+ -- @..@s and following check will fail without @canonicalizePath@.+ canonicalized <- canonicalizePath libdir+ unless (p `isPrefixOf` canonicalized) $+ die' verbosity $ msg libdir+ | otherwise+ = return ()+ -- NB: should be good enough to check this against the default+ -- component ID, but if we wanted to be strictly correct we'd+ -- check for each ComponentId.+ installDirs = absoluteInstallDirs pkg lbi NoCopyDest+ p = prefix installDirs+ ipkgs = PackageIndex.allPackages (installedPkgs lbi)+ msg l = "Library directory of a dependency: " ++ show l +++ "\nis not relative to the installation prefix:\n" +++ show p++-- -----------------------------------------------------------------------------+-- Testing foreign library requirements++unsupportedForeignLibs :: Compiler -> Platform -> [ForeignLib] -> [String]+unsupportedForeignLibs comp platform =+ mapMaybe (checkForeignLibSupported comp platform)++checkForeignLibSupported :: Compiler -> Platform -> ForeignLib -> Maybe String+checkForeignLibSupported comp platform flib = go (compilerFlavor comp)+ where+ go :: CompilerFlavor -> Maybe String+ go GHC+ | compilerVersion comp < mkVersion [7,8] = unsupported [+ "Building foreign libraires is only supported with GHC >= 7.8"+ ]+ | otherwise = goGhcPlatform platform+ go _ = unsupported [+ "Building foreign libraries is currently only supported with ghc"+ ]++ goGhcPlatform :: Platform -> Maybe String+ goGhcPlatform (Platform X86_64 OSX ) = goGhcOsx (foreignLibType flib)+ goGhcPlatform (Platform _ Linux ) = goGhcLinux (foreignLibType flib)+ goGhcPlatform (Platform I386 Windows) = goGhcWindows (foreignLibType flib)+ goGhcPlatform (Platform X86_64 Windows) = goGhcWindows (foreignLibType flib)+ goGhcPlatform _ = unsupported [+ "Building foreign libraries is currently only supported on OSX, "+ , "Linux and Windows"+ ]++ goGhcOsx :: ForeignLibType -> Maybe String+ goGhcOsx ForeignLibNativeShared+ | not (null (foreignLibModDefFile flib)) = unsupported [+ "Module definition file not supported on OSX"+ ]+ | not (null (foreignLibVersionInfo flib)) = unsupported [+ "Foreign library versioning not currently supported on OSX"+ ]+ | otherwise =+ Nothing+ goGhcOsx _ = unsupported [+ "We can currently only build shared foreign libraries on OSX"+ ]++ goGhcLinux :: ForeignLibType -> Maybe String+ goGhcLinux ForeignLibNativeShared+ | not (null (foreignLibModDefFile flib)) = unsupported [+ "Module definition file not supported on Linux"+ ]+ | not (null (foreignLibVersionInfo flib))+ && not (null (foreignLibVersionLinux flib)) = unsupported [+ "You must not specify both lib-version-info and lib-version-linux"+ ]+ | otherwise =+ Nothing+ goGhcLinux _ = unsupported [+ "We can currently only build shared foreign libraries on Linux"+ ]++ goGhcWindows :: ForeignLibType -> Maybe String+ goGhcWindows ForeignLibNativeShared+ | not standalone = unsupported [+ "We can currently only build standalone libraries on Windows. Use\n"+ , " if os(Windows)\n"+ , " options: standalone\n"+ , "in your foreign-library stanza."+ ]+ | not (null (foreignLibVersionInfo flib)) = unsupported [+ "Foreign library versioning not currently supported on Windows.\n"+ , "You can specify module definition files in the mod-def-file field."+ ]+ | otherwise =+ Nothing+ goGhcWindows _ = unsupported [+ "We can currently only build shared foreign libraries on Windows"+ ]++ standalone :: Bool+ standalone = ForeignLibStandalone `elem` foreignLibOptions flib++ unsupported :: [String] -> Maybe String+ unsupported = Just . concat
+ src/Distribution/Simple/Flag.hs view
@@ -0,0 +1,132 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Flag+-- Copyright : Isaac Jones 2003-2004+-- Duncan Coutts 2007+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Defines the 'Flag' type and it's 'Monoid' instance, see+-- <http://www.haskell.org/pipermail/cabal-devel/2007-December/001509.html>+-- for an explanation.+--+-- Split off from "Distribution.Simple.Setup" to break import cycles.+module Distribution.Simple.Flag (+ Flag(..),+ allFlags,+ toFlag,+ fromFlag,+ fromFlagOrDefault,+ flagElim,+ flagToMaybe,+ flagToList,+ maybeToFlag,+ BooleanFlag(..) ) where++import Prelude ()+import Distribution.Compat.Prelude hiding (get)+import Distribution.Compat.Stack++-- ------------------------------------------------------------+-- * Flag type+-- ------------------------------------------------------------++-- | All flags are monoids, they come in two flavours:+--+-- 1. list flags eg+--+-- > --ghc-option=foo --ghc-option=bar+--+-- gives us all the values ["foo", "bar"]+--+-- 2. singular value flags, eg:+--+-- > --enable-foo --disable-foo+--+-- gives us Just False+-- So this Flag type is for the latter singular kind of flag.+-- Its monoid instance gives us the behaviour where it starts out as+-- 'NoFlag' and later flags override earlier ones.+--+data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read, Typeable)++instance Binary a => Binary (Flag a)+instance Structured a => Structured (Flag a)++instance Functor Flag where+ fmap f (Flag x) = Flag (f x)+ fmap _ NoFlag = NoFlag++instance Applicative Flag where+ (Flag x) <*> y = x <$> y+ NoFlag <*> _ = NoFlag+ pure = Flag++instance Monoid (Flag a) where+ mempty = NoFlag+ mappend = (<>)++instance Semigroup (Flag a) where+ _ <> f@(Flag _) = f+ f <> NoFlag = f++instance Bounded a => Bounded (Flag a) where+ minBound = toFlag minBound+ maxBound = toFlag maxBound++instance Enum a => Enum (Flag a) where+ fromEnum = fromEnum . fromFlag+ toEnum = toFlag . toEnum+ enumFrom (Flag a) = map toFlag . enumFrom $ a+ enumFrom _ = []+ enumFromThen (Flag a) (Flag b) = toFlag `map` enumFromThen a b+ enumFromThen _ _ = []+ enumFromTo (Flag a) (Flag b) = toFlag `map` enumFromTo a b+ enumFromTo _ _ = []+ enumFromThenTo (Flag a) (Flag b) (Flag c) = toFlag `map` enumFromThenTo a b c+ enumFromThenTo _ _ _ = []++toFlag :: a -> Flag a+toFlag = Flag++fromFlag :: WithCallStack (Flag a -> a)+fromFlag (Flag x) = x+fromFlag NoFlag = error "fromFlag NoFlag. Use fromFlagOrDefault"++fromFlagOrDefault :: a -> Flag a -> a+fromFlagOrDefault _ (Flag x) = x+fromFlagOrDefault def NoFlag = def++flagToMaybe :: Flag a -> Maybe a+flagToMaybe (Flag x) = Just x+flagToMaybe NoFlag = Nothing++-- | @since 3.4.0.0+flagElim :: b -> (a -> b) -> Flag a -> b+flagElim n _ NoFlag = n+flagElim _ f (Flag x) = f x++flagToList :: Flag a -> [a]+flagToList (Flag x) = [x]+flagToList NoFlag = []++allFlags :: [Flag Bool] -> Flag Bool+allFlags flags = if all (\f -> fromFlagOrDefault False f) flags+ then Flag True+ else NoFlag++maybeToFlag :: Maybe a -> Flag a+maybeToFlag Nothing = NoFlag+maybeToFlag (Just x) = Flag x++-- | Types that represent boolean flags.+class BooleanFlag a where+ asBool :: a -> Bool++instance BooleanFlag Bool where+ asBool = id
+ src/Distribution/Simple/GHC.hs view
@@ -0,0 +1,2087 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE CPP #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.GHC+-- Copyright : Isaac Jones 2003-2007+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is a fairly large module. It contains most of the GHC-specific code for+-- configuring, building and installing packages. It also exports a function+-- for finding out what packages are already installed. Configuring involves+-- finding the @ghc@ and @ghc-pkg@ programs, finding what language extensions+-- this version of ghc supports and returning a 'Compiler' value.+--+-- 'getInstalledPackages' involves calling the @ghc-pkg@ program to find out+-- what packages are installed.+--+-- Building is somewhat complex as there is quite a bit of information to take+-- into account. We have to build libs and programs, possibly for profiling and+-- shared libs. We have to support building libraries that will be usable by+-- GHCi and also ghc's @-split-objs@ feature. We have to compile any C files+-- using ghc. Linking, especially for @split-objs@ is remarkably complex,+-- partly because there tend to be 1,000's of @.o@ files and this can often be+-- more than we can pass to the @ld@ or @ar@ programs in one go.+--+-- Installing for libs and exes involves finding the right files and copying+-- them to the right places. One of the more tricky things about this module is+-- remembering the layout of files in the build directory (which is not+-- explicitly documented) and thus what search dirs are used for various kinds+-- of files.++module Distribution.Simple.GHC (+ getGhcInfo,+ configure,+ getInstalledPackages,+ getInstalledPackagesMonitorFiles,+ getPackageDBContents,+ buildLib, buildFLib, buildExe,+ replLib, replFLib, replExe,+ startInterpreter,+ installLib, installFLib, installExe,+ libAbiHash,+ hcPkgInfo,+ registerPackage,+ componentGhcOptions,+ componentCcGhcOptions,+ getGhcAppDir,+ getLibDir,+ isDynamic,+ getGlobalPackageDB,+ pkgRoot,+ -- * Constructing and deconstructing GHC environment files+ Internal.GhcEnvironmentFileEntry(..),+ Internal.simpleGhcEnvironmentFile,+ Internal.renderGhcEnvironmentFile,+ Internal.writeGhcEnvironmentFile,+ Internal.ghcPlatformAndVersionString,+ readGhcEnvironmentFile,+ parseGhcEnvironmentFile,+ ParseErrorExc(..),+ -- * Version-specific implementation quirks+ getImplInfo,+ GhcImplInfo(..)+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Distribution.Simple.GHC.Internal as Internal+import Distribution.CabalSpecVersion+import Distribution.Simple.GHC.ImplInfo+import Distribution.Simple.GHC.EnvironmentParser+import Distribution.PackageDescription.Utils (cabalBug)+import Distribution.PackageDescription as PD+import Distribution.InstalledPackageInfo (InstalledPackageInfo)+import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo+import Distribution.Simple.PackageIndex (InstalledPackageIndex)+import qualified Distribution.Simple.PackageIndex as PackageIndex+import Distribution.Simple.LocalBuildInfo+import Distribution.Types.ComponentLocalBuildInfo+import qualified Distribution.Simple.Hpc as Hpc+import Distribution.Simple.BuildPaths+import Distribution.Simple.Utils+import Distribution.Package+import qualified Distribution.ModuleName as ModuleName+import Distribution.ModuleName (ModuleName)+import Distribution.Simple.Program+import Distribution.Simple.Program.Builtin (runghcProgram)+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+import qualified Distribution.Simple.Setup as Cabal+import Distribution.Simple.Compiler+import Distribution.Version+import Distribution.System+import Distribution.Verbosity+import Distribution.Pretty+import Distribution.Utils.NubList+import Distribution.Utils.Path+import Language.Haskell.Extension++import Control.Monad (msum, forM_)+import Data.Char (isLower)+import qualified Data.Map as Map+import System.Directory+ ( doesFileExist, getAppUserDataDirectory, createDirectoryIfMissing+ , canonicalizePath, removeFile, renameFile, getDirectoryContents )+import System.FilePath ( (</>), (<.>), takeExtension+ , takeDirectory, replaceExtension+ ,isRelative )+import qualified System.Info+#ifndef mingw32_HOST_OS+import System.Posix (createSymbolicLink)+#endif /* mingw32_HOST_OS */++-- -----------------------------------------------------------------------------+-- Configuring++configure :: Verbosity -> Maybe FilePath -> Maybe FilePath+ -> ProgramDb+ -> IO (Compiler, Maybe Platform, ProgramDb)+configure verbosity hcPath hcPkgPath conf0 = do++ (ghcProg, ghcVersion, progdb1) <-+ requireProgramVersion verbosity ghcProgram+ (orLaterVersion (mkVersion [7,0,1]))+ (userMaybeSpecifyPath "ghc" hcPath conf0)+ let implInfo = ghcVersionImplInfo ghcVersion++ -- Cabal currently supports ghc >= 7.0.1 && < 9.4+ -- ... and the following odd development version+ unless (ghcVersion < mkVersion [9,4]) $+ warn verbosity $+ "Unknown/unsupported 'ghc' version detected "+ ++ "(Cabal " ++ prettyShow cabalVersion ++ " supports 'ghc' version < 9.4): "+ ++ programPath ghcProg ++ " is version " ++ prettyShow ghcVersion++ -- This is slightly tricky, we have to configure ghc first, then we use the+ -- location of ghc to help find ghc-pkg in the case that the user did not+ -- specify the location of ghc-pkg directly:+ (ghcPkgProg, ghcPkgVersion, progdb2) <-+ requireProgramVersion verbosity ghcPkgProgram {+ programFindLocation = guessGhcPkgFromGhcPath ghcProg+ }+ anyVersion (userMaybeSpecifyPath "ghc-pkg" hcPkgPath progdb1)++ when (ghcVersion /= ghcPkgVersion) $ die' verbosity $+ "Version mismatch between ghc and ghc-pkg: "+ ++ programPath ghcProg ++ " is version " ++ prettyShow ghcVersion ++ " "+ ++ programPath ghcPkgProg ++ " is version " ++ prettyShow ghcPkgVersion++ -- Likewise we try to find the matching hsc2hs and haddock programs.+ let hsc2hsProgram' = hsc2hsProgram {+ programFindLocation = guessHsc2hsFromGhcPath ghcProg+ }+ haddockProgram' = haddockProgram {+ programFindLocation = guessHaddockFromGhcPath ghcProg+ }+ hpcProgram' = hpcProgram {+ programFindLocation = guessHpcFromGhcPath ghcProg+ }+ runghcProgram' = runghcProgram {+ programFindLocation = guessRunghcFromGhcPath ghcProg+ }+ progdb3 = addKnownProgram haddockProgram' $+ addKnownProgram hsc2hsProgram' $+ addKnownProgram hpcProgram' $+ addKnownProgram runghcProgram' progdb2++ languages <- Internal.getLanguages verbosity implInfo ghcProg+ extensions0 <- Internal.getExtensions verbosity implInfo ghcProg++ ghcInfo <- Internal.getGhcInfo verbosity implInfo ghcProg+ let ghcInfoMap = Map.fromList ghcInfo+ extensions = -- workaround https://gitlab.haskell.org/ghc/ghc/-/issues/11214+ filterExt JavaScriptFFI $+ -- see 'filterExtTH' comment below+ filterExtTH $ extensions0++ -- 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`+ filterExtTH | ghcVersion < mkVersion [8]+ , Just "NO" <- Map.lookup "Have interpreter" ghcInfoMap+ = filterExt TemplateHaskell+ | otherwise = id++ filterExt ext = filter ((/= EnableExtension ext) . fst)++ let comp = Compiler {+ compilerId = CompilerId GHC ghcVersion,+ compilerAbiTag = NoAbiTag,+ compilerCompat = [],+ compilerLanguages = languages,+ compilerExtensions = extensions,+ compilerProperties = ghcInfoMap+ }+ compPlatform = Internal.targetPlatform ghcInfo+ -- configure gcc and ld+ progdb4 = Internal.configureToolchain implInfo ghcProg ghcInfoMap progdb3+ return (comp, compPlatform, progdb4)++-- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find+-- the corresponding tool; e.g. if the tool is ghc-pkg, we try looking+-- for a versioned or unversioned ghc-pkg in the same dir, that is:+--+-- > /usr/local/bin/ghc-pkg-ghc-6.6.1(.exe)+-- > /usr/local/bin/ghc-pkg-6.6.1(.exe)+-- > /usr/local/bin/ghc-pkg(.exe)+--+guessToolFromGhcPath :: Program -> ConfiguredProgram+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+guessToolFromGhcPath tool ghcProg verbosity searchpath+ = do let toolname = programName tool+ 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 buildPlatform+ guessGhcVersioned dir suf = dir </> (toolname ++ "-ghc" ++ suf)+ <.> exeExtension buildPlatform+ guessVersioned dir suf = dir </> (toolname ++ suf)+ <.> exeExtension buildPlatform+ 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 " ++ given_dir+ debug verbosity $ "candidate locations: " ++ show guesses+ exists <- traverse 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+ let lookedAt = map fst+ . takeWhile (\(_file, exist) -> not exist)+ $ zip guesses exists+ return (Just (fp, lookedAt))++ where takeVersionSuffix :: FilePath -> String+ takeVersionSuffix = takeWhileEndLE isSuffixChar++ isSuffixChar :: Char -> Bool+ isSuffixChar c = isDigit c || c == '.' || c == '-'++-- | 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:+--+-- > /usr/local/bin/ghc-pkg-ghc-6.6.1(.exe)+-- > /usr/local/bin/ghc-pkg-6.6.1(.exe)+-- > /usr/local/bin/ghc-pkg(.exe)+--+guessGhcPkgFromGhcPath :: ConfiguredProgram+ -> 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+-- corresponding hsc2hs, we try looking for both a versioned and unversioned+-- hsc2hs in the same dir, that is:+--+-- > /usr/local/bin/hsc2hs-ghc-6.6.1(.exe)+-- > /usr/local/bin/hsc2hs-6.6.1(.exe)+-- > /usr/local/bin/hsc2hs(.exe)+--+guessHsc2hsFromGhcPath :: ConfiguredProgram+ -> 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++guessHpcFromGhcPath :: ConfiguredProgram+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+guessHpcFromGhcPath = guessToolFromGhcPath hpcProgram++guessRunghcFromGhcPath :: ConfiguredProgram+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+guessRunghcFromGhcPath = guessToolFromGhcPath runghcProgram+++getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)]+getGhcInfo verbosity ghcProg = Internal.getGhcInfo verbosity implInfo ghcProg+ where+ version = fromMaybe (error "GHC.getGhcInfo: no ghc version") $ programVersion ghcProg+ implInfo = ghcVersionImplInfo version++-- | Given a single package DB, return all installed packages.+getPackageDBContents :: Verbosity -> PackageDB -> ProgramDb+ -> IO InstalledPackageIndex+getPackageDBContents verbosity packagedb progdb = do+ pkgss <- getInstalledPackages' verbosity [packagedb] progdb+ toPackageIndex verbosity pkgss progdb++-- | Given a package DB stack, return all installed packages.+getInstalledPackages :: Verbosity -> Compiler -> PackageDBStack+ -> ProgramDb+ -> IO InstalledPackageIndex+getInstalledPackages verbosity comp packagedbs progdb = do+ checkPackageDbEnvVar verbosity+ checkPackageDbStack verbosity comp packagedbs+ pkgss <- getInstalledPackages' verbosity packagedbs progdb+ index <- toPackageIndex verbosity pkgss progdb+ return $! hackRtsPackage index++ where+ hackRtsPackage index =+ case PackageIndex.lookupPackageName index (mkPackageName "rts") of+ [(_,[rts])]+ -> PackageIndex.insert (removeMingwIncludeDir rts) index+ _ -> index -- No (or multiple) ghc rts package is registered!!+ -- Feh, whatever, the ghc test suite does some crazy stuff.++-- | Given a list of @(PackageDB, InstalledPackageInfo)@ pairs, produce a+-- @PackageIndex@. Helper function used by 'getPackageDBContents' and+-- 'getInstalledPackages'.+toPackageIndex :: Verbosity+ -> [(PackageDB, [InstalledPackageInfo])]+ -> ProgramDb+ -> IO InstalledPackageIndex+toPackageIndex verbosity pkgss progdb = do+ -- On Windows, various fields have $topdir/foo rather than full+ -- paths. We need to substitute the right value in so that when+ -- we, for example, call gcc, we have proper paths to give it.+ topDir <- getLibDir' verbosity ghcProg+ let indices = [ PackageIndex.fromList (map (Internal.substTopDir topDir) pkgs)+ | (_, pkgs) <- pkgss ]+ return $! mconcat indices++ where+ ghcProg = fromMaybe (error "GHC.toPackageIndex: no ghc program") $ lookupProgram ghcProgram progdb++-- | Return the 'FilePath' to the GHC application data directory.+--+-- @since 3.4.0.0+getGhcAppDir :: IO FilePath+getGhcAppDir = getAppUserDataDirectory "ghc"++getLibDir :: Verbosity -> LocalBuildInfo -> IO FilePath+getLibDir verbosity lbi =+ dropWhileEndLE isSpace `fmap`+ getDbProgramOutput verbosity ghcProgram+ (withPrograms lbi) ["--print-libdir"]++getLibDir' :: Verbosity -> ConfiguredProgram -> IO FilePath+getLibDir' verbosity ghcProg =+ dropWhileEndLE isSpace `fmap`+ getProgramOutput verbosity ghcProg ["--print-libdir"]+++-- | Return the 'FilePath' to the global GHC package database.+getGlobalPackageDB :: Verbosity -> ConfiguredProgram -> IO FilePath+getGlobalPackageDB verbosity ghcProg =+ dropWhileEndLE isSpace `fmap`+ getProgramOutput 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 = 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 <- getGhcAppDir+ return (appdir </> platformAndVersion </> packageConfFileName)+ where+ platformAndVersion = Internal.ghcPlatformAndVersionString+ platform ghcVersion+ packageConfFileName = "package.conf.d"+ ghcVersion = fromMaybe (error "GHC.getUserPackageDB: no ghc version") $ programVersion ghcProg++checkPackageDbEnvVar :: Verbosity -> IO ()+checkPackageDbEnvVar verbosity =+ Internal.checkPackageDbEnvVar verbosity "GHC" "GHC_PACKAGE_PATH"++checkPackageDbStack :: Verbosity -> Compiler -> PackageDBStack -> IO ()+checkPackageDbStack verbosity comp =+ if flagPackageConf implInfo+ then checkPackageDbStackPre76 verbosity+ else checkPackageDbStackPost76 verbosity+ where implInfo = ghcVersionImplInfo (compilerVersion comp)++checkPackageDbStackPost76 :: Verbosity -> PackageDBStack -> IO ()+checkPackageDbStackPost76 _ (GlobalPackageDB:rest)+ | GlobalPackageDB `notElem` rest = return ()+checkPackageDbStackPost76 verbosity rest+ | GlobalPackageDB `elem` rest =+ die' verbosity $ "If the global package db is specified, it must be "+ ++ "specified first and cannot be specified multiple times"+checkPackageDbStackPost76 _ _ = return ()++checkPackageDbStackPre76 :: Verbosity -> PackageDBStack -> IO ()+checkPackageDbStackPre76 _ (GlobalPackageDB:rest)+ | GlobalPackageDB `notElem` rest = return ()+checkPackageDbStackPre76 verbosity rest+ | GlobalPackageDB `notElem` rest =+ die' verbosity $+ "With current ghc versions the global package db is always used "+ ++ "and must be listed first. This ghc limitation is lifted in GHC 7.6,"+ ++ "see https://gitlab.haskell.org/ghc/ghc/-/issues/5977"+checkPackageDbStackPre76 verbosity _ =+ die' verbosity $ "If the global package db is specified, it must be "+ ++ "specified first and cannot be specified multiple times"++-- GHC < 6.10 put "$topdir/include/mingw" in rts's installDirs. This+-- breaks when you want to use a different gcc, so we need to filter+-- it out.+removeMingwIncludeDir :: InstalledPackageInfo -> InstalledPackageInfo+removeMingwIncludeDir pkg =+ let ids = InstalledPackageInfo.includeDirs pkg+ ids' = filter (not . ("mingw" `isSuffixOf`)) ids+ in pkg { InstalledPackageInfo.includeDirs = ids' }++-- | Get the packages from specific PackageDBs, not cumulative.+--+getInstalledPackages' :: Verbosity -> [PackageDB] -> ProgramDb+ -> IO [(PackageDB, [InstalledPackageInfo])]+getInstalledPackages' verbosity packagedbs progdb =+ sequenceA+ [ do pkgs <- HcPkg.dump (hcPkgInfo progdb) verbosity packagedb+ return (packagedb, pkgs)+ | packagedb <- packagedbs ]++getInstalledPackagesMonitorFiles :: Verbosity -> Platform+ -> ProgramDb+ -> [PackageDB]+ -> IO [FilePath]+getInstalledPackagesMonitorFiles verbosity platform progdb =+ traverse 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")++ ghcProg = fromMaybe (error "GHC.toPackageIndex: no ghc program") $ lookupProgram ghcProgram progdb+++-- -----------------------------------------------------------------------------+-- Building a library++buildLib :: Verbosity -> Cabal.Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> Library -> ComponentLocalBuildInfo -> IO ()+buildLib = buildOrReplLib Nothing++replLib :: [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> Library+ -> ComponentLocalBuildInfo -> IO ()+replLib = buildOrReplLib . Just++buildOrReplLib :: Maybe [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> Library+ -> ComponentLocalBuildInfo -> IO ()+buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do+ let uid = componentUnitId clbi+ libTargetDir = componentBuildDir lbi clbi+ whenVanillaLib forceVanilla =+ when (forceVanilla || withVanillaLib lbi)+ whenProfLib = when (withProfLib lbi)+ whenSharedLib forceShared =+ when (forceShared || withSharedLib lbi)+ whenStaticLib forceStatic =+ when (forceStatic || withStaticLib lbi)+ whenGHCiLib = when (withGHCiLib lbi)+ forRepl = maybe False (const True) mReplFlags+ whenReplLib = when forRepl+ replFlags = fromMaybe mempty mReplFlags+ comp = compiler lbi+ ghcVersion = compilerVersion comp+ implInfo = getImplInfo comp+ platform@(Platform _hostArch hostOS) = hostPlatform lbi+ has_code = not (componentIsIndefinite clbi)++ (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)+ let runGhcProg = runGHC verbosity ghcProg comp platform++ let libBi = libBuildInfo lib++ let isGhcDynamic = isDynamic comp+ dynamicTooSupported = supportsDynamicToo comp+ doingTH = usesTemplateHaskellOrQQ libBi+ forceVanillaLib = doingTH && not isGhcDynamic+ forceSharedLib = doingTH && isGhcDynamic+ -- TH always needs default libs, even when building for profiling++ -- Determine if program coverage should be enabled and if so, what+ -- '-hpcdir' should be.+ let isCoverageEnabled = libCoverage lbi+ -- TODO: Historically HPC files have been put into a directory which+ -- has the package name. I'm going to avoid changing this for+ -- now, but it would probably be better for this to be the+ -- component ID instead...+ pkg_name = prettyShow (PD.package pkg_descr)+ distPref = fromFlag $ configDistPref $ configFlags lbi+ hpcdir way+ | forRepl = mempty -- HPC is not supported in ghci+ | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way pkg_name+ | otherwise = mempty++ createDirectoryIfMissingVerbose verbosity True libTargetDir+ -- TODO: do we need to put hs-boot files into place for mutually recursive+ -- modules?+ let cLikeSources = fromNubListR $ mconcat+ [ toNubListR (cSources libBi)+ , toNubListR (cxxSources libBi)+ , toNubListR (cmmSources libBi)+ , toNubListR (asmSources libBi)+ ]+ cLikeObjs = map (`replaceExtension` objExtension) cLikeSources+ baseOpts = componentGhcOptions verbosity lbi libBi clbi libTargetDir+ vanillaOpts = baseOpts `mappend` mempty {+ ghcOptMode = toFlag GhcModeMake,+ ghcOptNumJobs = numJobs,+ ghcOptInputModules = toNubListR $ allLibModules lib clbi,+ 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 = hcProfOptions GHC libBi,+ ghcOptHPCDir = hpcdir Hpc.Prof+ }++ sharedOpts = vanillaOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptFPic = toFlag True,+ ghcOptHiSuffix = toFlag "dyn_hi",+ ghcOptObjSuffix = toFlag "dyn_o",+ ghcOptExtra = hcSharedOptions GHC libBi,+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }+ linkerOpts = mempty {+ ghcOptLinkOptions = PD.ldOptions libBi+ ++ [ "-static"+ | withFullyStaticExe lbi ]+ -- Pass extra `ld-options` given+ -- through to GHC's linker.+ ++ maybe [] programOverrideArgs+ (lookupProgram ldProgram (withPrograms lbi)),+ ghcOptLinkLibs = extraLibs libBi,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi,+ ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,+ ghcOptLinkFrameworkDirs = toNubListR $+ PD.extraFrameworkDirs libBi,+ ghcOptInputFiles = toNubListR+ [libTargetDir </> x | x <- cLikeObjs]+ }+ replOpts = vanillaOpts {+ ghcOptExtra = Internal.filterGhciFlags+ (ghcOptExtra vanillaOpts)+ <> replFlags,+ ghcOptNumJobs = mempty+ }+ `mappend` linkerOpts+ `mappend` mempty {+ ghcOptMode = toFlag GhcModeInteractive,+ ghcOptOptimisation = toFlag GhcNoOptimisation+ }++ vanillaSharedOpts = vanillaOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,+ ghcOptDynHiSuffix = toFlag "dyn_hi",+ ghcOptDynObjSuffix = toFlag "dyn_o",+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }++ unless (forRepl || null (allLibModules lib clbi)) $+ do let vanilla = whenVanillaLib forceVanillaLib (runGhcProg vanillaOpts)+ shared = whenSharedLib forceSharedLib (runGhcProg sharedOpts)+ useDynToo = dynamicTooSupported &&+ (forceVanillaLib || withVanillaLib lbi) &&+ (forceSharedLib || withSharedLib lbi) &&+ null (hcSharedOptions GHC libBi)+ if not has_code+ then vanilla+ else+ if useDynToo+ then do+ runGhcProg vanillaSharedOpts+ case (hpcdir Hpc.Dyn, hpcdir Hpc.Vanilla) of+ (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+ -- static and dynamically linked executables. We copy+ -- the modules interfaces so they are available under+ -- both ways.+ copyDirectoryRecursive verbosity dynDir vanillaDir+ _ -> return ()+ else if isGhcDynamic+ then do shared; vanilla+ else do vanilla; shared+ whenProfLib (runGhcProg profOpts)++ -- Build any C++ sources separately.+ unless (not has_code || null (cxxSources libBi)) $ do+ info verbosity "Building C++ Sources..."+ sequence_+ [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo+ lbi libBi clbi libTargetDir filename+ vanillaCxxOpts = if isGhcDynamic+ then baseCxxOpts { ghcOptFPic = toFlag True }+ else baseCxxOpts+ profCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptObjSuffix = toFlag "p_o"+ }+ sharedCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptObjSuffix = toFlag "dyn_o"+ }+ odir = fromFlag (ghcOptObjDir vanillaCxxOpts)+ createDirectoryIfMissingVerbose verbosity True odir+ let runGhcProgIfNeeded cxxOpts = do+ needsRecomp <- checkNeedsRecompilation filename cxxOpts+ when needsRecomp $ runGhcProg cxxOpts+ runGhcProgIfNeeded vanillaCxxOpts+ unless forRepl $+ whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCxxOpts)+ unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts)+ | filename <- cxxSources libBi]++ -- build any C sources+ unless (not has_code || null (cSources libBi)) $ do+ info verbosity "Building C Sources..."+ sequence_+ [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo+ lbi libBi clbi libTargetDir filename+ vanillaCcOpts = if isGhcDynamic+ -- Dynamic GHC requires C sources to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseCcOpts { ghcOptFPic = toFlag True }+ else baseCcOpts+ profCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptObjSuffix = toFlag "p_o"+ }+ sharedCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptObjSuffix = toFlag "dyn_o"+ }+ odir = fromFlag (ghcOptObjDir vanillaCcOpts)+ createDirectoryIfMissingVerbose verbosity True odir+ let runGhcProgIfNeeded ccOpts = do+ needsRecomp <- checkNeedsRecompilation filename ccOpts+ when needsRecomp $ runGhcProg ccOpts+ runGhcProgIfNeeded vanillaCcOpts+ unless forRepl $+ whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCcOpts)+ unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts)+ | filename <- cSources libBi]++ -- build any ASM sources+ unless (not has_code || null (asmSources libBi)) $ do+ info verbosity "Building Assembler Sources..."+ sequence_+ [ do let baseAsmOpts = Internal.componentAsmGhcOptions verbosity implInfo+ lbi libBi clbi libTargetDir filename+ vanillaAsmOpts = if isGhcDynamic+ -- Dynamic GHC requires objects to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseAsmOpts { ghcOptFPic = toFlag True }+ else baseAsmOpts+ profAsmOpts = vanillaAsmOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptObjSuffix = toFlag "p_o"+ }+ sharedAsmOpts = vanillaAsmOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptObjSuffix = toFlag "dyn_o"+ }+ odir = fromFlag (ghcOptObjDir vanillaAsmOpts)+ createDirectoryIfMissingVerbose verbosity True odir+ let runGhcProgIfNeeded asmOpts = do+ needsRecomp <- checkNeedsRecompilation filename asmOpts+ when needsRecomp $ runGhcProg asmOpts+ runGhcProgIfNeeded vanillaAsmOpts+ unless forRepl $+ whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedAsmOpts)+ unless forRepl $ whenProfLib (runGhcProgIfNeeded profAsmOpts)+ | filename <- asmSources libBi]++ -- build any Cmm sources+ unless (not has_code || null (cmmSources libBi)) $ do+ info verbosity "Building C-- Sources..."+ sequence_+ [ do let baseCmmOpts = Internal.componentCmmGhcOptions verbosity implInfo+ lbi libBi clbi libTargetDir filename+ vanillaCmmOpts = if isGhcDynamic+ -- Dynamic GHC requires C sources to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseCmmOpts { ghcOptFPic = toFlag True }+ else baseCmmOpts+ profCmmOpts = vanillaCmmOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptObjSuffix = toFlag "p_o"+ }+ sharedCmmOpts = vanillaCmmOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptObjSuffix = toFlag "dyn_o"+ }+ odir = fromFlag (ghcOptObjDir vanillaCmmOpts)+ createDirectoryIfMissingVerbose verbosity True odir+ let runGhcProgIfNeeded cmmOpts = do+ needsRecomp <- checkNeedsRecompilation filename cmmOpts+ when needsRecomp $ runGhcProg cmmOpts+ runGhcProgIfNeeded vanillaCmmOpts+ unless forRepl $+ whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCmmOpts)+ unless forRepl $ whenProfLib (runGhcProgIfNeeded profCmmOpts)+ | filename <- cmmSources libBi]++ -- TODO: problem here is we need the .c files built first, so we can load them+ -- with ghci, but .c files can depend on .h files generated by ghc by ffi+ -- exports.+ whenReplLib $ do+ when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"+ runGhcProg replOpts++ -- link:+ when has_code . unless forRepl $ do+ info verbosity "Linking..."+ let cLikeProfObjs = map (`replaceExtension` ("p_" ++ objExtension))+ cLikeSources+ cLikeSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))+ cLikeSources+ compiler_id = compilerId (compiler lbi)+ vanillaLibFilePath = libTargetDir </> mkLibName uid+ profileLibFilePath = libTargetDir </> mkProfLibName uid+ sharedLibFilePath = libTargetDir </>+ mkSharedLibName (hostPlatform lbi) compiler_id uid+ staticLibFilePath = libTargetDir </>+ mkStaticLibName (hostPlatform lbi) compiler_id uid+ ghciLibFilePath = libTargetDir </> Internal.mkGHCiLibName uid+ ghciProfLibFilePath = libTargetDir </> Internal.mkGHCiProfLibName uid+ libInstallPath = libdir $+ absoluteComponentInstallDirs+ pkg_descr lbi uid NoCopyDest+ sharedLibInstallPath = libInstallPath </>+ mkSharedLibName (hostPlatform lbi) compiler_id uid++ stubObjs <- catMaybes <$> sequenceA+ [ findFileWithExtension [objExtension] [libTargetDir]+ (ModuleName.toFilePath x ++"_stub")+ | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files+ , x <- allLibModules lib clbi ]+ stubProfObjs <- catMaybes <$> sequenceA+ [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]+ (ModuleName.toFilePath x ++"_stub")+ | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files+ , x <- allLibModules lib clbi ]+ stubSharedObjs <- catMaybes <$> sequenceA+ [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]+ (ModuleName.toFilePath x ++"_stub")+ | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files+ , x <- allLibModules lib clbi ]++ hObjs <- Internal.getHaskellObjects implInfo lib lbi clbi+ libTargetDir objExtension True+ hProfObjs <-+ if withProfLib lbi+ then Internal.getHaskellObjects implInfo lib lbi clbi+ libTargetDir ("p_" ++ objExtension) True+ else return []+ hSharedObjs <-+ if withSharedLib lbi+ then Internal.getHaskellObjects implInfo lib lbi clbi+ libTargetDir ("dyn_" ++ objExtension) False+ else return []++ unless (null hObjs && null cLikeObjs && null stubObjs) $ do+ rpaths <- getRPaths lbi clbi++ let staticObjectFiles =+ hObjs+ ++ map (libTargetDir </>) cLikeObjs+ ++ stubObjs+ profObjectFiles =+ hProfObjs+ ++ map (libTargetDir </>) cLikeProfObjs+ ++ stubProfObjs+ dynamicObjectFiles =+ hSharedObjs+ ++ map (libTargetDir </>) cLikeSharedObjs+ ++ stubSharedObjs+ -- After the relocation lib is created we invoke ghc -shared+ -- with the dependencies spelled out as -package arguments+ -- and ghc invokes the linker with the proper library paths+ ghcSharedLinkArgs =+ mempty {+ ghcOptShared = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptInputFiles = toNubListR dynamicObjectFiles,+ ghcOptOutputFile = toFlag sharedLibFilePath,+ ghcOptExtra = 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 < mkVersion [7,8]+ then toFlag sharedLibInstallPath+ else mempty,+ ghcOptHideAllPackages = toFlag True,+ ghcOptNoAutoLinkPackages = toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptThisUnitId = case clbi of+ LibComponentLocalBuildInfo { componentCompatPackageKey = pk }+ -> toFlag pk+ _ -> mempty,+ ghcOptThisComponentId = case clbi of+ LibComponentLocalBuildInfo+ { componentInstantiatedWith = insts } ->+ if null insts+ then mempty+ else toFlag (componentComponentId clbi)+ _ -> mempty,+ ghcOptInstantiatedWith = case clbi of+ LibComponentLocalBuildInfo+ { componentInstantiatedWith = insts }+ -> insts+ _ -> [],+ ghcOptPackages = toNubListR $+ Internal.mkGhcOptPackages clbi ,+ ghcOptLinkLibs = extraLibs libBi,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi,+ ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,+ ghcOptLinkFrameworkDirs =+ toNubListR $ PD.extraFrameworkDirs libBi,+ ghcOptRPaths = rpaths+ }+ ghcStaticLinkArgs =+ mempty {+ ghcOptStaticLib = toFlag True,+ ghcOptInputFiles = toNubListR staticObjectFiles,+ ghcOptOutputFile = toFlag staticLibFilePath,+ ghcOptExtra = hcStaticOptions GHC libBi,+ ghcOptHideAllPackages = toFlag True,+ ghcOptNoAutoLinkPackages = toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptThisUnitId = case clbi of+ LibComponentLocalBuildInfo { componentCompatPackageKey = pk }+ -> toFlag pk+ _ -> mempty,+ ghcOptThisComponentId = case clbi of+ LibComponentLocalBuildInfo+ { componentInstantiatedWith = insts } ->+ if null insts+ then mempty+ else toFlag (componentComponentId clbi)+ _ -> mempty,+ ghcOptInstantiatedWith = case clbi of+ LibComponentLocalBuildInfo+ { componentInstantiatedWith = insts }+ -> insts+ _ -> [],+ ghcOptPackages = toNubListR $+ Internal.mkGhcOptPackages clbi ,+ ghcOptLinkLibs = extraLibs libBi,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi+ }++ info verbosity (show (ghcOptPackages ghcSharedLinkArgs))++ whenVanillaLib False $ do+ Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles+ whenGHCiLib $ do+ (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)+ Ld.combineObjectFiles verbosity lbi ldProg+ ghciLibFilePath staticObjectFiles++ whenProfLib $ do+ Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles+ whenGHCiLib $ do+ (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)+ Ld.combineObjectFiles verbosity lbi ldProg+ ghciProfLibFilePath profObjectFiles++ whenSharedLib False $+ runGhcProg ghcSharedLinkArgs++ whenStaticLib False $+ runGhcProg ghcStaticLinkArgs++-- | Start a REPL without loading any source files.+startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform+ -> PackageDBStack -> IO ()+startInterpreter verbosity progdb comp platform packageDBs = do+ let replOpts = mempty {+ ghcOptMode = toFlag GhcModeInteractive,+ ghcOptPackageDBs = packageDBs+ }+ checkPackageDbStack verbosity comp packageDBs+ (ghcProg, _) <- requireProgram verbosity ghcProgram progdb+ runGHC verbosity ghcProg comp platform replOpts++-- -----------------------------------------------------------------------------+-- Building an executable or foreign library++-- | Build a foreign library+buildFLib+ :: Verbosity -> Cabal.Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> ForeignLib -> ComponentLocalBuildInfo -> IO ()+buildFLib v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildFLib++replFLib+ :: [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> ForeignLib+ -> ComponentLocalBuildInfo -> IO ()+replFLib replFlags v njobs pkg lbi =+ gbuild v njobs pkg lbi . GReplFLib replFlags++-- | Build an executable with GHC.+--+buildExe+ :: Verbosity -> Cabal.Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> Executable -> ComponentLocalBuildInfo -> IO ()+buildExe v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildExe++replExe+ :: [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> Executable+ -> ComponentLocalBuildInfo -> IO ()+replExe replFlags v njobs pkg lbi =+ gbuild v njobs pkg lbi . GReplExe replFlags++-- | Building an executable, starting the REPL, and building foreign+-- libraries are all very similar and implemented in 'gbuild'. The+-- 'GBuildMode' distinguishes between the various kinds of operation.+data GBuildMode =+ GBuildExe Executable+ | GReplExe [String] Executable+ | GBuildFLib ForeignLib+ | GReplFLib [String] ForeignLib++gbuildInfo :: GBuildMode -> BuildInfo+gbuildInfo (GBuildExe exe) = buildInfo exe+gbuildInfo (GReplExe _ exe) = buildInfo exe+gbuildInfo (GBuildFLib flib) = foreignLibBuildInfo flib+gbuildInfo (GReplFLib _ flib) = foreignLibBuildInfo flib++gbuildName :: GBuildMode -> String+gbuildName (GBuildExe exe) = unUnqualComponentName $ exeName exe+gbuildName (GReplExe _ exe) = unUnqualComponentName $ exeName exe+gbuildName (GBuildFLib flib) = unUnqualComponentName $ foreignLibName flib+gbuildName (GReplFLib _ flib) = unUnqualComponentName $ foreignLibName flib++gbuildTargetName :: LocalBuildInfo -> GBuildMode -> String+gbuildTargetName lbi (GBuildExe exe) = exeTargetName (hostPlatform lbi) exe+gbuildTargetName lbi (GReplExe _ exe) = exeTargetName (hostPlatform lbi) exe+gbuildTargetName lbi (GBuildFLib flib) = flibTargetName lbi flib+gbuildTargetName lbi (GReplFLib _ flib) = flibTargetName lbi flib++exeTargetName :: Platform -> Executable -> String+exeTargetName platform exe = unUnqualComponentName (exeName exe) `withExt` exeExtension platform++-- | Target name for a foreign library (the actual file name)+--+-- We do not use mkLibName and co here because the naming for foreign libraries+-- is slightly different (we don't use "_p" or compiler version suffices, and we+-- don't want the "lib" prefix on Windows).+--+-- TODO: We do use `dllExtension` and co here, but really that's wrong: they+-- use the OS used to build cabal to determine which extension to use, rather+-- than the target OS (but this is wrong elsewhere in Cabal as well).+flibTargetName :: LocalBuildInfo -> ForeignLib -> String+flibTargetName lbi flib =+ case (os, foreignLibType flib) of+ (Windows, ForeignLibNativeShared) -> nm <.> "dll"+ (Windows, ForeignLibNativeStatic) -> nm <.> "lib"+ (Linux, ForeignLibNativeShared) -> "lib" ++ nm <.> versionedExt+ (_other, ForeignLibNativeShared) ->+ "lib" ++ nm <.> dllExtension (hostPlatform lbi)+ (_other, ForeignLibNativeStatic) ->+ "lib" ++ nm <.> staticLibExtension (hostPlatform lbi)+ (_any, ForeignLibTypeUnknown) -> cabalBug "unknown foreign lib type"+ where+ nm :: String+ nm = unUnqualComponentName $ foreignLibName flib++ os :: OS+ os = let (Platform _ os') = hostPlatform lbi+ in os'++ -- If a foreign lib foo has lib-version-info 5:1:2 or+ -- lib-version-linux 3.2.1, it should be built as libfoo.so.3.2.1+ -- Libtool's version-info data is translated into library versions in a+ -- nontrivial way: so refer to libtool documentation.+ versionedExt :: String+ versionedExt =+ let nums = foreignLibVersion flib os+ in foldl (<.>) "so" (map show nums)++-- | Name for the library when building.+--+-- If the `lib-version-info` field or the `lib-version-linux` field of+-- a foreign library target is set, we need to incorporate that+-- version into the SONAME field.+--+-- If a foreign library foo has lib-version-info 5:1:2, it should be+-- built as libfoo.so.3.2.1. We want it to get soname libfoo.so.3.+-- However, GHC does not allow overriding soname by setting linker+-- options, as it sets a soname of its own (namely the output+-- filename), after the user-supplied linker options. Hence, we have+-- to compile the library with the soname as its filename. We rename+-- the compiled binary afterwards.+--+-- This method allows to adjust the name of the library at build time+-- such that the correct soname can be set.+flibBuildName :: LocalBuildInfo -> ForeignLib -> String+flibBuildName lbi flib+ -- On linux, if a foreign-library has version data, the first digit is used+ -- to produce the SONAME.+ | (os, foreignLibType flib) ==+ (Linux, ForeignLibNativeShared)+ = let nums = foreignLibVersion flib os+ in "lib" ++ nm <.> foldl (<.>) "so" (map show (take 1 nums))+ | otherwise = flibTargetName lbi flib+ where+ os :: OS+ os = let (Platform _ os') = hostPlatform lbi+ in os'++ nm :: String+ nm = unUnqualComponentName $ foreignLibName flib++gbuildIsRepl :: GBuildMode -> Bool+gbuildIsRepl (GBuildExe _) = False+gbuildIsRepl (GReplExe _ _) = True+gbuildIsRepl (GBuildFLib _) = False+gbuildIsRepl (GReplFLib _ _) = True++gbuildNeedDynamic :: LocalBuildInfo -> GBuildMode -> Bool+gbuildNeedDynamic lbi bm =+ case bm of+ GBuildExe _ -> withDynExe lbi+ GReplExe _ _ -> withDynExe lbi+ GBuildFLib flib -> withDynFLib flib+ GReplFLib _ flib -> withDynFLib flib+ where+ withDynFLib flib =+ case foreignLibType flib of+ ForeignLibNativeShared ->+ ForeignLibStandalone `notElem` foreignLibOptions flib+ ForeignLibNativeStatic ->+ False+ ForeignLibTypeUnknown ->+ cabalBug "unknown foreign lib type"++gbuildModDefFiles :: GBuildMode -> [FilePath]+gbuildModDefFiles (GBuildExe _) = []+gbuildModDefFiles (GReplExe _ _) = []+gbuildModDefFiles (GBuildFLib flib) = foreignLibModDefFile flib+gbuildModDefFiles (GReplFLib _ flib) = foreignLibModDefFile flib++-- | "Main" module name when overridden by @ghc-options: -main-is ...@+-- or 'Nothing' if no @-main-is@ flag could be found.+--+-- In case of 'Nothing', 'Distribution.ModuleName.main' can be assumed.+exeMainModuleName :: Executable -> Maybe ModuleName+exeMainModuleName Executable{buildInfo = bnfo} =+ -- GHC honors the last occurrence of a module name updated via -main-is+ --+ -- Moreover, -main-is when parsed left-to-right can update either+ -- the "Main" module name, or the "main" function name, or both,+ -- see also 'decodeMainIsArg'.+ msum $ reverse $ map decodeMainIsArg $ findIsMainArgs ghcopts+ where+ ghcopts = hcOptions GHC bnfo++ findIsMainArgs [] = []+ findIsMainArgs ("-main-is":arg:rest) = arg : findIsMainArgs rest+ findIsMainArgs (_:rest) = findIsMainArgs rest++-- | Decode argument to '-main-is'+--+-- Returns 'Nothing' if argument set only the function name.+--+-- This code has been stolen/refactored from GHC's DynFlags.setMainIs+-- function. The logic here is deliberately imperfect as it is+-- intended to be bug-compatible with GHC's parser. See discussion in+-- https://github.com/haskell/cabal/pull/4539#discussion_r118981753.+decodeMainIsArg :: String -> Maybe ModuleName+decodeMainIsArg arg+ | headOf main_fn isLower+ -- The arg looked like "Foo.Bar.baz"+ = Just (ModuleName.fromString main_mod)+ | headOf arg isUpper -- The arg looked like "Foo" or "Foo.Bar"+ = Just (ModuleName.fromString arg)+ | otherwise -- The arg looked like "baz"+ = Nothing+ where+ headOf :: String -> (Char -> Bool) -> Bool+ headOf str pred' = any pred' (safeHead str)++ (main_mod, main_fn) = splitLongestPrefix arg (== '.')++ splitLongestPrefix :: String -> (Char -> Bool) -> (String,String)+ splitLongestPrefix str pred'+ | null r_pre = (str, [])+ | otherwise = (reverse (safeTail r_pre), reverse r_suf)+ -- 'safeTail' drops the char satisfying 'pred'+ where (r_suf, r_pre) = break pred' (reverse str)++-- | A collection of:+-- * C input files+-- * C++ input files+-- * GHC input files+-- * GHC input modules+--+-- Used to correctly build and link sources.+data BuildSources = BuildSources {+ cSourcesFiles :: [FilePath],+ cxxSourceFiles :: [FilePath],+ inputSourceFiles :: [FilePath],+ inputSourceModules :: [ModuleName]+ }++-- | Locate and return the 'BuildSources' required to build and link.+gbuildSources :: Verbosity+ -> CabalSpecVersion+ -> FilePath+ -> GBuildMode+ -> IO BuildSources+gbuildSources verbosity specVer tmpDir bm =+ case bm of+ GBuildExe exe -> exeSources exe+ GReplExe _ exe -> exeSources exe+ GBuildFLib flib -> return $ flibSources flib+ GReplFLib _ flib -> return $ flibSources flib+ where+ exeSources :: Executable -> IO BuildSources+ exeSources exe@Executable{buildInfo = bnfo, modulePath = modPath} = do+ main <- findFileEx verbosity (tmpDir : map getSymbolicPath (hsSourceDirs bnfo)) modPath+ let mainModName = fromMaybe ModuleName.main $ exeMainModuleName exe+ otherModNames = exeModules exe++ if isHaskell main+ then+ if specVer < CabalSpecV2_0 && (mainModName `elem` otherModNames)+ then do+ -- The cabal manual clearly states that `other-modules` is+ -- intended for non-main modules. However, there's at least one+ -- important package on Hackage (happy-1.19.5) which+ -- violates this. We workaround this here so that we don't+ -- invoke GHC with e.g. 'ghc --make Main src/Main.hs' which+ -- would result in GHC complaining about duplicate Main+ -- modules.+ --+ -- Finally, we only enable this workaround for+ -- specVersion < 2, as 'cabal-version:>=2.0' cabal files+ -- have no excuse anymore to keep doing it wrong... ;-)+ warn verbosity $ "Enabling workaround for Main module '"+ ++ prettyShow mainModName+ ++ "' listed in 'other-modules' illegally!"++ return BuildSources {+ cSourcesFiles = cSources bnfo,+ cxxSourceFiles = cxxSources bnfo,+ inputSourceFiles = [main],+ inputSourceModules = filter (/= mainModName) $+ exeModules exe+ }++ else return BuildSources {+ cSourcesFiles = cSources bnfo,+ cxxSourceFiles = cxxSources bnfo,+ inputSourceFiles = [main],+ inputSourceModules = exeModules exe+ }+ else let (csf, cxxsf)+ | isCxx main = ( cSources bnfo, main : cxxSources bnfo)+ -- if main is not a Haskell source+ -- and main is not a C++ source+ -- then we assume that it is a C source+ | otherwise = (main : cSources bnfo, cxxSources bnfo)++ in return BuildSources {+ cSourcesFiles = csf,+ cxxSourceFiles = cxxsf,+ inputSourceFiles = [],+ inputSourceModules = exeModules exe+ }++ flibSources :: ForeignLib -> BuildSources+ flibSources flib@ForeignLib{foreignLibBuildInfo = bnfo} =+ BuildSources {+ cSourcesFiles = cSources bnfo,+ cxxSourceFiles = cxxSources bnfo,+ inputSourceFiles = [],+ inputSourceModules = foreignLibModules flib+ }++ isHaskell :: FilePath -> Bool+ isHaskell fp = elem (takeExtension fp) [".hs", ".lhs"]++ isCxx :: FilePath -> Bool+ isCxx fp = elem (takeExtension fp) [".cpp", ".cxx", ".c++"]++-- | Generic build function. See comment for 'GBuildMode'.+gbuild :: Verbosity -> Cabal.Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> GBuildMode -> ComponentLocalBuildInfo -> IO ()+gbuild verbosity numJobs pkg_descr lbi bm clbi = do+ (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)+ let replFlags = case bm of+ GReplExe flags _ -> flags+ GReplFLib flags _ -> flags+ GBuildExe{} -> mempty+ GBuildFLib{} -> mempty+ comp = compiler lbi+ platform = hostPlatform lbi+ implInfo = getImplInfo comp+ runGhcProg = runGHC verbosity ghcProg comp platform++ let (bnfo, threaded) = case bm of+ GBuildFLib _ -> popThreadedFlag (gbuildInfo bm)+ _ -> (gbuildInfo bm, False)++ -- the name that GHC really uses (e.g., with .exe on Windows for executables)+ let targetName = gbuildTargetName lbi bm+ let targetDir = buildDir lbi </> (gbuildName bm)+ let tmpDir = targetDir </> (gbuildName bm ++ "-tmp")+ createDirectoryIfMissingVerbose verbosity True targetDir+ createDirectoryIfMissingVerbose verbosity True tmpDir++ -- TODO: do we need to put hs-boot files into place for mutually recursive+ -- modules? FIX: what about exeName.hi-boot?++ -- Determine if program coverage should be enabled and if so, what+ -- '-hpcdir' should be.+ let isCoverageEnabled = exeCoverage lbi+ distPref = fromFlag $ configDistPref $ configFlags lbi+ hpcdir way+ | gbuildIsRepl bm = mempty -- HPC is not supported in ghci+ | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way (gbuildName bm)+ | otherwise = mempty++ rpaths <- getRPaths lbi clbi+ buildSources <- gbuildSources verbosity (specVersion pkg_descr) tmpDir bm++ let cSrcs = cSourcesFiles buildSources+ cxxSrcs = cxxSourceFiles buildSources+ inputFiles = inputSourceFiles buildSources+ inputModules = inputSourceModules buildSources+ isGhcDynamic = isDynamic comp+ dynamicTooSupported = supportsDynamicToo comp+ cLikeObjs = map (`replaceExtension` objExtension) cSrcs+ cxxObjs = map (`replaceExtension` objExtension) cxxSrcs+ needDynamic = gbuildNeedDynamic lbi bm+ needProfiling = withProfExe lbi++ -- build executables+ baseOpts = (componentGhcOptions verbosity lbi bnfo clbi tmpDir)+ `mappend` mempty {+ ghcOptMode = toFlag GhcModeMake,+ ghcOptInputFiles = toNubListR inputFiles,+ ghcOptInputModules = toNubListR inputModules+ }+ staticOpts = baseOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcStaticOnly,+ ghcOptHPCDir = hpcdir Hpc.Vanilla+ }+ profOpts = baseOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag False+ (withProfExeDetail lbi),+ ghcOptHiSuffix = toFlag "p_hi",+ ghcOptObjSuffix = toFlag "p_o",+ ghcOptExtra = hcProfOptions GHC bnfo,+ ghcOptHPCDir = hpcdir Hpc.Prof+ }+ dynOpts = baseOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ -- TODO: Does it hurt to set -fPIC for executables?+ ghcOptFPic = toFlag True,+ ghcOptHiSuffix = toFlag "dyn_hi",+ ghcOptObjSuffix = toFlag "dyn_o",+ ghcOptExtra = hcSharedOptions GHC bnfo,+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }+ dynTooOpts = staticOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,+ ghcOptDynHiSuffix = toFlag "dyn_hi",+ ghcOptDynObjSuffix = toFlag "dyn_o",+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }+ linkerOpts = mempty {+ ghcOptLinkOptions = PD.ldOptions bnfo+ ++ [ "-static"+ | withFullyStaticExe lbi ]+ -- Pass extra `ld-options` given+ -- through to GHC's linker.+ ++ maybe [] programOverrideArgs+ (lookupProgram ldProgram (withPrograms lbi)),+ ghcOptLinkLibs = extraLibs bnfo,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs bnfo,+ ghcOptLinkFrameworks = toNubListR $+ PD.frameworks bnfo,+ ghcOptLinkFrameworkDirs = toNubListR $+ PD.extraFrameworkDirs bnfo,+ ghcOptInputFiles = toNubListR+ [tmpDir </> x | x <- cLikeObjs ++ cxxObjs]+ }+ dynLinkerOpts = mempty {+ ghcOptRPaths = rpaths,+ ghcOptInputFiles = toNubListR+ [tmpDir </> x | x <- cLikeObjs ++ cxxObjs]+ }+ replOpts = baseOpts {+ ghcOptExtra = Internal.filterGhciFlags+ (ghcOptExtra baseOpts)+ <> replFlags+ }+ -- For a normal compile we do separate invocations of ghc for+ -- compiling as for linking. But for repl we have to do just+ -- the one invocation, so that one has to include all the+ -- linker stuff too, like -l flags and any .o files from C+ -- files etc.+ `mappend` linkerOpts+ `mappend` mempty {+ ghcOptMode = toFlag GhcModeInteractive,+ ghcOptOptimisation = toFlag GhcNoOptimisation+ }+ commonOpts | needProfiling = profOpts+ | needDynamic = dynOpts+ | otherwise = staticOpts+ compileOpts | useDynToo = dynTooOpts+ | otherwise = commonOpts+ withStaticExe = not needProfiling && not needDynamic++ -- For building exe's that use TH with -prof or -dynamic we actually have+ -- to build twice, once without -prof/-dynamic and then again with+ -- -prof/-dynamic. This is because the code that TH needs to run at+ -- compile time needs to be the vanilla ABI so it can be loaded up and run+ -- by the compiler.+ -- With dynamic-by-default GHC the TH object files loaded at compile-time+ -- need to be .dyn_o instead of .o.+ doingTH = usesTemplateHaskellOrQQ bnfo+ -- Should we use -dynamic-too instead of compiling twice?+ useDynToo = dynamicTooSupported && isGhcDynamic+ && doingTH && withStaticExe+ && null (hcSharedOptions GHC bnfo)+ compileTHOpts | isGhcDynamic = dynOpts+ | otherwise = staticOpts+ compileForTH+ | gbuildIsRepl bm = False+ | useDynToo = False+ | isGhcDynamic = doingTH && (needProfiling || withStaticExe)+ | otherwise = doingTH && (needProfiling || needDynamic)++ -- Build static/dynamic object files for TH, if needed.+ when compileForTH $+ runGhcProg compileTHOpts { ghcOptNoLink = toFlag True+ , ghcOptNumJobs = numJobs }++ -- Do not try to build anything if there are no input files.+ -- This can happen if the cabal file ends up with only cSrcs+ -- but no Haskell modules.+ unless ((null inputFiles && null inputModules)+ || gbuildIsRepl bm) $+ runGhcProg compileOpts { ghcOptNoLink = toFlag True+ , ghcOptNumJobs = numJobs }++ -- build any C++ sources+ unless (null cxxSrcs) $ do+ info verbosity "Building C++ Sources..."+ sequence_+ [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo+ lbi bnfo clbi tmpDir filename+ vanillaCxxOpts = if isGhcDynamic+ -- Dynamic GHC requires C++ sources to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseCxxOpts { ghcOptFPic = toFlag True }+ else baseCxxOpts+ profCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True+ }+ sharedCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly+ }+ opts | needProfiling = profCxxOpts+ | needDynamic = sharedCxxOpts+ | otherwise = vanillaCxxOpts+ -- TODO: Placing all Haskell, C, & C++ objects in a single directory+ -- Has the potential for file collisions. In general we would+ -- consider this a user error. However, we should strive to+ -- add a warning if this occurs.+ odir = fromFlag (ghcOptObjDir opts)+ createDirectoryIfMissingVerbose verbosity True odir+ needsRecomp <- checkNeedsRecompilation filename opts+ when needsRecomp $+ runGhcProg opts+ | filename <- cxxSrcs ]++ -- build any C sources+ unless (null cSrcs) $ do+ info verbosity "Building C Sources..."+ sequence_+ [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo+ lbi bnfo clbi tmpDir filename+ vanillaCcOpts = if isGhcDynamic+ -- Dynamic GHC requires C sources to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseCcOpts { ghcOptFPic = toFlag True }+ else baseCcOpts+ profCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True+ }+ sharedCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly+ }+ opts | needProfiling = profCcOpts+ | needDynamic = sharedCcOpts+ | otherwise = vanillaCcOpts+ odir = fromFlag (ghcOptObjDir opts)+ createDirectoryIfMissingVerbose verbosity True odir+ needsRecomp <- checkNeedsRecompilation filename opts+ when needsRecomp $+ runGhcProg opts+ | filename <- cSrcs ]++ -- TODO: problem here is we need the .c files built first, so we can load them+ -- with ghci, but .c files can depend on .h files generated by ghc by ffi+ -- exports.+ case bm of+ GReplExe _ _ -> runGhcProg replOpts+ GReplFLib _ _ -> runGhcProg replOpts+ GBuildExe _ -> do+ let linkOpts = commonOpts+ `mappend` linkerOpts+ `mappend` mempty {+ ghcOptLinkNoHsMain = toFlag (null inputFiles)+ }+ `mappend` (if withDynExe lbi then dynLinkerOpts else mempty)++ info verbosity "Linking..."+ -- Work around old GHCs not relinking in this+ -- situation, see #3294+ let target = targetDir </> targetName+ when (compilerVersion comp < mkVersion [7,7]) $ do+ e <- doesFileExist target+ when e (removeFile target)+ runGhcProg linkOpts { ghcOptOutputFile = toFlag target }+ GBuildFLib flib -> do+ let rtsInfo = extractRtsInfo lbi+ rtsOptLinkLibs = [+ if needDynamic+ then if threaded+ then dynRtsThreadedLib (rtsDynamicInfo rtsInfo)+ else dynRtsVanillaLib (rtsDynamicInfo rtsInfo)+ else if threaded+ then statRtsThreadedLib (rtsStaticInfo rtsInfo)+ else statRtsVanillaLib (rtsStaticInfo rtsInfo)+ ]+ linkOpts = case foreignLibType flib of+ ForeignLibNativeShared ->+ commonOpts+ `mappend` linkerOpts+ `mappend` dynLinkerOpts+ `mappend` mempty {+ ghcOptLinkNoHsMain = toFlag True,+ ghcOptShared = toFlag True,+ ghcOptLinkLibs = rtsOptLinkLibs,+ ghcOptLinkLibPath = toNubListR $ rtsLibPaths rtsInfo,+ ghcOptFPic = toFlag True,+ ghcOptLinkModDefFiles = toNubListR $ gbuildModDefFiles bm+ }+ -- See Note [RPATH]+ `mappend` ifNeedsRPathWorkaround lbi mempty {+ ghcOptLinkOptions = ["-Wl,--no-as-needed"]+ , ghcOptLinkLibs = ["ffi"]+ }+ ForeignLibNativeStatic ->+ -- this should be caught by buildFLib+ -- (and if we do implement this, we probably don't even want to call+ -- ghc here, but rather Ar.createArLibArchive or something)+ cabalBug "static libraries not yet implemented"+ ForeignLibTypeUnknown ->+ cabalBug "unknown foreign lib type"+ -- We build under a (potentially) different filename to set a+ -- soname on supported platforms. See also the note for+ -- @flibBuildName@.+ info verbosity "Linking..."+ let buildName = flibBuildName lbi flib+ runGhcProg linkOpts { ghcOptOutputFile = toFlag (targetDir </> buildName) }+ renameFile (targetDir </> buildName) (targetDir </> targetName)++{-+Note [RPATH]+~~~~~~~~~~~~++Suppose that the dynamic library depends on `base`, but not (directly) on+`integer-gmp` (which, however, is a dependency of `base`). We will link the+library as++ gcc ... -lHSbase-4.7.0.2-ghc7.8.4 -lHSinteger-gmp-0.5.1.0-ghc7.8.4 ...++However, on systems (like Ubuntu) where the linker gets called with `-as-needed`+by default, the linker will notice that `integer-gmp` isn't actually a direct+dependency and hence omit the link.++Then when we attempt to link a C program against this dynamic library, the+_static_ linker will attempt to verify that all symbols can be resolved. The+dynamic library itself does not require any symbols from `integer-gmp`, but+`base` does. In order to verify that the symbols used by `base` can be+resolved, the static linker needs to be able to _find_ integer-gmp.++Finding the `base` dependency is simple, because the dynamic elf header+(`readelf -d`) for the library that we have created looks something like++ (NEEDED) Shared library: [libHSbase-4.7.0.2-ghc7.8.4.so]+ (RPATH) Library rpath: [/path/to/base-4.7.0.2:...]++However, when it comes to resolving the dependency on `integer-gmp`, it needs+to look at the dynamic header for `base`. On modern ghc (7.8 and higher) this+looks something like++ (NEEDED) Shared library: [libHSinteger-gmp-0.5.1.0-ghc7.8.4.so]+ (RPATH) Library rpath: [$ORIGIN/../integer-gmp-0.5.1.0:...]++This specifies the location of `integer-gmp` _in terms of_ the location of base+(using the `$ORIGIN`) variable. But here's the crux: when the static linker+attempts to verify that all symbols can be resolved, [**IT DOES NOT RESOLVE+`$ORIGIN`**](http://stackoverflow.com/questions/6323603/ld-using-rpath-origin-inside-a-shared-library-recursive).+As a consequence, it will not be able to resolve the symbols and report the+missing symbols as errors, _even though the dynamic linker **would** be able to+resolve these symbols_. We can tell the static linker not to report these+errors by using `--unresolved-symbols=ignore-all` and all will be fine when we+run the program ([(indeed, this is what the gold linker+does)](https://sourceware.org/ml/binutils/2013-05/msg00038.html), but it makes+the resulting library more difficult to use.++Instead what we can do is make sure that the generated dynamic library has+explicit top-level dependencies on these libraries. This means that the static+linker knows where to find them, and when we have transitive dependencies on+the same libraries the linker will only load them once, so we avoid needing to+look at the `RPATH` of our dependencies. We can do this by passing+`--no-as-needed` to the linker, so that it doesn't omit any libraries.++Note that on older ghc (7.6 and before) the Haskell libraries don't have an+RPATH set at all, which makes it even more important that we make these+top-level dependencies.++Finally, we have to explicitly link against `libffi` for the same reason. For+newer ghc this _happens_ to be unnecessary on many systems because `libffi` is+a library which is not specific to GHC, and when the static linker verifies+that all symbols can be resolved it will find the `libffi` that is globally+installed (completely independent from ghc). Of course, this may well be the+_wrong_ version of `libffi`, but it's quite possible that symbol resolution+happens to work. This is of course the wrong approach, which is why we link+explicitly against `libffi` so that we will find the _right_ version of+`libffi`.+-}++-- | Do we need the RPATH workaround?+--+-- See Note [RPATH].+ifNeedsRPathWorkaround :: Monoid a => LocalBuildInfo -> a -> a+ifNeedsRPathWorkaround lbi a =+ case hostPlatform lbi of+ Platform _ Linux -> a+ _otherwise -> mempty++data DynamicRtsInfo = DynamicRtsInfo {+ dynRtsVanillaLib :: FilePath+ , dynRtsThreadedLib :: FilePath+ , dynRtsDebugLib :: FilePath+ , dynRtsEventlogLib :: FilePath+ , dynRtsThreadedDebugLib :: FilePath+ , dynRtsThreadedEventlogLib :: FilePath+ }++data StaticRtsInfo = StaticRtsInfo {+ statRtsVanillaLib :: FilePath+ , statRtsThreadedLib :: FilePath+ , statRtsDebugLib :: FilePath+ , statRtsEventlogLib :: FilePath+ , statRtsThreadedDebugLib :: FilePath+ , statRtsThreadedEventlogLib :: FilePath+ , statRtsProfilingLib :: FilePath+ , statRtsThreadedProfilingLib :: FilePath+ }++data RtsInfo = RtsInfo {+ rtsDynamicInfo :: DynamicRtsInfo+ , rtsStaticInfo :: StaticRtsInfo+ , rtsLibPaths :: [FilePath]+ }++-- | Extract (and compute) information about the RTS library+--+-- TODO: This hardcodes the name as @HSrts-ghc<version>@. I don't know if we can+-- find this information somewhere. We can lookup the 'hsLibraries' field of+-- 'InstalledPackageInfo' but it will tell us @["HSrts", "Cffi"]@, which+-- doesn't really help.+extractRtsInfo :: LocalBuildInfo -> RtsInfo+extractRtsInfo lbi =+ case PackageIndex.lookupPackageName+ (installedPkgs lbi) (mkPackageName "rts") of+ [(_, [rts])] -> aux rts+ _otherwise -> error "No (or multiple) ghc rts package is registered"+ where+ aux :: InstalledPackageInfo -> RtsInfo+ aux rts = RtsInfo {+ rtsDynamicInfo = DynamicRtsInfo {+ dynRtsVanillaLib = withGhcVersion "HSrts"+ , dynRtsThreadedLib = withGhcVersion "HSrts_thr"+ , dynRtsDebugLib = withGhcVersion "HSrts_debug"+ , dynRtsEventlogLib = withGhcVersion "HSrts_l"+ , dynRtsThreadedDebugLib = withGhcVersion "HSrts_thr_debug"+ , dynRtsThreadedEventlogLib = withGhcVersion "HSrts_thr_l"+ }+ , rtsStaticInfo = StaticRtsInfo {+ statRtsVanillaLib = "HSrts"+ , statRtsThreadedLib = "HSrts_thr"+ , statRtsDebugLib = "HSrts_debug"+ , statRtsEventlogLib = "HSrts_l"+ , statRtsThreadedDebugLib = "HSrts_thr_debug"+ , statRtsThreadedEventlogLib = "HSrts_thr_l"+ , statRtsProfilingLib = "HSrts_p"+ , statRtsThreadedProfilingLib = "HSrts_thr_p"+ }+ , rtsLibPaths = InstalledPackageInfo.libraryDirs rts+ }+ withGhcVersion = (++ ("-ghc" ++ prettyShow (compilerVersion (compiler lbi))))++-- | Returns True if the modification date of the given source file is newer than+-- the object file we last compiled for it, or if no object file exists yet.+checkNeedsRecompilation :: FilePath -> GhcOptions -> IO Bool+checkNeedsRecompilation filename opts = filename `moreRecentFile` oname+ where oname = getObjectFileName filename opts++-- | Finds the object file name of the given source file+getObjectFileName :: FilePath -> GhcOptions -> FilePath+getObjectFileName filename opts = oname+ where odir = fromFlag (ghcOptObjDir opts)+ oext = fromFlagOrDefault "o" (ghcOptObjSuffix opts)+ oname = odir </> replaceExtension filename oext++-- | Calculate the RPATHs for the component we are building.+--+-- Calculates relative RPATHs when 'relocatable' is set.+getRPaths :: LocalBuildInfo+ -> ComponentLocalBuildInfo -- ^ Component we are building+ -> IO (NubListR FilePath)+getRPaths lbi clbi | supportRPaths hostOS = do+ libraryPaths <- depLibraryPaths False (relocatable lbi) lbi clbi+ let hostPref = case hostOS of+ OSX -> "@loader_path"+ _ -> "$ORIGIN"+ relPath p = if isRelative p then hostPref </> p else p+ rpaths = toNubListR (map relPath libraryPaths)+ return rpaths+ where+ (Platform _ hostOS) = hostPlatform lbi+ compid = compilerId . compiler $ lbi++ -- The list of RPath-supported operating systems below reflects the+ -- platforms on which Cabal's RPATH handling is tested. It does _NOT_+ -- reflect whether the OS supports RPATH.++ -- E.g. when this comment was written, the *BSD operating systems were+ -- untested with regards to Cabal RPATH handling, and were hence set to+ -- 'False', while those operating systems themselves do support RPATH.+ supportRPaths Linux = True+ supportRPaths Windows = False+ supportRPaths OSX = True+ supportRPaths FreeBSD =+ case compid of+ CompilerId GHC ver | ver >= mkVersion [7,10,2] -> True+ _ -> False+ supportRPaths OpenBSD = False+ supportRPaths NetBSD = False+ supportRPaths DragonFly = False+ supportRPaths Solaris = False+ supportRPaths AIX = False+ supportRPaths HPUX = False+ 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.++getRPaths _ _ = return mempty++-- | Remove the "-threaded" flag when building a foreign library, as it has no+-- effect when used with "-shared". Returns the updated 'BuildInfo', along+-- with whether or not the flag was present, so we can use it to link against+-- the appropriate RTS on our own.+popThreadedFlag :: BuildInfo -> (BuildInfo, Bool)+popThreadedFlag bi =+ ( bi { options = filterHcOptions (/= "-threaded") (options bi) }+ , hasThreaded (options bi))++ where+ filterHcOptions :: (String -> Bool)+ -> PerCompilerFlavor [String]+ -> PerCompilerFlavor [String]+ filterHcOptions p (PerCompilerFlavor ghc ghcjs) =+ PerCompilerFlavor (filter p ghc) ghcjs++ hasThreaded :: PerCompilerFlavor [String] -> Bool+ hasThreaded (PerCompilerFlavor ghc _) = elem "-threaded" ghc++-- | Extracts a String representing a hash of the ABI of a built+-- library. It can fail if the library has not yet been built.+--+libAbiHash :: Verbosity -> PackageDescription -> LocalBuildInfo+ -> Library -> ComponentLocalBuildInfo -> IO String+libAbiHash verbosity _pkg_descr lbi lib clbi = do+ let+ libBi = libBuildInfo lib+ comp = compiler lbi+ platform = hostPlatform lbi+ vanillaArgs0 =+ (componentGhcOptions verbosity lbi libBi clbi (componentBuildDir lbi clbi))+ `mappend` mempty {+ ghcOptMode = toFlag GhcModeAbiHash,+ ghcOptInputModules = toNubListR $ exposedModules lib+ }+ vanillaArgs =+ -- Package DBs unnecessary, and break ghc-cabal. See #3633+ -- BUT, put at least the global database so that 7.4 doesn't+ -- break.+ vanillaArgs0 { ghcOptPackageDBs = [GlobalPackageDB]+ , ghcOptPackages = mempty }+ sharedArgs = vanillaArgs `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptFPic = toFlag True,+ ghcOptHiSuffix = toFlag "dyn_hi",+ ghcOptObjSuffix = toFlag "dyn_o",+ ghcOptExtra = hcSharedOptions GHC libBi+ }+ profArgs = vanillaArgs `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag True+ (withProfLibDetail lbi),+ ghcOptHiSuffix = toFlag "p_hi",+ ghcOptObjSuffix = toFlag "p_o",+ ghcOptExtra = hcProfOptions GHC libBi+ }+ 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 platform ghcArgs)+ return (takeWhile (not . isSpace) hash)++componentGhcOptions :: Verbosity -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo -> FilePath+ -> GhcOptions+componentGhcOptions verbosity lbi =+ Internal.componentGhcOptions verbosity implInfo lbi+ where+ comp = compiler lbi+ implInfo = getImplInfo comp++componentCcGhcOptions :: Verbosity -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> FilePath+ -> GhcOptions+componentCcGhcOptions verbosity lbi =+ Internal.componentCcGhcOptions verbosity implInfo lbi+ where+ comp = compiler lbi+ implInfo = getImplInfo comp++-- -----------------------------------------------------------------------------+-- Installing++-- |Install executables for GHC.+installExe :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^Where to copy the files to+ -> FilePath -- ^Build location+ -> (FilePath, FilePath) -- ^Executable (prefix,suffix)+ -> PackageDescription+ -> Executable+ -> IO ()+installExe verbosity lbi binDir buildPref+ (progprefix, progsuffix) _pkg exe = do+ createDirectoryIfMissingVerbose verbosity True binDir+ let exeName' = unUnqualComponentName $ exeName exe+ exeFileName = exeTargetName (hostPlatform lbi) exe+ fixedExeBaseName = progprefix ++ exeName' ++ progsuffix+ installBinary dest = do+ installExecutableFile verbosity+ (buildPref </> exeName' </> exeFileName)+ (dest <.> exeExtension (hostPlatform lbi))+ when (stripExes lbi) $+ Strip.stripExe verbosity (hostPlatform lbi) (withPrograms lbi)+ (dest <.> exeExtension (hostPlatform lbi))+ installBinary (binDir </> fixedExeBaseName)++-- |Install foreign library for GHC.+installFLib :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^install location+ -> FilePath -- ^Build location+ -> PackageDescription+ -> ForeignLib+ -> IO ()+installFLib verbosity lbi targetDir builtDir _pkg flib =+ install (foreignLibIsShared flib)+ builtDir+ targetDir+ (flibTargetName lbi flib)+ where+ install isShared srcDir dstDir name = do+ let src = srcDir </> name+ dst = dstDir </> name+ createDirectoryIfMissingVerbose verbosity True targetDir+ -- TODO: Should we strip? (stripLibs lbi)+ if isShared+ then installExecutableFile verbosity src dst+ else installOrdinaryFile verbosity src dst+ -- Now install appropriate symlinks if library is versioned+ let (Platform _ os) = hostPlatform lbi+ when (not (null (foreignLibVersion flib os))) $ do+ when (os /= Linux) $ die' verbosity+ -- It should be impossible to get here.+ "Can't install foreign-library symlink on non-Linux OS"+#ifndef mingw32_HOST_OS+ -- 'createSymbolicLink file1 file2' creates a symbolic link+ -- named 'file2' which points to the file 'file1'.+ -- Note that we do want a symlink to 'name' rather than+ -- 'dst', because the symlink will be relative to the+ -- directory it's created in.+ -- Finally, we first create the symlinks in a temporary+ -- directory and then rename to simulate 'ln --force'.+ withTempDirectory verbosity dstDir nm $ \tmpDir -> do+ let link1 = flibBuildName lbi flib+ link2 = "lib" ++ nm <.> "so"+ createSymbolicLink name (tmpDir </> link1)+ renameFile (tmpDir </> link1) (dstDir </> link1)+ createSymbolicLink name (tmpDir </> link2)+ renameFile (tmpDir </> link2) (dstDir </> link2)+ where+ nm :: String+ nm = unUnqualComponentName $ foreignLibName flib+#endif /* mingw32_HOST_OS */+++-- |Install for ghc, .hi, .a and, if --with-ghci given, .o+installLib :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^install location+ -> FilePath -- ^install location for dynamic libraries+ -> FilePath -- ^Build location+ -> PackageDescription+ -> Library+ -> ComponentLocalBuildInfo+ -> IO ()+installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do+ -- copy .hi files over:+ whenVanilla $ copyModuleFiles "hi"+ whenProf $ copyModuleFiles "p_hi"+ whenShared $ copyModuleFiles "dyn_hi"++ -- copy the built library files over:+ whenHasCode $ do+ whenVanilla $ do+ sequence_ [ installOrdinary+ builtDir+ targetDir+ (mkGenericStaticLibName (l ++ f))+ | l <- getHSLibraryName+ (componentUnitId clbi):(extraBundledLibs (libBuildInfo lib))+ , f <- "":extraLibFlavours (libBuildInfo lib)+ ]+ whenGHCi $ installOrdinary builtDir targetDir ghciLibName+ whenProf $ do+ installOrdinary builtDir targetDir profileLibName+ whenGHCi $ installOrdinary builtDir targetDir ghciProfLibName+ whenShared $ if+ -- The behavior for "extra-bundled-libraries" changed in version 2.5.0.+ -- See ghc issue #15837 and Cabal PR #5855.+ | specVersion pkg < CabalSpecV3_0 -> do+ sequence_ [ installShared builtDir dynlibTargetDir+ (mkGenericSharedLibName platform compiler_id (l ++ f))+ | l <- getHSLibraryName uid : extraBundledLibs (libBuildInfo lib)+ , f <- "":extraDynLibFlavours (libBuildInfo lib)+ ]+ | otherwise -> do+ sequence_ [ installShared+ builtDir+ dynlibTargetDir+ (mkGenericSharedLibName+ platform+ compiler_id+ (getHSLibraryName uid ++ f))+ | f <- "":extraDynLibFlavours (libBuildInfo lib)+ ]+ sequence_ [ do+ files <- getDirectoryContents builtDir+ let l' = mkGenericSharedBundledLibName+ platform+ compiler_id+ l+ forM_ files $ \ file ->+ when (l' `isPrefixOf` file) $ do+ isFile <- doesFileExist (builtDir </> file)+ when isFile $ do+ installShared+ builtDir+ dynlibTargetDir+ file+ | l <- extraBundledLibs (libBuildInfo lib)+ ]++ where+ builtDir = componentBuildDir lbi clbi++ install isShared srcDir dstDir name = do+ let src = srcDir </> name+ dst = dstDir </> name++ createDirectoryIfMissingVerbose verbosity True dstDir++ if isShared+ then installExecutableFile verbosity src dst+ else installOrdinaryFile verbosity src dst++ when (stripLibs lbi) $ Strip.stripLib verbosity+ platform (withPrograms lbi) dst++ installOrdinary = install False+ installShared = install True++ copyModuleFiles ext =+ findModuleFilesEx verbosity [builtDir] [ext] (allLibModules lib clbi)+ >>= installOrdinaryFiles verbosity targetDir++ compiler_id = compilerId (compiler lbi)+ platform = hostPlatform lbi+ uid = componentUnitId clbi+ profileLibName = mkProfLibName uid+ ghciLibName = Internal.mkGHCiLibName uid+ ghciProfLibName = Internal.mkGHCiProfLibName uid++ hasLib = not $ null (allLibModules lib clbi)+ && null (cSources (libBuildInfo lib))+ && null (cxxSources (libBuildInfo lib))+ && null (cmmSources (libBuildInfo lib))+ && null (asmSources (libBuildInfo lib))+ has_code = not (componentIsIndefinite clbi)+ whenHasCode = when has_code+ whenVanilla = when (hasLib && withVanillaLib lbi)+ whenProf = when (hasLib && withProfLib lbi && has_code)+ whenGHCi = when (hasLib && withGHCiLib lbi && has_code)+ whenShared = when (hasLib && withSharedLib lbi && has_code)++-- -----------------------------------------------------------------------------+-- Registering++hcPkgInfo :: ProgramDb -> HcPkg.HcPkgInfo+hcPkgInfo progdb = HcPkg.HcPkgInfo+ { HcPkg.hcPkgProgram = ghcPkgProg+ , HcPkg.noPkgDbStack = v < [6,9]+ , HcPkg.noVerboseFlag = v < [6,11]+ , HcPkg.flagPackageConf = v < [7,5]+ , HcPkg.supportsDirDbs = v >= [6,8]+ , HcPkg.requiresDirDbs = v >= [7,10]+ , HcPkg.nativeMultiInstance = v >= [7,10]+ , HcPkg.recacheMultiInstance = v >= [6,12]+ , HcPkg.suppressFilesCheck = v >= [6,6]+ }+ where+ v = versionNumbers ver+ ghcPkgProg = fromMaybe (error "GHC.hcPkgInfo: no ghc program") $ lookupProgram ghcPkgProgram progdb+ ver = fromMaybe (error "GHC.hcPkgInfo: no ghc version") $ programVersion ghcPkgProg++registerPackage+ :: Verbosity+ -> ProgramDb+ -> PackageDBStack+ -> InstalledPackageInfo+ -> HcPkg.RegisterOptions+ -> IO ()+registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions =+ HcPkg.register (hcPkgInfo progdb) verbosity packageDbs+ installedPkgInfo registerOptions++pkgRoot :: Verbosity -> LocalBuildInfo -> PackageDB -> IO FilePath+pkgRoot verbosity lbi = pkgRoot'+ where+ pkgRoot' GlobalPackageDB =+ let ghcProg = fromMaybe (error "GHC.pkgRoot: no ghc program") $ lookupProgram ghcProgram (withPrograms lbi)+ in fmap takeDirectory (getGlobalPackageDB verbosity ghcProg)+ pkgRoot' UserPackageDB = do+ appDir <- getGhcAppDir+ let ver = compilerVersion (compiler lbi)+ subdir = System.Info.arch ++ '-':System.Info.os+ ++ '-':prettyShow 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+ -- directory at the time of 'ghc-pkg register', and registration will+ -- fail.+ createDirectoryIfMissing True rootDir+ return rootDir+ pkgRoot' (SpecificPackageDB fp) = return (takeDirectory fp)++-- -----------------------------------------------------------------------------+-- Utils++isDynamic :: Compiler -> Bool+isDynamic = Internal.ghcLookupProperty "GHC Dynamic"++supportsDynamicToo :: Compiler -> Bool+supportsDynamicToo = Internal.ghcLookupProperty "Support dynamic-too"++withExt :: FilePath -> String -> FilePath+withExt fp ext = fp <.> if takeExtension fp /= ('.':ext) then ext else ""
+ src/Distribution/Simple/GHC/EnvironmentParser.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+module Distribution.Simple.GHC.EnvironmentParser+ ( parseGhcEnvironmentFile, readGhcEnvironmentFile, ParseErrorExc(..) ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.Compiler+ ( PackageDB(..) )+import Distribution.Simple.GHC.Internal+ ( GhcEnvironmentFileEntry(..) )+import Distribution.Types.UnitId+ ( mkUnitId )++import qualified Text.Parsec as P+import Text.Parsec.String+ ( Parser, parseFromFile )++parseEnvironmentFileLine :: Parser GhcEnvironmentFileEntry+parseEnvironmentFileLine = GhcEnvFileComment <$> comment+ <|> GhcEnvFilePackageId <$> unitId+ <|> GhcEnvFilePackageDb <$> packageDb+ <|> pure GhcEnvFileClearPackageDbStack <* clearDb+ where+ comment = P.string "--" *> P.many (P.noneOf "\r\n")+ unitId = P.try $ P.string "package-id" *> P.spaces *>+ (mkUnitId <$> P.many1 (P.satisfy $ \c -> isAlphaNum c || c `elem` "-_.+"))+ packageDb = (P.string "global-package-db" *> pure GlobalPackageDB)+ <|> (P.string "user-package-db" *> pure UserPackageDB)+ <|> (P.string "package-db" *> P.spaces *> (SpecificPackageDB <$> P.many1 (P.noneOf "\r\n") <* P.lookAhead P.endOfLine))+ clearDb = P.string "clear-package-db"++newtype ParseErrorExc = ParseErrorExc P.ParseError+ deriving (Show, Typeable)++instance Exception ParseErrorExc++parseGhcEnvironmentFile :: Parser [GhcEnvironmentFileEntry]+parseGhcEnvironmentFile = parseEnvironmentFileLine `P.sepEndBy` P.endOfLine <* P.eof++readGhcEnvironmentFile :: FilePath -> IO [GhcEnvironmentFileEntry]+readGhcEnvironmentFile path =+ either (throwIO . ParseErrorExc) return =<<+ parseFromFile parseGhcEnvironmentFile path
+ src/Distribution/Simple/GHC/ImplInfo.hs view
@@ -0,0 +1,96 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.GHC.ImplInfo+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module contains the data structure describing invocation+-- details for a GHC or GHC-derived compiler, such as supported flags+-- and workarounds for bugs.++module Distribution.Simple.GHC.ImplInfo (+ GhcImplInfo(..), getImplInfo,+ ghcVersionImplInfo, ghcjsVersionImplInfo+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.Compiler+import Distribution.Version++{- |+ Information about features and quirks of a GHC-based implementation.++ Compiler flavors based on GHC behave similarly enough that some of+ the support code for them is shared. Every implementation has its+ own peculiarities, that may or may not be a direct result of the+ underlying GHC version. This record keeps track of these differences.++ All shared code (i.e. everything not in the Distribution.Simple.FLAVOR+ module) should use implementation info rather than version numbers+ to test for supported features.+-}++data GhcImplInfo = GhcImplInfo+ { supportsHaskell2010 :: Bool -- ^ -XHaskell2010 and -XHaskell98 flags+ , supportsGHC2021 :: Bool -- ^ -XGHC2021 flag+ , 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+ , supportsDebugLevels :: Bool -- ^ supports numeric @-g@ levels+ , supportsPkgEnvFiles :: Bool -- ^ picks up @.ghc.environment@ files+ , flagWarnMissingHomeModules :: Bool -- ^ -Wmissing-home-modules is supported+ }++getImplInfo :: Compiler -> GhcImplInfo+getImplInfo comp =+ case compilerFlavor comp of+ GHC -> ghcVersionImplInfo (compilerVersion comp)+ GHCJS -> case compilerCompatVersion GHC comp of+ Just ghcVer -> ghcjsVersionImplInfo (compilerVersion comp) ghcVer+ _ -> error ("Distribution.Simple.GHC.Props.getImplProps: " +++ "could not find GHC version for GHCJS compiler")+ x -> error ("Distribution.Simple.GHC.Props.getImplProps only works" +++ "for GHC-like compilers (GHC, GHCJS)" +++ ", but found " ++ show x)++ghcVersionImplInfo :: Version -> GhcImplInfo+ghcVersionImplInfo ver = GhcImplInfo+ { supportsHaskell2010 = v >= [7]+ , supportsGHC2021 = v >= [9,1]+ , reportsNoExt = v >= [7]+ , alwaysNondecIndent = v < [7,1]+ , flagGhciScript = v >= [7,2]+ , flagProfAuto = v >= [7,4]+ , flagPackageConf = v < [7,5]+ , flagDebugInfo = v >= [7,10]+ , supportsDebugLevels = v >= [8,0]+ , supportsPkgEnvFiles = v >= [8,0,1,20160901] -- broken in 8.0.1, fixed in 8.0.2+ , flagWarnMissingHomeModules = v >= [8,2]+ }+ where+ v = versionNumbers ver++ghcjsVersionImplInfo :: Version -- ^ The GHCJS version+ -> Version -- ^ The GHC version+ -> GhcImplInfo+ghcjsVersionImplInfo _ghcjsver ghcver = GhcImplInfo+ { supportsHaskell2010 = True+ , supportsGHC2021 = True+ , reportsNoExt = True+ , alwaysNondecIndent = False+ , flagGhciScript = True+ , flagProfAuto = True+ , flagPackageConf = False+ , flagDebugInfo = False+ , supportsDebugLevels = ghcv >= [8,0]+ , supportsPkgEnvFiles = ghcv >= [8,0,2] --TODO: check this works in ghcjs+ , flagWarnMissingHomeModules = ghcv >= [8,2]+ }+ where+ ghcv = versionNumbers ghcver
+ src/Distribution/Simple/GHC/Internal.hs view
@@ -0,0 +1,686 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.GHC.Internal+-- Copyright : Isaac Jones 2003-2007+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module contains functions shared by GHC (Distribution.Simple.GHC)+-- and GHC-derived compilers.++module Distribution.Simple.GHC.Internal (+ configureToolchain,+ getLanguages,+ getExtensions,+ targetPlatform,+ getGhcInfo,+ componentCcGhcOptions,+ componentCmmGhcOptions,+ componentCxxGhcOptions,+ componentAsmGhcOptions,+ componentGhcOptions,+ mkGHCiLibName,+ mkGHCiProfLibName,+ filterGhciFlags,+ ghcLookupProperty,+ getHaskellObjects,+ mkGhcOptPackages,+ substTopDir,+ checkPackageDbEnvVar,+ profDetailLevelFlag,+ -- * GHC platform and version strings+ ghcArchString,+ ghcOsString,+ ghcPlatformAndVersionString,+ -- * Constructing GHC environment files+ GhcEnvironmentFileEntry(..),+ writeGhcEnvironmentFile,+ simpleGhcEnvironmentFile,+ ghcEnvironmentFileName,+ renderGhcEnvironmentFile,+ renderGhcEnvironmentFileEntry,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.GHC.ImplInfo+import Distribution.Types.ComponentLocalBuildInfo+import Distribution.Backpack+import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.PackageDescription+import Distribution.Lex+import Distribution.Simple.Compiler+import Distribution.Simple.Program.GHC+import Distribution.Simple.Setup+import qualified Distribution.ModuleName as ModuleName+import Distribution.Simple.Program+import Distribution.Simple.LocalBuildInfo+import Distribution.Types.UnitId+import Distribution.Types.LocalBuildInfo+import Distribution.Types.TargetInfo+import Distribution.Simple.Utils+import Distribution.Simple.BuildPaths+import Distribution.System+import Distribution.Pretty ( prettyShow )+import Distribution.Parsec ( simpleParsec )+import Distribution.Utils.NubList ( toNubListR )+import Distribution.Verbosity+import Distribution.Compat.Stack+import Distribution.Version (Version)+import Distribution.Utils.Path+import Language.Haskell.Extension++import qualified Data.Map as Map+import qualified Data.ByteString.Lazy.Char8 as BS+import System.Directory ( getDirectoryContents, getTemporaryDirectory )+import System.Environment ( getEnv )+import System.FilePath ( (</>), (<.>), takeExtension+ , takeDirectory, takeFileName)+import System.IO ( hClose, hPutStrLn )++targetPlatform :: [(String, String)] -> Maybe Platform+targetPlatform ghcInfo = platformFromTriple =<< lookup "Target platform" ghcInfo++-- | Adjust the way we find and configure gcc and ld+--+configureToolchain :: GhcImplInfo+ -> ConfiguredProgram+ -> Map String String+ -> ProgramDb+ -> ProgramDb+configureToolchain _implInfo ghcProg ghcInfo =+ addKnownProgram gccProgram {+ programFindLocation = findProg gccProgramName extraGccPath,+ programPostConf = configureGcc+ }+ . addKnownProgram ldProgram {+ programFindLocation = findProg ldProgramName extraLdPath,+ programPostConf = configureLd+ }+ . addKnownProgram arProgram {+ programFindLocation = findProg arProgramName extraArPath+ }+ . addKnownProgram stripProgram {+ programFindLocation = findProg stripProgramName extraStripPath+ }+ where+ compilerDir = takeDirectory (programPath ghcProg)+ base_dir = takeDirectory compilerDir+ mingwBinDir = base_dir </> "mingw" </> "bin"+ 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+ where+ mbDir = maybeToList . fmap takeDirectory $ mbPath++ extraGccPath = mkExtraPath mbGccLocation windowsExtraGccDir+ extraLdPath = mkExtraPath mbLdLocation windowsExtraLdDir+ extraArPath = mkExtraPath mbArLocation windowsExtraArDir+ extraStripPath = mkExtraPath mbStripLocation windowsExtraStripDir++ -- on Windows finding and configuring ghc's gcc & binutils is a bit special+ (windowsExtraGccDir, windowsExtraLdDir,+ windowsExtraArDir, windowsExtraStripDir) =+ let b = mingwBinDir </> binPrefix+ in (b, b, b, b)++ findProg :: String -> [FilePath]+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+ findProg progName extraPath v searchpath =+ findProgramOnSearchPath v searchpath' progName+ where+ searchpath' = (map ProgramSearchPathDir extraPath) ++ searchpath++ -- Read tool locations from the 'ghc --info' output. Useful when+ -- cross-compiling.+ mbGccLocation = Map.lookup "C compiler command" ghcInfo+ mbLdLocation = Map.lookup "ld command" ghcInfo+ mbArLocation = Map.lookup "ar command" ghcInfo+ mbStripLocation = Map.lookup "strip command" ghcInfo++ ccFlags = getFlags "C compiler flags"+ -- GHC 7.8 renamed "Gcc Linker flags" to "C compiler link flags"+ -- and "Ld Linker flags" to "ld flags" (GHC #4862).+ gccLinkerFlags = getFlags "Gcc Linker flags" ++ getFlags "C compiler link flags"+ ldLinkerFlags = getFlags "Ld Linker flags" ++ getFlags "ld flags"++ -- 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 Map.lookup key ghcInfo of+ Nothing -> []+ Just flags+ | (flags', ""):_ <- reads flags -> flags'+ | otherwise -> tokenizeQuotedWords flags++ configureGcc :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram+ configureGcc _v gccProg = do+ return gccProg {+ programDefaultArgs = programDefaultArgs gccProg+ ++ ccFlags ++ gccLinkerFlags+ }++ configureLd :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram+ configureLd v ldProg = do+ ldProg' <- configureLd' v ldProg+ return ldProg' {+ programDefaultArgs = programDefaultArgs ldProg' ++ ldLinkerFlags+ }++ -- we need to find out if ld supports the -x flag+ configureLd' :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram+ configureLd' verbosity ldProg = do+ tempDir <- getTemporaryDirectory+ ldx <- withTempFile tempDir ".c" $ \testcfile testchnd ->+ withTempFile tempDir ".o" $ \testofile testohnd -> do+ hPutStrLn testchnd "int foo() { return 0; }"+ hClose testchnd; hClose testohnd+ runProgram verbosity ghcProg+ [ "-hide-all-packages"+ , "-c", testcfile+ , "-o", testofile+ ]+ withTempFile tempDir ".o" $ \testofile' testohnd' ->+ do+ hClose testohnd'+ _ <- getProgramOutput verbosity ldProg+ ["-x", "-r", testofile, "-o", testofile']+ return True+ `catchIO` (\_ -> return False)+ `catchExit` (\_ -> return False)+ if ldx+ then return ldProg { programDefaultArgs = ["-x"] }+ else return ldProg++getLanguages :: Verbosity -> GhcImplInfo -> ConfiguredProgram+ -> IO [(Language, String)]+getLanguages _ implInfo _+ -- TODO: should be using --supported-languages rather than hard coding+ | supportsGHC2021 implInfo = return+ [ (GHC2021, "-XGHC2021")+ , (Haskell2010, "-XHaskell2010")+ , (Haskell98, "-XHaskell98")+ ]+ | supportsHaskell2010 implInfo = return [(Haskell98, "-XHaskell98")+ ,(Haskell2010, "-XHaskell2010")]+ | otherwise = return [(Haskell98, "")]++getGhcInfo :: Verbosity -> GhcImplInfo -> ConfiguredProgram+ -> IO [(String, String)]+getGhcInfo verbosity _implInfo ghcProg = do+ xs <- getProgramOutput verbosity (suppressOverrideArgs ghcProg)+ ["--info"]+ case reads xs of+ [(i, ss)]+ | all isSpace ss ->+ return i+ _ ->+ die' verbosity "Can't parse --info output of GHC"++getExtensions :: Verbosity -> GhcImplInfo -> ConfiguredProgram+ -> IO [(Extension, Maybe String)]+getExtensions verbosity implInfo ghcProg = do+ str <- getProgramOutput verbosity (suppressOverrideArgs ghcProg)+ ["--supported-languages"]+ let extStrs = if reportsNoExt implInfo+ then lines str+ else -- Older GHCs only gave us either Foo or NoFoo,+ -- so we have to work out the other one ourselves+ [ extStr''+ | extStr <- lines str+ , let extStr' = case extStr of+ 'N' : 'o' : xs -> xs+ _ -> "No" ++ extStr+ , extStr'' <- [extStr, extStr']+ ]+ let extensions0 = [ (ext, Just $ "-X" ++ prettyShow ext)+ | Just ext <- map simpleParsec extStrs ]+ extensions1 = if alwaysNondecIndent implInfo+ then -- ghc-7.2 split NondecreasingIndentation off+ -- into a proper extension. Before that it+ -- was always on.+ -- Since it was not a proper extension, it could+ -- not be turned off, hence we omit a+ -- DisableExtension entry here.+ (EnableExtension NondecreasingIndentation, Nothing) :+ extensions0+ else extensions0+ return extensions1++componentCcGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> FilePath+ -> GhcOptions+componentCcGhcOptions verbosity _implInfo lbi bi clbi odir filename =+ mempty {+ -- Respect -v0, but don't crank up verbosity on GHC if+ -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!+ ghcOptVerbosity = toFlag (min verbosity normal),+ ghcOptMode = toFlag GhcModeCompile,+ ghcOptInputFiles = toNubListR [filename],++ ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi+ ,odir]+ -- includes relative to the package+ ++ includeDirs bi+ -- potential includes generated by `configure'+ -- in the build directory+ ++ [buildDir lbi </> dir | dir <- includeDirs bi],+ ghcOptHideAllPackages= toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,+ ghcOptCcOptions = (case withOptimization lbi of+ NoOptimisation -> []+ _ -> ["-O2"]) +++ (case withDebugInfo lbi of+ NoDebugInfo -> []+ MinimalDebugInfo -> ["-g1"]+ NormalDebugInfo -> ["-g"]+ MaximalDebugInfo -> ["-g3"]) +++ ccOptions bi,+ ghcOptObjDir = toFlag odir+ }+++componentCxxGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> FilePath+ -> GhcOptions+componentCxxGhcOptions verbosity _implInfo lbi bi clbi odir filename =+ mempty {+ -- Respect -v0, but don't crank up verbosity on GHC if+ -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!+ ghcOptVerbosity = toFlag (min verbosity normal),+ ghcOptMode = toFlag GhcModeCompile,+ ghcOptInputFiles = toNubListR [filename],++ ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi+ ,odir]+ -- includes relative to the package+ ++ includeDirs bi+ -- potential includes generated by `configure'+ -- in the build directory+ ++ [buildDir lbi </> dir | dir <- includeDirs bi],+ ghcOptHideAllPackages= toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,+ ghcOptCxxOptions = (case withOptimization lbi of+ NoOptimisation -> []+ _ -> ["-O2"]) +++ (case withDebugInfo lbi of+ NoDebugInfo -> []+ MinimalDebugInfo -> ["-g1"]+ NormalDebugInfo -> ["-g"]+ MaximalDebugInfo -> ["-g3"]) +++ cxxOptions bi,+ ghcOptObjDir = toFlag odir+ }+++componentAsmGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> FilePath+ -> GhcOptions+componentAsmGhcOptions verbosity _implInfo lbi bi clbi odir filename =+ mempty {+ -- Respect -v0, but don't crank up verbosity on GHC if+ -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!+ ghcOptVerbosity = toFlag (min verbosity normal),+ ghcOptMode = toFlag GhcModeCompile,+ ghcOptInputFiles = toNubListR [filename],++ ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi+ ,odir]+ -- includes relative to the package+ ++ includeDirs bi+ -- potential includes generated by `configure'+ -- in the build directory+ ++ [buildDir lbi </> dir | dir <- includeDirs bi],+ ghcOptHideAllPackages= toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,+ ghcOptAsmOptions = (case withOptimization lbi of+ NoOptimisation -> []+ _ -> ["-O2"]) +++ (case withDebugInfo lbi of+ NoDebugInfo -> []+ MinimalDebugInfo -> ["-g1"]+ NormalDebugInfo -> ["-g"]+ MaximalDebugInfo -> ["-g3"]) +++ asmOptions bi,+ ghcOptObjDir = toFlag odir+ }+++componentGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo -> FilePath+ -> GhcOptions+componentGhcOptions verbosity implInfo lbi bi clbi odir =+ mempty {+ -- Respect -v0, but don't crank up verbosity on GHC if+ -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!+ ghcOptVerbosity = toFlag (min verbosity normal),+ ghcOptCabal = toFlag True,+ ghcOptThisUnitId = case clbi of+ LibComponentLocalBuildInfo { componentCompatPackageKey = pk }+ -> toFlag pk+ _ -> mempty,+ ghcOptThisComponentId = case clbi of+ LibComponentLocalBuildInfo { componentComponentId = cid+ , componentInstantiatedWith = insts } ->+ if null insts+ then mempty+ else toFlag cid+ _ -> mempty,+ ghcOptInstantiatedWith = case clbi of+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts }+ -> insts+ _ -> [],+ ghcOptNoCode = toFlag $ componentIsIndefinite clbi,+ ghcOptHideAllPackages = toFlag True,+ ghcOptWarnMissingHomeModules = toFlag $ flagWarnMissingHomeModules implInfo,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,+ ghcOptSplitSections = toFlag (splitSections lbi),+ ghcOptSplitObjs = toFlag (splitObjs lbi),+ ghcOptSourcePathClear = toFlag True,+ ghcOptSourcePath = toNubListR $ [odir] ++ (map getSymbolicPath (hsSourceDirs bi))+ ++ [autogenComponentModulesDir lbi clbi]+ ++ [autogenPackageModulesDir lbi],+ ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi+ ,odir]+ -- includes relative to the package+ ++ includeDirs bi+ -- potential includes generated by `configure'+ -- in the build directory+ ++ [buildDir lbi </> dir | dir <- includeDirs bi],+ ghcOptCppOptions = cppOptions bi,+ ghcOptCppIncludes = toNubListR $+ [autogenComponentModulesDir lbi clbi </> cppHeaderName],+ ghcOptFfiIncludes = toNubListR $ includes bi,+ ghcOptObjDir = toFlag odir,+ ghcOptHiDir = toFlag odir,+ ghcOptStubDir = toFlag odir,+ ghcOptOutputDir = toFlag odir,+ ghcOptOptimisation = toGhcOptimisation (withOptimization lbi),+ ghcOptDebugInfo = toFlag (withDebugInfo lbi),+ ghcOptExtra = hcOptions GHC bi,+ ghcOptExtraPath = toNubListR $ exe_paths,+ ghcOptLanguage = toFlag (fromMaybe Haskell98 (defaultLanguage bi)),+ -- Unsupported extensions have already been checked by configure+ ghcOptExtensions = toNubListR $ usedExtensions bi,+ ghcOptExtensionMap = Map.fromList . compilerExtensions $ (compiler lbi)+ }+ where+ exe_paths = [ componentBuildDir lbi (targetCLBI exe_tgt)+ | uid <- componentExeDeps clbi+ -- TODO: Ugh, localPkgDescr+ , Just exe_tgt <- [unitIdTarget' (localPkgDescr lbi) lbi uid] ]++toGhcOptimisation :: OptimisationLevel -> Flag GhcOptimisation+toGhcOptimisation NoOptimisation = mempty --TODO perhaps override?+toGhcOptimisation NormalOptimisation = toFlag GhcNormalOptimisation+toGhcOptimisation MaximumOptimisation = toFlag GhcMaximumOptimisation+++componentCmmGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> FilePath+ -> GhcOptions+componentCmmGhcOptions verbosity _implInfo lbi bi clbi odir filename =+ mempty {+ -- Respect -v0, but don't crank up verbosity on GHC if+ -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!+ ghcOptVerbosity = toFlag (min verbosity normal),+ ghcOptMode = toFlag GhcModeCompile,+ ghcOptInputFiles = toNubListR [filename],++ ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi+ ,odir]+ -- includes relative to the package+ ++ includeDirs bi+ -- potential includes generated by `configure'+ -- in the build directory+ ++ [buildDir lbi </> dir | dir <- includeDirs bi],+ ghcOptCppOptions = cppOptions bi,+ ghcOptCppIncludes = toNubListR $+ [autogenComponentModulesDir lbi clbi </> cppHeaderName],+ ghcOptHideAllPackages= toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,+ ghcOptOptimisation = toGhcOptimisation (withOptimization lbi),+ ghcOptDebugInfo = toFlag (withDebugInfo lbi),+ ghcOptExtra = cmmOptions bi,+ ghcOptObjDir = toFlag odir+ }+++-- | Strip out flags that are not supported in ghci+filterGhciFlags :: [String] -> [String]+filterGhciFlags = filter supported+ where+ supported ('-':'O':_) = False+ supported "-debug" = False+ supported "-threaded" = False+ supported "-ticky" = False+ supported "-eventlog" = False+ supported "-prof" = False+ supported "-unreg" = False+ supported _ = True++mkGHCiLibName :: UnitId -> String+mkGHCiLibName lib = getHSLibraryName lib <.> "o"++mkGHCiProfLibName :: UnitId -> String+mkGHCiProfLibName lib = getHSLibraryName lib <.> "p_o"++ghcLookupProperty :: String -> Compiler -> Bool+ghcLookupProperty prop comp =+ case Map.lookup prop (compilerProperties comp) of+ Just "YES" -> True+ _ -> False++-- when using -split-objs, we need to search for object files in the+-- Module_split directory for each module.+getHaskellObjects :: GhcImplInfo -> Library -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> FilePath -> String -> Bool -> IO [FilePath]+getHaskellObjects _implInfo lib lbi clbi pref wanted_obj_ext allow_split_objs+ | splitObjs lbi && allow_split_objs = do+ let splitSuffix = "_" ++ wanted_obj_ext ++ "_split"+ dirs = [ pref </> (ModuleName.toFilePath x ++ splitSuffix)+ | x <- allLibModules lib clbi ]+ objss <- traverse getDirectoryContents dirs+ let objs = [ dir </> obj+ | (objs',dir) <- zip objss dirs, obj <- objs',+ let obj_ext = takeExtension obj,+ '.':wanted_obj_ext == obj_ext ]+ return objs+ | otherwise =+ return [ pref </> ModuleName.toFilePath x <.> wanted_obj_ext+ | x <- allLibModules lib clbi ]++mkGhcOptPackages :: ComponentLocalBuildInfo+ -> [(OpenUnitId, ModuleRenaming)]+mkGhcOptPackages = componentIncludes++substTopDir :: FilePath -> IPI.InstalledPackageInfo -> IPI.InstalledPackageInfo+substTopDir topDir ipo+ = ipo {+ IPI.importDirs = map f (IPI.importDirs ipo),+ IPI.libraryDirs = map f (IPI.libraryDirs ipo),+ IPI.includeDirs = map f (IPI.includeDirs ipo),+ IPI.frameworkDirs = map f (IPI.frameworkDirs ipo),+ IPI.haddockInterfaces = map f (IPI.haddockInterfaces ipo),+ IPI.haddockHTMLs = map f (IPI.haddockHTMLs ipo)+ }+ where f ('$':'t':'o':'p':'d':'i':'r':rest) = topDir ++ rest+ f x = x++-- Cabal does not use the environment variable GHC{,JS}_PACKAGE_PATH; let+-- users know that this is the case. See ticket #335. Simply ignoring it is+-- not a good idea, since then ghc and cabal are looking at different sets+-- of package DBs and chaos is likely to ensue.+--+-- An exception to this is when running cabal from within a `cabal exec`+-- environment. In this case, `cabal exec` will set the+-- CABAL_SANDBOX_PACKAGE_PATH to the same value that it set+-- GHC{,JS}_PACKAGE_PATH to. If that is the case it is OK to allow+-- GHC{,JS}_PACKAGE_PATH.+checkPackageDbEnvVar :: Verbosity -> String -> String -> IO ()+checkPackageDbEnvVar verbosity compilerName packagePathEnvVar = do+ mPP <- lookupEnv packagePathEnvVar+ when (isJust mPP) $ do+ mcsPP <- lookupEnv "CABAL_SANDBOX_PACKAGE_PATH"+ unless (mPP == mcsPP) abort+ where+ lookupEnv :: String -> IO (Maybe String)+ lookupEnv name = (Just `fmap` getEnv name)+ `catchIO` const (return Nothing)+ abort =+ die' verbosity $ "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)."++ _ = callStack -- TODO: output stack when erroring++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 platform and version strings++-- | GHC's rendering of its host or target 'Arch' as used in its platform+-- strings and certain file locations (such as user package db location).+--+ghcArchString :: Arch -> String+ghcArchString PPC = "powerpc"+ghcArchString PPC64 = "powerpc64"+ghcArchString other = prettyShow other++-- | GHC's rendering of its host or target 'OS' as used in its platform+-- strings and certain file locations (such as user package db location).+--+ghcOsString :: OS -> String+ghcOsString Windows = "mingw32"+ghcOsString OSX = "darwin"+ghcOsString Solaris = "solaris2"+ghcOsString other = prettyShow other++-- | GHC's rendering of its platform and compiler version string as used in+-- certain file locations (such as user package db location).+-- For example @x86_64-linux-7.10.4@+--+ghcPlatformAndVersionString :: Platform -> Version -> String+ghcPlatformAndVersionString (Platform arch os) version =+ intercalate "-" [ ghcArchString arch, ghcOsString os, prettyShow version ]+++-- -----------------------------------------------------------------------------+-- Constructing GHC environment files++-- | The kinds of entries we can stick in a @.ghc.environment@ file.+--+data GhcEnvironmentFileEntry =+ GhcEnvFileComment String -- ^ @-- a comment@+ | GhcEnvFilePackageId UnitId -- ^ @package-id foo-1.0-4fe301a...@+ | GhcEnvFilePackageDb PackageDB -- ^ @global-package-db@,+ -- @user-package-db@ or+ -- @package-db blah/package.conf.d/@+ | GhcEnvFileClearPackageDbStack -- ^ @clear-package-db@+ deriving (Eq, Ord, Show)++-- | Make entries for a GHC environment file based on a 'PackageDBStack' and+-- a bunch of package (unit) ids.+--+-- If you need to do anything more complicated then either use this as a basis+-- and add more entries, or just make all the entries directly.+--+simpleGhcEnvironmentFile :: PackageDBStack+ -> [UnitId]+ -> [GhcEnvironmentFileEntry]+simpleGhcEnvironmentFile packageDBs pkgids =+ GhcEnvFileClearPackageDbStack+ : map GhcEnvFilePackageDb packageDBs+ ++ map GhcEnvFilePackageId pkgids++-- | Write a @.ghc.environment-$arch-$os-$ver@ file in the given directory.+--+-- The 'Platform' and GHC 'Version' are needed as part of the file name.+--+-- Returns the name of the file written.+writeGhcEnvironmentFile :: FilePath -- ^ directory in which to put it+ -> Platform -- ^ the GHC target platform+ -> Version -- ^ the GHC version+ -> [GhcEnvironmentFileEntry] -- ^ the content+ -> IO FilePath+writeGhcEnvironmentFile directory platform ghcversion entries = do+ writeFileAtomic envfile . BS.pack . renderGhcEnvironmentFile $ entries+ return envfile+ where+ envfile = directory </> ghcEnvironmentFileName platform ghcversion++-- | The @.ghc.environment-$arch-$os-$ver@ file name+--+ghcEnvironmentFileName :: Platform -> Version -> FilePath+ghcEnvironmentFileName platform ghcversion =+ ".ghc.environment." ++ ghcPlatformAndVersionString platform ghcversion++-- | Render a bunch of GHC environment file entries+--+renderGhcEnvironmentFile :: [GhcEnvironmentFileEntry] -> String+renderGhcEnvironmentFile =+ unlines . map renderGhcEnvironmentFileEntry++-- | Render an individual GHC environment file entry+--+renderGhcEnvironmentFileEntry :: GhcEnvironmentFileEntry -> String+renderGhcEnvironmentFileEntry entry = case entry of+ GhcEnvFileComment comment -> format comment+ where format = intercalate "\n" . map ("--" <++>) . lines+ pref <++> "" = pref+ pref <++> str = pref ++ " " ++ str+ GhcEnvFilePackageId pkgid -> "package-id " ++ prettyShow pkgid+ GhcEnvFilePackageDb pkgdb ->+ case pkgdb of+ GlobalPackageDB -> "global-package-db"+ UserPackageDB -> "user-package-db"+ SpecificPackageDB dbfile -> "package-db " ++ dbfile+ GhcEnvFileClearPackageDbStack -> "clear-package-db"
+ src/Distribution/Simple/GHCJS.hs view
@@ -0,0 +1,1831 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE CPP #-}++module Distribution.Simple.GHCJS (+ getGhcInfo,+ configure,+ getInstalledPackages,+ getInstalledPackagesMonitorFiles,+ getPackageDBContents,+ buildLib, buildFLib, buildExe,+ replLib, replFLib, replExe,+ startInterpreter,+ installLib, installFLib, installExe,+ libAbiHash,+ hcPkgInfo,+ registerPackage,+ componentGhcOptions,+ componentCcGhcOptions,+ getLibDir,+ isDynamic,+ getGlobalPackageDB,+ pkgRoot,+ runCmd,+ -- * Constructing and deconstructing GHC environment files+ Internal.GhcEnvironmentFileEntry(..),+ Internal.simpleGhcEnvironmentFile,+ Internal.renderGhcEnvironmentFile,+ Internal.writeGhcEnvironmentFile,+ Internal.ghcPlatformAndVersionString,+ readGhcEnvironmentFile,+ parseGhcEnvironmentFile,+ ParseErrorExc(..),+ -- * Version-specific implementation quirks+ getImplInfo,+ GhcImplInfo(..)+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Distribution.Simple.GHC.Internal as Internal+import Distribution.Simple.GHC.ImplInfo+import Distribution.Simple.GHC.EnvironmentParser+import Distribution.PackageDescription.Utils (cabalBug)+import Distribution.PackageDescription as PD+import Distribution.InstalledPackageInfo (InstalledPackageInfo)+import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo+import Distribution.Simple.PackageIndex (InstalledPackageIndex)+import qualified Distribution.Simple.PackageIndex as PackageIndex+import Distribution.Simple.LocalBuildInfo+import Distribution.Types.ComponentLocalBuildInfo+import qualified Distribution.Simple.Hpc as Hpc+import Distribution.Simple.BuildPaths+import Distribution.Simple.Utils+import Distribution.Package+import qualified Distribution.ModuleName as ModuleName+import Distribution.ModuleName (ModuleName)+import Distribution.Simple.Program+import qualified Distribution.Simple.Program.HcPkg as HcPkg+import qualified Distribution.Simple.Program.Strip as Strip+import Distribution.Simple.Program.GHC+import Distribution.Simple.Setup+import qualified Distribution.Simple.Setup as Cabal+import Distribution.Simple.Compiler+import Distribution.CabalSpecVersion+import Distribution.Version+import Distribution.System+import Distribution.Verbosity+import Distribution.Pretty+import Distribution.Utils.NubList+import Distribution.Utils.Path++import Control.Monad (msum)+import Data.Char (isLower)+import qualified Data.Map as Map+import System.Directory+ ( doesFileExist, getAppUserDataDirectory, createDirectoryIfMissing+ , canonicalizePath, removeFile, renameFile )+import System.FilePath ( (</>), (<.>), takeExtension+ , takeDirectory, replaceExtension+ ,isRelative )+import qualified System.Info++-- -----------------------------------------------------------------------------+-- Configuring++configure :: Verbosity -> Maybe FilePath -> Maybe FilePath+ -> ProgramDb+ -> IO (Compiler, Maybe Platform, ProgramDb)+configure verbosity hcPath hcPkgPath conf0 = do++ (ghcjsProg, ghcjsVersion, progdb1) <-+ requireProgramVersion verbosity ghcjsProgram+ (orLaterVersion (mkVersion [0,1]))+ (userMaybeSpecifyPath "ghcjs" hcPath conf0)++ Just ghcjsGhcVersion <- findGhcjsGhcVersion verbosity (programPath ghcjsProg)+ unless (ghcjsGhcVersion < mkVersion [8,8]) $+ warn verbosity $+ "Unknown/unsupported 'ghc' version detected "+ ++ "(Cabal " ++ prettyShow cabalVersion ++ " supports 'ghc' version < 8.8): "+ ++ programPath ghcjsProg ++ " is based on GHC version " +++ prettyShow ghcjsGhcVersion++ let implInfo = ghcjsVersionImplInfo ghcjsVersion ghcjsGhcVersion++ -- This is slightly tricky, we have to configure ghc first, then we use the+ -- location of ghc to help find ghc-pkg in the case that the user did not+ -- specify the location of ghc-pkg directly:+ (ghcjsPkgProg, ghcjsPkgVersion, progdb2) <-+ requireProgramVersion verbosity ghcjsPkgProgram {+ programFindLocation = guessGhcjsPkgFromGhcjsPath ghcjsProg+ }+ anyVersion (userMaybeSpecifyPath "ghcjs-pkg" hcPkgPath progdb1)++ Just ghcjsPkgGhcjsVersion <- findGhcjsPkgGhcjsVersion+ verbosity (programPath ghcjsPkgProg)++ when (ghcjsVersion /= ghcjsPkgGhcjsVersion) $ die' verbosity $+ "Version mismatch between ghcjs and ghcjs-pkg: "+ ++ programPath ghcjsProg ++ " is version " ++ prettyShow ghcjsVersion ++ " "+ ++ programPath ghcjsPkgProg ++ " is version " ++ prettyShow ghcjsPkgGhcjsVersion++ when (ghcjsGhcVersion /= ghcjsPkgVersion) $ die' verbosity $+ "Version mismatch between ghcjs and ghcjs-pkg: "+ ++ programPath ghcjsProg+ ++ " was built with GHC version " ++ prettyShow ghcjsGhcVersion ++ " "+ ++ programPath ghcjsPkgProg+ ++ " was built with GHC version " ++ prettyShow ghcjsPkgVersion+++ -- Likewise we try to find the matching hsc2hs and haddock programs.+ let hsc2hsProgram' = hsc2hsProgram {+ programFindLocation =+ guessHsc2hsFromGhcjsPath ghcjsProg+ }+ haddockProgram' = haddockProgram {+ programFindLocation =+ guessHaddockFromGhcjsPath ghcjsProg+ }+ hpcProgram' = hpcProgram {+ programFindLocation = guessHpcFromGhcjsPath ghcjsProg+ }+ {-+ runghcProgram' = runghcProgram {+ programFindLocation = guessRunghcFromGhcjsPath ghcjsProg+ } -}+ progdb3 = addKnownProgram haddockProgram' $+ addKnownProgram hsc2hsProgram' $+ addKnownProgram hpcProgram' $+ {- addKnownProgram runghcProgram' -} progdb2++ languages <- Internal.getLanguages verbosity implInfo ghcjsProg+ extensions <- Internal.getExtensions verbosity implInfo ghcjsProg++ ghcjsInfo <- Internal.getGhcInfo verbosity implInfo ghcjsProg+ let ghcInfoMap = Map.fromList ghcjsInfo++ let comp = Compiler {+ compilerId = CompilerId GHCJS ghcjsVersion,+ compilerAbiTag = AbiTag $+ "ghc" ++ intercalate "_" (map show . versionNumbers $ ghcjsGhcVersion),+ compilerCompat = [CompilerId GHC ghcjsGhcVersion],+ compilerLanguages = languages,+ compilerExtensions = extensions,+ compilerProperties = ghcInfoMap+ }+ compPlatform = Internal.targetPlatform ghcjsInfo+ return (comp, compPlatform, progdb3)++guessGhcjsPkgFromGhcjsPath :: ConfiguredProgram -> Verbosity+ -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))+guessGhcjsPkgFromGhcjsPath = guessToolFromGhcjsPath ghcjsPkgProgram++guessHsc2hsFromGhcjsPath :: ConfiguredProgram -> Verbosity+ -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))+guessHsc2hsFromGhcjsPath = guessToolFromGhcjsPath hsc2hsProgram++guessHaddockFromGhcjsPath :: ConfiguredProgram -> Verbosity+ -> ProgramSearchPath -> IO (Maybe (FilePath, [FilePath]))+guessHaddockFromGhcjsPath = guessToolFromGhcjsPath haddockProgram++guessHpcFromGhcjsPath :: ConfiguredProgram+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+guessHpcFromGhcjsPath = guessToolFromGhcjsPath hpcProgram+++guessToolFromGhcjsPath :: Program -> ConfiguredProgram+ -> Verbosity -> ProgramSearchPath+ -> IO (Maybe (FilePath, [FilePath]))+guessToolFromGhcjsPath tool ghcjsProg verbosity searchpath+ = do let toolname = programName tool+ given_path = programPath ghcjsProg+ 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 buildPlatform+ guessGhcjs dir = dir </> (toolname ++ "-ghcjs")+ <.> exeExtension buildPlatform+ guessGhcjsVersioned dir suf = dir </> (toolname ++ "-ghcjs" ++ suf)+ <.> exeExtension buildPlatform+ guessVersioned dir suf = dir </> (toolname ++ suf)+ <.> exeExtension buildPlatform+ mkGuesses dir suf | null suf = [guessGhcjs dir, guessNormal dir]+ | otherwise = [guessGhcjsVersioned dir suf,+ guessVersioned dir suf,+ guessGhcjs dir,+ 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 " ++ given_dir+ debug verbosity $ "candidate locations: " ++ show guesses+ exists <- traverse 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+ let lookedAt = map fst+ . takeWhile (\(_file, exist) -> not exist)+ $ zip guesses exists+ return (Just (fp, lookedAt))++ where takeVersionSuffix :: FilePath -> String+ takeVersionSuffix = takeWhileEndLE isSuffixChar++ isSuffixChar :: Char -> Bool+ isSuffixChar c = isDigit c || c == '.' || c == '-'++getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)]+getGhcInfo verbosity ghcjsProg = Internal.getGhcInfo verbosity implInfo ghcjsProg+ where+ version = fromMaybe (error "GHCJS.getGhcInfo: no version") $ programVersion ghcjsProg+ implInfo = ghcVersionImplInfo version++-- | Given a single package DB, return all installed packages.+getPackageDBContents :: Verbosity -> PackageDB -> ProgramDb+ -> IO InstalledPackageIndex+getPackageDBContents verbosity packagedb progdb = do+ pkgss <- getInstalledPackages' verbosity [packagedb] progdb+ toPackageIndex verbosity pkgss progdb++-- | Given a package DB stack, return all installed packages.+getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramDb+ -> IO InstalledPackageIndex+getInstalledPackages verbosity packagedbs progdb = do+ checkPackageDbEnvVar verbosity+ checkPackageDbStack verbosity packagedbs+ pkgss <- getInstalledPackages' verbosity packagedbs progdb+ index <- toPackageIndex verbosity pkgss progdb+ return $! index++toPackageIndex :: Verbosity+ -> [(PackageDB, [InstalledPackageInfo])]+ -> ProgramDb+ -> IO InstalledPackageIndex+toPackageIndex verbosity pkgss progdb = do+ -- On Windows, various fields have $topdir/foo rather than full+ -- paths. We need to substitute the right value in so that when+ -- we, for example, call gcc, we have proper paths to give it.+ topDir <- getLibDir' verbosity ghcjsProg+ let indices = [ PackageIndex.fromList (map (Internal.substTopDir topDir) pkgs)+ | (_, pkgs) <- pkgss ]+ return $! (mconcat indices)++ where+ ghcjsProg = fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb++getLibDir :: Verbosity -> LocalBuildInfo -> IO FilePath+getLibDir verbosity lbi =+ dropWhileEndLE isSpace `fmap`+ getDbProgramOutput verbosity ghcjsProgram+ (withPrograms lbi) ["--print-libdir"]++getLibDir' :: Verbosity -> ConfiguredProgram -> IO FilePath+getLibDir' verbosity ghcjsProg =+ dropWhileEndLE isSpace `fmap`+ getProgramOutput verbosity ghcjsProg ["--print-libdir"]+++-- | Return the 'FilePath' to the global GHC package database.+getGlobalPackageDB :: Verbosity -> ConfiguredProgram -> IO FilePath+getGlobalPackageDB verbosity ghcProg =+ dropWhileEndLE isSpace `fmap`+ getProgramOutput verbosity ghcProg ["--print-global-package-db"]++-- | Return the 'FilePath' to the per-user GHC package database.+getUserPackageDB :: Verbosity -> ConfiguredProgram -> Platform -> IO FilePath+getUserPackageDB _verbosity ghcjsProg platform = 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 "ghcjs"+ return (appdir </> platformAndVersion </> packageConfFileName)+ where+ platformAndVersion = Internal.ghcPlatformAndVersionString+ platform ghcjsVersion+ packageConfFileName = "package.conf.d"+ ghcjsVersion = fromMaybe (error "GHCJS.getUserPackageDB: no version") $ programVersion ghcjsProg++checkPackageDbEnvVar :: Verbosity -> IO ()+checkPackageDbEnvVar verbosity =+ Internal.checkPackageDbEnvVar verbosity "GHCJS" "GHCJS_PACKAGE_PATH"++checkPackageDbStack :: Verbosity -> PackageDBStack -> IO ()+checkPackageDbStack _ (GlobalPackageDB:rest)+ | GlobalPackageDB `notElem` rest = return ()+checkPackageDbStack verbosity rest+ | GlobalPackageDB `notElem` rest =+ die' verbosity $ "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 https://gitlab.haskell.org/ghc/ghc/-/issues/5977"+checkPackageDbStack verbosity _ =+ die' verbosity $ "If the global package db is specified, it must be "+ ++ "specified first and cannot be specified multiple times"++getInstalledPackages' :: Verbosity -> [PackageDB] -> ProgramDb+ -> IO [(PackageDB, [InstalledPackageInfo])]+getInstalledPackages' verbosity packagedbs progdb =+ sequenceA+ [ do pkgs <- HcPkg.dump (hcPkgInfo progdb) verbosity packagedb+ return (packagedb, pkgs)+ | packagedb <- packagedbs ]++-- | Get the packages from specific PackageDBs, not cumulative.+--+getInstalledPackagesMonitorFiles :: Verbosity -> Platform+ -> ProgramDb+ -> [PackageDB]+ -> IO [FilePath]+getInstalledPackagesMonitorFiles verbosity platform progdb =+ traverse getPackageDBPath+ where+ getPackageDBPath :: PackageDB -> IO FilePath+ getPackageDBPath GlobalPackageDB =+ selectMonitorFile =<< getGlobalPackageDB verbosity ghcjsProg++ getPackageDBPath UserPackageDB =+ selectMonitorFile =<< getUserPackageDB verbosity ghcjsProg 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")++ ghcjsProg = fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb+++toJSLibName :: String -> String+toJSLibName lib+ | takeExtension lib `elem` [".dll",".dylib",".so"]+ = replaceExtension lib "js_so"+ | takeExtension lib == ".a" = replaceExtension lib "js_a"+ | otherwise = lib <.> "js_a"++-- -----------------------------------------------------------------------------+-- Building a library++buildLib :: Verbosity -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo+ -> IO ()+buildLib = buildOrReplLib Nothing++replLib :: [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> Library+ -> ComponentLocalBuildInfo -> IO ()+replLib = buildOrReplLib . Just++buildOrReplLib :: Maybe [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> Library+ -> ComponentLocalBuildInfo -> IO ()+buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do+ let uid = componentUnitId clbi+ libTargetDir = componentBuildDir lbi clbi+ whenVanillaLib forceVanilla =+ when (forceVanilla || withVanillaLib lbi)+ whenProfLib = when (withProfLib lbi)+ whenSharedLib forceShared =+ when (forceShared || withSharedLib lbi)+ whenStaticLib forceStatic =+ when (forceStatic || withStaticLib lbi)+ -- whenGHCiLib = when (withGHCiLib lbi)+ forRepl = maybe False (const True) mReplFlags+ -- ifReplLib = when forRepl+ comp = compiler lbi+ implInfo = getImplInfo comp+ platform@(Platform _hostArch _hostOS) = hostPlatform lbi+ has_code = not (componentIsIndefinite clbi)++ (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)+ let runGhcjsProg = runGHC verbosity ghcjsProg comp platform++ let libBi = libBuildInfo lib++ -- fixme flags shouldn't depend on ghcjs being dynamic or not+ let isGhcjsDynamic = isDynamic comp+ dynamicTooSupported = supportsDynamicToo comp+ doingTH = usesTemplateHaskellOrQQ libBi+ forceVanillaLib = doingTH && not isGhcjsDynamic+ forceSharedLib = doingTH && isGhcjsDynamic+ -- TH always needs default libs, even when building for profiling++ -- Determine if program coverage should be enabled and if so, what+ -- '-hpcdir' should be.+ let isCoverageEnabled = libCoverage lbi+ -- TODO: Historically HPC files have been put into a directory which+ -- has the package name. I'm going to avoid changing this for+ -- now, but it would probably be better for this to be the+ -- component ID instead...+ pkg_name = prettyShow (PD.package pkg_descr)+ distPref = fromFlag $ configDistPref $ configFlags lbi+ hpcdir way+ | forRepl = mempty -- HPC is not supported in ghci+ | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way pkg_name+ | otherwise = mempty++ createDirectoryIfMissingVerbose verbosity True libTargetDir+ -- TODO: do we need to put hs-boot files into place for mutually recursive+ -- modules?+ let cLikeFiles = fromNubListR $ toNubListR (cSources libBi) <> toNubListR (cxxSources libBi)+ jsSrcs = jsSources libBi+ cObjs = map (`replaceExtension` objExtension) cLikeFiles+ baseOpts = componentGhcOptions verbosity lbi libBi clbi libTargetDir+ linkJsLibOpts = mempty {+ ghcOptExtra =+ [ "-link-js-lib" , getHSLibraryName uid+ , "-js-lib-outputdir", libTargetDir ] +++ jsSrcs+ }+ vanillaOptsNoJsLib = baseOpts `mappend` mempty {+ ghcOptMode = toFlag GhcModeMake,+ ghcOptNumJobs = numJobs,+ ghcOptInputModules = toNubListR $ allLibModules lib clbi,+ ghcOptHPCDir = hpcdir Hpc.Vanilla+ }+ vanillaOpts = vanillaOptsNoJsLib `mappend` linkJsLibOpts++ profOpts = adjustExts "p_hi" "p_o" vanillaOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag True+ (withProfLibDetail lbi),+ -- ghcOptHiSuffix = toFlag "p_hi",+ -- ghcOptObjSuffix = toFlag "p_o",+ ghcOptExtra = hcProfOptions GHC libBi,+ ghcOptHPCDir = hpcdir Hpc.Prof+ }++ sharedOpts = adjustExts "dyn_hi" "dyn_o" vanillaOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptFPic = toFlag True,+ -- ghcOptHiSuffix = toFlag "dyn_hi",+ -- ghcOptObjSuffix = toFlag "dyn_o",+ ghcOptExtra = hcSharedOptions GHC libBi,+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }++ vanillaSharedOpts = vanillaOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,+ ghcOptDynHiSuffix = toFlag "js_dyn_hi",+ ghcOptDynObjSuffix = toFlag "js_dyn_o",+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }++ unless (forRepl || null (allLibModules lib clbi) && null jsSrcs && null cObjs) $+ do let vanilla = whenVanillaLib forceVanillaLib (runGhcjsProg vanillaOpts)+ shared = whenSharedLib forceSharedLib (runGhcjsProg sharedOpts)+ useDynToo = dynamicTooSupported &&+ (forceVanillaLib || withVanillaLib lbi) &&+ (forceSharedLib || withSharedLib lbi) &&+ null (hcSharedOptions GHC libBi)+ if not has_code+ then vanilla+ else+ if useDynToo+ then do+ runGhcjsProg vanillaSharedOpts+ case (hpcdir Hpc.Dyn, hpcdir Hpc.Vanilla) of+ (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+ -- static and dynamically linked executables. We copy+ -- the modules interfaces so they are available under+ -- both ways.+ copyDirectoryRecursive verbosity dynDir vanillaDir+ _ -> return ()+ else if isGhcjsDynamic+ then do shared; vanilla+ else do vanilla; shared+ whenProfLib (runGhcjsProg profOpts)++ -- Build any C++ sources separately.+ {-+ unless (not has_code || null (cxxSources libBi) || not nativeToo) $ do+ info verbosity "Building C++ Sources..."+ sequence_+ [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo+ lbi libBi clbi libTargetDir filename+ vanillaCxxOpts = if isGhcjsDynamic+ then baseCxxOpts { ghcOptFPic = toFlag True }+ else baseCxxOpts+ profCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptObjSuffix = toFlag "p_o"+ }+ sharedCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptObjSuffix = toFlag "dyn_o"+ }+ odir = fromFlag (ghcOptObjDir vanillaCxxOpts)+ createDirectoryIfMissingVerbose verbosity True odir+ let runGhcProgIfNeeded cxxOpts = do+ needsRecomp <- checkNeedsRecompilation filename cxxOpts+ when needsRecomp $ runGhcjsProg cxxOpts+ runGhcProgIfNeeded vanillaCxxOpts+ unless forRepl $+ whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCxxOpts)+ unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts)+ | filename <- cxxSources libBi]++ ifReplLib $ do+ when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"+ ifReplLib (runGhcjsProg replOpts)+-}+ -- build any C sources+ -- TODO: Add support for S and CMM files.+ {-+ unless (not has_code || null (cSources libBi) || not nativeToo) $ do+ info verbosity "Building C Sources..."+ sequence_+ [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo+ lbi libBi clbi libTargetDir filename+ vanillaCcOpts = if isGhcjsDynamic+ -- Dynamic GHC requires C sources to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseCcOpts { ghcOptFPic = toFlag True }+ else baseCcOpts+ profCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptObjSuffix = toFlag "p_o"+ }+ sharedCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptObjSuffix = toFlag "dyn_o"+ }+ odir = fromFlag (ghcOptObjDir vanillaCcOpts)+ createDirectoryIfMissingVerbose verbosity True odir+ let runGhcProgIfNeeded ccOpts = do+ needsRecomp <- checkNeedsRecompilation filename ccOpts+ when needsRecomp $ runGhcjsProg ccOpts+ runGhcProgIfNeeded vanillaCcOpts+ unless forRepl $+ whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCcOpts)+ unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts)+ | filename <- cSources libBi]+-}+ -- TODO: problem here is we need the .c files built first, so we can load them+ -- with ghci, but .c files can depend on .h files generated by ghc by ffi+ -- exports.++ -- link:++ when has_code . when False {- fixme nativeToo -} . unless forRepl $ do+ info verbosity "Linking..."+ let cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))+ (cSources libBi ++ cxxSources libBi)+ compiler_id = compilerId (compiler lbi)+ sharedLibFilePath = libTargetDir </> mkSharedLibName (hostPlatform lbi) compiler_id uid+ staticLibFilePath = libTargetDir </> mkStaticLibName (hostPlatform lbi) compiler_id uid++ let stubObjs = []+ stubSharedObjs = []++{-+ stubObjs <- catMaybes <$> sequenceA+ [ findFileWithExtension [objExtension] [libTargetDir]+ (ModuleName.toFilePath x ++"_stub")+ | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files+ , x <- allLibModules lib clbi ]+ stubProfObjs <- catMaybes <$> sequenceA+ [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]+ (ModuleName.toFilePath x ++"_stub")+ | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files+ , x <- allLibModules lib clbi ]+ stubSharedObjs <- catMaybes <$> sequenceA+ [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]+ (ModuleName.toFilePath x ++"_stub")+ | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files+ , x <- allLibModules lib clbi ]+-}+ hObjs <- Internal.getHaskellObjects implInfo lib lbi clbi+ libTargetDir objExtension True+ hSharedObjs <-+ if withSharedLib lbi+ then Internal.getHaskellObjects implInfo lib lbi clbi+ libTargetDir ("dyn_" ++ objExtension) False+ else return []++ unless (null hObjs && null cObjs && null stubObjs) $ do+ rpaths <- getRPaths lbi clbi++ let staticObjectFiles =+ hObjs+ ++ map (libTargetDir </>) cObjs+ ++ stubObjs+ dynamicObjectFiles =+ hSharedObjs+ ++ map (libTargetDir </>) cSharedObjs+ ++ stubSharedObjs+ -- After the relocation lib is created we invoke ghc -shared+ -- with the dependencies spelled out as -package arguments+ -- and ghc invokes the linker with the proper library paths+ ghcSharedLinkArgs =+ mempty {+ ghcOptShared = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptInputFiles = toNubListR dynamicObjectFiles,+ ghcOptOutputFile = toFlag sharedLibFilePath,+ ghcOptExtra = 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 < mkVersion [7,8]+ then toFlag sharedLibInstallPath+ else mempty, -}+ ghcOptHideAllPackages = toFlag True,+ ghcOptNoAutoLinkPackages = toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptThisUnitId = case clbi of+ LibComponentLocalBuildInfo { componentCompatPackageKey = pk }+ -> toFlag pk+ _ -> mempty,+ ghcOptThisComponentId = case clbi of+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->+ if null insts+ then mempty+ else toFlag (componentComponentId clbi)+ _ -> mempty,+ ghcOptInstantiatedWith = case clbi of+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts }+ -> insts+ _ -> [],+ ghcOptPackages = toNubListR $+ Internal.mkGhcOptPackages clbi ,+ ghcOptLinkLibs = extraLibs libBi,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi,+ ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,+ ghcOptLinkFrameworkDirs =+ toNubListR $ PD.extraFrameworkDirs libBi,+ ghcOptRPaths = rpaths+ }+ ghcStaticLinkArgs =+ mempty {+ ghcOptStaticLib = toFlag True,+ ghcOptInputFiles = toNubListR staticObjectFiles,+ ghcOptOutputFile = toFlag staticLibFilePath,+ ghcOptExtra = hcStaticOptions GHC libBi,+ ghcOptHideAllPackages = toFlag True,+ ghcOptNoAutoLinkPackages = toFlag True,+ ghcOptPackageDBs = withPackageDB lbi,+ ghcOptThisUnitId = case clbi of+ LibComponentLocalBuildInfo { componentCompatPackageKey = pk }+ -> toFlag pk+ _ -> mempty,+ ghcOptThisComponentId = case clbi of+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->+ if null insts+ then mempty+ else toFlag (componentComponentId clbi)+ _ -> mempty,+ ghcOptInstantiatedWith = case clbi of+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts }+ -> insts+ _ -> [],+ ghcOptPackages = toNubListR $+ Internal.mkGhcOptPackages clbi ,+ ghcOptLinkLibs = extraLibs libBi,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs libBi+ }++ info verbosity (show (ghcOptPackages ghcSharedLinkArgs))+{-+ whenVanillaLib False $ do+ Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles+ whenGHCiLib $ do+ (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)+ Ld.combineObjectFiles verbosity lbi ldProg+ ghciLibFilePath staticObjectFiles+ -}+{-+ whenProfLib $ do+ Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles+ whenGHCiLib $ do+ (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)+ Ld.combineObjectFiles verbosity lbi ldProg+ ghciProfLibFilePath profObjectFiles+-}+ whenSharedLib False $+ runGhcjsProg ghcSharedLinkArgs++ whenStaticLib False $+ runGhcjsProg ghcStaticLinkArgs++-- | Start a REPL without loading any source files.+startInterpreter :: Verbosity -> ProgramDb -> Compiler -> Platform+ -> PackageDBStack -> IO ()+startInterpreter verbosity progdb comp platform packageDBs = do+ let replOpts = mempty {+ ghcOptMode = toFlag GhcModeInteractive,+ ghcOptPackageDBs = packageDBs+ }+ checkPackageDbStack verbosity packageDBs+ (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram progdb+ runGHC verbosity ghcjsProg comp platform replOpts++-- -----------------------------------------------------------------------------+-- Building an executable or foreign library++-- | Build a foreign library+buildFLib+ :: Verbosity -> Cabal.Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> ForeignLib -> ComponentLocalBuildInfo -> IO ()+buildFLib v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildFLib++replFLib+ :: [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> ForeignLib+ -> ComponentLocalBuildInfo -> IO ()+replFLib replFlags v njobs pkg lbi =+ gbuild v njobs pkg lbi . GReplFLib replFlags++-- | Build an executable with GHC.+--+buildExe+ :: Verbosity -> Cabal.Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> Executable -> ComponentLocalBuildInfo -> IO ()+buildExe v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildExe++replExe+ :: [String] -> Verbosity+ -> Cabal.Flag (Maybe Int) -> PackageDescription+ -> LocalBuildInfo -> Executable+ -> ComponentLocalBuildInfo -> IO ()+replExe replFlags v njobs pkg lbi =+ gbuild v njobs pkg lbi . GReplExe replFlags++-- | Building an executable, starting the REPL, and building foreign+-- libraries are all very similar and implemented in 'gbuild'. The+-- 'GBuildMode' distinguishes between the various kinds of operation.+data GBuildMode =+ GBuildExe Executable+ | GReplExe [String] Executable+ | GBuildFLib ForeignLib+ | GReplFLib [String] ForeignLib++gbuildInfo :: GBuildMode -> BuildInfo+gbuildInfo (GBuildExe exe) = buildInfo exe+gbuildInfo (GReplExe _ exe) = buildInfo exe+gbuildInfo (GBuildFLib flib) = foreignLibBuildInfo flib+gbuildInfo (GReplFLib _ flib) = foreignLibBuildInfo flib++gbuildName :: GBuildMode -> String+gbuildName (GBuildExe exe) = unUnqualComponentName $ exeName exe+gbuildName (GReplExe _ exe) = unUnqualComponentName $ exeName exe+gbuildName (GBuildFLib flib) = unUnqualComponentName $ foreignLibName flib+gbuildName (GReplFLib _ flib) = unUnqualComponentName $ foreignLibName flib++gbuildTargetName :: LocalBuildInfo -> GBuildMode -> String+gbuildTargetName lbi (GBuildExe exe) = exeTargetName (hostPlatform lbi) exe+gbuildTargetName lbi (GReplExe _ exe) = exeTargetName (hostPlatform lbi) exe+gbuildTargetName lbi (GBuildFLib flib) = flibTargetName lbi flib+gbuildTargetName lbi (GReplFLib _ flib) = flibTargetName lbi flib++exeTargetName :: Platform -> Executable -> String+exeTargetName platform exe = unUnqualComponentName (exeName exe) `withExt` exeExtension platform++-- | Target name for a foreign library (the actual file name)+--+-- We do not use mkLibName and co here because the naming for foreign libraries+-- is slightly different (we don't use "_p" or compiler version suffices, and we+-- don't want the "lib" prefix on Windows).+--+-- TODO: We do use `dllExtension` and co here, but really that's wrong: they+-- use the OS used to build cabal to determine which extension to use, rather+-- than the target OS (but this is wrong elsewhere in Cabal as well).+flibTargetName :: LocalBuildInfo -> ForeignLib -> String+flibTargetName lbi flib =+ case (os, foreignLibType flib) of+ (Windows, ForeignLibNativeShared) -> nm <.> "dll"+ (Windows, ForeignLibNativeStatic) -> nm <.> "lib"+ (Linux, ForeignLibNativeShared) -> "lib" ++ nm <.> versionedExt+ (_other, ForeignLibNativeShared) -> "lib" ++ nm <.> dllExtension (hostPlatform lbi)+ (_other, ForeignLibNativeStatic) -> "lib" ++ nm <.> staticLibExtension (hostPlatform lbi)+ (_any, ForeignLibTypeUnknown) -> cabalBug "unknown foreign lib type"+ where+ nm :: String+ nm = unUnqualComponentName $ foreignLibName flib++ os :: OS+ os = let (Platform _ os') = hostPlatform lbi+ in os'++ -- If a foreign lib foo has lib-version-info 5:1:2 or+ -- lib-version-linux 3.2.1, it should be built as libfoo.so.3.2.1+ -- Libtool's version-info data is translated into library versions in a+ -- nontrivial way: so refer to libtool documentation.+ versionedExt :: String+ versionedExt =+ let nums = foreignLibVersion flib os+ in foldl (<.>) "so" (map show nums)++-- | Name for the library when building.+--+-- If the `lib-version-info` field or the `lib-version-linux` field of+-- a foreign library target is set, we need to incorporate that+-- version into the SONAME field.+--+-- If a foreign library foo has lib-version-info 5:1:2, it should be+-- built as libfoo.so.3.2.1. We want it to get soname libfoo.so.3.+-- However, GHC does not allow overriding soname by setting linker+-- options, as it sets a soname of its own (namely the output+-- filename), after the user-supplied linker options. Hence, we have+-- to compile the library with the soname as its filename. We rename+-- the compiled binary afterwards.+--+-- This method allows to adjust the name of the library at build time+-- such that the correct soname can be set.+flibBuildName :: LocalBuildInfo -> ForeignLib -> String+flibBuildName lbi flib+ -- On linux, if a foreign-library has version data, the first digit is used+ -- to produce the SONAME.+ | (os, foreignLibType flib) ==+ (Linux, ForeignLibNativeShared)+ = let nums = foreignLibVersion flib os+ in "lib" ++ nm <.> foldl (<.>) "so" (map show (take 1 nums))+ | otherwise = flibTargetName lbi flib+ where+ os :: OS+ os = let (Platform _ os') = hostPlatform lbi+ in os'++ nm :: String+ nm = unUnqualComponentName $ foreignLibName flib++gbuildIsRepl :: GBuildMode -> Bool+gbuildIsRepl (GBuildExe _) = False+gbuildIsRepl (GReplExe _ _) = True+gbuildIsRepl (GBuildFLib _) = False+gbuildIsRepl (GReplFLib _ _) = True++gbuildNeedDynamic :: LocalBuildInfo -> GBuildMode -> Bool+gbuildNeedDynamic lbi bm =+ case bm of+ GBuildExe _ -> withDynExe lbi+ GReplExe _ _ -> withDynExe lbi+ GBuildFLib flib -> withDynFLib flib+ GReplFLib _ flib -> withDynFLib flib+ where+ withDynFLib flib =+ case foreignLibType flib of+ ForeignLibNativeShared ->+ ForeignLibStandalone `notElem` foreignLibOptions flib+ ForeignLibNativeStatic ->+ False+ ForeignLibTypeUnknown ->+ cabalBug "unknown foreign lib type"++gbuildModDefFiles :: GBuildMode -> [FilePath]+gbuildModDefFiles (GBuildExe _) = []+gbuildModDefFiles (GReplExe _ _) = []+gbuildModDefFiles (GBuildFLib flib) = foreignLibModDefFile flib+gbuildModDefFiles (GReplFLib _ flib) = foreignLibModDefFile flib++-- | "Main" module name when overridden by @ghc-options: -main-is ...@+-- or 'Nothing' if no @-main-is@ flag could be found.+--+-- In case of 'Nothing', 'Distribution.ModuleName.main' can be assumed.+exeMainModuleName :: Executable -> Maybe ModuleName+exeMainModuleName Executable{buildInfo = bnfo} =+ -- GHC honors the last occurrence of a module name updated via -main-is+ --+ -- Moreover, -main-is when parsed left-to-right can update either+ -- the "Main" module name, or the "main" function name, or both,+ -- see also 'decodeMainIsArg'.+ msum $ reverse $ map decodeMainIsArg $ findIsMainArgs ghcopts+ where+ ghcopts = hcOptions GHC bnfo++ findIsMainArgs [] = []+ findIsMainArgs ("-main-is":arg:rest) = arg : findIsMainArgs rest+ findIsMainArgs (_:rest) = findIsMainArgs rest++-- | Decode argument to '-main-is'+--+-- Returns 'Nothing' if argument set only the function name.+--+-- This code has been stolen/refactored from GHC's DynFlags.setMainIs+-- function. The logic here is deliberately imperfect as it is+-- intended to be bug-compatible with GHC's parser. See discussion in+-- https://github.com/haskell/cabal/pull/4539#discussion_r118981753.+decodeMainIsArg :: String -> Maybe ModuleName+decodeMainIsArg arg+ | headOf main_fn isLower+ -- The arg looked like "Foo.Bar.baz"+ = Just (ModuleName.fromString main_mod)+ | headOf arg isUpper -- The arg looked like "Foo" or "Foo.Bar"+ = Just (ModuleName.fromString arg)+ | otherwise -- The arg looked like "baz"+ = Nothing+ where+ headOf :: String -> (Char -> Bool) -> Bool+ headOf str pred' = any pred' (safeHead str)++ (main_mod, main_fn) = splitLongestPrefix arg (== '.')++ splitLongestPrefix :: String -> (Char -> Bool) -> (String,String)+ splitLongestPrefix str pred'+ | null r_pre = (str, [])+ | otherwise = (reverse (safeTail r_pre), reverse r_suf)+ -- 'safeTail' drops the char satisfying 'pred'+ where (r_suf, r_pre) = break pred' (reverse str)+++-- | A collection of:+-- * C input files+-- * C++ input files+-- * GHC input files+-- * GHC input modules+--+-- Used to correctly build and link sources.+data BuildSources = BuildSources {+ cSourcesFiles :: [FilePath],+ cxxSourceFiles :: [FilePath],+ inputSourceFiles :: [FilePath],+ inputSourceModules :: [ModuleName]+ }++-- | Locate and return the 'BuildSources' required to build and link.+gbuildSources :: Verbosity+ -> CabalSpecVersion+ -> FilePath+ -> GBuildMode+ -> IO BuildSources+gbuildSources verbosity specVer tmpDir bm =+ case bm of+ GBuildExe exe -> exeSources exe+ GReplExe _ exe -> exeSources exe+ GBuildFLib flib -> return $ flibSources flib+ GReplFLib _ flib -> return $ flibSources flib+ where+ exeSources :: Executable -> IO BuildSources+ exeSources exe@Executable{buildInfo = bnfo, modulePath = modPath} = do+ main <- findFileEx verbosity (tmpDir : map getSymbolicPath (hsSourceDirs bnfo)) modPath+ let mainModName = fromMaybe ModuleName.main $ exeMainModuleName exe+ otherModNames = exeModules exe++ if isHaskell main+ then+ if specVer < CabalSpecV2_0 && (mainModName `elem` otherModNames)+ then do+ -- The cabal manual clearly states that `other-modules` is+ -- intended for non-main modules. However, there's at least one+ -- important package on Hackage (happy-1.19.5) which+ -- violates this. We workaround this here so that we don't+ -- invoke GHC with e.g. 'ghc --make Main src/Main.hs' which+ -- would result in GHC complaining about duplicate Main+ -- modules.+ --+ -- Finally, we only enable this workaround for+ -- specVersion < 2, as 'cabal-version:>=2.0' cabal files+ -- have no excuse anymore to keep doing it wrong... ;-)+ warn verbosity $ "Enabling workaround for Main module '"+ ++ prettyShow mainModName+ ++ "' listed in 'other-modules' illegally!"++ return BuildSources {+ cSourcesFiles = cSources bnfo,+ cxxSourceFiles = cxxSources bnfo,+ inputSourceFiles = [main],+ inputSourceModules = filter (/= mainModName) $ exeModules exe+ }++ else return BuildSources {+ cSourcesFiles = cSources bnfo,+ cxxSourceFiles = cxxSources bnfo,+ inputSourceFiles = [main],+ inputSourceModules = exeModules exe+ }+ else let (csf, cxxsf)+ | isCxx main = ( cSources bnfo, main : cxxSources bnfo)+ -- if main is not a Haskell source+ -- and main is not a C++ source+ -- then we assume that it is a C source+ | otherwise = (main : cSources bnfo, cxxSources bnfo)++ in return BuildSources {+ cSourcesFiles = csf,+ cxxSourceFiles = cxxsf,+ inputSourceFiles = [],+ inputSourceModules = exeModules exe+ }++ flibSources :: ForeignLib -> BuildSources+ flibSources flib@ForeignLib{foreignLibBuildInfo = bnfo} =+ BuildSources {+ cSourcesFiles = cSources bnfo,+ cxxSourceFiles = cxxSources bnfo,+ inputSourceFiles = [],+ inputSourceModules = foreignLibModules flib+ }++ isHaskell :: FilePath -> Bool+ isHaskell fp = elem (takeExtension fp) [".hs", ".lhs"]++ isCxx :: FilePath -> Bool+ isCxx fp = elem (takeExtension fp) [".cpp", ".cxx", ".c++"]++-- | Generic build function. See comment for 'GBuildMode'.+gbuild :: Verbosity -> Cabal.Flag (Maybe Int)+ -> PackageDescription -> LocalBuildInfo+ -> GBuildMode -> ComponentLocalBuildInfo -> IO ()+gbuild verbosity numJobs pkg_descr lbi bm clbi = do+ (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)+ let replFlags = case bm of+ GReplExe flags _ -> flags+ GReplFLib flags _ -> flags+ GBuildExe{} -> mempty+ GBuildFLib{} -> mempty+ comp = compiler lbi+ platform = hostPlatform lbi+ implInfo = getImplInfo comp+ runGhcProg = runGHC verbosity ghcjsProg comp platform++ let (bnfo, threaded) = case bm of+ GBuildFLib _ -> popThreadedFlag (gbuildInfo bm)+ _ -> (gbuildInfo bm, False)++ -- the name that GHC really uses (e.g., with .exe on Windows for executables)+ let targetName = gbuildTargetName lbi bm+ let targetDir = buildDir lbi </> (gbuildName bm)+ let tmpDir = targetDir </> (gbuildName bm ++ "-tmp")+ createDirectoryIfMissingVerbose verbosity True targetDir+ createDirectoryIfMissingVerbose verbosity True tmpDir++ -- TODO: do we need to put hs-boot files into place for mutually recursive+ -- modules? FIX: what about exeName.hi-boot?++ -- Determine if program coverage should be enabled and if so, what+ -- '-hpcdir' should be.+ let isCoverageEnabled = exeCoverage lbi+ distPref = fromFlag $ configDistPref $ configFlags lbi+ hpcdir way+ | gbuildIsRepl bm = mempty -- HPC is not supported in ghci+ | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way (gbuildName bm)+ | otherwise = mempty++ rpaths <- getRPaths lbi clbi+ buildSources <- gbuildSources verbosity (specVersion pkg_descr) tmpDir bm++ let cSrcs = cSourcesFiles buildSources+ cxxSrcs = cxxSourceFiles buildSources+ inputFiles = inputSourceFiles buildSources+ inputModules = inputSourceModules buildSources+ isGhcDynamic = isDynamic comp+ dynamicTooSupported = supportsDynamicToo comp+ cObjs = map (`replaceExtension` objExtension) cSrcs+ cxxObjs = map (`replaceExtension` objExtension) cxxSrcs+ needDynamic = gbuildNeedDynamic lbi bm+ needProfiling = withProfExe lbi++ -- build executables+ baseOpts = (componentGhcOptions verbosity lbi bnfo clbi tmpDir)+ `mappend` mempty {+ ghcOptMode = toFlag GhcModeMake,+ ghcOptInputFiles = toNubListR inputFiles,+ ghcOptInputModules = toNubListR inputModules+ }+ staticOpts = baseOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcStaticOnly,+ ghcOptHPCDir = hpcdir Hpc.Vanilla+ }+ profOpts = baseOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag False+ (withProfExeDetail lbi),+ ghcOptHiSuffix = toFlag "p_hi",+ ghcOptObjSuffix = toFlag "p_o",+ ghcOptExtra = hcProfOptions GHC bnfo,+ ghcOptHPCDir = hpcdir Hpc.Prof+ }+ dynOpts = baseOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ -- TODO: Does it hurt to set -fPIC for executables?+ ghcOptFPic = toFlag True,+ ghcOptHiSuffix = toFlag "dyn_hi",+ ghcOptObjSuffix = toFlag "dyn_o",+ ghcOptExtra = hcSharedOptions GHC bnfo,+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }+ dynTooOpts = staticOpts `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcStaticAndDynamic,+ ghcOptDynHiSuffix = toFlag "dyn_hi",+ ghcOptDynObjSuffix = toFlag "dyn_o",+ ghcOptHPCDir = hpcdir Hpc.Dyn+ }+ linkerOpts = mempty {+ ghcOptLinkOptions = PD.ldOptions bnfo,+ ghcOptLinkLibs = extraLibs bnfo,+ ghcOptLinkLibPath = toNubListR $ extraLibDirs bnfo,+ ghcOptLinkFrameworks = toNubListR $+ PD.frameworks bnfo,+ ghcOptLinkFrameworkDirs = toNubListR $+ PD.extraFrameworkDirs bnfo,+ ghcOptInputFiles = toNubListR+ [tmpDir </> x | x <- cObjs ++ cxxObjs]+ }+ dynLinkerOpts = mempty {+ ghcOptRPaths = rpaths+ }+ replOpts = baseOpts {+ ghcOptExtra = Internal.filterGhciFlags+ (ghcOptExtra baseOpts)+ <> replFlags+ }+ -- For a normal compile we do separate invocations of ghc for+ -- compiling as for linking. But for repl we have to do just+ -- the one invocation, so that one has to include all the+ -- linker stuff too, like -l flags and any .o files from C+ -- files etc.+ `mappend` linkerOpts+ `mappend` mempty {+ ghcOptMode = toFlag GhcModeInteractive,+ ghcOptOptimisation = toFlag GhcNoOptimisation+ }+ commonOpts | needProfiling = profOpts+ | needDynamic = dynOpts+ | otherwise = staticOpts+ compileOpts | useDynToo = dynTooOpts+ | otherwise = commonOpts+ withStaticExe = not needProfiling && not needDynamic++ -- For building exe's that use TH with -prof or -dynamic we actually have+ -- to build twice, once without -prof/-dynamic and then again with+ -- -prof/-dynamic. This is because the code that TH needs to run at+ -- compile time needs to be the vanilla ABI so it can be loaded up and run+ -- by the compiler.+ -- With dynamic-by-default GHC the TH object files loaded at compile-time+ -- need to be .dyn_o instead of .o.+ doingTH = usesTemplateHaskellOrQQ bnfo+ -- Should we use -dynamic-too instead of compiling twice?+ useDynToo = dynamicTooSupported && isGhcDynamic+ && doingTH && withStaticExe+ && null (hcSharedOptions GHC bnfo)+ compileTHOpts | isGhcDynamic = dynOpts+ | otherwise = staticOpts+ compileForTH+ | gbuildIsRepl bm = False+ | useDynToo = False+ | isGhcDynamic = doingTH && (needProfiling || withStaticExe)+ | otherwise = doingTH && (needProfiling || needDynamic)++ -- Build static/dynamic object files for TH, if needed.+ when compileForTH $+ runGhcProg compileTHOpts { ghcOptNoLink = toFlag True+ , ghcOptNumJobs = numJobs }++ -- Do not try to build anything if there are no input files.+ -- This can happen if the cabal file ends up with only cSrcs+ -- but no Haskell modules.+ unless ((null inputFiles && null inputModules)+ || gbuildIsRepl bm) $+ runGhcProg compileOpts { ghcOptNoLink = toFlag True+ , ghcOptNumJobs = numJobs }++ -- build any C++ sources+ unless (null cxxSrcs) $ do+ info verbosity "Building C++ Sources..."+ sequence_+ [ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo+ lbi bnfo clbi tmpDir filename+ vanillaCxxOpts = if isGhcDynamic+ -- Dynamic GHC requires C++ sources to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseCxxOpts { ghcOptFPic = toFlag True }+ else baseCxxOpts+ profCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True+ }+ sharedCxxOpts = vanillaCxxOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly+ }+ opts | needProfiling = profCxxOpts+ | needDynamic = sharedCxxOpts+ | otherwise = vanillaCxxOpts+ -- TODO: Placing all Haskell, C, & C++ objects in a single directory+ -- Has the potential for file collisions. In general we would+ -- consider this a user error. However, we should strive to+ -- add a warning if this occurs.+ odir = fromFlag (ghcOptObjDir opts)+ createDirectoryIfMissingVerbose verbosity True odir+ needsRecomp <- checkNeedsRecompilation filename opts+ when needsRecomp $+ runGhcProg opts+ | filename <- cxxSrcs ]++ -- build any C sources+ unless (null cSrcs) $ do+ info verbosity "Building C Sources..."+ sequence_+ [ do let baseCcOpts = Internal.componentCcGhcOptions verbosity implInfo+ lbi bnfo clbi tmpDir filename+ vanillaCcOpts = if isGhcDynamic+ -- Dynamic GHC requires C sources to be built+ -- with -fPIC for REPL to work. See #2207.+ then baseCcOpts { ghcOptFPic = toFlag True }+ else baseCcOpts+ profCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptProfilingMode = toFlag True+ }+ sharedCcOpts = vanillaCcOpts `mappend` mempty {+ ghcOptFPic = toFlag True,+ ghcOptDynLinkMode = toFlag GhcDynamicOnly+ }+ opts | needProfiling = profCcOpts+ | needDynamic = sharedCcOpts+ | otherwise = vanillaCcOpts+ odir = fromFlag (ghcOptObjDir opts)+ createDirectoryIfMissingVerbose verbosity True odir+ needsRecomp <- checkNeedsRecompilation filename opts+ when needsRecomp $+ runGhcProg opts+ | filename <- cSrcs ]++ -- TODO: problem here is we need the .c files built first, so we can load them+ -- with ghci, but .c files can depend on .h files generated by ghc by ffi+ -- exports.+ case bm of+ GReplExe _ _ -> runGhcProg replOpts+ GReplFLib _ _ -> runGhcProg replOpts+ GBuildExe _ -> do+ let linkOpts = commonOpts+ `mappend` linkerOpts+ `mappend` mempty {+ ghcOptLinkNoHsMain = toFlag (null inputFiles)+ }+ `mappend` (if withDynExe lbi then dynLinkerOpts else mempty)++ info verbosity "Linking..."+ -- Work around old GHCs not relinking in this+ -- situation, see #3294+ let target = targetDir </> targetName+ when (compilerVersion comp < mkVersion [7,7]) $ do+ e <- doesFileExist target+ when e (removeFile target)+ runGhcProg linkOpts { ghcOptOutputFile = toFlag target }+ GBuildFLib flib -> do+ let rtsInfo = extractRtsInfo lbi+ rtsOptLinkLibs = [+ if needDynamic+ then if threaded+ then dynRtsThreadedLib (rtsDynamicInfo rtsInfo)+ else dynRtsVanillaLib (rtsDynamicInfo rtsInfo)+ else if threaded+ then statRtsThreadedLib (rtsStaticInfo rtsInfo)+ else statRtsVanillaLib (rtsStaticInfo rtsInfo)+ ]+ linkOpts = case foreignLibType flib of+ ForeignLibNativeShared ->+ commonOpts+ `mappend` linkerOpts+ `mappend` dynLinkerOpts+ `mappend` mempty {+ ghcOptLinkNoHsMain = toFlag True,+ ghcOptShared = toFlag True,+ ghcOptLinkLibs = rtsOptLinkLibs,+ ghcOptLinkLibPath = toNubListR $ rtsLibPaths rtsInfo,+ ghcOptFPic = toFlag True,+ ghcOptLinkModDefFiles = toNubListR $ gbuildModDefFiles bm+ }+ -- See Note [RPATH]+ `mappend` ifNeedsRPathWorkaround lbi mempty {+ ghcOptLinkOptions = ["-Wl,--no-as-needed"]+ , ghcOptLinkLibs = ["ffi"]+ }+ ForeignLibNativeStatic ->+ -- this should be caught by buildFLib+ -- (and if we do implement this, we probably don't even want to call+ -- ghc here, but rather Ar.createArLibArchive or something)+ cabalBug "static libraries not yet implemented"+ ForeignLibTypeUnknown ->+ cabalBug "unknown foreign lib type"+ -- We build under a (potentially) different filename to set a+ -- soname on supported platforms. See also the note for+ -- @flibBuildName@.+ info verbosity "Linking..."+ let buildName = flibBuildName lbi flib+ runGhcProg linkOpts { ghcOptOutputFile = toFlag (targetDir </> buildName) }+ renameFile (targetDir </> buildName) (targetDir </> targetName)++{-+Note [RPATH]+~~~~~~~~~~~~++Suppose that the dynamic library depends on `base`, but not (directly) on+`integer-gmp` (which, however, is a dependency of `base`). We will link the+library as++ gcc ... -lHSbase-4.7.0.2-ghc7.8.4 -lHSinteger-gmp-0.5.1.0-ghc7.8.4 ...++However, on systems (like Ubuntu) where the linker gets called with `-as-needed`+by default, the linker will notice that `integer-gmp` isn't actually a direct+dependency and hence omit the link.++Then when we attempt to link a C program against this dynamic library, the+_static_ linker will attempt to verify that all symbols can be resolved. The+dynamic library itself does not require any symbols from `integer-gmp`, but+`base` does. In order to verify that the symbols used by `base` can be+resolved, the static linker needs to be able to _find_ integer-gmp.++Finding the `base` dependency is simple, because the dynamic elf header+(`readelf -d`) for the library that we have created looks something like++ (NEEDED) Shared library: [libHSbase-4.7.0.2-ghc7.8.4.so]+ (RPATH) Library rpath: [/path/to/base-4.7.0.2:...]++However, when it comes to resolving the dependency on `integer-gmp`, it needs+to look at the dynamic header for `base`. On modern ghc (7.8 and higher) this+looks something like++ (NEEDED) Shared library: [libHSinteger-gmp-0.5.1.0-ghc7.8.4.so]+ (RPATH) Library rpath: [$ORIGIN/../integer-gmp-0.5.1.0:...]++This specifies the location of `integer-gmp` _in terms of_ the location of base+(using the `$ORIGIN`) variable. But here's the crux: when the static linker+attempts to verify that all symbols can be resolved, [**IT DOES NOT RESOLVE+`$ORIGIN`**](http://stackoverflow.com/questions/6323603/ld-using-rpath-origin-inside-a-shared-library-recursive).+As a consequence, it will not be able to resolve the symbols and report the+missing symbols as errors, _even though the dynamic linker **would** be able to+resolve these symbols_. We can tell the static linker not to report these+errors by using `--unresolved-symbols=ignore-all` and all will be fine when we+run the program ([(indeed, this is what the gold linker+does)](https://sourceware.org/ml/binutils/2013-05/msg00038.html), but it makes+the resulting library more difficult to use.++Instead what we can do is make sure that the generated dynamic library has+explicit top-level dependencies on these libraries. This means that the static+linker knows where to find them, and when we have transitive dependencies on+the same libraries the linker will only load them once, so we avoid needing to+look at the `RPATH` of our dependencies. We can do this by passing+`--no-as-needed` to the linker, so that it doesn't omit any libraries.++Note that on older ghc (7.6 and before) the Haskell libraries don't have an+RPATH set at all, which makes it even more important that we make these+top-level dependencies.++Finally, we have to explicitly link against `libffi` for the same reason. For+newer ghc this _happens_ to be unnecessary on many systems because `libffi` is+a library which is not specific to GHC, and when the static linker verifies+that all symbols can be resolved it will find the `libffi` that is globally+installed (completely independent from ghc). Of course, this may well be the+_wrong_ version of `libffi`, but it's quite possible that symbol resolution+happens to work. This is of course the wrong approach, which is why we link+explicitly against `libffi` so that we will find the _right_ version of+`libffi`.+-}++-- | Do we need the RPATH workaround?+--+-- See Note [RPATH].+ifNeedsRPathWorkaround :: Monoid a => LocalBuildInfo -> a -> a+ifNeedsRPathWorkaround lbi a =+ case hostPlatform lbi of+ Platform _ Linux -> a+ _otherwise -> mempty++data DynamicRtsInfo = DynamicRtsInfo {+ dynRtsVanillaLib :: FilePath+ , dynRtsThreadedLib :: FilePath+ , dynRtsDebugLib :: FilePath+ , dynRtsEventlogLib :: FilePath+ , dynRtsThreadedDebugLib :: FilePath+ , dynRtsThreadedEventlogLib :: FilePath+ }++data StaticRtsInfo = StaticRtsInfo {+ statRtsVanillaLib :: FilePath+ , statRtsThreadedLib :: FilePath+ , statRtsDebugLib :: FilePath+ , statRtsEventlogLib :: FilePath+ , statRtsThreadedDebugLib :: FilePath+ , statRtsThreadedEventlogLib :: FilePath+ , statRtsProfilingLib :: FilePath+ , statRtsThreadedProfilingLib :: FilePath+ }++data RtsInfo = RtsInfo {+ rtsDynamicInfo :: DynamicRtsInfo+ , rtsStaticInfo :: StaticRtsInfo+ , rtsLibPaths :: [FilePath]+ }++-- | Extract (and compute) information about the RTS library+--+-- TODO: This hardcodes the name as @HSrts-ghc<version>@. I don't know if we can+-- find this information somewhere. We can lookup the 'hsLibraries' field of+-- 'InstalledPackageInfo' but it will tell us @["HSrts", "Cffi"]@, which+-- doesn't really help.+extractRtsInfo :: LocalBuildInfo -> RtsInfo+extractRtsInfo lbi =+ case PackageIndex.lookupPackageName (installedPkgs lbi) (mkPackageName "rts") of+ [(_, [rts])] -> aux rts+ _otherwise -> error "No (or multiple) ghc rts package is registered"+ where+ aux :: InstalledPackageInfo -> RtsInfo+ aux rts = RtsInfo {+ rtsDynamicInfo = DynamicRtsInfo {+ dynRtsVanillaLib = withGhcVersion "HSrts"+ , dynRtsThreadedLib = withGhcVersion "HSrts_thr"+ , dynRtsDebugLib = withGhcVersion "HSrts_debug"+ , dynRtsEventlogLib = withGhcVersion "HSrts_l"+ , dynRtsThreadedDebugLib = withGhcVersion "HSrts_thr_debug"+ , dynRtsThreadedEventlogLib = withGhcVersion "HSrts_thr_l"+ }+ , rtsStaticInfo = StaticRtsInfo {+ statRtsVanillaLib = "HSrts"+ , statRtsThreadedLib = "HSrts_thr"+ , statRtsDebugLib = "HSrts_debug"+ , statRtsEventlogLib = "HSrts_l"+ , statRtsThreadedDebugLib = "HSrts_thr_debug"+ , statRtsThreadedEventlogLib = "HSrts_thr_l"+ , statRtsProfilingLib = "HSrts_p"+ , statRtsThreadedProfilingLib = "HSrts_thr_p"+ }+ , rtsLibPaths = InstalledPackageInfo.libraryDirs rts+ }+ withGhcVersion = (++ ("-ghc" ++ prettyShow (compilerVersion (compiler lbi))))++-- | Returns True if the modification date of the given source file is newer than+-- the object file we last compiled for it, or if no object file exists yet.+checkNeedsRecompilation :: FilePath -> GhcOptions -> IO Bool+checkNeedsRecompilation filename opts = filename `moreRecentFile` oname+ where oname = getObjectFileName filename opts++-- | Finds the object file name of the given source file+getObjectFileName :: FilePath -> GhcOptions -> FilePath+getObjectFileName filename opts = oname+ where odir = fromFlag (ghcOptObjDir opts)+ oext = fromFlagOrDefault "o" (ghcOptObjSuffix opts)+ oname = odir </> replaceExtension filename oext++-- | Calculate the RPATHs for the component we are building.+--+-- Calculates relative RPATHs when 'relocatable' is set.+getRPaths :: LocalBuildInfo+ -> ComponentLocalBuildInfo -- ^ Component we are building+ -> IO (NubListR FilePath)+getRPaths lbi clbi | supportRPaths hostOS = do+ libraryPaths <- depLibraryPaths False (relocatable lbi) lbi clbi+ let hostPref = case hostOS of+ OSX -> "@loader_path"+ _ -> "$ORIGIN"+ relPath p = if isRelative p then hostPref </> p else p+ rpaths = toNubListR (map relPath libraryPaths)+ return rpaths+ where+ (Platform _ hostOS) = hostPlatform lbi+ compid = compilerId . compiler $ lbi++ -- The list of RPath-supported operating systems below reflects the+ -- platforms on which Cabal's RPATH handling is tested. It does _NOT_+ -- reflect whether the OS supports RPATH.++ -- E.g. when this comment was written, the *BSD operating systems were+ -- untested with regards to Cabal RPATH handling, and were hence set to+ -- 'False', while those operating systems themselves do support RPATH.+ supportRPaths Linux = True+ supportRPaths Windows = False+ supportRPaths OSX = True+ supportRPaths FreeBSD =+ case compid of+ CompilerId GHC ver | ver >= mkVersion [7,10,2] -> True+ _ -> False+ supportRPaths OpenBSD = False+ supportRPaths NetBSD = False+ supportRPaths DragonFly = False+ supportRPaths Solaris = False+ supportRPaths AIX = False+ supportRPaths HPUX = False+ 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.++getRPaths _ _ = return mempty++-- | Remove the "-threaded" flag when building a foreign library, as it has no+-- effect when used with "-shared". Returns the updated 'BuildInfo', along+-- with whether or not the flag was present, so we can use it to link against+-- the appropriate RTS on our own.+popThreadedFlag :: BuildInfo -> (BuildInfo, Bool)+popThreadedFlag bi =+ ( bi { options = filterHcOptions (/= "-threaded") (options bi) }+ , hasThreaded (options bi))++ where+ filterHcOptions :: (String -> Bool)+ -> PerCompilerFlavor [String]+ -> PerCompilerFlavor [String]+ filterHcOptions p (PerCompilerFlavor ghc ghcjs) =+ PerCompilerFlavor (filter p ghc) ghcjs++ hasThreaded :: PerCompilerFlavor [String] -> Bool+ hasThreaded (PerCompilerFlavor ghc _) = elem "-threaded" ghc++-- | Extracts a String representing a hash of the ABI of a built+-- library. It can fail if the library has not yet been built.+--+libAbiHash :: Verbosity -> PackageDescription -> LocalBuildInfo+ -> Library -> ComponentLocalBuildInfo -> IO String+libAbiHash verbosity _pkg_descr lbi lib clbi = do+ let+ libBi = libBuildInfo lib+ comp = compiler lbi+ platform = hostPlatform lbi+ vanillaArgs0 =+ (componentGhcOptions verbosity lbi libBi clbi (componentBuildDir lbi clbi))+ `mappend` mempty {+ ghcOptMode = toFlag GhcModeAbiHash,+ ghcOptInputModules = toNubListR $ exposedModules lib+ }+ vanillaArgs =+ -- Package DBs unnecessary, and break ghc-cabal. See #3633+ -- BUT, put at least the global database so that 7.4 doesn't+ -- break.+ vanillaArgs0 { ghcOptPackageDBs = [GlobalPackageDB]+ , ghcOptPackages = mempty }+ sharedArgs = vanillaArgs `mappend` mempty {+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptFPic = toFlag True,+ ghcOptHiSuffix = toFlag "js_dyn_hi",+ ghcOptObjSuffix = toFlag "js_dyn_o",+ ghcOptExtra = hcSharedOptions GHC libBi+ }+ profArgs = vanillaArgs `mappend` mempty {+ ghcOptProfilingMode = toFlag True,+ ghcOptProfilingAuto = Internal.profDetailLevelFlag True+ (withProfLibDetail lbi),+ ghcOptHiSuffix = toFlag "js_p_hi",+ ghcOptObjSuffix = toFlag "js_p_o",+ ghcOptExtra = hcProfOptions GHC libBi+ }+ ghcArgs+ | withVanillaLib lbi = vanillaArgs+ | withSharedLib lbi = sharedArgs+ | withProfLib lbi = profArgs+ | otherwise = error "libAbiHash: Can't find an enabled library way"++ (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)+ hash <- getProgramInvocationOutput verbosity+ (ghcInvocation ghcjsProg comp platform ghcArgs)+ return (takeWhile (not . isSpace) hash)++componentGhcOptions :: Verbosity -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo -> FilePath+ -> GhcOptions+componentGhcOptions verbosity lbi bi clbi odir =+ let opts = Internal.componentGhcOptions verbosity implInfo lbi bi clbi odir+ comp = compiler lbi+ implInfo = getImplInfo comp+ in opts { ghcOptExtra = ghcOptExtra opts `mappend` hcOptions GHCJS bi+ }+++componentCcGhcOptions :: Verbosity -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> FilePath+ -> GhcOptions+componentCcGhcOptions verbosity lbi =+ Internal.componentCcGhcOptions verbosity implInfo lbi+ where+ comp = compiler lbi+ implInfo = getImplInfo comp+++-- -----------------------------------------------------------------------------+-- Installing++-- |Install executables for GHCJS.+installExe :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^Where to copy the files to+ -> FilePath -- ^Build location+ -> (FilePath, FilePath) -- ^Executable (prefix,suffix)+ -> PackageDescription+ -> Executable+ -> IO ()+installExe verbosity lbi binDir buildPref+ (progprefix, progsuffix) _pkg exe = do+ createDirectoryIfMissingVerbose verbosity True binDir+ let exeName' = unUnqualComponentName $ exeName exe+ exeFileName = exeName'+ fixedExeBaseName = progprefix ++ exeName' ++ progsuffix+ installBinary dest = do+ runDbProgram verbosity ghcjsProgram (withPrograms lbi) $+ [ "--install-executable"+ , buildPref </> exeName' </> exeFileName+ , "-o", dest+ ] +++ case (stripExes lbi, lookupProgram stripProgram $ withPrograms lbi) of+ (True, Just strip) -> ["-strip-program", programPath strip]+ _ -> []+ installBinary (binDir </> fixedExeBaseName)+++-- |Install foreign library for GHC.+installFLib :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^install location+ -> FilePath -- ^Build location+ -> PackageDescription+ -> ForeignLib+ -> IO ()+installFLib verbosity lbi targetDir builtDir _pkg flib =+ install (foreignLibIsShared flib)+ builtDir+ targetDir+ (flibTargetName lbi flib)+ where+ install _isShared srcDir dstDir name = do+ let src = srcDir </> name+ dst = dstDir </> name+ createDirectoryIfMissingVerbose verbosity True targetDir+ installOrdinaryFile verbosity src dst+++-- |Install for ghc, .hi, .a and, if --with-ghci given, .o+installLib :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^install location+ -> FilePath -- ^install location for dynamic libraries+ -> FilePath -- ^Build location+ -> PackageDescription+ -> Library+ -> ComponentLocalBuildInfo+ -> IO ()+installLib verbosity lbi targetDir dynlibTargetDir _builtDir _pkg lib clbi = do+ whenVanilla $ copyModuleFiles "js_hi"+ whenProf $ copyModuleFiles "js_p_hi"+ whenShared $ copyModuleFiles "js_dyn_hi"++ -- whenVanilla $ installOrdinary builtDir targetDir $ toJSLibName vanillaLibName+ -- whenProf $ installOrdinary builtDir targetDir $ toJSLibName profileLibName+ -- whenShared $ installShared builtDir dynlibTargetDir $ toJSLibName sharedLibName+ -- fixme do these make the correct lib names?+ whenHasCode $ do+ whenVanilla $ do+ sequence_ [ installOrdinary builtDir' targetDir (toJSLibName $ mkGenericStaticLibName (l ++ f))+ | l <- getHSLibraryName (componentUnitId clbi):(extraBundledLibs (libBuildInfo lib))+ , f <- "":extraLibFlavours (libBuildInfo lib)+ ]+ -- whenGHCi $ installOrdinary builtDir targetDir (toJSLibName ghciLibName)+ whenProf $ do+ installOrdinary builtDir' targetDir (toJSLibName profileLibName)+ -- whenGHCi $ installOrdinary builtDir targetDir (toJSLibName ghciProfLibName)+ whenShared $+ sequence_ [ installShared builtDir' dynlibTargetDir+ (toJSLibName $ mkGenericSharedLibName platform compiler_id (l ++ f))+ | l <- getHSLibraryName uid : extraBundledLibs (libBuildInfo lib)+ , f <- "":extraDynLibFlavours (libBuildInfo lib)+ ]+ where+ builtDir' = componentBuildDir lbi clbi++ install isShared isJS srcDir dstDir name = do+ let src = srcDir </> name+ dst = dstDir </> name+ createDirectoryIfMissingVerbose verbosity True dstDir++ if isShared+ then installExecutableFile verbosity src dst+ else installOrdinaryFile verbosity src dst++ when (stripLibs lbi && not isJS) $+ Strip.stripLib verbosity+ (hostPlatform lbi) (withPrograms lbi) dst++ installOrdinary = install False True+ installShared = install True True++ copyModuleFiles ext =+ findModuleFilesEx verbosity [builtDir'] [ext] (allLibModules lib clbi)+ >>= installOrdinaryFiles verbosity targetDir++ compiler_id = compilerId (compiler lbi)+ platform = hostPlatform lbi+ uid = componentUnitId clbi+ -- vanillaLibName = mkLibName uid+ profileLibName = mkProfLibName uid+ -- sharedLibName = (mkSharedLibName (hostPlatform lbi) compiler_id) uid++ hasLib = not $ null (allLibModules lib clbi)+ && null (cSources (libBuildInfo lib))+ && null (cxxSources (libBuildInfo lib))+ && null (jsSources (libBuildInfo lib))+ has_code = not (componentIsIndefinite clbi)+ whenHasCode = when has_code+ whenVanilla = when (hasLib && withVanillaLib lbi)+ whenProf = when (hasLib && withProfLib lbi && has_code)+ -- whenGHCi = when (hasLib && withGHCiLib lbi && has_code)+ whenShared = when (hasLib && withSharedLib lbi && has_code)+++adjustExts :: String -> String -> GhcOptions -> GhcOptions+adjustExts hiSuf objSuf opts =+ opts `mappend` mempty {+ ghcOptHiSuffix = toFlag hiSuf,+ ghcOptObjSuffix = toFlag objSuf+ }++isDynamic :: Compiler -> Bool+isDynamic = Internal.ghcLookupProperty "GHC Dynamic"++supportsDynamicToo :: Compiler -> Bool+supportsDynamicToo = Internal.ghcLookupProperty "Support dynamic-too"++withExt :: FilePath -> String -> FilePath+withExt fp ext = fp <.> if takeExtension fp /= ('.':ext) then ext else ""++findGhcjsGhcVersion :: Verbosity -> FilePath -> IO (Maybe Version)+findGhcjsGhcVersion verbosity pgm =+ findProgramVersion "--numeric-ghc-version" id verbosity pgm++findGhcjsPkgGhcjsVersion :: Verbosity -> FilePath -> IO (Maybe Version)+findGhcjsPkgGhcjsVersion verbosity pgm =+ findProgramVersion "--numeric-ghcjs-version" id verbosity pgm++-- -----------------------------------------------------------------------------+-- Registering++hcPkgInfo :: ProgramDb -> HcPkg.HcPkgInfo+hcPkgInfo progdb = HcPkg.HcPkgInfo { HcPkg.hcPkgProgram = ghcjsPkgProg+ , HcPkg.noPkgDbStack = False+ , HcPkg.noVerboseFlag = False+ , HcPkg.flagPackageConf = False+ , HcPkg.supportsDirDbs = True+ , HcPkg.requiresDirDbs = ver >= v7_10+ , HcPkg.nativeMultiInstance = ver >= v7_10+ , HcPkg.recacheMultiInstance = True+ , HcPkg.suppressFilesCheck = True+ }+ where+ v7_10 = mkVersion [7,10]+ ghcjsPkgProg = fromMaybe (error "GHCJS.hcPkgInfo no ghcjs program") $ lookupProgram ghcjsPkgProgram progdb+ ver = fromMaybe (error "GHCJS.hcPkgInfo no ghcjs version") $ programVersion ghcjsPkgProg++registerPackage+ :: Verbosity+ -> ProgramDb+ -> PackageDBStack+ -> InstalledPackageInfo+ -> HcPkg.RegisterOptions+ -> IO ()+registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions =+ HcPkg.register (hcPkgInfo progdb) verbosity packageDbs+ installedPkgInfo registerOptions++pkgRoot :: Verbosity -> LocalBuildInfo -> PackageDB -> IO FilePath+pkgRoot verbosity lbi = pkgRoot'+ where+ pkgRoot' GlobalPackageDB =+ let ghcjsProg = fromMaybe (error "GHCJS.pkgRoot: no ghcjs program") $ lookupProgram ghcjsProgram (withPrograms lbi)+ in fmap takeDirectory (getGlobalPackageDB verbosity ghcjsProg)+ pkgRoot' UserPackageDB = do+ appDir <- getAppUserDataDirectory "ghcjs"+ -- fixme correct this version+ let ver = compilerVersion (compiler lbi)+ subdir = System.Info.arch ++ '-':System.Info.os+ ++ '-':prettyShow 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+ -- directory at the time of 'ghc-pkg register', and registration will+ -- fail.+ createDirectoryIfMissing True rootDir+ return rootDir+ pkgRoot' (SpecificPackageDB fp) = return (takeDirectory fp)+++-- | Get the JavaScript file name and command and arguments to run a+-- program compiled by GHCJS+-- the exe should be the base program name without exe extension+runCmd :: ProgramDb -> FilePath+ -> (FilePath, FilePath, [String])+runCmd progdb exe =+ ( script+ , programPath ghcjsProg+ , programDefaultArgs ghcjsProg ++ programOverrideArgs ghcjsProg ++ ["--run"]+ )+ where+ script = exe <.> "jsexe" </> "all" <.> "js"+ ghcjsProg = fromMaybe (error "GHCJS.runCmd: no ghcjs program") $ lookupProgram ghcjsProgram progdb
+ src/Distribution/Simple/Glob.hs view
@@ -0,0 +1,320 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Glob+-- Copyright : Isaac Jones, Simon Marlow 2003-2004+-- License : BSD3+-- portions Copyright (c) 2007, Galois Inc.+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Simple file globbing.++module Distribution.Simple.Glob (+ GlobSyntaxError(..),+ GlobResult(..),+ matchDirFileGlob,+ matchDirFileGlobWithDie,+ runDirFileGlob,+ fileGlobMatches,+ parseFileGlob,+ explainGlobSyntaxError,+ Glob,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.CabalSpecVersion+import Distribution.Simple.Utils+import Distribution.Verbosity++import System.Directory (getDirectoryContents, doesDirectoryExist, doesFileExist)+import System.FilePath (joinPath, splitExtensions, splitDirectories, takeFileName, (</>), (<.>))++import qualified Data.List.NonEmpty as NE++-- Note throughout that we use splitDirectories, not splitPath. On+-- Posix, this makes no difference, but, because Windows accepts both+-- slash and backslash as its path separators, if we left in the+-- separators from the glob we might not end up properly normalised.++data GlobResult a+ = GlobMatch a+ -- ^ The glob matched the value supplied.+ | GlobWarnMultiDot a+ -- ^ The glob did not match the value supplied because the+ -- cabal-version is too low and the extensions on the file did+ -- not precisely match the glob's extensions, but rather the+ -- glob was a proper suffix of the file's extensions; i.e., if+ -- not for the low cabal-version, it would have matched.+ | GlobMissingDirectory FilePath+ -- ^ The glob couldn't match because the directory named doesn't+ -- exist. The directory will be as it appears in the glob (i.e.,+ -- relative to the directory passed to 'matchDirFileGlob', and,+ -- for 'data-files', relative to 'data-dir').+ deriving (Show, Eq, Ord, Functor)++-- | Extract the matches from a list of 'GlobResult's.+--+-- Note: throws away the 'GlobMissingDirectory' results; chances are+-- that you want to check for these and error out if any are present.+globMatches :: [GlobResult a] -> [a]+globMatches input = [ a | GlobMatch a <- input ]++data GlobSyntaxError+ = StarInDirectory+ | StarInFileName+ | StarInExtension+ | NoExtensionOnStar+ | EmptyGlob+ | LiteralFileNameGlobStar+ | VersionDoesNotSupportGlobStar+ | VersionDoesNotSupportGlob+ deriving (Eq, Show)++explainGlobSyntaxError :: FilePath -> GlobSyntaxError -> String+explainGlobSyntaxError filepath StarInDirectory =+ "invalid file glob '" ++ filepath+ ++ "'. A wildcard '**' is only allowed as the final parent"+ ++ " directory. Stars must not otherwise appear in the parent"+ ++ " directories."+explainGlobSyntaxError filepath StarInExtension =+ "invalid file glob '" ++ filepath+ ++ "'. Wildcards '*' are only allowed as the"+ ++ " file's base name, not in the file extension."+explainGlobSyntaxError filepath StarInFileName =+ "invalid file glob '" ++ filepath+ ++ "'. Wildcards '*' may only totally replace the"+ ++ " file's base name, not only parts of it."+explainGlobSyntaxError filepath NoExtensionOnStar =+ "invalid file glob '" ++ filepath+ ++ "'. If a wildcard '*' is used it must be with an file extension."+explainGlobSyntaxError filepath LiteralFileNameGlobStar =+ "invalid file glob '" ++ filepath+ ++ "'. If a wildcard '**' is used as a parent directory, the"+ ++ " file's base name must be a wildcard '*'."+explainGlobSyntaxError _ EmptyGlob =+ "invalid file glob. A glob cannot be the empty string."+explainGlobSyntaxError filepath VersionDoesNotSupportGlobStar =+ "invalid file glob '" ++ filepath+ ++ "'. Using the double-star syntax requires 'cabal-version: 2.4'"+ ++ " or greater. Alternatively, for compatibility with earlier Cabal"+ ++ " versions, list the included directories explicitly."+explainGlobSyntaxError filepath VersionDoesNotSupportGlob =+ "invalid file glob '" ++ filepath+ ++ "'. Using star wildcards requires 'cabal-version: >= 1.6'. "+ ++ "Alternatively if you require compatibility with earlier Cabal "+ ++ "versions then list all the files explicitly."++data IsRecursive = Recursive | NonRecursive++data MultiDot = MultiDotDisabled | MultiDotEnabled++data Glob+ = GlobStem FilePath Glob+ -- ^ A single subdirectory component + remainder.+ | GlobFinal GlobFinal++data GlobFinal+ = FinalMatch IsRecursive MultiDot String+ -- ^ First argument: Is this a @**/*.ext@ pattern?+ -- Second argument: should we match against the exact extensions, or accept a suffix?+ -- Third argument: the extensions to accept.+ | FinalLit FilePath+ -- ^ Literal file name.++reconstructGlob :: Glob -> FilePath+reconstructGlob (GlobStem dir glob) =+ dir </> reconstructGlob glob+reconstructGlob (GlobFinal final) = case final of+ FinalMatch Recursive _ exts -> "**" </> "*" <.> exts+ FinalMatch NonRecursive _ exts -> "*" <.> exts+ FinalLit path -> path++-- | Returns 'Nothing' if the glob didn't match at all, or 'Just' the+-- result if the glob matched (or would have matched with a higher+-- cabal-version).+fileGlobMatches :: Glob -> FilePath -> Maybe (GlobResult FilePath)+fileGlobMatches pat candidate = do+ match <- fileGlobMatchesSegments pat (splitDirectories candidate)+ return (candidate <$ match)++fileGlobMatchesSegments :: Glob -> [FilePath] -> Maybe (GlobResult ())+fileGlobMatchesSegments _ [] = Nothing+fileGlobMatchesSegments pat (seg : segs) = case pat of+ GlobStem dir pat' -> do+ guard (dir == seg)+ fileGlobMatchesSegments pat' segs+ GlobFinal final -> case final of+ FinalMatch Recursive multidot ext -> do+ let (candidateBase, candidateExts) = splitExtensions (NE.last $ seg:|segs)+ guard (not (null candidateBase))+ checkExt multidot ext candidateExts+ FinalMatch NonRecursive multidot ext -> do+ let (candidateBase, candidateExts) = splitExtensions seg+ guard (null segs && not (null candidateBase))+ checkExt multidot ext candidateExts+ FinalLit filename -> do+ guard (null segs && filename == seg)+ return (GlobMatch ())++checkExt+ :: MultiDot+ -> String -- ^ The pattern's extension+ -> String -- ^ The candidate file's extension+ -> Maybe (GlobResult ())+checkExt multidot ext candidate+ | ext == candidate = Just (GlobMatch ())+ | ext `isSuffixOf` candidate = case multidot of+ MultiDotDisabled -> Just (GlobWarnMultiDot ())+ MultiDotEnabled -> Just (GlobMatch ())+ | otherwise = Nothing++parseFileGlob :: CabalSpecVersion -> FilePath -> Either GlobSyntaxError Glob+parseFileGlob version filepath = case reverse (splitDirectories filepath) of+ [] ->+ Left EmptyGlob+ (filename : "**" : segments)+ | allowGlobStar -> do+ ext <- case splitExtensions filename of+ ("*", ext) | '*' `elem` ext -> Left StarInExtension+ | null ext -> Left NoExtensionOnStar+ | otherwise -> Right ext+ _ -> Left LiteralFileNameGlobStar+ foldM addStem (GlobFinal $ FinalMatch Recursive multidot ext) segments+ | otherwise -> Left VersionDoesNotSupportGlobStar+ (filename : segments) -> do+ pat <- case splitExtensions filename of+ ("*", ext) | not allowGlob -> Left VersionDoesNotSupportGlob+ | '*' `elem` ext -> Left StarInExtension+ | null ext -> Left NoExtensionOnStar+ | otherwise -> Right (FinalMatch NonRecursive multidot ext)+ (_, ext) | '*' `elem` ext -> Left StarInExtension+ | '*' `elem` filename -> Left StarInFileName+ | otherwise -> Right (FinalLit filename)+ foldM addStem (GlobFinal pat) segments+ where+ allowGlob = version >= CabalSpecV1_6+ allowGlobStar = version >= CabalSpecV2_4+ addStem pat seg+ | '*' `elem` seg = Left StarInDirectory+ | otherwise = Right (GlobStem seg pat)+ multidot+ | version >= CabalSpecV2_4 = MultiDotEnabled+ | otherwise = MultiDotDisabled++-- | This will 'die'' when the glob matches no files, or if the glob+-- refers to a missing directory, or if the glob fails to parse.+--+-- The 'Version' argument must be the spec version of the package+-- description being processed, as globs behave slightly differently+-- in different spec versions.+--+-- The first 'FilePath' argument is the directory that the glob is+-- relative to. It must be a valid directory (and hence it can't be+-- the empty string). The returned values will not include this+-- prefix.+--+-- The second 'FilePath' is the glob itself.+--+matchDirFileGlob :: Verbosity -> CabalSpecVersion -> FilePath -> FilePath -> IO [FilePath]+matchDirFileGlob v = matchDirFileGlobWithDie v die'++-- | Like 'matchDirFileGlob' but with customizable 'die'+--+-- @since 3.6.0.0+--+matchDirFileGlobWithDie :: Verbosity -> (Verbosity -> String -> IO [FilePath]) -> CabalSpecVersion -> FilePath -> FilePath -> IO [FilePath]+matchDirFileGlobWithDie verbosity rip version dir filepath = case parseFileGlob version filepath of+ Left err -> rip verbosity $ explainGlobSyntaxError filepath err+ Right glob -> do+ results <- runDirFileGlob verbosity dir glob+ let missingDirectories =+ [ missingDir | GlobMissingDirectory missingDir <- results ]+ matches = globMatches results++ let errors :: [String]+ errors =+ [ "filepath wildcard '" ++ filepath ++ "' refers to the directory"+ ++ " '" ++ missingDir ++ "', which does not exist or is not a directory."+ | missingDir <- missingDirectories+ ]+ +++ [ "filepath wildcard '" ++ filepath ++ "' does not match any files."+ | null matches+ ]++ if null errors+ then return matches+ else rip verbosity $ unlines errors++-- | Match files against a pre-parsed glob, starting in a directory.+--+-- The 'Version' argument must be the spec version of the package+-- description being processed, as globs behave slightly differently+-- in different spec versions.+--+-- The 'FilePath' argument is the directory that the glob is relative+-- to. It must be a valid directory (and hence it can't be the empty+-- string). The returned values will not include this prefix.+runDirFileGlob :: Verbosity -> FilePath -> Glob -> IO [GlobResult FilePath]+runDirFileGlob verbosity rawDir pat = do+ -- The default data-dir is null. Our callers -should- be+ -- converting that to '.' themselves, but it's a certainty that+ -- some future call-site will forget and trigger a really+ -- hard-to-debug failure if we don't check for that here.+ when (null rawDir) $+ warn verbosity $+ "Null dir passed to runDirFileGlob; interpreting it "+ ++ "as '.'. This is probably an internal error."+ let dir = if null rawDir then "." else rawDir+ debug verbosity $ "Expanding glob '" ++ reconstructGlob pat ++ "' in directory '" ++ dir ++ "'."+ -- This function might be called from the project root with dir as+ -- ".". Walking the tree starting there involves going into .git/+ -- and dist-newstyle/, which is a lot of work for no reward, so+ -- extract the constant prefix from the pattern and start walking+ -- there, and only walk as much as we need to: recursively if **,+ -- the whole directory if *, and just the specific file if it's a+ -- literal.+ let (prefixSegments, final) = splitConstantPrefix pat+ joinedPrefix = joinPath prefixSegments+ case final of+ FinalMatch recursive multidot exts -> do+ let prefix = dir </> joinedPrefix+ directoryExists <- doesDirectoryExist prefix+ if directoryExists+ then do+ candidates <- case recursive of+ Recursive -> getDirectoryContentsRecursive prefix+ NonRecursive -> filterM (doesFileExist . (prefix </>)) =<< getDirectoryContents prefix+ let checkName candidate = do+ let (candidateBase, candidateExts) = splitExtensions $ takeFileName candidate+ guard (not (null candidateBase))+ match <- checkExt multidot exts candidateExts+ return (joinedPrefix </> candidate <$ match)+ return $ mapMaybe checkName candidates+ else+ return [ GlobMissingDirectory joinedPrefix ]+ FinalLit fn -> do+ exists <- doesFileExist (dir </> joinedPrefix </> fn)+ return [ GlobMatch (joinedPrefix </> fn) | exists ]++unfoldr' :: (a -> Either r (b, a)) -> a -> ([b], r)+unfoldr' f a = case f a of+ Left r -> ([], r)+ Right (b, a') -> case unfoldr' f a' of+ (bs, r) -> (b : bs, r)++-- | Extract the (possibly null) constant prefix from the pattern.+-- This has the property that, if @(pref, final) = splitConstantPrefix pat@,+-- then @pat === foldr GlobStem (GlobFinal final) pref@.+splitConstantPrefix :: Glob -> ([FilePath], GlobFinal)+splitConstantPrefix = unfoldr' step+ where+ step (GlobStem seg pat) = Right (seg, pat)+ step (GlobFinal pat) = Left pat
+ src/Distribution/Simple/Haddock.hs view
@@ -0,0 +1,926 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Haddock+-- Copyright : Isaac Jones 2003-2005+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module deals with the @haddock@ and @hscolour@ commands.+-- It uses information about installed packages (from @ghc-pkg@) to find the+-- locations of documentation for dependent packages, so it can create links.+--+-- The @hscolour@ support allows generating HTML versions of the original+-- source, with coloured syntax highlighting.++module Distribution.Simple.Haddock (+ haddock, hscolour,++ haddockPackagePaths+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Distribution.Simple.GHC as GHC+import qualified Distribution.Simple.GHCJS as GHCJS++-- local+import Distribution.Backpack.DescribeUnitId+import Distribution.Backpack (OpenModule)+import Distribution.Types.ForeignLib+import Distribution.Types.UnqualComponentName+import Distribution.Types.ComponentLocalBuildInfo+import Distribution.Types.ExecutableScope+import Distribution.Types.LocalBuildInfo+import Distribution.Types.TargetInfo+import Distribution.Types.ExposedModule+import Distribution.Package+import qualified Distribution.ModuleName as ModuleName+import Distribution.PackageDescription+import Distribution.Simple.Compiler+import Distribution.Simple.Glob+import Distribution.Simple.Program.GHC+import Distribution.Simple.Program.ResponseFile+import Distribution.Simple.Program+import Distribution.Simple.PreProcess+import Distribution.Simple.Setup+import Distribution.Simple.Build+import Distribution.Simple.BuildTarget+import Distribution.Simple.InstallDirs+import Distribution.Simple.LocalBuildInfo hiding (substPathTemplate)+import Distribution.Simple.BuildPaths+import Distribution.Simple.Register+import qualified Distribution.Simple.Program.HcPkg as HcPkg+import qualified Distribution.Simple.PackageIndex as PackageIndex+import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo+import Distribution.InstalledPackageInfo ( InstalledPackageInfo )+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Pretty+import Distribution.Parsec (simpleParsec)+import Distribution.Utils.NubList+import Distribution.Version+import qualified Distribution.Utils.ShortText as ShortText++import Distribution.Verbosity+import Language.Haskell.Extension++import Distribution.Compat.Semigroup (All (..), Any (..))++import Control.Monad+import Data.Either ( rights )++import System.Directory (getCurrentDirectory, doesDirectoryExist, doesFileExist)+import System.FilePath ( (</>), (<.>), normalise, isAbsolute )+import System.IO (hClose, hPutStrLn, hSetEncoding, utf8)++-- ------------------------------------------------------------------------------+-- Types++-- | A record that represents the arguments to the haddock executable, a product+-- monoid.+data HaddockArgs = HaddockArgs {+ argInterfaceFile :: Flag FilePath,+ -- ^ Path to the interface file, relative to argOutputDir, required.+ argPackageName :: Flag PackageIdentifier,+ -- ^ Package name, required.+ argHideModules :: (All,[ModuleName.ModuleName]),+ -- ^ (Hide modules ?, modules to hide)+ argIgnoreExports :: Any,+ -- ^ Ignore export lists in modules?+ argLinkSource :: Flag (Template,Template,Template),+ -- ^ (Template for modules, template for symbols, template for lines).+ argLinkedSource :: Flag Bool,+ -- ^ Generate hyperlinked sources+ argQuickJump :: Flag Bool,+ -- ^ Generate quickjump index+ argCssFile :: Flag FilePath,+ -- ^ Optional custom CSS file.+ argContents :: Flag String,+ -- ^ Optional URL to contents page.+ argVerbose :: Any,+ argOutput :: Flag [Output],+ -- ^ HTML or Hoogle doc or both? Required.+ argInterfaces :: [(FilePath, Maybe String, Maybe String)],+ -- ^ [(Interface file, URL to the HTML docs and hyperlinked-source for links)].+ argOutputDir :: Directory,+ -- ^ Where to generate the documentation.+ argTitle :: Flag String,+ -- ^ Page title, required.+ argPrologue :: Flag String,+ -- ^ Prologue text, required.+ argGhcOptions :: GhcOptions,+ -- ^ Additional flags to pass to GHC.+ argGhcLibDir :: Flag FilePath,+ -- ^ To find the correct GHC, required.+ argReexports :: [OpenModule],+ -- ^ Re-exported modules+ 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)++unDir :: Directory -> FilePath+unDir = normalise . unDir'++type Template = String++data Output = Html | Hoogle++-- ------------------------------------------------------------------------------+-- Haddock support++haddock :: PackageDescription+ -> LocalBuildInfo+ -> [PPSuffixHandler]+ -> HaddockFlags+ -> IO ()+haddock pkg_descr _ _ haddockFlags+ | not (hasLibs pkg_descr)+ && not (fromFlag $ haddockExecutables haddockFlags)+ && not (fromFlag $ haddockTestSuites haddockFlags)+ && not (fromFlag $ haddockBenchmarks haddockFlags)+ && not (fromFlag $ haddockForeignLibs haddockFlags)+ =+ warn (fromFlag $ haddockVerbosity haddockFlags) $+ "No documentation was generated as this package does not contain "+ ++ "a library. Perhaps you want to use the --executables, --tests,"+ ++ " --benchmarks or --foreign-libraries flags."++haddock pkg_descr lbi suffixes flags' = do+ let verbosity = flag haddockVerbosity+ comp = compiler lbi+ platform = hostPlatform lbi++ quickJmpFlag = haddockQuickJump flags'+ flags = case haddockTarget of+ ForDevelopment -> flags'+ ForHackage -> flags'+ { haddockHoogle = Flag True+ , haddockHtml = Flag True+ , haddockHtmlLocation = Flag (pkg_url ++ "/docs")+ , haddockContents = Flag (toPathTemplate pkg_url)+ , haddockLinkedSource = Flag True+ , haddockQuickJump = Flag True+ }+ pkg_url = "/package/$pkg-$version"+ flag f = fromFlag $ f flags++ tmpFileOpts = defaultTempFileOptions+ { optKeepTempFiles = flag haddockKeepTempFiles }+ htmlTemplate = fmap toPathTemplate . flagToMaybe . haddockHtmlLocation+ $ flags+ haddockTarget =+ fromFlagOrDefault ForDevelopment (haddockForHackage flags')++ (haddockProg, version, _) <-+ requireProgramVersion verbosity haddockProgram+ (orLaterVersion (mkVersion [2,0])) (withPrograms lbi)++ -- various sanity checks+ when (flag haddockHoogle && version < mkVersion [2,2]) $+ die' verbosity "Haddock 2.0 and 2.1 do not support the --hoogle flag."+++ when (flag haddockQuickJump && version < mkVersion [2,19]) $ do+ let msg = "Haddock prior to 2.19 does not support the --quickjump flag."+ alt = "The generated documentation won't have the QuickJump feature."+ if Flag True == quickJmpFlag+ then die' verbosity msg+ else warn verbosity (msg ++ "\n" ++ alt)++ haddockGhcVersionStr <- getProgramOutput verbosity haddockProg+ ["--ghc-version"]+ case (simpleParsec haddockGhcVersionStr, compilerCompatVersion GHC comp) of+ (Nothing, _) -> die' verbosity "Could not get GHC version from Haddock"+ (_, Nothing) -> die' verbosity "Could not get GHC version from compiler"+ (Just haddockGhcVersion, Just ghcVersion)+ | haddockGhcVersion == ghcVersion -> return ()+ | otherwise -> die' verbosity $+ "Haddock's internal GHC version must match the configured "+ ++ "GHC version.\n"+ ++ "The GHC version is " ++ prettyShow ghcVersion ++ " but "+ ++ "haddock is using GHC version " ++ prettyShow haddockGhcVersion++ -- the tools match the requests, we can proceed++ -- We fall back to using HsColour only for versions of Haddock which don't+ -- support '--hyperlinked-sources'.+ when (flag haddockLinkedSource && version < mkVersion [2,17]) $+ hscolour' (warn verbosity) haddockTarget pkg_descr lbi suffixes+ (defaultHscolourFlags `mappend` haddockToHscolour flags)++ libdirArgs <- getGhcLibDir verbosity lbi+ let commonArgs = mconcat+ [ libdirArgs+ , fromFlags (haddockTemplateEnv lbi (packageId pkg_descr)) flags+ , fromPackageDescription haddockTarget pkg_descr ]++ targets <- readTargetInfos verbosity pkg_descr lbi (haddockArgs flags)++ let+ targets' =+ case targets of+ [] -> allTargetsInBuildOrder' pkg_descr lbi+ _ -> targets++ internalPackageDB <-+ createInternalPackageDB verbosity lbi (flag haddockDistPref)++ (\f -> foldM_ f (installedPkgs lbi) targets') $ \index target -> do++ let component = targetComponent target+ clbi = targetCLBI target++ componentInitialBuildSteps (flag haddockDistPref) pkg_descr lbi clbi verbosity++ let+ lbi' = lbi {+ withPackageDB = withPackageDB lbi ++ [internalPackageDB],+ installedPkgs = index+ }++ preprocessComponent pkg_descr component lbi' clbi False verbosity suffixes+ let+ doExe com = case (compToExe com) of+ Just exe -> do+ withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi') "tmp" $+ \tmp -> do+ exeArgs <- fromExecutable verbosity tmp lbi' clbi htmlTemplate+ version exe+ let exeArgs' = commonArgs `mappend` exeArgs+ runHaddock verbosity tmpFileOpts comp platform+ haddockProg exeArgs'+ Nothing -> do+ warn (fromFlag $ haddockVerbosity flags)+ "Unsupported component, skipping..."+ return ()+ -- We define 'smsg' once and then reuse it inside the case, so that+ -- we don't say we are running Haddock when we actually aren't+ -- (e.g., Haddock is not run on non-libraries)+ smsg :: IO ()+ smsg = setupMessage' verbosity "Running Haddock on" (packageId pkg_descr)+ (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)+ case component of+ CLib lib -> do+ withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi) "tmp" $+ \tmp -> do+ smsg+ libArgs <- fromLibrary verbosity tmp lbi' clbi htmlTemplate+ version lib+ let libArgs' = commonArgs `mappend` libArgs+ runHaddock verbosity tmpFileOpts comp platform haddockProg libArgs'++ case libName lib of+ LMainLibName ->+ pure index+ LSubLibName _ -> do+ pwd <- getCurrentDirectory++ let+ ipi = inplaceInstalledPackageInfo+ pwd (flag haddockDistPref) pkg_descr+ (mkAbiHash "inplace") lib lbi' clbi++ debug verbosity $ "Registering inplace:\n"+ ++ (InstalledPackageInfo.showInstalledPackageInfo ipi)++ registerPackage verbosity (compiler lbi') (withPrograms lbi')+ (withPackageDB lbi') ipi+ HcPkg.defaultRegisterOptions {+ HcPkg.registerMultiInstance = True+ }++ return $ PackageIndex.insert ipi index++ CFLib flib -> (when (flag haddockForeignLibs) $ do+ withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi') "tmp" $+ \tmp -> do+ smsg+ flibArgs <- fromForeignLib verbosity tmp lbi' clbi htmlTemplate+ version flib+ let libArgs' = commonArgs `mappend` flibArgs+ runHaddock verbosity tmpFileOpts comp platform haddockProg libArgs')++ >> return index++ CExe _ -> (when (flag haddockExecutables) $ smsg >> doExe component) >> return index+ CTest _ -> (when (flag haddockTestSuites) $ smsg >> doExe component) >> return index+ CBench _ -> (when (flag haddockBenchmarks) $ smsg >> doExe component) >> return index++ for_ (extraDocFiles pkg_descr) $ \ fpath -> do+ files <- matchDirFileGlob verbosity (specVersion pkg_descr) "." fpath+ for_ files $ copyFileTo verbosity (unDir $ argOutputDir commonArgs)++-- ------------------------------------------------------------------------------+-- Contributions to HaddockArgs (see also Doctest.hs for very similar code).++fromFlags :: PathTemplateEnv -> HaddockFlags -> HaddockArgs+fromFlags env flags =+ mempty {+ argHideModules = (maybe mempty (All . not)+ $ flagToMaybe (haddockInternal flags), mempty),+ argLinkSource = if fromFlag (haddockLinkedSource flags)+ then Flag ("src/%{MODULE/./-}.html"+ ,"src/%{MODULE/./-}.html#%{NAME}"+ ,"src/%{MODULE/./-}.html#line-%{LINE}")+ else NoFlag,+ argLinkedSource = haddockLinkedSource flags,+ argQuickJump = haddockQuickJump flags,+ argCssFile = haddockCss flags,+ argContents = fmap (fromPathTemplate . substPathTemplate env)+ (haddockContents flags),+ argVerbose = maybe mempty (Any . (>= deafening))+ . flagToMaybe $ haddockVerbosity flags,+ argOutput =+ Flag $ case [ Html | Flag True <- [haddockHtml flags] ] +++ [ Hoogle | Flag True <- [haddockHoogle flags] ]+ of [] -> [ Html ]+ os -> os,+ argOutputDir = maybe mempty Dir . flagToMaybe $ haddockDistPref flags,++ argGhcOptions = mempty { ghcOptExtra = ghcArgs }+ }+ where+ ghcArgs = fromMaybe [] . lookup "ghc" . haddockProgramArgs $ flags++fromPackageDescription :: HaddockTarget -> PackageDescription -> HaddockArgs+fromPackageDescription haddockTarget pkg_descr = mempty+ { argInterfaceFile = Flag $ haddockName pkg_descr+ , argPackageName = Flag $ packageId $ pkg_descr+ , argOutputDir = Dir $+ "doc" </> "html" </> haddockDirName haddockTarget pkg_descr+ , argPrologue = Flag $ ShortText.fromShortText $+ if ShortText.null desc+ then synopsis pkg_descr+ else desc+ , argTitle = Flag $ showPkg ++ subtitle+ }+ where+ desc = description pkg_descr+ showPkg = prettyShow (packageId pkg_descr)+ subtitle+ | ShortText.null (synopsis pkg_descr) = ""+ | otherwise = ": " ++ ShortText.fromShortText (synopsis pkg_descr)++componentGhcOptions :: Verbosity -> LocalBuildInfo+ -> BuildInfo -> ComponentLocalBuildInfo -> FilePath+ -> GhcOptions+componentGhcOptions verbosity lbi bi clbi odir =+ let f = case compilerFlavor (compiler lbi) of+ GHC -> GHC.componentGhcOptions+ GHCJS -> GHCJS.componentGhcOptions+ _ -> error $+ "Distribution.Simple.Haddock.componentGhcOptions:" +++ "haddock only supports GHC and GHCJS"+ in f verbosity lbi bi clbi odir++mkHaddockArgs :: Verbosity+ -> FilePath+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Maybe PathTemplate -- ^ template for HTML location+ -> Version+ -> [FilePath]+ -> BuildInfo+ -> IO HaddockArgs+mkHaddockArgs verbosity tmp lbi clbi htmlTemplate haddockVersion inFiles bi = do+ ifaceArgs <- getInterfaces verbosity lbi clbi htmlTemplate+ let vanillaOpts = (componentGhcOptions normal lbi bi clbi (buildDir lbi)) {+ -- Noooooooooo!!!!!111+ -- haddock stomps on our precious .hi+ -- and .o files. Workaround by telling+ -- haddock to write them elsewhere.+ ghcOptObjDir = toFlag tmp,+ ghcOptHiDir = toFlag tmp,+ ghcOptStubDir = toFlag tmp+ } `mappend` getGhcCppOpts haddockVersion bi+ sharedOpts = vanillaOpts {+ ghcOptDynLinkMode = toFlag GhcDynamicOnly,+ ghcOptFPic = toFlag True,+ ghcOptHiSuffix = toFlag "dyn_hi",+ ghcOptObjSuffix = toFlag "dyn_o",+ ghcOptExtra = hcSharedOptions GHC bi++ }+ opts <- if withVanillaLib lbi+ then return vanillaOpts+ else if withSharedLib lbi+ then return sharedOpts+ else die' verbosity $ "Must have vanilla or shared libraries "+ ++ "enabled in order to run haddock"++ return ifaceArgs+ { argGhcOptions = opts+ , argTargets = inFiles+ , argReexports = getReexports clbi+ }++fromLibrary :: Verbosity+ -> FilePath+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Maybe PathTemplate -- ^ template for HTML location+ -> Version+ -> Library+ -> IO HaddockArgs+fromLibrary verbosity tmp lbi clbi htmlTemplate haddockVersion lib = do+ inFiles <- map snd `fmap` getLibSourceFiles verbosity lbi lib clbi+ args <- mkHaddockArgs verbosity tmp lbi clbi htmlTemplate haddockVersion+ inFiles (libBuildInfo lib)+ return args {+ argHideModules = (mempty, otherModules (libBuildInfo lib))+ }++fromExecutable :: Verbosity+ -> FilePath+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Maybe PathTemplate -- ^ template for HTML location+ -> Version+ -> Executable+ -> IO HaddockArgs+fromExecutable verbosity tmp lbi clbi htmlTemplate haddockVersion exe = do+ inFiles <- map snd `fmap` getExeSourceFiles verbosity lbi exe clbi+ args <- mkHaddockArgs verbosity tmp lbi clbi htmlTemplate+ haddockVersion inFiles (buildInfo exe)+ return args {+ argOutputDir = Dir $ unUnqualComponentName $ exeName exe,+ argTitle = Flag $ unUnqualComponentName $ exeName exe+ }++fromForeignLib :: Verbosity+ -> FilePath+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Maybe PathTemplate -- ^ template for HTML location+ -> Version+ -> ForeignLib+ -> IO HaddockArgs+fromForeignLib verbosity tmp lbi clbi htmlTemplate haddockVersion flib = do+ inFiles <- map snd `fmap` getFLibSourceFiles verbosity lbi flib clbi+ args <- mkHaddockArgs verbosity tmp lbi clbi htmlTemplate+ haddockVersion inFiles (foreignLibBuildInfo flib)+ return args {+ argOutputDir = Dir $ unUnqualComponentName $ foreignLibName flib,+ argTitle = Flag $ unUnqualComponentName $ foreignLibName flib+ }++compToExe :: Component -> Maybe Executable+compToExe comp =+ case comp of+ CTest test@TestSuite { testInterface = TestSuiteExeV10 _ f } ->+ Just Executable {+ exeName = testName test,+ modulePath = f,+ exeScope = ExecutablePublic,+ buildInfo = testBuildInfo test+ }+ CBench bench@Benchmark { benchmarkInterface = BenchmarkExeV10 _ f } ->+ Just Executable {+ exeName = benchmarkName bench,+ modulePath = f,+ exeScope = ExecutablePublic,+ buildInfo = benchmarkBuildInfo bench+ }+ CExe exe -> Just exe+ _ -> Nothing++getInterfaces :: Verbosity+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Maybe PathTemplate -- ^ template for HTML location+ -> IO HaddockArgs+getInterfaces verbosity lbi clbi htmlTemplate = do+ (packageFlags, warnings) <- haddockPackageFlags verbosity lbi clbi htmlTemplate+ traverse_ (warn (verboseUnmarkOutput verbosity)) warnings+ return $ mempty {+ argInterfaces = packageFlags+ }++getReexports :: ComponentLocalBuildInfo -> [OpenModule]+getReexports LibComponentLocalBuildInfo {componentExposedModules = mods } =+ mapMaybe exposedReexport mods+getReexports _ = []++getGhcCppOpts :: Version+ -> BuildInfo+ -> GhcOptions+getGhcCppOpts haddockVersion bi =+ mempty {+ ghcOptExtensions = toNubListR [EnableExtension CPP | needsCpp],+ ghcOptCppOptions = defines+ }+ where+ needsCpp = EnableExtension CPP `elem` usedExtensions bi+ defines = [haddockVersionMacro]+ haddockVersionMacro = "-D__HADDOCK_VERSION__="+ ++ show (v1 * 1000 + v2 * 10 + v3)+ where+ (v1, v2, v3) = case versionNumbers haddockVersion of+ [] -> (0,0,0)+ [x] -> (x,0,0)+ [x,y] -> (x,y,0)+ (x:y:z:_) -> (x,y,z)++getGhcLibDir :: Verbosity -> LocalBuildInfo+ -> IO HaddockArgs+getGhcLibDir verbosity lbi = do+ l <- case compilerFlavor (compiler lbi) of+ GHC -> GHC.getLibDir verbosity lbi+ GHCJS -> GHCJS.getLibDir verbosity lbi+ _ -> error "haddock only supports GHC and GHCJS"+ return $ mempty { argGhcLibDir = Flag l }++-- ------------------------------------------------------------------------------+-- | Call haddock with the specified arguments.+runHaddock :: Verbosity+ -> TempFileOptions+ -> Compiler+ -> Platform+ -> ConfiguredProgram+ -> HaddockArgs+ -> IO ()+runHaddock verbosity tmpFileOpts comp platform haddockProg args+ | null (argTargets args) = warn verbosity $+ "Haddocks are being requested, but there aren't any modules given "+ ++ "to create documentation for."+ | otherwise = do+ let haddockVersion = fromMaybe (error "unable to determine haddock version")+ (programVersion haddockProg)+ renderArgs verbosity tmpFileOpts haddockVersion comp platform args $+ \(flags,result)-> do++ runProgram verbosity haddockProg flags++ notice verbosity $ "Documentation created: " ++ result+++renderArgs :: Verbosity+ -> TempFileOptions+ -> Version+ -> Compiler+ -> Platform+ -> HaddockArgs+ -> (([String], FilePath) -> IO a)+ -> IO a+renderArgs verbosity tmpFileOpts version comp platform args k = do+ let haddockSupportsUTF8 = version >= mkVersion [2,14,4]+ haddockSupportsResponseFiles = version > mkVersion [2,16,2]+ createDirectoryIfMissingVerbose verbosity True outputDir+ withTempFileEx tmpFileOpts outputDir "haddock-prologue.txt" $+ \prologueFileName h -> do+ do+ when haddockSupportsUTF8 (hSetEncoding h utf8)+ hPutStrLn h $ fromFlag $ argPrologue args+ hClose h+ let pflag = "--prologue=" ++ prologueFileName+ renderedArgs = pflag : renderPureArgs version comp platform args+ if haddockSupportsResponseFiles+ then+ withResponseFile+ verbosity+ tmpFileOpts+ outputDir+ "haddock-response.txt"+ (if haddockSupportsUTF8 then Just utf8 else Nothing)+ renderedArgs+ (\responseFileName -> k (["@" ++ responseFileName], result))+ else+ k (renderedArgs, result)+ where+ outputDir = (unDir $ argOutputDir args)+ result = intercalate ", "+ . map (\o -> outputDir </>+ case o of+ Html -> "index.html"+ Hoogle -> pkgstr <.> "txt")+ $ arg argOutput+ where+ pkgstr = prettyShow $ packageName pkgid+ pkgid = arg argPackageName+ arg f = fromFlag $ f args++renderPureArgs :: Version -> Compiler -> Platform -> HaddockArgs -> [String]+renderPureArgs version comp platform args = concat+ [ (:[]) . (\f -> "--dump-interface="++ unDir (argOutputDir args) </> f)+ . fromFlag . argInterfaceFile $ args++ , if isVersion 2 16+ then (\pkg -> [ "--package-name=" ++ prettyShow (pkgName pkg)+ , "--package-version=" ++ prettyShow (pkgVersion pkg)+ ])+ . fromFlag . argPackageName $ args+ else []++ , [ "--since-qual=external" | isVersion 2 20 ]++ , [ "--quickjump" | isVersion 2 19+ , fromFlag . argQuickJump $ args ]++ , [ "--hyperlinked-source" | isVersion 2 17+ , fromFlag . argLinkedSource $ args ]++ , (\(All b,xs) -> bool (map (("--hide=" ++) . prettyShow) xs) [] b)+ . argHideModules $ args++ , bool ["--ignore-all-exports"] [] . getAny . argIgnoreExports $ args++ , maybe [] (\(m,e,l) ->+ ["--source-module=" ++ m+ ,"--source-entity=" ++ e]+ ++ if isVersion 2 14 then ["--source-entity-line=" ++ l]+ else []+ ) . flagToMaybe . argLinkSource $ args++ , maybe [] ((:[]) . ("--css="++)) . flagToMaybe . argCssFile $ args++ , maybe [] ((:[]) . ("--use-contents="++)) . flagToMaybe . argContents $ args++ , bool [] [verbosityFlag] . getAny . argVerbose $ args++ , map (\o -> case o of Hoogle -> "--hoogle"; Html -> "--html")+ . fromFlag . argOutput $ args++ , renderInterfaces . argInterfaces $ args++ , (:[]) . ("--odir="++) . unDir . argOutputDir $ args++ , (:[]) . ("--title="++)+ . (bool (++" (internal documentation)")+ id (getAny $ argIgnoreExports args))+ . fromFlag . argTitle $ args++ , [ "--optghc=" ++ opt | let opts = argGhcOptions args+ , opt <- renderGhcOptions comp platform opts ]++ , maybe [] (\l -> ["-B"++l]) $+ flagToMaybe (argGhcLibDir args) -- error if Nothing?++ -- https://github.com/haskell/haddock/pull/547+ , [ "--reexport=" ++ prettyShow r+ | r <- argReexports args+ , isVersion 2 19+ ]++ , argTargets $ args+ ]+ where+ renderInterfaces = map renderInterface++ renderInterface :: (FilePath, Maybe FilePath, Maybe FilePath) -> String+ renderInterface (i, html, hypsrc) = "--read-interface=" +++ (intercalate "," $ concat [ [ x | Just x <- [html] ]+ , [ x | Just _ <- [html]+ -- only render hypsrc path if html path+ -- is given and hyperlinked-source is+ -- enabled+ , Just x <- [hypsrc]+ , isVersion 2 17+ , fromFlag . argLinkedSource $ args+ ]+ , [ i ]+ ])++ bool a b c = if c then a else b+ isVersion major minor = version >= mkVersion [major,minor]+ verbosityFlag+ | isVersion 2 5 = "--verbosity=1"+ | otherwise = "--verbose"++---------------------------------------------------------------------------------++-- | Given a list of 'InstalledPackageInfo's, return a list of interfaces and+-- HTML paths, and an optional warning for packages with missing documentation.+haddockPackagePaths :: [InstalledPackageInfo]+ -> Maybe (InstalledPackageInfo -> FilePath)+ -> IO ([( FilePath -- path to interface+ -- file++ , Maybe FilePath -- url to html+ -- documentation++ , Maybe FilePath -- url to hyperlinked+ -- source+ )]+ , Maybe String -- warning about+ -- missing documentation+ )+haddockPackagePaths ipkgs mkHtmlPath = do+ interfaces <- sequenceA+ [ case interfaceAndHtmlPath ipkg of+ Nothing -> return (Left (packageId ipkg))+ Just (interface, html) -> do++ (html', hypsrc') <-+ case html of+ Just htmlPath -> do+ let hypSrcPath = htmlPath </> defaultHyperlinkedSourceDirectory+ hypSrcExists <- doesDirectoryExist hypSrcPath+ return $ ( Just (fixFileUrl htmlPath)+ , if hypSrcExists+ then Just (fixFileUrl hypSrcPath)+ else Nothing+ )+ Nothing -> return (Nothing, Nothing)++ exists <- doesFileExist interface+ if exists+ then return (Right (interface, html', hypsrc'))+ else return (Left pkgid)+ | ipkg <- ipkgs, let pkgid = packageId ipkg+ , pkgName pkgid `notElem` noHaddockWhitelist+ ]++ let missing = [ pkgid | Left pkgid <- interfaces ]+ warning = "The documentation for the following packages are not "+ ++ "installed. No links will be generated to these packages: "+ ++ intercalate ", " (map prettyShow missing)+ flags = rights interfaces++ return (flags, if null missing then Nothing else Just warning)++ where+ -- Don't warn about missing documentation for these packages. See #1231.+ noHaddockWhitelist = map mkPackageName [ "rts" ]++ -- Actually extract interface and HTML paths from an 'InstalledPackageInfo'.+ interfaceAndHtmlPath :: InstalledPackageInfo+ -> Maybe (FilePath, Maybe FilePath)+ interfaceAndHtmlPath pkg = do+ interface <- listToMaybe (InstalledPackageInfo.haddockInterfaces pkg)+ html <- case mkHtmlPath of+ Nothing -> listToMaybe (InstalledPackageInfo.haddockHTMLs pkg)+ Just mkPath -> Just (mkPath pkg)+ return (interface, if null html then Nothing else Just html)++ -- The 'haddock-html' field in the hc-pkg output is often set as a+ -- native path, but we need it as a URL. See #1064. Also don't "fix"+ -- the path if it is an interpolated one.+ fixFileUrl f | Nothing <- mkHtmlPath+ , isAbsolute f = "file://" ++ f+ | otherwise = f++ -- 'src' is the default hyperlinked source directory ever since. It is+ -- not possible to configure that directory in any way in haddock.+ defaultHyperlinkedSourceDirectory = "src"+++haddockPackageFlags :: Verbosity+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Maybe PathTemplate+ -> IO ([( FilePath -- path to interface+ -- file++ , Maybe FilePath -- url to html+ -- documentation++ , Maybe FilePath -- url to hyperlinked+ -- source+ )]+ , Maybe String -- warning about+ -- missing documentation+ )+haddockPackageFlags verbosity lbi clbi htmlTemplate = do+ let allPkgs = installedPkgs lbi+ directDeps = map fst (componentPackageDeps clbi)+ transitiveDeps <- case PackageIndex.dependencyClosure allPkgs directDeps of+ Left x -> return x+ Right inf -> die' verbosity $ "internal error when calculating transitive "+ ++ "package dependencies.\nDebug info: " ++ show inf+ haddockPackagePaths (PackageIndex.allPackages transitiveDeps) mkHtmlPath+ where+ mkHtmlPath = fmap expandTemplateVars htmlTemplate+ expandTemplateVars tmpl pkg =+ fromPathTemplate . substPathTemplate (env pkg) $ tmpl+ env pkg = haddockTemplateEnv lbi (packageId pkg)+++haddockTemplateEnv :: LocalBuildInfo -> PackageIdentifier -> PathTemplateEnv+haddockTemplateEnv lbi pkg_id =+ (PrefixVar, prefix (installDirTemplates 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)++-- ------------------------------------------------------------------------------+-- hscolour support.++hscolour :: PackageDescription+ -> LocalBuildInfo+ -> [PPSuffixHandler]+ -> HscolourFlags+ -> IO ()+hscolour = hscolour' dieNoVerbosity ForDevelopment++hscolour' :: (String -> IO ()) -- ^ Called when the 'hscolour' exe is not found.+ -> HaddockTarget+ -> PackageDescription+ -> LocalBuildInfo+ -> [PPSuffixHandler]+ -> HscolourFlags+ -> IO ()+hscolour' onNoHsColour haddockTarget pkg_descr lbi suffixes flags =+ either onNoHsColour (\(hscolourProg, _, _) -> go hscolourProg) =<<+ lookupProgramVersion verbosity hscolourProgram+ (orLaterVersion (mkVersion [1,8])) (withPrograms lbi)+ where+ go :: ConfiguredProgram -> IO ()+ go hscolourProg = do+ warn verbosity $+ "the 'cabal hscolour' command is deprecated in favour of 'cabal " +++ "haddock --hyperlink-source' and will be removed in the next major " +++ "release."++ setupMessage verbosity "Running hscolour for" (packageId pkg_descr)+ createDirectoryIfMissingVerbose verbosity True $+ hscolourPref haddockTarget distPref pkg_descr++ withAllComponentsInBuildOrder pkg_descr lbi $ \comp clbi -> do+ componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity+ preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes+ let+ doExe com = case (compToExe com) of+ Just exe -> do+ let outputDir = hscolourPref haddockTarget distPref pkg_descr+ </> unUnqualComponentName (exeName exe) </> "src"+ runHsColour hscolourProg outputDir =<< getExeSourceFiles verbosity lbi exe clbi+ Nothing -> do+ warn (fromFlag $ hscolourVerbosity flags)+ "Unsupported component, skipping..."+ return ()+ case comp of+ CLib lib -> do+ let outputDir = hscolourPref haddockTarget distPref pkg_descr </> "src"+ runHsColour hscolourProg outputDir =<< getLibSourceFiles verbosity lbi lib clbi+ CFLib flib -> do+ let outputDir = hscolourPref haddockTarget distPref pkg_descr+ </> unUnqualComponentName (foreignLibName flib) </> "src"+ runHsColour hscolourProg outputDir =<< getFLibSourceFiles verbosity lbi flib clbi+ CExe _ -> when (fromFlag (hscolourExecutables flags)) $ doExe comp+ CTest _ -> when (fromFlag (hscolourTestSuites flags)) $ doExe comp+ CBench _ -> when (fromFlag (hscolourBenchmarks flags)) $ doExe comp++ stylesheet = flagToMaybe (hscolourCSS flags)++ verbosity = fromFlag (hscolourVerbosity flags)+ distPref = fromFlag (hscolourDistPref flags)++ runHsColour prog outputDir moduleFiles = do+ createDirectoryIfMissingVerbose verbosity True outputDir++ case stylesheet of -- copy the CSS file+ Nothing | programVersion prog >= Just (mkVersion [1,9]) ->+ runProgram verbosity prog+ ["-print-css", "-o" ++ outputDir </> "hscolour.css"]+ | otherwise -> return ()+ Just s -> copyFileVerbose verbosity s (outputDir </> "hscolour.css")++ for_ moduleFiles $ \(m, inFile) ->+ runProgram verbosity prog+ ["-css", "-anchor", "-o" ++ outFile m, inFile]+ where+ outFile m = outputDir </>+ intercalate "-" (ModuleName.components m) <.> "html"++haddockToHscolour :: HaddockFlags -> HscolourFlags+haddockToHscolour flags =+ HscolourFlags {+ hscolourCSS = haddockHscolourCss flags,+ hscolourExecutables = haddockExecutables flags,+ hscolourTestSuites = haddockTestSuites flags,+ hscolourBenchmarks = haddockBenchmarks flags,+ hscolourForeignLibs = haddockForeignLibs flags,+ hscolourVerbosity = haddockVerbosity flags,+ hscolourDistPref = haddockDistPref flags,+ hscolourCabalFilePath = haddockCabalFilePath flags+ }++-- ------------------------------------------------------------------------------+-- Boilerplate Monoid instance.+instance Monoid HaddockArgs where+ mempty = gmempty+ mappend = (<>)++instance Semigroup HaddockArgs where+ (<>) = gmappend++instance Monoid Directory where+ mempty = Dir "."+ mappend = (<>)++instance Semigroup Directory where+ Dir m <> Dir n = Dir $ m </> n
+ src/Distribution/Simple/HaskellSuite.hs view
@@ -0,0 +1,228 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++module Distribution.Simple.HaskellSuite where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Data.List.NonEmpty as NE++import Distribution.Simple.Program+import Distribution.Simple.Compiler+import Distribution.Simple.Utils+import Distribution.Simple.BuildPaths+import Distribution.Verbosity+import Distribution.Version+import Distribution.Pretty+import Distribution.Parsec (simpleParsec)+import Distribution.Package+import Distribution.InstalledPackageInfo hiding (includeDirs)+import Distribution.Simple.PackageIndex as PackageIndex+import Distribution.PackageDescription+import Distribution.Simple.LocalBuildInfo+import Distribution.System (Platform)+import Distribution.Utils.Path+import Language.Haskell.Extension+import Distribution.Simple.Program.Builtin++configure+ :: Verbosity -> Maybe FilePath -> Maybe FilePath+ -> ProgramDb -> IO (Compiler, Maybe Platform, ProgramDb)+configure verbosity mbHcPath hcPkgPath progdb0 = do++ -- We have no idea how a haskell-suite tool is named, so we require at+ -- least some information from the user.+ hcPath <-+ let msg = "You have to provide name or path of a haskell-suite tool (-w PATH)"+ in maybe (die' verbosity msg) return mbHcPath++ when (isJust hcPkgPath) $+ warn verbosity "--with-hc-pkg option is ignored for haskell-suite"++ (comp, confdCompiler, progdb1) <- configureCompiler hcPath progdb0++ -- Update our pkg tool. It uses the same executable as the compiler, but+ -- all command start with "pkg"+ (confdPkg, _) <- requireProgram verbosity haskellSuitePkgProgram progdb1+ let progdb2 =+ updateProgram+ confdPkg+ { programLocation = programLocation confdCompiler+ , programDefaultArgs = ["pkg"]+ }+ progdb1++ return (comp, Nothing, progdb2)++ where+ configureCompiler hcPath progdb0' = do+ let+ haskellSuiteProgram' =+ haskellSuiteProgram+ { 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.+ -- Instead, call configureProgram directly first.+ progdb1 <- configureProgram verbosity haskellSuiteProgram' progdb0'+ (confdCompiler, progdb2) <- requireProgram verbosity haskellSuiteProgram' progdb1++ extensions <- getExtensions verbosity confdCompiler+ languages <- getLanguages verbosity confdCompiler+ (compName, compVersion) <-+ getCompilerVersion verbosity confdCompiler++ let+ comp = Compiler {+ compilerId = CompilerId (HaskellSuite compName) compVersion,+ compilerAbiTag = NoAbiTag,+ compilerCompat = [],+ compilerLanguages = languages,+ compilerExtensions = extensions,+ compilerProperties = mempty+ }++ return (comp, confdCompiler, progdb2)++hstoolVersion :: Verbosity -> FilePath -> IO (Maybe Version)+hstoolVersion = findProgramVersion "--hspkg-version" id++numericVersion :: Verbosity -> FilePath -> IO (Maybe Version)+numericVersion = findProgramVersion "--compiler-version" (fromMaybe "" . safeLast . words)++getCompilerVersion :: Verbosity -> ConfiguredProgram -> IO (String, Version)+getCompilerVersion verbosity prog = do+ output <- rawSystemStdout verbosity (programPath prog) ["--compiler-version"]+ let+ parts = words output+ name = concat $ safeInit parts -- there shouldn't be any spaces in the name anyway+ versionStr = fromMaybe "" $ safeLast parts+ version <-+ maybe (die' verbosity "haskell-suite: couldn't determine compiler version") return $+ simpleParsec versionStr+ return (name, version)++getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Maybe CompilerFlag)]+getExtensions verbosity prog = do+ extStrs <-+ lines `fmap`+ rawSystemStdout verbosity (programPath prog) ["--supported-extensions"]+ return+ [ (ext, Just $ "-X" ++ prettyShow ext) | Just ext <- map simpleParsec extStrs ]++getLanguages :: Verbosity -> ConfiguredProgram -> IO [(Language, CompilerFlag)]+getLanguages verbosity prog = do+ langStrs <-+ lines `fmap`+ rawSystemStdout verbosity (programPath prog) ["--supported-languages"]+ return+ [ (ext, "-G" ++ prettyShow ext) | Just ext <- map simpleParsec langStrs ]++-- Other compilers do some kind of a packagedb stack check here. Not sure+-- if we need something like that as well.+getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramDb+ -> IO InstalledPackageIndex+getInstalledPackages verbosity packagedbs progdb =+ liftM (PackageIndex.fromList . concat) $ for packagedbs $ \packagedb ->+ do str <-+ getDbProgramOutput verbosity haskellSuitePkgProgram progdb+ ["dump", packageDbOpt packagedb]+ `catchExit` \_ -> die' verbosity $ "pkg dump failed"+ case parsePackages str of+ Right ok -> return ok+ _ -> die' verbosity "failed to parse output of 'pkg dump'"++ where+ parsePackages str =+ case partitionEithers $ map (parseInstalledPackageInfo . toUTF8BS) (splitPkgs str) of+ ([], ok) -> Right [ pkg | (_, pkg) <- ok ]+ (msgss, _) -> Left (foldMap NE.toList msgss)++ splitPkgs :: String -> [String]+ splitPkgs = map unlines . splitWith ("---" ==) . lines+ where+ splitWith :: (a -> Bool) -> [a] -> [[a]]+ splitWith p xs = ys : case zs of+ [] -> []+ _:ws -> splitWith p ws+ where (ys,zs) = break p xs++buildLib+ :: Verbosity -> PackageDescription -> LocalBuildInfo+ -> Library -> ComponentLocalBuildInfo -> IO ()+buildLib verbosity pkg_descr lbi lib clbi = do+ -- In future, there should be a mechanism for the compiler to request any+ -- number of the above parameters (or their parts) — in particular,+ -- pieces of PackageDescription.+ --+ -- For now, we only pass those that we know are used.++ let odir = buildDir lbi+ bi = libBuildInfo lib+ srcDirs = map getSymbolicPath (hsSourceDirs bi) ++ [odir]+ dbStack = withPackageDB lbi+ language = fromMaybe Haskell98 (defaultLanguage bi)+ progdb = withPrograms lbi+ pkgid = packageId pkg_descr++ runDbProgram verbosity haskellSuiteProgram progdb $+ [ "compile", "--build-dir", odir ] +++ concat [ ["-i", d] | d <- srcDirs ] +++ concat [ ["-I", d] | d <- [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi+ ,odir] ++ includeDirs bi ] +++ [ packageDbOpt pkgDb | pkgDb <- dbStack ] +++ [ "--package-name", prettyShow pkgid ] +++ concat [ ["--package-id", prettyShow ipkgid ]+ | (ipkgid, _) <- componentPackageDeps clbi ] +++ ["-G", prettyShow language] +++ concat [ ["-X", prettyShow ex] | ex <- usedExtensions bi ] +++ cppOptions (libBuildInfo lib) +++ [ prettyShow modu | modu <- allLibModules lib clbi ]++++installLib+ :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^install location+ -> FilePath -- ^install location for dynamic libraries+ -> FilePath -- ^Build location+ -> PackageDescription+ -> Library+ -> ComponentLocalBuildInfo+ -> IO ()+installLib verbosity lbi targetDir dynlibTargetDir builtDir pkg lib clbi = do+ let progdb = withPrograms lbi+ runDbProgram verbosity haskellSuitePkgProgram progdb $+ [ "install-library"+ , "--build-dir", builtDir+ , "--target-dir", targetDir+ , "--dynlib-target-dir", dynlibTargetDir+ , "--package-id", prettyShow $ packageId pkg+ ] ++ map prettyShow (allLibModules lib clbi)++registerPackage+ :: Verbosity+ -> ProgramDb+ -> PackageDBStack+ -> InstalledPackageInfo+ -> IO ()+registerPackage verbosity progdb packageDbs installedPkgInfo = do+ (hspkg, _) <- requireProgram verbosity haskellSuitePkgProgram progdb++ runProgramInvocation verbosity $+ (programInvocation hspkg+ ["update", packageDbOpt $ registrationPackageDB packageDbs])+ { progInvokeInput = Just $ IODataText $ showInstalledPackageInfo installedPkgInfo }++initPackageDB :: Verbosity -> ProgramDb -> FilePath -> IO ()+initPackageDB verbosity progdb dbPath =+ runDbProgram verbosity haskellSuitePkgProgram progdb+ ["init", dbPath]++packageDbOpt :: PackageDB -> String+packageDbOpt GlobalPackageDB = "--global"+packageDbOpt UserPackageDB = "--user"+packageDbOpt (SpecificPackageDB db) = "--package-db=" ++ db
+ src/Distribution/Simple/Hpc.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Hpc+-- Copyright : Thomas Tuegel 2011+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides functions for locating various HPC-related paths and+-- a function for adding the necessary options to a PackageDescription to+-- build test suites with HPC enabled.++module Distribution.Simple.Hpc+ ( Way(..), guessWay+ , htmlDir+ , mixDir+ , tixDir+ , tixFilePath+ , markupPackage+ , markupTest+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.UnqualComponentName+import Distribution.ModuleName ( main )+import qualified Distribution.PackageDescription as PD+import Distribution.PackageDescription+ ( Library(..)+ , TestSuite(..)+ , testModules+ )+import Distribution.Pretty+import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..) )+import Distribution.Simple.Program+ ( hpcProgram+ , requireProgramVersion+ )+import Distribution.Simple.Program.Hpc ( markup, union )+import Distribution.Simple.Utils ( notice )+import Distribution.Version ( anyVersion )+import Distribution.Verbosity ( Verbosity() )+import System.Directory ( createDirectoryIfMissing, doesFileExist )+import System.FilePath++-- -------------------------------------------------------------------------+-- Haskell Program Coverage++data Way = Vanilla | Prof | Dyn+ deriving (Bounded, Enum, Eq, Read, Show)++hpcDir :: FilePath -- ^ \"dist/\" prefix+ -> Way+ -> FilePath -- ^ Directory containing component's HPC .mix files+hpcDir distPref way = distPref </> "hpc" </> wayDir+ where+ wayDir = case way of+ Vanilla -> "vanilla"+ Prof -> "prof"+ Dyn -> "dyn"++mixDir :: FilePath -- ^ \"dist/\" prefix+ -> Way+ -> FilePath -- ^ Component name+ -> FilePath -- ^ Directory containing test suite's .mix files+mixDir distPref way name = hpcDir distPref way </> "mix" </> name++tixDir :: FilePath -- ^ \"dist/\" prefix+ -> Way+ -> FilePath -- ^ Component name+ -> FilePath -- ^ Directory containing test suite's .tix files+tixDir distPref way name = hpcDir distPref way </> "tix" </> name++-- | Path to the .tix file containing a test suite's sum statistics.+tixFilePath :: FilePath -- ^ \"dist/\" prefix+ -> Way+ -> FilePath -- ^ Component name+ -> FilePath -- ^ Path to test suite's .tix file+tixFilePath distPref way name = tixDir distPref way name </> name <.> "tix"++htmlDir :: FilePath -- ^ \"dist/\" prefix+ -> Way+ -> FilePath -- ^ Component name+ -> FilePath -- ^ Path to test suite's HTML markup directory+htmlDir distPref way name = hpcDir distPref way </> "html" </> name++-- | Attempt to guess the way the test suites in this package were compiled+-- and linked with the library so the correct module interfaces are found.+guessWay :: LocalBuildInfo -> Way+guessWay lbi+ | withProfExe lbi = Prof+ | withDynExe lbi = Dyn+ | otherwise = Vanilla++-- | Generate the HTML markup for a test suite.+markupTest :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^ \"dist/\" prefix+ -> String -- ^ Library name+ -> TestSuite+ -> Library+ -> IO ()+markupTest verbosity lbi distPref libraryName suite library = do+ tixFileExists <- doesFileExist $ tixFilePath distPref way $ testName'+ when tixFileExists $ do+ -- behaviour of 'markup' depends on version, so we need *a* version+ -- but no particular one+ (hpc, hpcVer, _) <- requireProgramVersion verbosity+ hpcProgram anyVersion (withPrograms lbi)+ let htmlDir_ = htmlDir distPref way testName'+ markup hpc hpcVer verbosity+ (tixFilePath distPref way testName') mixDirs+ htmlDir_+ (exposedModules library)+ notice verbosity $ "Test coverage report written to "+ ++ htmlDir_ </> "hpc_index" <.> "html"+ where+ way = guessWay lbi+ testName' = unUnqualComponentName $ testName suite+ mixDirs = map (mixDir distPref way) [ testName', libraryName ]++-- | Generate the HTML markup for all of a package's test suites.+markupPackage :: Verbosity+ -> LocalBuildInfo+ -> FilePath -- ^ \"dist/\" prefix+ -> PD.PackageDescription+ -> [TestSuite]+ -> IO ()+markupPackage verbosity lbi distPref pkg_descr suites = do+ let tixFiles = map (tixFilePath distPref way) testNames+ tixFilesExist <- traverse doesFileExist tixFiles+ when (and tixFilesExist) $ do+ -- behaviour of 'markup' depends on version, so we need *a* version+ -- but no particular one+ (hpc, hpcVer, _) <- requireProgramVersion verbosity+ hpcProgram anyVersion (withPrograms lbi)+ let outFile = tixFilePath distPref way libraryName+ htmlDir' = htmlDir distPref way libraryName+ excluded = concatMap testModules suites ++ [ main ]+ createDirectoryIfMissing True $ takeDirectory outFile+ union hpc verbosity tixFiles outFile excluded+ markup hpc hpcVer verbosity outFile mixDirs htmlDir' included+ notice verbosity $ "Package coverage report written to "+ ++ htmlDir' </> "hpc_index.html"+ where+ way = guessWay lbi+ testNames = fmap (unUnqualComponentName . testName) suites+ mixDirs = map (mixDir distPref way) $ libraryName : testNames+ included = concatMap (exposedModules) $ PD.allLibraries pkg_descr+ libraryName = prettyShow $ PD.package pkg_descr
+ src/Distribution/Simple/Install.hs view
@@ -0,0 +1,260 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Install+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is the entry point into installing a built package. Performs the+-- \"@.\/setup install@\" and \"@.\/setup copy@\" actions. It moves files into+-- place based on the prefix argument. It does the generic bits and then calls+-- compiler-specific functions to do the rest.++module Distribution.Simple.Install (+ install,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.TargetInfo+import Distribution.Types.LocalBuildInfo+import Distribution.Types.ForeignLib+import Distribution.Types.PackageDescription+import Distribution.Types.UnqualComponentName+import Distribution.Types.ExecutableScope++import Distribution.Package+import Distribution.PackageDescription+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.BuildPaths (haddockName, haddockPref)+import Distribution.Simple.Glob (matchDirFileGlob)+import Distribution.Simple.Utils+ ( createDirectoryIfMissingVerbose+ , installDirectoryContents, installOrdinaryFile, isInSearchPath+ , die', info, noticeNoWrap, warn )+import Distribution.Simple.Compiler+ ( CompilerFlavor(..), compilerFlavor )+import Distribution.Simple.Setup+ ( CopyFlags(..), fromFlag, HaddockTarget(ForDevelopment) )+import Distribution.Simple.BuildTarget+import Distribution.Utils.Path (getSymbolicPath)++import qualified Distribution.Simple.GHC as GHC+import qualified Distribution.Simple.GHCJS as GHCJS+import qualified Distribution.Simple.UHC as UHC+import qualified Distribution.Simple.HaskellSuite as HaskellSuite+import Distribution.Compat.Graph (IsNode(..))++import System.Directory+ ( doesDirectoryExist, doesFileExist )+import System.FilePath+ ( takeFileName, takeDirectory, (</>), isRelative )++import Distribution.Verbosity+import Distribution.Pretty+ ( prettyShow )++-- |Perform the \"@.\/setup install@\" and \"@.\/setup copy@\"+-- actions. Move files into place based on the prefix argument.+--+-- This does NOT register libraries, you should call 'register'+-- to do that.++install :: PackageDescription -- ^information from the .cabal file+ -> LocalBuildInfo -- ^information from the configure step+ -> CopyFlags -- ^flags sent to copy or install+ -> IO ()+install pkg_descr lbi flags = do+ checkHasLibsOrExes+ targets <- readTargetInfos verbosity pkg_descr lbi (copyArgs flags)++ copyPackage verbosity pkg_descr lbi distPref copydest++ -- It's not necessary to do these in build-order, but it's harmless+ withNeededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets) $ \target ->+ let comp = targetComponent target+ clbi = targetCLBI target+ in copyComponent verbosity pkg_descr lbi comp clbi copydest+ where+ distPref = fromFlag (copyDistPref flags)+ verbosity = fromFlag (copyVerbosity flags)+ copydest = fromFlag (copyDest flags)++ checkHasLibsOrExes =+ unless (hasLibs pkg_descr || hasForeignLibs pkg_descr || hasExes pkg_descr) $+ die' verbosity "No executables and no library found. Nothing to do."++-- | Copy package global files.+copyPackage :: Verbosity -> PackageDescription+ -> LocalBuildInfo -> FilePath -> CopyDest -> IO ()+copyPackage verbosity pkg_descr lbi distPref copydest = do+ let -- This is a bit of a hack, to handle files which are not+ -- per-component (data files and Haddock files.)+ InstallDirs {+ datadir = dataPref,+ docdir = docPref,+ htmldir = htmlPref,+ haddockdir = interfacePref+ } = absoluteInstallCommandDirs pkg_descr lbi (localUnitId lbi) copydest++ -- Install (package-global) data files+ installDataFiles verbosity pkg_descr dataPref++ -- Install (package-global) Haddock files+ -- TODO: these should be done per-library+ docExists <- doesDirectoryExist $ haddockPref ForDevelopment distPref pkg_descr+ info verbosity ("directory " ++ haddockPref ForDevelopment distPref pkg_descr +++ " does exist: " ++ show docExists)++ -- TODO: this is a bit questionable, Haddock files really should+ -- be per library (when there are convenience libraries.)+ when docExists $ do+ createDirectoryIfMissingVerbose verbosity True htmlPref+ installDirectoryContents verbosity+ (haddockPref ForDevelopment distPref pkg_descr) htmlPref+ -- setPermissionsRecursive [Read] htmlPref+ -- The haddock interface file actually already got installed+ -- in the recursive copy, but now we install it where we actually+ -- want it to be (normally the same place). We could remove the+ -- copy in htmlPref first.+ let haddockInterfaceFileSrc = haddockPref ForDevelopment distPref pkg_descr+ </> haddockName pkg_descr+ haddockInterfaceFileDest = interfacePref </> haddockName pkg_descr+ -- We only generate the haddock interface file for libs, So if the+ -- package consists only of executables there will not be one:+ exists <- doesFileExist haddockInterfaceFileSrc+ when exists $ do+ createDirectoryIfMissingVerbose verbosity True interfacePref+ installOrdinaryFile verbosity haddockInterfaceFileSrc+ haddockInterfaceFileDest++ let lfiles = licenseFiles pkg_descr+ unless (null lfiles) $ do+ createDirectoryIfMissingVerbose verbosity True docPref+ for_ lfiles $ \lfile' -> do+ let lfile :: FilePath+ lfile = getSymbolicPath lfile'+ installOrdinaryFile verbosity lfile (docPref </> takeFileName lfile)++-- | Copy files associated with a component.+copyComponent :: Verbosity -> PackageDescription+ -> LocalBuildInfo -> Component -> ComponentLocalBuildInfo+ -> CopyDest+ -> IO ()+copyComponent verbosity pkg_descr lbi (CLib lib) clbi copydest = do+ let InstallDirs{+ libdir = libPref,+ dynlibdir = dynlibPref,+ includedir = incPref+ } = absoluteInstallCommandDirs pkg_descr lbi (componentUnitId clbi) copydest+ buildPref = componentBuildDir lbi clbi++ case libName lib of+ LMainLibName -> noticeNoWrap verbosity ("Installing library in " ++ libPref)+ LSubLibName n -> noticeNoWrap verbosity ("Installing internal library " ++ prettyShow n ++ " in " ++ libPref)++ -- install include files for all compilers - they may be needed to compile+ -- haskell files (using the CPP extension)+ installIncludeFiles verbosity (libBuildInfo lib) lbi buildPref incPref++ case compilerFlavor (compiler lbi) of+ GHC -> GHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi+ GHCJS -> GHCJS.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi+ UHC -> UHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi+ HaskellSuite _ -> HaskellSuite.installLib+ verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi+ _ -> die' verbosity $ "installing with "+ ++ prettyShow (compilerFlavor (compiler lbi))+ ++ " is not implemented"++copyComponent verbosity pkg_descr lbi (CFLib flib) clbi copydest = do+ let InstallDirs{+ flibdir = flibPref,+ includedir = incPref+ } = absoluteComponentInstallDirs pkg_descr lbi (componentUnitId clbi) copydest+ buildPref = componentBuildDir lbi clbi++ noticeNoWrap verbosity ("Installing foreign library " ++ unUnqualComponentName (foreignLibName flib) ++ " in " ++ flibPref)+ installIncludeFiles verbosity (foreignLibBuildInfo flib) lbi buildPref incPref++ case compilerFlavor (compiler lbi) of+ GHC -> GHC.installFLib verbosity lbi flibPref buildPref pkg_descr flib+ GHCJS -> GHCJS.installFLib verbosity lbi flibPref buildPref pkg_descr flib+ _ -> die' verbosity $ "installing foreign lib with "+ ++ prettyShow (compilerFlavor (compiler lbi))+ ++ " is not implemented"++copyComponent verbosity pkg_descr lbi (CExe exe) clbi copydest = do+ let installDirs = absoluteComponentInstallDirs pkg_descr lbi (componentUnitId clbi) copydest+ -- the installers know how to find the actual location of the+ -- binaries+ buildPref = buildDir lbi+ uid = componentUnitId clbi+ pkgid = packageId pkg_descr+ binPref | ExecutablePrivate <- exeScope exe = libexecdir installDirs+ | otherwise = bindir installDirs+ progPrefixPref = substPathTemplate pkgid lbi uid (progPrefix lbi)+ progSuffixPref = substPathTemplate pkgid lbi uid (progSuffix lbi)+ progFix = (progPrefixPref, progSuffixPref)+ noticeNoWrap verbosity ("Installing executable " ++ prettyShow (exeName exe)+ ++ " in " ++ binPref)+ inPath <- isInSearchPath binPref+ when (not inPath) $+ warn verbosity ("The directory " ++ binPref+ ++ " is not in the system search path.")+ case compilerFlavor (compiler lbi) of+ GHC -> GHC.installExe verbosity lbi binPref buildPref progFix pkg_descr exe+ GHCJS -> GHCJS.installExe verbosity lbi binPref buildPref progFix pkg_descr exe+ UHC -> return ()+ HaskellSuite {} -> return ()+ _ -> die' verbosity $ "installing with "+ ++ prettyShow (compilerFlavor (compiler lbi))+ ++ " is not implemented"++-- Nothing to do for benchmark/testsuite+copyComponent _ _ _ (CBench _) _ _ = return ()+copyComponent _ _ _ (CTest _) _ _ = return ()++-- | Install the files listed in data-files+--+installDataFiles :: Verbosity -> PackageDescription -> FilePath -> IO ()+installDataFiles verbosity pkg_descr destDataDir =+ flip traverse_ (dataFiles pkg_descr) $ \ glob -> do+ let srcDataDirRaw = dataDir pkg_descr+ srcDataDir = if null srcDataDirRaw+ then "."+ else srcDataDirRaw+ files <- matchDirFileGlob verbosity (specVersion pkg_descr) srcDataDir glob+ for_ files $ \ file' -> do+ let src = srcDataDir </> file'+ dst = destDataDir </> file'+ createDirectoryIfMissingVerbose verbosity True (takeDirectory dst)+ installOrdinaryFile verbosity src dst++-- | Install the files listed in install-includes for a library+--+installIncludeFiles :: Verbosity -> BuildInfo -> LocalBuildInfo -> FilePath -> FilePath -> IO ()+installIncludeFiles verbosity libBi lbi buildPref destIncludeDir = do+ let relincdirs = "." : filter isRelative (includeDirs libBi)+ incdirs = [ baseDir lbi </> dir | dir <- relincdirs ]+ ++ [ buildPref </> dir | dir <- relincdirs ]+ incs <- traverse (findInc incdirs) (installIncludes libBi)+ sequence_+ [ do createDirectoryIfMissingVerbose verbosity True destDir+ installOrdinaryFile verbosity srcFile destFile+ | (relFile, srcFile) <- incs+ , let destFile = destIncludeDir </> relFile+ destDir = takeDirectory destFile ]+ where+ baseDir lbi' = fromMaybe "" (takeDirectory <$> cabalFilePath lbi')+ findInc [] file = die' verbosity ("can't find include file " ++ file)+ findInc (dir:dirs) file = do+ let path = dir </> file+ exists <- doesFileExist path+ if exists then return (file, path) else findInc dirs file
+ src/Distribution/Simple/InstallDirs.hs view
@@ -0,0 +1,506 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.InstallDirs+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This manages everything to do with where files get installed (though does+-- not get involved with actually doing any installation). It provides an+-- 'InstallDirs' type which is a set of directories for where to install+-- things. It also handles the fact that we use templates in these install+-- dirs. For example most install dirs are relative to some @$prefix@ and by+-- changing the prefix all other dirs still end up changed appropriately. So it+-- provides a 'PathTemplate' type and functions for substituting for these+-- templates.++module Distribution.Simple.InstallDirs (+ InstallDirs(..),+ InstallDirTemplates,+ defaultInstallDirs,+ defaultInstallDirs',+ combineInstallDirs,+ absoluteInstallDirs,+ CopyDest(..),+ prefixRelativeInstallDirs,+ substituteInstallDirTemplates,++ PathTemplate,+ PathTemplateVariable(..),+ PathTemplateEnv,+ toPathTemplate,+ fromPathTemplate,+ combinePathTemplate,+ substPathTemplate,+ initialPathTemplateEnv,+ platformTemplateEnv,+ compilerTemplateEnv,+ packageTemplateEnv,+ abiTemplateEnv,+ installDirsTemplateEnv,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Compat.Environment (lookupEnv)+import Distribution.Pretty+import Distribution.Package+import Distribution.System+import Distribution.Compiler+import Distribution.Simple.InstallDirs.Internal++import System.Directory (getAppUserDataDirectory)+import System.FilePath+ ( (</>), isPathSeparator+ , pathSeparator, dropDrive+ , takeDirectory )++#ifdef mingw32_HOST_OS+import qualified Prelude+import Foreign+import Foreign.C+#endif++-- ---------------------------------------------------------------------------+-- Installation directories+++-- | The directories where we will install files for packages.+--+-- We have several different directories for different types of files since+-- many systems have conventions whereby different types of files in a package+-- are installed in different directories. This is particularly the case on+-- Unix style systems.+--+data InstallDirs dir = InstallDirs {+ prefix :: dir,+ bindir :: dir,+ libdir :: dir,+ libsubdir :: dir,+ dynlibdir :: dir,+ flibdir :: dir, -- ^ foreign libraries+ libexecdir :: dir,+ libexecsubdir:: dir,+ includedir :: dir,+ datadir :: dir,+ datasubdir :: dir,+ docdir :: dir,+ mandir :: dir,+ htmldir :: dir,+ haddockdir :: dir,+ sysconfdir :: dir+ } deriving (Eq, Read, Show, Functor, Generic, Typeable)++instance Binary dir => Binary (InstallDirs dir)+instance Structured dir => Structured (InstallDirs dir)++instance (Semigroup dir, Monoid dir) => Monoid (InstallDirs dir) where+ mempty = gmempty+ mappend = (<>)++instance Semigroup dir => Semigroup (InstallDirs dir) where+ (<>) = gmappend++combineInstallDirs :: (a -> b -> c)+ -> InstallDirs a+ -> InstallDirs b+ -> InstallDirs c+combineInstallDirs combine a b = InstallDirs {+ prefix = prefix a `combine` prefix b,+ bindir = bindir a `combine` bindir b,+ libdir = libdir a `combine` libdir b,+ libsubdir = libsubdir a `combine` libsubdir b,+ dynlibdir = dynlibdir a `combine` dynlibdir b,+ flibdir = flibdir a `combine` flibdir b,+ libexecdir = libexecdir a `combine` libexecdir b,+ libexecsubdir= libexecsubdir a `combine` libexecsubdir b,+ includedir = includedir a `combine` includedir b,+ datadir = datadir a `combine` datadir b,+ datasubdir = datasubdir a `combine` datasubdir b,+ docdir = docdir a `combine` docdir b,+ mandir = mandir a `combine` mandir b,+ htmldir = htmldir a `combine` htmldir b,+ haddockdir = haddockdir a `combine` haddockdir b,+ sysconfdir = sysconfdir a `combine` sysconfdir b+ }++appendSubdirs :: (a -> a -> a) -> InstallDirs a -> InstallDirs a+appendSubdirs append dirs = dirs {+ libdir = libdir dirs `append` libsubdir dirs,+ libexecdir = libexecdir dirs `append` libexecsubdir dirs,+ datadir = datadir dirs `append` datasubdir dirs,+ libsubdir = error "internal error InstallDirs.libsubdir",+ libexecsubdir = error "internal error InstallDirs.libexecsubdir",+ datasubdir = error "internal error InstallDirs.datasubdir"+ }++-- | The installation directories in terms of 'PathTemplate's that contain+-- variables.+--+-- The defaults for most of the directories are relative to each other, in+-- particular they are all relative to a single prefix. This makes it+-- convenient for the user to override the default installation directory+-- by only having to specify --prefix=... rather than overriding each+-- individually. This is done by allowing $-style variables in the dirs.+-- These are expanded by textual substitution (see 'substPathTemplate').+--+-- A few of these installation directories are split into two components, the+-- dir and subdir. The full installation path is formed by combining the two+-- together with @\/@. The reason for this is compatibility with other Unix+-- build systems which also support @--libdir@ and @--datadir@. We would like+-- users to be able to configure @--libdir=\/usr\/lib64@ for example but+-- because by default we want to support installing multiple versions of+-- packages and building the same package for multiple compilers we append the+-- libsubdir to get: @\/usr\/lib64\/$libname\/$compiler@.+--+-- An additional complication is the need to support relocatable packages on+-- systems which support such things, like Windows.+--+type InstallDirTemplates = InstallDirs PathTemplate++-- ---------------------------------------------------------------------------+-- Default installation directories++defaultInstallDirs :: CompilerFlavor -> Bool -> Bool -> IO InstallDirTemplates+defaultInstallDirs = defaultInstallDirs' False++defaultInstallDirs' :: Bool {- use external internal deps -}+ -> CompilerFlavor -> Bool -> Bool -> IO InstallDirTemplates+defaultInstallDirs' True comp userInstall hasLibs = do+ dflt <- defaultInstallDirs' False comp userInstall hasLibs+ -- Be a bit more hermetic about per-component installs+ return dflt { datasubdir = toPathTemplate $ "$abi" </> "$libname",+ docdir = toPathTemplate $ "$datadir" </> "doc" </> "$abi" </> "$libname"+ }+defaultInstallDirs' False comp userInstall _hasLibs = do+ installPrefix <-+ if userInstall+ then do+ mDir <- lookupEnv "CABAL_DIR"+ case mDir of+ Nothing -> getAppUserDataDirectory "cabal"+ Just dir -> return dir+ else case buildOS of+ Windows -> do windowsProgramFilesDir <- getWindowsProgramFilesDir+ return (windowsProgramFilesDir </> "Haskell")+ _ -> return "/usr/local"+ installLibDir <-+ case buildOS of+ Windows -> return "$prefix"+ _ -> return ("$prefix" </> "lib")+ return $ fmap toPathTemplate $ InstallDirs {+ prefix = installPrefix,+ bindir = "$prefix" </> "bin",+ libdir = installLibDir,+ libsubdir = case comp of+ UHC -> "$pkgid"+ _other -> "$abi" </> "$libname",+ dynlibdir = "$libdir" </> case comp of+ UHC -> "$pkgid"+ _other -> "$abi",+ libexecsubdir= "$abi" </> "$pkgid",+ flibdir = "$libdir",+ libexecdir = case buildOS of+ Windows -> "$prefix" </> "$libname"+ _other -> "$prefix" </> "libexec",+ includedir = "$libdir" </> "$libsubdir" </> "include",+ datadir = case buildOS of+ Windows -> "$prefix"+ _other -> "$prefix" </> "share",+ datasubdir = "$abi" </> "$pkgid",+ docdir = "$datadir" </> "doc" </> "$abi" </> "$pkgid",+ mandir = "$datadir" </> "man",+ htmldir = "$docdir" </> "html",+ haddockdir = "$htmldir",+ sysconfdir = "$prefix" </> "etc"+ }++-- ---------------------------------------------------------------------------+-- Converting directories, absolute or prefix-relative++-- | Substitute the install dir templates into each other.+--+-- To prevent cyclic substitutions, only some variables are allowed in+-- particular dir templates. If out of scope vars are present, they are not+-- substituted for. Checking for any remaining unsubstituted vars can be done+-- as a subsequent operation.+--+-- The reason it is done this way is so that in 'prefixRelativeInstallDirs' we+-- can replace 'prefix' with the 'PrefixVar' and get resulting+-- 'PathTemplate's that still have the 'PrefixVar' in them. Doing this makes it+-- each to check which paths are relative to the $prefix.+--+substituteInstallDirTemplates :: PathTemplateEnv+ -> InstallDirTemplates -> InstallDirTemplates+substituteInstallDirTemplates env dirs = dirs'+ where+ dirs' = InstallDirs {+ -- So this specifies exactly which vars are allowed in each template+ prefix = subst prefix [],+ bindir = subst bindir [prefixVar],+ libdir = subst libdir [prefixVar, bindirVar],+ libsubdir = subst libsubdir [],+ dynlibdir = subst dynlibdir [prefixVar, bindirVar, libdirVar],+ flibdir = subst flibdir [prefixVar, bindirVar, libdirVar],+ libexecdir = subst libexecdir prefixBinLibVars,+ libexecsubdir = subst libexecsubdir [],+ includedir = subst includedir prefixBinLibVars,+ datadir = subst datadir prefixBinLibVars,+ datasubdir = subst datasubdir [],+ docdir = subst docdir prefixBinLibDataVars,+ mandir = subst mandir (prefixBinLibDataVars ++ [docdirVar]),+ htmldir = subst htmldir (prefixBinLibDataVars ++ [docdirVar]),+ haddockdir = subst haddockdir (prefixBinLibDataVars +++ [docdirVar, htmldirVar]),+ sysconfdir = subst sysconfdir prefixBinLibVars+ }+ subst dir env' = substPathTemplate (env'++env) (dir dirs)++ prefixVar = (PrefixVar, prefix dirs')+ bindirVar = (BindirVar, bindir dirs')+ libdirVar = (LibdirVar, libdir dirs')+ libsubdirVar = (LibsubdirVar, libsubdir dirs')+ datadirVar = (DatadirVar, datadir dirs')+ datasubdirVar = (DatasubdirVar, datasubdir dirs')+ docdirVar = (DocdirVar, docdir dirs')+ htmldirVar = (HtmldirVar, htmldir dirs')+ prefixBinLibVars = [prefixVar, bindirVar, libdirVar, libsubdirVar]+ prefixBinLibDataVars = prefixBinLibVars ++ [datadirVar, datasubdirVar]++-- | Convert from abstract install directories to actual absolute ones by+-- substituting for all the variables in the abstract paths, to get real+-- absolute path.+absoluteInstallDirs :: PackageIdentifier+ -> UnitId+ -> CompilerInfo+ -> CopyDest+ -> Platform+ -> InstallDirs PathTemplate+ -> InstallDirs FilePath+absoluteInstallDirs pkgId libname compilerId copydest platform dirs =+ (case copydest of+ CopyTo destdir -> fmap ((destdir </>) . dropDrive)+ CopyToDb dbdir -> fmap (substPrefix "${pkgroot}" (takeDirectory dbdir))+ _ -> id)+ . appendSubdirs (</>)+ . fmap fromPathTemplate+ $ substituteInstallDirTemplates env dirs+ where+ env = initialPathTemplateEnv pkgId libname compilerId platform+ substPrefix pre root path+ | pre `isPrefixOf` path = root ++ drop (length pre) path+ | otherwise = path+++-- |The location prefix for the /copy/ command.+data CopyDest+ = NoCopyDest+ | CopyTo FilePath+ | CopyToDb FilePath+ -- ^ when using the ${pkgroot} as prefix. The CopyToDb will+ -- adjust the paths to be relative to the provided package+ -- database when copying / installing.+ deriving (Eq, Show, Generic)++instance Binary CopyDest++-- | Check which of the paths are relative to the installation $prefix.+--+-- If any of the paths are not relative, ie they are absolute paths, then it+-- prevents us from making a relocatable package (also known as a \"prefix+-- independent\" package).+--+prefixRelativeInstallDirs :: PackageIdentifier+ -> UnitId+ -> CompilerInfo+ -> Platform+ -> InstallDirTemplates+ -> InstallDirs (Maybe FilePath)+prefixRelativeInstallDirs pkgId libname compilerId platform dirs =+ fmap relative+ . appendSubdirs combinePathTemplate+ $ -- substitute the path template into each other, except that we map+ -- \$prefix back to $prefix. We're trying to end up with templates that+ -- mention no vars except $prefix.+ substituteInstallDirTemplates env dirs {+ prefix = PathTemplate [Variable PrefixVar]+ }+ where+ 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+ relative dir = case dir of+ PathTemplate cs -> fmap (fromPathTemplate . PathTemplate) (relative' cs)+ relative' (Variable PrefixVar : Ordinary (s:rest) : rest')+ | isPathSeparator s = Just (Ordinary rest : rest')+ relative' (Variable PrefixVar : rest) = Just rest+ relative' _ = Nothing++-- ---------------------------------------------------------------------------+-- Path templates++-- | An abstract path, possibly containing variables that need to be+-- substituted for to get a real 'FilePath'.+--+newtype PathTemplate = PathTemplate [PathComponent]+ deriving (Eq, Ord, Generic, Typeable)++instance Binary PathTemplate+instance Structured PathTemplate++type PathTemplateEnv = [(PathTemplateVariable, PathTemplate)]++-- | Convert a 'FilePath' to a 'PathTemplate' including any template vars.+--+toPathTemplate :: FilePath -> PathTemplate+toPathTemplate fp = PathTemplate+ . fromMaybe (error $ "panic! toPathTemplate " ++ show fp)+ . readMaybe -- TODO: eradicateNoParse+ $ fp++-- | Convert back to a path, any remaining vars are included+--+fromPathTemplate :: PathTemplate -> FilePath+fromPathTemplate (PathTemplate template) = show template++combinePathTemplate :: PathTemplate -> PathTemplate -> PathTemplate+combinePathTemplate (PathTemplate t1) (PathTemplate t2) =+ PathTemplate (t1 ++ [Ordinary [pathSeparator]] ++ t2)++substPathTemplate :: PathTemplateEnv -> PathTemplate -> PathTemplate+substPathTemplate environment (PathTemplate template) =+ PathTemplate (concatMap subst template)++ where subst component@(Ordinary _) = [component]+ subst component@(Variable variable) =+ case lookup variable environment of+ Just (PathTemplate components) -> components+ Nothing -> [component]++-- | The initial environment has all the static stuff but no paths+initialPathTemplateEnv :: PackageIdentifier+ -> UnitId+ -> CompilerInfo+ -> Platform+ -> PathTemplateEnv+initialPathTemplateEnv pkgId libname compiler platform =+ packageTemplateEnv pkgId libname+ ++ compilerTemplateEnv compiler+ ++ platformTemplateEnv platform+ ++ abiTemplateEnv compiler platform++packageTemplateEnv :: PackageIdentifier -> UnitId -> PathTemplateEnv+packageTemplateEnv pkgId uid =+ [(PkgNameVar, PathTemplate [Ordinary $ prettyShow (packageName pkgId)])+ ,(PkgVerVar, PathTemplate [Ordinary $ prettyShow (packageVersion pkgId)])+ -- Invariant: uid is actually a HashedUnitId. Hard to enforce because+ -- it's an API change.+ ,(LibNameVar, PathTemplate [Ordinary $ prettyShow uid])+ ,(PkgIdVar, PathTemplate [Ordinary $ prettyShow pkgId])+ ]++compilerTemplateEnv :: CompilerInfo -> PathTemplateEnv+compilerTemplateEnv compiler =+ [(CompilerVar, PathTemplate [Ordinary $ prettyShow (compilerInfoId compiler)])+ ]++platformTemplateEnv :: Platform -> PathTemplateEnv+platformTemplateEnv (Platform arch os) =+ [(OSVar, PathTemplate [Ordinary $ prettyShow os])+ ,(ArchVar, PathTemplate [Ordinary $ prettyShow arch])+ ]++abiTemplateEnv :: CompilerInfo -> Platform -> PathTemplateEnv+abiTemplateEnv compiler (Platform arch os) =+ [(AbiVar, PathTemplate [Ordinary $ prettyShow arch ++ '-':prettyShow os +++ '-':prettyShow (compilerInfoId compiler) +++ case compilerInfoAbiTag compiler of+ NoAbiTag -> ""+ AbiTag tag -> '-':tag])+ ,(AbiTagVar, PathTemplate [Ordinary $ abiTagString (compilerInfoAbiTag compiler)])+ ]++installDirsTemplateEnv :: InstallDirs PathTemplate -> PathTemplateEnv+installDirsTemplateEnv dirs =+ [(PrefixVar, prefix dirs)+ ,(BindirVar, bindir dirs)+ ,(LibdirVar, libdir dirs)+ ,(LibsubdirVar, libsubdir dirs)+ ,(DynlibdirVar, dynlibdir dirs)+ ,(DatadirVar, datadir dirs)+ ,(DatasubdirVar, datasubdir dirs)+ ,(DocdirVar, docdir dirs)+ ,(HtmldirVar, htmldir dirs)+ ]+++-- ---------------------------------------------------------------------------+-- Parsing and showing path templates:++-- The textual format is that of an ordinary Haskell String, eg+-- "$prefix/bin"+-- and this gets parsed to the internal representation as a sequence of path+-- spans which are either strings or variables, eg:+-- PathTemplate [Variable PrefixVar, Ordinary "/bin" ]++instance Show PathTemplate where+ show (PathTemplate template) = show (show template)++instance Read PathTemplate where+ readsPrec p s = [ (PathTemplate template, s')+ | (path, s') <- readsPrec p s+ , (template, "") <- reads path ]++-- ---------------------------------------------------------------------------+-- Internal utilities++getWindowsProgramFilesDir :: IO FilePath+getWindowsProgramFilesDir = do+#ifdef mingw32_HOST_OS+ m <- shGetFolderPath csidl_PROGRAM_FILES+#else+ let m = Nothing+#endif+ return (fromMaybe "C:\\Program Files" m)++#ifdef mingw32_HOST_OS+shGetFolderPath :: CInt -> IO (Maybe FilePath)+shGetFolderPath n =+ allocaArray long_path_size $ \pPath -> do+ r <- c_SHGetFolderPath nullPtr n nullPtr 0 pPath+ if (r /= 0)+ then return Nothing+ else do s <- peekCWString pPath; return (Just s)+ where+ long_path_size = 1024 -- MAX_PATH is 260, this should be plenty++csidl_PROGRAM_FILES :: CInt+csidl_PROGRAM_FILES = 0x0026+-- csidl_PROGRAM_FILES_COMMON :: CInt+-- csidl_PROGRAM_FILES_COMMON = 0x002b++#ifdef x86_64_HOST_ARCH+#define CALLCONV ccall+#else+#define CALLCONV stdcall+#endif++foreign import CALLCONV unsafe "shlobj.h SHGetFolderPathW"+ c_SHGetFolderPath :: Ptr ()+ -> CInt+ -> Ptr ()+ -> CInt+ -> CWString+ -> Prelude.IO CInt+#endif
+ src/Distribution/Simple/InstallDirs/Internal.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Simple.InstallDirs.Internal+ ( PathComponent(..)+ , PathTemplateVariable(..)+ ) where++import Prelude ()+import Distribution.Compat.Prelude++data PathComponent =+ Ordinary FilePath+ | Variable PathTemplateVariable+ deriving (Eq, Ord, Generic, Typeable)++instance Binary PathComponent+instance Structured PathComponent++data PathTemplateVariable =+ PrefixVar -- ^ The @$prefix@ path variable+ | BindirVar -- ^ The @$bindir@ path variable+ | LibdirVar -- ^ The @$libdir@ path variable+ | LibsubdirVar -- ^ The @$libsubdir@ path variable+ | DynlibdirVar -- ^ The @$dynlibdir@ path variable+ | DatadirVar -- ^ The @$datadir@ path variable+ | DatasubdirVar -- ^ The @$datasubdir@ path variable+ | DocdirVar -- ^ The @$docdir@ path variable+ | HtmldirVar -- ^ The @$htmldir@ path variable+ | 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@+ | 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@+ | AbiVar -- ^ The compiler's ABI identifier,+ --- $arch-$os-$compiler-$abitag+ | AbiTagVar -- ^ The optional ABI tag for the compiler+ | ExecutableNameVar -- ^ The executable name; used in shell wrappers+ | TestSuiteNameVar -- ^ The name of the test suite being run+ | TestSuiteResultVar -- ^ The result of the test suite being run, eg+ -- @pass@, @fail@, or @error@.+ | BenchmarkNameVar -- ^ The name of the benchmark being run+ deriving (Eq, Ord, Generic, Typeable)++instance Binary PathTemplateVariable+instance Structured PathTemplateVariable++instance Show PathTemplateVariable where+ show PrefixVar = "prefix"+ show LibNameVar = "libname"+ show BindirVar = "bindir"+ show LibdirVar = "libdir"+ show LibsubdirVar = "libsubdir"+ show DynlibdirVar = "dynlibdir"+ show DatadirVar = "datadir"+ show DatasubdirVar = "datasubdir"+ show DocdirVar = "docdir"+ show HtmldirVar = "htmldir"+ show PkgNameVar = "pkg"+ show PkgVerVar = "version"+ show PkgIdVar = "pkgid"+ show CompilerVar = "compiler"+ show OSVar = "os"+ show ArchVar = "arch"+ show AbiTagVar = "abitag"+ show AbiVar = "abi"+ show ExecutableNameVar = "executablename"+ show TestSuiteNameVar = "test-suite"+ show TestSuiteResultVar = "result"+ show BenchmarkNameVar = "benchmark"++instance Read PathTemplateVariable where+ readsPrec _ s =+ take 1+ [ (var, drop (length varStr) s)+ | (varStr, var) <- vars+ , varStr `isPrefixOf` s ]+ -- NB: order matters! Longer strings first+ where vars = [("prefix", PrefixVar)+ ,("bindir", BindirVar)+ ,("libdir", LibdirVar)+ ,("libsubdir", LibsubdirVar)+ ,("dynlibdir", DynlibdirVar)+ ,("datadir", DatadirVar)+ ,("datasubdir", DatasubdirVar)+ ,("docdir", DocdirVar)+ ,("htmldir", HtmldirVar)+ ,("pkgid", PkgIdVar)+ ,("libname", LibNameVar)+ ,("pkgkey", LibNameVar) -- backwards compatibility+ ,("pkg", PkgNameVar)+ ,("version", PkgVerVar)+ ,("compiler", CompilerVar)+ ,("os", OSVar)+ ,("arch", ArchVar)+ ,("abitag", AbiTagVar)+ ,("abi", AbiVar)+ ,("executablename", ExecutableNameVar)+ ,("test-suite", TestSuiteNameVar)+ ,("result", TestSuiteResultVar)+ ,("benchmark", BenchmarkNameVar)]++instance Show PathComponent where+ show (Ordinary path) = path+ show (Variable var) = '$':show var+ showList = foldr (\x -> (shows x .)) id++instance Read PathComponent where+ -- for some reason we collapse multiple $ symbols here+ readsPrec _ = lex0+ where lex0 [] = []+ lex0 ('$':'$':s') = lex0 ('$':s')+ lex0 ('$':s') = case [ (Variable var, s'')+ | (var, s'') <- reads s' ] of+ [] -> lex1 "$" s'+ ok -> ok+ lex0 s' = lex1 [] s'+ lex1 "" "" = []+ lex1 acc "" = [(Ordinary (reverse acc), "")]+ lex1 acc ('$':'$':s) = lex1 acc ('$':s)+ lex1 acc ('$':s) = [(Ordinary (reverse acc), '$':s)]+ lex1 acc (c:s) = lex1 (c:acc) s+ readList [] = [([],"")]+ readList s = [ (component:components, s'')+ | (component, s') <- reads s+ , (components, s'') <- readList s' ]
+ src/Distribution/Simple/LocalBuildInfo.hs view
@@ -0,0 +1,365 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.LocalBuildInfo+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Once a package has been configured we have resolved conditionals and+-- dependencies, configured the compiler and other needed external programs.+-- The 'LocalBuildInfo' is used to hold all this information. It holds the+-- install dirs, the compiler, the exact package dependencies, the configured+-- programs, the package database to use and a bunch of miscellaneous configure+-- flags. It gets saved and reloaded from a file (@dist\/setup-config@). It gets+-- passed in to very many subsequent build actions.++module Distribution.Simple.LocalBuildInfo (+ LocalBuildInfo(..),+ localComponentId,+ localUnitId,+ localCompatPackageKey,++ -- * Buildable package components+ Component(..),+ ComponentName(..),+ LibraryName(..),+ defaultLibName,+ showComponentName,+ componentNameString,+ ComponentLocalBuildInfo(..),+ componentBuildDir,+ foldComponent,+ componentName,+ componentBuildInfo,+ componentBuildable,+ pkgComponents,+ pkgBuildableComponents,+ lookupComponent,+ getComponent,+ allComponentsInBuildOrder,+ depLibraryPaths,+ allLibModules,++ withAllComponentsInBuildOrder,+ withLibLBI,+ withExeLBI,+ withBenchLBI,+ withTestLBI,+ enabledTestLBIs,+ enabledBenchLBIs,++ -- * Installation directories+ module Distribution.Simple.InstallDirs,+ absoluteInstallDirs, prefixRelativeInstallDirs,+ absoluteInstallCommandDirs,+ absoluteComponentInstallDirs, prefixRelativeComponentInstallDirs,+ substPathTemplate,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.Component+import Distribution.Types.PackageId+import Distribution.Types.UnitId+import Distribution.Types.ComponentName+import Distribution.Types.UnqualComponentName+import Distribution.Types.PackageDescription+import Distribution.Types.ComponentLocalBuildInfo+import Distribution.Types.LocalBuildInfo+import Distribution.Types.TargetInfo++import Distribution.Simple.InstallDirs hiding (absoluteInstallDirs,+ prefixRelativeInstallDirs,+ substPathTemplate, )+import qualified Distribution.Simple.InstallDirs as InstallDirs+import Distribution.PackageDescription+import qualified Distribution.InstalledPackageInfo as Installed+import Distribution.Package+import Distribution.ModuleName+import Distribution.Simple.Compiler+import Distribution.Simple.PackageIndex+import Distribution.Simple.Utils+import Distribution.Pretty+import qualified Distribution.Compat.Graph as Graph++import Data.List (stripPrefix)+import System.FilePath++import System.Directory (doesDirectoryExist, canonicalizePath)++-- -----------------------------------------------------------------------------+-- Configuration information of buildable components++componentBuildDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath+-- For now, we assume that libraries/executables/test-suites/benchmarks+-- are only ever built once. With Backpack, we need a special case for+-- libraries so that we can handle building them multiple times.+componentBuildDir lbi clbi+ = buildDir lbi </>+ case componentLocalName clbi of+ CLibName LMainLibName ->+ if prettyShow (componentUnitId clbi) == prettyShow (componentComponentId clbi)+ then ""+ else prettyShow (componentUnitId clbi)+ CLibName (LSubLibName s) ->+ if prettyShow (componentUnitId clbi) == prettyShow (componentComponentId clbi)+ then unUnqualComponentName s+ else prettyShow (componentUnitId clbi)+ CFLibName s -> unUnqualComponentName s+ CExeName s -> unUnqualComponentName s+ CTestName s -> unUnqualComponentName s+ CBenchName s -> unUnqualComponentName s++-- | Perform the action on each enabled 'library' in the package+-- description with the 'ComponentLocalBuildInfo'.+withLibLBI :: PackageDescription -> LocalBuildInfo+ -> (Library -> ComponentLocalBuildInfo -> IO ()) -> IO ()+withLibLBI pkg lbi f =+ withAllTargetsInBuildOrder' pkg lbi $ \target ->+ case targetComponent target of+ CLib lib -> f lib (targetCLBI target)+ _ -> return ()++-- | Perform the action on each enabled 'Executable' in the package+-- description. Extended version of 'withExe' that also gives corresponding+-- build info.+withExeLBI :: PackageDescription -> LocalBuildInfo+ -> (Executable -> ComponentLocalBuildInfo -> IO ()) -> IO ()+withExeLBI pkg lbi f =+ withAllTargetsInBuildOrder' pkg lbi $ \target ->+ case targetComponent target of+ CExe exe -> f exe (targetCLBI target)+ _ -> return ()++-- | Perform the action on each enabled 'Benchmark' in the package+-- description.+withBenchLBI :: PackageDescription -> LocalBuildInfo+ -> (Benchmark -> ComponentLocalBuildInfo -> IO ()) -> IO ()+withBenchLBI pkg lbi f =+ sequence_ [ f bench clbi | (bench, clbi) <- enabledBenchLBIs pkg lbi ]++withTestLBI :: PackageDescription -> LocalBuildInfo+ -> (TestSuite -> ComponentLocalBuildInfo -> IO ()) -> IO ()+withTestLBI pkg lbi f =+ sequence_ [ f test clbi | (test, clbi) <- enabledTestLBIs pkg lbi ]++enabledTestLBIs :: PackageDescription -> LocalBuildInfo+ -> [(TestSuite, ComponentLocalBuildInfo)]+enabledTestLBIs pkg lbi =+ [ (test, targetCLBI target)+ | target <- allTargetsInBuildOrder' pkg lbi+ , CTest test <- [targetComponent target] ]++enabledBenchLBIs :: PackageDescription -> LocalBuildInfo+ -> [(Benchmark, ComponentLocalBuildInfo)]+enabledBenchLBIs pkg lbi =+ [ (bench, targetCLBI target)+ | target <- allTargetsInBuildOrder' pkg lbi+ , CBench bench <- [targetComponent target] ]++-- | Perform the action on each buildable 'Library' or 'Executable' (Component)+-- in the PackageDescription, subject to the build order specified by the+-- 'compBuildOrder' field of the given 'LocalBuildInfo'+withAllComponentsInBuildOrder :: PackageDescription -> LocalBuildInfo+ -> (Component -> ComponentLocalBuildInfo -> IO ())+ -> IO ()+withAllComponentsInBuildOrder pkg lbi f =+ withAllTargetsInBuildOrder' pkg lbi $ \target ->+ f (targetComponent target) (targetCLBI target)++allComponentsInBuildOrder :: LocalBuildInfo+ -> [ComponentLocalBuildInfo]+allComponentsInBuildOrder lbi =+ Graph.topSort (componentGraph lbi)++-- -----------------------------------------------------------------------------+-- A random function that has no business in this module++-- | Determine the directories containing the dynamic libraries of the+-- transitive dependencies of the component we are building.+--+-- When wanted, and possible, returns paths relative to the installDirs 'prefix'+depLibraryPaths :: Bool -- ^ Building for inplace?+ -> Bool -- ^ Generate prefix-relative library paths+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo -- ^ Component that is being built+ -> IO [FilePath]+depLibraryPaths inplace relative lbi clbi = do+ let pkgDescr = localPkgDescr lbi+ installDirs = absoluteComponentInstallDirs pkgDescr lbi (componentUnitId clbi) NoCopyDest+ executable = case clbi of+ ExeComponentLocalBuildInfo {} -> True+ _ -> False+ relDir | executable = bindir installDirs+ | otherwise = libdir installDirs++ let -- TODO: this is kind of inefficient+ internalDeps = [ uid+ | (uid, _) <- componentPackageDeps clbi+ -- Test that it's internal+ , sub_target <- allTargetsInBuildOrder' pkgDescr lbi+ , componentUnitId (targetCLBI (sub_target)) == uid ]+ internalLibs = [ getLibDir (targetCLBI sub_target)+ | sub_target <- neededTargetsInBuildOrder'+ pkgDescr lbi internalDeps ]+ {-+ -- This is better, but it doesn't work, because we may be passed a+ -- CLBI which doesn't actually exist, and was faked up when we+ -- were building a test suite/benchmark. See #3599 for proposal+ -- to fix this.+ let internalCLBIs = filter ((/= componentUnitId clbi) . componentUnitId)+ . map targetCLBI+ $ neededTargetsInBuildOrder lbi [componentUnitId clbi]+ internalLibs = map getLibDir internalCLBIs+ -}+ getLibDir sub_clbi+ | inplace = componentBuildDir lbi sub_clbi+ | otherwise = dynlibdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)++ -- Why do we go through all the trouble of a hand-crafting+ -- internalLibs, when 'installedPkgs' actually contains the+ -- internal libraries? The trouble is that 'installedPkgs'+ -- may contain *inplace* entries, which we must NOT use for+ -- not inplace 'depLibraryPaths' (e.g., for RPATH calculation).+ -- See #4025 for more details. This is all horrible but it+ -- is a moot point if you are using a per-component build,+ -- because you never have any internal libraries in this case;+ -- they're all external.+ let external_ipkgs = filter is_external (allPackages (installedPkgs lbi))+ is_external ipkg = not (installedUnitId ipkg `elem` internalDeps)+ -- First look for dynamic libraries in `dynamic-library-dirs`, and use+ -- `library-dirs` as a fall back.+ getDynDir pkg = case Installed.libraryDynDirs pkg of+ [] -> Installed.libraryDirs pkg+ d -> d+ allDepLibDirs = concatMap getDynDir external_ipkgs++ allDepLibDirs' = internalLibs ++ allDepLibDirs+ allDepLibDirsC <- traverse canonicalizePathNoFail allDepLibDirs'++ let p = prefix installDirs+ prefixRelative l = isJust (stripPrefix p l)+ libPaths+ | relative &&+ prefixRelative relDir = map (\l ->+ if prefixRelative l+ then shortRelativePath relDir l+ else l+ ) allDepLibDirsC+ | otherwise = allDepLibDirsC++ return libPaths+ where+ -- 'canonicalizePath' fails on UNIX when the directory does not exists.+ -- So just don't canonicalize when it doesn't exist.+ canonicalizePathNoFail p = do+ exists <- doesDirectoryExist p+ if exists+ then canonicalizePath p+ else return p++-- | Get all module names that needed to be built by GHC; i.e., all+-- of these 'ModuleName's have interface files associated with them+-- that need to be installed.+allLibModules :: Library -> ComponentLocalBuildInfo -> [ModuleName]+allLibModules lib clbi =+ ordNub $+ explicitLibModules lib +++ case clbi of+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts } -> map fst insts+ _ -> []++-- -----------------------------------------------------------------------------+-- Wrappers for a couple functions from InstallDirs++-- | Backwards compatibility function which computes the InstallDirs+-- assuming that @$libname@ points to the public library (or some fake+-- package identifier if there is no public library.) IF AT ALL+-- POSSIBLE, please use 'absoluteComponentInstallDirs' instead.+absoluteInstallDirs :: PackageDescription -> LocalBuildInfo+ -> CopyDest+ -> InstallDirs FilePath+absoluteInstallDirs pkg lbi copydest =+ absoluteComponentInstallDirs pkg lbi (localUnitId lbi) copydest++-- | See 'InstallDirs.absoluteInstallDirs'.+absoluteComponentInstallDirs :: PackageDescription -> LocalBuildInfo+ -> UnitId+ -> CopyDest+ -> InstallDirs FilePath+absoluteComponentInstallDirs pkg lbi uid copydest =+ InstallDirs.absoluteInstallDirs+ (packageId pkg)+ uid+ (compilerInfo (compiler lbi))+ copydest+ (hostPlatform lbi)+ (installDirTemplates lbi)++absoluteInstallCommandDirs :: PackageDescription -> LocalBuildInfo+ -> UnitId+ -> CopyDest+ -> InstallDirs FilePath+absoluteInstallCommandDirs pkg lbi uid copydest =+ dirs {+ -- Handle files which are not+ -- per-component (data files and Haddock files.)+ datadir = datadir dirs',+ -- NB: The situation with Haddock is a bit delicate. On the+ -- one hand, the easiest to understand Haddock documentation+ -- path is pkgname-0.1, which means it's per-package (not+ -- per-component). But this means that it's impossible to+ -- install Haddock documentation for internal libraries. We'll+ -- keep this constraint for now; this means you can't use+ -- Cabal to Haddock internal libraries. This does not seem+ -- like a big problem.+ docdir = docdir dirs',+ htmldir = htmldir dirs',+ haddockdir = haddockdir dirs'+ }+ where+ dirs = absoluteComponentInstallDirs pkg lbi uid copydest+ -- Notice use of 'absoluteInstallDirs' (not the+ -- per-component variant). This means for non-library+ -- packages we'll just pick a nondescriptive foo-0.1+ dirs' = absoluteInstallDirs pkg lbi copydest++-- | Backwards compatibility function which computes the InstallDirs+-- assuming that @$libname@ points to the public library (or some fake+-- package identifier if there is no public library.) IF AT ALL+-- POSSIBLE, please use 'prefixRelativeComponentInstallDirs' instead.+prefixRelativeInstallDirs :: PackageId -> LocalBuildInfo+ -> InstallDirs (Maybe FilePath)+prefixRelativeInstallDirs pkg_descr lbi =+ prefixRelativeComponentInstallDirs pkg_descr lbi (localUnitId lbi)++-- |See 'InstallDirs.prefixRelativeInstallDirs'+prefixRelativeComponentInstallDirs :: PackageId -> LocalBuildInfo+ -> UnitId+ -> InstallDirs (Maybe FilePath)+prefixRelativeComponentInstallDirs pkg_descr lbi uid =+ InstallDirs.prefixRelativeInstallDirs+ (packageId pkg_descr)+ uid+ (compilerInfo (compiler lbi))+ (hostPlatform lbi)+ (installDirTemplates lbi)++substPathTemplate :: PackageId -> LocalBuildInfo+ -> UnitId+ -> PathTemplate -> FilePath+substPathTemplate pkgid lbi uid = fromPathTemplate+ . ( InstallDirs.substPathTemplate env )+ where env = initialPathTemplateEnv+ pkgid+ uid+ (compilerInfo (compiler lbi))+ (hostPlatform lbi)+
+ src/Distribution/Simple/PackageIndex.hs view
@@ -0,0 +1,716 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.PackageIndex+-- Copyright : (c) David Himmelstrup 2005,+-- Bjorn Bringert 2007,+-- Duncan Coutts 2008-2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- An index of packages whose primary key is 'UnitId'. Public libraries+-- are additionally indexed by 'PackageName' and 'Version'.+-- Technically, these are an index of *units* (so we should eventually+-- rename it to 'UnitIndex'); but in the absence of internal libraries+-- or Backpack each unit is equivalent to a package.+--+-- While 'PackageIndex' is parametric over what it actually records,+-- it is in fact only ever instantiated with a single element:+-- The 'InstalledPackageIndex' (defined here) contains a graph of+-- 'InstalledPackageInfo's representing the packages in a+-- package database stack. It is used in a variety of ways:+--+-- * The primary use to let Cabal access the same installed+-- package database which is used by GHC during compilation.+-- For example, this data structure is used by 'ghc-pkg'+-- and 'Cabal' to do consistency checks on the database+-- (are the references closed).+--+-- * Given a set of dependencies, we can compute the transitive+-- closure of dependencies. This is to check if the versions+-- of packages are consistent, and also needed by multiple+-- tools (Haddock must be explicitly told about the every+-- transitive package to do cross-package linking;+-- preprocessors must know about the include paths of all+-- transitive dependencies.)+--+-- This 'PackageIndex' is NOT to be confused with+-- 'Distribution.Client.PackageIndex', which indexes packages only by+-- 'PackageName' (this makes it suitable for indexing source packages,+-- for which we don't know 'UnitId's.)+--+module Distribution.Simple.PackageIndex (+ -- * Package index data type+ InstalledPackageIndex,+ PackageIndex,++ -- * Creating an index+ fromList,++ -- * Updates+ merge,++ insert,++ deleteUnitId,+ deleteSourcePackageId,+ deletePackageName,+-- deleteDependency,++ -- * Queries++ -- ** Precise lookups+ lookupUnitId,+ lookupComponentId,+ lookupSourcePackageId,+ lookupPackageId,+ lookupPackageName,+ lookupDependency,+ lookupInternalDependency,++ -- ** Case-insensitive searches+ searchByName,+ SearchResult(..),+ searchByNameSubstring,+ searchWithPredicate,++ -- ** Bulk queries+ allPackages,+ allPackagesByName,+ allPackagesBySourcePackageId,+ allPackagesBySourcePackageIdAndLibName,++ -- ** Special queries+ brokenPackages,+ dependencyClosure,+ reverseDependencyClosure,+ topologicalOrder,+ reverseTopologicalOrder,+ dependencyInconsistencies,+ dependencyCycles,+ dependencyGraph,+ moduleNameIndex+ ) where++import Prelude ()+import Distribution.Compat.Prelude hiding (lookup)+import qualified Data.Map.Strict as Map++import Distribution.Package+import Distribution.Backpack+import Distribution.ModuleName+import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.Version+import Distribution.Simple.Utils+import Distribution.Types.LibraryName++import Control.Exception (assert)+import Data.Array ((!))+import qualified Data.Array as Array+import qualified Data.Graph as Graph+import Data.List as List ( groupBy, deleteBy, deleteFirstsBy )+import qualified Data.List.NonEmpty as NE+import qualified Data.Tree as Tree+import Control.Monad+import Distribution.Compat.Stack++import qualified Prelude (foldr1)++-- | 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 '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 UnitId.+ --+ unitIdIndex :: !(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+ -- versions satisfying a dependency.+ --+ -- 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 UnitId+ -- and are kept in preference order.+ --+ -- FIXME: Clarify what "preference order" means. Check that this invariant is+ -- preserved. See #1463 for discussion.+ packageIdIndex :: !(Map (PackageName, LibraryName) (Map Version [a]))++ } deriving (Eq, Generic, Show, Read, Typeable)++instance Binary a => Binary (PackageIndex a)+instance Structured a => Structured (PackageIndex a)++-- | The default package index which contains 'InstalledPackageInfo'. Normally+-- use this.+type InstalledPackageIndex = PackageIndex IPI.InstalledPackageInfo++instance Monoid (PackageIndex IPI.InstalledPackageInfo) where+ mempty = PackageIndex Map.empty Map.empty+ mappend = (<>)+ --save one mappend with empty in the common case:+ mconcat [] = mempty+ mconcat xs = Prelude.foldr1 mappend xs++instance Semigroup (PackageIndex IPI.InstalledPackageInfo) where+ (<>) = merge++{-# NOINLINE invariant #-}+invariant :: WithCallStack (InstalledPackageIndex -> Bool)+invariant (PackageIndex pids pnames) =+ -- trace (show pids' ++ "\n" ++ show pnames') $+ pids' == pnames'+ where+ pids' = map installedUnitId (Map.elems pids)+ pnames' = sort+ [ assert pinstOk (installedUnitId pinst)+ | ((pname, plib), pvers) <- Map.toList pnames+ , let pversOk = not (Map.null pvers)+ , (pver, pinsts) <- assert pversOk $ Map.toList pvers+ , let pinsts' = sortBy (comparing installedUnitId) pinsts+ pinstsOk = all (\g -> length g == 1)+ (groupBy (equating installedUnitId) pinsts')+ , pinst <- assert pinstsOk $ pinsts'+ , let pinstOk = packageName pinst == pname+ && packageVersion pinst == pver+ && IPI.sourceLibName pinst == plib+ ]+ -- If you see this invariant failing (ie the assert in mkPackageIndex below)+ -- then one thing to check is if it is happening in fromList. Check if the+ -- second list above (the sort [...] bit) is ending up with duplicates. This+ -- has been observed in practice once due to a messed up ghc-pkg db. How/why+ -- it became messed up was not discovered.+++--+-- * Internal helpers+--++mkPackageIndex :: WithCallStack (Map UnitId IPI.InstalledPackageInfo+ -> Map (PackageName, LibraryName)+ (Map Version [IPI.InstalledPackageInfo])+ -> InstalledPackageIndex)+mkPackageIndex pids pnames = assert (invariant index) index+ where index = PackageIndex pids pnames+++--+-- * Construction+--++-- | Build an index out of a bunch of packages.+--+-- If there are duplicates by 'UnitId' then later ones mask earlier+-- ones.+--+fromList :: [IPI.InstalledPackageInfo] -> InstalledPackageIndex+fromList pkgs = mkPackageIndex pids ((fmap . fmap) toList pnames)+ where+ pids = Map.fromList [ (installedUnitId pkg, pkg) | pkg <- pkgs ]+ pnames =+ Map.fromList+ [ (liftM2 (,) packageName IPI.sourceLibName (NE.head pkgsN), pvers)+ | pkgsN <- NE.groupBy (equating (liftM2 (,) packageName IPI.sourceLibName))+ . sortBy (comparing (liftM3 (,,) packageName IPI.sourceLibName packageVersion))+ $ pkgs+ , let pvers =+ Map.fromList+ [ (packageVersion (NE.head pkgsNV),+ NE.nubBy (equating installedUnitId) (NE.reverse pkgsNV))+ | pkgsNV <- NE.groupBy (equating packageVersion) pkgsN+ ]+ ]++--+-- * Updates+--++-- | Merge two indexes.+--+-- Packages from the second mask packages from the first if they have the exact+-- 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 :: InstalledPackageIndex -> InstalledPackageIndex+ -> InstalledPackageIndex+merge (PackageIndex pids1 pnames1) (PackageIndex pids2 pnames2) =+ mkPackageIndex (Map.unionWith (\_ y -> y) pids1 pids2)+ (Map.unionWith (Map.unionWith mergeBuckets) pnames1 pnames2)+ where+ -- 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 installedUnitId)+++-- | Inserts a single package into the index.+--+-- This is equivalent to (but slightly quicker than) using 'mappend' or+-- 'merge' with a singleton index.+--+insert :: IPI.InstalledPackageInfo -> InstalledPackageIndex -> InstalledPackageIndex+insert pkg (PackageIndex pids pnames) =+ mkPackageIndex pids' pnames'++ where+ pids' = Map.insert (installedUnitId pkg) pkg pids+ pnames' = insertPackageName pnames+ insertPackageName =+ Map.insertWith (\_ -> insertPackageVersion)+ (packageName pkg, IPI.sourceLibName pkg)+ (Map.singleton (packageVersion pkg) [pkg])++ insertPackageVersion =+ Map.insertWith (\_ -> insertPackageInstance)+ (packageVersion pkg) [pkg]++ insertPackageInstance pkgs =+ pkg : deleteBy (equating installedUnitId) pkg pkgs+++-- | Removes a single installed package from the index.+--+deleteUnitId :: UnitId -> InstalledPackageIndex+ -> InstalledPackageIndex+deleteUnitId ipkgid original@(PackageIndex pids pnames) =+ case Map.updateLookupWithKey (\_ _ -> Nothing) ipkgid pids of+ (Nothing, _) -> original+ (Just spkgid, pids') -> mkPackageIndex pids'+ (deletePkgName spkgid pnames)++ where+ deletePkgName spkgid =+ Map.update (deletePkgVersion spkgid) (packageName spkgid, IPI.sourceLibName spkgid)++ deletePkgVersion spkgid =+ (\m -> if Map.null m then Nothing else Just m)+ . Map.update deletePkgInstance (packageVersion spkgid)++ deletePkgInstance =+ (\xs -> if null xs then Nothing else Just xs)+ . List.deleteBy (\_ pkg -> installedUnitId pkg == ipkgid) undefined++-- | Removes all packages with this source 'PackageId' from the index.+--+deleteSourcePackageId :: PackageId -> InstalledPackageIndex+ -> InstalledPackageIndex+deleteSourcePackageId pkgid original@(PackageIndex pids pnames) =+ -- NB: Doesn't delete internal packages+ case Map.lookup (packageName pkgid, LMainLibName) pnames of+ Nothing -> original+ Just pvers -> case Map.lookup (packageVersion pkgid) pvers of+ Nothing -> original+ Just pkgs -> mkPackageIndex+ (foldl' (flip (Map.delete . installedUnitId)) pids pkgs)+ (deletePkgName pnames)+ where+ deletePkgName =+ Map.update deletePkgVersion (packageName pkgid, LMainLibName)++ deletePkgVersion =+ (\m -> if Map.null m then Nothing else Just m)+ . Map.delete (packageVersion pkgid)+++-- | Removes all packages with this (case-sensitive) name from the index.+--+-- NB: Does NOT delete internal libraries from this package.+--+deletePackageName :: PackageName -> InstalledPackageIndex+ -> InstalledPackageIndex+deletePackageName name original@(PackageIndex pids pnames) =+ case Map.lookup (name, LMainLibName) pnames of+ Nothing -> original+ Just pvers -> mkPackageIndex+ (foldl' (flip (Map.delete . installedUnitId)) pids+ (concat (Map.elems pvers)))+ (Map.delete (name, LMainLibName) pnames)++{-+-- | Removes all packages satisfying this dependency from the index.+--+deleteDependency :: Dependency -> PackageIndex -> PackageIndex+deleteDependency (Dependency name verstionRange) =+ delete' name (\pkg -> packageVersion pkg `withinRange` verstionRange)+-}++--+-- * Bulk queries+--++-- | Get all the packages from the index.+--+allPackages :: PackageIndex a -> [a]+allPackages = Map.elems . unitIdIndex++-- | Get all the packages from the index.+--+-- They are grouped by package name (case-sensitively).+--+-- (Doesn't include private libraries.)+--+allPackagesByName :: PackageIndex a -> [(PackageName, [a])]+allPackagesByName index =+ [ (pkgname, concat (Map.elems pvers))+ | ((pkgname, LMainLibName), pvers) <- Map.toList (packageIdIndex index) ]++-- | Get all the packages from the index.+--+-- They are grouped by source package id (package name and version).+--+-- (Doesn't include private libraries)+--+allPackagesBySourcePackageId :: HasUnitId a => PackageIndex a+ -> [(PackageId, [a])]+allPackagesBySourcePackageId index =+ [ (packageId ipkg, ipkgs)+ | ((_, LMainLibName), pvers) <- Map.toList (packageIdIndex index)+ , ipkgs@(ipkg:_) <- Map.elems pvers ]++-- | Get all the packages from the index.+--+-- They are grouped by source package id and library name.+--+-- This DOES include internal libraries.+allPackagesBySourcePackageIdAndLibName :: HasUnitId a => PackageIndex a+ -> [((PackageId, LibraryName), [a])]+allPackagesBySourcePackageIdAndLibName index =+ [ ((packageId ipkg, ln), ipkgs)+ | ((_, ln), pvers) <- Map.toList (packageIdIndex index)+ , ipkgs@(ipkg:_) <- Map.elems pvers ]++--+-- * Lookups+--++-- | Does a lookup by unit identifier.+--+-- Since multiple package DBs mask each other by 'UnitId',+-- then we get back at most one package.+--+lookupUnitId :: PackageIndex a -> UnitId+ -> Maybe a+lookupUnitId index uid = Map.lookup uid (unitIdIndex index)++-- | Does a lookup by component identifier. In the absence+-- of Backpack, this is just a 'lookupUnitId'.+--+lookupComponentId :: PackageIndex a -> ComponentId+ -> Maybe a+lookupComponentId index cid =+ Map.lookup (newSimpleUnitId cid) (unitIdIndex index)++-- | Does a lookup by source package id (name & version).+--+-- There can be multiple installed packages with the same source 'PackageId'+-- but different 'UnitId'. They are returned in order of+-- preference, with the most preferred first.+--+lookupSourcePackageId :: PackageIndex a -> PackageId -> [a]+lookupSourcePackageId index pkgid =+ -- Do not lookup internal libraries+ case Map.lookup (packageName pkgid, LMainLibName) (packageIdIndex index) of+ Nothing -> []+ Just pvers -> case Map.lookup (packageVersion pkgid) pvers of+ Nothing -> []+ Just pkgs -> pkgs -- in preference order++-- | Convenient alias of 'lookupSourcePackageId', but assuming only+-- one package per package ID.+lookupPackageId :: PackageIndex a -> PackageId -> Maybe a+lookupPackageId index pkgid = case lookupSourcePackageId index pkgid of+ [] -> Nothing+ [pkg] -> Just pkg+ _ -> error "Distribution.Simple.PackageIndex: multiple matches found"++-- | Does a lookup by source package name.+--+lookupPackageName :: PackageIndex a -> PackageName+ -> [(Version, [a])]+lookupPackageName index name =+ -- Do not match internal libraries+ case Map.lookup (name, LMainLibName) (packageIdIndex index) of+ Nothing -> []+ Just pvers -> Map.toList pvers+++-- | Does a lookup by source package name and a range of versions.+--+-- We get back any number of versions of the specified package name, all+-- satisfying the version range constraint.+--+-- This does NOT work for internal dependencies, DO NOT use this+-- function on those; use 'lookupInternalDependency' instead.+--+-- INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.+--+lookupDependency :: InstalledPackageIndex -> PackageName -> VersionRange+ -> [(Version, [IPI.InstalledPackageInfo])]+lookupDependency index pn vr =+ -- Yes, a little bit of a misnomer here!+ lookupInternalDependency index pn vr LMainLibName++-- | Does a lookup by source package name and a range of versions.+--+-- We get back any number of versions of the specified package name, all+-- satisfying the version range constraint.+--+-- INVARIANT: List of eligible 'IPI.InstalledPackageInfo' is non-empty.+--+lookupInternalDependency :: InstalledPackageIndex -> PackageName -> VersionRange+ -> LibraryName+ -> [(Version, [IPI.InstalledPackageInfo])]+lookupInternalDependency index name versionRange libn =+ case Map.lookup (name, libn) (packageIdIndex index) of+ Nothing -> []+ Just pvers -> [ (ver, pkgs')+ | (ver, pkgs) <- Map.toList pvers+ , ver `withinRange` versionRange+ , let pkgs' = filter eligible pkgs+ -- Enforce the invariant+ , not (null pkgs')+ ]+ where+ -- When we select for dependencies, we ONLY want to pick up indefinite+ -- packages, or packages with no instantiations. We'll do mix-in+ -- linking to improve any such package into an instantiated one+ -- later.+ eligible pkg = IPI.indefinite pkg || null (IPI.instantiatedWith pkg)+++--+-- * Case insensitive name lookups+--++-- | Does a case-insensitive search by package name.+--+-- If there is only one package that compares case-insensitively to this name+-- then the search is unambiguous and we get back all versions of that package.+-- If several match case-insensitively but one matches exactly then it is also+-- unambiguous.+--+-- If however several match case-insensitively and none match exactly then we+-- have an ambiguous result, and we get back all the versions of all the+-- packages. The list of ambiguous results is split by exact package name. So+-- it is a non-empty list of non-empty lists.+--+searchByName :: PackageIndex a -> String -> SearchResult [a]+searchByName index name =+ -- Don't match internal packages+ case [ pkgs | pkgs@((pname, LMainLibName),_) <- Map.toList (packageIdIndex index)+ , lowercase (unPackageName pname) == lname ] of+ [] -> None+ [(_,pvers)] -> Unambiguous (concat (Map.elems pvers))+ pkgss -> case find ((mkPackageName name ==) . fst . fst) pkgss of+ Just (_,pvers) -> Unambiguous (concat (Map.elems pvers))+ Nothing -> Ambiguous (map (concat . Map.elems . snd) pkgss)+ where lname = lowercase name++data SearchResult a = None | Unambiguous a | Ambiguous [a]++-- | Does a case-insensitive substring search by package name.+--+-- That is, all packages that contain the given string in their name.+--+searchByNameSubstring :: PackageIndex a -> String -> [a]+searchByNameSubstring index searchterm =+ searchWithPredicate index (\n -> lsearchterm `isInfixOf` lowercase n)+ where lsearchterm = lowercase searchterm++-- | @since 3.4.0.0+searchWithPredicate :: PackageIndex a -> (String -> Bool) -> [a]+searchWithPredicate index predicate =+ [ pkg+ -- Don't match internal packages+ | ((pname, LMainLibName), pvers) <- Map.toList (packageIdIndex index)+ , predicate (unPackageName pname)+ , pkgs <- Map.elems pvers+ , pkg <- pkgs ]++--+-- * Special queries+--++-- None of the stuff below depends on the internal representation of the index.+--++-- | Find if there are any cycles in the dependency graph. If there are no+-- cycles the result is @[]@.+--+-- This actually computes the strongly connected components. So it gives us a+-- list of groups of packages where within each group they all depend on each+-- other, directly or indirectly.+--+dependencyCycles :: PackageInstalled a => PackageIndex a -> [[a]]+dependencyCycles index =+ [ vs | Graph.CyclicSCC vs <- Graph.stronglyConnComp adjacencyList ]+ where+ adjacencyList = [ (pkg, installedUnitId pkg, installedDepends pkg)+ | pkg <- allPackages index ]+++-- | All packages that have immediate dependencies that are not in the index.+--+-- Returns such packages along with the dependencies that they're missing.+--+brokenPackages :: PackageInstalled a => PackageIndex a+ -> [(a, [UnitId])]+brokenPackages index =+ [ (pkg, missing)+ | pkg <- allPackages index+ , let missing = [ pkg' | pkg' <- installedDepends pkg+ , isNothing (lookupUnitId index pkg') ]+ , not (null missing) ]++-- | Tries to take the transitive closure of the package dependencies.+--+-- If the transitive closure is complete then it returns that subset of the+-- index. Otherwise it returns the broken packages as in 'brokenPackages'.+--+-- * Note that if the result is @Right []@ it is because at least one of+-- the original given 'PackageId's do not occur in the index.+--+dependencyClosure :: InstalledPackageIndex+ -> [UnitId]+ -> Either (InstalledPackageIndex)+ [(IPI.InstalledPackageInfo, [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 lookupUnitId index pkgid of+ Nothing -> closure completed (pkgid:failed) pkgids+ Just pkg -> case lookupUnitId completed (installedUnitId pkg) of+ Just _ -> closure completed failed pkgids+ Nothing -> closure completed' failed pkgids'+ where completed' = insert pkg completed+ pkgids' = installedDepends pkg ++ pkgids++-- | Takes the transitive closure of the packages reverse dependencies.+--+-- * The given 'PackageId's must be in the index.+--+reverseDependencyClosure :: PackageInstalled a => PackageIndex a+ -> [UnitId]+ -> [a]+reverseDependencyClosure index =+ map vertexToPkg+ . concatMap Tree.flatten+ . Graph.dfs reverseDepGraph+ . map (fromMaybe noSuchPkgId . pkgIdToVertex)++ where+ (depGraph, vertexToPkg, pkgIdToVertex) = dependencyGraph index+ reverseDepGraph = Graph.transposeG depGraph+ noSuchPkgId = error "reverseDependencyClosure: package is not in the graph"++topologicalOrder :: PackageInstalled a => PackageIndex a -> [a]+topologicalOrder index = map toPkgId+ . Graph.topSort+ $ graph+ where (graph, toPkgId, _) = dependencyGraph index++reverseTopologicalOrder :: PackageInstalled a => PackageIndex a -> [a]+reverseTopologicalOrder index = map toPkgId+ . Graph.topSort+ . Graph.transposeG+ $ graph+ where (graph, toPkgId, _) = dependencyGraph index++-- | Builds a graph of the package dependencies.+--+-- Dependencies on other packages that are not in the index are discarded.+-- You can check if there are any such dependencies with 'brokenPackages'.+--+dependencyGraph :: PackageInstalled a => PackageIndex a+ -> (Graph.Graph,+ Graph.Vertex -> a,+ 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 installedUnitId pkgs) [0..]+ vertex_map = Map.fromList vertices+ id_to_vertex pid = Map.lookup pid vertex_map++ vertex_to_pkg vertex = pkgTable ! vertex++ pkgTable = Array.listArray bounds pkgs+ topBound = length pkgs - 1+ bounds = (0, topBound)++-- | We maintain the invariant that, for any 'DepUniqueKey', there+-- is only one instance of the package in our database.+type DepUniqueKey = (PackageName, LibraryName, Map ModuleName OpenModule)++-- | Given a package index where we assume we want to use all the packages+-- (use 'dependencyClosure' if you need to get such a index subset) find out+-- if the dependencies within it use consistent versions of each package.+-- Return all cases where multiple packages depend on different versions of+-- some other package.+--+-- Each element in the result is a package name along with the packages that+-- depend on it and the versions they require. These are guaranteed to be+-- distinct.+--+dependencyInconsistencies :: InstalledPackageIndex+ -- At DepUniqueKey...+ -> [(DepUniqueKey,+ -- There were multiple packages (BAD!)+ [(UnitId,+ -- And here are the packages which+ -- immediately depended on it+ [IPI.InstalledPackageInfo])])]+dependencyInconsistencies index = do+ (dep_key, insts_map) <- Map.toList inverseIndex+ let insts = Map.toList insts_map+ guard (length insts >= 2)+ return (dep_key, insts)+ where+ inverseIndex :: Map DepUniqueKey (Map UnitId [IPI.InstalledPackageInfo])+ inverseIndex = Map.fromListWith (Map.unionWith (++)) $ do+ pkg <- allPackages index+ dep_ipid <- installedDepends pkg+ Just dep <- [lookupUnitId index dep_ipid]+ let dep_key = (packageName dep, IPI.sourceLibName dep,+ Map.fromList (IPI.instantiatedWith dep))+ return (dep_key, Map.singleton dep_ipid [pkg])++-- | 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+ case reexport of+ Nothing -> return (m, [pkg])+ Just (OpenModuleVar _) -> []+ Just (OpenModule _ m') | m == m' -> []+ | otherwise -> return (m', [pkg])+ -- The heuristic is this: we want to prefer the original package+ -- which originally exported a module. However, if a reexport+ -- also *renamed* the module (m /= m'), then we have to use the+ -- downstream package, since the upstream package has the wrong+ -- module name!
+ src/Distribution/Simple/PreProcess.hs view
@@ -0,0 +1,779 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.PreProcess+-- Copyright : (c) 2003-2005, Isaac Jones, Malcolm Wallace+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This defines a 'PreProcessor' abstraction which represents a pre-processor+-- that can transform one kind of file into another. There is also a+-- 'PPSuffixHandler' which is a combination of a file extension and a function+-- for configuring a 'PreProcessor'. It defines a bunch of known built-in+-- preprocessors like @cpp@, @cpphs@, @c2hs@, @hsc2hs@, @happy@, @alex@ etc and+-- lists them in 'knownSuffixHandlers'. On top of this it provides a function+-- for actually preprocessing some sources given a bunch of known suffix+-- 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, preprocessExtras,+ knownSuffixHandlers, ppSuffixes,+ PPSuffixHandler, PreProcessor(..),+ mkSimplePreProcessor, runSimplePreProcessor,+ ppCpp, ppCpp', ppGreenCard, ppC2hs, ppHsc2hs,+ ppHappy, ppAlex, ppUnlit, platformDefines+ )+ where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Compat.Stack++import Distribution.Simple.PreProcess.Unlit+import Distribution.Backpack.DescribeUnitId+import Distribution.Package+import qualified Distribution.ModuleName as ModuleName+import Distribution.ModuleName (ModuleName)+import Distribution.PackageDescription as PD+import qualified Distribution.InstalledPackageInfo as Installed+import qualified Distribution.Simple.PackageIndex as PackageIndex+import Distribution.Simple.CCompiler+import Distribution.Simple.Compiler+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.BuildPaths+import Distribution.Simple.Utils+import Distribution.Simple.Program+import Distribution.Simple.Program.ResponseFile+import Distribution.Simple.Test.LibV09+import Distribution.System+import Distribution.Pretty+import Distribution.Version+import Distribution.Verbosity+import Distribution.Utils.Path++import System.Directory (doesFileExist)+import System.Info (os, arch)+import System.FilePath (splitExtension, dropExtensions, (</>), (<.>),+ 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+-- the input file, the name of the output file and a verbosity level.+-- Here is a simple example that merely prepends a comment to the given+-- source file:+--+-- > ppTestHandler :: PreProcessor+-- > ppTestHandler =+-- > PreProcessor {+-- > platformIndependent = True,+-- > runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->+-- > do info verbosity (inFile++" has been preprocessed to "++outFile)+-- > stuff <- readFile inFile+-- > writeFile outFile ("-- preprocessed as a test\n\n" ++ stuff)+-- > return ExitSuccess+--+-- We split the input and output file names into a base directory and the+-- rest of the file name. The input base dir is the path in the list of search+-- dirs that this file was found in. The output base dir is the build dir where+-- all the generated source files are put.+--+-- The reason for splitting it up this way is that some pre-processors don't+-- simply generate one output .hs file from one input file but have+-- dependencies on other generated files (notably c2hs, where building one+-- .hs file may require reading other .chi files, and then compiling the .hs+-- file may require reading a generated .h file). In these cases the generated+-- files need to embed relative path names to each other (eg the generated .hs+-- file mentions the .h file in the FFI imports). This path must be relative to+-- the base directory where the generated files are located, it cannot be+-- relative to the top level of the build tree because the compilers do not+-- look for .h files relative to there, ie we do not use \"-I .\", instead we+-- use \"-I dist\/build\" (or whatever dist dir has been set by the user)+--+-- Most pre-processors do not care of course, so mkSimplePreProcessor and+-- runSimplePreProcessor functions handle the simple case.+--+data PreProcessor = PreProcessor {++ -- Is the output of the pre-processor platform independent? eg happy output+ -- is portable haskell but c2hs's output is platform dependent.+ -- This matters since only platform independent generated code can be+ -- included into a source tarball.+ platformIndependent :: Bool,++ -- TODO: deal with pre-processors that have implementation dependent output+ -- eg alex and happy have --ghc flags. However we can't really include+ -- ghc-specific code into supposedly portable source tarballs.++ runPreProcessor :: (FilePath, FilePath) -- Location of the source file relative to a base dir+ -> (FilePath, FilePath) -- Output file name, relative to an output base dir+ -> Verbosity -- verbosity+ -> 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 ()+mkSimplePreProcessor simplePP+ (inBaseDir, inRelativeFile)+ (outBaseDir, outRelativeFile) verbosity = simplePP inFile outFile verbosity+ where inFile = normalise (inBaseDir </> inRelativeFile)+ outFile = normalise (outBaseDir </> outRelativeFile)++runSimplePreProcessor :: PreProcessor -> FilePath -> FilePath -> Verbosity+ -> IO ()+runSimplePreProcessor pp inFile outFile verbosity =+ runPreProcessor pp (".", inFile) (".", outFile) verbosity++-- |A preprocessor for turning non-Haskell files with the given extension+-- into plain Haskell source files.+type PPSuffixHandler+ = (String, BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor)++-- | Apply preprocessors to the sources from 'hsSourceDirs' for a given+-- component (lib, exe, or test suite).+--+-- XXX: This is terrible+preprocessComponent :: PackageDescription+ -> Component+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Bool+ -> Verbosity+ -> [PPSuffixHandler]+ -> IO ()+preprocessComponent pd comp lbi clbi isSrcDist verbosity handlers = do+ -- NB: never report instantiation here; we'll report it properly when+ -- building.+ setupMessage' verbosity "Preprocessing" (packageId pd)+ (componentLocalName clbi) (Nothing :: Maybe [(ModuleName, Module)])+ case comp of+ (CLib lib@Library{ libBuildInfo = bi }) -> do+ let dirs = map getSymbolicPath (hsSourceDirs bi) +++ [ autogenComponentModulesDir lbi clbi ,autogenPackageModulesDir lbi]+ for_ (map ModuleName.toFilePath $ allLibModules lib clbi) $+ pre dirs (componentBuildDir lbi clbi) (localHandlers bi)+ (CFLib flib@ForeignLib { foreignLibBuildInfo = bi, foreignLibName = nm }) -> do+ let nm' = unUnqualComponentName nm+ let flibDir = buildDir lbi </> nm' </> nm' ++ "-tmp"+ dirs = map getSymbolicPath (hsSourceDirs bi) ++ [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi]+ for_ (map ModuleName.toFilePath $ foreignLibModules flib) $+ pre dirs flibDir (localHandlers bi)+ (CExe exe@Executable { buildInfo = bi, exeName = nm }) -> do+ let nm' = unUnqualComponentName nm+ let exeDir = buildDir lbi </> nm' </> nm' ++ "-tmp"+ dirs = map getSymbolicPath (hsSourceDirs bi) ++ [autogenComponentModulesDir lbi clbi+ ,autogenPackageModulesDir lbi]+ for_ (map ModuleName.toFilePath $ otherModules bi) $+ pre dirs exeDir (localHandlers bi)+ pre (map getSymbolicPath (hsSourceDirs bi)) exeDir (localHandlers bi) $+ dropExtensions (modulePath exe)+ CTest test@TestSuite{ testName = nm } -> do+ let nm' = unUnqualComponentName nm+ case testInterface test of+ TestSuiteExeV10 _ f ->+ preProcessTest test f $ buildDir lbi </> nm' </> nm' ++ "-tmp"+ TestSuiteLibV09 _ _ -> do+ let testDir = buildDir lbi </> stubName test+ </> stubName test ++ "-tmp"+ writeSimpleTestStub test testDir+ preProcessTest test (stubFilePath test) testDir+ TestSuiteUnsupported tt ->+ die' verbosity $ "No support for preprocessing test "+ ++ "suite type " ++ prettyShow tt+ CBench bm@Benchmark{ benchmarkName = nm } -> do+ let nm' = unUnqualComponentName nm+ case benchmarkInterface bm of+ BenchmarkExeV10 _ f ->+ preProcessBench bm f $ buildDir lbi </> nm' </> nm' ++ "-tmp"+ BenchmarkUnsupported tt ->+ die' verbosity $ "No support for preprocessing benchmark "+ ++ "type " ++ prettyShow tt+ where+ builtinHaskellSuffixes = ["hs", "lhs", "hsig", "lhsig"]+ builtinCSuffixes = cSourceExtensions+ builtinSuffixes = builtinHaskellSuffixes ++ builtinCSuffixes+ localHandlers bi = [(ext, h bi lbi clbi) | (ext, h) <- handlers]+ pre dirs dir lhndlrs fp =+ preprocessFile (map unsafeMakeSymbolicPath dirs) dir isSrcDist fp verbosity builtinSuffixes lhndlrs+ preProcessTest test = preProcessComponent (testBuildInfo test)+ (testModules test)+ preProcessBench bm = preProcessComponent (benchmarkBuildInfo bm)+ (benchmarkModules bm)++ preProcessComponent+ :: BuildInfo+ -> [ModuleName]+ -> FilePath+ -> FilePath+ -> IO ()+ preProcessComponent bi modules exePath dir = do+ let biHandlers = localHandlers bi+ sourceDirs = map getSymbolicPath (hsSourceDirs bi) ++ [ autogenComponentModulesDir lbi clbi+ , autogenPackageModulesDir lbi ]+ sequence_ [ preprocessFile (map unsafeMakeSymbolicPath sourceDirs) dir isSrcDist+ (ModuleName.toFilePath modu) verbosity builtinSuffixes+ biHandlers+ | modu <- modules ]++ -- XXX: what we do here (re SymbolicPath dir)+ -- XXX: 2020-10-15 do we rely here on CWD being the PackageDir?+ preprocessFile (unsafeMakeSymbolicPath dir : hsSourceDirs bi) dir isSrcDist+ (dropExtensions $ exePath) verbosity+ builtinSuffixes biHandlers++--TODO: try to list all the modules that could not be found+-- not just the first one. It's annoying and slow due to the need+-- to reconfigure after editing the .cabal file each time.++-- |Find the first extension of the file that exists, and preprocess it+-- if required.+preprocessFile+ :: [SymbolicPath PackageDir SourceDir] -- ^ source directories++ -> FilePath -- ^build directory+ -> Bool -- ^preprocess for sdist+ -> FilePath -- ^module file name+ -> Verbosity -- ^verbosity+ -> [String] -- ^builtin suffixes+ -> [(String, PreProcessor)] -- ^possible preprocessors+ -> IO ()+preprocessFile searchLoc buildLoc forSDist baseFile verbosity builtinSuffixes handlers = do+ -- look for files in the various source dirs with this module name+ -- and a file extension of a known preprocessor+ psrcFiles <- findFileWithExtension' (map fst handlers) (map getSymbolicPath searchLoc) baseFile+ case psrcFiles of+ -- no preprocessor file exists, look for an ordinary source file+ -- just to make sure one actually exists at all for this module.+ -- Note: by looking in the target/output build dir too, we allow+ -- source files to appear magically in the target build dir without+ -- any corresponding "real" source file. This lets custom Setup.hs+ -- files generate source modules directly into the build dir without+ -- the rest of the build system being aware of it (somewhat dodgy)+ Nothing -> do+ bsrcFiles <- findFileWithExtension builtinSuffixes (buildLoc : map getSymbolicPath searchLoc) baseFile+ case bsrcFiles of+ Nothing ->+ die' verbosity $ "can't find source for " ++ baseFile+ ++ " in " ++ intercalate ", " (map getSymbolicPath searchLoc)+ _ -> return ()+ -- found a pre-processable file in one of the source dirs+ Just (psrcLoc, psrcRelFile) -> do+ let (srcStem, ext) = splitExtension psrcRelFile+ psrcFile = psrcLoc </> psrcRelFile+ pp = fromMaybe (error "Distribution.Simple.PreProcess: Just expected")+ (lookup (safeTail ext) handlers)+ -- Preprocessing files for 'sdist' is different from preprocessing+ -- for 'build'. When preprocessing for sdist we preprocess to+ -- avoid that the user has to have the preprocessors available.+ -- ATM, we don't have a way to specify which files are to be+ -- preprocessed and which not, so for sdist we only process+ -- platform independent files and put them into the 'buildLoc'+ -- (which we assume is set to the temp. directory that will become+ -- the tarball).+ --TODO: eliminate sdist variant, just supply different handlers+ when (not forSDist || forSDist && platformIndependent pp) $ do+ -- look for existing pre-processed source file in the dest dir to+ -- see if we really have to re-run the preprocessor.+ ppsrcFiles <- findFileWithExtension builtinSuffixes [buildLoc] baseFile+ recomp <- case ppsrcFiles of+ Nothing -> return True+ Just ppsrcFile ->+ psrcFile `moreRecentFile` ppsrcFile+ when recomp $ do+ let destDir = buildLoc </> dirName srcStem+ createDirectoryIfMissingVerbose verbosity True destDir+ runPreProcessorWithHsBootHack pp+ (psrcLoc, psrcRelFile)+ (buildLoc, srcStem <.> "hs")++ where+ dirName = takeDirectory++ -- FIXME: This is a somewhat nasty hack. GHC requires that hs-boot files+ -- be in the same place as the hs files, so if we put the hs file in dist/+ -- then we need to copy the hs-boot file there too. This should probably be+ -- done another way. Possibly we should also be looking for .lhs-boot+ -- files, but I think that preprocessors only produce .hs files.+ runPreProcessorWithHsBootHack pp+ (inBaseDir, inRelativeFile)+ (outBaseDir, outRelativeFile) = do+ runPreProcessor pp+ (inBaseDir, inRelativeFile)+ (outBaseDir, outRelativeFile) verbosity++ exists <- doesFileExist inBoot+ when exists $ copyFileVerbose verbosity inBoot outBoot++ where+ inBoot = replaceExtension inFile "hs-boot"+ outBoot = replaceExtension outFile "hs-boot"++ inFile = normalise (inBaseDir </> inRelativeFile)+ outFile = normalise (outBaseDir </> outRelativeFile)++-- ------------------------------------------------------------+-- * known preprocessors+-- ------------------------------------------------------------++ppGreenCard :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppGreenCard _ lbi _+ = PreProcessor {+ platformIndependent = False,+ runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->+ runDbProgram verbosity greencardProgram (withPrograms lbi)+ (["-tffi", "-o" ++ outFile, inFile])+ }++-- This one is useful for preprocessors that can't handle literate source.+-- We also need a way to chain preprocessors.+ppUnlit :: PreProcessor+ppUnlit =+ PreProcessor {+ platformIndependent = True,+ runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->+ withUTF8FileContents inFile $ \contents ->+ either (writeUTF8File outFile) (die' verbosity) (unlit inFile contents)+ }++ppCpp :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppCpp = ppCpp' []++ppCpp' :: [String] -> BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppCpp' extraArgs bi lbi clbi =+ case compilerFlavor (compiler lbi) of+ GHC -> ppGhcCpp ghcProgram (const True) args bi lbi clbi+ GHCJS -> ppGhcCpp ghcjsProgram (const True) args bi lbi clbi+ _ -> ppCpphs args bi lbi clbi+ where cppArgs = getCppOptions bi lbi+ args = cppArgs ++ extraArgs++ppGhcCpp :: Program -> (Version -> Bool)+ -> [String] -> BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppGhcCpp program xHs extraArgs _bi lbi clbi =+ PreProcessor {+ platformIndependent = False,+ runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity -> do+ (prog, version, _) <- requireProgramVersion verbosity+ program anyVersion (withPrograms lbi)+ runProgram verbosity prog $+ ["-E", "-cpp"]+ -- This is a bit of an ugly hack. We're going to+ -- unlit the file ourselves later on if appropriate,+ -- so we need GHC not to unlit it now or it'll get+ -- double-unlitted. In the future we might switch to+ -- using cpphs --unlit instead.+ ++ (if xHs version then ["-x", "hs"] else [])+ ++ [ "-optP-include", "-optP"++ (autogenComponentModulesDir lbi clbi </> cppHeaderName) ]+ ++ ["-o", outFile, inFile]+ ++ extraArgs+ }++ppCpphs :: [String] -> BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppCpphs extraArgs _bi lbi clbi =+ PreProcessor {+ platformIndependent = False,+ runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity -> do+ (cpphsProg, cpphsVersion, _) <- requireProgramVersion verbosity+ cpphsProgram anyVersion (withPrograms lbi)+ runProgram verbosity cpphsProg $+ ("-O" ++ outFile) : inFile+ : "--noline" : "--strip"+ : (if cpphsVersion >= mkVersion [1,6]+ then ["--include="++ (autogenComponentModulesDir lbi clbi </> cppHeaderName)]+ else [])+ ++ extraArgs+ }++ppHsc2hs :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppHsc2hs bi lbi clbi =+ PreProcessor {+ platformIndependent = False,+ runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity -> do+ (gccProg, _) <- requireProgram verbosity gccProgram (withPrograms lbi)+ (hsc2hsProg, hsc2hsVersion, _) <- requireProgramVersion verbosity+ hsc2hsProgram anyVersion (withPrograms lbi)+ -- See Trac #13896 and https://github.com/haskell/cabal/issues/3122.+ let isCross = hostPlatform lbi /= buildPlatform+ prependCrossFlags = if isCross then ("-x":) else id+ let hsc2hsSupportsResponseFiles = hsc2hsVersion >= mkVersion [0,68,4]+ pureArgs = genPureArgs hsc2hsVersion gccProg inFile outFile+ if hsc2hsSupportsResponseFiles+ then withResponseFile+ verbosity+ defaultTempFileOptions+ (takeDirectory outFile)+ "hsc2hs-response.txt"+ Nothing+ pureArgs+ (\responseFileName ->+ runProgram verbosity hsc2hsProg (prependCrossFlags ["@"++ responseFileName]))+ else runProgram verbosity hsc2hsProg (prependCrossFlags pureArgs)+ }+ where+ -- Returns a list of command line arguments that can either be passed+ -- directly, or via a response file.+ genPureArgs :: Version -> ConfiguredProgram -> String -> String -> [String]+ genPureArgs hsc2hsVersion gccProg inFile outFile =+ -- Additional gcc options+ [ "--cflag=" ++ opt | opt <- programDefaultArgs gccProg+ ++ programOverrideArgs gccProg ]+ ++ [ "--lflag=" ++ opt | opt <- programDefaultArgs gccProg+ ++ programOverrideArgs gccProg ]++ -- OSX frameworks:+ ++ [ what ++ "=-F" ++ opt+ | isOSX+ , opt <- nub (concatMap Installed.frameworkDirs pkgs)+ , what <- ["--cflag", "--lflag"] ]+ ++ [ "--lflag=" ++ arg+ | isOSX+ , opt <- PD.frameworks bi ++ concatMap Installed.frameworks pkgs+ , arg <- ["-framework", opt] ]++ -- Note that on ELF systems, wherever we use -L, we must also use -R+ -- because presumably that -L dir is not on the normal path for the+ -- system's dynamic linker. This is needed because hsc2hs works by+ -- compiling a C program and then running it.++ ++ [ "--cflag=" ++ opt | opt <- platformDefines lbi ]++ -- Options from the current package:+ ++ [ "--cflag=-I" ++ dir | dir <- PD.includeDirs bi ]+ ++ [ "--cflag=-I" ++ buildDir lbi </> dir | dir <- PD.includeDirs bi ]+ ++ [ "--cflag=" ++ opt | opt <- PD.ccOptions bi+ ++ PD.cppOptions bi+ -- hsc2hs uses the C ABI+ -- We assume that there are only C sources+ -- and C++ functions are exported via a C+ -- interface and wrapped in a C source file.+ -- Therefore we do not supply C++ flags+ -- because there will not be C++ sources.+ --+ -- DO NOT add PD.cxxOptions unless this changes!+ ]+ ++ [ "--cflag=" ++ opt | opt <-+ [ "-I" ++ autogenComponentModulesDir lbi clbi,+ "-I" ++ autogenPackageModulesDir lbi,+ "-include", autogenComponentModulesDir lbi clbi </> cppHeaderName ] ]+ ++ [ "--lflag=-L" ++ opt | opt <- PD.extraLibDirs bi ]+ ++ [ "--lflag=-Wl,-R," ++ opt | isELF+ , opt <- PD.extraLibDirs bi ]+ ++ [ "--lflag=-l" ++ opt | opt <- PD.extraLibs bi ]+ ++ [ "--lflag=" ++ opt | opt <- PD.ldOptions bi ]++ -- Options from dependent packages+ ++ [ "--cflag=" ++ opt+ | pkg <- pkgs+ , opt <- [ "-I" ++ opt | opt <- Installed.includeDirs pkg ]+ ++ [ opt | opt <- Installed.ccOptions pkg ] ]+ ++ [ "--lflag=" ++ opt+ | pkg <- pkgs+ , opt <- [ "-L" ++ opt | opt <- Installed.libraryDirs pkg ]+ ++ [ "-Wl,-R," ++ opt | isELF+ , opt <- Installed.libraryDirs pkg ]+ ++ [ "-l" ++ opt | opt <- Installed.extraLibraries pkg ]+ ++ [ opt | opt <- Installed.ldOptions pkg ] ]+ ++ preccldFlags+ ++ hsc2hsOptions bi+ ++ postccldFlags++ ++ ["-o", outFile, inFile]+ where+ -- hsc2hs flag parsing was wrong+ -- (see -- https://github.com/haskell/hsc2hs/issues/35)+ -- so we need to put -- --cc/--ld *after* hsc2hsOptions,+ -- for older hsc2hs (pre 0.68.8) so that they can be overridden.+ ccldFlags =+ [ "--cc=" ++ programPath gccProg+ , "--ld=" ++ programPath gccProg+ ]++ (preccldFlags, postccldFlags)+ | hsc2hsVersion >= mkVersion [0,68,8] = (ccldFlags, [])+ | otherwise = ([], ccldFlags)++ hacked_index = packageHacks (installedPkgs lbi)+ -- Look only at the dependencies of the current component+ -- being built! This relies on 'installedPkgs' maintaining+ -- 'InstalledPackageInfo' for internal deps too; see #2971.+ pkgs = PackageIndex.topologicalOrder $+ case PackageIndex.dependencyClosure hacked_index+ (map fst (componentPackageDeps clbi)) of+ Left index' -> index'+ Right inf ->+ error ("ppHsc2hs: broken closure: " ++ show inf)+ isOSX = case buildOS of OSX -> True; _ -> False+ isELF = case buildOS of OSX -> False; Windows -> False; AIX -> False; _ -> True;+ packageHacks = case compilerFlavor (compiler lbi) of+ GHC -> hackRtsPackage+ GHCJS -> hackRtsPackage+ _ -> id+ -- We don't link in the actual Haskell libraries of our dependencies, so+ -- the -u flags in the ldOptions of the rts package mean linking fails on+ -- OS X (its ld is a tad stricter than gnu ld). Thus we remove the+ -- ldOptions for GHC's rts package:+ hackRtsPackage index =+ case PackageIndex.lookupPackageName index (mkPackageName "rts") of+ [(_, [rts])]+ -> 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 -> ComponentLocalBuildInfo -> PreProcessor+ppC2hs bi lbi clbi =+ PreProcessor {+ platformIndependent = False,+ runPreProcessor = \(inBaseDir, inRelativeFile)+ (outBaseDir, outRelativeFile) verbosity -> do+ (c2hsProg, _, _) <- requireProgramVersion verbosity+ c2hsProgram (orLaterVersion (mkVersion [0,15]))+ (withPrograms lbi)+ (gccProg, _) <- requireProgram verbosity gccProgram (withPrograms lbi)+ runProgram verbosity c2hsProg $++ -- Options from the current package:+ [ "--cpp=" ++ programPath gccProg, "--cppopts=-E" ]+ ++ [ "--cppopts=" ++ opt | opt <- getCppOptions bi lbi ]+ ++ [ "--cppopts=-include" ++ (autogenComponentModulesDir lbi clbi </> cppHeaderName) ]+ ++ [ "--include=" ++ outBaseDir ]++ -- Options from dependent packages+ ++ [ "--cppopts=" ++ opt+ | pkg <- pkgs+ , opt <- [ "-I" ++ opt | opt <- Installed.includeDirs pkg ]+ ++ [ opt | opt@('-':c:_) <- Installed.ccOptions pkg+ -- c2hs uses the C ABI+ -- We assume that there are only C sources+ -- and C++ functions are exported via a C+ -- interface and wrapped in a C source file.+ -- Therefore we do not supply C++ flags+ -- because there will not be C++ sources.+ --+ --+ -- DO NOT add Installed.cxxOptions unless this changes!+ , c `elem` "DIU" ] ]+ --TODO: install .chi files for packages, so we can --include+ -- those dirs here, for the dependencies++ -- input and output files+ ++ [ "--output-dir=" ++ outBaseDir+ , "--output=" ++ outRelativeFile+ , inBaseDir </> inRelativeFile ]+ }+ 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+--TODO: Refactor and add separate getCppOptionsForHs, getCppOptionsForCxx, & getCppOptionsForC+-- instead of combining all these cases in a single function. This blind combination can+-- potentially lead to compilation inconsistencies.+getCppOptions :: BuildInfo -> LocalBuildInfo -> [String]+getCppOptions bi lbi+ = platformDefines lbi+ ++ cppOptions bi+ ++ ["-I" ++ dir | dir <- PD.includeDirs bi]+ ++ [opt | opt@('-':c:_) <- PD.ccOptions bi ++ PD.cxxOptions bi, c `elem` "DIU"]++platformDefines :: LocalBuildInfo -> [String]+platformDefines lbi =+ case compilerFlavor comp of+ GHC ->+ ["-D__GLASGOW_HASKELL__=" ++ versionInt version] +++ ["-D" ++ os ++ "_BUILD_OS=1"] +++ ["-D" ++ arch ++ "_BUILD_ARCH=1"] +++ map (\os' -> "-D" ++ os' ++ "_HOST_OS=1") osStr +++ map (\arch' -> "-D" ++ arch' ++ "_HOST_ARCH=1") archStr+ GHCJS ->+ compatGlasgowHaskell +++ ["-D__GHCJS__=" ++ versionInt version] +++ ["-D" ++ os ++ "_BUILD_OS=1"] +++ ["-D" ++ arch ++ "_BUILD_ARCH=1"] +++ map (\os' -> "-D" ++ os' ++ "_HOST_OS=1") osStr +++ map (\arch' -> "-D" ++ arch' ++ "_HOST_ARCH=1") archStr+ HaskellSuite {} ->+ ["-D__HASKELL_SUITE__"] +++ map (\os' -> "-D" ++ os' ++ "_HOST_OS=1") osStr +++ map (\arch' -> "-D" ++ arch' ++ "_HOST_ARCH=1") archStr+ _ -> []+ where+ comp = compiler lbi+ Platform hostArch hostOS = hostPlatform lbi+ version = compilerVersion comp+ compatGlasgowHaskell =+ maybe [] (\v -> ["-D__GLASGOW_HASKELL__=" ++ versionInt v])+ (compilerCompatVersion GHC comp)+ -- TODO: move this into the compiler abstraction+ -- FIXME: this forces GHC's crazy 4.8.2 -> 408 convention on all+ -- the other compilers. Check if that's really what they want.+ versionInt :: Version -> String+ versionInt v = case versionNumbers v of+ [] -> "1"+ [n] -> show n+ n1:n2:_ ->+ -- 6.8.x -> 608+ -- 6.10.x -> 610+ let s1 = show n1+ s2 = show n2+ middle = case s2 of+ _ : _ : _ -> ""+ _ -> "0"+ in s1 ++ middle ++ s2++ osStr = case hostOS of+ Linux -> ["linux"]+ Windows -> ["mingw32"]+ OSX -> ["darwin"]+ FreeBSD -> ["freebsd"]+ OpenBSD -> ["openbsd"]+ NetBSD -> ["netbsd"]+ DragonFly -> ["dragonfly"]+ Solaris -> ["solaris2"]+ AIX -> ["aix"]+ HPUX -> ["hpux"]+ IRIX -> ["irix"]+ HaLVM -> []+ IOS -> ["ios"]+ Android -> ["android"]+ Ghcjs -> ["ghcjs"]+ Hurd -> ["hurd"]+ OtherOS _ -> []+ archStr = case hostArch of+ I386 -> ["i386"]+ X86_64 -> ["x86_64"]+ PPC -> ["powerpc"]+ PPC64 -> ["powerpc64"]+ Sparc -> ["sparc"]+ Arm -> ["arm"]+ AArch64 -> ["aarch64"]+ Mips -> ["mips"]+ SH -> []+ IA64 -> ["ia64"]+ S390 -> ["s390"]+ Alpha -> ["alpha"]+ Hppa -> ["hppa"]+ Rs6000 -> ["rs6000"]+ M68k -> ["m68k"]+ Vax -> ["vax"]+ JavaScript -> ["javascript"]+ OtherArch _ -> []++ppHappy :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppHappy _ lbi _ = pp { platformIndependent = True }+ where pp = standardPP lbi happyProgram (hcFlags hc)+ hc = compilerFlavor (compiler lbi)+ hcFlags GHC = ["-agc"]+ hcFlags GHCJS = ["-agc"]+ hcFlags _ = []++ppAlex :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor+ppAlex _ lbi _ = pp { platformIndependent = True }+ where pp = standardPP lbi alexProgram (hcFlags hc)+ hc = compilerFlavor (compiler lbi)+ hcFlags GHC = ["-g"]+ hcFlags GHCJS = ["-g"]+ hcFlags _ = []++standardPP :: LocalBuildInfo -> Program -> [String] -> PreProcessor+standardPP lbi prog args =+ PreProcessor {+ platformIndependent = False,+ runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->+ runDbProgram verbosity prog (withPrograms lbi)+ (args ++ ["-o", outFile, inFile])+ }++-- |Convenience function; get the suffixes of these preprocessors.+ppSuffixes :: [ PPSuffixHandler ] -> [String]+ppSuffixes = map fst++-- |Standard preprocessors: GreenCard, c2hs, hsc2hs, happy, alex and cpphs.+knownSuffixHandlers :: [ PPSuffixHandler ]+knownSuffixHandlers =+ [ ("gc", ppGreenCard)+ , ("chs", ppC2hs)+ , ("hsc", ppHsc2hs)+ , ("x", ppAlex)+ , ("y", ppHappy)+ , ("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 :: Verbosity+ -> Component+ -> LocalBuildInfo+ -> IO [FilePath]+preprocessExtras verbosity comp lbi = case comp of+ CLib _ -> pp $ buildDir lbi+ (CExe Executable { exeName = nm }) -> do+ let nm' = unUnqualComponentName nm+ pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"+ (CFLib ForeignLib { foreignLibName = nm }) -> do+ let nm' = unUnqualComponentName nm+ pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"+ CTest test -> do+ let nm' = unUnqualComponentName $ testName test+ case testInterface test of+ TestSuiteExeV10 _ _ ->+ pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"+ TestSuiteLibV09 _ _ ->+ pp $ buildDir lbi </> stubName test </> stubName test ++ "-tmp"+ TestSuiteUnsupported tt ->+ die' verbosity $ "No support for preprocessing test suite type " +++ prettyShow tt+ CBench bm -> do+ let nm' = unUnqualComponentName $ benchmarkName bm+ case benchmarkInterface bm of+ BenchmarkExeV10 _ _ ->+ pp $ buildDir lbi </> nm' </> nm' ++ "-tmp"+ BenchmarkUnsupported tt ->+ die' verbosity $ "No support for preprocessing benchmark "+ ++ "type " ++ prettyShow tt+ where+ pp :: FilePath -> IO [FilePath]+ pp dir = (map (dir </>) . filter not_sub . concat)+ <$> for knownExtrasHandlers+ (withLexicalCallStack (\f -> f dir))+ -- TODO: This is a terrible hack to work around #3545 while we don't+ -- reorganize the directory layout. Basically, for the main+ -- library, we might accidentally pick up autogenerated sources for+ -- our subcomponents, because they are all stored as subdirectories+ -- in dist/build. This is a cheap and cheerful check to prevent+ -- this from happening. It is not particularly correct; for example+ -- if a user has a test suite named foobar and puts their C file in+ -- foobar/foo.c, this test will incorrectly exclude it. But I+ -- didn't want to break BC...+ not_sub p = and [ not (pre `isPrefixOf` p) | pre <- component_dirs ]+ component_dirs = component_names (localPkgDescr lbi)+ -- TODO: libify me+ component_names pkg_descr = fmap unUnqualComponentName $+ mapMaybe (libraryNameString . libName) (subLibraries pkg_descr) +++ map exeName (executables pkg_descr) +++ map testName (testSuites pkg_descr) +++ map benchmarkName (benchmarks pkg_descr)
+ src/Distribution/Simple/PreProcess/Unlit.hs view
@@ -0,0 +1,167 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.PreProcess.Unlit+-- Copyright : ...+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Remove the \"literal\" markups from a Haskell source file, including+-- \"@>@\", \"@\\begin{code}@\", \"@\\end{code}@\", and \"@#@\"++-- This version is interesting because instead of striping comment lines, it+-- turns them into "-- " style comments. This allows using haddock markup+-- in literate scripts without having to use "> --" prefix.++module Distribution.Simple.PreProcess.Unlit (unlit,plain) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.Generic (safeTail, safeLast, safeInit)++import Data.List (mapAccumL)++data Classified = BirdTrack String | Blank String | Ordinary String+ | Line !Int String | CPP String+ | BeginCode | EndCode+ -- output only:+ | Error String | Comment String++-- | No unliteration.+plain :: String -> String -> String+plain _ hs = hs++classify :: String -> Classified+classify ('>':s) = BirdTrack s+classify ('#':s) = case tokens s of+ (line:file@('"':_:_):_) | all isDigit line+ && safeLast file == Just '"'+ -- this shouldn't fail as we tested for 'all isDigit'+ -> Line (fromMaybe (error $ "panic! read @Int " ++ show line) $ readMaybe line) (safeTail (safeInit file)) -- TODO:eradicateNoParse+ _ -> CPP s+ where tokens = unfoldr $ \str -> case lex str of+ (t@(_:_), str'):_ -> Just (t, str')+ _ -> Nothing+classify ('\\':s)+ | "begin{code}" `isPrefixOf` s = BeginCode+ | "end{code}" `isPrefixOf` s = EndCode+classify s | all isSpace s = Blank s+classify s = Ordinary s++-- So the weird exception for comment indenting is to make things work with+-- haddock, see classifyAndCheckForBirdTracks below.+unclassify :: Bool -> Classified -> String+unclassify _ (BirdTrack s) = ' ':s+unclassify _ (Blank s) = s+unclassify _ (Ordinary s) = s+unclassify _ (Line n file) = "# " ++ show n ++ " " ++ show file+unclassify _ (CPP s) = '#':s+unclassify True (Comment "") = " --"+unclassify True (Comment s) = " -- " ++ s+unclassify False (Comment "") = "--"+unclassify False (Comment s) = "-- " ++ s+unclassify _ _ = internalError++-- | 'unlit' takes a filename (for error reports), and transforms the+-- given string, to eliminate the literate comments from the program text.+unlit :: FilePath -> String -> Either String String+unlit file input =+ let (usesBirdTracks, classified) = classifyAndCheckForBirdTracks+ . inlines+ $ input+ in either (Left . unlines . map (unclassify usesBirdTracks))+ Right+ . checkErrors+ . reclassify+ $ classified++ where+ -- So haddock requires comments and code to align, since it treats comments+ -- as following the layout rule. This is a pain for us since bird track+ -- style literate code typically gets indented by two since ">" is replaced+ -- by " " and people usually use one additional space of indent ie+ -- "> then the code". On the other hand we cannot just go and indent all+ -- the comments by two since that does not work for latex style literate+ -- code. So the hacky solution we use here is that if we see any bird track+ -- style code then we'll indent all comments by two, otherwise by none.+ -- Of course this will not work for mixed latex/bird track .lhs files but+ -- nobody does that, it's silly and specifically recommended against in the+ -- H98 unlit spec.+ --+ classifyAndCheckForBirdTracks =+ flip mapAccumL False $ \seenBirdTrack line ->+ let classification = classify line+ in (seenBirdTrack || isBirdTrack classification, classification)++ isBirdTrack (BirdTrack _) = True+ isBirdTrack _ = False++ checkErrors ls = case [ e | Error e <- ls ] of+ [] -> Left ls+ (message:_) -> Right (f ++ ":" ++ show n ++ ": " ++ message)+ where (f, n) = errorPos file 1 ls+ errorPos f n [] = (f, n)+ errorPos f n (Error _:_) = (f, n)+ errorPos _ _ (Line n' f':ls) = errorPos f' n' ls+ errorPos f n (_ :ls) = errorPos f (n+1) ls++-- Here we model a state machine, with each state represented by+-- a local function. We only have four states (well, five,+-- if you count the error state), but the rules+-- to transition between then are not so simple.+-- Would it be simpler to have more states?+--+-- Each state represents the type of line that was last read+-- i.e. are we in a comment section, or a latex-code section,+-- or a bird-code section, etc?+reclassify :: [Classified] -> [Classified]+reclassify = blank -- begin in blank state+ where+ latex [] = []+ latex (EndCode :ls) = Blank "" : comment ls+ latex (BeginCode :_ ) = [Error "\\begin{code} in code section"]+ latex (BirdTrack l:ls) = Ordinary ('>':l) : latex ls+ latex ( l:ls) = l : latex ls++ blank [] = []+ blank (EndCode :_ ) = [Error "\\end{code} without \\begin{code}"]+ blank (BeginCode :ls) = Blank "" : latex ls+ blank (BirdTrack l:ls) = BirdTrack l : bird ls+ blank (Ordinary l:ls) = Comment l : comment ls+ blank ( l:ls) = l : blank ls++ bird [] = []+ bird (EndCode :_ ) = [Error "\\end{code} without \\begin{code}"]+ bird (BeginCode :ls) = Blank "" : latex ls+ bird (Blank l :ls) = Blank l : blank ls+ bird (Ordinary _:_ ) = [Error "program line before comment line"]+ bird ( l:ls) = l : bird ls++ comment [] = []+ comment (EndCode :_ ) = [Error "\\end{code} without \\begin{code}"]+ comment (BeginCode :ls) = Blank "" : latex ls+ comment (CPP l :ls) = CPP l : comment ls+ comment (BirdTrack _:_ ) = [Error "comment line before program line"]+ -- a blank line and another ordinary line following a comment+ -- will be treated as continuing the comment. Otherwise it's+ -- then end of the comment, with a blank line.+ comment (Blank l:ls@(Ordinary _:_)) = Comment l : comment ls+ comment (Blank l:ls) = Blank l : blank ls+ comment (Line n f :ls) = Line n f : comment ls+ comment (Ordinary l:ls) = Comment l : comment ls+ comment (Comment _: _) = internalError+ comment (Error _: _) = internalError++-- Re-implementation of 'lines', for better efficiency (but decreased laziness).+-- Also, importantly, accepts non-standard DOS and Mac line ending characters.+inlines :: String -> [String]+inlines xs = lines' xs id+ where+ lines' [] acc = [acc []]+ lines' ('\^M':'\n':s) acc = acc [] : lines' s id -- DOS+ lines' ('\^M':s) acc = acc [] : lines' s id -- MacOS+ lines' ('\n':s) acc = acc [] : lines' s id -- Unix+ lines' (c:s) acc = lines' s (acc . (c:))++internalError :: a+internalError = error "unlit: internal error"
+ src/Distribution/Simple/Program.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program+-- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This provides an abstraction which deals with configuring and running+-- programs. A 'Program' is a static notion of a known program. A+-- 'ConfiguredProgram' is a 'Program' that has been found on the current+-- machine and is ready to be run (possibly with some user-supplied default+-- args). Configuring a program involves finding its location and if necessary+-- finding its version. There is also a 'ProgramDb' type which holds+-- configured and not-yet configured programs. It is the parameter to lots of+-- actions elsewhere in Cabal that need to look up and run programs. If we had+-- a Cabal monad, the 'ProgramDb' would probably be a reader or+-- state component of it.+--+-- The module also defines all the known built-in 'Program's and the+-- 'defaultProgramDb' which contains them all.+--+-- One nice thing about using it is that any program that is+-- registered with Cabal will get some \"configure\" and \".cabal\"+-- helpers like --with-foo-args --foo-path= and extra-foo-args.+--+-- There's also good default behavior for trying to find \"foo\" in+-- PATH, being able to override its location, etc.+--+-- There's also a hook for adding programs in a Setup.lhs script. See+-- hookedPrograms in 'Distribution.Simple.UserHooks'. This gives a+-- hook user the ability to get the above flags and such so that they+-- don't have to write all the PATH logic inside Setup.lhs.++module Distribution.Simple.Program (+ -- * Program and functions for constructing them+ Program(..)+ , ProgramSearchPath+ , ProgramSearchPathEntry(..)+ , simpleProgram+ , findProgramOnSearchPath+ , defaultProgramSearchPath+ , findProgramVersion++ -- * Configured program and related functions+ , ConfiguredProgram(..)+ , programPath+ , ProgArg+ , ProgramLocation(..)+ , runProgram+ , getProgramOutput+ , suppressOverrideArgs++ -- * Program invocations+ , ProgramInvocation(..)+ , emptyProgramInvocation+ , simpleProgramInvocation+ , programInvocation+ , runProgramInvocation+ , getProgramInvocationOutput+ , getProgramInvocationLBS++ -- * The collection of unconfigured and configured programs+ , builtinPrograms++ -- * The collection of configured programs we can run+ , ProgramDb+ , defaultProgramDb+ , emptyProgramDb+ , restoreProgramDb+ , addKnownProgram+ , addKnownPrograms+ , lookupKnownProgram+ , knownPrograms+ , getProgramSearchPath+ , setProgramSearchPath+ , userSpecifyPath+ , userSpecifyPaths+ , userMaybeSpecifyPath+ , userSpecifyArgs+ , userSpecifyArgss+ , userSpecifiedArgs+ , lookupProgram+ , lookupProgramVersion+ , updateProgram+ , configureProgram+ , configureAllKnownPrograms+ , reconfigurePrograms+ , requireProgram+ , requireProgramVersion+ , needProgram+ , runDbProgram+ , getDbProgramOutput++ -- * Programs that Cabal knows about+ , ghcProgram+ , ghcPkgProgram+ , ghcjsProgram+ , ghcjsPkgProgram+ , hmakeProgram+ , jhcProgram+ , uhcProgram+ , gccProgram+ , arProgram+ , stripProgram+ , happyProgram+ , alexProgram+ , hsc2hsProgram+ , c2hsProgram+ , cpphsProgram+ , hscolourProgram+ , doctestProgram+ , haddockProgram+ , greencardProgram+ , ldProgram+ , tarProgram+ , cppProgram+ , pkgConfigProgram+ , hpcProgram+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.Program.Types+import Distribution.Simple.Program.Run+import Distribution.Simple.Program.Db+import Distribution.Simple.Program.Builtin+import Distribution.Simple.Program.Find+import Distribution.Simple.Utils+import Distribution.Verbosity++-- | Runs the given configured program.+runProgram :: Verbosity -- ^Verbosity+ -> ConfiguredProgram -- ^The program to run+ -> [ProgArg] -- ^Any /extra/ arguments to add+ -> IO ()+runProgram verbosity prog args =+ runProgramInvocation verbosity (programInvocation prog args)+++-- | Runs the given configured program and gets the output.+--+getProgramOutput :: Verbosity -- ^Verbosity+ -> ConfiguredProgram -- ^The program to run+ -> [ProgArg] -- ^Any /extra/ arguments to add+ -> IO String+getProgramOutput verbosity prog args =+ getProgramInvocationOutput verbosity (programInvocation prog args)+++-- | Looks up the given program in the program database and runs it.+--+runDbProgram :: Verbosity -- ^verbosity+ -> Program -- ^The program to run+ -> ProgramDb -- ^look up the program here+ -> [ProgArg] -- ^Any /extra/ arguments to add+ -> IO ()+runDbProgram verbosity prog programDb args =+ case lookupProgram prog programDb of+ Nothing -> die' verbosity notFound+ Just configuredProg -> runProgram verbosity configuredProg args+ where+ notFound = "The program '" ++ programName prog+ ++ "' is required but it could not be found"++-- | Looks up the given program in the program database and runs it.+--+getDbProgramOutput :: Verbosity -- ^verbosity+ -> Program -- ^The program to run+ -> ProgramDb -- ^look up the program here+ -> [ProgArg] -- ^Any /extra/ arguments to add+ -> IO String+getDbProgramOutput verbosity prog programDb args =+ case lookupProgram prog programDb of+ Nothing -> die' verbosity notFound+ Just configuredProg -> getProgramOutput verbosity configuredProg args+ where+ notFound = "The program '" ++ programName prog+ ++ "' is required but it could not be found"
+ src/Distribution/Simple/Program/Ar.hs view
@@ -0,0 +1,191 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE NondecreasingIndentation #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Ar+-- Copyright : Duncan Coutts 2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides an library interface to the @ar@ program.++module Distribution.Simple.Program.Ar (+ createArLibArchive,+ multiStageProgramInvocation+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS8+import Distribution.Compat.CopyFile (filesEqual)+import Distribution.Simple.Compiler (arResponseFilesSupported)+import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))+import Distribution.Simple.Program+ ( ProgramInvocation, arProgram, requireProgram )+import Distribution.Simple.Program.ResponseFile+ ( withResponseFile )+import Distribution.Simple.Program.Run+ ( programInvocation, multiStageProgramInvocation+ , runProgramInvocation )+import Distribution.Simple.Setup+ ( fromFlagOrDefault, configUseResponseFiles )+import Distribution.Simple.Utils+ ( defaultTempFileOptions, dieWithLocation', withTempDirectory )+import Distribution.System+ ( Arch(..), OS(..), Platform(..) )+import Distribution.Verbosity+ ( Verbosity, deafening, verbose )+import System.Directory (doesFileExist, renameFile)+import System.FilePath ((</>), splitFileName)+import System.IO+ ( Handle, IOMode(ReadWriteMode), SeekMode(AbsoluteSeek)+ , hFileSize, hSeek, withBinaryFile )++-- | Call @ar@ to create a library archive from a bunch of object files.+--+createArLibArchive :: Verbosity -> LocalBuildInfo+ -> FilePath -> [FilePath] -> IO ()+createArLibArchive verbosity lbi targetPath files = do+ (ar, _) <- requireProgram verbosity arProgram progDb++ let (targetDir, targetName) = splitFileName targetPath+ withTempDirectory verbosity targetDir "objs" $ \ tmpDir -> do+ let tmpPath = tmpDir </> targetName++ -- The args to use with "ar" are actually rather subtle and system-dependent.+ -- In particular we have the following issues:+ --+ -- -- On OS X, "ar q" does not make an archive index. Archives with no+ -- index cannot be used.+ --+ -- -- GNU "ar r" will not let us add duplicate objects, only "ar q" lets us+ -- do that. We have duplicates because of modules like "A.M" and "B.M"+ -- both make an object file "M.o" and ar does not consider the directory.+ --+ -- Our solution is to use "ar r" in the simple case when one call is enough.+ -- When we need to call ar multiple times we use "ar q" and for the last+ -- call on OSX we use "ar qs" so that it'll make the index.++ let simpleArgs = case hostOS of+ OSX -> ["-r", "-s"]+ _ -> ["-r"]++ initialArgs = ["-q"]+ finalArgs = case hostOS of+ OSX -> ["-q", "-s"]+ _ -> ["-q"]++ extraArgs = verbosityOpts verbosity ++ [tmpPath]++ simple = programInvocation ar (simpleArgs ++ extraArgs)+ initial = programInvocation ar (initialArgs ++ extraArgs)+ middle = initial+ final = programInvocation ar (finalArgs ++ extraArgs)++ oldVersionManualOverride =+ fromFlagOrDefault False $ configUseResponseFiles $ configFlags lbi+ responseArgumentsNotSupported =+ not (arResponseFilesSupported (compiler lbi))++ invokeWithResponesFile :: FilePath -> ProgramInvocation+ invokeWithResponesFile atFile =+ programInvocation ar $+ simpleArgs ++ extraArgs ++ ['@' : atFile]++ if oldVersionManualOverride || responseArgumentsNotSupported+ then+ sequence_+ [ runProgramInvocation verbosity inv+ | inv <- multiStageProgramInvocation+ simple (initial, middle, final) files ]+ else+ withResponseFile verbosity defaultTempFileOptions tmpDir "ar.rsp" Nothing files $+ \path -> runProgramInvocation verbosity $ invokeWithResponesFile path++ unless (hostArch == Arm -- See #1537+ || hostOS == AIX) $ -- AIX uses its own "ar" format variant+ wipeMetadata verbosity tmpPath+ equal <- filesEqual tmpPath targetPath+ unless equal $ renameFile tmpPath targetPath++ where+ progDb = withPrograms lbi+ Platform hostArch hostOS = hostPlatform lbi+ verbosityOpts v+ | v >= deafening = ["-v"]+ | v >= verbose = []+ | otherwise = ["-c"] -- Do not warn if library had to be created.++-- | @ar@ by default includes various metadata for each object file in their+-- respective headers, so the output can differ for the same inputs, making+-- it difficult to avoid re-linking. GNU @ar@(1) has a deterministic mode+-- (@-D@) flag that always writes zero for the mtime, UID and GID, and 0644+-- for the file mode. However detecting whether @-D@ is supported seems+-- rather harder than just re-implementing this feature.+wipeMetadata :: Verbosity -> FilePath -> IO ()+wipeMetadata verbosity path = do+ -- Check for existence first (ReadWriteMode would create one otherwise)+ exists <- doesFileExist path+ unless exists $ wipeError "Temporary file disappeared"+ withBinaryFile path ReadWriteMode $ \ h -> hFileSize h >>= wipeArchive h++ where+ wipeError msg = dieWithLocation' verbosity path Nothing $+ "Distribution.Simple.Program.Ar.wipeMetadata: " ++ msg+ archLF = "!<arch>\x0a" -- global magic, 8 bytes+ x60LF = "\x60\x0a" -- header magic, 2 bytes+ metadata = BS.concat+ [ "0 " -- mtime, 12 bytes+ , "0 " -- UID, 6 bytes+ , "0 " -- GID, 6 bytes+ , "0644 " -- mode, 8 bytes+ ]+ headerSize :: Int+ headerSize = 60++ -- http://en.wikipedia.org/wiki/Ar_(Unix)#File_format_details+ wipeArchive :: Handle -> Integer -> IO ()+ wipeArchive h archiveSize = do+ global <- BS.hGet h (BS.length archLF)+ unless (global == archLF) $ wipeError "Bad global header"+ wipeHeader (toInteger $ BS.length archLF)++ where+ wipeHeader :: Integer -> IO ()+ wipeHeader offset = case compare offset archiveSize of+ EQ -> return ()+ GT -> wipeError (atOffset "Archive truncated")+ LT -> do+ header <- BS.hGet h headerSize+ unless (BS.length header == headerSize) $+ wipeError (atOffset "Short header")+ let magic = BS.drop 58 header+ unless (magic == x60LF) . wipeError . atOffset $+ "Bad magic " ++ show magic ++ " in header"++ let name = BS.take 16 header+ let size = BS.take 10 $ BS.drop 48 header+ objSize <- case reads (BS8.unpack size) of+ [(n, s)] | all isSpace s -> return n+ _ -> wipeError (atOffset "Bad file size in header")++ let replacement = BS.concat [ name, metadata, size, magic ]+ unless (BS.length replacement == headerSize) $+ wipeError (atOffset "Something has gone terribly wrong")+ hSeek h AbsoluteSeek offset+ BS.hPut h replacement++ let nextHeader = offset + toInteger headerSize ++ -- Odd objects are padded with an extra '\x0a'+ if odd objSize then objSize + 1 else objSize+ hSeek h AbsoluteSeek nextHeader+ wipeHeader nextHeader++ where+ atOffset msg = msg ++ " at offset " ++ show offset
+ src/Distribution/Simple/Program/Builtin.hs view
@@ -0,0 +1,348 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Builtin+-- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- The module defines all the known built-in 'Program's.+--+-- Where possible we try to find their version numbers.+--+module Distribution.Simple.Program.Builtin (++ -- * The collection of unconfigured and configured programs+ builtinPrograms,++ -- * Programs that Cabal knows about+ ghcProgram,+ ghcPkgProgram,+ runghcProgram,+ ghcjsProgram,+ ghcjsPkgProgram,+ hmakeProgram,+ jhcProgram,+ haskellSuiteProgram,+ haskellSuitePkgProgram,+ uhcProgram,+ gccProgram,+ arProgram,+ stripProgram,+ happyProgram,+ alexProgram,+ hsc2hsProgram,+ c2hsProgram,+ cpphsProgram,+ hscolourProgram,+ doctestProgram,+ haddockProgram,+ greencardProgram,+ ldProgram,+ tarProgram,+ cppProgram,+ pkgConfigProgram,+ hpcProgram,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.Program.GHC+import Distribution.Simple.Program.Find+import Distribution.Simple.Program.Internal+import Distribution.Simple.Program.Run+import Distribution.Simple.Program.Types+import Distribution.Simple.Utils+import Distribution.Verbosity+import Distribution.Version++import qualified Data.Map as Map++-- ------------------------------------------------------------+-- * Known programs+-- ------------------------------------------------------------++-- | The default list of programs.+-- These programs are typically used internally to Cabal.+builtinPrograms :: [Program]+builtinPrograms =+ [+ -- compilers and related progs+ ghcProgram+ , runghcProgram+ , ghcPkgProgram+ , ghcjsProgram+ , ghcjsPkgProgram+ , haskellSuiteProgram+ , haskellSuitePkgProgram+ , hmakeProgram+ , jhcProgram+ , uhcProgram+ , hpcProgram+ -- preprocessors+ , hscolourProgram+ , doctestProgram+ , haddockProgram+ , happyProgram+ , alexProgram+ , hsc2hsProgram+ , c2hsProgram+ , cpphsProgram+ , greencardProgram+ -- platform toolchain+ , gccProgram+ , arProgram+ , stripProgram+ , ldProgram+ , tarProgram+ -- configuration tools+ , pkgConfigProgram+ ]++ghcProgram :: Program+ghcProgram = (simpleProgram "ghc") {+ programFindVersion = findProgramVersion "--numeric-version" id,++ -- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/8825+ -- (spurious warning on non-english locales)+ programPostConf = \_verbosity ghcProg ->+ do let ghcProg' = ghcProg {+ programOverrideEnv = ("LANGUAGE", Just "en")+ : programOverrideEnv ghcProg+ }+ -- Only the 7.8 branch seems to be affected. Fixed in 7.8.4.+ affectedVersionRange = intersectVersionRanges+ (laterVersion $ mkVersion [7,8,0])+ (earlierVersion $ mkVersion [7,8,4])+ return $ maybe ghcProg+ (\v -> if withinRange v affectedVersionRange+ then ghcProg' else ghcProg)+ (programVersion ghcProg),++ programNormaliseArgs = normaliseGhcArgs+ }++runghcProgram :: Program+runghcProgram = (simpleProgram "runghc") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ case words str of+ -- "runghc 7.10.3"+ (_:ver:_) -> ver+ _ -> ""+ }++ghcPkgProgram :: Program+ghcPkgProgram = (simpleProgram "ghc-pkg") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- Invoking "ghc-pkg --version" gives a string like+ -- "GHC package manager version 6.4.1"+ case words str of+ (_:_:_:_:ver:_) -> ver+ _ -> ""+ }++ghcjsProgram :: Program+ghcjsProgram = (simpleProgram "ghcjs") {+ programFindVersion = findProgramVersion "--numeric-ghcjs-version" id+ }++-- note: version is the version number of the GHC version that ghcjs-pkg was built with+ghcjsPkgProgram :: Program+ghcjsPkgProgram = (simpleProgram "ghcjs-pkg") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- Invoking "ghcjs-pkg --version" gives a string like+ -- "GHCJS package manager version 6.4.1"+ case words str of+ (_:_:_:_:ver:_) -> ver+ _ -> ""+ }++hmakeProgram :: Program+hmakeProgram = (simpleProgram "hmake") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- Invoking "hmake --version" gives a string line+ -- "/usr/local/bin/hmake: 3.13 (2006-11-01)"+ case words str of+ (_:ver:_) -> ver+ _ -> ""+ }++jhcProgram :: Program+jhcProgram = (simpleProgram "jhc") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- invoking "jhc --version" gives a string like+ -- "jhc 0.3.20080208 (wubgipkamcep-2)+ -- compiled by ghc-6.8 on a x86_64 running linux"+ case words str of+ (_:ver:_) -> ver+ _ -> ""+ }++uhcProgram :: Program+uhcProgram = (simpleProgram "uhc") {+ programFindVersion = findProgramVersion "--version-dotted" id+ }++hpcProgram :: Program+hpcProgram = (simpleProgram "hpc")+ {+ programFindVersion = findProgramVersion "version" $ \str ->+ case words str of+ (_ : _ : _ : ver : _) -> ver+ _ -> ""+ }++-- This represents a haskell-suite compiler. Of course, the compiler+-- itself probably is not called "haskell-suite", so this is not a real+-- program. (But we don't know statically the name of the actual compiler,+-- so this is the best we can do.)+--+-- Having this Program value serves two purposes:+--+-- 1. We can accept options for the compiler in the form of+--+-- --haskell-suite-option(s)=...+--+-- 2. We can find a program later using this static id (with+-- requireProgram).+--+-- The path to the real compiler is found and recorded in the ProgramDb+-- during the configure phase.+haskellSuiteProgram :: Program+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", [])+ }++-- 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", [])+ }+++happyProgram :: Program+happyProgram = (simpleProgram "happy") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- Invoking "happy --version" gives a string like+ -- "Happy Version 1.16 Copyright (c) ...."+ case words str of+ (_:_:ver:_) -> ver+ _ -> ""+ }++alexProgram :: Program+alexProgram = (simpleProgram "alex") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- Invoking "alex --version" gives a string like+ -- "Alex version 2.1.0, (c) 2003 Chris Dornan and Simon Marlow"+ case words str of+ (_:_:ver:_) -> takeWhile (\x -> isDigit x || x == '.') ver+ _ -> ""+ }++gccProgram :: Program+gccProgram = (simpleProgram "gcc") {+ programFindVersion = findProgramVersion "-dumpversion" id+ }++arProgram :: Program+arProgram = simpleProgram "ar"++stripProgram :: Program+stripProgram = (simpleProgram "strip") {+ programFindVersion = \verbosity ->+ findProgramVersion "--version" stripExtractVersion (lessVerbose verbosity)+ }++hsc2hsProgram :: Program+hsc2hsProgram = (simpleProgram "hsc2hs") {+ programFindVersion =+ findProgramVersion "--version" $ \str ->+ -- Invoking "hsc2hs --version" gives a string like "hsc2hs version 0.66"+ case words str of+ (_:_:ver:_) -> ver+ _ -> ""+ }++c2hsProgram :: Program+c2hsProgram = (simpleProgram "c2hs") {+ programFindVersion = findProgramVersion "--numeric-version" id+ }++cpphsProgram :: Program+cpphsProgram = (simpleProgram "cpphs") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- Invoking "cpphs --version" gives a string like "cpphs 1.3"+ case words str of+ (_:ver:_) -> ver+ _ -> ""+ }++hscolourProgram :: Program+hscolourProgram = (simpleProgram "hscolour") {+ programFindLocation = \v p -> findProgramOnSearchPath v p "HsColour",+ programFindVersion = findProgramVersion "-version" $ \str ->+ -- Invoking "HsColour -version" gives a string like "HsColour 1.7"+ case words str of+ (_:ver:_) -> ver+ _ -> ""+ }++-- TODO: Ensure that doctest is built against the same GHC as the one+-- that's being used. Same for haddock. @phadej pointed this out.+doctestProgram :: Program+doctestProgram = (simpleProgram "doctest") {+ programFindLocation = \v p -> findProgramOnSearchPath v p "doctest"+ , programFindVersion = findProgramVersion "--version" $ \str ->+ -- "doctest version 0.11.2"+ case words str of+ (_:_:ver:_) -> ver+ _ -> ""+ }++haddockProgram :: Program+haddockProgram = (simpleProgram "haddock") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ -- Invoking "haddock --version" gives a string like+ -- "Haddock version 0.8, (c) Simon Marlow 2006"+ case words str of+ (_:_:ver:_) -> takeWhile (`elem` ('.':['0'..'9'])) ver+ _ -> "",++ programNormaliseArgs = \_ _ args -> args+ }++greencardProgram :: Program+greencardProgram = simpleProgram "greencard"++ldProgram :: Program+ldProgram = simpleProgram "ld"++tarProgram :: Program+tarProgram = (simpleProgram "tar") {+ -- See #1901. Some versions of 'tar' (OpenBSD, NetBSD, ...) don't support the+ -- '--format' option.+ programPostConf = \verbosity tarProg -> do+ tarHelpOutput <- getProgramInvocationOutput+ verbosity (programInvocation tarProg ["--help"])+ -- Some versions of tar don't support '--help'.+ `catchIO` (\_ -> return "")+ let k = "Supports --format"+ v = if ("--format" `isInfixOf` tarHelpOutput) then "YES" else "NO"+ m = Map.insert k v (programProperties tarProg)+ return $ tarProg { programProperties = m }+ }++cppProgram :: Program+cppProgram = simpleProgram "cpp"++pkgConfigProgram :: Program+pkgConfigProgram = (simpleProgram "pkg-config") {+ programFindVersion = findProgramVersion "--version" id+ }
+ src/Distribution/Simple/Program/Db.hs view
@@ -0,0 +1,505 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Db+-- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This provides a 'ProgramDb' type which holds configured and not-yet+-- configured programs. It is the parameter to lots of actions elsewhere in+-- Cabal that need to look up and run programs. If we had a Cabal monad,+-- the 'ProgramDb' would probably be a reader or state component of it.+--+-- One nice thing about using it is that any program that is+-- registered with Cabal will get some \"configure\" and \".cabal\"+-- helpers like --with-foo-args --foo-path= and extra-foo-args.+--+-- There's also a hook for adding programs in a Setup.lhs script. See+-- hookedPrograms in 'Distribution.Simple.UserHooks'. This gives a+-- hook user the ability to get the above flags and such so that they+-- don't have to write all the PATH logic inside Setup.lhs.++module Distribution.Simple.Program.Db (+ -- * The collection of configured programs we can run+ ProgramDb,+ emptyProgramDb,+ defaultProgramDb,+ restoreProgramDb,++ -- ** Query and manipulate the program db+ addKnownProgram,+ addKnownPrograms,+ lookupKnownProgram,+ knownPrograms,+ getProgramSearchPath,+ setProgramSearchPath,+ modifyProgramSearchPath,+ userSpecifyPath,+ userSpecifyPaths,+ userMaybeSpecifyPath,+ userSpecifyArgs,+ userSpecifyArgss,+ userSpecifiedArgs,+ lookupProgram,+ updateProgram,+ configuredPrograms,++ -- ** Query and manipulate the program db+ configureProgram,+ configureAllKnownPrograms,+ unconfigureProgram,+ lookupProgramVersion,+ reconfigurePrograms,+ requireProgram,+ requireProgramVersion,+ needProgram,++ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Pretty+import Distribution.Simple.Program.Builtin+import Distribution.Simple.Program.Find+import Distribution.Simple.Program.Types+import Distribution.Simple.Utils+import Distribution.Utils.Structured (Structure (..), Structured (..))+import Distribution.Verbosity+import Distribution.Version++import Data.Tuple (swap)++import qualified Data.Map as Map++-- ------------------------------------------------------------+-- * Programs database+-- ------------------------------------------------------------++-- | The configuration is a collection of information about programs. It+-- contains information both about configured programs and also about programs+-- that we are yet to configure.+--+-- The idea is that we start from a collection of unconfigured programs and one+-- by one we try to configure them at which point we move them into the+-- configured collection. For unconfigured programs we record not just the+-- 'Program' but also any user-provided arguments and location for the program.+data ProgramDb = ProgramDb {+ unconfiguredProgs :: UnconfiguredProgs,+ progSearchPath :: ProgramSearchPath,+ configuredProgs :: ConfiguredProgs+ }+ deriving (Typeable)++type UnconfiguredProgram = (Program, Maybe FilePath, [ProgArg])+type UnconfiguredProgs = Map.Map String UnconfiguredProgram+type ConfiguredProgs = Map.Map String ConfiguredProgram+++emptyProgramDb :: ProgramDb+emptyProgramDb = ProgramDb Map.empty defaultProgramSearchPath Map.empty++defaultProgramDb :: ProgramDb+defaultProgramDb = restoreProgramDb builtinPrograms emptyProgramDb+++-- internal helpers:+updateUnconfiguredProgs :: (UnconfiguredProgs -> UnconfiguredProgs)+ -> ProgramDb -> ProgramDb+updateUnconfiguredProgs update progdb =+ progdb { unconfiguredProgs = update (unconfiguredProgs progdb) }++updateConfiguredProgs :: (ConfiguredProgs -> ConfiguredProgs)+ -> ProgramDb -> ProgramDb+updateConfiguredProgs update progdb =+ progdb { configuredProgs = update (configuredProgs progdb) }+++-- Read & Show instances are based on listToFM++-- | 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 db = do+ put (progSearchPath db)+ put (configuredProgs db)++ get = do+ searchpath <- get+ progs <- get+ return $! emptyProgramDb {+ progSearchPath = searchpath,+ configuredProgs = progs+ }++instance Structured ProgramDb where+ structure p = Nominal (typeRep p) 0 "ProgramDb"+ [ structure (Proxy :: Proxy ProgramSearchPath)+ , structure (Proxy :: Proxy ConfiguredProgs)+ ]+++-- | 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.+--+restoreProgramDb :: [Program] -> ProgramDb -> ProgramDb+restoreProgramDb = addKnownPrograms+++-- -------------------------------+-- Managing unconfigured programs++-- | Add a known program that we may configure later+--+addKnownProgram :: Program -> ProgramDb -> ProgramDb+addKnownProgram prog = updateUnconfiguredProgs $+ Map.insertWith combine (programName prog) (prog, Nothing, [])+ where combine _ (_, path, args) = (prog, path, args)+++addKnownPrograms :: [Program] -> ProgramDb -> ProgramDb+addKnownPrograms progs progdb = foldl' (flip addKnownProgram) progdb progs+++lookupKnownProgram :: String -> ProgramDb -> Maybe Program+lookupKnownProgram name =+ fmap (\(p,_,_)->p) . Map.lookup name . unconfiguredProgs+++knownPrograms :: ProgramDb -> [(Program, Maybe ConfiguredProgram)]+knownPrograms progdb =+ [ (p,p') | (p,_,_) <- Map.elems (unconfiguredProgs progdb)+ , let p' = Map.lookup (programName p) (configuredProgs progdb) ]++-- | Get the current 'ProgramSearchPath' used by the 'ProgramDb'.+-- This is the default list of locations where programs are looked for when+-- configuring them. This can be overridden for specific programs (with+-- 'userSpecifyPath'), and specific known programs can modify or ignore this+-- search path in their own configuration code.+--+getProgramSearchPath :: ProgramDb -> ProgramSearchPath+getProgramSearchPath = progSearchPath++-- | Change the current 'ProgramSearchPath' used by the 'ProgramDb'.+-- This will affect programs that are configured from here on, so you+-- should usually set it before configuring any programs.+--+setProgramSearchPath :: ProgramSearchPath -> ProgramDb -> ProgramDb+setProgramSearchPath searchpath db = db { progSearchPath = searchpath }++-- | Modify the current 'ProgramSearchPath' used by the 'ProgramDb'.+-- This will affect programs that are configured from here on, so you+-- should usually modify it before configuring any programs.+--+modifyProgramSearchPath :: (ProgramSearchPath -> ProgramSearchPath)+ -> ProgramDb+ -> ProgramDb+modifyProgramSearchPath f db =+ setProgramSearchPath (f $ getProgramSearchPath db) db++-- |User-specify this path. Basically override any path information+-- for this program in the configuration. If it's not a known+-- program ignore it.+--+userSpecifyPath :: String -- ^Program name+ -> FilePath -- ^user-specified path to the program+ -> ProgramDb -> ProgramDb+userSpecifyPath name path = updateUnconfiguredProgs $+ flip Map.update name $ \(prog, _, args) -> Just (prog, Just path, args)+++userMaybeSpecifyPath :: String -> Maybe FilePath+ -> ProgramDb -> ProgramDb+userMaybeSpecifyPath _ Nothing progdb = progdb+userMaybeSpecifyPath name (Just path) progdb = userSpecifyPath name path progdb+++-- |User-specify the arguments for this program. Basically override+-- any args information for this program in the configuration. If it's+-- not a known program, ignore it..+userSpecifyArgs :: String -- ^Program name+ -> [ProgArg] -- ^user-specified args+ -> ProgramDb+ -> ProgramDb+userSpecifyArgs name args' =+ updateUnconfiguredProgs+ (flip Map.update name $+ \(prog, path, args) -> Just (prog, path, args ++ args'))+ . updateConfiguredProgs+ (flip Map.update name $+ \prog -> Just prog { programOverrideArgs = programOverrideArgs prog+ ++ args' })+++-- | Like 'userSpecifyPath' but for a list of progs and their paths.+--+userSpecifyPaths :: [(String, FilePath)]+ -> ProgramDb+ -> ProgramDb+userSpecifyPaths paths progdb =+ foldl' (\progdb' (prog, path) -> userSpecifyPath prog path progdb') progdb paths+++-- | Like 'userSpecifyPath' but for a list of progs and their args.+--+userSpecifyArgss :: [(String, [ProgArg])]+ -> ProgramDb+ -> ProgramDb+userSpecifyArgss argss progdb =+ foldl' (\progdb' (prog, args) -> userSpecifyArgs prog args progdb') progdb argss+++-- | Get the path that has been previously specified for a program, if any.+--+userSpecifiedPath :: Program -> ProgramDb -> Maybe FilePath+userSpecifiedPath prog =+ join . fmap (\(_,p,_)->p) . Map.lookup (programName prog) . unconfiguredProgs+++-- | Get any extra args that have been previously specified for a program.+--+userSpecifiedArgs :: Program -> ProgramDb -> [ProgArg]+userSpecifiedArgs prog =+ maybe [] (\(_,_,as)->as) . Map.lookup (programName prog) . unconfiguredProgs+++-- -----------------------------+-- Managing configured programs++-- | Try to find a configured program+lookupProgram :: Program -> ProgramDb -> Maybe ConfiguredProgram+lookupProgram prog = Map.lookup (programName prog) . configuredProgs+++-- | Update a configured program in the database.+updateProgram :: ConfiguredProgram -> ProgramDb+ -> ProgramDb+updateProgram prog = updateConfiguredProgs $+ Map.insert (programId prog) prog+++-- | List all configured programs.+configuredPrograms :: ProgramDb -> [ConfiguredProgram]+configuredPrograms = Map.elems . configuredProgs++-- ---------------------------+-- Configuring known programs++-- | Try to configure a specific program. If the program is already included in+-- the collection of unconfigured programs then we use any user-supplied+-- location and arguments. If the program gets configured successfully it gets+-- added to the configured collection.+--+-- Note that it is not a failure if the program cannot be configured. It's only+-- a failure if the user supplied a location and the program could not be found+-- at that location.+--+-- The reason for it not being a failure at this stage is that we don't know up+-- front all the programs we will need, so we try to configure them all.+-- To verify that a program was actually successfully configured use+-- 'requireProgram'.+--+configureProgram :: Verbosity+ -> Program+ -> ProgramDb+ -> IO ProgramDb+configureProgram verbosity prog progdb = do+ let name = programName prog+ maybeLocation <- case userSpecifiedPath prog progdb of+ Nothing ->+ programFindLocation prog verbosity (progSearchPath progdb)+ >>= return . fmap (swap . fmap FoundOnSystem . swap)+ Just path -> do+ absolute <- doesExecutableExist path+ if absolute+ then return (Just (UserSpecified path, []))+ else findProgramOnSearchPath verbosity (progSearchPath progdb) path+ >>= maybe (die' verbosity 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 progdb+ Just (location, triedLocations) -> do+ version <- programFindVersion prog verbosity (locationPath location)+ newPath <- programSearchPathAsPATHVar (progSearchPath progdb)+ let configuredProg = ConfiguredProgram {+ programId = name,+ programVersion = version,+ programDefaultArgs = [],+ programOverrideArgs = userSpecifiedArgs prog progdb,+ programOverrideEnv = [("PATH", Just newPath)],+ programProperties = Map.empty,+ programLocation = location,+ programMonitorFiles = triedLocations+ }+ configuredProg' <- programPostConf prog verbosity configuredProg+ return (updateConfiguredProgs (Map.insert name configuredProg') progdb)+++-- | Configure a bunch of programs using 'configureProgram'. Just a 'foldM'.+--+configurePrograms :: Verbosity+ -> [Program]+ -> ProgramDb+ -> IO ProgramDb+configurePrograms verbosity progs progdb =+ foldM (flip (configureProgram verbosity)) progdb progs+++-- | Unconfigure a program. This is basically a hack and you shouldn't+-- use it, but it can be handy for making sure a 'requireProgram'+-- actually reconfigures.+unconfigureProgram :: String -> ProgramDb -> ProgramDb+unconfigureProgram progname =+ updateConfiguredProgs $ Map.delete progname++-- | Try to configure all the known programs that have not yet been configured.+--+configureAllKnownPrograms :: Verbosity+ -> ProgramDb+ -> IO ProgramDb+configureAllKnownPrograms verbosity progdb =+ configurePrograms verbosity+ [ prog | (prog,_,_) <- Map.elems notYetConfigured ] progdb+ where+ notYetConfigured = unconfiguredProgs progdb+ `Map.difference` configuredProgs progdb+++-- | reconfigure a bunch of programs given new user-specified args. It takes+-- the same inputs as 'userSpecifyPath' and 'userSpecifyArgs' and for all progs+-- with a new path it calls 'configureProgram'.+--+reconfigurePrograms :: Verbosity+ -> [(String, FilePath)]+ -> [(String, [ProgArg])]+ -> ProgramDb+ -> IO ProgramDb+reconfigurePrograms verbosity paths argss progdb = do+ configurePrograms verbosity progs+ . userSpecifyPaths paths+ . userSpecifyArgss argss+ $ progdb++ where+ progs = catMaybes [ lookupKnownProgram name progdb | (name,_) <- paths ]+++-- | Check that a program is configured and available to be run.+--+-- It raises an exception if the program could not be configured, otherwise+-- it returns the configured program.+--+requireProgram :: Verbosity -> Program -> ProgramDb+ -> IO (ConfiguredProgram, ProgramDb)+requireProgram verbosity prog progdb = do+ mres <- needProgram verbosity prog progdb+ case mres of+ Nothing -> die' verbosity notFound+ Just res -> return res+ where+ notFound = "The program '" ++ programName prog ++ "' is required but it could not be found."++-- | Check that a program is configured and available to be run.+--+-- It returns 'Nothing' if the program couldn't be configured,+-- or is not found.+--+-- @since 3.0.1.0+needProgram :: Verbosity -> Program -> ProgramDb+ -> IO (Maybe (ConfiguredProgram, ProgramDb))+needProgram verbosity prog progdb = do++ -- If it's not already been configured, try to configure it now+ progdb' <- case lookupProgram prog progdb of+ Nothing -> configureProgram verbosity prog progdb+ Just _ -> return progdb++ case lookupProgram prog progdb' of+ Nothing -> return Nothing+ Just configuredProg -> return (Just (configuredProg, progdb'))++-- | Check that a program is configured and available to be run.+--+-- Additionally check that the program version number is suitable and return+-- it. For example you could require 'AnyVersion' or @'orLaterVersion'+-- ('Version' [1,0] [])@+--+-- It returns the configured program, its version number and a possibly updated+-- 'ProgramDb'. If the program could not be configured or the version is+-- unsuitable, it returns an error value.+--+lookupProgramVersion+ :: Verbosity -> Program -> VersionRange -> ProgramDb+ -> IO (Either String (ConfiguredProgram, Version, ProgramDb))+lookupProgramVersion verbosity prog range programDb = do++ -- If it's not already been configured, try to configure it now+ programDb' <- case lookupProgram prog programDb of+ Nothing -> configureProgram verbosity prog programDb+ Just _ -> return programDb++ case lookupProgram prog programDb' of+ Nothing -> return $! Left notFound+ Just configuredProg@ConfiguredProgram { programLocation = location } ->+ case programVersion configuredProg of+ Just version+ | withinRange version range ->+ return $! Right (configuredProg, version ,programDb')+ | otherwise ->+ return $! Left (badVersion version location)+ Nothing ->+ return $! Left (unknownVersion location)++ where notFound = "The program '"+ ++ programName prog ++ "'" ++ versionRequirement+ ++ " is required but it could not be found."+ badVersion v l = "The program '"+ ++ programName prog ++ "'" ++ versionRequirement+ ++ " is required but the version found at "+ ++ locationPath l ++ " is version " ++ prettyShow v+ unknownVersion l = "The program '"+ ++ programName prog ++ "'" ++ versionRequirement+ ++ " is required but the version of "+ ++ locationPath l ++ " could not be determined."+ versionRequirement+ | isAnyVersion range = ""+ | otherwise = " version " ++ prettyShow range++-- | Like 'lookupProgramVersion', but raises an exception in case of error+-- instead of returning 'Left errMsg'.+--+requireProgramVersion :: Verbosity -> Program -> VersionRange+ -> ProgramDb+ -> IO (ConfiguredProgram, Version, ProgramDb)+requireProgramVersion verbosity prog range programDb =+ join $ either (die' verbosity) return `fmap`+ lookupProgramVersion verbosity prog range programDb
+ src/Distribution/Simple/Program/Find.hs view
@@ -0,0 +1,198 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Find+-- Copyright : Duncan Coutts 2013+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- A somewhat extended notion of the normal program search path concept.+--+-- Usually when finding executables we just want to look in the usual places+-- using the OS's usual method for doing so. In Haskell the normal OS-specific+-- method is captured by 'findExecutable'. On all common OSs that makes use of+-- a @PATH@ environment variable, (though on Windows it is not just the @PATH@).+--+-- However it is sometimes useful to be able to look in additional locations+-- without having to change the process-global @PATH@ environment variable.+-- So we need an extension of the usual 'findExecutable' that can look in+-- additional locations, either before, after or instead of the normal OS+-- locations.+--+module Distribution.Simple.Program.Find (+ -- * Program search path+ ProgramSearchPath,+ ProgramSearchPathEntry(..),+ defaultProgramSearchPath,+ findProgramOnSearchPath,+ programSearchPathAsPATHVar,+ getSystemSearchPath,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Verbosity+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Compat.Environment++import qualified System.Directory as Directory+ ( findExecutable )+import System.FilePath as FilePath+ ( (</>), (<.>), splitSearchPath, searchPathSeparator, getSearchPath+ , takeDirectory )+#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+-- the system default method for finding executables ('findExecutable' which+-- on unix is simply looking on the @$PATH@ but on win32 is a bit more+-- complicated).+--+-- The default to use is @[ProgSearchPathDefault]@ but you can add extra dirs+-- either before, after or instead of the default, e.g. here we add an extra+-- dir to search after the usual ones.+--+-- > ['ProgramSearchPathDefault', 'ProgramSearchPathDir' dir]+--+type ProgramSearchPath = [ProgramSearchPathEntry]+data ProgramSearchPathEntry =+ ProgramSearchPathDir FilePath -- ^ A specific dir+ | ProgramSearchPathDefault -- ^ The system default+ deriving (Eq, Generic, Typeable)++instance Binary ProgramSearchPathEntry+instance Structured ProgramSearchPathEntry++defaultProgramSearchPath :: ProgramSearchPath+defaultProgramSearchPath = [ProgramSearchPathDefault]++findProgramOnSearchPath :: Verbosity -> ProgramSearchPath+ -> FilePath -> IO (Maybe (FilePath, [FilePath]))+findProgramOnSearchPath verbosity searchpath prog = do+ debug verbosity $ "Searching for " ++ prog ++ " in path."+ res <- tryPathElems [] searchpath+ case res of+ Nothing -> debug verbosity ("Cannot find " ++ prog ++ " on the path")+ Just (path, _) -> debug verbosity ("Found " ++ prog ++ " at "++ path)+ return res+ where+ tryPathElems :: [[FilePath]] -> [ProgramSearchPathEntry]+ -> IO (Maybe (FilePath, [FilePath]))+ tryPathElems _ [] = return Nothing+ tryPathElems tried (pe:pes) = do+ res <- tryPathElem pe+ case res of+ (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 <- exeExtensions ]++ -- 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 <- firstJustM [ findExecutable (prog <.> ext) | ext <- exeExtensions ]+ syspath <- getSystemSearchPath+ case mExe of+ Nothing ->+ let notfoundat = [ dir </> prog | dir <- syspath ] in+ return (Nothing, notfoundat)++ 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++ -- Helper for evaluating actions until the first one returns 'Just'+ firstJustM :: Monad m => [m (Maybe a)] -> m (Maybe a)+ firstJustM [] = return Nothing+ firstJustM (ma:mas) = do+ a <- ma+ case a of+ Just _ -> return a+ Nothing -> firstJustM mas++-- | 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%@.+programSearchPathAsPATHVar :: ProgramSearchPath -> IO String+programSearchPathAsPATHVar searchpath = do+ ess <- traverse getEntries searchpath+ return (intercalate [searchPathSeparator] (concat ess))+ where+ getEntries (ProgramSearchPathDir dir) = return [dir]+ 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+
+ src/Distribution/Simple/Program/GHC.hs view
@@ -0,0 +1,850 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Distribution.Simple.Program.GHC (+ GhcOptions(..),+ GhcMode(..),+ GhcOptimisation(..),+ GhcDynLinkMode(..),+ GhcProfAuto(..),++ ghcInvocation,+ renderGhcOptions,++ runGHC,++ packageDbArgsDb,+ normaliseGhcArgs++ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Backpack+import Distribution.Compat.Semigroup (First'(..), Last'(..), Option'(..))+import Distribution.Simple.GHC.ImplInfo+import Distribution.PackageDescription+import Distribution.ModuleName+import Distribution.Simple.Compiler+import Distribution.Simple.Flag+import Distribution.Simple.Program.Types+import Distribution.Simple.Program.Run+import Distribution.System+import Distribution.Pretty+import Distribution.Types.ComponentId+import Distribution.Verbosity+import Distribution.Version+import Distribution.Utils.NubList+import Language.Haskell.Extension++import Data.List (stripPrefix)+import qualified Data.Map as Map+import Data.Monoid (All(..), Any(..), Endo(..))+import qualified Data.Set as Set++normaliseGhcArgs :: Maybe Version -> PackageDescription -> [String] -> [String]+normaliseGhcArgs (Just ghcVersion) PackageDescription{..} ghcArgs+ | ghcVersion `withinRange` supportedGHCVersions+ = argumentFilters . filter simpleFilters . filterRtsOpts $ ghcArgs+ where+ supportedGHCVersions :: VersionRange+ supportedGHCVersions = intersectVersionRanges+ (orLaterVersion (mkVersion [8,0]))+ (earlierVersion (mkVersion [9,1]))++ from :: Monoid m => [Int] -> m -> m+ from version flags+ | ghcVersion `withinRange` orLaterVersion (mkVersion version) = flags+ | otherwise = mempty++ to :: Monoid m => [Int] -> m -> m+ to version flags+ | ghcVersion `withinRange` earlierVersion (mkVersion version) = flags+ | otherwise = mempty++ checkGhcFlags :: forall m . Monoid m => ([String] -> m) -> m+ checkGhcFlags fun = mconcat+ [ fun ghcArgs+ , checkComponentFlags libBuildInfo pkgLibs+ , checkComponentFlags buildInfo executables+ , checkComponentFlags testBuildInfo testSuites+ , checkComponentFlags benchmarkBuildInfo benchmarks+ ]+ where+ pkgLibs = maybeToList library ++ subLibraries++ checkComponentFlags :: (a -> BuildInfo) -> [a] -> m+ checkComponentFlags getInfo = foldMap (checkComponent . getInfo)+ where+ checkComponent :: BuildInfo -> m+ checkComponent = foldMap fun . filterGhcOptions . allGhcOptions++ allGhcOptions :: BuildInfo -> [(CompilerFlavor, [String])]+ allGhcOptions = foldMap (perCompilerFlavorToList .)+ [options, profOptions, sharedOptions, staticOptions]++ filterGhcOptions :: [(CompilerFlavor, [String])] -> [[String]]+ filterGhcOptions l = [opts | (GHC, opts) <- l]++ safeToFilterWarnings :: Bool+ safeToFilterWarnings = getAll $ checkGhcFlags checkWarnings+ where+ checkWarnings :: [String] -> All+ checkWarnings = All . Set.null . foldr alter Set.empty++ alter :: String -> Set String -> Set String+ alter flag = appEndo $ mconcat+ [ \s -> Endo $ if s == "-Werror" then Set.insert s else id+ , \s -> Endo $ if s == "-Wwarn" then const Set.empty else id+ , \s -> from [8,6] . Endo $+ if s == "-Werror=compat"+ then Set.union compatWarningSet else id+ , \s -> from [8,6] . Endo $+ if s == "-Wno-error=compat"+ then (`Set.difference` compatWarningSet) else id+ , \s -> from [8,6] . Endo $+ if s == "-Wwarn=compat"+ then (`Set.difference` compatWarningSet) else id+ , from [8,4] $ markFlag "-Werror=" Set.insert+ , from [8,4] $ markFlag "-Wwarn=" Set.delete+ , from [8,4] $ markFlag "-Wno-error=" Set.delete+ ] flag++ markFlag+ :: String+ -> (String -> Set String -> Set String)+ -> String+ -> Endo (Set String)+ markFlag name update flag = Endo $ case stripPrefix name flag of+ Just rest | not (null rest) && rest /= "compat" -> update rest+ _ -> id++ flagArgumentFilter :: [String] -> [String] -> [String]+ flagArgumentFilter flags = go+ where+ makeFilter :: String -> String -> Option' (First' ([String] -> [String]))+ makeFilter flag arg = Option' $ First' . filterRest <$> stripPrefix flag arg+ where+ filterRest leftOver = case dropEq leftOver of+ [] -> drop 1+ _ -> id++ checkFilter :: String -> Maybe ([String] -> [String])+ checkFilter = fmap getFirst' . getOption' . foldMap makeFilter flags++ go :: [String] -> [String]+ go [] = []+ go (arg:args) = case checkFilter arg of+ Just f -> go (f args)+ Nothing -> arg : go args++ argumentFilters :: [String] -> [String]+ argumentFilters = flagArgumentFilter+ ["-ghci-script", "-H", "-interactive-print"]++ filterRtsOpts :: [String] -> [String]+ filterRtsOpts = go False+ where+ go :: Bool -> [String] -> [String]+ go _ [] = []+ go _ ("+RTS":opts) = go True opts+ go _ ("-RTS":opts) = go False opts+ go isRTSopts (opt:opts) = addOpt $ go isRTSopts opts+ where+ addOpt | isRTSopts = id+ | otherwise = (opt:)++ simpleFilters :: String -> Bool+ simpleFilters = not . getAny . mconcat+ [ flagIn simpleFlags+ , Any . isPrefixOf "-ddump-"+ , Any . isPrefixOf "-dsuppress-"+ , Any . isPrefixOf "-dno-suppress-"+ , flagIn $ invertibleFlagSet "-" ["ignore-dot-ghci"]+ , flagIn . invertibleFlagSet "-f" . mconcat $+ [ [ "reverse-errors", "warn-unused-binds", "break-on-error"+ , "break-on-exception", "print-bind-result"+ , "print-bind-contents", "print-evld-with-show"+ , "implicit-import-qualified", "error-spans"+ ]+ , from [7,8]+ [ "print-explicit-foralls" -- maybe also earlier, but GHC-7.6 doesn't have --show-options+ , "print-explicit-kinds"+ ]+ , from [8,0]+ [ "print-explicit-coercions"+ , "print-explicit-runtime-reps"+ , "print-equality-relations"+ , "print-unicode-syntax"+ , "print-expanded-synonyms"+ , "print-potential-instances"+ , "print-typechecker-elaboration"+ ]+ , from [8,2]+ [ "diagnostics-show-caret", "local-ghci-history"+ , "show-warning-groups", "hide-source-paths"+ , "show-hole-constraints"+ ]+ , from [8,4] ["show-loaded-modules"]+ , from [8,6] [ "ghci-leak-check", "no-it" ]+ , from [8,10]+ [ "defer-diagnostics" -- affects printing of diagnostics+ , "keep-going" -- try harder, the build will still fail if it's erroneous+ , "print-axiom-incomps" -- print more debug info for closed type families+ ]+ ]+ , flagIn . invertibleFlagSet "-d" $ [ "ppr-case-as-let", "ppr-ticks" ]+ , isOptIntFlag+ , isIntFlag+ , if safeToFilterWarnings+ then isWarning <> (Any . ("-w"==))+ else mempty+ , from [8,6] $+ if safeToFilterHoles+ then isTypedHoleFlag+ else mempty+ ]++ flagIn :: Set String -> String -> Any+ flagIn set flag = Any $ Set.member flag set++ isWarning :: String -> Any+ isWarning = mconcat $ map ((Any .) . isPrefixOf)+ ["-fwarn-", "-fno-warn-", "-W", "-Wno-"]++ simpleFlags :: Set String+ simpleFlags = Set.fromList . mconcat $+ [ [ "-n", "-#include", "-Rghc-timing", "-dstg-stats"+ , "-dth-dec-file", "-dsource-stats", "-dverbose-core2core"+ , "-dverbose-stg2stg", "-dcore-lint", "-dstg-lint", "-dcmm-lint"+ , "-dasm-lint", "-dannot-lint", "-dshow-passes", "-dfaststring-stats"+ , "-fno-max-relevant-binds", "-recomp", "-no-recomp", "-fforce-recomp"+ , "-fno-force-recomp"+ ]++ , from [8,2]+ [ "-fno-max-errors", "-fdiagnostics-color=auto"+ , "-fdiagnostics-color=always", "-fdiagnostics-color=never"+ , "-dppr-debug", "-dno-debug-output"+ ]++ , from [8,4] [ "-ddebug-output" ]+ , from [8,4] $ to [8,6] [ "-fno-max-valid-substitutions" ]+ , from [8,6] [ "-dhex-word-literals" ]+ , from [8,8] [ "-fshow-docs-of-hole-fits", "-fno-show-docs-of-hole-fits" ]+ , from [9,0] [ "-dlinear-core-lint" ]+ ]++ isOptIntFlag :: String -> Any+ isOptIntFlag = mconcat . map (dropIntFlag True) $ ["-v", "-j"]++ isIntFlag :: String -> Any+ isIntFlag = mconcat . map (dropIntFlag False) . mconcat $+ [ [ "-fmax-relevant-binds", "-ddpr-user-length", "-ddpr-cols"+ , "-dtrace-level", "-fghci-hist-size" ]+ , from [8,2] ["-fmax-uncovered-patterns", "-fmax-errors"]+ , from [8,4] $ to [8,6] ["-fmax-valid-substitutions"]+ ]++ dropIntFlag :: Bool -> String -> String -> Any+ dropIntFlag isOpt flag input = Any $ case stripPrefix flag input of+ Nothing -> False+ Just rest | isOpt && null rest -> True+ | otherwise -> case parseInt rest of+ Just _ -> True+ Nothing -> False+ where+ parseInt :: String -> Maybe Int+ parseInt = readMaybe . dropEq++ dropEq :: String -> String+ dropEq ('=':s) = s+ dropEq s = s++ invertibleFlagSet :: String -> [String] -> Set String+ invertibleFlagSet prefix flagNames =+ Set.fromList $ (++) <$> [prefix, prefix ++ "no-"] <*> flagNames++ compatWarningSet :: Set String+ compatWarningSet = Set.fromList $ mconcat+ [ from [8,6]+ [ "missing-monadfail-instances", "semigroup"+ , "noncanonical-monoid-instances", "implicit-kind-vars" ]+ ]++ safeToFilterHoles :: Bool+ safeToFilterHoles = getAll . checkGhcFlags $+ All . fromMaybe True . fmap getLast' . getOption' . foldMap notDeferred+ where+ notDeferred :: String -> Option' (Last' Bool)+ notDeferred "-fdefer-typed-holes" = Option' . Just . Last' $ False+ notDeferred "-fno-defer-typed-holes" = Option' . Just . Last' $ True+ notDeferred _ = Option' Nothing++ isTypedHoleFlag :: String -> Any+ isTypedHoleFlag = mconcat+ [ flagIn . invertibleFlagSet "-f" $+ [ "show-hole-constraints", "show-valid-substitutions"+ , "show-valid-hole-fits", "sort-valid-hole-fits"+ , "sort-by-size-hole-fits", "sort-by-subsumption-hole-fits"+ , "abstract-refinement-hole-fits", "show-provenance-of-hole-fits"+ , "show-hole-matches-of-hole-fits", "show-type-of-hole-fits"+ , "show-type-app-of-hole-fits", "show-type-app-vars-of-hole-fits"+ , "unclutter-valid-hole-fits"+ ]+ , flagIn . Set.fromList $+ [ "-fno-max-valid-hole-fits", "-fno-max-refinement-hole-fits"+ , "-fno-refinement-level-hole-fits" ]+ , mconcat . map (dropIntFlag False) $+ [ "-fmax-valid-hole-fits", "-fmax-refinement-hole-fits"+ , "-frefinement-level-hole-fits" ]+ ]++normaliseGhcArgs _ _ args = args++-- | A structured set of GHC options/flags+--+-- Note that options containing lists fall into two categories:+--+-- * options that can be safely deduplicated, e.g. input modules or+-- enabled extensions;+-- * options that cannot be deduplicated in general without changing+-- semantics, e.g. extra ghc options or linking options.+data GhcOptions = GhcOptions {++ -- | The major mode for the ghc invocation.+ ghcOptMode :: Flag GhcMode,++ -- | Any extra options to pass directly to ghc. These go at the end and hence+ -- override other stuff.+ ghcOptExtra :: [String],++ -- | Extra default flags to pass directly to ghc. These go at the beginning+ -- and so can be overridden by other stuff.+ ghcOptExtraDefault :: [String],++ -----------------------+ -- Inputs and outputs++ -- | The main input files; could be .hs, .hi, .c, .o, depending on mode.+ ghcOptInputFiles :: NubListR FilePath,++ -- | The names of input Haskell modules, mainly for @--make@ mode.+ ghcOptInputModules :: NubListR ModuleName,++ -- | Location for output file; the @ghc -o@ flag.+ ghcOptOutputFile :: Flag FilePath,++ -- | Location for dynamic output file in 'GhcStaticAndDynamic' mode;+ -- the @ghc -dyno@ flag.+ ghcOptOutputDynFile :: Flag FilePath,++ -- | Start with an empty search path for Haskell source files;+ -- the @ghc -i@ flag (@-i@ on its own with no path argument).+ ghcOptSourcePathClear :: Flag Bool,++ -- | Search path for Haskell source files; the @ghc -i@ flag.+ ghcOptSourcePath :: NubListR FilePath,++ -------------+ -- Packages++ -- | 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 doesn't make any assumptions about the format of+ -- definite unit ids, so when we are instantiating a package it+ -- needs to be told explicitly what the component being instantiated+ -- is. This only gets set when 'ghcOptInstantiatedWith' is non-empty+ ghcOptThisComponentId :: Flag ComponentId,++ -- | How the requirements of the package being compiled are to+ -- be filled. When typechecking an indefinite package, the 'OpenModule'+ -- is always a 'OpenModuleVar'; otherwise, it specifies the installed module+ -- that instantiates a package.+ ghcOptInstantiatedWith :: [(ModuleName, OpenModule)],++ -- | No code? (But we turn on interface writing+ ghcOptNoCode :: Flag Bool,++ -- | GHC package databases to use, the @ghc -package-conf@ flag.+ ghcOptPackageDBs :: PackageDBStack,++ -- | The GHC packages to bring into scope when compiling,+ -- the @ghc -package-id@ flags.+ ghcOptPackages ::+ NubListR (OpenUnitId, ModuleRenaming),++ -- | Start with a clean package set; the @ghc -hide-all-packages@ flag+ ghcOptHideAllPackages :: Flag Bool,++ -- | Warn about modules, not listed in command line+ ghcOptWarnMissingHomeModules :: Flag Bool,++ -- | Don't automatically link in Haskell98 etc; the @ghc+ -- -no-auto-link-packages@ flag.+ ghcOptNoAutoLinkPackages :: Flag Bool,++ -----------------+ -- Linker stuff++ -- | Names of libraries to link in; the @ghc -l@ flag.+ ghcOptLinkLibs :: [FilePath],++ -- | Search path for libraries to link in; the @ghc -L@ flag.+ ghcOptLinkLibPath :: NubListR FilePath,++ -- | Options to pass through to the linker; the @ghc -optl@ flag.+ ghcOptLinkOptions :: [String],++ -- | 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,++ -- | Don't link in the normal RTS @main@ entry point; the @ghc -no-hs-main@+ -- flag.+ ghcOptLinkNoHsMain :: Flag Bool,++ -- | Module definition files (Windows specific)+ ghcOptLinkModDefFiles :: NubListR FilePath,++ --------------------+ -- C and CPP stuff++ -- | Options to pass through to the C compiler; the @ghc -optc@ flag.+ ghcOptCcOptions :: [String],++ -- | Options to pass through to the C++ compiler.+ ghcOptCxxOptions :: [String],++ -- | Options to pass through to the Assembler.+ ghcOptAsmOptions :: [String],++ -- | Options to pass through to CPP; the @ghc -optP@ flag.+ ghcOptCppOptions :: [String],++ -- | Search path for CPP includes like header files; the @ghc -I@ flag.+ ghcOptCppIncludePath :: NubListR FilePath,++ -- | Extra header files to include at CPP stage; the @ghc -optP-include@ flag.+ ghcOptCppIncludes :: NubListR FilePath,++ -- | Extra header files to include for old-style FFI; the @ghc -#include@ flag.+ ghcOptFfiIncludes :: NubListR FilePath,++ ----------------------------+ -- Language and extensions++ -- | The base language; the @ghc -XHaskell98@ or @-XHaskell2010@ flag.+ ghcOptLanguage :: Flag Language,++ -- | The language extensions; the @ghc -X@ flag.+ ghcOptExtensions :: NubListR Extension,++ -- | A GHC version-dependent mapping of extensions to flags. This must be+ -- set to be able to make use of the 'ghcOptExtensions'.+ ghcOptExtensionMap :: Map Extension (Maybe CompilerFlag),++ ----------------+ -- Compilation++ -- | What optimisation level to use; the @ghc -O@ flag.+ ghcOptOptimisation :: Flag GhcOptimisation,++ -- | Emit debug info; the @ghc -g@ flag.+ ghcOptDebugInfo :: Flag DebugInfoLevel,++ -- | 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 sections\" feature; the @ghc -split-sections@ flag.+ ghcOptSplitSections :: Flag Bool,++ -- | Use the \"split object files\" feature; the @ghc -split-objs@ flag.+ ghcOptSplitObjs :: Flag Bool,++ -- | Run N jobs simultaneously (if possible).+ ghcOptNumJobs :: Flag (Maybe Int),++ -- | Enable coverage analysis; the @ghc -fhpc -hpcdir@ flags.+ ghcOptHPCDir :: Flag FilePath,++ ----------------+ -- GHCi++ -- | Extra GHCi startup scripts; the @-ghci-script@ flag+ ghcOptGHCiScripts :: [FilePath],++ ------------------------+ -- Redirecting outputs++ ghcOptHiSuffix :: Flag String,+ ghcOptObjSuffix :: Flag String,+ ghcOptDynHiSuffix :: Flag String, -- ^ only in 'GhcStaticAndDynamic' mode+ ghcOptDynObjSuffix :: Flag String, -- ^ only in 'GhcStaticAndDynamic' mode+ ghcOptHiDir :: Flag FilePath,+ ghcOptObjDir :: Flag FilePath,+ ghcOptOutputDir :: Flag FilePath,+ ghcOptStubDir :: Flag FilePath,++ --------------------+ -- Creating libraries++ ghcOptDynLinkMode :: Flag GhcDynLinkMode,+ ghcOptStaticLib :: Flag Bool,+ ghcOptShared :: Flag Bool,+ ghcOptFPic :: Flag Bool,+ ghcOptDylibName :: Flag String,+ ghcOptRPaths :: NubListR FilePath,++ ---------------+ -- Misc flags++ -- | Get GHC to be quiet or verbose with what it's doing; the @ghc -v@ flag.+ ghcOptVerbosity :: Flag Verbosity,++ -- | Put the extra folders in the PATH environment variable we invoke+ -- GHC with+ ghcOptExtraPath :: NubListR FilePath,++ -- | Let GHC know that it is Cabal that's calling it.+ -- Modifies some of the GHC error messages.+ ghcOptCabal :: Flag Bool++} deriving (Show, Generic)+++data GhcMode = GhcModeCompile -- ^ @ghc -c@+ | GhcModeLink -- ^ @ghc@+ | GhcModeMake -- ^ @ghc --make@+ | GhcModeInteractive -- ^ @ghci@ \/ @ghc --interactive@+ | GhcModeAbiHash -- ^ @ghc --abi-hash@+-- | GhcModeDepAnalysis -- ^ @ghc -M@+-- | GhcModeEvaluate -- ^ @ghc -e@+ deriving (Show, Eq)++data GhcOptimisation = GhcNoOptimisation -- ^ @-O0@+ | GhcNormalOptimisation -- ^ @-O@+ | GhcMaximumOptimisation -- ^ @-O2@+ | GhcSpecialOptimisation String -- ^ e.g. @-Odph@+ deriving (Show, Eq)++data GhcDynLinkMode = GhcStaticOnly -- ^ @-static@+ | GhcDynamicOnly -- ^ @-dynamic@+ | 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 -> Platform -> GhcOptions+ -> IO ()+runGHC verbosity ghcProg comp platform opts = do+ runProgramInvocation verbosity (ghcInvocation ghcProg comp platform opts)+++ghcInvocation :: ConfiguredProgram -> Compiler -> Platform -> GhcOptions+ -> ProgramInvocation+ghcInvocation prog comp platform opts =+ (programInvocation prog (renderGhcOptions comp platform opts)) {+ progInvokePathEnv = fromNubListR (ghcOptExtraPath 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'!"+ | otherwise =+ concat+ [ case flagToMaybe (ghcOptMode opts) of+ Nothing -> []+ Just GhcModeCompile -> ["-c"]+ Just GhcModeLink -> []+ Just GhcModeMake -> ["--make"]+ Just GhcModeInteractive -> ["--interactive"]+ Just GhcModeAbiHash -> ["--abi-hash"]+-- Just GhcModeDepAnalysis -> ["-M"]+-- Just GhcModeEvaluate -> ["-e", expr]++ , ghcOptExtraDefault opts++ , [ "-no-link" | flagBool ghcOptNoLink ]++ ---------------+ -- Misc flags++ , maybe [] verbosityOpts (flagToMaybe (ghcOptVerbosity opts))++ , [ "-fbuilding-cabal-package" | flagBool ghcOptCabal ]++ ----------------+ -- Compilation++ , case flagToMaybe (ghcOptOptimisation opts) of+ Nothing -> []+ Just GhcNoOptimisation -> ["-O0"]+ Just GhcNormalOptimisation -> ["-O"]+ Just GhcMaximumOptimisation -> ["-O2"]+ Just (GhcSpecialOptimisation s) -> ["-O" ++ s] -- eg -Odph++ , case flagToMaybe (ghcOptDebugInfo opts) of+ Nothing -> []+ Just NoDebugInfo -> []+ Just MinimalDebugInfo -> ["-g1"]+ Just NormalDebugInfo -> ["-g2"]+ Just MaximalDebugInfo -> ["-g3"]++ , [ "-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-sections" | flagBool ghcOptSplitSections ]+ , [ "-split-objs" | flagBool ghcOptSplitObjs ]++ , case flagToMaybe (ghcOptHPCDir opts) of+ Nothing -> []+ Just hpcdir -> ["-fhpc", "-hpcdir", hpcdir]++ , if parmakeSupported comp+ then case ghcOptNumJobs opts of+ NoFlag -> []+ Flag n -> ["-j" ++ maybe "" show n]+ else []++ --------------------+ -- Creating libraries++ , [ "-staticlib" | flagBool ghcOptStaticLib ]+ , [ "-shared" | flagBool ghcOptShared ]+ , case flagToMaybe (ghcOptDynLinkMode opts) of+ Nothing -> []+ Just GhcStaticOnly -> ["-static"]+ Just GhcDynamicOnly -> ["-dynamic"]+ Just GhcStaticAndDynamic -> ["-static", "-dynamic-too"]+ , [ "-fPIC" | flagBool ghcOptFPic ]++ , concat [ ["-dylib-install-name", libname] | libname <- flag ghcOptDylibName ]++ ------------------------+ -- Redirecting outputs++ , concat [ ["-osuf", suf] | suf <- flag ghcOptObjSuffix ]+ , concat [ ["-hisuf", suf] | suf <- flag ghcOptHiSuffix ]+ , concat [ ["-dynosuf", suf] | suf <- flag ghcOptDynObjSuffix ]+ , concat [ ["-dynhisuf",suf] | suf <- flag ghcOptDynHiSuffix ]+ , concat [ ["-outputdir", dir] | dir <- flag ghcOptOutputDir ]+ , concat [ ["-odir", dir] | dir <- flag ghcOptObjDir ]+ , concat [ ["-hidir", dir] | dir <- flag ghcOptHiDir ]+ , concat [ ["-stubdir", dir] | dir <- flag ghcOptStubDir ]++ -----------------------+ -- Source search path++ , [ "-i" | flagBool ghcOptSourcePathClear ]+ , [ "-i" ++ dir | dir <- flags ghcOptSourcePath ]++ --------------------++ --------------------+ -- CPP, C, and C++ stuff++ , [ "-I" ++ dir | dir <- flags ghcOptCppIncludePath ]+ , [ "-optP" ++ opt | opt <- ghcOptCppOptions opts]+ , concat [ [ "-optP-include", "-optP" ++ inc]+ | inc <- flags ghcOptCppIncludes ]+ , [ "-optc" ++ opt | opt <- ghcOptCcOptions opts]+ , -- C++ compiler options: GHC >= 8.10 requires -optcxx, older requires -optc+ let cxxflag = case compilerCompatVersion GHC comp of+ Just v | v >= mkVersion [8, 10] -> "-optcxx"+ _ -> "-optc"+ in [ cxxflag ++ opt | opt <- ghcOptCxxOptions opts]+ , [ "-opta" ++ opt | opt <- ghcOptAsmOptions opts]++ -----------------+ -- Linker stuff++ , [ "-optl" ++ opt | opt <- ghcOptLinkOptions opts]+ , ["-l" ++ lib | lib <- ghcOptLinkLibs opts]+ , ["-L" ++ dir | dir <- flags ghcOptLinkLibPath ]+ , 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]+ | dir <- flags ghcOptRPaths ]+ , [ modDefFile | modDefFile <- flags ghcOptLinkModDefFiles ]++ -------------+ -- Packages++ , concat [ [ case () of+ _ | unitIdSupported comp -> "-this-unit-id"+ | packageKeySupported comp -> "-this-package-key"+ | otherwise -> "-package-name"+ , this_arg ]+ | this_arg <- flag ghcOptThisUnitId ]++ , concat [ ["-this-component-id", prettyShow this_cid ]+ | this_cid <- flag ghcOptThisComponentId ]++ , if null (ghcOptInstantiatedWith opts)+ then []+ else "-instantiated-with"+ : intercalate "," (map (\(n,m) -> prettyShow n ++ "="+ ++ prettyShow m)+ (ghcOptInstantiatedWith opts))+ : []++ , concat [ ["-fno-code", "-fwrite-interface"] | flagBool ghcOptNoCode ]++ , [ "-hide-all-packages" | flagBool ghcOptHideAllPackages ]+ , [ "-Wmissing-home-modules" | flagBool ghcOptWarnMissingHomeModules ]+ , [ "-no-auto-link-packages" | flagBool ghcOptNoAutoLinkPackages ]++ , packageDbArgs implInfo (ghcOptPackageDBs opts)++ , concat $ let space "" = ""+ space xs = ' ' : xs+ in [ ["-package-id", prettyShow ipkgid ++ space (prettyShow rns)]+ | (ipkgid,rns) <- flags ghcOptPackages ]++ ----------------------------+ -- Language and extensions++ , if supportsHaskell2010 implInfo+ then [ "-X" ++ prettyShow lang | lang <- flag ghcOptLanguage ]+ else []++ , [ ext'+ | ext <- flags ghcOptExtensions+ , ext' <- case Map.lookup ext (ghcOptExtensionMap opts) of+ Just (Just arg) -> [arg]+ Just Nothing -> []+ Nothing ->+ error $ "Distribution.Simple.Program.GHC.renderGhcOptions: "+ ++ prettyShow ext ++ " not present in ghcOptExtensionMap."+ ]++ ----------------+ -- GHCi++ , concat [ [ "-ghci-script", script ] | script <- ghcOptGHCiScripts opts+ , flagGhciScript implInfo ]++ ---------------+ -- Inputs++ -- Specify the input file(s) first, so that in ghci the `main-is` module is+ -- in scope instead of the first module defined in `other-modules`.+ , flags ghcOptInputFiles+ , [ prettyShow modu | modu <- flags ghcOptInputModules ]++ , concat [ [ "-o", out] | out <- flag ghcOptOutputFile ]+ , concat [ [ "-dyno", out] | out <- flag ghcOptOutputDynFile ]++ ---------------+ -- Extra++ , ghcOptExtra opts++ ]+++ where+ implInfo = getImplInfo comp+ isOSX = os == OSX+ flag flg = flagToList (flg opts)+ flags flg = fromNubListR . flg $ opts+ flagBool flg = fromFlagOrDefault False (flg opts)++verbosityOpts :: Verbosity -> [String]+verbosityOpts verbosity+ | verbosity >= deafening = ["-v"]+ | verbosity >= normal = []+ | otherwise = ["-w", "-v0"]+++-- | 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-package-conf")+ : concatMap specific dbs+ _ -> ierror+ where+ 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://gitlab.haskell.org/ghc/ghc/-/issues/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 = gmempty+ mappend = (<>)++instance Semigroup GhcOptions where+ (<>) = gmappend
+ src/Distribution/Simple/Program/HcPkg.hs view
@@ -0,0 +1,516 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.HcPkg+-- Copyright : Duncan Coutts 2009, 2013+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides an library interface to the @hc-pkg@ program.+-- Currently only GHC and GHCJS have hc-pkg programs.++module Distribution.Simple.Program.HcPkg (+ -- * Types+ HcPkgInfo(..),+ RegisterOptions(..),+ defaultRegisterOptions,++ -- * Actions+ init,+ invoke,+ register,+ unregister,+ recache,+ expose,+ hide,+ dump,+ describe,+ list,++ -- * Program invocations+ initInvocation,+ registerInvocation,+ unregisterInvocation,+ recacheInvocation,+ exposeInvocation,+ hideInvocation,+ dumpInvocation,+ describeInvocation,+ listInvocation,+ ) where++import Distribution.Compat.Prelude hiding (init)+import Prelude ()++import Distribution.InstalledPackageInfo+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Simple.Compiler+import Distribution.Simple.Program.Run+import Distribution.Simple.Program.Types+import Distribution.Simple.Utils+import Distribution.Types.ComponentId+import Distribution.Types.PackageId+import Distribution.Types.UnitId+import Distribution.Verbosity++import Data.List (stripPrefix)+import System.FilePath as FilePath (isPathSeparator, joinPath, splitDirectories, splitPath, (<.>), (</>))++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as LBS+import qualified Data.List.NonEmpty as NE+import qualified System.FilePath.Posix as FilePath.Posix++-- | Information about the features and capabilities of an @hc-pkg@+-- program.+--+data HcPkgInfo = HcPkgInfo+ { hcPkgProgram :: ConfiguredProgram+ , 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+ , 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+ , suppressFilesCheck :: Bool -- ^ supports --force-files or equivalent+ }+++-- | Call @hc-pkg@ to initialise a package database at the location {path}.+--+-- > hc-pkg init {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 ()+invoke hpi verbosity dbStack extraArgs =+ runProgramInvocation verbosity invocation+ where+ args = packageDbStackOpts hpi dbStack ++ extraArgs+ invocation = programInvocation (hcPkgProgram hpi) args++-- | Additional variations in the behaviour for 'register'.+data RegisterOptions = RegisterOptions {+ -- | Allows re-registering \/ overwriting an existing package+ registerAllowOverwrite :: Bool,++ -- | Insist on the ability to register multiple instances of a+ -- single version of a single package. This will fail if the @hc-pkg@+ -- does not support it, see 'nativeMultiInstance' and+ -- 'recacheMultiInstance'.+ registerMultiInstance :: Bool,++ -- | Require that no checks are performed on the existence of package+ -- files mentioned in the registration info. This must be used if+ -- registering prior to putting the files in their final place. This will+ -- fail if the @hc-pkg@ does not support it, see 'suppressFilesCheck'.+ registerSuppressFilesCheck :: Bool+ }++-- | Defaults are @True@, @False@ and @False@+defaultRegisterOptions :: RegisterOptions+defaultRegisterOptions = RegisterOptions {+ registerAllowOverwrite = True,+ registerMultiInstance = False,+ registerSuppressFilesCheck = False+ }++-- | Call @hc-pkg@ to register a package.+--+-- > hc-pkg register {filename | -} [--user | --global | --package-db]+--+register :: HcPkgInfo -> Verbosity -> PackageDBStack+ -> InstalledPackageInfo+ -> RegisterOptions+ -> IO ()+register hpi verbosity packagedbs pkgInfo registerOptions+ | registerMultiInstance registerOptions+ , not (nativeMultiInstance hpi || recacheMultiInstance hpi)+ = die' verbosity $ "HcPkg.register: the compiler does not support "+ ++ "registering multiple instances of packages."++ | registerSuppressFilesCheck registerOptions+ , not (suppressFilesCheck hpi)+ = die' verbosity $ "HcPkg.register: the compiler does not support "+ ++ "suppressing checks on files."++ -- 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.+ --+ | registerMultiInstance registerOptions+ , recacheMultiInstance hpi+ = do let pkgdb = registrationPackageDB packagedbs+ writeRegistrationFileDirectly verbosity hpi pkgdb pkgInfo+ recache hpi verbosity pkgdb++ | otherwise+ = runProgramInvocation verbosity+ (registerInvocation hpi verbosity packagedbs pkgInfo registerOptions)++writeRegistrationFileDirectly :: Verbosity+ -> HcPkgInfo+ -> PackageDB+ -> InstalledPackageInfo+ -> IO ()+writeRegistrationFileDirectly verbosity hpi (SpecificPackageDB dir) pkgInfo+ | supportsDirDbs hpi+ = do let pkgfile = dir </> prettyShow (installedUnitId pkgInfo) <.> "conf"+ writeUTF8File pkgfile (showInstalledPackageInfo pkgInfo)++ | otherwise+ = die' verbosity $ "HcPkg.writeRegistrationFileDirectly: compiler does not support dir style package dbs"++writeRegistrationFileDirectly verbosity _ _ _ =+ -- 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' verbosity $ "HcPkg.writeRegistrationFileDirectly: only supports SpecificPackageDB for now"+++-- | Call @hc-pkg@ to unregister a package+--+-- > hc-pkg unregister [pkgid] [--user | --global | --package-db]+--+unregister :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> IO ()+unregister hpi verbosity packagedb pkgid =+ runProgramInvocation verbosity+ (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]+--+expose :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> IO ()+expose hpi verbosity packagedb pkgid =+ 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 <- getProgramInvocationLBS verbosity+ (describeInvocation hpi verbosity packagedb pid)+ `catchIO` \_ -> return mempty++ case parsePackages output of+ Left ok -> return ok+ _ -> die' verbosity $ "failed to parse output of '"+ ++ programId (hcPkgProgram hpi) ++ " describe " ++ prettyShow pid ++ "'"++-- | Call @hc-pkg@ to hide a package.+--+-- > hc-pkg hide [pkgid] [--user | --global | --package-db]+--+hide :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId -> IO ()+hide hpi verbosity packagedb pkgid =+ runProgramInvocation verbosity+ (hideInvocation hpi verbosity packagedb pkgid)+++-- | Call @hc-pkg@ to get all the details of all the packages in the given+-- package database.+--+dump :: HcPkgInfo -> Verbosity -> PackageDB -> IO [InstalledPackageInfo]+dump hpi verbosity packagedb = do++ output <- getProgramInvocationLBS verbosity+ (dumpInvocation hpi verbosity packagedb)+ `catchIO` \e -> die' verbosity $ programId (hcPkgProgram hpi) ++ " dump failed: "+ ++ displayException e++ case parsePackages output of+ Left ok -> return ok+ _ -> die' verbosity $ "failed to parse output of '"+ ++ programId (hcPkgProgram hpi) ++ " dump'"+++parsePackages :: LBS.ByteString -> Either [InstalledPackageInfo] [String]+parsePackages lbs0 =+ case traverse parseInstalledPackageInfo $ splitPkgs lbs0 of+ Right ok -> Left [ setUnitId . maybe id mungePackagePaths (pkgRoot pkg) $ pkg | (_, pkg) <- ok ]+ Left msgs -> Right (NE.toList msgs)+ where+ splitPkgs :: LBS.ByteString -> [BS.ByteString]+ splitPkgs = checkEmpty . doSplit+ where+ -- Handle the case of there being no packages at all.+ checkEmpty [s] | BS.all isSpace8 s = []+ checkEmpty ss = ss++ isSpace8 :: Word8 -> Bool+ isSpace8 9 = True -- '\t'+ isSpace8 10 = True -- '\n'+ isSpace8 13 = True -- '\r'+ isSpace8 32 = True -- ' '+ isSpace8 _ = False++ doSplit :: LBS.ByteString -> [BS.ByteString]+ doSplit lbs = go (LBS.findIndices (\w -> w == 10 || w == 13) lbs)+ where+ go :: [Int64] -> [BS.ByteString]+ go [] = [ LBS.toStrict lbs ]+ go (idx:idxs) =+ let (pfx, sfx) = LBS.splitAt idx lbs+ in case foldr (<|>) Nothing $ map (`lbsStripPrefix` sfx) separators of+ Just sfx' -> LBS.toStrict pfx : doSplit sfx'+ Nothing -> go idxs++ separators :: [LBS.ByteString]+ separators = ["\n---\n", "\r\n---\r\n", "\r---\r"]++lbsStripPrefix :: LBS.ByteString -> LBS.ByteString -> Maybe LBS.ByteString+#if MIN_VERSION_bytestring(0,10,8)+lbsStripPrefix pfx lbs = LBS.stripPrefix pfx lbs+#else+lbsStripPrefix pfx lbs+ | LBS.isPrefixOf pfx lbs = Just (LBS.drop (LBS.length pfx) lbs)+ | otherwise = Nothing+#endif+++mungePackagePaths :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo+-- Perform path/URL variable substitution as per the Cabal ${pkgroot} spec+-- (http://www.haskell.org/pipermail/libraries/2009-May/011772.html)+-- Paths/URLs can be relative to ${pkgroot} or ${pkgrooturl}.+-- The "pkgroot" is the directory containing the package database.+mungePackagePaths pkgroot pkginfo =+ pkginfo {+ importDirs = mungePaths (importDirs pkginfo),+ includeDirs = mungePaths (includeDirs pkginfo),+ libraryDirs = mungePaths (libraryDirs pkginfo),+ libraryDynDirs = mungePaths (libraryDynDirs pkginfo),+ frameworkDirs = mungePaths (frameworkDirs pkginfo),+ haddockInterfaces = mungePaths (haddockInterfaces pkginfo),+ haddockHTMLs = mungeUrls (haddockHTMLs pkginfo)+ }+ where+ mungePaths = map mungePath+ mungeUrls = map mungeUrl++ mungePath p = case stripVarPrefix "${pkgroot}" p of+ Just p' -> pkgroot </> p'+ Nothing -> p++ mungeUrl p = case stripVarPrefix "${pkgrooturl}" p of+ Just p' -> toUrlPath pkgroot p'+ Nothing -> p++ toUrlPath r p = "file:///"+ -- URLs always use posix style '/' separators:+ ++ FilePath.Posix.joinPath (r : FilePath.splitDirectories p)++ stripVarPrefix var p =+ case splitPath p of+ (root:path') -> case stripPrefix var root of+ Just [sep] | isPathSeparator sep -> Just (joinPath path')+ _ -> Nothing+ _ -> Nothing+++-- 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.+-- NB: Internal libraries not supported.+setUnitId :: InstalledPackageInfo -> InstalledPackageInfo+setUnitId pkginfo@InstalledPackageInfo {+ installedUnitId = uid,+ sourcePackageId = pid+ } | unUnitId uid == ""+ = pkginfo {+ installedUnitId = mkLegacyUnitId pid,+ installedComponentId_ = mkComponentId (prettyShow pid)+ }+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 'UnitId', just+-- the source 'PackageId' which is not necessarily unique in any package db.+--+list :: HcPkgInfo -> Verbosity -> PackageDB+ -> IO [PackageId]+list hpi verbosity packagedb = do++ output <- getProgramInvocationOutput verbosity+ (listInvocation hpi verbosity packagedb)+ `catchIO` \_ -> die' verbosity $ programId (hcPkgProgram hpi) ++ " list failed"++ case parsePackageIds output of+ Just ok -> return ok+ _ -> die' verbosity $ "failed to parse output of '"+ ++ programId (hcPkgProgram hpi) ++ " list'"++ where+ parsePackageIds = traverse simpleParsec . words++--------------------------+-- The program invocations+--++initInvocation :: HcPkgInfo -> Verbosity -> FilePath -> ProgramInvocation+initInvocation hpi verbosity path =+ programInvocation (hcPkgProgram hpi) args+ where+ args = ["init", path]+ ++ verbosityOpts hpi verbosity++registerInvocation+ :: HcPkgInfo -> Verbosity -> PackageDBStack+ -> InstalledPackageInfo+ -> RegisterOptions+ -> ProgramInvocation+registerInvocation hpi verbosity packagedbs pkgInfo registerOptions =+ (programInvocation (hcPkgProgram hpi) (args "-")) {+ progInvokeInput = Just $ IODataText $ showInstalledPackageInfo pkgInfo,+ progInvokeInputEncoding = IOEncodingUTF8+ }+ where+ cmdname+ | registerAllowOverwrite registerOptions = "update"+ | registerMultiInstance registerOptions = "update"+ | otherwise = "register"++ args file = [cmdname, file]+ ++ packageDbStackOpts hpi packagedbs+ ++ [ "--enable-multi-instance"+ | registerMultiInstance registerOptions ]+ ++ [ "--force-files"+ | registerSuppressFilesCheck registerOptions ]+ ++ verbosityOpts hpi verbosity++unregisterInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId+ -> ProgramInvocation+unregisterInvocation hpi verbosity packagedb pkgid =+ programInvocation (hcPkgProgram hpi) $+ ["unregister", packageDbOpts hpi packagedb, prettyShow pkgid]+ ++ 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 =+ programInvocation (hcPkgProgram hpi) $+ ["expose", packageDbOpts hpi packagedb, prettyShow pkgid]+ ++ verbosityOpts hpi verbosity++describeInvocation :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId+ -> ProgramInvocation+describeInvocation hpi verbosity packagedbs pkgid =+ programInvocation (hcPkgProgram hpi) $+ ["describe", prettyShow pkgid]+ ++ packageDbStackOpts hpi packagedbs+ ++ verbosityOpts hpi verbosity++hideInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId+ -> ProgramInvocation+hideInvocation hpi verbosity packagedb pkgid =+ programInvocation (hcPkgProgram hpi) $+ ["hide", packageDbOpts hpi packagedb, prettyShow pkgid]+ ++ verbosityOpts hpi verbosity+++dumpInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> ProgramInvocation+dumpInvocation hpi _verbosity packagedb =+ (programInvocation (hcPkgProgram hpi) args) {+ progInvokeOutputEncoding = IOEncodingUTF8+ }+ where+ args = ["dump", packageDbOpts hpi packagedb]+ ++ verbosityOpts hpi silent+ -- We use verbosity level 'silent' because it is important that we+ -- do not contaminate the output with info/debug messages.++listInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> ProgramInvocation+listInvocation hpi _verbosity packagedb =+ (programInvocation (hcPkgProgram hpi) args) {+ progInvokeOutputEncoding = IOEncodingUTF8+ }+ where+ args = ["list", "--simple-output", packageDbOpts hpi packagedb]+ ++ verbosityOpts hpi silent+ -- We use verbosity level 'silent' because it is important that we+ -- do not contaminate the output with info/debug messages.+++packageDbStackOpts :: HcPkgInfo -> PackageDBStack -> [String]+packageDbStackOpts hpi dbstack+ | noPkgDbStack hpi = [packageDbOpts hpi (registrationPackageDB dbstack)]+ | otherwise = case dbstack of+ (GlobalPackageDB:UserPackageDB:dbs) -> "--global"+ : "--user"+ : map specific dbs+ (GlobalPackageDB:dbs) -> "--global"+ : ("--no-user-" ++ packageDbFlag hpi)+ : map specific dbs+ _ -> ierror+ where+ specific (SpecificPackageDB db) = "--" ++ packageDbFlag hpi ++ "=" ++ db+ specific _ = ierror+ ierror :: a+ ierror = error ("internal error: unexpected package db stack: " ++ show dbstack)++packageDbFlag :: HcPkgInfo -> String+packageDbFlag hpi+ | flagPackageConf hpi+ = "package-conf"+ | otherwise+ = "package-db"++packageDbOpts :: HcPkgInfo -> PackageDB -> String+packageDbOpts _ GlobalPackageDB = "--global"+packageDbOpts _ UserPackageDB = "--user"+packageDbOpts hpi (SpecificPackageDB db) = "--" ++ packageDbFlag hpi ++ "=" ++ db++verbosityOpts :: HcPkgInfo -> Verbosity -> [String]+verbosityOpts hpi v+ | noVerboseFlag hpi+ = []+ | v >= deafening = ["-v2"]+ | v == silent = ["-v0"]+ | otherwise = []
+ src/Distribution/Simple/Program/Hpc.hs view
@@ -0,0 +1,109 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Hpc+-- Copyright : Thomas Tuegel 2011+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides an library interface to the @hpc@ program.++module Distribution.Simple.Program.Hpc+ ( markup+ , union+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import System.Directory (makeRelativeToCurrentDirectory)++import Distribution.ModuleName+import Distribution.Simple.Program.Run+import Distribution.Simple.Program.Types+import Distribution.Pretty+import Distribution.Simple.Utils+import Distribution.Verbosity+import Distribution.Version++-- | Invoke hpc with the given parameters.+--+-- Prior to HPC version 0.7 (packaged with GHC 7.8), hpc did not handle+-- multiple .mix paths correctly, so we print a warning, and only pass it the+-- first path in the list. This means that e.g. test suites that import their+-- library as a dependency can still work, but those that include the library+-- modules directly (in other-modules) don't.+markup :: ConfiguredProgram+ -> Version+ -> Verbosity+ -> FilePath -- ^ Path to .tix file+ -> [FilePath] -- ^ Paths to .mix file directories+ -> FilePath -- ^ Path where html output should be located+ -> [ModuleName] -- ^ List of modules to include in the report+ -> IO ()+markup hpc hpcVer verbosity tixFile hpcDirs destDir included = do+ hpcDirs' <- if withinRange hpcVer (orLaterVersion version07)+ then return hpcDirs+ else do+ warn verbosity $ "Your version of HPC (" ++ prettyShow hpcVer+ ++ ") does not properly handle multiple search paths. "+ ++ "Coverage report generation may fail unexpectedly. These "+ ++ "issues are addressed in version 0.7 or later (GHC 7.8 or "+ ++ "later)."+ ++ if null droppedDirs+ then ""+ else " The following search paths have been abandoned: "+ ++ show droppedDirs+ return passedDirs++ -- Prior to GHC 8.0, hpc assumes all .mix paths are relative.+ hpcDirs'' <- traverse makeRelativeToCurrentDirectory hpcDirs'++ runProgramInvocation verbosity+ (markupInvocation hpc tixFile hpcDirs'' destDir included)+ where+ version07 = mkVersion [0, 7]+ (passedDirs, droppedDirs) = splitAt 1 hpcDirs++markupInvocation :: ConfiguredProgram+ -> FilePath -- ^ Path to .tix file+ -> [FilePath] -- ^ Paths to .mix file directories+ -> FilePath -- ^ Path where html output should be+ -- located+ -> [ModuleName] -- ^ List of modules to include+ -> ProgramInvocation+markupInvocation hpc tixFile hpcDirs destDir included =+ let args = [ "markup", tixFile+ , "--destdir=" ++ destDir+ ]+ ++ map ("--hpcdir=" ++) hpcDirs+ ++ ["--include=" ++ prettyShow moduleName+ | moduleName <- included ]+ in programInvocation hpc args++union :: ConfiguredProgram+ -> Verbosity+ -> [FilePath] -- ^ Paths to .tix files+ -> FilePath -- ^ Path to resultant .tix file+ -> [ModuleName] -- ^ List of modules to exclude from union+ -> IO ()+union hpc verbosity tixFiles outFile excluded =+ runProgramInvocation verbosity+ (unionInvocation hpc tixFiles outFile excluded)++unionInvocation :: ConfiguredProgram+ -> [FilePath] -- ^ Paths to .tix files+ -> FilePath -- ^ Path to resultant .tix file+ -> [ModuleName] -- ^ List of modules to exclude from union+ -> ProgramInvocation+unionInvocation hpc tixFiles outFile excluded =+ programInvocation hpc $ concat+ [ ["sum", "--union"]+ , tixFiles+ , ["--output=" ++ outFile]+ , ["--exclude=" ++ prettyShow moduleName+ | moduleName <- excluded ]+ ]
+ src/Distribution/Simple/Program/Internal.hs view
@@ -0,0 +1,47 @@+-----------------------------------------------------------------------------+-- |+-- 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 Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.Generic(safeTail)++-- | 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) ((safeTail 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+ _ -> ""
+ src/Distribution/Simple/Program/Ld.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Ld+-- Copyright : Duncan Coutts 2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides an library interface to the @ld@ linker program.++module Distribution.Simple.Program.Ld (+ combineObjectFiles,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.Compiler (arResponseFilesSupported)+import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))+import Distribution.Simple.Program.ResponseFile+ ( withResponseFile )+import Distribution.Simple.Program.Run+ ( ProgramInvocation, programInvocation, multiStageProgramInvocation+ , runProgramInvocation )+import Distribution.Simple.Program.Types+ ( ConfiguredProgram(..) )+import Distribution.Simple.Setup+ ( fromFlagOrDefault, configUseResponseFiles )+import Distribution.Simple.Utils+ ( defaultTempFileOptions )+import Distribution.Verbosity+ ( Verbosity )++import System.Directory+ ( renameFile )+import System.FilePath+ ( (<.>), takeDirectory )++-- | Call @ld -r@ to link a bunch of object files together.+--+combineObjectFiles :: Verbosity -> LocalBuildInfo -> ConfiguredProgram+ -> FilePath -> [FilePath] -> IO ()+combineObjectFiles verbosity lbi ld target files = do++ -- Unlike "ar", the "ld" tool is not designed to be used with xargs. That is,+ -- if we have more object files than fit on a single command line then we+ -- have a slight problem. What we have to do is link files in batches into+ -- a temp object file and then include that one in the next batch.++ let simpleArgs = ["-r", "-o", target]++ initialArgs = ["-r", "-o", target]+ middleArgs = ["-r", "-o", target, tmpfile]+ finalArgs = middleArgs++ simple = programInvocation ld simpleArgs+ initial = programInvocation ld initialArgs+ middle = programInvocation ld middleArgs+ final = programInvocation ld finalArgs++ targetDir = takeDirectory target++ invokeWithResponesFile :: FilePath -> ProgramInvocation+ invokeWithResponesFile atFile =+ programInvocation ld $ simpleArgs ++ ['@' : atFile]++ oldVersionManualOverride =+ fromFlagOrDefault False $ configUseResponseFiles $ configFlags lbi+ -- Whether ghc's ar supports response files is a good proxy for+ -- whether ghc's ld supports them as well.+ responseArgumentsNotSupported =+ not (arResponseFilesSupported (compiler lbi))++ if oldVersionManualOverride || responseArgumentsNotSupported+ then+ run $ multiStageProgramInvocation simple (initial, middle, final) files+ else+ withResponseFile verbosity defaultTempFileOptions targetDir "ld.rsp" Nothing files $+ \path -> runProgramInvocation verbosity $ invokeWithResponesFile path++ where+ tmpfile = target <.> "tmp" -- perhaps should use a proper temp file++ run :: [ProgramInvocation] -> IO ()+ run [] = return ()+ run [inv] = runProgramInvocation verbosity inv+ run (inv:invs) = do runProgramInvocation verbosity inv+ renameFile target tmpfile+ run invs
+ src/Distribution/Simple/Program/ResponseFile.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.ResponseFile+-- Copyright : (c) Sergey Vinokurov 2017+-- License : BSD3-style+--+-- Maintainer : cabal-devel@haskell.org+-- Created : 23 July 2017+----------------------------------------------------------------------------++module Distribution.Simple.Program.ResponseFile (withResponseFile) where++import Prelude ()+import System.IO (TextEncoding, hSetEncoding, hPutStr, hClose)++import Distribution.Compat.Prelude+import Distribution.Simple.Utils (TempFileOptions, withTempFileEx, debug)+import Distribution.Verbosity++withResponseFile+ :: Verbosity+ -> TempFileOptions+ -> FilePath -- ^ Working directory to create response file in.+ -> FilePath -- ^ Template for response file name.+ -> Maybe TextEncoding -- ^ Encoding to use for response file contents.+ -> [String] -- ^ Arguments to put into response file.+ -> (FilePath -> IO a)+ -> IO a+withResponseFile verbosity tmpFileOpts workDir fileNameTemplate encoding arguments f =+ withTempFileEx tmpFileOpts workDir fileNameTemplate $ \responseFileName hf -> do+ traverse_ (hSetEncoding hf) encoding+ let responseContents = unlines $ map escapeResponseFileArg arguments+ hPutStr hf responseContents+ hClose hf+ debug verbosity $ responseFileName ++ " contents: <<<"+ debug verbosity responseContents+ debug verbosity $ ">>> " ++ responseFileName+ f responseFileName++-- Support a gcc-like response file syntax. Each separate+-- argument and its possible parameter(s), will be separated in the+-- response file by an actual newline; all other whitespace,+-- single quotes, double quotes, and the character used for escaping+-- (backslash) are escaped. The called program will need to do a similar+-- inverse operation to de-escape and re-constitute the argument list.+escapeResponseFileArg :: String -> String+escapeResponseFileArg = reverse . foldl' escape []+ where+ escape :: String -> Char -> String+ escape cs c =+ case c of+ '\\' -> c:'\\':cs+ '\'' -> c:'\\':cs+ '"' -> c:'\\':cs+ _ | isSpace c -> c:'\\':cs+ | otherwise -> c:cs++
+ src/Distribution/Simple/Program/Run.hs view
@@ -0,0 +1,297 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Run+-- Copyright : Duncan Coutts 2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides a data type for program invocations and functions to+-- run them.++module Distribution.Simple.Program.Run (+ ProgramInvocation(..),+ IOEncoding(..),+ emptyProgramInvocation,+ simpleProgramInvocation,+ programInvocation,+ multiStageProgramInvocation,++ runProgramInvocation,+ getProgramInvocationOutput,+ getProgramInvocationLBS,+ getProgramInvocationOutputAndErrors,++ getEffectiveEnvironment,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Compat.Environment+import Distribution.Simple.Program.Types+import Distribution.Simple.Utils+import Distribution.Utils.Generic+import Distribution.Verbosity++import System.FilePath (searchPathSeparator)++import qualified Data.ByteString.Lazy as LBS+import qualified Data.Map as Map++-- | Represents a specific invocation of a specific program.+--+-- This is used as an intermediate type between deciding how to call a program+-- and actually doing it. This provides the opportunity to the caller to+-- adjust how the program will be called. These invocations can either be run+-- directly or turned into shell or batch scripts.+--+data ProgramInvocation = ProgramInvocation {+ progInvokePath :: FilePath,+ progInvokeArgs :: [String],+ progInvokeEnv :: [(String, Maybe String)],+ -- Extra paths to add to PATH+ progInvokePathEnv :: [FilePath],+ progInvokeCwd :: Maybe FilePath,+ progInvokeInput :: Maybe IOData,+ progInvokeInputEncoding :: IOEncoding, -- ^ TODO: remove this, make user decide when constructing 'progInvokeInput'.+ progInvokeOutputEncoding :: IOEncoding+ }++data IOEncoding = IOEncodingText -- locale mode text+ | IOEncodingUTF8 -- always utf8++encodeToIOData :: IOEncoding -> IOData -> IOData+encodeToIOData _ iod@(IODataBinary _) = iod+encodeToIOData IOEncodingText iod@(IODataText _) = iod+encodeToIOData IOEncodingUTF8 (IODataText str) = IODataBinary (toUTF8LBS str)++emptyProgramInvocation :: ProgramInvocation+emptyProgramInvocation =+ ProgramInvocation {+ progInvokePath = "",+ progInvokeArgs = [],+ progInvokeEnv = [],+ progInvokePathEnv = [],+ progInvokeCwd = Nothing,+ progInvokeInput = Nothing,+ progInvokeInputEncoding = IOEncodingText,+ progInvokeOutputEncoding = IOEncodingText+ }++simpleProgramInvocation :: FilePath -> [String] -> ProgramInvocation+simpleProgramInvocation path args =+ emptyProgramInvocation {+ progInvokePath = path,+ progInvokeArgs = args+ }++programInvocation :: ConfiguredProgram -> [String] -> ProgramInvocation+programInvocation prog args =+ emptyProgramInvocation {+ progInvokePath = programPath prog,+ progInvokeArgs = programDefaultArgs prog+ ++ args+ ++ programOverrideArgs prog,+ progInvokeEnv = programOverrideEnv prog+ }+++runProgramInvocation :: Verbosity -> ProgramInvocation -> IO ()+runProgramInvocation verbosity+ ProgramInvocation {+ progInvokePath = path,+ progInvokeArgs = args,+ progInvokeEnv = [],+ progInvokePathEnv = [],+ progInvokeCwd = Nothing,+ progInvokeInput = Nothing+ } =+ rawSystemExit verbosity path args++runProgramInvocation verbosity+ ProgramInvocation {+ progInvokePath = path,+ progInvokeArgs = args,+ progInvokeEnv = envOverrides,+ progInvokePathEnv = extraPath,+ progInvokeCwd = mcwd,+ progInvokeInput = Nothing+ } = do+ pathOverride <- getExtraPathEnv envOverrides extraPath+ menv <- getEffectiveEnvironment (envOverrides ++ pathOverride)+ exitCode <- rawSystemIOWithEnv verbosity+ path args+ mcwd menv+ Nothing Nothing Nothing+ when (exitCode /= ExitSuccess) $+ exitWith exitCode++runProgramInvocation verbosity+ ProgramInvocation {+ progInvokePath = path,+ progInvokeArgs = args,+ progInvokeEnv = envOverrides,+ progInvokePathEnv = extraPath,+ progInvokeCwd = mcwd,+ progInvokeInput = Just inputStr,+ progInvokeInputEncoding = encoding+ } = do+ pathOverride <- getExtraPathEnv envOverrides extraPath+ menv <- getEffectiveEnvironment (envOverrides ++ pathOverride)+ (_, errors, exitCode) <- rawSystemStdInOut verbosity+ path args+ mcwd menv+ (Just input) IODataModeBinary+ when (exitCode /= ExitSuccess) $+ die' verbosity $ "'" ++ path ++ "' exited with an error:\n" ++ errors+ where+ input = encodeToIOData encoding inputStr++getProgramInvocationOutput :: Verbosity -> ProgramInvocation -> IO String+getProgramInvocationOutput verbosity inv = do+ (output, errors, exitCode) <- getProgramInvocationOutputAndErrors verbosity inv+ when (exitCode /= ExitSuccess) $+ die' verbosity $ "'" ++ progInvokePath inv ++ "' exited with an error:\n" ++ errors+ return output++getProgramInvocationLBS :: Verbosity -> ProgramInvocation -> IO LBS.ByteString+getProgramInvocationLBS verbosity inv = do+ (output, errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeBinary+ when (exitCode /= ExitSuccess) $+ die' verbosity $ "'" ++ progInvokePath inv ++ "' exited with an error:\n" ++ errors+ return output++getProgramInvocationOutputAndErrors :: Verbosity -> ProgramInvocation+ -> IO (String, String, ExitCode)+getProgramInvocationOutputAndErrors verbosity inv = case progInvokeOutputEncoding inv of+ IOEncodingText -> do+ (output, errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeText+ return (output, errors, exitCode)+ IOEncodingUTF8 -> do+ (output', errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeBinary+ return (normaliseLineEndings (fromUTF8LBS output'), errors, exitCode)++getProgramInvocationIODataAndErrors+ :: KnownIODataMode mode => Verbosity -> ProgramInvocation -> IODataMode mode+ -> IO (mode, String, ExitCode)+getProgramInvocationIODataAndErrors+ verbosity+ ProgramInvocation+ { progInvokePath = path+ , progInvokeArgs = args+ , progInvokeEnv = envOverrides+ , progInvokePathEnv = extraPath+ , progInvokeCwd = mcwd+ , progInvokeInput = minputStr+ , progInvokeInputEncoding = encoding+ }+ mode = do+ pathOverride <- getExtraPathEnv envOverrides extraPath+ menv <- getEffectiveEnvironment (envOverrides ++ pathOverride)+ rawSystemStdInOut verbosity path args mcwd menv input mode+ where+ input = encodeToIOData encoding <$> minputStr++getExtraPathEnv :: [(String, Maybe String)] -> [FilePath] -> IO [(String, Maybe String)]+getExtraPathEnv _ [] = return []+getExtraPathEnv env extras = do+ mb_path <- case lookup "PATH" env of+ Just x -> return x+ Nothing -> lookupEnv "PATH"+ let extra = intercalate [searchPathSeparator] extras+ path' = case mb_path of+ Nothing -> extra+ Just path -> extra ++ searchPathSeparator : path+ return [("PATH", Just path')]++-- | Return the current environment extended with the given overrides.+-- If an entry is specified twice in @overrides@, the second entry takes+-- precedence.+--+getEffectiveEnvironment :: [(String, Maybe String)]+ -> IO (Maybe [(String, String)])+getEffectiveEnvironment [] = return Nothing+getEffectiveEnvironment overrides =+ fmap (Just . Map.toList . apply overrides . Map.fromList) getEnvironment+ where+ apply os env = foldl' (flip update) env os+ update (var, Nothing) = Map.delete var+ update (var, Just val) = Map.insert var val++-- | Like the unix xargs program. Useful for when we've got very long command+-- lines that might overflow an OS limit on command line length and so you+-- need to invoke a command multiple times to get all the args in.+--+-- It takes four template invocations corresponding to the simple, initial,+-- middle and last invocations. If the number of args given is small enough+-- that we can get away with just a single invocation then the simple one is+-- used:+--+-- > $ simple args+--+-- If the number of args given means that we need to use multiple invocations+-- then the templates for the initial, middle and last invocations are used:+--+-- > $ initial args_0+-- > $ middle args_1+-- > $ middle args_2+-- > ...+-- > $ final args_n+--+multiStageProgramInvocation+ :: ProgramInvocation+ -> (ProgramInvocation, ProgramInvocation, ProgramInvocation)+ -> [String]+ -> [ProgramInvocation]+multiStageProgramInvocation simple (initial, middle, final) args =++ let argSize inv = length (progInvokePath inv)+ + foldl' (\s a -> length a + 1 + s) 1 (progInvokeArgs inv)+ fixedArgSize = maximum (map argSize [simple, initial, middle, final])+ chunkSize = maxCommandLineSize - fixedArgSize++ in case splitChunks chunkSize args of+ [] -> [ simple ]++ [c] -> [ simple `appendArgs` c ]++ (c:c2:cs) | (xs, x) <- unsnocNE (c2:|cs) ->+ [ initial `appendArgs` c ]+ ++ [ middle `appendArgs` c'| c' <- xs ]+ ++ [ final `appendArgs` x ]++ where+ appendArgs :: ProgramInvocation -> [String] -> ProgramInvocation+ inv `appendArgs` as = inv { progInvokeArgs = progInvokeArgs inv ++ as }++ splitChunks :: Int -> [[a]] -> [[[a]]]+ splitChunks len = unfoldr $ \s ->+ if null s then Nothing+ else Just (chunk len s)++ chunk :: Int -> [[a]] -> ([[a]], [[a]])+ chunk len (s:_) | length s >= len = error toolong+ chunk len ss = chunk' [] len ss++ chunk' :: [[a]] -> Int -> [[a]] -> ([[a]], [[a]])+ chunk' acc len (s:ss)+ | len' < len = chunk' (s:acc) (len-len'-1) ss+ where len' = length s+ chunk' acc _ ss = (reverse acc, ss)++ toolong = "multiStageProgramInvocation: a single program arg is larger "+ ++ "than the maximum command line length!"+++--FIXME: discover this at configure time or runtime on unix+-- The value is 32k on Windows and posix specifies a minimum of 4k+-- but all sensible unixes use more than 4k.+-- we could use getSysVar ArgumentLimit but that's in the unix lib+--+maxCommandLineSize :: Int+maxCommandLineSize = 30 * 1024
+ src/Distribution/Simple/Program/Script.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE GADTs #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Script+-- Copyright : Duncan Coutts 2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides an library interface to the @hc-pkg@ program.+-- Currently only GHC and LHC have hc-pkg programs.++module Distribution.Simple.Program.Script (++ invocationAsSystemScript,+ invocationAsShellScript,+ invocationAsBatchFile,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.Program.Run+import Distribution.Simple.Utils+import Distribution.System++-- | Generate a system script, either POSIX shell script or Windows batch file+-- as appropriate for the given system.+--+invocationAsSystemScript :: OS -> ProgramInvocation -> String+invocationAsSystemScript Windows = invocationAsBatchFile+invocationAsSystemScript _ = invocationAsShellScript+++-- | Generate a POSIX shell script that invokes a program.+--+invocationAsShellScript :: ProgramInvocation -> String+invocationAsShellScript+ ProgramInvocation {+ progInvokePath = path,+ progInvokeArgs = args,+ progInvokeEnv = envExtra,+ progInvokeCwd = mcwd,+ progInvokeInput = minput+ } = unlines $+ [ "#!/bin/sh" ]+ ++ concatMap setEnv envExtra+ ++ [ "cd " ++ quote cwd | cwd <- maybeToList mcwd ]+ ++ [ (case minput of+ Nothing -> ""+ Just input -> "echo " ++ quote (iodataToText input) ++ " | ")+ ++ unwords (map quote $ path : args) ++ " \"$@\""]++ where+ setEnv (var, Nothing) = ["unset " ++ var, "export " ++ var]+ setEnv (var, Just val) = ["export " ++ var ++ "=" ++ quote val]++ quote :: String -> String+ quote s = "'" ++ escape s ++ "'"++ escape [] = []+ escape ('\'':cs) = "'\\''" ++ escape cs+ escape (c :cs) = c : escape cs++iodataToText :: IOData -> String+iodataToText (IODataText str) = str+iodataToText (IODataBinary lbs) = fromUTF8LBS lbs+++-- | Generate a Windows batch file that invokes a program.+--+invocationAsBatchFile :: ProgramInvocation -> String+invocationAsBatchFile+ ProgramInvocation {+ progInvokePath = path,+ progInvokeArgs = args,+ progInvokeEnv = envExtra,+ progInvokeCwd = mcwd,+ progInvokeInput = minput+ } = unlines $+ [ "@echo off" ]+ ++ map setEnv envExtra+ ++ [ "cd \"" ++ cwd ++ "\"" | cwd <- maybeToList mcwd ]+ ++ case minput of+ Nothing ->+ [ path ++ concatMap (' ':) args ]++ Just input ->+ [ "(" ]+ ++ [ "echo " ++ escape line | line <- lines $ iodataToText input ]+ ++ [ ") | "+ ++ "\"" ++ path ++ "\""+ ++ concatMap (\arg -> ' ':quote arg) args ]++ where+ setEnv (var, Nothing) = "set " ++ var ++ "="+ setEnv (var, Just val) = "set " ++ var ++ "=" ++ escape val++ quote :: String -> String+ quote s = "\"" ++ escapeQ s ++ "\""++ escapeQ [] = []+ escapeQ ('"':cs) = "\"\"\"" ++ escapeQ cs+ escapeQ (c :cs) = c : escapeQ cs++ escape [] = []+ escape ('|':cs) = "^|" ++ escape cs+ escape ('<':cs) = "^<" ++ escape cs+ escape ('>':cs) = "^>" ++ escape cs+ escape ('&':cs) = "^&" ++ escape cs+ escape ('(':cs) = "^(" ++ escape cs+ escape (')':cs) = "^)" ++ escape cs+ escape ('^':cs) = "^^" ++ escape cs+ escape (c :cs) = c : escape cs
+ src/Distribution/Simple/Program/Strip.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Strip+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module provides an library interface to the @strip@ program.++module Distribution.Simple.Program.Strip (stripLib, stripExe)+ where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Simple.Program+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Verbosity+import Distribution.Version++import System.FilePath (takeBaseName)++runStrip :: Verbosity -> ProgramDb -> FilePath -> [String] -> IO ()+runStrip verbosity progDb path args =+ case lookupProgram stripProgram progDb of+ Just strip -> runProgram verbosity strip (args ++ [path])+ Nothing -> unless (buildOS == Windows) $+ -- Don't bother warning on windows, we don't expect them to+ -- have the strip program anyway.+ warn verbosity $ "Unable to strip executable or library '"+ ++ (takeBaseName path)+ ++ "' (missing the 'strip' program)"++stripExe :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()+stripExe verbosity (Platform _arch os) progdb path =+ runStrip verbosity progdb path args+ where+ args = case os of+ OSX -> ["-x"] -- By default, stripping the ghc binary on at least+ -- some OS X installations causes:+ -- HSbase-3.0.o: unknown symbol `_environ'"+ -- The -x flag fixes that.+ _ -> []++stripLib :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()+stripLib verbosity (Platform arch os) progdb path = do+ case os of+ 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+ -- #1784.+ return()+ Linux | arch == I386 ->+ -- Versions of 'strip' on 32-bit Linux older than 2.18 are+ -- broken. See #2339.+ let okVersion = orLaterVersion (mkVersion [2,18])+ in case programVersion =<< lookupProgram stripProgram progdb of+ Just v | withinRange v okVersion ->+ runStrip verbosity progdb path args+ _ -> warn verbosity $ "Unable to strip library '"+ ++ (takeBaseName path)+ ++ "' (version of 'strip' too old; "+ ++ "requires >= 2.18 on 32-bit Linux)"+ _ -> runStrip verbosity progdb path args+ where+ args = ["--strip-unneeded"]
+ src/Distribution/Simple/Program/Types.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE DeriveDataTypeable #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Program.Types+-- Copyright : Isaac Jones 2006, Duncan Coutts 2007-2009+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This provides an abstraction which deals with configuring and running+-- programs. A 'Program' is a static notion of a known program. A+-- 'ConfiguredProgram' is a 'Program' that has been found on the current+-- machine and is ready to be run (possibly with some user-supplied default+-- args). Configuring a program involves finding its location and if necessary+-- finding its version. There's reasonable default behavior for trying to find+-- \"foo\" in PATH, being able to override its location, etc.+--+module Distribution.Simple.Program.Types (+ -- * Program and functions for constructing them+ Program(..),+ ProgramSearchPath,+ ProgramSearchPathEntry(..),+ simpleProgram,++ -- * Configured program and related functions+ ConfiguredProgram(..),+ programPath,+ suppressOverrideArgs,+ ProgArg,+ ProgramLocation(..),+ simpleConfiguredProgram,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.PackageDescription+import Distribution.Simple.Program.Find+import Distribution.Version+import Distribution.Verbosity++import qualified Data.Map as Map++-- | Represents a program which can be configured.+--+-- Note: rather than constructing this directly, start with 'simpleProgram' and+-- override any extra fields.+--+data Program = Program {+ -- | The simple name of the program, eg. ghc+ programName :: String,++ -- | A function to search for the program if its location was not+ -- specified by the user. Usually this will just be a call to+ -- 'findProgramOnSearchPath'.+ --+ -- 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, [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.+ programFindVersion :: Verbosity -> FilePath -> IO (Maybe Version),++ -- | A function to do any additional configuration after we have+ -- located the program (and perhaps identified its version). For example+ -- it could add args, or environment vars.+ programPostConf :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram,+ -- | A function that filters any arguments that don't impact the output+ -- from a commandline. Used to limit the volatility of dependency hashes+ -- when using new-build.+ programNormaliseArgs :: Maybe Version -> PackageDescription -> [String] -> [String]+ }+instance Show Program where+ show (Program name _ _ _ _) = "Program: " ++ name++type ProgArg = String++-- | Represents a program which has been configured and is thus ready to be run.+--+-- These are usually made by configuring a 'Program', but if you have to+-- construct one directly then start with 'simpleConfiguredProgram' and+-- override any extra fields.+--+data ConfiguredProgram = ConfiguredProgram {+ -- | Just the name again+ programId :: String,++ -- | The version of this program, if it is known.+ programVersion :: Maybe Version,++ -- | Default command-line args for this program.+ -- These flags will appear first on the command line, so they can be+ -- overridden by subsequent flags.+ programDefaultArgs :: [String],++ -- | Override command-line args for this program.+ -- These flags will appear last on the command line, so they override+ -- all earlier flags.+ programOverrideArgs :: [String],++ -- | Override environment variables for this program.+ -- These env vars will extend\/override the prevailing environment of+ -- the current to form the environment for the new process.+ programOverrideEnv :: [(String, Maybe String)],++ -- | A key-value map listing various properties of the program, useful+ -- for feature detection. Populated during the configuration step, key+ -- names depend on the specific program.+ programProperties :: Map.Map String String,++ -- | Location of the program. eg. @\/usr\/bin\/ghc-6.4@+ 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, Typeable)++instance Binary ConfiguredProgram+instance Structured ConfiguredProgram++-- | Where a program was found. Also tells us whether it's specified by user or+-- not. This includes not just the path, but the program as well.+data ProgramLocation+ = UserSpecified { locationPath :: FilePath }+ -- ^The user gave the path to this program,+ -- eg. --ghc-path=\/usr\/bin\/ghc-6.6+ | FoundOnSystem { locationPath :: FilePath }+ -- ^The program was found automatically.+ deriving (Eq, Generic, Read, Show, Typeable)++instance Binary ProgramLocation+instance Structured ProgramLocation++-- | The full path of a configured program.+programPath :: ConfiguredProgram -> FilePath+programPath = locationPath . programLocation++-- | Suppress any extra arguments added by the user.+suppressOverrideArgs :: ConfiguredProgram -> ConfiguredProgram+suppressOverrideArgs prog = prog { programOverrideArgs = [] }++-- | Make a simple named program.+--+-- By default we'll just search for it in the path and not try to find the+-- version name. You can override these behaviours if necessary, eg:+--+-- > (simpleProgram "foo") { programFindLocation = ... , programFindVersion ... }+--+simpleProgram :: String -> Program+simpleProgram name = Program {+ programName = name,+ programFindLocation = \v p -> findProgramOnSearchPath v p name,+ programFindVersion = \_ _ -> return Nothing,+ programPostConf = \_ p -> return p,+ programNormaliseArgs = \_ _ -> id+ }++-- | Make a simple 'ConfiguredProgram'.+--+-- > simpleConfiguredProgram "foo" (FoundOnSystem path)+--+simpleConfiguredProgram :: String -> ProgramLocation -> ConfiguredProgram+simpleConfiguredProgram name loc = ConfiguredProgram {+ programId = name,+ programVersion = Nothing,+ programDefaultArgs = [],+ programOverrideArgs = [],+ programOverrideEnv = [],+ programProperties = Map.empty,+ programLocation = loc,+ programMonitorFiles = [] -- did not look in any other locations+ }
+ src/Distribution/Simple/Register.hs view
@@ -0,0 +1,595 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Register+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module deals with registering and unregistering packages. There are a+-- couple ways it can do this, one is to do it directly. Another is to generate+-- a script that can be run later to do it. The idea here being that the user+-- is shielded from the details of what command to use for package registration+-- for a particular compiler. In practice this aspect was not especially+-- popular so we also provide a way to simply generate the package registration+-- file which then must be manually passed to @ghc-pkg@. It is possible to+-- generate registration information for where the package is to be installed,+-- or alternatively to register the package in place in the build tree. The+-- latter is occasionally handy, and will become more important when we try to+-- build multi-package systems.+--+-- This module does not delegate anything to the per-compiler modules but just+-- mixes it all in this module, which is rather unsatisfactory. The script+-- generation and the unregister feature are not well used or tested.++module Distribution.Simple.Register (+ register,+ unregister,++ internalPackageDBPath,++ initPackageDB,+ doesPackageDBExist,+ createPackageDB,+ deletePackageDB,++ abiHash,+ invokeHcPkg,+ registerPackage,+ HcPkg.RegisterOptions(..),+ HcPkg.defaultRegisterOptions,+ generateRegistrationInfo,+ inplaceInstalledPackageInfo,+ absoluteInstalledPackageInfo,+ generalInstalledPackageInfo,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.TargetInfo+import Distribution.Types.LocalBuildInfo+import Distribution.Types.ComponentLocalBuildInfo++import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.BuildPaths+import Distribution.Simple.BuildTarget++import qualified Distribution.Simple.GHC as GHC+import qualified Distribution.Simple.GHCJS as GHCJS+import qualified Distribution.Simple.UHC as UHC+import qualified Distribution.Simple.HaskellSuite as HaskellSuite+import qualified Distribution.Simple.PackageIndex as Index++import Distribution.Backpack.DescribeUnitId+import Distribution.Simple.Compiler+import Distribution.Simple.Program+import Distribution.Simple.Program.Script+import qualified Distribution.Simple.Program.HcPkg as HcPkg+import Distribution.Simple.Setup+import Distribution.PackageDescription+import Distribution.Package+import Distribution.License (licenseToSPDX, licenseFromSPDX)+import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.InstalledPackageInfo (InstalledPackageInfo)+import Distribution.Simple.Utils+import Distribution.Utils.MapAccum+import Distribution.System+import Distribution.Pretty+import Distribution.Verbosity as Verbosity+import Distribution.Version+import Distribution.Compat.Graph (IsNode(nodeKey))++import System.FilePath ((</>), (<.>), isAbsolute)+import System.Directory++import qualified Data.ByteString.Lazy.Char8 as BS.Char8++-- -----------------------------------------------------------------------------+-- Registration++register :: PackageDescription -> LocalBuildInfo+ -> RegisterFlags -- ^Install in the user's database?; verbose+ -> IO ()+register pkg_descr lbi0 flags =+ -- Duncan originally asked for us to not register/install files+ -- when there was no public library. But with per-component+ -- configure, we legitimately need to install internal libraries+ -- so that we can get them. So just unconditionally install.+ doRegister+ where+ doRegister = do+ targets <- readTargetInfos verbosity pkg_descr lbi0 (regArgs flags)++ -- It's important to register in build order, because ghc-pkg+ -- will complain if a dependency is not registered.+ let componentsToRegister+ = neededTargetsInBuildOrder' pkg_descr lbi0 (map nodeKey targets)++ (_, ipi_mbs) <-+ mapAccumM `flip` installedPkgs lbi0 `flip` componentsToRegister $ \index tgt ->+ case targetComponent tgt of+ CLib lib -> do+ let clbi = targetCLBI tgt+ lbi = lbi0 { installedPkgs = index }+ ipi <- generateOne pkg_descr lib lbi clbi flags+ return (Index.insert ipi index, Just ipi)+ _ -> return (index, Nothing)++ registerAll pkg_descr lbi0 flags (catMaybes ipi_mbs)+ where+ verbosity = fromFlag (regVerbosity flags)++generateOne :: PackageDescription -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo+ -> RegisterFlags+ -> IO InstalledPackageInfo+generateOne pkg lib lbi clbi regFlags+ = do+ absPackageDBs <- absolutePackageDBPaths packageDbs+ installedPkgInfo <- generateRegistrationInfo+ verbosity pkg lib lbi clbi inplace reloc distPref+ (registrationPackageDB absPackageDBs)+ info verbosity (IPI.showInstalledPackageInfo installedPkgInfo)+ return installedPkgInfo+ where+ inplace = fromFlag (regInPlace regFlags)+ reloc = relocatable lbi+ -- FIXME: there's really no guarantee this will work.+ -- registering into a totally different db stack can+ -- fail if dependencies cannot be satisfied.+ packageDbs = nub $ withPackageDB lbi+ ++ maybeToList (flagToMaybe (regPackageDB regFlags))+ distPref = fromFlag (regDistPref regFlags)+ verbosity = fromFlag (regVerbosity regFlags)++registerAll :: PackageDescription -> LocalBuildInfo -> RegisterFlags+ -> [InstalledPackageInfo]+ -> IO ()+registerAll pkg lbi regFlags ipis+ = do+ when (fromFlag (regPrintId regFlags)) $ do+ for_ ipis $ \installedPkgInfo ->+ -- Only print the public library's IPI+ when (packageId installedPkgInfo == packageId pkg+ && IPI.sourceLibName installedPkgInfo == LMainLibName) $+ putStrLn (prettyShow (IPI.installedUnitId installedPkgInfo))++ -- Three different modes:+ case () of+ _ | modeGenerateRegFile -> writeRegistrationFileOrDirectory+ | modeGenerateRegScript -> writeRegisterScript+ | otherwise -> do+ for_ ipis $ \ipi -> do+ setupMessage' verbosity "Registering" (packageId pkg)+ (CLibName (IPI.sourceLibName ipi))+ (Just (IPI.instantiatedWith ipi))+ registerPackage verbosity (compiler lbi) (withPrograms lbi)+ packageDbs ipi HcPkg.defaultRegisterOptions++ where+ modeGenerateRegFile = isJust (flagToMaybe (regGenPkgConf regFlags))+ regFile = fromMaybe (prettyShow (packageId pkg) <.> "conf")+ (fromFlag (regGenPkgConf regFlags))++ modeGenerateRegScript = fromFlag (regGenScript regFlags)++ -- FIXME: there's really no guarantee this will work.+ -- registering into a totally different db stack can+ -- fail if dependencies cannot be satisfied.+ packageDbs = nub $ withPackageDB lbi+ ++ maybeToList (flagToMaybe (regPackageDB regFlags))+ verbosity = fromFlag (regVerbosity regFlags)++ writeRegistrationFileOrDirectory = do+ -- Handles overwriting both directory and file+ deletePackageDB regFile+ case ipis of+ [installedPkgInfo] -> do+ info verbosity ("Creating package registration file: " ++ regFile)+ writeUTF8File regFile (IPI.showInstalledPackageInfo installedPkgInfo)+ _ -> do+ info verbosity ("Creating package registration directory: " ++ regFile)+ createDirectory regFile+ let num_ipis = length ipis+ lpad m xs = replicate (m - length ys) '0' ++ ys+ where ys = take m xs+ number i = lpad (length (show num_ipis)) (show i)+ for_ (zip ([1..] :: [Int]) ipis) $ \(i, installedPkgInfo) ->+ writeUTF8File (regFile </> (number i ++ "-" ++ prettyShow (IPI.installedUnitId installedPkgInfo)))+ (IPI.showInstalledPackageInfo installedPkgInfo)++ writeRegisterScript =+ case compilerFlavor (compiler lbi) of+ UHC -> notice verbosity "Registration scripts not needed for uhc"+ _ -> withHcPkg verbosity+ "Registration scripts are not implemented for this compiler"+ (compiler lbi) (withPrograms lbi)+ (writeHcPkgRegisterScript verbosity ipis packageDbs)+++generateRegistrationInfo :: Verbosity+ -> PackageDescription+ -> Library+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> Bool+ -> Bool+ -> FilePath+ -> PackageDB+ -> IO InstalledPackageInfo+generateRegistrationInfo verbosity pkg lib lbi clbi inplace reloc distPref packageDb = do+ --TODO: eliminate pwd!+ pwd <- getCurrentDirectory++ installedPkgInfo <-+ if inplace+ -- NB: With an inplace installation, the user may run './Setup+ -- build' to update the library files, without reregistering.+ -- In this case, it is critical that the ABI hash not flip.+ then return (inplaceInstalledPackageInfo pwd distPref+ pkg (mkAbiHash "inplace") lib lbi clbi)+ else do+ abi_hash <- abiHash verbosity pkg distPref lbi lib clbi+ if reloc+ then relocRegistrationInfo verbosity+ pkg lib lbi clbi abi_hash packageDb+ else return (absoluteInstalledPackageInfo+ pkg abi_hash lib lbi clbi)+++ return installedPkgInfo++-- | Compute the 'AbiHash' of a library that we built inplace.+abiHash :: Verbosity+ -> PackageDescription+ -> FilePath+ -> LocalBuildInfo+ -> Library+ -> ComponentLocalBuildInfo+ -> IO AbiHash+abiHash verbosity pkg distPref lbi lib clbi =+ case compilerFlavor comp of+ GHC -> do+ fmap mkAbiHash $ GHC.libAbiHash verbosity pkg lbi' lib clbi+ GHCJS -> do+ fmap mkAbiHash $ GHCJS.libAbiHash verbosity pkg lbi' lib clbi+ _ -> return (mkAbiHash "")+ where+ comp = compiler lbi+ lbi' = lbi {+ withPackageDB = withPackageDB lbi+ ++ [SpecificPackageDB (internalPackageDBPath lbi distPref)]+ }++relocRegistrationInfo :: Verbosity+ -> PackageDescription+ -> Library+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> AbiHash+ -> PackageDB+ -> IO InstalledPackageInfo+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 abi_hash lib lbi clbi fs)+ _ -> die' verbosity+ "Distribution.Simple.Register.relocRegistrationInfo: \+ \not implemented for this compiler"++initPackageDB :: Verbosity -> Compiler -> ProgramDb -> FilePath -> IO ()+initPackageDB verbosity comp progdb dbPath =+ createPackageDB verbosity comp progdb False dbPath++-- | Create an empty package DB at the specified location.+createPackageDB :: Verbosity -> Compiler -> ProgramDb -> 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+ UHC -> return ()+ HaskellSuite _ -> HaskellSuite.initPackageDB verbosity progdb dbPath+ _ -> die' verbosity $+ "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 -> ProgramDb -> PackageDBStack+ -> [String] -> IO ()+invokeHcPkg verbosity comp progdb dbStack extraArgs =+ withHcPkg verbosity "invokeHcPkg" comp progdb+ (\hpi -> HcPkg.invoke hpi verbosity dbStack extraArgs)++withHcPkg :: Verbosity -> String -> Compiler -> ProgramDb+ -> (HcPkg.HcPkgInfo -> IO a) -> IO a+withHcPkg verbosity name comp progdb f =+ case compilerFlavor comp of+ GHC -> f (GHC.hcPkgInfo progdb)+ GHCJS -> f (GHCJS.hcPkgInfo progdb)+ _ -> die' verbosity ("Distribution.Simple.Register." ++ name ++ ":\+ \not implemented for this compiler")++registerPackage :: Verbosity+ -> Compiler+ -> ProgramDb+ -> PackageDBStack+ -> InstalledPackageInfo+ -> HcPkg.RegisterOptions+ -> IO ()+registerPackage verbosity comp progdb packageDbs installedPkgInfo registerOptions =+ case compilerFlavor comp of+ GHC -> GHC.registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions+ GHCJS -> GHCJS.registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions+ HaskellSuite {} ->+ HaskellSuite.registerPackage verbosity progdb packageDbs installedPkgInfo+ _ | HcPkg.registerMultiInstance registerOptions+ -> die' verbosity "Registering multiple package instances is not yet supported for this compiler"+ UHC -> UHC.registerPackage verbosity comp progdb packageDbs installedPkgInfo+ _ -> die' verbosity "Registering is not implemented for this compiler"++writeHcPkgRegisterScript :: Verbosity+ -> [InstalledPackageInfo]+ -> PackageDBStack+ -> HcPkg.HcPkgInfo+ -> IO ()+writeHcPkgRegisterScript verbosity ipis packageDbs hpi = do+ let genScript installedPkgInfo =+ let invocation = HcPkg.registerInvocation hpi Verbosity.normal+ packageDbs installedPkgInfo+ HcPkg.defaultRegisterOptions+ in invocationAsSystemScript buildOS invocation+ scripts = map genScript ipis+ -- TODO: Do something more robust here+ regScript = unlines scripts++ info verbosity ("Creating package registration script: " ++ regScriptFileName)+ writeUTF8File regScriptFileName regScript+ setFileExecutable regScriptFileName++regScriptFileName :: FilePath+regScriptFileName = case buildOS of+ Windows -> "register.bat"+ _ -> "register.sh"+++-- -----------------------------------------------------------------------------+-- Making the InstalledPackageInfo++-- | Construct 'InstalledPackageInfo' for a library in a package, given a set+-- of installation directories.+--+generalInstalledPackageInfo+ :: ([FilePath] -> [FilePath]) -- ^ Translate relative include dir paths to+ -- absolute paths.+ -> PackageDescription+ -> AbiHash+ -> Library+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> InstallDirs FilePath+ -> InstalledPackageInfo+generalInstalledPackageInfo adjustRelIncDirs pkg abi_hash lib lbi clbi installDirs =+ IPI.InstalledPackageInfo {+ IPI.sourcePackageId = packageId pkg,+ IPI.installedUnitId = componentUnitId clbi,+ IPI.installedComponentId_ = componentComponentId clbi,+ IPI.instantiatedWith = componentInstantiatedWith clbi,+ IPI.sourceLibName = libName lib,+ IPI.compatPackageKey = componentCompatPackageKey clbi,+ -- If GHC >= 8.4 we register with SDPX, otherwise with legacy license+ IPI.license =+ if ghc84+ then Left $ either id licenseToSPDX $ licenseRaw pkg+ else Right $ either licenseFromSPDX id $ licenseRaw pkg,+ IPI.copyright = copyright pkg,+ IPI.maintainer = maintainer pkg,+ IPI.author = author pkg,+ IPI.stability = stability pkg,+ IPI.homepage = homepage pkg,+ IPI.pkgUrl = pkgUrl pkg,+ IPI.synopsis = synopsis pkg,+ IPI.description = description pkg,+ IPI.category = category pkg,+ IPI.abiHash = abi_hash,+ IPI.indefinite = componentIsIndefinite clbi,+ IPI.exposed = libExposed lib,+ IPI.exposedModules = componentExposedModules clbi+ -- add virtual modules into the list of exposed modules for the+ -- package database as well.+ ++ map (\name -> IPI.ExposedModule name Nothing) (virtualModules bi),+ IPI.hiddenModules = otherModules bi,+ IPI.trusted = IPI.trusted IPI.emptyInstalledPackageInfo,+ IPI.importDirs = [ libdir installDirs | hasModules ],+ IPI.libraryDirs = libdirs,+ IPI.libraryDynDirs = dynlibdirs,+ IPI.dataDir = datadir installDirs,+ IPI.hsLibraries = (if hasLibrary+ then [getHSLibraryName (componentUnitId clbi)]+ else []) ++ extraBundledLibs bi,+ IPI.extraLibraries = extraLibs bi,+ IPI.extraGHCiLibraries = extraGHCiLibs bi,+ IPI.includeDirs = absinc ++ adjustRelIncDirs relinc,+ IPI.includes = includes bi,+ IPI.depends = depends,+ IPI.abiDepends = [], -- due to #5465+ IPI.ccOptions = [], -- Note. NOT ccOptions bi!+ -- We don't want cc-options to be propagated+ -- to C compilations in other packages.+ IPI.cxxOptions = [], -- Also. NOT cxxOptions bi!+ IPI.ldOptions = ldOptions bi,+ IPI.frameworks = frameworks bi,+ IPI.frameworkDirs = extraFrameworkDirs bi,+ IPI.haddockInterfaces = [haddockdir installDirs </> haddockName pkg],+ IPI.haddockHTMLs = [htmldir installDirs],+ IPI.pkgRoot = Nothing,+ IPI.libVisibility = libVisibility lib+ }+ where+ ghc84 = case compilerId $ compiler lbi of+ CompilerId GHC v -> v >= mkVersion [8, 4]+ _ -> False++ bi = libBuildInfo lib+ --TODO: unclear what the root cause of the+ -- duplication is, but we nub it here for now:+ depends = ordNub $ map fst (componentPackageDeps clbi)+ (absinc, relinc) = partition isAbsolute (includeDirs bi)+ hasModules = not $ null (allLibModules lib clbi)+ comp = compiler lbi+ hasLibrary = (hasModules || not (null (cSources bi))+ || not (null (asmSources bi))+ || not (null (cmmSources bi))+ || not (null (cxxSources bi))+ || (not (null (jsSources bi)) &&+ compilerFlavor comp == GHCJS))+ && not (componentIsIndefinite clbi)+ (libdirs, dynlibdirs)+ | not hasLibrary+ = (extraLibDirs bi, [])+ -- the dynamic-library-dirs defaults to the library-dirs if not specified,+ -- so this works whether the dynamic-library-dirs field is supported or not++ | libraryDynDirSupported comp+ = (libdir installDirs : extraLibDirs bi,+ dynlibdir installDirs : extraLibDirs bi)++ | otherwise+ = (libdir installDirs : dynlibdir installDirs : extraLibDirs bi, [])+ -- the compiler doesn't understand the dynamic-library-dirs field so we+ -- add the dyn directory to the "normal" list in the library-dirs field++-- | Construct 'InstalledPackageInfo' for a library that is in place in the+-- build tree.+--+-- This function knows about the layout of in place packages.+--+inplaceInstalledPackageInfo :: FilePath -- ^ top of the build tree+ -> FilePath -- ^ location of the dist tree+ -> PackageDescription+ -> AbiHash+ -> Library+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> InstalledPackageInfo+inplaceInstalledPackageInfo inplaceDir distPref pkg abi_hash lib lbi clbi =+ generalInstalledPackageInfo adjustRelativeIncludeDirs+ pkg abi_hash lib lbi clbi installDirs+ where+ adjustRelativeIncludeDirs = concatMap $ \d ->+ [ inplaceDir </> d -- local include-dir+ , inplaceDir </> libTargetDir </> d -- autogen include-dir+ ]+ libTargetDir = componentBuildDir lbi clbi+ installDirs =+ (absoluteComponentInstallDirs pkg lbi (componentUnitId clbi) NoCopyDest) {+ libdir = inplaceDir </> libTargetDir,+ dynlibdir = inplaceDir </> libTargetDir,+ datadir = inplaceDir </> dataDir pkg,+ docdir = inplaceDocdir,+ htmldir = inplaceHtmldir,+ haddockdir = inplaceHtmldir+ }+ inplaceDocdir = inplaceDir </> distPref </> "doc"+ inplaceHtmldir = inplaceDocdir </> "html" </> prettyShow (packageName pkg)+++-- | Construct 'InstalledPackageInfo' for the final install location of a+-- library package.+--+-- This function knows about the layout of installed packages.+--+absoluteInstalledPackageInfo :: PackageDescription+ -> AbiHash+ -> Library+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> InstalledPackageInfo+absoluteInstalledPackageInfo pkg abi_hash lib lbi clbi =+ generalInstalledPackageInfo adjustReativeIncludeDirs+ 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.+ adjustReativeIncludeDirs _+ | null (installIncludes bi) = []+ | otherwise = [includedir installDirs]+ bi = libBuildInfo lib+ installDirs = absoluteComponentInstallDirs pkg lbi (componentUnitId clbi) NoCopyDest+++relocatableInstalledPackageInfo :: PackageDescription+ -> AbiHash+ -> Library+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> FilePath+ -> InstalledPackageInfo+relocatableInstalledPackageInfo pkg abi_hash lib lbi clbi pkgroot =+ generalInstalledPackageInfo adjustReativeIncludeDirs+ 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.+ adjustReativeIncludeDirs _+ | null (installIncludes bi) = []+ | otherwise = [includedir installDirs]+ bi = libBuildInfo lib++ installDirs = fmap (("${pkgroot}" </>) . shortRelativePath pkgroot)+ $ absoluteComponentInstallDirs pkg lbi (componentUnitId clbi) NoCopyDest++-- -----------------------------------------------------------------------------+-- Unregistration++unregister :: PackageDescription -> LocalBuildInfo -> RegisterFlags -> IO ()+unregister pkg lbi regFlags = do+ let pkgid = packageId pkg+ genScript = fromFlag (regGenScript regFlags)+ verbosity = fromFlag (regVerbosity regFlags)+ packageDb = fromFlagOrDefault (registrationPackageDB (withPackageDB lbi))+ (regPackageDB regFlags)+ unreg hpi =+ let invocation = HcPkg.unregisterInvocation+ hpi Verbosity.normal packageDb pkgid+ in if genScript+ then writeFileAtomic unregScriptFileName+ (BS.Char8.pack $ invocationAsSystemScript buildOS invocation)+ else runProgramInvocation verbosity invocation+ setupMessage verbosity "Unregistering" pkgid+ withHcPkg verbosity "unregistering is only implemented for GHC and GHCJS"+ (compiler lbi) (withPrograms lbi) unreg++unregScriptFileName :: FilePath+unregScriptFileName = case buildOS of+ Windows -> "unregister.bat"+ _ -> "unregister.sh"++internalPackageDBPath :: LocalBuildInfo -> FilePath -> FilePath+internalPackageDBPath lbi distPref =+ case compilerFlavor (compiler lbi) of+ UHC -> UHC.inplacePackageDbPath lbi+ _ -> distPref </> "package.conf.inplace"
+ src/Distribution/Simple/Setup.hs view
@@ -0,0 +1,2348 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Setup+-- Copyright : Isaac Jones 2003-2004+-- Duncan Coutts 2007+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is a big module, but not very complicated. The code is very regular+-- and repetitive. It defines the command line interface for all the Cabal+-- commands. For each command (like @configure@, @build@ etc) it defines a type+-- that holds all the flags, the default set of flags and a 'CommandUI' that+-- maps command line flags to and from the corresponding flags type.+--+-- All the flags types are instances of 'Monoid', see+-- <http://www.haskell.org/pipermail/cabal-devel/2007-December/001509.html>+-- for an explanation.+--+-- The types defined here get used in the front end and especially in+-- @cabal-install@ which has to do quite a bit of manipulating sets of command+-- line flags.+--+-- This is actually relatively nice, it works quite well. The main change it+-- needs is to unify it with the code for managing sets of fields that can be+-- read and written from files. This would allow us to save configure flags in+-- config files.++module Distribution.Simple.Setup (++ GlobalFlags(..), emptyGlobalFlags, defaultGlobalFlags, globalCommand,+ ConfigFlags(..), emptyConfigFlags, defaultConfigFlags, configureCommand,+ configPrograms,+ configAbsolutePaths, readPackageDbList, showPackageDbList,+ CopyFlags(..), emptyCopyFlags, defaultCopyFlags, copyCommand,+ InstallFlags(..), emptyInstallFlags, defaultInstallFlags, installCommand,+ HaddockTarget(..),+ HaddockFlags(..), emptyHaddockFlags, defaultHaddockFlags, haddockCommand,+ HscolourFlags(..), emptyHscolourFlags, defaultHscolourFlags, hscolourCommand,+ BuildFlags(..), emptyBuildFlags, defaultBuildFlags, buildCommand,+ ShowBuildInfoFlags(..), defaultShowBuildFlags, showBuildInfoCommand,+ ReplFlags(..), defaultReplFlags, replCommand,+ CleanFlags(..), emptyCleanFlags, defaultCleanFlags, cleanCommand,+ RegisterFlags(..), emptyRegisterFlags, defaultRegisterFlags, registerCommand,+ unregisterCommand,+ SDistFlags(..), emptySDistFlags, defaultSDistFlags, sdistCommand,+ TestFlags(..), emptyTestFlags, defaultTestFlags, testCommand,+ TestShowDetails(..),+ BenchmarkFlags(..), emptyBenchmarkFlags,+ defaultBenchmarkFlags, benchmarkCommand,+ CopyDest(..),+ configureArgs, configureOptions, configureCCompiler, configureLinker,+ buildOptions, haddockOptions, installDirsOptions,+ testOptions', benchmarkOptions',+ programDbOptions, programDbPaths',+ programFlagsDescription,+ replOptions,+ splitArgs,++ defaultDistPref, optionDistPref,++ Flag(..),+ toFlag,+ fromFlag,+ fromFlagOrDefault,+ flagToMaybe,+ flagToList,+ maybeToFlag,+ BooleanFlag(..),+ boolOpt, boolOpt', trueArg, falseArg,+ optionVerbosity, optionNumJobs) where++import Prelude ()+import Distribution.Compat.Prelude hiding (get)++import Distribution.Compiler+import Distribution.ReadE+import Distribution.Parsec+import Distribution.Pretty+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp+import Distribution.ModuleName+import Distribution.PackageDescription+import Distribution.Simple.Command hiding (boolOpt, boolOpt')+import qualified Distribution.Simple.Command as Command+import Distribution.Simple.Compiler+import Distribution.Simple.Flag+import Distribution.Simple.Utils+import Distribution.Simple.Program+import Distribution.Simple.InstallDirs+import Distribution.Verbosity+import Distribution.Utils.NubList+import Distribution.Types.ComponentId+import Distribution.Types.GivenComponent+import Distribution.Types.Module+import Distribution.Types.PackageVersionConstraint++import Distribution.Compat.Stack+import Distribution.Compat.Semigroup (Last' (..), Option' (..))++-- FIXME Not sure where this should live+defaultDistPref :: FilePath+defaultDistPref = "dist"++-- ------------------------------------------------------------+-- * Global flags+-- ------------------------------------------------------------++-- In fact since individual flags types are monoids and these are just sets of+-- flags then they are also monoids pointwise. This turns out to be really+-- useful. The mempty is the set of empty flags and mappend allows us to+-- override specific flags. For example we can start with default flags and+-- override with the ones we get from a file or the command line, or both.++-- | Flags that apply at the top level, not to any sub-command.+data GlobalFlags = GlobalFlags {+ globalVersion :: Flag Bool,+ globalNumericVersion :: Flag Bool+ } deriving (Generic, Typeable)++defaultGlobalFlags :: GlobalFlags+defaultGlobalFlags = GlobalFlags {+ globalVersion = Flag False,+ globalNumericVersion = Flag False+ }++globalCommand :: [Command action] -> CommandUI GlobalFlags+globalCommand commands = CommandUI+ { commandName = ""+ , commandSynopsis = ""+ , commandUsage = \pname ->+ "This Setup program uses the Haskell Cabal Infrastructure.\n"+ ++ "See http://www.haskell.org/cabal/ for more information.\n"+ ++ "\n"+ ++ "Usage: " ++ pname ++ " [GLOBAL FLAGS] [COMMAND [FLAGS]]\n"+ , commandDescription = Just $ \pname ->+ let+ commands' = commands ++ [commandAddAction helpCommandUI undefined]+ cmdDescs = getNormalCommandDescriptions commands'+ maxlen = maximum $ [length name | (name, _) <- cmdDescs]+ align str = str ++ replicate (maxlen - length str) ' '+ in+ "Commands:\n"+ ++ unlines [ " " ++ align name ++ " " ++ descr+ | (name, descr) <- cmdDescs ]+ ++ "\n"+ ++ "For more information about a command use\n"+ ++ " " ++ pname ++ " COMMAND --help\n\n"+ ++ "Typical steps for installing Cabal packages:\n"+ ++ concat [ " " ++ pname ++ " " ++ x ++ "\n"+ | x <- ["configure", "build", "install"]]+ , commandNotes = Nothing+ , commandDefaultFlags = defaultGlobalFlags+ , commandOptions = \_ ->+ [option ['V'] ["version"]+ "Print version information"+ globalVersion (\v flags -> flags { globalVersion = v })+ trueArg+ ,option [] ["numeric-version"]+ "Print just the version number"+ globalNumericVersion (\v flags -> flags { globalNumericVersion = v })+ trueArg+ ]+ }++emptyGlobalFlags :: GlobalFlags+emptyGlobalFlags = mempty++instance Monoid GlobalFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup GlobalFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Config flags+-- ------------------------------------------------------------++-- | Flags to @configure@ command.+--+-- IMPORTANT: every time a new flag is added, 'D.C.Setup.filterConfigureFlags'+-- should be updated.+-- IMPORTANT: every time a new flag is added, it should be added to the Eq instance+data ConfigFlags = ConfigFlags {+ -- This is the same hack as in 'buildArgs' and 'copyArgs'.+ -- TODO: Stop using this eventually when 'UserHooks' gets changed+ configArgs :: [String],++ --FIXME: the configPrograms is only here to pass info through to configure+ -- because the type of configure is constrained by the UserHooks.+ -- when we change UserHooks next we should pass the initial+ -- ProgramDb directly and not via ConfigFlags+ configPrograms_ :: Option' (Last' ProgramDb), -- ^All programs that+ -- @cabal@ may run++ configProgramPaths :: [(String, FilePath)], -- ^user specified programs paths+ configProgramArgs :: [(String, [String])], -- ^user specified programs args+ configProgramPathExtra :: NubList FilePath, -- ^Extend the $PATH+ configHcFlavor :: Flag CompilerFlavor, -- ^The \"flavor\" of the+ -- compiler, e.g. GHC.+ configHcPath :: Flag FilePath, -- ^given compiler location+ configHcPkg :: Flag FilePath, -- ^given hc-pkg location+ configVanillaLib :: Flag Bool, -- ^Enable vanilla library+ configProfLib :: Flag Bool, -- ^Enable profiling in the library+ configSharedLib :: Flag Bool, -- ^Build shared library+ configStaticLib :: Flag Bool, -- ^Build static library+ configDynExe :: Flag Bool, -- ^Enable dynamic linking of the+ -- executables.+ configFullyStaticExe :: Flag Bool, -- ^Enable fully static linking of the+ -- 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.+ configProgSuffix :: Flag PathTemplate, -- ^Installed executable suffix.+ configInstallDirs :: InstallDirs (Flag PathTemplate), -- ^Installation+ -- 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+ configCID :: Flag ComponentId, -- ^ explicit CID to be used+ configDeterministic :: Flag Bool, -- ^ be as deterministic as possible+ -- (e.g., invariant over GHC, database,+ -- etc). Used by the test suite++ configDistPref :: Flag FilePath, -- ^"dist" prefix+ configCabalFilePath :: Flag FilePath, -- ^ Cabal file to use+ configVerbosity :: Flag Verbosity, -- ^verbosity level+ configUserInstall :: Flag Bool, -- ^The --user\/--global flag+ configPackageDBs :: [Maybe PackageDB], -- ^Which package DBs to use+ configGHCiLib :: Flag Bool, -- ^Enable compiling library for GHCi+ configSplitSections :: Flag Bool, -- ^Enable -split-sections with GHC+ configSplitObjs :: Flag Bool, -- ^Enable -split-objs with GHC+ configStripExes :: Flag Bool, -- ^Enable executable stripping+ configStripLibs :: Flag Bool, -- ^Enable library stripping+ configConstraints :: [PackageVersionConstraint], -- ^Additional constraints for+ -- dependencies.+ configDependencies :: [GivenComponent],+ -- ^The packages depended on.+ configInstantiateWith :: [(ModuleName, Module)],+ -- ^ The requested Backpack instantiation. If empty, either this+ -- package does not use Backpack, or we just want to typecheck+ -- the indefinite package.+ configConfigurationsFlags :: FlagAssignment,+ configTests :: Flag Bool, -- ^Enable test suite compilation+ configBenchmarks :: Flag Bool, -- ^Enable benchmark compilation+ configCoverage :: Flag Bool, -- ^Enable program coverage+ configLibCoverage :: Flag Bool, -- ^Enable program coverage (deprecated)+ configExactConfiguration :: Flag Bool,+ -- ^All direct dependencies and flags are provided on the command line by+ -- the user via the '--dependency' and '--flags' options.+ 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.+ configUseResponseFiles :: Flag Bool,+ -- ^ Whether to use response files at all. They're used for such tools+ -- as haddock, or ld.+ configAllowDependingOnPrivateLibs :: Flag Bool+ -- ^ Allow depending on private sublibraries. This is used by external+ -- tools (like cabal-install) so they can add multiple-public-libraries+ -- compatibility to older ghcs by checking visibility externally.+ }+ deriving (Generic, Read, Show, Typeable)++instance Binary ConfigFlags+instance Structured ConfigFlags++-- | More convenient version of 'configPrograms'. Results in an+-- 'error' if internal invariant is violated.+configPrograms :: WithCallStack (ConfigFlags -> ProgramDb)+configPrograms = fromMaybe (error "FIXME: remove configPrograms") . fmap getLast'+ . getOption' . configPrograms_++instance Eq ConfigFlags where+ (==) a b =+ -- configPrograms skipped: not user specified, has no Eq instance+ equal configProgramPaths+ && equal configProgramArgs+ && equal configProgramPathExtra+ && equal configHcFlavor+ && equal configHcPath+ && equal configHcPkg+ && equal configVanillaLib+ && equal configProfLib+ && equal configSharedLib+ && equal configStaticLib+ && equal configDynExe+ && equal configFullyStaticExe+ && equal configProfExe+ && equal configProf+ && equal configProfDetail+ && equal configProfLibDetail+ && equal configConfigureArgs+ && equal configOptimization+ && equal configProgPrefix+ && equal configProgSuffix+ && equal configInstallDirs+ && equal configScratchDir+ && equal configExtraLibDirs+ && equal configExtraIncludeDirs+ && equal configIPID+ && equal configDeterministic+ && equal configDistPref+ && equal configVerbosity+ && equal configUserInstall+ && equal configPackageDBs+ && equal configGHCiLib+ && equal configSplitSections+ && equal configSplitObjs+ && equal configStripExes+ && equal configStripLibs+ && equal configConstraints+ && equal configDependencies+ && equal configConfigurationsFlags+ && equal configTests+ && equal configBenchmarks+ && equal configCoverage+ && equal configLibCoverage+ && equal configExactConfiguration+ && equal configFlagError+ && equal configRelocatable+ && equal configDebugInfo+ && equal configUseResponseFiles+ where+ equal f = on (==) f a b++configAbsolutePaths :: ConfigFlags -> IO ConfigFlags+configAbsolutePaths f =+ (\v -> f { configPackageDBs = v })+ `liftM` traverse (maybe (return Nothing) (liftM Just . absolutePackageDBPath))+ (configPackageDBs f)++defaultConfigFlags :: ProgramDb -> ConfigFlags+defaultConfigFlags progDb = emptyConfigFlags {+ configArgs = [],+ configPrograms_ = Option' (Just (Last' progDb)),+ configHcFlavor = maybe NoFlag Flag defaultCompilerFlavor,+ configVanillaLib = Flag True,+ configProfLib = NoFlag,+ configSharedLib = NoFlag,+ configStaticLib = NoFlag,+ configDynExe = Flag False,+ configFullyStaticExe = Flag False,+ configProfExe = NoFlag,+ configProf = NoFlag,+ configProfDetail = NoFlag,+ configProfLibDetail= NoFlag,+ configOptimization = Flag NormalOptimisation,+ configProgPrefix = Flag (toPathTemplate ""),+ configProgSuffix = Flag (toPathTemplate ""),+ configDistPref = NoFlag,+ configCabalFilePath = NoFlag,+ configVerbosity = Flag normal,+ configUserInstall = Flag False, --TODO: reverse this+#if defined(mingw32_HOST_OS)+ -- See #1589.+ configGHCiLib = Flag True,+#else+ configGHCiLib = NoFlag,+#endif+ configSplitSections = Flag False,+ configSplitObjs = Flag False, -- takes longer, so turn off by default+ configStripExes = NoFlag,+ configStripLibs = NoFlag,+ configTests = Flag False,+ configBenchmarks = Flag False,+ configCoverage = Flag False,+ configLibCoverage = NoFlag,+ configExactConfiguration = Flag False,+ configFlagError = NoFlag,+ configRelocatable = Flag False,+ configDebugInfo = Flag NoDebugInfo,+ configUseResponseFiles = NoFlag+ }++configureCommand :: ProgramDb -> CommandUI ConfigFlags+configureCommand progDb = CommandUI+ { commandName = "configure"+ , commandSynopsis = "Prepare to build the package."+ , commandDescription = Just $ \_ -> wrapText $+ "Configure how the package is built by setting "+ ++ "package (and other) flags.\n"+ ++ "\n"+ ++ "The configuration affects several other commands, "+ ++ "including build, test, bench, run, repl.\n"+ , commandNotes = Just $ \_pname -> programFlagsDescription progDb+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " configure [FLAGS]\n"+ , commandDefaultFlags = defaultConfigFlags progDb+ , commandOptions = \showOrParseArgs ->+ configureOptions showOrParseArgs+ ++ programDbPaths progDb showOrParseArgs+ configProgramPaths (\v fs -> fs { configProgramPaths = v })+ ++ programDbOption progDb showOrParseArgs+ configProgramArgs (\v fs -> fs { configProgramArgs = v })+ ++ programDbOptions progDb showOrParseArgs+ configProgramArgs (\v fs -> fs { configProgramArgs = v })+ }++-- | Inverse to 'dispModSubstEntry'.+parsecModSubstEntry :: ParsecParser (ModuleName, Module)+parsecModSubstEntry = do+ k <- parsec+ _ <- P.char '='+ v <- parsec+ return (k, v)++-- | Pretty-print a single entry of a module substitution.+dispModSubstEntry :: (ModuleName, Module) -> Disp.Doc+dispModSubstEntry (k, v) = pretty k <<>> Disp.char '=' <<>> pretty v++configureOptions :: ShowOrParseArgs -> [OptionField ConfigFlags]+configureOptions showOrParseArgs =+ [optionVerbosity configVerbosity+ (\v flags -> flags { configVerbosity = v })+ ,optionDistPref+ configDistPref (\d flags -> flags { configDistPref = d })+ showOrParseArgs++ ,option [] ["compiler"] "compiler"+ configHcFlavor (\v flags -> flags { configHcFlavor = v })+ (choiceOpt [ (Flag GHC, ("g", ["ghc"]), "compile with GHC")+ , (Flag GHCJS, ([] , ["ghcjs"]), "compile with GHCJS")+ , (Flag UHC, ([] , ["uhc"]), "compile with UHC")+ -- "haskell-suite" compiler id string will be replaced+ -- by a more specific one during the configure stage+ , (Flag (HaskellSuite "haskell-suite"), ([] , ["haskell-suite"]),+ "compile with a haskell-suite compiler")])++ ,option "" ["cabal-file"]+ "use this Cabal file"+ configCabalFilePath (\v flags -> flags { configCabalFilePath = v })+ (reqArgFlag "PATH")++ ,option "w" ["with-compiler"]+ "give the path to a particular compiler"+ configHcPath (\v flags -> flags { configHcPath = v })+ (reqArgFlag "PATH")++ ,option "" ["with-hc-pkg"]+ "give the path to the package tool"+ configHcPkg (\v flags -> flags { configHcPkg = v })+ (reqArgFlag "PATH")+ ]+ ++ map liftInstallDirs installDirsOptions+ ++ [option "" ["program-prefix"]+ "prefix to be applied to installed executables"+ configProgPrefix+ (\v flags -> flags { configProgPrefix = v })+ (reqPathTemplateArgFlag "PREFIX")++ ,option "" ["program-suffix"]+ "suffix to be applied to installed executables"+ configProgSuffix (\v flags -> flags { configProgSuffix = v } )+ (reqPathTemplateArgFlag "SUFFIX")++ ,option "" ["library-vanilla"]+ "Vanilla libraries"+ configVanillaLib (\v flags -> flags { configVanillaLib = v })+ (boolOpt [] [])++ ,option "p" ["library-profiling"]+ "Library profiling"+ configProfLib (\v flags -> flags { configProfLib = v })+ (boolOpt "p" [])++ ,option "" ["shared"]+ "Shared library"+ configSharedLib (\v flags -> flags { configSharedLib = v })+ (boolOpt [] [])++ ,option "" ["static"]+ "Static library"+ configStaticLib (\v flags -> flags { configStaticLib = v })+ (boolOpt [] [])++ ,option "" ["executable-dynamic"]+ "Executable dynamic linking"+ configDynExe (\v flags -> flags { configDynExe = v })+ (boolOpt [] [])++ ,option "" ["executable-static"]+ "Executable fully static linking"+ configFullyStaticExe (\v flags -> flags { configFullyStaticExe = v })+ (boolOpt [] [])++ ,option "" ["profiling"]+ "Executable and library profiling"+ configProf (\v flags -> flags { configProf = v })+ (boolOpt [] [])++ ,option "" ["executable-profiling"]+ "Executable profiling (DEPRECATED)"+ 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)+ (\f -> case f of+ Flag NoOptimisation -> []+ Flag NormalOptimisation -> [Nothing]+ Flag MaximumOptimisation -> [Just "2"]+ _ -> [])+ "O" ["enable-optimization","enable-optimisation"]+ "Build with optimization (n is 0--2, default is 1)",+ noArg (Flag NoOptimisation) []+ ["disable-optimization","disable-optimisation"]+ "Build without optimization"+ ]++ ,multiOption "debug-info"+ configDebugInfo (\v flags -> flags { configDebugInfo = v })+ [optArg' "n" (Flag . flagToDebugInfoLevel)+ (\f -> case f of+ Flag NoDebugInfo -> []+ Flag MinimalDebugInfo -> [Just "1"]+ Flag NormalDebugInfo -> [Nothing]+ Flag MaximalDebugInfo -> [Just "3"]+ _ -> [])+ "" ["enable-debug-info"]+ "Emit debug info (n is 0--3, default is 0)",+ noArg (Flag NoDebugInfo) []+ ["disable-debug-info"]+ "Don't emit debug info"+ ]++ ,option "" ["library-for-ghci"]+ "compile library for use with GHCi"+ configGHCiLib (\v flags -> flags { configGHCiLib = v })+ (boolOpt [] [])++ ,option "" ["split-sections"]+ "compile library code such that unneeded definitions can be dropped from the final executable (GHC 7.8+)"+ configSplitSections (\v flags -> flags { configSplitSections = v })+ (boolOpt [] [])++ ,option "" ["split-objs"]+ "split library into smaller objects to reduce binary sizes (GHC 6.6+)"+ configSplitObjs (\v flags -> flags { configSplitObjs = v })+ (boolOpt [] [])++ ,option "" ["executable-stripping"]+ "strip executables upon installation to reduce binary sizes"+ configStripExes (\v flags -> flags { configStripExes = v })+ (boolOpt [] [])++ ,option "" ["library-stripping"]+ "strip libraries upon installation to reduce binary sizes"+ configStripLibs (\v flags -> flags { configStripLibs = v })+ (boolOpt [] [])++ ,option "" ["configure-option"]+ "Extra option for configure"+ configConfigureArgs (\v flags -> flags { configConfigureArgs = v })+ (reqArg' "OPT" (\x -> [x]) id)++ ,option "" ["user-install"]+ "doing a per-user installation"+ configUserInstall (\v flags -> flags { configUserInstall = v })+ (boolOpt' ([],["user"]) ([], ["global"]))++ ,option "" ["package-db"]+ ( "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)++ ,option "f" ["flags"]+ "Force values for the given flags in Cabal conditionals in the .cabal file. E.g., --flags=\"debug -usebytestrings\" forces the flag \"debug\" to true and \"usebytestrings\" to false."+ configConfigurationsFlags (\v flags -> flags { configConfigurationsFlags = v })+ (reqArg "FLAGS"+ (parsecToReadE (\err -> "Invalid flag assignment: " ++ err) legacyParsecFlagAssignment)+ legacyShowFlagAssignment')++ ,option "" ["extra-include-dirs"]+ "A list of directories to search for header files"+ configExtraIncludeDirs (\v flags -> flags {configExtraIncludeDirs = v})+ (reqArg' "PATH" (\x -> [x]) id)++ ,option "" ["deterministic"]+ "Try to be as deterministic as possible (used by the test suite)"+ configDeterministic (\v flags -> flags {configDeterministic = v})+ (boolOpt [] [])++ ,option "" ["ipid"]+ "Installed package ID to compile this package as"+ configIPID (\v flags -> flags {configIPID = v})+ (reqArgFlag "IPID")++ ,option "" ["cid"]+ "Installed component ID to compile this component as"+ (fmap prettyShow . configCID) (\v flags -> flags {configCID = fmap mkComponentId v})+ (reqArgFlag "CID")++ ,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})+ (reqArg' "PATH" (\x -> toNubList [x]) fromNubList)++ ,option "" ["constraint"]+ "A list of additional constraints on the dependencies."+ configConstraints (\v flags -> flags { configConstraints = v})+ (reqArg "DEPENDENCY"+ (parsecToReadE (const "dependency expected") ((\x -> [x]) `fmap` parsec))+ (map prettyShow))++ ,option "" ["dependency"]+ "A list of exact dependencies. E.g., --dependency=\"void=void-0.5.8-177d5cdf20962d0581fe2e4932a6c309\""+ configDependencies (\v flags -> flags { configDependencies = v})+ (reqArg "NAME[:COMPONENT_NAME]=CID"+ (parsecToReadE (const "dependency expected") ((\x -> [x]) `fmap` parsecGivenComponent))+ (map (\(GivenComponent pn cn cid) ->+ prettyShow pn+ ++ case cn of LMainLibName -> ""+ LSubLibName n -> ":" ++ prettyShow n+ ++ "=" ++ prettyShow cid)))++ ,option "" ["instantiate-with"]+ "A mapping of signature names to concrete module instantiations."+ configInstantiateWith (\v flags -> flags { configInstantiateWith = v })+ (reqArg "NAME=MOD"+ (parsecToReadE ("Cannot parse module substitution: " ++) (fmap (:[]) parsecModSubstEntry))+ (map (Disp.renderStyle defaultStyle . dispModSubstEntry)))++ ,option "" ["tests"]+ "dependency checking and compilation for test suites listed in the package description file."+ configTests (\v flags -> flags { configTests = v })+ (boolOpt [] [])++ ,option "" ["coverage"]+ "build package with Haskell Program Coverage. (GHC only)"+ configCoverage (\v flags -> flags { configCoverage = v })+ (boolOpt [] [])++ ,option "" ["library-coverage"]+ "build package with Haskell Program Coverage. (GHC only) (DEPRECATED)"+ configLibCoverage (\v flags -> flags { configLibCoverage = v })+ (boolOpt [] [])++ ,option "" ["exact-configuration"]+ "All direct dependencies and flags are provided on the command line."+ configExactConfiguration+ (\v flags -> flags { configExactConfiguration = v })+ trueArg++ ,option "" ["benchmarks"]+ "dependency checking and compilation for benchmarks listed in the package description file."+ configBenchmarks (\v flags -> flags { configBenchmarks = v })+ (boolOpt [] [])++ ,option "" ["relocatable"]+ "building a package that is relocatable. (GHC only)"+ configRelocatable (\v flags -> flags { configRelocatable = v})+ (boolOpt [] [])++ ,option "" ["response-files"]+ "enable workaround for old versions of programs like \"ar\" that do not support @file arguments"+ configUseResponseFiles+ (\v flags -> flags { configUseResponseFiles = v })+ (boolOpt' ([], ["disable-response-files"]) ([], []))++ ,option "" ["allow-depending-on-private-libs"]+ ( "Allow depending on private libraries. "+ ++ "If set, the library visibility check MUST be done externally." )+ configAllowDependingOnPrivateLibs+ (\v flags -> flags { configAllowDependingOnPrivateLibs = v })+ trueArg+ ]+ where+ liftInstallDirs =+ liftOption configInstallDirs (\v flags -> flags { configInstallDirs = v })++ reqPathTemplateArgFlag title _sf _lf d get set =+ reqArgFlag title _sf _lf d+ (fmap fromPathTemplate . get) (set . fmap toPathTemplate)++readPackageDbList :: String -> [Maybe PackageDB]+readPackageDbList "clear" = [Nothing]+readPackageDbList "global" = [Just GlobalPackageDB]+readPackageDbList "user" = [Just UserPackageDB]+readPackageDbList other = [Just (SpecificPackageDB other)]++showPackageDbList :: [Maybe PackageDB] -> [String]+showPackageDbList = map showPackageDb+ where+ showPackageDb Nothing = "clear"+ showPackageDb (Just GlobalPackageDB) = "global"+ showPackageDb (Just UserPackageDB) = "user"+ showPackageDb (Just (SpecificPackageDB db)) = db++showProfDetailLevelFlag :: Flag ProfDetailLevel -> [String]+showProfDetailLevelFlag NoFlag = []+showProfDetailLevelFlag (Flag dl) = [showProfDetailLevel dl]++parsecGivenComponent :: ParsecParser GivenComponent+parsecGivenComponent = do+ pn <- parsec+ ln <- P.option LMainLibName $ do+ _ <- P.char ':'+ ucn <- parsec+ return $ if unUnqualComponentName ucn == unPackageName pn+ then LMainLibName+ else LSubLibName ucn+ _ <- P.char '='+ cid <- parsec+ return $ GivenComponent pn ln cid++installDirsOptions :: [OptionField (InstallDirs (Flag PathTemplate))]+installDirsOptions =+ [ option "" ["prefix"]+ "bake this prefix in preparation of installation"+ prefix (\v flags -> flags { prefix = v })+ installDirArg++ , option "" ["bindir"]+ "installation directory for executables"+ bindir (\v flags -> flags { bindir = v })+ installDirArg++ , option "" ["libdir"]+ "installation directory for libraries"+ libdir (\v flags -> flags { libdir = v })+ installDirArg++ , option "" ["libsubdir"]+ "subdirectory of libdir in which libs are installed"+ libsubdir (\v flags -> flags { libsubdir = v })+ installDirArg++ , option "" ["dynlibdir"]+ "installation directory for dynamic libraries"+ dynlibdir (\v flags -> flags { dynlibdir = v })+ installDirArg++ , option "" ["libexecdir"]+ "installation directory for program executables"+ libexecdir (\v flags -> flags { libexecdir = v })+ installDirArg++ , option "" ["libexecsubdir"]+ "subdirectory of libexecdir in which private executables are installed"+ libexecsubdir (\v flags -> flags { libexecsubdir = v })+ installDirArg++ , option "" ["datadir"]+ "installation directory for read-only data"+ datadir (\v flags -> flags { datadir = v })+ installDirArg++ , option "" ["datasubdir"]+ "subdirectory of datadir in which data files are installed"+ datasubdir (\v flags -> flags { datasubdir = v })+ installDirArg++ , option "" ["docdir"]+ "installation directory for documentation"+ docdir (\v flags -> flags { docdir = v })+ installDirArg++ , option "" ["htmldir"]+ "installation directory for HTML documentation"+ htmldir (\v flags -> flags { htmldir = v })+ installDirArg++ , option "" ["haddockdir"]+ "installation directory for haddock interfaces"+ haddockdir (\v flags -> flags { haddockdir = v })+ installDirArg++ , option "" ["sysconfdir"]+ "installation directory for configuration files"+ sysconfdir (\v flags -> flags { sysconfdir = v })+ installDirArg+ ]+ where+ installDirArg _sf _lf d get set =+ reqArgFlag "DIR" _sf _lf d+ (fmap fromPathTemplate . get) (set . fmap toPathTemplate)++emptyConfigFlags :: ConfigFlags+emptyConfigFlags = mempty++instance Monoid ConfigFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup ConfigFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Copy flags+-- ------------------------------------------------------------++-- | Flags to @copy@: (destdir, copy-prefix (backwards compat), verbosity)+data CopyFlags = CopyFlags {+ copyDest :: Flag CopyDest,+ copyDistPref :: Flag FilePath,+ copyVerbosity :: Flag Verbosity,+ -- This is the same hack as in 'buildArgs'. But I (ezyang) don't+ -- think it's a hack, it's the right way to make hooks more robust+ -- TODO: Stop using this eventually when 'UserHooks' gets changed+ copyArgs :: [String],+ copyCabalFilePath :: Flag FilePath+ }+ deriving (Show, Generic)++defaultCopyFlags :: CopyFlags+defaultCopyFlags = CopyFlags {+ copyDest = Flag NoCopyDest,+ copyDistPref = NoFlag,+ copyVerbosity = Flag normal,+ copyArgs = [],+ copyCabalFilePath = mempty+ }++copyCommand :: CommandUI CopyFlags+copyCommand = CommandUI+ { commandName = "copy"+ , commandSynopsis = "Copy the files of all/specific components to install locations."+ , commandDescription = Just $ \_ -> wrapText $+ "Components encompass executables and libraries. "+ ++ "Does not call register, and allows a prefix at install time. "+ ++ "Without the --destdir flag, configure determines location.\n"+ , commandNotes = Just $ \pname ->+ "Examples:\n"+ ++ " " ++ pname ++ " copy "+ ++ " All the components in the package\n"+ ++ " " ++ pname ++ " copy foo "+ ++ " A component (i.e. lib, exe, test suite)"+ , commandUsage = usageAlternatives "copy" $+ [ "[FLAGS]"+ , "COMPONENTS [FLAGS]"+ ]+ , commandDefaultFlags = defaultCopyFlags+ , commandOptions = \showOrParseArgs -> case showOrParseArgs of+ ShowArgs -> filter ((`notElem` ["target-package-db"])+ . optionName) $ copyOptions ShowArgs+ ParseArgs -> copyOptions ParseArgs+}++copyOptions :: ShowOrParseArgs -> [OptionField CopyFlags]+copyOptions showOrParseArgs =+ [optionVerbosity copyVerbosity (\v flags -> flags { copyVerbosity = v })++ ,optionDistPref+ copyDistPref (\d flags -> flags { copyDistPref = d })+ showOrParseArgs++ ,option "" ["destdir"]+ "directory to copy files to, prepended to installation directories"+ copyDest (\v flags -> case copyDest flags of+ Flag (CopyToDb _) -> error "Use either 'destdir' or 'target-package-db'."+ _ -> flags { copyDest = v })+ (reqArg "DIR" (succeedReadE (Flag . CopyTo))+ (\f -> case f of Flag (CopyTo p) -> [p]; _ -> []))++ ,option "" ["target-package-db"]+ "package database to copy files into. Required when using ${pkgroot} prefix."+ copyDest (\v flags -> case copyDest flags of+ NoFlag -> flags { copyDest = v }+ Flag NoCopyDest -> flags { copyDest = v }+ _ -> error "Use either 'destdir' or 'target-package-db'.")+ (reqArg "DATABASE" (succeedReadE (Flag . CopyToDb))+ (\f -> case f of Flag (CopyToDb p) -> [p]; _ -> []))+ ]++emptyCopyFlags :: CopyFlags+emptyCopyFlags = mempty++instance Monoid CopyFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup CopyFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Install flags+-- ------------------------------------------------------------++-- | Flags to @install@: (package db, verbosity)+data InstallFlags = InstallFlags {+ installPackageDB :: Flag PackageDB,+ installDest :: Flag CopyDest,+ installDistPref :: Flag FilePath,+ installUseWrapper :: Flag Bool,+ installInPlace :: Flag Bool,+ installVerbosity :: Flag Verbosity,+ -- this is only here, because we can not+ -- change the hooks API.+ installCabalFilePath :: Flag FilePath+ }+ deriving (Show, Generic)++defaultInstallFlags :: InstallFlags+defaultInstallFlags = InstallFlags {+ installPackageDB = NoFlag,+ installDest = Flag NoCopyDest,+ installDistPref = NoFlag,+ installUseWrapper = Flag False,+ installInPlace = Flag False,+ installVerbosity = Flag normal,+ installCabalFilePath = mempty+ }++installCommand :: CommandUI InstallFlags+installCommand = CommandUI+ { commandName = "install"+ , commandSynopsis =+ "Copy the files into the install locations. Run register."+ , commandDescription = Just $ \_ -> wrapText $+ "Unlike the copy command, install calls the register command."+ ++ "If you want to install into a location that is not what was"+ ++ "specified in the configure step, use the copy command.\n"+ , commandNotes = Nothing+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " install [FLAGS]\n"+ , commandDefaultFlags = defaultInstallFlags+ , commandOptions = \showOrParseArgs -> case showOrParseArgs of+ ShowArgs -> filter ((`notElem` ["target-package-db"])+ . optionName) $ installOptions ShowArgs+ ParseArgs -> installOptions ParseArgs+ }++installOptions :: ShowOrParseArgs -> [OptionField InstallFlags]+installOptions showOrParseArgs =+ [optionVerbosity installVerbosity (\v flags -> flags { installVerbosity = v })+ ,optionDistPref+ installDistPref (\d flags -> flags { installDistPref = d })+ showOrParseArgs++ ,option "" ["inplace"]+ "install the package in the install subdirectory of the dist prefix, so it can be used without being installed"+ installInPlace (\v flags -> flags { installInPlace = v })+ trueArg++ ,option "" ["shell-wrappers"]+ "using shell script wrappers around executables"+ installUseWrapper (\v flags -> flags { installUseWrapper = v })+ (boolOpt [] [])++ ,option "" ["package-db"] ""+ installPackageDB (\v flags -> flags { installPackageDB = v })+ (choiceOpt [ (Flag UserPackageDB, ([],["user"]),+ "upon configuration register this package in the user's local package database")+ , (Flag GlobalPackageDB, ([],["global"]),+ "(default) upon configuration register this package in the system-wide package database")])+ ,option "" ["target-package-db"]+ "package database to install into. Required when using ${pkgroot} prefix."+ installDest (\v flags -> flags { installDest = v })+ (reqArg "DATABASE" (succeedReadE (Flag . CopyToDb))+ (\f -> case f of Flag (CopyToDb p) -> [p]; _ -> []))+ ]++emptyInstallFlags :: InstallFlags+emptyInstallFlags = mempty++instance Monoid InstallFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup InstallFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * SDist flags+-- ------------------------------------------------------------++-- | Flags to @sdist@: (snapshot, verbosity)+data SDistFlags = SDistFlags {+ sDistSnapshot :: Flag Bool,+ sDistDirectory :: Flag FilePath,+ sDistDistPref :: Flag FilePath,+ sDistListSources :: Flag FilePath,+ sDistVerbosity :: Flag Verbosity+ }+ deriving (Show, Generic, Typeable)++defaultSDistFlags :: SDistFlags+defaultSDistFlags = SDistFlags {+ sDistSnapshot = Flag False,+ sDistDirectory = mempty,+ sDistDistPref = NoFlag,+ sDistListSources = mempty,+ sDistVerbosity = Flag normal+ }++sdistCommand :: CommandUI SDistFlags+sdistCommand = CommandUI+ { commandName = "sdist"+ , commandSynopsis =+ "Generate a source distribution file (.tar.gz)."+ , commandDescription = Nothing+ , commandNotes = Nothing+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " sdist [FLAGS]\n"+ , commandDefaultFlags = defaultSDistFlags+ , commandOptions = \showOrParseArgs ->+ [optionVerbosity sDistVerbosity (\v flags -> flags { sDistVerbosity = v })+ ,optionDistPref+ sDistDistPref (\d flags -> flags { sDistDistPref = d })+ showOrParseArgs++ ,option "" ["list-sources"]+ "Just write a list of the package's sources to a file"+ sDistListSources (\v flags -> flags { sDistListSources = v })+ (reqArgFlag "FILE")++ ,option "" ["snapshot"]+ "Produce a snapshot source distribution"+ sDistSnapshot (\v flags -> flags { sDistSnapshot = v })+ trueArg++ ,option "" ["output-directory"]+ ("Generate a source distribution in the given directory, "+ ++ "without creating a tarball")+ sDistDirectory (\v flags -> flags { sDistDirectory = v })+ (reqArgFlag "DIR")+ ]+ }++emptySDistFlags :: SDistFlags+emptySDistFlags = mempty++instance Monoid SDistFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup SDistFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Register flags+-- ------------------------------------------------------------++-- | Flags to @register@ and @unregister@: (user package, gen-script,+-- in-place, verbosity)+data RegisterFlags = RegisterFlags {+ regPackageDB :: Flag PackageDB,+ regGenScript :: Flag Bool,+ regGenPkgConf :: Flag (Maybe FilePath),+ regInPlace :: Flag Bool,+ regDistPref :: Flag FilePath,+ regPrintId :: Flag Bool,+ regVerbosity :: Flag Verbosity,+ -- Same as in 'buildArgs' and 'copyArgs'+ regArgs :: [String],+ regCabalFilePath :: Flag FilePath+ }+ deriving (Show, Generic, Typeable)++defaultRegisterFlags :: RegisterFlags+defaultRegisterFlags = RegisterFlags {+ regPackageDB = NoFlag,+ regGenScript = Flag False,+ regGenPkgConf = NoFlag,+ regInPlace = Flag False,+ regDistPref = NoFlag,+ regPrintId = Flag False,+ regArgs = [],+ regCabalFilePath = mempty,+ regVerbosity = Flag normal+ }++registerCommand :: CommandUI RegisterFlags+registerCommand = CommandUI+ { commandName = "register"+ , commandSynopsis =+ "Register this package with the compiler."+ , commandDescription = Nothing+ , commandNotes = Nothing+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " register [FLAGS]\n"+ , commandDefaultFlags = defaultRegisterFlags+ , commandOptions = \showOrParseArgs ->+ [optionVerbosity regVerbosity (\v flags -> flags { regVerbosity = v })+ ,optionDistPref+ regDistPref (\d flags -> flags { regDistPref = d })+ showOrParseArgs++ ,option "" ["packageDB"] ""+ regPackageDB (\v flags -> flags { regPackageDB = v })+ (choiceOpt [ (Flag UserPackageDB, ([],["user"]),+ "upon registration, register this package in the user's local package database")+ , (Flag GlobalPackageDB, ([],["global"]),+ "(default)upon registration, register this package in the system-wide package database")])++ ,option "" ["inplace"]+ "register the package in the build location, so it can be used without being installed"+ regInPlace (\v flags -> flags { regInPlace = v })+ trueArg++ ,option "" ["gen-script"]+ "instead of registering, generate a script to register later"+ regGenScript (\v flags -> flags { regGenScript = v })+ trueArg++ ,option "" ["gen-pkg-config"]+ "instead of registering, generate a package registration file/directory"+ regGenPkgConf (\v flags -> flags { regGenPkgConf = v })+ (optArg' "PKG" Flag flagToList)++ ,option "" ["print-ipid"]+ "print the installed package ID calculated for this package"+ regPrintId (\v flags -> flags { regPrintId = v })+ trueArg+ ]+ }++unregisterCommand :: CommandUI RegisterFlags+unregisterCommand = CommandUI+ { commandName = "unregister"+ , commandSynopsis =+ "Unregister this package with the compiler."+ , commandDescription = Nothing+ , commandNotes = Nothing+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " unregister [FLAGS]\n"+ , commandDefaultFlags = defaultRegisterFlags+ , commandOptions = \showOrParseArgs ->+ [optionVerbosity regVerbosity (\v flags -> flags { regVerbosity = v })+ ,optionDistPref+ regDistPref (\d flags -> flags { regDistPref = d })+ showOrParseArgs++ ,option "" ["user"] ""+ regPackageDB (\v flags -> flags { regPackageDB = v })+ (choiceOpt [ (Flag UserPackageDB, ([],["user"]),+ "unregister this package in the user's local package database")+ , (Flag GlobalPackageDB, ([],["global"]),+ "(default) unregister this package in the system-wide package database")])++ ,option "" ["gen-script"]+ "Instead of performing the unregister command, generate a script to unregister later"+ regGenScript (\v flags -> flags { regGenScript = v })+ trueArg+ ]+ }++emptyRegisterFlags :: RegisterFlags+emptyRegisterFlags = mempty++instance Monoid RegisterFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup RegisterFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * HsColour flags+-- ------------------------------------------------------------++data HscolourFlags = HscolourFlags {+ hscolourCSS :: Flag FilePath,+ hscolourExecutables :: Flag Bool,+ hscolourTestSuites :: Flag Bool,+ hscolourBenchmarks :: Flag Bool,+ hscolourForeignLibs :: Flag Bool,+ hscolourDistPref :: Flag FilePath,+ hscolourVerbosity :: Flag Verbosity,+ hscolourCabalFilePath :: Flag FilePath+ }+ deriving (Show, Generic, Typeable)++emptyHscolourFlags :: HscolourFlags+emptyHscolourFlags = mempty++defaultHscolourFlags :: HscolourFlags+defaultHscolourFlags = HscolourFlags {+ hscolourCSS = NoFlag,+ hscolourExecutables = Flag False,+ hscolourTestSuites = Flag False,+ hscolourBenchmarks = Flag False,+ hscolourDistPref = NoFlag,+ hscolourForeignLibs = Flag False,+ hscolourVerbosity = Flag normal,+ hscolourCabalFilePath = mempty+ }++instance Monoid HscolourFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup HscolourFlags where+ (<>) = gmappend++hscolourCommand :: CommandUI HscolourFlags+hscolourCommand = CommandUI+ { commandName = "hscolour"+ , commandSynopsis =+ "Generate HsColour colourised code, in HTML format."+ , commandDescription = Just (\_ -> "Requires the hscolour program.\n")+ , commandNotes = Just $ \_ ->+ "Deprecated in favour of 'cabal haddock --hyperlink-source'."+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " hscolour [FLAGS]\n"+ , commandDefaultFlags = defaultHscolourFlags+ , commandOptions = \showOrParseArgs ->+ [optionVerbosity hscolourVerbosity+ (\v flags -> flags { hscolourVerbosity = v })+ ,optionDistPref+ hscolourDistPref (\d flags -> flags { hscolourDistPref = d })+ showOrParseArgs++ ,option "" ["executables"]+ "Run hscolour for Executables targets"+ hscolourExecutables (\v flags -> flags { hscolourExecutables = v })+ trueArg++ ,option "" ["tests"]+ "Run hscolour for Test Suite targets"+ hscolourTestSuites (\v flags -> flags { hscolourTestSuites = v })+ trueArg++ ,option "" ["benchmarks"]+ "Run hscolour for Benchmark targets"+ hscolourBenchmarks (\v flags -> flags { hscolourBenchmarks = v })+ trueArg++ ,option "" ["foreign-libraries"]+ "Run hscolour for Foreign Library targets"+ hscolourForeignLibs (\v flags -> flags { hscolourForeignLibs = v })+ trueArg++ ,option "" ["all"]+ "Run hscolour for all targets"+ (\f -> allFlags [ hscolourExecutables f+ , hscolourTestSuites f+ , hscolourBenchmarks f+ , hscolourForeignLibs f+ ])+ (\v flags -> flags { hscolourExecutables = v+ , hscolourTestSuites = v+ , hscolourBenchmarks = v+ , hscolourForeignLibs = v+ })+ trueArg++ ,option "" ["css"]+ "Use a cascading style sheet"+ hscolourCSS (\v flags -> flags { hscolourCSS = v })+ (reqArgFlag "PATH")+ ]+ }++-- ------------------------------------------------------------+-- * Haddock flags+-- ------------------------------------------------------------+++-- | When we build haddock documentation, there are two cases:+--+-- 1. We build haddocks only for the current development version,+-- intended for local use and not for distribution. In this case,+-- we store the generated documentation in @<dist>/doc/html/<package name>@.+--+-- 2. We build haddocks for intended for uploading them to hackage.+-- In this case, we need to follow the layout that hackage expects+-- from documentation tarballs, and we might also want to use different+-- flags than for development builds, so in this case we store the generated+-- documentation in @<dist>/doc/html/<package id>-docs@.+data HaddockTarget = ForHackage | ForDevelopment deriving (Eq, Show, Generic, Typeable)++instance Binary HaddockTarget+instance Structured HaddockTarget++instance Pretty HaddockTarget where+ pretty ForHackage = Disp.text "for-hackage"+ pretty ForDevelopment = Disp.text "for-development"++instance Parsec HaddockTarget where+ parsec = P.choice [ P.try $ P.string "for-hackage" >> return ForHackage+ , P.string "for-development" >> return ForDevelopment]++data HaddockFlags = HaddockFlags {+ haddockProgramPaths :: [(String, FilePath)],+ haddockProgramArgs :: [(String, [String])],+ haddockHoogle :: Flag Bool,+ haddockHtml :: Flag Bool,+ haddockHtmlLocation :: Flag String,+ haddockForHackage :: Flag HaddockTarget,+ haddockExecutables :: Flag Bool,+ haddockTestSuites :: Flag Bool,+ haddockBenchmarks :: Flag Bool,+ haddockForeignLibs :: Flag Bool,+ haddockInternal :: Flag Bool,+ haddockCss :: Flag FilePath,+ haddockLinkedSource :: Flag Bool,+ haddockQuickJump :: Flag Bool,+ haddockHscolourCss :: Flag FilePath,+ haddockContents :: Flag PathTemplate,+ haddockDistPref :: Flag FilePath,+ haddockKeepTempFiles:: Flag Bool,+ haddockVerbosity :: Flag Verbosity,+ haddockCabalFilePath :: Flag FilePath,+ haddockArgs :: [String]+ }+ deriving (Show, Generic, Typeable)++defaultHaddockFlags :: HaddockFlags+defaultHaddockFlags = HaddockFlags {+ haddockProgramPaths = mempty,+ haddockProgramArgs = [],+ haddockHoogle = Flag False,+ haddockHtml = Flag False,+ haddockHtmlLocation = NoFlag,+ haddockForHackage = NoFlag,+ haddockExecutables = Flag False,+ haddockTestSuites = Flag False,+ haddockBenchmarks = Flag False,+ haddockForeignLibs = Flag False,+ haddockInternal = Flag False,+ haddockCss = NoFlag,+ haddockLinkedSource = Flag False,+ haddockQuickJump = Flag False,+ haddockHscolourCss = NoFlag,+ haddockContents = NoFlag,+ haddockDistPref = NoFlag,+ haddockKeepTempFiles= Flag False,+ haddockVerbosity = Flag normal,+ haddockCabalFilePath = mempty,+ haddockArgs = mempty+ }++haddockCommand :: CommandUI HaddockFlags+haddockCommand = CommandUI+ { commandName = "haddock"+ , commandSynopsis = "Generate Haddock HTML documentation."+ , commandDescription = Just $ \_ ->+ "Requires the program haddock, version 2.x.\n"+ , commandNotes = Nothing+ , commandUsage = usageAlternatives "haddock" $+ [ "[FLAGS]"+ , "COMPONENTS [FLAGS]"+ ]+ , commandDefaultFlags = defaultHaddockFlags+ , commandOptions = \showOrParseArgs ->+ haddockOptions showOrParseArgs+ ++ programDbPaths progDb ParseArgs+ haddockProgramPaths (\v flags -> flags { haddockProgramPaths = v})+ ++ programDbOption progDb showOrParseArgs+ haddockProgramArgs (\v fs -> fs { haddockProgramArgs = v })+ ++ programDbOptions progDb ParseArgs+ haddockProgramArgs (\v flags -> flags { haddockProgramArgs = v})+ }+ where+ progDb = addKnownProgram haddockProgram+ $ addKnownProgram ghcProgram+ $ emptyProgramDb++haddockOptions :: ShowOrParseArgs -> [OptionField HaddockFlags]+haddockOptions showOrParseArgs =+ [optionVerbosity haddockVerbosity+ (\v flags -> flags { haddockVerbosity = v })+ ,optionDistPref+ haddockDistPref (\d flags -> flags { haddockDistPref = d })+ showOrParseArgs++ ,option "" ["keep-temp-files"]+ "Keep temporary files"+ haddockKeepTempFiles (\b flags -> flags { haddockKeepTempFiles = b })+ trueArg++ ,option "" ["hoogle"]+ "Generate a hoogle database"+ haddockHoogle (\v flags -> flags { haddockHoogle = v })+ trueArg++ ,option "" ["html"]+ "Generate HTML documentation (the default)"+ haddockHtml (\v flags -> flags { haddockHtml = v })+ trueArg++ ,option "" ["html-location"]+ "Location of HTML documentation for pre-requisite packages"+ 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 })+ (noArg (Flag ForHackage))++ ,option "" ["executables"]+ "Run haddock for Executables targets"+ haddockExecutables (\v flags -> flags { haddockExecutables = v })+ trueArg++ ,option "" ["tests"]+ "Run haddock for Test Suite targets"+ haddockTestSuites (\v flags -> flags { haddockTestSuites = v })+ trueArg++ ,option "" ["benchmarks"]+ "Run haddock for Benchmark targets"+ haddockBenchmarks (\v flags -> flags { haddockBenchmarks = v })+ trueArg++ ,option "" ["foreign-libraries"]+ "Run haddock for Foreign Library targets"+ haddockForeignLibs (\v flags -> flags { haddockForeignLibs = v })+ trueArg++ ,option "" ["all"]+ "Run haddock for all targets"+ (\f -> allFlags [ haddockExecutables f+ , haddockTestSuites f+ , haddockBenchmarks f+ , haddockForeignLibs f+ ])+ (\v flags -> flags { haddockExecutables = v+ , haddockTestSuites = v+ , haddockBenchmarks = v+ , haddockForeignLibs = v+ })+ trueArg++ ,option "" ["internal"]+ "Run haddock for internal modules and include all symbols"+ haddockInternal (\v flags -> flags { haddockInternal = v })+ trueArg++ ,option "" ["css"]+ "Use PATH as the haddock stylesheet"+ haddockCss (\v flags -> flags { haddockCss = v })+ (reqArgFlag "PATH")++ ,option "" ["hyperlink-source","hyperlink-sources","hyperlinked-source"]+ "Hyperlink the documentation to the source code"+ haddockLinkedSource (\v flags -> flags { haddockLinkedSource = v })+ trueArg++ ,option "" ["quickjump"]+ "Generate an index for interactive documentation navigation"+ haddockQuickJump (\v flags -> flags { haddockQuickJump = v })+ trueArg++ ,option "" ["hscolour-css"]+ "Use PATH as the HsColour stylesheet"+ haddockHscolourCss (\v flags -> flags { haddockHscolourCss = v })+ (reqArgFlag "PATH")++ ,option "" ["contents-location"]+ "Bake URL in as the location for the contents page"+ haddockContents (\v flags -> flags { haddockContents = v })+ (reqArg' "URL"+ (toFlag . toPathTemplate)+ (flagToList . fmap fromPathTemplate))+ ]++emptyHaddockFlags :: HaddockFlags+emptyHaddockFlags = mempty++instance Monoid HaddockFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup HaddockFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Clean flags+-- ------------------------------------------------------------++data CleanFlags = CleanFlags {+ cleanSaveConf :: Flag Bool,+ cleanDistPref :: Flag FilePath,+ cleanVerbosity :: Flag Verbosity,+ cleanCabalFilePath :: Flag FilePath+ }+ deriving (Show, Generic, Typeable)++defaultCleanFlags :: CleanFlags+defaultCleanFlags = CleanFlags {+ cleanSaveConf = Flag False,+ cleanDistPref = NoFlag,+ cleanVerbosity = Flag normal,+ cleanCabalFilePath = mempty+ }++cleanCommand :: CommandUI CleanFlags+cleanCommand = CommandUI+ { commandName = "clean"+ , commandSynopsis = "Clean up after a build."+ , commandDescription = Just $ \_ ->+ "Removes .hi, .o, preprocessed sources, etc.\n"+ , commandNotes = Nothing+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " clean [FLAGS]\n"+ , commandDefaultFlags = defaultCleanFlags+ , commandOptions = \showOrParseArgs ->+ [optionVerbosity cleanVerbosity (\v flags -> flags { cleanVerbosity = v })+ ,optionDistPref+ cleanDistPref (\d flags -> flags { cleanDistPref = d })+ showOrParseArgs++ ,option "s" ["save-configure"]+ "Do not remove the configuration file (dist/setup-config) during cleaning. Saves need to reconfigure."+ cleanSaveConf (\v flags -> flags { cleanSaveConf = v })+ trueArg+ ]+ }++emptyCleanFlags :: CleanFlags+emptyCleanFlags = mempty++instance Monoid CleanFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup CleanFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Build flags+-- ------------------------------------------------------------++data BuildFlags = BuildFlags {+ buildProgramPaths :: [(String, FilePath)],+ buildProgramArgs :: [(String, [String])],+ buildDistPref :: Flag FilePath,+ buildVerbosity :: Flag Verbosity,+ buildNumJobs :: Flag (Maybe Int),+ -- TODO: this one should not be here, it's just that the silly+ -- UserHooks stop us from passing extra info in other ways+ buildArgs :: [String],+ buildCabalFilePath :: Flag FilePath+ }+ deriving (Read, Show, Generic, Typeable)++defaultBuildFlags :: BuildFlags+defaultBuildFlags = BuildFlags {+ buildProgramPaths = mempty,+ buildProgramArgs = [],+ buildDistPref = mempty,+ buildVerbosity = Flag normal,+ buildNumJobs = mempty,+ buildArgs = [],+ buildCabalFilePath = mempty+ }++buildCommand :: ProgramDb -> CommandUI BuildFlags+buildCommand progDb = CommandUI+ { commandName = "build"+ , commandSynopsis = "Compile all/specific components."+ , commandDescription = Just $ \_ -> wrapText $+ "Components encompass executables, tests, and benchmarks.\n"+ ++ "\n"+ ++ "Affected by configuration options, see `configure`.\n"+ , commandNotes = Just $ \pname ->+ "Examples:\n"+ ++ " " ++ pname ++ " build "+ ++ " All the components in the package\n"+ ++ " " ++ pname ++ " build foo "+ ++ " A component (i.e. lib, exe, test suite)\n\n"+ ++ programFlagsDescription progDb+--TODO: re-enable once we have support for module/file targets+-- ++ " " ++ pname ++ " build Foo.Bar "+-- ++ " A module\n"+-- ++ " " ++ pname ++ " build Foo/Bar.hs"+-- ++ " A file\n\n"+-- ++ "If a target is ambiguous it can be qualified with the component "+-- ++ "name, e.g.\n"+-- ++ " " ++ pname ++ " build foo:Foo.Bar\n"+-- ++ " " ++ pname ++ " build testsuite1:Foo/Bar.hs\n"+ , commandUsage = usageAlternatives "build" $+ [ "[FLAGS]"+ , "COMPONENTS [FLAGS]"+ ]+ , commandDefaultFlags = defaultBuildFlags+ , commandOptions = \showOrParseArgs ->+ [ optionVerbosity+ buildVerbosity (\v flags -> flags { buildVerbosity = v })++ , optionDistPref+ buildDistPref (\d flags -> flags { buildDistPref = d }) showOrParseArgs+ ]+ ++ buildOptions progDb showOrParseArgs+ }++buildOptions :: ProgramDb -> ShowOrParseArgs+ -> [OptionField BuildFlags]+buildOptions progDb showOrParseArgs =+ [ optionNumJobs+ buildNumJobs (\v flags -> flags { buildNumJobs = v })+ ]++ ++ programDbPaths progDb showOrParseArgs+ buildProgramPaths (\v flags -> flags { buildProgramPaths = v})++ ++ programDbOption progDb showOrParseArgs+ buildProgramArgs (\v fs -> fs { buildProgramArgs = v })++ ++ programDbOptions progDb showOrParseArgs+ buildProgramArgs (\v flags -> flags { buildProgramArgs = v})++emptyBuildFlags :: BuildFlags+emptyBuildFlags = mempty++instance Monoid BuildFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup BuildFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * REPL Flags+-- ------------------------------------------------------------++data ReplFlags = ReplFlags {+ replProgramPaths :: [(String, FilePath)],+ replProgramArgs :: [(String, [String])],+ replDistPref :: Flag FilePath,+ replVerbosity :: Flag Verbosity,+ replReload :: Flag Bool,+ replReplOptions :: [String]+ }+ deriving (Show, Generic, Typeable)++defaultReplFlags :: ReplFlags+defaultReplFlags = ReplFlags {+ replProgramPaths = mempty,+ replProgramArgs = [],+ replDistPref = NoFlag,+ replVerbosity = Flag normal,+ replReload = Flag False,+ replReplOptions = []+ }++instance Monoid ReplFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup ReplFlags where+ (<>) = gmappend++replCommand :: ProgramDb -> CommandUI ReplFlags+replCommand progDb = CommandUI+ { commandName = "repl"+ , commandSynopsis =+ "Open an interpreter session for the given component."+ , commandDescription = Just $ \pname -> wrapText $+ "If the current directory contains no package, ignores COMPONENT "+ ++ "parameters and opens an interactive interpreter session; if a "+ ++ "sandbox is present, its package database will be used.\n"+ ++ "\n"+ ++ "Otherwise, (re)configures with the given or default flags, and "+ ++ "loads the interpreter with the relevant modules. For executables, "+ ++ "tests and benchmarks, loads the main module (and its "+ ++ "dependencies); for libraries all exposed/other modules.\n"+ ++ "\n"+ ++ "The default component is the library itself, or the executable "+ ++ "if that is the only component.\n"+ ++ "\n"+ ++ "Support for loading specific modules is planned but not "+ ++ "implemented yet. For certain scenarios, `" ++ pname+ ++ " exec -- ghci :l Foo` may be used instead. Note that `exec` will "+ ++ "not (re)configure and you will have to specify the location of "+ ++ "other modules, if required.\n"++ , commandNotes = Just $ \pname ->+ "Examples:\n"+ ++ " " ++ pname ++ " repl "+ ++ " The first component in the package\n"+ ++ " " ++ pname ++ " repl foo "+ ++ " A named component (i.e. lib, exe, test suite)\n"+ ++ " " ++ pname ++ " repl --repl-options=\"-lstdc++\""+ ++ " Specifying flags for interpreter\n"+--TODO: re-enable once we have support for module/file targets+-- ++ " " ++ pname ++ " repl Foo.Bar "+-- ++ " A module\n"+-- ++ " " ++ pname ++ " repl Foo/Bar.hs"+-- ++ " A file\n\n"+-- ++ "If a target is ambiguous it can be qualified with the component "+-- ++ "name, e.g.\n"+-- ++ " " ++ pname ++ " repl foo:Foo.Bar\n"+-- ++ " " ++ pname ++ " repl testsuite1:Foo/Bar.hs\n"+ , commandUsage = \pname -> "Usage: " ++ pname ++ " repl [COMPONENT] [FLAGS]\n"+ , commandDefaultFlags = defaultReplFlags+ , commandOptions = \showOrParseArgs ->+ optionVerbosity replVerbosity (\v flags -> flags { replVerbosity = v })+ : optionDistPref+ replDistPref (\d flags -> flags { replDistPref = d })+ showOrParseArgs++ : programDbPaths progDb showOrParseArgs+ replProgramPaths (\v flags -> flags { replProgramPaths = v})++ ++ programDbOption progDb showOrParseArgs+ replProgramArgs (\v flags -> flags { replProgramArgs = v})++ ++ programDbOptions progDb showOrParseArgs+ replProgramArgs (\v flags -> flags { replProgramArgs = v})++ ++ case showOrParseArgs of+ ParseArgs ->+ [ option "" ["reload"]+ "Used from within an interpreter to update files."+ replReload (\v flags -> flags { replReload = v })+ trueArg+ ]+ _ -> []+ ++ map liftReplOption (replOptions showOrParseArgs)+ }+ where+ liftReplOption = liftOption replReplOptions (\v flags -> flags { replReplOptions = v })++replOptions :: ShowOrParseArgs -> [OptionField [String]]+replOptions _ = [ option [] ["repl-options"] "use this option for the repl" id+ const (reqArg "FLAG" (succeedReadE (:[])) id) ]++-- ------------------------------------------------------------+-- * Test flags+-- ------------------------------------------------------------++data TestShowDetails = Never | Failures | Always | Streaming | Direct+ deriving (Eq, Ord, Enum, Bounded, Generic, Show, Typeable)++instance Binary TestShowDetails+instance Structured TestShowDetails++knownTestShowDetails :: [TestShowDetails]+knownTestShowDetails = [minBound..maxBound]++instance Pretty TestShowDetails where+ pretty = Disp.text . lowercase . show++instance Parsec TestShowDetails where+ parsec = maybe (fail "invalid TestShowDetails") return . classify =<< ident+ where+ ident = P.munch1 (\c -> isAlpha c || c == '_' || c == '-')+ classify str = lookup (lowercase str) enumMap+ enumMap :: [(String, TestShowDetails)]+ enumMap = [ (prettyShow x, x)+ | x <- knownTestShowDetails ]++--TODO: do we need this instance?+instance Monoid TestShowDetails where+ mempty = Never+ mappend = (<>)++instance Semigroup TestShowDetails where+ a <> b = if a < b then b else a++data TestFlags = TestFlags {+ testDistPref :: Flag FilePath,+ testVerbosity :: Flag Verbosity,+ testHumanLog :: Flag PathTemplate,+ testMachineLog :: Flag PathTemplate,+ testShowDetails :: Flag TestShowDetails,+ testKeepTix :: Flag Bool,+ testWrapper :: Flag FilePath,+ testFailWhenNoTestSuites :: Flag Bool,+ -- TODO: think about if/how options are passed to test exes+ testOptions :: [PathTemplate]+ } deriving (Show, Generic, Typeable)++defaultTestFlags :: TestFlags+defaultTestFlags = TestFlags {+ testDistPref = NoFlag,+ testVerbosity = Flag normal,+ testHumanLog = toFlag $ toPathTemplate $ "$pkgid-$test-suite.log",+ testMachineLog = toFlag $ toPathTemplate $ "$pkgid.log",+ testShowDetails = toFlag Failures,+ testKeepTix = toFlag False,+ testWrapper = NoFlag,+ testFailWhenNoTestSuites = toFlag False,+ testOptions = []+ }++testCommand :: CommandUI TestFlags+testCommand = CommandUI+ { commandName = "test"+ , commandSynopsis =+ "Run all/specific tests in the test suite."+ , commandDescription = Just $ \pname -> wrapText $+ "If necessary (re)configures with `--enable-tests` flag and builds"+ ++ " the test suite.\n"+ ++ "\n"+ ++ "Remember that the tests' dependencies must be installed if there"+ ++ " are additional ones; e.g. with `" ++ pname+ ++ " install --only-dependencies --enable-tests`.\n"+ ++ "\n"+ ++ "By defining UserHooks in a custom Setup.hs, the package can"+ ++ " define actions to be executed before and after running tests.\n"+ , commandNotes = Nothing+ , commandUsage = usageAlternatives "test"+ [ "[FLAGS]"+ , "TESTCOMPONENTS [FLAGS]"+ ]+ , commandDefaultFlags = defaultTestFlags+ , commandOptions = testOptions'+ }++testOptions' :: ShowOrParseArgs -> [OptionField TestFlags]+testOptions' showOrParseArgs =+ [ optionVerbosity testVerbosity (\v flags -> flags { testVerbosity = v })+ , optionDistPref+ testDistPref (\d flags -> flags { testDistPref = d })+ showOrParseArgs+ , option [] ["log"]+ ("Log all test suite results to file (name template can use "+ ++ "$pkgid, $compiler, $os, $arch, $test-suite, $result)")+ testHumanLog (\v flags -> flags { testHumanLog = v })+ (reqArg' "TEMPLATE"+ (toFlag . toPathTemplate)+ (flagToList . fmap fromPathTemplate))+ , option [] ["machine-log"]+ ("Produce a machine-readable log file (name template can use "+ ++ "$pkgid, $compiler, $os, $arch, $result)")+ testMachineLog (\v flags -> flags { testMachineLog = v })+ (reqArg' "TEMPLATE"+ (toFlag . toPathTemplate)+ (flagToList . fmap fromPathTemplate))+ , option [] ["show-details"]+ ("'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."+ ++ "'direct': send results of test cases in real time; no log file.")+ testShowDetails (\v flags -> flags { testShowDetails = v })+ (reqArg "FILTER"+ (parsecToReadE (\_ -> "--show-details flag expects one of "+ ++ intercalate ", "+ (map prettyShow knownTestShowDetails))+ (fmap toFlag parsec))+ (flagToList . fmap prettyShow))+ , option [] ["keep-tix-files"]+ "keep .tix files for HPC between test runs"+ testKeepTix (\v flags -> flags { testKeepTix = v})+ trueArg+ , option [] ["test-wrapper"]+ "Run test through a wrapper."+ testWrapper (\v flags -> flags { testWrapper = v })+ (reqArg' "FILE" (toFlag :: FilePath -> Flag FilePath)+ (flagToList :: Flag FilePath -> [FilePath]))+ , option [] ["fail-when-no-test-suites"]+ ("Exit with failure when no test suites are found.")+ testFailWhenNoTestSuites (\v flags -> flags { testFailWhenNoTestSuites = v})+ trueArg+ , option [] ["test-options"]+ ("give extra options to test executables "+ ++ "(name templates can use $pkgid, $compiler, "+ ++ "$os, $arch, $test-suite)")+ testOptions (\v flags -> flags { testOptions = v })+ (reqArg' "TEMPLATES" (map toPathTemplate . splitArgs)+ (const []))+ , option [] ["test-option"]+ ("give extra option to test executables "+ ++ "(no need to quote options containing spaces, "+ ++ "name template can use $pkgid, $compiler, "+ ++ "$os, $arch, $test-suite)")+ testOptions (\v flags -> flags { testOptions = v })+ (reqArg' "TEMPLATE" (\x -> [toPathTemplate x])+ (map fromPathTemplate))+ ]++emptyTestFlags :: TestFlags+emptyTestFlags = mempty++instance Monoid TestFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup TestFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Benchmark flags+-- ------------------------------------------------------------++data BenchmarkFlags = BenchmarkFlags {+ benchmarkDistPref :: Flag FilePath,+ benchmarkVerbosity :: Flag Verbosity,+ benchmarkOptions :: [PathTemplate]+ } deriving (Show, Generic, Typeable)++defaultBenchmarkFlags :: BenchmarkFlags+defaultBenchmarkFlags = BenchmarkFlags {+ benchmarkDistPref = NoFlag,+ benchmarkVerbosity = Flag normal,+ benchmarkOptions = []+ }++benchmarkCommand :: CommandUI BenchmarkFlags+benchmarkCommand = CommandUI+ { commandName = "bench"+ , commandSynopsis =+ "Run all/specific benchmarks."+ , commandDescription = Just $ \pname -> wrapText $+ "If necessary (re)configures with `--enable-benchmarks` flag and"+ ++ " builds the benchmarks.\n"+ ++ "\n"+ ++ "Remember that the benchmarks' dependencies must be installed if"+ ++ " there are additional ones; e.g. with `" ++ pname+ ++ " install --only-dependencies --enable-benchmarks`.\n"+ ++ "\n"+ ++ "By defining UserHooks in a custom Setup.hs, the package can"+ ++ " define actions to be executed before and after running"+ ++ " benchmarks.\n"+ , commandNotes = Nothing+ , commandUsage = usageAlternatives "bench"+ [ "[FLAGS]"+ , "BENCHCOMPONENTS [FLAGS]"+ ]+ , commandDefaultFlags = defaultBenchmarkFlags+ , commandOptions = benchmarkOptions'+ }++benchmarkOptions' :: ShowOrParseArgs -> [OptionField BenchmarkFlags]+benchmarkOptions' showOrParseArgs =+ [ optionVerbosity benchmarkVerbosity+ (\v flags -> flags { benchmarkVerbosity = v })+ , optionDistPref+ benchmarkDistPref (\d flags -> flags { benchmarkDistPref = d })+ showOrParseArgs+ , option [] ["benchmark-options"]+ ("give extra options to benchmark executables "+ ++ "(name templates can use $pkgid, $compiler, "+ ++ "$os, $arch, $benchmark)")+ benchmarkOptions (\v flags -> flags { benchmarkOptions = v })+ (reqArg' "TEMPLATES" (map toPathTemplate . splitArgs)+ (const []))+ , option [] ["benchmark-option"]+ ("give extra option to benchmark executables "+ ++ "(no need to quote options containing spaces, "+ ++ "name template can use $pkgid, $compiler, "+ ++ "$os, $arch, $benchmark)")+ benchmarkOptions (\v flags -> flags { benchmarkOptions = v })+ (reqArg' "TEMPLATE" (\x -> [toPathTemplate x])+ (map fromPathTemplate))+ ]++emptyBenchmarkFlags :: BenchmarkFlags+emptyBenchmarkFlags = mempty++instance Monoid BenchmarkFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup BenchmarkFlags where+ (<>) = gmappend++-- ------------------------------------------------------------+-- * Shared options utils+-- ------------------------------------------------------------++programFlagsDescription :: ProgramDb -> String+programFlagsDescription progDb =+ "The flags --with-PROG and --PROG-option(s) can be used with"+ ++ " the following programs:"+ ++ (concatMap (\line -> "\n " ++ unwords line) . wrapLine 77 . sort)+ [ programName prog | (prog, _) <- knownPrograms progDb ]+ ++ "\n"++-- | For each known program @PROG@ in 'progDb', produce a @with-PROG@+-- 'OptionField'.+programDbPaths+ :: ProgramDb+ -> ShowOrParseArgs+ -> (flags -> [(String, FilePath)])+ -> ([(String, FilePath)] -> (flags -> flags))+ -> [OptionField flags]+programDbPaths progDb showOrParseArgs get set =+ programDbPaths' ("with-" ++) progDb showOrParseArgs get set++-- | Like 'programDbPaths', but allows to customise the option name.+programDbPaths'+ :: (String -> String)+ -> ProgramDb+ -> ShowOrParseArgs+ -> (flags -> [(String, FilePath)])+ -> ([(String, FilePath)] -> (flags -> flags))+ -> [OptionField flags]+programDbPaths' mkName progDb showOrParseArgs get set =+ case showOrParseArgs of+ -- we don't want a verbose help text list so we just show a generic one:+ ShowArgs -> [withProgramPath "PROG"]+ ParseArgs -> map (withProgramPath . programName . fst)+ (knownPrograms progDb)+ where+ withProgramPath prog =+ option "" [mkName prog]+ ("give the path to " ++ prog)+ get set+ (reqArg' "PATH" (\path -> [(prog, path)])+ (\progPaths -> [ path | (prog', path) <- progPaths, prog==prog' ]))++-- | For each known program @PROG@ in 'progDb', produce a @PROG-option@+-- 'OptionField'.+programDbOption+ :: ProgramDb+ -> ShowOrParseArgs+ -> (flags -> [(String, [String])])+ -> ([(String, [String])] -> (flags -> flags))+ -> [OptionField flags]+programDbOption progDb showOrParseArgs get set =+ case showOrParseArgs of+ -- we don't want a verbose help text list so we just show a generic one:+ ShowArgs -> [programOption "PROG"]+ ParseArgs -> map (programOption . programName . fst)+ (knownPrograms progDb)+ where+ programOption prog =+ option "" [prog ++ "-option"]+ ("give an extra option to " ++ prog +++ " (no need to quote options containing spaces)")+ get set+ (reqArg' "OPT" (\arg -> [(prog, [arg])])+ (\progArgs -> concat [ args+ | (prog', args) <- progArgs, prog==prog' ]))+++-- | For each known program @PROG@ in 'progDb', produce a @PROG-options@+-- 'OptionField'.+programDbOptions+ :: ProgramDb+ -> ShowOrParseArgs+ -> (flags -> [(String, [String])])+ -> ([(String, [String])] -> (flags -> flags))+ -> [OptionField flags]+programDbOptions progDb showOrParseArgs get set =+ case showOrParseArgs of+ -- we don't want a verbose help text list so we just show a generic one:+ ShowArgs -> [programOptions "PROG"]+ ParseArgs -> map (programOptions . programName . fst)+ (knownPrograms progDb)+ where+ programOptions prog =+ option "" [prog ++ "-options"]+ ("give extra options to " ++ prog)+ get set+ (reqArg' "OPTS" (\args -> [(prog, splitArgs args)]) (const []))++-- ------------------------------------------------------------+-- * GetOpt Utils+-- ------------------------------------------------------------++boolOpt :: SFlags -> SFlags+ -> MkOptDescr (a -> Flag Bool) (Flag Bool -> a -> a) a+boolOpt = Command.boolOpt flagToMaybe Flag++boolOpt' :: OptFlags -> OptFlags+ -> MkOptDescr (a -> Flag Bool) (Flag Bool -> a -> a) a+boolOpt' = Command.boolOpt' flagToMaybe Flag++trueArg, falseArg :: MkOptDescr (a -> Flag Bool) (Flag Bool -> a -> a) a+trueArg sfT lfT = boolOpt' (sfT, lfT) ([], []) sfT lfT+falseArg sfF lfF = boolOpt' ([], []) (sfF, lfF) sfF lfF++reqArgFlag :: ArgPlaceHolder -> SFlags -> LFlags -> Description ->+ (b -> Flag String) -> (Flag String -> b -> b) -> OptDescr b+reqArgFlag ad = reqArg ad (succeedReadE Flag) flagToList++optionDistPref :: (flags -> Flag FilePath)+ -> (Flag FilePath -> flags -> flags)+ -> ShowOrParseArgs+ -> OptionField flags+optionDistPref get set = \showOrParseArgs ->+ option "" (distPrefFlagName showOrParseArgs)+ ( "The directory where Cabal puts generated build files "+ ++ "(default " ++ defaultDistPref ++ ")")+ get set+ (reqArgFlag "DIR")+ where+ distPrefFlagName ShowArgs = ["builddir"]+ distPrefFlagName ParseArgs = ["builddir", "distdir", "distpref"]++optionVerbosity :: (flags -> Flag Verbosity)+ -> (Flag Verbosity -> flags -> flags)+ -> OptionField flags+optionVerbosity get set =+ option "v" ["verbose"]+ "Control verbosity (n is 0--3, default verbosity level is 1)"+ get set+ (optArg "n" (fmap Flag flagToVerbosity)+ (Flag verbose) -- default Value if no n is given+ (fmap (Just . showForCabal) . flagToList))++optionNumJobs :: (flags -> Flag (Maybe Int))+ -> (Flag (Maybe Int) -> flags -> flags)+ -> OptionField flags+optionNumJobs get set =+ option "j" ["jobs"]+ "Run NUM jobs simultaneously (or '$ncpus' if no NUM is given)."+ get set+ (optArg "NUM" (fmap Flag numJobsParser)+ (Flag Nothing)+ (map (Just . maybe "$ncpus" show) . flagToList))+ where+ numJobsParser :: ReadE (Maybe Int)+ numJobsParser = ReadE $ \s ->+ case s of+ "$ncpus" -> Right Nothing+ _ -> case reads s of+ [(n, "")]+ | n < 1 -> Left "The number of jobs should be 1 or more."+ | otherwise -> Right (Just n)+ _ -> Left "The jobs value should be a number or '$ncpus'"+++-- ------------------------------------------------------------+-- * show-build-info command flags+-- ------------------------------------------------------------++data ShowBuildInfoFlags = ShowBuildInfoFlags+ { buildInfoBuildFlags :: BuildFlags+ , buildInfoOutputFile :: Maybe FilePath+ } deriving (Show, Typeable)++defaultShowBuildFlags :: ShowBuildInfoFlags+defaultShowBuildFlags =+ ShowBuildInfoFlags+ { buildInfoBuildFlags = defaultBuildFlags+ , buildInfoOutputFile = Nothing+ }++showBuildInfoCommand :: ProgramDb -> CommandUI ShowBuildInfoFlags+showBuildInfoCommand progDb = CommandUI+ { commandName = "show-build-info"+ , commandSynopsis = "Emit details about how a package would be built."+ , commandDescription = Just $ \_ -> wrapText $+ "Components encompass executables, tests, and benchmarks.\n"+ ++ "\n"+ ++ "Affected by configuration options, see `configure`.\n"+ , commandNotes = Just $ \pname ->+ "Examples:\n"+ ++ " " ++ pname ++ " show-build-info "+ ++ " All the components in the package\n"+ ++ " " ++ pname ++ " show-build-info foo "+ ++ " A component (i.e. lib, exe, test suite)\n\n"+ ++ programFlagsDescription progDb+--TODO: re-enable once we have support for module/file targets+-- ++ " " ++ pname ++ " show-build-info Foo.Bar "+-- ++ " A module\n"+-- ++ " " ++ pname ++ " show-build-info Foo/Bar.hs"+-- ++ " A file\n\n"+-- ++ "If a target is ambiguous it can be qualified with the component "+-- ++ "name, e.g.\n"+-- ++ " " ++ pname ++ " show-build-info foo:Foo.Bar\n"+-- ++ " " ++ pname ++ " show-build-info testsuite1:Foo/Bar.hs\n"+ , commandUsage = usageAlternatives "show-build-info" $+ [ "[FLAGS]"+ , "COMPONENTS [FLAGS]"+ ]+ , commandDefaultFlags = defaultShowBuildFlags+ , commandOptions = \showOrParseArgs ->+ parseBuildFlagsForShowBuildInfoFlags showOrParseArgs progDb+ +++ [ option [] ["buildinfo-json-output"]+ "Write the result to the given file instead of stdout"+ buildInfoOutputFile (\pf flags -> flags { buildInfoOutputFile = pf })+ (reqArg' "FILE" Just (maybe [] pure))+ ]++ }++parseBuildFlagsForShowBuildInfoFlags :: ShowOrParseArgs -> ProgramDb -> [OptionField ShowBuildInfoFlags]+parseBuildFlagsForShowBuildInfoFlags showOrParseArgs progDb =+ map+ (liftOption+ buildInfoBuildFlags+ (\bf flags -> flags { buildInfoBuildFlags = bf } )+ )+ buildFlags+ where+ buildFlags = buildOptions progDb showOrParseArgs+ +++ [ optionVerbosity+ buildVerbosity (\v flags -> flags { buildVerbosity = v })++ , optionDistPref+ buildDistPref (\d flags -> flags { buildDistPref = d }) showOrParseArgs+ ]++-- ------------------------------------------------------------+-- * Other Utils+-- ------------------------------------------------------------++-- | Arguments to pass to a @configure@ script, e.g. generated by+-- @autoconf@.+configureArgs :: Bool -> ConfigFlags -> [String]+configureArgs bcHack flags+ = hc_flag+ ++ optFlag "with-hc-pkg" configHcPkg+ ++ optFlag' "prefix" prefix+ ++ optFlag' "bindir" bindir+ ++ optFlag' "libdir" libdir+ ++ optFlag' "libexecdir" libexecdir+ ++ optFlag' "datadir" datadir+ ++ optFlag' "sysconfdir" sysconfdir+ ++ configConfigureArgs flags+ where+ hc_flag = case (configHcFlavor flags, configHcPath flags) of+ (_, Flag hc_path) -> [hc_flag_name ++ hc_path]+ (Flag hc, NoFlag) -> [hc_flag_name ++ prettyShow hc]+ (NoFlag,NoFlag) -> []+ hc_flag_name+ --TODO kill off thic bc hack when defaultUserHooks is removed.+ | bcHack = "--with-hc="+ | otherwise = "--with-compiler="+ optFlag name config_field = case config_field flags of+ Flag p -> ["--" ++ name ++ "=" ++ p]+ NoFlag -> []+ optFlag' name config_field = optFlag name (fmap fromPathTemplate+ . config_field+ . configInstallDirs)++configureCCompiler :: Verbosity -> ProgramDb+ -> IO (FilePath, [String])+configureCCompiler verbosity progdb = configureProg verbosity progdb gccProgram++configureLinker :: Verbosity -> ProgramDb -> IO (FilePath, [String])+configureLinker verbosity progdb = configureProg verbosity progdb ldProgram++configureProg :: Verbosity -> ProgramDb -> Program+ -> IO (FilePath, [String])+configureProg verbosity programDb prog = do+ (p, _) <- requireProgram verbosity prog programDb+ let pInv = programInvocation p []+ return (progInvokePath pInv, progInvokeArgs pInv)++-- | Helper function to split a string into a list of arguments.+-- It's supposed to handle quoted things sensibly, eg:+--+-- > splitArgs "--foo=\"C:/Program Files/Bar/" --baz"+-- > = ["--foo=C:/Program Files/Bar", "--baz"]+--+-- > splitArgs "\"-DMSGSTR=\\\"foo bar\\\"\" --baz"+-- > = ["-DMSGSTR=\"foo bar\"","--baz"]+--+splitArgs :: String -> [String]+splitArgs = space []+ where+ space :: String -> String -> [String]+ space w [] = word w []+ space w ( c :s)+ | isSpace c = word w (space [] s)+ space w ('"':s) = string w s+ space w s = nonstring w s++ string :: String -> String -> [String]+ string w [] = word w []+ string w ('"':s) = space w s+ string w ('\\':'"':s) = string ('"':w) s+ string w ( c :s) = string (c:w) s++ nonstring :: String -> String -> [String]+ nonstring w [] = word w []+ nonstring w ('"':s) = string w s+ nonstring w ( c :s) = space (c:w) s++ word [] s = s+ word w s = reverse w : s++-- The test cases kinda have to be rewritten from the ground up... :/+--hunitTests :: [Test]+--hunitTests =+-- let m = [("ghc", GHC), ("nhc98", NHC), ("hugs", Hugs)]+-- (flags, commands', unkFlags, ers)+-- = getOpt Permute options ["configure", "foobar", "--prefix=/foo", "--ghc", "--nhc98", "--hugs", "--with-compiler=/comp", "--unknown1", "--unknown2", "--install-prefix=/foo", "--user", "--global"]+-- in [TestLabel "very basic option parsing" $ TestList [+-- "getOpt flags" ~: "failed" ~:+-- [Prefix "/foo", GhcFlag, NhcFlag, HugsFlag,+-- WithCompiler "/comp", InstPrefix "/foo", UserFlag, GlobalFlag]+-- ~=? flags,+-- "getOpt commands" ~: "failed" ~: ["configure", "foobar"] ~=? commands',+-- "getOpt unknown opts" ~: "failed" ~:+-- ["--unknown1", "--unknown2"] ~=? unkFlags,+-- "getOpt errors" ~: "failed" ~: [] ~=? ers],+--+-- TestLabel "test location of various compilers" $ TestList+-- ["configure parsing for prefix and compiler flag" ~: "failed" ~:+-- (Right (ConfigCmd (Just comp, Nothing, Just "/usr/local"), []))+-- ~=? (parseArgs ["--prefix=/usr/local", "--"++name, "configure"])+-- | (name, comp) <- m],+--+-- TestLabel "find the package tool" $ TestList+-- ["configure parsing for prefix comp flag, withcompiler" ~: "failed" ~:+-- (Right (ConfigCmd (Just comp, Just "/foo/comp", Just "/usr/local"), []))+-- ~=? (parseArgs ["--prefix=/usr/local", "--"++name,+-- "--with-compiler=/foo/comp", "configure"])+-- | (name, comp) <- m],+--+-- TestLabel "simpler commands" $ TestList+-- [flag ~: "failed" ~: (Right (flagCmd, [])) ~=? (parseArgs [flag])+-- | (flag, flagCmd) <- [("build", BuildCmd),+-- ("install", InstallCmd Nothing False),+-- ("sdist", SDistCmd),+-- ("register", RegisterCmd False)]+-- ]+-- ]++{- Testing ideas:+ * IO to look for hugs and hugs-pkg (which hugs, etc)+ * quickCheck to test permutations of arguments+ * what other options can we over-ride with a command-line flag?+-}
+ src/Distribution/Simple/ShowBuildInfo.hs view
@@ -0,0 +1,162 @@+-- |+-- This module defines a simple JSON-based format for exporting basic+-- information about a Cabal package and the compiler configuration Cabal+-- would use to build it. This can be produced with the+-- @cabal new-show-build-info@ command.+--+--+-- This format is intended for consumption by external tooling and should+-- therefore be rather stable. Moreover, this allows tooling users to avoid+-- linking against Cabal. This is an important advantage as direct API usage+-- tends to be rather fragile in the presence of user-initiated upgrades of+-- Cabal.+--+-- Below is an example of the output this module produces,+--+-- @+-- { "cabal-version": "1.23.0.0",+-- "compiler": {+-- "flavour": "GHC",+-- "compiler-id": "ghc-7.10.2",+-- "path": "/usr/bin/ghc",+-- },+-- "components": [+-- { "type": "lib",+-- "name": "lib:Cabal",+-- "compiler-args":+-- ["-O", "-XHaskell98", "-Wall",+-- "-package-id", "parallel-3.2.0.6-b79c38c5c25fff77f3ea7271851879eb"]+-- "modules": ["Project.ModA", "Project.ModB", "Paths_project"],+-- "src-files": [],+-- "src-dirs": ["src"]+-- }+-- ]+-- }+-- @+--+-- The @cabal-version@ property provides the version of the Cabal library+-- which generated the output. The @compiler@ property gives some basic+-- information about the compiler Cabal would use to compile the package.+--+-- The @components@ property gives a list of the Cabal 'Component's defined by+-- the package. Each has,+--+-- * @type@: the type of the component (one of @lib@, @exe@,+-- @test@, @bench@, or @flib@)+-- * @name@: a string serving to uniquely identify the component within the+-- package.+-- * @compiler-args@: the command-line arguments Cabal would pass to the+-- compiler to compile the component+-- * @modules@: the modules belonging to the component+-- * @src-dirs@: a list of directories where the modules might be found+-- * @src-files@: any other Haskell sources needed by the component+--+-- Note: At the moment this is only supported when using the GHC compiler.+--++module Distribution.Simple.ShowBuildInfo (mkBuildInfo) where++import Distribution.Compat.Prelude+import Prelude ()++import qualified Distribution.Simple.GHC as GHC+import qualified Distribution.Simple.Program.GHC as GHC++import Distribution.PackageDescription+import Distribution.Compiler+import Distribution.Verbosity+import Distribution.Simple.Compiler+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.Program+import Distribution.Simple.Setup+import Distribution.Simple.Utils (cabalVersion)+import Distribution.Simple.Utils.Json+import Distribution.Types.TargetInfo+import Distribution.Text+import Distribution.Pretty+import Distribution.Utils.Path++-- | Construct a JSON document describing the build information for a+-- package.+mkBuildInfo+ :: PackageDescription -- ^ Mostly information from the .cabal file+ -> LocalBuildInfo -- ^ Configuration information+ -> BuildFlags -- ^ Flags that the user passed to build+ -> [TargetInfo]+ -> Json+mkBuildInfo pkg_descr lbi _flags targetsToBuild = info+ where+ targetToNameAndLBI target =+ (componentLocalName $ targetCLBI target, targetCLBI target)+ componentsToBuild = map targetToNameAndLBI targetsToBuild+ (.=) :: String -> Json -> (String, Json)+ k .= v = (k, v)++ info = JsonObject+ [ "cabal-version" .= JsonString (display cabalVersion)+ , "compiler" .= mkCompilerInfo+ , "components" .= JsonArray (map mkComponentInfo componentsToBuild)+ ]++ mkCompilerInfo = JsonObject+ [ "flavour" .= JsonString (prettyShow $ compilerFlavor $ compiler lbi)+ , "compiler-id" .= JsonString (showCompilerId $ compiler lbi)+ , "path" .= path+ ]+ where+ path = maybe JsonNull (JsonString . programPath)+ $ (flavorToProgram . compilerFlavor $ compiler lbi)+ >>= flip lookupProgram (withPrograms lbi)++ flavorToProgram :: CompilerFlavor -> Maybe Program+ flavorToProgram GHC = Just ghcProgram+ flavorToProgram GHCJS = Just ghcjsProgram+ flavorToProgram UHC = Just uhcProgram+ flavorToProgram JHC = Just jhcProgram+ flavorToProgram _ = Nothing++ mkComponentInfo (name, clbi) = JsonObject+ [ "type" .= JsonString compType+ , "name" .= JsonString (prettyShow name)+ , "unit-id" .= JsonString (prettyShow $ componentUnitId clbi)+ , "compiler-args" .= JsonArray (map JsonString $ getCompilerArgs bi lbi clbi)+ , "modules" .= JsonArray (map (JsonString . display) modules)+ , "src-files" .= JsonArray (map JsonString sourceFiles)+ , "src-dirs" .= JsonArray (map JsonString $ map getSymbolicPath $ hsSourceDirs bi)+ ]+ where+ bi = componentBuildInfo comp+ comp = fromMaybe (error $ "mkBuildInfo: no component " ++ prettyShow name) $ lookupComponent pkg_descr name+ compType = case comp of+ CLib _ -> "lib"+ CExe _ -> "exe"+ CTest _ -> "test"+ CBench _ -> "bench"+ CFLib _ -> "flib"+ modules = case comp of+ CLib lib -> explicitLibModules lib+ CExe exe -> exeModules exe+ _ -> []+ sourceFiles = case comp of+ CLib _ -> []+ CExe exe -> [modulePath exe]+ _ -> []++-- | Get the command-line arguments that would be passed+-- to the compiler to build the given component.+getCompilerArgs+ :: BuildInfo+ -> LocalBuildInfo+ -> ComponentLocalBuildInfo+ -> [String]+getCompilerArgs bi lbi clbi =+ case compilerFlavor $ compiler lbi of+ GHC -> ghc+ GHCJS -> ghc+ c -> error $ "ShowBuildInfo.getCompilerArgs: Don't know how to get "+++ "build arguments for compiler "++show c+ where+ -- This is absolutely awful+ ghc = GHC.renderGhcOptions (compiler lbi) (hostPlatform lbi) baseOpts+ where+ baseOpts = GHC.componentGhcOptions normal lbi bi clbi (buildDir lbi)
+ src/Distribution/Simple/SrcDist.hs view
@@ -0,0 +1,520 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.SrcDist+-- Copyright : Simon Marlow 2004+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This handles the @sdist@ command. The module exports an 'sdist' action but+-- also some of the phases that make it up so that other tools can use just the+-- bits they need. In particular the preparation of the tree of files to go+-- into the source tarball is separated from actually building the source+-- tarball.+--+-- The 'createArchive' action uses the external @tar@ program and assumes that+-- it accepts the @-z@ flag. Neither of these assumptions are valid on Windows.+-- The 'sdist' action now also does some distribution QA checks.++-- NOTE: FIX: we don't have a great way of testing this module, since+-- we can't easily look inside a tarball once its created.++module Distribution.Simple.SrcDist (+ -- * The top level action+ sdist,++ -- ** Parts of 'sdist'+ printPackageProblems,+ prepareTree,+ createArchive,++ -- ** Snapshots+ prepareSnapshotTree,+ snapshotPackage,+ snapshotVersion,+ dateToSnapshotNumber,++ -- * Extracting the source files+ listPackageSources,+ listPackageSourcesWithDie,++ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.PackageDescription+import Distribution.PackageDescription.Check hiding (doesFileExist)+import Distribution.Package+import Distribution.ModuleName+import qualified Distribution.ModuleName as ModuleName+import Distribution.Version+import Distribution.Simple.Configure (findDistPrefOrDefault)+import Distribution.Simple.Glob (matchDirFileGlobWithDie)+import Distribution.Simple.Utils+import Distribution.Simple.Setup+import Distribution.Simple.PreProcess+import Distribution.Simple.BuildPaths+import Distribution.Simple.Program+import Distribution.Pretty+import Distribution.Verbosity+import Distribution.Utils.Path++import qualified Data.Map as Map+import Data.Time (UTCTime, getCurrentTime, toGregorian, utctDay)+import System.Directory ( doesFileExist )+import System.IO (IOMode(WriteMode), hPutStrLn, withFile)+import System.FilePath ((</>), (<.>), dropExtension, isRelative)++-- |Create a source distribution.+sdist :: PackageDescription -- ^ information from the tarball+ -> SDistFlags -- ^ verbosity & snapshot+ -> (FilePath -> FilePath) -- ^ build prefix (temp dir)+ -> [PPSuffixHandler] -- ^ extra preprocessors (includes suffixes)+ -> IO ()+sdist pkg flags mkTmpDir pps = do++ distPref <- findDistPrefOrDefault $ sDistDistPref flags+ let targetPref = distPref+ tmpTargetDir = mkTmpDir distPref++ -- When given --list-sources, just output the list of sources to a file.+ case sDistListSources flags of+ Flag path -> withFile path WriteMode $ \outHandle -> do+ ordinary <- listPackageSources verbosity "." pkg pps+ traverse_ (hPutStrLn outHandle) ordinary+ notice verbosity $ "List of package sources written to file '" ++ path ++ "'"++ NoFlag -> do+ -- do some QA+ printPackageProblems verbosity pkg++ date <- getCurrentTime+ let pkg' | snapshot = snapshotPackage date pkg+ | otherwise = pkg++ case flagToMaybe (sDistDirectory flags) of+ Just targetDir -> do+ generateSourceDir targetDir pkg'+ info verbosity $ "Source directory created: " ++ targetDir++ Nothing -> do+ createDirectoryIfMissingVerbose verbosity True tmpTargetDir+ withTempDirectory verbosity tmpTargetDir "sdist." $ \tmpDir -> do+ let targetDir = tmpDir </> tarBallName pkg'+ generateSourceDir targetDir pkg'+ targzFile <- createArchive verbosity pkg' tmpDir targetPref+ notice verbosity $ "Source tarball created: " ++ targzFile++ where+ generateSourceDir :: FilePath -> PackageDescription -> IO ()+ generateSourceDir targetDir pkg' = do+ setupMessage verbosity "Building source dist for" (packageId pkg')+ prepareTree verbosity pkg' targetDir pps+ when snapshot $+ overwriteSnapshotPackageDesc verbosity pkg' targetDir++ verbosity = fromFlag (sDistVerbosity flags)+ snapshot = fromFlag (sDistSnapshot flags)++-- | List all source files of a package.+--+-- Since @Cabal-3.4@ returns a single list. There shouldn't be any+-- executable files, they are hardly portable.+-- +listPackageSources+ :: Verbosity -- ^ verbosity+ -> FilePath -- ^ directory with cabal file+ -> PackageDescription -- ^ info from the cabal file+ -> [PPSuffixHandler] -- ^ extra preprocessors (include suffixes)+ -> IO [FilePath] -- ^ relative paths+listPackageSources verbosity cwd pkg_descr0 pps = do+ -- Call helpers that actually do all work.+ listPackageSources' verbosity die' cwd pkg_descr pps+ where+ pkg_descr = filterAutogenModules pkg_descr0++-- | A variant of 'listPackageSources' with configurable 'die'.+--+-- /Note:/ may still 'die' directly. For example on missing include file.+--+-- Since @3.4.0.0+listPackageSourcesWithDie+ :: Verbosity -- ^ verbosity+ -> (Verbosity -> String -> IO [FilePath]) -- ^ 'die'' alternative+ -> FilePath -- ^ directory with cabal file+ -> PackageDescription -- ^ info from the cabal file+ -> [PPSuffixHandler] -- ^ extra preprocessors (include suffixes)+ -> IO [FilePath] -- ^ relative paths+listPackageSourcesWithDie verbosity rip cwd pkg_descr0 pps = do+ -- Call helpers that actually do all work.+ listPackageSources' verbosity rip cwd pkg_descr pps+ where+ pkg_descr = filterAutogenModules pkg_descr0+++listPackageSources'+ :: Verbosity+ -> (Verbosity -> String -> IO [FilePath])+ -> FilePath+ -> PackageDescription+ -> [PPSuffixHandler]+ -> IO [FilePath]+listPackageSources' verbosity rip cwd pkg_descr pps =+ fmap concat . sequenceA $+ [+ -- Library sources.+ fmap concat+ . withAllLib $ \Library {+ exposedModules = modules,+ signatures = sigs,+ libBuildInfo = libBi+ } ->+ allSourcesBuildInfo verbosity rip cwd libBi pps (modules ++ sigs)++ -- Executables sources.+ , fmap concat+ . withAllExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do+ biSrcs <- allSourcesBuildInfo verbosity rip cwd exeBi pps []+ mainSrc <- findMainExeFile verbosity cwd exeBi pps mainPath+ return (mainSrc:biSrcs)++ -- Foreign library sources+ , fmap concat+ . withAllFLib $ \flib@(ForeignLib { foreignLibBuildInfo = flibBi }) -> do+ biSrcs <- allSourcesBuildInfo verbosity rip cwd flibBi pps []+ defFiles <- traverse (findModDefFile verbosity cwd flibBi pps)+ (foreignLibModDefFile flib)+ return (defFiles ++ biSrcs)++ -- Test suites sources.+ , fmap concat+ . withAllTest $ \t -> do+ let bi = testBuildInfo t+ case testInterface t of+ TestSuiteExeV10 _ mainPath -> do+ biSrcs <- allSourcesBuildInfo verbosity rip cwd bi pps []+ srcMainFile <- findMainExeFile verbosity cwd bi pps mainPath+ return (srcMainFile:biSrcs)+ TestSuiteLibV09 _ m ->+ allSourcesBuildInfo verbosity rip cwd bi pps [m]+ TestSuiteUnsupported tp ->+ rip verbosity $ "Unsupported test suite type: " ++ show tp++ -- Benchmarks sources.+ , fmap concat+ . withAllBenchmark $ \bm -> do+ let bi = benchmarkBuildInfo bm+ case benchmarkInterface bm of+ BenchmarkExeV10 _ mainPath -> do+ biSrcs <- allSourcesBuildInfo verbosity rip cwd bi pps []+ srcMainFile <- findMainExeFile verbosity cwd bi pps mainPath+ return (srcMainFile:biSrcs)+ BenchmarkUnsupported tp ->+ rip verbosity $ "Unsupported benchmark type: " ++ show tp++ -- Data files.+ , fmap concat+ . for (dataFiles pkg_descr) $ \filename -> do+ let srcDataDirRaw = dataDir pkg_descr+ srcDataDir | null srcDataDirRaw = "."+ | otherwise = srcDataDirRaw+ matchDirFileGlobWithDie verbosity rip (specVersion pkg_descr) cwd (srcDataDir </> filename)++ -- Extra source files.+ , fmap concat . for (extraSrcFiles pkg_descr) $ \fpath ->+ matchDirFileGlobWithDie verbosity rip (specVersion pkg_descr) cwd fpath++ -- Extra doc files.+ , fmap concat+ . for (extraDocFiles pkg_descr) $ \ filename ->+ matchDirFileGlobWithDie verbosity rip (specVersion pkg_descr) cwd filename++ -- License file(s).+ , return (map getSymbolicPath $ licenseFiles pkg_descr)++ -- Install-include files, without autogen-include files+ , fmap concat+ . withAllLib $ \ l -> do+ let lbi = libBuildInfo l+ incls = filter (`notElem` autogenIncludes lbi) (installIncludes lbi)+ relincdirs = "." : filter isRelative (includeDirs lbi)+ traverse (fmap snd . findIncludeFile verbosity cwd relincdirs) incls++ -- Setup script, if it exists.+ , fmap (maybe [] (\f -> [f])) $ findSetupFile cwd++ -- The .cabal file itself.+ , fmap (\d -> [d]) (tryFindPackageDescCwd verbosity cwd ".")++ ]+ where+ -- We have to deal with all libs and executables, so we have local+ -- versions of these functions that ignore the 'buildable' attribute:+ withAllLib action = traverse action (allLibraries pkg_descr)+ withAllFLib action = traverse action (foreignLibs pkg_descr)+ withAllExe action = traverse action (executables pkg_descr)+ withAllTest action = traverse action (testSuites pkg_descr)+ withAllBenchmark action = traverse action (benchmarks pkg_descr)+++-- |Prepare a directory tree of source files.+prepareTree :: Verbosity -- ^verbosity+ -> PackageDescription -- ^info from the cabal file+ -> FilePath -- ^source tree to populate+ -> [PPSuffixHandler] -- ^extra preprocessors (includes suffixes)+ -> IO ()+prepareTree verbosity pkg_descr0 targetDir pps = do+ ordinary <- listPackageSources verbosity "." pkg_descr pps+ installOrdinaryFiles verbosity targetDir (zip (repeat []) ordinary)+ maybeCreateDefaultSetupScript targetDir+ where+ pkg_descr = filterAutogenModules pkg_descr0++-- | Find the setup script file, if it exists.+findSetupFile :: FilePath -> IO (Maybe FilePath)+findSetupFile targetDir = do+ hsExists <- doesFileExist (targetDir </> setupHs)+ lhsExists <- doesFileExist (targetDir </> setupLhs)+ if hsExists+ then return (Just setupHs)+ else if lhsExists+ then return (Just setupLhs)+ else return Nothing+ where+ setupHs = "Setup.hs"+ setupLhs = "Setup.lhs"++-- | Create a default setup script in the target directory, if it doesn't exist.+maybeCreateDefaultSetupScript :: FilePath -> IO ()+maybeCreateDefaultSetupScript targetDir = do+ mSetupFile <- findSetupFile targetDir+ case mSetupFile of+ Just _setupFile -> return ()+ Nothing -> do+ writeUTF8File (targetDir </> "Setup.hs") $ unlines [+ "import Distribution.Simple",+ "main = defaultMain"]++-- | Find the main executable file.+findMainExeFile+ :: Verbosity+ -> FilePath -- ^ cwd+ -> BuildInfo+ -> [PPSuffixHandler]+ -> FilePath -- ^ main-is+ -> IO FilePath+findMainExeFile verbosity cwd exeBi pps mainPath = do+ ppFile <- findFileCwdWithExtension cwd (ppSuffixes pps) (map getSymbolicPath (hsSourceDirs exeBi))+ (dropExtension mainPath)+ case ppFile of+ Nothing -> findFileCwd verbosity cwd (map getSymbolicPath (hsSourceDirs exeBi)) mainPath+ Just pp -> return pp++-- | Find a module definition file+--+-- TODO: I don't know if this is right+findModDefFile+ :: Verbosity -> FilePath -> BuildInfo -> [PPSuffixHandler] -> FilePath -> IO FilePath+findModDefFile verbosity cwd flibBi _pps modDefPath =+ findFileCwd verbosity cwd ("." : map getSymbolicPath (hsSourceDirs flibBi)) modDefPath++-- | Given a list of include paths, try to find the include file named+-- @f@. Return the name of the file and the full path, or exit with error if+-- there's no such file.+findIncludeFile :: Verbosity -> FilePath -> [FilePath] -> String -> IO (String, FilePath)+findIncludeFile verbosity _ [] f = die' verbosity ("can't find include file " ++ f)+findIncludeFile verbosity cwd (d:ds) f = do+ let path = (d </> f)+ b <- doesFileExist (cwd </> path)+ if b then return (f,path) else findIncludeFile verbosity cwd ds f++-- | Remove the auto-generated modules (like 'Paths_*') from 'exposed-modules' +-- and 'other-modules'.+filterAutogenModules :: PackageDescription -> PackageDescription+filterAutogenModules pkg_descr0 = mapLib filterAutogenModuleLib $+ mapAllBuildInfo filterAutogenModuleBI pkg_descr0+ where+ mapLib f pkg = pkg { library = fmap f (library pkg)+ , subLibraries = map f (subLibraries pkg) }+ filterAutogenModuleLib lib = lib {+ exposedModules = filter (filterFunction (libBuildInfo lib)) (exposedModules lib)+ }+ filterAutogenModuleBI bi = bi {+ otherModules = filter (filterFunction bi) (otherModules bi)+ }+ pathsModule = autogenPathsModuleName pkg_descr0+ filterFunction bi = \mn ->+ mn /= pathsModule+ && not (mn `elem` autogenModules bi)++-- | Prepare a directory tree of source files for a snapshot version.+-- It is expected that the appropriate snapshot version has already been set+-- in the package description, eg using 'snapshotPackage' or 'snapshotVersion'.+--+prepareSnapshotTree+ :: Verbosity -- ^verbosity+ -> PackageDescription -- ^info from the cabal file+ -> FilePath -- ^source tree to populate+ -> [PPSuffixHandler] -- ^extra preprocessors (includes suffixes)+ -> IO ()+prepareSnapshotTree verbosity pkg targetDir pps = do+ prepareTree verbosity pkg targetDir pps+ overwriteSnapshotPackageDesc verbosity pkg targetDir++overwriteSnapshotPackageDesc :: Verbosity -- ^verbosity+ -> PackageDescription -- ^info from the cabal file+ -> FilePath -- ^source tree+ -> IO ()+overwriteSnapshotPackageDesc verbosity pkg targetDir = do+ -- We could just writePackageDescription targetDescFile pkg_descr,+ -- but that would lose comments and formatting.+ descFile <- defaultPackageDesc verbosity+ withUTF8FileContents descFile $+ writeUTF8File (targetDir </> descFile)+ . unlines . map (replaceVersion (packageVersion pkg)) . lines++ where+ replaceVersion :: Version -> String -> String+ replaceVersion version line+ | "version:" `isPrefixOf` map toLower line+ = "version: " ++ prettyShow version+ | otherwise = line++-- | Modifies a 'PackageDescription' by appending a snapshot number+-- corresponding to the given date.+--+snapshotPackage :: UTCTime -> PackageDescription -> PackageDescription+snapshotPackage date pkg =+ pkg {+ package = pkgid { pkgVersion = snapshotVersion date (pkgVersion pkgid) }+ }+ where pkgid = packageId pkg++-- | Modifies a 'Version' by appending a snapshot number corresponding+-- to the given date.+--+snapshotVersion :: UTCTime -> Version -> Version+snapshotVersion date = alterVersion (++ [dateToSnapshotNumber date])++-- | Given a date produce a corresponding integer representation.+-- For example given a date @18/03/2008@ produce the number @20080318@.+--+dateToSnapshotNumber :: UTCTime -> Int+dateToSnapshotNumber date = case toGregorian (utctDay date) of+ (year, month, day) ->+ fromIntegral year * 10000+ + month * 100+ + day++-- | Create an archive from a tree of source files, and clean up the tree.+createArchive+ :: Verbosity -- ^ verbosity+ -> PackageDescription -- ^ info from cabal file+ -> FilePath -- ^ source tree to archive+ -> FilePath -- ^ name of archive to create+ -> IO FilePath+createArchive verbosity pkg_descr tmpDir targetPref = do+ let tarBallFilePath = targetPref </> tarBallName pkg_descr <.> "tar.gz"+ (tarProg, _) <- requireProgram verbosity tarProgram defaultProgramDb+ let formatOptSupported = maybe False (== "YES") $+ Map.lookup "Supports --format"+ (programProperties tarProg)+ runProgram verbosity tarProg $+ -- Hmm: I could well be skating on thinner ice here by using the -C option+ -- (=> seems to be supported at least by GNU and *BSD tar) [The+ -- prev. solution used pipes and sub-command sequences to set up the paths+ -- correctly, which is problematic in a Windows setting.]+ ["-czf", tarBallFilePath, "-C", tmpDir]+ ++ (if formatOptSupported then ["--format", "ustar"] else [])+ ++ [tarBallName pkg_descr]+ return tarBallFilePath++-- | Given a buildinfo, return the names of all source files.+allSourcesBuildInfo+ :: Verbosity+ -> (Verbosity -> String -> IO [FilePath])+ -> FilePath -- ^ cwd -- change me to 'BuildPath Absolute PackageDir'+ -> BuildInfo+ -> [PPSuffixHandler] -- ^ Extra preprocessors+ -> [ModuleName] -- ^ Exposed modules+ -> IO [FilePath]+allSourcesBuildInfo verbosity rip cwd bi pps modules = do+ let searchDirs = map getSymbolicPath (hsSourceDirs bi)+ sources <- fmap concat $ sequenceA $+ [ let file = ModuleName.toFilePath module_+ -- NB: *Not* findFileWithExtension, because the same source+ -- file may show up in multiple paths due to a conditional;+ -- we need to package all of them. See #367.+ in findAllFilesCwdWithExtension cwd suffixes searchDirs file+ >>= nonEmpty' (notFound module_) return+ | module_ <- modules ++ otherModules bi ]+ bootFiles <- sequenceA+ [ let file = ModuleName.toFilePath module_+ fileExts = ["hs-boot", "lhs-boot"]+ in findFileCwdWithExtension cwd fileExts (map getSymbolicPath (hsSourceDirs bi)) file+ | module_ <- modules ++ otherModules bi ]++ return $ sources ++ catMaybes bootFiles ++ cSources bi ++ cxxSources bi +++ cmmSources bi ++ asmSources bi ++ jsSources bi++ where+ nonEmpty' :: b -> ([a] -> b) -> [a] -> b+ nonEmpty' x _ [] = x+ nonEmpty' _ f xs = f xs++ suffixes = ppSuffixes pps ++ ["hs", "lhs", "hsig", "lhsig"]++ notFound :: ModuleName -> IO [FilePath]+ notFound m = rip verbosity $ "Error: Could not find module: " ++ prettyShow m+ ++ " with any suffix: " ++ show suffixes ++ ". If the module "+ ++ "is autogenerated it should be added to 'autogen-modules'."+++-- | Note: must be called with the CWD set to the directory containing+-- the '.cabal' file.+printPackageProblems :: Verbosity -> PackageDescription -> IO ()+printPackageProblems verbosity pkg_descr = do+ ioChecks <- checkPackageFiles verbosity pkg_descr "."+ let pureChecks = checkConfiguredPackage pkg_descr+ isDistError (PackageDistSuspicious _) = False+ isDistError (PackageDistSuspiciousWarn _) = False+ isDistError _ = True+ (errors, warnings) = partition isDistError (pureChecks ++ ioChecks)+ unless (null errors) $+ notice verbosity $ "Distribution quality errors:\n"+ ++ unlines (map explanation errors)+ unless (null warnings) $+ notice verbosity $ "Distribution quality warnings:\n"+ ++ unlines (map explanation warnings)+ unless (null errors) $+ notice verbosity+ "Note: the public hackage server would reject this package."++------------------------------------------------------------++-- | The name of the tarball without extension+--+tarBallName :: PackageDescription -> String+tarBallName = prettyShow . packageId++mapAllBuildInfo :: (BuildInfo -> BuildInfo)+ -> (PackageDescription -> PackageDescription)+mapAllBuildInfo f pkg = pkg {+ library = fmap mapLibBi (library pkg),+ subLibraries = fmap mapLibBi (subLibraries pkg),+ foreignLibs = fmap mapFLibBi (foreignLibs pkg),+ executables = fmap mapExeBi (executables pkg),+ testSuites = fmap mapTestBi (testSuites pkg),+ benchmarks = fmap mapBenchBi (benchmarks pkg)+ }+ where+ mapLibBi lib = lib { libBuildInfo = f (libBuildInfo lib) }+ mapFLibBi flib = flib { foreignLibBuildInfo = f (foreignLibBuildInfo flib) }+ mapExeBi exe = exe { buildInfo = f (buildInfo exe) }+ mapTestBi tst = tst { testBuildInfo = f (testBuildInfo tst) }+ mapBenchBi bm = bm { benchmarkBuildInfo = f (benchmarkBuildInfo bm) }
+ src/Distribution/Simple/Test.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Test+-- Copyright : Thomas Tuegel 2010+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This is the entry point into testing a built package. It performs the+-- \"@.\/setup test@\" action. It runs test suites designated in the package+-- description and reports on the results.++module Distribution.Simple.Test+ ( test+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.UnqualComponentName+import qualified Distribution.PackageDescription as PD+import Distribution.Simple.Compiler+import Distribution.Simple.Hpc+import Distribution.Simple.InstallDirs+import qualified Distribution.Simple.LocalBuildInfo as LBI+import qualified Distribution.Types.LocalBuildInfo as LBI+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+import Distribution.TestSuite+import Distribution.Pretty++import System.Directory+ ( createDirectoryIfMissing, doesFileExist, getDirectoryContents+ , removeFile )+import System.FilePath ( (</>) )++-- |Perform the \"@.\/setup test@\" action.+test :: Args -- ^positional command-line arguments+ -> PD.PackageDescription -- ^information from the .cabal file+ -> LBI.LocalBuildInfo -- ^information from the configure step+ -> TestFlags -- ^flags sent to test+ -> IO ()+test args pkg_descr lbi flags = do+ let verbosity = fromFlag $ testVerbosity flags+ machineTemplate = fromFlag $ testMachineLog flags+ distPref = fromFlag $ testDistPref flags+ testLogDir = distPref </> "test"+ testNames = args+ pkgTests = PD.testSuites pkg_descr+ enabledTests = LBI.enabledTestLBIs pkg_descr lbi++ doTest :: ((PD.TestSuite, LBI.ComponentLocalBuildInfo),+ Maybe TestSuiteLog) -> IO TestSuiteLog+ doTest ((suite, clbi), _) =+ case PD.testInterface suite of+ PD.TestSuiteExeV10 _ _ ->+ ExeV10.runTest pkg_descr lbi clbi flags suite++ PD.TestSuiteLibV09 _ _ ->+ LibV09.runTest pkg_descr lbi clbi flags suite++ _ -> return TestSuiteLog+ { testSuiteName = PD.testName suite+ , testLogs = TestLog+ { testName = unUnqualComponentName $ PD.testName suite+ , testOptionsReturned = []+ , testResult =+ Error $ "No support for running test suite type: "+ ++ show (pretty $ PD.testType suite)+ }+ , logFile = ""+ }++ unless (PD.hasTests pkg_descr) $ do+ notice verbosity "Package has no test suites."+ exitSuccess++ when (PD.hasTests pkg_descr && null enabledTests) $+ die' verbosity $+ "No test suites enabled. Did you remember to configure with "+ ++ "\'--enable-tests\'?"++ testsToRun <- case testNames of+ [] -> return $ zip enabledTests $ repeat Nothing+ names -> for names $ \tName ->+ let testMap = zip enabledNames enabledTests+ enabledNames = map (PD.testName . fst) enabledTests+ allNames = map PD.testName pkgTests+ tCompName = mkUnqualComponentName tName+ in case lookup tCompName testMap of+ Just t -> return (t, Nothing)+ _ | tCompName `elem` allNames ->+ die' verbosity $ "Package configured with test suite "+ ++ tName ++ " disabled."+ | otherwise -> die' verbosity $ "no such test: " ++ tName++ createDirectoryIfMissing True testLogDir++ -- Delete ordinary files from test log directory.+ getDirectoryContents testLogDir+ >>= filterM doesFileExist . map (testLogDir </>)+ >>= traverse_ removeFile++ let totalSuites = length testsToRun+ notice verbosity $ "Running " ++ show totalSuites ++ " test suites..."+ suites <- traverse doTest testsToRun+ let packageLog = (localPackageLog pkg_descr lbi) { testSuites = suites }+ packageLogFile = (</>) testLogDir+ $ packageLogPath machineTemplate pkg_descr lbi+ allOk <- summarizePackage verbosity packageLog+ writeFile packageLogFile $ show packageLog++ when (LBI.testCoverage lbi) $+ markupPackage verbosity lbi distPref pkg_descr $+ map (fst . fst) testsToRun++ unless allOk exitFailure++packageLogPath :: PathTemplate+ -> PD.PackageDescription+ -> LBI.LocalBuildInfo+ -> FilePath+packageLogPath template pkg_descr lbi =+ fromPathTemplate $ substPathTemplate env template+ where+ env = initialPathTemplateEnv+ (PD.package pkg_descr) (LBI.localUnitId lbi)+ (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)
+ src/Distribution/Simple/Test/ExeV10.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++module Distribution.Simple.Test.ExeV10+ ( runTest+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.UnqualComponentName+import Distribution.Compat.CreatePipe+import Distribution.Compat.Environment+import qualified Distribution.PackageDescription as PD+import Distribution.Simple.Build.PathsModule+import Distribution.Simple.BuildPaths+import Distribution.Simple.Compiler+import Distribution.Simple.Hpc+import Distribution.Simple.InstallDirs+import qualified Distribution.Simple.LocalBuildInfo as LBI+import qualified Distribution.Types.LocalBuildInfo as LBI+import Distribution.Simple.Setup+import Distribution.Simple.Test.Log+import Distribution.Simple.Utils+import Distribution.System+import Distribution.TestSuite+import Distribution.Pretty+import Distribution.Verbosity++import System.Directory+ ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist+ , getCurrentDirectory, removeDirectoryRecursive )+import System.FilePath ( (</>), (<.>) )+import System.IO ( stdout, stderr )++import qualified Data.ByteString.Lazy as LBS++runTest :: PD.PackageDescription+ -> LBI.LocalBuildInfo+ -> LBI.ComponentLocalBuildInfo+ -> TestFlags+ -> PD.TestSuite+ -> IO TestSuiteLog+runTest pkg_descr lbi clbi flags suite = do+ let isCoverageEnabled = LBI.testCoverage lbi+ way = guessWay lbi+ tixDir_ = tixDir distPref way testName'++ pwd <- getCurrentDirectory+ existingEnv <- getEnvironment++ let cmd = LBI.buildDir lbi </> testName'+ </> testName' <.> exeExtension (LBI.hostPlatform lbi)+ -- Check that the test executable exists.+ exists <- doesFileExist cmd+ unless exists $ die' verbosity $ "Error: Could not find test program \"" ++ cmd+ ++ "\". Did you build the package first?"++ -- Remove old .tix files if appropriate.+ unless (fromFlag $ testKeepTix flags) $ do+ exists' <- doesDirectoryExist tixDir_+ when exists' $ removeDirectoryRecursive tixDir_++ -- Create directory for HPC files.+ createDirectoryIfMissing True tixDir_++ -- Write summary notices indicating start of test suite+ notice verbosity $ summarizeSuiteStart $ testName'+++ -- Run the test executable+ let opts = map (testOption pkg_descr lbi suite)+ (testOptions flags)+ dataDirPath = pwd </> PD.dataDir pkg_descr+ tixFile = pwd </> tixFilePath distPref way (testName')+ pkgPathEnv = (pkgPathEnvVar pkg_descr "datadir", dataDirPath)+ : existingEnv+ shellEnv = [("HPCTIXFILE", tixFile) | isCoverageEnabled] ++ pkgPathEnv++ -- Add (DY)LD_LIBRARY_PATH if needed+ shellEnv' <- if LBI.withDynExe lbi+ then do let (Platform _ os) = LBI.hostPlatform lbi+ paths <- LBI.depLibraryPaths True False lbi clbi+ return (addLibraryPath os paths shellEnv)+ else return shellEnv++ -- Output logger+ (wOut, wErr, getLogText) <- case details of+ Direct -> return (stdout, stderr, return LBS.empty)+ _ -> do+ (rOut, wOut) <- createPipe++ return $ (,,) wOut wOut $ do+ -- Read test executables' output+ logText <- LBS.hGetContents rOut++ -- '--show-details=streaming': print the log output in another thread+ when (details == Streaming) $ LBS.putStr logText++ -- drain the output.+ evaluate (force logText)++ (exit, logText) <- case testWrapper flags of+ Flag path -> rawSystemIOWithEnvAndAction+ verbosity path (cmd:opts) Nothing (Just shellEnv')+ getLogText+ -- these handles are automatically closed+ Nothing (Just wOut) (Just wErr)++ NoFlag -> rawSystemIOWithEnvAndAction+ verbosity cmd opts Nothing (Just shellEnv')+ getLogText+ -- these handles are automatically closed+ Nothing (Just wOut) (Just wErr)++ -- Generate TestSuiteLog from executable exit code and a machine-+ -- readable test log.+ let suiteLog = buildLog exit++ -- Write summary notice to log file indicating start of test suite+ appendFile (logFile suiteLog) $ summarizeSuiteStart $ testName'++ -- Append contents of temporary log file to the final human-+ -- readable log file+ LBS.appendFile (logFile suiteLog) logText++ -- Write end-of-suite summary notice to log file+ appendFile (logFile suiteLog) $ summarizeSuiteFinish suiteLog++ -- 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 == Always ||+ details == Failures && not (suitePassed $ testLogs suiteLog))+ -- verbosity overrides show-details+ && verbosity >= normal+ whenPrinting $ do+ LBS.putStr logText+ putChar '\n'++ -- Write summary notice to terminal indicating end of test suite+ notice verbosity $ summarizeSuiteFinish suiteLog++ when isCoverageEnabled $+ case PD.library pkg_descr of+ Nothing ->+ die' verbosity $ "Error: test coverage is only supported for packages with a library component"++ Just library ->+ markupTest verbosity lbi distPref (prettyShow $ PD.package pkg_descr) suite library++ return suiteLog+ where+ testName' = unUnqualComponentName $ PD.testName suite++ distPref = fromFlag $ testDistPref flags+ verbosity = fromFlag $ testVerbosity flags+ details = fromFlag $ testShowDetails flags+ testLogDir = distPref </> "test"++ buildLog exit =+ let r = case exit of+ ExitSuccess -> Pass+ ExitFailure c -> Fail $ "exit code: " ++ show c+ --n = unUnqualComponentName $ PD.testName suite+ l = TestLog+ { testName = testName'+ , testOptionsReturned = []+ , testResult = r+ }+ in TestSuiteLog+ { testSuiteName = PD.testName suite+ , testLogs = l+ , logFile =+ testLogDir+ </> testSuiteLogPath (fromFlag $ testHumanLog flags)+ pkg_descr lbi testName' l+ }++-- TODO: This is abusing the notion of a 'PathTemplate'. The result isn't+-- necessarily a path.+testOption :: PD.PackageDescription+ -> LBI.LocalBuildInfo+ -> PD.TestSuite+ -> PathTemplate+ -> String+testOption pkg_descr lbi suite template =+ fromPathTemplate $ substPathTemplate env template+ where+ env = initialPathTemplateEnv+ (PD.package pkg_descr) (LBI.localUnitId lbi)+ (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) +++ [(TestSuiteNameVar, toPathTemplate $ unUnqualComponentName $ PD.testName suite)]
+ src/Distribution/Simple/Test/LibV09.hs view
@@ -0,0 +1,292 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++module Distribution.Simple.Test.LibV09+ ( runTest+ -- Test stub+ , simpleTestStub+ , stubFilePath, stubMain, stubName, stubWriteLog+ , writeSimpleTestStub+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Types.UnqualComponentName++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+import Distribution.Simple.BuildPaths+import Distribution.Simple.Compiler+import Distribution.Simple.Hpc+import Distribution.Simple.InstallDirs+import qualified Distribution.Simple.LocalBuildInfo as LBI+import qualified Distribution.Types.LocalBuildInfo as LBI+import Distribution.Simple.Setup+import Distribution.Simple.Test.Log+import Distribution.Simple.Utils+import Distribution.System+import Distribution.TestSuite+import Distribution.Pretty+import Distribution.Verbosity++import qualified Control.Exception as CE+import qualified Data.ByteString.Lazy as LBS+import System.Directory+ ( createDirectoryIfMissing, canonicalizePath+ , doesDirectoryExist, doesFileExist+ , getCurrentDirectory, removeDirectoryRecursive, removeFile+ , setCurrentDirectory )+import System.FilePath ( (</>), (<.>) )+import System.IO ( hClose, hPutStr )+import System.Process (StdStream(..), waitForProcess)++runTest :: PD.PackageDescription+ -> LBI.LocalBuildInfo+ -> LBI.ComponentLocalBuildInfo+ -> TestFlags+ -> PD.TestSuite+ -> IO TestSuiteLog+runTest pkg_descr lbi clbi flags suite = do+ let isCoverageEnabled = LBI.testCoverage lbi+ way = guessWay lbi++ pwd <- getCurrentDirectory+ existingEnv <- getEnvironment++ let cmd = LBI.buildDir lbi </> stubName suite+ </> stubName suite <.> exeExtension (LBI.hostPlatform lbi)+ -- Check that the test executable exists.+ exists <- doesFileExist cmd+ unless exists $+ die' verbosity $ "Error: Could not find test program \"" ++ cmd+ ++ "\". Did you build the package first?"++ -- Remove old .tix files if appropriate.+ unless (fromFlag $ testKeepTix flags) $ do+ let tDir = tixDir distPref way testName'+ exists' <- doesDirectoryExist tDir+ when exists' $ removeDirectoryRecursive tDir++ -- Create directory for HPC files.+ createDirectoryIfMissing True $ tixDir distPref way testName'++ -- Write summary notices indicating start of test suite+ notice verbosity $ summarizeSuiteStart testName'++ suiteLog <- CE.bracket openCabalTemp deleteIfExists $ \tempLog -> do++ -- TODO: this setup is broken,+ -- if the test output is too big, we will deadlock.+ (rOut, wOut) <- createPipe++ -- Run test executable+ (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 testName'+ pkgPathEnv = (pkgPathEnvVar pkg_descr "datadir", dataDirPath)+ : existingEnv+ shellEnv = [("HPCTIXFILE", tixFile) | isCoverageEnabled]+ ++ pkgPathEnv+ -- Add (DY)LD_LIBRARY_PATH if needed+ shellEnv' <-+ if LBI.withDynExe lbi+ then do+ let (Platform _ os) = LBI.hostPlatform lbi+ paths <- LBI.depLibraryPaths True False lbi clbi+ cpath <- canonicalizePath $ LBI.componentBuildDir lbi clbi+ return (addLibraryPath os (cpath : paths) shellEnv)+ else return shellEnv+ case testWrapper flags of+ Flag path -> createProcessWithEnv verbosity path (cmd:opts) Nothing (Just shellEnv')+ -- these handles are closed automatically+ CreatePipe (UseHandle wOut) (UseHandle wOut)++ NoFlag -> 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 <- LBS.hGetContents rOut+ -- Force the IO manager to drain the test output pipe+ _ <- evaluate (force logText)++ exitcode <- waitForProcess process+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ cmd ++ " returned " ++ show exitcode++ -- Generate final log file name+ let finalLogName l = testLogDir+ </> testSuiteLogPath+ (fromFlag $ testHumanLog flags) pkg_descr lbi+ (unUnqualComponentName $ testSuiteName l) (testLogs l)+ -- Generate TestSuiteLog from executable exit code and a machine-+ -- readable test log+ suiteLog <- fmap (\s -> (\l -> l { logFile = finalLogName l })+ . fromMaybe (error $ "panic! read @TestSuiteLog " ++ show s) $ readMaybe s) -- TODO: eradicateNoParse+ $ readFile tempLog++ -- Write summary notice to log file indicating start of test suite+ appendFile (logFile suiteLog) $ summarizeSuiteStart testName'++ LBS.appendFile (logFile suiteLog) logText++ -- Write end-of-suite summary notice to log file+ appendFile (logFile suiteLog) $ summarizeSuiteFinish suiteLog++ -- Show the contents of the human-readable log file on the terminal+ -- if there is a failure and/or detailed output is requested+ let details = fromFlag $ testShowDetails flags+ whenPrinting = when $ (details > Never)+ && (not (suitePassed $ testLogs suiteLog) || details == Always)+ && verbosity >= normal+ whenPrinting $ do+ LBS.putStr logText+ putChar '\n'++ return suiteLog++ -- Write summary notice to terminal indicating end of test suite+ notice verbosity $ summarizeSuiteFinish suiteLog++ when isCoverageEnabled $+ case PD.library pkg_descr of+ Nothing ->+ die' verbosity $ "Error: test coverage is only supported for packages with a library component"++ Just library ->+ markupTest verbosity lbi distPref (prettyShow $ PD.package pkg_descr) suite library++ return suiteLog+ where+ testName' = unUnqualComponentName $ PD.testName suite++ deleteIfExists file = do+ exists <- doesFileExist file+ when exists $ removeFile file++ testLogDir = distPref </> "test"+ openCabalTemp = do+ (f, h) <- openTempFile testLogDir $ "cabal-test-" <.> "log"+ hClose h >> return f++ distPref = fromFlag $ testDistPref flags+ verbosity = fromFlag $ testVerbosity flags++-- TODO: This is abusing the notion of a 'PathTemplate'. The result isn't+-- necessarily a path.+testOption :: PD.PackageDescription+ -> LBI.LocalBuildInfo+ -> PD.TestSuite+ -> PathTemplate+ -> String+testOption pkg_descr lbi suite template =+ fromPathTemplate $ substPathTemplate env template+ where+ env = initialPathTemplateEnv+ (PD.package pkg_descr) (LBI.localUnitId lbi)+ (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) +++ [(TestSuiteNameVar, toPathTemplate $ unUnqualComponentName $ PD.testName suite)]++-- Test stub ----------++-- | The name of the stub executable associated with a library 'TestSuite'.+stubName :: PD.TestSuite -> FilePath+stubName t = unUnqualComponentName (PD.testName t) ++ "Stub"++-- | The filename of the source file for the stub executable associated with a+-- library 'TestSuite'.+stubFilePath :: PD.TestSuite -> FilePath+stubFilePath t = stubName t <.> "hs"++-- | Write the source file for a library 'TestSuite' stub executable.+writeSimpleTestStub :: PD.TestSuite -- ^ library 'TestSuite' for which a stub+ -- is being created+ -> FilePath -- ^ path to directory where stub source+ -- should be located+ -> IO ()+writeSimpleTestStub t dir = do+ createDirectoryIfMissing True dir+ let filename = dir </> stubFilePath t+ m = case PD.testInterface t of+ PD.TestSuiteLibV09 _ m' -> m'+ _ -> error "writeSimpleTestStub: invalid TestSuite passed"+ writeFile filename $ simpleTestStub m++-- | Source code for library test suite stub executable+simpleTestStub :: ModuleName -> String+simpleTestStub m = unlines+ [ "module Main ( main ) where"+ , "import Distribution.Simple.Test.LibV09 ( stubMain )"+ , "import " ++ show (pretty m) ++ " ( tests )"+ , "main :: IO ()"+ , "main = stubMain tests"+ ]++-- | Main function for test stubs. Once, it was written directly into the stub,+-- but minimizing the amount of code actually in the stub maximizes the number+-- of detectable errors when Cabal is compiled.+stubMain :: IO [Test] -> IO ()+stubMain tests = do+ (f, n) <- fmap (\s -> fromMaybe (error $ "panic! read " ++ show s) $ readMaybe s) getContents -- TODO: eradicateNoParse+ dir <- getCurrentDirectory+ results <- (tests >>= stubRunTests) `CE.catch` errHandler+ setCurrentDirectory dir+ stubWriteLog f n results+ where+ errHandler :: CE.SomeException -> IO TestLogs+ errHandler e = case CE.fromException e of+ Just CE.UserInterrupt -> CE.throwIO e+ _ -> return $ TestLog { testName = "Cabal test suite exception",+ testOptionsReturned = [],+ testResult = Error $ show e }++-- | The test runner used in library "TestSuite" stub executables. Runs a list+-- of 'Test's. An executable calling this function is meant to be invoked as+-- the child of a Cabal process during @.\/setup test@. A 'TestSuiteLog',+-- provided by Cabal, is read from the standard input; it supplies the name of+-- the test suite and the location of the machine-readable test suite log file.+-- Human-readable log information is written to the standard output for capture+-- by the calling Cabal process.+stubRunTests :: [Test] -> IO TestLogs+stubRunTests tests = do+ logs <- traverse stubRunTests' tests+ return $ GroupLogs "Default" logs+ where+ stubRunTests' (Test t) = do+ l <- run t >>= finish+ summarizeTest normal Always l+ return l+ where+ finish (Finished result) =+ return TestLog+ { testName = name t+ , testOptionsReturned = defaultOptions t+ , testResult = result+ }+ finish (Progress _ next) = next >>= finish+ stubRunTests' g@(Group {}) = do+ logs <- traverse stubRunTests' $ groupTests g+ return $ GroupLogs (groupName g) logs+ stubRunTests' (ExtraOptions _ t) = stubRunTests' t+ maybeDefaultOption opt =+ maybe Nothing (\d -> Just (optionName opt, d)) $ optionDefault opt+ defaultOptions testInst = mapMaybe maybeDefaultOption $ options testInst++-- | From a test stub, write the 'TestSuiteLog' to temporary file for the calling+-- Cabal process to read.+stubWriteLog :: FilePath -> UnqualComponentName -> TestLogs -> IO ()+stubWriteLog f n logs = do+ let testLog = TestSuiteLog { testSuiteName = n, testLogs = logs, logFile = f }+ writeFile (logFile testLog) $ show testLog+ when (suiteError logs) $ exitWith $ ExitFailure 2+ when (suiteFailed logs) $ exitWith $ ExitFailure 1+ exitSuccess
+ src/Distribution/Simple/Test/Log.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++module Distribution.Simple.Test.Log+ ( PackageLog(..)+ , TestLogs(..)+ , TestSuiteLog(..)+ , countTestResults+ , localPackageLog+ , summarizePackage+ , summarizeSuiteFinish, summarizeSuiteStart+ , summarizeTest+ , suiteError, suiteFailed, suitePassed+ , testSuiteLogPath+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Package+import Distribution.Types.UnqualComponentName+import qualified Distribution.PackageDescription as PD+import Distribution.Simple.Compiler+import Distribution.Simple.InstallDirs+import qualified Distribution.Simple.LocalBuildInfo as LBI+import Distribution.Simple.Setup+import Distribution.Simple.Utils+import Distribution.System+import Distribution.TestSuite+import Distribution.Verbosity+import Distribution.Pretty++import qualified Prelude (foldl1)++-- | Logs all test results for a package, broken down first by test suite and+-- then by test case.+data PackageLog = PackageLog+ { package :: PackageId+ , compiler :: CompilerId+ , platform :: Platform+ , testSuites :: [TestSuiteLog]+ }+ deriving (Read, Show, Eq)++-- | A 'PackageLog' with package and platform information specified.+localPackageLog :: PD.PackageDescription -> LBI.LocalBuildInfo -> PackageLog+localPackageLog pkg_descr lbi = PackageLog+ { package = PD.package pkg_descr+ , compiler = compilerId $ LBI.compiler lbi+ , platform = LBI.hostPlatform lbi+ , testSuites = []+ }++-- | Logs test suite results, itemized by test case.+data TestSuiteLog = TestSuiteLog+ { testSuiteName :: UnqualComponentName+ , testLogs :: TestLogs+ , logFile :: FilePath -- path to human-readable log file+ }+ deriving (Read, Show, Eq)++data TestLogs+ = TestLog+ { testName :: String+ , testOptionsReturned :: Options+ , testResult :: Result+ }+ | GroupLogs String [TestLogs]+ deriving (Read, Show, Eq)++-- | Count the number of pass, fail, and error test results in a 'TestLogs'+-- tree.+countTestResults :: TestLogs+ -> (Int, Int, Int) -- ^ Passes, fails, and errors,+ -- respectively.+countTestResults = go (0, 0, 0)+ where+ go (p, f, e) (TestLog { testResult = r }) =+ case r of+ Pass -> (p + 1, f, e)+ Fail _ -> (p, f + 1, e)+ Error _ -> (p, f, e + 1)+ go (p, f, e) (GroupLogs _ ts) = foldl go (p, f, e) ts++-- | From a 'TestSuiteLog', determine if the test suite passed.+suitePassed :: TestLogs -> Bool+suitePassed l =+ case countTestResults l of+ (_, 0, 0) -> True+ _ -> False++-- | From a 'TestSuiteLog', determine if the test suite failed.+suiteFailed :: TestLogs -> Bool+suiteFailed l =+ case countTestResults l of+ (_, 0, _) -> False+ _ -> True++-- | From a 'TestSuiteLog', determine if the test suite encountered errors.+suiteError :: TestLogs -> Bool+suiteError l =+ case countTestResults l of+ (_, _, 0) -> False+ _ -> True++resultString :: TestLogs -> String+resultString l | suiteError l = "error"+ | suiteFailed l = "fail"+ | otherwise = "pass"++testSuiteLogPath :: PathTemplate+ -> PD.PackageDescription+ -> LBI.LocalBuildInfo+ -> String -- ^ test suite name+ -> TestLogs -- ^ test suite results+ -> FilePath+testSuiteLogPath template pkg_descr lbi test_name result =+ fromPathTemplate $ substPathTemplate env template+ where+ env = initialPathTemplateEnv+ (PD.package pkg_descr) (LBI.localUnitId lbi)+ (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)+ ++ [ (TestSuiteNameVar, toPathTemplate test_name)+ , (TestSuiteResultVar, toPathTemplate $ resultString result)+ ]++-- | Print a summary to the console after all test suites have been run+-- indicating the number of successful test suites and cases. Returns 'True' if+-- all test suites passed and 'False' otherwise.+summarizePackage :: Verbosity -> PackageLog -> IO Bool+summarizePackage verbosity packageLog = do+ let counts = map (countTestResults . testLogs) $ testSuites packageLog+ (passed, failed, errors) = Prelude.foldl1 addTriple counts+ totalCases = passed + failed + errors+ passedSuites = length+ $ filter (suitePassed . testLogs)+ $ testSuites packageLog+ totalSuites = length $ testSuites packageLog+ notice verbosity $ show passedSuites ++ " of " ++ show totalSuites+ ++ " test suites (" ++ show passed ++ " of "+ ++ show totalCases ++ " test cases) passed."+ return $! passedSuites == totalSuites+ where+ addTriple (p1, f1, e1) (p2, f2, e2) = (p1 + p2, f1 + f2, e1 + e2)++-- | Print a summary of a single test case's result to the console, suppressing+-- output for certain verbosity or test filter levels.+summarizeTest :: Verbosity -> TestShowDetails -> TestLogs -> IO ()+summarizeTest _ _ (GroupLogs {}) = return ()+summarizeTest verbosity details t =+ when shouldPrint $ notice verbosity $ "Test case " ++ testName t+ ++ ": " ++ show (testResult t)+ where shouldPrint = (details > Never) && (notPassed || details == Always)+ notPassed = testResult t /= Pass++-- | Print a summary of the test suite's results on the console, suppressing+-- output for certain verbosity or test filter levels.+summarizeSuiteFinish :: TestSuiteLog -> String+summarizeSuiteFinish testLog = unlines+ [ "Test suite " ++ prettyShow (testSuiteName testLog) ++ ": " ++ resStr+ , "Test suite logged to: " ++ logFile testLog+ ]+ where resStr = map toUpper (resultString $ testLogs testLog)++summarizeSuiteStart :: String -> String+summarizeSuiteStart n = "Test suite " ++ n ++ ": RUNNING...\n"
+ src/Distribution/Simple/UHC.hs view
@@ -0,0 +1,296 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.UHC+-- Copyright : Andres Loeh 2009+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module contains most of the UHC-specific code for configuring, building+-- and installing packages.+--+-- Thanks to the authors of the other implementation-specific files, in+-- particular to Isaac Jones, Duncan Coutts and Henning Thielemann, for+-- inspiration on how to design this module.++module Distribution.Simple.UHC (+ configure, getInstalledPackages,+ buildLib, buildExe, installLib, registerPackage, inplacePackageDbPath+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.InstalledPackageInfo+import Distribution.Package hiding (installedUnitId)+import Distribution.PackageDescription+import Distribution.Simple.BuildPaths+import Distribution.Simple.Compiler+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.PackageIndex+import Distribution.Simple.Program+import Distribution.Simple.Utils+import Distribution.Pretty+import Distribution.Parsec+import Distribution.Types.MungedPackageId+import Distribution.Verbosity+import Distribution.Version+import Distribution.System+import Language.Haskell.Extension+import Distribution.Utils.Path++import qualified Data.Map as Map ( empty )+import System.Directory+import System.FilePath++-- -----------------------------------------------------------------------------+-- Configuring++configure :: Verbosity -> Maybe FilePath -> Maybe FilePath+ -> ProgramDb -> IO (Compiler, Maybe Platform, ProgramDb)+configure verbosity hcPath _hcPkgPath progdb = do++ (_uhcProg, uhcVersion, progdb') <-+ requireProgramVersion verbosity uhcProgram+ (orLaterVersion (mkVersion [1,0,2]))+ (userMaybeSpecifyPath "uhc" hcPath progdb)++ let comp = Compiler {+ compilerId = CompilerId UHC uhcVersion,+ compilerAbiTag = NoAbiTag,+ compilerCompat = [],+ compilerLanguages = uhcLanguages,+ compilerExtensions = uhcLanguageExtensions,+ compilerProperties = Map.empty+ }+ compPlatform = Nothing+ return (comp, compPlatform, progdb')++uhcLanguages :: [(Language, CompilerFlag)]+uhcLanguages = [(Haskell98, "")]++-- | The flags for the supported extensions.+uhcLanguageExtensions :: [(Extension, Maybe CompilerFlag)]+uhcLanguageExtensions =+ let doFlag (f, (enable, disable)) = [(EnableExtension f, enable),+ (DisableExtension f, disable)]+ alwaysOn = (Nothing, Nothing{- wrong -})+ in concatMap doFlag+ [(CPP, (Just "--cpp", Nothing{- wrong -})),+ (PolymorphicComponents, alwaysOn),+ (ExistentialQuantification, alwaysOn),+ (ForeignFunctionInterface, alwaysOn),+ (UndecidableInstances, alwaysOn),+ (MultiParamTypeClasses, alwaysOn),+ (Rank2Types, alwaysOn),+ (PatternSignatures, alwaysOn),+ (EmptyDataDecls, alwaysOn),+ (ImplicitPrelude, (Nothing, Just "--no-prelude"{- wrong -})),+ (TypeOperators, alwaysOn),+ (OverlappingInstances, alwaysOn),+ (FlexibleInstances, alwaysOn)]++getInstalledPackages :: Verbosity -> Compiler -> PackageDBStack -> ProgramDb+ -> IO InstalledPackageIndex+getInstalledPackages verbosity comp packagedbs progdb = do+ let compilerid = compilerId comp+ systemPkgDir <- getGlobalPackageDir verbosity progdb+ userPkgDir <- getUserPackageDir+ let pkgDirs = nub (concatMap (packageDbPaths userPkgDir systemPkgDir) packagedbs)+ -- putStrLn $ "pkgdirs: " ++ show pkgDirs+ pkgs <- liftM (map addBuiltinVersions . concat) $+ traverse (\ d -> getDirectoryContents d >>= filterM (isPkgDir (prettyShow compilerid) d))+ pkgDirs+ -- putStrLn $ "pkgs: " ++ show pkgs+ let iPkgs =+ map mkInstalledPackageInfo $+ concatMap parsePackage $+ pkgs+ -- putStrLn $ "installed pkgs: " ++ show iPkgs+ return (fromList iPkgs)++getGlobalPackageDir :: Verbosity -> ProgramDb -> IO FilePath+getGlobalPackageDir verbosity progdb = do+ output <- getDbProgramOutput verbosity+ uhcProgram progdb ["--meta-pkgdir-system"]+ -- we need to trim because pkgdir contains an extra newline at the end+ let pkgdir = trimEnd output+ return pkgdir+ where+ trimEnd = reverse . dropWhile isSpace . reverse++getUserPackageDir :: IO FilePath+getUserPackageDir = do+ homeDir <- getHomeDirectory+ return $ homeDir </> ".cabal" </> "lib" -- TODO: determine in some other way++packageDbPaths :: FilePath -> FilePath -> PackageDB -> [FilePath]+packageDbPaths user system db =+ case db of+ GlobalPackageDB -> [ system ]+ UserPackageDB -> [ user ]+ SpecificPackageDB path -> [ path ]++-- | Hack to add version numbers to UHC-built-in packages. This should sooner or+-- later be fixed on the UHC side.+addBuiltinVersions :: String -> String+{-+addBuiltinVersions "uhcbase" = "uhcbase-1.0"+addBuiltinVersions "base" = "base-3.0"+addBuiltinVersions "array" = "array-0.2"+-}+addBuiltinVersions xs = xs++-- | Name of the installed package config file.+installedPkgConfig :: String+installedPkgConfig = "installed-pkg-config"++-- | Check if a certain dir contains a valid package. Currently, we are+-- looking only for the presence of an installed package configuration.+-- TODO: Actually make use of the information provided in the file.+isPkgDir :: String -> String -> String -> IO Bool+isPkgDir _ _ ('.' : _) = return False -- ignore files starting with a .+isPkgDir c dir xs = do+ let candidate = dir </> uhcPackageDir xs c+ -- putStrLn $ "trying: " ++ candidate+ doesFileExist (candidate </> installedPkgConfig)++parsePackage :: String -> [PackageId]+parsePackage = toList . simpleParsec++-- | Create a trivial package info from a directory name.+mkInstalledPackageInfo :: PackageId -> InstalledPackageInfo+mkInstalledPackageInfo p = emptyInstalledPackageInfo+ { installedUnitId = mkLegacyUnitId p,+ sourcePackageId = p }+++-- -----------------------------------------------------------------------------+-- Building++buildLib :: Verbosity -> PackageDescription -> LocalBuildInfo+ -> Library -> ComponentLocalBuildInfo -> IO ()+buildLib verbosity pkg_descr lbi lib clbi = do++ systemPkgDir <- getGlobalPackageDir verbosity (withPrograms lbi)+ userPkgDir <- getUserPackageDir+ let runUhcProg = runDbProgram verbosity uhcProgram (withPrograms lbi)+ let uhcArgs = -- set package name+ ["--pkg-build=" ++ prettyShow (packageId pkg_descr)]+ -- common flags lib/exe+ ++ constructUHCCmdLine userPkgDir systemPkgDir+ lbi (libBuildInfo lib) clbi+ (buildDir lbi) verbosity+ -- source files+ -- suboptimal: UHC does not understand module names, so+ -- we replace periods by path separators+ ++ map (map (\ c -> if c == '.' then pathSeparator else c))+ (map prettyShow (allLibModules lib clbi))++ runUhcProg uhcArgs++ return ()++buildExe :: Verbosity -> PackageDescription -> LocalBuildInfo+ -> Executable -> ComponentLocalBuildInfo -> IO ()+buildExe verbosity _pkg_descr lbi exe clbi = do+ systemPkgDir <- getGlobalPackageDir verbosity (withPrograms lbi)+ userPkgDir <- getUserPackageDir+ let runUhcProg = runDbProgram verbosity uhcProgram (withPrograms lbi)+ let uhcArgs = -- common flags lib/exe+ constructUHCCmdLine userPkgDir systemPkgDir+ lbi (buildInfo exe) clbi+ (buildDir lbi) verbosity+ -- output file+ ++ ["--output", buildDir lbi </> prettyShow (exeName exe)]+ -- main source module+ ++ [modulePath exe]+ runUhcProg uhcArgs++constructUHCCmdLine :: FilePath -> FilePath+ -> LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo+ -> FilePath -> Verbosity -> [String]+constructUHCCmdLine user system lbi bi clbi odir verbosity =+ -- verbosity+ (if verbosity >= deafening then ["-v4"]+ else if verbosity >= normal then []+ else ["-v0"])+ ++ hcOptions UHC bi+ -- flags for language extensions+ ++ languageToFlags (compiler lbi) (defaultLanguage bi)+ ++ extensionsToFlags (compiler lbi) (usedExtensions bi)+ -- packages+ ++ ["--hide-all-packages"]+ ++ uhcPackageDbOptions user system (withPackageDB lbi)+ ++ ["--package=uhcbase"]+ ++ ["--package=" ++ prettyShow (mungedName pkgid) | (_, pkgid) <- componentPackageDeps clbi ]+ -- search paths+ ++ ["-i" ++ odir]+ ++ ["-i" ++ getSymbolicPath l | l <- nub (hsSourceDirs bi)]+ ++ ["-i" ++ autogenComponentModulesDir lbi clbi]+ ++ ["-i" ++ autogenPackageModulesDir lbi]+ -- cpp options+ ++ ["--optP=" ++ opt | opt <- cppOptions bi]+ -- output path+ ++ ["--odir=" ++ odir]+ -- optimization+ ++ (case withOptimization lbi of+ NoOptimisation -> ["-O0"]+ NormalOptimisation -> ["-O1"]+ MaximumOptimisation -> ["-O2"])++uhcPackageDbOptions :: FilePath -> FilePath -> PackageDBStack -> [String]+uhcPackageDbOptions user system db = map (\ x -> "--pkg-searchpath=" ++ x)+ (concatMap (packageDbPaths user system) db)++-- -----------------------------------------------------------------------------+-- Installation++installLib :: Verbosity -> LocalBuildInfo+ -> FilePath -> FilePath -> FilePath+ -> PackageDescription -> Library -> ComponentLocalBuildInfo -> IO ()+installLib verbosity _lbi targetDir _dynlibTargetDir builtDir pkg _library _clbi = do+ -- putStrLn $ "dest: " ++ targetDir+ -- putStrLn $ "built: " ++ builtDir+ installDirectoryContents verbosity (builtDir </> prettyShow (packageId pkg)) targetDir++-- currently hard-coded UHC code generator and variant to use+uhcTarget, uhcTargetVariant :: String+uhcTarget = "bc"+uhcTargetVariant = "plain"++-- root directory for a package in UHC+uhcPackageDir :: String -> String -> FilePath+uhcPackageSubDir :: String -> FilePath+uhcPackageDir pkgid compilerid = pkgid </> uhcPackageSubDir compilerid+uhcPackageSubDir compilerid = compilerid </> uhcTarget </> uhcTargetVariant++-- -----------------------------------------------------------------------------+-- Registering++registerPackage+ :: Verbosity+ -> Compiler+ -> ProgramDb+ -> PackageDBStack+ -> InstalledPackageInfo+ -> IO ()+registerPackage verbosity comp progdb packageDbs installedPkgInfo = do+ dbdir <- case registrationPackageDB packageDbs of+ GlobalPackageDB -> getGlobalPackageDir verbosity progdb+ UserPackageDB -> getUserPackageDir+ SpecificPackageDB dir -> return dir+ let pkgdir = dbdir </> uhcPackageDir (prettyShow pkgid) (prettyShow compilerid)+ createDirectoryIfMissingVerbose verbosity True pkgdir+ writeUTF8File (pkgdir </> installedPkgConfig)+ (showInstalledPackageInfo installedPkgInfo)+ where+ pkgid = sourcePackageId installedPkgInfo+ compilerid = compilerId comp++inplacePackageDbPath :: LocalBuildInfo -> FilePath+inplacePackageDbPath lbi = buildDir lbi
+ src/Distribution/Simple/UserHooks.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.UserHooks+-- Copyright : Isaac Jones 2003-2005+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This defines the API that @Setup.hs@ scripts can use to customise the way+-- the build works. This module just defines the 'UserHooks' type. The+-- predefined sets of hooks that implement the @Simple@, @Make@ and @Configure@+-- build systems are defined in "Distribution.Simple". The 'UserHooks' is a big+-- record of functions. There are 3 for each action, a pre, post and the action+-- itself. There are few other miscellaneous hooks, ones to extend the set of+-- programs and preprocessors and one to override the function used to read the+-- @.cabal@ file.+--+-- This hooks type is widely agreed to not be the right solution. Partly this+-- is because changes to it usually break custom @Setup.hs@ files and yet many+-- internal code changes do require changes to the hooks. For example we cannot+-- pass any extra parameters to most of the functions that implement the+-- various phases because it would involve changing the types of the+-- corresponding hook. At some point it will have to be replaced.++module Distribution.Simple.UserHooks (+ UserHooks(..), Args,+ emptyUserHooks,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.PackageDescription+import Distribution.Simple.Program+import Distribution.Simple.Command+import Distribution.Simple.PreProcess+import Distribution.Simple.Setup+import Distribution.Simple.LocalBuildInfo++type Args = [String]++-- | Hooks allow authors to add specific functionality before and after a+-- command is run, and also to specify additional preprocessors.+--+-- * WARNING: The hooks interface is under rather constant flux as we try to+-- understand users needs. Setup files that depend on this interface may+-- break in future releases.+data UserHooks = UserHooks {++ -- | Read the description file+ readDesc :: IO (Maybe GenericPackageDescription),+ -- | Custom preprocessors in addition to and overriding 'knownSuffixHandlers'.+ hookedPreProcessors :: [ PPSuffixHandler ],+ -- | These programs are detected at configure time. Arguments for them are+ -- added to the configure command.+ hookedPrograms :: [Program],++ -- |Hook to run before configure command+ preConf :: Args -> ConfigFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during configure.+ confHook :: (GenericPackageDescription, HookedBuildInfo)+ -> ConfigFlags -> IO LocalBuildInfo,+ -- |Hook to run after configure command+ postConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before build command. Second arg indicates verbosity level.+ preBuild :: Args -> BuildFlags -> IO HookedBuildInfo,++ -- |Over-ride this hook to get different behavior during build.+ buildHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO (),+ -- |Hook to run after build command. Second arg indicates verbosity level.+ postBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before repl command. Second arg indicates verbosity level.+ preRepl :: Args -> ReplFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during interpretation.+ replHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO (),+ -- |Hook to run after repl command. Second arg indicates verbosity level.+ postRepl :: Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before clean command. Second arg indicates verbosity level.+ preClean :: Args -> CleanFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during clean.+ cleanHook :: PackageDescription -> () -> UserHooks -> CleanFlags -> IO (),+ -- |Hook to run after clean command. Second arg indicates verbosity level.+ postClean :: Args -> CleanFlags -> PackageDescription -> () -> IO (),++ -- |Hook to run before copy command+ preCopy :: Args -> CopyFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during copy.+ copyHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO (),+ -- |Hook to run after copy command+ postCopy :: Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before install command+ preInst :: Args -> InstallFlags -> IO HookedBuildInfo,++ -- |Over-ride this hook to get different behavior during install.+ instHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO (),+ -- |Hook to run after install command. postInst should be run+ -- on the target, not on the build machine.+ postInst :: Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before register command+ preReg :: Args -> RegisterFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during registration.+ regHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO (),+ -- |Hook to run after register command+ postReg :: Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before unregister command+ preUnreg :: Args -> RegisterFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during unregistration.+ unregHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO (),+ -- |Hook to run after unregister command+ postUnreg :: Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before hscolour command. Second arg indicates verbosity level.+ preHscolour :: Args -> HscolourFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during hscolour.+ hscolourHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO (),+ -- |Hook to run after hscolour command. Second arg indicates verbosity level.+ postHscolour :: Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before haddock command. Second arg indicates verbosity level.+ preHaddock :: Args -> HaddockFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during haddock.+ haddockHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO (),+ -- |Hook to run after haddock command. Second arg indicates verbosity level.+ postHaddock :: Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before test command.+ preTest :: Args -> TestFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during test.+ testHook :: Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO (),+ -- |Hook to run after test command.+ postTest :: Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO (),++ -- |Hook to run before bench command.+ preBench :: Args -> BenchmarkFlags -> IO HookedBuildInfo,+ -- |Over-ride this hook to get different behavior during bench.+ benchHook :: Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO (),+ -- |Hook to run after bench command.+ postBench :: Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()+ }++-- |Empty 'UserHooks' which do nothing.+emptyUserHooks :: UserHooks+emptyUserHooks+ = UserHooks {+ readDesc = return Nothing,+ hookedPreProcessors = [],+ hookedPrograms = [],+ preConf = rn',+ confHook = (\_ _ -> return (error "No local build info generated during configure. Over-ride empty configure hook.")),+ postConf = ru,+ preBuild = rn',+ buildHook = ru,+ postBuild = ru,+ preRepl = \_ _ -> return emptyHookedBuildInfo,+ replHook = \_ _ _ _ _ -> return (),+ postRepl = ru,+ preClean = rn,+ cleanHook = ru,+ postClean = ru,+ preCopy = rn',+ copyHook = ru,+ postCopy = ru,+ preInst = rn,+ instHook = ru,+ postInst = ru,+ preReg = rn',+ regHook = ru,+ postReg = ru,+ preUnreg = rn,+ unregHook = ru,+ postUnreg = ru,+ preHscolour = rn,+ hscolourHook = ru,+ postHscolour = ru,+ preHaddock = rn',+ haddockHook = ru,+ postHaddock = ru,+ preTest = rn',+ testHook = \_ -> ru,+ postTest = ru,+ preBench = rn',+ benchHook = \_ -> ru,+ postBench = ru+ }+ where rn args _ = noExtraFlags args >> return emptyHookedBuildInfo+ rn' _ _ = return emptyHookedBuildInfo+ ru _ _ _ _ = return ()
+ src/Distribution/Simple/Utils.hs view
@@ -0,0 +1,1609 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE BangPatterns #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Utils+-- Copyright : Isaac Jones, Simon Marlow 2003-2004+-- License : BSD3+-- portions Copyright (c) 2007, Galois Inc.+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- A large and somewhat miscellaneous collection of utility functions used+-- throughout the rest of the Cabal lib and in other tools that use the Cabal+-- lib like @cabal-install@. It has a very simple set of logging actions. It+-- has low level functions for running programs, a bunch of wrappers for+-- various directory and file functions that do extra logging.++module Distribution.Simple.Utils (+ cabalVersion,++ -- * logging and errors+ dieNoVerbosity,+ die', dieWithLocation',+ dieNoWrap,+ topHandler, topHandlerWith,+ warn,+ notice, noticeNoWrap, noticeDoc,+ setupMessage,+ info, infoNoWrap,+ debug, debugNoWrap,+ chattyTry,+ annotateIO,+ printRawCommandAndArgs, printRawCommandAndArgsAndEnv,+ withOutputMarker,++ -- * exceptions+ handleDoesNotExist,++ -- * running programs+ rawSystemExit,+ rawSystemExitCode,+ rawSystemExitWithEnv,+ rawSystemStdout,+ rawSystemStdInOut,+ rawSystemIOWithEnv,+ rawSystemIOWithEnvAndAction,+ createProcessWithEnv,+ maybeExit,+ xargs,+ findProgramVersion,++ -- ** 'IOData' re-export+ --+ -- These types are re-exported from+ -- "Distribution.Utils.IOData" for convience as they're+ -- exposed in the API of 'rawSystemStdInOut'+ IOData(..),+ KnownIODataMode (..),+ IODataMode (..),++ -- * copying files+ createDirectoryIfMissingVerbose,+ copyFileVerbose,+ copyFiles,+ copyFileTo,++ -- * installing files+ installOrdinaryFile,+ installExecutableFile,+ installMaybeExecutableFile,+ installOrdinaryFiles,+ installExecutableFiles,+ installMaybeExecutableFiles,+ installDirectoryContents,+ copyDirectoryRecursive,++ -- * File permissions+ doesExecutableExist,+ setFileOrdinary,+ setFileExecutable,++ -- * file names+ currentDir,+ shortRelativePath,+ dropExeExtension,+ exeExtensions,++ -- * finding files+ findFileEx,+ findFileCwd,+ findFirstFile,+ findFileWithExtension,+ findFileCwdWithExtension,+ findFileWithExtension',+ findAllFilesWithExtension,+ findAllFilesCwdWithExtension,+ findModuleFileEx,+ findModuleFilesEx,+ getDirectoryContentsRecursive,++ -- * environment variables+ isInSearchPath,+ addLibraryPath,++ -- * modification time+ moreRecentFile,+ existsAndIsMoreRecentThan,++ -- * temp files and dirs+ TempFileOptions(..), defaultTempFileOptions,+ withTempFile, withTempFileEx,+ withTempDirectory, withTempDirectoryEx,+ createTempDirectory,++ -- * .cabal and .buildinfo files+ defaultPackageDesc,+ findPackageDesc,+ findPackageDescCwd,+ tryFindPackageDesc,+ tryFindPackageDescCwd,+ findHookedPackageDesc,++ -- * reading and writing files safely+ withFileContents,+ writeFileAtomic,+ rewriteFileEx,+ rewriteFileLBS,++ -- * Unicode+ fromUTF8BS,+ fromUTF8LBS,+ toUTF8BS,+ toUTF8LBS,+ readUTF8File,+ withUTF8FileContents,+ writeUTF8File,+ normaliseLineEndings,++ -- * BOM+ ignoreBOM,++ -- * generic utils+ dropWhileEndLE,+ takeWhileEndLE,+ equating,+ comparing,+ isInfixOf,+ intercalate,+ lowercase,+ listUnion,+ listUnionRight,+ ordNub,+ ordNubBy,+ ordNubRight,+ safeHead,+ safeTail,+ safeLast,+ safeInit,+ unintersperse,+ wrapText,+ wrapLine,++ -- * FilePath stuff+ isAbsoluteOnAnyPlatform,+ isRelativeOnAnyPlatform,++ -- * Deprecated functions+ findFile,+ findModuleFile,+ findModuleFiles,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Utils.Generic+import Distribution.Utils.IOData (IOData(..), IODataMode (..), KnownIODataMode (..))+import qualified Distribution.Utils.IOData as IOData+import Distribution.ModuleName as ModuleName+import Distribution.System+import Distribution.Version+import Distribution.Compat.Async+import Distribution.Compat.CopyFile+import Distribution.Compat.Internal.TempFile+import Distribution.Compat.FilePath as FilePath+import Distribution.Compat.Stack+import Distribution.Verbosity+import Distribution.Types.PackageId++#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 Distribution.Pretty+import Distribution.Parsec++import Data.Typeable+ ( cast )+import qualified Data.ByteString.Lazy as BS++import System.Directory+ ( Permissions(executable), getDirectoryContents, getPermissions+ , doesDirectoryExist, doesFileExist, removeFile+ , getModificationTime, createDirectory, removeDirectoryRecursive )+import System.Environment+ ( getProgName )+import System.FilePath as FilePath+ ( normalise, (</>), (<.>)+ , getSearchPath, joinPath, takeDirectory, splitExtension+ , splitDirectories, searchPathSeparator )+import System.IO+ ( Handle, hSetBinaryMode, hGetContents, stderr, stdout, hPutStr, hFlush+ , hClose, hSetBuffering, BufferMode(..), hPutStrLn )+import System.IO.Error+import System.IO.Unsafe+ ( unsafeInterleaveIO )+import qualified Control.Exception as Exception++import Foreign.C.Error (Errno (..), ePIPE)+import Data.Time.Clock.POSIX (getPOSIXTime, POSIXTime)+import Numeric (showFFloat)+import Distribution.Compat.Process (createProcess, rawSystem, runInteractiveProcess)+import System.Process+ ( ProcessHandle+ , showCommandForUser, waitForProcess)+import qualified System.Process as Process+import qualified GHC.IO.Exception as GHC++import qualified Text.PrettyPrint as Disp++-- We only get our own version number when we're building with ourselves+cabalVersion :: Version+#if defined(BOOTSTRAPPED_CABAL)+cabalVersion = mkVersion' Paths_Cabal.version+#elif defined(CABAL_VERSION)+cabalVersion = mkVersion [CABAL_VERSION]+#else+cabalVersion = mkVersion [3,0] --used when bootstrapping+#endif++-- ----------------------------------------------------------------------------+-- Exception and logging utils++-- Cabal's logging infrastructure has a few constraints:+--+-- * We must make all logging formatting and emissions decisions based+-- on the 'Verbosity' parameter, which is the only parameter that is+-- plumbed to enough call-sites to actually be used for this matter.+-- (One of Cabal's "big mistakes" is to have never have defined a+-- monad of its own.)+--+-- * When we 'die', we must raise an IOError. This a backwards+-- compatibility consideration, because that's what we've raised+-- previously, and if we change to any other exception type,+-- exception handlers which match on IOError will no longer work.+-- One case where it is known we rely on IOError being catchable+-- is 'readPkgConfigDb' in cabal-install; there may be other+-- user code that also assumes this.+--+-- * The 'topHandler' does not know what 'Verbosity' is, because+-- it gets called before we've done command line parsing (where+-- the 'Verbosity' parameter would come from).+--+-- This leads to two big architectural choices:+--+-- * Although naively we might imagine 'Verbosity' to be a simple+-- enumeration type, actually it is a full-on abstract data type+-- that may contain arbitrarily complex information. At the+-- moment, it is fully representable as a string, but we might+-- eventually also use verbosity to let users register their+-- own logging handler.+--+-- * When we call 'die', we perform all the formatting and addition+-- of extra information we need, and then ship this in the IOError+-- to the top-level handler. Here are alternate designs that+-- don't work:+--+-- a) Ship the unformatted info to the handler. This doesn't+-- work because at the point the handler gets the message,+-- we've lost call stacks, and even if we did, we don't have access+-- to 'Verbosity' to decide whether or not to render it.+--+-- b) Print the information at the 'die' site, then raise an+-- error. This means that if the exception is subsequently+-- caught by a handler, we will still have emitted the output,+-- which is not the correct behavior.+--+-- For the top-level handler to "know" that an error message+-- contains one of these fully formatted packets, we set a sentinel+-- in one of IOError's extra fields. This is handled by+-- 'ioeSetVerbatim' and 'ioeGetVerbatim'.+--++dieNoVerbosity :: String -> IO a+dieNoVerbosity msg+ = ioError (userError msg)+ where+ _ = callStack -- TODO: Attach CallStack to exception++-- | Tag an 'IOError' whose error string should be output to the screen+-- verbatim.+ioeSetVerbatim :: IOError -> IOError+ioeSetVerbatim e = ioeSetLocation e "dieVerbatim"++-- | Check if an 'IOError' should be output verbatim to screen.+ioeGetVerbatim :: IOError -> Bool+ioeGetVerbatim e = ioeGetLocation e == "dieVerbatim"++-- | Create a 'userError' whose error text will be output verbatim+verbatimUserError :: String -> IOError+verbatimUserError = ioeSetVerbatim . userError++dieWithLocation' :: Verbosity -> FilePath -> Maybe Int -> String -> IO a+dieWithLocation' verbosity filename mb_lineno msg = withFrozenCallStack $ do+ ts <- getPOSIXTime+ pname <- getProgName+ ioError . verbatimUserError+ . withMetadata ts AlwaysMark VerboseTrace verbosity+ . wrapTextVerbosity verbosity+ $ pname ++ ": " +++ filename ++ (case mb_lineno of+ Just lineno -> ":" ++ show lineno+ Nothing -> "") +++ ": " ++ msg++die' :: Verbosity -> String -> IO a+die' verbosity msg = withFrozenCallStack $ do+ ts <- getPOSIXTime+ pname <- getProgName+ ioError . verbatimUserError+ . withMetadata ts AlwaysMark VerboseTrace verbosity+ . wrapTextVerbosity verbosity+ $ pname ++ ": " ++ msg++dieNoWrap :: Verbosity -> String -> IO a+dieNoWrap verbosity msg = withFrozenCallStack $ do+ -- TODO: should this have program name or not?+ ts <- getPOSIXTime+ ioError . verbatimUserError+ . withMetadata ts AlwaysMark VerboseTrace verbosity+ $ msg++-- | Given a block of IO code that may raise an exception, annotate+-- it with the metadata from the current scope. Use this as close+-- to external code that raises IO exceptions as possible, since+-- this function unconditionally wraps the error message with a trace+-- (so it is NOT idempotent.)+annotateIO :: Verbosity -> IO a -> IO a+annotateIO verbosity act = do+ ts <- getPOSIXTime+ modifyIOError (f ts) act+ where+ f ts ioe = ioeSetErrorString ioe+ . withMetadata ts NeverMark VerboseTrace verbosity+ $ ioeGetErrorString ioe+++{-# NOINLINE topHandlerWith #-}+topHandlerWith :: forall a. (Exception.SomeException -> IO a) -> IO a -> IO a+topHandlerWith cont prog = do+ -- By default, stderr to a terminal device is NoBuffering. But this+ -- is *really slow*+ hSetBuffering stderr LineBuffering+ Exception.catches prog [+ Exception.Handler rethrowAsyncExceptions+ , Exception.Handler rethrowExitStatus+ , Exception.Handler handle+ ]+ where+ -- Let async exceptions rise to the top for the default top-handler+ rethrowAsyncExceptions :: Exception.AsyncException -> IO a+ rethrowAsyncExceptions a = throwIO a++ -- 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 (message pname se)+ cont se++ message :: String -> Exception.SomeException -> String+ message pname (Exception.SomeException se) =+ case cast se :: Maybe Exception.IOException of+ Just ioe+ | ioeGetVerbatim ioe ->+ -- Use the message verbatim+ ioeGetErrorString ioe ++ "\n"+ | isUserError ioe ->+ let file = case ioeGetFileName ioe of+ Nothing -> ""+ Just path -> path ++ location ++ ": "+ location = case ioeGetLocation ioe of+ l@(n:_) | isDigit n -> ':' : l+ _ -> ""+ detail = ioeGetErrorString ioe+ in wrapText (pname ++ ": " ++ file ++ detail)+ _ ->+ displaySomeException se ++ "\n"++-- | BC wrapper around 'Exception.displayException'.+displaySomeException :: Exception.Exception e => e -> String+displaySomeException se =+#if __GLASGOW_HASKELL__ < 710+ show se+#else+ Exception.displayException se+#endif++topHandler :: IO a -> IO a+topHandler prog = topHandlerWith (const $ exitWith (ExitFailure 1)) prog++verbosityHandle :: Verbosity -> Handle+verbosityHandle verbosity+ | isVerboseStderr verbosity = stderr+ | otherwise = stdout++-- | Non fatal conditions that may be indicative of an error or problem.+--+-- We display these at the 'normal' verbosity level.+--+warn :: Verbosity -> String -> IO ()+warn verbosity msg = withFrozenCallStack $ do+ when (verbosity >= normal) $ do+ ts <- getPOSIXTime+ hFlush stdout+ hPutStr stderr . withMetadata ts NormalMark FlagTrace verbosity+ . wrapTextVerbosity verbosity+ $ "Warning: " ++ msg++-- | Useful status messages.+--+-- We display these at the 'normal' verbosity level.+--+-- This is for the ordinary helpful status messages that users see. Just+-- enough information to know that things are working but not floods of detail.+--+notice :: Verbosity -> String -> IO ()+notice verbosity msg = withFrozenCallStack $ do+ when (verbosity >= normal) $ do+ let h = verbosityHandle verbosity+ ts <- getPOSIXTime+ hPutStr h+ $ withMetadata ts NormalMark FlagTrace verbosity+ $ wrapTextVerbosity verbosity+ $ msg++-- | Display a message at 'normal' verbosity level, but without+-- wrapping.+--+noticeNoWrap :: Verbosity -> String -> IO ()+noticeNoWrap verbosity msg = withFrozenCallStack $ do+ when (verbosity >= normal) $ do+ let h = verbosityHandle verbosity+ ts <- getPOSIXTime+ hPutStr h . withMetadata ts NormalMark FlagTrace verbosity $ msg++-- | Pretty-print a 'Disp.Doc' status message at 'normal' verbosity+-- level. Use this if you need fancy formatting.+--+noticeDoc :: Verbosity -> Disp.Doc -> IO ()+noticeDoc verbosity msg = withFrozenCallStack $ do+ when (verbosity >= normal) $ do+ let h = verbosityHandle verbosity+ ts <- getPOSIXTime+ hPutStr h+ $ withMetadata ts NormalMark FlagTrace verbosity+ $ Disp.renderStyle defaultStyle+ $ msg++-- | Display a "setup status message". Prefer using setupMessage'+-- if possible.+--+setupMessage :: Verbosity -> String -> PackageIdentifier -> IO ()+setupMessage verbosity msg pkgid = withFrozenCallStack $ do+ noticeNoWrap verbosity (msg ++ ' ': prettyShow pkgid ++ "...")++-- | More detail on the operation of some action.+--+-- We display these messages when the verbosity level is 'verbose'+--+info :: Verbosity -> String -> IO ()+info verbosity msg = withFrozenCallStack $+ when (verbosity >= verbose) $ do+ let h = verbosityHandle verbosity+ ts <- getPOSIXTime+ hPutStr h+ $ withMetadata ts NeverMark FlagTrace verbosity+ $ wrapTextVerbosity verbosity+ $ msg++infoNoWrap :: Verbosity -> String -> IO ()+infoNoWrap verbosity msg = withFrozenCallStack $+ when (verbosity >= verbose) $ do+ let h = verbosityHandle verbosity+ ts <- getPOSIXTime+ hPutStr h+ $ withMetadata ts NeverMark FlagTrace verbosity+ $ msg++-- | Detailed internal debugging information+--+-- We display these messages when the verbosity level is 'deafening'+--+debug :: Verbosity -> String -> IO ()+debug verbosity msg = withFrozenCallStack $+ when (verbosity >= deafening) $ do+ let h = verbosityHandle verbosity+ ts <- getPOSIXTime+ hPutStr h $ withMetadata ts NeverMark FlagTrace verbosity+ $ wrapTextVerbosity verbosity+ $ msg+ -- ensure that we don't lose output if we segfault/infinite loop+ hFlush stdout++-- | A variant of 'debug' that doesn't perform the automatic line+-- wrapping. Produces better output in some cases.+debugNoWrap :: Verbosity -> String -> IO ()+debugNoWrap verbosity msg = withFrozenCallStack $+ when (verbosity >= deafening) $ do+ let h = verbosityHandle verbosity+ ts <- getPOSIXTime+ hPutStr h+ $ withMetadata ts NeverMark FlagTrace verbosity+ $ msg+ -- ensure that we don't lose output if we segfault/infinite loop+ hFlush stdout++-- | Perform an IO action, catching any IO exceptions and printing an error+-- if one occurs.+chattyTry :: String -- ^ a description of the action we were attempting+ -> IO () -- ^ the action itself+ -> IO ()+chattyTry desc action =+ catchIO action $ \exception ->+ hPutStrLn stderr $ "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++-- | Wraps text unless the @+nowrap@ verbosity flag is active+wrapTextVerbosity :: Verbosity -> String -> String+wrapTextVerbosity verb+ | isVerboseNoWrap verb = withTrailingNewline+ | otherwise = withTrailingNewline . wrapText+++-- | Prepends a timestamp if @+timestamp@ verbosity flag is set+--+-- This is used by 'withMetadata'+--+withTimestamp :: Verbosity -> POSIXTime -> String -> String+withTimestamp v ts msg+ | isVerboseTimestamp v = msg'+ | otherwise = msg -- no-op+ where+ msg' = case lines msg of+ [] -> tsstr "\n"+ l1:rest -> unlines (tsstr (' ':l1) : map (contpfx++) rest)++ -- format timestamp to be prepended to first line with msec precision+ tsstr = showFFloat (Just 3) (realToFrac ts :: Double)++ -- continuation prefix for subsequent lines of msg+ contpfx = replicate (length (tsstr " ")) ' '++-- | Wrap output with a marker if @+markoutput@ verbosity flag is set.+--+-- NB: Why is markoutput done with start/end markers, and not prefixes?+-- Markers are more convenient to add (if we want to add prefixes,+-- we have to 'lines' and then 'map'; here's it's just some+-- concatenates). Note that even in the prefix case, we can't+-- guarantee that the markers are unambiguous, because some of+-- Cabal's output comes straight from external programs, where+-- we don't have the ability to interpose on the output.+--+-- This is used by 'withMetadata'+--+withOutputMarker :: Verbosity -> String -> String+withOutputMarker v xs | not (isVerboseMarkOutput v) = xs+withOutputMarker _ "" = "" -- Minor optimization, don't mark uselessly+withOutputMarker _ xs =+ "-----BEGIN CABAL OUTPUT-----\n" +++ withTrailingNewline xs +++ "-----END CABAL OUTPUT-----\n"++-- | Append a trailing newline to a string if it does not+-- already have a trailing newline.+--+withTrailingNewline :: String -> String+withTrailingNewline "" = ""+withTrailingNewline (x:xs) = x : go x xs+ where+ go _ (c:cs) = c : go c cs+ go '\n' "" = ""+ go _ "" = "\n"++-- | Prepend a call-site and/or call-stack based on Verbosity+--+withCallStackPrefix :: WithCallStack (TraceWhen -> Verbosity -> String -> String)+withCallStackPrefix tracer verbosity s = withFrozenCallStack $+ (if isVerboseCallSite verbosity+ then parentSrcLocPrefix +++ -- Hack: need a newline before starting output marker :(+ if isVerboseMarkOutput verbosity+ then "\n"+ else ""+ else "") +++ (case traceWhen verbosity tracer of+ Just pre -> pre ++ prettyCallStack callStack ++ "\n"+ Nothing -> "") +++ s++-- | When should we emit the call stack? We always emit+-- for internal errors, emit the trace for errors when we+-- are in verbose mode, and otherwise only emit it if+-- explicitly asked for using the @+callstack@ verbosity+-- flag. (At the moment, 'AlwaysTrace' is not used.+--+data TraceWhen+ = AlwaysTrace+ | VerboseTrace+ | FlagTrace+ deriving (Eq)++-- | Determine if we should emit a call stack.+-- If we trace, it also emits any prefix we should append.+traceWhen :: Verbosity -> TraceWhen -> Maybe String+traceWhen _ AlwaysTrace = Just ""+traceWhen v VerboseTrace | v >= verbose = Just ""+traceWhen v FlagTrace | isVerboseCallStack v = Just "----\n"+traceWhen _ _ = Nothing++-- | When should we output the marker? Things like 'die'+-- always get marked, but a 'NormalMark' will only be+-- output if we're not a quiet verbosity.+--+data MarkWhen = AlwaysMark | NormalMark | NeverMark++-- | Add all necessary metadata to a logging message+--+withMetadata :: WithCallStack (POSIXTime -> MarkWhen -> TraceWhen -> Verbosity -> String -> String)+withMetadata ts marker tracer verbosity x = withFrozenCallStack $+ -- NB: order matters. Output marker first because we+ -- don't want to capture call stacks.+ withTrailingNewline+ . withCallStackPrefix tracer verbosity+ . (case marker of+ AlwaysMark -> withOutputMarker verbosity+ NormalMark | not (isVerboseQuiet verbosity)+ -> withOutputMarker verbosity+ | otherwise+ -> id+ NeverMark -> id)+ -- Clear out any existing markers+ . clearMarkers+ . withTimestamp verbosity ts+ $ x++clearMarkers :: String -> String+clearMarkers s = unlines . filter isMarker $ lines s+ where+ isMarker "-----BEGIN CABAL OUTPUT-----" = False+ isMarker "-----END CABAL OUTPUT-----" = False+ isMarker _ = True++-- -----------------------------------------------------------------------------+-- rawSystem variants+maybeExit :: IO ExitCode -> IO ()+maybeExit cmd = do+ res <- cmd+ unless (res == ExitSuccess) $ exitWith res++++printRawCommandAndArgs :: Verbosity -> FilePath -> [String] -> IO ()+printRawCommandAndArgs verbosity path args = withFrozenCallStack $+ printRawCommandAndArgsAndEnv verbosity path args Nothing Nothing++printRawCommandAndArgsAndEnv :: Verbosity+ -> FilePath+ -> [String]+ -> Maybe FilePath+ -> Maybe [(String, String)]+ -> IO ()+printRawCommandAndArgsAndEnv verbosity path args mcwd menv = do+ case menv of+ Just env -> debugNoWrap verbosity ("Environment: " ++ show env)+ Nothing -> return ()+ case mcwd of+ Just cwd -> debugNoWrap verbosity ("Working directory: " ++ show cwd)+ Nothing -> return ()+ infoNoWrap verbosity (showCommandForUser path args)++-- Exit with the same exit code if the subcommand fails+rawSystemExit :: Verbosity -> FilePath -> [String] -> IO ()+rawSystemExit verbosity path args = withFrozenCallStack $ do+ printRawCommandAndArgs verbosity path args+ hFlush stdout+ exitcode <- rawSystem path args+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ path ++ " returned " ++ show exitcode+ exitWith exitcode++rawSystemExitCode :: Verbosity -> FilePath -> [String] -> IO ExitCode+rawSystemExitCode verbosity path args = withFrozenCallStack $ do+ printRawCommandAndArgs verbosity path args+ hFlush stdout+ exitcode <- rawSystem path args+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ path ++ " returned " ++ show exitcode+ return exitcode++rawSystemExitWithEnv :: Verbosity+ -> FilePath+ -> [String]+ -> [(String, String)]+ -> IO ()+rawSystemExitWithEnv verbosity path args env = withFrozenCallStack $ do+ printRawCommandAndArgsAndEnv verbosity path args Nothing (Just env)+ hFlush stdout+ (_,_,_,ph) <- createProcess $+ (Process.proc path args) { Process.env = (Just env)+#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+#endif+#endif+ }+ exitcode <- waitForProcess ph+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ path ++ " returned " ++ show exitcode+ exitWith exitcode++-- Closes the passed in handles before returning.+rawSystemIOWithEnv :: Verbosity+ -> FilePath+ -> [String]+ -> Maybe FilePath -- ^ New working dir or inherit+ -> Maybe [(String, String)] -- ^ New environment or inherit+ -> Maybe Handle -- ^ stdin+ -> Maybe Handle -- ^ stdout+ -> Maybe Handle -- ^ stderr+ -> IO ExitCode+rawSystemIOWithEnv verbosity path args mcwd menv inp out err = withFrozenCallStack $ 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++rawSystemIOWithEnvAndAction+ :: Verbosity+ -> FilePath+ -> [String]+ -> Maybe FilePath -- ^ New working dir or inherit+ -> Maybe [(String, String)] -- ^ New environment or inherit+ -> IO a -- ^ action to perform after process is created, but before 'waitForProcess'.+ -> Maybe Handle -- ^ stdin+ -> Maybe Handle -- ^ stdout+ -> Maybe Handle -- ^ stderr+ -> IO (ExitCode, a)+rawSystemIOWithEnvAndAction verbosity path args mcwd menv action inp out err = withFrozenCallStack $ do+ (_,_,_,ph) <- createProcessWithEnv verbosity path args mcwd menv+ (mbToStd inp) (mbToStd out) (mbToStd err)+ a <- action+ exitcode <- waitForProcess ph+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ path ++ " returned " ++ show exitcode+ return (exitcode, a)+ 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 = withFrozenCallStack $ do+ printRawCommandAndArgsAndEnv verbosity path args mcwd menv+ hFlush stdout+ (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+#endif+#endif+ }+ return (inp', out', err', ph)++-- | Run a command and return its output.+--+-- The output is assumed to be text in the locale encoding.+--+rawSystemStdout :: forall mode. KnownIODataMode mode => Verbosity -> FilePath -> [String] -> IO mode+rawSystemStdout verbosity path args = withFrozenCallStack $ do+ (output, errors, exitCode) <- rawSystemStdInOut verbosity path args+ Nothing Nothing Nothing (IOData.iodataMode :: IODataMode mode)+ when (exitCode /= ExitSuccess) $+ die' verbosity errors+ return output++-- | Run a command and return its output, errors and exit status. Optionally+-- also supply some input. Also provides control over whether the binary/text+-- mode of the input and output.+--+rawSystemStdInOut :: KnownIODataMode mode+ => Verbosity+ -> FilePath -- ^ Program location+ -> [String] -- ^ Arguments+ -> Maybe FilePath -- ^ New working dir or inherit+ -> Maybe [(String, String)] -- ^ New environment or inherit+ -> Maybe IOData -- ^ input text and binary mode+ -> IODataMode mode -- ^ iodata mode, acts as proxy+ -> IO (mode, String, ExitCode) -- ^ output, errors, exit+rawSystemStdInOut verbosity path args mcwd menv input _ = withFrozenCallStack $ do+ printRawCommandAndArgs verbosity path args++ Exception.bracket+ (runInteractiveProcess path args mcwd menv)+ (\(inh,outh,errh,_) -> hClose inh >> hClose outh >> hClose errh)+ $ \(inh,outh,errh,pid) -> do++ -- output mode depends on what the caller wants+ -- but the errors are always assumed to be text (in the current locale)+ hSetBinaryMode errh False++ -- fork off a couple threads to pull on the stderr and stdout+ -- so if the process writes to stderr we do not block.++ withAsyncNF (hGetContents errh) $ \errA -> withAsyncNF (IOData.hGetIODataContents outh) $ \outA -> do+ -- push all the input, if any+ ignoreSigPipe $ case input of+ Nothing -> hClose inh+ Just inputData -> IOData.hPutContents inh inputData++ -- wait for both to finish+ mberr1 <- waitCatch outA+ mberr2 <- waitCatch errA++ -- wait for the program to terminate+ exitcode <- waitForProcess pid++ -- get the stderr, so it can be added to error message+ err <- reportOutputIOError mberr2++ unless (exitcode == ExitSuccess) $+ debug verbosity $ path ++ " returned " ++ show exitcode+ ++ if null err then "" else+ " with error message:\n" ++ err+ ++ case input of+ Nothing -> ""+ Just d | IOData.null d -> ""+ Just (IODataText inp) -> "\nstdin input:\n" ++ inp+ Just (IODataBinary inp) -> "\nstdin input (binary):\n" ++ show inp++ -- Check if we hit an exception while consuming the output+ -- (e.g. a text decoding error)+ out <- reportOutputIOError mberr1++ return (out, err, exitcode)+ where+ reportOutputIOError :: Either Exception.SomeException a -> IO a+ reportOutputIOError (Right x) = return x+ reportOutputIOError (Left exc) = case fromException exc of+ Just ioe -> throwIO (ioeSetFileName ioe ("output of " ++ path))+ Nothing -> throwIO exc++ ignoreSigPipe :: IO () -> IO ()+ ignoreSigPipe = Exception.handle $ \e -> case e of+ GHC.IOError { GHC.ioe_type = GHC.ResourceVanished, GHC.ioe_errno = Just ioe }+ | Errno ioe == ePIPE -> return ()+ _ -> throwIO e++-- | Look for a program and try to find it's version number. It can accept+-- either an absolute path or the name of a program binary, in which case we+-- will look for the program on the path.+--+findProgramVersion :: String -- ^ version args+ -> (String -> String) -- ^ function to select version+ -- number from program output+ -> Verbosity+ -> FilePath -- ^ location+ -> IO (Maybe Version)+findProgramVersion versionArg selectVersion verbosity path = withFrozenCallStack $ do+ str <- rawSystemStdout verbosity path [versionArg]+ `catchIO` (\_ -> return "")+ `catchExit` (\_ -> return "")+ let version :: Maybe Version+ version = simpleParsec (selectVersion str)+ case version of+ Nothing -> warn verbosity $ "cannot determine version of " ++ path+ ++ " :\n" ++ show str+ Just v -> debug verbosity $ path ++ " is version " ++ prettyShow v+ return version+++-- | Like the Unix xargs program. Useful for when we've got very long command+-- lines that might overflow an OS limit on command line length and so you+-- need to invoke a command multiple times to get all the args in.+--+-- Use it with either of the rawSystem variants above. For example:+--+-- > xargs (32*1024) (rawSystemExit verbosity) prog fixedArgs bigArgs+--+xargs :: Int -> ([String] -> IO ())+ -> [String] -> [String] -> IO ()+xargs maxSize rawSystemFun fixedArgs bigArgs =+ let fixedArgSize = sum (map length fixedArgs) + length fixedArgs+ chunkSize = maxSize - fixedArgSize+ in traverse_ (rawSystemFun . (fixedArgs ++)) (chunks chunkSize bigArgs)++ where chunks len = unfoldr $ \s ->+ if null s then Nothing+ else Just (chunk [] len s)++ chunk acc _ [] = (reverse acc,[])+ chunk acc len (s:ss)+ | len' < len = chunk (s:acc) (len-len'-1) ss+ | otherwise = (reverse acc, s:ss)+ where len' = length s++-- ------------------------------------------------------------+-- * File Utilities+-- ------------------------------------------------------------++----------------+-- Finding files+++{-# DEPRECATED findFile "Use findFileEx instead. This symbol will be removed in Cabal 3.2 (est. December 2019)" #-}+findFile :: [FilePath] -- ^search locations+ -> FilePath -- ^File Name+ -> IO FilePath+findFile = findFileEx normal++-- | Find a file by looking in a search path. The file path must match exactly.+--+-- @since 3.4.0.0+findFileCwd+ :: Verbosity+ -> FilePath -- ^ cwd+ -> [FilePath] -- ^ relative search location+ -> FilePath -- ^ File Name+ -> IO FilePath+findFileCwd verbosity cwd searchPath fileName =+ findFirstFile (cwd </>)+ [ path </> fileName+ | path <- nub searchPath]+ >>= maybe (die' verbosity $ fileName ++ " doesn't exist") return++-- | Find a file by looking in a search path. The file path must match exactly.+--+findFileEx :: Verbosity+ -> [FilePath] -- ^search locations+ -> FilePath -- ^File Name+ -> IO FilePath+findFileEx verbosity searchPath fileName =+ findFirstFile id+ [ path </> fileName+ | path <- nub searchPath]+ >>= maybe (die' verbosity $ fileName ++ " doesn't exist") return++-- | Find a file by looking in a search path with one of a list of possible+-- file extensions. The file base name should be given and it will be tried+-- with each of the extensions in each element of the search path.+--+findFileWithExtension :: [String]+ -> [FilePath]+ -> FilePath+ -> IO (Maybe FilePath)+findFileWithExtension extensions searchPath baseName =+ findFirstFile id+ [ path </> baseName <.> ext+ | path <- nub searchPath+ , ext <- nub extensions ]++-- | @since 3.4.0.0+findFileCwdWithExtension+ :: FilePath+ -> [String]+ -> [FilePath]+ -> FilePath+ -> IO (Maybe FilePath)+findFileCwdWithExtension cwd extensions searchPath baseName =+ findFirstFile (cwd </>)+ [ path </> baseName <.> ext+ | path <- nub searchPath+ , ext <- nub extensions ]++-- | @since 3.4.0.0+findAllFilesCwdWithExtension+ :: FilePath -- ^ cwd+ -> [String] -- ^ extensions+ -> [FilePath] -- ^ relative search locations+ -> FilePath -- ^ basename+ -> IO [FilePath]+findAllFilesCwdWithExtension cwd extensions searchPath basename =+ findAllFiles (cwd </>)+ [ path </> basename <.> ext+ | 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.+--+findFileWithExtension' :: [String]+ -> [FilePath]+ -> FilePath+ -> IO (Maybe (FilePath, FilePath))+findFileWithExtension' extensions searchPath baseName =+ findFirstFile (uncurry (</>))+ [ (path, baseName <.> ext)+ | path <- nub searchPath+ , ext <- nub extensions ]++findFirstFile :: (a -> FilePath) -> [a] -> IO (Maybe a)+findFirstFile file = findFirst+ where findFirst [] = return Nothing+ findFirst (x:xs) = do exists <- doesFileExist (file x)+ if exists+ then return (Just x)+ else findFirst xs++findAllFiles :: (a -> FilePath) -> [a] -> IO [a]+findAllFiles file = filterM (doesFileExist . file)+++{-# DEPRECATED findModuleFiles "Use findModuleFilesEx instead. This symbol will be removed in Cabal 3.2 (est. December 2019)" #-}+findModuleFiles :: [FilePath] -- ^ build prefix (location of objects)+ -> [String] -- ^ search suffixes+ -> [ModuleName] -- ^ modules+ -> IO [(FilePath, FilePath)]+findModuleFiles = findModuleFilesEx normal++-- | Finds the files corresponding to a list of Haskell module names.+--+-- As 'findModuleFile' but for a list of module names.+--+findModuleFilesEx :: Verbosity+ -> [FilePath] -- ^ build prefix (location of objects)+ -> [String] -- ^ search suffixes+ -> [ModuleName] -- ^ modules+ -> IO [(FilePath, FilePath)]+findModuleFilesEx verbosity searchPath extensions moduleNames =+ traverse (findModuleFileEx verbosity searchPath extensions) moduleNames++{-# DEPRECATED findModuleFile "Use findModuleFileEx instead. This symbol will be removed in Cabal 3.2 (est. December 2019)" #-}+findModuleFile :: [FilePath] -- ^ build prefix (location of objects)+ -> [String] -- ^ search suffixes+ -> ModuleName -- ^ module+ -> IO (FilePath, FilePath)+findModuleFile = findModuleFileEx normal++-- | Find the file corresponding to a Haskell module name.+--+-- This is similar to 'findFileWithExtension'' but specialised to a module+-- name. The function fails if the file corresponding to the module is missing.+--+findModuleFileEx :: Verbosity+ -> [FilePath] -- ^ build prefix (location of objects)+ -> [String] -- ^ search suffixes+ -> ModuleName -- ^ module+ -> IO (FilePath, FilePath)+findModuleFileEx verbosity searchPath extensions mod_name =+ maybe notFound return+ =<< findFileWithExtension' extensions searchPath+ (ModuleName.toFilePath mod_name)+ where+ notFound = die' verbosity $+ "Error: Could not find module: " ++ prettyShow mod_name+ ++ " with any suffix: " ++ show extensions+ ++ " in the search path: " ++ show searchPath++-- | List all the files in a directory and all subdirectories.+--+-- The order places files in sub-directories after all the files in their+-- parent directories. The list is generated lazily so is not well defined if+-- the source directory structure changes before the list is used.+--+getDirectoryContentsRecursive :: FilePath -> IO [FilePath]+getDirectoryContentsRecursive topdir = recurseDirectories [""]+ where+ recurseDirectories :: [FilePath] -> IO [FilePath]+ recurseDirectories [] = return []+ recurseDirectories (dir:dirs) = unsafeInterleaveIO $ do+ (files, dirs') <- collect [] [] =<< getDirectoryContents (topdir </> dir)+ files' <- recurseDirectories (dirs' ++ dirs)+ return (files ++ files')++ where+ collect files dirs' [] = return (reverse files+ ,reverse dirs')+ collect files dirs' (entry:entries) | ignore entry+ = collect files dirs' entries+ collect files dirs' (entry:entries) = do+ let dirEntry = dir </> entry+ isDirectory <- doesDirectoryExist (topdir </> dirEntry)+ if isDirectory+ then collect files (dirEntry:dirs') entries+ else collect (dirEntry:files) dirs' entries++ ignore ['.'] = True+ ignore ['.', '.'] = True+ ignore _ = False++------------------------+-- Environment variables++-- | Is this directory in the system search path?+isInSearchPath :: FilePath -> IO Bool+isInSearchPath path = fmap (elem path) getSearchPath++addLibraryPath :: OS+ -> [FilePath]+ -> [(String,String)]+ -> [(String,String)]+addLibraryPath os paths = addEnv+ where+ pathsString = intercalate [searchPathSeparator] paths+ ldPath = case os of+ OSX -> "DYLD_LIBRARY_PATH"+ _ -> "LD_LIBRARY_PATH"++ addEnv [] = [(ldPath,pathsString)]+ addEnv ((key,value):xs)+ | key == ldPath =+ if null value+ then (key,pathsString):xs+ else (key,value ++ (searchPathSeparator:pathsString)):xs+ | otherwise = (key,value):addEnv xs++--------------------+-- Modification time++-- | Compare the modification times of two files to see if the first is newer+-- than the second. The first file must exist but the second need not.+-- The expected use case is when the second file is generated using the first.+-- In this use case, if the result is True then the second file is out of date.+--+moreRecentFile :: FilePath -> FilePath -> IO Bool+moreRecentFile a b = do+ exists <- doesFileExist b+ if not exists+ then return True+ else do tb <- getModificationTime b+ ta <- getModificationTime a+ return (ta > tb)++-- | Like 'moreRecentFile', but also checks that the first file exists.+existsAndIsMoreRecentThan :: FilePath -> FilePath -> IO Bool+existsAndIsMoreRecentThan a b = do+ exists <- doesFileExist a+ if not exists+ then return False+ else a `moreRecentFile` b++----------------------------------------+-- Copying and installing files and dirs++-- | Same as 'createDirectoryIfMissing' but logs at higher verbosity levels.+--+createDirectoryIfMissingVerbose :: Verbosity+ -> Bool -- ^ Create its parents too?+ -> FilePath+ -> IO ()+createDirectoryIfMissingVerbose verbosity create_parents path0+ | create_parents = withFrozenCallStack $ createDirs (parents path0)+ | otherwise = withFrozenCallStack $ createDirs (take 1 (parents path0))+ where+ parents = reverse . scanl1 (</>) . splitDirectories . normalise++ createDirs [] = return ()+ createDirs (dir:[]) = createDir dir throwIO+ createDirs (dir:dirs) =+ createDir dir $ \_ -> do+ createDirs dirs+ createDir dir throwIO++ createDir :: FilePath -> (IOException -> IO ()) -> IO ()+ createDir dir notExistHandler = do+ r <- tryIO $ createDirectoryVerbose verbosity dir+ case (r :: Either IOException ()) of+ Right () -> return ()+ Left e+ | isDoesNotExistError e -> notExistHandler e+ -- createDirectory (and indeed POSIX mkdir) does not distinguish+ -- between a dir already existing and a file already existing. So we+ -- check for it here. Unfortunately there is a slight race condition+ -- here, but we think it is benign. It could report an exception in+ -- the case that the dir did exist but another process deletes the+ -- directory and creates a file in its place before we can check+ -- that the directory did indeed exist.+ | isAlreadyExistsError e -> (do+ isDir <- doesDirectoryExist dir+ unless isDir $ throwIO e+ ) `catchIO` ((\_ -> return ()) :: IOException -> IO ())+ | otherwise -> throwIO e++createDirectoryVerbose :: Verbosity -> FilePath -> IO ()+createDirectoryVerbose verbosity dir = withFrozenCallStack $ do+ info verbosity $ "creating " ++ dir+ createDirectory dir+ setDirOrdinary dir++-- | Copies a file without copying file permissions. The target file is created+-- with default permissions. Any existing target file is replaced.+--+-- At higher verbosity levels it logs an info message.+--+copyFileVerbose :: Verbosity -> FilePath -> FilePath -> IO ()+copyFileVerbose verbosity src dest = withFrozenCallStack $ do+ info verbosity ("copy " ++ src ++ " to " ++ dest)+ copyFile src dest++-- | Install an ordinary file. This is like a file copy but the permissions+-- are set appropriately for an installed file. On Unix it is \"-rw-r--r--\"+-- while on Windows it uses the default permissions for the target directory.+--+installOrdinaryFile :: Verbosity -> FilePath -> FilePath -> IO ()+installOrdinaryFile verbosity src dest = withFrozenCallStack $ do+ info verbosity ("Installing " ++ src ++ " to " ++ dest)+ copyOrdinaryFile src dest++-- | Install an executable file. This is like a file copy but the permissions+-- are set appropriately for an installed file. On Unix it is \"-rwxr-xr-x\"+-- while on Windows it uses the default permissions for the target directory.+--+installExecutableFile :: Verbosity -> FilePath -> FilePath -> IO ()+installExecutableFile verbosity src dest = withFrozenCallStack $ do+ info verbosity ("Installing executable " ++ src ++ " to " ++ dest)+ copyExecutableFile src dest++-- | Install a file that may or not be executable, preserving permissions.+installMaybeExecutableFile :: Verbosity -> FilePath -> FilePath -> IO ()+installMaybeExecutableFile verbosity src dest = withFrozenCallStack $ do+ perms <- getPermissions src+ if (executable perms) --only checks user x bit+ then installExecutableFile verbosity src dest+ else installOrdinaryFile verbosity src dest++-- | Given a relative path to a file, copy it to the given directory, preserving+-- the relative path and creating the parent directories if needed.+copyFileTo :: Verbosity -> FilePath -> FilePath -> IO ()+copyFileTo verbosity dir file = withFrozenCallStack $ do+ let targetFile = dir </> file+ createDirectoryIfMissingVerbose verbosity True (takeDirectory targetFile)+ installOrdinaryFile verbosity file targetFile++-- | Common implementation of 'copyFiles', 'installOrdinaryFiles',+-- 'installExecutableFiles' and 'installMaybeExecutableFiles'.+copyFilesWith :: (Verbosity -> FilePath -> FilePath -> IO ())+ -> Verbosity -> FilePath -> [(FilePath, FilePath)] -> IO ()+copyFilesWith doCopy verbosity targetDir srcFiles = withFrozenCallStack $ do++ -- Create parent directories for everything+ let dirs = map (targetDir </>) . nub . map (takeDirectory . snd) $ srcFiles+ traverse_ (createDirectoryIfMissingVerbose verbosity True) dirs++ -- Copy all the files+ sequence_ [ let src = srcBase </> srcFile+ dest = targetDir </> srcFile+ in doCopy verbosity src dest+ | (srcBase, srcFile) <- srcFiles ]++-- | Copies a bunch of files to a target directory, preserving the directory+-- structure in the target location. The target directories are created if they+-- do not exist.+--+-- The files are identified by a pair of base directory and a path relative to+-- that base. It is only the relative part that is preserved in the+-- destination.+--+-- For example:+--+-- > copyFiles normal "dist/src"+-- > [("", "src/Foo.hs"), ("dist/build/", "src/Bar.hs")]+--+-- This would copy \"src\/Foo.hs\" to \"dist\/src\/src\/Foo.hs\" and+-- copy \"dist\/build\/src\/Bar.hs\" to \"dist\/src\/src\/Bar.hs\".+--+-- This operation is not atomic. Any IO failure during the copy (including any+-- missing source files) leaves the target in an unknown state so it is best to+-- use it with a freshly created directory so that it can be simply deleted if+-- anything goes wrong.+--+copyFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)] -> IO ()+copyFiles v fp fs = withFrozenCallStack (copyFilesWith copyFileVerbose v fp fs)++-- | This is like 'copyFiles' but uses 'installOrdinaryFile'.+--+installOrdinaryFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)] -> IO ()+installOrdinaryFiles v fp fs = withFrozenCallStack (copyFilesWith installOrdinaryFile v fp fs)++-- | This is like 'copyFiles' but uses 'installExecutableFile'.+--+installExecutableFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)]+ -> IO ()+installExecutableFiles v fp fs = withFrozenCallStack (copyFilesWith installExecutableFile v fp fs)++-- | This is like 'copyFiles' but uses 'installMaybeExecutableFile'.+--+installMaybeExecutableFiles :: Verbosity -> FilePath -> [(FilePath, FilePath)]+ -> IO ()+installMaybeExecutableFiles v fp fs = withFrozenCallStack (copyFilesWith installMaybeExecutableFile v fp fs)++-- | This installs all the files in a directory to a target location,+-- preserving the directory layout. All the files are assumed to be ordinary+-- rather than executable files.+--+installDirectoryContents :: Verbosity -> FilePath -> FilePath -> IO ()+installDirectoryContents verbosity srcDir destDir = withFrozenCallStack $ do+ info verbosity ("copy directory '" ++ srcDir ++ "' to '" ++ destDir ++ "'.")+ srcFiles <- getDirectoryContentsRecursive srcDir+ installOrdinaryFiles verbosity destDir [ (srcDir, f) | f <- srcFiles ]++-- | Recursively copy the contents of one directory to another path.+copyDirectoryRecursive :: Verbosity -> FilePath -> FilePath -> IO ()+copyDirectoryRecursive verbosity srcDir destDir = withFrozenCallStack $ do+ info verbosity ("copy directory '" ++ srcDir ++ "' to '" ++ destDir ++ "'.")+ srcFiles <- getDirectoryContentsRecursive srcDir+ copyFilesWith (const copyFile) verbosity destDir [ (srcDir, f)+ | f <- srcFiles ]++-------------------+-- File permissions++-- | Like 'doesFileExist', but also checks that the file is executable.+doesExecutableExist :: FilePath -> IO Bool+doesExecutableExist f = do+ exists <- doesFileExist f+ if exists+ then do perms <- getPermissions f+ return (executable perms)+ else return False++---------------------------+-- Temporary files and dirs++-- | Advanced options for 'withTempFile' and 'withTempDirectory'.+data TempFileOptions = TempFileOptions {+ optKeepTempFiles :: Bool -- ^ Keep temporary files?+ }++defaultTempFileOptions :: TempFileOptions+defaultTempFileOptions = TempFileOptions { optKeepTempFiles = False }++-- | Use a temporary filename that doesn't already exist.+--+withTempFile :: FilePath -- ^ Temp dir to create the file in+ -> String -- ^ File name template. See 'openTempFile'.+ -> (FilePath -> Handle -> IO a) -> IO a+withTempFile tmpDir template action =+ withTempFileEx defaultTempFileOptions tmpDir template action++-- | A version of 'withTempFile' that additionally takes a 'TempFileOptions'+-- argument.+withTempFileEx :: TempFileOptions+ -> FilePath -- ^ Temp dir to create the file in+ -> String -- ^ File name template. See 'openTempFile'.+ -> (FilePath -> Handle -> IO a) -> IO a+withTempFileEx opts tmpDir template action =+ Exception.bracket+ (openTempFile tmpDir template)+ (\(name, handle) -> do hClose handle+ unless (optKeepTempFiles opts) $+ handleDoesNotExist () . removeFile $ name)+ (withLexicalCallStack (\x -> uncurry action x))++-- | Create and use a temporary directory.+--+-- Creates a new temporary directory inside the given directory, making use+-- of the template. The temp directory is deleted after use. For example:+--+-- > withTempDirectory verbosity "src" "sdist." $ \tmpDir -> do ...+--+-- The @tmpDir@ will be a new subdirectory of the given directory, e.g.+-- @src/sdist.342@.+--+withTempDirectory :: Verbosity -> FilePath -> String -> (FilePath -> IO a) -> IO a+withTempDirectory verbosity targetDir template f = withFrozenCallStack $+ withTempDirectoryEx verbosity defaultTempFileOptions targetDir template+ (withLexicalCallStack (\x -> f x))++-- | A version of 'withTempDirectory' that additionally takes a+-- 'TempFileOptions' argument.+withTempDirectoryEx :: Verbosity -> TempFileOptions+ -> FilePath -> String -> (FilePath -> IO a) -> IO a+withTempDirectoryEx _verbosity opts targetDir template f = withFrozenCallStack $+ Exception.bracket+ (createTempDirectory targetDir template)+ (unless (optKeepTempFiles opts)+ . handleDoesNotExist () . removeDirectoryRecursive)+ (withLexicalCallStack (\x -> f x))++-----------------------------------+-- Safely reading and writing files++-- | Write a file but only if it would have new content. If we would be writing+-- the same as the existing content then leave the file as is so that we do not+-- update the file's modification time.+--+-- NB: Before Cabal-3.0 the file content was assumed to be+-- ASCII-representable. Since Cabal-3.0 the file is assumed to be+-- UTF-8 encoded.+rewriteFileEx :: Verbosity -> FilePath -> String -> IO ()+rewriteFileEx verbosity path =+ rewriteFileLBS verbosity path . toUTF8LBS++-- | Same as `rewriteFileEx` but for 'ByteString's.+rewriteFileLBS :: Verbosity -> FilePath -> BS.ByteString -> IO ()+rewriteFileLBS verbosity path newContent =+ flip catchIO mightNotExist $ do+ existingContent <- annotateIO verbosity $ BS.readFile path+ _ <- evaluate (BS.length existingContent)+ unless (existingContent == newContent) $+ annotateIO verbosity $+ writeFileAtomic path newContent+ where+ mightNotExist e | isDoesNotExistError e+ = annotateIO verbosity $ writeFileAtomic path newContent+ | otherwise+ = ioError e+++-- | The path name that represents the current directory.+-- In Unix, it's @\".\"@, but this is system-specific.+-- (E.g. AmigaOS uses the empty string @\"\"@ for the current directory.)+currentDir :: FilePath+currentDir = "."++shortRelativePath :: FilePath -> FilePath -> FilePath+shortRelativePath from to =+ case dropCommonPrefix (splitDirectories from) (splitDirectories to) of+ (stuff, path) -> joinPath (map (const "..") stuff ++ path)+ where+ dropCommonPrefix :: Eq a => [a] -> [a] -> ([a],[a])+ dropCommonPrefix (x:xs) (y:ys)+ | 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 =+ -- System.FilePath's extension handling functions are horribly+ -- inconsistent, consider:+ --+ -- isExtensionOf "" "foo" == False but+ -- isExtensionOf "" "foo." == True.+ --+ -- On the other hand stripExtension doesn't remove the empty extension:+ --+ -- stripExtension "" "foo." == Just "foo."+ --+ -- Since by "" in exeExtensions we mean 'no extension' anyways we can+ -- just always ignore it here.+ let exts = [ ext | ext <- exeExtensions, ext /= "" ] in+ fromMaybe filepath $ do+ ext <- find (`FilePath.isExtensionOf` filepath) exts+ ext `FilePath.stripExtension` filepath++-- | List of possible executable file extensions on the current build+-- 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+-- ------------------------------------------------------------++-- | Package description file (/pkgname/@.cabal@)+defaultPackageDesc :: Verbosity -> IO FilePath+defaultPackageDesc verbosity = tryFindPackageDesc verbosity currentDir++-- |Find a package description file in the given directory. Looks for+-- @.cabal@ files.+findPackageDesc :: FilePath -- ^Where to look+ -> IO (Either String FilePath) -- ^<pkgname>.cabal+findPackageDesc = findPackageDescCwd "."++-- | @since 3.4.0.0+findPackageDescCwd+ :: FilePath -- ^ project root+ -> FilePath -- ^ relative directory+ -> IO (Either String FilePath) -- ^ <pkgname>.cabal relative to the project root+findPackageDescCwd cwd dir+ = do files <- getDirectoryContents (cwd </> 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 . snd)+ [ (dir </> file, cwd </> dir </> file)+ | file <- files+ , let (name, ext) = splitExtension file+ , not (null name) && ext == ".cabal" ]+ case map fst cabalFiles of+ [] -> return (Left noDesc)+ [cabalFile] -> return (Right cabalFile)+ multiple -> return (Left $ 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++-- |Like 'findPackageDesc', but calls 'die' in case of error.+tryFindPackageDesc :: Verbosity -> FilePath -> IO FilePath+tryFindPackageDesc verbosity dir =+ either (die' verbosity) return =<< findPackageDesc dir++-- | Like 'findPackageDescCwd', but calls 'die' in case of error.+--+-- @since 3.4.0.0+tryFindPackageDescCwd :: Verbosity -> FilePath -> FilePath -> IO FilePath+tryFindPackageDescCwd verbosity cwd dir =+ either (die' verbosity) return =<< findPackageDescCwd cwd dir++-- |Find auxiliary package information in the given directory.+-- Looks for @.buildinfo@ files.+findHookedPackageDesc+ :: Verbosity+ -> FilePath -- ^Directory to search+ -> IO (Maybe FilePath) -- ^/dir/@\/@/pkgname/@.buildinfo@, if present+findHookedPackageDesc verbosity dir = do+ files <- getDirectoryContents dir+ buildInfoFiles <- filterM doesFileExist+ [ dir </> file+ | file <- files+ , let (name, ext) = splitExtension file+ , not (null name) && ext == buildInfoExt ]+ case buildInfoFiles of+ [] -> return Nothing+ [f] -> return (Just f)+ _ -> die' verbosity ("Multiple files with extension " ++ buildInfoExt)++buildInfoExt :: String+buildInfoExt = ".buildinfo"
+ src/Distribution/Simple/Utils/Json.hs view
@@ -0,0 +1,46 @@+-- | Utility json lib for Cabal+-- TODO: Remove it again.+module Distribution.Simple.Utils.Json+ ( Json(..)+ , renderJson+ ) where++data Json = JsonArray [Json]+ | JsonBool !Bool+ | JsonNull+ | JsonNumber !Int+ | JsonObject [(String, Json)]+ | JsonString !String++renderJson :: Json -> ShowS+renderJson (JsonArray objs) =+ surround "[" "]" $ intercalate "," $ map renderJson objs+renderJson (JsonBool True) = showString "true"+renderJson (JsonBool False) = showString "false"+renderJson JsonNull = showString "null"+renderJson (JsonNumber n) = shows n+renderJson (JsonObject attrs) =+ surround "{" "}" $ intercalate "," $ map render attrs+ where+ render (k,v) = (surround "\"" "\"" $ showString' k) . showString ":" . renderJson v+renderJson (JsonString s) = surround "\"" "\"" $ showString' s++surround :: String -> String -> ShowS -> ShowS+surround begin end middle = showString begin . middle . showString end++showString' :: String -> ShowS+showString' xs = showStringWorker xs+ where+ showStringWorker :: String -> ShowS+ showStringWorker ('\"':as) = showString "\\\"" . showStringWorker as+ showStringWorker ('\\':as) = showString "\\\\" . showStringWorker as+ showStringWorker ('\'':as) = showString "\\\'" . showStringWorker as+ showStringWorker (x:as) = showString [x] . showStringWorker as+ showStringWorker [] = showString ""++intercalate :: String -> [ShowS] -> ShowS+intercalate sep = go+ where+ go [] = id+ go [x] = x+ go (x:xs) = x . showString' sep . go xs
+ src/Distribution/System.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.System+-- Copyright : Duncan Coutts 2007-2008+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Cabal often needs to do slightly different things on specific platforms. You+-- 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 \"mingw32\"). So to make it+-- more consistent and easy to use we have an 'OS' enumeration.+--+module Distribution.System (+ -- * Operating System+ OS(..),+ buildOS,++ -- * Machine Architecture+ Arch(..),+ buildArch,++ -- * Platform is a pair of arch and OS+ Platform(..),+ buildPlatform,+ platformFromTriple,++ -- * Internal+ knownOSs,+ knownArches,++ -- * Classification+ ClassificationStrictness (..),+ classifyOS,+ classifyArch,+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Control.Applicative (liftA2)++import qualified System.Info (os, arch)+import Distribution.Utils.Generic (lowercase)++import Distribution.Parsec+import Distribution.Pretty++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | How strict to be when classifying strings into the 'OS' and 'Arch' enums.+--+-- The reason we have multiple ways to do the classification is because there+-- are two situations where we need to do it.+--+-- For parsing OS and arch names in .cabal files we really want everyone to be+-- referring to the same or arch by the same name. Variety is not a virtue+-- in this case. We don't mind about case though.+--+-- For the System.Info.os\/arch different Haskell implementations use different+-- names for the same or\/arch. Also they tend to distinguish versions of an+-- OS\/arch which we just don't care about.+--+-- The 'Compat' classification allows us to recognise aliases that are already+-- in common use but it allows us to distinguish them from the canonical name+-- which enables us to warn about such deprecated aliases.+--+data ClassificationStrictness = Permissive | Compat | Strict++-- ------------------------------------------------------------+-- * Operating System+-- ------------------------------------------------------------++-- | These are the known OS names: Linux, Windows, OSX+-- ,FreeBSD, OpenBSD, NetBSD, DragonFly+-- ,Solaris, AIX, HPUX, IRIX+-- ,HaLVM ,Hurd ,IOS, Android,Ghcjs+--+-- The following aliases can also be used:,+-- * Windows aliases: mingw32, win32, cygwin32+-- * OSX alias: darwin+-- * Hurd alias: gnu+-- * FreeBSD alias: kfreebsdgnu+-- * Solaris alias: solaris2+--+data OS = Linux | Windows | OSX -- tier 1 desktop OSs+ | FreeBSD | OpenBSD | NetBSD -- other free Unix OSs+ | DragonFly+ | Solaris | AIX | HPUX | IRIX -- ageing Unix OSs+ | HaLVM -- bare metal / VMs / hypervisors+ | Hurd -- GNU's microkernel+ | IOS | Android -- mobile OSs+ | Ghcjs+ | OtherOS String+ deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)++instance Binary OS+instance Structured OS+instance NFData OS where rnf = genericRnf++knownOSs :: [OS]+knownOSs = [Linux, Windows, OSX+ ,FreeBSD, OpenBSD, NetBSD, DragonFly+ ,Solaris, AIX, HPUX, IRIX+ ,HaLVM+ ,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"]+osAliases Compat Solaris = ["solaris2"]+osAliases Permissive Android = ["linux-android", "linux-androideabi", "linux-androideabihf"]+osAliases Compat Android = ["linux-android"]+osAliases _ _ = []++instance Pretty OS where+ pretty (OtherOS name) = Disp.text name+ pretty other = Disp.text (lowercase (show other))++instance Parsec OS where+ parsec = classifyOS Compat <$> parsecIdent++++classifyOS :: ClassificationStrictness -> String -> OS+classifyOS strictness s =+ fromMaybe (OtherOS s) $ lookup (lowercase s) osMap+ where+ osMap = [ (name, os)+ | os <- knownOSs+ , name <- prettyShow os : osAliases strictness os ]++buildOS :: OS+buildOS = classifyOS Permissive System.Info.os++-- ------------------------------------------------------------+-- * Machine Architecture+-- ------------------------------------------------------------++-- | These are the known Arches: I386, X86_64, PPC, PPC64, Sparc,+-- Arm, AArch64, Mips, SH, IA64, S39, Alpha, Hppa, Rs6000, M68k,+-- Vax, and JavaScript.+--+-- The following aliases can also be used:+-- * PPC alias: powerpc+-- * PPC64 alias : powerpc64, powerpc64le+-- * Sparc aliases: sparc64, sun4+-- * Mips aliases: mipsel, mipseb+-- * Arm aliases: armeb, armel+-- * AArch64 aliases: arm64+--+data Arch = I386 | X86_64 | PPC | PPC64 | Sparc+ | Arm | AArch64 | Mips | SH+ | IA64 | S390+ | Alpha | Hppa | Rs6000+ | M68k | Vax+ | JavaScript+ | OtherArch String+ deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)++instance Binary Arch+instance Structured Arch+instance NFData Arch where rnf = genericRnf++knownArches :: [Arch]+knownArches = [I386, X86_64, PPC, PPC64, Sparc+ ,Arm, AArch64, Mips, SH+ ,IA64, S390+ ,Alpha, Hppa, Rs6000+ ,M68k, Vax+ ,JavaScript]++archAliases :: ClassificationStrictness -> Arch -> [String]+archAliases Strict _ = []+archAliases Compat _ = []+archAliases _ PPC = ["powerpc"]+archAliases _ PPC64 = ["powerpc64", "powerpc64le"]+archAliases _ Sparc = ["sparc64", "sun4"]+archAliases _ Mips = ["mipsel", "mipseb"]+archAliases _ Arm = ["armeb", "armel"]+archAliases _ AArch64 = ["arm64"]+archAliases _ _ = []++instance Pretty Arch where+ pretty (OtherArch name) = Disp.text name+ pretty other = Disp.text (lowercase (show other))++instance Parsec Arch where+ parsec = classifyArch Strict <$> parsecIdent++classifyArch :: ClassificationStrictness -> String -> Arch+classifyArch strictness s =+ fromMaybe (OtherArch s) $ lookup (lowercase s) archMap+ where+ archMap = [ (name, arch)+ | arch <- knownArches+ , name <- prettyShow arch : archAliases strictness arch ]++buildArch :: Arch+buildArch = classifyArch Permissive System.Info.arch++-- ------------------------------------------------------------+-- * Platform+-- ------------------------------------------------------------++data Platform = Platform Arch OS+ deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)++instance Binary Platform+instance Structured Platform+instance NFData Platform where rnf = genericRnf++instance Pretty Platform where+ pretty (Platform arch os) = pretty arch <<>> Disp.char '-' <<>> pretty os++instance Parsec Platform where+ -- 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.+ parsec = do+ arch <- parsecDashlessArch+ _ <- P.char '-'+ os <- parsec+ return (Platform arch os)+ where+ parsecDashlessArch = classifyArch Strict <$> dashlessIdent++ dashlessIdent = liftA2 (:) firstChar rest+ where+ firstChar = P.satisfy isAlpha+ rest = P.munch (\c -> isAlphaNum c || c == '_')++-- | The platform Cabal was compiled on. In most cases,+-- @LocalBuildInfo.hostPlatform@ should be used instead (the platform we're+-- targeting).+buildPlatform :: Platform+buildPlatform = Platform buildArch buildOS++-- Utils:++parsecIdent :: CabalParsing m => m String+parsecIdent = (:) <$> firstChar <*> rest+ where+ firstChar = P.satisfy isAlpha+ rest = P.munch (\c -> isAlphaNum c || c == '_' || c == '-')++platformFromTriple :: String -> Maybe Platform+platformFromTriple triple =+ either (const Nothing) Just $ explicitEitherParsec parseTriple triple+ where parseWord = P.munch1 (\c -> isAlphaNum c || c == '_')+ parseTriple = do+ arch <- fmap (classifyArch Permissive) parseWord+ _ <- P.char '-'+ _ <- parseWord -- Skip vendor+ _ <- P.char '-'+ os <- fmap (classifyOS Permissive) parsecIdent -- OS may have hyphens, like+ -- 'nto-qnx'+ return $ Platform arch os
+ src/Distribution/TestSuite.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.TestSuite+-- Copyright : Thomas Tuegel 2010+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This module defines the detailed test suite interface which makes it+-- possible to expose individual tests to Cabal or other test agents.++module Distribution.TestSuite+ ( TestInstance(..)+ , OptionDescr(..)+ , OptionType(..)+ , Test(..)+ , Options+ , Progress(..)+ , Result(..)+ , testGroup+ ) where++import Prelude ()+import Distribution.Compat.Prelude++data TestInstance = TestInstance+ { run :: IO Progress -- ^ Perform the test.+ , name :: String -- ^ A name for the test, unique within a+ -- test suite.+ , tags :: [String] -- ^ Users can select groups of tests by+ -- their tags.+ , options :: [OptionDescr] -- ^ Descriptions of the options recognized+ -- by this test.+ , setOption :: String -> String -> Either String TestInstance+ -- ^ Try to set the named option to the given value. Returns an error+ -- message if the option is not supported or the value could not be+ -- correctly parsed; otherwise, a 'TestInstance' with the option set to+ -- the given value is returned.+ }++data OptionDescr = OptionDescr+ { optionName :: String+ , optionDescription :: String -- ^ A human-readable description of the+ -- option to guide the user setting it.+ , optionType :: OptionType+ , optionDefault :: Maybe String+ }+ deriving (Eq, Read, Show)++data OptionType+ = OptionFile+ { optionFileMustExist :: Bool+ , optionFileIsDir :: Bool+ , optionFileExtensions :: [String]+ }+ | OptionString+ { optionStringMultiline :: Bool+ }+ | OptionNumber+ { optionNumberIsInt :: Bool+ , optionNumberBounds :: (Maybe String, Maybe String)+ }+ | OptionBool+ | OptionEnum [String]+ | OptionSet [String]+ | OptionRngSeed+ deriving (Eq, Read, Show)++data Test+ = Test TestInstance+ | Group+ { groupName :: String+ , concurrently :: Bool+ -- ^ If true, then children of this group may be run in parallel.+ -- Note that this setting is not inherited by children. In+ -- particular, consider a group F with "concurrently = False" that+ -- has some children, including a group T with "concurrently =+ -- True". The children of group T may be run concurrently with each+ -- other, as long as none are run at the same time as any of the+ -- direct children of group F.+ , groupTests :: [Test]+ }+ | ExtraOptions [OptionDescr] Test++type Options = [(String, String)]++data Progress = Finished Result+ | Progress String (IO Progress)++data Result = Pass+ | Fail String+ | Error String+ deriving (Eq, Read, Show)++-- | Create a named group of tests, which are assumed to be safe to run in+-- parallel.+testGroup :: String -> [Test] -> Test+testGroup n ts = Group { groupName = n, concurrently = True, groupTests = ts }
+ src/Distribution/Text.hs view
@@ -0,0 +1,12 @@+-- Since @3.0@ this is a compat module.+module Distribution.Text (display, simpleParse) where+{- {-# DEPRECATED "Use Distribution.Parsec or Distribution.Pretty" #-} -}++import Distribution.Pretty+import Distribution.Parsec++display :: Pretty a => a -> String+display = prettyShow++simpleParse :: Parsec a => String -> Maybe a+simpleParse = simpleParsec
+ src/Distribution/Types/AbiDependency.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.AbiDependency where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty++import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.Package as Package+import qualified Text.PrettyPrint as Disp++-- | An ABI dependency is a dependency on a library which also+-- records the ABI hash ('abiHash') of the library it depends+-- on.+--+-- The primary utility of this is to enable an extra sanity when+-- GHC loads libraries: it can check if the dependency has a matching+-- ABI and if not, refuse to load this library. This information+-- is critical if we are shadowing libraries; differences in the+-- ABI hash let us know what packages get shadowed by the new version+-- of a package.+data AbiDependency = AbiDependency {+ depUnitId :: Package.UnitId,+ depAbiHash :: Package.AbiHash+ }+ deriving (Eq, Generic, Read, Show, Typeable)++instance Pretty AbiDependency where+ pretty (AbiDependency uid abi) =+ pretty uid <<>> Disp.char '=' <<>> pretty abi++instance Parsec AbiDependency where+ parsec = do+ uid <- parsec+ _ <- P.char '='+ abi <- parsec+ return (AbiDependency uid abi)++instance Binary AbiDependency+instance Structured AbiDependency+instance NFData AbiDependency where rnf = genericRnf
+ src/Distribution/Types/AbiHash.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Distribution.Types.AbiHash+ ( AbiHash, unAbiHash, mkAbiHash+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.ShortText++import qualified Distribution.Compat.CharParsing as P+import Distribution.Pretty+import Distribution.Parsec++import Text.PrettyPrint (text)++-- | ABI Hashes+--+-- Use 'mkAbiHash' and 'unAbiHash' to convert from/to a+-- 'String'.+--+-- This type is opaque since @Cabal-2.0@+--+-- @since 2.0.0.2+newtype AbiHash = AbiHash ShortText+ deriving (Eq, Show, Read, Generic, Typeable)++-- | Construct a 'AbiHash' from a 'String'+--+-- 'mkAbiHash' is the inverse to 'unAbiHash'+--+-- Note: No validations are performed to ensure that the resulting+-- 'AbiHash' is valid+--+-- @since 2.0.0.2+unAbiHash :: AbiHash -> String+unAbiHash (AbiHash h) = fromShortText h++-- | Convert 'AbiHash' to 'String'+--+-- @since 2.0.0.2+mkAbiHash :: String -> AbiHash+mkAbiHash = AbiHash . toShortText++-- | 'mkAbiHash'+--+-- @since 2.0.0.2+instance IsString AbiHash where+ fromString = mkAbiHash++instance Binary AbiHash+instance Structured AbiHash+instance NFData AbiHash where rnf = genericRnf++instance Pretty AbiHash where+ pretty = text . unAbiHash++instance Parsec AbiHash where+ parsec = fmap mkAbiHash (P.munch isAlphaNum)
+ src/Distribution/Types/AnnotatedId.hs view
@@ -0,0 +1,34 @@+module Distribution.Types.AnnotatedId (+ AnnotatedId(..)+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Package+import Distribution.Types.ComponentName++-- | An 'AnnotatedId' is a 'ComponentId', 'UnitId', etc.+-- which is annotated with some other useful information+-- that is useful for printing to users, etc.+--+-- Invariant: if ann_id x == ann_id y, then ann_pid x == ann_pid y+-- and ann_cname x == ann_cname y+data AnnotatedId id = AnnotatedId {+ ann_pid :: PackageId,+ ann_cname :: ComponentName,+ ann_id :: id+ }+ deriving (Show)++instance Eq id => Eq (AnnotatedId id) where+ x == y = ann_id x == ann_id y++instance Ord id => Ord (AnnotatedId id) where+ compare x y = compare (ann_id x) (ann_id y)++instance Package (AnnotatedId id) where+ packageId = ann_pid++instance Functor AnnotatedId where+ fmap f (AnnotatedId pid cn x) = AnnotatedId pid cn (f x)
+ src/Distribution/Types/Benchmark.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.Benchmark (+ Benchmark(..),+ emptyBenchmark,+ benchmarkType,+ benchmarkModules,+ benchmarkModulesAutogen+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.BuildInfo+import Distribution.Types.BenchmarkType+import Distribution.Types.BenchmarkInterface+import Distribution.Types.UnqualComponentName++import Distribution.ModuleName++import qualified Distribution.Types.BuildInfo.Lens as L++-- | A \"benchmark\" stanza in a cabal file.+--+data Benchmark = Benchmark {+ benchmarkName :: UnqualComponentName,+ benchmarkInterface :: BenchmarkInterface,+ benchmarkBuildInfo :: BuildInfo+ }+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary Benchmark+instance Structured Benchmark+instance NFData Benchmark where rnf = genericRnf++instance L.HasBuildInfo Benchmark where+ buildInfo f (Benchmark x1 x2 x3) = fmap (\y1 -> Benchmark x1 x2 y1) (f x3)++instance Monoid Benchmark where+ mempty = Benchmark {+ benchmarkName = mempty,+ benchmarkInterface = mempty,+ benchmarkBuildInfo = mempty+ }+ mappend = (<>)++instance Semigroup Benchmark where+ a <> b = Benchmark {+ benchmarkName = combine' benchmarkName,+ benchmarkInterface = combine benchmarkInterface,+ benchmarkBuildInfo = combine benchmarkBuildInfo+ }+ where combine field = field a `mappend` field b+ combine' field = case ( unUnqualComponentName $ field a+ , unUnqualComponentName $ field b) of+ ("", _) -> field b+ (_, "") -> field a+ (x, y) -> error $ "Ambiguous values for test field: '"+ ++ x ++ "' and '" ++ y ++ "'"++emptyBenchmark :: Benchmark+emptyBenchmark = mempty++benchmarkType :: Benchmark -> BenchmarkType+benchmarkType benchmark = case benchmarkInterface benchmark of+ BenchmarkExeV10 ver _ -> BenchmarkTypeExe ver+ BenchmarkUnsupported benchmarktype -> benchmarktype++-- | Get all the module names from a benchmark.+benchmarkModules :: Benchmark -> [ModuleName]+benchmarkModules benchmark = otherModules (benchmarkBuildInfo benchmark)++-- | Get all the auto generated module names from a benchmark.+-- This are a subset of 'benchmarkModules'.+benchmarkModulesAutogen :: Benchmark -> [ModuleName]+benchmarkModulesAutogen benchmark = autogenModules (benchmarkBuildInfo benchmark)
+ src/Distribution/Types/Benchmark/Lens.hs view
@@ -0,0 +1,27 @@+module Distribution.Types.Benchmark.Lens (+ Benchmark,+ module Distribution.Types.Benchmark.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.Benchmark (Benchmark)+import Distribution.Types.BenchmarkInterface (BenchmarkInterface)+import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.UnqualComponentName (UnqualComponentName)++import qualified Distribution.Types.Benchmark as T++benchmarkName :: Lens' Benchmark UnqualComponentName+benchmarkName f s = fmap (\x -> s { T.benchmarkName = x }) (f (T.benchmarkName s))+{-# INLINE benchmarkName #-}++benchmarkInterface :: Lens' Benchmark BenchmarkInterface+benchmarkInterface f s = fmap (\x -> s { T.benchmarkInterface = x }) (f (T.benchmarkInterface s))+{-# INLINE benchmarkInterface #-}++benchmarkBuildInfo :: Lens' Benchmark BuildInfo+benchmarkBuildInfo f s = fmap (\x -> s { T.benchmarkBuildInfo = x }) (f (T.benchmarkBuildInfo s))+{-# INLINE benchmarkBuildInfo #-}
+ src/Distribution/Types/BenchmarkInterface.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.BenchmarkInterface (+ BenchmarkInterface(..),+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.BenchmarkType+import Distribution.Version++-- | The benchmark interfaces that are currently defined. Each+-- benchmark must specify which interface it supports.+--+-- More interfaces may be defined in future, either new revisions or+-- totally new interfaces.+--+data BenchmarkInterface =++ -- | Benchmark interface \"exitcode-stdio-1.0\". The benchmark+ -- takes the form of an executable. It returns a zero exit code+ -- for success, non-zero for failure. The stdout and stderr+ -- channels may be logged. It takes no command line parameters+ -- and nothing on stdin.+ --+ BenchmarkExeV10 Version FilePath++ -- | A benchmark that does not conform to one of the above+ -- interfaces for the given reason (e.g. unknown benchmark type).+ --+ | BenchmarkUnsupported BenchmarkType+ deriving (Eq, Generic, Read, Show, Typeable, Data)++instance Binary BenchmarkInterface+instance Structured BenchmarkInterface+instance NFData BenchmarkInterface where rnf = genericRnf++instance Monoid BenchmarkInterface where+ mempty = BenchmarkUnsupported (BenchmarkTypeUnknown mempty nullVersion)+ mappend = (<>)++instance Semigroup BenchmarkInterface where+ a <> (BenchmarkUnsupported _) = a+ _ <> b = b
+ src/Distribution/Types/BenchmarkType.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Distribution.Types.BenchmarkType (+ BenchmarkType(..),+ knownBenchmarkTypes,+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Version+import Text.PrettyPrint (char, text)++-- | The \"benchmark-type\" field in the benchmark stanza.+--+data BenchmarkType = BenchmarkTypeExe Version+ -- ^ \"type: exitcode-stdio-x.y\"+ | BenchmarkTypeUnknown String Version+ -- ^ Some unknown benchmark type e.g. \"type: foo\"+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary BenchmarkType+instance Structured BenchmarkType+instance NFData BenchmarkType where rnf = genericRnf++knownBenchmarkTypes :: [BenchmarkType]+knownBenchmarkTypes = [ BenchmarkTypeExe (mkVersion [1,0]) ]++instance Pretty BenchmarkType where+ pretty (BenchmarkTypeExe ver) = text "exitcode-stdio-" <<>> pretty ver+ pretty (BenchmarkTypeUnknown name ver) = text name <<>> char '-' <<>> pretty ver++instance Parsec BenchmarkType where+ parsec = parsecStandard $ \ver name -> case name of+ "exitcode-stdio" -> BenchmarkTypeExe ver+ _ -> BenchmarkTypeUnknown name ver
+ src/Distribution/Types/BuildInfo.hs view
@@ -0,0 +1,266 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.BuildInfo (+ BuildInfo(..),++ emptyBuildInfo,+ allLanguages,+ allExtensions,+ usedExtensions,+ usesTemplateHaskellOrQQ,++ hcOptions,+ hcProfOptions,+ hcSharedOptions,+ hcStaticOptions,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.Mixin+import Distribution.Types.Dependency+import Distribution.Types.ExeDependency+import Distribution.Types.LegacyExeDependency+import Distribution.Types.PkgconfigDependency+import Distribution.Utils.Path++import Distribution.ModuleName+import Distribution.Compiler+import Language.Haskell.Extension++-- Consider refactoring into executable and library versions.+data BuildInfo = BuildInfo {+ -- | component is buildable here+ buildable :: Bool,+ -- | Tools needed to build this bit.+ --+ -- This is a legacy field that 'buildToolDepends' largely supersedes.+ --+ -- Unless use are very sure what you are doing, use the functions in+ -- "Distribution.Simple.BuildToolDepends" rather than accessing this+ -- field directly.+ buildTools :: [LegacyExeDependency],+ -- | Haskell tools needed to build this bit+ --+ -- This field is better than 'buildTools' because it allows one to+ -- precisely specify an executable in a package.+ --+ -- Unless use are very sure what you are doing, use the functions in+ -- "Distribution.Simple.BuildToolDepends" rather than accessing this+ -- field directly.+ buildToolDepends :: [ExeDependency],+ cppOptions :: [String], -- ^ options for pre-processing Haskell code+ asmOptions :: [String], -- ^ options for assmebler+ cmmOptions :: [String], -- ^ options for C-- compiler+ ccOptions :: [String], -- ^ options for C compiler+ cxxOptions :: [String], -- ^ options for C++ compiler+ ldOptions :: [String], -- ^ options for linker+ hsc2hsOptions :: [String], -- ^ options for hsc2hs+ pkgconfigDepends :: [PkgconfigDependency], -- ^ pkg-config packages that are used+ frameworks :: [String], -- ^support frameworks for Mac OS X+ extraFrameworkDirs:: [String], -- ^ extra locations to find frameworks.+ asmSources :: [FilePath], -- ^ Assembly files.+ cmmSources :: [FilePath], -- ^ C-- files.+ cSources :: [FilePath],+ cxxSources :: [FilePath],+ jsSources :: [FilePath],+ hsSourceDirs :: [SymbolicPath PackageDir SourceDir], -- ^ where to look for the Haskell module hierarchy+ otherModules :: [ModuleName], -- ^ non-exposed or non-main modules+ virtualModules :: [ModuleName], -- ^ exposed modules that do not have a source file (e.g. @GHC.Prim@ from @ghc-prim@ package)+ autogenModules :: [ModuleName], -- ^ not present on sdist, Paths_* or user-generated with a custom Setup.hs++ defaultLanguage :: Maybe Language,-- ^ language used when not explicitly specified+ otherLanguages :: [Language], -- ^ other languages used within the package+ defaultExtensions :: [Extension], -- ^ language extensions used by all modules+ otherExtensions :: [Extension], -- ^ other language extensions used within the package+ oldExtensions :: [Extension], -- ^ the old extensions field, treated same as 'defaultExtensions'++ extraLibs :: [String], -- ^ what libraries to link with when compiling a program that uses your package+ extraGHCiLibs :: [String], -- ^ if present, overrides extraLibs when package is loaded with GHCi.+ extraBundledLibs :: [String], -- ^ if present, adds libs to hs-libraries, which become part of the package.+ -- Example: the Cffi library shipping with the rts, alognside the HSrts-1.0.a,.o,...+ -- Example 2: a library that is being built by a foreing tool (e.g. rust)+ -- and copied and registered together with this library. The+ -- logic on how this library is built will have to be encoded in a+ -- custom Setup for now. Otherwise cabal would need to lear how to+ -- call arbitrary library builders.+ extraLibFlavours :: [String], -- ^ Hidden Flag. This set of strings, will be appended to all libraries when+ -- copying. E.g. [libHS<name>_<flavour> | flavour <- extraLibFlavours]. This+ -- should only be needed in very specific cases, e.g. the `rts` package, where+ -- there are multiple copies of slightly differently built libs.+ extraDynLibFlavours :: [String], -- ^ Hidden Flag. This set of strings will be appended to all /dynamic/+ -- libraries when copying. This is particularly useful with the `rts` package,+ -- where we want different dynamic flavours of the RTS library to be installed.+ extraLibDirs :: [String],+ includeDirs :: [FilePath], -- ^directories to find .h files+ includes :: [FilePath], -- ^ The .h files to be found in includeDirs+ autogenIncludes :: [FilePath], -- ^ The .h files to be generated (e.g. by @autoconf@)+ installIncludes :: [FilePath], -- ^ .h files to install with the package+ options :: PerCompilerFlavor [String],+ profOptions :: PerCompilerFlavor [String],+ sharedOptions :: PerCompilerFlavor [String],+ staticOptions :: PerCompilerFlavor [String],+ customFieldsBI :: [(String,String)], -- ^Custom fields starting+ -- with x-, stored in a+ -- simple assoc-list.+ targetBuildDepends :: [Dependency], -- ^ Dependencies specific to a library or executable target+ mixins :: [Mixin]+ }+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary BuildInfo+instance Structured BuildInfo+instance NFData BuildInfo where rnf = genericRnf++instance Monoid BuildInfo where+ mempty = BuildInfo {+ buildable = True,+ buildTools = [],+ buildToolDepends = [],+ cppOptions = [],+ asmOptions = [],+ cmmOptions = [],+ ccOptions = [],+ cxxOptions = [],+ ldOptions = [],+ hsc2hsOptions = [],+ pkgconfigDepends = [],+ frameworks = [],+ extraFrameworkDirs = [],+ asmSources = [],+ cmmSources = [],+ cSources = [],+ cxxSources = [],+ jsSources = [],+ hsSourceDirs = [],+ otherModules = [],+ virtualModules = [],+ autogenModules = [],+ defaultLanguage = Nothing,+ otherLanguages = [],+ defaultExtensions = [],+ otherExtensions = [],+ oldExtensions = [],+ extraLibs = [],+ extraGHCiLibs = [],+ extraBundledLibs = [],+ extraLibFlavours = [],+ extraDynLibFlavours = [],+ extraLibDirs = [],+ includeDirs = [],+ includes = [],+ autogenIncludes = [],+ installIncludes = [],+ options = mempty,+ profOptions = mempty,+ sharedOptions = mempty,+ staticOptions = mempty,+ customFieldsBI = [],+ targetBuildDepends = [],+ mixins = []+ }+ mappend = (<>)++instance Semigroup BuildInfo where+ a <> b = BuildInfo {+ buildable = buildable a && buildable b,+ buildTools = combine buildTools,+ buildToolDepends = combine buildToolDepends,+ cppOptions = combine cppOptions,+ asmOptions = combine asmOptions,+ cmmOptions = combine cmmOptions,+ ccOptions = combine ccOptions,+ cxxOptions = combine cxxOptions,+ ldOptions = combine ldOptions,+ hsc2hsOptions = combine hsc2hsOptions,+ pkgconfigDepends = combine pkgconfigDepends,+ frameworks = combineNub frameworks,+ extraFrameworkDirs = combineNub extraFrameworkDirs,+ asmSources = combineNub asmSources,+ cmmSources = combineNub cmmSources,+ cSources = combineNub cSources,+ cxxSources = combineNub cxxSources,+ jsSources = combineNub jsSources,+ hsSourceDirs = combineNub hsSourceDirs,+ otherModules = combineNub otherModules,+ virtualModules = combineNub virtualModules,+ autogenModules = combineNub autogenModules,+ defaultLanguage = combineMby defaultLanguage,+ otherLanguages = combineNub otherLanguages,+ defaultExtensions = combineNub defaultExtensions,+ otherExtensions = combineNub otherExtensions,+ oldExtensions = combineNub oldExtensions,+ extraLibs = combine extraLibs,+ extraGHCiLibs = combine extraGHCiLibs,+ extraBundledLibs = combine extraBundledLibs,+ extraLibFlavours = combine extraLibFlavours,+ extraDynLibFlavours = combine extraDynLibFlavours,+ extraLibDirs = combineNub extraLibDirs,+ includeDirs = combineNub includeDirs,+ includes = combineNub includes,+ autogenIncludes = combineNub autogenIncludes,+ installIncludes = combineNub installIncludes,+ options = combine options,+ profOptions = combine profOptions,+ sharedOptions = combine sharedOptions,+ staticOptions = combine staticOptions,+ customFieldsBI = combine customFieldsBI,+ targetBuildDepends = combineNub targetBuildDepends,+ mixins = combine mixins+ }+ where+ combine field = field a `mappend` field b+ combineNub field = nub (combine field)+ combineMby field = field b `mplus` field a++emptyBuildInfo :: BuildInfo+emptyBuildInfo = mempty++-- | The 'Language's used by this component+--+allLanguages :: BuildInfo -> [Language]+allLanguages bi = maybeToList (defaultLanguage bi)+ ++ otherLanguages bi++-- | The 'Extension's that are used somewhere by this component+--+allExtensions :: BuildInfo -> [Extension]+allExtensions bi = usedExtensions bi+ ++ otherExtensions bi++-- | The 'Extensions' that are used by all modules in this component+--+usedExtensions :: BuildInfo -> [Extension]+usedExtensions bi = oldExtensions bi+ ++ defaultExtensions bi++-- | Whether any modules in this component use Template Haskell or+-- Quasi Quotes+usesTemplateHaskellOrQQ :: BuildInfo -> Bool+usesTemplateHaskellOrQQ bi = any p (allExtensions bi)+ where+ p ex = ex `elem`+ [EnableExtension TemplateHaskell, EnableExtension QuasiQuotes]++-- |Select options for a particular Haskell compiler.+hcOptions :: CompilerFlavor -> BuildInfo -> [String]+hcOptions = lookupHcOptions options++hcProfOptions :: CompilerFlavor -> BuildInfo -> [String]+hcProfOptions = lookupHcOptions profOptions++hcSharedOptions :: CompilerFlavor -> BuildInfo -> [String]+hcSharedOptions = lookupHcOptions sharedOptions++hcStaticOptions :: CompilerFlavor -> BuildInfo -> [String]+hcStaticOptions = lookupHcOptions staticOptions++lookupHcOptions :: (BuildInfo -> PerCompilerFlavor [String])+ -> CompilerFlavor -> BuildInfo -> [String]+lookupHcOptions f hc bi = case f bi of+ PerCompilerFlavor ghc ghcjs+ | hc == GHC -> ghc+ | hc == GHCJS -> ghcjs+ | otherwise -> mempty
+ src/Distribution/Types/BuildInfo/Lens.hs view
@@ -0,0 +1,342 @@+module Distribution.Types.BuildInfo.Lens (+ BuildInfo,+ HasBuildInfo (..),+ HasBuildInfos (..),+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Compiler (PerCompilerFlavor)+import Distribution.ModuleName (ModuleName)+import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.Dependency (Dependency)+import Distribution.Types.ExeDependency (ExeDependency)+import Distribution.Types.LegacyExeDependency (LegacyExeDependency)+import Distribution.Types.Mixin (Mixin)+import Distribution.Types.PkgconfigDependency (PkgconfigDependency)+import Distribution.Utils.Path+import Language.Haskell.Extension (Extension, Language)++import qualified Distribution.Types.BuildInfo as T++-- | Classy lenses for 'BuildInfo'.+class HasBuildInfo a where+ buildInfo :: Lens' a BuildInfo++ buildable :: Lens' a Bool+ buildable = buildInfo . buildable+ {-# INLINE buildable #-}++ buildTools :: Lens' a [LegacyExeDependency]+ buildTools = buildInfo . buildTools+ {-# INLINE buildTools #-}++ buildToolDepends :: Lens' a [ExeDependency]+ buildToolDepends = buildInfo . buildToolDepends+ {-# INLINE buildToolDepends #-}++ cppOptions :: Lens' a [String]+ cppOptions = buildInfo . cppOptions+ {-# INLINE cppOptions #-}++ asmOptions :: Lens' a [String]+ asmOptions = buildInfo . asmOptions+ {-# INLINE asmOptions #-}++ cmmOptions :: Lens' a [String]+ cmmOptions = buildInfo . cmmOptions+ {-# INLINE cmmOptions #-}++ ccOptions :: Lens' a [String]+ ccOptions = buildInfo . ccOptions+ {-# INLINE ccOptions #-}++ cxxOptions :: Lens' a [String]+ cxxOptions = buildInfo . cxxOptions+ {-# INLINE cxxOptions #-}++ ldOptions :: Lens' a [String]+ ldOptions = buildInfo . ldOptions+ {-# INLINE ldOptions #-}++ hsc2hsOptions :: Lens' a [String]+ hsc2hsOptions = buildInfo . hsc2hsOptions+ {-# INLINE hsc2hsOptions #-}++ pkgconfigDepends :: Lens' a [PkgconfigDependency]+ pkgconfigDepends = buildInfo . pkgconfigDepends+ {-# INLINE pkgconfigDepends #-}++ frameworks :: Lens' a [String]+ frameworks = buildInfo . frameworks+ {-# INLINE frameworks #-}++ extraFrameworkDirs :: Lens' a [String]+ extraFrameworkDirs = buildInfo . extraFrameworkDirs+ {-# INLINE extraFrameworkDirs #-}++ asmSources :: Lens' a [FilePath]+ asmSources = buildInfo . asmSources+ {-# INLINE asmSources #-}++ cmmSources :: Lens' a [FilePath]+ cmmSources = buildInfo . cmmSources+ {-# INLINE cmmSources #-}++ cSources :: Lens' a [FilePath]+ cSources = buildInfo . cSources+ {-# INLINE cSources #-}++ cxxSources :: Lens' a [FilePath]+ cxxSources = buildInfo . cxxSources+ {-# INLINE cxxSources #-}++ jsSources :: Lens' a [FilePath]+ jsSources = buildInfo . jsSources+ {-# INLINE jsSources #-}++ hsSourceDirs :: Lens' a [SymbolicPath PackageDir SourceDir]+ hsSourceDirs = buildInfo . hsSourceDirs+ {-# INLINE hsSourceDirs #-}++ otherModules :: Lens' a [ModuleName]+ otherModules = buildInfo . otherModules+ {-# INLINE otherModules #-}++ virtualModules :: Lens' a [ModuleName]+ virtualModules = buildInfo . virtualModules+ {-# INLINE virtualModules #-}++ autogenModules :: Lens' a [ModuleName]+ autogenModules = buildInfo . autogenModules+ {-# INLINE autogenModules #-}++ defaultLanguage :: Lens' a (Maybe Language)+ defaultLanguage = buildInfo . defaultLanguage+ {-# INLINE defaultLanguage #-}++ otherLanguages :: Lens' a [Language]+ otherLanguages = buildInfo . otherLanguages+ {-# INLINE otherLanguages #-}++ defaultExtensions :: Lens' a [Extension]+ defaultExtensions = buildInfo . defaultExtensions+ {-# INLINE defaultExtensions #-}++ otherExtensions :: Lens' a [Extension]+ otherExtensions = buildInfo . otherExtensions+ {-# INLINE otherExtensions #-}++ oldExtensions :: Lens' a [Extension]+ oldExtensions = buildInfo . oldExtensions+ {-# INLINE oldExtensions #-}++ extraLibs :: Lens' a [String]+ extraLibs = buildInfo . extraLibs+ {-# INLINE extraLibs #-}++ extraGHCiLibs :: Lens' a [String]+ extraGHCiLibs = buildInfo . extraGHCiLibs+ {-# INLINE extraGHCiLibs #-}++ extraBundledLibs :: Lens' a [String]+ extraBundledLibs = buildInfo . extraBundledLibs+ {-# INLINE extraBundledLibs #-}++ extraLibFlavours :: Lens' a [String]+ extraLibFlavours = buildInfo . extraLibFlavours+ {-# INLINE extraLibFlavours #-}++ extraDynLibFlavours :: Lens' a [String]+ extraDynLibFlavours = buildInfo . extraDynLibFlavours+ {-# INLINE extraDynLibFlavours #-}++ extraLibDirs :: Lens' a [String]+ extraLibDirs = buildInfo . extraLibDirs+ {-# INLINE extraLibDirs #-}++ includeDirs :: Lens' a [FilePath]+ includeDirs = buildInfo . includeDirs+ {-# INLINE includeDirs #-}++ includes :: Lens' a [FilePath]+ includes = buildInfo . includes+ {-# INLINE includes #-}++ autogenIncludes :: Lens' a [FilePath]+ autogenIncludes = buildInfo . autogenIncludes+ {-# INLINE autogenIncludes #-}++ installIncludes :: Lens' a [FilePath]+ installIncludes = buildInfo . installIncludes+ {-# INLINE installIncludes #-}++ options :: Lens' a (PerCompilerFlavor [String])+ options = buildInfo . options+ {-# INLINE options #-}++ profOptions :: Lens' a (PerCompilerFlavor [String])+ profOptions = buildInfo . profOptions+ {-# INLINE profOptions #-}++ sharedOptions :: Lens' a (PerCompilerFlavor [String])+ sharedOptions = buildInfo . sharedOptions+ {-# INLINE sharedOptions #-}++ staticOptions :: Lens' a (PerCompilerFlavor [String])+ staticOptions = buildInfo . staticOptions+ {-# INLINE staticOptions #-}++ customFieldsBI :: Lens' a [(String,String)]+ customFieldsBI = buildInfo . customFieldsBI+ {-# INLINE customFieldsBI #-}++ targetBuildDepends :: Lens' a [Dependency]+ targetBuildDepends = buildInfo . targetBuildDepends+ {-# INLINE targetBuildDepends #-}++ mixins :: Lens' a [Mixin]+ mixins = buildInfo . mixins+ {-# INLINE mixins #-}+++instance HasBuildInfo BuildInfo where+ buildInfo = id+ {-# INLINE buildInfo #-}++ buildable f s = fmap (\x -> s { T.buildable = x }) (f (T.buildable s))+ {-# INLINE buildable #-}++ buildTools f s = fmap (\x -> s { T.buildTools = x }) (f (T.buildTools s))+ {-# INLINE buildTools #-}++ buildToolDepends f s = fmap (\x -> s { T.buildToolDepends = x }) (f (T.buildToolDepends s))+ {-# INLINE buildToolDepends #-}++ cppOptions f s = fmap (\x -> s { T.cppOptions = x }) (f (T.cppOptions s))+ {-# INLINE cppOptions #-}++ asmOptions f s = fmap (\x -> s { T.asmOptions = x }) (f (T.asmOptions s))+ {-# INLINE asmOptions #-}++ cmmOptions f s = fmap (\x -> s { T.cmmOptions = x }) (f (T.cmmOptions s))+ {-# INLINE cmmOptions #-}++ ccOptions f s = fmap (\x -> s { T.ccOptions = x }) (f (T.ccOptions s))+ {-# INLINE ccOptions #-}++ cxxOptions f s = fmap (\x -> s { T.cxxOptions = x }) (f (T.cxxOptions s))+ {-# INLINE cxxOptions #-}++ ldOptions f s = fmap (\x -> s { T.ldOptions = x }) (f (T.ldOptions s))+ {-# INLINE ldOptions #-}++ hsc2hsOptions f s = fmap (\x -> s { T.hsc2hsOptions = x }) (f (T.hsc2hsOptions s))+ {-# INLINE hsc2hsOptions #-}++ pkgconfigDepends f s = fmap (\x -> s { T.pkgconfigDepends = x }) (f (T.pkgconfigDepends s))+ {-# INLINE pkgconfigDepends #-}++ frameworks f s = fmap (\x -> s { T.frameworks = x }) (f (T.frameworks s))+ {-# INLINE frameworks #-}++ extraFrameworkDirs f s = fmap (\x -> s { T.extraFrameworkDirs = x }) (f (T.extraFrameworkDirs s))+ {-# INLINE extraFrameworkDirs #-}++ asmSources f s = fmap (\x -> s { T.asmSources = x }) (f (T.asmSources s))+ {-# INLINE asmSources #-}++ cmmSources f s = fmap (\x -> s { T.cmmSources = x }) (f (T.cmmSources s))+ {-# INLINE cmmSources #-}++ cSources f s = fmap (\x -> s { T.cSources = x }) (f (T.cSources s))+ {-# INLINE cSources #-}++ cxxSources f s = fmap (\x -> s { T.cSources = x }) (f (T.cxxSources s))+ {-# INLINE cxxSources #-}++ jsSources f s = fmap (\x -> s { T.jsSources = x }) (f (T.jsSources s))+ {-# INLINE jsSources #-}++ hsSourceDirs f s = fmap (\x -> s { T.hsSourceDirs = x }) (f (T.hsSourceDirs s))+ {-# INLINE hsSourceDirs #-}++ otherModules f s = fmap (\x -> s { T.otherModules = x }) (f (T.otherModules s))+ {-# INLINE otherModules #-}++ virtualModules f s = fmap (\x -> s { T.virtualModules = x }) (f (T.virtualModules s))+ {-# INLINE virtualModules #-}++ autogenModules f s = fmap (\x -> s { T.autogenModules = x }) (f (T.autogenModules s))+ {-# INLINE autogenModules #-}++ defaultLanguage f s = fmap (\x -> s { T.defaultLanguage = x }) (f (T.defaultLanguage s))+ {-# INLINE defaultLanguage #-}++ otherLanguages f s = fmap (\x -> s { T.otherLanguages = x }) (f (T.otherLanguages s))+ {-# INLINE otherLanguages #-}++ defaultExtensions f s = fmap (\x -> s { T.defaultExtensions = x }) (f (T.defaultExtensions s))+ {-# INLINE defaultExtensions #-}++ otherExtensions f s = fmap (\x -> s { T.otherExtensions = x }) (f (T.otherExtensions s))+ {-# INLINE otherExtensions #-}++ oldExtensions f s = fmap (\x -> s { T.oldExtensions = x }) (f (T.oldExtensions s))+ {-# INLINE oldExtensions #-}++ extraLibs f s = fmap (\x -> s { T.extraLibs = x }) (f (T.extraLibs s))+ {-# INLINE extraLibs #-}++ extraGHCiLibs f s = fmap (\x -> s { T.extraGHCiLibs = x }) (f (T.extraGHCiLibs s))+ {-# INLINE extraGHCiLibs #-}++ extraBundledLibs f s = fmap (\x -> s { T.extraBundledLibs = x }) (f (T.extraBundledLibs s))+ {-# INLINE extraBundledLibs #-}++ extraLibFlavours f s = fmap (\x -> s { T.extraLibFlavours = x }) (f (T.extraLibFlavours s))+ {-# INLINE extraLibFlavours #-}++ extraDynLibFlavours f s = fmap (\x -> s { T.extraDynLibFlavours = x}) (f (T.extraDynLibFlavours s))+ {-# INLINE extraDynLibFlavours #-}++ extraLibDirs f s = fmap (\x -> s { T.extraLibDirs = x }) (f (T.extraLibDirs s))+ {-# INLINE extraLibDirs #-}++ includeDirs f s = fmap (\x -> s { T.includeDirs = x }) (f (T.includeDirs s))+ {-# INLINE includeDirs #-}++ includes f s = fmap (\x -> s { T.includes = x }) (f (T.includes s))+ {-# INLINE includes #-}++ autogenIncludes f s = fmap (\x -> s { T.autogenIncludes = x }) (f (T.autogenIncludes s))+ {-# INLINE autogenIncludes #-}++ installIncludes f s = fmap (\x -> s { T.installIncludes = x }) (f (T.installIncludes s))+ {-# INLINE installIncludes #-}++ options f s = fmap (\x -> s { T.options = x }) (f (T.options s))+ {-# INLINE options #-}++ profOptions f s = fmap (\x -> s { T.profOptions = x }) (f (T.profOptions s))+ {-# INLINE profOptions #-}++ sharedOptions f s = fmap (\x -> s { T.sharedOptions = x }) (f (T.sharedOptions s))+ {-# INLINE sharedOptions #-}++ staticOptions f s = fmap (\x -> s { T.staticOptions = x }) (f (T.staticOptions s))+ {-# INLINE staticOptions #-}++ customFieldsBI f s = fmap (\x -> s { T.customFieldsBI = x }) (f (T.customFieldsBI s))+ {-# INLINE customFieldsBI #-}++ targetBuildDepends f s = fmap (\x -> s { T.targetBuildDepends = x }) (f (T.targetBuildDepends s))+ {-# INLINE targetBuildDepends #-}++ mixins f s = fmap (\x -> s { T.mixins = x }) (f (T.mixins s))+ {-# INLINE mixins #-}++class HasBuildInfos a where+ traverseBuildInfos :: Traversal' a BuildInfo
+ src/Distribution/Types/BuildType.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Distribution.Types.BuildType (+ BuildType(..),+ knownBuildTypes,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.CabalSpecVersion (CabalSpecVersion (..))+import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | The type of build system used by this package.+data BuildType+ = Simple -- ^ calls @Distribution.Simple.defaultMain@+ | Configure -- ^ calls @Distribution.Simple.defaultMainWithHooks defaultUserHooks@,+ -- which invokes @configure@ to generate additional build+ -- information used by later phases.+ | Make -- ^ calls @Distribution.Make.defaultMain@+ | Custom -- ^ uses user-supplied @Setup.hs@ or @Setup.lhs@ (default)+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary BuildType+instance Structured BuildType+instance NFData BuildType where rnf = genericRnf++knownBuildTypes :: [BuildType]+knownBuildTypes = [Simple, Configure, Make, Custom]++instance Pretty BuildType where+ pretty = Disp.text . show++instance Parsec BuildType where+ parsec = do+ name <- P.munch1 isAlphaNum+ case name of+ "Simple" -> return Simple+ "Configure" -> return Configure+ "Custom" -> return Custom+ "Make" -> return Make+ "Default" -> do+ v <- askCabalSpecVersion+ if v <= CabalSpecV1_18 -- oldest version needing this, based on hackage-tests+ then do+ parsecWarning PWTBuildTypeDefault "build-type: Default is parsed as Custom for legacy reasons. See https://github.com/haskell/cabal/issues/5020"+ return Custom+ else fail ("unknown build-type: '" ++ name ++ "'")+ _ -> fail ("unknown build-type: '" ++ name ++ "'")
+ src/Distribution/Types/Component.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.Component (+ Component(..),+ foldComponent,+ componentBuildInfo,+ componentBuildable,+ componentName,+ partitionComponents,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.Library+import Distribution.Types.ForeignLib+import Distribution.Types.Executable+import Distribution.Types.TestSuite+import Distribution.Types.Benchmark++import Distribution.Types.ComponentName+import Distribution.Types.BuildInfo++import qualified Distribution.Types.BuildInfo.Lens as L++data Component = CLib Library+ | CFLib ForeignLib+ | CExe Executable+ | CTest TestSuite+ | CBench Benchmark+ deriving (Show, Eq, Read)++instance Semigroup Component where+ CLib l <> CLib l' = CLib (l <> l')+ CFLib l <> CFLib l' = CFLib (l <> l')+ CExe e <> CExe e' = CExe (e <> e')+ CTest t <> CTest t' = CTest (t <> t')+ CBench b <> CBench b' = CBench (b <> b')+ _ <> _ = error "Cannot merge Component"++instance L.HasBuildInfo Component where+ buildInfo f (CLib l) = CLib <$> L.buildInfo f l+ buildInfo f (CFLib l) = CFLib <$> L.buildInfo f l+ buildInfo f (CExe e) = CExe <$> L.buildInfo f e+ buildInfo f (CTest t) = CTest <$> L.buildInfo f t+ buildInfo f (CBench b) = CBench <$> L.buildInfo f b++foldComponent :: (Library -> a)+ -> (ForeignLib -> a)+ -> (Executable -> a)+ -> (TestSuite -> a)+ -> (Benchmark -> a)+ -> Component+ -> a+foldComponent f _ _ _ _ (CLib lib) = f lib+foldComponent _ f _ _ _ (CFLib flib)= f flib+foldComponent _ _ f _ _ (CExe exe) = f exe+foldComponent _ _ _ f _ (CTest tst) = f tst+foldComponent _ _ _ _ f (CBench bch) = f bch++componentBuildInfo :: Component -> BuildInfo+componentBuildInfo =+ foldComponent libBuildInfo foreignLibBuildInfo buildInfo testBuildInfo benchmarkBuildInfo++-- | Is a component buildable (i.e., not marked with @buildable: False@)?+-- See also this note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".+--+-- @since 2.0.0.2+--+componentBuildable :: Component -> Bool+componentBuildable = buildable . componentBuildInfo++componentName :: Component -> ComponentName+componentName =+ foldComponent (CLibName . libName)+ (CFLibName . foreignLibName)+ (CExeName . exeName)+ (CTestName . testName)+ (CBenchName . benchmarkName)++partitionComponents+ :: [Component]+ -> ([Library], [ForeignLib], [Executable], [TestSuite], [Benchmark])+partitionComponents = foldr (foldComponent fa fb fc fd fe) ([],[],[],[],[])+ where+ fa x ~(a,b,c,d,e) = (x:a,b,c,d,e)+ fb x ~(a,b,c,d,e) = (a,x:b,c,d,e)+ fc x ~(a,b,c,d,e) = (a,b,x:c,d,e)+ fd x ~(a,b,c,d,e) = (a,b,c,x:d,e)+ fe x ~(a,b,c,d,e) = (a,b,c,d,x:e)
+ src/Distribution/Types/ComponentId.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Distribution.Types.ComponentId+ ( ComponentId, unComponentId, mkComponentId+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.ShortText++import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import Text.PrettyPrint (text)++-- | A 'ComponentId' uniquely identifies the transitive source+-- code closure of a component (i.e. libraries, executables).+--+-- For non-Backpack components, this corresponds one to one with+-- the 'UnitId', which serves as the basis for install paths,+-- linker symbols, etc.+--+-- Use 'mkComponentId' and 'unComponentId' to convert from/to a+-- 'String'.+--+-- This type is opaque since @Cabal-2.0@+--+-- @since 2.0.0.2+newtype ComponentId = ComponentId ShortText+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++-- | Construct a 'ComponentId' from a 'String'+--+-- 'mkComponentId' is the inverse to 'unComponentId'+--+-- Note: No validations are performed to ensure that the resulting+-- 'ComponentId' is valid+--+-- @since 2.0.0.2+mkComponentId :: String -> ComponentId+mkComponentId = ComponentId . toShortText++-- | Convert 'ComponentId' to 'String'+--+-- @since 2.0.0.2+unComponentId :: ComponentId -> String+unComponentId (ComponentId s) = fromShortText s++-- | 'mkComponentId'+--+-- @since 2.0.0.2+instance IsString ComponentId where+ fromString = mkComponentId++instance Binary ComponentId+instance Structured ComponentId++instance Pretty ComponentId where+ pretty = text . unComponentId++instance Parsec ComponentId where+ parsec = mkComponentId `fmap` P.munch1 abi_char+ where abi_char c = isAlphaNum c || c `elem` "-_."++instance NFData ComponentId where+ rnf = rnf . unComponentId
+ src/Distribution/Types/ComponentInclude.hs view
@@ -0,0 +1,32 @@+module Distribution.Types.ComponentInclude (+ ComponentInclude(..),+ ci_id,+ ci_pkgid,+ ci_cname+) where++import Distribution.Types.PackageId+import Distribution.Types.ComponentName+import Distribution.Types.AnnotatedId++-- Once ci_id is refined to an 'OpenUnitId' or 'DefUnitId',+-- the 'includeRequiresRn' is not so useful (because it+-- includes the requirements renaming that is no longer+-- needed); use 'ci_prov_renaming' instead.+data ComponentInclude id rn = ComponentInclude {+ ci_ann_id :: AnnotatedId id,+ ci_renaming :: rn,+ -- | Did this come from an entry in @mixins@, or+ -- was implicitly generated by @build-depends@?+ ci_implicit :: Bool+ }++ci_id :: ComponentInclude id rn -> id+ci_id = ann_id . ci_ann_id++ci_pkgid :: ComponentInclude id rn -> PackageId+ci_pkgid = ann_pid . ci_ann_id++-- | This should always return 'CLibName' or 'CSubLibName'+ci_cname :: ComponentInclude id rn -> ComponentName+ci_cname = ann_cname . ci_ann_id
+ src/Distribution/Types/ComponentLocalBuildInfo.hs view
@@ -0,0 +1,129 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeFamilies #-}++module Distribution.Types.ComponentLocalBuildInfo (+ ComponentLocalBuildInfo(..),+ componentIsIndefinite,+ maybeComponentInstantiatedWith,+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.ModuleName++import Distribution.Backpack+import Distribution.Compat.Graph+import Distribution.Types.ComponentId+import Distribution.Types.MungedPackageId+import Distribution.Types.UnitId+import Distribution.Types.ComponentName+import Distribution.Types.MungedPackageName+import Distribution.Types.ModuleRenaming++import qualified Distribution.InstalledPackageInfo as Installed++-- | The first five fields are common across all algebraic variants.+data ComponentLocalBuildInfo+ = LibComponentLocalBuildInfo {+ -- | It would be very convenient to store the literal Library here,+ -- but if we do that, it will get serialized (via the Binary)+ -- instance twice. So instead we just provide the ComponentName,+ -- which can be used to find the Component in the+ -- PackageDescription. NB: eventually, this will NOT uniquely+ -- identify the ComponentLocalBuildInfo.+ componentLocalName :: ComponentName,+ -- | The computed 'ComponentId' of this component.+ componentComponentId :: ComponentId,+ -- | The computed 'UnitId' which uniquely identifies this+ -- component. Might be hashed.+ componentUnitId :: UnitId,+ -- | Is this an indefinite component (i.e. has unfilled holes)?+ componentIsIndefinite_ :: Bool,+ -- | How the component was instantiated+ componentInstantiatedWith :: [(ModuleName, OpenModule)],+ -- | Resolved internal and external package dependencies for this component.+ -- 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 :: [(UnitId, MungedPackageId)],+ -- | The set of packages that are brought into scope during+ -- compilation, including a 'ModuleRenaming' which may used+ -- to hide or rename modules. This is what gets translated into+ -- @-package-id@ arguments. This is a modernized version of+ -- 'componentPackageDeps', which is kept around for BC purposes.+ componentIncludes :: [(OpenUnitId, ModuleRenaming)],+ componentExeDeps :: [UnitId],+ -- | The internal dependencies which induce a graph on the+ -- 'ComponentLocalBuildInfo' of this package. This does NOT+ -- coincide with 'componentPackageDeps' because it ALSO records+ -- 'build-tool' dependencies on executables. Maybe one day+ -- @cabal-install@ will also handle these correctly too!+ componentInternalDeps :: [UnitId],+ -- | Compatibility "package key" that we pass to older versions of GHC.+ componentCompatPackageKey :: String,+ -- | Compatibility "package name" that we register this component as.+ componentCompatPackageName :: MungedPackageName,+ -- | A list of exposed modules (either defined in this component,+ -- or reexported from another component.)+ componentExposedModules :: [Installed.ExposedModule],+ -- | Convenience field, specifying whether or not this is the+ -- "public library" that has the same name as the package.+ componentIsPublic :: Bool+ }+ -- TODO: refactor all these duplicates+ | FLibComponentLocalBuildInfo {+ componentLocalName :: ComponentName,+ componentComponentId :: ComponentId,+ componentUnitId :: UnitId,+ componentPackageDeps :: [(UnitId, MungedPackageId)],+ componentIncludes :: [(OpenUnitId, ModuleRenaming)],+ componentExeDeps :: [UnitId],+ componentInternalDeps :: [UnitId]+ }+ | ExeComponentLocalBuildInfo {+ componentLocalName :: ComponentName,+ componentComponentId :: ComponentId,+ componentUnitId :: UnitId,+ componentPackageDeps :: [(UnitId, MungedPackageId)],+ componentIncludes :: [(OpenUnitId, ModuleRenaming)],+ componentExeDeps :: [UnitId],+ componentInternalDeps :: [UnitId]+ }+ | TestComponentLocalBuildInfo {+ componentLocalName :: ComponentName,+ componentComponentId :: ComponentId,+ componentUnitId :: UnitId,+ componentPackageDeps :: [(UnitId, MungedPackageId)],+ componentIncludes :: [(OpenUnitId, ModuleRenaming)],+ componentExeDeps :: [UnitId],+ componentInternalDeps :: [UnitId]++ }+ | BenchComponentLocalBuildInfo {+ componentLocalName :: ComponentName,+ componentComponentId :: ComponentId,+ componentUnitId :: UnitId,+ componentPackageDeps :: [(UnitId, MungedPackageId)],+ componentIncludes :: [(OpenUnitId, ModuleRenaming)],+ componentExeDeps :: [UnitId],+ componentInternalDeps :: [UnitId]+ }+ deriving (Generic, Read, Show, Typeable)++instance Binary ComponentLocalBuildInfo+instance Structured ComponentLocalBuildInfo++instance IsNode ComponentLocalBuildInfo where+ type Key ComponentLocalBuildInfo = UnitId+ nodeKey = componentUnitId+ nodeNeighbors = componentInternalDeps++componentIsIndefinite :: ComponentLocalBuildInfo -> Bool+componentIsIndefinite LibComponentLocalBuildInfo{ componentIsIndefinite_ = b } = b+componentIsIndefinite _ = False++maybeComponentInstantiatedWith :: ComponentLocalBuildInfo -> Maybe [(ModuleName, OpenModule)]+maybeComponentInstantiatedWith+ LibComponentLocalBuildInfo { componentInstantiatedWith = insts } = Just insts+maybeComponentInstantiatedWith _ = Nothing
+ src/Distribution/Types/ComponentName.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.ComponentName (+ ComponentName(..),+ showComponentName,+ componentNameStanza,+ componentNameString,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.UnqualComponentName+import Distribution.Types.LibraryName+import Distribution.Pretty+import Distribution.Parsec++import qualified Text.PrettyPrint as Disp+import qualified Distribution.Compat.CharParsing as P++-- Libraries live in a separate namespace, so must distinguish+data ComponentName = CLibName LibraryName+ | CFLibName UnqualComponentName+ | CExeName UnqualComponentName+ | CTestName UnqualComponentName+ | CBenchName UnqualComponentName+ deriving (Eq, Generic, Ord, Read, Show, Typeable)++instance Binary ComponentName+instance Structured ComponentName++-- Build-target-ish syntax+instance Pretty ComponentName where+ pretty (CLibName lib) = prettyLibraryNameComponent lib+ pretty (CFLibName str) = Disp.text "flib:" <<>> pretty str+ pretty (CExeName str) = Disp.text "exe:" <<>> pretty str+ pretty (CTestName str) = Disp.text "test:" <<>> pretty str+ pretty (CBenchName str) = Disp.text "bench:" <<>> pretty str++instance Parsec ComponentName where+ -- note: this works as lib/flib/... all start with different character!+ parsec = parseComposite <|> parseLib+ where+ parseLib = CLibName <$> parsecLibraryNameComponent+ parseComposite = do+ ctor <- P.choice+ [ P.string "flib:" >> return CFLibName+ , P.string "exe:" >> return CExeName+ , P.string "bench:" >> return CBenchName+ , P.string "test:" >> return CTestName+ ]+ ctor <$> parsec++showComponentName :: ComponentName -> String+showComponentName (CLibName lib) = showLibraryName lib+showComponentName (CFLibName name) = "foreign library '" ++ prettyShow name ++ "'"+showComponentName (CExeName name) = "executable '" ++ prettyShow name ++ "'"+showComponentName (CTestName name) = "test suite '" ++ prettyShow name ++ "'"+showComponentName (CBenchName name) = "benchmark '" ++ prettyShow name ++ "'"++componentNameStanza :: ComponentName -> String+componentNameStanza (CLibName lib) = libraryNameStanza lib+componentNameStanza (CFLibName name) = "foreign-library " ++ prettyShow name+componentNameStanza (CExeName name) = "executable " ++ prettyShow name+componentNameStanza (CTestName name) = "test-suite " ++ prettyShow name+componentNameStanza (CBenchName name) = "benchmark " ++ prettyShow name++-- | This gets the underlying unqualified component name. In fact, it is+-- guaranteed to uniquely identify a component, returning+-- @Nothing@ if the 'ComponentName' was for the public+-- library.+componentNameString :: ComponentName -> Maybe UnqualComponentName+componentNameString (CLibName lib) = libraryNameString lib+componentNameString (CFLibName n) = Just n+componentNameString (CExeName n) = Just n+componentNameString (CTestName n) = Just n+componentNameString (CBenchName n) = Just n
+ src/Distribution/Types/ComponentRequestedSpec.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.ComponentRequestedSpec (+ -- $buildable_vs_enabled_components++ ComponentRequestedSpec(..),+ ComponentDisabledReason(..),++ defaultComponentRequestedSpec,+ componentNameRequested,++ componentEnabled,+ componentDisabledReason,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.Component -- TODO: maybe remove me?+import Distribution.Types.ComponentName++import Distribution.Pretty (prettyShow)++-- $buildable_vs_enabled_components+-- #buildable_vs_enabled_components#+--+-- = Note: Buildable versus requested versus enabled components+-- What's the difference between a buildable component (ala+-- 'componentBuildable'), a requested component+-- (ala 'componentNameRequested'), and an enabled component (ala+-- 'componentEnabled')?+--+-- A component is __buildable__ if, after resolving flags and+-- conditionals, there is no @buildable: False@ property in it.+-- This is a /static/ property that arises from the+-- Cabal file and the package description flattening; once we have+-- a 'PackageDescription' buildability is known.+--+-- A component is __requested__ if a user specified, via a+-- the flags and arguments passed to configure, that it should be+-- built. E.g., @--enable-tests@ or @--enable-benchmarks@ request+-- all tests and benchmarks, if they are provided. What is requested+-- can be read off directly from 'ComponentRequestedSpec'. A requested+-- component is not always buildable; e.g., a user may @--enable-tests@+-- but one of the test suites may have @buildable: False@.+--+-- A component is __enabled__ if it is BOTH buildable+-- and requested. Once we have a 'LocalBuildInfo', whether or not a+-- component is enabled is known.+--+-- Generally speaking, most Cabal API code cares if a component+-- is enabled. (For example, if you want to run a preprocessor on each+-- component prior to building them, you want to run this on each+-- /enabled/ component.)+--+-- Note that post-configuration, you will generally not see a+-- non-buildable 'Component'. This is because 'flattenPD' will drop+-- any such components from 'PackageDescription'. See #3858 for+-- an example where this causes problems.++-- | Describes what components are enabled by user-interaction.+-- See also this note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".+--+-- @since 2.0.0.2+data ComponentRequestedSpec+ = ComponentRequestedSpec { testsRequested :: Bool+ , benchmarksRequested :: Bool }+ | OneComponentRequestedSpec ComponentName+ deriving (Generic, Read, Show, Eq, Typeable)++instance Binary ComponentRequestedSpec+instance Structured ComponentRequestedSpec++-- | The default set of enabled components. Historically tests and+-- benchmarks are NOT enabled by default.+--+-- @since 2.0.0.2+defaultComponentRequestedSpec :: ComponentRequestedSpec+defaultComponentRequestedSpec = ComponentRequestedSpec False False++-- | Is this component enabled? See also this note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".+--+-- @since 2.0.0.2+componentEnabled :: ComponentRequestedSpec -> Component -> Bool+componentEnabled enabled = isNothing . componentDisabledReason enabled++-- | Is this component name enabled? See also this note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components".+--+-- @since 2.0.0.2+componentNameRequested :: ComponentRequestedSpec -> ComponentName -> Bool+componentNameRequested enabled = isNothing . componentNameNotRequestedReason enabled++-- | Is this component disabled, and if so, why?+--+-- @since 2.0.0.2+componentDisabledReason :: ComponentRequestedSpec -> Component+ -> Maybe ComponentDisabledReason+componentDisabledReason enabled comp+ | not (componentBuildable comp) = Just DisabledComponent+ | otherwise = componentNameNotRequestedReason enabled (componentName comp)++-- | Is this component name disabled, and if so, why?+--+-- @since 2.0.0.2+componentNameNotRequestedReason :: ComponentRequestedSpec -> ComponentName+ -> Maybe ComponentDisabledReason+componentNameNotRequestedReason+ ComponentRequestedSpec{ testsRequested = False } (CTestName _)+ = Just DisabledAllTests+componentNameNotRequestedReason+ ComponentRequestedSpec{ benchmarksRequested = False } (CBenchName _)+ = Just DisabledAllBenchmarks+componentNameNotRequestedReason ComponentRequestedSpec{} _ = Nothing+componentNameNotRequestedReason (OneComponentRequestedSpec cname) c+ | c == cname = Nothing+ | otherwise = Just (DisabledAllButOne (prettyShow cname))++-- | A reason explaining why a component is disabled.+--+-- @since 2.0.0.2+data ComponentDisabledReason = DisabledComponent+ | DisabledAllTests+ | DisabledAllBenchmarks+ | DisabledAllButOne String
+ src/Distribution/Types/CondTree.hs view
@@ -0,0 +1,181 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Distribution.Types.CondTree (+ CondTree(..),+ CondBranch(..),+ condIfThen,+ condIfThenElse,+ mapCondTree,+ mapTreeConstrs,+ mapTreeConds,+ mapTreeData,+ traverseCondTreeV,+ traverseCondBranchV,+ traverseCondTreeC,+ traverseCondBranchC,+ extractCondition,+ simplifyCondTree,+ ignoreConditions,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.Condition++import qualified Distribution.Compat.Lens as L+++-- | A 'CondTree' is used to represent the conditional structure of+-- a Cabal file, reflecting a syntax element subject to constraints,+-- and then any number of sub-elements which may be enabled subject+-- to some condition. Both @a@ and @c@ are usually 'Monoid's.+--+-- To be more concrete, consider the following fragment of a @Cabal@+-- file:+--+-- @+-- build-depends: base >= 4.0+-- if flag(extra)+-- build-depends: base >= 4.2+-- @+--+-- One way to represent this is to have @'CondTree' 'ConfVar'+-- ['Dependency'] 'BuildInfo'@. Here, 'condTreeData' represents+-- the actual fields which are not behind any conditional, while+-- 'condTreeComponents' recursively records any further fields+-- which are behind a conditional. 'condTreeConstraints' records+-- the constraints (in this case, @base >= 4.0@) which would+-- be applied if you use this syntax; in general, this is+-- derived off of 'targetBuildInfo' (perhaps a good refactoring+-- would be to convert this into an opaque type, with a smart+-- constructor that pre-computes the dependencies.)+--+data CondTree v c a = CondNode+ { condTreeData :: a+ , condTreeConstraints :: c+ , condTreeComponents :: [CondBranch v c a]+ }+ deriving (Show, Eq, Typeable, Data, Generic, Functor, Foldable, Traversable)++instance (Binary v, Binary c, Binary a) => Binary (CondTree v c a)+instance (Structured v, Structured c, Structured a) => Structured (CondTree v c a)+instance (NFData v, NFData c, NFData a) => NFData (CondTree v c a) where rnf = genericRnf++-- | A 'CondBranch' represents a conditional branch, e.g., @if+-- flag(foo)@ on some syntax @a@. It also has an optional false+-- branch.+--+data CondBranch v c a = CondBranch+ { condBranchCondition :: Condition v+ , condBranchIfTrue :: CondTree v c a+ , condBranchIfFalse :: Maybe (CondTree v c a)+ }+ deriving (Show, Eq, Typeable, Data, Generic, Functor, Traversable)++-- This instance is written by hand because GHC 8.0.1/8.0.2 infinite+-- loops when trying to derive it with optimizations. See+-- https://gitlab.haskell.org/ghc/ghc/-/issues/13056+instance Foldable (CondBranch v c) where+ foldMap f (CondBranch _ c Nothing) = foldMap f c+ foldMap f (CondBranch _ c (Just a)) = foldMap f c `mappend` foldMap f a++instance (Binary v, Binary c, Binary a) => Binary (CondBranch v c a)+instance (Structured v, Structured c, Structured a) => Structured (CondBranch v c a)+instance (NFData v, NFData c, NFData a) => NFData (CondBranch v c a) where rnf = genericRnf++condIfThen :: Condition v -> CondTree v c a -> CondBranch v c a+condIfThen c t = CondBranch c t Nothing++condIfThenElse :: Condition v -> CondTree v c a -> CondTree v c a -> CondBranch v c a+condIfThenElse c t e = CondBranch c t (Just e)++mapCondTree :: (a -> b) -> (c -> d) -> (Condition v -> Condition w)+ -> CondTree v c a -> CondTree w d b+mapCondTree fa fc fcnd (CondNode a c ifs) =+ CondNode (fa a) (fc c) (map g ifs)+ where+ g (CondBranch cnd t me)+ = CondBranch (fcnd cnd)+ (mapCondTree fa fc fcnd t)+ (fmap (mapCondTree fa fc fcnd) me)++mapTreeConstrs :: (c -> d) -> CondTree v c a -> CondTree v d a+mapTreeConstrs f = mapCondTree id f id++mapTreeConds :: (Condition v -> Condition w) -> CondTree v c a -> CondTree w c a+mapTreeConds f = mapCondTree id id f++mapTreeData :: (a -> b) -> CondTree v c a -> CondTree v c b+mapTreeData f = mapCondTree f id id++-- | @@Traversal@@ for the variables+traverseCondTreeV :: L.Traversal (CondTree v c a) (CondTree w c a) v w+traverseCondTreeV f (CondNode a c ifs) =+ CondNode a c <$> traverse (traverseCondBranchV f) ifs++-- | @@Traversal@@ for the variables+traverseCondBranchV :: L.Traversal (CondBranch v c a) (CondBranch w c a) v w+traverseCondBranchV f (CondBranch cnd t me) = CondBranch+ <$> traverse f cnd+ <*> traverseCondTreeV f t+ <*> traverse (traverseCondTreeV f) me++-- | @@Traversal@@ for the aggregated constraints+traverseCondTreeC :: L.Traversal (CondTree v c a) (CondTree v d a) c d+traverseCondTreeC f (CondNode a c ifs) =+ CondNode a <$> f c <*> traverse (traverseCondBranchC f) ifs++-- | @@Traversal@@ for the aggregated constraints+traverseCondBranchC :: L.Traversal (CondBranch v c a) (CondBranch v d a) c d+traverseCondBranchC f (CondBranch cnd t me) = CondBranch cnd+ <$> traverseCondTreeC f t+ <*> traverse (traverseCondTreeC f) me+++-- | Extract the condition matched by the given predicate from a cond tree.+--+-- We use this mainly for extracting buildable conditions (see the Note in+-- Distribution.PackageDescription.Configuration), 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 (CondBranch 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++-- | Flattens a CondTree using a partial flag assignment. When a condition+-- cannot be evaluated, both branches are ignored.+simplifyCondTree :: (Semigroup a, Semigroup d) =>+ (v -> Either v Bool)+ -> CondTree v d a+ -> (d, a)+simplifyCondTree env (CondNode a d ifs) =+ foldl (<>) (d, a) $ mapMaybe simplifyIf ifs+ where+ simplifyIf (CondBranch cnd t me) =+ case simplifyCondition cnd env of+ (Lit True, _) -> Just $ simplifyCondTree env t+ (Lit False, _) -> fmap (simplifyCondTree env) me+ _ -> Nothing++-- | Flatten a CondTree. This will resolve the CondTree by taking all+-- possible paths into account. Note that since branches represent exclusive+-- choices this may not result in a \"sane\" result.+ignoreConditions :: (Semigroup a, Semigroup c) => CondTree v c a -> (a, c)+ignoreConditions (CondNode a c ifs) = foldl (<>) (a, c) $ concatMap f ifs+ where f (CondBranch _ t me) = ignoreConditions t+ : maybeToList (fmap ignoreConditions me)
+ src/Distribution/Types/Condition.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.Condition (+ Condition(..),+ cNot,+ cAnd,+ cOr,+ simplifyCondition,+) where++import Prelude ()+import Distribution.Compat.Prelude++-- | 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, 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 = 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` 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 = 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 = (<>)++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)+instance Structured c => Structured (Condition c)+instance NFData c => NFData (Condition c) where rnf = genericRnf++-- | Simplify the condition and return its free variables.+simplifyCondition :: Condition c+ -> (c -> Either d Bool) -- ^ (partial) variable assignment+ -> (Condition d, [d])+simplifyCondition cond i = fv . walk $ cond+ where+ walk cnd = case cnd of+ Var v -> either Var Lit (i v)+ Lit b -> Lit b+ CNot c -> case walk c of+ Lit True -> Lit False+ Lit False -> Lit True+ c' -> CNot c'+ COr c d -> case (walk c, walk d) of+ (Lit False, d') -> d'+ (Lit True, _) -> Lit True+ (c', Lit False) -> c'+ (_, Lit True) -> Lit True+ (c',d') -> COr c' d'+ CAnd c d -> case (walk c, walk d) of+ (Lit False, _) -> Lit False+ (Lit True, d') -> d'+ (_, Lit False) -> Lit False+ (c', Lit True) -> c'+ (c',d') -> CAnd c' d'+ -- gather free vars+ fv c = (c, fv' c)+ fv' c = case c of+ Var v -> [v]+ Lit _ -> []+ CNot c' -> fv' c'+ COr c1 c2 -> fv' c1 ++ fv' c2+ CAnd c1 c2 -> fv' c1 ++ fv' c2
+ src/Distribution/Types/ConfVar.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.ConfVar (+ ConfVar(..),+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.Flag+import Distribution.Types.VersionRange+import Distribution.Compiler+import Distribution.System++-- | A @ConfVar@ represents the variable type used.+data ConfVar = OS OS+ | Arch Arch+ | PackageFlag FlagName+ | Impl CompilerFlavor VersionRange+ deriving (Eq, Show, Typeable, Data, Generic)++instance Binary ConfVar+instance Structured ConfVar++instance NFData ConfVar where rnf = genericRnf
+ src/Distribution/Types/Dependency.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.Dependency+ ( Dependency(..)+ , mkDependency+ , depPkgName+ , depVerRange+ , depLibraries+ , simplifyDependency+ , mainLibSet+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.VersionRange (isAnyVersionLight)+import Distribution.Version (VersionRange, anyVersion, simplifyVersionRange)++import Distribution.CabalSpecVersion+import Distribution.Compat.CharParsing (char, spaces)+import Distribution.Compat.Parsing (between, option)+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.LibraryName+import Distribution.Types.PackageName+import Distribution.Types.UnqualComponentName++import qualified Distribution.Compat.NonEmptySet as NES+import qualified Text.PrettyPrint as PP++-- | Describes a dependency on a source package (API)+--+-- /Invariant:/ package name does not appear as 'LSubLibName' in+-- set of library names.+--+data Dependency = Dependency+ PackageName+ VersionRange+ (NonEmptySet LibraryName)+ -- ^ The set of libraries required from the package.+ -- Only the selected libraries will be built.+ -- It does not affect the cabal-install solver yet.+ deriving (Generic, Read, Show, Eq, Typeable, Data)++depPkgName :: Dependency -> PackageName+depPkgName (Dependency pn _ _) = pn++depVerRange :: Dependency -> VersionRange+depVerRange (Dependency _ vr _) = vr++depLibraries :: Dependency -> NonEmptySet LibraryName+depLibraries (Dependency _ _ cs) = cs++-- | Smart constructor of 'Dependency'.+--+-- If 'PackageName' is appears as 'LSubLibName' in a set of sublibraries,+-- it is automatically converted to 'LMainLibName'.+--+-- @since 3.4.0.0+--+mkDependency :: PackageName -> VersionRange -> NonEmptySet LibraryName -> Dependency+mkDependency pn vr lb = Dependency pn vr (NES.map conv lb)+ where+ pn' = packageNameToUnqualComponentName pn++ conv l@LMainLibName = l+ conv l@(LSubLibName ln) | ln == pn' = LMainLibName+ | otherwise = l++instance Binary Dependency+instance Structured Dependency+instance NFData Dependency where rnf = genericRnf++-- |+--+-- >>> prettyShow $ Dependency "pkg" anyVersion mainLibSet+-- "pkg"+--+-- >>> prettyShow $ Dependency "pkg" anyVersion $ NES.insert (LSubLibName "sublib") mainLibSet+-- "pkg:{pkg, sublib}"+--+-- >>> prettyShow $ Dependency "pkg" anyVersion $ NES.singleton (LSubLibName "sublib")+-- "pkg:sublib"+--+-- >>> prettyShow $ Dependency "pkg" anyVersion $ NES.insert (LSubLibName "sublib-b") $ NES.singleton (LSubLibName "sublib-a")+-- "pkg:{sublib-a, sublib-b}"+--+instance Pretty Dependency where+ pretty (Dependency name ver sublibs) = withSubLibs (pretty name) <+> pver+ where+ -- TODO: change to isAnyVersion after #6736+ pver | isAnyVersionLight ver = PP.empty+ | otherwise = pretty ver++ withSubLibs doc = case NES.toList sublibs of+ [LMainLibName] -> doc+ [LSubLibName uq] -> doc <<>> PP.colon <<>> pretty uq+ _ -> doc <<>> PP.colon <<>> PP.braces prettySublibs++ prettySublibs = PP.hsep $ PP.punctuate PP.comma $ prettySublib <$> NES.toList sublibs++ prettySublib LMainLibName = PP.text $ unPackageName name+ prettySublib (LSubLibName un) = PP.text $ unUnqualComponentName un++-- |+--+-- >>> simpleParsec "mylib:sub" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub") :| [])))+--+-- >>> simpleParsec "mylib:{sub1,sub2}" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))+--+-- >>> simpleParsec "mylib:{ sub1 , sub2 }" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))+--+-- >>> simpleParsec "mylib:{ sub1 , sub2 } ^>= 42" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (MajorBoundVersion (mkVersion [42])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))+--+-- >>> simpleParsec "mylib:{ } ^>= 42" :: Maybe Dependency+-- Nothing+--+-- >>> traverse_ print (map simpleParsec ["mylib:mylib", "mylib:{mylib}", "mylib:{mylib,sublib}" ] :: [Maybe Dependency])+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [])))+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [])))+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [LSubLibName (UnqualComponentName "sublib")])))+--+-- Spaces around colon are not allowed:+--+-- >>> map simpleParsec ["mylib: sub", "mylib :sub", "mylib: {sub1,sub2}", "mylib :{sub1,sub2}"] :: [Maybe Dependency]+-- [Nothing,Nothing,Nothing,Nothing]+--+-- Sublibrary syntax is accepted since @cabal-version: 3.0@+--+-- >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe Dependency]+-- [Nothing,Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub") :| [])))]+--+instance Parsec Dependency where+ parsec = do+ name <- parsec++ libs <- option mainLibSet $ do+ _ <- char ':'+ versionGuardMultilibs+ parsecWarning PWTExperimental "colon specifier is experimental feature (issue #5660)"+ NES.singleton <$> parseLib <|> parseMultipleLibs++ spaces -- https://github.com/haskell/cabal/issues/5846++ ver <- parsec <|> pure anyVersion+ return $ mkDependency name ver libs+ where+ parseLib = LSubLibName <$> parsec+ parseMultipleLibs = between+ (char '{' *> spaces)+ (spaces *> char '}')+ (NES.fromNonEmpty <$> parsecCommaNonEmpty parseLib)++versionGuardMultilibs :: CabalParsing m => m ()+versionGuardMultilibs = do+ csv <- askCabalSpecVersion+ when (csv < CabalSpecV3_0) $ fail $ unwords+ [ "Sublibrary dependency syntax used."+ , "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."+ , "Alternatively, if you are depending on an internal library, you can write"+ , "directly the library name as it were a package."+ ]++-- | Library set with main library.+--+-- @since 3.4.0.0+mainLibSet :: NonEmptySet LibraryName+mainLibSet = NES.singleton LMainLibName++-- | Simplify the 'VersionRange' expression in a 'Dependency'.+-- See 'simplifyVersionRange'.+--+simplifyDependency :: Dependency -> Dependency+simplifyDependency (Dependency name range comps) =+ Dependency name (simplifyVersionRange range) comps
+ src/Distribution/Types/DependencyMap.hs view
@@ -0,0 +1,57 @@+module Distribution.Types.DependencyMap (+ DependencyMap,+ toDepMap,+ fromDepMap,+ constrainBy,+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.Dependency+import Distribution.Types.LibraryName+import Distribution.Types.PackageName+import Distribution.Types.PackageVersionConstraint+import Distribution.Version++import qualified Data.Map.Lazy as Map++-- | 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, NonEmptySet LibraryName) }+ deriving (Show, Read)++instance Monoid DependencyMap where+ mempty = DependencyMap Map.empty+ mappend = (<>)++instance Semigroup DependencyMap where+ (DependencyMap a) <> (DependencyMap b) =+ DependencyMap (Map.unionWith intersectVersionRangesAndJoinComponents a b)++intersectVersionRangesAndJoinComponents :: (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName)+intersectVersionRangesAndJoinComponents (va, ca) (vb, cb) =+ (intersectVersionRanges va vb, ca <> cb)++toDepMap :: [Dependency] -> DependencyMap+toDepMap ds =+ DependencyMap $ Map.fromListWith intersectVersionRangesAndJoinComponents [ (p,(vr,cs)) | Dependency p vr cs <- ds ]++fromDepMap :: DependencyMap -> [Dependency]+fromDepMap m = [ Dependency p vr cs | (p,(vr,cs)) <- Map.toList (unDependencyMap m) ]++-- Apply extra constraints to a dependency map.+-- Combines dependencies where the result will only contain keys from the left+-- (first) map. If a key also exists in the right map, both constraints will+-- be intersected.+constrainBy+ :: DependencyMap+ -> [PackageVersionConstraint]+ -> DependencyMap+constrainBy = foldl' tightenConstraint where+ tightenConstraint (DependencyMap l) (PackageVersionConstraint pn vr) = DependencyMap $+ case Map.lookup pn l of+ Nothing -> l+ Just (vr', cs) -> Map.insert pn (intersectVersionRanges vr' vr, cs) l
+ src/Distribution/Types/ExeDependency.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.ExeDependency+ ( ExeDependency(..)+ , qualifiedExeName+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.ComponentName+import Distribution.Types.PackageName+import Distribution.Types.UnqualComponentName+import Distribution.Version (VersionRange, anyVersion, isAnyVersion)++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP++-- | Describes a dependency on an executable from a package+--+data ExeDependency = ExeDependency+ PackageName+ UnqualComponentName -- name of executable component of package+ VersionRange+ deriving (Generic, Read, Show, Eq, Typeable, Data)++instance Binary ExeDependency+instance Structured ExeDependency+instance NFData ExeDependency where rnf = genericRnf++instance Pretty ExeDependency where+ pretty (ExeDependency name exe ver) =+ pretty name <<>> PP.colon <<>> pretty exe PP.<+> pver+ where+ pver | isAnyVersion ver = PP.empty+ | otherwise = pretty ver++-- | +--+-- Examples+--+-- >>> simpleParsec "happy:happy" :: Maybe ExeDependency+-- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [0])))+--+-- >>> simpleParsec "happy:happy >= 1.19.12" :: Maybe ExeDependency+-- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [1,19,12])))+--+-- >>> simpleParsec "happy:happy>=1.19.12" :: Maybe ExeDependency+-- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [1,19,12])))+--+-- >>> simpleParsec "happy : happy >= 1.19.12" :: Maybe ExeDependency+-- Nothing+--+-- >>> simpleParsec "happy: happy >= 1.19.12" :: Maybe ExeDependency+-- Nothing+--+-- >>> simpleParsec "happy :happy >= 1.19.12" :: Maybe ExeDependency+-- Nothing+--+instance Parsec ExeDependency where+ parsec = do+ name <- parsec+ _ <- P.char ':'+ exe <- lexemeParsec+ ver <- parsec <|> pure anyVersion+ return (ExeDependency name exe ver)++qualifiedExeName :: ExeDependency -> ComponentName+qualifiedExeName (ExeDependency _ ucn _) = CExeName ucn
+ src/Distribution/Types/Executable.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.Executable (+ Executable(..),+ emptyExecutable,+ exeModules,+ exeModulesAutogen+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.BuildInfo+import Distribution.Types.UnqualComponentName+import Distribution.Types.ExecutableScope+import Distribution.ModuleName++import qualified Distribution.Types.BuildInfo.Lens as L++data Executable = Executable {+ exeName :: UnqualComponentName,+ modulePath :: FilePath,+ exeScope :: ExecutableScope,+ buildInfo :: BuildInfo+ }+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance L.HasBuildInfo Executable where+ buildInfo f l = (\x -> l { buildInfo = x }) <$> f (buildInfo l)++instance Binary Executable+instance Structured Executable+instance NFData Executable where rnf = genericRnf++instance Monoid Executable where+ mempty = gmempty+ mappend = (<>)++instance Semigroup Executable where+ a <> b = Executable{+ exeName = combine' exeName,+ modulePath = combine modulePath,+ exeScope = combine exeScope,+ buildInfo = combine buildInfo+ }+ where combine field = field a `mappend` field b+ combine' field = case ( unUnqualComponentName $ field a+ , unUnqualComponentName $ field b) of+ ("", _) -> field b+ (_, "") -> field a+ (x, y) -> error $ "Ambiguous values for executable field: '"+ ++ x ++ "' and '" ++ y ++ "'"++emptyExecutable :: Executable+emptyExecutable = mempty++-- | Get all the module names from an exe+exeModules :: Executable -> [ModuleName]+exeModules exe = otherModules (buildInfo exe)++-- | Get all the auto generated module names from an exe+-- This are a subset of 'exeModules'.+exeModulesAutogen :: Executable -> [ModuleName]+exeModulesAutogen exe = autogenModules (buildInfo exe)
+ src/Distribution/Types/Executable/Lens.hs view
@@ -0,0 +1,31 @@+module Distribution.Types.Executable.Lens (+ Executable,+ module Distribution.Types.Executable.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.Executable (Executable)+import Distribution.Types.ExecutableScope (ExecutableScope)+import Distribution.Types.UnqualComponentName (UnqualComponentName)++import qualified Distribution.Types.Executable as T++exeName :: Lens' Executable UnqualComponentName+exeName f s = fmap (\x -> s { T.exeName = x }) (f (T.exeName s))+{-# INLINE exeName #-}++modulePath :: Lens' Executable String+modulePath f s = fmap (\x -> s { T.modulePath = x }) (f (T.modulePath s))+{-# INLINE modulePath #-}++exeScope :: Lens' Executable ExecutableScope+exeScope f s = fmap (\x -> s { T.exeScope = x }) (f (T.exeScope s))+{-# INLINE exeScope #-}++exeBuildInfo :: Lens' Executable BuildInfo+exeBuildInfo f s = fmap (\x -> s { T.buildInfo = x }) (f (T.buildInfo s))+{-# INLINE exeBuildInfo #-}
+ src/Distribution/Types/ExecutableScope.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Distribution.Types.ExecutableScope (+ ExecutableScope(..),+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++data ExecutableScope = ExecutablePublic+ | ExecutablePrivate+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Pretty ExecutableScope where+ pretty ExecutablePublic = Disp.text "public"+ pretty ExecutablePrivate = Disp.text "private"++instance Parsec ExecutableScope where+ parsec = P.try pub <|> pri where+ pub = ExecutablePublic <$ P.string "public"+ pri = ExecutablePrivate <$ P.string "private"++instance Binary ExecutableScope+instance Structured ExecutableScope+instance NFData ExecutableScope where rnf = genericRnf++-- | 'Any' like semigroup, where 'ExecutablePrivate' is 'Any True'+instance Semigroup ExecutableScope where+ ExecutablePublic <> x = x+ x@ExecutablePrivate <> _ = x++-- | 'mempty' = 'ExecutablePublic'+instance Monoid ExecutableScope where+ mempty = ExecutablePublic+ mappend = (<>)
+ src/Distribution/Types/ExposedModule.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.ExposedModule where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Backpack+import Distribution.ModuleName+import Distribution.Parsec+import Distribution.Pretty++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++data ExposedModule+ = ExposedModule {+ exposedName :: ModuleName,+ exposedReexport :: Maybe OpenModule+ }+ deriving (Eq, Generic, Read, Show, Typeable)++instance Pretty ExposedModule where+ pretty (ExposedModule m reexport) =+ Disp.hsep [ pretty m+ , case reexport of+ Just m' -> Disp.hsep [Disp.text "from", pretty m']+ Nothing -> Disp.empty+ ]++instance Parsec ExposedModule where+ parsec = do+ m <- parsecMaybeQuoted parsec+ P.spaces++ reexport <- P.optional $ do+ _ <- P.string "from"+ P.skipSpaces1+ parsec++ return (ExposedModule m reexport)++instance Binary ExposedModule+instance Structured ExposedModule+instance NFData ExposedModule where rnf = genericRnf
+ src/Distribution/Types/Flag.hs view
@@ -0,0 +1,346 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Distribution.Types.Flag (+ -- * Package flag+ PackageFlag(..),+ emptyFlag,+ -- * Flag name+ FlagName,+ mkFlagName,+ unFlagName,+ -- * Flag assignment+ FlagAssignment,+ mkFlagAssignment,+ unFlagAssignment,+ lookupFlagAssignment,+ insertFlagAssignment,+ diffFlagAssignment,+ findDuplicateFlagAssignments,+ nullFlagAssignment,+ showFlagValue,+ dispFlagAssignment,+ showFlagAssignment,+ parsecFlagAssignment,+ parsecFlagAssignmentNonEmpty,+ -- ** Legacy formats+ legacyShowFlagAssignment,+ legacyShowFlagAssignment',+ legacyParsecFlagAssignment,+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.ShortText+import Distribution.Utils.Generic (lowercase)++import Distribution.Parsec+import Distribution.Pretty++import qualified Data.Map as Map+import qualified Text.PrettyPrint as Disp+import qualified Distribution.Compat.CharParsing as P++-- -----------------------------------------------------------------------------+-- The Flag' type++-- | 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.+data PackageFlag = MkPackageFlag+ { flagName :: FlagName+ , flagDescription :: String+ , flagDefault :: Bool+ , flagManual :: Bool+ }+ deriving (Show, Eq, Typeable, Data, Generic)++instance Binary PackageFlag+instance Structured PackageFlag+instance NFData PackageFlag where rnf = genericRnf++-- | A 'PackageFlag' initialized with default parameters.+emptyFlag :: FlagName -> PackageFlag+emptyFlag name = MkPackageFlag+ { flagName = name+ , flagDescription = ""+ , flagDefault = True+ , flagManual = False+ }++-- | A 'FlagName' is the name of a user-defined configuration flag+--+-- Use 'mkFlagName' and 'unFlagName' to convert from/to a 'String'.+--+-- This type is opaque since @Cabal-2.0@+--+-- @since 2.0.0.2+newtype FlagName = FlagName ShortText+ deriving (Eq, Generic, Ord, Show, Read, Typeable, Data, NFData)++-- | Construct a 'FlagName' from a 'String'+--+-- 'mkFlagName' is the inverse to 'unFlagName'+--+-- Note: No validations are performed to ensure that the resulting+-- 'FlagName' is valid+--+-- @since 2.0.0.2+mkFlagName :: String -> FlagName+mkFlagName = FlagName . toShortText++-- | 'mkFlagName'+--+-- @since 2.0.0.2+instance IsString FlagName where+ fromString = mkFlagName++-- | Convert 'FlagName' to 'String'+--+-- @since 2.0.0.2+unFlagName :: FlagName -> String+unFlagName (FlagName s) = fromShortText s++instance Binary FlagName+instance Structured FlagName++instance Pretty FlagName where+ pretty = Disp.text . unFlagName++instance Parsec FlagName where+ -- Note: we don't check that FlagName doesn't have leading dash,+ -- cabal check will do that.+ parsec = mkFlagName . lowercase <$> parsec'+ where+ parsec' = (:) <$> lead <*> rest+ lead = P.satisfy (\c -> isAlphaNum c || c == '_')+ rest = P.munch (\c -> isAlphaNum c || c == '_' || c == '-')++-- | A 'FlagAssignment' is a total or partial mapping of 'FlagName's to+-- 'Bool' flag values. It represents the flags chosen by the user or+-- discovered during configuration. For example @--flags=foo --flags=-bar@+-- becomes @[("foo", True), ("bar", False)]@+--+-- TODO: Why we record the multiplicity of the flag?+--+newtype FlagAssignment+ = FlagAssignment { getFlagAssignment :: Map.Map FlagName (Int, Bool) }+ deriving (Binary, Generic, NFData, Typeable)++instance Structured FlagAssignment++instance Eq FlagAssignment where+ (==) (FlagAssignment m1) (FlagAssignment m2)+ = fmap snd m1 == fmap snd m2++instance Ord FlagAssignment where+ compare (FlagAssignment m1) (FlagAssignment m2)+ = fmap snd m1 `compare` fmap snd m2++-- | Combines pairs of values contained in the 'FlagAssignment' Map.+--+-- The last flag specified takes precedence, and we record the number+-- of times we have seen the flag.+--+combineFlagValues :: (Int, Bool) -> (Int, Bool) -> (Int, Bool)+combineFlagValues (c1, _) (c2, b2) = (c1 + c2, b2)++-- The 'Semigroup' instance currently is right-biased.+--+-- If duplicate flags are specified, we want the last flag specified to+-- take precedence and we want to know how many times the flag has been+-- specified so that we have the option of warning the user about+-- supplying duplicate flags.+instance Semigroup FlagAssignment where+ (<>) (FlagAssignment m1) (FlagAssignment m2)+ = FlagAssignment (Map.unionWith combineFlagValues m1 m2)++instance Monoid FlagAssignment where+ mempty = FlagAssignment Map.empty+ mappend = (<>)++-- | Construct a 'FlagAssignment' from a list of flag/value pairs.+--+-- If duplicate flags occur in the input list, the later entries+-- in the list will take precedence.+--+-- @since 2.2.0+mkFlagAssignment :: [(FlagName, Bool)] -> FlagAssignment+mkFlagAssignment =+ FlagAssignment .+ Map.fromListWith (flip combineFlagValues) . fmap (fmap (\b -> (1, b)))++-- | Deconstruct a 'FlagAssignment' into a list of flag/value pairs.+--+-- @ 'null' ('findDuplicateFlagAssignments' fa) ==> ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @+--+-- @since 2.2.0+unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]+unFlagAssignment = fmap (fmap snd) . Map.toList . getFlagAssignment++-- | Test whether 'FlagAssignment' is empty.+--+-- @since 2.2.0+nullFlagAssignment :: FlagAssignment -> Bool+nullFlagAssignment = Map.null . getFlagAssignment++-- | Lookup the value for a flag+--+-- Returns 'Nothing' if the flag isn't contained in the 'FlagAssignment'.+--+-- @since 2.2.0+lookupFlagAssignment :: FlagName -> FlagAssignment -> Maybe Bool+lookupFlagAssignment fn = fmap snd . Map.lookup fn . getFlagAssignment++-- | Insert or update the boolean value of a flag.+--+-- If the flag is already present in the 'FlagAssigment', the+-- value will be updated and the fact that multiple values have+-- been provided for that flag will be recorded so that a+-- warning can be generated later on.+--+-- @since 2.2.0+insertFlagAssignment :: FlagName -> Bool -> FlagAssignment -> FlagAssignment+-- TODO: this currently just shadows prior values for an existing+-- flag; rather than enforcing uniqueness at construction, it's+-- verified later on via `D.C.Dependency.configuredPackageProblems`+insertFlagAssignment flag val =+ FlagAssignment .+ Map.insertWith (flip combineFlagValues) flag (1, val) . getFlagAssignment++-- | Remove all flag-assignments from the first 'FlagAssignment' that+-- are contained in the second 'FlagAssignment'+--+-- NB/TODO: This currently only removes flag assignments which also+-- match the value assignment! We should review the code which uses+-- this operation to figure out if this it's not enough to only+-- compare the flagnames without the values.+--+-- @since 2.2.0+diffFlagAssignment :: FlagAssignment -> FlagAssignment -> FlagAssignment+diffFlagAssignment fa1 fa2 = FlagAssignment+ (Map.difference (getFlagAssignment fa1) (getFlagAssignment fa2))++-- | Find the 'FlagName's that have been listed more than once.+--+-- @since 2.2.0+findDuplicateFlagAssignments :: FlagAssignment -> [FlagName]+findDuplicateFlagAssignments =+ Map.keys . Map.filter ((> 1) . fst) . getFlagAssignment++-- | @since 2.2.0+instance Read FlagAssignment where+ readsPrec p s = [ (FlagAssignment x, rest) | (x,rest) <- readsPrec p s ]++-- | @since 2.2.0+instance Show FlagAssignment where+ showsPrec p (FlagAssignment xs) = showsPrec p xs++-- | String representation of a flag-value pair.+showFlagValue :: (FlagName, Bool) -> String+showFlagValue (f, True) = '+' : unFlagName f+showFlagValue (f, False) = '-' : unFlagName f++-- | @since 3.4.0.0+instance Pretty FlagAssignment where+ pretty = dispFlagAssignment++-- |+--+-- >>> simpleParsec "" :: Maybe FlagAssignment+-- Just (fromList [])+--+-- >>> simpleParsec "+foo -bar" :: Maybe FlagAssignment+-- Just (fromList [(FlagName "bar",(1,False)),(FlagName "foo",(1,True))])+--+-- >>> simpleParsec "-none -any" :: Maybe FlagAssignment+-- Just (fromList [(FlagName "any",(1,False)),(FlagName "none",(1,False))])+--+-- >>> simpleParsec "+foo -foo +foo +foo" :: Maybe FlagAssignment+-- Just (fromList [(FlagName "foo",(4,True))])+--+-- >>> simpleParsec "+foo -bar baz" :: Maybe FlagAssignment+-- Nothing+--+-- @since 3.4.0.0+--+instance Parsec FlagAssignment where+ parsec = parsecFlagAssignment++-- | Pretty-prints a flag assignment.+dispFlagAssignment :: FlagAssignment -> Disp.Doc+dispFlagAssignment = Disp.hsep . map (Disp.text . showFlagValue) . unFlagAssignment++-- | Parses a flag assignment.+parsecFlagAssignment :: CabalParsing m => m FlagAssignment+parsecFlagAssignment = mkFlagAssignment <$>+ P.sepBy (onFlag <|> offFlag) P.skipSpaces1+ where+ onFlag = do+ _ <- P.char '+'+ f <- parsec+ return (f, True)+ offFlag = do+ _ <- P.char '-'+ f <- parsec+ return (f, False)++-- | Parse a non-empty flag assignment+--+-- The flags have to explicitly start with minus or plus.+--+-- @since 3.4.0.0+parsecFlagAssignmentNonEmpty :: CabalParsing m => m FlagAssignment+parsecFlagAssignmentNonEmpty = mkFlagAssignment . toList <$>+ P.sepByNonEmpty (onFlag <|> offFlag) P.skipSpaces1+ where+ onFlag = do+ _ <- P.char '+'+ f <- parsec+ return (f, True)+ offFlag = do+ _ <- P.char '-'+ f <- parsec+ return (f, False)++-- | Show flag assignment.+--+-- @since 3.4.0.0+showFlagAssignment :: FlagAssignment -> String+showFlagAssignment = prettyShow . dispFlagAssignment++-------------------------------------------------------------------------------+-- Legacy: without requiring ++-------------------------------------------------------------------------------++-- | We need this as far as we support custom setups older than 2.2.0.0+--+-- @since 3.4.0.0+legacyShowFlagAssignment :: FlagAssignment -> String+legacyShowFlagAssignment =+ prettyShow . Disp.hsep . map Disp.text . legacyShowFlagAssignment'++-- | @since 3.4.0.0+legacyShowFlagAssignment' :: FlagAssignment -> [String]+legacyShowFlagAssignment' = map legacyShowFlagValue . unFlagAssignment++-- | @since 3.4.0.0+legacyShowFlagValue :: (FlagName, Bool) -> String+legacyShowFlagValue (f, True) = unFlagName f+legacyShowFlagValue (f, False) = '-' : unFlagName f++-- |+-- We need this as far as we support custom setups older than 2.2.0.0+--+-- @since 3.4.0.0+legacyParsecFlagAssignment :: CabalParsing m => m FlagAssignment+legacyParsecFlagAssignment = mkFlagAssignment <$>+ P.sepBy (onFlag <|> offFlag) P.skipSpaces1+ where+ onFlag = do+ _ <- P.optional (P.char '+')+ f <- parsec+ return (f, True)+ offFlag = do+ _ <- P.char '-'+ f <- parsec+ return (f, False)
+ src/Distribution/Types/ForeignLib.hs view
@@ -0,0 +1,199 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.ForeignLib(+ ForeignLib(..),+ emptyForeignLib,+ foreignLibModules,+ foreignLibIsShared,+ foreignLibVersion,++ LibVersionInfo,+ mkLibVersionInfo,+ libVersionInfoCRA,+ libVersionNumber,+ libVersionNumberShow,+ libVersionMajor+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.ModuleName+import Distribution.Parsec+import Distribution.Pretty+import Distribution.System+import Distribution.Types.BuildInfo+import Distribution.Types.ForeignLibOption+import Distribution.Types.ForeignLibType+import Distribution.Types.UnqualComponentName+import Distribution.Version++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp+import qualified Text.Read as Read++import qualified Distribution.Types.BuildInfo.Lens as L++-- | A foreign library stanza is like a library stanza, except that+-- the built code is intended for consumption by a non-Haskell client.+data ForeignLib = ForeignLib {+ -- | Name of the foreign library+ foreignLibName :: UnqualComponentName+ -- | What kind of foreign library is this (static or dynamic).+ , foreignLibType :: ForeignLibType+ -- | What options apply to this foreign library (e.g., are we+ -- merging in all foreign dependencies.)+ , foreignLibOptions :: [ForeignLibOption]+ -- | Build information for this foreign library.+ , foreignLibBuildInfo :: BuildInfo+ -- | Libtool-style version-info data to compute library version.+ -- Refer to the libtool documentation on the+ -- current:revision:age versioning scheme.+ , foreignLibVersionInfo :: Maybe LibVersionInfo+ -- | Linux library version+ , foreignLibVersionLinux :: Maybe Version++ -- | (Windows-specific) module definition files+ --+ -- This is a list rather than a maybe field so that we can flatten+ -- the condition trees (for instance, when creating an sdist)+ , foreignLibModDefFile :: [FilePath]+ }+ deriving (Generic, Show, Read, Eq, Typeable, Data)++data LibVersionInfo = LibVersionInfo Int Int Int deriving (Data, Eq, Generic, Typeable)++instance Ord LibVersionInfo where+ LibVersionInfo c r _ `compare` LibVersionInfo c' r' _ =+ case c `compare` c' of+ EQ -> r `compare` r'+ e -> e++instance Show LibVersionInfo where+ showsPrec d (LibVersionInfo c r a) = showParen (d > 10)+ $ showString "mkLibVersionInfo "+ . showsPrec 11 (c,r,a)++instance Read LibVersionInfo where+ readPrec = Read.parens $ do+ Read.Ident "mkLibVersionInfo" <- Read.lexP+ t <- Read.step Read.readPrec+ return (mkLibVersionInfo t)++instance Binary LibVersionInfo+instance Structured LibVersionInfo+instance NFData LibVersionInfo where rnf = genericRnf++instance Pretty LibVersionInfo where+ pretty (LibVersionInfo c r a)+ = Disp.hcat $ Disp.punctuate (Disp.char ':') $ map Disp.int [c,r,a]++instance Parsec LibVersionInfo where+ parsec = do+ c <- P.integral+ (r, a) <- P.option (0,0) $ do+ _ <- P.char ':'+ r <- P.integral+ a <- P.option 0 $ do+ _ <- P.char ':'+ P.integral+ return (r,a)+ return $ mkLibVersionInfo (c,r,a)++-- | Construct 'LibVersionInfo' from @(current, revision, age)@+-- numbers.+--+-- For instance, @mkLibVersionInfo (3,0,0)@ constructs a+-- 'LibVersionInfo' representing the version-info @3:0:0@.+--+-- All version components must be non-negative.+mkLibVersionInfo :: (Int, Int, Int) -> LibVersionInfo+mkLibVersionInfo (c,r,a) = LibVersionInfo c r a++-- | From a given 'LibVersionInfo', extract the @(current, revision,+-- age)@ numbers.+libVersionInfoCRA :: LibVersionInfo -> (Int, Int, Int)+libVersionInfoCRA (LibVersionInfo c r a) = (c,r,a)++-- | Given a version-info field, produce a @major.minor.build@ version+libVersionNumber :: LibVersionInfo -> (Int, Int, Int)+libVersionNumber (LibVersionInfo c r a) = (c-a , a , r)++-- | Given a version-info field, return @"major.minor.build"@ as a+-- 'String'+libVersionNumberShow :: LibVersionInfo -> String+libVersionNumberShow v =+ let (major, minor, build) = libVersionNumber v+ in show major ++ "." ++ show minor ++ "." ++ show build++-- | Return the @major@ version of a version-info field.+libVersionMajor :: LibVersionInfo -> Int+libVersionMajor (LibVersionInfo c _ a) = c-a++instance L.HasBuildInfo ForeignLib where+ buildInfo f l = (\x -> l { foreignLibBuildInfo = x }) <$> f (foreignLibBuildInfo l)++instance Binary ForeignLib+instance Structured ForeignLib+instance NFData ForeignLib where rnf = genericRnf++instance Semigroup ForeignLib where+ a <> b = ForeignLib {+ foreignLibName = combine' foreignLibName+ , foreignLibType = combine foreignLibType+ , foreignLibOptions = combine foreignLibOptions+ , foreignLibBuildInfo = combine foreignLibBuildInfo+ , foreignLibVersionInfo = combine'' foreignLibVersionInfo+ , foreignLibVersionLinux = combine'' foreignLibVersionLinux+ , foreignLibModDefFile = combine foreignLibModDefFile+ }+ where combine field = field a `mappend` field b+ combine' field = case ( unUnqualComponentName $ field a+ , unUnqualComponentName $ field b) of+ ("", _) -> field b+ (_, "") -> field a+ (x, y) -> error $ "Ambiguous values for executable field: '"+ ++ x ++ "' and '" ++ y ++ "'"+ combine'' field = field b++instance Monoid ForeignLib where+ mempty = ForeignLib {+ foreignLibName = mempty+ , foreignLibType = ForeignLibTypeUnknown+ , foreignLibOptions = []+ , foreignLibBuildInfo = mempty+ , foreignLibVersionInfo = Nothing+ , foreignLibVersionLinux = Nothing+ , foreignLibModDefFile = []+ }+ mappend = (<>)++-- | An empty foreign library.+emptyForeignLib :: ForeignLib+emptyForeignLib = mempty++-- | Modules defined by a foreign library.+foreignLibModules :: ForeignLib -> [ModuleName]+foreignLibModules = otherModules . foreignLibBuildInfo++-- | Is the foreign library shared?+foreignLibIsShared :: ForeignLib -> Bool+foreignLibIsShared = foreignLibTypeIsShared . foreignLibType++-- | Get a version number for a foreign library.+-- If we're on Linux, and a Linux version is specified, use that.+-- If we're on Linux, and libtool-style version-info is specified, translate+-- that field into appropriate version numbers.+-- Otherwise, this feature is unsupported so we don't return any version data.+foreignLibVersion :: ForeignLib -> OS -> [Int]+foreignLibVersion flib Linux =+ case foreignLibVersionLinux flib of+ Just v -> versionNumbers v+ Nothing ->+ case foreignLibVersionInfo flib of+ Just v' ->+ let (major, minor, build) = libVersionNumber v'+ in [major, minor, build]+ Nothing -> []+foreignLibVersion _ _ = []
+ src/Distribution/Types/ForeignLib/Lens.hs view
@@ -0,0 +1,45 @@+module Distribution.Types.ForeignLib.Lens (+ ForeignLib,+ module Distribution.Types.ForeignLib.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.ForeignLib (ForeignLib, LibVersionInfo)+import Distribution.Types.ForeignLibOption (ForeignLibOption)+import Distribution.Types.ForeignLibType (ForeignLibType)+import Distribution.Types.UnqualComponentName (UnqualComponentName)+import Distribution.Version (Version)++import qualified Distribution.Types.ForeignLib as T++foreignLibName :: Lens' ForeignLib UnqualComponentName+foreignLibName f s = fmap (\x -> s { T.foreignLibName = x }) (f (T.foreignLibName s))+{-# INLINE foreignLibName #-}++foreignLibType :: Lens' ForeignLib ForeignLibType+foreignLibType f s = fmap (\x -> s { T.foreignLibType = x }) (f (T.foreignLibType s))+{-# INLINE foreignLibType #-}++foreignLibOptions :: Lens' ForeignLib [ForeignLibOption]+foreignLibOptions f s = fmap (\x -> s { T.foreignLibOptions = x }) (f (T.foreignLibOptions s))+{-# INLINE foreignLibOptions #-}++foreignLibBuildInfo :: Lens' ForeignLib BuildInfo+foreignLibBuildInfo f s = fmap (\x -> s { T.foreignLibBuildInfo = x }) (f (T.foreignLibBuildInfo s))+{-# INLINE foreignLibBuildInfo #-}++foreignLibVersionInfo :: Lens' ForeignLib (Maybe LibVersionInfo)+foreignLibVersionInfo f s = fmap (\x -> s { T.foreignLibVersionInfo = x }) (f (T.foreignLibVersionInfo s))+{-# INLINE foreignLibVersionInfo #-}++foreignLibVersionLinux :: Lens' ForeignLib (Maybe Version)+foreignLibVersionLinux f s = fmap (\x -> s { T.foreignLibVersionLinux = x }) (f (T.foreignLibVersionLinux s))+{-# INLINE foreignLibVersionLinux #-}++foreignLibModDefFile :: Lens' ForeignLib [FilePath]+foreignLibModDefFile f s = fmap (\x -> s { T.foreignLibModDefFile = x }) (f (T.foreignLibModDefFile s))+{-# INLINE foreignLibModDefFile #-}
+ src/Distribution/Types/ForeignLibOption.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Distribution.Types.ForeignLibOption(+ ForeignLibOption(..)+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++data ForeignLibOption =+ -- | Merge in all dependent libraries (i.e., use+ -- @ghc -shared -static@ rather than just record+ -- the dependencies, ala @ghc -shared -dynamic@).+ -- This option is compulsory on Windows and unsupported+ -- on other platforms.+ ForeignLibStandalone+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Pretty ForeignLibOption where+ pretty ForeignLibStandalone = Disp.text "standalone"++instance Parsec ForeignLibOption where+ parsec = do+ name <- P.munch1 (\c -> isAlphaNum c || c == '-')+ case name of+ "standalone" -> return ForeignLibStandalone+ _ -> fail "unrecognized foreign-library option"++instance Binary ForeignLibOption+instance Structured ForeignLibOption+instance NFData ForeignLibOption where rnf = genericRnf
+ src/Distribution/Types/ForeignLibType.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Distribution.Types.ForeignLibType(+ ForeignLibType(..),+ knownForeignLibTypes,+ foreignLibTypeIsShared,+) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.PackageDescription.Utils++import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | What kind of foreign library is to be built?+data ForeignLibType =+ -- | A native shared library (@.so@ on Linux, @.dylib@ on OSX, or+ -- @.dll@ on Windows).+ ForeignLibNativeShared+ -- | A native static library (not currently supported.)+ | ForeignLibNativeStatic+ -- TODO: Maybe this should record a string?+ | ForeignLibTypeUnknown+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Pretty ForeignLibType where+ pretty ForeignLibNativeShared = Disp.text "native-shared"+ pretty ForeignLibNativeStatic = Disp.text "native-static"+ pretty ForeignLibTypeUnknown = Disp.text "unknown"++instance Parsec ForeignLibType where+ parsec = do+ name <- P.munch1 (\c -> isAlphaNum c || c == '-')+ return $ case name of+ "native-shared" -> ForeignLibNativeShared+ "native-static" -> ForeignLibNativeStatic+ _ -> ForeignLibTypeUnknown++instance Binary ForeignLibType+instance Structured ForeignLibType+instance NFData ForeignLibType where rnf = genericRnf++instance Semigroup ForeignLibType where+ ForeignLibTypeUnknown <> b = b+ a <> ForeignLibTypeUnknown = a+ _ <> _ = error "Ambiguous foreign library type"++instance Monoid ForeignLibType where+ mempty = ForeignLibTypeUnknown+ mappend = (<>)++knownForeignLibTypes :: [ForeignLibType]+knownForeignLibTypes = [+ ForeignLibNativeShared+ , ForeignLibNativeStatic+ ]++foreignLibTypeIsShared :: ForeignLibType -> Bool+foreignLibTypeIsShared t =+ case t of+ ForeignLibNativeShared -> True+ ForeignLibNativeStatic -> False+ ForeignLibTypeUnknown -> cabalBug "Unknown foreign library type"
+ src/Distribution/Types/GenericPackageDescription.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Distribution.Types.GenericPackageDescription (+ GenericPackageDescription(..),+ emptyGenericPackageDescription,+) where++import Prelude ()+import Distribution.Compat.Prelude++-- lens+import Distribution.Compat.Lens as L+import qualified Distribution.Types.BuildInfo.Lens as L++import Distribution.Types.PackageDescription++import Distribution.Types.Benchmark+import Distribution.Types.CondTree+import Distribution.Types.ConfVar+import Distribution.Types.Dependency+import Distribution.Types.Executable+import Distribution.Types.Flag+import Distribution.Types.ForeignLib+import Distribution.Types.Library+import Distribution.Types.TestSuite+import Distribution.Types.UnqualComponentName+import Distribution.Package+import Distribution.Version++-- ---------------------------------------------------------------------------+-- The 'GenericPackageDescription' type++data GenericPackageDescription =+ GenericPackageDescription+ { packageDescription :: PackageDescription+ , gpdScannedVersion :: Maybe Version+ -- ^ This is a version as specified in source.+ -- We populate this field in index reading for dummy GPDs,+ -- only when GPD reading failed, but scanning haven't.+ --+ -- Cabal-the-library never produces GPDs with Just as gpdScannedVersion.+ --+ -- Perfectly, PackageIndex should have sum type, so we don't need to+ -- have dummy GPDs.+ , genPackageFlags :: [PackageFlag]+ , condLibrary :: Maybe (CondTree ConfVar [Dependency] Library)+ , condSubLibraries :: [( UnqualComponentName+ , CondTree ConfVar [Dependency] Library )]+ , condForeignLibs :: [( UnqualComponentName+ , CondTree ConfVar [Dependency] ForeignLib )]+ , condExecutables :: [( UnqualComponentName+ , CondTree ConfVar [Dependency] Executable )]+ , condTestSuites :: [( UnqualComponentName+ , CondTree ConfVar [Dependency] TestSuite )]+ , condBenchmarks :: [( UnqualComponentName+ , CondTree ConfVar [Dependency] Benchmark )]+ }+ deriving (Show, Eq, Typeable, Data, Generic)++instance Package GenericPackageDescription where+ packageId = packageId . packageDescription++instance Binary GenericPackageDescription+instance Structured GenericPackageDescription+instance NFData GenericPackageDescription where rnf = genericRnf++emptyGenericPackageDescription :: GenericPackageDescription+emptyGenericPackageDescription = GenericPackageDescription emptyPackageDescription Nothing [] Nothing [] [] [] [] []++-- -----------------------------------------------------------------------------+-- Traversal Instances++instance L.HasBuildInfos GenericPackageDescription where+ traverseBuildInfos f (GenericPackageDescription p v a1 x1 x2 x3 x4 x5 x6) =+ GenericPackageDescription+ <$> L.traverseBuildInfos f p+ <*> pure v+ <*> pure a1+ <*> (traverse . traverseCondTreeBuildInfo) f x1+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x2+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x3+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x4+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x5+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x6+ where++-- We use this traversal to keep [Dependency] field in CondTree up to date.+traverseCondTreeBuildInfo+ :: forall f comp v. (Applicative f, L.HasBuildInfo comp)+ => LensLike' f (CondTree v [Dependency] comp) L.BuildInfo+traverseCondTreeBuildInfo g = node where+ mkCondNode :: comp -> [CondBranch v [Dependency] comp] -> CondTree v [Dependency] comp+ mkCondNode comp branches = CondNode comp (view L.targetBuildDepends comp) branches++ node (CondNode comp _ branches) = mkCondNode+ <$> L.buildInfo g comp+ <*> traverse branch branches++ branch (CondBranch v x y) = CondBranch v+ <$> node x+ <*> traverse node y
+ src/Distribution/Types/GenericPackageDescription/Lens.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE Rank2Types #-}+module Distribution.Types.GenericPackageDescription.Lens (+ GenericPackageDescription,+ PackageFlag,+ FlagName,+ ConfVar (..),+ module Distribution.Types.GenericPackageDescription.Lens,+ ) where++import Prelude()+import Distribution.Compat.Prelude+import Distribution.Compat.Lens++import qualified Distribution.Types.GenericPackageDescription as T++-- We import types from their packages, so we can remove unused imports+-- and have wider inter-module dependency graph+import Distribution.Types.CondTree (CondTree)+import Distribution.Types.Dependency (Dependency)+import Distribution.Types.Executable (Executable)+import Distribution.Types.PackageDescription (PackageDescription)+import Distribution.Types.Benchmark (Benchmark)+import Distribution.Types.ForeignLib (ForeignLib)+import Distribution.Types.GenericPackageDescription (GenericPackageDescription(GenericPackageDescription) )+import Distribution.Types.Flag (PackageFlag(MkPackageFlag), FlagName)+import Distribution.Types.ConfVar (ConfVar (..))+import Distribution.Types.Library (Library)+import Distribution.Types.TestSuite (TestSuite)+import Distribution.Types.UnqualComponentName (UnqualComponentName)+import Distribution.System (Arch, OS)+import Distribution.Compiler (CompilerFlavor)+import Distribution.Version (Version, VersionRange)++-------------------------------------------------------------------------------+-- GenericPackageDescription+-------------------------------------------------------------------------------++packageDescription :: Lens' GenericPackageDescription PackageDescription+packageDescription f s = fmap (\x -> s { T.packageDescription = x }) (f (T.packageDescription s))+{-# INLINE packageDescription #-}++gpdScannedVersion :: Lens' GenericPackageDescription (Maybe Version)+gpdScannedVersion f s = fmap (\x -> s { T.gpdScannedVersion = x }) (f (T.gpdScannedVersion s))+{-# INLINE gpdScannedVersion #-}++genPackageFlags :: Lens' GenericPackageDescription [PackageFlag]+genPackageFlags f s = fmap (\x -> s { T.genPackageFlags = x }) (f (T.genPackageFlags s))+{-# INLINE genPackageFlags #-}++condLibrary :: Lens' GenericPackageDescription (Maybe (CondTree ConfVar [Dependency] Library))+condLibrary f s = fmap (\x -> s { T.condLibrary = x }) (f (T.condLibrary s))+{-# INLINE condLibrary #-}++condSubLibraries :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] Library))]+condSubLibraries f s = fmap (\x -> s { T.condSubLibraries = x }) (f (T.condSubLibraries s))+{-# INLINE condSubLibraries #-}++condForeignLibs :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] ForeignLib))]+condForeignLibs f s = fmap (\x -> s { T.condForeignLibs = x }) (f (T.condForeignLibs s))+{-# INLINE condForeignLibs #-}++condExecutables :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] Executable))]+condExecutables f s = fmap (\x -> s { T.condExecutables = x }) (f (T.condExecutables s))+{-# INLINE condExecutables #-}++condTestSuites :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] TestSuite))]+condTestSuites f s = fmap (\x -> s { T.condTestSuites = x }) (f (T.condTestSuites s))+{-# INLINE condTestSuites #-}++condBenchmarks :: Lens' GenericPackageDescription [(UnqualComponentName,(CondTree ConfVar [Dependency] Benchmark))]+condBenchmarks f s = fmap (\x -> s { T.condBenchmarks = x }) (f (T.condBenchmarks s))+{-# INLINE condBenchmarks #-}++allCondTrees+ :: Applicative f+ => (forall a. CondTree ConfVar [Dependency] a+ -> f (CondTree ConfVar [Dependency] a))+ -> GenericPackageDescription+ -> f GenericPackageDescription+allCondTrees f (GenericPackageDescription p v a1 x1 x2 x3 x4 x5 x6) =+ GenericPackageDescription+ <$> pure p+ <*> pure v+ <*> pure a1+ <*> traverse f x1+ <*> (traverse . _2) f x2+ <*> (traverse . _2) f x3+ <*> (traverse . _2) f x4+ <*> (traverse . _2) f x5+ <*> (traverse . _2) f x6+++-------------------------------------------------------------------------------+-- Flag+-------------------------------------------------------------------------------++flagName :: Lens' PackageFlag FlagName+flagName f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag y1 x2 x3 x4) (f x1)+{-# INLINE flagName #-}++flagDescription :: Lens' PackageFlag String+flagDescription f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 y1 x3 x4) (f x2)+{-# INLINE flagDescription #-}++flagDefault :: Lens' PackageFlag Bool+flagDefault f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 x2 y1 x4) (f x3)+{-# INLINE flagDefault #-}++flagManual :: Lens' PackageFlag Bool+flagManual f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 x2 x3 y1) (f x4)+{-# INLINE flagManual #-}++-------------------------------------------------------------------------------+-- ConfVar+-------------------------------------------------------------------------------++_OS :: Traversal' ConfVar OS+_OS f (OS os) = OS <$> f os+_OS _ x = pure x++_Arch :: Traversal' ConfVar Arch+_Arch f (Arch arch) = Arch <$> f arch+_Arch _ x = pure x++_PackageFlag :: Traversal' ConfVar FlagName+_PackageFlag f (PackageFlag flag) = PackageFlag <$> f flag+_PackageFlag _ x = pure x++_Impl :: Traversal' ConfVar (CompilerFlavor, VersionRange)+_Impl f (Impl cf vr) = uncurry Impl <$> f (cf, vr)+_Impl _ x = pure x
+ src/Distribution/Types/GivenComponent.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.GivenComponent (+ GivenComponent(..)+) where++import Distribution.Compat.Prelude++import Distribution.Types.ComponentId+import Distribution.Types.LibraryName+import Distribution.Types.PackageName++-- | A 'GivenComponent' represents a library depended on and explicitly+-- specified by the user/client with @--dependency@+--+-- It enables Cabal to know which 'ComponentId' to associate with a library+--+-- @since 2.3.0.0+data GivenComponent =+ GivenComponent+ { givenComponentPackage :: PackageName+ , givenComponentName :: LibraryName -- --dependency is for libraries+ -- only, not for any component+ , givenComponentId :: ComponentId }+ deriving (Generic, Read, Show, Eq, Typeable)++instance Binary GivenComponent+instance Structured GivenComponent
+ src/Distribution/Types/HookedBuildInfo.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.HookedBuildInfo (+ HookedBuildInfo,+ emptyHookedBuildInfo,+ ) where++-- import Distribution.Compat.Prelude+import Distribution.Types.BuildInfo+import Distribution.Types.UnqualComponentName++-- | 'HookedBuildInfo' is mechanism that hooks can use to+-- override the 'BuildInfo's inside packages. One example+-- use-case (which is used in core libraries today) is as+-- a way of passing flags which are computed by a configure+-- script into Cabal. In this case, the autoconf build type adds+-- hooks to read in a textual 'HookedBuildInfo' format prior+-- to doing any operations.+--+-- Quite honestly, this mechanism is a massive hack since we shouldn't+-- be editing the 'PackageDescription' data structure (it's easy+-- to assume that this data structure shouldn't change and+-- run into bugs, see for example 1c20a6328579af9e37677d507e2e9836ef70ab9d).+-- But it's a bit convenient, because there isn't another data+-- structure that allows adding extra 'BuildInfo' style things.+--+-- In any case, a lot of care has to be taken to make sure the+-- 'HookedBuildInfo' is applied to the 'PackageDescription'. In+-- general this process occurs in "Distribution.Simple", which is+-- responsible for orchestrating the hooks mechanism. The+-- general strategy:+--+-- 1. We run the pre-hook, which produces a 'HookedBuildInfo'+-- (e.g., in the Autoconf case, it reads it out from a file).+-- 2. We sanity-check the hooked build info with+-- 'sanityCheckHookedBuildInfo'.+-- 3. We update our 'PackageDescription' (either freshly read+-- or cached from 'LocalBuildInfo') with 'updatePackageDescription'.+--+-- In principle, we are also supposed to update the copy of+-- the 'PackageDescription' stored in 'LocalBuildInfo'+-- at 'localPkgDescr'. Unfortunately, in practice, there+-- are lots of Custom setup scripts which fail to update+-- 'localPkgDescr' so you really shouldn't rely on it.+-- It's not DEPRECATED because there are legitimate uses+-- for it, but... yeah. Sharp knife. See+-- <https://github.com/haskell/cabal/issues/3606>+-- for more information on the issue.+--+-- It is not well-specified whether or not a 'HookedBuildInfo' applied+-- at configure time is persistent to the 'LocalBuildInfo'. The+-- fact that 'HookedBuildInfo' is passed to 'confHook' MIGHT SUGGEST+-- that the 'HookedBuildInfo' is applied at this time, but actually+-- since 9317b67e6122ab14e53f81b573bd0ecb388eca5a it has been ONLY used+-- to create a modified package description that we check for problems:+-- it is never actually saved to the LBI. Since 'HookedBuildInfo' is+-- applied monoidally to the existing build infos (and it is not an+-- idempotent monoid), it could break things to save it, since we+-- are obligated to apply any new 'HookedBuildInfo' and then we'd+-- get the effect twice. But this does mean we have to re-apply+-- it every time. Hey, it's more flexibility.+type HookedBuildInfo = (Maybe BuildInfo, [(UnqualComponentName, BuildInfo)])++emptyHookedBuildInfo :: HookedBuildInfo+emptyHookedBuildInfo = (Nothing, [])
+ src/Distribution/Types/IncludeRenaming.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.IncludeRenaming (+ IncludeRenaming(..),+ defaultIncludeRenaming,+ isDefaultIncludeRenaming,+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.ModuleRenaming++import qualified Distribution.Compat.CharParsing as P+import Distribution.Parsec+import Distribution.Pretty+import Text.PrettyPrint (text)+import qualified Text.PrettyPrint as Disp++-- ---------------------------------------------------------------------------+-- Module renaming++-- | A renaming on an include: (provides renaming, requires renaming)+data IncludeRenaming+ = IncludeRenaming {+ includeProvidesRn :: ModuleRenaming,+ includeRequiresRn :: ModuleRenaming+ }+ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)++instance Binary IncludeRenaming+instance Structured IncludeRenaming++instance NFData IncludeRenaming where rnf = genericRnf++-- | The 'defaultIncludeRenaming' applied when you only @build-depends@+-- on a package.+defaultIncludeRenaming :: IncludeRenaming+defaultIncludeRenaming = IncludeRenaming defaultRenaming defaultRenaming++-- | Is an 'IncludeRenaming' the default one?+isDefaultIncludeRenaming :: IncludeRenaming -> Bool+isDefaultIncludeRenaming (IncludeRenaming p r) = isDefaultRenaming p && isDefaultRenaming r++instance Pretty IncludeRenaming where+ pretty (IncludeRenaming prov_rn req_rn) =+ pretty prov_rn+ <+> (if isDefaultRenaming req_rn+ then Disp.empty+ else text "requires" <+> pretty req_rn)++instance Parsec IncludeRenaming where+ parsec = do+ prov_rn <- parsec+ req_rn <- P.option defaultRenaming $ P.try $ do+ P.spaces -- no need to be space+ _ <- P.string "requires"+ P.spaces+ parsec+ -- Requirements don't really care if they're mentioned+ -- or not (since you can't thin a requirement.) But+ -- we have a little hack in Configure to combine+ -- the provisions and requirements together before passing+ -- them to GHC, and so the most neutral choice for a requirement+ -- is for the "with" field to be False, so we correctly+ -- thin provisions.+ return (IncludeRenaming prov_rn req_rn)
+ src/Distribution/Types/InstalledPackageInfo.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE OverloadedStrings #-}+module Distribution.Types.InstalledPackageInfo (+ InstalledPackageInfo (..),+ emptyInstalledPackageInfo,+ mungedPackageId,+ mungedPackageName,+ AbiDependency (..),+ ExposedModule (..),+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Backpack+import Distribution.Compat.Graph (IsNode (..))+import Distribution.License+import Distribution.ModuleName+import Distribution.Package hiding (installedUnitId)+import Distribution.Types.AbiDependency+import Distribution.Types.ExposedModule+import Distribution.Types.LibraryName+import Distribution.Types.LibraryVisibility+import Distribution.Types.MungedPackageId+import Distribution.Types.MungedPackageName+import Distribution.Version (nullVersion)+import Distribution.Utils.ShortText (ShortText)++import qualified Distribution.Package as Package+import qualified Distribution.SPDX as SPDX++-- -----------------------------------------------------------------------------+-- The InstalledPackageInfo type++-- 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 (sourcePackageId, installedUnitId) are+ -- exactly the same as PackageDescription+ sourcePackageId :: PackageId,+ sourceLibName :: LibraryName,+ installedComponentId_ :: ComponentId,+ libVisibility :: LibraryVisibility,+ installedUnitId :: UnitId,+ -- INVARIANT: if this package is definite, OpenModule's+ -- OpenUnitId directly records UnitId. If it is+ -- indefinite, OpenModule is always an OpenModuleVar+ -- with the same ModuleName as the key.+ instantiatedWith :: [(ModuleName, OpenModule)],+ compatPackageKey :: String,+ license :: Either SPDX.License License,+ copyright :: !ShortText,+ maintainer :: !ShortText,+ author :: !ShortText,+ stability :: !ShortText,+ homepage :: !ShortText,+ pkgUrl :: !ShortText,+ synopsis :: !ShortText,+ description :: !ShortText,+ category :: !ShortText,+ -- these parts are required by an installed package only:+ abiHash :: AbiHash,+ indefinite :: Bool,+ exposed :: Bool,+ -- INVARIANT: if the package is definite, OpenModule's+ -- OpenUnitId directly records UnitId.+ exposedModules :: [ExposedModule],+ hiddenModules :: [ModuleName],+ trusted :: Bool,+ importDirs :: [FilePath],+ libraryDirs :: [FilePath],+ libraryDynDirs :: [FilePath], -- ^ overrides 'libraryDirs'+ dataDir :: FilePath,+ hsLibraries :: [String],+ extraLibraries :: [String],+ extraGHCiLibraries:: [String], -- overrides extraLibraries for GHCi+ includeDirs :: [FilePath],+ includes :: [String],+ -- INVARIANT: if the package is definite, UnitId is NOT+ -- a ComponentId of an indefinite package+ depends :: [UnitId],+ abiDepends :: [AbiDependency],+ ccOptions :: [String],+ cxxOptions :: [String],+ ldOptions :: [String],+ frameworkDirs :: [FilePath],+ frameworks :: [String],+ haddockInterfaces :: [FilePath],+ haddockHTMLs :: [FilePath],+ pkgRoot :: Maybe FilePath+ }+ deriving (Eq, Generic, Typeable, Read, Show)++instance Binary InstalledPackageInfo+instance Structured InstalledPackageInfo++instance NFData InstalledPackageInfo where rnf = genericRnf++instance Package.HasMungedPackageId InstalledPackageInfo where+ mungedId = mungedPackageId++instance Package.Package InstalledPackageInfo where+ packageId = sourcePackageId++instance Package.HasUnitId InstalledPackageInfo where+ installedUnitId = installedUnitId++instance Package.PackageInstalled InstalledPackageInfo where+ installedDepends = depends++instance IsNode InstalledPackageInfo where+ type Key InstalledPackageInfo = UnitId+ nodeKey = installedUnitId+ nodeNeighbors = depends++mungedPackageId :: InstalledPackageInfo -> MungedPackageId+mungedPackageId ipi =+ MungedPackageId (mungedPackageName ipi) (packageVersion ipi)++-- | Returns the munged package name, which we write into @name@ for+-- compatibility with old versions of GHC.+mungedPackageName :: InstalledPackageInfo -> MungedPackageName+mungedPackageName ipi = MungedPackageName (packageName ipi) (sourceLibName ipi)++emptyInstalledPackageInfo :: InstalledPackageInfo+emptyInstalledPackageInfo+ = InstalledPackageInfo {+ sourcePackageId = PackageIdentifier (mkPackageName "") nullVersion,+ sourceLibName = LMainLibName,+ installedComponentId_ = mkComponentId "",+ installedUnitId = mkUnitId "",+ instantiatedWith = [],+ compatPackageKey = "",+ license = Left SPDX.NONE,+ copyright = "",+ maintainer = "",+ author = "",+ stability = "",+ homepage = "",+ pkgUrl = "",+ synopsis = "",+ description = "",+ category = "",+ abiHash = mkAbiHash "",+ indefinite = False,+ exposed = False,+ exposedModules = [],+ hiddenModules = [],+ trusted = False,+ importDirs = [],+ libraryDirs = [],+ libraryDynDirs = [],+ dataDir = "",+ hsLibraries = [],+ extraLibraries = [],+ extraGHCiLibraries= [],+ includeDirs = [],+ includes = [],+ depends = [],+ abiDepends = [],+ ccOptions = [],+ cxxOptions = [],+ ldOptions = [],+ frameworkDirs = [],+ frameworks = [],+ haddockInterfaces = [],+ haddockHTMLs = [],+ pkgRoot = Nothing,+ libVisibility = LibraryVisibilityPrivate+ }
+ src/Distribution/Types/InstalledPackageInfo/FieldGrammar.hs view
@@ -0,0 +1,317 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+module Distribution.Types.InstalledPackageInfo.FieldGrammar (+ ipiFieldGrammar,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Backpack+import Distribution.CabalSpecVersion+import Distribution.Compat.Lens (Lens', (&), (.~))+import Distribution.Compat.Newtype+import Distribution.FieldGrammar+import Distribution.FieldGrammar.FieldDescrs+import Distribution.License+import Distribution.ModuleName+import Distribution.Package+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.LibraryName+import Distribution.Types.LibraryVisibility+import Distribution.Types.MungedPackageName+import Distribution.Types.UnqualComponentName+import Distribution.Version++import qualified Data.Char as Char+import qualified Data.Map as Map+import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.SPDX as SPDX+import qualified Text.PrettyPrint as Disp++import Distribution.Types.InstalledPackageInfo++import qualified Distribution.Types.InstalledPackageInfo.Lens as L+import qualified Distribution.Types.PackageId.Lens as L++-- Note: GHC goes nuts and inlines everything,+-- One can see e.g. in -ddump-simpl-stats:+--+-- 34886 KnownBranch+-- 8197 wild1_ixF0+--+-- https://gitlab.haskell.org/ghc/ghc/-/issues/13253 might be the cause.+--+-- The workaround is to prevent GHC optimising the code:+infixl 4 <@>+(<@>) :: Applicative f => f (a -> b) -> f a -> f b+f <@> x = f <*> x+{-# NOINLINE (<@>) #-}++ipiFieldGrammar+ :: ( FieldGrammar c g, Applicative (g InstalledPackageInfo), Applicative (g Basic)+ , c (Identity AbiHash)+ , c (Identity LibraryVisibility)+ , c (Identity PackageName)+ , c (Identity UnitId)+ , c (Identity UnqualComponentName)+ , c (List FSep (Identity AbiDependency) AbiDependency)+ , c (List FSep (Identity UnitId) UnitId)+ , c (List FSep (MQuoted ModuleName) ModuleName)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (MQuoted MungedPackageName)+ , c (MQuoted Version)+ , c CompatPackageKey+ , c ExposedModules+ , c InstWith+ , c SpecLicenseLenient+ )+ => g InstalledPackageInfo InstalledPackageInfo+ipiFieldGrammar = mkInstalledPackageInfo+ -- Deprecated fields+ <$> monoidalFieldAla "hugs-options" (alaList' FSep Token) unitedList+ --- https://github.com/haskell/cabal/commit/40f3601e17024f07e0da8e64d3dd390177ce908b+ ^^^ deprecatedSince CabalSpecV1_22 "hugs isn't supported anymore"+ -- Very basic fields: name, version, package-name, lib-name and visibility+ <@> blurFieldGrammar basic basicFieldGrammar+ -- Basic fields+ <@> optionalFieldDef "id" L.installedUnitId (mkUnitId "")+ <@> optionalFieldDefAla "instantiated-with" InstWith L.instantiatedWith []+ <@> optionalFieldDefAla "key" CompatPackageKey L.compatPackageKey ""+ <@> optionalFieldDefAla "license" SpecLicenseLenient L.license (Left SPDX.NONE)+ <@> freeTextFieldDefST "copyright" L.copyright+ <@> freeTextFieldDefST "maintainer" L.maintainer+ <@> freeTextFieldDefST "author" L.author+ <@> freeTextFieldDefST "stability" L.stability+ <@> freeTextFieldDefST "homepage" L.homepage+ <@> freeTextFieldDefST "package-url" L.pkgUrl+ <@> freeTextFieldDefST "synopsis" L.synopsis+ <@> freeTextFieldDefST "description" L.description+ <@> freeTextFieldDefST "category" L.category+ -- Installed fields+ <@> optionalFieldDef "abi" L.abiHash (mkAbiHash "")+ <@> booleanFieldDef "indefinite" L.indefinite False+ <@> booleanFieldDef "exposed" L.exposed False+ <@> monoidalFieldAla "exposed-modules" ExposedModules L.exposedModules+ <@> monoidalFieldAla "hidden-modules" (alaList' FSep MQuoted) L.hiddenModules+ <@> booleanFieldDef "trusted" L.trusted False+ <@> monoidalFieldAla "import-dirs" (alaList' FSep FilePathNT) L.importDirs+ <@> monoidalFieldAla "library-dirs" (alaList' FSep FilePathNT) L.libraryDirs+ <@> monoidalFieldAla "dynamic-library-dirs" (alaList' FSep FilePathNT) L.libraryDynDirs+ <@> optionalFieldDefAla "data-dir" FilePathNT L.dataDir ""+ <@> monoidalFieldAla "hs-libraries" (alaList' FSep Token) L.hsLibraries+ <@> monoidalFieldAla "extra-libraries" (alaList' FSep Token) L.extraLibraries+ <@> monoidalFieldAla "extra-ghci-libraries" (alaList' FSep Token) L.extraGHCiLibraries+ <@> monoidalFieldAla "include-dirs" (alaList' FSep FilePathNT) L.includeDirs+ <@> monoidalFieldAla "includes" (alaList' FSep FilePathNT) L.includes+ <@> monoidalFieldAla "depends" (alaList FSep) L.depends+ <@> monoidalFieldAla "abi-depends" (alaList FSep) L.abiDepends+ <@> monoidalFieldAla "cc-options" (alaList' FSep Token) L.ccOptions+ <@> monoidalFieldAla "cxx-options" (alaList' FSep Token) L.cxxOptions+ <@> monoidalFieldAla "ld-options" (alaList' FSep Token) L.ldOptions+ <@> monoidalFieldAla "framework-dirs" (alaList' FSep FilePathNT) L.frameworkDirs+ <@> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks+ <@> monoidalFieldAla "haddock-interfaces" (alaList' FSep FilePathNT) L.haddockInterfaces+ <@> monoidalFieldAla "haddock-html" (alaList' FSep FilePathNT) L.haddockHTMLs+ <@> optionalFieldAla "pkgroot" FilePathNT L.pkgRoot+ where+ mkInstalledPackageInfo _ Basic {..} = InstalledPackageInfo+ -- _basicPkgName is not used+ -- setMaybePackageId says it can be no-op.+ (PackageIdentifier pn _basicVersion)+ (combineLibraryName ln _basicLibName)+ (mkComponentId "") -- installedComponentId_, not in use+ _basicLibVisibility+ where+ MungedPackageName pn ln = _basicName+{-# SPECIALIZE ipiFieldGrammar :: FieldDescrs InstalledPackageInfo InstalledPackageInfo #-}+{-# SPECIALIZE ipiFieldGrammar :: ParsecFieldGrammar InstalledPackageInfo InstalledPackageInfo #-}+{-# SPECIALIZE ipiFieldGrammar :: PrettyFieldGrammar InstalledPackageInfo InstalledPackageInfo #-}++-- (forall b. [b]) ~ ()+unitedList :: Lens' a [b]+unitedList f s = s <$ f []++-------------------------------------------------------------------------------+-- Helper functions+-------------------------------------------------------------------------------++-- | Combine 'LibraryName'. in parsing we prefer value coming+-- from munged @name@ field over the @lib-name@.+--+-- /Should/ be irrelevant.+combineLibraryName :: LibraryName -> LibraryName -> LibraryName+combineLibraryName l@(LSubLibName _) _ = l+combineLibraryName _ l = l++-- To maintain backwards-compatibility, we accept both comma/non-comma+-- separated variants of this field. You SHOULD use the comma syntax if you+-- use any new functions, although actually it's unambiguous due to a quirk+-- of the fact that modules must start with capital letters.++showExposedModules :: [ExposedModule] -> Disp.Doc+showExposedModules xs+ | all isExposedModule xs = Disp.fsep (map pretty xs)+ | otherwise = Disp.fsep (Disp.punctuate Disp.comma (map pretty xs))+ where isExposedModule (ExposedModule _ Nothing) = True+ isExposedModule _ = False++-- | Setter for the @package-name@ field. It should be acceptable for this+-- to be a no-op.+setMaybePackageName :: Maybe PackageName -> InstalledPackageInfo -> InstalledPackageInfo+setMaybePackageName Nothing ipi = ipi+setMaybePackageName (Just pn) ipi = ipi+ { sourcePackageId = (sourcePackageId ipi) {pkgName=pn}+ }++setMungedPackageName :: MungedPackageName -> InstalledPackageInfo -> InstalledPackageInfo+setMungedPackageName (MungedPackageName pn ln) ipi = ipi+ { sourcePackageId = (sourcePackageId ipi) {pkgName=pn}+ , sourceLibName = ln+ }++--- | Returns @Just@ if the @name@ field of the IPI record would not contain+--- the package name verbatim. This helps us avoid writing @package-name@+--- when it's redundant.+maybePackageName :: InstalledPackageInfo -> Maybe PackageName+maybePackageName ipi = case sourceLibName ipi of+ LMainLibName -> Nothing+ LSubLibName _ -> Just (packageName ipi)++-------------------------------------------------------------------------------+-- Auxiliary types+-------------------------------------------------------------------------------++newtype ExposedModules = ExposedModules { getExposedModules :: [ExposedModule] }++instance Newtype [ExposedModule] ExposedModules++instance Parsec ExposedModules where+ parsec = ExposedModules <$> parsecOptCommaList parsec++instance Pretty ExposedModules where+ pretty = showExposedModules . getExposedModules++newtype CompatPackageKey = CompatPackageKey { getCompatPackageKey :: String }++instance Newtype String CompatPackageKey++instance Pretty CompatPackageKey where+ pretty = Disp.text . getCompatPackageKey++instance Parsec CompatPackageKey where+ parsec = CompatPackageKey <$> P.munch1 uid_char where+ uid_char c = Char.isAlphaNum c || c `elem` ("-_.=[],:<>+" :: String)++newtype InstWith = InstWith { getInstWith :: [(ModuleName,OpenModule)] }++instance Newtype [(ModuleName, OpenModule)] InstWith++instance Pretty InstWith where+ pretty = dispOpenModuleSubst . Map.fromList . getInstWith++instance Parsec InstWith where+ parsec = InstWith . Map.toList <$> parsecOpenModuleSubst++-- | SPDX License expression or legacy license. Lenient parser, accepts either.+newtype SpecLicenseLenient = SpecLicenseLenient { getSpecLicenseLenient :: Either SPDX.License License }++instance Newtype (Either SPDX.License License) SpecLicenseLenient++instance Parsec SpecLicenseLenient where+ parsec = fmap SpecLicenseLenient $ Left <$> P.try parsec <|> Right <$> parsec++instance Pretty SpecLicenseLenient where+ pretty = either pretty pretty . getSpecLicenseLenient++-------------------------------------------------------------------------------+-- Basic fields+-------------------------------------------------------------------------------++-- | This type is used to mangle fields as+-- in serialised textual representation+-- to the actual 'InstalledPackageInfo' fields.+data Basic = Basic+ { _basicName :: MungedPackageName+ , _basicVersion :: Version+ , _basicPkgName :: Maybe PackageName+ , _basicLibName :: LibraryName+ , _basicLibVisibility :: LibraryVisibility+ }++basic :: Lens' InstalledPackageInfo Basic+basic f ipi = g <$> f b+ where+ b = Basic+ (mungedPackageName ipi)+ (packageVersion ipi)+ (maybePackageName ipi)+ (sourceLibName ipi)+ (libVisibility ipi)++ g (Basic n v pn ln lv) = ipi+ & setMungedPackageName n+ & L.sourcePackageId . L.pkgVersion .~ v+ & setMaybePackageName pn+ & L.sourceLibName .~ ln+ & L.libVisibility .~ lv++basicName :: Lens' Basic MungedPackageName+basicName f b = (\x -> b { _basicName = x }) <$> f (_basicName b)+{-# INLINE basicName #-}++basicVersion :: Lens' Basic Version+basicVersion f b = (\x -> b { _basicVersion = x }) <$> f (_basicVersion b)+{-# INLINE basicVersion #-}++basicPkgName :: Lens' Basic (Maybe PackageName)+basicPkgName f b = (\x -> b { _basicPkgName = x }) <$> f (_basicPkgName b)+{-# INLINE basicPkgName #-}++basicLibName :: Lens' Basic (Maybe UnqualComponentName)+basicLibName f b = (\x -> b { _basicLibName = maybeToLibraryName x }) <$>+ f (libraryNameString (_basicLibName b))+{-# INLINE basicLibName #-}++basicLibVisibility :: Lens' Basic LibraryVisibility+basicLibVisibility f b = (\x -> b { _basicLibVisibility = x }) <$>+ f (_basicLibVisibility b)+{-# INLINE basicLibVisibility #-}++basicFieldGrammar+ :: ( FieldGrammar c g, Applicative (g Basic)+ , c (Identity LibraryVisibility)+ , c (Identity PackageName)+ , c (Identity UnqualComponentName)+ , c (MQuoted MungedPackageName)+ , c (MQuoted Version)+ )+ => g Basic Basic+basicFieldGrammar = mkBasic+ <$> optionalFieldDefAla "name" MQuoted basicName (mungedPackageName emptyInstalledPackageInfo)+ <*> optionalFieldDefAla "version" MQuoted basicVersion nullVersion+ <*> optionalField "package-name" basicPkgName+ <*> optionalField "lib-name" basicLibName+ <*> optionalFieldDef "visibility" basicLibVisibility LibraryVisibilityPrivate+ where+ mkBasic n v pn ln lv = Basic n v pn ln' lv'+ where+ ln' = maybe LMainLibName LSubLibName ln+ -- Older GHCs (<8.8) always report installed libraries as private+ -- because their ghc-pkg builds with an older Cabal.+ -- So we always set LibraryVisibilityPublic for main (unnamed) libs.+ -- This can be removed once we stop supporting GHC<8.8, at the+ -- condition that we keep marking main libraries as public when+ -- registering them.+ lv' = if+ let MungedPackageName _ mln = n in+ -- We need to check both because on ghc<8.2 ln' will always+ -- be LMainLibName+ ln' == LMainLibName && mln == LMainLibName+ then LibraryVisibilityPublic+ else lv
+ src/Distribution/Types/InstalledPackageInfo/Lens.hs view
@@ -0,0 +1,190 @@+module Distribution.Types.InstalledPackageInfo.Lens (+ InstalledPackageInfo,+ module Distribution.Types.InstalledPackageInfo.Lens+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Backpack (OpenModule)+import Distribution.License (License)+import Distribution.ModuleName (ModuleName)+import Distribution.Package (AbiHash, ComponentId, PackageIdentifier, UnitId)+import Distribution.Types.InstalledPackageInfo (AbiDependency, ExposedModule, InstalledPackageInfo)+import Distribution.Types.LibraryName (LibraryName)+import Distribution.Types.LibraryVisibility (LibraryVisibility)+import Distribution.Utils.ShortText (ShortText)+++import qualified Distribution.SPDX as SPDX+import qualified Distribution.Types.InstalledPackageInfo as T++sourcePackageId :: Lens' InstalledPackageInfo PackageIdentifier+sourcePackageId f s = fmap (\x -> s { T.sourcePackageId = x }) (f (T.sourcePackageId s))+{-# INLINE sourcePackageId #-}++installedUnitId :: Lens' InstalledPackageInfo UnitId+installedUnitId f s = fmap (\x -> s { T.installedUnitId = x }) (f (T.installedUnitId s))+{-# INLINE installedUnitId #-}++installedComponentId_ :: Lens' InstalledPackageInfo ComponentId+installedComponentId_ f s = fmap (\x -> s { T.installedComponentId_ = x }) (f (T.installedComponentId_ s))+{-# INLINE installedComponentId_ #-}++instantiatedWith :: Lens' InstalledPackageInfo [(ModuleName,OpenModule)]+instantiatedWith f s = fmap (\x -> s { T.instantiatedWith = x }) (f (T.instantiatedWith s))+{-# INLINE instantiatedWith #-}++sourceLibName :: Lens' InstalledPackageInfo LibraryName+sourceLibName f s = fmap (\x -> s { T.sourceLibName = x }) (f (T.sourceLibName s))+{-# INLINE sourceLibName #-}++compatPackageKey :: Lens' InstalledPackageInfo String+compatPackageKey f s = fmap (\x -> s { T.compatPackageKey = x }) (f (T.compatPackageKey s))+{-# INLINE compatPackageKey #-}++license :: Lens' InstalledPackageInfo (Either SPDX.License License)+license f s = fmap (\x -> s { T.license = x }) (f (T.license s))+{-# INLINE license #-}++copyright :: Lens' InstalledPackageInfo ShortText+copyright f s = fmap (\x -> s { T.copyright = x }) (f (T.copyright s))+{-# INLINE copyright #-}++maintainer :: Lens' InstalledPackageInfo ShortText+maintainer f s = fmap (\x -> s { T.maintainer = x }) (f (T.maintainer s))+{-# INLINE maintainer #-}++author :: Lens' InstalledPackageInfo ShortText+author f s = fmap (\x -> s { T.author = x }) (f (T.author s))+{-# INLINE author #-}++stability :: Lens' InstalledPackageInfo ShortText+stability f s = fmap (\x -> s { T.stability = x }) (f (T.stability s))+{-# INLINE stability #-}++homepage :: Lens' InstalledPackageInfo ShortText+homepage f s = fmap (\x -> s { T.homepage = x }) (f (T.homepage s))+{-# INLINE homepage #-}++pkgUrl :: Lens' InstalledPackageInfo ShortText+pkgUrl f s = fmap (\x -> s { T.pkgUrl = x }) (f (T.pkgUrl s))+{-# INLINE pkgUrl #-}++synopsis :: Lens' InstalledPackageInfo ShortText+synopsis f s = fmap (\x -> s { T.synopsis = x }) (f (T.synopsis s))+{-# INLINE synopsis #-}++description :: Lens' InstalledPackageInfo ShortText+description f s = fmap (\x -> s { T.description = x }) (f (T.description s))+{-# INLINE description #-}++category :: Lens' InstalledPackageInfo ShortText+category f s = fmap (\x -> s { T.category = x }) (f (T.category s))+{-# INLINE category #-}++abiHash :: Lens' InstalledPackageInfo AbiHash+abiHash f s = fmap (\x -> s { T.abiHash = x }) (f (T.abiHash s))+{-# INLINE abiHash #-}++indefinite :: Lens' InstalledPackageInfo Bool+indefinite f s = fmap (\x -> s { T.indefinite = x }) (f (T.indefinite s))+{-# INLINE indefinite #-}++exposed :: Lens' InstalledPackageInfo Bool+exposed f s = fmap (\x -> s { T.exposed = x }) (f (T.exposed s))+{-# INLINE exposed #-}++exposedModules :: Lens' InstalledPackageInfo [ExposedModule]+exposedModules f s = fmap (\x -> s { T.exposedModules = x }) (f (T.exposedModules s))+{-# INLINE exposedModules #-}++hiddenModules :: Lens' InstalledPackageInfo [ModuleName]+hiddenModules f s = fmap (\x -> s { T.hiddenModules = x }) (f (T.hiddenModules s))+{-# INLINE hiddenModules #-}++trusted :: Lens' InstalledPackageInfo Bool+trusted f s = fmap (\x -> s { T.trusted = x }) (f (T.trusted s))+{-# INLINE trusted #-}++importDirs :: Lens' InstalledPackageInfo [FilePath]+importDirs f s = fmap (\x -> s { T.importDirs = x }) (f (T.importDirs s))+{-# INLINE importDirs #-}++libraryDirs :: Lens' InstalledPackageInfo [FilePath]+libraryDirs f s = fmap (\x -> s { T.libraryDirs = x }) (f (T.libraryDirs s))+{-# INLINE libraryDirs #-}++libraryDynDirs :: Lens' InstalledPackageInfo [FilePath]+libraryDynDirs f s = fmap (\x -> s { T.libraryDynDirs = x }) (f (T.libraryDynDirs s))+{-# INLINE libraryDynDirs #-}++dataDir :: Lens' InstalledPackageInfo FilePath+dataDir f s = fmap (\x -> s { T.dataDir = x }) (f (T.dataDir s))+{-# INLINE dataDir #-}++hsLibraries :: Lens' InstalledPackageInfo [String]+hsLibraries f s = fmap (\x -> s { T.hsLibraries = x }) (f (T.hsLibraries s))+{-# INLINE hsLibraries #-}++extraLibraries :: Lens' InstalledPackageInfo [String]+extraLibraries f s = fmap (\x -> s { T.extraLibraries = x }) (f (T.extraLibraries s))+{-# INLINE extraLibraries #-}++extraGHCiLibraries :: Lens' InstalledPackageInfo [String]+extraGHCiLibraries f s = fmap (\x -> s { T.extraGHCiLibraries = x }) (f (T.extraGHCiLibraries s))+{-# INLINE extraGHCiLibraries #-}++includeDirs :: Lens' InstalledPackageInfo [FilePath]+includeDirs f s = fmap (\x -> s { T.includeDirs = x }) (f (T.includeDirs s))+{-# INLINE includeDirs #-}++includes :: Lens' InstalledPackageInfo [String]+includes f s = fmap (\x -> s { T.includes = x }) (f (T.includes s))+{-# INLINE includes #-}++depends :: Lens' InstalledPackageInfo [UnitId]+depends f s = fmap (\x -> s { T.depends = x }) (f (T.depends s))+{-# INLINE depends #-}++abiDepends :: Lens' InstalledPackageInfo [AbiDependency]+abiDepends f s = fmap (\x -> s { T.abiDepends = x }) (f (T.abiDepends s))+{-# INLINE abiDepends #-}++ccOptions :: Lens' InstalledPackageInfo [String]+ccOptions f s = fmap (\x -> s { T.ccOptions = x }) (f (T.ccOptions s))+{-# INLINE ccOptions #-}++cxxOptions :: Lens' InstalledPackageInfo [String]+cxxOptions f s = fmap (\x -> s { T.cxxOptions = x }) (f (T.cxxOptions s))+{-# INLINE cxxOptions #-}++ldOptions :: Lens' InstalledPackageInfo [String]+ldOptions f s = fmap (\x -> s { T.ldOptions = x }) (f (T.ldOptions s))+{-# INLINE ldOptions #-}++frameworkDirs :: Lens' InstalledPackageInfo [FilePath]+frameworkDirs f s = fmap (\x -> s { T.frameworkDirs = x }) (f (T.frameworkDirs s))+{-# INLINE frameworkDirs #-}++frameworks :: Lens' InstalledPackageInfo [String]+frameworks f s = fmap (\x -> s { T.frameworks = x }) (f (T.frameworks s))+{-# INLINE frameworks #-}++haddockInterfaces :: Lens' InstalledPackageInfo [FilePath]+haddockInterfaces f s = fmap (\x -> s { T.haddockInterfaces = x }) (f (T.haddockInterfaces s))+{-# INLINE haddockInterfaces #-}++haddockHTMLs :: Lens' InstalledPackageInfo [FilePath]+haddockHTMLs f s = fmap (\x -> s { T.haddockHTMLs = x }) (f (T.haddockHTMLs s))+{-# INLINE haddockHTMLs #-}++pkgRoot :: Lens' InstalledPackageInfo (Maybe FilePath)+pkgRoot f s = fmap (\x -> s { T.pkgRoot = x }) (f (T.pkgRoot s))+{-# INLINE pkgRoot #-}++libVisibility :: Lens' InstalledPackageInfo LibraryVisibility+libVisibility f s = fmap (\x -> s { T.libVisibility = x }) (f (T.libVisibility s))+{-# INLINE libVisibility #-}+
+ src/Distribution/Types/LegacyExeDependency.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.LegacyExeDependency+ ( LegacyExeDependency(..)+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Version (VersionRange, anyVersion)++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | Describes a legacy `build-tools`-style dependency on an executable+--+-- It is "legacy" because we do not know what the build-tool referred to. It+-- could refer to a pkg-config executable (PkgconfigName), or an internal+-- executable (UnqualComponentName). Thus the name is stringly typed.+--+-- @since 2.0.0.2+data LegacyExeDependency = LegacyExeDependency+ String+ VersionRange+ deriving (Generic, Read, Show, Eq, Typeable, Data)++instance Binary LegacyExeDependency+instance Structured LegacyExeDependency+instance NFData LegacyExeDependency where rnf = genericRnf++instance Pretty LegacyExeDependency where+ pretty (LegacyExeDependency name ver) =+ Disp.text name <+> pretty ver++instance Parsec LegacyExeDependency where+ parsec = do+ name <- parsecMaybeQuoted nameP+ P.spaces+ verRange <- parsecMaybeQuoted parsec <|> pure anyVersion+ pure $ LegacyExeDependency name verRange+ where+ nameP = intercalate "-" <$> toList <$> P.sepByNonEmpty component (P.char '-')+ component = do+ cs <- P.munch1 (\c -> isAlphaNum c || c == '+' || c == '_')+ if all isDigit cs then fail "invalid component" else return cs
+ src/Distribution/Types/Lens.hs view
@@ -0,0 +1,25 @@+module Distribution.Types.Lens (+ module Distribution.Types.Benchmark.Lens,+ module Distribution.Types.BuildInfo.Lens,+ module Distribution.Types.Executable.Lens,+ module Distribution.Types.ForeignLib.Lens,+ module Distribution.Types.GenericPackageDescription.Lens,+ module Distribution.Types.Library.Lens,+ module Distribution.Types.PackageDescription.Lens,+ module Distribution.Types.PackageId.Lens,+ module Distribution.Types.SetupBuildInfo.Lens,+ module Distribution.Types.SourceRepo.Lens,+ module Distribution.Types.TestSuite.Lens,+ ) where++import Distribution.Types.Benchmark.Lens+import Distribution.Types.BuildInfo.Lens+import Distribution.Types.Executable.Lens+import Distribution.Types.ForeignLib.Lens+import Distribution.Types.GenericPackageDescription.Lens+import Distribution.Types.Library.Lens+import Distribution.Types.PackageDescription.Lens+import Distribution.Types.PackageId.Lens+import Distribution.Types.SetupBuildInfo.Lens+import Distribution.Types.SourceRepo.Lens+import Distribution.Types.TestSuite.Lens
+ src/Distribution/Types/Library.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.Library (+ Library(..),+ emptyLibrary,+ explicitLibModules,+ libModulesAutogen,+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.ModuleName+import Distribution.Types.BuildInfo+import Distribution.Types.LibraryVisibility+import Distribution.Types.ModuleReexport+import Distribution.Types.LibraryName++import qualified Distribution.Types.BuildInfo.Lens as L++data Library = Library+ { libName :: LibraryName+ , exposedModules :: [ModuleName]+ , reexportedModules :: [ModuleReexport]+ , signatures :: [ModuleName] -- ^ What sigs need implementations?+ , libExposed :: Bool -- ^ Is the lib to be exposed by default? (i.e. whether its modules available in GHCi for example)+ , libVisibility :: LibraryVisibility -- ^ Whether this multilib can be dependent from outside.+ , libBuildInfo :: BuildInfo+ }+ deriving (Generic, Show, Eq, Read, Typeable, Data)++instance L.HasBuildInfo Library where+ buildInfo f l = (\x -> l { libBuildInfo = x }) <$> f (libBuildInfo l)++instance Binary Library+instance Structured Library+instance NFData Library where rnf = genericRnf++emptyLibrary :: Library+emptyLibrary = Library+ { libName = LMainLibName+ , exposedModules = mempty+ , reexportedModules = mempty+ , signatures = mempty+ , libExposed = True+ , libVisibility = mempty+ , libBuildInfo = mempty+ }++-- | This instance is not good.+--+-- We need it for 'PackageDescription.Configuration.addBuildableCondition'.+-- More correct method would be some kind of "create empty clone".+--+-- More concretely, 'addBuildableCondition' will make `libVisibility = False`+-- libraries when `buildable: false`. This may cause problems.+--+instance Monoid Library where+ mempty = emptyLibrary+ mappend = (<>)++instance Semigroup Library where+ a <> b = Library+ { libName = combineLibraryName (libName a) (libName b)+ , exposedModules = combine exposedModules+ , reexportedModules = combine reexportedModules+ , signatures = combine signatures+ , libExposed = libExposed a && libExposed b -- so False propagates+ , libVisibility = combine libVisibility+ , libBuildInfo = combine libBuildInfo+ }+ where combine field = field a `mappend` field b++-- | Get all the module names from the library (exposed and internal modules)+-- which are explicitly listed in the package description which would+-- need to be compiled. (This does not include reexports, which+-- do not need to be compiled.) This may not include all modules for which+-- GHC generated interface files (i.e., implicit modules.)+explicitLibModules :: Library -> [ModuleName]+explicitLibModules lib = exposedModules lib+ ++ otherModules (libBuildInfo lib)+ ++ signatures lib++-- | Get all the auto generated module names from the library, exposed or not.+-- This are a subset of 'libModules'.+libModulesAutogen :: Library -> [ModuleName]+libModulesAutogen lib = autogenModules (libBuildInfo lib)++-- | Combine 'LibraryName'. in parsing we prefer value coming+-- from munged @name@ field over the @lib-name@.+--+-- /Should/ be irrelevant.+combineLibraryName :: LibraryName -> LibraryName -> LibraryName+combineLibraryName l@(LSubLibName _) _ = l+combineLibraryName _ l = l
+ src/Distribution/Types/Library/Lens.hs view
@@ -0,0 +1,45 @@+module Distribution.Types.Library.Lens (+ Library,+ module Distribution.Types.Library.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.ModuleName (ModuleName)+import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.Library (Library)+import Distribution.Types.LibraryName (LibraryName)+import Distribution.Types.LibraryVisibility (LibraryVisibility)+import Distribution.Types.ModuleReexport (ModuleReexport)++import qualified Distribution.Types.Library as T++libName :: Lens' Library LibraryName+libName f s = fmap (\x -> s { T.libName = x }) (f (T.libName s))+{-# INLINE libName #-}++exposedModules :: Lens' Library [ModuleName]+exposedModules f s = fmap (\x -> s { T.exposedModules = x }) (f (T.exposedModules s))+{-# INLINE exposedModules #-}++reexportedModules :: Lens' Library [ModuleReexport]+reexportedModules f s = fmap (\x -> s { T.reexportedModules = x }) (f (T.reexportedModules s))+{-# INLINE reexportedModules #-}++signatures :: Lens' Library [ModuleName]+signatures f s = fmap (\x -> s { T.signatures = x }) (f (T.signatures s))+{-# INLINE signatures #-}++libExposed :: Lens' Library Bool+libExposed f s = fmap (\x -> s { T.libExposed = x }) (f (T.libExposed s))+{-# INLINE libExposed #-}++libVisibility :: Lens' Library LibraryVisibility+libVisibility f s = fmap (\x -> s { T.libVisibility = x }) (f (T.libVisibility s))+{-# INLINE libVisibility #-}++libBuildInfo :: Lens' Library BuildInfo+libBuildInfo f s = fmap (\x -> s { T.libBuildInfo = x }) (f (T.libBuildInfo s))+{-# INLINE libBuildInfo #-}
+ src/Distribution/Types/LibraryName.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.LibraryName (+ LibraryName(..),+ defaultLibName,+ maybeToLibraryName,+ showLibraryName,+ libraryNameStanza,+ libraryNameString,+ -- * Pretty & Parse+ prettyLibraryNameComponent,+ parsecLibraryNameComponent,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.UnqualComponentName+import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++data LibraryName = LMainLibName+ | LSubLibName UnqualComponentName+ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)++instance Binary LibraryName+instance Structured LibraryName+instance NFData LibraryName where rnf = genericRnf++-- | Pretty print 'LibraryName' in build-target-ish syntax.+--+-- /Note:/ there are no 'Pretty' or 'Parsec' instances,+-- as there's other way to represent 'LibraryName', namely as bare+-- 'UnqualComponentName'. +prettyLibraryNameComponent :: LibraryName -> Disp.Doc+prettyLibraryNameComponent LMainLibName = Disp.text "lib"+prettyLibraryNameComponent (LSubLibName str) = Disp.text "lib:" <<>> pretty str++parsecLibraryNameComponent :: CabalParsing m => m LibraryName+parsecLibraryNameComponent = do+ _ <- P.string "lib"+ parseComposite <|> parseSingle+ where+ parseSingle = return LMainLibName+ parseComposite = do+ _ <- P.char ':'+ LSubLibName <$> parsec++defaultLibName :: LibraryName+defaultLibName = LMainLibName++showLibraryName :: LibraryName -> String+showLibraryName LMainLibName = "library"+showLibraryName (LSubLibName name) = "library '" ++ prettyShow name ++ "'"++libraryNameStanza :: LibraryName -> String+libraryNameStanza LMainLibName = "library"+libraryNameStanza (LSubLibName name) = "library " ++ prettyShow name++libraryNameString :: LibraryName -> Maybe UnqualComponentName+libraryNameString LMainLibName = Nothing+libraryNameString (LSubLibName n) = Just n++-- | Convert the 'UnqualComponentName' of a library into a+-- 'LibraryName'.+maybeToLibraryName :: Maybe UnqualComponentName -> LibraryName+maybeToLibraryName Nothing = LMainLibName+maybeToLibraryName (Just n) = LSubLibName n+
+ src/Distribution/Types/LibraryVisibility.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Distribution.Types.LibraryVisibility(+ LibraryVisibility(..),+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | Multi-lib visibility+--+-- @since 3.0.0.0+--+data LibraryVisibility+ -- | Can be depenendent from other packages+ = LibraryVisibilityPublic+ -- | Internal library, default+ | LibraryVisibilityPrivate+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Pretty LibraryVisibility where+ pretty LibraryVisibilityPublic = Disp.text "public"+ pretty LibraryVisibilityPrivate = Disp.text "private"++instance Parsec LibraryVisibility where+ parsec = do+ name <- P.munch1 isAlpha+ parsecWarning PWTExperimental "visibility is experimental feature (issue #5660)"+ case name of+ "public" -> return LibraryVisibilityPublic+ "private" -> return LibraryVisibilityPrivate+ _ -> fail $ "Unknown visibility: " ++ name++instance Binary LibraryVisibility+instance Structured LibraryVisibility+instance NFData LibraryVisibility where rnf = genericRnf++instance Semigroup LibraryVisibility where+ LibraryVisibilityPrivate <> LibraryVisibilityPrivate = LibraryVisibilityPrivate+ _ <> _ = LibraryVisibilityPublic++instance Monoid LibraryVisibility where+ mempty = LibraryVisibilityPrivate+ mappend = (<>)
+ src/Distribution/Types/LocalBuildInfo.hs view
@@ -0,0 +1,304 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++module Distribution.Types.LocalBuildInfo (+ -- * The type++ LocalBuildInfo(..),++ -- * Convenience accessors++ localComponentId,+ localUnitId,+ localCompatPackageKey,+ localPackage,++ -- * Build targets of the 'LocalBuildInfo'.++ componentNameCLBIs,++ -- NB: the primes mean that they take a 'PackageDescription'+ -- which may not match 'localPkgDescr' in 'LocalBuildInfo'.+ -- More logical types would drop this argument, but+ -- at the moment, this is the ONLY supported function, because+ -- 'localPkgDescr' is not guaranteed to match. At some point+ -- we will fix it and then we can use the (free) unprimed+ -- namespace for the correct commands.+ --+ -- See https://github.com/haskell/cabal/issues/3606 for more+ -- details.++ componentNameTargets',+ unitIdTarget',+ allTargetsInBuildOrder',+ withAllTargetsInBuildOrder',+ neededTargetsInBuildOrder',+ withNeededTargetsInBuildOrder',+ testCoverage,++ -- * Functions you SHOULD NOT USE (yet), but are defined here to+ -- prevent someone from accidentally defining them++ componentNameTargets,+ unitIdTarget,+ allTargetsInBuildOrder,+ withAllTargetsInBuildOrder,+ neededTargetsInBuildOrder,+ withNeededTargetsInBuildOrder,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.PackageDescription+import Distribution.Types.ComponentLocalBuildInfo+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.ComponentId+import Distribution.Types.PackageId+import Distribution.Types.UnitId+import Distribution.Types.TargetInfo++import Distribution.Simple.InstallDirs hiding (absoluteInstallDirs,+ prefixRelativeInstallDirs,+ substPathTemplate, )+import Distribution.Simple.Program+import Distribution.PackageDescription+import Distribution.Simple.Compiler+import Distribution.Simple.PackageIndex+import Distribution.Simple.Setup+import Distribution.System+import Distribution.Pretty++import Distribution.Compat.Graph (Graph)+import qualified Distribution.Compat.Graph as Graph+import qualified Data.Map as Map++-- | Data cached after configuration step. See also+-- 'Distribution.Simple.Setup.ConfigFlags'.+data LocalBuildInfo = LocalBuildInfo {+ 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+ componentEnabledSpec :: ComponentRequestedSpec,+ -- ^ What components were enabled during configuration, and why.+ extraConfigArgs :: [String],+ -- ^ Extra args on the command line for the configuration step.+ -- Needed to re-run configuration when .cabal is out of date+ installDirTemplates :: InstallDirTemplates,+ -- ^ The installation directories for the various different+ -- kinds of files+ --TODO: inplaceDirTemplates :: InstallDirs FilePath+ compiler :: Compiler,+ -- ^ The compiler we're building with+ hostPlatform :: Platform,+ -- ^ The platform we're building for+ buildDir :: FilePath,+ -- ^ Where to build the package.+ cabalFilePath :: Maybe FilePath,+ -- ^ Path to the cabal file, if given during configuration.+ componentGraph :: Graph ComponentLocalBuildInfo,+ -- ^ All the components to build, ordered by topological+ -- sort, and with their INTERNAL dependencies over the+ -- intrapackage dependency graph.+ -- TODO: this is assumed to be short; otherwise we want+ -- some sort of ordered map.+ componentNameMap :: Map ComponentName [ComponentLocalBuildInfo],+ -- ^ A map from component name to all matching+ -- components. These coincide with 'componentGraph'+ installedPkgs :: InstalledPackageIndex,+ -- ^ All the info about the installed packages that the+ -- current package depends on (directly or indirectly).+ -- The copy saved on disk does NOT include internal+ -- dependencies (because we just don't have enough+ -- information at this point to have an+ -- 'InstalledPackageInfo' for an internal dep), but we+ -- will often update it with the internal dependencies;+ -- see for example 'Distribution.Simple.Build.build'.+ -- (This admonition doesn't apply for per-component builds.)+ pkgDescrFile :: Maybe FilePath,+ -- ^ the filename containing the .cabal file, if available+ localPkgDescr :: PackageDescription,+ -- ^ WARNING WARNING WARNING Be VERY careful about using+ -- this function; we haven't deprecated it but using it+ -- could introduce subtle bugs related to+ -- 'HookedBuildInfo'.+ --+ -- In principle, this is supposed to contain the+ -- resolved package description, that does not contain+ -- any conditionals. However, it MAY NOT contain+ -- the description with a 'HookedBuildInfo' applied+ -- to it; see 'HookedBuildInfo' for the whole sordid saga.+ -- As much as possible, Cabal library should avoid using+ -- this parameter.+ withPrograms :: ProgramDb, -- ^Location and args for all programs+ withPackageDB :: PackageDBStack, -- ^What package database to use, global\/user+ withVanillaLib:: Bool, -- ^Whether to build normal libs.+ withProfLib :: Bool, -- ^Whether to build profiling versions of libs.+ withSharedLib :: Bool, -- ^Whether to build shared versions of libs.+ withStaticLib :: Bool, -- ^Whether to build static versions of libs (with all other libs rolled in)+ withDynExe :: Bool, -- ^Whether to link executables dynamically+ withFullyStaticExe :: Bool, -- ^Whether to link executables fully statically+ 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.+ splitSections :: Bool, -- ^Use -split-sections with GHC, if available+ splitObjs :: Bool, -- ^Use -split-objs with GHC, if available+ stripExes :: Bool, -- ^Whether to strip executables during install+ stripLibs :: Bool, -- ^Whether to strip libraries during install+ exeCoverage :: Bool, -- ^Whether to enable executable program coverage+ libCoverage :: Bool, -- ^Whether to enable library program coverage+ progPrefix :: PathTemplate, -- ^Prefix to be prepended to installed executables+ progSuffix :: PathTemplate, -- ^Suffix to be appended to installed executables+ relocatable :: Bool -- ^Whether to build a relocatable package+ } deriving (Generic, Read, Show, Typeable)++instance Binary LocalBuildInfo+instance Structured LocalBuildInfo++-------------------------------------------------------------------------------+-- Accessor functions++-- TODO: Get rid of these functions, as much as possible. They are+-- a bit useful in some cases, but you should be very careful!++-- | Extract the 'ComponentId' from the public 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 componentNameCLBIs lbi (CLibName LMainLibName) of+ [LibComponentLocalBuildInfo { componentComponentId = cid }]+ -> cid+ _ -> mkComponentId (prettyShow (localPackage lbi))++-- | Extract the 'PackageIdentifier' of a 'LocalBuildInfo'.+-- This is a "safe" use of 'localPkgDescr'+localPackage :: LocalBuildInfo -> PackageId+localPackage lbi = package (localPkgDescr lbi)++-- | 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 =+ case componentNameCLBIs lbi (CLibName LMainLibName) of+ [LibComponentLocalBuildInfo { componentUnitId = uid }]+ -> uid+ _ -> mkLegacyUnitId $ localPackage lbi++-- | Extract the compatibility package key from the public library component of a+-- 'LocalBuildInfo' if it exists, or make a fake package key based+-- on the package ID.+localCompatPackageKey :: LocalBuildInfo -> String+localCompatPackageKey lbi =+ case componentNameCLBIs lbi (CLibName LMainLibName) of+ [LibComponentLocalBuildInfo { componentCompatPackageKey = pk }]+ -> pk+ _ -> prettyShow (localPackage lbi)++-- | Convenience function to generate a default 'TargetInfo' from a+-- 'ComponentLocalBuildInfo'. The idea is to call this once, and then+-- use 'TargetInfo' everywhere else. Private to this module.+mkTargetInfo :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> TargetInfo+mkTargetInfo pkg_descr _lbi clbi =+ TargetInfo {+ targetCLBI = clbi,+ -- NB: @pkg_descr@, not @localPkgDescr lbi@!+ targetComponent = getComponent pkg_descr+ (componentLocalName clbi)+ }++-- | Return all 'TargetInfo's associated with 'ComponentName'.+-- In the presence of Backpack there may be more than one!+-- Has a prime because it takes a 'PackageDescription' argument+-- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.+componentNameTargets' :: PackageDescription -> LocalBuildInfo -> ComponentName -> [TargetInfo]+componentNameTargets' pkg_descr lbi cname =+ case Map.lookup cname (componentNameMap lbi) of+ Just clbis -> map (mkTargetInfo pkg_descr lbi) clbis+ Nothing -> []++unitIdTarget' :: PackageDescription -> LocalBuildInfo -> UnitId -> Maybe TargetInfo+unitIdTarget' pkg_descr lbi uid =+ case Graph.lookup uid (componentGraph lbi) of+ Just clbi -> Just (mkTargetInfo pkg_descr lbi clbi)+ Nothing -> Nothing++-- | Return all 'ComponentLocalBuildInfo's associated with 'ComponentName'.+-- In the presence of Backpack there may be more than one!+componentNameCLBIs :: LocalBuildInfo -> ComponentName -> [ComponentLocalBuildInfo]+componentNameCLBIs lbi cname =+ case Map.lookup cname (componentNameMap lbi) of+ Just clbis -> clbis+ Nothing -> []++-- TODO: Maybe cache topsort (Graph can do this)++-- | Return the list of default 'TargetInfo's associated with a+-- configured package, in the order they need to be built.+-- Has a prime because it takes a 'PackageDescription' argument+-- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.+allTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> [TargetInfo]+allTargetsInBuildOrder' pkg_descr lbi+ = map (mkTargetInfo pkg_descr lbi) (Graph.revTopSort (componentGraph lbi))++-- | Execute @f@ for every 'TargetInfo' in the package, respecting the+-- build dependency order. (TODO: We should use Shake!)+-- Has a prime because it takes a 'PackageDescription' argument+-- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.+withAllTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> (TargetInfo -> IO ()) -> IO ()+withAllTargetsInBuildOrder' pkg_descr lbi f+ = sequence_ [ f target | target <- allTargetsInBuildOrder' pkg_descr lbi ]++-- | Return the list of all targets needed to build the @uids@, in+-- the order they need to be built.+-- Has a prime because it takes a 'PackageDescription' argument+-- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.+neededTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> [UnitId] -> [TargetInfo]+neededTargetsInBuildOrder' pkg_descr lbi uids =+ case Graph.closure (componentGraph lbi) uids of+ Nothing -> error $ "localBuildPlan: missing uids " ++ intercalate ", " (map prettyShow uids)+ Just clos -> map (mkTargetInfo pkg_descr lbi) (Graph.revTopSort (Graph.fromDistinctList clos))++-- | Execute @f@ for every 'TargetInfo' needed to build @uid@s, respecting+-- the build dependency order.+-- Has a prime because it takes a 'PackageDescription' argument+-- which may disagree with 'localPkgDescr' in 'LocalBuildInfo'.+withNeededTargetsInBuildOrder' :: PackageDescription -> LocalBuildInfo -> [UnitId] -> (TargetInfo -> IO ()) -> IO ()+withNeededTargetsInBuildOrder' pkg_descr lbi uids f+ = sequence_ [ f target | target <- neededTargetsInBuildOrder' pkg_descr lbi uids ]++-- | Is coverage enabled for test suites? In practice, this requires library+-- and executable profiling to be enabled.+testCoverage :: LocalBuildInfo -> Bool+testCoverage lbi = exeCoverage lbi && libCoverage lbi++-------------------------------------------------------------------------------+-- Stub functions to prevent someone from accidentally defining them++{-# WARNING componentNameTargets, unitIdTarget, allTargetsInBuildOrder, withAllTargetsInBuildOrder, neededTargetsInBuildOrder, withNeededTargetsInBuildOrder "By using this function, you may be introducing a bug where you retrieve a 'Component' which does not have 'HookedBuildInfo' applied to it. See the documentation for 'HookedBuildInfo' for an explanation of the issue. If you have a 'PakcageDescription' handy (NOT from the 'LocalBuildInfo'), try using the primed version of the function, which takes it as an extra argument." #-}++componentNameTargets :: LocalBuildInfo -> ComponentName -> [TargetInfo]+componentNameTargets lbi = componentNameTargets' (localPkgDescr lbi) lbi++unitIdTarget :: LocalBuildInfo -> UnitId -> Maybe TargetInfo+unitIdTarget lbi = unitIdTarget' (localPkgDescr lbi) lbi++allTargetsInBuildOrder :: LocalBuildInfo -> [TargetInfo]+allTargetsInBuildOrder lbi = allTargetsInBuildOrder' (localPkgDescr lbi) lbi++withAllTargetsInBuildOrder :: LocalBuildInfo -> (TargetInfo -> IO ()) -> IO ()+withAllTargetsInBuildOrder lbi = withAllTargetsInBuildOrder' (localPkgDescr lbi) lbi++neededTargetsInBuildOrder :: LocalBuildInfo -> [UnitId] -> [TargetInfo]+neededTargetsInBuildOrder lbi = neededTargetsInBuildOrder' (localPkgDescr lbi) lbi++withNeededTargetsInBuildOrder :: LocalBuildInfo -> [UnitId] -> (TargetInfo -> IO ()) -> IO ()+withNeededTargetsInBuildOrder lbi = withNeededTargetsInBuildOrder' (localPkgDescr lbi) lbi
+ src/Distribution/Types/Mixin.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.Mixin (+ Mixin(..),+ mkMixin,+ normaliseMixin,+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.CabalSpecVersion+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.IncludeRenaming+import Distribution.Types.LibraryName+import Distribution.Types.PackageName+import Distribution.Types.UnqualComponentName++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP++-- |+--+-- /Invariant:/ if 'mixinLibraryName' is 'LSubLibName', it's not+-- the same as 'mixinPackageName'. In other words,+-- the same invariant as 'Dependency' has.+--+data Mixin = Mixin { mixinPackageName :: PackageName+ , mixinLibraryName :: LibraryName+ , mixinIncludeRenaming :: IncludeRenaming }+ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)++instance Binary Mixin+instance Structured Mixin++instance NFData Mixin where rnf = genericRnf++instance Pretty Mixin where+ pretty (Mixin pn LMainLibName incl) = pretty pn <+> pretty incl+ pretty (Mixin pn (LSubLibName ln) incl) = pretty pn <<>> PP.colon <<>> pretty ln <+> pretty incl++-- |+--+-- >>> simpleParsec "mylib" :: Maybe Mixin+-- Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})+--+-- >>> simpleParsec "thatlib:sublib" :: Maybe Mixin+-- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LSubLibName (UnqualComponentName "sublib"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})+--+-- >>> simpleParsec "thatlib:thatlib" :: Maybe Mixin+-- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})+--+-- Sublibrary syntax is accepted since @cabal-version: 3.4@.+--+-- >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV3_0, CabalSpecV3_4] :: [Maybe Mixin]+-- [Nothing,Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LSubLibName (UnqualComponentName "sub"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})]+--+instance Parsec Mixin where+ parsec = do+ pn <- parsec+ ln <- P.option LMainLibName $ do+ _ <- P.char ':'+ versionGuardMultilibs+ parsecWarning PWTExperimental "colon specifier is experimental feature (issue #5660)"+ LSubLibName <$> parsec+ P.spaces+ incl <- parsec+ return (mkMixin pn ln incl)+ where++versionGuardMultilibs :: CabalParsing m => m ()+versionGuardMultilibs = do+ csv <- askCabalSpecVersion+ when (csv < CabalSpecV3_4) $ fail $ unwords+ [ "Sublibrary mixin syntax used."+ , "To use this syntax the package needs to specify at least 'cabal-version: 3.4'."+ ]++-- | Smart constructor of 'Mixin', enforces invariant.+-- +-- @since 3.4.0.0+mkMixin :: PackageName -> LibraryName -> IncludeRenaming -> Mixin+mkMixin pn (LSubLibName uqn) incl+ | packageNameToUnqualComponentName pn == uqn+ = Mixin pn LMainLibName incl+mkMixin pn ln incl+ = Mixin pn ln incl++-- | Restore invariant+normaliseMixin :: Mixin -> Mixin+normaliseMixin (Mixin pn ln incl) = mkMixin pn ln incl
+ src/Distribution/Types/Module.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Distribution.Types.Module+ ( Module(..)+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp+import Distribution.Pretty+import Distribution.Parsec+import Distribution.Types.UnitId+import Distribution.ModuleName++-- | A module identity uniquely identifies a Haskell module by+-- qualifying a 'ModuleName' with the 'UnitId' which defined+-- it. This type distinguishes between two packages+-- which provide a module with the same name, or a module+-- from the same package compiled with different dependencies.+-- There are a few cases where Cabal needs to know about+-- module identities, e.g., when writing out reexported modules in+-- the 'InstalledPackageInfo'.+data Module =+ Module DefUnitId ModuleName+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++instance Binary Module+instance Structured Module++instance Pretty Module where+ pretty (Module uid mod_name) =+ pretty uid <<>> Disp.text ":" <<>> pretty mod_name++instance Parsec Module where+ parsec = do+ uid <- parsec+ _ <- P.char ':'+ mod_name <- parsec+ return (Module uid mod_name)++instance NFData Module where+ rnf (Module uid mod_name) = rnf uid `seq` rnf mod_name
+ src/Distribution/Types/ModuleReexport.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.ModuleReexport (+ ModuleReexport(..)+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.ModuleName+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.PackageName++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- -----------------------------------------------------------------------------+-- Module re-exports++data ModuleReexport = ModuleReexport {+ moduleReexportOriginalPackage :: Maybe PackageName,+ moduleReexportOriginalName :: ModuleName,+ moduleReexportName :: ModuleName+ }+ deriving (Eq, Generic, Read, Show, Typeable, Data)++instance Binary ModuleReexport+instance Structured ModuleReexport+instance NFData ModuleReexport where rnf = genericRnf++instance Pretty ModuleReexport where+ pretty (ModuleReexport mpkgname origname newname) =+ maybe Disp.empty (\pkgname -> pretty pkgname <<>> Disp.char ':') mpkgname+ <<>> pretty origname+ <+> if newname == origname+ then Disp.empty+ else Disp.text "as" <+> pretty newname++instance Parsec ModuleReexport where+ parsec = do+ mpkgname <- P.optional (P.try $ parsec <* P.char ':')+ origname <- parsec+ newname <- P.option origname $ P.try $ do+ P.spaces+ _ <- P.string "as"+ P.spaces+ parsec+ return (ModuleReexport mpkgname origname newname)
+ src/Distribution/Types/ModuleRenaming.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE RankNTypes #-}++module Distribution.Types.ModuleRenaming (+ ModuleRenaming(..),+ interpModuleRenaming,+ defaultRenaming,+ isDefaultRenaming,+) where++import Distribution.CabalSpecVersion+import Distribution.Compat.Prelude hiding (empty)+import Prelude ()++import Distribution.ModuleName+import Distribution.Parsec+import Distribution.Pretty++import qualified Data.Map as Map+import qualified Data.Set as Set+import qualified Distribution.Compat.CharParsing as P+import Text.PrettyPrint (hsep, parens, punctuate, text, comma)++-- | Renaming applied to the modules provided by a package.+-- The boolean indicates whether or not to also include all of the+-- original names of modules. Thus, @ModuleRenaming False []@ is+-- "don't expose any modules, and @ModuleRenaming True [("Data.Bool", "Bool")]@+-- is, "expose all modules, but also expose @Data.Bool@ as @Bool@".+-- If a renaming is omitted you get the 'DefaultRenaming'.+--+-- (NB: This is a list not a map so that we can preserve order.)+--+data ModuleRenaming+ -- | A module renaming/thinning; e.g., @(A as B, C as C)@+ -- brings @B@ and @C@ into scope.+ = ModuleRenaming [(ModuleName, ModuleName)]+ -- | The default renaming, bringing all exported modules+ -- into scope.+ | DefaultRenaming+ -- | Hiding renaming, e.g., @hiding (A, B)@, bringing all+ -- exported modules into scope except the hidden ones.+ | HidingRenaming [ModuleName]+ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)++-- | Interpret a 'ModuleRenaming' as a partial map from 'ModuleName'+-- to 'ModuleName'. For efficiency, you should partially apply it+-- with 'ModuleRenaming' and then reuse it.+interpModuleRenaming :: ModuleRenaming -> ModuleName -> Maybe ModuleName+interpModuleRenaming DefaultRenaming = Just+interpModuleRenaming (ModuleRenaming rns) =+ let m = Map.fromList rns+ in \k -> Map.lookup k m+interpModuleRenaming (HidingRenaming hs) =+ let s = Set.fromList hs+ in \k -> if k `Set.member` s then Nothing else Just k++-- | The default renaming, if something is specified in @build-depends@+-- only.+defaultRenaming :: ModuleRenaming+defaultRenaming = DefaultRenaming++-- | Tests if its the default renaming; we can use a more compact syntax+-- in 'Distribution.Types.IncludeRenaming.IncludeRenaming' in this case.+isDefaultRenaming :: ModuleRenaming -> Bool+isDefaultRenaming DefaultRenaming = True+isDefaultRenaming _ = False++++instance Binary ModuleRenaming where+instance Structured ModuleRenaming where++instance NFData ModuleRenaming where rnf = genericRnf++-- NB: parentheses are mandatory, because later we may extend this syntax+-- to allow "hiding (A, B)" or other modifier words.+instance Pretty ModuleRenaming where+ pretty DefaultRenaming = mempty+ pretty (HidingRenaming hides)+ = text "hiding" <+> parens (hsep (punctuate comma (map pretty hides)))+ pretty (ModuleRenaming rns)+ = parens . hsep $ punctuate comma (map dispEntry rns)+ where dispEntry (orig, new)+ | orig == new = pretty orig+ | otherwise = pretty orig <+> text "as" <+> pretty new++instance Parsec ModuleRenaming where+ parsec = do+ csv <- askCabalSpecVersion+ if csv >= CabalSpecV3_0+ then moduleRenamingParsec parensLax lexemeParsec+ else moduleRenamingParsec parensStrict parsec+ where+ -- For cabal spec versions < 3.0 white spaces were not skipped+ -- after the '(' and ')' tokens in the mixin field. This+ -- parser checks the cabal file version and does the correct+ -- skipping of spaces.+ parensLax p = P.between (P.char '(' >> P.spaces) (P.char ')' >> P.spaces) p+ parensStrict p = P.between (P.char '(' >> warnSpaces) (P.char ')') p++ warnSpaces = P.optional $+ P.space *> fail "space after parenthesis, use cabal-version: 3.0 or higher"++moduleRenamingParsec+ :: CabalParsing m+ => (forall a. m a -> m a) -- ^ between parens+ -> m ModuleName -- ^ module name parser+ -> m ModuleRenaming+moduleRenamingParsec bp mn =+ -- NB: try not necessary as the first token is obvious+ P.choice [ parseRename, parseHiding, return DefaultRenaming ]+ where+ cma = P.char ',' >> P.spaces+ parseRename = do+ rns <- bp parseList+ P.spaces+ return (ModuleRenaming rns)+ parseHiding = do+ _ <- P.string "hiding"+ P.spaces -- space isn't strictly required as next is an open paren+ hides <- bp (P.sepBy mn cma)+ return (HidingRenaming hides)+ parseList =+ P.sepBy parseEntry cma+ parseEntry = do+ orig <- parsec+ P.spaces+ P.option (orig, orig) $ do+ _ <- P.string "as"+ P.skipSpaces1 -- require space after "as"+ new <- parsec+ P.spaces+ return (orig, new)
+ src/Distribution/Types/MungedPackageId.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.MungedPackageId+ ( MungedPackageId(..)+ , computeCompatPackageId+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.LibraryName+import Distribution.Types.MungedPackageName+import Distribution.Types.PackageId+import Distribution.Version (Version, nullVersion)++import qualified Text.PrettyPrint as Disp++-- | A simple pair of a 'MungedPackageName' and 'Version'. 'MungedPackageName' is to+-- 'MungedPackageId' as 'PackageName' is to 'PackageId'. See 'MungedPackageName' for more+-- info.+data MungedPackageId+ = MungedPackageId {+ -- | The combined package and component name. see documentation for+ -- 'MungedPackageName'.+ mungedName :: MungedPackageName,+ -- | The version of this package / component, eg 1.2+ mungedVersion :: Version+ }+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++instance Binary MungedPackageId+instance Structured MungedPackageId++-- |+--+-- >>> prettyShow $ MungedPackageId (MungedPackageName "servant" LMainLibName) (mkVersion [1,2,3])+-- "servant-1.2.3"+--+-- >>> prettyShow $ MungedPackageId (MungedPackageName "servant" (LSubLibName "lackey")) (mkVersion [0,1,2])+-- "z-servant-z-lackey-0.1.2"+--+instance Pretty MungedPackageId where+ pretty (MungedPackageId n v)+ | v == nullVersion = pretty n -- if no version, don't show version.+ | otherwise = pretty n <<>> Disp.char '-' <<>> pretty v++-- |+--+-- >>> simpleParsec "foo-bar-0" :: Maybe MungedPackageId+-- Just (MungedPackageId {mungedName = MungedPackageName (PackageName "foo-bar") LMainLibName, mungedVersion = mkVersion [0]})+--+-- >>> simpleParsec "foo-bar" :: Maybe MungedPackageId+-- Just (MungedPackageId {mungedName = MungedPackageName (PackageName "foo-bar") LMainLibName, mungedVersion = mkVersion []})+--+-- >>> simpleParsec "z-foo-bar-z-baz-0" :: Maybe MungedPackageId+-- Just (MungedPackageId {mungedName = MungedPackageName (PackageName "foo-bar") (LSubLibName (UnqualComponentName "baz")), mungedVersion = mkVersion [0]})+--+-- >>> simpleParsec "foo-bar-0-0" :: Maybe MungedPackageId+-- Nothing+--+-- >>> simpleParsec "foo-bar.0" :: Maybe MungedPackageId+-- Nothing+--+-- >>> simpleParsec "foo-bar.4-2" :: Maybe MungedPackageId+-- Nothing+--+instance Parsec MungedPackageId where+ parsec = do+ PackageIdentifier pn v <- parsec+ return $ MungedPackageId (decodeCompatPackageName pn) v++instance NFData MungedPackageId where+ rnf (MungedPackageId name version) = rnf name `seq` rnf version++computeCompatPackageId :: PackageId -> LibraryName -> MungedPackageId+computeCompatPackageId (PackageIdentifier pn vr) ln =+ MungedPackageId (MungedPackageName pn ln) vr++-- $setup+-- >>> :seti -XOverloadedStrings+-- >>> import Distribution.Types.Version
+ src/Distribution/Types/MungedPackageName.hs view
@@ -0,0 +1,157 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.MungedPackageName+ ( MungedPackageName (..)+ , decodeCompatPackageName+ , encodeCompatPackageName+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.LibraryName+import Distribution.Types.PackageName+import Distribution.Types.UnqualComponentName++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | A combination of a package and component name used in various legacy+-- interfaces, chiefly bundled with a version as 'MungedPackageId'. It's generally+-- better to use a 'UnitId' to opaquely refer to some compilation/packing unit,+-- but that doesn't always work, e.g. where a "name" is needed, in which case+-- this can be used as a fallback.+--+-- Use 'mkMungedPackageName' and 'unMungedPackageName' to convert from/to a 'String'.+--+-- In @3.0.0.0@ representation was changed from opaque (string) to semantic representation.+--+-- @since 2.0.0.2+--+data MungedPackageName = MungedPackageName !PackageName !LibraryName+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++instance Binary MungedPackageName+instance Structured MungedPackageName+instance NFData MungedPackageName where rnf = genericRnf++-- | Computes the package name for a library. If this is the public+-- library, it will just be the original package name; otherwise,+-- it will be a munged package name recording the original package+-- name as well as the name of the internal library.+--+-- A lot of tooling in the Haskell ecosystem assumes that if something+-- is installed to the package database with the package name 'foo',+-- then it actually is an entry for the (only public) library in package+-- 'foo'. With internal packages, this is not necessarily true:+-- a public library as well as arbitrarily many internal libraries may+-- come from the same package. To prevent tools from getting confused+-- in this case, the package name of these internal libraries is munged+-- so that they do not conflict the public library proper. A particular+-- case where this matters is ghc-pkg: if we don't munge the package+-- name, the inplace registration will OVERRIDE a different internal+-- library.+--+-- We munge into a reserved namespace, "z-", and encode both the+-- component name and the package name of an internal library using the+-- following format:+--+-- compat-pkg-name ::= "z-" package-name "-z-" library-name+--+-- where package-name and library-name have "-" ( "z" + ) "-"+-- segments encoded by adding an extra "z".+--+-- When we have the public library, the compat-pkg-name is just the+-- package-name, no surprises there!+--+-- >>> prettyShow $ MungedPackageName "servant" LMainLibName+-- "servant"+--+-- >>> prettyShow $ MungedPackageName "servant" (LSubLibName "lackey")+-- "z-servant-z-lackey"+--+instance Pretty MungedPackageName where+ -- First handle the cases where we can just use the original 'PackageName'.+ -- This is for the PRIMARY library, and it is non-Backpack, or the+ -- indefinite package for us.+ pretty = Disp.text . encodeCompatPackageName'++-- |+--+-- >>> simpleParsec "servant" :: Maybe MungedPackageName+-- Just (MungedPackageName (PackageName "servant") LMainLibName)+--+-- >>> simpleParsec "z-servant-z-lackey" :: Maybe MungedPackageName+-- Just (MungedPackageName (PackageName "servant") (LSubLibName (UnqualComponentName "lackey")))+--+-- >>> simpleParsec "z-servant-zz" :: Maybe MungedPackageName+-- Just (MungedPackageName (PackageName "z-servant-zz") LMainLibName)+--+instance Parsec MungedPackageName where+ parsec = decodeCompatPackageName' <$> parsecUnqualComponentName++-------------------------------------------------------------------------------+-- ZDashCode conversions+-------------------------------------------------------------------------------++-- | Intended for internal use only+--+-- >>> decodeCompatPackageName "z-servant-z-lackey"+-- MungedPackageName (PackageName "servant") (LSubLibName (UnqualComponentName "lackey"))+--+decodeCompatPackageName :: PackageName -> MungedPackageName+decodeCompatPackageName = decodeCompatPackageName' . unPackageName++-- | Intended for internal use only+--+-- >>> encodeCompatPackageName $ MungedPackageName "servant" (LSubLibName "lackey")+-- PackageName "z-servant-z-lackey"+--+-- This is used in @cabal-install@ in the Solver.+-- May become obsolete as solver moves to per-component solving.+--+encodeCompatPackageName :: MungedPackageName -> PackageName+encodeCompatPackageName = mkPackageName . encodeCompatPackageName'++decodeCompatPackageName' :: String -> MungedPackageName+decodeCompatPackageName' m =+ case m of+ 'z':'-':rest | Right [pn, cn] <- explicitEitherParsec parseZDashCode rest+ -> MungedPackageName (mkPackageName pn) (LSubLibName (mkUnqualComponentName cn))+ s -> MungedPackageName (mkPackageName s) LMainLibName++encodeCompatPackageName' :: MungedPackageName -> String+encodeCompatPackageName' (MungedPackageName pn LMainLibName) = unPackageName pn+encodeCompatPackageName' (MungedPackageName pn (LSubLibName uqn)) =+ "z-" ++ zdashcode (unPackageName pn) +++ "-z-" ++ zdashcode (unUnqualComponentName uqn)++zdashcode :: String -> String+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)++parseZDashCode :: CabalParsing m => m [String]+parseZDashCode = do+ ns <- toList <$> P.sepByNonEmpty (some (P.satisfy (/= '-'))) (P.char '-')+ return (go ns)+ where+ go ns = case break (=="z") ns of+ (_, []) -> [paste ns]+ (as, "z":bs) -> paste as : go bs+ _ -> error "parseZDashCode: go"+ unZ :: String -> String+ unZ "" = error "parseZDashCode: unZ"+ unZ r@('z':zs) | all (=='z') zs = zs+ | otherwise = r+ unZ r = r+ paste :: [String] -> String+ paste = intercalate "-" . map unZ++-- $setup+-- >>> :seti -XOverloadedStrings
+ src/Distribution/Types/PackageDescription.hs view
@@ -0,0 +1,457 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Types.PackageDescription+-- Copyright : Isaac Jones 2003-2005+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- This defines the data structure for the @.cabal@ file format. There are+-- several parts to this structure. It has top level info and then 'Library',+-- 'Executable', 'TestSuite', and 'Benchmark' sections each of which have+-- associated 'BuildInfo' data that's used to build the library, exe, test, or+-- benchmark. To further complicate things there is both a 'PackageDescription'+-- and a 'GenericPackageDescription'. This distinction relates to cabal+-- configurations. When we initially read a @.cabal@ file we get a+-- 'GenericPackageDescription' which has all the conditional sections.+-- Before actually building a package we have to decide+-- on each conditional. Once we've done that we get a 'PackageDescription'.+-- It was done this way initially to avoid breaking too much stuff when the+-- feature was introduced. It could probably do with being rationalised at some+-- point to make it simpler.++module Distribution.Types.PackageDescription (+ PackageDescription(..),+ license,+ license',+ buildType,+ emptyPackageDescription,+ hasPublicLib,+ hasLibs,+ allLibraries,+ withLib,+ hasExes,+ withExe,+ hasTests,+ withTest,+ hasBenchmarks,+ withBenchmark,+ hasForeignLibs,+ withForeignLib,+ allBuildInfo,+ enabledBuildInfos,+ allBuildDepends,+ enabledBuildDepends,+ updatePackageDescription,+ pkgComponents,+ pkgBuildableComponents,+ enabledComponents,+ lookupComponent,+ getComponent,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Control.Monad ((<=<))++-- lens+import qualified Distribution.Types.BuildInfo.Lens as L+import Distribution.Types.Library+import Distribution.Types.TestSuite+import Distribution.Types.Executable+import Distribution.Types.Benchmark+import Distribution.Types.ForeignLib++import Distribution.Types.Component+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.Dependency+import Distribution.Types.PackageId+import Distribution.Types.ComponentName+import Distribution.Types.PackageName+import Distribution.Types.UnqualComponentName+import Distribution.Types.SetupBuildInfo+import Distribution.Types.BuildInfo+import Distribution.Types.BuildType+import Distribution.Types.SourceRepo+import Distribution.Types.HookedBuildInfo++import Distribution.CabalSpecVersion+import Distribution.Compiler+import Distribution.License+import Distribution.Package+import Distribution.Version+import Distribution.Utils.Path+import Distribution.Utils.ShortText++import qualified Distribution.SPDX as SPDX++-- -----------------------------------------------------------------------------+-- The PackageDescription type++-- | This data type is the internal representation of the file @pkg.cabal@.+-- It contains two kinds of information about the package: information+-- which is needed for all packages, such as the package name and version, and+-- information which is needed for the simple build system only, such as+-- the compiler options and library name.+--+data PackageDescription+ = PackageDescription {+ -- the following are required by all packages:++ -- | The version of the Cabal spec that this package description uses.+ specVersion :: CabalSpecVersion,+ package :: PackageIdentifier,+ licenseRaw :: Either SPDX.License License,+ licenseFiles :: [SymbolicPath PackageDir LicenseFile],+ copyright :: !ShortText,+ maintainer :: !ShortText,+ author :: !ShortText,+ stability :: !ShortText,+ testedWith :: [(CompilerFlavor,VersionRange)],+ homepage :: !ShortText,+ pkgUrl :: !ShortText,+ bugReports :: !ShortText,+ sourceRepos :: [SourceRepo],+ synopsis :: !ShortText, -- ^A one-line summary of this package+ description :: !ShortText, -- ^A more verbose description of this package+ category :: !ShortText,+ customFieldsPD :: [(String,String)], -- ^Custom fields starting+ -- with x-, stored in a+ -- simple assoc-list.++ -- | The original @build-type@ value as parsed from the+ -- @.cabal@ file without defaulting. See also 'buildType'.+ --+ -- @since 2.2+ buildTypeRaw :: Maybe BuildType,+ setupBuildInfo :: Maybe SetupBuildInfo,+ -- components+ library :: Maybe Library,+ subLibraries :: [Library],+ executables :: [Executable],+ foreignLibs :: [ForeignLib],+ testSuites :: [TestSuite],+ benchmarks :: [Benchmark],+ -- files+ dataFiles :: [FilePath],+ dataDir :: FilePath,+ extraSrcFiles :: [FilePath],+ extraTmpFiles :: [FilePath],+ extraDocFiles :: [FilePath]+ }+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary PackageDescription+instance Structured PackageDescription++instance NFData PackageDescription where rnf = genericRnf++instance Package PackageDescription where+ packageId = package++-- | The SPDX 'LicenseExpression' of the package.+--+-- @since 2.2.0.0+license :: PackageDescription -> SPDX.License+license = license' . licenseRaw++-- | See 'license'.+--+-- @since 2.2.0.0+license' :: Either SPDX.License License -> SPDX.License+license' = either id licenseToSPDX++-- | The effective @build-type@ after applying defaulting rules.+--+-- The original @build-type@ value parsed is stored in the+-- 'buildTypeRaw' field. However, the @build-type@ field is optional+-- and can therefore be empty in which case we need to compute the+-- /effective/ @build-type@. This function implements the following+-- defaulting rules:+--+-- * For @cabal-version:2.0@ and below, default to the @Custom@+-- build-type unconditionally.+--+-- * Otherwise, if a @custom-setup@ stanza is defined, default to+-- the @Custom@ build-type; else default to @Simple@ build-type.+--+-- @since 2.2+buildType :: PackageDescription -> BuildType+buildType pkg+ | specVersion pkg >= CabalSpecV2_2+ = fromMaybe newDefault (buildTypeRaw pkg)+ | otherwise -- cabal-version < 2.1+ = fromMaybe Custom (buildTypeRaw pkg)+ where+ newDefault | isNothing (setupBuildInfo pkg) = Simple+ | otherwise = Custom++emptyPackageDescription :: PackageDescription+emptyPackageDescription+ = PackageDescription {+ package = PackageIdentifier (mkPackageName "")+ nullVersion,+ licenseRaw = Right UnspecifiedLicense, -- TODO:+ licenseFiles = [],+ specVersion = CabalSpecV1_0,+ buildTypeRaw = Nothing,+ copyright = mempty,+ maintainer = mempty,+ author = mempty,+ stability = mempty,+ testedWith = [],+ homepage = mempty,+ pkgUrl = mempty,+ bugReports = mempty,+ sourceRepos = [],+ synopsis = mempty,+ description = mempty,+ category = mempty,+ customFieldsPD = [],+ setupBuildInfo = Nothing,+ library = Nothing,+ subLibraries = [],+ foreignLibs = [],+ executables = [],+ testSuites = [],+ benchmarks = [],+ dataFiles = [],+ dataDir = ".",+ extraSrcFiles = [],+ extraTmpFiles = [],+ extraDocFiles = []+ }++-- ---------------------------------------------------------------------------+-- The Library type++-- | Does this package have a buildable PUBLIC library?+hasPublicLib :: PackageDescription -> Bool+hasPublicLib p =+ case library p of+ Just lib -> buildable (libBuildInfo lib)+ Nothing -> False++-- | Does this package have any libraries?+hasLibs :: PackageDescription -> Bool+hasLibs p = any (buildable . libBuildInfo) (allLibraries p)++allLibraries :: PackageDescription -> [Library]+allLibraries p = maybeToList (library p) ++ subLibraries p++-- | If the package description has a buildable library section,+-- call the given function with the library build info as argument.+-- You probably want 'withLibLBI' if you have a 'LocalBuildInfo',+-- see the note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"+-- for more information.+withLib :: PackageDescription -> (Library -> IO ()) -> IO ()+withLib pkg_descr f =+ sequence_ [f lib | lib <- allLibraries pkg_descr, buildable (libBuildInfo lib)]++-- ---------------------------------------------------------------------------+-- The Executable type++-- |does this package have any executables?+hasExes :: PackageDescription -> Bool+hasExes p = any (buildable . buildInfo) (executables p)++-- | Perform the action on each buildable 'Executable' in the package+-- description. You probably want 'withExeLBI' if you have a+-- 'LocalBuildInfo', see the note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"+-- for more information.+withExe :: PackageDescription -> (Executable -> IO ()) -> IO ()+withExe pkg_descr f =+ sequence_ [f exe | exe <- executables pkg_descr, buildable (buildInfo exe)]++-- ---------------------------------------------------------------------------+-- The TestSuite type++-- | Does this package have any test suites?+hasTests :: PackageDescription -> Bool+hasTests = any (buildable . testBuildInfo) . testSuites++-- | Perform an action on each buildable 'TestSuite' in a package.+-- You probably want 'withTestLBI' if you have a 'LocalBuildInfo', see the note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"+-- for more information.++withTest :: PackageDescription -> (TestSuite -> IO ()) -> IO ()+withTest pkg_descr f =+ sequence_ [ f test | test <- testSuites pkg_descr, buildable (testBuildInfo test) ]++-- ---------------------------------------------------------------------------+-- The Benchmark type++-- | Does this package have any benchmarks?+hasBenchmarks :: PackageDescription -> Bool+hasBenchmarks = any (buildable . benchmarkBuildInfo) . benchmarks++-- | Perform an action on each buildable 'Benchmark' in a package.+-- You probably want 'withBenchLBI' if you have a 'LocalBuildInfo', see the note in+-- "Distribution.Types.ComponentRequestedSpec#buildable_vs_enabled_components"+-- for more information.++withBenchmark :: PackageDescription -> (Benchmark -> IO ()) -> IO ()+withBenchmark pkg_descr f =+ sequence_ [f bench | bench <- benchmarks pkg_descr, buildable (benchmarkBuildInfo bench)]++-- ---------------------------------------------------------------------------+-- The ForeignLib type++-- | Does this package have any foreign libraries?+hasForeignLibs :: PackageDescription -> Bool+hasForeignLibs p = any (buildable . foreignLibBuildInfo) (foreignLibs p)++-- | Perform the action on each buildable 'ForeignLib' in the package+-- description.+withForeignLib :: PackageDescription -> (ForeignLib -> IO ()) -> IO ()+withForeignLib pkg_descr f =+ sequence_ [ f flib+ | flib <- foreignLibs pkg_descr+ , buildable (foreignLibBuildInfo flib)+ ]++-- ---------------------------------------------------------------------------+-- The BuildInfo type++-- | All 'BuildInfo' in the 'PackageDescription':+-- libraries, executables, test-suites and benchmarks.+--+-- Useful for implementing package checks.+allBuildInfo :: PackageDescription -> [BuildInfo]+allBuildInfo pkg_descr = [ bi | lib <- allLibraries pkg_descr+ , let bi = libBuildInfo lib ]+ ++ [ bi | flib <- foreignLibs pkg_descr+ , let bi = foreignLibBuildInfo flib ]+ ++ [ bi | exe <- executables pkg_descr+ , let bi = buildInfo exe ]+ ++ [ bi | tst <- testSuites pkg_descr+ , let bi = testBuildInfo tst ]+ ++ [ bi | tst <- benchmarks pkg_descr+ , let bi = benchmarkBuildInfo tst ]++-- | Return all of the 'BuildInfo's of enabled components, i.e., all of+-- the ones that would be built if you run @./Setup build@.+enabledBuildInfos :: PackageDescription -> ComponentRequestedSpec -> [BuildInfo]+enabledBuildInfos pkg enabled =+ [ componentBuildInfo comp+ | comp <- enabledComponents pkg enabled ]+++-- ------------------------------------------------------------+-- * Utils+-- ------------------------------------------------------------++-- | Get the combined build-depends entries of all components.+allBuildDepends :: PackageDescription -> [Dependency]+allBuildDepends = targetBuildDepends <=< allBuildInfo++-- | Get the combined build-depends entries of all enabled components, per the+-- given request spec.+enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [Dependency]+enabledBuildDepends spec pd = targetBuildDepends =<< enabledBuildInfos spec pd+++updatePackageDescription :: HookedBuildInfo -> PackageDescription -> PackageDescription+updatePackageDescription (mb_lib_bi, exe_bi) p+ = p{ executables = updateExecutables exe_bi (executables p)+ , library = updateLibrary mb_lib_bi (library p) }+ where+ updateLibrary :: Maybe BuildInfo -> Maybe Library -> Maybe Library+ updateLibrary (Just bi) (Just lib) = Just (lib{libBuildInfo = bi `mappend` libBuildInfo lib})+ updateLibrary Nothing mb_lib = mb_lib+ updateLibrary (Just _) Nothing = Nothing++ updateExecutables :: [(UnqualComponentName, BuildInfo)] -- ^[(exeName, new buildinfo)]+ -> [Executable] -- ^list of executables to update+ -> [Executable] -- ^list with exeNames updated+ updateExecutables exe_bi' executables' = foldr updateExecutable executables' exe_bi'++ updateExecutable :: (UnqualComponentName, BuildInfo) -- ^(exeName, new buildinfo)+ -> [Executable] -- ^list of executables to update+ -> [Executable] -- ^list with exeName updated+ updateExecutable _ [] = []+ updateExecutable exe_bi'@(name,bi) (exe:exes)+ | exeName exe == name = exe{buildInfo = bi `mappend` buildInfo exe} : exes+ | otherwise = exe : updateExecutable exe_bi' exes++-- -----------------------------------------------------------------------------+-- Source-representation of buildable components++-- | All the components in the package.+--+pkgComponents :: PackageDescription -> [Component]+pkgComponents pkg =+ [ CLib lib | lib <- allLibraries pkg ]+ ++ [ CFLib flib | flib <- foreignLibs pkg ]+ ++ [ CExe exe | exe <- executables pkg ]+ ++ [ CTest tst | tst <- testSuites pkg ]+ ++ [ CBench bm | bm <- benchmarks pkg ]++-- | A list of all components in the package that are buildable,+-- i.e., were not marked with @buildable: False@. This does NOT+-- indicate if we are actually going to build the component,+-- see 'enabledComponents' instead.+--+-- @since 2.0.0.2+--+pkgBuildableComponents :: PackageDescription -> [Component]+pkgBuildableComponents = filter componentBuildable . pkgComponents++-- | A list of all components in the package that are enabled.+--+-- @since 2.0.0.2+--+enabledComponents :: PackageDescription -> ComponentRequestedSpec -> [Component]+enabledComponents pkg enabled = filter (componentEnabled enabled) $ pkgBuildableComponents pkg++lookupComponent :: PackageDescription -> ComponentName -> Maybe Component+lookupComponent pkg (CLibName name) =+ fmap CLib $ find ((name ==) . libName) (allLibraries pkg)+lookupComponent pkg (CFLibName name) =+ fmap CFLib $ find ((name ==) . foreignLibName) (foreignLibs pkg)+lookupComponent pkg (CExeName name) =+ fmap CExe $ find ((name ==) . exeName) (executables pkg)+lookupComponent pkg (CTestName name) =+ fmap CTest $ find ((name ==) . testName) (testSuites pkg)+lookupComponent pkg (CBenchName name) =+ fmap CBench $ find ((name ==) . benchmarkName) (benchmarks pkg)++getComponent :: PackageDescription -> ComponentName -> Component+getComponent pkg cname =+ case lookupComponent pkg cname of+ Just cpnt -> cpnt+ Nothing -> missingComponent+ where+ missingComponent =+ error $ "internal error: the package description contains no "+ ++ "component corresponding to " ++ show cname++-- -----------------------------------------------------------------------------+-- Traversal Instances++instance L.HasBuildInfos PackageDescription where+ traverseBuildInfos f (PackageDescription a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19+ x1 x2 x3 x4 x5 x6+ a20 a21 a22 a23 a24) =+ PackageDescription a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19+ <$> (traverse . L.buildInfo) f x1 -- library+ <*> (traverse . L.buildInfo) f x2 -- sub libraries+ <*> (traverse . L.buildInfo) f x3 -- executables+ <*> (traverse . L.buildInfo) f x4 -- foreign libs+ <*> (traverse . L.buildInfo) f x5 -- test suites+ <*> (traverse . L.buildInfo) f x6 -- benchmarks+ <*> pure a20 -- data files+ <*> pure a21 -- data dir+ <*> pure a22 -- extra src files+ <*> pure a23 -- extra temp files+ <*> pure a24 -- extra doc files
+ src/Distribution/Types/PackageDescription/Lens.hs view
@@ -0,0 +1,221 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+module Distribution.Types.PackageDescription.Lens (+ PackageDescription,+ module Distribution.Types.PackageDescription.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.CabalSpecVersion (CabalSpecVersion)+import Distribution.Compiler (CompilerFlavor)+import Distribution.License (License)+import Distribution.ModuleName (ModuleName)+import Distribution.Types.Benchmark (Benchmark, benchmarkModules)+import Distribution.Types.Benchmark.Lens (benchmarkBuildInfo, benchmarkName)+import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.BuildType (BuildType)+import Distribution.Types.ComponentName (ComponentName (..))+import Distribution.Types.Executable (Executable, exeModules)+import Distribution.Types.Executable.Lens (exeBuildInfo, exeName)+import Distribution.Types.ForeignLib (ForeignLib, foreignLibModules)+import Distribution.Types.ForeignLib.Lens (foreignLibBuildInfo, foreignLibName)+import Distribution.Types.Library (Library, explicitLibModules)+import Distribution.Types.Library.Lens (libBuildInfo, libName)+import Distribution.Types.PackageDescription (PackageDescription)+import Distribution.Types.PackageId (PackageIdentifier)+import Distribution.Types.SetupBuildInfo (SetupBuildInfo)+import Distribution.Types.SourceRepo (SourceRepo)+import Distribution.Types.TestSuite (TestSuite, testModules)+import Distribution.Types.TestSuite.Lens (testBuildInfo, testName)+import Distribution.Utils.Path (LicenseFile, PackageDir, SymbolicPath)+import Distribution.Utils.ShortText (ShortText)+import Distribution.Version (VersionRange)++import qualified Distribution.SPDX as SPDX+import qualified Distribution.Types.PackageDescription as T++package :: Lens' PackageDescription PackageIdentifier+package f s = fmap (\x -> s { T.package = x }) (f (T.package s))+{-# INLINE package #-}++licenseRaw :: Lens' PackageDescription (Either SPDX.License License)+licenseRaw f s = fmap (\x -> s { T.licenseRaw = x }) (f (T.licenseRaw s))+{-# INLINE licenseRaw #-}++licenseFiles :: Lens' PackageDescription [SymbolicPath PackageDir LicenseFile]+licenseFiles f s = fmap (\x -> s { T.licenseFiles = x }) (f (T.licenseFiles s))+{-# INLINE licenseFiles #-}++copyright :: Lens' PackageDescription ShortText+copyright f s = fmap (\x -> s { T.copyright = x }) (f (T.copyright s))+{-# INLINE copyright #-}++maintainer :: Lens' PackageDescription ShortText+maintainer f s = fmap (\x -> s { T.maintainer = x }) (f (T.maintainer s))+{-# INLINE maintainer #-}++author :: Lens' PackageDescription ShortText+author f s = fmap (\x -> s { T.author = x }) (f (T.author s))+{-# INLINE author #-}++stability :: Lens' PackageDescription ShortText+stability f s = fmap (\x -> s { T.stability = x }) (f (T.stability s))+{-# INLINE stability #-}++testedWith :: Lens' PackageDescription [(CompilerFlavor,VersionRange)]+testedWith f s = fmap (\x -> s { T.testedWith = x }) (f (T.testedWith s))+{-# INLINE testedWith #-}++homepage :: Lens' PackageDescription ShortText+homepage f s = fmap (\x -> s { T.homepage = x }) (f (T.homepage s))+{-# INLINE homepage #-}++pkgUrl :: Lens' PackageDescription ShortText+pkgUrl f s = fmap (\x -> s { T.pkgUrl = x }) (f (T.pkgUrl s))+{-# INLINE pkgUrl #-}++bugReports :: Lens' PackageDescription ShortText+bugReports f s = fmap (\x -> s { T.bugReports = x }) (f (T.bugReports s))+{-# INLINE bugReports #-}++sourceRepos :: Lens' PackageDescription [SourceRepo]+sourceRepos f s = fmap (\x -> s { T.sourceRepos = x }) (f (T.sourceRepos s))+{-# INLINE sourceRepos #-}++synopsis :: Lens' PackageDescription ShortText+synopsis f s = fmap (\x -> s { T.synopsis = x }) (f (T.synopsis s))+{-# INLINE synopsis #-}++description :: Lens' PackageDescription ShortText+description f s = fmap (\x -> s { T.description = x }) (f (T.description s))+{-# INLINE description #-}++category :: Lens' PackageDescription ShortText+category f s = fmap (\x -> s { T.category = x }) (f (T.category s))+{-# INLINE category #-}++customFieldsPD :: Lens' PackageDescription [(String,String)]+customFieldsPD f s = fmap (\x -> s { T.customFieldsPD = x }) (f (T.customFieldsPD s))+{-# INLINE customFieldsPD #-}++specVersion :: Lens' PackageDescription CabalSpecVersion+specVersion f s = fmap (\x -> s { T.specVersion = x }) (f (T.specVersion s))+{-# INLINE specVersion #-}++buildTypeRaw :: Lens' PackageDescription (Maybe BuildType)+buildTypeRaw f s = fmap (\x -> s { T.buildTypeRaw = x }) (f (T.buildTypeRaw s))+{-# INLINE buildTypeRaw #-}++setupBuildInfo :: Lens' PackageDescription (Maybe SetupBuildInfo)+setupBuildInfo f s = fmap (\x -> s { T.setupBuildInfo = x }) (f (T.setupBuildInfo s))+{-# INLINE setupBuildInfo #-}++library :: Lens' PackageDescription (Maybe Library)+library f s = fmap (\x -> s { T.library = x }) (f (T.library s))+{-# INLINE library #-}++subLibraries :: Lens' PackageDescription [Library]+subLibraries f s = fmap (\x -> s { T.subLibraries = x }) (f (T.subLibraries s))+{-# INLINE subLibraries #-}++executables :: Lens' PackageDescription [Executable]+executables f s = fmap (\x -> s { T.executables = x }) (f (T.executables s))+{-# INLINE executables #-}++foreignLibs :: Lens' PackageDescription [ForeignLib]+foreignLibs f s = fmap (\x -> s { T.foreignLibs = x }) (f (T.foreignLibs s))+{-# INLINE foreignLibs #-}++testSuites :: Lens' PackageDescription [TestSuite]+testSuites f s = fmap (\x -> s { T.testSuites = x }) (f (T.testSuites s))+{-# INLINE testSuites #-}++benchmarks :: Lens' PackageDescription [Benchmark]+benchmarks f s = fmap (\x -> s { T.benchmarks = x }) (f (T.benchmarks s))+{-# INLINE benchmarks #-}++dataFiles :: Lens' PackageDescription [FilePath]+dataFiles f s = fmap (\x -> s { T.dataFiles = x }) (f (T.dataFiles s))+{-# INLINE dataFiles #-}++dataDir :: Lens' PackageDescription FilePath+dataDir f s = fmap (\x -> s { T.dataDir = x }) (f (T.dataDir s))+{-# INLINE dataDir #-}++extraSrcFiles :: Lens' PackageDescription [String]+extraSrcFiles f s = fmap (\x -> s { T.extraSrcFiles = x }) (f (T.extraSrcFiles s))+{-# INLINE extraSrcFiles #-}++extraTmpFiles :: Lens' PackageDescription [String]+extraTmpFiles f s = fmap (\x -> s { T.extraTmpFiles = x }) (f (T.extraTmpFiles s))+{-# INLINE extraTmpFiles #-}++extraDocFiles :: Lens' PackageDescription [String]+extraDocFiles f s = fmap (\x -> s { T.extraDocFiles = x }) (f (T.extraDocFiles s))+{-# INLINE extraDocFiles #-}++-- | @since 3.0.0.0+allLibraries :: Traversal' PackageDescription Library+allLibraries f pd = mk <$> traverse f (T.library pd) <*> traverse f (T.subLibraries pd)+ where+ mk l ls = pd { T.library = l, T.subLibraries = ls }++-- | @since 2.4+componentModules :: Monoid r => ComponentName -> Getting r PackageDescription [ModuleName]+componentModules cname = case cname of+ CLibName name ->+ componentModules' name allLibraries libName explicitLibModules+ CFLibName name ->+ componentModules' name (foreignLibs . traverse) foreignLibName foreignLibModules+ CExeName name ->+ componentModules' name (executables . traverse) exeName exeModules+ CTestName name ->+ componentModules' name (testSuites . traverse) testName testModules+ CBenchName name ->+ componentModules' name (benchmarks . traverse) benchmarkName benchmarkModules+ where+ componentModules'+ :: (Eq name, Monoid r)+ => name+ -> Traversal' PackageDescription a+ -> Lens' a name+ -> (a -> [ModuleName])+ -> Getting r PackageDescription [ModuleName]+ componentModules' name pdL nameL modules =+ pdL+ . filtered ((== name) . view nameL)+ . getting modules++ filtered :: (a -> Bool) -> Traversal' a a+ filtered p f s = if p s then f s else pure s++-- | @since 2.4+componentBuildInfo :: ComponentName -> Traversal' PackageDescription BuildInfo+componentBuildInfo cname = case cname of+ CLibName name ->+ componentBuildInfo' name allLibraries libName libBuildInfo+ CFLibName name ->+ componentBuildInfo' name (foreignLibs . traverse) foreignLibName foreignLibBuildInfo+ CExeName name ->+ componentBuildInfo' name (executables . traverse) exeName exeBuildInfo+ CTestName name ->+ componentBuildInfo' name (testSuites . traverse) testName testBuildInfo+ CBenchName name ->+ componentBuildInfo' name (benchmarks . traverse) benchmarkName benchmarkBuildInfo+ where+ componentBuildInfo' :: Eq name+ => name+ -> Traversal' PackageDescription a+ -> Lens' a name+ -> Traversal' a BuildInfo+ -> Traversal' PackageDescription BuildInfo+ componentBuildInfo' name pdL nameL biL =+ pdL+ . filtered ((== name) . view nameL)+ . biL++ filtered :: (a -> Bool) -> Traversal' a a+ filtered p f s = if p s then f s else pure s
+ src/Distribution/Types/PackageId.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.PackageId+ ( PackageIdentifier(..)+ , PackageId+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec (Parsec (..), simpleParsec)+import Distribution.Pretty+import Distribution.Types.PackageName+import Distribution.Version (Version, nullVersion)++import qualified Data.List.NonEmpty as NE+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | Type alias so we can use the shorter name PackageId.+type PackageId = PackageIdentifier++-- | The name and version of a package.+data PackageIdentifier+ = PackageIdentifier {+ pkgName :: PackageName, -- ^The name of this package, eg. foo+ pkgVersion :: Version -- ^the version of this package, eg 1.2+ }+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++instance Binary PackageIdentifier+instance Structured PackageIdentifier++instance Pretty PackageIdentifier where+ pretty (PackageIdentifier n v)+ | v == nullVersion = pretty n -- if no version, don't show version.+ | otherwise = pretty n <<>> Disp.char '-' <<>> pretty v++-- |+--+-- >>> simpleParsec "foo-bar-0" :: Maybe PackageIdentifier+-- Just (PackageIdentifier {pkgName = PackageName "foo-bar", pkgVersion = mkVersion [0]})+--+-- >>> simpleParsec "foo-bar" :: Maybe PackageIdentifier+-- Just (PackageIdentifier {pkgName = PackageName "foo-bar", pkgVersion = mkVersion []})+--+-- /Note:/ Stricter than 'Text' instance+--+-- >>> simpleParsec "foo-bar-0-0" :: Maybe PackageIdentifier+-- Nothing+--+-- >>> simpleParsec "foo-bar.0" :: Maybe PackageIdentifier+-- Nothing+--+-- >>> simpleParsec "foo-bar.4-2" :: Maybe PackageIdentifier+-- Nothing+--+-- >>> simpleParsec "1.2.3" :: Maybe PackageIdentifier+-- Nothing+--+instance Parsec PackageIdentifier where+ parsec = do+ xs' <- P.sepByNonEmpty component (P.char '-')+ (v, xs) <- case simpleParsec (NE.last xs') of+ Nothing -> return (nullVersion, toList xs') -- all components are version+ Just v -> return (v, NE.init xs')+ if not (null xs) && all (\c -> all (/= '.') c && not (all isDigit c)) xs+ then return $ PackageIdentifier (mkPackageName (intercalate "-" xs)) v+ else fail "all digits or a dot in a portion of package name"+ where+ component = P.munch1 (\c -> isAlphaNum c || c == '.')++instance NFData PackageIdentifier where+ rnf (PackageIdentifier name version) = rnf name `seq` rnf version
+ src/Distribution/Types/PackageId/Lens.hs view
@@ -0,0 +1,22 @@+module Distribution.Types.PackageId.Lens (+ PackageIdentifier,+ module Distribution.Types.PackageId.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.PackageId (PackageIdentifier)+import Distribution.Types.PackageName (PackageName)+import Distribution.Version (Version)++import qualified Distribution.Types.PackageId as T++pkgName :: Lens' PackageIdentifier PackageName+pkgName f s = fmap (\x -> s { T.pkgName = x }) (f (T.pkgName s))+{-# INLINE pkgName #-}++pkgVersion :: Lens' PackageIdentifier Version+pkgVersion f s = fmap (\x -> s { T.pkgVersion = x }) (f (T.pkgVersion s))+{-# INLINE pkgVersion #-}
+ src/Distribution/Types/PackageName.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.PackageName+ ( PackageName+ , unPackageName, mkPackageName+ , unPackageNameST, mkPackageNameST+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.ShortText++import qualified Text.PrettyPrint as Disp+import Distribution.Pretty+import Distribution.Parsec++-- | A package name.+--+-- Use 'mkPackageName' and 'unPackageName' to convert from/to a+-- 'String'.+--+-- This type is opaque since @Cabal-2.0@+--+-- @since 2.0.0.2+newtype PackageName = PackageName ShortText+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++-- | Convert 'PackageName' to 'String'+unPackageName :: PackageName -> String+unPackageName (PackageName s) = fromShortText s++-- | @since 3.4.0.0+unPackageNameST :: PackageName -> ShortText+unPackageNameST (PackageName s) = s++-- | Construct a 'PackageName' from a 'String'+--+-- 'mkPackageName' is the inverse to 'unPackageName'+--+-- Note: No validations are performed to ensure that the resulting+-- 'PackageName' is valid+--+-- @since 2.0.0.2+mkPackageName :: String -> PackageName+mkPackageName = PackageName . toShortText++-- | Construct a 'PackageName' from a 'ShortText'+--+-- Note: No validations are performed to ensure that the resulting+-- 'PackageName' is valid+--+-- @since 3.4.0.0+mkPackageNameST :: ShortText -> PackageName+mkPackageNameST = PackageName++-- | 'mkPackageName'+--+-- @since 2.0.0.2+instance IsString PackageName where+ fromString = mkPackageName++instance Binary PackageName+instance Structured PackageName++instance Pretty PackageName where+ pretty = Disp.text . unPackageName++instance Parsec PackageName where+ parsec = mkPackageName <$> parsecUnqualComponentName++instance NFData PackageName where+ rnf (PackageName pkg) = rnf pkg
+ src/Distribution/Types/PackageName/Magic.hs view
@@ -0,0 +1,20 @@+-- | Magic 'PackageName's.+--+-- @since 3.0.0.0+module Distribution.Types.PackageName.Magic where++import Distribution.Types.PackageId+import Distribution.Types.PackageName+import Distribution.Types.Version++-- | Used as a placeholder in "Distribution.Backpack.ReadyComponent"+nonExistentPackageThisIsCabalBug :: PackageName+nonExistentPackageThisIsCabalBug = mkPackageName "nonexistent-package-this-is-a-cabal-bug"++-- | Used by @cabal new-repl@ and @cabal new-run@+fakePackageName :: PackageName+fakePackageName = mkPackageName "fake-package"++-- | 'fakePackageName' with 'version0'.+fakePackageId :: PackageId+fakePackageId = PackageIdentifier fakePackageName version0
+ src/Distribution/Types/PackageVersionConstraint.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.PackageVersionConstraint (+ PackageVersionConstraint(..),+ thisPackageVersionConstraint,+ simplifyPackageVersionConstraint,+) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.PackageId+import Distribution.Types.PackageName+import Distribution.Types.Version+import Distribution.Types.VersionRange.Internal+import Distribution.Version (simplifyVersionRange)++import qualified Distribution.Compat.CharParsing as P++-- | A version constraint on a package. Different from 'ExeDependency' and+-- 'Dependency' since it does not specify the need for a component, not even+-- the main library.+-- There are a few places in the codebase where 'Dependency' was used where+-- 'PackageVersionConstraint' is not used instead (#5570).+data PackageVersionConstraint = PackageVersionConstraint PackageName VersionRange+ deriving (Generic, Read, Show, Eq, Typeable, Data)++instance Binary PackageVersionConstraint+instance Structured PackageVersionConstraint+instance NFData PackageVersionConstraint where rnf = genericRnf++instance Pretty PackageVersionConstraint where+ -- Cannot do: PackageVersionConstraint have to be parseable+ -- as Dependency, due roundtrip problems. (e.g. talking to old ./Setup).+ --+ -- pretty (PackageVersionConstraint name (ThisVersion ver)) =+ -- pretty (PackageIdentifier name ver)+ pretty (PackageVersionConstraint name ver) =+ pretty name <+> pretty ver++-- |+--+-- >>> simpleParsec "foo" :: Maybe PackageVersionConstraint+-- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [0])))+--+-- >>> simpleParsec "foo >=2.0" :: Maybe PackageVersionConstraint+-- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [2,0])))+--+-- >>> simpleParsec "foo-2.0" :: Maybe PackageVersionConstraint+-- Just (PackageVersionConstraint (PackageName "foo") (ThisVersion (mkVersion [2,0])))+--+instance Parsec PackageVersionConstraint where+ parsec = do+ PackageIdentifier name ver <- parsec+ if ver == nullVersion+ then do+ P.spaces+ vr <- parsec <|> return anyVersion+ P.spaces+ return (PackageVersionConstraint name vr)+ else+ pure (PackageVersionConstraint name (thisVersion ver))++-- | @since 3.4.0.0+thisPackageVersionConstraint :: PackageIdentifier -> PackageVersionConstraint+thisPackageVersionConstraint (PackageIdentifier pn vr) =+ PackageVersionConstraint pn (thisVersion vr)++-- | @since 3.4.0.0+simplifyPackageVersionConstraint :: PackageVersionConstraint -> PackageVersionConstraint+simplifyPackageVersionConstraint (PackageVersionConstraint pn vr) =+ PackageVersionConstraint pn (simplifyVersionRange vr)
+ src/Distribution/Types/PkgconfigDependency.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.PkgconfigDependency+ ( PkgconfigDependency(..)+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.PkgconfigName+import Distribution.Types.PkgconfigVersionRange++import Distribution.Parsec+import Distribution.Pretty++import qualified Distribution.Compat.CharParsing as P++-- | Describes a dependency on a pkg-config library+--+-- @since 2.0.0.2+data PkgconfigDependency = PkgconfigDependency+ PkgconfigName+ PkgconfigVersionRange+ deriving (Generic, Read, Show, Eq, Typeable, Data)++instance Binary PkgconfigDependency+instance Structured PkgconfigDependency+instance NFData PkgconfigDependency where rnf = genericRnf++instance Pretty PkgconfigDependency where+ pretty (PkgconfigDependency name PcAnyVersion) = pretty name+ pretty (PkgconfigDependency name ver) = pretty name <+> pretty ver++instance Parsec PkgconfigDependency where+ parsec = do+ name <- parsec+ P.spaces+ verRange <- parsec <|> pure anyPkgconfigVersion+ pure $ PkgconfigDependency name verRange
+ src/Distribution/Types/PkgconfigName.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.PkgconfigName+ ( PkgconfigName, unPkgconfigName, mkPkgconfigName+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.ShortText++import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- | A pkg-config library name+--+-- This is parsed as any valid argument to the pkg-config utility.+--+-- @since 2.0.0.2+newtype PkgconfigName = PkgconfigName ShortText+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)++-- | Convert 'PkgconfigName' to 'String'+--+-- @since 2.0.0.2+unPkgconfigName :: PkgconfigName -> String+unPkgconfigName (PkgconfigName s) = fromShortText s++-- | Construct a 'PkgconfigName' from a 'String'+--+-- 'mkPkgconfigName' is the inverse to 'unPkgconfigName'+--+-- Note: No validations are performed to ensure that the resulting+-- 'PkgconfigName' is valid+--+-- @since 2.0.0.2+mkPkgconfigName :: String -> PkgconfigName+mkPkgconfigName = PkgconfigName . toShortText++-- | 'mkPkgconfigName'+--+-- @since 2.0.0.2+instance IsString PkgconfigName where+ fromString = mkPkgconfigName++instance Binary PkgconfigName+instance Structured PkgconfigName++-- pkg-config allows versions and other letters in package names, eg+-- "gtk+-2.0" is a valid pkg-config package _name_. It then has a package+-- version number like 2.10.13+instance Pretty PkgconfigName where+ pretty = Disp.text . unPkgconfigName++instance Parsec PkgconfigName where+ parsec = mkPkgconfigName <$> P.munch1 isNameChar where+ -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isNameChar '-' = True+ isNameChar '_' = True+ isNameChar '.' = True+ isNameChar '+' = True+ isNameChar c = isAlphaNum c++instance NFData PkgconfigName where+ rnf (PkgconfigName pkg) = rnf pkg
+ src/Distribution/Types/PkgconfigVersion.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+-- @since 3.0+module Distribution.Types.PkgconfigVersion (+ PkgconfigVersion (..),+ rpmvercmp,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Utils.Generic (isAsciiAlphaNum)++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS8+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP++-- | @pkg-config@ versions.+--+-- In fact, this can be arbitrary 'BS.ByteString',+-- but 'Parsec' instance is a little pickier.+--+-- @since 3.0+newtype PkgconfigVersion = PkgconfigVersion BS.ByteString+ deriving (Generic, Read, Show, Typeable, Data)++instance Eq PkgconfigVersion where+ PkgconfigVersion a == PkgconfigVersion b = rpmvercmp a b == EQ++instance Ord PkgconfigVersion where+ PkgconfigVersion a `compare` PkgconfigVersion b = rpmvercmp a b++instance Binary PkgconfigVersion+instance Structured PkgconfigVersion+instance NFData PkgconfigVersion where rnf = genericRnf++instance Pretty PkgconfigVersion where+ pretty (PkgconfigVersion bs) = PP.text (BS8.unpack bs)++-- |+--+-- >>> simpleParsec "1.0.2n" :: Maybe PkgconfigVersion+-- Just (PkgconfigVersion "1.0.2n")+--+-- >>> simpleParsec "0.3.5+ds" :: Maybe PkgconfigVersion+-- Nothing+--+instance Parsec PkgconfigVersion where+ parsec = PkgconfigVersion . BS8.pack <$> P.munch1 predicate where+ predicate c = isAsciiAlphaNum c || c == '.' || c == '-'++-------------------------------------------------------------------------------+-- rmpvercmp - pure Haskell implementation+-------------------------------------------------------------------------------++-- | Compare two version strings as @pkg-config@ would compare them.+--+-- @since 3.0+rpmvercmp :: BS.ByteString -> BS.ByteString -> Ordering+rpmvercmp a b = go0 (BS.unpack a) (BS.unpack b)+ where+ go0 :: [Word8] -> [Word8] -> Ordering+ -- if there is _any_ trailing "garbage", it seems to affect result+ -- https://github.com/haskell/cabal/issues/6805+ go0 [] [] = EQ+ go0 [] _ = LT+ go0 _ [] = GT+ go0 xs ys = go1 (dropNonAlnum8 xs) (dropNonAlnum8 ys)++ go1 :: [Word8] -> [Word8] -> Ordering+ go1 [] [] = EQ+ go1 [] _ = LT+ go1 _ [] = GT+ go1 xs@(x:_) ys+ | isDigit8 x =+ let (xs1, xs2) = span isDigit8 xs+ (ys1, ys2) = span isDigit8 ys+ -- numeric segments are always newer than alpha segments+ in if null ys1+ then GT+ else compareInt xs1 ys1 <> go0 xs2 ys2++ -- isAlpha+ | otherwise =+ let (xs1, xs2) = span isAlpha8 xs+ (ys1, ys2) = span isAlpha8 ys+ in if null ys1+ then LT+ else compareStr xs1 ys1 <> go0 xs2 ys2++-- compare as numbers+compareInt :: [Word8] -> [Word8] -> Ordering+compareInt xs ys =+ -- whichever number has more digits wins+ compare (length xs') (length ys') <>+ -- equal length: use per character compare, "strcmp"+ compare xs' ys'+ where+ -- drop leading zeros+ xs' = dropWhile (== 0x30) xs+ ys' = dropWhile (== 0x30) ys++-- strcmp+compareStr :: [Word8] -> [Word8] -> Ordering+compareStr = compare++dropNonAlnum8 :: [Word8] -> [Word8]+dropNonAlnum8 = dropWhile (\w -> not (isDigit8 w || isAlpha8 w))++isDigit8 :: Word8 -> Bool+isDigit8 w = 0x30 <= w && w <= 0x39++isAlpha8 :: Word8 -> Bool+isAlpha8 w = (0x41 <= w && w <= 0x5A) || (0x61 <= w && w <= 0x7A)++
+ src/Distribution/Types/PkgconfigVersionRange.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.PkgconfigVersionRange (+ PkgconfigVersionRange (..),+ anyPkgconfigVersion,+ isAnyPkgconfigVersion,+ withinPkgconfigVersionRange,+ -- * Internal+ versionToPkgconfigVersion,+ versionRangeToPkgconfigVersionRange,+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.CabalSpecVersion+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.PkgconfigVersion+import Distribution.Types.Version+import Distribution.Types.VersionInterval+import Distribution.Types.VersionRange++import qualified Data.ByteString.Char8 as BS8+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP++-- | @since 3.0+data PkgconfigVersionRange+ = PcAnyVersion+ | PcThisVersion PkgconfigVersion -- = version+ | PcLaterVersion PkgconfigVersion -- > version (NB. not >=)+ | PcEarlierVersion PkgconfigVersion -- < version+ | PcOrLaterVersion PkgconfigVersion -- >= version+ | PcOrEarlierVersion PkgconfigVersion -- =< version+ | PcUnionVersionRanges PkgconfigVersionRange PkgconfigVersionRange+ | PcIntersectVersionRanges PkgconfigVersionRange PkgconfigVersionRange+ deriving (Generic, Read, Show, Eq, Typeable, Data)++instance Binary PkgconfigVersionRange+instance Structured PkgconfigVersionRange+instance NFData PkgconfigVersionRange where rnf = genericRnf++instance Pretty PkgconfigVersionRange where+ pretty = pp 0 where+ pp :: Int -> PkgconfigVersionRange -> PP.Doc+ pp _ PcAnyVersion = PP.text "-any"+ pp _ (PcThisVersion v) = PP.text "==" <<>> pretty v+ pp _ (PcLaterVersion v) = PP.text ">" <<>> pretty v+ pp _ (PcEarlierVersion v) = PP.text "<" <<>> pretty v+ pp _ (PcOrLaterVersion v) = PP.text ">=" <<>> pretty v+ pp _ (PcOrEarlierVersion v) = PP.text "<=" <<>> pretty v++ pp d (PcUnionVersionRanges v u) = parens (d >= 1) $+ pp 1 v PP.<+> PP.text "||" PP.<+> pp 0 u+ pp d (PcIntersectVersionRanges v u) = parens (d >= 2) $+ pp 2 v PP.<+> PP.text "&&" PP.<+> pp 1 u++ parens True = PP.parens+ parens False = id++instance Parsec PkgconfigVersionRange where+ -- note: the wildcard is used in some places, e.g+ -- http://hackage.haskell.org/package/bindings-libzip-0.10.1/bindings-libzip.cabal+ --+ -- however, in the presence of alphanumerics etc. lax version parser,+ -- wildcard is ill-specified++ parsec = do+ csv <- askCabalSpecVersion+ if csv >= CabalSpecV3_0+ then pkgconfigParser+ else versionRangeToPkgconfigVersionRange <$> versionRangeParser P.integral csv++-- "modern" parser of @pkg-config@ package versions.+pkgconfigParser :: CabalParsing m => m PkgconfigVersionRange+pkgconfigParser = P.spaces >> expr where+ -- every parser here eats trailing space+ expr = do+ ts <- term `P.sepByNonEmpty` (P.string "||" >> P.spaces)+ return $ foldr1 PcUnionVersionRanges ts++ term = do+ fs <- factor `P.sepByNonEmpty` (P.string "&&" >> P.spaces)+ return $ foldr1 PcIntersectVersionRanges fs++ factor = parens expr <|> prim++ prim = do+ op <- P.munch1 isOpChar P.<?> "operator"+ case op of+ "-" -> anyPkgconfigVersion <$ (P.string "any" *> P.spaces)++ "==" -> afterOp PcThisVersion+ ">" -> afterOp PcLaterVersion+ "<" -> afterOp PcEarlierVersion+ ">=" -> afterOp PcOrLaterVersion+ "<=" -> afterOp PcOrEarlierVersion++ _ -> P.unexpected $ "Unknown version operator " ++ show op++ -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isOpChar '<' = True+ isOpChar '=' = True+ isOpChar '>' = True+ isOpChar '^' = True+ isOpChar '-' = True+ isOpChar _ = False++ afterOp f = do+ P.spaces+ v <- parsec+ P.spaces+ return (f v)++ parens = P.between+ ((P.char '(' P.<?> "opening paren") >> P.spaces)+ (P.char ')' >> P.spaces)++anyPkgconfigVersion :: PkgconfigVersionRange+anyPkgconfigVersion = PcAnyVersion++-- | TODO: this is not precise, but used only to prettify output.+isAnyPkgconfigVersion :: PkgconfigVersionRange -> Bool+isAnyPkgconfigVersion = (== PcAnyVersion)++withinPkgconfigVersionRange :: PkgconfigVersion -> PkgconfigVersionRange -> Bool+withinPkgconfigVersionRange v = go where+ go PcAnyVersion = True+ go (PcThisVersion u) = v == u+ go (PcLaterVersion u) = v > u+ go (PcEarlierVersion u) = v < u+ go (PcOrLaterVersion u) = v >= u+ go (PcOrEarlierVersion u) = v <= u+ go (PcUnionVersionRanges a b) = go a || go b+ go (PcIntersectVersionRanges a b) = go a && go b++-------------------------------------------------------------------------------+-- Conversion+-------------------------------------------------------------------------------++versionToPkgconfigVersion :: Version -> PkgconfigVersion+versionToPkgconfigVersion = PkgconfigVersion . BS8.pack . prettyShow++versionRangeToPkgconfigVersionRange :: VersionRange -> PkgconfigVersionRange+versionRangeToPkgconfigVersionRange vr+ | isAnyVersion vr+ = PcAnyVersion+ | otherwise+ = case asVersionIntervals vr of+ [] -> PcEarlierVersion (PkgconfigVersion (BS8.pack "0"))+ (i:is) -> foldl (\r j -> PcUnionVersionRanges r (conv j)) (conv i) is+ where+ conv (VersionInterval (LowerBound v b) NoUpperBound) = convL v b+ conv (VersionInterval (LowerBound v b) (UpperBound u c)) = PcIntersectVersionRanges (convL v b) (convU u c)++ convL v ExclusiveBound = PcLaterVersion (versionToPkgconfigVersion v)+ convL v InclusiveBound = PcOrLaterVersion (versionToPkgconfigVersion v)++ convU v ExclusiveBound = PcEarlierVersion (versionToPkgconfigVersion v)+ convU v InclusiveBound = PcOrEarlierVersion (versionToPkgconfigVersion v)
+ src/Distribution/Types/SetupBuildInfo.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.SetupBuildInfo (+ SetupBuildInfo(..)+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.Dependency++-- ---------------------------------------------------------------------------+-- 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 Structured SetupBuildInfo+instance NFData SetupBuildInfo where rnf = genericRnf++instance Monoid SetupBuildInfo where+ mempty = SetupBuildInfo [] False+ mappend = (<>)++instance Semigroup SetupBuildInfo where+ a <> b = SetupBuildInfo+ (setupDepends a <> setupDepends b)+ (defaultSetupDepends a || defaultSetupDepends b)
+ src/Distribution/Types/SetupBuildInfo/Lens.hs view
@@ -0,0 +1,21 @@+module Distribution.Types.SetupBuildInfo.Lens (+ SetupBuildInfo,+ module Distribution.Types.SetupBuildInfo.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.Dependency (Dependency)+import Distribution.Types.SetupBuildInfo (SetupBuildInfo)++import qualified Distribution.Types.SetupBuildInfo as T++setupDepends :: Lens' SetupBuildInfo [Dependency]+setupDepends f s = fmap (\x -> s { T.setupDepends = x }) (f (T.setupDepends s))+{-# INLINE setupDepends #-}++defaultSetupDepends :: Lens' SetupBuildInfo Bool+defaultSetupDepends f s = fmap (\x -> s { T.defaultSetupDepends = x }) (f (T.defaultSetupDepends s))+{-# INLINE defaultSetupDepends #-}
+ src/Distribution/Types/SourceRepo.hs view
@@ -0,0 +1,201 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.SourceRepo (+ SourceRepo(..),+ RepoKind(..),+ RepoType(..),+ KnownRepoType (..),+ knownRepoTypes,+ emptySourceRepo,+ classifyRepoType,+ classifyRepoKind,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Utils.Generic (lowercase)++import Distribution.Pretty+import Distribution.Parsec++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp+import qualified Data.Map.Strict as M++-- ------------------------------------------------------------+-- * Source repos+-- ------------------------------------------------------------++-- | Information about the source revision control system for a package.+--+-- When specifying a repo it is useful to know the meaning or intention of the+-- information as doing so enables automation. There are two obvious common+-- purposes: one is to find the repo for the latest development version, the+-- other is to find the repo for this specific release. The 'ReopKind'+-- specifies which one we mean (or another custom one).+--+-- A package can specify one or the other kind or both. Most will specify just+-- a head repo but some may want to specify a repo to reconstruct the sources+-- for this package release.+--+-- The required information is the 'RepoType' which tells us if it's using+-- 'Darcs', 'Git' for example. The 'repoLocation' and other details are+-- interpreted according to the repo type.+--+data SourceRepo = SourceRepo {+ -- | The kind of repo. This field is required.+ repoKind :: RepoKind,++ -- | The type of the source repository system for this repo, eg 'Darcs' or+ -- 'Git'. This field is required.+ repoType :: Maybe RepoType,++ -- | The location of the repository. For most 'RepoType's this is a URL.+ -- This field is required.+ repoLocation :: Maybe String,++ -- | 'CVS' can put multiple \"modules\" on one server and requires a+ -- module name in addition to the location to identify a particular repo.+ -- Logically this is part of the location but unfortunately has to be+ -- specified separately. This field is required for the 'CVS' 'RepoType' and+ -- should not be given otherwise.+ repoModule :: Maybe String,++ -- | The name or identifier of the branch, if any. Many source control+ -- systems have the notion of multiple branches in a repo that exist in the+ -- same location. For example 'Git' and 'CVS' use this while systems like+ -- 'Darcs' use different locations for different branches. This field is+ -- optional but should be used if necessary to identify the sources,+ -- especially for the 'RepoThis' repo kind.+ repoBranch :: Maybe String,++ -- | The tag identify a particular state of the repository. This should be+ -- given for the 'RepoThis' repo kind and not for 'RepoHead' kind.+ --+ repoTag :: Maybe String,++ -- | Some repositories contain multiple projects in different subdirectories+ -- This field specifies the subdirectory where this packages sources can be+ -- found, eg the subdirectory containing the @.cabal@ file. It is interpreted+ -- relative to the root of the repository. This field is optional. If not+ -- given the default is \".\" ie no subdirectory.+ repoSubdir :: Maybe FilePath+}+ deriving (Eq, Ord, Generic, Read, Show, Typeable, Data)++emptySourceRepo :: RepoKind -> SourceRepo+emptySourceRepo kind = SourceRepo+ { repoKind = kind+ , repoType = Nothing+ , repoLocation = Nothing+ , repoModule = Nothing+ , repoBranch = Nothing+ , repoTag = Nothing+ , repoSubdir = Nothing+ }++instance Binary SourceRepo+instance Structured SourceRepo+instance NFData SourceRepo where rnf = genericRnf++-- | What this repo info is for, what it represents.+--+data RepoKind =+ -- | The repository for the \"head\" or development version of the project.+ -- This repo is where we should track the latest development activity or+ -- the usual repo people should get to contribute patches.+ RepoHead++ -- | The repository containing the sources for this exact package version+ -- or release. For this kind of repo a tag should be given to give enough+ -- information to re-create the exact sources.+ | RepoThis++ | RepoKindUnknown String+ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)++instance Binary RepoKind+instance Structured RepoKind+instance NFData RepoKind where rnf = genericRnf++-- | An enumeration of common source control systems. The fields used in the+-- 'SourceRepo' depend on the type of repo. The tools and methods used to+-- obtain and track the repo depend on the repo type.+--+data KnownRepoType = Darcs | Git | SVN | CVS+ | Mercurial | GnuArch | Bazaar | Monotone+ | Pijul -- ^ @since 3.4.0.0+ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data, Enum, Bounded)++instance Binary KnownRepoType+instance Structured KnownRepoType+instance NFData KnownRepoType where rnf = genericRnf++instance Parsec KnownRepoType where+ parsec = do+ str <- P.munch1 isIdent+ maybe+ (P.unexpected $ "Could not parse KnownRepoType from " ++ str)+ return+ (M.lookup str knownRepoTypeMap)++instance Pretty KnownRepoType where+ pretty = Disp.text . lowercase . show++data RepoType = KnownRepoType KnownRepoType+ | OtherRepoType String+ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)++instance Binary RepoType+instance Structured RepoType+instance NFData RepoType where rnf = genericRnf++knownRepoTypes :: [KnownRepoType]+knownRepoTypes = [minBound .. maxBound]++repoTypeAliases :: KnownRepoType -> [String]+repoTypeAliases Bazaar = ["bzr"]+repoTypeAliases Mercurial = ["hg"]+repoTypeAliases GnuArch = ["arch"]+repoTypeAliases _ = []++instance Pretty RepoKind where+ pretty RepoHead = Disp.text "head"+ pretty RepoThis = Disp.text "this"+ pretty (RepoKindUnknown other) = Disp.text other++instance Parsec RepoKind where+ parsec = classifyRepoKind <$> P.munch1 isIdent++classifyRepoKind :: String -> RepoKind+classifyRepoKind name = case lowercase name of+ "head" -> RepoHead+ "this" -> RepoThis+ _ -> RepoKindUnknown name++instance Parsec RepoType where+ parsec = classifyRepoType <$> P.munch1 isIdent++instance Pretty RepoType where+ pretty (OtherRepoType other) = Disp.text other+ pretty (KnownRepoType t) = pretty t++classifyRepoType :: String -> RepoType+classifyRepoType s =+ maybe+ (OtherRepoType s)+ KnownRepoType+ (M.lookup (lowercase s) knownRepoTypeMap)++knownRepoTypeMap :: Map String KnownRepoType+knownRepoTypeMap =+ M.fromList+ [ (name, repoType')+ | repoType' <- knownRepoTypes+ , name <- prettyShow repoType' : repoTypeAliases repoType'+ ]++isIdent :: Char -> Bool+isIdent c = isAlphaNum c || c == '_' || c == '-'
+ src/Distribution/Types/SourceRepo/Lens.hs view
@@ -0,0 +1,39 @@+module Distribution.Types.SourceRepo.Lens (+ T.SourceRepo,+ module Distribution.Types.SourceRepo.Lens,+ ) where++import Prelude()+import Distribution.Compat.Prelude+import Distribution.Compat.Lens++import Distribution.Types.SourceRepo (SourceRepo, RepoKind, RepoType)+import qualified Distribution.Types.SourceRepo as T++repoKind :: Lens' SourceRepo RepoKind+repoKind f s = fmap (\x -> s { T.repoKind = x }) (f (T.repoKind s))+{-# INLINE repoKind #-}++repoType :: Lens' SourceRepo (Maybe RepoType)+repoType f s = fmap (\x -> s { T.repoType = x }) (f (T.repoType s))+{-# INLINE repoType #-}++repoLocation :: Lens' SourceRepo (Maybe String)+repoLocation f s = fmap (\x -> s { T.repoLocation = x }) (f (T.repoLocation s))+{-# INLINE repoLocation #-}++repoModule :: Lens' SourceRepo (Maybe String)+repoModule f s = fmap (\x -> s { T.repoModule = x }) (f (T.repoModule s))+{-# INLINE repoModule #-}++repoBranch :: Lens' SourceRepo (Maybe String)+repoBranch f s = fmap (\x -> s { T.repoBranch = x }) (f (T.repoBranch s))+{-# INLINE repoBranch #-}++repoTag :: Lens' SourceRepo (Maybe String)+repoTag f s = fmap (\x -> s { T.repoTag = x }) (f (T.repoTag s))+{-# INLINE repoTag #-}++repoSubdir :: Lens' SourceRepo (Maybe FilePath)+repoSubdir f s = fmap (\x -> s { T.repoSubdir = x }) (f (T.repoSubdir s))+{-# INLINE repoSubdir #-}
+ src/Distribution/Types/TargetInfo.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE TypeFamilies #-}+module Distribution.Types.TargetInfo (+ TargetInfo(..)+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.ComponentLocalBuildInfo+import Distribution.Types.Component+import Distribution.Types.UnitId++import Distribution.Compat.Graph (IsNode(..))++-- | The 'TargetInfo' contains all the information necessary to build a+-- specific target (e.g., component/module/file) in a package. In+-- principle, one can get the 'Component' from a+-- 'ComponentLocalBuildInfo' and 'LocalBuildInfo', but it is much more+-- convenient to have the component in hand.+data TargetInfo = TargetInfo {+ targetCLBI :: ComponentLocalBuildInfo,+ targetComponent :: Component+ -- TODO: BuildTargets supporting parsing these is dumb,+ -- we don't have support for compiling single modules or+ -- file paths. Accommodating it now is premature+ -- generalization. Figure it out later.+ -- targetSub :: Maybe (Either ModuleName FilePath)+ }++instance IsNode TargetInfo where+ type Key TargetInfo = UnitId+ nodeKey = nodeKey . targetCLBI+ nodeNeighbors = nodeNeighbors . targetCLBI
+ src/Distribution/Types/TestSuite.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.TestSuite (+ TestSuite(..),+ emptyTestSuite,+ testType,+ testModules,+ testModulesAutogen+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.BuildInfo+import Distribution.Types.TestType+import Distribution.Types.TestSuiteInterface+import Distribution.Types.UnqualComponentName++import Distribution.ModuleName++import qualified Distribution.Types.BuildInfo.Lens as L++-- | A \"test-suite\" stanza in a cabal file.+--+data TestSuite = TestSuite {+ testName :: UnqualComponentName,+ testInterface :: TestSuiteInterface,+ testBuildInfo :: BuildInfo+ }+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance L.HasBuildInfo TestSuite where+ buildInfo f l = (\x -> l { testBuildInfo = x }) <$> f (testBuildInfo l)++instance Binary TestSuite+instance Structured TestSuite++instance NFData TestSuite where rnf = genericRnf++instance Monoid TestSuite where+ mempty = TestSuite {+ testName = mempty,+ testInterface = mempty,+ testBuildInfo = mempty+ }+ mappend = (<>)++instance Semigroup TestSuite where+ a <> b = TestSuite {+ testName = combine' testName,+ testInterface = combine testInterface,+ testBuildInfo = combine testBuildInfo+ }+ where combine field = field a `mappend` field b+ combine' field = case ( unUnqualComponentName $ field a+ , unUnqualComponentName $ field b) of+ ("", _) -> field b+ (_, "") -> field a+ (x, y) -> error $ "Ambiguous values for test field: '"+ ++ x ++ "' and '" ++ y ++ "'"++emptyTestSuite :: TestSuite+emptyTestSuite = mempty+++testType :: TestSuite -> TestType+testType test = case testInterface test of+ TestSuiteExeV10 ver _ -> TestTypeExe ver+ TestSuiteLibV09 ver _ -> TestTypeLib ver+ TestSuiteUnsupported testtype -> testtype++-- | Get all the module names from a test suite.+testModules :: TestSuite -> [ModuleName]+testModules test = (case testInterface test of+ TestSuiteLibV09 _ m -> [m]+ _ -> [])+ ++ otherModules (testBuildInfo test)++-- | Get all the auto generated module names from a test suite.+-- This are a subset of 'testModules'.+testModulesAutogen :: TestSuite -> [ModuleName]+testModulesAutogen test = autogenModules (testBuildInfo test)
+ src/Distribution/Types/TestSuite/Lens.hs view
@@ -0,0 +1,27 @@+module Distribution.Types.TestSuite.Lens (+ TestSuite,+ module Distribution.Types.TestSuite.Lens,+ ) where++import Distribution.Compat.Lens+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.TestSuite (TestSuite)+import Distribution.Types.TestSuiteInterface (TestSuiteInterface)+import Distribution.Types.UnqualComponentName (UnqualComponentName)++import qualified Distribution.Types.TestSuite as T++testName :: Lens' TestSuite UnqualComponentName+testName f s = fmap (\x -> s { T.testName = x }) (f (T.testName s))+{-# INLINE testName #-}++testInterface :: Lens' TestSuite TestSuiteInterface+testInterface f s = fmap (\x -> s { T.testInterface = x }) (f (T.testInterface s))+{-# INLINE testInterface #-}++testBuildInfo :: Lens' TestSuite BuildInfo+testBuildInfo f s = fmap (\x -> s { T.testBuildInfo = x }) (f (T.testBuildInfo s))+{-# INLINE testBuildInfo #-}
+ src/Distribution/Types/TestSuiteInterface.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Distribution.Types.TestSuiteInterface (+ TestSuiteInterface(..),+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Types.TestType+import Distribution.ModuleName+import Distribution.Version++-- | The test suite interfaces that are currently defined. Each test suite must+-- specify which interface it supports.+--+-- More interfaces may be defined in future, either new revisions or totally+-- new interfaces.+--+data TestSuiteInterface =++ -- | Test interface \"exitcode-stdio-1.0\". The test-suite takes the form+ -- of an executable. It returns a zero exit code for success, non-zero for+ -- failure. The stdout and stderr channels may be logged. It takes no+ -- command line parameters and nothing on stdin.+ --+ TestSuiteExeV10 Version FilePath++ -- | Test interface \"detailed-0.9\". The test-suite takes the form of a+ -- library containing a designated module that exports \"tests :: [Test]\".+ --+ | TestSuiteLibV09 Version ModuleName++ -- | A test suite that does not conform to one of the above interfaces for+ -- the given reason (e.g. unknown test type).+ --+ | TestSuiteUnsupported TestType+ deriving (Eq, Generic, Read, Show, Typeable, Data)++instance Binary TestSuiteInterface+instance Structured TestSuiteInterface++instance NFData TestSuiteInterface where rnf = genericRnf++instance Monoid TestSuiteInterface where+ mempty = TestSuiteUnsupported (TestTypeUnknown mempty nullVersion)+ mappend = (<>)++instance Semigroup TestSuiteInterface where+ a <> (TestSuiteUnsupported _) = a+ _ <> b = b
+ src/Distribution/Types/TestType.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Distribution.Types.TestType (+ TestType(..),+ knownTestTypes,+) where++import Distribution.Compat.Prelude+import Distribution.Version+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Text.PrettyPrint (char, text)++-- | The \"test-type\" field in the test suite stanza.+--+data TestType = TestTypeExe Version -- ^ \"type: exitcode-stdio-x.y\"+ | TestTypeLib Version -- ^ \"type: detailed-x.y\"+ | TestTypeUnknown String Version -- ^ Some unknown test type e.g. \"type: foo\"+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary TestType+instance Structured TestType++instance NFData TestType where rnf = genericRnf++knownTestTypes :: [TestType]+knownTestTypes = [ TestTypeExe (mkVersion [1,0])+ , TestTypeLib (mkVersion [0,9]) ]++instance Pretty TestType where+ pretty (TestTypeExe ver) = text "exitcode-stdio-" <<>> pretty ver+ pretty (TestTypeLib ver) = text "detailed-" <<>> pretty ver+ pretty (TestTypeUnknown name ver) = text name <<>> char '-' <<>> pretty ver++instance Parsec TestType where+ parsec = parsecStandard $ \ver name -> case name of+ "exitcode-stdio" -> TestTypeExe ver+ "detailed" -> TestTypeLib ver+ _ -> TestTypeUnknown name ver
+ src/Distribution/Types/UnitId.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleContexts #-}++module Distribution.Types.UnitId+ ( UnitId, unUnitId, mkUnitId+ , DefUnitId+ , unsafeMkDefUnitId+ , unDefUnitId+ , newSimpleUnitId+ , mkLegacyUnitId+ , getHSLibraryName+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Distribution.Utils.ShortText++import qualified Distribution.Compat.CharParsing as P+import Distribution.Pretty+import Distribution.Parsec+import Distribution.Types.ComponentId+import Distribution.Types.PackageId++import Text.PrettyPrint (text)++-- | A unit identifier identifies a (possibly instantiated)+-- package/component that can be installed the installed package+-- database. There are several types of components that can be+-- installed:+--+-- * A traditional library with no holes, so that 'unitIdHash'+-- is @Nothing@. In the absence of Backpack, 'UnitId'+-- is the same as a 'ComponentId'.+--+-- * An indefinite, Backpack library with holes. In this case,+-- 'unitIdHash' is still @Nothing@, but in the install,+-- there are only interfaces, no compiled objects.+--+-- * An instantiated Backpack library with all the holes+-- filled in. 'unitIdHash' is a @Just@ a hash of the+-- instantiating mapping.+--+-- A unit is a component plus the additional information on how the+-- holes are filled in. Thus there is a one to many relationship: for a+-- particular component there are many different ways of filling in the+-- holes, and each different combination is a unit (and has a separate+-- 'UnitId').+--+-- 'UnitId' is distinct from 'OpenUnitId', in that it is always+-- installed, whereas 'OpenUnitId' are intermediate unit identities+-- that arise during mixin linking, and don't necessarily correspond+-- to any actually installed unit. Since the mapping is not actually+-- recorded in a 'UnitId', you can't actually substitute over them+-- (but you can substitute over 'OpenUnitId'). See also+-- "Distribution.Backpack.FullUnitId" for a mechanism for expanding an+-- instantiated 'UnitId' to retrieve its mapping.+--+-- Backwards compatibility note: if you need to get the string+-- representation of a UnitId to pass, e.g., as a @-package-id@+-- flag, use the 'display' function, which will work on all+-- versions of Cabal.+--+newtype UnitId = UnitId ShortText+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, NFData)++instance Binary UnitId+instance Structured UnitId++-- | The textual format for 'UnitId' coincides with the format+-- GHC accepts for @-package-id@.+--+instance Pretty UnitId where+ pretty = text . unUnitId++-- | The textual format for 'UnitId' coincides with the format+-- GHC accepts for @-package-id@.+--+instance Parsec UnitId where+ parsec = mkUnitId <$> P.munch1 isUnitChar where+ -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isUnitChar '-' = True+ isUnitChar '_' = True+ isUnitChar '.' = True+ isUnitChar '+' = True+ isUnitChar c = isAlphaNum c++-- | If you need backwards compatibility, consider using 'display'+-- instead, which is supported by all versions of Cabal.+--+unUnitId :: UnitId -> String+unUnitId (UnitId s) = fromShortText s++mkUnitId :: String -> UnitId+mkUnitId = UnitId . toShortText++-- | 'mkUnitId'+--+-- @since 2.0.0.2+instance IsString UnitId where+ fromString = mkUnitId++-- | Create a unit identity with no associated hash directly+-- from a 'ComponentId'.+newSimpleUnitId :: ComponentId -> UnitId+newSimpleUnitId = mkUnitId . unComponentId++-- | Make an old-style UnitId from a package identifier.+-- Assumed to be for the public library+mkLegacyUnitId :: PackageId -> UnitId+mkLegacyUnitId = newSimpleUnitId . mkComponentId . prettyShow++-- | Returns library name prefixed with HS, suitable for filenames+getHSLibraryName :: UnitId -> String+getHSLibraryName uid = "HS" ++ prettyShow uid++-- | A 'UnitId' for a definite package. The 'DefUnitId' invariant says+-- that a 'UnitId' identified this way is definite; i.e., it has no+-- unfilled holes.+newtype DefUnitId = DefUnitId { unDefUnitId :: UnitId }+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, Binary, NFData, Pretty)++instance Structured DefUnitId++-- Workaround for a GHC 8.0.1 bug, see+-- https://github.com/haskell/cabal/issues/4793#issuecomment-334258288+instance Parsec DefUnitId where+ parsec = DefUnitId <$> parsec++-- | Unsafely create a 'DefUnitId' from a 'UnitId'. Your responsibility+-- is to ensure that the 'DefUnitId' invariant holds.+unsafeMkDefUnitId :: UnitId -> DefUnitId+unsafeMkDefUnitId = DefUnitId
+ src/Distribution/Types/UnqualComponentName.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Distribution.Types.UnqualComponentName+ ( UnqualComponentName, unUnqualComponentName, unUnqualComponentNameST, mkUnqualComponentName+ , packageNameToUnqualComponentName, unqualComponentNameToPackageName+ ) where++import Distribution.Compat.Prelude+import Distribution.Utils.ShortText+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Types.PackageName++-- | An unqualified component name, for any kind of component.+--+-- This is distinguished from a 'ComponentName' and 'ComponentId'. The former+-- also states which of a library, executable, etc the name refers too. The+-- later uniquely identifiers a component and its closure.+--+-- @since 2.0.0.2+newtype UnqualComponentName = UnqualComponentName ShortText+ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data,+ Semigroup, Monoid) -- TODO: bad enabler of bad monoids++-- | Convert 'UnqualComponentName' to 'String'+--+-- @since 2.0.0.2+unUnqualComponentName :: UnqualComponentName -> String+unUnqualComponentName (UnqualComponentName s) = fromShortText s++-- | @since 3.4.0.0+unUnqualComponentNameST :: UnqualComponentName -> ShortText+unUnqualComponentNameST (UnqualComponentName s) = s++-- | Construct a 'UnqualComponentName' from a 'String'+--+-- 'mkUnqualComponentName' is the inverse to 'unUnqualComponentName'+--+-- Note: No validations are performed to ensure that the resulting+-- 'UnqualComponentName' is valid+--+-- @since 2.0.0.2+mkUnqualComponentName :: String -> UnqualComponentName+mkUnqualComponentName = UnqualComponentName . toShortText++-- | 'mkUnqualComponentName'+--+-- @since 2.0.0.2+instance IsString UnqualComponentName where+ fromString = mkUnqualComponentName++instance Binary UnqualComponentName+instance Structured UnqualComponentName++instance Pretty UnqualComponentName where+ pretty = showToken . unUnqualComponentName++instance Parsec UnqualComponentName where+ parsec = mkUnqualComponentName <$> parsecUnqualComponentName++instance NFData UnqualComponentName where+ rnf (UnqualComponentName pkg) = rnf pkg++-- TODO avoid String round trip with these PackageName <->+-- UnqualComponentName converters.++-- | Converts a package name to an unqualified component name+--+-- Useful in legacy situations where a package name may refer to an internal+-- component, if one is defined with that name.+--+-- 2018-12-21: These "legacy" situations are not legacy.+-- We can @build-depends@ on the internal library. However+-- Now dependency contains @Set LibraryName@, and we should use that.+--+-- @since 2.0.0.2+packageNameToUnqualComponentName :: PackageName -> UnqualComponentName+packageNameToUnqualComponentName = UnqualComponentName . unPackageNameST++-- | Converts an unqualified component name to a package name+--+-- `packageNameToUnqualComponentName` is the inverse of+-- `unqualComponentNameToPackageName`.+--+-- Useful in legacy situations where a package name may refer to an internal+-- component, if one is defined with that name.+--+-- @since 2.0.0.2+unqualComponentNameToPackageName :: UnqualComponentName -> PackageName+unqualComponentNameToPackageName = mkPackageNameST . unUnqualComponentNameST
+ src/Distribution/Types/Version.hs view
@@ -0,0 +1,242 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Types.Version (+ -- * Package versions+ Version,+ mkVersion,+ mkVersion',+ versionNumbers,+ nullVersion,+ alterVersion,+ version0,++ -- * Internal+ validVersion,+ versionDigitParser,+ ) where++import Data.Bits (shiftL, shiftR, (.&.), (.|.))+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Parsec+import Distribution.Pretty++import qualified Data.Version as Base+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp+import qualified Text.Read as Read++-- | A 'Version' represents the version of a software entity.+--+-- Instances of 'Eq' and 'Ord' are provided, which gives exact+-- equality and lexicographic ordering of the version number+-- components (i.e. 2.1 > 2.0, 1.2.3 > 1.2.2, etc.).+--+-- This type is opaque and distinct from the 'Base.Version' type in+-- "Data.Version" since @Cabal-2.0@. The difference extends to the+-- 'Binary' instance using a different (and more compact) encoding.+--+-- @since 2.0.0.2+data Version = PV0 {-# UNPACK #-} !Word64+ | PV1 !Int [Int]+ -- NOTE: If a version fits into the packed Word64+ -- representation (i.e. at most four version components+ -- which all fall into the [0..0xfffe] range), then PV0+ -- MUST be used. This is essential for the 'Eq' instance+ -- to work.+ deriving (Data,Eq,Generic,Typeable)++instance Ord Version where+ compare (PV0 x) (PV0 y) = compare x y+ compare (PV1 x xs) (PV1 y ys) = case compare x y of+ EQ -> compare xs ys+ c -> c+ compare (PV0 w) (PV1 y ys) = case compare x y of+ EQ -> compare [x2,x3,x4] ys+ c -> c+ where+ x = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1+ x2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1+ x3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1+ x4 = fromIntegral (w .&. 0xffff) - 1+ compare (PV1 x xs) (PV0 w) = case compare x y of+ EQ -> compare xs [y2,y3,y4]+ c -> c+ where+ y = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1+ y2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1+ y3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1+ y4 = fromIntegral (w .&. 0xffff) - 1++instance Show Version where+ showsPrec d v = showParen (d > 10)+ $ showString "mkVersion "+ . showsPrec 11 (versionNumbers v)++instance Read Version where+ readPrec = Read.parens $ do+ Read.Ident "mkVersion" <- Read.lexP+ v <- Read.step Read.readPrec+ return (mkVersion v)++instance Binary Version+instance Structured Version++instance NFData Version where+ rnf (PV0 _) = ()+ rnf (PV1 _ ns) = rnf ns++instance Pretty Version where+ pretty ver+ = Disp.hcat (Disp.punctuate (Disp.char '.')+ (map Disp.int $ versionNumbers ver))++instance Parsec Version where+ parsec = mkVersion <$> toList <$> P.sepByNonEmpty versionDigitParser (P.char '.') <* tags+ where+ tags = do+ ts <- many $ P.char '-' *> some (P.satisfy isAlphaNum)+ case ts of+ [] -> pure ()+ (_ : _) -> parsecWarning PWTVersionTag "version with tags"++-- | An integral without leading zeroes.+--+-- @since 3.0+versionDigitParser :: CabalParsing m => m Int+versionDigitParser = (some d >>= toNumber) P.<?> "version digit (integral without leading zeroes)"+ where+ toNumber :: CabalParsing m => [Int] -> m Int+ toNumber [0] = return 0+ toNumber (0:_) = P.unexpected "Version digit with leading zero"+ toNumber xs+ -- 10^9 = 1000000000+ -- 2^30 = 1073741824+ --+ -- GHC Int is at least 32 bits, so 2^31-1 is the 'maxBound'.+ | length xs > 9 = P.unexpected "At most 9 numbers are allowed per version number part"+ | otherwise = return $ foldl' (\a b -> a * 10 + b) 0 xs++ d :: P.CharParsing m => m Int+ d = f <$> P.satisfyRange '0' '9'+ f c = ord c - ord '0'++-- | Construct 'Version' from list of version number components.+--+-- For instance, @mkVersion [3,2,1]@ constructs a 'Version'+-- representing the version @3.2.1@.+--+-- All version components must be non-negative. @mkVersion []@+-- currently represents the special /null/ version; see also 'nullVersion'.+--+-- @since 2.0.0.2+mkVersion :: [Int] -> Version+-- TODO: add validity check; disallow 'mkVersion []' (we have+-- 'nullVersion' for that)+mkVersion [] = nullVersion+mkVersion (v1:[])+ | inWord16VerRep1 v1 = PV0 (mkWord64VerRep1 v1)+ | otherwise = PV1 v1 []+ where+ inWord16VerRep1 x1 = inWord16 (x1 .|. (x1+1))+ mkWord64VerRep1 y1 = mkWord64VerRep (y1+1) 0 0 0++mkVersion (v1:vs@(v2:[]))+ | inWord16VerRep2 v1 v2 = PV0 (mkWord64VerRep2 v1 v2)+ | otherwise = PV1 v1 vs+ where+ inWord16VerRep2 x1 x2 = inWord16 (x1 .|. (x1+1)+ .|. x2 .|. (x2+1))+ mkWord64VerRep2 y1 y2 = mkWord64VerRep (y1+1) (y2+1) 0 0++mkVersion (v1:vs@(v2:v3:[]))+ | inWord16VerRep3 v1 v2 v3 = PV0 (mkWord64VerRep3 v1 v2 v3)+ | otherwise = PV1 v1 vs+ where+ inWord16VerRep3 x1 x2 x3 = inWord16 (x1 .|. (x1+1)+ .|. x2 .|. (x2+1)+ .|. x3 .|. (x3+1))+ mkWord64VerRep3 y1 y2 y3 = mkWord64VerRep (y1+1) (y2+1) (y3+1) 0++mkVersion (v1:vs@(v2:v3:v4:[]))+ | inWord16VerRep4 v1 v2 v3 v4 = PV0 (mkWord64VerRep4 v1 v2 v3 v4)+ | otherwise = PV1 v1 vs+ where+ inWord16VerRep4 x1 x2 x3 x4 = inWord16 (x1 .|. (x1+1)+ .|. x2 .|. (x2+1)+ .|. x3 .|. (x3+1)+ .|. x4 .|. (x4+1))+ mkWord64VerRep4 y1 y2 y3 y4 = mkWord64VerRep (y1+1) (y2+1) (y3+1) (y4+1)++mkVersion (v1:vs) = PV1 v1 vs++-- | Version 0. A lower bound of 'Version'.+--+-- @since 2.2+version0 :: Version+version0 = mkVersion [0]++{-# INLINE mkWord64VerRep #-}+mkWord64VerRep :: Int -> Int -> Int -> Int -> Word64+mkWord64VerRep v1 v2 v3 v4 =+ (fromIntegral v1 `shiftL` 48)+ .|. (fromIntegral v2 `shiftL` 32)+ .|. (fromIntegral v3 `shiftL` 16)+ .|. fromIntegral v4++{-# INLINE inWord16 #-}+inWord16 :: Int -> Bool+inWord16 x = (fromIntegral x :: Word) <= 0xffff++-- | Variant of 'mkVersion' which converts a "Data.Version"+-- 'Base.Version' into Cabal's 'Version' type.+--+-- @since 2.0.0.2+mkVersion' :: Base.Version -> Version+mkVersion' = mkVersion . Base.versionBranch++-- | Unpack 'Version' into list of version number components.+--+-- This is the inverse to 'mkVersion', so the following holds:+--+-- > (versionNumbers . mkVersion) vs == vs+--+-- @since 2.0.0.2+versionNumbers :: Version -> [Int]+versionNumbers (PV1 n ns) = n:ns+versionNumbers (PV0 w)+ | v1 < 0 = []+ | v2 < 0 = [v1]+ | v3 < 0 = [v1,v2]+ | v4 < 0 = [v1,v2,v3]+ | otherwise = [v1,v2,v3,v4]+ where+ v1 = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1+ v2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1+ v3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1+ v4 = fromIntegral (w .&. 0xffff) - 1+++-- | Constant representing the special /null/ 'Version'+--+-- The 'nullVersion' compares (via 'Ord') as less than every proper+-- 'Version' value.+--+-- @since 2.0.0.2+nullVersion :: Version+-- TODO: at some point, 'mkVersion' may disallow creating /null/+-- 'Version's+nullVersion = PV0 0++-- | Apply function to list of version number components+--+-- > alterVersion f == mkVersion . f . versionNumbers+--+-- @since 2.0.0.2+alterVersion :: ([Int] -> [Int]) -> Version -> Version+alterVersion f = mkVersion . f . versionNumbers++-- internal helper+validVersion :: Version -> Bool+validVersion v = v /= nullVersion && all (>=0) (versionNumbers v)
+ src/Distribution/Types/VersionInterval.hs view
@@ -0,0 +1,345 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveDataTypeable #-}+-- | In @Cabal-3.6@ this module have been rewritten.+--+--+module Distribution.Types.VersionInterval (+ -- * Version intervals+ VersionIntervals,+ unVersionIntervals,++ -- * Conversions+ toVersionIntervals,+ fromVersionIntervals,++ -- ** Normalisation+ normaliseVersionRange2,++ -- * Relaxation+ relaxLastInterval,+ relaxHeadInterval,++ -- * Version intervals view+ asVersionIntervals,+ VersionInterval (..),+ LowerBound(..),+ UpperBound(..),+ Bound(..),++ -- * Invariants+ invariantVersionIntervals,+ ) where++import Control.Applicative (liftA2)+import Control.Exception (assert)+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Types.Version+import Distribution.Types.VersionRange.Internal++-- To test this module, and to run version range normalisation benchmarks:+--+-- cabal run Cabal:unit-tests -- -p Distribution.Version+-- cabal run cabal-benchmarks -- -o bench.html normaliseVersionRange++-------------------------------------------------------------------------------+-- Data+-------------------------------------------------------------------------------++-- | A complementary representation of a 'VersionRange'. Instead of a boolean+-- version predicate it uses an increasing sequence of non-overlapping,+-- non-empty intervals.+--+-- The key point is that this representation gives a canonical representation+-- for the semantics of 'VersionRange's. This makes it easier to check things+-- like whether a version range is empty, covers all versions, or requires a+-- certain minimum or maximum version. It also makes it easy to check equality+-- or containment. It also makes it easier to identify \'simple\' version+-- predicates for translation into foreign packaging systems that do not+-- support complex version range expressions.+--+newtype VersionIntervals = VersionIntervals [VersionInterval]+ deriving (Eq, Show, Typeable)++-- | Inspect the list of version intervals.+--+unVersionIntervals :: VersionIntervals -> [VersionInterval]+unVersionIntervals (VersionIntervals is) = is++data VersionInterval = VersionInterval !LowerBound !UpperBound deriving (Eq, Show)+data LowerBound = LowerBound !Version !Bound deriving (Eq, Show)+data UpperBound = NoUpperBound | UpperBound !Version !Bound deriving (Eq, Show)+data Bound = ExclusiveBound | InclusiveBound deriving (Eq, Show)++zeroLowerBound :: LowerBound+zeroLowerBound = LowerBound version0 InclusiveBound++isVersion0 :: Version -> Bool+isVersion0 = (==) version0++-------------------------------------------------------------------------------+-- Stage1+-------------------------------------------------------------------------------++stage1 :: VersionRange -> [VersionInterval]+stage1 = cataVersionRange alg where+ -- version range leafs transform into singleton intervals+ alg (ThisVersionF v) = [VersionInterval (LowerBound v InclusiveBound) (UpperBound v InclusiveBound)]+ alg (LaterVersionF v) = [VersionInterval (LowerBound v ExclusiveBound) NoUpperBound]+ alg (OrLaterVersionF v) = [VersionInterval (LowerBound v InclusiveBound) NoUpperBound]+ alg (EarlierVersionF v)+ | isVersion0 v = []+ | otherwise = [VersionInterval zeroLowerBound (UpperBound v ExclusiveBound)]+ alg (OrEarlierVersionF v) = [VersionInterval zeroLowerBound (UpperBound v InclusiveBound)]++ -- ^>= version-range's upper bound should be MajorBound+ alg (MajorBoundVersionF v) = [VersionInterval (LowerBound v InclusiveBound) (UpperBound (majorUpperBound v) ExclusiveBound)]++ -- union: just merge the version intervals+ alg (UnionVersionRangesF v1 v2) = v1 ++ v2++ -- intersection: pairwise intersect. Strip empty intervals. Sort to restore the invariant.+ alg (IntersectVersionRangesF v1 v2) = mapMaybe nonEmptyInterval $ liftA2 intersectInterval (stage2and3 v1) (stage2and3 v2)++-- | Creck that interval is non-empty+nonEmptyInterval :: VersionInterval -> Maybe VersionInterval+nonEmptyInterval i | nonEmptyVI i = Just i+nonEmptyInterval _ = Nothing++-------------------------------------------------------------------------------+-- Stage2+-------------------------------------------------------------------------------++stage2 :: [VersionInterval] -> [VersionInterval]+stage2 = sortBy lowerboundCmp++lowerboundCmp :: VersionInterval -> VersionInterval -> Ordering+lowerboundCmp (VersionInterval (LowerBound v vb) _) (VersionInterval (LowerBound u ub) _) =+ compare v u `mappend` compareBound vb ub+ where+ compareBound :: Bound -> Bound -> Ordering+ compareBound InclusiveBound InclusiveBound = EQ+ compareBound InclusiveBound ExclusiveBound = LT+ compareBound ExclusiveBound InclusiveBound = GT+ compareBound ExclusiveBound ExclusiveBound = EQ++-------------------------------------------------------------------------------+-- Postprocess+-------------------------------------------------------------------------------++-- | Post-processing takes a list of ordered version intervals,+-- but possibly overlapping, and creates 'VersionIntervals'.+--+postprocess :: [VersionInterval] -> VersionIntervals+postprocess = checkInvariant . VersionIntervals . stage2and3++stage2and3 :: [VersionInterval] -> [VersionInterval]+stage2and3 = stage3 . stage2++stage3 :: [VersionInterval] -> [VersionInterval]+stage3 [] = []+stage3 (VersionInterval lb ub : rest) = stage3go lb ub rest++stage3go :: LowerBound -> UpperBound -> [VersionInterval] -> [VersionInterval]+stage3go !lb NoUpperBound _ = [VersionInterval lb NoUpperBound]+stage3go !lb !ub [] = [VersionInterval lb ub]+stage3go !lb !ub (VersionInterval lb' ub' : rest')+ | doesNotTouch ub lb' = VersionInterval lb ub : stage3go lb' ub' rest'+ | otherwise = stage3go lb (unionUpper ub ub') rest'++-------------------------------------------------------------------------------+-- Intersections+-------------------------------------------------------------------------------++intersectInterval :: VersionInterval -> VersionInterval -> VersionInterval+intersectInterval (VersionInterval lv uv) (VersionInterval lu uu) =+ VersionInterval (intersectLower lv lu) (intersectUpper uv uu)++intersectLower :: LowerBound -> LowerBound -> LowerBound+intersectLower (LowerBound v vb) (LowerBound u ub) = case compare v u of+ EQ -> LowerBound v (intersectBound vb ub)+ LT -> LowerBound u ub+ GT -> LowerBound v vb++intersectUpper :: UpperBound -> UpperBound -> UpperBound+intersectUpper NoUpperBound b = b+intersectUpper b NoUpperBound = b+intersectUpper (UpperBound v vb) (UpperBound u ub) = case compare v u of+ EQ -> UpperBound v (intersectBound vb ub)+ LT -> UpperBound v vb+ GT -> UpperBound u ub++intersectBound :: Bound -> Bound -> Bound+intersectBound InclusiveBound InclusiveBound = InclusiveBound+intersectBound _ _ = ExclusiveBound++-------------------------------------------------------------------------------+-- Unions+-------------------------------------------------------------------------------++unionUpper :: UpperBound -> UpperBound -> UpperBound+unionUpper NoUpperBound _ = NoUpperBound+unionUpper _ NoUpperBound = NoUpperBound+unionUpper (UpperBound v vb) (UpperBound u ub) = case compare v u of+ EQ -> UpperBound v (unionBound vb ub)+ LT -> UpperBound u ub+ GT -> UpperBound v vb++unionBound :: Bound -> Bound -> Bound+unionBound ExclusiveBound ExclusiveBound = ExclusiveBound+unionBound _ _ = InclusiveBound++-------------------------------------------------------------------------------+-- VersionRange+-------------------------------------------------------------------------------++-- | View a 'VersionRange' as a union of intervals.+--+-- This provides a canonical view of the semantics of a 'VersionRange' as+-- opposed to the syntax of the expression used to define it. For the syntactic+-- view use 'foldVersionRange'.+--+-- Each interval is non-empty. The sequence is in increasing order and no+-- intervals overlap or touch. Therefore only the first and last can be+-- unbounded. The sequence can be empty if the range is empty+-- (e.g. a range expression like @< 1 && > 2@).+--+-- Other checks are trivial to implement using this view. For example:+--+-- > isNoVersion vr | [] <- asVersionIntervals vr = True+-- > | otherwise = False+--+-- > isSpecificVersion vr+-- > | [(LowerBound v InclusiveBound+-- > ,UpperBound v' InclusiveBound)] <- asVersionIntervals vr+-- > , v == v' = Just v+-- > | otherwise = Nothing+--+asVersionIntervals :: VersionRange -> [VersionInterval]+asVersionIntervals = unVersionIntervals . toVersionIntervals++-------------------------------------------------------------------------------+-- Helpers+-------------------------------------------------------------------------------++-- | Check an upper bound does not intersect, or even touch a lower bound:+--+-- @+-- ---| or ---) but not ---] or ---) or ---]+-- |--- (--- (--- [--- [---+-- @+--+doesNotTouch :: UpperBound -> LowerBound -> Bool+doesNotTouch NoUpperBound _ = False+doesNotTouch (UpperBound u ub) (LowerBound l lb) =+ (u < l) || (u == l && ub == ExclusiveBound && lb == ExclusiveBound)++-------------------------------------------------------------------------------+-- Invariants+-------------------------------------------------------------------------------++-- | 'VersionIntervals' invariant:+--+-- * all intervals are valid (lower bound is less then upper bound, i.e. non-empty)+-- * intervals doesn't touch each other (distinct)+--+invariantVersionIntervals :: VersionIntervals -> Bool+invariantVersionIntervals (VersionIntervals intervals) =+ all validInterval intervals &&+ all doesNotTouch' adjacentIntervals+ where+ doesNotTouch' :: (VersionInterval, VersionInterval) -> Bool+ doesNotTouch' (VersionInterval _ u, VersionInterval l' _) = doesNotTouch u l'++ adjacentIntervals :: [(VersionInterval, VersionInterval)]+ adjacentIntervals = case intervals of+ [] -> []+ (_:tl) -> zip intervals tl++checkInvariant :: VersionIntervals -> VersionIntervals+checkInvariant is = assert (invariantVersionIntervals is) is+{-# INLINE checkInvariant #-}++validInterval :: VersionInterval -> Bool+validInterval i@(VersionInterval l u) = validLower l && validUpper u && nonEmptyVI i+ where+ validLower (LowerBound v _) = validVersion v+ validUpper NoUpperBound = True+ validUpper (UpperBound v _) = validVersion v++-- Check an interval is non-empty+--+nonEmptyVI :: VersionInterval -> Bool+nonEmptyVI (VersionInterval _ NoUpperBound) = True+nonEmptyVI (VersionInterval (LowerBound l lb) (UpperBound u ub)) =+ (l < u) || (l == u && lb == InclusiveBound && ub == InclusiveBound)++-------------------------------------------------------------------------------+-- Conversions+-------------------------------------------------------------------------------++-- | Convert a 'VersionRange' to a sequence of version intervals.+--+toVersionIntervals :: VersionRange -> VersionIntervals+toVersionIntervals = postprocess . stage1++-- | Convert a 'VersionIntervals' value back into a 'VersionRange' expression+-- representing the version intervals.+--+fromVersionIntervals :: VersionIntervals -> VersionRange+fromVersionIntervals (VersionIntervals []) = noVersion+fromVersionIntervals (VersionIntervals (x:xs)) = foldr1 unionVersionRanges (fmap intervalToVersionRange (x:|xs))++intervalToVersionRange :: VersionInterval -> VersionRange+intervalToVersionRange (VersionInterval (LowerBound v vb) upper') = case upper' of+ NoUpperBound+ -> lowerBound++ UpperBound u ub+ | vb == InclusiveBound+ , ub == InclusiveBound+ , v == u+ -> thisVersion v++ UpperBound u ub -> withLowerBound (makeUpperBound u ub)+ where+ lowerBound :: VersionRange+ lowerBound = case vb of+ InclusiveBound -> orLaterVersion v+ ExclusiveBound -> laterVersion v++ withLowerBound :: VersionRange -> VersionRange+ withLowerBound vr+ | isVersion0 v, vb == InclusiveBound = vr+ | otherwise = intersectVersionRanges lowerBound vr++ makeUpperBound :: Version -> Bound -> VersionRange+ makeUpperBound u InclusiveBound = orEarlierVersion u+ makeUpperBound u ExclusiveBound = earlierVersion u++-------------------------------------------------------------------------------+-- Normalisation+-------------------------------------------------------------------------------++-- | Since @Cabal-3.6@ this function.. TODO+--+normaliseVersionRange2 :: VersionRange -> VersionRange+normaliseVersionRange2 = fromVersionIntervals . toVersionIntervals++-------------------------------------------------------------------------------+-- Relaxation+-------------------------------------------------------------------------------++relaxLastInterval :: VersionIntervals -> VersionIntervals+relaxLastInterval (VersionIntervals xs) = VersionIntervals (relaxLastInterval' xs)+ where+ relaxLastInterval' [] = []+ relaxLastInterval' [VersionInterval l _] = [VersionInterval l NoUpperBound]+ relaxLastInterval' (i:is) = i : relaxLastInterval' is++relaxHeadInterval :: VersionIntervals -> VersionIntervals+relaxHeadInterval (VersionIntervals xs) = VersionIntervals (relaxHeadInterval' xs)+ where+ relaxHeadInterval' [] = []+ relaxHeadInterval' (VersionInterval _ u : is) = VersionInterval zeroLowerBound u : is
+ src/Distribution/Types/VersionInterval/Legacy.hs view
@@ -0,0 +1,368 @@+{-# LANGUAGE DeriveDataTypeable #-}+-- | This is old version of "Distribution.Types.VersionInterval" module.+--+-- It will be removed in @Cabal-3.8@.+--+module Distribution.Types.VersionInterval.Legacy {-# DEPRECATED "Use Distribution.Types.VersionInterval instead" #-} (+ -- * Version intervals+ VersionIntervals,+ toVersionIntervals,+ fromVersionIntervals,+ withinIntervals,+ versionIntervals,+ mkVersionIntervals,+ unionVersionIntervals,+ intersectVersionIntervals,+ invertVersionIntervals,+ relaxLastInterval,+ relaxHeadInterval,++ -- * Version intervals view+ asVersionIntervals,+ VersionInterval,+ LowerBound(..),+ UpperBound(..),+ Bound(..),+ ) where++import Prelude ()+import Distribution.Compat.Prelude+import Control.Exception (assert)++import Distribution.Types.Version+import Distribution.Types.VersionRange.Internal++-- NonEmpty+import qualified Prelude (foldr1)++-------------------------------------------------------------------------------+-- VersionRange+-------------------------------------------------------------------------------++-- | View a 'VersionRange' as a union of intervals.+--+-- This provides a canonical view of the semantics of a 'VersionRange' as+-- opposed to the syntax of the expression used to define it. For the syntactic+-- view use 'foldVersionRange'.+--+-- Each interval is non-empty. The sequence is in increasing order and no+-- intervals overlap or touch. Therefore only the first and last can be+-- unbounded. The sequence can be empty if the range is empty+-- (e.g. a range expression like @< 1 && > 2@).+--+-- Other checks are trivial to implement using this view. For example:+--+-- > isNoVersion vr | [] <- asVersionIntervals vr = True+-- > | otherwise = False+--+-- > isSpecificVersion vr+-- > | [(LowerBound v InclusiveBound+-- > ,UpperBound v' InclusiveBound)] <- asVersionIntervals vr+-- > , v == v' = Just v+-- > | otherwise = Nothing+--+asVersionIntervals :: VersionRange -> [VersionInterval]+asVersionIntervals = versionIntervals . toVersionIntervals+++-------------------------------------------------------------------------------+-- VersionInterval+-------------------------------------------------------------------------------++-- | A complementary representation of a 'VersionRange'. Instead of a boolean+-- version predicate it uses an increasing sequence of non-overlapping,+-- non-empty intervals.+--+-- The key point is that this representation gives a canonical representation+-- for the semantics of 'VersionRange's. This makes it easier to check things+-- like whether a version range is empty, covers all versions, or requires a+-- certain minimum or maximum version. It also makes it easy to check equality+-- or containment. It also makes it easier to identify \'simple\' version+-- predicates for translation into foreign packaging systems that do not+-- support complex version range expressions.+--+newtype VersionIntervals = VersionIntervals [VersionInterval]+ deriving (Eq, Show, Typeable)++-- | Inspect the list of version intervals.+--+versionIntervals :: VersionIntervals -> [VersionInterval]+versionIntervals (VersionIntervals is) = is++type VersionInterval = (LowerBound, UpperBound)+data LowerBound = LowerBound Version !Bound deriving (Eq, Show)+data UpperBound = NoUpperBound | UpperBound Version !Bound deriving (Eq, Show)+data Bound = ExclusiveBound | InclusiveBound deriving (Eq, Show)++minLowerBound :: LowerBound+minLowerBound = LowerBound (mkVersion [0]) InclusiveBound++isVersion0 :: Version -> Bool+isVersion0 = (==) version0++instance Ord LowerBound where+ LowerBound ver bound <= LowerBound ver' bound' = case compare ver ver' of+ LT -> True+ EQ -> not (bound == ExclusiveBound && bound' == InclusiveBound)+ GT -> False++instance Ord UpperBound where+ _ <= NoUpperBound = True+ NoUpperBound <= UpperBound _ _ = False+ UpperBound ver bound <= UpperBound ver' bound' = case compare ver ver' of+ LT -> True+ EQ -> not (bound == InclusiveBound && bound' == ExclusiveBound)+ GT -> False++invariant :: VersionIntervals -> Bool+invariant (VersionIntervals intervals) = all validInterval intervals+ && all doesNotTouch' adjacentIntervals+ where+ doesNotTouch' :: (VersionInterval, VersionInterval) -> Bool+ doesNotTouch' ((_,u), (l',_)) = doesNotTouch u l'++ adjacentIntervals :: [(VersionInterval, VersionInterval)]+ adjacentIntervals = case intervals of+ [] -> []+ (_:tl) -> zip intervals tl++checkInvariant :: VersionIntervals -> VersionIntervals+checkInvariant is = assert (invariant is) is++-- | Directly construct a 'VersionIntervals' from a list of intervals.+--+-- In @Cabal-2.2@ the 'Maybe' is dropped from the result type.+--+mkVersionIntervals :: [VersionInterval] -> VersionIntervals+mkVersionIntervals intervals+ | invariant (VersionIntervals intervals) = VersionIntervals intervals+ | otherwise+ = checkInvariant+ . foldl' (flip insertInterval) (VersionIntervals [])+ . filter validInterval+ $ intervals++insertInterval :: VersionInterval -> VersionIntervals -> VersionIntervals+insertInterval i is = unionVersionIntervals (VersionIntervals [i]) is++validInterval :: (LowerBound, UpperBound) -> Bool+validInterval i@(l, u) = validLower l && validUpper u && nonEmptyVI i+ where+ validLower (LowerBound v _) = validVersion v+ validUpper NoUpperBound = True+ validUpper (UpperBound v _) = validVersion v++-- Check an interval is non-empty+--+nonEmptyVI :: VersionInterval -> Bool+nonEmptyVI (_, NoUpperBound ) = True+nonEmptyVI (LowerBound l lb, UpperBound u ub) =+ (l < u) || (l == u && lb == InclusiveBound && ub == InclusiveBound)++-- Check an upper bound does not intersect, or even touch a lower bound:+--+-- ---| or ---) but not ---] or ---) or ---]+-- |--- (--- (--- [--- [---+--+doesNotTouch :: UpperBound -> LowerBound -> Bool+doesNotTouch NoUpperBound _ = False+doesNotTouch (UpperBound u ub) (LowerBound l lb) =+ u < l+ || (u == l && ub == ExclusiveBound && lb == ExclusiveBound)++-- | Check an upper bound does not intersect a lower bound:+--+-- ---| or ---) or ---] or ---) but not ---]+-- |--- (--- (--- [--- [---+--+doesNotIntersect :: UpperBound -> LowerBound -> Bool+doesNotIntersect NoUpperBound _ = False+doesNotIntersect (UpperBound u ub) (LowerBound l lb) =+ u < l+ || (u == l && not (ub == InclusiveBound && lb == InclusiveBound))++-- | Test if a version falls within the version intervals.+--+-- It exists mostly for completeness and testing. It satisfies the following+-- properties:+--+-- > withinIntervals v (toVersionIntervals vr) = withinRange v vr+-- > withinIntervals v ivs = withinRange v (fromVersionIntervals ivs)+--+withinIntervals :: Version -> VersionIntervals -> Bool+withinIntervals v (VersionIntervals intervals) = any withinInterval intervals+ where+ withinInterval (lowerBound, upperBound) = withinLower lowerBound+ && withinUpper upperBound+ withinLower (LowerBound v' ExclusiveBound) = v' < v+ withinLower (LowerBound v' InclusiveBound) = v' <= v++ withinUpper NoUpperBound = True+ withinUpper (UpperBound v' ExclusiveBound) = v' > v+ withinUpper (UpperBound v' InclusiveBound) = v' >= v++-- | Convert a 'VersionRange' to a sequence of version intervals.+--+toVersionIntervals :: VersionRange -> VersionIntervals+toVersionIntervals = cataVersionRange alg where+ alg (ThisVersionF v) = chkIvl (LowerBound v InclusiveBound, UpperBound v InclusiveBound)+ alg (LaterVersionF v) = chkIvl (LowerBound v ExclusiveBound, NoUpperBound)+ alg (OrLaterVersionF v) = chkIvl (LowerBound v InclusiveBound, NoUpperBound)+ alg (EarlierVersionF v)+ | isVersion0 v = VersionIntervals []+ | otherwise = chkIvl (minLowerBound, UpperBound v ExclusiveBound)+ alg (OrEarlierVersionF v) = chkIvl (minLowerBound, UpperBound v InclusiveBound)+ alg (MajorBoundVersionF v) = chkIvl (LowerBound v InclusiveBound, UpperBound (majorUpperBound v) ExclusiveBound)+ alg (UnionVersionRangesF v1 v2) = unionVersionIntervals v1 v2+ alg (IntersectVersionRangesF v1 v2) = intersectVersionIntervals v1 v2++ chkIvl interval = checkInvariant (VersionIntervals [interval])++-- | Convert a 'VersionIntervals' value back into a 'VersionRange' expression+-- representing the version intervals.+--+fromVersionIntervals :: VersionIntervals -> VersionRange+fromVersionIntervals (VersionIntervals []) = noVersion+fromVersionIntervals (VersionIntervals intervals) =+ Prelude.foldr1 unionVersionRanges [ interval l u | (l, u) <- intervals ]++ where+ interval (LowerBound v InclusiveBound)+ (UpperBound v' InclusiveBound) | v == v'+ = thisVersion v+ interval l u = lowerBound l `intersectVersionRanges'` upperBound u++ lowerBound (LowerBound v InclusiveBound)+ | isVersion0 v = Nothing+ | otherwise = Just (orLaterVersion v)+ lowerBound (LowerBound v ExclusiveBound) = Just (laterVersion v)++ upperBound NoUpperBound = Nothing+ upperBound (UpperBound v InclusiveBound) = Just (orEarlierVersion v)+ upperBound (UpperBound v ExclusiveBound) = Just (earlierVersion v)++ intersectVersionRanges' Nothing Nothing = anyVersion+ intersectVersionRanges' (Just vr) Nothing = vr+ intersectVersionRanges' Nothing (Just vr) = vr+ intersectVersionRanges' (Just vr) (Just vr') = intersectVersionRanges vr vr'++unionVersionIntervals :: VersionIntervals -> VersionIntervals+ -> VersionIntervals+unionVersionIntervals (VersionIntervals is0) (VersionIntervals is'0) =+ checkInvariant (VersionIntervals (union is0 is'0))+ where+ union is [] = is+ union [] is' = is'+ union (i:is) (i':is') = case unionInterval i i' of+ Left Nothing -> i : union is (i' :is')+ Left (Just i'') -> union is (i'':is')+ Right Nothing -> i' : union (i :is) is'+ Right (Just i'') -> union (i'':is) is'++unionInterval :: VersionInterval -> VersionInterval+ -> Either (Maybe VersionInterval) (Maybe VersionInterval)+unionInterval (lower , upper ) (lower', upper')++ -- Non-intersecting intervals with the left interval ending first+ | upper `doesNotTouch` lower' = Left Nothing++ -- Non-intersecting intervals with the right interval first+ | upper' `doesNotTouch` lower = Right Nothing++ -- Complete or partial overlap, with the left interval ending first+ | upper <= upper' = lowerBound `seq`+ Left (Just (lowerBound, upper'))++ -- Complete or partial overlap, with the left interval ending first+ | otherwise = lowerBound `seq`+ Right (Just (lowerBound, upper))+ where+ lowerBound = min lower lower'++intersectVersionIntervals :: VersionIntervals -> VersionIntervals+ -> VersionIntervals+intersectVersionIntervals (VersionIntervals is0) (VersionIntervals is'0) =+ checkInvariant (VersionIntervals (intersect is0 is'0))+ where+ intersect _ [] = []+ intersect [] _ = []+ intersect (i:is) (i':is') = case intersectInterval i i' of+ Left Nothing -> intersect is (i':is')+ Left (Just i'') -> i'' : intersect is (i':is')+ Right Nothing -> intersect (i:is) is'+ Right (Just i'') -> i'' : intersect (i:is) is'++intersectInterval :: VersionInterval -> VersionInterval+ -> Either (Maybe VersionInterval) (Maybe VersionInterval)+intersectInterval (lower , upper ) (lower', upper')++ -- Non-intersecting intervals with the left interval ending first+ | upper `doesNotIntersect` lower' = Left Nothing++ -- Non-intersecting intervals with the right interval first+ | upper' `doesNotIntersect` lower = Right Nothing++ -- Complete or partial overlap, with the left interval ending first+ | upper <= upper' = lowerBound `seq`+ Left (Just (lowerBound, upper))++ -- Complete or partial overlap, with the right interval ending first+ | otherwise = lowerBound `seq`+ Right (Just (lowerBound, upper'))+ 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 (mkVersion [0]) InclusiveBound+++relaxLastInterval :: VersionIntervals -> VersionIntervals+relaxLastInterval (VersionIntervals xs) = VersionIntervals (relaxLastInterval' xs)+ where+ relaxLastInterval' [] = []+ relaxLastInterval' [(l,_)] = [(l, NoUpperBound)]+ relaxLastInterval' (i:is) = i : relaxLastInterval' is++relaxHeadInterval :: VersionIntervals -> VersionIntervals+relaxHeadInterval (VersionIntervals xs) = VersionIntervals (relaxHeadInterval' xs)+ where+ relaxHeadInterval' [] = []+ relaxHeadInterval' ((_,u):is) = (minLowerBound,u) : is
+ src/Distribution/Types/VersionRange.hs view
@@ -0,0 +1,180 @@+module Distribution.Types.VersionRange (+ -- * Version ranges+ VersionRange,++ -- ** Constructing+ anyVersion, noVersion,+ thisVersion, notThisVersion,+ laterVersion, earlierVersion,+ orLaterVersion, orEarlierVersion,+ unionVersionRanges, intersectVersionRanges,+ withinVersion,+ majorBoundVersion,++ -- ** Inspection+ --+ -- See "Distribution.Version" for more utilities.+ withinRange,+ foldVersionRange,+ normaliseVersionRange,+ stripParensVersionRange,+ hasUpperBound,+ hasLowerBound,++ -- ** Cata & ana+ VersionRangeF (..),+ cataVersionRange,+ anaVersionRange,+ hyloVersionRange,+ projectVersionRange,+ embedVersionRange,++ -- ** Utilities+ isAnyVersion,+ isAnyVersionLight,+ wildcardUpperBound,+ majorUpperBound,+ isWildcardRange,+ versionRangeParser,+ ) where++import Distribution.Compat.Prelude+import Distribution.Types.Version+import Distribution.Types.VersionInterval+import Distribution.Types.VersionRange.Internal+import Prelude ()++-- | Fold over the basic syntactic structure of a 'VersionRange'.+--+-- This provides a syntactic view of the expression defining the version range.+-- The syntactic sugar @\">= v\"@, @\"<= v\"@ and @\"== v.*\"@ is presented+-- in terms of the other basic syntax.+--+-- For a semantic view use 'asVersionIntervals'.+--+foldVersionRange :: a -- ^ @\"-any\"@ version+ -> (Version -> a) -- ^ @\"== v\"@+ -> (Version -> a) -- ^ @\"> v\"@+ -> (Version -> a) -- ^ @\"< v\"@+ -> (a -> a -> a) -- ^ @\"_ || _\"@ union+ -> (a -> a -> a) -- ^ @\"_ && _\"@ intersection+ -> VersionRange -> a+foldVersionRange _any this later earlier union intersect = fold+ where+ fold = cataVersionRange alg++ alg (ThisVersionF v) = this v+ alg (LaterVersionF v) = later v+ alg (OrLaterVersionF v) = union (this v) (later v)+ alg (EarlierVersionF v) = earlier v+ alg (OrEarlierVersionF v) = union (this v) (earlier v)+ alg (MajorBoundVersionF v) = fold (majorBound v)+ alg (UnionVersionRangesF v1 v2) = union v1 v2+ alg (IntersectVersionRangesF v1 v2) = intersect v1 v2++ majorBound v = intersectVersionRanges+ (orLaterVersion v)+ (earlierVersion (majorUpperBound v))++-- | Normalise 'VersionRange'.+--+-- In particular collapse @(== v || > v)@ into @>= v@, and so on.+normaliseVersionRange :: VersionRange -> VersionRange+normaliseVersionRange = hyloVersionRange embed projectVersionRange+ where+ -- == v || > v, > v || == v ==> >= v+ embed (UnionVersionRangesF (ThisVersion v) (LaterVersion v')) | v == v' =+ orLaterVersion v+ embed (UnionVersionRangesF (LaterVersion v) (ThisVersion v')) | v == v' =+ orLaterVersion v++ -- == v || < v, < v || == v ==> <= v+ embed (UnionVersionRangesF (ThisVersion v) (EarlierVersion v')) | v == v' =+ orEarlierVersion v+ embed (UnionVersionRangesF (EarlierVersion v) (ThisVersion v')) | v == v' =+ orEarlierVersion v++ -- otherwise embed normally+ embed vr = embedVersionRange vr++-- | Remove 'VersionRangeParens' constructors.+--+-- Since version 3.4 this function is 'id', there aren't 'VersionRangeParens' constructor in 'VersionRange' anymore.+--+-- @since 2.2+stripParensVersionRange :: VersionRange -> VersionRange+stripParensVersionRange = id++-- | Does this version fall within the given range?+--+-- This is the evaluation function for the 'VersionRange' type.+--+withinRange :: Version -> VersionRange -> Bool+withinRange v = foldVersionRange+ True+ (\v' -> v == v')+ (\v' -> v > v')+ (\v' -> v < v')+ (||)+ (&&)++-- | Does this 'VersionRange' place any restriction on the 'Version' or is it+-- in fact equivalent to 'AnyVersion'.+--+-- Note this is a semantic check, not simply a syntactic check. So for example+-- the following is @True@ (for all @v@).+--+-- > isAnyVersion (EarlierVersion v `UnionVersionRanges` orLaterVersion v)+--+isAnyVersion :: VersionRange -> Bool+isAnyVersion vr = case asVersionIntervals vr of+ [VersionInterval (LowerBound v InclusiveBound) NoUpperBound] -> v == version0+ _ -> False++-- A fast and non-precise version of 'isAnyVersion',+-- returns 'True' only for @>= 0@ 'VersionRange's.+--+-- /Do not use/. The "VersionIntervals don't destroy MajorBoundVersion"+-- https://github.com/haskell/cabal/pull/6736 pull-request+-- will change 'simplifyVersionRange' to properly preserve semantics.+-- Then we can use it to normalise 'VersionRange's in tests.+--+isAnyVersionLight :: VersionRange -> Bool+isAnyVersionLight (OrLaterVersion v) = v == version0+isAnyVersionLight _vr = False++----------------------------+-- Wildcard range utilities+--+++isWildcardRange :: Version -> Version -> Bool+isWildcardRange ver1 ver2 = check (versionNumbers ver1) (versionNumbers ver2)+ where check (n:[]) (m:[]) | n+1 == m = True+ check (n:ns) (m:ms) | n == m = check ns ms+ check _ _ = False++-- | 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)+ (&&) (||)
+ src/Distribution/Types/VersionRange/Internal.hs view
@@ -0,0 +1,526 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- | The only purpose of this module is to prevent the export of+-- 'VersionRange' constructors from+-- 'Distribution.Types.VersionRange'. To avoid creating orphan+-- instances, a lot of related code had to be moved here too.++module Distribution.Types.VersionRange.Internal+ ( VersionRange(..)+ , anyVersion, noVersion+ , thisVersion, notThisVersion+ , laterVersion, earlierVersion+ , orLaterVersion, orEarlierVersion+ , unionVersionRanges, intersectVersionRanges+ , withinVersion+ , majorBoundVersion++ , VersionRangeF(..)+ , projectVersionRange+ , embedVersionRange+ , cataVersionRange+ , anaVersionRange+ , hyloVersionRange+ , versionRangeParser++ , majorUpperBound+ , wildcardUpperBound+ ) where++import Distribution.Compat.Prelude+import Distribution.Types.Version+import Prelude ()++import Distribution.CabalSpecVersion+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Utils.Generic (unsnoc)++import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.Compat.DList as DList+import qualified Text.PrettyPrint as Disp++data VersionRange+ = ThisVersion Version -- = version+ | LaterVersion Version -- > version (NB. not >=)+ | OrLaterVersion Version -- >= version+ | EarlierVersion Version -- < version+ | OrEarlierVersion Version -- <= version+ | MajorBoundVersion Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1)+ | UnionVersionRanges VersionRange VersionRange+ | IntersectVersionRanges VersionRange VersionRange+ deriving ( Data, Eq, Generic, Read, Show, Typeable )++instance Binary VersionRange+instance Structured VersionRange+instance NFData VersionRange where rnf = genericRnf++-- | The version range @-any@. That is, a version range containing all+-- versions.+--+-- > withinRange v anyVersion = True+--+anyVersion :: VersionRange+anyVersion = OrLaterVersion (mkVersion [0])++-- | The empty version range, that is a version range containing no versions.+--+-- This can be constructed using any unsatisfiable version range expression,+-- for example @< 0@.+--+-- > withinRange v noVersion = False+--+noVersion :: VersionRange+noVersion = EarlierVersion (mkVersion [0])++-- | The version range @== v@+--+-- > withinRange v' (thisVersion v) = v' == v+--+thisVersion :: Version -> VersionRange+thisVersion = ThisVersion++-- | The version range @< v || > v@+--+-- > withinRange v' (notThisVersion v) = v' /= v+--+notThisVersion :: Version -> VersionRange+notThisVersion v = UnionVersionRanges (EarlierVersion v) (LaterVersion v)++-- | The version range @> v@+--+-- > withinRange v' (laterVersion v) = v' > v+--+laterVersion :: Version -> VersionRange+laterVersion = LaterVersion++-- | The version range @>= v@+--+-- > withinRange v' (orLaterVersion v) = v' >= v+--+orLaterVersion :: Version -> VersionRange+orLaterVersion = OrLaterVersion++-- | The version range @< v@+--+-- > withinRange v' (earlierVersion v) = v' < v+--+earlierVersion :: Version -> VersionRange+earlierVersion = EarlierVersion++-- | The version range @<= v@+--+-- > withinRange v' (orEarlierVersion v) = v' <= v+--+orEarlierVersion :: Version -> VersionRange+orEarlierVersion = OrEarlierVersion++-- | The version range @vr1 || vr2@+--+-- > withinRange v' (unionVersionRanges vr1 vr2)+-- > = withinRange v' vr1 || withinRange v' vr2+--+unionVersionRanges :: VersionRange -> VersionRange -> VersionRange+unionVersionRanges = UnionVersionRanges++-- | The version range @vr1 && vr2@+--+-- > withinRange v' (intersectVersionRanges vr1 vr2)+-- > = withinRange v' vr1 && withinRange v' vr2+--+intersectVersionRanges :: VersionRange -> VersionRange -> VersionRange+intersectVersionRanges = IntersectVersionRanges++-- | The version range @== v.*@.+--+-- For example, for version @1.2@, the version range @== 1.2.*@ is the same as+-- @>= 1.2 && < 1.3@+--+-- > withinRange v' (laterVersion v) = v' >= v && v' < upper v+-- > where+-- > upper (Version lower t) = Version (init lower ++ [last lower + 1]) t+--+withinVersion :: Version -> VersionRange+withinVersion v = intersectVersionRanges+ (orLaterVersion v)+ (earlierVersion (wildcardUpperBound v))++-- | The version range @^>= v@.+--+-- For example, for version @1.2.3.4@, the version range @^>= 1.2.3.4@+-- is the same as @>= 1.2.3.4 && < 1.3@.+--+-- Note that @^>= 1@ is equivalent to @>= 1 && < 1.1@.+--+-- @since 2.0.0.2+majorBoundVersion :: Version -> VersionRange+majorBoundVersion = MajorBoundVersion+++-- | F-Algebra of 'VersionRange'. See 'cataVersionRange'.+--+-- @since 2.2+data VersionRangeF a+ = ThisVersionF Version -- = version+ | LaterVersionF Version -- > version (NB. not >=)+ | OrLaterVersionF Version -- >= version+ | EarlierVersionF Version -- < version+ | OrEarlierVersionF Version -- <= version+ | MajorBoundVersionF Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1)+ | UnionVersionRangesF a a+ | IntersectVersionRangesF a a+ deriving ( Data, Eq, Generic, Read, Show, Typeable+ , Functor, Foldable, Traversable )++-- | @since 2.2+projectVersionRange :: VersionRange -> VersionRangeF VersionRange+projectVersionRange (ThisVersion v) = ThisVersionF v+projectVersionRange (LaterVersion v) = LaterVersionF v+projectVersionRange (OrLaterVersion v) = OrLaterVersionF v+projectVersionRange (EarlierVersion v) = EarlierVersionF v+projectVersionRange (OrEarlierVersion v) = OrEarlierVersionF v+projectVersionRange (MajorBoundVersion v) = MajorBoundVersionF v+projectVersionRange (UnionVersionRanges a b) = UnionVersionRangesF a b+projectVersionRange (IntersectVersionRanges a b) = IntersectVersionRangesF a b++-- | Fold 'VersionRange'.+--+-- @since 2.2+cataVersionRange :: (VersionRangeF a -> a) -> VersionRange -> a+cataVersionRange f = c where c = f . fmap c . projectVersionRange++-- | @since 2.2+embedVersionRange :: VersionRangeF VersionRange -> VersionRange+embedVersionRange (ThisVersionF v) = ThisVersion v+embedVersionRange (LaterVersionF v) = LaterVersion v+embedVersionRange (OrLaterVersionF v) = OrLaterVersion v+embedVersionRange (EarlierVersionF v) = EarlierVersion v+embedVersionRange (OrEarlierVersionF v) = OrEarlierVersion v+embedVersionRange (MajorBoundVersionF v) = MajorBoundVersion v+embedVersionRange (UnionVersionRangesF a b) = UnionVersionRanges a b+embedVersionRange (IntersectVersionRangesF a b) = IntersectVersionRanges a b++-- | Unfold 'VersionRange'.+--+-- @since 2.2+anaVersionRange :: (a -> VersionRangeF a) -> a -> VersionRange+anaVersionRange g = a where a = embedVersionRange . fmap a . g++-- | Refold 'VersionRange'+--+-- @since 2.2+hyloVersionRange :: (VersionRangeF VersionRange -> VersionRange)+ -> (VersionRange -> VersionRangeF VersionRange)+ -> VersionRange -> VersionRange+hyloVersionRange f g = h where h = f . fmap h . g++-------------------------------------------------------------------------------+-- Parsec & Pretty+-------------------------------------------------------------------------------++-- |+--+-- >>> fmap pretty (simpleParsec' CabalSpecV1_6 "== 3.2.*" :: Maybe VersionRange)+-- Just >=3.2 && <3.3+--+-- >>> fmap (prettyVersioned CabalSpecV1_6) (simpleParsec' CabalSpecV1_6 "== 3.2.*" :: Maybe VersionRange)+-- Just ==3.2.*+--+-- >>> fmap pretty (simpleParsec' CabalSpecV1_6 "-any" :: Maybe VersionRange)+-- Just >=0+--+-- >>> fmap (prettyVersioned CabalSpecV1_6) (simpleParsec' CabalSpecV1_6 "-any" :: Maybe VersionRange)+-- Just >=0+--+instance Pretty VersionRange where+ pretty = prettyVersioned cabalSpecLatest++ prettyVersioned csv+ | csv > CabalSpecV1_6 = prettyVersionRange+ | otherwise = prettyVersionRange16++prettyVersionRange :: VersionRange -> Disp.Doc+prettyVersionRange vr = cataVersionRange alg vr 0+ where+ alg :: VersionRangeF (Int -> Disp.Doc) -> Int -> Disp.Doc+ alg (ThisVersionF v) _ = Disp.text "==" <<>> pretty v+ alg (LaterVersionF v) _ = Disp.text ">" <<>> pretty v+ alg (OrLaterVersionF v) _ = Disp.text ">=" <<>> pretty v+ alg (EarlierVersionF v) _ = Disp.text "<" <<>> pretty v+ alg (OrEarlierVersionF v) _ = Disp.text "<=" <<>> pretty v+ alg (MajorBoundVersionF v) _ = Disp.text "^>=" <<>> pretty v+ alg (UnionVersionRangesF r1 r2) d = parens (d > 0)+ $ r1 1 <+> Disp.text "||" <+> r2 0+ alg (IntersectVersionRangesF r1 r2) d = parens (d > 1)+ $ r1 2 <+> Disp.text "&&" <+> r2 1++ parens True = Disp.parens+ parens False = id++-- | Don't use && and || operators. If possible.+prettyVersionRange16 :: VersionRange -> Disp.Doc+prettyVersionRange16 (IntersectVersionRanges (OrLaterVersion v) (EarlierVersion u))+ | u == wildcardUpperBound v+ = Disp.text "==" <<>> dispWild v+ where+ dispWild ver =+ Disp.hcat (Disp.punctuate (Disp.char '.')+ (map Disp.int $ versionNumbers ver))+ <<>> Disp.text ".*"++prettyVersionRange16 vr = prettyVersionRange vr++-- |+--+-- >>> simpleParsec "^>= 3.4" :: Maybe VersionRange+-- Just (MajorBoundVersion (mkVersion [3,4]))+--+-- Small history:+--+-- @-any@ and @-none@ removed in 3.4+-- Use @>=0@ and @<0@ instead.+--+-- >>> map (`simpleParsec'` "-none") [CabalSpecV3_0, CabalSpecV3_4] :: [Maybe VersionRange]+-- [Just (EarlierVersion (mkVersion [0])),Nothing]+--+-- Set operations are introduced in 3.0+--+-- >>> map (`simpleParsec'` "^>= { 1.2 , 1.3 }") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe VersionRange]+-- [Nothing,Just (UnionVersionRanges (MajorBoundVersion (mkVersion [1,2])) (MajorBoundVersion (mkVersion [1,3])))]+--+-- @^>=@ is introduced in 2.0+--+-- >>> map (`simpleParsec'` "^>=1.2") [CabalSpecV1_24, CabalSpecV2_0] :: [Maybe VersionRange]+-- [Nothing,Just (MajorBoundVersion (mkVersion [1,2]))]+--+-- @-none@ is introduced in 1.22+--+-- >>> map (`simpleParsec'` "-none") [CabalSpecV1_20, CabalSpecV1_22] :: [Maybe VersionRange]+-- [Nothing,Just (EarlierVersion (mkVersion [0]))]+--+-- Operators are introduced in 1.8. Issues only a warning.+--+-- >>> map (`simpleParsecW'` "== 1 || ==2") [CabalSpecV1_6, CabalSpecV1_8] :: [Maybe VersionRange]+-- [Nothing,Just (UnionVersionRanges (ThisVersion (mkVersion [1])) (ThisVersion (mkVersion [2])))]+--+-- Wild-version ranges are introduced in 1.6. Issues only a warning.+--+-- >>> map (`simpleParsecW'` "== 1.2.*") [CabalSpecV1_4, CabalSpecV1_6] :: [Maybe VersionRange]+-- [Nothing,Just (IntersectVersionRanges (OrLaterVersion (mkVersion [1,2])) (EarlierVersion (mkVersion [1,3])))]+--+instance Parsec VersionRange where+ parsec = askCabalSpecVersion >>= versionRangeParser versionDigitParser++-- | 'VersionRange' parser parametrised by version digit parser+--+-- - 'versionDigitParser' is used for all 'VersionRange'.+-- - 'P.integral' is used for backward-compat @pkgconfig-depends@+-- versions, 'PkgConfigVersionRange'.+--+-- @since 3.0+versionRangeParser :: forall m. CabalParsing m => m Int -> CabalSpecVersion -> m VersionRange+versionRangeParser digitParser csv = expr+ where+ expr = do P.spaces+ t <- term+ P.spaces+ (do _ <- P.string "||"+ checkOp+ P.spaces+ e <- expr+ return (unionVersionRanges t e)+ <|>+ return t)+ term = do f <- factor+ P.spaces+ (do _ <- P.string "&&"+ checkOp+ P.spaces+ t <- term+ return (intersectVersionRanges f t)+ <|>+ return f)+ factor = parens expr <|> prim++ prim = do+ op <- P.munch1 isOpChar P.<?> "operator"+ case op of+ "-" -> anyVersion <$ P.string "any" <|> P.string "none" *> noVersion'++ "==" -> do+ P.spaces+ (do (wild, v) <- verOrWild+ checkWild wild+ pure $ (if wild then withinVersion else thisVersion) v+ <|>+ (verSet' thisVersion =<< verSet))++ "^>=" -> do+ P.spaces+ (do (wild, v) <- verOrWild+ when wild $ P.unexpected $+ "wild-card version after ^>= operator"+ majorBoundVersion' v+ <|>+ (verSet' majorBoundVersion =<< verSet))++ _ -> do+ P.spaces+ (wild, v) <- verOrWild+ when wild $ P.unexpected $+ "wild-card version after non-== operator: " ++ show op+ case op of+ ">=" -> pure $ orLaterVersion v+ "<" -> pure $ earlierVersion v+ "<=" -> pure $ orEarlierVersion v+ ">" -> pure $ laterVersion v+ _ -> fail $ "Unknown version operator " ++ show op++ -- Cannot be warning+ -- On 2020-03-16 there was around 27400 files on Hackage failing to parse due this+ -- For example https://hackage.haskell.org/package/haxr-3000.0.0/haxr.cabal+ --+ checkOp = when (csv < CabalSpecV1_8) $+ parsecWarning PWTVersionOperator $ unwords+ [ "version operators used."+ , "To use version operators the package needs to specify at least 'cabal-version: >= 1.8'."+ ]++ -- Cannot be warning+ -- On 2020-03-16 there was 46 files on Hackage failing to parse due this+ -- For example https://hackage.haskell.org/package/derive-0.1.2/derive.cabal+ --+ checkWild False = pure ()+ checkWild True = when (csv < CabalSpecV1_6) $+ parsecWarning PWTVersionWildcard $ unwords+ [ "Wildcard syntax used."+ , "To use version wildcards the package needs to specify at least 'cabal-version: >= 1.6'."+ ]++ -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isOpChar '<' = True+ isOpChar '=' = True+ isOpChar '>' = True+ isOpChar '^' = True+ isOpChar '-' = csv < CabalSpecV3_4+ -- https://github.com/haskell/cabal/issues/6589+ -- Unfortunately we have must not consume the dash,+ -- as otherwise following parts may not be parsed.+ --+ -- i.e. we cannot fail here with good error.+ isOpChar _ = False++ -- -none version range is available since 1.22+ noVersion' =+ if csv >= CabalSpecV1_22+ then pure noVersion+ else fail $ unwords+ [ "-none version range used."+ , "To use this syntax the package needs to specify at least 'cabal-version: 1.22'."+ , "Alternatively, if broader compatibility is important then use"+ , "<0 or other empty range."+ ]++ -- ^>= is available since 2.0+ majorBoundVersion' v =+ if csv >= CabalSpecV2_0+ then pure $ majorBoundVersion v+ else fail $ unwords+ [ "major bounded version syntax (caret, ^>=) used."+ , "To use this syntax the package need to specify at least 'cabal-version: 2.0'."+ , "Alternatively, if broader compatibility is important then use:"+ , prettyShow $ eliminateMajorBoundSyntax $ majorBoundVersion v+ ]+ where+ eliminateMajorBoundSyntax = hyloVersionRange embed projectVersionRange+ embed (MajorBoundVersionF u) = intersectVersionRanges+ (orLaterVersion u) (earlierVersion (majorUpperBound u))+ embed vr = embedVersionRange vr++ -- version set notation (e.g. "== { 0.0.1.0, 0.0.2.0, 0.1.0.0 }")+ verSet' op vs =+ if csv >= CabalSpecV3_0+ then pure $ foldr1 unionVersionRanges (fmap op vs)+ else fail $ unwords+ [ "version set syntax used."+ , "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."+ , "Alternatively, if broader compatibility is important then use"+ , "a series of single version constraints joined with the || operator:"+ , prettyShow (foldr1 unionVersionRanges (fmap op vs))+ ]++ verSet :: CabalParsing m => m (NonEmpty Version)+ verSet = do+ _ <- P.char '{'+ P.spaces+ vs <- P.sepByNonEmpty (verPlain <* P.spaces) (P.char ',' *> P.spaces)+ _ <- P.char '}'+ pure vs++ -- a plain version without tags or wildcards+ verPlain :: CabalParsing m => m Version+ verPlain = mkVersion <$> toList <$> P.sepByNonEmpty digitParser (P.char '.')++ -- either wildcard or normal version+ verOrWild :: CabalParsing m => m (Bool, Version)+ verOrWild = do+ x <- digitParser+ verLoop (DList.singleton x)++ -- trailing: wildcard (.y.*) or normal version (optional tags) (.y.z-tag)+ verLoop :: CabalParsing m => DList.DList Int -> m (Bool, Version)+ verLoop acc = verLoop' acc+ <|> (tags *> pure (False, mkVersion (DList.toList acc)))++ verLoop' :: CabalParsing m => DList.DList Int -> m (Bool, Version)+ verLoop' acc = do+ _ <- P.char '.'+ let digit = digitParser >>= verLoop . DList.snoc acc+ let wild = (True, mkVersion (DList.toList acc)) <$ P.char '*'+ digit <|> wild++ parens p = P.between+ ((P.char '(' P.<?> "opening paren") >> P.spaces)+ (P.char ')' >> P.spaces)+ $ do+ a <- p+ P.spaces+ return a++ tags :: CabalParsing m => m ()+ tags = do+ ts <- many $ P.char '-' *> some (P.satisfy isAlphaNum)+ case ts of+ [] -> pure ()+ (_ : _) -> parsecWarning PWTVersionTag "version with tags"+++----------------------------+-- Wildcard range utilities+--++-- | Compute next greater major version to be used as upper bound+--+-- Example: @0.4.1@ produces the version @0.5@ which then can be used+-- to construct a range @>= 0.4.1 && < 0.5@+--+-- @since 2.2+majorUpperBound :: Version -> Version+majorUpperBound = alterVersion $ \numbers -> case numbers of+ [] -> [0,1] -- should not happen+ [m1] -> [m1,1] -- e.g. version '1'+ (m1:m2:_) -> [m1,m2+1]++-- | @since 2.2+wildcardUpperBound :: Version -> Version+wildcardUpperBound = alterVersion $+ \lowerBound -> case unsnoc lowerBound of+ Nothing -> []+ Just (xs, x) -> xs ++ [x + 1]
+ src/Distribution/Utils/Base62.hs view
@@ -0,0 +1,22 @@++-- | Implementation of base-62 encoding, which we use when computing hashes+-- for fully instantiated unit ids.+module Distribution.Utils.Base62 (hashToBase62) where++import GHC.Fingerprint ( Fingerprint(..), fingerprintString )+import Numeric ( showIntAtBase )+import Data.Char ( chr )++-- | Hash a string using GHC's fingerprinting algorithm (a 128-bit+-- MD5 hash) and then encode the resulting hash in base 62.+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+
+ src/Distribution/Utils/Generic.hs view
@@ -0,0 +1,576 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE BangPatterns #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Simple.Utils+-- Copyright : Isaac Jones, Simon Marlow 2003-2004+-- License : BSD3+-- portions Copyright (c) 2007, Galois Inc.+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- A large and somewhat miscellaneous collection of utility functions used+-- throughout the rest of the Cabal lib and in other tools that use the Cabal+-- lib like @cabal-install@. It has a very simple set of logging actions. It+-- has low level functions for running programs, a bunch of wrappers for+-- various directory and file functions that do extra logging.++module Distribution.Utils.Generic (+ -- * reading and writing files safely+ withFileContents,+ writeFileAtomic,++ -- * Unicode++ -- ** Conversions+ fromUTF8BS,+ fromUTF8LBS,++ toUTF8BS,+ toUTF8LBS,++ validateUTF8,++ -- ** File I/O+ readUTF8File,+ withUTF8FileContents,+ writeUTF8File,++ -- ** BOM+ ignoreBOM,++ -- ** Misc+ normaliseLineEndings,++ -- * generic utils+ dropWhileEndLE,+ takeWhileEndLE,+ equating,+ comparing,+ isInfixOf,+ intercalate,+ lowercase,+ isAscii,+ isAsciiAlpha,+ isAsciiAlphaNum,+ listUnion,+ listUnionRight,+ ordNub,+ ordNubBy,+ ordNubRight,+ safeHead,+ safeTail,+ safeLast,+ safeInit,+ unintersperse,+ wrapText,+ wrapLine,+ unfoldrM,+ spanMaybe,+ breakMaybe,+ unsnoc,+ unsnocNE,++ -- * Triples+ fstOf3,+ sndOf3,+ trdOf3,++ -- * FilePath stuff+ isAbsoluteOnAnyPlatform,+ isRelativeOnAnyPlatform,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Utils.String++import Data.Bits ((.&.), (.|.), shiftL)+import Data.List+ ( isInfixOf )+import qualified Data.Set as Set+import qualified Data.ByteString as SBS+import qualified Data.ByteString.Lazy as LBS++import System.Directory+ ( removeFile, renameFile )+import System.FilePath+ ( (<.>), splitFileName )+import System.IO+ ( withFile, withBinaryFile+ , openBinaryTempFileWithDefaultPermissions+ , IOMode(ReadMode), hGetContents, hClose )+import qualified Control.Exception as Exception++-- -----------------------------------------------------------------------------+-- Helper functions++-- | Wraps text to the default line width. Existing newlines are preserved.+wrapText :: String -> String+wrapText = unlines+ . map (intercalate "\n"+ . map unwords+ . wrapLine 79+ . words)+ . lines++-- | Wraps a list of words to a list of lines of words of a particular width.+wrapLine :: Int -> [String] -> [[String]]+wrapLine width = wrap 0 []+ where wrap :: Int -> [String] -> [String] -> [[String]]+ wrap 0 [] (w:ws)+ | length w + 1 > width+ = wrap (length w) [w] ws+ wrap col line (w:ws)+ | col + length w + 1 > width+ = reverse line : wrap 0 [] (w:ws)+ wrap col line (w:ws)+ = let col' = col + length w + 1+ in wrap col' (w:line) ws+ wrap _ [] [] = []+ wrap _ line [] = [reverse line]++-----------------------------------+-- Safely reading and writing files++-- | Gets the contents of a file, but guarantee that it gets closed.+--+-- The file is read lazily but if it is not fully consumed by the action then+-- the remaining input is truncated and the file is closed.+--+withFileContents :: FilePath -> (String -> IO a) -> IO a+withFileContents name action =+ withFile name ReadMode+ (\hnd -> hGetContents hnd >>= action)++-- | Writes a file atomically.+--+-- The file is either written successfully or an IO exception is raised and+-- the original file is left unchanged.+--+-- On windows it is not possible to delete a file that is open by a process.+-- This case will give an IO exception but the atomic property is not affected.+--+writeFileAtomic :: FilePath -> LBS.ByteString -> IO ()+writeFileAtomic targetPath content = do+ let (targetDir, targetFile) = splitFileName targetPath+ Exception.bracketOnError+ (openBinaryTempFileWithDefaultPermissions targetDir $ targetFile <.> "tmp")+ (\(tmpPath, handle) -> hClose handle >> removeFile tmpPath)+ (\(tmpPath, handle) -> do+ LBS.hPut handle content+ hClose handle+ renameFile tmpPath targetPath)++-- ------------------------------------------------------------+-- * Unicode stuff+-- ------------------------------------------------------------++-- | Decode 'String' from UTF8-encoded 'BS.ByteString'+--+-- Invalid data in the UTF8 stream (this includes code-points @U+D800@+-- through @U+DFFF@) will be decoded as the replacement character (@U+FFFD@).+--+fromUTF8BS :: SBS.ByteString -> String+fromUTF8BS = decodeStringUtf8 . SBS.unpack++-- | Variant of 'fromUTF8BS' for lazy 'BS.ByteString's+--+fromUTF8LBS :: LBS.ByteString -> String+fromUTF8LBS = decodeStringUtf8 . LBS.unpack++-- | Encode 'String' to UTF8-encoded 'SBS.ByteString'+--+-- Code-points in the @U+D800@-@U+DFFF@ range will be encoded+-- as the replacement character (i.e. @U+FFFD@).+--+toUTF8BS :: String -> SBS.ByteString+toUTF8BS = SBS.pack . encodeStringUtf8++-- | Variant of 'toUTF8BS' for lazy 'BS.ByteString's+--+toUTF8LBS :: String -> LBS.ByteString+toUTF8LBS = LBS.pack . encodeStringUtf8++-- | Check that strict 'ByteString' is valid UTF8. Returns 'Just offset' if it's not.+validateUTF8 :: SBS.ByteString -> Maybe Int+validateUTF8 = go 0 where+ go off bs = case SBS.uncons bs of+ Nothing -> Nothing+ Just (c, bs')+ | c <= 0x7F -> go (off + 1) bs'+ | c <= 0xBF -> Just off+ | c <= 0xDF -> twoBytes off c bs'+ | c <= 0xEF -> moreBytes off 3 0x800 bs' (fromIntegral $ c .&. 0xF)+ | c <= 0xF7 -> moreBytes off 4 0x10000 bs' (fromIntegral $ c .&. 0x7)+ | c <= 0xFB -> moreBytes off 5 0x200000 bs' (fromIntegral $ c .&. 0x3)+ | c <= 0xFD -> moreBytes off 6 0x4000000 bs' (fromIntegral $ c .&. 0x1)+ | otherwise -> Just off++ twoBytes off c0 bs = case SBS.uncons bs of+ Nothing -> Just off+ Just (c1, bs')+ | c1 .&. 0xC0 == 0x80 ->+ if d >= (0x80 :: Int)+ then go (off + 2) bs'+ else Just off+ | otherwise -> Just off+ where+ d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6) .|. fromIntegral (c1 .&. 0x3F)++ moreBytes :: Int -> Int -> Int -> SBS.ByteString -> Int -> Maybe Int+ moreBytes off 1 overlong cs' acc+ | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc+ = go (off + 1) cs'++ | otherwise+ = Just off++ moreBytes off byteCount overlong bs acc = case SBS.uncons bs of+ Just (cn, bs') | cn .&. 0xC0 == 0x80 ->+ moreBytes (off + 1) (byteCount-1) overlong bs' ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)+ _ -> Just off+ ++-- | Ignore a Unicode byte order mark (BOM) at the beginning of the input+--+ignoreBOM :: String -> String+ignoreBOM ('\xFEFF':string) = string+ignoreBOM string = string++-- | Reads a UTF8 encoded text file as a Unicode String+--+-- Reads lazily using ordinary 'readFile'.+--+readUTF8File :: FilePath -> IO String+readUTF8File f = (ignoreBOM . fromUTF8LBS) <$> LBS.readFile f++-- | Reads a UTF8 encoded text file as a Unicode String+--+-- Same behaviour as 'withFileContents'.+--+withUTF8FileContents :: FilePath -> (String -> IO a) -> IO a+withUTF8FileContents name action =+ withBinaryFile name ReadMode+ (\hnd -> LBS.hGetContents hnd >>= action . ignoreBOM . fromUTF8LBS)++-- | Writes a Unicode String as a UTF8 encoded text file.+--+-- Uses 'writeFileAtomic', so provides the same guarantees.+--+writeUTF8File :: FilePath -> String -> IO ()+writeUTF8File path = writeFileAtomic path . toUTF8LBS++-- | Fix different systems silly line ending conventions+normaliseLineEndings :: String -> String+normaliseLineEndings [] = []+normaliseLineEndings ('\r':'\n':s) = '\n' : normaliseLineEndings s -- windows+normaliseLineEndings ('\r':s) = '\n' : normaliseLineEndings s -- old OS X+normaliseLineEndings ( c :s) = c : normaliseLineEndings s++-- ------------------------------------------------------------+-- * Common utils+-- ------------------------------------------------------------++-- | @dropWhileEndLE p@ is equivalent to @reverse . dropWhile p . reverse@, but+-- quite a bit faster. The difference between "Data.List.dropWhileEnd" and this+-- version is that the one in "Data.List" is strict in elements, but spine-lazy,+-- while this one is spine-strict but lazy in elements. That's what @LE@ stands+-- for - "lazy in elements".+--+-- Example:+--+-- >>> safeTail $ Data.List.dropWhileEnd (<3) [undefined, 5, 4, 3, 2, 1]+-- *** Exception: Prelude.undefined+-- ...+--+-- >>> safeTail $ dropWhileEndLE (<3) [undefined, 5, 4, 3, 2, 1]+-- [5,4,3]+--+-- >>> take 3 $ Data.List.dropWhileEnd (<3) [5, 4, 3, 2, 1, undefined]+-- [5,4,3]+--+-- >>> take 3 $ dropWhileEndLE (<3) [5, 4, 3, 2, 1, undefined]+-- *** Exception: Prelude.undefined+-- ...+--+dropWhileEndLE :: (a -> Bool) -> [a] -> [a]+dropWhileEndLE p = foldr (\x r -> if null r && p x then [] else x:r) []++-- | @takeWhileEndLE p@ is equivalent to @reverse . takeWhile p . reverse@, but+-- is usually faster (as well as being easier to read).+takeWhileEndLE :: (a -> Bool) -> [a] -> [a]+takeWhileEndLE p = fst . foldr go ([], False)+ where+ go x (rest, done)+ | not done && p x = (x:rest, False)+ | otherwise = (rest, True)++-- | Like 'Data.List.nub', but has @O(n log n)@ complexity instead of+-- @O(n^2)@. Code for 'ordNub' and 'listUnion' taken from Niklas Hambüchen's+-- <http://github.com/nh2/haskell-ordnub ordnub> package.+ordNub :: Ord a => [a] -> [a]+ordNub = ordNubBy id++-- | Like 'ordNub' and 'Data.List.nubBy'. Selects a key for each element and+-- takes the nub based on that key.+ordNubBy :: Ord b => (a -> b) -> [a] -> [a]+ordNubBy f l = go Set.empty l+ where+ go !_ [] = []+ go !s (x:xs)+ | y `Set.member` s = go s xs+ | otherwise = let !s' = Set.insert y s+ in x : go s' xs+ where+ y = f x++-- | Like "Data.List.union", but has @O(n log n)@ complexity instead of+-- @O(n^2)@.+listUnion :: (Ord a) => [a] -> [a] -> [a]+listUnion a b = a ++ ordNub (filter (`Set.notMember` aSet) b)+ where+ aSet = Set.fromList a++-- | A right-biased version of 'ordNub'.+--+-- Example:+--+-- >>> ordNub [1,2,1] :: [Int]+-- [1,2]+--+-- >>> ordNubRight [1,2,1] :: [Int]+-- [2,1]+--+ordNubRight :: (Ord a) => [a] -> [a]+ordNubRight = fst . foldr go ([], Set.empty)+ where+ go x p@(l, s) = if x `Set.member` s then p+ else (x:l, Set.insert x s)++-- | A right-biased version of 'listUnion'.+--+-- Example:+--+-- >>> listUnion [1,2,3,4,3] [2,1,1]+-- [1,2,3,4,3]+--+-- >>> listUnionRight [1,2,3,4,3] [2,1,1]+-- [4,3,2,1,1]+--+listUnionRight :: (Ord a) => [a] -> [a] -> [a]+listUnionRight a b = ordNubRight (filter (`Set.notMember` bSet) a) ++ b+ where+ bSet = Set.fromList b++-- | A total variant of 'head'.+--+-- @since 3.2.0.0+safeHead :: [a] -> Maybe a+safeHead [] = Nothing+safeHead (x:_) = Just x++-- | A total variant of 'tail'.+--+-- @since 3.2.0.0+safeTail :: [a] -> [a]+safeTail [] = []+safeTail (_:xs) = xs++-- | A total variant of 'last'.+--+-- @since 3.2.0.0+safeLast :: [a] -> Maybe a+safeLast [] = Nothing+safeLast (x:xs) = Just (foldl (\_ a -> a) x xs)++-- | A total variant of 'init'.+--+-- @since 3.2.0.0+safeInit :: [a] -> [a]+safeInit [] = []+safeInit [_] = []+safeInit (x:xs) = x : safeInit xs++equating :: Eq a => (b -> a) -> b -> b -> Bool+equating p x y = p x == p y++-- | Lower case string+--+-- >>> lowercase "Foobar"+-- "foobar"+lowercase :: String -> String+lowercase = map toLower++-- | Ascii characters+isAscii :: Char -> Bool+isAscii c = fromEnum c < 0x80++-- | Ascii letters.+isAsciiAlpha :: Char -> Bool+isAsciiAlpha c = ('a' <= c && c <= 'z')+ || ('A' <= c && c <= 'Z')++-- | Ascii letters and digits.+--+-- >>> isAsciiAlphaNum 'a'+-- True+--+-- >>> isAsciiAlphaNum 'ä'+-- False+--+isAsciiAlphaNum :: Char -> Bool+isAsciiAlphaNum c = isAscii c && isAlphaNum c++unintersperse :: Char -> String -> [String]+unintersperse mark = unfoldr unintersperse1 where+ unintersperse1 str+ | null str = Nothing+ | otherwise =+ let (this, rest) = break (== mark) str in+ Just (this, safeTail rest)++-- | Like 'break', but with 'Maybe' predicate+--+-- >>> breakMaybe (readMaybe :: String -> Maybe Int) ["foo", "bar", "1", "2", "quu"]+-- (["foo","bar"],Just (1,["2","quu"]))+--+-- >>> breakMaybe (readMaybe :: String -> Maybe Int) ["foo", "bar"]+-- (["foo","bar"],Nothing)+--+-- @since 2.2+--+breakMaybe :: (a -> Maybe b) -> [a] -> ([a], Maybe (b, [a]))+breakMaybe f = go id where+ go !acc [] = (acc [], Nothing)+ go !acc (x:xs) = case f x of+ Nothing -> go (acc . (x:)) xs+ Just b -> (acc [], Just (b, xs))++-- | Like 'span' but with 'Maybe' predicate+--+-- >>> spanMaybe listToMaybe [[1,2],[3],[],[4,5],[6,7]]+-- ([1,3],[[],[4,5],[6,7]])+--+-- >>> spanMaybe (readMaybe :: String -> Maybe Int) ["1", "2", "foo"]+-- ([1,2],["foo"])+--+-- @since 2.2+--+spanMaybe :: (a -> Maybe b) -> [a] -> ([b],[a])+spanMaybe _ xs@[] = ([], xs)+spanMaybe p xs@(x:xs') = case p x of+ Just y -> let (ys, zs) = spanMaybe p xs' in (y : ys, zs)+ Nothing -> ([], xs)++-- | 'unfoldr' with monadic action.+--+-- >>> take 5 $ unfoldrM (\b r -> Just (r + b, b + 1)) (1 :: Int) 2+-- [3,4,5,6,7]+--+-- @since 2.2+--+unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> m [a]+unfoldrM f = go where+ go b = do+ m <- f b+ case m of+ Nothing -> return []+ Just (a, b') -> liftM (a :) (go b')++-- | The opposite of 'snoc', which is the reverse of 'cons'+--+-- Example:+--+-- >>> unsnoc [1, 2, 3]+-- Just ([1,2],3)+--+-- >>> unsnoc []+-- Nothing+--+-- @since 3.2.0.0+--+unsnoc :: [a] -> Maybe ([a], a)+unsnoc [] = Nothing+unsnoc (x:xs) = Just (unsnocNE (x :| xs))++-- | Like 'unsnoc', but for 'NonEmpty' so without the 'Maybe'+--+-- Example:+--+-- >>> unsnocNE (1 :| [2, 3])+-- ([1,2],3)+--+-- >>> unsnocNE (1 :| [])+-- ([],1)+--+-- @since 3.2.0.0+--+unsnocNE :: NonEmpty a -> ([a], a)+unsnocNE (x:|xs) = go x xs where+ go y [] = ([], y)+ go y (z:zs) = let ~(ws, w) = go z zs in (y : ws, w)++-------------------------------------------------------------------------------+-- Triples+-------------------------------------------------------------------------------++-- | @since 3.4.0.0+fstOf3 :: (a,b,c) -> a+fstOf3 (a,_,_) = a++-- | @since 3.4.0.0+sndOf3 :: (a,b,c) -> b+sndOf3 (_,b,_) = b++-- | @since 3.4.0.0+trdOf3 :: (a,b,c) -> c+trdOf3 (_,_,c) = c++-- ------------------------------------------------------------+-- * FilePath stuff+-- ------------------------------------------------------------++-- | 'isAbsoluteOnAnyPlatform' and 'isRelativeOnAnyPlatform' are like+-- 'System.FilePath.isAbsolute' and 'System.FilePath.isRelative' but have+-- platform independent heuristics.+-- The System.FilePath exists in two versions, Windows and Posix. The two+-- versions don't agree on what is a relative path and we don't know if we're+-- given Windows or Posix paths.+-- This results in false positives when running on Posix and inspecting+-- Windows paths, like the hackage server does.+-- System.FilePath.Posix.isAbsolute \"C:\\hello\" == False+-- System.FilePath.Windows.isAbsolute \"/hello\" == False+-- This means that we would treat paths that start with \"/\" to be absolute.+-- On Posix they are indeed absolute, while on Windows they are not.+--+-- The portable versions should be used when we might deal with paths that+-- are from another OS than the host OS. For example, the Hackage Server+-- deals with both Windows and Posix paths while performing the+-- PackageDescription checks. In contrast, when we run 'cabal configure' we+-- do expect the paths to be correct for our OS and we should not have to use+-- the platform independent heuristics.+isAbsoluteOnAnyPlatform :: FilePath -> Bool+-- C:\\directory+isAbsoluteOnAnyPlatform (drive:':':'\\':_) = isAlpha drive+isAbsoluteOnAnyPlatform (drive:':':'/':_) = isAlpha drive+-- UNC+isAbsoluteOnAnyPlatform ('\\':'\\':_) = True+-- Posix root+isAbsoluteOnAnyPlatform ('/':_) = True+isAbsoluteOnAnyPlatform _ = False++-- | @isRelativeOnAnyPlatform = not . 'isAbsoluteOnAnyPlatform'@+isRelativeOnAnyPlatform :: FilePath -> Bool+isRelativeOnAnyPlatform = not . isAbsoluteOnAnyPlatform++-- $setup+-- >>> import Data.Maybe+-- >>> import Text.Read
+ src/Distribution/Utils/IOData.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+-- | @since 2.2.0+module Distribution.Utils.IOData+ ( -- * 'IOData' & 'IODataMode' type+ IOData (..)+ , IODataMode (..)+ , KnownIODataMode (..)+ , withIOData+ , null+ , hPutContents+ ) where++import qualified Data.ByteString.Lazy as LBS+import Distribution.Compat.Prelude hiding (null)+import qualified Prelude+import qualified System.IO++-- | Represents either textual or binary data passed via I/O functions+-- which support binary/text mode+--+-- @since 2.2+data IOData+ = IODataText String+ -- ^ How Text gets encoded is usually locale-dependent.+ | IODataBinary LBS.ByteString+ -- ^ Raw binary which gets read/written in binary mode.++withIOData :: IOData -> (forall mode. IODataMode mode -> mode -> r) -> r+withIOData (IODataText str) k = k IODataModeText str+withIOData (IODataBinary lbs) k = k IODataModeBinary lbs++-- | Test whether 'IOData' is empty+null :: IOData -> Bool+null (IODataText s) = Prelude.null s+null (IODataBinary b) = LBS.null b++instance NFData IOData where+ rnf (IODataText s) = rnf s+ rnf (IODataBinary lbs) = rnf lbs++-- | @since 2.2+class NFData mode => KnownIODataMode mode where+ -- | 'IOData' Wrapper for 'System.IO.hGetContents'+ --+ -- __Note__: This operation uses lazy I/O. Use 'NFData' to force all+ -- data to be read and consequently the internal file handle to be+ -- closed.+ --+ hGetIODataContents :: System.IO.Handle -> Prelude.IO mode++ toIOData :: mode -> IOData+ iodataMode :: IODataMode mode++-- | @since 3.2+data IODataMode mode where+ IODataModeText :: IODataMode String+ IODataModeBinary :: IODataMode LBS.ByteString++instance a ~ Char => KnownIODataMode [a] where+ hGetIODataContents h = do+ System.IO.hSetBinaryMode h False+ System.IO.hGetContents h++ toIOData = IODataText+ iodataMode = IODataModeText++instance KnownIODataMode LBS.ByteString where+ hGetIODataContents h = do+ System.IO.hSetBinaryMode h True+ LBS.hGetContents h++ toIOData = IODataBinary+ iodataMode = IODataModeBinary++-- | 'IOData' Wrapper for 'System.IO.hPutStr' and 'System.IO.hClose'+--+-- This is the dual operation ot 'hGetIODataContents',+-- and consequently the handle is closed with `hClose`.+--+-- /Note:/ this performs lazy-IO.+--+-- @since 2.2+hPutContents :: System.IO.Handle -> IOData -> Prelude.IO ()+hPutContents h (IODataText c) = do+ System.IO.hSetBinaryMode h False+ System.IO.hPutStr h c+ System.IO.hClose h+hPutContents h (IODataBinary c) = do+ System.IO.hSetBinaryMode h True+ LBS.hPutStr h c+ System.IO.hClose h
+ src/Distribution/Utils/LogProgress.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE FlexibleContexts #-}+module Distribution.Utils.LogProgress (+ LogProgress,+ runLogProgress,+ warnProgress,+ infoProgress,+ dieProgress,+ addProgressCtx,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Utils.Progress+import Distribution.Verbosity+import Distribution.Simple.Utils+import Text.PrettyPrint++type CtxMsg = Doc+type LogMsg = Doc+type ErrMsg = Doc++data LogEnv = LogEnv {+ le_verbosity :: Verbosity,+ le_context :: [CtxMsg]+ }++-- | The 'Progress' monad with specialized logging and+-- error messages.+newtype LogProgress a = LogProgress { unLogProgress :: LogEnv -> Progress LogMsg ErrMsg a }++instance Functor LogProgress where+ fmap f (LogProgress m) = LogProgress (fmap (fmap f) m)++instance Applicative LogProgress where+ pure x = LogProgress (pure (pure x))+ LogProgress f <*> LogProgress x = LogProgress $ \r -> f r `ap` x r++instance Monad LogProgress where+ return = pure+ LogProgress m >>= f = LogProgress $ \r -> m r >>= \x -> unLogProgress (f x) r++-- | Run 'LogProgress', outputting traces according to 'Verbosity',+-- 'die' if there is an error.+runLogProgress :: Verbosity -> LogProgress a -> IO a+runLogProgress verbosity (LogProgress m) =+ foldProgress step_fn fail_fn return (m env)+ where+ env = LogEnv {+ le_verbosity = verbosity,+ le_context = []+ }+ step_fn :: LogMsg -> IO a -> IO a+ step_fn doc go = do+ putStrLn (render doc)+ go+ fail_fn :: Doc -> IO a+ fail_fn doc = do+ dieNoWrap verbosity (render doc)++-- | Output a warning trace message in 'LogProgress'.+warnProgress :: Doc -> LogProgress ()+warnProgress s = LogProgress $ \env ->+ when (le_verbosity env >= normal) $+ stepProgress $+ hang (text "Warning:") 4 (formatMsg (le_context env) s)++-- | Output an informational trace message in 'LogProgress'.+infoProgress :: Doc -> LogProgress ()+infoProgress s = LogProgress $ \env ->+ when (le_verbosity env >= verbose) $+ stepProgress s++-- | Fail the computation with an error message.+dieProgress :: Doc -> LogProgress a+dieProgress s = LogProgress $ \env ->+ failProgress $+ hang (text "Error:") 4 (formatMsg (le_context env) s)++-- | Format a message with context. (Something simple for now.)+formatMsg :: [CtxMsg] -> Doc -> Doc+formatMsg ctx doc = doc $$ vcat ctx++-- | Add a message to the error/warning context.+addProgressCtx :: CtxMsg -> LogProgress a -> LogProgress a+addProgressCtx s (LogProgress m) = LogProgress $ \env ->+ m env { le_context = s : le_context env }
+ src/Distribution/Utils/MD5.hs view
@@ -0,0 +1,79 @@+module Distribution.Utils.MD5 (+ MD5,+ showMD5,+ md5,+ -- * Helpers+ md5FromInteger,+ -- * Binary+ binaryPutMD5,+ binaryGetMD5,+ ) where++import Data.Binary (Get, Put)+import Data.Binary.Get (getWord64le)+import Data.Binary.Put (putWord64le)+import Data.Bits (complement, shiftR, (.&.))+import Foreign.Ptr (castPtr)+import GHC.Fingerprint (Fingerprint (..), fingerprintData)+import Numeric (showHex)+import System.IO.Unsafe (unsafeDupablePerformIO)++import qualified Data.ByteString as BS+import qualified Data.ByteString.Unsafe as BS++type MD5 = Fingerprint++-- | Show 'MD5' in human readable form+--+-- >>> showMD5 (Fingerprint 123 456)+-- "000000000000007b00000000000001c8"+--+-- >>> showMD5 $ md5 $ BS.pack [0..127]+-- "37eff01866ba3f538421b30b7cbefcac"+--+-- @since 3.2.0.0+showMD5 :: MD5 -> String+showMD5 (Fingerprint a b) = pad a' ++ pad b' where+ a' = showHex a ""+ b' = showHex b ""+ pad s = replicate (16 - length s) '0' ++ s++-- | @since 3.2.0.0+md5 :: BS.ByteString -> MD5+md5 bs = unsafeDupablePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, len) ->+ fingerprintData (castPtr ptr) len++-- | @since 3.2.0.0+binaryPutMD5 :: MD5 -> Put+binaryPutMD5 (Fingerprint a b) = do+ putWord64le a+ putWord64le b++-- | @since 3.2.0.0+binaryGetMD5 :: Get MD5+binaryGetMD5 = do+ a <- getWord64le+ b <- getWord64le+ return (Fingerprint a b)++-- |+--+-- >>> showMD5 $ md5FromInteger 0x37eff01866ba3f538421b30b7cbefcac+-- "37eff01866ba3f538421b30b7cbefcac"+--+-- Note: the input is truncated:+--+-- >>> showMD5 $ md5FromInteger 0x1230000037eff01866ba3f538421b30b7cbefcac+-- "37eff01866ba3f538421b30b7cbefcac"+--+-- Yet, negative numbers are not a problem...+--+-- >>> showMD5 $ md5FromInteger (-1)+-- "ffffffffffffffffffffffffffffffff"+--+-- @since 3.4.0.0+md5FromInteger :: Integer -> MD5+md5FromInteger i = Fingerprint hi lo where+ mask = complement 0+ lo = mask .&. fromInteger i+ hi = mask .&. fromInteger (i `shiftR` 64)
+ src/Distribution/Utils/MapAccum.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE CPP #-}+module Distribution.Utils.MapAccum (mapAccumM) where++import Distribution.Compat.Prelude+import Prelude ()++-- Like StateT but with return tuple swapped+newtype StateM s m a = StateM { runStateM :: s -> m (s, a) }++instance Functor m => Functor (StateM s m) where+ fmap f (StateM x) = StateM $ \s -> fmap (\(s', a) -> (s', f a)) (x s)++instance+#if __GLASGOW_HASKELL__ < 709+ (Functor m, Monad m)+#else+ Monad m+#endif+ => Applicative (StateM s m) where+ pure x = StateM $ \s -> return (s, x)+ StateM f <*> StateM x = StateM $ \s -> do (s', f') <- f s+ (s'', x') <- x s'+ return (s'', f' x')++-- | Monadic variant of 'mapAccumL'.+mapAccumM ::+#if __GLASGOW_HASKELL__ < 709+ (Functor m, Monad m, Traversable t)+#else+ (Monad m, Traversable t)+#endif+ => (a -> b -> m (a, c)) -> a -> t b -> m (a, t c)+mapAccumM f s t = runStateM (traverse (\x -> StateM (\s' -> f s' x)) t) s+
+ src/Distribution/Utils/NubList.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Distribution.Utils.NubList+ ( NubList -- opaque+ , toNubList -- smart construtor+ , fromNubList+ , overNubList++ , NubListR+ , toNubListR+ , fromNubListR+ , overNubListR+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Distribution.Simple.Utils++import qualified Text.Read as R++-- | NubList : A de-duplicated list that maintains the original order.+newtype NubList a =+ NubList { fromNubList :: [a] }+ deriving (Eq, Generic, Typeable)++-- NubList assumes that nub retains the list order while removing duplicate+-- elements (keeping the first occurrence). Documentation for "Data.List.nub"+-- does not specifically state that ordering is maintained so we will add a test+-- for that to the test suite.++-- | Smart constructor for the NubList type.+toNubList :: Ord a => [a] -> NubList a+toNubList list = NubList $ ordNub list++-- | Lift a function over lists to a function over NubLists.+overNubList :: Ord a => ([a] -> [a]) -> NubList a -> NubList a+overNubList f (NubList list) = toNubList . f $ list++-- | Monoid operations on NubLists.+-- For a valid Monoid instance we need to satistfy the required monoid laws;+-- identity, associativity and closure.+--+-- Identity : by inspection:+-- mempty `mappend` NubList xs == NubList xs `mappend` mempty+--+-- Associativity : by inspection:+-- (NubList xs `mappend` NubList ys) `mappend` NubList zs+-- == NubList xs `mappend` (NubList ys `mappend` NubList zs)+--+-- Closure : appending two lists of type a and removing duplicates obviously+-- does not change the type.++instance Ord a => Monoid (NubList a) where+ mempty = NubList []+ mappend = (<>)++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++instance (Ord a, Read a) => Read (NubList a) where+ readPrec = readNubList toNubList++-- | Helper used by NubList/NubListR's Read instances.+readNubList :: (Read a) => ([a] -> l a) -> R.ReadPrec (l a)+readNubList listToL = R.parens . R.prec 10 $ fmap listToL R.readPrec++-- | Binary instance for 'NubList a' is the same as for '[a]'. For 'put', we+-- just pull off constructor and put the list. For 'get', we get the list and+-- make a 'NubList' out of it using 'toNubList'.+instance (Ord a, Binary a) => Binary (NubList a) where+ put (NubList l) = put l+ get = fmap toNubList get++instance Structured a => Structured (NubList a)++-- | NubListR : A right-biased version of 'NubList'. That is @toNubListR+-- ["-XNoFoo", "-XFoo", "-XNoFoo"]@ will result in @["-XFoo", "-XNoFoo"]@,+-- unlike the normal 'NubList', which is left-biased. Built on top of+-- 'ordNubRight' and 'listUnionRight'.+newtype NubListR a =+ NubListR { fromNubListR :: [a] }+ deriving Eq++-- | Smart constructor for the NubListR type.+toNubListR :: Ord a => [a] -> NubListR a+toNubListR list = NubListR $ ordNubRight list++-- | Lift a function over lists to a function over NubListRs.+overNubListR :: Ord a => ([a] -> [a]) -> NubListR a -> NubListR a+overNubListR f (NubListR list) = toNubListR . f $ list++instance Ord a => Monoid (NubListR a) where+ mempty = NubListR []+ mappend = (<>)++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++instance (Ord a, Read a) => Read (NubListR a) where+ readPrec = readNubList toNubListR
+ src/Distribution/Utils/Path.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE StandaloneDeriving #-}+module Distribution.Utils.Path (+ -- * Symbolic path+ SymbolicPath,+ getSymbolicPath,+ sameDirectory,+ unsafeMakeSymbolicPath,+ -- * Path ends+ PackageDir,+ SourceDir,+ LicenseFile,+ IsDir,+) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.Parsec+import Distribution.Pretty+import Distribution.Utils.Generic (isAbsoluteOnAnyPlatform)++import qualified Distribution.Compat.CharParsing as P+-- import qualified Text.PrettyPrint as Disp++-------------------------------------------------------------------------------+-- * SymbolicPath+-------------------------------------------------------------------------------++-- | Symbolic paths.+--+-- These paths are system independent and relative.+-- They are *symbolic* which means we cannot perform any 'IO'+-- until we interpret them.+--+newtype SymbolicPath from to = SymbolicPath FilePath+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary (SymbolicPath from to)+instance (Typeable from, Typeable to) => Structured (SymbolicPath from to)+instance NFData (SymbolicPath from to) where rnf = genericRnf++-- | Extract underlying 'FilePath'.+--+-- Avoid using this in new code.+--+getSymbolicPath :: SymbolicPath from to -> FilePath+getSymbolicPath (SymbolicPath p) = p++sameDirectory :: (IsDir from, IsDir to) => SymbolicPath from to+sameDirectory = SymbolicPath "."++-- | Make 'SymbolicPath' without performing any checks.+unsafeMakeSymbolicPath :: FilePath -> SymbolicPath from to+unsafeMakeSymbolicPath = SymbolicPath++-------------------------------------------------------------------------------+-- ** Parsing and pretty printing+-------------------------------------------------------------------------------++instance Parsec (SymbolicPath from to) where+ parsec = do+ token <- parsecToken+ if null token then P.unexpected "empty FilePath"+ else if isAbsoluteOnAnyPlatform token then P.unexpected "absolute FilePath"+ else return (SymbolicPath token) -- TODO: normalise++instance Pretty (SymbolicPath from to) where+ pretty = showFilePath . getSymbolicPath++-------------------------------------------------------------------------------+-- * Composition+-------------------------------------------------------------------------------++-- TODO+-- infixr 5 <//>+--+-- -- | Path composition+-- --+-- -- We don't reuse @</>@ name to not clash with "System.FilePath".+-- --+-- (<//>) :: path a b -> path b c -> path a c++-------------------------------------------------------------------------------+-- * Path ends+-------------------------------------------------------------------------------++-- | Class telling that index is for directories.+class IsDir dir++data PackageDir deriving (Typeable)+data SourceDir deriving (Typeable)++data LicenseFile deriving (Typeable)++-- These instances needs to be derived standalone at least on GHC-7.6+deriving instance Data PackageDir+deriving instance Data SourceDir+deriving instance Data LicenseFile++instance IsDir PackageDir+instance IsDir SourceDir
+ src/Distribution/Utils/Progress.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveFunctor #-}+-- Note: This module was copied from cabal-install.++-- | A progress monad, which we use to report failure and logging from+-- otherwise pure code.+module Distribution.Utils.Progress+ ( Progress+ , stepProgress+ , failProgress+ , foldProgress+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import qualified Data.Monoid as Mon+++-- | A type to represent the unfolding of an expensive long running+-- calculation that may fail (or maybe not expensive, but complicated!)+-- We may get intermediate steps before the final+-- result which may be used to indicate progress and\/or logging messages.+--+-- TODO: Apply Codensity to avoid left-associativity problem.+-- See http://comonad.com/reader/2011/free-monads-for-less/ and+-- http://blog.ezyang.com/2012/01/problem-set-the-codensity-transformation/+--+data Progress step fail done = Step step (Progress step fail done)+ | Fail fail+ | Done done+ deriving (Functor)++-- | Emit a step and then continue.+--+stepProgress :: step -> Progress step fail ()+stepProgress step = Step step (Done ())++-- | Fail the computation.+failProgress :: fail -> Progress step fail done+failProgress err = Fail err++-- | Consume a 'Progress' calculation. Much like 'foldr' for lists but with two+-- base cases, one for a final result and one for failure.+--+-- Eg to convert into a simple 'Either' result use:+--+-- > foldProgress (flip const) Left Right+--+foldProgress :: (step -> a -> a) -> (fail -> a) -> (done -> a)+ -> Progress step fail done -> a+foldProgress step err done = fold+ where fold (Step s p) = step s (fold p)+ fold (Fail f) = err f+ fold (Done r) = done r++instance Monad (Progress step fail) where+ return = pure+ p >>= f = foldProgress Step Fail f p++instance Applicative (Progress step fail) where+ pure a = Done a+ p <*> x = foldProgress Step Fail (flip fmap x) p++instance Monoid fail => Alternative (Progress step fail) where+ empty = Fail Mon.mempty+ p <|> q = foldProgress Step (const q) Done p
+ src/Distribution/Utils/ShortText.hs view
@@ -0,0 +1,159 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++-- | Compact representation of short 'Strings'+--+-- This module is designed to be import qualifeid+--+-- @+-- import Distribution.Utils.ShortText (ShortText)+-- import qualified Distribution.Utils.ShortText as ShortText+-- @+module Distribution.Utils.ShortText+ ( -- * 'ShortText' type+ ShortText+ , toShortText+ , fromShortText+ , unsafeFromUTF8BS++ -- * Operations+ , null+ , length++ -- * internal utilities+ , decodeStringUtf8+ , encodeStringUtf8+ ) where++import Distribution.Compat.Prelude hiding (length, null)+import Prelude ()++import Distribution.Utils.String (decodeStringUtf8, encodeStringUtf8)+import Distribution.Utils.Structured (Structured (..), nominalStructure)++#if defined(MIN_VERSION_bytestring)+# if MIN_VERSION_bytestring(0,10,4)+# define HAVE_SHORTBYTESTRING 1+# endif+#endif++-- Hack for GHC bootstrapping+--+-- Currently (as of GHC 8.1), GHC bootstraps Cabal by building+-- binary and Cabal in one giant ghc --make command. This+-- means no MIN_VERSION_binary macro is available.+--+-- We could try to cleverly figure something out in this case,+-- but there is a better plan: just use the unoptimized version+-- of the Binary instance. We're not going to use it for anything+-- real in any case.+--+-- WARNING: Don't use MIN_VERSION_binary to smooth over a BC-break!+--+#ifndef MIN_VERSION_binary+#define MIN_VERSION_binary(x, y, z) 0+#endif++import qualified Data.ByteString as BS+import qualified Data.List as List++#if HAVE_SHORTBYTESTRING+import qualified Data.ByteString.Short as BS.Short+#else+import Distribution.Utils.Generic (fromUTF8BS)+#endif++-- | Construct 'ShortText' from 'String'+toShortText :: String -> ShortText++-- | Convert 'ShortText' to 'String'+fromShortText :: ShortText -> String++-- | Convert from UTF-8 encoded strict 'ByteString'.+--+-- @since 3.2.0.0+unsafeFromUTF8BS :: BS.ByteString -> ShortText++-- | Text whether 'ShortText' is empty.+--+-- @since 3.2.0.0+null :: ShortText -> Bool++-- | Compact representation of short 'Strings'+--+-- The data is stored internally as UTF8 in an+-- 'BS.Short.ShortByteString' when compiled against @bytestring >=+-- 0.10.4@, and otherwise the fallback is to use plain old non-compat+-- '[Char]'.+--+-- Note: This type is for internal uses (such as e.g. 'PackageName')+-- and shall not be exposed in Cabal's API+--+-- @since 2.0.0.2+#if HAVE_SHORTBYTESTRING+newtype ShortText = ST { unST :: BS.Short.ShortByteString }+ deriving (Eq,Ord,Generic,Data,Typeable)++# if MIN_VERSION_binary(0,8,1)+instance Binary ShortText where+ put = put . unST+ get = fmap ST get+# else+instance Binary ShortText where+ put = put . BS.Short.fromShort . unST+ get = fmap (ST . BS.Short.toShort) get+# endif+++toShortText = ST . BS.Short.pack . encodeStringUtf8++fromShortText = decodeStringUtf8 . BS.Short.unpack . unST++unsafeFromUTF8BS = ST . BS.Short.toShort++null = BS.Short.null . unST+#else+newtype ShortText = ST { unST :: String }+ deriving (Eq,Ord,Generic,Data,Typeable)++instance Binary ShortText where+ put = put . encodeStringUtf8 . unST+ get = fmap (ST . decodeStringUtf8) get++toShortText = ST++fromShortText = unST++unsafeFromUTF8BS = ST . fromUTF8BS++null = List.null . unST+#endif++instance Structured ShortText where structure = nominalStructure++instance NFData ShortText where+ rnf = rnf . unST++instance Show ShortText where+ show = show . fromShortText++instance Read ShortText where+ readsPrec p = map (first toShortText) . readsPrec p++instance Semigroup ShortText where+ ST a <> ST b = ST (mappend a b)++instance Monoid ShortText where+ mempty = ST mempty+ mappend = (<>)++instance IsString ShortText where+ fromString = toShortText++-- | /O(n)/. Length in characters. /Slow/ as converts to string.+--+-- @since 3.2.0.0+length :: ShortText -> Int+length = List.length . fromShortText+-- Note: avoid using it, we use it @cabal check@ implementation, where it's ok.
+ src/Distribution/Utils/String.hs view
@@ -0,0 +1,93 @@+module Distribution.Utils.String+ ( -- * Encode to/from UTF8+ decodeStringUtf8+ , encodeStringUtf8+ ) where++import Data.Word+import Data.Bits+import Data.Char (chr,ord)++-- | Decode 'String' from UTF8-encoded octets.+--+-- Invalid data in the UTF8 stream (this includes code-points @U+D800@+-- through @U+DFFF@) will be decoded as the replacement character (@U+FFFD@).+--+-- See also 'encodeStringUtf8'+decodeStringUtf8 :: [Word8] -> String+decodeStringUtf8 = go+ where+ go :: [Word8] -> String+ go [] = []+ go (c : cs)+ | c <= 0x7F = chr (fromIntegral c) : go cs+ | c <= 0xBF = replacementChar : go cs+ | c <= 0xDF = twoBytes c cs+ | c <= 0xEF = moreBytes 3 0x800 cs (fromIntegral $ c .&. 0xF)+ | c <= 0xF7 = moreBytes 4 0x10000 cs (fromIntegral $ c .&. 0x7)+ | c <= 0xFB = moreBytes 5 0x200000 cs (fromIntegral $ c .&. 0x3)+ | c <= 0xFD = moreBytes 6 0x4000000 cs (fromIntegral $ c .&. 0x1)+ | otherwise = replacementChar : go cs++ twoBytes :: Word8 -> [Word8] -> String+ twoBytes c0 (c1:cs')+ | c1 .&. 0xC0 == 0x80+ = let d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6)+ .|. fromIntegral (c1 .&. 0x3F)+ in if d >= 0x80+ then chr d : go cs'+ else replacementChar : go cs'+ twoBytes _ cs' = replacementChar : go cs'++ moreBytes :: Int -> Int -> [Word8] -> Int -> [Char]+ moreBytes 1 overlong cs' acc+ | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc+ = chr acc : go cs'++ | otherwise+ = replacementChar : go cs'++ moreBytes byteCount overlong (cn:cs') acc+ | cn .&. 0xC0 == 0x80+ = moreBytes (byteCount-1) overlong cs'+ ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)++ moreBytes _ _ cs' _+ = replacementChar : go cs'++ replacementChar = '\xfffd'+++-- | Encode 'String' to a list of UTF8-encoded octets+--+-- Code-points in the @U+D800@-@U+DFFF@ range will be encoded+-- as the replacement character (i.e. @U+FFFD@).+--+-- See also 'decodeUtf8'+encodeStringUtf8 :: String -> [Word8]+encodeStringUtf8 [] = []+encodeStringUtf8 (c:cs)+ | c <= '\x07F' = w8+ : encodeStringUtf8 cs+ | c <= '\x7FF' = (0xC0 .|. w8ShiftR 6 )+ : (0x80 .|. (w8 .&. 0x3F))+ : encodeStringUtf8 cs+ | c <= '\xD7FF'= (0xE0 .|. w8ShiftR 12 )+ : (0x80 .|. (w8ShiftR 6 .&. 0x3F))+ : (0x80 .|. (w8 .&. 0x3F))+ : encodeStringUtf8 cs+ | c <= '\xDFFF'= 0xEF : 0xBF : 0xBD -- U+FFFD+ : encodeStringUtf8 cs+ | c <= '\xFFFF'= (0xE0 .|. w8ShiftR 12 )+ : (0x80 .|. (w8ShiftR 6 .&. 0x3F))+ : (0x80 .|. (w8 .&. 0x3F))+ : encodeStringUtf8 cs+ | otherwise = (0xf0 .|. w8ShiftR 18 )+ : (0x80 .|. (w8ShiftR 12 .&. 0x3F))+ : (0x80 .|. (w8ShiftR 6 .&. 0x3F))+ : (0x80 .|. (w8 .&. 0x3F))+ : encodeStringUtf8 cs+ where+ w8 = fromIntegral (ord c) :: Word8+ w8ShiftR :: Int -> Word8+ w8ShiftR = fromIntegral . shiftR (ord c)
+ src/Distribution/Utils/Structured.hs view
@@ -0,0 +1,476 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+#if __GLASGOW_HASKELL__ >= 711+{-# LANGUAGE PatternSynonyms #-}+#endif+#if __GLASGOW_HASKELL__ >= 800+{-# LANGUAGE TypeInType #-}+#endif+-- |+--+-- Copyright: (c) 2019 Oleg Grenrus+--+-- Structurally tag binary serialisaton stream.+-- Useful when most 'Binary' instances are 'Generic' derived.+--+-- Say you have a data type+--+-- @+-- data Record = Record+-- { _recordFields :: HM.HashMap Text (Integer, ByteString)+-- , _recordEnabled :: Bool+-- }+-- deriving (Eq, Show, Generic)+--+-- instance 'Binary' Record+-- instance 'Structured' Record+-- @+--+-- then you can serialise and deserialise @Record@ values with a structure tag by simply+--+-- @+-- 'structuredEncode' record :: 'LBS.ByteString'+-- 'structuredDecode' lbs :: IO Record+-- @+--+-- If structure of @Record@ changes in between, deserialisation will fail early.+--+-- Technically, 'Structured' is not related to 'Binary', and may+-- be useful in other uses.+--+module Distribution.Utils.Structured (+ -- * Encoding and decoding+ -- | These functions operate like @binary@'s counterparts,+ -- but the serialised version has a structure hash in front.+ structuredEncode,+ structuredEncodeFile,+ structuredDecode,+ structuredDecodeOrFailIO,+ structuredDecodeFileOrFail,+ -- * Structured class+ Structured (structure),+ MD5,+ structureHash,+ structureBuilder,+ genericStructure,+ GStructured,+ nominalStructure,+ containerStructure,+ -- * Structure type+ Structure (..),+ TypeName,+ ConstructorName,+ TypeVersion,+ SopStructure,+ hashStructure,+ typeVersion,+ typeName,+ ) where++import Data.Int (Int16, Int32, Int64, Int8)+import Data.List.NonEmpty (NonEmpty)+import Data.Proxy (Proxy (..))+import Data.Ratio (Ratio)+import Data.Word (Word, Word16, Word32, Word64, Word8)++import qualified Control.Monad.Trans.State.Strict as State++import Control.Exception (ErrorCall (..), catch, evaluate)++import GHC.Generics++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as LBS+#if MIN_VERSION_bytestring(0,10,4)+import qualified Data.ByteString.Builder as Builder+#else+import qualified Data.ByteString.Lazy.Builder as Builder+#endif+import qualified Data.IntMap as IM+import qualified Data.IntSet as IS+import qualified Data.Map as Map+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Data.Time as Time+import qualified Distribution.Compat.Binary as Binary++#ifdef MIN_VERSION_aeson+import qualified Data.Aeson as Aeson+#endif++#if __GLASGOW_HASKELL__ >= 800+import Data.Kind (Type)+#else+#define Type *+#endif++import Distribution.Compat.Typeable (Typeable, TypeRep, typeRep)+import Distribution.Utils.MD5++import Data.Monoid (mconcat)++import qualified Data.Semigroup+import qualified Data.Foldable++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (pure)+import Data.Traversable (traverse)+#endif++#if !MIN_VERSION_base(4,7,0)+import Data.Typeable (Typeable1, typeOf1)+#endif+++-------------------------------------------------------------------------------+-- Types+-------------------------------------------------------------------------------++type TypeName = String+type ConstructorName = String++-- | A sematic version of a data type. Usually 0.+type TypeVersion = Word32++-- | Structure of a datatype.+--+-- It can be infinite, as far as 'TypeRep's involved are finite.+-- (e.g. polymorphic recursion might cause troubles).+--+data Structure+ = Nominal !TypeRep !TypeVersion TypeName [Structure] -- ^ nominal, yet can be parametrised by other structures.+ | Newtype !TypeRep !TypeVersion TypeName Structure -- ^ a newtype wrapper+ | Structure !TypeRep !TypeVersion TypeName SopStructure -- ^ sum-of-products structure+ deriving (Eq, Ord, Show, Generic)++type SopStructure = [(ConstructorName, [Structure])]++-- | A MD5 hash digest of 'Structure'.+hashStructure :: Structure -> MD5+hashStructure = md5 . LBS.toStrict . Builder.toLazyByteString . structureBuilder++-- | A van-Laarhoven lens into 'TypeVersion' of 'Structure'+--+-- @+-- 'typeVersion' :: Lens' 'Structure' 'TypeVersion'+-- @+typeVersion :: Functor f => (TypeVersion -> f TypeVersion) -> Structure -> f Structure+typeVersion f (Nominal t v n s) = fmap (\v' -> Nominal t v' n s) (f v)+typeVersion f (Newtype t v n s) = fmap (\v' -> Newtype t v' n s) (f v)+typeVersion f (Structure t v n s) = fmap (\v' -> Structure t v' n s) (f v)++-- | A van-Laarhoven lens into 'TypeName' of 'Structure'+--+-- @+-- 'typeName' :: Lens' 'Structure' 'TypeName'+-- @+typeName :: Functor f => (TypeName -> f TypeName) -> Structure -> f Structure+typeName f (Nominal t v n s) = fmap (\n' -> Nominal t v n' s) (f n)+typeName f (Newtype t v n s) = fmap (\n' -> Newtype t v n' s) (f n)+typeName f (Structure t v n s) = fmap (\n' -> Structure t v n' s) (f n)++-------------------------------------------------------------------------------+-- Builder+-------------------------------------------------------------------------------++-- | Flatten 'Structure' into something we can calculate hash of.+--+-- As 'Structure' can be potentially infinite. For mutually recursive types,+-- we keep track of 'TypeRep's, and put just 'TypeRep' name when it's occurred+-- another time.+structureBuilder :: Structure -> Builder.Builder+structureBuilder s0 = State.evalState (go s0) Map.empty where+ go :: Structure -> State.State (Map.Map String (NonEmpty TypeRep)) Builder.Builder+ go (Nominal t v n s) = withTypeRep t $ do+ s' <- traverse go s+ return $ mconcat $ Builder.word8 1 : Builder.word32LE v : Builder.stringUtf8 n : s'++ go (Newtype t v n s) = withTypeRep t $ do+ s' <- go s+ return $ mconcat [Builder.word8 2, Builder.word32LE v, Builder.stringUtf8 n, s']++ go (Structure t v n s) = withTypeRep t $ do+ s' <- goSop s+ return $ mconcat [Builder.word8 3, Builder.word32LE v, Builder.stringUtf8 n, s']++ withTypeRep t k = do+ acc <- State.get+ case insert t acc of+ Nothing -> return $ mconcat [ Builder.word8 0, Builder.stringUtf8 (show t) ]+ Just acc' -> do+ State.put acc'+ k ++ goSop :: SopStructure -> State.State (Map.Map String (NonEmpty TypeRep)) Builder.Builder+ goSop sop = do+ parts <- traverse part sop+ return $ mconcat parts++ part (cn, s) = do+ s' <- traverse go s+ return $ Data.Monoid.mconcat [ Builder.stringUtf8 cn, mconcat s' ]++ insert :: TypeRep -> Map.Map String (NonEmpty TypeRep) -> Maybe (Map.Map String (NonEmpty TypeRep))+ insert tr m = case Map.lookup trShown m of+ Nothing -> inserted+ Just ne | tr `Data.Foldable.elem` ne -> Nothing+ | otherwise -> inserted+ where+ inserted = Just (Map.insertWith (Data.Semigroup.<>) trShown (pure tr) m)+ trShown = show tr++-------------------------------------------------------------------------------+-- Classes+-------------------------------------------------------------------------------++-- | Class of types with a known 'Structure'.+--+-- For regular data types 'Structured' can be derived generically.+--+-- @+-- data Record = Record { a :: Int, b :: Bool, c :: [Char] } deriving ('Generic')+-- instance 'Structured' Record+-- @+--+-- @since 3.2.0.0+--+class Typeable a => Structured a where+ structure :: Proxy a -> Structure+ default structure :: (Generic a, GStructured (Rep a)) => Proxy a -> Structure+ structure = genericStructure++ -- This member is hidden. It's there to precalc+ structureHash' :: Tagged a MD5+ structureHash' = Tagged (hashStructure (structure (Proxy :: Proxy a)))++-- private Tagged+newtype Tagged a b = Tagged { untag :: b }++-- | Semantically @'hashStructure' . 'structure'@.+structureHash :: forall a. Structured a => Proxy a -> MD5+structureHash _ = untag (structureHash' :: Tagged a MD5)++-------------------------------------------------------------------------------+-- Functions+-------------------------------------------------------------------------------++-- | Structured 'Binary.encode'.+-- Encode a value to using binary serialisation to a lazy 'LBS.ByteString'.+-- Encoding starts with 16 byte large structure hash.+structuredEncode+ :: forall a. (Binary.Binary a, Structured a)+ => a -> LBS.ByteString+structuredEncode x = Binary.encode (Tag :: Tag a, x)++-- | Lazily serialise a value to a file+structuredEncodeFile :: (Binary.Binary a, Structured a) => FilePath -> a -> IO ()+structuredEncodeFile f = LBS.writeFile f . structuredEncode++-- | Structured 'Binary.decode'.+-- Decode a value from a lazy 'LBS.ByteString', reconstructing the original structure.+-- Throws pure exception on invalid inputs.+structuredDecode+ :: forall a. (Binary.Binary a, Structured a)+ => LBS.ByteString -> a+structuredDecode lbs = snd (Binary.decode lbs :: (Tag a, a))++structuredDecodeOrFailIO :: (Binary.Binary a, Structured a) => LBS.ByteString -> IO (Either String a)+structuredDecodeOrFailIO bs =+ catch (evaluate (structuredDecode bs) >>= return . Right) handler+ where+#if MIN_VERSION_base(4,9,0)+ handler (ErrorCallWithLocation str _) = return $ Left str+#else+ handler (ErrorCall str) = return $ Left str+#endif++-- | Lazily reconstruct a value previously written to a file.+structuredDecodeFileOrFail :: (Binary.Binary a, Structured a) => FilePath -> IO (Either String a)+structuredDecodeFileOrFail f = structuredDecodeOrFailIO =<< LBS.readFile f++-------------------------------------------------------------------------------+-- Helper data+-------------------------------------------------------------------------------++data Tag a = Tag++instance Structured a => Binary.Binary (Tag a) where+ get = do+ actual <- binaryGetMD5+ if actual == expected+ then return Tag+ else fail $ concat+ [ "Non-matching structured hashes: "+ , showMD5 actual+ , "; expected: "+ , showMD5 expected+ ]+ where+ expected = untag (structureHash' :: Tagged a MD5)++ put _ = binaryPutMD5 expected+ where+ expected = untag (structureHash' :: Tagged a MD5)++-------------------------------------------------------------------------------+-- Smart constructors+-------------------------------------------------------------------------------++-- | Use 'Typeable' to infer name+nominalStructure :: Typeable a => Proxy a -> Structure+nominalStructure p = Nominal tr 0 (show tr) [] where+ tr = typeRep p++#if MIN_VERSION_base(4,7,0)+containerStructure :: forall f a. (Typeable f, Structured a) => Proxy (f a) -> Structure+containerStructure _ = Nominal faTypeRep 0 (show fTypeRep)+ [ structure (Proxy :: Proxy a)+ ]+ where+ fTypeRep = typeRep (Proxy :: Proxy f)+ faTypeRep = typeRep (Proxy :: Proxy (f a))++#else+containerStructure :: forall f a. (Typeable1 f, Structured a) => Proxy (f a) -> Structure+containerStructure _ = Nominal faTypeRep 0 (show fTypeRep)+ [ structure (Proxy :: Proxy a)+ ]+ where+ fTypeRep = typeOf1 (undefined :: f ())+ faTypeRep = typeRep (Proxy :: Proxy (f a))+#endif++-------------------------------------------------------------------------------+-- Generic+-------------------------------------------------------------------------------++-- | Derive 'structure' genrically.+genericStructure :: forall a. (Typeable a, Generic a, GStructured (Rep a)) => Proxy a -> Structure+genericStructure _ = gstructured (typeRep (Proxy :: Proxy a)) (Proxy :: Proxy (Rep a)) 0++-- | Used to implement 'genericStructure'.+class GStructured (f :: Type -> Type) where+ gstructured :: TypeRep -> Proxy f -> TypeVersion -> Structure++instance (i ~ D, Datatype c, GStructuredSum f) => GStructured (M1 i c f) where+ gstructured tr _ v = case sop of+#if MIN_VERSION_base(4,7,0)+ [(_, [s])] | isNewtype p -> Newtype tr v name s+#endif+ _ -> Structure tr v name sop+ where+ p = undefined :: M1 i c f ()+ name = datatypeName p+ sop = gstructuredSum (Proxy :: Proxy f) []++class GStructuredSum (f :: Type -> Type) where+ gstructuredSum :: Proxy f -> SopStructure -> SopStructure++instance (i ~ C, Constructor c, GStructuredProd f) => GStructuredSum (M1 i c f) where+ gstructuredSum _ xs = (name, prod) : xs+ where+ name = conName (undefined :: M1 i c f ())+ prod = gstructuredProd (Proxy :: Proxy f) []++instance (GStructuredSum f, GStructuredSum g) => GStructuredSum (f :+: g) where+ gstructuredSum _ xs+ = gstructuredSum (Proxy :: Proxy f)+ $ gstructuredSum (Proxy :: Proxy g) xs++instance GStructuredSum V1 where+ gstructuredSum _ = id++class GStructuredProd (f :: Type -> Type) where+ gstructuredProd :: Proxy f -> [Structure] -> [Structure]++instance (i ~ S, GStructuredProd f) => GStructuredProd (M1 i c f) where+ gstructuredProd _ = gstructuredProd (Proxy :: Proxy f)++instance Structured c => GStructuredProd (K1 i c) where+ gstructuredProd _ xs = structure (Proxy :: Proxy c) : xs++instance GStructuredProd U1 where+ gstructuredProd _ = id++instance (GStructuredProd f, GStructuredProd g) => GStructuredProd (f :*: g) where+ gstructuredProd _ xs+ = gstructuredProd (Proxy :: Proxy f)+ $ gstructuredProd (Proxy :: Proxy g) xs++-------------------------------------------------------------------------------+-- instances+-------------------------------------------------------------------------------++instance Structured ()+instance Structured Bool+instance Structured Ordering++instance Structured Char where structure = nominalStructure+instance Structured Int where structure = nominalStructure+instance Structured Integer where structure = nominalStructure++instance Structured Data.Word.Word where structure = nominalStructure++instance Structured Int8 where structure = nominalStructure+instance Structured Int16 where structure = nominalStructure+instance Structured Int32 where structure = nominalStructure+instance Structured Int64 where structure = nominalStructure++instance Structured Word8 where structure = nominalStructure+instance Structured Word16 where structure = nominalStructure+instance Structured Word32 where structure = nominalStructure+instance Structured Word64 where structure = nominalStructure++instance Structured Float where structure = nominalStructure+instance Structured Double where structure = nominalStructure++instance Structured a => Structured (Maybe a)+instance (Structured a, Structured b) => Structured (Either a b)+instance Structured a => Structured (Ratio a) where structure = containerStructure+instance Structured a => Structured [a] where structure = containerStructure+instance Structured a => Structured (NonEmpty a) where structure = containerStructure++instance (Structured a1, Structured a2) => Structured (a1, a2)+instance (Structured a1, Structured a2, Structured a3) => Structured (a1, a2, a3)+instance (Structured a1, Structured a2, Structured a3, Structured a4) => Structured (a1, a2, a3, a4)+instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5) => Structured (a1, a2, a3, a4, a5)+instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5, Structured a6) => Structured (a1, a2, a3, a4, a5, a6)+instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5, Structured a6, Structured a7) => Structured (a1, a2, a3, a4, a5, a6, a7)++instance Structured BS.ByteString where structure = nominalStructure+instance Structured LBS.ByteString where structure = nominalStructure++instance Structured T.Text where structure = nominalStructure+instance Structured LT.Text where structure = nominalStructure++instance (Structured k, Structured v) => Structured (Map.Map k v) where structure _ = Nominal (typeRep (Proxy :: Proxy (Map.Map k v))) 0 "Map" [ structure (Proxy :: Proxy k), structure (Proxy :: Proxy v) ]+instance (Structured k) => Structured (Set.Set k) where structure = containerStructure+instance (Structured v) => Structured (IM.IntMap v) where structure = containerStructure+instance Structured IS.IntSet where structure = nominalStructure+instance (Structured v) => Structured (Seq.Seq v) where structure = containerStructure++instance Structured Time.UTCTime where structure = nominalStructure+instance Structured Time.DiffTime where structure = nominalStructure+instance Structured Time.UniversalTime where structure = nominalStructure+instance Structured Time.NominalDiffTime where structure = nominalStructure+instance Structured Time.Day where structure = nominalStructure+instance Structured Time.TimeZone where structure = nominalStructure+instance Structured Time.TimeOfDay where structure = nominalStructure+instance Structured Time.LocalTime where structure = nominalStructure++-- Proxy isn't Typeable in base-4.8 / base++-- #if __GLASGOW_HASKELL__ >= 800+-- instance (Typeable k, Typeable (a :: k)) => Structured (Proxy a)+-- #else+-- instance (Typeable a) => Structured (Proxy a) where+-- structure p = Structure (typeRep p) 0 "Proxy" [("Proxy",[])]+-- #endif
+ src/Distribution/Utils/UnionFind.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE NondecreasingIndentation #-}+-- | A simple mutable union-find data structure.+--+-- It is used in a unification algorithm for backpack mix-in linking.+--+-- This implementation is based off of the one in \"The Essence of ML Type+-- Inference\". (N.B. the union-find package is also based off of this.)+--+module Distribution.Utils.UnionFind (+ Point,+ fresh,+ find,+ union,+ equivalent,+) where++import Data.STRef+import Control.Monad+import Control.Monad.ST++-- | A variable which can be unified; alternately, this can be thought+-- of as an equivalence class with a distinguished representative.+newtype Point s a = Point (STRef s (Link s a))+ deriving (Eq)++-- | Mutable write to a 'Point'+writePoint :: Point s a -> Link s a -> ST s ()+writePoint (Point v) = writeSTRef v++-- | Read the current value of 'Point'.+readPoint :: Point s a -> ST s (Link s a)+readPoint (Point v) = readSTRef v++-- | The internal data structure for a 'Point', which either records+-- the representative element of an equivalence class, or a link to+-- the 'Point' that actually stores the representative type.+data Link s a+ -- NB: it is too bad we can't say STRef Int#; the weights remain boxed+ = Info {-# UNPACK #-} !(STRef s Int) {-# UNPACK #-} !(STRef s a)+ | Link {-# UNPACK #-} !(Point s a)++-- | Create a fresh equivalence class with one element.+fresh :: a -> ST s (Point s a)+fresh desc = do+ weight <- newSTRef 1+ descriptor <- newSTRef desc+ Point `fmap` newSTRef (Info weight descriptor)++-- | Flatten any chains of links, returning a 'Point'+-- which points directly to the canonical representation.+repr :: Point s a -> ST s (Point s a)+repr point = readPoint point >>= \r ->+ case r of+ Link point' -> do+ point'' <- repr point'+ when (point'' /= point') $ do+ writePoint point =<< readPoint point'+ return point''+ Info _ _ -> return point++-- | Return the canonical element of an equivalence+-- class 'Point'.+find :: Point s a -> ST s a+find point =+ -- Optimize length 0 and 1 case at expense of+ -- general case+ readPoint point >>= \r ->+ case r of+ Info _ d_ref -> readSTRef d_ref+ Link point' -> readPoint point' >>= \r' ->+ case r' of+ Info _ d_ref -> readSTRef d_ref+ Link _ -> repr point >>= find++-- | Unify two equivalence classes, so that they share+-- a canonical element. Keeps the descriptor of point2.+union :: Point s a -> Point s a -> ST s ()+union refpoint1 refpoint2 = do+ point1 <- repr refpoint1+ point2 <- repr refpoint2+ when (point1 /= point2) $ do+ l1 <- readPoint point1+ l2 <- readPoint point2+ case (l1, l2) of+ (Info wref1 dref1, Info wref2 dref2) -> do+ weight1 <- readSTRef wref1+ weight2 <- readSTRef wref2+ -- Should be able to optimize the == case separately+ if weight1 >= weight2+ then do+ writePoint point2 (Link point1)+ -- The weight calculation here seems a bit dodgy+ writeSTRef wref1 (weight1 + weight2)+ writeSTRef dref1 =<< readSTRef dref2+ else do+ writePoint point1 (Link point2)+ writeSTRef wref2 (weight1 + weight2)+ _ -> error "UnionFind.union: repr invariant broken"++-- | Test if two points are in the same equivalence class.+equivalent :: Point s a -> Point s a -> ST s Bool+equivalent point1 point2 = liftM2 (==) (repr point1) (repr point2)
+ src/Distribution/Verbosity.hs view
@@ -0,0 +1,345 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Verbosity+-- Copyright : Ian Lynagh 2007+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- A 'Verbosity' type with associated utilities.+--+-- There are 4 standard verbosity levels from 'silent', 'normal',+-- 'verbose' up to 'deafening'. This is used for deciding what logging+-- messages to print.+--+-- Verbosity also is equipped with some internal settings which can be+-- used to control at a fine granularity the verbosity of specific+-- settings (e.g., so that you can trace only particular things you+-- are interested in.) It's important to note that the instances+-- for 'Verbosity' assume that this does not exist.++-- Verbosity for Cabal functions.++module Distribution.Verbosity (+ -- * Verbosity+ Verbosity,+ silent, normal, verbose, deafening,+ moreVerbose, lessVerbose, isVerboseQuiet,+ intToVerbosity, flagToVerbosity,+ showForCabal, showForGHC,+ verboseNoFlags, verboseHasFlags,+ modifyVerbosity,++ -- * Call stacks+ verboseCallSite, verboseCallStack,+ isVerboseCallSite, isVerboseCallStack,++ -- * Output markets+ verboseMarkOutput, isVerboseMarkOutput,+ verboseUnmarkOutput,++ -- * line-wrapping+ verboseNoWrap, isVerboseNoWrap,++ -- * timestamps+ verboseTimestamp, isVerboseTimestamp,+ verboseNoTimestamp,++ -- * Stderr+ verboseStderr, isVerboseStderr,+ verboseNoStderr,+ ) where++import Prelude ()+import Distribution.Compat.Prelude++import Distribution.ReadE++import Data.List (elemIndex)+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Verbosity.Internal+import Distribution.Utils.Generic (isAsciiAlpha)++import qualified Data.Set as Set+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP++data Verbosity = Verbosity {+ vLevel :: VerbosityLevel,+ vFlags :: Set VerbosityFlag,+ vQuiet :: Bool+ } deriving (Generic, Show, Read, Typeable)++mkVerbosity :: VerbosityLevel -> Verbosity+mkVerbosity l = Verbosity { vLevel = l, vFlags = Set.empty, vQuiet = False }++instance Eq Verbosity where+ x == y = vLevel x == vLevel y++instance Ord Verbosity where+ compare x y = compare (vLevel x) (vLevel y)++instance Enum Verbosity where+ toEnum = mkVerbosity . toEnum+ fromEnum = fromEnum . vLevel++instance Bounded Verbosity where+ minBound = mkVerbosity minBound+ maxBound = mkVerbosity maxBound++instance Binary Verbosity+instance Structured Verbosity++-- We shouldn't print /anything/ unless an error occurs in silent mode+silent :: Verbosity+silent = mkVerbosity Silent++-- Print stuff we want to see by default+normal :: Verbosity+normal = mkVerbosity Normal++-- Be more verbose about what's going on+verbose :: Verbosity+verbose = mkVerbosity Verbose++-- Not only are we verbose ourselves (perhaps even noisier than when+-- being "verbose"), but we tell everything we run to be verbose too+deafening :: Verbosity+deafening = mkVerbosity Deafening++moreVerbose :: Verbosity -> Verbosity+moreVerbose v =+ case vLevel v of+ Silent -> v -- silent should stay silent+ Normal -> v { vLevel = Verbose }+ Verbose -> v { vLevel = Deafening }+ Deafening -> v++lessVerbose :: Verbosity -> Verbosity+lessVerbose v =+ verboseQuiet $+ case vLevel v of+ Deafening -> v -- deafening stays deafening+ Verbose -> v { vLevel = Normal }+ Normal -> v { vLevel = Silent }+ Silent -> v++-- | Combinator for transforming verbosity level while retaining the+-- original hidden state.+--+-- For instance, the following property holds+--+-- prop> isVerboseNoWrap (modifyVerbosity (max verbose) v) == isVerboseNoWrap v+--+-- __Note__: you can use @modifyVerbosity (const v1) v0@ to overwrite+-- @v1@'s flags with @v0@'s flags.+--+-- @since 2.0.1.0+modifyVerbosity :: (Verbosity -> Verbosity) -> Verbosity -> Verbosity+modifyVerbosity f v = v { vLevel = vLevel (f v) }++intToVerbosity :: Int -> Maybe Verbosity+intToVerbosity 0 = Just (mkVerbosity Silent)+intToVerbosity 1 = Just (mkVerbosity Normal)+intToVerbosity 2 = Just (mkVerbosity Verbose)+intToVerbosity 3 = Just (mkVerbosity Deafening)+intToVerbosity _ = Nothing++-- | Parser verbosity+--+-- >>> explicitEitherParsec parsecVerbosity "normal"+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [], vQuiet = False})+--+-- >>> explicitEitherParsec parsecVerbosity "normal+nowrap "+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap], vQuiet = False})+--+-- >>> explicitEitherParsec parsecVerbosity "normal+nowrap +markoutput"+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})+--+-- >>> explicitEitherParsec parsecVerbosity "normal +nowrap +markoutput"+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})+--+-- >>> explicitEitherParsec parsecVerbosity "normal+nowrap+markoutput"+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False})+--+-- >>> explicitEitherParsec parsecVerbosity "deafening+nowrap+stdout+stderr+callsite+callstack"+-- Right (Verbosity {vLevel = Deafening, vFlags = fromList [VCallStack,VCallSite,VNoWrap,VStderr], vQuiet = False})+--+-- /Note:/ this parser will eat trailing spaces.+--+instance Parsec Verbosity where+ parsec = parsecVerbosity++instance Pretty Verbosity where+ pretty = PP.text . showForCabal++parsecVerbosity :: CabalParsing m => m Verbosity+parsecVerbosity = parseIntVerbosity <|> parseStringVerbosity+ where+ parseIntVerbosity = do+ i <- P.integral+ case intToVerbosity i of+ Just v -> return v+ Nothing -> P.unexpected $ "Bad integral verbosity: " ++ show i ++ ". Valid values are 0..3"++ parseStringVerbosity = do+ level <- parseVerbosityLevel+ _ <- P.spaces+ flags <- many (parseFlag <* P.spaces)+ return $ foldl' (flip ($)) (mkVerbosity level) flags++ parseVerbosityLevel = do+ token <- P.munch1 isAsciiAlpha+ case token of+ "silent" -> return Silent+ "normal" -> return Normal+ "verbose" -> return Verbose+ "debug" -> return Deafening+ "deafening" -> return Deafening+ _ -> P.unexpected $ "Bad verbosity level: " ++ token+ parseFlag = do+ _ <- P.char '+'+ token <- P.munch1 isAsciiAlpha+ case token of+ "callsite" -> return verboseCallSite+ "callstack" -> return verboseCallStack+ "nowrap" -> return verboseNoWrap+ "markoutput" -> return verboseMarkOutput+ "timestamp" -> return verboseTimestamp+ "stderr" -> return verboseStderr+ "stdout" -> return verboseNoStderr+ _ -> P.unexpected $ "Bad verbosity flag: " ++ token++flagToVerbosity :: ReadE Verbosity+flagToVerbosity = parsecToReadE id parsecVerbosity++showForCabal :: Verbosity -> String+showForCabal v+ | Set.null (vFlags v)+ = maybe (error "unknown verbosity") show $+ elemIndex v [silent,normal,verbose,deafening]+ | otherwise+ = unwords+ $ showLevel (vLevel v)+ : concatMap showFlag (Set.toList (vFlags v))+ where+ showLevel Silent = "silent"+ showLevel Normal = "normal"+ showLevel Verbose = "verbose"+ showLevel Deafening = "debug"++ showFlag VCallSite = ["+callsite"]+ showFlag VCallStack = ["+callstack"]+ showFlag VNoWrap = ["+nowrap"]+ showFlag VMarkOutput = ["+markoutput"]+ showFlag VTimestamp = ["+timestamp"]+ showFlag VStderr = ["+stderr"]++showForGHC :: Verbosity -> String+showForGHC v = maybe (error "unknown verbosity") show $+ elemIndex v [silent,normal,__,verbose,deafening]+ where __ = silent -- this will be always ignored by elemIndex++-- | Turn on verbose call-site printing when we log.+verboseCallSite :: Verbosity -> Verbosity+verboseCallSite = verboseFlag VCallSite++-- | Turn on verbose call-stack printing when we log.+verboseCallStack :: Verbosity -> Verbosity+verboseCallStack = verboseFlag VCallStack++-- | Turn on @-----BEGIN CABAL OUTPUT-----@ markers for output+-- from Cabal (as opposed to GHC, or system dependent).+verboseMarkOutput :: Verbosity -> Verbosity+verboseMarkOutput = verboseFlag VMarkOutput++-- | Turn off marking; useful for suppressing nondeterministic output.+verboseUnmarkOutput :: Verbosity -> Verbosity+verboseUnmarkOutput = verboseNoFlag VMarkOutput++-- | Disable line-wrapping for log messages.+verboseNoWrap :: Verbosity -> Verbosity+verboseNoWrap = verboseFlag VNoWrap++-- | Mark the verbosity as quiet+verboseQuiet :: Verbosity -> Verbosity+verboseQuiet v = v { vQuiet = True }++-- | Turn on timestamps for log messages.+verboseTimestamp :: Verbosity -> Verbosity+verboseTimestamp = verboseFlag VTimestamp++-- | Turn off timestamps for log messages.+verboseNoTimestamp :: Verbosity -> Verbosity+verboseNoTimestamp = verboseNoFlag VTimestamp++-- | Turn on timestamps for log messages.+--+-- @since 3.4.0.0+verboseStderr :: Verbosity -> Verbosity+verboseStderr = verboseFlag VStderr++-- | Turn off timestamps for log messages.+--+-- @since 3.4.0.0+verboseNoStderr :: Verbosity -> Verbosity+verboseNoStderr = verboseNoFlag VStderr++-- | Helper function for flag enabling functions+verboseFlag :: VerbosityFlag -> (Verbosity -> Verbosity)+verboseFlag flag v = v { vFlags = Set.insert flag (vFlags v) }++-- | Helper function for flag disabling functions+verboseNoFlag :: VerbosityFlag -> (Verbosity -> Verbosity)+verboseNoFlag flag v = v { vFlags = Set.delete flag (vFlags v) }++-- | Turn off all flags+verboseNoFlags :: Verbosity -> Verbosity+verboseNoFlags v = v { vFlags = Set.empty }++verboseHasFlags :: Verbosity -> Bool+verboseHasFlags = not . Set.null . vFlags++-- | Test if we should output call sites when we log.+isVerboseCallSite :: Verbosity -> Bool+isVerboseCallSite = isVerboseFlag VCallSite++-- | Test if we should output call stacks when we log.+isVerboseCallStack :: Verbosity -> Bool+isVerboseCallStack = isVerboseFlag VCallStack++-- | Test if we should output markets.+isVerboseMarkOutput :: Verbosity -> Bool+isVerboseMarkOutput = isVerboseFlag VMarkOutput++-- | Test if line-wrapping is disabled for log messages.+isVerboseNoWrap :: Verbosity -> Bool+isVerboseNoWrap = isVerboseFlag VNoWrap++-- | Test if we had called 'lessVerbose' on the verbosity+isVerboseQuiet :: Verbosity -> Bool+isVerboseQuiet = vQuiet++-- | Test if we should output timestamps when we log.+isVerboseTimestamp :: Verbosity -> Bool+isVerboseTimestamp = isVerboseFlag VTimestamp++-- | Test if we should output to stderr when we log.+--+-- @since 3.4.0.0+isVerboseStderr :: Verbosity -> Bool+isVerboseStderr = isVerboseFlag VStderr++-- | Helper function for flag testing functions.+isVerboseFlag :: VerbosityFlag -> Verbosity -> Bool+isVerboseFlag flag = (Set.member flag) . vFlags++-- $setup+-- >>> import Test.QuickCheck (Arbitrary (..), arbitraryBoundedEnum)+-- >>> instance Arbitrary VerbosityLevel where arbitrary = arbitraryBoundedEnum+-- >>> instance Arbitrary Verbosity where arbitrary = fmap mkVerbosity arbitrary
+ src/Distribution/Verbosity/Internal.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Verbosity.Internal+ ( VerbosityLevel(..)+ , VerbosityFlag(..)+ ) where++import Prelude ()+import Distribution.Compat.Prelude++data VerbosityLevel = Silent | Normal | Verbose | Deafening+ deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable)++instance Binary VerbosityLevel+instance Structured VerbosityLevel++data VerbosityFlag+ = VCallStack+ | VCallSite+ | VNoWrap+ | VMarkOutput+ | VTimestamp+ | VStderr -- ^ @since 3.4.0.0+ deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable)++instance Binary VerbosityFlag+instance Structured VerbosityFlag
+ src/Distribution/Version.hs view
@@ -0,0 +1,185 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Version+-- Copyright : Isaac Jones, Simon Marlow 2003-2004+-- Duncan Coutts 2008+-- License : BSD3+--+-- Maintainer : cabal-devel@haskell.org+-- Portability : portable+--+-- Exports the 'Version' type along with a parser and pretty printer. A version+-- is something like @\"1.3.3\"@. It also defines the 'VersionRange' data+-- types. Version ranges are like @\">= 1.2 && < 2\"@.++module Distribution.Version (+ -- * Package versions+ Version,+ version0,+ mkVersion,+ mkVersion',+ versionNumbers,+ nullVersion,+ alterVersion,++ -- * Version ranges+ VersionRange,++ -- ** Constructing+ anyVersion, noVersion,+ thisVersion, notThisVersion,+ laterVersion, earlierVersion,+ orLaterVersion, orEarlierVersion,+ unionVersionRanges, intersectVersionRanges,+ withinVersion,+ majorBoundVersion,++ -- ** Inspection+ withinRange,+ isAnyVersion,+ isNoVersion,+ isSpecificVersion,+ simplifyVersionRange,+ foldVersionRange,+ normaliseVersionRange,+ stripParensVersionRange,+ hasUpperBound,+ hasLowerBound,++ -- ** Cata & ana+ VersionRangeF (..),+ cataVersionRange,+ anaVersionRange,+ hyloVersionRange,+ projectVersionRange,+ embedVersionRange,++ -- ** Utilities+ wildcardUpperBound,+ majorUpperBound,++ -- ** Modification+ removeUpperBound,+ removeLowerBound,+ transformCaret,+ transformCaretUpper,+ transformCaretLower,++ -- * Version intervals view+ asVersionIntervals,+ VersionInterval(..),+ LowerBound(..),+ UpperBound(..),+ Bound(..),++ -- ** 'VersionIntervals' abstract type+ -- | The 'VersionIntervals' type and the accompanying functions are exposed+ -- primarily for completeness and testing purposes. In practice+ -- 'asVersionIntervals' is the main function to use to+ -- view a 'VersionRange' as a bunch of 'VersionInterval's.+ --+ VersionIntervals,+ toVersionIntervals,+ fromVersionIntervals,+ unVersionIntervals,++ ) where++import Distribution.Types.Version+import Distribution.Types.VersionRange+import Distribution.Types.VersionInterval++-------------------------------------------------------------------------------+-- Utilities on VersionRange requiring VersionInterval+-------------------------------------------------------------------------------++-- | This is the converse of 'isAnyVersion'. It check if the version range is+-- empty, if there is no possible version that satisfies the version range.+--+-- For example this is @True@ (for all @v@):+--+-- > isNoVersion (EarlierVersion v `IntersectVersionRanges` LaterVersion v)+--+isNoVersion :: VersionRange -> Bool+isNoVersion vr = case asVersionIntervals vr of+ [] -> True+ _ -> False++-- | Is this version range in fact just a specific version?+--+-- For example the version range @\">= 3 && <= 3\"@ contains only the version+-- @3@.+--+isSpecificVersion :: VersionRange -> Maybe Version+isSpecificVersion vr = case asVersionIntervals vr of+ [VersionInterval (LowerBound v InclusiveBound) (UpperBound v' InclusiveBound)]+ | v == v' -> Just v+ _ -> Nothing++-------------------------------------------------------------------------------+-- Transformations+-------------------------------------------------------------------------------++-- | Simplify a 'VersionRange' expression. For non-empty version ranges+-- this produces a canonical form. Empty or inconsistent version ranges+-- are left as-is because that provides more information.+--+-- If you need a canonical form use+-- @fromVersionIntervals . toVersionIntervals@+--+-- It satisfies the following properties:+--+-- > withinRange v (simplifyVersionRange r) = withinRange v r+--+-- > withinRange v r = withinRange v r'+-- > ==> simplifyVersionRange r = simplifyVersionRange r'+-- > || isNoVersion r+-- > || isNoVersion r'+--+simplifyVersionRange :: VersionRange -> VersionRange+simplifyVersionRange vr+ -- If the version range is inconsistent then we just return the+ -- original since that has more information than ">1 && < 1", which+ -- is the canonical inconsistent version range.+ | null (unVersionIntervals vi) = vr+ | otherwise = fromVersionIntervals vi+ where+ vi = toVersionIntervals vr++-- | Given a version range, remove the highest upper bound. Example: @(>= 1 && <+-- 3) || (>= 4 && < 5)@ is converted to @(>= 1 && < 3) || (>= 4)@.+removeUpperBound :: VersionRange -> VersionRange+removeUpperBound = fromVersionIntervals . relaxLastInterval . toVersionIntervals++-- | Given a version range, remove the lowest lower bound.+-- Example: @(>= 1 && < 3) || (>= 4 && < 5)@ is converted to+-- @(>= 0 && < 3) || (>= 4 && < 5)@.+removeLowerBound :: VersionRange -> VersionRange+removeLowerBound = fromVersionIntervals . relaxHeadInterval . toVersionIntervals++-- | Rewrite @^>= x.y.z@ into @>= x.y.z && < x.(y+1)@+--+-- @since 3.6.0.0+--+transformCaret :: VersionRange -> VersionRange+transformCaret = hyloVersionRange embed projectVersionRange where+ embed (MajorBoundVersionF v) = orLaterVersion v `intersectVersionRanges` earlierVersion (majorUpperBound v)+ embed vr = embedVersionRange vr++-- | Rewrite @^>= x.y.z@ into @>= x.y.z@+--+-- @since 3.6.0.0+--+transformCaretUpper :: VersionRange -> VersionRange+transformCaretUpper = hyloVersionRange embed projectVersionRange where+ embed (MajorBoundVersionF v) = orLaterVersion v+ embed vr = embedVersionRange vr++-- | Rewrite @^>= x.y.z@ into @<x.(y+1)@+--+-- @since 3.6.0.0+--+transformCaretLower :: VersionRange -> VersionRange+transformCaretLower = hyloVersionRange embed projectVersionRange where+ embed (MajorBoundVersionF v) = earlierVersion (majorUpperBound v)+ embed vr = embedVersionRange vr
+ src/Distribution/ZinzaPrelude.hs view
@@ -0,0 +1,43 @@+-- | A small prelude used in @zinza@ generated+-- template modules.+module Distribution.ZinzaPrelude (+ Writer,+ execWriter,+ tell,+ -- * Re-exports+ forM_,+ Generic,+ PackageName,+ Version,+ prettyShow+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Control.Monad (forM_)+import Distribution.Pretty (prettyShow)+import Distribution.Types.PackageName (PackageName)+import Distribution.Types.Version (Version)++newtype Writer a = W { unW :: ShowS -> (ShowS, a) }++instance Functor Writer where+ fmap = liftM++instance Applicative Writer where+ pure x = W $ \ss -> (ss, x)+ (<*>) = ap++instance Monad Writer where+ return = pure+ m >>= k = W $ \s1 ->+ let (s2, x) = unW m s1+ in unW (k x) s2+ {-# INLINE (>>=) #-}++execWriter :: Writer a -> String+execWriter w = fst (unW w id) ""++tell :: String -> Writer ()+tell s = W $ \s' -> (s' . showString s, ())
+ src/Language/Haskell/Extension.hs view
@@ -0,0 +1,933 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------+-- |+-- Module : Language.Haskell.Extension+-- Copyright : Isaac Jones 2003-2004+-- License : BSD3+--+-- Maintainer : libraries@haskell.org+-- Portability : portable+--+-- Haskell language dialects and extensions++module Language.Haskell.Extension (+ Language(..),+ knownLanguages,+ classifyLanguage,++ Extension(..),+ KnownExtension(..),+ deprecatedExtensions,+ classifyExtension,+ ) where++import qualified Prelude (head)+import Distribution.Compat.Prelude++import Data.Array (Array, accumArray, bounds, Ix(inRange), (!))++import Distribution.Parsec+import Distribution.Pretty++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- ------------------------------------------------------------+-- * Language+-- ------------------------------------------------------------++-- | This represents a Haskell language dialect.+--+-- Language 'Extension's are interpreted relative to one of these base+-- languages.+--+data Language =++ -- | The Haskell 98 language as defined by the Haskell 98 report.+ -- <http://haskell.org/onlinereport/>+ Haskell98++ -- | The Haskell 2010 language as defined by the Haskell 2010 report.+ -- <http://www.haskell.org/onlinereport/haskell2010>+ | Haskell2010++ -- | The GHC2021 collection of language extensions.+ -- <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0380-ghc2021.rst>+ | GHC2021++ -- | An unknown language, identified by its name.+ | UnknownLanguage String+ deriving (Generic, Show, Read, Eq, Typeable, Data)++instance Binary Language+instance Structured Language++instance NFData Language where rnf = genericRnf++-- | List of known (supported) languages for GHC+knownLanguages :: [Language]+knownLanguages = [Haskell98, Haskell2010, GHC2021]++instance Pretty Language where+ pretty (UnknownLanguage other) = Disp.text other+ pretty other = Disp.text (show other)++instance Parsec Language where+ parsec = classifyLanguage <$> P.munch1 isAlphaNum++classifyLanguage :: String -> Language+classifyLanguage = \str -> case lookup str langTable of+ Just lang -> lang+ Nothing -> UnknownLanguage str+ where+ langTable = [ (show lang, lang)+ | lang <- knownLanguages ]++-- ------------------------------------------------------------+-- * Extension+-- ------------------------------------------------------------++-- Note: if you add a new 'KnownExtension':+--+-- * also add it to the Distribution.Simple.X.languageExtensions lists+-- (where X is each compiler: GHC, UHC, HaskellSuite)+--+-- | This represents language extensions beyond a base 'Language' definition+-- (such as 'Haskell98') that are supported by some implementations, usually+-- in some special mode.+--+-- Where applicable, references are given to an implementation's+-- official documentation.++data Extension =+ -- | Enable a known extension+ EnableExtension KnownExtension++ -- | Disable a known extension+ | DisableExtension KnownExtension++ -- | An unknown extension, identified by the name of its @LANGUAGE@+ -- pragma.+ | UnknownExtension String++ deriving (Generic, Show, Read, Eq, Ord, Typeable, Data)++instance Binary Extension+instance Structured Extension++instance NFData Extension where rnf = genericRnf++data KnownExtension =++ -- | Allow overlapping class instances, provided there is a unique+ -- most specific instance for each use.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XOverlappingInstances>+ OverlappingInstances++ -- | Ignore structural rules guaranteeing the termination of class+ -- instance resolution. Termination is guaranteed by a fixed-depth+ -- recursion stack, and compilation may fail if this depth is+ -- exceeded.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XUndecidableInstances>+ | UndecidableInstances++ -- | Implies 'OverlappingInstances'. Allow the implementation to+ -- choose an instance even when it is possible that further+ -- instantiation of types will lead to a more specific instance+ -- being applicable.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XIncoherentInstances>+ | IncoherentInstances++ -- | /(deprecated)/ Deprecated in favour of 'RecursiveDo'.+ --+ -- Old description: Allow recursive bindings in @do@ blocks, using+ -- the @rec@ keyword. See also 'RecursiveDo'.+ | DoRec++ -- | Allow recursive bindings in @do@ blocks, using the @rec@+ -- keyword, or @mdo@, a variant of @do@.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRecursiveDo>+ | RecursiveDo++ -- | Provide syntax for writing list comprehensions which iterate+ -- over several lists together, like the 'zipWith' family of+ -- functions.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XParallelListComp>+ | ParallelListComp++ -- | Allow multiple parameters in a type class.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMultiParamTypeClasses>+ | MultiParamTypeClasses++ -- | Enable the dreaded monomorphism restriction.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNoMonomorphismRestriction>+ | MonomorphismRestriction++ -- | Allow a specification attached to a multi-parameter type class+ -- which indicates that some parameters are entirely determined by+ -- others. The implementation will check that this property holds+ -- for the declared instances, and will use this property to reduce+ -- ambiguity in instance resolution.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XFunctionalDependencies>+ | FunctionalDependencies++ -- | /(deprecated)/ A synonym for 'RankNTypes'.+ --+ -- Old description: Like 'RankNTypes' but does not allow a+ -- higher-rank type to itself appear on the left of a function+ -- arrow.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRank2Types>+ | Rank2Types++ -- | Allow a universally-quantified type to occur on the left of a+ -- function arrow.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRankNTypes>+ | RankNTypes++ -- | /(deprecated)/ A synonym for 'RankNTypes'.+ --+ -- Old description: Allow data constructors to have polymorphic+ -- arguments. Unlike 'RankNTypes', does not allow this for ordinary+ -- functions.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#arbitrary-rank-polymorphism>+ | PolymorphicComponents++ -- | Allow existentially-quantified data constructors.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XExistentialQuantification>+ | ExistentialQuantification++ -- | Cause a type variable in a signature, which has an explicit+ -- @forall@ quantifier, to scope over the definition of the+ -- accompanying value declaration.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XScopedTypeVariables>+ | ScopedTypeVariables++ -- | Deprecated, use 'ScopedTypeVariables' instead.+ | PatternSignatures++ -- | Enable implicit function parameters with dynamic scope.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XImplicitParams>+ | ImplicitParams++ -- | Relax some restrictions on the form of the context of a type+ -- signature.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XFlexibleContexts>+ | FlexibleContexts++ -- | Relax some restrictions on the form of the context of an+ -- instance declaration.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XFlexibleInstances>+ | FlexibleInstances++ -- | Allow data type declarations with no constructors.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XEmptyDataDecls>+ | EmptyDataDecls++ -- | Run the C preprocessor on Haskell source code.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#language-pragma>+ | CPP++ -- | Allow an explicit kind signature giving the kind of types over+ -- which a type variable ranges.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XKindSignatures>+ | KindSignatures++ -- | Enable a form of pattern which forces evaluation before an+ -- attempted match, and a form of strict @let@/@where@ binding.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XBangPatterns>+ | BangPatterns++ -- | Allow type synonyms in instance heads.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTypeSynonymInstances>+ | TypeSynonymInstances++ -- | Enable Template Haskell, a system for compile-time+ -- metaprogramming.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTemplateHaskell>+ | TemplateHaskell++ -- | Enable the Foreign Function Interface. In GHC, implements the+ -- standard Haskell 98 Foreign Function Interface Addendum, plus+ -- some GHC-specific extensions.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#language-pragma>+ | ForeignFunctionInterface++ -- | Enable arrow notation.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XArrows>+ | Arrows++ -- | /(deprecated)/ Enable generic type classes, with default instances defined in+ -- terms of the algebraic structure of a type.+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#generic-classes>+ | Generics++ -- | Enable the implicit importing of the module "Prelude". When+ -- disabled, when desugaring certain built-in syntax into ordinary+ -- identifiers, use whatever is in scope rather than the "Prelude"+ -- -- version.+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#rebindable-syntax-and-the-implicit-prelude-import>+ | ImplicitPrelude++ -- | Enable syntax for implicitly binding local names corresponding+ -- to the field names of a record. Puns bind specific names, unlike+ -- 'RecordWildCards'.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNamedFieldPuns>+ | NamedFieldPuns++ -- | Enable a form of guard which matches a pattern and binds+ -- variables.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPatternGuards>+ | PatternGuards++ -- | Allow a type declared with @newtype@ to use @deriving@ for any+ -- class with an instance for the underlying type.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XGeneralizedNewtypeDeriving>+ | GeneralizedNewtypeDeriving++ -- Synonym for GeneralizedNewtypeDeriving added in GHC 8.6.1.+ | GeneralisedNewtypeDeriving++ -- | Enable the \"Trex\" extensible records system.+ --+ -- * <http://haskell.org/hugs/pages/users_guide/hugs-only.html#TREX>+ | ExtensibleRecords++ -- | Enable type synonyms which are transparent in some definitions+ -- and opaque elsewhere, as a way of implementing abstract+ -- datatypes.+ --+ -- * <http://haskell.org/hugs/pages/users_guide/restricted-synonyms.html>+ | RestrictedTypeSynonyms++ -- | Enable an alternate syntax for string literals,+ -- with string templating.+ --+ -- * <http://haskell.org/hugs/pages/users_guide/here-documents.html>+ | HereDocuments++ -- | Allow the character @#@ as a postfix modifier on identifiers.+ -- Also enables literal syntax for unboxed values.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMagicHash>+ | MagicHash++ -- | Allow data types and type synonyms which are indexed by types,+ -- i.e. ad-hoc polymorphism for types.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTypeFamilies>+ | TypeFamilies++ -- | Allow a standalone declaration which invokes the type class+ -- @deriving@ mechanism.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XStandaloneDeriving>+ | StandaloneDeriving++ -- | Allow certain Unicode characters to stand for certain ASCII+ -- character sequences, e.g. keywords and punctuation.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XUnicodeSyntax>+ | UnicodeSyntax++ -- | Allow the use of unboxed types as foreign types, e.g. in+ -- @foreign import@ and @foreign export@.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#language-options>+ | UnliftedFFITypes++ -- | Enable interruptible FFI.+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/ffi-chap.html#interruptible-foreign-calls>+ | InterruptibleFFI++ -- | Allow use of CAPI FFI calling convention (@foreign import capi@).+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/ffi-chap.html#the-capi-calling-convention>+ | CApiFFI++ -- | Defer validity checking of types until after expanding type+ -- synonyms, relaxing the constraints on how synonyms may be used.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XLiberalTypeSynonyms>+ | LiberalTypeSynonyms++ -- | Allow the name of a type constructor, type class, or type+ -- variable to be an infix operator.+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTypeOperators>+ | TypeOperators++ -- | Enable syntax for implicitly binding local names corresponding+ -- to the field names of a record. A wildcard binds all unmentioned+ -- names, unlike 'NamedFieldPuns'.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRecordWildCards>+ | RecordWildCards++ -- | Deprecated, use 'NamedFieldPuns' instead.+ | RecordPuns++ -- | Allow a record field name to be disambiguated by the type of+ -- the record it's in.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDisambiguateRecordFields>+ | DisambiguateRecordFields++ -- | Enable traditional record syntax (as supported by Haskell 98)+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#traditional-record-syntax>+ | TraditionalRecordSyntax++ -- | Enable overloading of string literals using a type class, much+ -- like integer literals.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XOverloadedStrings>+ | OverloadedStrings++ -- | Enable generalized algebraic data types, in which type+ -- variables may be instantiated on a per-constructor basis. Implies+ -- 'GADTSyntax'.+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#generalised-algebraic-data-types-gadts>+ | GADTs++ -- | Enable GADT syntax for declaring ordinary algebraic datatypes.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XGADTSyntax>+ | GADTSyntax++ -- | /(deprecated)/ Has no effect.+ --+ -- Old description: Make pattern bindings monomorphic.+ --+ -- * <https://downloads.haskell.org/~ghc/7.6.3/docs/html/users_guide/monomorphism.html>+ | MonoPatBinds++ -- | Relax the requirements on mutually-recursive polymorphic+ -- functions.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRelaxedPolyRec>+ | RelaxedPolyRec++ -- | Allow default instantiation of polymorphic types in more+ -- situations.+ --+ -- * <http://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#type-defaulting-in-ghci>+ | ExtendedDefaultRules++ -- | Enable unboxed tuples.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XUnboxedTuples>+ | UnboxedTuples++ -- | Enable @deriving@ for classes 'Data.Typeable.Typeable' and+ -- 'Data.Generics.Data'.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveDataTypeable>+ | DeriveDataTypeable++ -- | Enable @deriving@ for 'GHC.Generics.Generic' and 'GHC.Generics.Generic1'.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveGeneric>+ | DeriveGeneric++ -- | Enable support for default signatures.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDefaultSignatures>+ | DefaultSignatures++ -- | Allow type signatures to be specified in instance declarations.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XInstanceSigs>+ | InstanceSigs++ -- | Allow a class method's type to place additional constraints on+ -- a class type variable.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XConstrainedClassMethods>+ | ConstrainedClassMethods++ -- | Allow imports to be qualified by the package name the module is+ -- intended to be imported from, e.g.+ --+ -- > import "network" Network.Socket+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPackageImports>+ | PackageImports++ -- | /(deprecated)/ Allow a type variable to be instantiated at a+ -- polymorphic type.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XImpredicativeTypes>+ | ImpredicativeTypes++ -- | /(deprecated)/ Change the syntax for qualified infix operators.+ --+ -- * <http://www.haskell.org/ghc/docs/6.12.3/html/users_guide/syntax-extns.html#new-qualified-operators>+ | NewQualifiedOperators++ -- | Relax the interpretation of left operator sections to allow+ -- unary postfix operators.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPostfixOperators>+ | PostfixOperators++ -- | Enable quasi-quotation, a mechanism for defining new concrete+ -- syntax for expressions and patterns.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XQuasiQuotes>+ | QuasiQuotes++ -- | Enable generalized list comprehensions, supporting operations+ -- such as sorting and grouping.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTransformListComp>+ | TransformListComp++ -- | Enable monad comprehensions, which generalise the list+ -- comprehension syntax to work for any monad.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMonadComprehensions>+ | MonadComprehensions++ -- | Enable view patterns, which match a value by applying a+ -- function and matching on the result.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XViewPatterns>+ | ViewPatterns++ -- | Allow concrete XML syntax to be used in expressions and patterns,+ -- as per the Haskell Server Pages extension language:+ -- <http://www.haskell.org/haskellwiki/HSP>. The ideas behind it are+ -- discussed in the paper \"Haskell Server Pages through Dynamic Loading\"+ -- by Niklas Broberg, from Haskell Workshop '05.+ | XmlSyntax++ -- | Allow regular pattern matching over lists, as discussed in the+ -- paper \"Regular Expression Patterns\" by Niklas Broberg, Andreas Farre+ -- and Josef Svenningsson, from ICFP '04.+ | RegularPatterns++ -- | Enable the use of tuple sections, e.g. @(, True)@ desugars into+ -- @\x -> (x, True)@.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XTupleSections>+ | TupleSections++ -- | Allow GHC primops, written in C--, to be imported into a Haskell+ -- file.+ | GHCForeignImportPrim++ -- | Support for patterns of the form @n + k@, where @k@ is an+ -- integer literal.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNPlusKPatterns>+ | NPlusKPatterns++ -- | Improve the layout rule when @if@ expressions are used in a @do@+ -- block.+ | DoAndIfThenElse++ -- | Enable support for multi-way @if@-expressions.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMultiWayIf>+ | MultiWayIf++ -- | Enable support lambda-@case@ expressions.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XLambdaCase>+ | LambdaCase++ -- | Makes much of the Haskell sugar be desugared into calls to the+ -- function with a particular name that is in scope.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRebindableSyntax>+ | RebindableSyntax++ -- | Make @forall@ a keyword in types, which can be used to give the+ -- generalisation explicitly.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XExplicitForAll>+ | ExplicitForAll++ -- | Allow contexts to be put on datatypes, e.g. the @Eq a@ in+ -- @data Eq a => Set a = NilSet | ConsSet a (Set a)@.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDatatypeContexts>+ | DatatypeContexts++ -- | Local (@let@ and @where@) bindings are monomorphic.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XMonoLocalBinds>+ | MonoLocalBinds++ -- | Enable @deriving@ for the 'Data.Functor.Functor' class.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveFunctor>+ | DeriveFunctor++ -- | Enable @deriving@ for the 'Data.Traversable.Traversable' class.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveTraversable>+ | DeriveTraversable++ -- | Enable @deriving@ for the 'Data.Foldable.Foldable' class.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveFoldable>+ | DeriveFoldable++ -- | Enable non-decreasing indentation for @do@ blocks.+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/bugs.html#context-free-syntax>+ | NondecreasingIndentation++ -- | Allow imports to be qualified with a safe keyword that requires+ -- the imported module be trusted as according to the Safe Haskell+ -- definition of trust.+ --+ -- > import safe Network.Socket+ --+ -- * <https://haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#safe-imports>+ | SafeImports++ -- | Compile a module in the Safe, Safe Haskell mode -- a restricted+ -- form of the Haskell language to ensure type safety.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/safe_haskell.html#ghc-flag--XSafe>+ | Safe++ -- | Compile a module in the Trustworthy, Safe Haskell mode -- no+ -- restrictions apply but the module is marked as trusted as long as+ -- the package the module resides in is trusted.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/safe_haskell.html#ghc-flag--XTrustworthy>+ | Trustworthy++ -- | Compile a module in the Unsafe, Safe Haskell mode so that+ -- modules compiled using Safe, Safe Haskell mode can't import it.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/safe_haskell.html#ghc-flag--XUnsafe>+ | Unsafe++ -- | Allow type class/implicit parameter/equality constraints to be+ -- used as types with the special kind constraint. Also generalise+ -- the @(ctxt => ty)@ syntax so that any type of kind constraint can+ -- occur before the arrow.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XConstraintKinds>+ | ConstraintKinds++ -- | Enable kind polymorphism.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPolyKinds>+ | PolyKinds++ -- | Enable datatype promotion.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDataKinds>+ | DataKinds++ -- | Enable parallel arrays syntax (@[:@, @:]@) for /Data Parallel Haskell/.+ --+ -- * <http://www.haskell.org/haskellwiki/GHC/Data_Parallel_Haskell>+ | ParallelArrays++ -- | Enable explicit role annotations, like in (@type role Foo representational representational@).+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XRoleAnnotations>+ | RoleAnnotations++ -- | Enable overloading of list literals, arithmetic sequences and+ -- list patterns using the 'IsList' type class.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XOverloadedLists>+ | OverloadedLists++ -- | Enable case expressions that have no alternatives. Also applies to lambda-case expressions if they are enabled.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XEmptyCase>+ | EmptyCase++ -- | /(deprecated)/ Deprecated in favour of 'DeriveDataTypeable'.+ --+ -- Old description: Triggers the generation of derived 'Typeable'+ -- instances for every datatype and type class declaration.+ --+ -- * <https://haskell.org/ghc/docs/7.8.4/html/users_guide/deriving.html#auto-derive-typeable>+ | AutoDeriveTypeable++ -- | Desugars negative literals directly (without using negate).+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNegativeLiterals>+ | NegativeLiterals++ -- | Allow the use of binary integer literal syntax (e.g. @0b11001001@ to denote @201@).+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XBinaryLiterals>+ | BinaryLiterals++ -- | Allow the use of floating literal syntax for all instances of 'Num', including 'Int' and 'Integer'.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNumDecimals>+ | NumDecimals++ -- | Enable support for type classes with no type parameter.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNullaryTypeClasses>+ | NullaryTypeClasses++ -- | Enable explicit namespaces in module import/export lists.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XExplicitNamespaces>+ | ExplicitNamespaces++ -- | Allow the user to write ambiguous types, and the type inference engine to infer them.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XAllowAmbiguousTypes>+ | AllowAmbiguousTypes++ -- | Enable @foreign import javascript@.+ | JavaScriptFFI++ -- | Allow giving names to and abstracting over patterns.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPatternSynonyms>+ | PatternSynonyms++ -- | Allow anonymous placeholders (underscore) inside type signatures. The+ -- type inference engine will generate a message describing the type inferred+ -- at the hole's location.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XPartialTypeSignatures>+ | PartialTypeSignatures++ -- | Allow named placeholders written with a leading underscore inside type+ -- signatures. Wildcards with the same name unify to the same type.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XNamedWildCards>+ | NamedWildCards++ -- | Enable @deriving@ for any class.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveAnyClass>+ | DeriveAnyClass++ -- | Enable @deriving@ for the 'Language.Haskell.TH.Syntax.Lift' class.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XDeriveLift>+ | DeriveLift++ -- | Enable support for 'static pointers' (and the @static@+ -- keyword) to refer to globally stable names, even across+ -- different programs.+ --+ -- * <https://www.haskell.org/ghc/docs/latest/html/users_guide/glasgow_exts.html#ghc-flag--XStaticPointers>+ | 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 @~@.+ --+ -- * <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#ghc-flag--XStrictData>+ | 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@.+ --+ -- * <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#ghc-flag--XStrict>+ | 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 undecidable) 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 quoting.+ | TemplateHaskellQuotes++ -- | Allows use of the @#label@ syntax.+ | OverloadedLabels++ -- | Allow functional dependency annotations on type families to declare them+ -- as injective.+ | TypeFamilyDependencies++ -- | Allow multiple @deriving@ clauses, each optionally qualified with a+ -- /strategy/.+ | DerivingStrategies++ -- | Enable deriving instances via types of the same runtime representation.+ -- Implies 'DerivingStrategies'.+ | DerivingVia++ -- | Enable the use of unboxed sum syntax.+ | UnboxedSums++ -- | Allow use of hexadecimal literal notation for floating-point values.+ | HexFloatLiterals++ -- | Allow @do@ blocks etc. in argument position.+ | BlockArguments++ -- | Allow use of underscores in numeric literals.+ | NumericUnderscores++ -- | Allow @forall@ in constraints.+ | QuantifiedConstraints++ -- | Have @*@ refer to @Type@.+ | StarIsType++ -- | Liberalises deriving to provide instances for empty data types.+ --+ -- * <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#deriving-instances-for-empty-data-types>+ | EmptyDataDeriving++ -- | Enable detection of complete user-supplied kind signatures.+ | CUSKs++ -- | Allows the syntax @import M qualified@.+ | ImportQualifiedPost++ -- | Allow the use of standalone kind signatures.+ | StandaloneKindSignatures++ -- | Enable unlifted newtypes.+ | UnliftedNewtypes++ -- | Use whitespace to determine whether the minus sign stands for negation or subtraction.+ | LexicalNegation++ -- | Enable qualified do-notation desugaring.+ | QualifiedDo++ -- | Enable linear types.+ | LinearTypes++ -- | Enable the generation of selector functions corresponding to record fields.+ | FieldSelectors++ -- | Enable the use of record dot-accessor and updater syntax+ | OverloadedRecordDot++ -- | Enable data types for which an unlifted or levity-polymorphic result kind is inferred.+ | UnliftedDatatypes++ deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable, Data)++instance Binary KnownExtension+instance Structured KnownExtension++instance NFData KnownExtension where rnf = genericRnf++-- | Extensions that have been deprecated, possibly paired with another+-- extension that replaces it.+--+deprecatedExtensions :: [(Extension, Maybe Extension)]+deprecatedExtensions =+ [ (EnableExtension RecordPuns, Just (EnableExtension NamedFieldPuns))+ , (EnableExtension PatternSignatures, Just (EnableExtension ScopedTypeVariables))+ ]+-- NOTE: when adding deprecated extensions that have new alternatives+-- we must be careful to make sure that the deprecation messages are+-- valid. We must not recommend aliases that cannot be used with older+-- compilers, perhaps by adding support in Cabal to translate the new+-- name to the old one for older compilers. Otherwise we are in danger+-- of the scenario in ticket #689.++instance Pretty Extension where+ pretty (UnknownExtension other) = Disp.text other+ pretty (EnableExtension ke) = Disp.text (show ke)+ pretty (DisableExtension ke) = Disp.text ("No" ++ show ke)++instance Parsec Extension where+ parsec = classifyExtension <$> P.munch1 isAlphaNum++instance Pretty KnownExtension where+ pretty ke = Disp.text (show ke)++classifyExtension :: String -> Extension+classifyExtension string+ = case classifyKnownExtension string of+ Just ext -> EnableExtension ext+ Nothing ->+ case string of+ 'N':'o':string' ->+ case classifyKnownExtension string' of+ Just ext -> DisableExtension ext+ Nothing -> UnknownExtension string+ _ -> UnknownExtension string++-- | 'read' for 'KnownExtension's is really really slow so for the Text+-- instance+-- what we do is make a simple table indexed off the first letter in the+-- extension name. The extension names actually cover the range @'A'-'Z'@+-- pretty densely and the biggest bucket is 7 so it's not too bad. We just do+-- a linear search within each bucket.+--+-- This gives an order of magnitude improvement in parsing speed, and it'll+-- also allow us to do case insensitive matches in future if we prefer.+--+classifyKnownExtension :: String -> Maybe KnownExtension+classifyKnownExtension "" = Nothing+classifyKnownExtension string@(c : _)+ | inRange (bounds knownExtensionTable) c+ = lookup string (knownExtensionTable ! c)+ | otherwise = Nothing++knownExtensionTable :: Array Char [(String, KnownExtension)]+knownExtensionTable =+ accumArray (flip (:)) [] ('A', 'Z')+ [ (Prelude.head str, (str, extension)) -- assume KnownExtension's Show returns a non-empty string+ | extension <- [toEnum 0 ..]+ , let str = show extension ]
− tests/CheckTests.hs
@@ -1,98 +0,0 @@-module Main- ( main- ) where--import Test.Tasty-import Test.Tasty.Golden.Advanced (goldenTest)--import Data.Algorithm.Diff (PolyDiff (..), getGroupedDiff)-import Distribution.Fields (runParseResult)-import Distribution.PackageDescription.Check (checkPackage)-import Distribution.PackageDescription.Parsec (parseGenericPackageDescription)-import Distribution.Parsec-import Distribution.Utils.Generic (fromUTF8BS, toUTF8BS)-import System.Directory (setCurrentDirectory)-import System.Environment (getArgs, withArgs)-import System.FilePath (replaceExtension, (</>))--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS8-import qualified Data.List.NonEmpty as NE--tests :: TestTree-tests = checkTests------------------------------------------------------------------------------------ Regressions----------------------------------------------------------------------------------checkTests :: TestTree-checkTests = testGroup "regressions"- [ checkTest "nothing-unicode.cabal"- , checkTest "haddock-api-2.18.1-check.cabal"- , checkTest "issue-774.cabal"- , checkTest "extensions-paths-5054.cabal"- , checkTest "pre-1.6-glob.cabal"- , checkTest "pre-2.4-globstar.cabal"- , checkTest "bad-glob-syntax.cabal"- , checkTest "cc-options-with-optimization.cabal"- , checkTest "cxx-options-with-optimization.cabal"- , checkTest "ghc-option-j.cabal"- , checkTest "multiple-libs-2.cabal"- , checkTest "assoc-cpp-options.cabal"- , checkTest "public-multilib-1.cabal"- , checkTest "public-multilib-2.cabal"- , checkTest "issue-6288-a.cabal"- , checkTest "issue-6288-b.cabal"- , checkTest "issue-6288-c.cabal"- , checkTest "issue-6288-d.cabal"- , checkTest "issue-6288-e.cabal"- , checkTest "issue-6288-f.cabal"- , checkTest "denormalised-paths.cabal"- ]--checkTest :: FilePath -> TestTree-checkTest fp = cabalGoldenTest fp correct $ do- contents <- BS.readFile input- let res = parseGenericPackageDescription contents- let (ws, x) = runParseResult res-- return $ toUTF8BS $ case x of- Right gpd ->- -- Note: parser warnings are reported by `cabal check`, but not by- -- D.PD.Check functionality.- unlines (map (showPWarning fp) ws) ++- unlines (map show (checkPackage gpd Nothing))- Left (_, errs) -> unlines $ map (("ERROR: " ++) . showPError fp) $ NE.toList errs- where- input = "tests" </> "ParserTests" </> "regressions" </> fp- correct = replaceExtension input "check"------------------------------------------------------------------------------------ Main----------------------------------------------------------------------------------main :: IO ()-main = do- args <- getArgs- case args of- ("--cwd" : cwd : args') -> do- setCurrentDirectory cwd- withArgs args' $ defaultMain tests- _ -> defaultMain tests--cabalGoldenTest :: TestName -> FilePath -> IO BS.ByteString -> TestTree-cabalGoldenTest name ref act = goldenTest name (BS.readFile ref) act cmp upd- where- upd = BS.writeFile ref- cmp x y | x == y = return Nothing- cmp x y = return $ Just $ unlines $- concatMap f (getGroupedDiff (BS8.lines x) (BS8.lines y))- where- f (First xs) = map (cons3 '-' . fromUTF8BS) xs- f (Second ys) = map (cons3 '+' . fromUTF8BS) ys- -- we print unchanged lines too. It shouldn't be a problem while we have- -- reasonably small examples- f (Both xs _) = map (cons3 ' ' . fromUTF8BS) xs- -- we add three characters, so the changed lines are easier to spot- cons3 c cs = c : c : c : ' ' : cs
− tests/HackageTests.hs
@@ -1,431 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-#if !MIN_VERSION_deepseq(1,4,0)-{-# OPTIONS_GHC -fno-warn-orphans #-}-#endif--module Main where--import Distribution.Compat.Semigroup-import Prelude ()-import Prelude.Compat--import Control.Applicative (many, (<**>), (<|>))-import Control.DeepSeq (NFData (..), force)-import Control.Exception (evaluate)-import Control.Monad (join, unless, when)-import Data.Foldable (traverse_)-import Data.List (isPrefixOf, isSuffixOf)-import Data.Maybe (mapMaybe)-import Data.Monoid (Sum (..))-import Distribution.PackageDescription.Check (PackageCheck (..), checkPackage)-import Distribution.PackageDescription.PrettyPrint (showGenericPackageDescription)-import Distribution.PackageDescription.Quirks (patchQuirks)-import Distribution.Simple.Utils (fromUTF8BS, toUTF8BS)-import Numeric (showFFloat)-import System.Directory (getAppUserDataDirectory)-import System.Environment (lookupEnv)-import System.Exit (exitFailure)-import System.FilePath ((</>))--import Data.Orphans ()--import qualified Codec.Archive.Tar as Tar-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as B8-import qualified Data.ByteString.Lazy as BSL-import qualified Distribution.Fields.Parser as Parsec-import qualified Distribution.Fields.Pretty as PP-import qualified Distribution.PackageDescription.Parsec as Parsec-import qualified Distribution.Parsec as Parsec-import qualified Options.Applicative as O-import qualified System.Clock as Clock--import Distribution.Compat.Lens-import qualified Distribution.Types.GenericPackageDescription.Lens as L-import qualified Distribution.Types.PackageDescription.Lens as L---- import Distribution.Types.BuildInfo (BuildInfo (cppOptions))--- import qualified Distribution.Types.BuildInfo.Lens as L--#ifdef MIN_VERSION_tree_diff-import Data.TreeDiff (ediff)-import Data.TreeDiff.Instances.Cabal ()-import Data.TreeDiff.Pretty (ansiWlEditExprCompact)-#endif------------------------------------------------------------------------------------ parseIndex: Index traversal----------------------------------------------------------------------------------parseIndex :: (Monoid a, NFData a) => (FilePath -> Bool)- -> (FilePath -> B.ByteString -> IO a) -> IO a-parseIndex predicate action = do- cabalDir <- getAppUserDataDirectory "cabal"- configPath <- getCabalConfigPath cabalDir- cfg <- B.readFile configPath- cfgFields <- either (fail . show) pure $ Parsec.readFields cfg- let repos = reposFromConfig cfgFields- repoCache = case lookupInConfig "remote-repo-cache" cfgFields of- [] -> cabalDir </> "packages" -- Default- (rrc : _) -> rrc -- User-specified- tarName repo = repoCache </> repo </> "01-index.tar"- mconcat <$> traverse (parseIndex' predicate action . tarName) repos- where- getCabalConfigPath cabalDir = do- mx <- lookupEnv "CABAL_CONFIG"- case mx of- Just x -> return x- Nothing -> return (cabalDir </> "config")---parseIndex'- :: (Monoid a, NFData a)- => (FilePath -> Bool)- -> (FilePath -> B.ByteString -> IO a) -> FilePath -> IO a-parseIndex' predicate action path = do- putStrLn $ "Reading index from: " ++ path- contents <- BSL.readFile path- let entries = Tar.read contents- entries' = Tar.foldEntries cons [] (error . show) entries- foldIO f entries'-- where- cons entry entries- | predicate (Tar.entryPath entry) = entry : entries- | otherwise = entries-- f entry = case Tar.entryContent entry of- Tar.NormalFile contents _- | ".cabal" `isSuffixOf` fpath -> do- bs <- evaluate (BSL.toStrict contents)- res <- action fpath bs- evaluate (force res)- | otherwise ->- return mempty- Tar.Directory -> return mempty- _ -> putStrLn ("Unknown content in " ++ fpath)- >> return mempty- where- fpath = Tar.entryPath entry------------------------------------------------------------------------------------ readFields tests: very fast test for 'readFields' - first step of parser----------------------------------------------------------------------------------readFieldTest :: FilePath -> B.ByteString -> IO ()-readFieldTest fpath bs = case Parsec.readFields bs' of- Right _ -> return ()- Left err -> do- putStrLn fpath- print err- exitFailure- where- (_, bs') = patchQuirks bs------------------------------------------------------------------------------------ Parsec test: whether we can parse everything----------------------------------------------------------------------------------parseParsecTest :: Bool -> FilePath -> B.ByteString -> IO ParsecResult-parseParsecTest keepGoing fpath bs = do- let (warnings, result) = Parsec.runParseResult $- Parsec.parseGenericPackageDescription bs-- let w | null warnings = 0- | otherwise = 1-- case result of- Right gpd -> do- forEachGPD fpath bs gpd- return (ParsecResult 1 w 0)-- Left (_, errors) | keepGoing -> do- traverse_ (putStrLn . Parsec.showPError fpath) errors- return (ParsecResult 1 w 1)- | otherwise -> do- traverse_ (putStrLn . Parsec.showPError fpath) errors- exitFailure---- | A hook to make queries on Hackage-forEachGPD :: FilePath -> B8.ByteString -> L.GenericPackageDescription -> IO ()-forEachGPD _ _ _ = return ()------------------------------------------------------------------------------------ ParsecResult----------------------------------------------------------------------------------data ParsecResult = ParsecResult !Int !Int !Int- deriving (Eq, Show)--instance Semigroup ParsecResult where- ParsecResult x y z <> ParsecResult u v w = ParsecResult (x + u) (y + v) (z + w)--instance Monoid ParsecResult where- mempty = ParsecResult 0 0 0- mappend = (<>)--instance NFData ParsecResult where- rnf (ParsecResult _ _ _) = ()------------------------------------------------------------------------------------ Check test----------------------------------------------------------------------------------parseCheckTest :: FilePath -> B.ByteString -> IO CheckResult-parseCheckTest fpath bs = do- let (warnings, parsec) = Parsec.runParseResult $- Parsec.parseGenericPackageDescription bs- case parsec of- Right gpd -> do- let checks = checkPackage gpd Nothing- let w [] = 0- w _ = 1-- -- Look into invalid cpp options- -- _ <- L.traverseBuildInfos checkCppFlags gpd-- -- one for file, many checks- return (CheckResult 1 (w warnings) 0 0 0 0 0 0 <> foldMap toCheckResult checks)- Left (_, errors) -> do- traverse_ (putStrLn . Parsec.showPError fpath) errors- exitFailure---- checkCppFlags :: BuildInfo -> IO BuildInfo--- checkCppFlags bi = do--- for_ (cppOptions bi) $ \opt ->--- unless (any (`isPrefixOf` opt) ["-D", "-U", "-I"]) $--- putStrLn opt------ return bi--data CheckResult = CheckResult !Int !Int !Int !Int !Int !Int !Int !Int--instance NFData CheckResult where- rnf !_ = ()--instance Semigroup CheckResult where- CheckResult n w a b c d e f <> CheckResult n' w' a' b' c' d' e' f' =- CheckResult (n + n') (w + w') (a + a') (b + b') (c + c') (d + d') (e + e') (f + f')--instance Monoid CheckResult where- mempty = CheckResult 0 0 0 0 0 0 0 0- mappend = (<>)--toCheckResult :: PackageCheck -> CheckResult-toCheckResult PackageBuildImpossible {} = CheckResult 0 0 1 1 0 0 0 0-toCheckResult PackageBuildWarning {} = CheckResult 0 0 1 0 1 0 0 0-toCheckResult PackageDistSuspicious {} = CheckResult 0 0 1 0 0 1 0 0-toCheckResult PackageDistSuspiciousWarn {} = CheckResult 0 0 1 0 0 0 1 0-toCheckResult PackageDistInexcusable {} = CheckResult 0 0 1 0 0 0 0 1------------------------------------------------------------------------------------ Roundtrip test----------------------------------------------------------------------------------roundtripTest :: Bool -> FilePath -> B.ByteString -> IO (Sum Int)-roundtripTest testFieldsTransform fpath bs = do- x0 <- parse "1st" bs- let bs' = showGenericPackageDescription x0- y0 <- parse "2nd" (toUTF8BS bs')-- -- we mungled license here- let y1 = y0-- -- license-files: ""- let stripEmpty = filter (/="")- let x1 = x0 & L.packageDescription . L.licenseFiles %~ stripEmpty- let y2 = y1 & L.packageDescription . L.licenseFiles %~ stripEmpty-- let y = y2 & L.packageDescription . L.description .~ mempty- let x = x1 & L.packageDescription . L.description .~ mempty-- assertEqual' bs' x y-- -- fromParsecField, "shallow" parser/pretty roundtrip- when testFieldsTransform $- if checkUTF8 patchedBs- then do- parsecFields <- assertRight $ Parsec.readFields patchedBs- let prettyFields = PP.fromParsecFields parsecFields- let bs'' = PP.showFields (return []) prettyFields- z0 <- parse "3rd" (toUTF8BS bs'')-- -- note: we compare "raw" GPDs, on purpose; stricter equality- assertEqual' bs'' x0 z0- else- putStrLn $ fpath ++ " : looks like invalid UTF8"-- return (Sum 1)- where- patchedBs = snd (patchQuirks bs)-- checkUTF8 bs' = replacementChar `notElem` fromUTF8BS bs' where- replacementChar = '\xfffd'--- assertRight (Right x) = return x- assertRight (Left err) = do- putStrLn fpath- print err- exitFailure-- assertEqual' bs' x y = unless (x == y || fpath == "ixset/1.0.4/ixset.cabal") $ do- putStrLn fpath-#ifdef MIN_VERSION_tree_diff- putStrLn "====== tree-diff:"- print $ ansiWlEditExprCompact $ ediff x y-#else- putStrLn "<<<<<<"- print x- putStrLn "======"- print y- putStrLn ">>>>>>"-#endif- putStrLn "====== contents:"- putStrLn bs'- exitFailure-- parse phase c = do- let (_, x') = Parsec.runParseResult $- Parsec.parseGenericPackageDescription c- case x' of- Right gpd -> pure gpd- Left (_, errs) -> do- putStrLn $ fpath ++ " " ++ phase- traverse_ print errs- B.putStr c- fail "parse error"------------------------------------------------------------------------------------ Main----------------------------------------------------------------------------------main :: IO ()-main = join (O.execParser opts)- where- opts = O.info (optsP <**> O.helper) $ mconcat- [ O.fullDesc- , O.progDesc "tests using Hackage's index"- ]-- optsP = subparser- [ command "read-fields" readFieldsP- "Parse outer format (to '[Field]', TODO: apply Quirks)"- , command "parsec" parsecP "Parse GPD with parsec"- , command "roundtrip" roundtripP "parse . pretty . parse = parse"- , command "check" checkP "Check GPD"- ] <|> pure defaultA-- defaultA = do- putStrLn "Default action: parsec k"- parsecA (mkPredicate ["k"]) False-- readFieldsP = readFieldsA <$> prefixP- readFieldsA pfx = parseIndex pfx readFieldTest-- parsecP = parsecA <$> prefixP <*> keepGoingP- keepGoingP =- O.flag' True (O.long "keep-going") <|>- O.flag' False (O.long "no-keep-going") <|>- pure False-- parsecA pfx keepGoing = do- begin <- Clock.getTime Clock.Monotonic- ParsecResult n w f <- parseIndex pfx (parseParsecTest keepGoing)- end <- Clock.getTime Clock.Monotonic- let diff = Clock.toNanoSecs $ Clock.diffTimeSpec end begin-- putStrLn $ show n ++ " files processed"- putStrLn $ show w ++ " files contained warnings"- putStrLn $ show f ++ " files failed to parse"- putStrLn $ showFFloat (Just 6) (fromInteger diff / 1e9 :: Double) " seconds elapsed"-- roundtripP = roundtripA <$> prefixP <*> testFieldsP- roundtripA pfx testFieldsTransform = do- Sum n <- parseIndex pfx (roundtripTest testFieldsTransform)- putStrLn $ show n ++ " files processed"-- checkP = checkA <$> prefixP- checkA pfx = do- CheckResult n w x a b c d e <- parseIndex pfx parseCheckTest- putStrLn $ show n ++ " files processed"- putStrLn $ show w ++ " files have lexer/parser warnings"- putStrLn $ show x ++ " files have check warnings"- putStrLn $ show a ++ " build impossible"- putStrLn $ show b ++ " build warning"- putStrLn $ show c ++ " build dist suspicious"- putStrLn $ show d ++ " build dist suspicious warning"- putStrLn $ show e ++ " build dist inexcusable"-- prefixP = fmap mkPredicate $ many $ O.strArgument $ mconcat- [ O.metavar "PREFIX"- , O.help "Check only files starting with a prefix"- ]-- testFieldsP = O.switch $ mconcat- [ O.long "fields-transform"- , O.help "Test also 'showFields . fromParsecFields . readFields' transform"- ]-- mkPredicate [] = const True- mkPredicate pfxs = \n -> any (`isPrefixOf` n) pfxs-- command name p desc = O.command name- (O.info (p <**> O.helper) (O.progDesc desc))- subparser = O.subparser . mconcat------------------------------------------------------------------------------------ Index shuffling------------------------------------------------------------------------------------ TODO: Use 'Cabal' for this?-reposFromConfig :: [Parsec.Field ann] -> [String]-reposFromConfig fields = takeWhile (/= ':') <$> mapMaybe f fields- where- f (Parsec.Field (Parsec.Name _ name) fieldLines)- | B8.unpack name == "remote-repo" =- Just $ fieldLinesToString fieldLines- f (Parsec.Section (Parsec.Name _ name)- [Parsec.SecArgName _ secName] _fieldLines)- | B8.unpack name == "repository" =- Just $ B8.unpack secName- f _ = Nothing---- | Looks up the given key in the cabal configuration file-lookupInConfig :: String -> [Parsec.Field ann] -> [String]-lookupInConfig key = mapMaybe f- where- f (Parsec.Field (Parsec.Name _ name) fieldLines)- | B8.unpack name == key =- Just $ fieldLinesToString fieldLines- f _ = Nothing--fieldLinesToString :: [Parsec.FieldLine ann] -> String-fieldLinesToString fieldLines =- B8.unpack $ B.concat $ bsFromFieldLine <$> fieldLines- where- bsFromFieldLine (Parsec.FieldLine _ bs) = bs------------------------------------------------------------------------------------ Utilities------------------------------------------------------------------------------------ | We assume that monoid is commutative.------ First we chunk input (as single cabal file is little work)-foldIO :: forall a m. (Monoid m, NFData m) => (a -> IO m) -> [a] -> IO m-foldIO f = go mempty where- go !acc [] = acc- go !acc (x:xs) = go (mappend acc (f x)) xs------------------------------------------------------------------------------------ Orphans----------------------------------------------------------------------------------#if !MIN_VERSION_deepseq(1,4,0)-instance NFData a => NFData (Sum a) where- rnf (Sum a) = rnf a-#endif
− tests/ParserTests.hs
@@ -1,378 +0,0 @@-{-# LANGUAGE CPP #-}-module Main- ( main- ) where--import Prelude ()-import Prelude.Compat--import Test.Tasty-import Test.Tasty.Golden.Advanced (goldenTest)-import Test.Tasty.HUnit--import Control.Monad (unless, void)-import Data.Algorithm.Diff (PolyDiff (..), getGroupedDiff)-import Data.Maybe (isNothing)-import Distribution.Fields (runParseResult)-import Distribution.PackageDescription (GenericPackageDescription)-import Distribution.PackageDescription.Parsec (parseGenericPackageDescription)-import Distribution.PackageDescription.PrettyPrint (showGenericPackageDescription)-import Distribution.Parsec (PWarnType (..), PWarning (..), showPError, showPWarning)-import Distribution.Pretty (prettyShow)-import Distribution.Utils.Generic (fromUTF8BS, toUTF8BS)-import System.Directory (setCurrentDirectory)-import System.Environment (getArgs, withArgs)-import System.FilePath (replaceExtension, (</>))--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS8-import qualified Data.List.NonEmpty as NE--import qualified Distribution.InstalledPackageInfo as IPI--#ifdef MIN_VERSION_tree_diff-import Data.TreeDiff (ansiWlEditExpr, ediff, toExpr)-import Data.TreeDiff.Golden (ediffGolden)-import Data.TreeDiff.Instances.Cabal ()-#endif--tests :: TestTree-tests = testGroup "parsec tests"- [ regressionTests- , warningTests- , errorTests- , ipiTests- ]------------------------------------------------------------------------------------ Warnings------------------------------------------------------------------------------------ Verify that we trigger warnings-warningTests :: TestTree-warningTests = testGroup "warnings triggered"- [ warningTest PWTLexBOM "bom.cabal"- , warningTest PWTLexNBSP "nbsp.cabal"- , warningTest PWTLexTab "tab.cabal"- , warningTest PWTUTF "utf8.cabal"- , warningTest PWTBoolCase "bool.cabal"- , warningTest PWTVersionTag "versiontag.cabal"- , warningTest PWTNewSyntax "newsyntax.cabal"- , warningTest PWTOldSyntax "oldsyntax.cabal"- , warningTest PWTDeprecatedField "deprecatedfield.cabal"- , warningTest PWTInvalidSubsection "subsection.cabal"- , warningTest PWTUnknownField "unknownfield.cabal"- , warningTest PWTUnknownSection "unknownsection.cabal"- , warningTest PWTTrailingFields "trailingfield.cabal"- , warningTest PWTDoubleDash "doubledash.cabal"- , warningTest PWTMultipleSingularField "multiplesingular.cabal"- , warningTest PWTVersionWildcard "wildcard.cabal"- , warningTest PWTVersionOperator "operator.cabal"- , warningTest PWTSpecVersion "specversion-a.cabal"- , warningTest PWTSpecVersion "specversion-b.cabal"- , warningTest PWTSpecVersion "specversion-c.cabal"- -- TODO: not implemented yet- -- , warningTest PWTExtraTestModule "extratestmodule.cabal"- ]--warningTest :: PWarnType -> FilePath -> TestTree-warningTest wt fp = testCase (show wt) $ do- contents <- BS.readFile $ "tests" </> "ParserTests" </> "warnings" </> fp-- let res = parseGenericPackageDescription contents- let (warns, x) = runParseResult res-- assertBool ("should parse successfully: " ++ show x) $ isRight x-- case warns of- [PWarning wt' _ _] -> assertEqual "warning type" wt wt'- [] -> assertFailure "got no warnings"- _ -> assertFailure $ "got multiple warnings: " ++ show warns- where- isRight (Right _) = True- isRight _ = False------------------------------------------------------------------------------------ Errors----------------------------------------------------------------------------------errorTests :: TestTree-errorTests = testGroup "errors"- [ errorTest "common1.cabal"- , errorTest "common2.cabal"- , errorTest "common3.cabal"- , errorTest "leading-comma.cabal"- , errorTest "leading-comma-2.cabal"- , errorTest "leading-comma-2b.cabal"- , errorTest "leading-comma-2c.cabal"- , errorTest "range-ge-wild.cabal"- , errorTest "forward-compat.cabal"- , errorTest "forward-compat2.cabal"- , errorTest "forward-compat3.cabal"- , errorTest "issue-5055.cabal"- , errorTest "issue-5055-2.cabal"- , errorTest "noVersion.cabal"- , errorTest "noVersion2.cabal"- , errorTest "multiple-libs.cabal"- , errorTest "spdx-1.cabal"- , errorTest "spdx-2.cabal"- , errorTest "spdx-3.cabal"- , errorTest "removed-fields.cabal"- , errorTest "version-sets-1.cabal"- , errorTest "version-sets-2.cabal"- , errorTest "version-sets-3.cabal"- , errorTest "version-sets-4.cabal"- , errorTest "undefined-flag.cabal"- , errorTest "mixin-1.cabal"- , errorTest "mixin-2.cabal"- , errorTest "libpq1.cabal"- , errorTest "libpq2.cabal"- , errorTest "MiniAgda.cabal"- , errorTest "big-version.cabal"- , errorTest "anynone.cabal"- ]--errorTest :: FilePath -> TestTree-errorTest fp = cabalGoldenTest fp correct $ do- contents <- BS.readFile input- let res = parseGenericPackageDescription contents- let (_, x) = runParseResult res-- return $ toUTF8BS $ case x of- Right gpd ->- "UNXPECTED SUCCESS\n" ++- showGenericPackageDescription gpd- Left (v, errs) ->- unlines $ ("VERSION: " ++ show v) : map (showPError fp) (NE.toList errs)- where- input = "tests" </> "ParserTests" </> "errors" </> fp- correct = replaceExtension input "errors"------------------------------------------------------------------------------------ Regressions----------------------------------------------------------------------------------regressionTests :: TestTree-regressionTests = testGroup "regressions"- [ regressionTest "encoding-0.8.cabal"- , regressionTest "Octree-0.5.cabal"- , regressionTest "nothing-unicode.cabal"- , regressionTest "multiple-libs-2.cabal"- , regressionTest "issue-774.cabal"- , regressionTest "generics-sop.cabal"- , regressionTest "elif.cabal"- , regressionTest "elif2.cabal"- , regressionTest "shake.cabal"- , regressionTest "common.cabal"- , regressionTest "common2.cabal"- , regressionTest "common3.cabal"- , regressionTest "common-conditional.cabal"- , regressionTest "leading-comma.cabal"- , regressionTest "leading-comma-2.cabal"- , regressionTest "wl-pprint-indef.cabal"- , regressionTest "th-lift-instances.cabal"- , regressionTest "issue-5055.cabal"- , regressionTest "issue-6083-pkg-pkg.cabal"- , regressionTest "issue-6083-a.cabal"- , regressionTest "issue-6083-b.cabal"- , regressionTest "issue-6083-c.cabal"- , regressionTest "noVersion.cabal"- , regressionTest "spdx-1.cabal"- , regressionTest "spdx-2.cabal"- , regressionTest "spdx-3.cabal"- , regressionTest "hidden-main-lib.cabal"- , regressionTest "jaeger-flamegraph.cabal"- , regressionTest "version-sets.cabal"- , regressionTest "mixin-1.cabal"- , regressionTest "mixin-2.cabal"- , regressionTest "mixin-3.cabal"- , regressionTest "libpq1.cabal"- , regressionTest "libpq2.cabal"- , regressionTest "issue-5846.cabal"- , regressionTest "indentation.cabal"- , regressionTest "indentation2.cabal"- , regressionTest "indentation3.cabal"- , regressionTest "big-version.cabal"- , regressionTest "anynone.cabal"- , regressionTest "monad-param.cabal"- , regressionTest "hasktorch.cabal"- ]--regressionTest :: FilePath -> TestTree-regressionTest fp = testGroup fp- [ formatGoldenTest fp- , formatRoundTripTest fp-#ifdef MIN_VERSION_tree_diff- , treeDiffGoldenTest fp-#endif- ]--formatGoldenTest :: FilePath -> TestTree-formatGoldenTest fp = cabalGoldenTest "format" correct $ do- contents <- BS.readFile input- let res = parseGenericPackageDescription contents- let (warns, x) = runParseResult res-- return $ toUTF8BS $ case x of- Right gpd ->- unlines (map (showPWarning fp) warns)- ++ showGenericPackageDescription gpd- Left (csv, errs) ->- unlines $- "ERROR" :- maybe "unknown-version" prettyShow csv :- map (showPError fp) (NE.toList errs)- where- input = "tests" </> "ParserTests" </> "regressions" </> fp- correct = replaceExtension input "format"--#ifdef MIN_VERSION_tree_diff-treeDiffGoldenTest :: FilePath -> TestTree-treeDiffGoldenTest fp = ediffGolden goldenTest "expr" exprFile $ do- contents <- BS.readFile input- let res = parseGenericPackageDescription contents- let (_, x) = runParseResult res- case x of- Right gpd -> pure (toExpr gpd)- Left (_, errs) -> fail $ unlines $ "ERROR" : map (showPError fp) (NE.toList errs)- where- input = "tests" </> "ParserTests" </> "regressions" </> fp- exprFile = replaceExtension input "expr"-#endif--formatRoundTripTest :: FilePath -> TestTree-formatRoundTripTest fp = testCase "roundtrip" $ do- contents <- BS.readFile input- x <- parse contents- let contents' = showGenericPackageDescription x- y <- parse (toUTF8BS contents')- -- previously we mangled licenses a bit- let y' = y- unless (x == y') $-#ifdef MIN_VERSION_tree_diff- assertFailure $ unlines- [ "re-parsed doesn't match"- , show $ ansiWlEditExpr $ ediff x y- ]-#else- assertFailure $ unlines- [ "re-parsed doesn't match"- , "expected"- , show x- , "actual"- , show y- ]-#endif- where- parse :: BS.ByteString -> IO GenericPackageDescription- parse c = do- let (_, x') = runParseResult $ parseGenericPackageDescription c- case x' of- Right gpd -> pure gpd- Left (_, errs) -> do- void $ assertFailure $ unlines (map (showPError fp) $ NE.toList errs)- fail "failure"- input = "tests" </> "ParserTests" </> "regressions" </> fp------------------------------------------------------------------------------------ InstalledPackageInfo regressions----------------------------------------------------------------------------------ipiTests :: TestTree-ipiTests = testGroup "ipis"- [ ipiTest "transformers.cabal"- , ipiTest "Includes2.cabal"- , ipiTest "issue-2276-ghc-9885.cabal"- , ipiTest "internal-preprocessor-test.cabal"- ]--ipiTest :: FilePath -> TestTree-ipiTest fp = testGroup fp $-#ifdef MIN_VERSION_tree_diff- [ ipiTreeDiffGoldenTest fp ] ++-#endif- [ ipiFormatGoldenTest fp- , ipiFormatRoundTripTest fp- ]--ipiFormatGoldenTest :: FilePath -> TestTree-ipiFormatGoldenTest fp = cabalGoldenTest "format" correct $ do- contents <- BS.readFile input- let res = IPI.parseInstalledPackageInfo contents- return $ toUTF8BS $ case res of- Left err -> "ERROR " ++ show err- Right (ws, ipi) ->- unlines ws ++ IPI.showInstalledPackageInfo ipi- where- input = "tests" </> "ParserTests" </> "ipi" </> fp- correct = replaceExtension input "format"--#ifdef MIN_VERSION_tree_diff-ipiTreeDiffGoldenTest :: FilePath -> TestTree-ipiTreeDiffGoldenTest fp = ediffGolden goldenTest "expr" exprFile $ do- contents <- BS.readFile input- let res = IPI.parseInstalledPackageInfo contents- case res of- Left err -> fail $ "ERROR " ++ show err- Right (_ws, ipi) -> pure (toExpr ipi)- where- input = "tests" </> "ParserTests" </> "ipi" </> fp- exprFile = replaceExtension input "expr"-#endif--ipiFormatRoundTripTest :: FilePath -> TestTree-ipiFormatRoundTripTest fp = testCase "roundtrip" $ do- contents <- BS.readFile input- x <- parse contents- let contents' = IPI.showInstalledPackageInfo x- y <- parse (toUTF8BS contents')-- -- ghc-pkg prints pkgroot itself, based on cli arguments!- let x' = x { IPI.pkgRoot = Nothing }- let y' = y- assertBool "pkgRoot isn't shown" (isNothing (IPI.pkgRoot y))- assertEqual "re-parsed doesn't match" x' y'-- -- Complete round-trip- let contents2 = IPI.showFullInstalledPackageInfo x- z <- parse (toUTF8BS contents2)- assertEqual "re-parsed doesn't match" x z-- where- parse :: BS.ByteString -> IO IPI.InstalledPackageInfo- parse c = do- case IPI.parseInstalledPackageInfo c of- Right (_, ipi) -> return ipi- Left err -> do- void $ assertFailure $ show err- fail "failure"- input = "tests" </> "ParserTests" </> "ipi" </> fp------------------------------------------------------------------------------------ Main----------------------------------------------------------------------------------main :: IO ()-main = do- args <- getArgs- case args of- ("--cwd" : cwd : args') -> do- setCurrentDirectory cwd- withArgs args' $ defaultMain tests- _ -> defaultMain tests--cabalGoldenTest :: TestName -> FilePath -> IO BS.ByteString -> TestTree-cabalGoldenTest name ref act = goldenTest name (BS.readFile ref) act cmp upd- where- upd = BS.writeFile ref- cmp x y | x == y = return Nothing- cmp x y = return $ Just $ unlines $- concatMap f (getGroupedDiff (BS8.lines x) (BS8.lines y))- where- f (First xs) = map (cons3 '-' . fromUTF8BS) xs- f (Second ys) = map (cons3 '+' . fromUTF8BS) ys- -- we print unchanged lines too. It shouldn't be a problem while we have- -- reasonably small examples- f (Both xs _) = map (cons3 ' ' . fromUTF8BS) xs- -- we add three characters, so the changed lines are easier to spot- cons3 c cs = c : c : c : ' ' : cs
− tests/ParserTests/errors/MiniAgda.cabal
@@ -1,89 +0,0 @@-name: MiniAgda-version: 0.2017.02.18-build-type: Simple-cabal-version: 1.22-license: OtherLicense-license-file: LICENSE-author: Andreas Abel and Karl Mehltretter-maintainer: Andreas Abel <andreas.abel@ifi.lmu.de>-homepage: http://www.tcs.ifi.lmu.de/~abel/miniagda/-bug-reports: https://github.com/andreasabel/miniagda/issues-category: Dependent types-synopsis: A toy dependently typed programming language with type-based termination.-description:- MiniAgda is a tiny dependently-typed programming language in the style- of Agda. It serves as a laboratory to test potential additions to the- language and type system of Agda. MiniAgda's termination checker is a- fusion of sized types and size-change termination and supports- coinduction. Equality incorporates eta-expansion at record and- singleton types. Function arguments can be declared as static; such- arguments are discarded during equality checking and compilation.-- Recent features include bounded size quantification and destructor- patterns for a more general handling of coinduction.--tested-with: GHC == 7.6.3- GHC == 7.8.4- GHC == 7.10.3- GHC == 8.0.1--extra-source-files: Makefile--data-files: test/succeed/Makefile- test/succeed/*.ma- test/fail/Makefile- test/fail/*.ma- test/fail/*.err- test/fail/adm/*.ma- test/fail/adm/*.err- lib/*.ma-source-repository head- type: git- location: https://github.com/andreasabel/miniagda--executable miniagda- hs-source-dirs: src- build-depends: array >= 0.3 && < 0.6,- base >= 4.6 && < 4.11,- containers >= 0.3 && < 0.6,- haskell-src-exts >= 1.17 && < 1.18,- mtl >= 2.2.0.1 && < 2.3,- pretty >= 1.0 && < 1.2- build-tools: happy >= 1.15 && < 2,- alex >= 3.0 && < 4- default-language: Haskell98- default-extensions: CPP- MultiParamTypeClasses- TypeSynonymInstances- FlexibleInstances- FlexibleContexts- GeneralizedNewtypeDeriving- NoMonomorphismRestriction- PatternGuards- TupleSections- NamedFieldPuns- main-is: Main.hs- other-modules: Abstract- Collection- Concrete- Eval- Extract- HsSyntax- Lexer- Main- Parser- Polarity- PrettyTCM- ScopeChecker- Semiring- SparseMatrix- TCM- Termination- ToHaskell- Tokens- TraceError- TreeShapedOrder- TypeChecker- Util- Value- Warshall
− tests/ParserTests/errors/MiniAgda.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [1,22])-MiniAgda.cabal:2:27: -unexpected Version digit with leading zero-
− tests/ParserTests/errors/anynone.cabal
@@ -1,10 +0,0 @@-cabal-version: 3.4-name: anynone-version: 0-synopsis: The -any none demo-build-type: Simple--library- default-language: Haskell2010- exposed-modules: AnyNone- build-depends: base -any
− tests/ParserTests/errors/anynone.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [3,4])-anynone.cabal:10:26: -unexpected '-'-expecting space, white space, opening paren, operator, comma or end of input-
− tests/ParserTests/errors/big-version.cabal
@@ -1,7 +0,0 @@-cabal-version: 3.0-name: big-version--- 10 digits-version: 1234567890--library- default-language: Haskell2010
− tests/ParserTests/errors/big-version.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [3,0])-big-version.cabal:4:32: -unexpected At most 9 numbers are allowed per version number part-
− tests/ParserTests/errors/common1.cabal
@@ -1,29 +0,0 @@-cabal-version: 2.2-name: common-version: 0-synopsis: Common-stanza demo demo-build-type: Simple--source-repository head- Type: git- Location: https://github.com/hvr/-.git--common windows- if os(windows)- build-depends: Win32---- Non-existing common stanza-common deps- import: windo- build-depends:- base >=4.10 && <4.11,- containers--library- import: deps-- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends:- ghc-prim
− tests/ParserTests/errors/common1.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [2,2])-common1.cabal:17:3: Undefined common stanza imported: windo
− tests/ParserTests/errors/common2.cabal
@@ -1,29 +0,0 @@-cabal-version: 2.2-name: common-version: 0-synopsis: Common-stanza demo demo-build-type: Simple--source-repository head- Type: git- Location: https://github.com/hvr/-.git---- Used before use-common deps- import: windows- build-depends:- base >=4.10 && <4.11,- containers--common windows- if os(windows)- build-depends: Win32--library- import: deps-- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends:- ghc-prim
− tests/ParserTests/errors/common2.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [2,2])-common2.cabal:13:3: Undefined common stanza imported: windows
− tests/ParserTests/errors/common3.cabal
@@ -1,31 +0,0 @@-cabal-version: 2.2-name: common-version: 0-synopsis: Common-stanza demo demo-build-type: Simple--source-repository head- Type: git- Location: https://github.com/hvr/-.git--common windows- if os(windows)- build-depends: Win32--common deps- import: windows- build-depends:- base >=4.10 && <4.11,- containers---- Duplicate-common deps--library- import: deps-- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends:- ghc-prim
− tests/ParserTests/errors/common3.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [2,2])-common3.cabal:22:1: Duplicate common stanza: deps
− tests/ParserTests/errors/forward-compat.cabal
@@ -1,4 +0,0 @@-cabal-version: 99999.9-name: future-============-Lexically completely changed future
− tests/ParserTests/errors/forward-compat.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [99999,9])-forward-compat.cabal:0:0: Unsupported cabal-version 99999.9. See https://github.com/haskell/cabal/issues/4899.
− tests/ParserTests/errors/forward-compat2.cabal
@@ -1,16 +0,0 @@-name: common-version: 0-synopsis: Common-stanza demo demo-build-type: Simple-cabal-version: 2.2--source-repository head- Type: git- Location: https://github.com/hvr/-.git--library- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends:- ghc-prim
− tests/ParserTests/errors/forward-compat2.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [2,2])-forward-compat2.cabal:5:1: cabal-version should be at the beginning of the file starting with spec version 2.2. See https://github.com/haskell/cabal/issues/4899
− tests/ParserTests/errors/forward-compat3.cabal
@@ -1,16 +0,0 @@-cabal-version: 99999.99-name: forward-compat-version: 0-synopsis: Forward compat, too new cabal-version: we fail.-build-type: Simple--source-repository head- Type: git- Location: https://github.com/hvr/-.git--library- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends:- ghc-prim
− tests/ParserTests/errors/forward-compat3.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [99999,99])-forward-compat3.cabal:0:0: Unsupported cabal-version 99999.99. See https://github.com/haskell/cabal/issues/4899.
− tests/ParserTests/errors/issue-5055-2.cabal
@@ -1,25 +0,0 @@-name: issue-version: 5055-synopsis: no type in all branches-description: no type in all branches.-license: BSD3-category: Test-build-type: Simple-cabal-version: 2.0--executable flag-test-exe- main-is: FirstMain.hs- build-depends: base >= 4.8 && < 5- default-language: Haskell2010--test-suite flag-cabal-test- -- TODO: fix so `type` can be on the top level- build-depends: base >= 4.8 && < 5- default-language: Haskell2010-- if os(windows)- main-is: FirstMain.hs- type: exitcode-stdio-1.0- else:- main-is: SecondMain.hs- type: exitcode-stdio-1.0
− tests/ParserTests/errors/issue-5055-2.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [2,0])-issue-5055-2.cabal:15:1: Test suite "flag-cabal-test" is missing required field "type" or the field is not present in all conditional branches. The available test types are: exitcode-stdio-1.0, detailed-0.9
− tests/ParserTests/errors/issue-5055.cabal
@@ -1,21 +0,0 @@-name: issue-version: 5055-synopsis: no type in all branches-description: no type in all branches.-license: BSD3-category: Test-build-type: Simple-cabal-version: 2.0--executable flag-test-exe- main-is: FirstMain.hs- build-depends: base >= 4.8 && < 5- default-language: Haskell2010--test-suite flag-cabal-test- build-depends: base >= 4.8 && < 5- default-language: Haskell2010-- if os(windows)- main-is: FirstMain.hs- type: exitcode-stdio-1.0
− tests/ParserTests/errors/issue-5055.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [2,0])-issue-5055.cabal:15:1: Test suite "flag-cabal-test" is missing required field "type" or the field is not present in all conditional branches. The available test types are: exitcode-stdio-1.0, detailed-0.9
− tests/ParserTests/errors/leading-comma-2.cabal
@@ -1,23 +0,0 @@-cabal-version: 2.4--- too small cabal-version--name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--library- default-language: Haskell2010- exposed-modules:- , LeadingComma- , LeadingComma-- build-depends: base, containers-- build-depends:- deepseq,- transformers,-- build-depends:- , filepath- , directory
− tests/ParserTests/errors/leading-comma-2.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [2,4])-leading-comma-2.cabal:12:5: -unexpected ','-expecting white space, "\"" or end of input-
− tests/ParserTests/errors/leading-comma-2b.cabal
@@ -1,23 +0,0 @@-cabal-version: 2.4--- too small cabal-version--name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--library- default-language: Haskell2010- exposed-modules:- TrailingComma,- TrailingComma2,-- build-depends: base, containers-- build-depends:- deepseq,- transformers,-- build-depends:- , filepath- , directory
− tests/ParserTests/errors/leading-comma-2b.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [2,4])-leading-comma-2b.cabal:13:20: -unexpected end of input-expecting white space or "\""-
− tests/ParserTests/errors/leading-comma-2c.cabal
@@ -1,21 +0,0 @@-cabal-version: 3.0-name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--library- default-language: Haskell2010- exposed-modules:- LeadingComma, MixedComma NoComma- -- build-depends: base, containers-- build-depends:- deepseq,- transformers,-- build-depends:- , filepath- , directory
− tests/ParserTests/errors/leading-comma-2c.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [3,0])-leading-comma-2c.cabal:10:30: -unexpected 'N'-expecting space, comma, white space or end of input-
− tests/ParserTests/errors/leading-comma.cabal
@@ -1,20 +0,0 @@-name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--- too small cabal-version-cabal-version: 2.0--library- default-language: Haskell2010- exposed-modules: LeadingComma-- build-depends: base, containers-- build-depends:- deepseq,- transformers,-- build-depends:- , filepath- , directory
− tests/ParserTests/errors/leading-comma.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [2,0])-leading-comma.cabal:16:18: -unexpected end of input-expecting white space-
− tests/ParserTests/errors/libpq1.cabal
@@ -1,81 +0,0 @@-Name: postgresql-libpq-Version: 0.9.4.2-Synopsis: low-level binding to libpq--Description: This is a binding to libpq: the C application- programmer's interface to PostgreSQL. libpq is a- set of library functions that allow client- programs to pass queries to the PostgreSQL- backend server and to receive the results of- these queries.--Homepage: https://github.com/phadej/postgresql-libpq-License: BSD3-License-file: LICENSE-Author: Grant Monroe, Leon P Smith, Joey Adams-Maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-Copyright: (c) 2010 Grant Monroe- (c) 2011 Leon P Smith-Category: Database-Build-type: Custom-Extra-source-files: cbits/noticehandlers.h-Cabal-version: >=1.8-Tested-with:- GHC==7.0.4,- GHC==7.2.2,- GHC==7.4.2,- GHC==7.6.3,- GHC==7.8.4,- GHC==7.10.3,- GHC==8.0.2,- GHC==8.2.2,- GHC==8.4.3,- GHC==8.6.1--extra-source-files:- CHANGELOG.md--Custom-setup- setup-depends:- base >= 4.3 && <5, Cabal >= 1.10 && <2.5---- If true, use pkg-config, otherwise use the pg_config based build--- configuration-Flag use-pkg-config- default: False- manual: True--Library- hs-source-dirs: src- c-sources: cbits/noticehandlers.c- include-dirs: cbits- Exposed-modules: Database.PostgreSQL.LibPQ- Database.PostgreSQL.LibPQ.Internal- Build-depends: base >=4.3 && <4.13- , bytestring >=0.9.1.0 && <0.11-- if !os(windows)- Build-depends: unix >=2.4.2.0 && <2.8-- if os(windows)- Build-depends: Win32 >=2.2.0.2 && <2.7-- GHC-Options: -Wall-- if flag(use-pkg-config)- Pkgconfig-depends: libpq ==9.3h- else- if os(windows)- -- Due to https://sourceware.org/bugzilla/show_bug.cgi?id=22948,- -- if we specify pq instead of libpq, then ld might link against- -- libpq.dll directly, which can lead to segfaults. As a temporary hack,- -- we force ld to link against the libpq.lib import library directly- -- by specifying libpq here.- Extra-Libraries: libpq- else- Extra-Libraries: pq- if os(openbsd)- Extra-Libraries: crypto ssl-- -- Other-modules:- Build-tools: hsc2hs
− tests/ParserTests/errors/libpq1.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [1,8])-libpq1.cabal:66:37: -unexpected 'h'-expecting ".", "-", white space, "&&", "||", comma or end of input-
− tests/ParserTests/errors/libpq2.cabal
@@ -1,81 +0,0 @@-Cabal-version: 3.0-Name: postgresql-libpq-Version: 0.9.4.2-Synopsis: low-level binding to libpq--Description: This is a binding to libpq: the C application- programmer's interface to PostgreSQL. libpq is a- set of library functions that allow client- programs to pass queries to the PostgreSQL- backend server and to receive the results of- these queries.--Homepage: https://github.com/phadej/postgresql-libpq-License: BSD-3-Clause-License-file: LICENSE-Author: Grant Monroe, Leon P Smith, Joey Adams-Maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-Copyright: (c) 2010 Grant Monroe- (c) 2011 Leon P Smith-Category: Database-Build-type: Custom-Extra-source-files: cbits/noticehandlers.h-Tested-with:- GHC==7.0.4,- GHC==7.2.2,- GHC==7.4.2,- GHC==7.6.3,- GHC==7.8.4,- GHC==7.10.3,- GHC==8.0.2,- GHC==8.2.2,- GHC==8.4.3,- GHC==8.6.1--extra-source-files:- CHANGELOG.md--Custom-setup- setup-depends:- base >= 4.3 && <5, Cabal >= 1.10 && <2.5---- If true, use pkg-config, otherwise use the pg_config based build--- configuration-Flag use-pkg-config- default: False- manual: True--Library- hs-source-dirs: src- c-sources: cbits/noticehandlers.c- include-dirs: cbits- Exposed-modules: Database.PostgreSQL.LibPQ- Database.PostgreSQL.LibPQ.Internal- Build-depends: base >=4.3 && <4.13- , bytestring >=0.9.1.0 && <0.11-- if !os(windows)- Build-depends: unix >=2.4.2.0 && <2.8-- if os(windows)- Build-depends: Win32 >=2.2.0.2 && <2.7-- GHC-Options: -Wall-- if flag(use-pkg-config)- Pkgconfig-depends: libpq >=9.*- else- if os(windows)- -- Due to https://sourceware.org/bugzilla/show_bug.cgi?id=22948,- -- if we specify pq instead of libpq, then ld might link against- -- libpq.dll directly, which can lead to segfaults. As a temporary hack,- -- we force ld to link against the libpq.lib import library directly- -- by specifying libpq here.- Extra-Libraries: libpq- else- Extra-Libraries: pq- if os(openbsd)- Extra-Libraries: crypto ssl-- -- Other-modules:- Build-tools-depends: hsc2hs:hsc2hs
− tests/ParserTests/errors/libpq2.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [3,0])-libpq2.cabal:66:36: -unexpected '*'-expecting white space, "&&", "||", comma or end of input-
− tests/ParserTests/errors/mixin-1.cabal
@@ -1,15 +0,0 @@-cabal-version: 2.4-name: mixin-version: 0---- mixin field:--- in 2.2 we got leading/trailing commas--- in 3.0 we got lax space parsing------ This should fail-executable str-example- main-is: Main.hs- build-depends: base, str-string, str-bytestring- mixins: str-string ( Str as Str.String ),- str-bytestring ( Str as Str.ByteString ),- hs-source-dirs: str-example
− tests/ParserTests/errors/mixin-1.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [2,4])-mixin-1.cabal:13:41: -unexpected space after parenthesis, use cabal-version: 3.0 or higher-
− tests/ParserTests/errors/mixin-2.cabal
@@ -1,14 +0,0 @@-cabal-version: 2.2-name: mixin-version: 0---- mixin field:--- in 2.2 we got leading/trailing commas--- in 2.2 we got lax space parsing------ This should fail-executable str-example- main-is: Main.hs- build-depends: base, str-string, str-bytestring- mixins: str-string hiding ( Foo )- hs-source-dirs: str-example
− tests/ParserTests/errors/mixin-2.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [2,2])-mixin-2.cabal:13:48: -unexpected space after parenthesis, use cabal-version: 3.0 or higher-
− tests/ParserTests/errors/multiple-libs.cabal
@@ -1,14 +0,0 @@-name: multipleLibs-version: 0-synopsis: multiple main/nameless libs-build-type: Simple-cabal-version: 1.20--library- default-language: Haskell2010- exposed-modules: ElseIf- build-depends: base--library- default-language: Haskell2010- exposed-modules: ElseIf
− tests/ParserTests/errors/multiple-libs.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [1,20])-multiple-libs.cabal:12:1: Multiple main libraries; have you forgotten to specify a name for an internal library?
− tests/ParserTests/errors/noVersion.cabal
@@ -1,10 +0,0 @@-name: noVersion-version: 0-synopsis: -none in build-depends-build-type: Simple-cabal-version: 1.20--library- default-language: Haskell2010- exposed-modules: ElseIf- build-depends: bad-package -none
− tests/ParserTests/errors/noVersion.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [1,20])-noVersion.cabal:10:38: -unexpected -none version range used. To use this syntax the package needs to specify at least 'cabal-version: 1.22'. Alternatively, if broader compatibility is important then use <0 or other empty range.-
− tests/ParserTests/errors/noVersion2.cabal
@@ -1,10 +0,0 @@-name: noVersion-version: 0-synopsis: ^>= in build-depends-build-type: Simple-cabal-version: 1.20--library- default-language: Haskell2010- exposed-modules: ElseIf- build-depends: bad-package ^>= 2.0
− tests/ParserTests/errors/noVersion2.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [1,20])-noVersion2.cabal:10:40: -unexpected major bounded version syntax (caret, ^>=) used. To use this syntax the package need to specify at least 'cabal-version: 2.0'. Alternatively, if broader compatibility is important then use: >=2.0 && <2.1-expecting "." or "-"-
− tests/ParserTests/errors/range-ge-wild.cabal
@@ -1,10 +0,0 @@-name: range-ge-wild-version: 0-synopsis: Wild range after non-== op-build-type: Simple-cabal-version: >=1.10--library- build-depends:- -- comment, to check that position is right- base >= 4.*
− tests/ParserTests/errors/range-ge-wild.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [1,10])-range-ge-wild.cabal:10:16: -unexpected wild-card version after non-== operator: ">="-
− tests/ParserTests/errors/removed-fields.cabal
@@ -1,14 +0,0 @@-cabal-version: 3.0-name: removed-fields-version: 0-synopsis: some fields are removed-build-type: Simple--library- default-language: Haskell2010- exposed-modules: RemovedFields-- build-depends: base, containers-- extensions: CPP- extensions: DeriveFunctor
− tests/ParserTests/errors/removed-fields.errors
@@ -1,3 +0,0 @@-VERSION: Just (mkVersion [3,0])-removed-fields.cabal:13:3: The field "extensions" is removed in the Cabal specification version 3.0. Please use 'default-extensions' or 'other-extensions' fields.-removed-fields.cabal:14:3: The field "extensions" is removed in the Cabal specification version 3.0. Please use 'default-extensions' or 'other-extensions' fields.
− tests/ParserTests/errors/spdx-1.cabal
@@ -1,9 +0,0 @@-cabal-version: 2.2-name: spdx-version: 0-synopsis: testing positive parsing of spdx identifiers-build-type: Simple-license: BSD3--library- default-language: Haskell2010
− tests/ParserTests/errors/spdx-1.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [2,2])-spdx-1.cabal:6:26: -unexpected Unknown SPDX license identifier: 'BSD3' Do you mean BSD-3-Clause?-
− tests/ParserTests/errors/spdx-2.cabal
@@ -1,9 +0,0 @@-cabal-version: 2.4-name: spdx-version: 0-synopsis: testing positive parsing of spdx identifiers-build-type: Simple-license: AGPL-1.0--library- default-language: Haskell2010
− tests/ParserTests/errors/spdx-2.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [2,4])-spdx-2.cabal:6:30: -unexpected Unknown SPDX license identifier: 'AGPL-1.0' -
− tests/ParserTests/errors/spdx-3.cabal
@@ -1,9 +0,0 @@-cabal-version: 2.2-name: spdx-version: 0-synopsis: testing positive parsing of spdx identifiers-build-type: Simple-license: AGPL-1.0-only--library- default-language: Haskell2010
− tests/ParserTests/errors/spdx-3.errors
@@ -1,4 +0,0 @@-VERSION: Just (mkVersion [2,2])-spdx-3.cabal:6:35: -unexpected Unknown SPDX license identifier: 'AGPL-1.0-only' -
− tests/ParserTests/errors/undefined-flag.cabal
@@ -1,26 +0,0 @@-name: hpython-test-common-version: 0.1.0.0--- synopsis:--- description:-license: BSD3-license-file: LICENSE-author: Isaac Elliott-maintainer: isaace71295@gmail.com--- copyright:-category: Testing-build-type: Simple-extra-source-files: CHANGELOG.md-cabal-version: >=1.10--library- exposed-modules: Helpers- build-depends: base >=4.11 && <5- hs-source-dirs: src- ghc-options: -Wall- -Wincomplete-patterns- -Wincomplete-record-updates- -Wunused-imports- -fno-warn-name-shadowing- if flag(development)- ghc-options: -Werror- default-language: Haskell2010
− tests/ParserTests/errors/undefined-flag.errors
@@ -1,2 +0,0 @@-VERSION: Just (mkVersion [1,10])-undefined-flag.cabal:0:0: These flags are used without having been defined: development
− tests/ParserTests/errors/version-sets-1.cabal
@@ -1,8 +0,0 @@-cabal-version: 3.0-name: version-sets-version: 0-synopsis: version set notation--library- default-language: Haskell2010- build-depends: network == { }
− tests/ParserTests/errors/version-sets-1.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [3,0])-version-sets-1.cabal:8:31: -unexpected "}"-expecting space or version digit (integral without leading zeroes)-
− tests/ParserTests/errors/version-sets-2.cabal
@@ -1,8 +0,0 @@-cabal-version: 3.0-name: version-sets-version: 0-synopsis: version set notation--library- default-language: Haskell2010- build-depends: network >= { 2.8.0.0 }
− tests/ParserTests/errors/version-sets-2.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [3,0])-version-sets-2.cabal:8:29: -unexpected "{"-expecting space or version digit (integral without leading zeroes)-
− tests/ParserTests/errors/version-sets-3.cabal
@@ -1,8 +0,0 @@-cabal-version: 3.0-name: version-sets-version: 0-synopsis: version set notation--library- default-language: Haskell2010- build-depends: network == { 2.8.0.0, }
− tests/ParserTests/errors/version-sets-3.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [3,0])-version-sets-3.cabal:8:40: -unexpected "}"-expecting space or version digit (integral without leading zeroes)-
− tests/ParserTests/errors/version-sets-4.cabal
@@ -1,8 +0,0 @@-cabal-version: 3.0-name: version-sets-version: 0-synopsis: version set notation--library- default-language: Haskell2010- build-depends: network == { 2.8.* }
− tests/ParserTests/errors/version-sets-4.errors
@@ -1,5 +0,0 @@-VERSION: Just (mkVersion [3,0])-version-sets-4.cabal:8:35: -unexpected "*"-expecting version digit (integral without leading zeroes)-
− tests/ParserTests/ipi/Includes2.cabal
@@ -1,27 +0,0 @@-name: z-Includes2-z-mylib-version: 0.1.0.0-id: Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-instantiated-with: Database=Includes2-0.1.0.0-inplace-mysql:Database.MySQL-package-name: Includes2-lib-name: mylib-key: Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-license: BSD3-maintainer: ezyang@cs.stanford.edu-author: Edward Z. Yang-exposed: False-indefinite: False-exposed-modules:- Mine-abi: inplace-trusted: False-import-dirs: /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-library-dirs: /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-dynamic-library-dirs: /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-data-dir: /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2-hs-libraries: HSIncludes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-depends:- base-4.10.1.0 Includes2-0.1.0.0-inplace-mysql-abi-depends: base-4.10.1.0=35a7f6be752ee4f7385cb5bf28677879- Includes2-0.1.0.0-inplace-mysql=inplace-haddock-interfaces: /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/doc/html/Includes2/Includes2.haddock-haddock-html: /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/doc/html/Includes2
− tests/ParserTests/ipi/Includes2.expr
@@ -1,58 +0,0 @@-InstalledPackageInfo- {abiDepends = [AbiDependency- {depAbiHash = AbiHash "35a7f6be752ee4f7385cb5bf28677879",- depUnitId = UnitId "base-4.10.1.0"},- AbiDependency- {depAbiHash = AbiHash "inplace",- depUnitId = UnitId "Includes2-0.1.0.0-inplace-mysql"}],- abiHash = AbiHash "inplace",- author = "Edward Z. Yang",- category = "",- ccOptions = [],- compatPackageKey = "Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n",- copyright = "",- cxxOptions = [],- dataDir = "/home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2",- depends = [UnitId "base-4.10.1.0",- UnitId "Includes2-0.1.0.0-inplace-mysql"],- description = "",- exposed = False,- exposedModules = [ExposedModule- {exposedName = ModuleName "Mine", exposedReexport = Nothing}],- extraGHCiLibraries = [],- extraLibraries = [],- frameworkDirs = [],- frameworks = [],- haddockHTMLs = ["/home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/doc/html/Includes2"],- haddockInterfaces = ["/home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/doc/html/Includes2/Includes2.haddock"],- hiddenModules = [],- homepage = "",- hsLibraries = ["HSIncludes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n"],- importDirs = ["/home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n"],- includeDirs = [],- includes = [],- indefinite = False,- installedComponentId_ = ComponentId "",- installedUnitId = UnitId- "Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n",- instantiatedWith = [_×_- (ModuleName "Database")- (OpenModule- (DefiniteUnitId- (DefUnitId (UnitId "Includes2-0.1.0.0-inplace-mysql")))- (ModuleName "Database.MySQL"))],- ldOptions = [],- libVisibility = LibraryVisibilityPrivate,- libraryDirs = ["/home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n"],- libraryDynDirs = ["/home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n"],- license = Right BSD3,- maintainer = "ezyang@cs.stanford.edu",- pkgRoot = Nothing,- pkgUrl = "",- sourceLibName = LSubLibName (UnqualComponentName "mylib"),- sourcePackageId = PackageIdentifier- {pkgName = PackageName "Includes2",- pkgVersion = mkVersion [0, 1, 0, 0]},- stability = "",- synopsis = "",- trusted = False}
− tests/ParserTests/ipi/Includes2.format
@@ -1,35 +0,0 @@-name: z-Includes2-z-mylib-version: 0.1.0.0-package-name: Includes2-lib-name: mylib-id: Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-instantiated-with: Database=Includes2-0.1.0.0-inplace-mysql:Database.MySQL-key: Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-license: BSD3-maintainer: ezyang@cs.stanford.edu-author: Edward Z. Yang-abi: inplace-exposed-modules: Mine-import-dirs:- /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n--library-dirs:- /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n--dynamic-library-dirs:- /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/build/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n--data-dir:- /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2--hs-libraries: HSIncludes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n-depends: base-4.10.1.0 Includes2-0.1.0.0-inplace-mysql-abi-depends:- base-4.10.1.0=35a7f6be752ee4f7385cb5bf28677879- Includes2-0.1.0.0-inplace-mysql=inplace--haddock-interfaces:- /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/doc/html/Includes2/Includes2.haddock--haddock-html:- /home/travis/build/haskell/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.dist/work/./dist/build/x86_64-linux/ghc-8.2.2/Includes2-0.1.0.0/l/mylib/Includes2-0.1.0.0-inplace-mylib+3gY9SyjX86dBypHcOaev1n/doc/html/Includes2
− tests/ParserTests/ipi/internal-preprocessor-test.cabal
@@ -1,26 +0,0 @@-name: internal-preprocessor-test-version: 0.1.0.0-id: internal-preprocessor-test-0.1.0.0-key: internal-preprocessor-test-0.1.0.0-license: GPL-3-maintainer: mikhail.glushenkov@gmail.com-synopsis: Internal custom preprocessor example.-description:- See https://github.com/haskell/cabal/issues/1541#issuecomment-30155513-category: Testing-author: Mikhail Glushenkov-exposed: True-exposed-modules:- A-trusted: False-import-dirs: /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build-library-dirs: /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build- /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build-data-dir: /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess-hs-libraries: HSinternal-preprocessor-test-0.1.0.0-depends:- base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d-haddock-interfaces: /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/doc/html/internal-preprocessor-test/internal-preprocessor-test.haddock-haddock-html: /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/doc/html/internal-preprocessor-test-pkgroot: "/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist"-
− tests/ParserTests/ipi/internal-preprocessor-test.expr
@@ -1,48 +0,0 @@-InstalledPackageInfo- {abiDepends = [],- abiHash = AbiHash "",- author = "Mikhail Glushenkov",- category = "Testing",- ccOptions = [],- compatPackageKey = "internal-preprocessor-test-0.1.0.0",- copyright = "",- cxxOptions = [],- dataDir = "/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess",- depends = [UnitId "base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d"],- description = "See https://github.com/haskell/cabal/issues/1541#issuecomment-30155513",- exposed = True,- exposedModules = [ExposedModule- {exposedName = ModuleName "A", exposedReexport = Nothing}],- extraGHCiLibraries = [],- extraLibraries = [],- frameworkDirs = [],- frameworks = [],- haddockHTMLs = ["/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/doc/html/internal-preprocessor-test"],- haddockInterfaces = ["/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/doc/html/internal-preprocessor-test/internal-preprocessor-test.haddock"],- hiddenModules = [],- homepage = "",- hsLibraries = ["HSinternal-preprocessor-test-0.1.0.0"],- importDirs = ["/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build"],- includeDirs = [],- includes = [],- indefinite = False,- installedComponentId_ = ComponentId "",- installedUnitId = UnitId "internal-preprocessor-test-0.1.0.0",- instantiatedWith = [],- ldOptions = [],- libVisibility = LibraryVisibilityPublic,- libraryDirs = ["/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build",- "/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build"],- libraryDynDirs = [],- license = Right (GPL (Just (mkVersion [3]))),- maintainer = "mikhail.glushenkov@gmail.com",- pkgRoot = Just- "/home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist",- pkgUrl = "",- sourceLibName = LMainLibName,- sourcePackageId = PackageIdentifier- {pkgName = PackageName "internal-preprocessor-test",- pkgVersion = mkVersion [0, 1, 0, 0]},- stability = "",- synopsis = "Internal custom preprocessor example.",- trusted = False}
− tests/ParserTests/ipi/internal-preprocessor-test.format
@@ -1,32 +0,0 @@-name: internal-preprocessor-test-version: 0.1.0.0-visibility: public-id: internal-preprocessor-test-0.1.0.0-key: internal-preprocessor-test-0.1.0.0-license: GPL-3-maintainer: mikhail.glushenkov@gmail.com-author: Mikhail Glushenkov-synopsis: Internal custom preprocessor example.-description:- See https://github.com/haskell/cabal/issues/1541#issuecomment-30155513--category: Testing-exposed: True-exposed-modules: A-import-dirs:- /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build--library-dirs:- /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build- /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/build--data-dir:- /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess--hs-libraries: HSinternal-preprocessor-test-0.1.0.0-depends: base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d-haddock-interfaces:- /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/doc/html/internal-preprocessor-test/internal-preprocessor-test.haddock--haddock-html:- /home/ogre/Documents/other-haskell/cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.dist/work/dist/doc/html/internal-preprocessor-test
− tests/ParserTests/ipi/issue-2276-ghc-9885.cabal
@@ -1,175 +0,0 @@-name: transformers-version: 0.5.2.0-id: transformers-0.5.2.0-key: transformers-0.5.2.0-license: BSD3-maintainer: Ross Paterson <R.Paterson@city.ac.uk>-synopsis: Concrete functor and monad transformers-description:- A portable library of functor and monad transformers, inspired by- the paper \"Functional Programming with Overloading and Higher-Order- Polymorphism\", by Mark P Jones,- in /Advanced School of Functional Programming/, 1995- (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).- .- This package contains:- .- * the monad transformer class (in "Control.Monad.Trans.Class")- and IO monad class (in "Control.Monad.IO.Class")- .- * concrete functor and monad transformers, each with associated- operations and functions to lift operations associated with other- transformers.- .- The package can be used on its own in portable Haskell code, in- which case operations need to be manually lifted through transformer- stacks (see "Control.Monad.Trans.Class" for some examples).- Alternatively, it can be used with the non-portable monad classes in- the @mtl@ or @monads-tf@ packages, which automatically lift operations- introduced by monad transformers through other transformers.-category: Control-author: Andy Gill, Ross Paterson-exposed: True-indefinite: False-exposed-modules:- Control.Applicative.Backwards Control.Applicative.Lift- Control.Monad.Signatures Control.Monad.Trans.Class- Control.Monad.Trans.Cont Control.Monad.Trans.Error- Control.Monad.Trans.Except Control.Monad.Trans.Identity- Control.Monad.Trans.List Control.Monad.Trans.Maybe- Control.Monad.Trans.RWS Control.Monad.Trans.RWS.Lazy- Control.Monad.Trans.RWS.Strict Control.Monad.Trans.Reader- Control.Monad.Trans.State Control.Monad.Trans.State.Lazy- Control.Monad.Trans.State.Strict Control.Monad.Trans.Writer- Control.Monad.Trans.Writer.Lazy Control.Monad.Trans.Writer.Strict- Data.Functor.Constant Data.Functor.Reverse-abi: e04579c0363c9229351d1a0b394bf2d5-trusted: False-import-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-dynamic-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-data-dir: /opt/ghc/8.2.2/share/x86_64-linux-ghc-8.2.2/transformers-0.5.2.0-hs-libraries: HStransformers-0.5.2.0-depends:- base-4.10.1.0-abi-depends: base-4.10.1.0=35a7f6be752ee4f7385cb5bf28677879-haddock-interfaces: /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0/transformers.haddock-haddock-html: /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0-ld-options: -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm
− tests/ParserTests/ipi/issue-2276-ghc-9885.expr
@@ -1,2133 +0,0 @@-InstalledPackageInfo- {abiDepends = [AbiDependency- {depAbiHash = AbiHash "35a7f6be752ee4f7385cb5bf28677879",- depUnitId = UnitId "base-4.10.1.0"}],- abiHash = AbiHash "e04579c0363c9229351d1a0b394bf2d5",- author = "Andy Gill, Ross Paterson",- category = "Control",- ccOptions = [],- compatPackageKey = "transformers-0.5.2.0",- copyright = "",- cxxOptions = [],- dataDir = "/opt/ghc/8.2.2/share/x86_64-linux-ghc-8.2.2/transformers-0.5.2.0",- depends = [UnitId "base-4.10.1.0"],- description = concat- ["A portable library of functor and monad transformers, inspired by\n",- "the paper \\\"Functional Programming with Overloading and Higher-Order\n",- "Polymorphism\\\", by Mark P Jones,\n",- "in /Advanced School of Functional Programming/, 1995\n",- "(<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).\n",- ".\n",- "This package contains:\n",- ".\n",- "* the monad transformer class (in \"Control.Monad.Trans.Class\")\n",- "and IO monad class (in \"Control.Monad.IO.Class\")\n",- ".\n",- "* concrete functor and monad transformers, each with associated\n",- "operations and functions to lift operations associated with other\n",- "transformers.\n",- ".\n",- "The package can be used on its own in portable Haskell code, in\n",- "which case operations need to be manually lifted through transformer\n",- "stacks (see \"Control.Monad.Trans.Class\" for some examples).\n",- "Alternatively, it can be used with the non-portable monad classes in\n",- "the @mtl@ or @monads-tf@ packages, which automatically lift operations\n",- "introduced by monad transformers through other transformers."],- exposed = True,- exposedModules = [ExposedModule- {exposedName = ModuleName "Control.Applicative.Backwards",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Applicative.Lift",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Signatures",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Class",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Cont",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Error",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Except",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Identity",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.List",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Maybe",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.RWS",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.RWS.Lazy",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.RWS.Strict",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Reader",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.State",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.State.Lazy",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.State.Strict",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Writer",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Writer.Lazy",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Writer.Strict",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Data.Functor.Constant",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Data.Functor.Reverse",- exposedReexport = Nothing}],- extraGHCiLibraries = [],- extraLibraries = [],- frameworkDirs = [],- frameworks = [],- haddockHTMLs = ["/opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0"],- haddockInterfaces = ["/opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0/transformers.haddock"],- hiddenModules = [],- homepage = "",- hsLibraries = ["HStransformers-0.5.2.0"],- importDirs = ["/opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0"],- includeDirs = [],- includes = [],- indefinite = False,- installedComponentId_ = ComponentId "",- installedUnitId = UnitId "transformers-0.5.2.0",- instantiatedWith = [],- ldOptions = ["-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm",- "-lm"],- libVisibility = LibraryVisibilityPublic,- libraryDirs = ["/opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0"],- libraryDynDirs = ["/opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0"],- license = Right BSD3,- maintainer = "Ross Paterson <R.Paterson@city.ac.uk>",- pkgRoot = Nothing,- pkgUrl = "",- sourceLibName = LMainLibName,- sourcePackageId = PackageIdentifier- {pkgName = PackageName "transformers",- pkgVersion = mkVersion [0, 5, 2, 0]},- stability = "",- synopsis = "Concrete functor and monad transformers",- trusted = False}
− tests/ParserTests/ipi/issue-2276-ghc-9885.format
@@ -1,182 +0,0 @@-name: transformers-version: 0.5.2.0-visibility: public-id: transformers-0.5.2.0-key: transformers-0.5.2.0-license: BSD3-maintainer: Ross Paterson <R.Paterson@city.ac.uk>-author: Andy Gill, Ross Paterson-synopsis: Concrete functor and monad transformers-description:- A portable library of functor and monad transformers, inspired by- the paper \"Functional Programming with Overloading and Higher-Order- Polymorphism\", by Mark P Jones,- in /Advanced School of Functional Programming/, 1995- (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).- .- This package contains:- .- * the monad transformer class (in "Control.Monad.Trans.Class")- and IO monad class (in "Control.Monad.IO.Class")- .- * concrete functor and monad transformers, each with associated- operations and functions to lift operations associated with other- transformers.- .- The package can be used on its own in portable Haskell code, in- which case operations need to be manually lifted through transformer- stacks (see "Control.Monad.Trans.Class" for some examples).- Alternatively, it can be used with the non-portable monad classes in- the @mtl@ or @monads-tf@ packages, which automatically lift operations- introduced by monad transformers through other transformers.--category: Control-abi: e04579c0363c9229351d1a0b394bf2d5-exposed: True-exposed-modules:- Control.Applicative.Backwards Control.Applicative.Lift- Control.Monad.Signatures Control.Monad.Trans.Class- Control.Monad.Trans.Cont Control.Monad.Trans.Error- Control.Monad.Trans.Except Control.Monad.Trans.Identity- Control.Monad.Trans.List Control.Monad.Trans.Maybe- Control.Monad.Trans.RWS Control.Monad.Trans.RWS.Lazy- Control.Monad.Trans.RWS.Strict Control.Monad.Trans.Reader- Control.Monad.Trans.State Control.Monad.Trans.State.Lazy- Control.Monad.Trans.State.Strict Control.Monad.Trans.Writer- Control.Monad.Trans.Writer.Lazy Control.Monad.Trans.Writer.Strict- Data.Functor.Constant Data.Functor.Reverse--import-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-dynamic-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-data-dir:- /opt/ghc/8.2.2/share/x86_64-linux-ghc-8.2.2/transformers-0.5.2.0--hs-libraries: HStransformers-0.5.2.0-depends: base-4.10.1.0-abi-depends: base-4.10.1.0=35a7f6be752ee4f7385cb5bf28677879-ld-options:- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm- -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm -lm--haddock-interfaces:- /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0/transformers.haddock--haddock-html:- /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0
− tests/ParserTests/ipi/transformers.cabal
@@ -1,59 +0,0 @@-name: transformers-version: 0.5.2.0-id: transformers-0.5.2.0-key: transformers-0.5.2.0-license: BSD3-maintainer: Ross Paterson <R.Paterson@city.ac.uk>-synopsis: Concrete functor and monad transformers-description:- A portable library of functor and monad transformers, inspired by- the paper \"Functional Programming with Overloading and Higher-Order- Polymorphism\", by Mark P Jones,- in /Advanced School of Functional Programming/, 1995- (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).- .- This package contains:- .- * the monad transformer class (in "Control.Monad.Trans.Class")- and IO monad class (in "Control.Monad.IO.Class")- .- * concrete functor and monad transformers, each with associated- operations and functions to lift operations associated with other- transformers.- .- The package can be used on its own in portable Haskell code, in- which case operations need to be manually lifted through transformer- stacks (see "Control.Monad.Trans.Class" for some examples).- Alternatively, it can be used with the non-portable monad classes in- the @mtl@ or @monads-tf@ packages, which automatically lift operations- introduced by monad transformers through other transformers.-category: Control-author: Andy Gill, Ross Paterson-exposed: True-indefinite: False-exposed-modules:- Control.Applicative.Backwards Control.Applicative.Lift- Control.Monad.Signatures Control.Monad.Trans.Class- Control.Monad.Trans.Cont Control.Monad.Trans.Error- Control.Monad.Trans.Except Control.Monad.Trans.Identity- Control.Monad.Trans.List Control.Monad.Trans.Maybe- Control.Monad.Trans.RWS Control.Monad.Trans.RWS.Lazy- Control.Monad.Trans.RWS.Strict Control.Monad.Trans.Reader- Control.Monad.Trans.State Control.Monad.Trans.State.Lazy- Control.Monad.Trans.State.Strict Control.Monad.Trans.Writer- Control.Monad.Trans.Writer.Lazy Control.Monad.Trans.Writer.Strict- Data.Functor.Constant Data.Functor.Reverse-abi: e04579c0363c9229351d1a0b394bf2d5-trusted: False-import-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-dynamic-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-data-dir: /opt/ghc/8.2.2/share/x86_64-linux-ghc-8.2.2/transformers-0.5.2.0-hs-libraries: HStransformers-0.5.2.0-depends:- base-4.10.1.0-abi-depends: base-4.10.1.0=35a7f6be752ee4f7385cb5bf28677879-haddock-interfaces: /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0/transformers.haddock-haddock-html: /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0-pkgroot: "/opt/ghc/8.2.2/lib/ghc-8.2.2"-
− tests/ParserTests/ipi/transformers.expr
@@ -1,133 +0,0 @@-InstalledPackageInfo- {abiDepends = [AbiDependency- {depAbiHash = AbiHash "35a7f6be752ee4f7385cb5bf28677879",- depUnitId = UnitId "base-4.10.1.0"}],- abiHash = AbiHash "e04579c0363c9229351d1a0b394bf2d5",- author = "Andy Gill, Ross Paterson",- category = "Control",- ccOptions = [],- compatPackageKey = "transformers-0.5.2.0",- copyright = "",- cxxOptions = [],- dataDir = "/opt/ghc/8.2.2/share/x86_64-linux-ghc-8.2.2/transformers-0.5.2.0",- depends = [UnitId "base-4.10.1.0"],- description = concat- ["A portable library of functor and monad transformers, inspired by\n",- "the paper \\\"Functional Programming with Overloading and Higher-Order\n",- "Polymorphism\\\", by Mark P Jones,\n",- "in /Advanced School of Functional Programming/, 1995\n",- "(<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).\n",- ".\n",- "This package contains:\n",- ".\n",- "* the monad transformer class (in \"Control.Monad.Trans.Class\")\n",- "and IO monad class (in \"Control.Monad.IO.Class\")\n",- ".\n",- "* concrete functor and monad transformers, each with associated\n",- "operations and functions to lift operations associated with other\n",- "transformers.\n",- ".\n",- "The package can be used on its own in portable Haskell code, in\n",- "which case operations need to be manually lifted through transformer\n",- "stacks (see \"Control.Monad.Trans.Class\" for some examples).\n",- "Alternatively, it can be used with the non-portable monad classes in\n",- "the @mtl@ or @monads-tf@ packages, which automatically lift operations\n",- "introduced by monad transformers through other transformers."],- exposed = True,- exposedModules = [ExposedModule- {exposedName = ModuleName "Control.Applicative.Backwards",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Applicative.Lift",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Signatures",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Class",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Cont",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Error",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Except",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Identity",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.List",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Maybe",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.RWS",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.RWS.Lazy",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.RWS.Strict",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Reader",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.State",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.State.Lazy",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.State.Strict",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Writer",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Writer.Lazy",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Control.Monad.Trans.Writer.Strict",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Data.Functor.Constant",- exposedReexport = Nothing},- ExposedModule- {exposedName = ModuleName "Data.Functor.Reverse",- exposedReexport = Nothing}],- extraGHCiLibraries = [],- extraLibraries = [],- frameworkDirs = [],- frameworks = [],- haddockHTMLs = ["/opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0"],- haddockInterfaces = ["/opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0/transformers.haddock"],- hiddenModules = [],- homepage = "",- hsLibraries = ["HStransformers-0.5.2.0"],- importDirs = ["/opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0"],- includeDirs = [],- includes = [],- indefinite = False,- installedComponentId_ = ComponentId "",- installedUnitId = UnitId "transformers-0.5.2.0",- instantiatedWith = [],- ldOptions = [],- libVisibility = LibraryVisibilityPublic,- libraryDirs = ["/opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0"],- libraryDynDirs = ["/opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0"],- license = Right BSD3,- maintainer = "Ross Paterson <R.Paterson@city.ac.uk>",- pkgRoot = Just "/opt/ghc/8.2.2/lib/ghc-8.2.2",- pkgUrl = "",- sourceLibName = LMainLibName,- sourcePackageId = PackageIdentifier- {pkgName = PackageName "transformers",- pkgVersion = mkVersion [0, 5, 2, 0]},- stability = "",- synopsis = "Concrete functor and monad transformers",- trusted = False}
− tests/ParserTests/ipi/transformers.format
@@ -1,62 +0,0 @@-name: transformers-version: 0.5.2.0-visibility: public-id: transformers-0.5.2.0-key: transformers-0.5.2.0-license: BSD3-maintainer: Ross Paterson <R.Paterson@city.ac.uk>-author: Andy Gill, Ross Paterson-synopsis: Concrete functor and monad transformers-description:- A portable library of functor and monad transformers, inspired by- the paper \"Functional Programming with Overloading and Higher-Order- Polymorphism\", by Mark P Jones,- in /Advanced School of Functional Programming/, 1995- (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>).- .- This package contains:- .- * the monad transformer class (in "Control.Monad.Trans.Class")- and IO monad class (in "Control.Monad.IO.Class")- .- * concrete functor and monad transformers, each with associated- operations and functions to lift operations associated with other- transformers.- .- The package can be used on its own in portable Haskell code, in- which case operations need to be manually lifted through transformer- stacks (see "Control.Monad.Trans.Class" for some examples).- Alternatively, it can be used with the non-portable monad classes in- the @mtl@ or @monads-tf@ packages, which automatically lift operations- introduced by monad transformers through other transformers.--category: Control-abi: e04579c0363c9229351d1a0b394bf2d5-exposed: True-exposed-modules:- Control.Applicative.Backwards Control.Applicative.Lift- Control.Monad.Signatures Control.Monad.Trans.Class- Control.Monad.Trans.Cont Control.Monad.Trans.Error- Control.Monad.Trans.Except Control.Monad.Trans.Identity- Control.Monad.Trans.List Control.Monad.Trans.Maybe- Control.Monad.Trans.RWS Control.Monad.Trans.RWS.Lazy- Control.Monad.Trans.RWS.Strict Control.Monad.Trans.Reader- Control.Monad.Trans.State Control.Monad.Trans.State.Lazy- Control.Monad.Trans.State.Strict Control.Monad.Trans.Writer- Control.Monad.Trans.Writer.Lazy Control.Monad.Trans.Writer.Strict- Data.Functor.Constant Data.Functor.Reverse--import-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-dynamic-library-dirs: /opt/ghc/8.2.2/lib/ghc-8.2.2/transformers-0.5.2.0-data-dir:- /opt/ghc/8.2.2/share/x86_64-linux-ghc-8.2.2/transformers-0.5.2.0--hs-libraries: HStransformers-0.5.2.0-depends: base-4.10.1.0-abi-depends: base-4.10.1.0=35a7f6be752ee4f7385cb5bf28677879-haddock-interfaces:- /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0/transformers.haddock--haddock-html:- /opt/ghc/8.2.2/share/doc/ghc-8.2.2/html/libraries/transformers-0.5.2.0
− tests/ParserTests/regressions/Octree-0.5.cabal
@@ -1,44 +0,0 @@-name: Octree-version: 0.5-stability: beta-homepage: https://github.com/mgajda/octree-package-url: http://hackage.haskell.org/package/octree-synopsis: Simple unbalanced Octree for storing data about 3D points-description: Octree data structure is relatively shallow data structure for space partitioning.-category: Data-license: BSD3-license-file: LICENSE--author: Michal J. Gajda-copyright: Copyright by Michal J. Gajda '2012-maintainer: mjgajda@googlemail.com-bug-reports: mailto:mjgajda@googlemail.com---build-type: Simple-cabal-version: >=1.8-tested-with: GHC==7.0.4,GHC==7.4.1,GHC==7.4.2,GHC==7.6.0--source-repository head- type: git- location: git@github.com:mgajda/octree.git--Library- build-depends: base>=4.0 && < 4.7, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0- exposed-modules: Data.Octree- other-modules: Data.Octree.Internal- exposed: True- extensions: ScopedTypeVariables--Test-suite test_Octree- Type: exitcode-stdio-1.0- Build-depends: base>=4.0 && < 4.7, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0- Main-is: tests/test_Octree.hs--Test-suite readme- type: exitcode-stdio-1.0- -- We have a symlink: README.lhs -> README.md- main-is: README.lhs- Build-depends: base>=4.0 && < 4.7, AC-Vector >= 2.3.0, QuickCheck >= 2.4.0, markdown-unlit- ghc-options: -pgmL markdown-unlit-
− tests/ParserTests/regressions/Octree-0.5.expr
@@ -1,357 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 0]))- (EarlierVersion (mkVersion [4, 7])))- mainLibSet,- Dependency- (PackageName "AC-Vector")- (OrLaterVersion (mkVersion [2, 3, 0]))- mainLibSet,- Dependency- (PackageName "QuickCheck")- (OrLaterVersion (mkVersion [2, 4, 0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Data.Octree"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [EnableExtension- ScopedTypeVariables],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "Data.Octree.Internal"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4, 0]))- (EarlierVersion- (mkVersion- [4, 7])))- mainLibSet,- Dependency- (PackageName- "AC-Vector")- (OrLaterVersion- (mkVersion- [2, 3, 0]))- mainLibSet,- Dependency- (PackageName- "QuickCheck")- (OrLaterVersion- (mkVersion- [2, 4, 0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "test_Octree")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 0]))- (EarlierVersion (mkVersion [4, 7])))- mainLibSet,- Dependency- (PackageName "AC-Vector")- (OrLaterVersion (mkVersion [2, 3, 0]))- mainLibSet,- Dependency- (PackageName "QuickCheck")- (OrLaterVersion (mkVersion [2, 4, 0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 0]))- (EarlierVersion- (mkVersion- [4,- 7])))- mainLibSet,- Dependency- (PackageName- "AC-Vector")- (OrLaterVersion- (mkVersion- [2,- 3,- 0]))- mainLibSet,- Dependency- (PackageName- "QuickCheck")- (OrLaterVersion- (mkVersion- [2,- 4,- 0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0])- "tests/test_Octree.hs",- testName = UnqualComponentName ""}},- _×_- (UnqualComponentName "readme")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 0]))- (EarlierVersion (mkVersion [4, 7])))- mainLibSet,- Dependency- (PackageName "AC-Vector")- (OrLaterVersion (mkVersion [2, 3, 0]))- mainLibSet,- Dependency- (PackageName "QuickCheck")- (OrLaterVersion (mkVersion [2, 4, 0]))- mainLibSet,- Dependency- (PackageName "markdown-unlit")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-pgmL",- "markdown-unlit"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 0]))- (EarlierVersion- (mkVersion- [4,- 7])))- mainLibSet,- Dependency- (PackageName- "AC-Vector")- (OrLaterVersion- (mkVersion- [2,- 3,- 0]))- mainLibSet,- Dependency- (PackageName- "QuickCheck")- (OrLaterVersion- (mkVersion- [2,- 4,- 0]))- mainLibSet,- Dependency- (PackageName- "markdown-unlit")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "README.lhs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Michal J. Gajda",- benchmarks = [],- bugReports = "mailto:mjgajda@googlemail.com",- buildTypeRaw = Just Simple,- category = "Data",- copyright = "Copyright by Michal J. Gajda '2012",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "Octree data structure is relatively shallow data structure for space partitioning.",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "https://github.com/mgajda/octree",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Right BSD3,- maintainer = "mjgajda@googlemail.com",- package = PackageIdentifier- {pkgName = PackageName "Octree",- pkgVersion = mkVersion [0, 5]},- pkgUrl = "http://hackage.haskell.org/package/octree",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "git@github.com:mgajda/octree.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_8,- stability = "beta",- subLibraries = [],- synopsis = "Simple unbalanced Octree for storing data about 3D points",- testSuites = [],- testedWith = [_×_ GHC (ThisVersion (mkVersion [7, 0, 4])),- _×_ GHC (ThisVersion (mkVersion [7, 4, 1])),- _×_ GHC (ThisVersion (mkVersion [7, 4, 2])),- _×_ GHC (ThisVersion (mkVersion [7, 6, 0]))]}}
− tests/ParserTests/regressions/Octree-0.5.format
@@ -1,51 +0,0 @@-Octree-0.5.cabal:39:3: Non breaking spaces at 39:3, 41:3, 43:3-cabal-version: >=1.8-name: Octree-version: 0.5-license: BSD3-license-file: LICENSE-copyright: Copyright by Michal J. Gajda '2012-maintainer: mjgajda@googlemail.com-author: Michal J. Gajda-stability: beta-tested-with: ghc ==7.0.4 ghc ==7.4.1 ghc ==7.4.2 ghc ==7.6.0-homepage: https://github.com/mgajda/octree-package-url: http://hackage.haskell.org/package/octree-bug-reports: mailto:mjgajda@googlemail.com-synopsis: Simple unbalanced Octree for storing data about 3D points-description:- Octree data structure is relatively shallow data structure for space partitioning.--category: Data-build-type: Simple--source-repository head- type: git- location: git@github.com:mgajda/octree.git--library- exposed-modules: Data.Octree- other-modules: Data.Octree.Internal- extensions: ScopedTypeVariables- build-depends:- base >=4.0 && <4.7,- AC-Vector >=2.3.0,- QuickCheck >=2.4.0--test-suite test_Octree- type: exitcode-stdio-1.0- main-is: tests/test_Octree.hs- build-depends:- base >=4.0 && <4.7,- AC-Vector >=2.3.0,- QuickCheck >=2.4.0--test-suite readme- type: exitcode-stdio-1.0- main-is: README.lhs- ghc-options: -pgmL markdown-unlit- build-depends:- base >=4.0 && <4.7,- AC-Vector >=2.3.0,- QuickCheck >=2.4.0,- markdown-unlit
− tests/ParserTests/regressions/anynone.cabal
@@ -1,10 +0,0 @@-cabal-version: 3.0-name: anynone-version: 0-synopsis: The -any none demo-build-type: Simple--library- default-language: Haskell2010- exposed-modules: AnyNone- build-depends: base -any
− tests/ParserTests/regressions/anynone.expr
@@ -1,105 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "AnyNone"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "anynone",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "The -any none demo",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/anynone.format
@@ -1,10 +0,0 @@-cabal-version: 3.0-name: anynone-version: 0-synopsis: The -any none demo-build-type: Simple--library- exposed-modules: AnyNone- default-language: Haskell2010- build-depends: base
− tests/ParserTests/regressions/assoc-cpp-options.cabal
@@ -1,48 +0,0 @@-cabal-version: 1.12-name: assoc-version: 1.1-license: BSD3-license-file: LICENSE-synopsis: swap and assoc: Symmetric and Semigroupy Bifunctors-category: Data-description:- Provides generalisations of- @swap :: (a,b) -> (b,a)@ and- @assoc :: ((a,b),c) -> (a,(b,c))@- to- @Bifunctor@s supporting similar operations (e.g. @Either@, @These@).--author: Oleg Grenrus <oleg.grenrus@iki.fi>-maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-build-type: Simple-tested-with:- GHC ==7.0.4- || ==7.2.2- || ==7.4.2- || ==7.6.3- || ==7.8.4- || ==7.10.3- || ==8.0.2- || ==8.2.2- || ==8.4.4- || ==8.6.5- || ==8.8.1--source-repository head- type: git- location: https://github.com/phadej/assoc.git--library- default-language: Haskell2010- hs-source-dirs: src- build-depends:- base >=4.3 && <4.13- , bifunctors >=5.5.4 && <5.6-- cpp-options: -traditional-- exposed-modules:- Data.Bifunctor.Assoc- Data.Bifunctor.Swap-- other-extensions: TypeFamilies
− tests/ParserTests/regressions/assoc-cpp-options.check
@@ -1,1 +0,0 @@-'cpp-options': -traditional is not portable C-preprocessor flag
− tests/ParserTests/regressions/bad-glob-syntax.cabal
@@ -1,16 +0,0 @@-cabal-version: 2.2-name: bad-glob-syntax-version: 0-extra-source-files:- foo/blah-*.hs- foo/*/bar-license: BSD-3-Clause-synopsis: no-description: none-category: Test-maintainer: none--library- default-language: Haskell2010- exposed-modules:- Foo
− tests/ParserTests/regressions/bad-glob-syntax.check
@@ -1,2 +0,0 @@-In the 'extra-source-files' field: invalid file glob 'foo/blah-*.hs'. Wildcards '*' may only totally replace the file's base name, not only parts of it.-In the 'extra-source-files' field: invalid file glob 'foo/*/bar'. A wildcard '**' is only allowed as the final parent directory. Stars must not otherwise appear in the parent directories.
− tests/ParserTests/regressions/big-version.cabal
@@ -1,7 +0,0 @@-cabal-version: 3.0-name: big-version--- 9 digits-version: 123456789--library- default-language: Haskell2010
− tests/ParserTests/regressions/big-version.expr
@@ -1,96 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "big-version",- pkgVersion = mkVersion [123456789]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/big-version.format
@@ -1,6 +0,0 @@-cabal-version: 3.0-name: big-version-version: 123456789--library- default-language: Haskell2010
− tests/ParserTests/regressions/cc-options-with-optimization.cabal
@@ -1,15 +0,0 @@-cabal-version: 2.2-category: test-description: test a build check involving C++-options field-license: BSD-3-Clause-maintainer: me@example.com-name: cxx-options-with-optimization-synopsis: test a build check-version: 1- -library- build-depends: base >= 4.9 && <4.10- cc-options: -O2- default-language: Haskell2010- exposed-modules: Prelude- hs-source-dirs: .
− tests/ParserTests/regressions/cc-options-with-optimization.check
@@ -1,1 +0,0 @@-'cc-options: -O[n]' is generally not needed. When building with optimisations Cabal automatically adds '-O2' for C code. Setting it yourself interferes with the --disable-optimization flag.
− tests/ParserTests/regressions/common-conditional.cabal
@@ -1,49 +0,0 @@-cabal-version: 3.0-name: common-conditional-version: 0-synopsis: Common-stanza demo demo-build-type: Simple--source-repository head- Type: git- Location: https://github.com/hvr/-.git--flag foo- manual: True- default: True--common win-dows- if os(windows)- build-depends: Win32--common deps- import: win-dows- buildable: True- build-depends:- base >=4.10 && <4.11,- containers--library- if flag(foo)- import: deps-- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends:- ghc-prim--test-suite tests- -- buildable fields verify that we don't have duplicate field warnings- buildable: True- if os(windows)- buildable: False-- if flag(foo)- import: deps, win-dows-- type: exitcode-stdio-1.0- main-is: Tests.hs-- build-depends:- HUnit
− tests/ParserTests/regressions/common-conditional.expr
@@ -1,682 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "foo"))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "ghc-prim")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "ghc-prim")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "tests")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = False,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}},- CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "foo"))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}},- CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [Dependency- (PackageName "HUnit")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "HUnit")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Tests.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [MkPackageFlag- {flagDefault = True,- flagDescription = "",- flagManual = True,- flagName = FlagName "foo"}],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "common-conditional",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "https://github.com/hvr/-.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "Common-stanza demo demo",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/common-conditional.format
@@ -1,44 +0,0 @@-cabal-version: 3.0-name: common-conditional-version: 0-synopsis: Common-stanza demo demo-build-type: Simple--source-repository head- type: git- location: https://github.com/hvr/-.git--flag foo- manual: True--library- exposed-modules: ElseIf- default-language: Haskell2010- build-depends: ghc-prim-- if flag(foo)- build-depends:- base >=4.10 && <4.11,- containers-- if os(windows)- build-depends: Win32--test-suite tests- type: exitcode-stdio-1.0- main-is: Tests.hs- build-depends: HUnit-- if os(windows)- buildable: False-- if flag(foo)- build-depends:- base >=4.10 && <4.11,- containers-- if os(windows)- build-depends: Win32-- if os(windows)- build-depends: Win32
− tests/ParserTests/regressions/common.cabal
@@ -1,35 +0,0 @@-name: common-version: 0-x-revision: 1-synopsis: Common-stanza demo demo-build-type: Simple-cabal-version: >=1.10--- note: empty field-x-follows-version-policy:--source-repository head- Type: git- Location: https://github.com/hvr/-.git--common deps- build-depends:- base >=4.10 && <4.11,- containers--library- import: deps-- default-language: Haskell2010- exposed-modules: "ElseIf"-- build-depends:- ghc-prim--test-suite tests- import: deps-- type: exitcode-stdio-1.0- main-is: Tests.hs-- build-depends:- HUnit
− tests/ParserTests/regressions/common.expr
@@ -1,176 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "ghc-prim")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "ghc-prim")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "tests")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "HUnit")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "HUnit")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Tests.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [_×_ "x-revision" "1",- _×_ "x-follows-version-policy" ""],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "common", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "https://github.com/hvr/-.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_10,- stability = "",- subLibraries = [],- synopsis = "Common-stanza demo demo",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/common.format
@@ -1,24 +0,0 @@-common.cabal:29:3: Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas-common.cabal:20:3: Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas-common.cabal:14:1: Ignoring section: common. You should set cabal-version: 2.2 or larger to use common stanzas.-cabal-version: >=1.10-name: common-version: 0-synopsis: Common-stanza demo demo-x-revision: 1-x-follows-version-policy:-build-type: Simple--source-repository head- type: git- location: https://github.com/hvr/-.git--library- exposed-modules: ElseIf- default-language: Haskell2010- build-depends: ghc-prim--test-suite tests- type: exitcode-stdio-1.0- main-is: Tests.hs- build-depends: HUnit
− tests/ParserTests/regressions/common2.cabal
@@ -1,53 +0,0 @@-cabal-version: 2.2-name: common-version: 0-synopsis: Common-stanza demo demo-build-type: Simple--source-repository head- Type: git- Location: https://github.com/hvr/-.git--common win-dows- if os(windows)- build-depends: Win32--common deps- import: win-dows- buildable: True- build-depends:- base >=4.10 && <4.11,- containers--library- import: deps-- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends:- ghc-prim---- .expr should show libVisible: False-library internal- import: deps-- default-language: Haskell2010- exposed-modules: ElseIf2-- build-depends:- ghc-prim--test-suite tests- import: deps, win-dows-- -- buildable fields verify that we don't have duplicate field warnings- buildable: True- if os(windows)- buildable: False-- type: exitcode-stdio-1.0- main-is: Tests.hs-- build-depends:- HUnit
− tests/ParserTests/regressions/common2.expr
@@ -1,707 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 10]))- (EarlierVersion (mkVersion [4, 11])))- mainLibSet,- Dependency- (PackageName "containers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "ghc-prim")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4, 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "ghc-prim")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [_×_- (UnqualComponentName "internal")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "internal"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 10]))- (EarlierVersion (mkVersion [4, 11])))- mainLibSet,- Dependency- (PackageName "containers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "ghc-prim")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf2"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "ghc-prim")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName "internal"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}],- condTestSuites = [_×_- (UnqualComponentName "tests")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}},- CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}},- CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = False,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 10]))- (EarlierVersion (mkVersion [4, 11])))- mainLibSet,- Dependency- (PackageName "containers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "HUnit")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "HUnit")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Tests.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "common", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "https://github.com/hvr/-.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV2_2,- stability = "",- subLibraries = [],- synopsis = "Common-stanza demo demo",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/common2.format
@@ -1,48 +0,0 @@-cabal-version: 2.2-name: common-version: 0-synopsis: Common-stanza demo demo-build-type: Simple--source-repository head- type: git- location: https://github.com/hvr/-.git--library- exposed-modules: ElseIf- default-language: Haskell2010- build-depends:- base >=4.10 && <4.11,- containers,- ghc-prim-- if os(windows)- build-depends: Win32--library internal- exposed-modules: ElseIf2- default-language: Haskell2010- build-depends:- base >=4.10 && <4.11,- containers,- ghc-prim-- if os(windows)- build-depends: Win32--test-suite tests- type: exitcode-stdio-1.0- main-is: Tests.hs- build-depends:- base >=4.10 && <4.11,- containers,- HUnit-- if os(windows)- build-depends: Win32-- if os(windows)- build-depends: Win32-- if os(windows)- buildable: False
− tests/ParserTests/regressions/common3.cabal
@@ -1,36 +0,0 @@-cabal-version: 2.2-name: common-version: 0-x-revision: 1-synopsis: Common-stanza demo demo-build-type: Simple--- note: empty field-x-follows-version-policy:--source-repository head- Type: git- Location: https://github.com/hvr/-.git--common deps- build-depends:- base >=4.10 && <4.11,- containers--library- default-language: Haskell2010- exposed-modules: "ElseIf"-- -- not first: will be omitted and generate warning- import: deps-- build-depends:- ghc-prim--test-suite tests- import: deps-- type: exitcode-stdio-1.0- main-is: Tests.hs-- build-depends:- HUnit
− tests/ParserTests/regressions/common3.expr
@@ -1,206 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "ghc-prim")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "ghc-prim")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "tests")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 10]))- (EarlierVersion (mkVersion [4, 11])))- mainLibSet,- Dependency- (PackageName "containers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "HUnit")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 10]))- (EarlierVersion- (mkVersion- [4,- 11])))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "HUnit")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Tests.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [_×_ "x-revision" "1",- _×_ "x-follows-version-policy" ""],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "common", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "https://github.com/hvr/-.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV2_2,- stability = "",- subLibraries = [],- synopsis = "Common-stanza demo demo",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/common3.format
@@ -1,25 +0,0 @@-common3.cabal:24:3: Unknown field: import. Common stanza imports should be at the top of the enclosing section-cabal-version: 2.2-name: common-version: 0-synopsis: Common-stanza demo demo-x-revision: 1-x-follows-version-policy:-build-type: Simple--source-repository head- type: git- location: https://github.com/hvr/-.git--library- exposed-modules: ElseIf- default-language: Haskell2010- build-depends: ghc-prim--test-suite tests- type: exitcode-stdio-1.0- main-is: Tests.hs- build-depends:- base >=4.10 && <4.11,- containers,- HUnit
− tests/ParserTests/regressions/cxx-options-with-optimization.cabal
@@ -1,15 +0,0 @@-cabal-version: 2.2-category: test-description: test a build check involving C++-options field-license: BSD-3-Clause-maintainer: me@example.com-name: cxx-options-with-optimization-synopsis: test a build check-version: 1- -library- build-depends: base >= 4.9 && <4.10- cxx-options: -O2- default-language: Haskell2010- exposed-modules: Prelude- hs-source-dirs: .
− tests/ParserTests/regressions/cxx-options-with-optimization.check
@@ -1,1 +0,0 @@-'cxx-options: -O[n]' is generally not needed. When building with optimisations Cabal automatically adds '-O2' for C++ code. Setting it yourself interferes with the --disable-optimization flag.
− tests/ParserTests/regressions/denormalised-paths.cabal
@@ -1,71 +0,0 @@-cabal-version: 2.4-name: assoc-version: 1.1-license: BSD-3-Clause-license-files: LICENSE LICENSE2/ .-synopsis: swap and assoc: Symmetric and Semigroupy Bifunctors-category: Data-description:- Provides generalisations of- @swap :: (a,b) -> (b,a)@ and- @assoc :: ((a,b),c) -> (a,(b,c))@- to- @Bifunctor@s supporting similar operations (e.g. @Either@, @These@).--author: Oleg Grenrus <oleg.grenrus@iki.fi>-maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-build-type: Simple-tested-with:- GHC ==7.0.4- || ==7.2.2- || ==7.4.2- || ==7.6.3- || ==7.8.4- || ==7.10.3- || ==8.0.2- || ==8.2.2- || ==8.4.4- || ==8.6.5- || ==8.8.1--extra-source-files:- files/**/*.txt/- files/../foo.txt--source-repository head- type: git- location: https://github.com/phadej/assoc.git- subdir: ./.--source-repository this- type: git- location: https://github.com/phadej/assoc.git- tag: v1.1- subdir: foo/--library- default-language: Haskell2010- build-depends:- base >=4.3 && <4.13- , bifunctors >=5.5.4 && <5.6-- exposed-modules:- Data.Bifunctor.Assoc- Data.Bifunctor.Swap-- -- this is fine- hs-source-dirs: src/-- -- collection of invalid sources- hs-source-dirs: src/.- hs-source-dirs: src/../src- hs-source-dirs: src/../../assoc/src- -- this is forbidden by a parser- -- hs-source-dirs: C:/foo/bar- hs-source-dirs: C:foo/bar- hs-source-dirs: ||s- -- this is forbidden by a parser- -- hs-source-dirs: /var/secret/source-- -- this is the only case catched by Cabal-3.0.2.0- hs-source-dirs: ../../assoc/src
− tests/ParserTests/regressions/denormalised-paths.check
@@ -1,12 +0,0 @@-The 'subdir' field of a source-repository is not a good relative path: "trailing same directory segment: ."-'hs-source-dirs: ../../assoc/src' is a relative path outside of the source tree. This will not work when generating a tarball with 'sdist'.-'extra-source-files: files/**/*.txt/' is not good relative path: trailing slash-'extra-source-files: files/../foo.txt' is not good relative path: parent directory segment: ..-'license-file: LICENSE2/' is not good relative path: trailing slash-'license-file: .' is not good relative path: trailing dot segment-'hs-source-dirs: src/.' is not good relative path: trailing same directory segment: .-'hs-source-dirs: src/../src' is not good relative path: parent directory segment: ..-'hs-source-dirs: src/../../assoc/src' is not good relative path: parent directory segment: ..-'hs-source-dirs: C:foo/bar' is not good relative path: reserved character ':'-'hs-source-dirs: ||s' is not good relative path: reserved character '|'-'hs-source-dirs: ../../assoc/src' is not good relative path: parent directory segment: ..
− tests/ParserTests/regressions/elif.cabal
@@ -1,20 +0,0 @@-name: elif-version: 0-synopsis: The elif demo-build-type: Simple-cabal-version: >=1.10--source-repository head- Type: git- Location: https://github.com/hvr/-.git--library- default-language: Haskell2010- exposed-modules: ElseIf-- if os(linux)- build-depends: unix- elif os(windows)- build-depends: Win32- else- buildable: False
− tests/ParserTests/regressions/elif.expr
@@ -1,178 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Linux)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "elif", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "https://github.com/hvr/-.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_10,- stability = "",- subLibraries = [],- synopsis = "The elif demo",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/elif.format
@@ -1,18 +0,0 @@-elif.cabal:19:3: invalid subsection "else"-elif.cabal:17:3: invalid subsection "elif". You should set cabal-version: 2.2 or larger to use elif-conditionals.-cabal-version: >=1.10-name: elif-version: 0-synopsis: The elif demo-build-type: Simple--source-repository head- type: git- location: https://github.com/hvr/-.git--library- exposed-modules: ElseIf- default-language: Haskell2010-- if os(linux)- build-depends: unix
− tests/ParserTests/regressions/elif2.cabal
@@ -1,20 +0,0 @@-cabal-version: 2.2-name: elif-version: 0-synopsis: The elif demo-build-type: Simple--source-repository head- Type: git- Location: https://github.com/hvr/-.git--library- default-language: Haskell2010- exposed-modules: ElseIf-- if os(linux)- build-depends: unix- elif os(windows)- build-depends: Win32- else- buildable: False
− tests/ParserTests/regressions/elif2.expr
@@ -1,378 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Linux)`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = False,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "elif", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "https://github.com/hvr/-.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV2_2,- stability = "",- subLibraries = [],- synopsis = "The elif demo",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/elif2.format
@@ -1,23 +0,0 @@-cabal-version: 2.2-name: elif-version: 0-synopsis: The elif demo-build-type: Simple--source-repository head- type: git- location: https://github.com/hvr/-.git--library- exposed-modules: ElseIf- default-language: Haskell2010-- if os(linux)- build-depends: unix-- else- if os(windows)- build-depends: Win32-- else- buildable: False
− tests/ParserTests/regressions/encoding-0.8.cabal
@@ -1,24 +0,0 @@-Name: encoding-wrong-Name: encoding-Version: 0.8-cabal-version: >=1.12--- double-dash files-extra-source-files:- -- this is comment- README.md "--"- "--"--custom-setup- setup-depends:- base < 5,- ghc-prim--Library- -- version range round trip is better- build-depends: base (> 4.4 || == 4.4)-- Exposed-Modules:- Data.Encoding-- -- options with spaces- GHC-Options: -Wall -O2 -threaded -rtsopts "-with-rtsopts=-N1 -A64m"
− tests/ParserTests/regressions/encoding-0.8.expr
@@ -1,127 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (UnionVersionRanges- (LaterVersion (mkVersion [4, 4]))- (ThisVersion (mkVersion [4, 4])))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Data.Encoding"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall",- "-O2",- "-threaded",- "-rtsopts",- "-with-rtsopts=-N1 -A64m"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (UnionVersionRanges- (LaterVersion- (mkVersion- [4, 4]))- (ThisVersion- (mkVersion- [4, 4])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = ["README.md", "--", "--"],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "encoding",- pkgVersion = mkVersion [0, 8]},- pkgUrl = "",- setupBuildInfo = Just- SetupBuildInfo- {defaultSetupDepends = False,- setupDepends = [Dependency- (PackageName "base")- (EarlierVersion (mkVersion [5]))- mainLibSet,- Dependency- (PackageName "ghc-prim")- (OrLaterVersion (mkVersion [0]))- mainLibSet]},- sourceRepos = [],- specVersion = CabalSpecV1_12,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/encoding-0.8.format
@@ -1,19 +0,0 @@-encoding-0.8.cabal:1:1: The field "name" is specified more than once at positions 1:1, 2:1-encoding-0.8.cabal:4:22: Packages with 'cabal-version: 1.12' or later should specify a specific version of the Cabal spec of the form 'cabal-version: x.y'. Use 'cabal-version: 1.12'.-cabal-version: 1.12-name: encoding-version: 0.8-extra-source-files:- README.md- "--"- "--"--custom-setup- setup-depends:- base <5,- ghc-prim--library- exposed-modules: Data.Encoding- ghc-options: -Wall -O2 -threaded -rtsopts "-with-rtsopts=-N1 -A64m"- build-depends: base >4.4 || ==4.4
− tests/ParserTests/regressions/extensions-paths-5054.cabal
@@ -1,39 +0,0 @@-name: extensions-paths-version: 5054-category: Test-maintainer: Oleg Grenrus-license: BSD3-license-file: LICENSe-synopsis: Paths_pkg module + "bad" extensions + old cabal-description:- Only cabal-version: 2.2 or later will build Paths_pkg ok with-- * RebindableSyntax and-- * OverloadedLists or OverloadedStrings-- `fromList` or `fromString` will be out-of-scope when compiling Paths_ module.-- Other extensions (like NoImplicitPrelude) were handled before-build-type: Simple-cabal-version: 1.12--library- default-language: Haskell2010- exposed-modules: Issue Paths_extensions_paths- default-extensions:- RebindableSyntax- OverloadedStrings--test-suite tests- default-language: Haskell2010- main-is: Test.hs- type: exitcode-stdio-1.0- if os(linux)- other-modules: Paths_extensions_paths- else- buildable: False-- default-extensions:- OverloadedLists- RebindableSyntax
− tests/ParserTests/regressions/extensions-paths-5054.check
@@ -1,1 +0,0 @@-The package uses RebindableSyntax with OverloadedStrings or OverloadedLists in default-extensions, and also Paths_ autogen module. That configuration is known to cause compile failures with Cabal < 2.2. To use these default-extensions with Paths_ autogen module specify at least 'cabal-version: 2.2'.
− tests/ParserTests/regressions/generics-sop.cabal
@@ -1,128 +0,0 @@-name: generics-sop-version: 0.3.1.0-synopsis: Generic Programming using True Sums of Products-description:- A library to support the definition of generic functions.- Datatypes are viewed in a uniform, structured way:- the choice between constructors is represented using an n-ary- sum, and the arguments of each constructor are represented using- an n-ary product.- .- The module "Generics.SOP" is the main module of this library and contains- more detailed documentation.- .- Examples of using this library are provided by the following- packages:- .- * @<https://hackage.haskell.org/package/basic-sop basic-sop>@ basic examples,- .- * @<https://hackage.haskell.org/package/pretty-sop pretty-sop>@ generic pretty printing,- .- * @<https://hackage.haskell.org/package/lens-sop lens-sop>@ generically computed lenses,- .- * @<https://hackage.haskell.org/package/json-sop json-sop>@ generic JSON conversions.- .- A detailed description of the ideas behind this library is provided by- the paper:- .- * Edsko de Vries and Andres Löh.- <http://www.andres-loeh.de/TrueSumsOfProducts True Sums of Products>.- Workshop on Generic Programming (WGP) 2014.- .-license: BSD3-license-file: LICENSE-author: Edsko de Vries <edsko@well-typed.com>, Andres Löh <andres@well-typed.com>-maintainer: andres@well-typed.com-category: Generics-build-type: Custom-cabal-version: >=1.10-extra-source-files: CHANGELOG.md-tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2, GHC == 8.2.1, GHC == 8.3.*--custom-setup- setup-depends:- base,- Cabal,- cabal-doctest >= 1.0.2 && <1.1--source-repository head- type: git- location: https://github.com/well-typed/generics-sop--library- exposed-modules: Generics.SOP- Generics.SOP.GGP- Generics.SOP.TH- Generics.SOP.Dict- Generics.SOP.Type.Metadata- -- exposed via Generics.SOP:- Generics.SOP.BasicFunctors- Generics.SOP.Classes- Generics.SOP.Constraint- Generics.SOP.Instances- Generics.SOP.Metadata- Generics.SOP.NP- Generics.SOP.NS- Generics.SOP.Universe- Generics.SOP.Sing- build-depends: base >= 4.7 && < 5,- template-haskell >= 2.8 && < 2.13,- ghc-prim >= 0.3 && < 0.6,- deepseq >= 1.3 && < 1.5- if !impl (ghc >= 7.8)- build-depends: tagged >= 0.7 && < 0.9- if !impl (ghc >= 8.0)- build-depends: transformers-compat >= 0.3 && < 0.6,- transformers >= 0.3 && < 0.6-- hs-source-dirs: src- default-language: Haskell2010- ghc-options: -Wall- default-extensions: CPP- ScopedTypeVariables- TypeFamilies- RankNTypes- TypeOperators- GADTs- ConstraintKinds- MultiParamTypeClasses- TypeSynonymInstances- FlexibleInstances- FlexibleContexts- DeriveFunctor- DeriveFoldable- DeriveTraversable- DefaultSignatures- KindSignatures- DataKinds- FunctionalDependencies- if impl (ghc >= 7.8)- default-extensions: AutoDeriveTypeable- other-extensions: OverloadedStrings- PolyKinds- UndecidableInstances- TemplateHaskell- DeriveGeneric- StandaloneDeriving- if impl (ghc < 7.10)- other-extensions: OverlappingInstances--test-suite doctests- type: exitcode-stdio-1.0- main-is: doctests.hs- x-doctest-options: --preserve-it- hs-source-dirs: test- default-language: Haskell2010- build-depends: base,- doctest >= 0.13 && <0.14- ghc-options: -Wall -threaded--test-suite generics-sop-examples- type: exitcode-stdio-1.0- main-is: Example.hs- other-modules: HTransExample- hs-source-dirs: test- default-language: Haskell2010- ghc-options: -Wall- build-depends: base >= 4.6 && < 5,- generics-sop
− tests/ParserTests/regressions/generics-sop.expr
@@ -1,789 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (Impl GHC (OrLaterVersion (mkVersion [7,8]))))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "tagged")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 7]))- (EarlierVersion- (mkVersion- [0,- 9])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "tagged")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 7]))- (EarlierVersion- (mkVersion- [0,- 9])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `CNot (Var (Impl GHC (OrLaterVersion (mkVersion [8,0]))))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "transformers-compat")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 3]))- (EarlierVersion- (mkVersion- [0,- 6])))- mainLibSet,- Dependency- (PackageName- "transformers")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 3]))- (EarlierVersion- (mkVersion- [0,- 6])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "transformers-compat")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 3]))- (EarlierVersion- (mkVersion- [0,- 6])))- mainLibSet,- Dependency- (PackageName- "transformers")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 3]))- (EarlierVersion- (mkVersion- [0,- 6])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `Var (Impl GHC (OrLaterVersion (mkVersion [7,8])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [EnableExtension- AutoDeriveTypeable],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `Var (Impl GHC (EarlierVersion (mkVersion [7,10])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [EnableExtension- OverlappingInstances],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 7]))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "template-haskell")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [2, 8]))- (EarlierVersion (mkVersion [2, 13])))- mainLibSet,- Dependency- (PackageName "ghc-prim")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 3]))- (EarlierVersion (mkVersion [0, 6])))- mainLibSet,- Dependency- (PackageName "deepseq")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [1, 3]))- (EarlierVersion (mkVersion [1, 5])))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Generics.SOP",- ModuleName "Generics.SOP.GGP",- ModuleName "Generics.SOP.TH",- ModuleName "Generics.SOP.Dict",- ModuleName "Generics.SOP.Type.Metadata",- ModuleName "Generics.SOP.BasicFunctors",- ModuleName "Generics.SOP.Classes",- ModuleName "Generics.SOP.Constraint",- ModuleName "Generics.SOP.Instances",- ModuleName "Generics.SOP.Metadata",- ModuleName "Generics.SOP.NP",- ModuleName "Generics.SOP.NS",- ModuleName "Generics.SOP.Universe",- ModuleName "Generics.SOP.Sing"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [EnableExtension CPP,- EnableExtension- ScopedTypeVariables,- EnableExtension- TypeFamilies,- EnableExtension- RankNTypes,- EnableExtension- TypeOperators,- EnableExtension- GADTs,- EnableExtension- ConstraintKinds,- EnableExtension- MultiParamTypeClasses,- EnableExtension- TypeSynonymInstances,- EnableExtension- FlexibleInstances,- EnableExtension- FlexibleContexts,- EnableExtension- DeriveFunctor,- EnableExtension- DeriveFoldable,- EnableExtension- DeriveTraversable,- EnableExtension- DefaultSignatures,- EnableExtension- KindSignatures,- EnableExtension- DataKinds,- EnableExtension- FunctionalDependencies],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor ["-Wall"] [],- otherExtensions = [EnableExtension- OverloadedStrings,- EnableExtension- PolyKinds,- EnableExtension- UndecidableInstances,- EnableExtension- TemplateHaskell,- EnableExtension- DeriveGeneric,- EnableExtension- StandaloneDeriving],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4, 7]))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "template-haskell")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2, 8]))- (EarlierVersion- (mkVersion- [2,- 13])))- mainLibSet,- Dependency- (PackageName- "ghc-prim")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0, 3]))- (EarlierVersion- (mkVersion- [0, 6])))- mainLibSet,- Dependency- (PackageName- "deepseq")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [1, 3]))- (EarlierVersion- (mkVersion- [1, 5])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "doctests")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "doctest")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 13]))- (EarlierVersion (mkVersion [0, 14])))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [_×_- "x-doctest-options"- "--preserve-it"],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["test"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall", "-threaded"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "doctest")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 13]))- (EarlierVersion- (mkVersion- [0,- 14])))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "doctests.hs",- testName = UnqualComponentName ""}},- _×_- (UnqualComponentName "generics-sop-examples")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 6]))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "generics-sop")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["test"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall"] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "HTransExample"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 6]))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "generics-sop")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Example.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Edsko de Vries <edsko@well-typed.com>, Andres L\246h <andres@well-typed.com>",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Custom,- category = "Generics",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["A library to support the definition of generic functions.\n",- "Datatypes are viewed in a uniform, structured way:\n",- "the choice between constructors is represented using an n-ary\n",- "sum, and the arguments of each constructor are represented using\n",- "an n-ary product.\n",- "\n",- "The module \"Generics.SOP\" is the main module of this library and contains\n",- "more detailed documentation.\n",- "\n",- "Examples of using this library are provided by the following\n",- "packages:\n",- "\n",- "* @<https://hackage.haskell.org/package/basic-sop basic-sop>@ basic examples,\n",- "\n",- "* @<https://hackage.haskell.org/package/pretty-sop pretty-sop>@ generic pretty printing,\n",- "\n",- "* @<https://hackage.haskell.org/package/lens-sop lens-sop>@ generically computed lenses,\n",- "\n",- "* @<https://hackage.haskell.org/package/json-sop json-sop>@ generic JSON conversions.\n",- "\n",- "A detailed description of the ideas behind this library is provided by\n",- "the paper:\n",- "\n",- "* Edsko de Vries and Andres L\246h.\n",- "<http://www.andres-loeh.de/TrueSumsOfProducts True Sums of Products>.\n",- "Workshop on Generic Programming (WGP) 2014.\n"],- executables = [],- extraDocFiles = [],- extraSrcFiles = ["CHANGELOG.md"],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Right BSD3,- maintainer = "andres@well-typed.com",- package = PackageIdentifier- {pkgName = PackageName "generics-sop",- pkgVersion = mkVersion [0, 3, 1, 0]},- pkgUrl = "",- setupBuildInfo = Just- SetupBuildInfo- {defaultSetupDepends = False,- setupDepends = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "Cabal")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "cabal-doctest")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion [1, 0, 2]))- (EarlierVersion- (mkVersion [1, 1])))- mainLibSet]},- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just- "https://github.com/well-typed/generics-sop",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_10,- stability = "",- subLibraries = [],- synopsis = "Generic Programming using True Sums of Products",- testSuites = [],- testedWith = [_×_ GHC (ThisVersion (mkVersion [7, 8, 4])),- _×_ GHC (ThisVersion (mkVersion [7, 10, 3])),- _×_ GHC (ThisVersion (mkVersion [8, 0, 1])),- _×_ GHC (ThisVersion (mkVersion [8, 0, 2])),- _×_ GHC (ThisVersion (mkVersion [8, 2, 1])),- _×_- GHC- (IntersectVersionRanges- (OrLaterVersion (mkVersion [8, 3]))- (EarlierVersion (mkVersion [8, 4])))]}}
− tests/ParserTests/regressions/generics-sop.format
@@ -1,129 +0,0 @@-cabal-version: >=1.10-name: generics-sop-version: 0.3.1.0-license: BSD3-license-file: LICENSE-maintainer: andres@well-typed.com-author:- Edsko de Vries <edsko@well-typed.com>, Andres Löh <andres@well-typed.com>--tested-with:- ghc ==7.8.4 ghc ==7.10.3 ghc ==8.0.1 ghc ==8.0.2 ghc ==8.2.1- ghc >=8.3 && <8.4--synopsis: Generic Programming using True Sums of Products-description:- A library to support the definition of generic functions.- Datatypes are viewed in a uniform, structured way:- the choice between constructors is represented using an n-ary- sum, and the arguments of each constructor are represented using- an n-ary product.- .- The module "Generics.SOP" is the main module of this library and contains- more detailed documentation.- .- Examples of using this library are provided by the following- packages:- .- * @<https://hackage.haskell.org/package/basic-sop basic-sop>@ basic examples,- .- * @<https://hackage.haskell.org/package/pretty-sop pretty-sop>@ generic pretty printing,- .- * @<https://hackage.haskell.org/package/lens-sop lens-sop>@ generically computed lenses,- .- * @<https://hackage.haskell.org/package/json-sop json-sop>@ generic JSON conversions.- .- A detailed description of the ideas behind this library is provided by- the paper:- .- * Edsko de Vries and Andres Löh.- <http://www.andres-loeh.de/TrueSumsOfProducts True Sums of Products>.- Workshop on Generic Programming (WGP) 2014.- .--category: Generics-build-type: Custom-extra-source-files: CHANGELOG.md--source-repository head- type: git- location: https://github.com/well-typed/generics-sop--custom-setup- setup-depends:- base,- Cabal,- cabal-doctest >=1.0.2 && <1.1--library- exposed-modules:- Generics.SOP- Generics.SOP.GGP- Generics.SOP.TH- Generics.SOP.Dict- Generics.SOP.Type.Metadata- Generics.SOP.BasicFunctors- Generics.SOP.Classes- Generics.SOP.Constraint- Generics.SOP.Instances- Generics.SOP.Metadata- Generics.SOP.NP- Generics.SOP.NS- Generics.SOP.Universe- Generics.SOP.Sing-- hs-source-dirs: src- default-language: Haskell2010- default-extensions:- CPP ScopedTypeVariables TypeFamilies RankNTypes TypeOperators GADTs- ConstraintKinds MultiParamTypeClasses TypeSynonymInstances- FlexibleInstances FlexibleContexts DeriveFunctor DeriveFoldable- DeriveTraversable DefaultSignatures KindSignatures DataKinds- FunctionalDependencies-- other-extensions:- OverloadedStrings PolyKinds UndecidableInstances TemplateHaskell- DeriveGeneric StandaloneDeriving-- ghc-options: -Wall- build-depends:- base >=4.7 && <5,- template-haskell >=2.8 && <2.13,- ghc-prim >=0.3 && <0.6,- deepseq >=1.3 && <1.5-- if !impl(ghc >=7.8)- build-depends: tagged >=0.7 && <0.9-- if !impl(ghc >=8.0)- build-depends:- transformers-compat >=0.3 && <0.6,- transformers >=0.3 && <0.6-- if impl(ghc >=7.8)- default-extensions: AutoDeriveTypeable-- if impl(ghc <7.10)- other-extensions: OverlappingInstances--test-suite doctests- type: exitcode-stdio-1.0- main-is: doctests.hs- hs-source-dirs: test- default-language: Haskell2010- ghc-options: -Wall -threaded- x-doctest-options: --preserve-it- build-depends:- base,- doctest >=0.13 && <0.14--test-suite generics-sop-examples- type: exitcode-stdio-1.0- main-is: Example.hs- hs-source-dirs: test- other-modules: HTransExample- default-language: Haskell2010- ghc-options: -Wall- build-depends:- base >=4.6 && <5,- generics-sop
− tests/ParserTests/regressions/ghc-option-j.cabal
@@ -1,18 +0,0 @@-cabal-version: 2.2-name: ghc-option-j-version: 0-license: BSD-2-Clause-synopsis: Test-description: Testy test.-maintainer: none-category: none--library- exposed-modules: Foo- ghc-options: -Wall -j -Wno-all- default-language: Haskell2010--executable foo- main-is: Main.hs- ghc-shared-options: -Wall -j2 -Wno-all- default-language: Haskell2010
− tests/ParserTests/regressions/ghc-option-j.check
@@ -1,2 +0,0 @@-'ghc-options: -j[N]' can make sense for specific user's setup, but it is not appropriate for a distributed package. 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.-'ghc-shared-options: -j[N]' can make sense for specific user's setup, but it is not appropriate for a distributed package. 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.
− tests/ParserTests/regressions/haddock-api-2.18.1-check.cabal
@@ -1,147 +0,0 @@-name: haddock-api -version: 2.18.1 -synopsis: A documentation-generation tool for Haskell libraries -description: Haddock is a documentation-generation tool for Haskell - libraries -license: BSD3 -license-file: LICENSE -author: Simon Marlow, David Waern -maintainer: Alex Biehl <alexbiehl@gmail.com>, Simon Hengel <sol@typeful.net>, Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk> -homepage: http://www.haskell.org/haddock/ -bug-reports: https://github.com/haskell/haddock/issues -copyright: (c) Simon Marlow, David Waern -category: Documentation -build-type: Simple -cabal-version: >= 1.10 - -extra-source-files: - CHANGES.md - -data-dir: - resources -data-files: - html/solarized.css - html/haddock-util.js - html/highlight.js - html/Classic.theme/haskell_icon.gif - html/Classic.theme/minus.gif - html/Classic.theme/plus.gif - html/Classic.theme/xhaddock.css - html/Ocean.std-theme/hslogo-16.png - html/Ocean.std-theme/minus.gif - html/Ocean.std-theme/ocean.css - html/Ocean.std-theme/plus.gif - html/Ocean.std-theme/synopsis.png - latex/haddock.sty - -library - default-language: Haskell2010 - - -- this package typically supports only single major versions - build-depends: base ^>= 4.10.0 - , Cabal ^>= 2.0.0 - , ghc ^>= 8.2 - , ghc-paths ^>= 0.1.0.9 - , haddock-library == 1.4.4.* - , xhtml ^>= 3000.2.2 - - -- Versions for the dependencies below are transitively pinned by - -- the non-reinstallable `ghc` package and hence need no version - -- bounds - build-depends: array - , bytestring - , containers - , deepseq - , directory - , filepath - , ghc-boot - , transformers - - hs-source-dirs: src - - ghc-options: -funbox-strict-fields -Wall -fwarn-tabs -O2 - ghc-options: -Wall - if impl(ghc >= 8.0) - ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances - - exposed-modules: - Documentation.Haddock - - other-modules: - Haddock - Haddock.Interface - Haddock.Interface.Rename - Haddock.Interface.Create - Haddock.Interface.AttachInstances - Haddock.Interface.LexParseRn - Haddock.Interface.ParseModuleHeader - Haddock.Interface.Specialize - Haddock.Parser - Haddock.Utils - Haddock.Backends.Xhtml - Haddock.Backends.Xhtml.Decl - Haddock.Backends.Xhtml.DocMarkup - Haddock.Backends.Xhtml.Layout - Haddock.Backends.Xhtml.Names - Haddock.Backends.Xhtml.Themes - Haddock.Backends.Xhtml.Types - Haddock.Backends.Xhtml.Utils - Haddock.Backends.LaTeX - Haddock.Backends.HaddockDB - Haddock.Backends.Hoogle - Haddock.Backends.Hyperlinker - Haddock.Backends.Hyperlinker.Ast - Haddock.Backends.Hyperlinker.Parser - Haddock.Backends.Hyperlinker.Renderer - Haddock.Backends.Hyperlinker.Types - Haddock.Backends.Hyperlinker.Utils - Haddock.ModuleTree - Haddock.Types - Haddock.Doc - Haddock.Version - Haddock.InterfaceFile - Haddock.Options - Haddock.GhcUtils - Haddock.Syb - Haddock.Convert - Paths_haddock_api - - autogen-modules: - Paths_haddock_api - -test-suite spec - type: exitcode-stdio-1.0 - default-language: Haskell2010 - main-is: Spec.hs - ghc-options: -Wall - - hs-source-dirs: - test - , src - - -- NB: We only use a small subset of lib:haddock-api here, which - -- explains why this component has a smaller build-depends set - other-modules: - Haddock.Backends.Hyperlinker.ParserSpec - Haddock.Backends.Hyperlinker.Parser - Haddock.Backends.Hyperlinker.Types - - build-depends: - ghc ^>= 8.2 - , hspec ^>= 2.4.4 - , QuickCheck ^>= 2.10 - - -- Versions for the dependencies below are transitively pinned by - -- the non-reinstallable `ghc` package and hence need no version - -- bounds - build-depends: - base - , containers - - build-tool-depends: - hspec-discover:hspec-discover ^>= 2.4.4 - -source-repository head - type: git - subdir: haddock-api - location: https://github.com/haskell/haddock.git
− tests/ParserTests/regressions/haddock-api-2.18.1-check.check
@@ -1,4 +0,0 @@-ERROR: haddock-api-2.18.1-check.cabal:41:44: -unexpected major bounded version syntax (caret, ^>=) used. To use this syntax the package need to specify at least 'cabal-version: 2.0'. Alternatively, if broader compatibility is important then use: >=4.10.0 && <4.11-expecting "." or "-"-
− tests/ParserTests/regressions/hasktorch.cabal
@@ -1,558 +0,0 @@-cabal-version: 2.2--- ================================================================ ----- ======== This cabal file has been modified from dhall ========== ----- ======== This constitutes the 0.0.1.0 release. ========== ----- ======== Dhall can generate this file, but will never ========== ----- ======== be able to upload to hackage. For more, see: ========== ----- ==== https://github.com/haskell/hackage-server/issues/795 ====== ----- ================================================================ ---name: hasktorch-version: 0.0.1.0-license: BSD-3-Clause-maintainer: Sam Stites <fnz@fgvgrf.vb>, Austin Huang <nhfgvau@nyhz.zvg.rqh> - cipher:ROT13-author: Hasktorch dev team-homepage: https://github.com/hasktorch/hasktorch#readme-bug-reports: https://github.com/hasktorch/hasktorch/issues-synopsis: Torch for tensors and neural networks in Haskell-description:- Hasktorch is a library for tensors and neural networks in Haskell. It is an independent open source community project which leverages the core C libraries shared by Torch and PyTorch. This library leverages @cabal v2-build@ and @backpack@. *Note that this project is in early development and should only be used by contributing developers. Expect substantial changes to the library API as it evolves. Contributions and PRs are welcome (see details on github).*-category: Tensors, Machine Learning, AI-build-type: Simple--source-repository head- type: git- location: https://github.com/hasktorch/hasktorch--flag cuda- description:- build with THC support- default: False--flag lite- description:- only build with Double and Long support- default: False--library- exposed-modules:- Torch.Core.Exceptions- Torch.Core.Random- Torch.Core.LogAdd- reexported-modules: Torch.Types.Numeric,- Torch.Long,- Torch.Long.Dynamic,- Torch.Long.Storage,- Torch.Double,- Torch.Double.Dynamic,- Torch.Double.Storage,- Torch.Double.NN,- Torch.Double.NN.Activation,- Torch.Double.NN.Backprop,- Torch.Double.NN.Conv1d,- Torch.Double.NN.Conv2d,- Torch.Double.NN.Criterion,- Torch.Double.NN.Layers,- Torch.Double.NN.Linear,- Torch.Double.NN.Math,- Torch.Double.NN.Padding,- Torch.Double.NN.Pooling,- Torch.Double.NN.Sampling,- Torch.Double.Dynamic.NN,- Torch.Double.Dynamic.NN.Activation,- Torch.Double.Dynamic.NN.Pooling,- Torch.Double.Dynamic.NN.Criterion- hs-source-dirs: utils- default-language: Haskell2010- default-extensions: LambdaCase DataKinds TypeFamilies- TypeSynonymInstances ScopedTypeVariables FlexibleContexts CPP- build-depends:- base (==4.7 || >4.7) && <5,- -- containers ==0.5.10 || >0.5.10,- -- deepseq ==1.3.0 || >1.3.0,- dimensions ==1.0 || >1.0,- -- managed (==1.0.0 || >1.0.0) && <1.1,- -- microlens ==0.4.8 || >0.4.8,- -- numeric-limits ==0.1.0 || >0.1.0,- safe-exceptions ==0.1.0 || >0.1.0,- singletons ==2.2 || >2.2,- text ==1.2.2 || >1.2.2,- -- typelits-witnesses ==0.2.3 || >0.2.3,- hasktorch-cpu -any,- hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2-- -- <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> --- -- BEGIN EDITS- -- <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> --- if !flag(lite)- reexported-modules:- Torch.Byte,- Torch.Byte.Dynamic,- Torch.Byte.Storage,- Torch.Char,- Torch.Char.Dynamic,- Torch.Char.Storage,- Torch.Short,- Torch.Short.Dynamic,- Torch.Short.Storage,- Torch.Int,- Torch.Int.Dynamic,- Torch.Int.Storage,- Torch.Float,- Torch.Float.Dynamic,- Torch.Float.Storage-- if flag(cuda)- build-depends:- hasktorch-gpu -any- reexported-modules:- Torch.Cuda.Long,- Torch.Cuda.Long.Dynamic,- Torch.Cuda.Long.Storage,- Torch.Cuda.Double,- Torch.Cuda.Double.Dynamic,- Torch.Cuda.Double.Storage,- Torch.Cuda.Double.NN,- Torch.Cuda.Double.NN.Activation,- Torch.Cuda.Double.NN.Backprop,- Torch.Cuda.Double.NN.Conv1d,- Torch.Cuda.Double.NN.Conv2d,- Torch.Cuda.Double.NN.Criterion,- Torch.Cuda.Double.NN.Layers,- Torch.Cuda.Double.NN.Linear,- Torch.Cuda.Double.NN.Math,- Torch.Cuda.Double.NN.Padding,- Torch.Cuda.Double.NN.Pooling,- Torch.Cuda.Double.NN.Sampling,- Torch.Cuda.Double.Dynamic.NN,- Torch.Cuda.Double.Dynamic.NN.Activation,- Torch.Cuda.Double.Dynamic.NN.Pooling,- Torch.Cuda.Double.Dynamic.NN.Criterion- if !flag(lite)- reexported-modules:- Torch.Cuda.Byte,- Torch.Cuda.Byte.Dynamic,- Torch.Cuda.Byte.Storage,- Torch.Cuda.Char,- Torch.Cuda.Char.Dynamic,- Torch.Cuda.Char.Storage,- Torch.Cuda.Short,- Torch.Cuda.Short.Dynamic,- Torch.Cuda.Short.Storage,- Torch.Cuda.Int,- Torch.Cuda.Int.Dynamic,- Torch.Cuda.Int.Storage,- Torch.Cuda.Float,- Torch.Cuda.Float.Dynamic,- Torch.Cuda.Float.Storage- -- <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> --- -- END EDITS- -- <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> ----library hasktorch-cpu- exposed-modules:- Torch.Long- Torch.Long.Dynamic- Torch.Long.Storage- Torch.Double- Torch.Double.Dynamic- Torch.Double.Storage- reexported-modules: Torch.Double.NN,- Torch.Double.NN.Activation,- Torch.Double.NN.Backprop,- Torch.Double.NN.Conv1d,- Torch.Double.NN.Conv2d,- Torch.Double.NN.Criterion,- Torch.Double.NN.Layers,- Torch.Double.NN.Linear,- Torch.Double.NN.Math,- Torch.Double.NN.Padding,- Torch.Double.NN.Pooling,- Torch.Double.NN.Sampling,- Torch.Double.Dynamic.NN,- Torch.Double.Dynamic.NN.Activation,- Torch.Double.Dynamic.NN.Pooling,- Torch.Double.Dynamic.NN.Criterion,- Torch.Float.NN,- Torch.Float.NN.Activation,- Torch.Float.NN.Backprop,- Torch.Float.NN.Conv1d,- Torch.Float.NN.Conv2d,- Torch.Float.NN.Criterion,- Torch.Float.NN.Layers,- Torch.Float.NN.Linear,- Torch.Float.NN.Math,- Torch.Float.NN.Padding,- Torch.Float.NN.Pooling,- Torch.Float.NN.Sampling,- Torch.Float.Dynamic.NN,- Torch.Float.Dynamic.NN.Activation,- Torch.Float.Dynamic.NN.Pooling,- Torch.Float.Dynamic.NN.Criterion- hs-source-dirs: utils src- other-modules:- Torch.Core.Exceptions- Torch.Core.Random- Torch.Core.LogAdd- default-language: Haskell2010- default-extensions: LambdaCase DataKinds TypeFamilies- TypeSynonymInstances ScopedTypeVariables FlexibleContexts CPP- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- -- containers ==0.5.10 || >0.5.10,- -- deepseq ==1.3.0 || >1.3.0,- dimensions ==1.0 || >1.0,- hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- -- managed (==1.0.0 || >1.0.0) && <1.1,- -- microlens ==0.4.8 || >0.4.8,- -- numeric-limits ==0.1.0 || >0.1.0,- safe-exceptions ==0.1.0 || >0.1.0,- singletons ==2.2 || >2.2,- text ==1.2.2 || >1.2.2,- -- typelits-witnesses ==0.2.3 || >0.2.3,- hasktorch-indef-floating -any,- hasktorch-indef-signed -any- mixins: hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Long.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Long.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Long.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Long.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Long.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Long.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Long.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Long.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Long.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Long.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Long.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Long.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Long.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Long.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Long.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Long.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Long.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Long.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Long.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Long.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Long.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Long.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Long.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Long.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Long.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Long.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Long.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Long.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Long.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Long.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Long.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Long.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Long.Types, Torch.Indef.Index as Torch.Long.Index, Torch.Indef.Mask as Torch.Long.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Long.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Long.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Long, Torch.Sig.Storage as Torch.FFI.TH.Long.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Long.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Long.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Long.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Long.TensorMath),- hasktorch-indef-floating (Torch.Indef.Storage as Torch.Indef.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Double.Types, Torch.Indef.Index as Torch.Double.Index, Torch.Indef.Mask as Torch.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Blas as Torch.Indef.Double.Dynamic.Tensor.Math.Blas, Torch.Indef.Dynamic.Tensor.Math.Lapack as Torch.Indef.Double.Dynamic.Tensor.Math.Lapack, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Floating, Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating as Torch.Indef.Double.Dynamic.Tensor.Math.Reduce.Floating, Torch.Indef.Dynamic.Tensor.Math.Floating as Torch.Indef.Double.Dynamic.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Math.Blas as Torch.Indef.Double.Tensor.Math.Blas, Torch.Indef.Static.Tensor.Math.Lapack as Torch.Indef.Double.Tensor.Math.Lapack, Torch.Indef.Static.Tensor.Math.Pointwise.Floating as Torch.Indef.Double.Tensor.Math.Pointwise.Floating, Torch.Indef.Static.Tensor.Math.Reduce.Floating as Torch.Indef.Double.Tensor.Math.Reduce.Floating, Torch.Indef.Static.Tensor.Math.Floating as Torch.Indef.Double.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Random.TH as Torch.Indef.Double.Tensor.Random.TH, Torch.Indef.Static.Tensor.Math.Random.TH as Torch.Indef.Double.Tensor.Math.Random.TH, Torch.Indef.Dynamic.Tensor.Random.TH as Torch.Indef.Double.Dynamic.Tensor.Random.TH, Torch.Indef.Dynamic.Tensor.Math.Random.TH as Torch.Indef.Double.Dynamic.Tensor.Math.Random.TH, Torch.Undefined.Tensor.Random.THC as Torch.Undefined.Double.Tensor.Random.THC, Torch.Indef.Storage as Torch.Indef.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Double.Types, Torch.Indef.Index as Torch.Double.Index, Torch.Indef.Mask as Torch.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.NN as Torch.Double.Dynamic.NN, Torch.Indef.Dynamic.NN.Activation as Torch.Double.Dynamic.NN.Activation, Torch.Indef.Dynamic.NN.Pooling as Torch.Double.Dynamic.NN.Pooling, Torch.Indef.Dynamic.NN.Criterion as Torch.Double.Dynamic.NN.Criterion, Torch.Indef.Static.NN as Torch.Double.NN, Torch.Indef.Static.NN as Torch.Double.NN, Torch.Indef.Static.NN.Activation as Torch.Double.NN.Activation, Torch.Indef.Static.NN.Backprop as Torch.Double.NN.Backprop, Torch.Indef.Static.NN.Conv1d as Torch.Double.NN.Conv1d, Torch.Indef.Static.NN.Conv2d as Torch.Double.NN.Conv2d, Torch.Indef.Static.NN.Criterion as Torch.Double.NN.Criterion, Torch.Indef.Static.NN.Layers as Torch.Double.NN.Layers, Torch.Indef.Static.NN.Linear as Torch.Double.NN.Linear, Torch.Indef.Static.NN.Math as Torch.Double.NN.Math, Torch.Indef.Static.NN.Padding as Torch.Double.NN.Padding, Torch.Indef.Static.NN.Pooling as Torch.Double.NN.Pooling, Torch.Indef.Static.NN.Sampling as Torch.Double.NN.Sampling) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Double, Torch.Sig.Storage as Torch.FFI.TH.Double.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Double.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Double.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Double.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Double.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Double.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Blas as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Lapack as Torch.FFI.TH.Double.TensorLapack, Torch.Sig.NN as Torch.FFI.TH.NN.Double, Torch.Sig.Types.NN as Torch.Types.TH, Torch.Sig.Tensor.Math.Random.TH as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Random.TH as Torch.FFI.TH.Double.TensorRandom, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Double.Tensor.Random.THC)- - if flag(lite)- else- exposed-modules:- Torch.Byte- Torch.Byte.Dynamic- Torch.Byte.Storage- Torch.Char- Torch.Char.Dynamic- Torch.Char.Storage- Torch.Short- Torch.Short.Dynamic- Torch.Short.Storage- Torch.Int- Torch.Int.Dynamic- Torch.Int.Storage- Torch.Float- Torch.Float.Dynamic- Torch.Float.Storage- build-depends:- hasktorch-indef-unsigned -any- mixins: hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Byte.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Byte.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Byte.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Byte.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Byte.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Byte.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Byte.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Byte.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Byte.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Byte.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Byte.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Byte.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Byte.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Byte.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Byte.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Byte.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Byte.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Byte.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Byte.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Byte.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Byte.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Byte.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Byte.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Byte.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Byte.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Byte.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Byte.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Byte.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Byte.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Byte.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Byte.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Byte.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Byte.Types, Torch.Indef.Index as Torch.Byte.Index, Torch.Indef.Mask as Torch.Byte.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Byte, Torch.Sig.Storage as Torch.FFI.TH.Byte.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Byte.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Byte.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Byte.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Byte.TensorMath),- hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Char.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Char.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Char.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Char.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Char.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Char.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Char.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Char.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Char.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Char.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Char.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Char.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Char.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Char.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Char.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Char.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Char.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Char.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Char.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Char.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Char.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Char.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Char.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Char.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Char.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Char.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Char.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Char.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Char.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Char.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Char.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Char.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Char.Types, Torch.Indef.Index as Torch.Char.Index, Torch.Indef.Mask as Torch.Char.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Char, Torch.Sig.Storage as Torch.FFI.TH.Char.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Char.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Char.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Char.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Char.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Char.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Char.TensorMath),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Short.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Short.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Short.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Short.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Short.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Short.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Short.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Short.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Short.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Short.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Short.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Short.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Short.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Short.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Short.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Short.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Short.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Short.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Short.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Short.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Short.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Short.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Short.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Short.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Short.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Short.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Short.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Short.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Short.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Short.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Short.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Short.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Short.Types, Torch.Indef.Index as Torch.Short.Index, Torch.Indef.Mask as Torch.Short.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Short.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Short.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Short, Torch.Sig.Storage as Torch.FFI.TH.Short.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Short.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Short.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Short.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Short.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Short.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Short.TensorMath),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Int.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Int.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Int.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Int.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Int.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Int.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Int.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Int.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Int.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Int.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Int.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Int.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Int.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Int.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Int.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Int.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Int.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Int.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Int.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Int.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Int.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Int.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Int.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Int.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Int.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Int.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Int.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Int.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Int.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Int.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Int.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Int.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Int.Types, Torch.Indef.Index as Torch.Int.Index, Torch.Indef.Mask as Torch.Int.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Int.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Int.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Int, Torch.Sig.Storage as Torch.FFI.TH.Int.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Int.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Int.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Int.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Int.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Int.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Int.TensorMath),- hasktorch-indef-floating (Torch.Indef.Storage as Torch.Indef.Float.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Float.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Float.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Float.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Float.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Float.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Float.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Float.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Float.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Float.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Float.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Float.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Float.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Float.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Float.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Float.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Float.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Float.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Float.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Float.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Float.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Float.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Float.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Float.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Float.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Float.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Float.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Float.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Float.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Float.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Float.Types, Torch.Indef.Index as Torch.Float.Index, Torch.Indef.Mask as Torch.Float.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Blas as Torch.Indef.Float.Dynamic.Tensor.Math.Blas, Torch.Indef.Dynamic.Tensor.Math.Lapack as Torch.Indef.Float.Dynamic.Tensor.Math.Lapack, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Floating, Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating as Torch.Indef.Float.Dynamic.Tensor.Math.Reduce.Floating, Torch.Indef.Dynamic.Tensor.Math.Floating as Torch.Indef.Float.Dynamic.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Math.Blas as Torch.Indef.Float.Tensor.Math.Blas, Torch.Indef.Static.Tensor.Math.Lapack as Torch.Indef.Float.Tensor.Math.Lapack, Torch.Indef.Static.Tensor.Math.Pointwise.Floating as Torch.Indef.Float.Tensor.Math.Pointwise.Floating, Torch.Indef.Static.Tensor.Math.Reduce.Floating as Torch.Indef.Float.Tensor.Math.Reduce.Floating, Torch.Indef.Static.Tensor.Math.Floating as Torch.Indef.Float.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Random.TH as Torch.Indef.Float.Tensor.Random.TH, Torch.Indef.Static.Tensor.Math.Random.TH as Torch.Indef.Float.Tensor.Math.Random.TH, Torch.Indef.Dynamic.Tensor.Random.TH as Torch.Indef.Float.Dynamic.Tensor.Random.TH, Torch.Indef.Dynamic.Tensor.Math.Random.TH as Torch.Indef.Float.Dynamic.Tensor.Math.Random.TH, Torch.Undefined.Tensor.Random.THC as Torch.Undefined.Float.Tensor.Random.THC, Torch.Indef.Storage as Torch.Indef.Float.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Float.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Float.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Float.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Float.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Float.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Float.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Float.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Float.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Float.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Float.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Float.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Float.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Float.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Float.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Float.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Float.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Float.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Float.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Float.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Float.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Float.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Float.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Float.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Float.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Float.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Float.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Float.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Float.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Float.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Float.Types, Torch.Indef.Index as Torch.Float.Index, Torch.Indef.Mask as Torch.Float.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.NN as Torch.Float.Dynamic.NN, Torch.Indef.Dynamic.NN.Activation as Torch.Float.Dynamic.NN.Activation, Torch.Indef.Dynamic.NN.Pooling as Torch.Float.Dynamic.NN.Pooling, Torch.Indef.Dynamic.NN.Criterion as Torch.Float.Dynamic.NN.Criterion, Torch.Indef.Static.NN as Torch.Float.NN, Torch.Indef.Static.NN as Torch.Float.NN, Torch.Indef.Static.NN.Activation as Torch.Float.NN.Activation, Torch.Indef.Static.NN.Backprop as Torch.Float.NN.Backprop, Torch.Indef.Static.NN.Conv1d as Torch.Float.NN.Conv1d, Torch.Indef.Static.NN.Conv2d as Torch.Float.NN.Conv2d, Torch.Indef.Static.NN.Criterion as Torch.Float.NN.Criterion, Torch.Indef.Static.NN.Layers as Torch.Float.NN.Layers, Torch.Indef.Static.NN.Linear as Torch.Float.NN.Linear, Torch.Indef.Static.NN.Math as Torch.Float.NN.Math, Torch.Indef.Static.NN.Padding as Torch.Float.NN.Padding, Torch.Indef.Static.NN.Pooling as Torch.Float.NN.Pooling, Torch.Indef.Static.NN.Sampling as Torch.Float.NN.Sampling) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Float, Torch.Sig.Storage as Torch.FFI.TH.Float.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Float.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Float.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Float.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Float.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Float.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Floating as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Blas as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Lapack as Torch.FFI.TH.Float.TensorLapack, Torch.Sig.NN as Torch.FFI.TH.NN.Float, Torch.Sig.Types.NN as Torch.Types.TH, Torch.Sig.Tensor.Math.Random.TH as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Random.TH as Torch.FFI.TH.Float.TensorRandom, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Float.Tensor.Random.THC)--library hasktorch-gpu- exposed-modules:- Torch.Cuda.Long- Torch.Cuda.Long.Dynamic- Torch.Cuda.Long.Storage- Torch.Cuda.Double- Torch.Cuda.Double.Dynamic- Torch.Cuda.Double.Storage- reexported-modules: Torch.Cuda.Double.NN,- Torch.Cuda.Double.NN.Activation,- Torch.Cuda.Double.NN.Backprop,- Torch.Cuda.Double.NN.Conv1d,- Torch.Cuda.Double.NN.Conv2d,- Torch.Cuda.Double.NN.Criterion,- Torch.Cuda.Double.NN.Layers,- Torch.Cuda.Double.NN.Linear,- Torch.Cuda.Double.NN.Math,- Torch.Cuda.Double.NN.Padding,- Torch.Cuda.Double.NN.Pooling,- Torch.Cuda.Double.NN.Sampling,- Torch.Cuda.Double.Dynamic.NN,- Torch.Cuda.Double.Dynamic.NN.Activation,- Torch.Cuda.Double.Dynamic.NN.Pooling,- Torch.Cuda.Double.Dynamic.NN.Criterion- cpp-options: -DCUDA -DHASKTORCH_INTERNAL_CUDA- hs-source-dirs: utils src- other-modules:- Torch.Core.Exceptions- Torch.Core.Random- Torch.Core.LogAdd- default-language: Haskell2010- default-extensions: LambdaCase DataKinds TypeFamilies- TypeSynonymInstances ScopedTypeVariables FlexibleContexts CPP- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- -- containers ==0.5.10 || >0.5.10,- -- deepseq ==1.3.0 || >1.3.0,- dimensions ==1.0 || >1.0,- hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- -- managed (==1.0.0 || >1.0.0) && <1.1,- -- microlens ==0.4.8 || >0.4.8,- -- numeric-limits ==0.1.0 || >0.1.0,- safe-exceptions ==0.1.0 || >0.1.0,- singletons ==2.2 || >2.2,- text ==1.2.2 || >1.2.2,- -- typelits-witnesses ==0.2.3 || >0.2.3,- hasktorch-indef-floating -any,- hasktorch-indef-signed -any,- hasktorch-ffi-thc (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-thc (==0.0.1 || >0.0.1) && <0.0.2- mixins: hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Cuda.Long.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Long.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Long.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Long.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Long.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Long.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Long.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Long.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Long.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Long.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Long.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Long.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Long.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Long.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Long.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Long.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Long.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Long.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Long.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Long.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Long.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Long.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Long.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Long.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Long.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Long.Types, Torch.Indef.Index as Torch.Cuda.Long.Index, Torch.Indef.Mask as Torch.Cuda.Long.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Long.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Long, Torch.Sig.Storage as Torch.FFI.THC.Long.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Long.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Long.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Long.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Long.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Long.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Long.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Long.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Long.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Long.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Long.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Long.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Long.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Long.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Long.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Long.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Long.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Long.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Long.TensorMathPointwise),- hasktorch-indef-floating (Torch.Indef.Storage as Torch.Indef.Cuda.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Double.Types, Torch.Indef.Index as Torch.Cuda.Double.Index, Torch.Indef.Mask as Torch.Cuda.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Blas as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Blas, Torch.Indef.Dynamic.Tensor.Math.Lapack as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Lapack, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Floating, Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce.Floating, Torch.Indef.Dynamic.Tensor.Math.Floating as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Math.Blas as Torch.Indef.Cuda.Double.Tensor.Math.Blas, Torch.Indef.Static.Tensor.Math.Lapack as Torch.Indef.Cuda.Double.Tensor.Math.Lapack, Torch.Indef.Static.Tensor.Math.Pointwise.Floating as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Floating, Torch.Indef.Static.Tensor.Math.Reduce.Floating as Torch.Indef.Cuda.Double.Tensor.Math.Reduce.Floating, Torch.Indef.Static.Tensor.Math.Floating as Torch.Indef.Cuda.Double.Tensor.Math.Floating, Torch.Undefined.Tensor.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Random.TH, Torch.Undefined.Tensor.Math.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Math.Random.TH, Torch.Indef.Static.Tensor.Random.THC as Torch.Indef.Cuda.Double.Tensor.Random.THC, Torch.Indef.Dynamic.Tensor.Random.THC as Torch.Indef.Cuda.Double.Dynamic.Tensor.Random.THC, Torch.Indef.Storage as Torch.Indef.Cuda.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Double.Types, Torch.Indef.Index as Torch.Cuda.Double.Index, Torch.Indef.Mask as Torch.Cuda.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.NN as Torch.Cuda.Double.Dynamic.NN, Torch.Indef.Dynamic.NN.Activation as Torch.Cuda.Double.Dynamic.NN.Activation, Torch.Indef.Dynamic.NN.Pooling as Torch.Cuda.Double.Dynamic.NN.Pooling, Torch.Indef.Dynamic.NN.Criterion as Torch.Cuda.Double.Dynamic.NN.Criterion, Torch.Indef.Static.NN as Torch.Cuda.Double.NN, Torch.Indef.Static.NN as Torch.Cuda.Double.NN, Torch.Indef.Static.NN.Activation as Torch.Cuda.Double.NN.Activation, Torch.Indef.Static.NN.Backprop as Torch.Cuda.Double.NN.Backprop, Torch.Indef.Static.NN.Conv1d as Torch.Cuda.Double.NN.Conv1d, Torch.Indef.Static.NN.Conv2d as Torch.Cuda.Double.NN.Conv2d, Torch.Indef.Static.NN.Criterion as Torch.Cuda.Double.NN.Criterion, Torch.Indef.Static.NN.Layers as Torch.Cuda.Double.NN.Layers, Torch.Indef.Static.NN.Linear as Torch.Cuda.Double.NN.Linear, Torch.Indef.Static.NN.Math as Torch.Cuda.Double.NN.Math, Torch.Indef.Static.NN.Padding as Torch.Cuda.Double.NN.Padding, Torch.Indef.Static.NN.Pooling as Torch.Cuda.Double.NN.Pooling, Torch.Indef.Static.NN.Sampling as Torch.Cuda.Double.NN.Sampling) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Double, Torch.Sig.Storage as Torch.FFI.THC.Double.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Double.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Double.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Double.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Double.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Double.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Double.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Double.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Double.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Double.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Double.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Double.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Double.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Double.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Double.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Double.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Double.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Double.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Double.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Double.TensorMathPointwise, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.FFI.THC.Double.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.FFI.THC.Double.TensorMathReduce, Torch.Sig.Tensor.Math.Floating as Torch.FFI.THC.Double.TensorMath, Torch.Sig.Tensor.Math.Blas as Torch.FFI.THC.Double.TensorMathBlas, Torch.Sig.Tensor.Math.Lapack as Torch.FFI.THC.Double.TensorMathMagma, Torch.Sig.NN as Torch.FFI.THC.NN.Double, Torch.Sig.Types.NN as Torch.Types.THC, Torch.Sig.Tensor.Math.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Math.Random.TH, Torch.Sig.Tensor.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Random.TH, Torch.Sig.Tensor.Random.THC as Torch.FFI.THC.Double.TensorRandom)- - if flag(lite)- else- exposed-modules:- Torch.Cuda.Byte- Torch.Cuda.Byte.Dynamic- Torch.Cuda.Byte.Storage- Torch.Cuda.Char- Torch.Cuda.Char.Dynamic- Torch.Cuda.Char.Storage- Torch.Cuda.Short- Torch.Cuda.Short.Dynamic- Torch.Cuda.Short.Storage- Torch.Cuda.Int- Torch.Cuda.Int.Dynamic- Torch.Cuda.Int.Storage- build-depends:- hasktorch-indef-unsigned -any- mixins: hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Cuda.Byte.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Byte.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Byte.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Byte.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Byte.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Byte.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Byte.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Byte.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Byte.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Byte.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Byte.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Byte.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Byte.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Byte.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Byte.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Byte.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Byte.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Byte.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Byte.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Byte.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Byte.Types, Torch.Indef.Index as Torch.Cuda.Byte.Index, Torch.Indef.Mask as Torch.Cuda.Byte.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Byte, Torch.Sig.Storage as Torch.FFI.THC.Byte.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Byte.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Byte.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Byte.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Byte.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Byte.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Byte.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Byte.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Byte.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Byte.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Byte.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Byte.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Byte.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Byte.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Byte.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Byte.TensorTopK),- hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Cuda.Char.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Char.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Char.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Char.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Char.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Char.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Char.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Char.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Char.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Char.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Char.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Char.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Char.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Char.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Char.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Char.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Char.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Char.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Char.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Char.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Char.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Char.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Char.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Char.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Char.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Char.Types, Torch.Indef.Index as Torch.Cuda.Char.Index, Torch.Indef.Mask as Torch.Cuda.Char.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Char, Torch.Sig.Storage as Torch.FFI.THC.Char.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Char.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Char.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Char.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Char.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Char.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Char.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Char.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Char.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Char.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Char.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Char.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Char.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Char.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Char.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Char.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Char.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Char.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Char.TensorTopK),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Cuda.Short.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Short.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Short.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Short.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Short.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Short.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Short.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Short.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Short.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Short.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Short.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Short.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Short.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Short.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Short.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Short.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Short.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Short.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Short.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Short.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Short.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Short.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Short.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Short.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Short.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Short.Types, Torch.Indef.Index as Torch.Cuda.Short.Index, Torch.Indef.Mask as Torch.Cuda.Short.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Short.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Short, Torch.Sig.Storage as Torch.FFI.THC.Short.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Short.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Short.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Short.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Short.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Short.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Short.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Short.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Short.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Short.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Short.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Short.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Short.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Short.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Short.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Short.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Short.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Short.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Short.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Short.TensorMathPointwise),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Cuda.Int.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Int.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Int.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Int.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Int.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Int.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Int.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Int.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Int.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Int.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Int.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Int.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Int.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Int.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Int.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Int.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Int.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Int.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Int.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Int.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Int.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Int.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Int.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Int.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Int.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Int.Types, Torch.Indef.Index as Torch.Cuda.Int.Index, Torch.Indef.Mask as Torch.Cuda.Int.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Int.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Int, Torch.Sig.Storage as Torch.FFI.THC.Int.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Int.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Int.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Int.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Int.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Int.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Int.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Int.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Int.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Int.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Int.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Int.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Int.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Int.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Int.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Int.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Int.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Int.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Int.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Int.TensorMathPointwise)--library hasktorch-indef-unsigned- reexported-modules: Torch.Indef.Index,- Torch.Indef.Mask,- Torch.Indef.Types,- Torch.Indef.Storage,- Torch.Indef.Storage.Copy,- Torch.Indef.Dynamic.Print,- Torch.Indef.Dynamic.Tensor,- Torch.Indef.Dynamic.Tensor.Copy,- Torch.Indef.Dynamic.Tensor.Index,- Torch.Indef.Dynamic.Tensor.Masked,- Torch.Indef.Dynamic.Tensor.Math,- Torch.Indef.Dynamic.Tensor.Math.Compare,- Torch.Indef.Dynamic.Tensor.Math.CompareT,- Torch.Indef.Dynamic.Tensor.Math.Pairwise,- Torch.Indef.Dynamic.Tensor.Math.Pointwise,- Torch.Indef.Dynamic.Tensor.Math.Reduce,- Torch.Indef.Dynamic.Tensor.Math.Scan,- Torch.Indef.Dynamic.Tensor.Mode,- Torch.Indef.Dynamic.Tensor.ScatterGather,- Torch.Indef.Dynamic.Tensor.Sort,- Torch.Indef.Dynamic.Tensor.TopK,- Torch.Indef.Static.Tensor,- Torch.Indef.Static.Tensor.Copy,- Torch.Indef.Static.Tensor.Index,- Torch.Indef.Static.Tensor.Masked,- Torch.Indef.Static.Tensor.Math,- Torch.Indef.Static.Tensor.Math.Compare,- Torch.Indef.Static.Tensor.Math.CompareT,- Torch.Indef.Static.Tensor.Math.Pairwise,- Torch.Indef.Static.Tensor.Math.Pointwise,- Torch.Indef.Static.Tensor.Math.Reduce,- Torch.Indef.Static.Tensor.Math.Scan,- Torch.Indef.Static.Tensor.Mode,- Torch.Indef.Static.Tensor.ScatterGather,- Torch.Indef.Static.Tensor.Sort,- Torch.Indef.Static.Tensor.TopK- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-signatures-partial (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-indef -any- mixins: hasktorch-indef requires (Torch.Sig.NN as Torch.Undefined.NN, Torch.Sig.Types.NN as Torch.Undefined.Types.NN, Torch.Sig.Tensor.Math.Blas as Torch.Undefined.Tensor.Math.Blas, Torch.Sig.Tensor.Math.Floating as Torch.Undefined.Tensor.Math.Floating, Torch.Sig.Tensor.Math.Lapack as Torch.Undefined.Tensor.Math.Lapack, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.Undefined.Tensor.Math.Pointwise.Signed, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.Undefined.Tensor.Math.Pointwise.Floating, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.Undefined.Tensor.Math.Reduce.Floating, Torch.Sig.Tensor.Math.Random.TH as Torch.Undefined.Tensor.Math.Random.TH, Torch.Sig.Tensor.Random.TH as Torch.Undefined.Tensor.Random.TH, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Tensor.Random.THC)--library hasktorch-indef-signed- reexported-modules: Torch.Indef.Index,- Torch.Indef.Mask,- Torch.Indef.Types,- Torch.Indef.Storage,- Torch.Indef.Storage.Copy,- Torch.Indef.Dynamic.Print,- Torch.Indef.Dynamic.Tensor,- Torch.Indef.Dynamic.Tensor.Copy,- Torch.Indef.Dynamic.Tensor.Index,- Torch.Indef.Dynamic.Tensor.Masked,- Torch.Indef.Dynamic.Tensor.Math,- Torch.Indef.Dynamic.Tensor.Math.Compare,- Torch.Indef.Dynamic.Tensor.Math.CompareT,- Torch.Indef.Dynamic.Tensor.Math.Pairwise,- Torch.Indef.Dynamic.Tensor.Math.Pointwise,- Torch.Indef.Dynamic.Tensor.Math.Reduce,- Torch.Indef.Dynamic.Tensor.Math.Scan,- Torch.Indef.Dynamic.Tensor.Mode,- Torch.Indef.Dynamic.Tensor.ScatterGather,- Torch.Indef.Dynamic.Tensor.Sort,- Torch.Indef.Dynamic.Tensor.TopK,- Torch.Indef.Static.Tensor,- Torch.Indef.Static.Tensor.Copy,- Torch.Indef.Static.Tensor.Index,- Torch.Indef.Static.Tensor.Masked,- Torch.Indef.Static.Tensor.Math,- Torch.Indef.Static.Tensor.Math.Compare,- Torch.Indef.Static.Tensor.Math.CompareT,- Torch.Indef.Static.Tensor.Math.Pairwise,- Torch.Indef.Static.Tensor.Math.Pointwise,- Torch.Indef.Static.Tensor.Math.Reduce,- Torch.Indef.Static.Tensor.Math.Scan,- Torch.Indef.Static.Tensor.Mode,- Torch.Indef.Static.Tensor.ScatterGather,- Torch.Indef.Static.Tensor.Sort,- Torch.Indef.Static.Tensor.TopK,- Torch.Indef.Static.Tensor.Math.Pointwise.Signed,- Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-signatures-partial (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-indef -any- mixins: hasktorch-indef requires (Torch.Sig.NN as Torch.Undefined.NN, Torch.Sig.Types.NN as Torch.Undefined.Types.NN, Torch.Sig.Tensor.Math.Blas as Torch.Undefined.Tensor.Math.Blas, Torch.Sig.Tensor.Math.Floating as Torch.Undefined.Tensor.Math.Floating, Torch.Sig.Tensor.Math.Lapack as Torch.Undefined.Tensor.Math.Lapack, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.Undefined.Tensor.Math.Pointwise.Floating, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.Undefined.Tensor.Math.Reduce.Floating, Torch.Sig.Tensor.Math.Random.TH as Torch.Undefined.Tensor.Math.Random.TH, Torch.Sig.Tensor.Random.TH as Torch.Undefined.Tensor.Random.TH, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Tensor.Random.THC)--library hasktorch-indef-floating- reexported-modules: Torch.Indef.Index,- Torch.Indef.Mask,- Torch.Indef.Types,- Torch.Indef.Storage,- Torch.Indef.Storage.Copy,- Torch.Indef.Dynamic.Print,- Torch.Indef.Dynamic.Tensor,- Torch.Indef.Dynamic.Tensor.Copy,- Torch.Indef.Dynamic.Tensor.Index,- Torch.Indef.Dynamic.Tensor.Masked,- Torch.Indef.Dynamic.Tensor.Math,- Torch.Indef.Dynamic.Tensor.Math.Compare,- Torch.Indef.Dynamic.Tensor.Math.CompareT,- Torch.Indef.Dynamic.Tensor.Math.Pairwise,- Torch.Indef.Dynamic.Tensor.Math.Pointwise,- Torch.Indef.Dynamic.Tensor.Math.Reduce,- Torch.Indef.Dynamic.Tensor.Math.Scan,- Torch.Indef.Dynamic.Tensor.Mode,- Torch.Indef.Dynamic.Tensor.ScatterGather,- Torch.Indef.Dynamic.Tensor.Sort,- Torch.Indef.Dynamic.Tensor.TopK,- Torch.Indef.Static.Tensor,- Torch.Indef.Static.Tensor.Copy,- Torch.Indef.Static.Tensor.Index,- Torch.Indef.Static.Tensor.Masked,- Torch.Indef.Static.Tensor.Math,- Torch.Indef.Static.Tensor.Math.Compare,- Torch.Indef.Static.Tensor.Math.CompareT,- Torch.Indef.Static.Tensor.Math.Pairwise,- Torch.Indef.Static.Tensor.Math.Pointwise,- Torch.Indef.Static.Tensor.Math.Reduce,- Torch.Indef.Static.Tensor.Math.Scan,- Torch.Indef.Static.Tensor.Mode,- Torch.Indef.Static.Tensor.ScatterGather,- Torch.Indef.Static.Tensor.Sort,- Torch.Indef.Static.Tensor.TopK,- Torch.Indef.Static.Tensor.Math.Pointwise.Signed,- Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed,- Torch.Indef.Dynamic.Tensor.Math.Blas,- Torch.Indef.Dynamic.Tensor.Math.Floating,- Torch.Indef.Dynamic.Tensor.Math.Lapack,- Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating,- Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating,- Torch.Indef.Dynamic.Tensor.Random.TH,- Torch.Indef.Dynamic.Tensor.Random.THC,- Torch.Indef.Dynamic.Tensor.Math.Random.TH,- Torch.Indef.Static.Tensor.Math.Blas,- Torch.Indef.Static.Tensor.Math.Floating,- Torch.Indef.Static.Tensor.Math.Lapack,- Torch.Indef.Static.Tensor.Math.Pointwise.Floating,- Torch.Indef.Static.Tensor.Math.Reduce.Floating,- Torch.Indef.Static.Tensor.Random.TH,- Torch.Indef.Static.Tensor.Random.THC,- Torch.Indef.Static.Tensor.Math.Random.TH,- Torch.Indef.Dynamic.NN,- Torch.Indef.Dynamic.NN.Activation,- Torch.Indef.Dynamic.NN.Pooling,- Torch.Indef.Dynamic.NN.Criterion,- Torch.Indef.Static.NN,- Torch.Indef.Static.NN.Activation,- Torch.Indef.Static.NN.Backprop,- Torch.Indef.Static.NN.Conv1d,- Torch.Indef.Static.NN.Conv2d,- Torch.Indef.Static.NN.Criterion,- Torch.Indef.Static.NN.Layers,- Torch.Indef.Static.NN.Linear,- Torch.Indef.Static.NN.Math,- Torch.Indef.Static.NN.Padding,- Torch.Indef.Static.NN.Pooling,- Torch.Indef.Static.NN.Sampling,- Torch.Undefined.Tensor.Math.Random.TH,- Torch.Undefined.Tensor.Random.TH,- Torch.Undefined.Tensor.Random.THC- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-indef -any,- hasktorch-signatures-partial (==0.0.1 || >0.0.1) && <0.0.2--executable isdefinite-cpu- main-is: Noop.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-cpu -any--executable isdefinite-gpu- main-is: Noop.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-gpu -any--executable isdefinite- main-is: Noop.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch -any--executable memcheck- main-is: Memcheck.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch -any--test-suite spec- type: exitcode-stdio-1.0- main-is: Spec.hs- hs-source-dirs: tests- other-modules:- Orphans- MemorySpec- RawLapackSVDSpec- GarbageCollectionSpec- Torch.Prelude.Extras- Torch.Core.LogAddSpec- Torch.Core.RandomSpec- Torch.Static.NN.AbsSpec- Torch.Static.NN.LinearSpec- default-language: Haskell2010- default-extensions: LambdaCase DataKinds TypeFamilies- TypeSynonymInstances ScopedTypeVariables FlexibleContexts CPP- build-depends:- QuickCheck ==2.11 || >2.11,- backprop ==0.2.5 || >0.2.5,- base (==4.7 || >4.7) && <5,- dimensions ==1.0 || >1.0,- ghc-typelits-natnormalise -any,- hasktorch -any,- hspec ==2.4.4 || >2.4.4,- singletons ==2.2 || >2.2,- -- text ==1.2.2 || >1.2.2,- mtl ==2.2.2 || >2.2.2,- microlens-platform ==0.3.10 || >0.3.10,- monad-loops ==0.4.3 || >0.4.3,- time ==1.8.0 || >1.8.0,- transformers ==0.5.5 || >0.5.5,- generic-lens -any-
− tests/ParserTests/regressions/hasktorch.expr
@@ -1,9817 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "isdefinite-cpu")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-cpu")]))],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["exe"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-cpu")]))],- virtualModules = []},- exeName = UnqualComponentName "isdefinite-cpu",- exeScope = ExecutablePublic,- modulePath = "Noop.hs"}},- _×_- (UnqualComponentName "isdefinite-gpu")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-gpu")]))],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["exe"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-gpu")]))],- virtualModules = []},- exeName = UnqualComponentName "isdefinite-gpu",- exeScope = ExecutablePublic,- modulePath = "Noop.hs"}},- _×_- (UnqualComponentName "isdefinite")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["exe"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "isdefinite",- exeScope = ExecutablePublic,- modulePath = "Noop.hs"}},- _×_- (UnqualComponentName "memcheck")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["exe"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "memcheck",- exeScope = ExecutablePublic,- modulePath = "Memcheck.hs"}}],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (PackageFlag (FlagName "lite")))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Byte",- moduleReexportOriginalName = ModuleName- "Torch.Byte",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Byte.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Byte.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Byte.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Byte.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Char",- moduleReexportOriginalName = ModuleName- "Torch.Char",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Char.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Char.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Char.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Char.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Short",- moduleReexportOriginalName = ModuleName- "Torch.Short",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Short.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Short.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Short.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Short.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Int",- moduleReexportOriginalName = ModuleName- "Torch.Int",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Int.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Int.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Int.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Int.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float",- moduleReexportOriginalName = ModuleName- "Torch.Float",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Float.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Float.Storage",- moduleReexportOriginalPackage = Nothing}],- signatures = []}}},- CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "cuda"))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (PackageFlag (FlagName "lite")))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Byte",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Byte",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Byte.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Byte.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Byte.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Byte.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Char",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Char",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Char.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Char.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Char.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Char.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Short",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Short",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Short.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Short.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Short.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Short.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Int",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Int",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Int.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Int.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Int.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Int.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Float",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Float",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Float.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Float.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Float.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Float.Storage",- moduleReexportOriginalPackage = Nothing}],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-gpu")]))],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-gpu")]))],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Long",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Long",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Long.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Long.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Long.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Long.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Backprop",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Backprop",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Conv1d",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Conv1d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Conv2d",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Conv2d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Layers",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Layers",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Linear",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Linear",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Math",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Padding",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Padding",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Sampling",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Sampling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Criterion",- moduleReexportOriginalPackage = Nothing}],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "dimensions")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 0]))- (LaterVersion (mkVersion [1, 0])))- mainLibSet,- Dependency- (PackageName "safe-exceptions")- (UnionVersionRanges- (ThisVersion (mkVersion [0, 1, 0]))- (LaterVersion (mkVersion [0, 1, 0])))- mainLibSet,- Dependency- (PackageName "singletons")- (UnionVersionRanges- (ThisVersion (mkVersion [2, 2]))- (LaterVersion (mkVersion [2, 2])))- mainLibSet,- Dependency- (PackageName "text")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 2, 2]))- (LaterVersion (mkVersion [1, 2, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName "hasktorch-cpu")])),- Dependency- (PackageName "hasktorch-ffi-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Torch.Core.Exceptions",- ModuleName "Torch.Core.Random",- ModuleName "Torch.Core.LogAdd"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [EnableExtension- LambdaCase,- EnableExtension- DataKinds,- EnableExtension- TypeFamilies,- EnableExtension- TypeSynonymInstances,- EnableExtension- ScopedTypeVariables,- EnableExtension- FlexibleContexts,- EnableExtension CPP],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["utils"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "dimensions")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1, 0]))- (LaterVersion- (mkVersion- [1, 0])))- mainLibSet,- Dependency- (PackageName- "safe-exceptions")- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 1,- 0]))- (LaterVersion- (mkVersion- [0,- 1,- 0])))- mainLibSet,- Dependency- (PackageName- "singletons")- (UnionVersionRanges- (ThisVersion- (mkVersion- [2, 2]))- (LaterVersion- (mkVersion- [2, 2])))- mainLibSet,- Dependency- (PackageName- "text")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1,- 2,- 2]))- (LaterVersion- (mkVersion- [1,- 2,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-cpu")])),- Dependency- (PackageName- "hasktorch-ffi-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Types.Numeric",- moduleReexportOriginalName = ModuleName- "Torch.Types.Numeric",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Long",- moduleReexportOriginalName = ModuleName- "Torch.Long",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Long.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Long.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Long.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Long.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double",- moduleReexportOriginalName = ModuleName- "Torch.Double",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Double.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Backprop",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Backprop",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Conv1d",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Conv1d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Conv2d",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Conv2d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Layers",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Layers",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Linear",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Linear",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Math",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Padding",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Padding",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Sampling",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Sampling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN.Criterion",- moduleReexportOriginalPackage = Nothing}],- signatures = []}},- condSubLibraries = [_×_- (UnqualComponentName "hasktorch-cpu")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "lite"))`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned")]))],- condTreeData = Library- {exposedModules = [ModuleName- "Torch.Byte",- ModuleName- "Torch.Byte.Dynamic",- ModuleName- "Torch.Byte.Storage",- ModuleName- "Torch.Char",- ModuleName- "Torch.Char.Dynamic",- ModuleName- "Torch.Char.Storage",- ModuleName- "Torch.Short",- ModuleName- "Torch.Short.Dynamic",- ModuleName- "Torch.Short.Storage",- ModuleName- "Torch.Int",- ModuleName- "Torch.Int.Dynamic",- ModuleName- "Torch.Int.Storage",- ModuleName- "Torch.Float",- ModuleName- "Torch.Float.Dynamic",- ModuleName- "Torch.Float.Storage"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Byte.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Byte.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Byte.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Byte.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Byte.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Byte.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Byte.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Byte.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Byte.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Byte.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Byte.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Byte.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Byte.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Byte.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Byte.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Byte.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Byte.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Byte.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Byte.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Byte.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Byte.Mask")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.TH.Byte"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.TH.Byte.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.TH.Byte.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.TH.Byte.FreeStorage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.TH.Byte.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Char.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Char.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Char.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Char.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Char.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Char.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Char.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Char.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Char.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Char.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Char.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Char.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Char.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Char.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Char.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Char.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Char.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Char.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Char.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Char.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Char.Mask")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.TH.Char"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.TH.Char.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.TH.Char.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.TH.Char.FreeStorage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.TH.Char.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.TH.Char.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.TH.Char.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.TH.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.TH.Char.TensorMath")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Short.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Short.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Short.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Short.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Short.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Short.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Short.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Short.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Short.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Short.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Short.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Short.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Short.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Short.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Short.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Short.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Short.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Short.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Short.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Short.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Short.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Short.Dynamic.Tensor.Math.Pointwise.Signed")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.TH.Short"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.TH.Short.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.TH.Short.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.TH.Short.FreeStorage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.TH.Short.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.TH.Short.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.TH.Short.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.TH.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.TH.Short.TensorMath")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-signed"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Int.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Int.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Int.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Int.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Int.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Int.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Int.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Int.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Int.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Int.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Int.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Int.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Int.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Int.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Int.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Int.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Int.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Int.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Int.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Int.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Int.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Int.Dynamic.Tensor.Math.Pointwise.Signed")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.TH.Int"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.TH.Int.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.TH.Int.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.TH.Int.FreeStorage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.TH.Int.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.TH.Int.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.TH.Int.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.TH.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.TH.Int.TensorMath")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-signed"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Float.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Float.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Float.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Float.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Float.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Float.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Float.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Float.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Float.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Float.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Float.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Float.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Float.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Float.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Float.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Blas")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Lapack")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Floating")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Blas")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Lapack")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Floating")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Random.TH")- (ModuleName- "Torch.Indef.Float.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Random.TH")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Random.TH")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Random.TH")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Undefined.Tensor.Random.THC")- (ModuleName- "Torch.Undefined.Float.Tensor.Random.THC"),- _×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Float.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Float.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Float.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Float.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Float.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Float.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Float.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Float.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Float.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Float.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Float.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Float.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Float.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Float.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Float.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Float.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN")- (ModuleName- "Torch.Float.Dynamic.NN"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Activation")- (ModuleName- "Torch.Float.Dynamic.NN.Activation"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Pooling")- (ModuleName- "Torch.Float.Dynamic.NN.Pooling"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Criterion")- (ModuleName- "Torch.Float.Dynamic.NN.Criterion"),- _×_- (ModuleName- "Torch.Indef.Static.NN")- (ModuleName- "Torch.Float.NN"),- _×_- (ModuleName- "Torch.Indef.Static.NN")- (ModuleName- "Torch.Float.NN"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Activation")- (ModuleName- "Torch.Float.NN.Activation"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Backprop")- (ModuleName- "Torch.Float.NN.Backprop"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Conv1d")- (ModuleName- "Torch.Float.NN.Conv1d"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Conv2d")- (ModuleName- "Torch.Float.NN.Conv2d"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Criterion")- (ModuleName- "Torch.Float.NN.Criterion"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Layers")- (ModuleName- "Torch.Float.NN.Layers"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Linear")- (ModuleName- "Torch.Float.NN.Linear"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Math")- (ModuleName- "Torch.Float.NN.Math"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Padding")- (ModuleName- "Torch.Float.NN.Padding"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Pooling")- (ModuleName- "Torch.Float.NN.Pooling"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Sampling")- (ModuleName- "Torch.Float.NN.Sampling")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.TH.Float"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.TH.Float.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.TH.Float.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.TH.Float.FreeStorage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.TH.Float.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.TH.Float.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.TH.Float.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Floating")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Blas")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Lapack")- (ModuleName- "Torch.FFI.TH.Float.TensorLapack"),- _×_- (ModuleName- "Torch.Sig.NN")- (ModuleName- "Torch.FFI.TH.NN.Float"),- _×_- (ModuleName- "Torch.Sig.Types.NN")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Random.TH")- (ModuleName- "Torch.FFI.TH.Float.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.TH")- (ModuleName- "Torch.FFI.TH.Float.TensorRandom"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.THC")- (ModuleName- "Torch.Undefined.Float.Tensor.Random.THC")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-floating"),- mixinPackageName = PackageName- "hasktorch"}],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned")]))],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "hasktorch-cpu"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "hasktorch-cpu"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "dimensions")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 0]))- (LaterVersion (mkVersion [1, 0])))- mainLibSet,- Dependency- (PackageName "hasktorch-ffi-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "safe-exceptions")- (UnionVersionRanges- (ThisVersion (mkVersion [0, 1, 0]))- (LaterVersion (mkVersion [0, 1, 0])))- mainLibSet,- Dependency- (PackageName "singletons")- (UnionVersionRanges- (ThisVersion (mkVersion [2, 2]))- (LaterVersion (mkVersion [2, 2])))- mainLibSet,- Dependency- (PackageName "text")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 2, 2]))- (LaterVersion (mkVersion [1, 2, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-floating")])),- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-signed")]))],- condTreeData = Library- {exposedModules = [ModuleName "Torch.Long",- ModuleName "Torch.Long.Dynamic",- ModuleName "Torch.Long.Storage",- ModuleName "Torch.Double",- ModuleName "Torch.Double.Dynamic",- ModuleName "Torch.Double.Storage"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [EnableExtension- LambdaCase,- EnableExtension- DataKinds,- EnableExtension- TypeFamilies,- EnableExtension- TypeSynonymInstances,- EnableExtension- ScopedTypeVariables,- EnableExtension- FlexibleContexts,- EnableExtension- CPP],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["utils", "src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Long.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Long.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Long.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Long.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Long.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Long.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Long.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Long.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Long.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Long.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Long.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Long.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Long.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Long.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Long.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Long.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Long.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Long.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Long.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Long.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Long.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Long.Dynamic.Tensor.Math.Pointwise.Signed")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.TH.Long"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.TH.Long.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.TH.Long.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.TH.Long.FreeStorage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.TH.Long.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.TH.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.TH.Long.TensorMath")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-signed"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Double.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Double.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Double.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Double.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Double.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Double.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Double.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Double.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Double.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Double.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Double.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Double.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Double.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Double.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Double.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Blas")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Lapack")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Floating")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Blas")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Lapack")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Floating")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Random.TH")- (ModuleName- "Torch.Indef.Double.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Random.TH")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Random.TH")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Random.TH")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Undefined.Tensor.Random.THC")- (ModuleName- "Torch.Undefined.Double.Tensor.Random.THC"),- _×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Double.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Double.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Double.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Double.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Double.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Double.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Double.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Double.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Double.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Double.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Double.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Double.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Double.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Double.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Double.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Double.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN")- (ModuleName- "Torch.Double.Dynamic.NN"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Activation")- (ModuleName- "Torch.Double.Dynamic.NN.Activation"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Pooling")- (ModuleName- "Torch.Double.Dynamic.NN.Pooling"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Criterion")- (ModuleName- "Torch.Double.Dynamic.NN.Criterion"),- _×_- (ModuleName- "Torch.Indef.Static.NN")- (ModuleName- "Torch.Double.NN"),- _×_- (ModuleName- "Torch.Indef.Static.NN")- (ModuleName- "Torch.Double.NN"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Activation")- (ModuleName- "Torch.Double.NN.Activation"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Backprop")- (ModuleName- "Torch.Double.NN.Backprop"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Conv1d")- (ModuleName- "Torch.Double.NN.Conv1d"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Conv2d")- (ModuleName- "Torch.Double.NN.Conv2d"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Criterion")- (ModuleName- "Torch.Double.NN.Criterion"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Layers")- (ModuleName- "Torch.Double.NN.Layers"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Linear")- (ModuleName- "Torch.Double.NN.Linear"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Math")- (ModuleName- "Torch.Double.NN.Math"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Padding")- (ModuleName- "Torch.Double.NN.Padding"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Pooling")- (ModuleName- "Torch.Double.NN.Pooling"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Sampling")- (ModuleName- "Torch.Double.NN.Sampling")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.TH.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.TH.Long.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.TH.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.TH.Byte.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.TH.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.TH.Double"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.TH.Double.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.TH.Double.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.TH.Double.FreeStorage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.TH.Double.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.TH.Double.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.TH.Double.FreeTensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Floating")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Blas")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Lapack")- (ModuleName- "Torch.FFI.TH.Double.TensorLapack"),- _×_- (ModuleName- "Torch.Sig.NN")- (ModuleName- "Torch.FFI.TH.NN.Double"),- _×_- (ModuleName- "Torch.Sig.Types.NN")- (ModuleName- "Torch.Types.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Random.TH")- (ModuleName- "Torch.FFI.TH.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.TH")- (ModuleName- "Torch.FFI.TH.Double.TensorRandom"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.THC")- (ModuleName- "Torch.Undefined.Double.Tensor.Random.THC")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-floating"),- mixinPackageName = PackageName- "hasktorch"}],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "Torch.Core.Exceptions",- ModuleName- "Torch.Core.Random",- ModuleName- "Torch.Core.LogAdd"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "dimensions")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1,- 0]))- (LaterVersion- (mkVersion- [1,- 0])))- mainLibSet,- Dependency- (PackageName- "hasktorch-ffi-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "safe-exceptions")- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 1,- 0]))- (LaterVersion- (mkVersion- [0,- 1,- 0])))- mainLibSet,- Dependency- (PackageName- "singletons")- (UnionVersionRanges- (ThisVersion- (mkVersion- [2,- 2]))- (LaterVersion- (mkVersion- [2,- 2])))- mainLibSet,- Dependency- (PackageName- "text")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1,- 2,- 2]))- (LaterVersion- (mkVersion- [1,- 2,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-floating")])),- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-signed")]))],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName "hasktorch-cpu"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Backprop",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Backprop",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Conv1d",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Conv1d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Conv2d",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Conv2d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Layers",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Layers",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Linear",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Linear",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Math",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Padding",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Padding",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.NN.Sampling",- moduleReexportOriginalName = ModuleName- "Torch.Double.NN.Sampling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Double.Dynamic.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Double.Dynamic.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Backprop",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Backprop",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Conv1d",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Conv1d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Conv2d",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Conv2d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Layers",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Layers",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Linear",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Linear",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Math",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Padding",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Padding",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.NN.Sampling",- moduleReexportOriginalName = ModuleName- "Torch.Float.NN.Sampling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.Dynamic.NN",- moduleReexportOriginalName = ModuleName- "Torch.Float.Dynamic.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.Dynamic.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Float.Dynamic.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.Dynamic.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Float.Dynamic.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Float.Dynamic.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Float.Dynamic.NN.Criterion",- moduleReexportOriginalPackage = Nothing}],- signatures = []}},- _×_- (UnqualComponentName "hasktorch-gpu")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "lite"))`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned")]))],- condTreeData = Library- {exposedModules = [ModuleName- "Torch.Cuda.Byte",- ModuleName- "Torch.Cuda.Byte.Dynamic",- ModuleName- "Torch.Cuda.Byte.Storage",- ModuleName- "Torch.Cuda.Char",- ModuleName- "Torch.Cuda.Char.Dynamic",- ModuleName- "Torch.Cuda.Char.Storage",- ModuleName- "Torch.Cuda.Short",- ModuleName- "Torch.Cuda.Short.Dynamic",- ModuleName- "Torch.Cuda.Short.Storage",- ModuleName- "Torch.Cuda.Int",- ModuleName- "Torch.Cuda.Int.Dynamic",- ModuleName- "Torch.Cuda.Int.Storage"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Cuda.Byte.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Cuda.Byte.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Byte.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Byte.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Cuda.Byte.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Cuda.Byte.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Cuda.Byte.Mask")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.FFI.THC.State"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.THC"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.THC.Byte"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.THC.Byte.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.THC.Byte.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.THC.Byte.Storage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.THC.Byte.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.THC.Byte.TensorIndex"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.THC.Byte.TensorMasked"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.THC.Byte.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathCompare"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathCompareT"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathPairwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathScan"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.THC.Byte.TensorMode"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.THC.Byte.TensorScatterGather"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.THC.Byte.TensorSort"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.THC.Byte.TensorTopK")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Cuda.Char.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Cuda.Char.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Char.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Char.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Cuda.Char.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Cuda.Char.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Cuda.Char.Mask")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.FFI.THC.State"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.THC"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.THC.Char"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.THC.Char.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.THC.Char.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.THC.Char.Storage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.THC.Char.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.THC.Char.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.THC.Char.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.THC.Char.TensorIndex"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.THC.Char.TensorMasked"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.THC.Char.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.THC.Char.TensorMathCompare"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.THC.Char.TensorMathCompareT"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.THC.Char.TensorMathPairwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.THC.Char.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.THC.Char.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.THC.Char.TensorMathScan"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.THC.Char.TensorMode"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.THC.Char.TensorScatterGather"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.THC.Char.TensorSort"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.THC.Char.TensorTopK")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Cuda.Short.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Cuda.Short.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Cuda.Short.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Cuda.Short.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Cuda.Short.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Short.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pointwise.Signed")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.FFI.THC.State"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.THC"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.THC.Short"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.THC.Short.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.THC.Short.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.THC.Short.Storage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.THC.Short.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.THC.Short.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.THC.Short.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.THC.Short.TensorIndex"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.THC.Short.TensorMasked"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.THC.Short.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.THC.Short.TensorMathCompare"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.THC.Short.TensorMathCompareT"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.THC.Short.TensorMathPairwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.THC.Short.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.THC.Short.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.THC.Short.TensorMathScan"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.THC.Short.TensorMode"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.THC.Short.TensorScatterGather"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.THC.Short.TensorSort"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.THC.Short.TensorTopK"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.THC.Short.TensorMathPointwise")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-signed"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Cuda.Int.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Cuda.Int.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Cuda.Int.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Cuda.Int.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Cuda.Int.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Int.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pointwise.Signed")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.FFI.THC.State"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.THC"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.THC.Int"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.THC.Int.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.THC.Int.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.THC.Int.Storage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.THC.Int.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.THC.Int.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.THC.Int.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.THC.Int.TensorIndex"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.THC.Int.TensorMasked"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.THC.Int.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.THC.Int.TensorMathCompare"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.THC.Int.TensorMathCompareT"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.THC.Int.TensorMathPairwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.THC.Int.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.THC.Int.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.THC.Int.TensorMathScan"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.THC.Int.TensorMode"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.THC.Int.TensorScatterGather"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.THC.Int.TensorSort"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.THC.Int.TensorTopK"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.THC.Int.TensorMathPointwise")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-signed"),- mixinPackageName = PackageName- "hasktorch"}],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned")]))],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "hasktorch-gpu"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "hasktorch-gpu"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "dimensions")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 0]))- (LaterVersion (mkVersion [1, 0])))- mainLibSet,- Dependency- (PackageName "hasktorch-ffi-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "safe-exceptions")- (UnionVersionRanges- (ThisVersion (mkVersion [0, 1, 0]))- (LaterVersion (mkVersion [0, 1, 0])))- mainLibSet,- Dependency- (PackageName "singletons")- (UnionVersionRanges- (ThisVersion (mkVersion [2, 2]))- (LaterVersion (mkVersion [2, 2])))- mainLibSet,- Dependency- (PackageName "text")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 2, 2]))- (LaterVersion (mkVersion [1, 2, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-floating")])),- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-signed")])),- Dependency- (PackageName "hasktorch-ffi-thc")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch-types-thc")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Torch.Cuda.Long",- ModuleName- "Torch.Cuda.Long.Dynamic",- ModuleName- "Torch.Cuda.Long.Storage",- ModuleName "Torch.Cuda.Double",- ModuleName- "Torch.Cuda.Double.Dynamic",- ModuleName- "Torch.Cuda.Double.Storage"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = ["-DCUDA",- "-DHASKTORCH_INTERNAL_CUDA"],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [EnableExtension- LambdaCase,- EnableExtension- DataKinds,- EnableExtension- TypeFamilies,- EnableExtension- TypeSynonymInstances,- EnableExtension- ScopedTypeVariables,- EnableExtension- FlexibleContexts,- EnableExtension- CPP],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["utils", "src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Cuda.Long.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Cuda.Long.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Cuda.Long.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Cuda.Long.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Cuda.Long.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Long.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pointwise.Signed")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.FFI.THC.State"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.THC"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.THC.Long"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.THC.Long.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.THC.Long.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.THC.Long.Storage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.THC.Long.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.THC.Long.TensorIndex"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.THC.Long.TensorMasked"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.THC.Long.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.THC.Long.TensorMathCompare"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.THC.Long.TensorMathCompareT"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.THC.Long.TensorMathPairwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.THC.Long.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.THC.Long.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.THC.Long.TensorMathScan"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.THC.Long.TensorMode"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.THC.Long.TensorScatterGather"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.THC.Long.TensorSort"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.THC.Long.TensorTopK"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.THC.Long.TensorMathPointwise")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-signed"),- mixinPackageName = PackageName- "hasktorch"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Cuda.Double.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Cuda.Double.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Cuda.Double.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Cuda.Double.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Cuda.Double.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Blas")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Lapack")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Floating")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Blas")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Lapack")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Floating")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Undefined.Tensor.Random.TH")- (ModuleName- "Torch.Undefined.Cuda.Double.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Undefined.Tensor.Math.Random.TH")- (ModuleName- "Torch.Undefined.Cuda.Double.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Random.THC")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Random.THC"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Random.THC")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Random.THC"),- _×_- (ModuleName- "Torch.Indef.Storage")- (ModuleName- "Torch.Indef.Cuda.Double.Storage"),- _×_- (ModuleName- "Torch.Indef.Storage.Copy")- (ModuleName- "Torch.Indef.Cuda.Double.Storage.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Copy")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Copy"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Index")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Index"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Masked")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Masked"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Compare"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.CompareT"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pairwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Scan"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Mode")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Mode"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.ScatterGather"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Sort")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Sort"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.TopK")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.TopK"),- _×_- (ModuleName- "Torch.Indef.Types")- (ModuleName- "Torch.Cuda.Double.Types"),- _×_- (ModuleName- "Torch.Indef.Index")- (ModuleName- "Torch.Cuda.Double.Index"),- _×_- (ModuleName- "Torch.Indef.Mask")- (ModuleName- "Torch.Cuda.Double.Mask"),- _×_- (ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN")- (ModuleName- "Torch.Cuda.Double.Dynamic.NN"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Activation")- (ModuleName- "Torch.Cuda.Double.Dynamic.NN.Activation"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Pooling")- (ModuleName- "Torch.Cuda.Double.Dynamic.NN.Pooling"),- _×_- (ModuleName- "Torch.Indef.Dynamic.NN.Criterion")- (ModuleName- "Torch.Cuda.Double.Dynamic.NN.Criterion"),- _×_- (ModuleName- "Torch.Indef.Static.NN")- (ModuleName- "Torch.Cuda.Double.NN"),- _×_- (ModuleName- "Torch.Indef.Static.NN")- (ModuleName- "Torch.Cuda.Double.NN"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Activation")- (ModuleName- "Torch.Cuda.Double.NN.Activation"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Backprop")- (ModuleName- "Torch.Cuda.Double.NN.Backprop"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Conv1d")- (ModuleName- "Torch.Cuda.Double.NN.Conv1d"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Conv2d")- (ModuleName- "Torch.Cuda.Double.NN.Conv2d"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Criterion")- (ModuleName- "Torch.Cuda.Double.NN.Criterion"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Layers")- (ModuleName- "Torch.Cuda.Double.NN.Layers"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Linear")- (ModuleName- "Torch.Cuda.Double.NN.Linear"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Math")- (ModuleName- "Torch.Cuda.Double.NN.Math"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Padding")- (ModuleName- "Torch.Cuda.Double.NN.Padding"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Pooling")- (ModuleName- "Torch.Cuda.Double.NN.Pooling"),- _×_- (ModuleName- "Torch.Indef.Static.NN.Sampling")- (ModuleName- "Torch.Cuda.Double.NN.Sampling")],- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.Index.Tensor")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Index.TensorFree")- (ModuleName- "Torch.FFI.THC.Long.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.Tensor")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.TensorFree")- (ModuleName- "Torch.FFI.THC.Byte.Tensor"),- _×_- (ModuleName- "Torch.Sig.Mask.MathReduce")- (ModuleName- "Torch.FFI.THC.Byte.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.State")- (ModuleName- "Torch.FFI.THC.State"),- _×_- (ModuleName- "Torch.Sig.Types.Global")- (ModuleName- "Torch.Types.THC"),- _×_- (ModuleName- "Torch.Sig.Types")- (ModuleName- "Torch.Types.THC.Double"),- _×_- (ModuleName- "Torch.Sig.Storage")- (ModuleName- "Torch.FFI.THC.Double.Storage"),- _×_- (ModuleName- "Torch.Sig.Storage.Copy")- (ModuleName- "Torch.FFI.THC.Double.StorageCopy"),- _×_- (ModuleName- "Torch.Sig.Storage.Memory")- (ModuleName- "Torch.FFI.THC.Double.Storage"),- _×_- (ModuleName- "Torch.Sig.Tensor")- (ModuleName- "Torch.FFI.THC.Double.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Copy")- (ModuleName- "Torch.FFI.THC.Double.TensorCopy"),- _×_- (ModuleName- "Torch.Sig.Tensor.Memory")- (ModuleName- "Torch.FFI.THC.Double.Tensor"),- _×_- (ModuleName- "Torch.Sig.Tensor.Index")- (ModuleName- "Torch.FFI.THC.Double.TensorIndex"),- _×_- (ModuleName- "Torch.Sig.Tensor.Masked")- (ModuleName- "Torch.FFI.THC.Double.TensorMasked"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math")- (ModuleName- "Torch.FFI.THC.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Compare")- (ModuleName- "Torch.FFI.THC.Double.TensorMathCompare"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.CompareT")- (ModuleName- "Torch.FFI.THC.Double.TensorMathCompareT"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pairwise")- (ModuleName- "Torch.FFI.THC.Double.TensorMathPairwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise")- (ModuleName- "Torch.FFI.THC.Double.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce")- (ModuleName- "Torch.FFI.THC.Double.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Scan")- (ModuleName- "Torch.FFI.THC.Double.TensorMathScan"),- _×_- (ModuleName- "Torch.Sig.Tensor.Mode")- (ModuleName- "Torch.FFI.THC.Double.TensorMode"),- _×_- (ModuleName- "Torch.Sig.Tensor.ScatterGather")- (ModuleName- "Torch.FFI.THC.Double.TensorScatterGather"),- _×_- (ModuleName- "Torch.Sig.Tensor.Sort")- (ModuleName- "Torch.FFI.THC.Double.TensorSort"),- _×_- (ModuleName- "Torch.Sig.Tensor.TopK")- (ModuleName- "Torch.FFI.THC.Double.TensorTopK"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.FFI.THC.Double.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.FFI.THC.Double.TensorMathPointwise"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.FFI.THC.Double.TensorMathReduce"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Floating")- (ModuleName- "Torch.FFI.THC.Double.TensorMath"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Blas")- (ModuleName- "Torch.FFI.THC.Double.TensorMathBlas"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Lapack")- (ModuleName- "Torch.FFI.THC.Double.TensorMathMagma"),- _×_- (ModuleName- "Torch.Sig.NN")- (ModuleName- "Torch.FFI.THC.NN.Double"),- _×_- (ModuleName- "Torch.Sig.Types.NN")- (ModuleName- "Torch.Types.THC"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Random.TH")- (ModuleName- "Torch.Undefined.Cuda.Double.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.TH")- (ModuleName- "Torch.Undefined.Cuda.Double.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.THC")- (ModuleName- "Torch.FFI.THC.Double.TensorRandom")]},- mixinLibraryName = LSubLibName- (UnqualComponentName- "hasktorch-indef-floating"),- mixinPackageName = PackageName- "hasktorch"}],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "Torch.Core.Exceptions",- ModuleName- "Torch.Core.Random",- ModuleName- "Torch.Core.LogAdd"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "dimensions")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1,- 0]))- (LaterVersion- (mkVersion- [1,- 0])))- mainLibSet,- Dependency- (PackageName- "hasktorch-ffi-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch-types-th")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "safe-exceptions")- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 1,- 0]))- (LaterVersion- (mkVersion- [0,- 1,- 0])))- mainLibSet,- Dependency- (PackageName- "singletons")- (UnionVersionRanges- (ThisVersion- (mkVersion- [2,- 2]))- (LaterVersion- (mkVersion- [2,- 2])))- mainLibSet,- Dependency- (PackageName- "text")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1,- 2,- 2]))- (LaterVersion- (mkVersion- [1,- 2,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-floating")])),- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "hasktorch-indef-signed")])),- Dependency- (PackageName- "hasktorch-ffi-thc")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch-types-thc")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName "hasktorch-gpu"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Backprop",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Backprop",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Conv1d",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Conv1d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Conv2d",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Conv2d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Layers",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Layers",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Linear",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Linear",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Math",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Padding",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Padding",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.NN.Sampling",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.NN.Sampling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Cuda.Double.Dynamic.NN.Criterion",- moduleReexportOriginalPackage = Nothing}],- signatures = []}},- _×_- (UnqualComponentName "hasktorch-indef-unsigned")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch-signatures-partial")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch-indef")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = DefaultRenaming,- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.NN")- (ModuleName- "Torch.Undefined.NN"),- _×_- (ModuleName- "Torch.Sig.Types.NN")- (ModuleName- "Torch.Undefined.Types.NN"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Blas")- (ModuleName- "Torch.Undefined.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Floating")- (ModuleName- "Torch.Undefined.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Lapack")- (ModuleName- "Torch.Undefined.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Signed")- (ModuleName- "Torch.Undefined.Tensor.Math.Pointwise.Signed"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Undefined.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Undefined.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Random.TH")- (ModuleName- "Torch.Undefined.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.TH")- (ModuleName- "Torch.Undefined.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.THC")- (ModuleName- "Torch.Undefined.Tensor.Random.THC")]},- mixinLibraryName = LMainLibName,- mixinPackageName = PackageName- "hasktorch-indef"}],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch-signatures-partial")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch-indef")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "hasktorch-indef-unsigned"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Mask",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Mask",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Types",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Types",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Storage.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Storage.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Print",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Print",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Masked",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Masked",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Mode",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Mode",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Sort",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Sort",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.TopK",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.TopK",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Masked",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Masked",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Compare",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Compare",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Scan",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Scan",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Mode",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Mode",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.ScatterGather",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.ScatterGather",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Sort",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Sort",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.TopK",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.TopK",- moduleReexportOriginalPackage = Nothing}],- signatures = []}},- _×_- (UnqualComponentName "hasktorch-indef-signed")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch-signatures-partial")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet,- Dependency- (PackageName "hasktorch-indef")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = DefaultRenaming,- includeRequiresRn = ModuleRenaming- [_×_- (ModuleName- "Torch.Sig.NN")- (ModuleName- "Torch.Undefined.NN"),- _×_- (ModuleName- "Torch.Sig.Types.NN")- (ModuleName- "Torch.Undefined.Types.NN"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Blas")- (ModuleName- "Torch.Undefined.Tensor.Math.Blas"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Floating")- (ModuleName- "Torch.Undefined.Tensor.Math.Floating"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Lapack")- (ModuleName- "Torch.Undefined.Tensor.Math.Lapack"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Pointwise.Floating")- (ModuleName- "Torch.Undefined.Tensor.Math.Pointwise.Floating"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Reduce.Floating")- (ModuleName- "Torch.Undefined.Tensor.Math.Reduce.Floating"),- _×_- (ModuleName- "Torch.Sig.Tensor.Math.Random.TH")- (ModuleName- "Torch.Undefined.Tensor.Math.Random.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.TH")- (ModuleName- "Torch.Undefined.Tensor.Random.TH"),- _×_- (ModuleName- "Torch.Sig.Tensor.Random.THC")- (ModuleName- "Torch.Undefined.Tensor.Random.THC")]},- mixinLibraryName = LMainLibName,- mixinPackageName = PackageName- "hasktorch-indef"}],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch-signatures-partial")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet,- Dependency- (PackageName- "hasktorch-indef")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "hasktorch-indef-signed"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Mask",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Mask",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Types",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Types",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Storage.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Storage.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Print",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Print",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Masked",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Masked",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Mode",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Mode",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Sort",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Sort",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.TopK",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.TopK",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Masked",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Masked",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Compare",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Compare",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Scan",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Scan",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Mode",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Mode",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.ScatterGather",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.ScatterGather",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Sort",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Sort",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.TopK",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.TopK",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalPackage = Nothing}],- signatures = []}},- _×_- (UnqualComponentName "hasktorch-indef-floating")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "hasktorch-indef")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "hasktorch-signatures-partial")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [0, 0, 1]))- (LaterVersion (mkVersion [0, 0, 1])))- (EarlierVersion (mkVersion [0, 0, 2])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "hasktorch-indef")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "hasktorch-signatures-partial")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 0,- 1]))- (LaterVersion- (mkVersion- [0,- 0,- 1])))- (EarlierVersion- (mkVersion- [0,- 0,- 2])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LSubLibName- (UnqualComponentName- "hasktorch-indef-floating"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Mask",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Mask",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Types",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Types",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Storage",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Storage",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Storage.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Storage.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Print",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Print",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Masked",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Masked",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Compare",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.CompareT",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pairwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Scan",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Mode",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Mode",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.ScatterGather",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Sort",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Sort",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.TopK",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.TopK",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Copy",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Copy",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Index",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Index",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Masked",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Masked",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Compare",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Compare",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.CompareT",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pairwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Scan",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Scan",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Mode",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Mode",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.ScatterGather",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.ScatterGather",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Sort",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Sort",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.TopK",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.TopK",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Blas",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Blas",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Floating",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Floating",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Lapack",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Lapack",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Random.TH",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Random.TH",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Random.THC",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Random.THC",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Random.TH",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.Tensor.Math.Random.TH",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Blas",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Blas",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Floating",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Floating",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Lapack",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Lapack",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Floating",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Pointwise.Floating",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce.Floating",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Reduce.Floating",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Random.TH",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Random.TH",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Random.THC",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Random.THC",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.Tensor.Math.Random.TH",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.Tensor.Math.Random.TH",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.NN",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Dynamic.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Dynamic.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Activation",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Activation",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Backprop",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Backprop",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Conv1d",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Conv1d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Conv2d",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Conv2d",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Criterion",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Criterion",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Layers",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Layers",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Linear",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Linear",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Math",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Math",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Padding",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Padding",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Pooling",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Pooling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Indef.Static.NN.Sampling",- moduleReexportOriginalName = ModuleName- "Torch.Indef.Static.NN.Sampling",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Undefined.Tensor.Math.Random.TH",- moduleReexportOriginalName = ModuleName- "Torch.Undefined.Tensor.Math.Random.TH",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Undefined.Tensor.Random.TH",- moduleReexportOriginalName = ModuleName- "Torch.Undefined.Tensor.Random.TH",- moduleReexportOriginalPackage = Nothing},- ModuleReexport- {moduleReexportName = ModuleName- "Torch.Undefined.Tensor.Random.THC",- moduleReexportOriginalName = ModuleName- "Torch.Undefined.Tensor.Random.THC",- moduleReexportOriginalPackage = Nothing}],- signatures = []}}],- condTestSuites = [_×_- (UnqualComponentName "spec")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "QuickCheck")- (UnionVersionRanges- (ThisVersion (mkVersion [2, 11]))- (LaterVersion (mkVersion [2, 11])))- mainLibSet,- Dependency- (PackageName "backprop")- (UnionVersionRanges- (ThisVersion (mkVersion [0, 2, 5]))- (LaterVersion (mkVersion [0, 2, 5])))- mainLibSet,- Dependency- (PackageName "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion (mkVersion [4, 7]))- (LaterVersion (mkVersion [4, 7])))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "dimensions")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 0]))- (LaterVersion (mkVersion [1, 0])))- mainLibSet,- Dependency- (PackageName "ghc-typelits-natnormalise")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "hasktorch")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "hspec")- (UnionVersionRanges- (ThisVersion (mkVersion [2, 4, 4]))- (LaterVersion (mkVersion [2, 4, 4])))- mainLibSet,- Dependency- (PackageName "singletons")- (UnionVersionRanges- (ThisVersion (mkVersion [2, 2]))- (LaterVersion (mkVersion [2, 2])))- mainLibSet,- Dependency- (PackageName "mtl")- (UnionVersionRanges- (ThisVersion (mkVersion [2, 2, 2]))- (LaterVersion (mkVersion [2, 2, 2])))- mainLibSet,- Dependency- (PackageName "microlens-platform")- (UnionVersionRanges- (ThisVersion (mkVersion [0, 3, 10]))- (LaterVersion (mkVersion [0, 3, 10])))- mainLibSet,- Dependency- (PackageName "monad-loops")- (UnionVersionRanges- (ThisVersion (mkVersion [0, 4, 3]))- (LaterVersion (mkVersion [0, 4, 3])))- mainLibSet,- Dependency- (PackageName "time")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 8, 0]))- (LaterVersion (mkVersion [1, 8, 0])))- mainLibSet,- Dependency- (PackageName "transformers")- (UnionVersionRanges- (ThisVersion (mkVersion [0, 5, 5]))- (LaterVersion (mkVersion [0, 5, 5])))- mainLibSet,- Dependency- (PackageName "generic-lens")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [EnableExtension- LambdaCase,- EnableExtension- DataKinds,- EnableExtension- TypeFamilies,- EnableExtension- TypeSynonymInstances,- EnableExtension- ScopedTypeVariables,- EnableExtension- FlexibleContexts,- EnableExtension- CPP],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["tests"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName "Orphans",- ModuleName- "MemorySpec",- ModuleName- "RawLapackSVDSpec",- ModuleName- "GarbageCollectionSpec",- ModuleName- "Torch.Prelude.Extras",- ModuleName- "Torch.Core.LogAddSpec",- ModuleName- "Torch.Core.RandomSpec",- ModuleName- "Torch.Static.NN.AbsSpec",- ModuleName- "Torch.Static.NN.LinearSpec"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "QuickCheck")- (UnionVersionRanges- (ThisVersion- (mkVersion- [2,- 11]))- (LaterVersion- (mkVersion- [2,- 11])))- mainLibSet,- Dependency- (PackageName- "backprop")- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 2,- 5]))- (LaterVersion- (mkVersion- [0,- 2,- 5])))- mainLibSet,- Dependency- (PackageName- "base")- (IntersectVersionRanges- (UnionVersionRanges- (ThisVersion- (mkVersion- [4,- 7]))- (LaterVersion- (mkVersion- [4,- 7])))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "dimensions")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1,- 0]))- (LaterVersion- (mkVersion- [1,- 0])))- mainLibSet,- Dependency- (PackageName- "ghc-typelits-natnormalise")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "hasktorch")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "hspec")- (UnionVersionRanges- (ThisVersion- (mkVersion- [2,- 4,- 4]))- (LaterVersion- (mkVersion- [2,- 4,- 4])))- mainLibSet,- Dependency- (PackageName- "singletons")- (UnionVersionRanges- (ThisVersion- (mkVersion- [2,- 2]))- (LaterVersion- (mkVersion- [2,- 2])))- mainLibSet,- Dependency- (PackageName- "mtl")- (UnionVersionRanges- (ThisVersion- (mkVersion- [2,- 2,- 2]))- (LaterVersion- (mkVersion- [2,- 2,- 2])))- mainLibSet,- Dependency- (PackageName- "microlens-platform")- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 3,- 10]))- (LaterVersion- (mkVersion- [0,- 3,- 10])))- mainLibSet,- Dependency- (PackageName- "monad-loops")- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 4,- 3]))- (LaterVersion- (mkVersion- [0,- 4,- 3])))- mainLibSet,- Dependency- (PackageName- "time")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1,- 8,- 0]))- (LaterVersion- (mkVersion- [1,- 8,- 0])))- mainLibSet,- Dependency- (PackageName- "transformers")- (UnionVersionRanges- (ThisVersion- (mkVersion- [0,- 5,- 5]))- (LaterVersion- (mkVersion- [0,- 5,- 5])))- mainLibSet,- Dependency- (PackageName- "generic-lens")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Spec.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [MkPackageFlag- {flagDefault = False,- flagDescription = "build with THC support",- flagManual = False,- flagName = FlagName "cuda"},- MkPackageFlag- {flagDefault = False,- flagDescription = "only build with Double and Long support",- flagManual = False,- flagName = FlagName "lite"}],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Hasktorch dev team",- benchmarks = [],- bugReports = "https://github.com/hasktorch/hasktorch/issues",- buildTypeRaw = Just Simple,- category = "Tensors, Machine Learning, AI",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "Hasktorch is a library for tensors and neural networks in Haskell. It is an independent open source community project which leverages the core C libraries shared by Torch and PyTorch. This library leverages @cabal v2-build@ and @backpack@. *Note that this project is in early development and should only be used by contributing developers. Expect substantial changes to the library API as it evolves. Contributions and PRs are welcome (see details on github).*",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "https://github.com/hasktorch/hasktorch#readme",- library = Nothing,- licenseFiles = [],- licenseRaw = Left- (License (ELicense (ELicenseId BSD_3_Clause) Nothing)),- maintainer = "Sam Stites <fnz@fgvgrf.vb>, Austin Huang <nhfgvau@nyhz.zvg.rqh> - cipher:ROT13",- package = PackageIdentifier- {pkgName = PackageName "hasktorch",- pkgVersion = mkVersion [0, 0, 1, 0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just- "https://github.com/hasktorch/hasktorch",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV2_2,- stability = "",- subLibraries = [],- synopsis = "Torch for tensors and neural networks in Haskell",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/hasktorch.format
@@ -1,565 +0,0 @@-cabal-version: 2.2-name: hasktorch-version: 0.0.1.0-license: BSD-3-Clause-maintainer:- Sam Stites <fnz@fgvgrf.vb>, Austin Huang <nhfgvau@nyhz.zvg.rqh> - cipher:ROT13--author: Hasktorch dev team-homepage: https://github.com/hasktorch/hasktorch#readme-bug-reports: https://github.com/hasktorch/hasktorch/issues-synopsis: Torch for tensors and neural networks in Haskell-description:- Hasktorch is a library for tensors and neural networks in Haskell. It is an independent open source community project which leverages the core C libraries shared by Torch and PyTorch. This library leverages @cabal v2-build@ and @backpack@. *Note that this project is in early development and should only be used by contributing developers. Expect substantial changes to the library API as it evolves. Contributions and PRs are welcome (see details on github).*--category: Tensors, Machine Learning, AI-build-type: Simple--source-repository head- type: git- location: https://github.com/hasktorch/hasktorch--flag cuda- description: build with THC support- default: False--flag lite- description: only build with Double and Long support- default: False--library- exposed-modules:- Torch.Core.Exceptions- Torch.Core.Random- Torch.Core.LogAdd-- reexported-modules:- Torch.Types.Numeric,- Torch.Long,- Torch.Long.Dynamic,- Torch.Long.Storage,- Torch.Double,- Torch.Double.Dynamic,- Torch.Double.Storage,- Torch.Double.NN,- Torch.Double.NN.Activation,- Torch.Double.NN.Backprop,- Torch.Double.NN.Conv1d,- Torch.Double.NN.Conv2d,- Torch.Double.NN.Criterion,- Torch.Double.NN.Layers,- Torch.Double.NN.Linear,- Torch.Double.NN.Math,- Torch.Double.NN.Padding,- Torch.Double.NN.Pooling,- Torch.Double.NN.Sampling,- Torch.Double.Dynamic.NN,- Torch.Double.Dynamic.NN.Activation,- Torch.Double.Dynamic.NN.Pooling,- Torch.Double.Dynamic.NN.Criterion-- hs-source-dirs: utils- default-language: Haskell2010- default-extensions:- LambdaCase DataKinds TypeFamilies TypeSynonymInstances- ScopedTypeVariables FlexibleContexts CPP-- build-depends:- base (==4.7 || >4.7) && <5,- dimensions ==1.0 || >1.0,- safe-exceptions ==0.1.0 || >0.1.0,- singletons ==2.2 || >2.2,- text ==1.2.2 || >1.2.2,- hasktorch-cpu,- hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2-- if !flag(lite)- reexported-modules:- Torch.Byte,- Torch.Byte.Dynamic,- Torch.Byte.Storage,- Torch.Char,- Torch.Char.Dynamic,- Torch.Char.Storage,- Torch.Short,- Torch.Short.Dynamic,- Torch.Short.Storage,- Torch.Int,- Torch.Int.Dynamic,- Torch.Int.Storage,- Torch.Float,- Torch.Float.Dynamic,- Torch.Float.Storage-- if flag(cuda)- reexported-modules:- Torch.Cuda.Long,- Torch.Cuda.Long.Dynamic,- Torch.Cuda.Long.Storage,- Torch.Cuda.Double,- Torch.Cuda.Double.Dynamic,- Torch.Cuda.Double.Storage,- Torch.Cuda.Double.NN,- Torch.Cuda.Double.NN.Activation,- Torch.Cuda.Double.NN.Backprop,- Torch.Cuda.Double.NN.Conv1d,- Torch.Cuda.Double.NN.Conv2d,- Torch.Cuda.Double.NN.Criterion,- Torch.Cuda.Double.NN.Layers,- Torch.Cuda.Double.NN.Linear,- Torch.Cuda.Double.NN.Math,- Torch.Cuda.Double.NN.Padding,- Torch.Cuda.Double.NN.Pooling,- Torch.Cuda.Double.NN.Sampling,- Torch.Cuda.Double.Dynamic.NN,- Torch.Cuda.Double.Dynamic.NN.Activation,- Torch.Cuda.Double.Dynamic.NN.Pooling,- Torch.Cuda.Double.Dynamic.NN.Criterion-- build-depends: hasktorch-gpu-- if !flag(lite)- reexported-modules:- Torch.Cuda.Byte,- Torch.Cuda.Byte.Dynamic,- Torch.Cuda.Byte.Storage,- Torch.Cuda.Char,- Torch.Cuda.Char.Dynamic,- Torch.Cuda.Char.Storage,- Torch.Cuda.Short,- Torch.Cuda.Short.Dynamic,- Torch.Cuda.Short.Storage,- Torch.Cuda.Int,- Torch.Cuda.Int.Dynamic,- Torch.Cuda.Int.Storage,- Torch.Cuda.Float,- Torch.Cuda.Float.Dynamic,- Torch.Cuda.Float.Storage--library hasktorch-cpu- exposed-modules:- Torch.Long- Torch.Long.Dynamic- Torch.Long.Storage- Torch.Double- Torch.Double.Dynamic- Torch.Double.Storage-- reexported-modules:- Torch.Double.NN,- Torch.Double.NN.Activation,- Torch.Double.NN.Backprop,- Torch.Double.NN.Conv1d,- Torch.Double.NN.Conv2d,- Torch.Double.NN.Criterion,- Torch.Double.NN.Layers,- Torch.Double.NN.Linear,- Torch.Double.NN.Math,- Torch.Double.NN.Padding,- Torch.Double.NN.Pooling,- Torch.Double.NN.Sampling,- Torch.Double.Dynamic.NN,- Torch.Double.Dynamic.NN.Activation,- Torch.Double.Dynamic.NN.Pooling,- Torch.Double.Dynamic.NN.Criterion,- Torch.Float.NN,- Torch.Float.NN.Activation,- Torch.Float.NN.Backprop,- Torch.Float.NN.Conv1d,- Torch.Float.NN.Conv2d,- Torch.Float.NN.Criterion,- Torch.Float.NN.Layers,- Torch.Float.NN.Linear,- Torch.Float.NN.Math,- Torch.Float.NN.Padding,- Torch.Float.NN.Pooling,- Torch.Float.NN.Sampling,- Torch.Float.Dynamic.NN,- Torch.Float.Dynamic.NN.Activation,- Torch.Float.Dynamic.NN.Pooling,- Torch.Float.Dynamic.NN.Criterion-- hs-source-dirs: utils src- other-modules:- Torch.Core.Exceptions- Torch.Core.Random- Torch.Core.LogAdd-- default-language: Haskell2010- default-extensions:- LambdaCase DataKinds TypeFamilies TypeSynonymInstances- ScopedTypeVariables FlexibleContexts CPP-- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- dimensions ==1.0 || >1.0,- hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- safe-exceptions ==0.1.0 || >0.1.0,- singletons ==2.2 || >2.2,- text ==1.2.2 || >1.2.2,- hasktorch-indef-floating,- hasktorch-indef-signed-- mixins:- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Long.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Long.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Long.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Long.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Long.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Long.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Long.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Long.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Long.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Long.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Long.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Long.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Long.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Long.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Long.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Long.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Long.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Long.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Long.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Long.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Long.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Long.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Long.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Long.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Long.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Long.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Long.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Long.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Long.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Long.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Long.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Long.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Long.Types, Torch.Indef.Index as Torch.Long.Index, Torch.Indef.Mask as Torch.Long.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Long.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Long.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Long, Torch.Sig.Storage as Torch.FFI.TH.Long.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Long.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Long.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Long.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Long.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Long.TensorMath),- hasktorch-indef-floating (Torch.Indef.Storage as Torch.Indef.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Double.Types, Torch.Indef.Index as Torch.Double.Index, Torch.Indef.Mask as Torch.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Blas as Torch.Indef.Double.Dynamic.Tensor.Math.Blas, Torch.Indef.Dynamic.Tensor.Math.Lapack as Torch.Indef.Double.Dynamic.Tensor.Math.Lapack, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Floating, Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating as Torch.Indef.Double.Dynamic.Tensor.Math.Reduce.Floating, Torch.Indef.Dynamic.Tensor.Math.Floating as Torch.Indef.Double.Dynamic.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Math.Blas as Torch.Indef.Double.Tensor.Math.Blas, Torch.Indef.Static.Tensor.Math.Lapack as Torch.Indef.Double.Tensor.Math.Lapack, Torch.Indef.Static.Tensor.Math.Pointwise.Floating as Torch.Indef.Double.Tensor.Math.Pointwise.Floating, Torch.Indef.Static.Tensor.Math.Reduce.Floating as Torch.Indef.Double.Tensor.Math.Reduce.Floating, Torch.Indef.Static.Tensor.Math.Floating as Torch.Indef.Double.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Random.TH as Torch.Indef.Double.Tensor.Random.TH, Torch.Indef.Static.Tensor.Math.Random.TH as Torch.Indef.Double.Tensor.Math.Random.TH, Torch.Indef.Dynamic.Tensor.Random.TH as Torch.Indef.Double.Dynamic.Tensor.Random.TH, Torch.Indef.Dynamic.Tensor.Math.Random.TH as Torch.Indef.Double.Dynamic.Tensor.Math.Random.TH, Torch.Undefined.Tensor.Random.THC as Torch.Undefined.Double.Tensor.Random.THC, Torch.Indef.Storage as Torch.Indef.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Double.Types, Torch.Indef.Index as Torch.Double.Index, Torch.Indef.Mask as Torch.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.NN as Torch.Double.Dynamic.NN, Torch.Indef.Dynamic.NN.Activation as Torch.Double.Dynamic.NN.Activation, Torch.Indef.Dynamic.NN.Pooling as Torch.Double.Dynamic.NN.Pooling, Torch.Indef.Dynamic.NN.Criterion as Torch.Double.Dynamic.NN.Criterion, Torch.Indef.Static.NN as Torch.Double.NN, Torch.Indef.Static.NN as Torch.Double.NN, Torch.Indef.Static.NN.Activation as Torch.Double.NN.Activation, Torch.Indef.Static.NN.Backprop as Torch.Double.NN.Backprop, Torch.Indef.Static.NN.Conv1d as Torch.Double.NN.Conv1d, Torch.Indef.Static.NN.Conv2d as Torch.Double.NN.Conv2d, Torch.Indef.Static.NN.Criterion as Torch.Double.NN.Criterion, Torch.Indef.Static.NN.Layers as Torch.Double.NN.Layers, Torch.Indef.Static.NN.Linear as Torch.Double.NN.Linear, Torch.Indef.Static.NN.Math as Torch.Double.NN.Math, Torch.Indef.Static.NN.Padding as Torch.Double.NN.Padding, Torch.Indef.Static.NN.Pooling as Torch.Double.NN.Pooling, Torch.Indef.Static.NN.Sampling as Torch.Double.NN.Sampling) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Double, Torch.Sig.Storage as Torch.FFI.TH.Double.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Double.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Double.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Double.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Double.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Double.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Floating as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Blas as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Math.Lapack as Torch.FFI.TH.Double.TensorLapack, Torch.Sig.NN as Torch.FFI.TH.NN.Double, Torch.Sig.Types.NN as Torch.Types.TH, Torch.Sig.Tensor.Math.Random.TH as Torch.FFI.TH.Double.TensorMath, Torch.Sig.Tensor.Random.TH as Torch.FFI.TH.Double.TensorRandom, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Double.Tensor.Random.THC)-- if flag(lite)-- else- exposed-modules:- Torch.Byte- Torch.Byte.Dynamic- Torch.Byte.Storage- Torch.Char- Torch.Char.Dynamic- Torch.Char.Storage- Torch.Short- Torch.Short.Dynamic- Torch.Short.Storage- Torch.Int- Torch.Int.Dynamic- Torch.Int.Storage- Torch.Float- Torch.Float.Dynamic- Torch.Float.Storage-- build-depends: hasktorch-indef-unsigned- mixins:- hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Byte.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Byte.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Byte.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Byte.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Byte.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Byte.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Byte.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Byte.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Byte.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Byte.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Byte.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Byte.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Byte.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Byte.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Byte.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Byte.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Byte.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Byte.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Byte.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Byte.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Byte.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Byte.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Byte.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Byte.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Byte.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Byte.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Byte.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Byte.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Byte.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Byte.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Byte.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Byte.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Byte.Types, Torch.Indef.Index as Torch.Byte.Index, Torch.Indef.Mask as Torch.Byte.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Byte, Torch.Sig.Storage as Torch.FFI.TH.Byte.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Byte.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Byte.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Byte.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Byte.TensorMath),- hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Char.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Char.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Char.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Char.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Char.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Char.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Char.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Char.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Char.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Char.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Char.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Char.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Char.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Char.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Char.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Char.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Char.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Char.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Char.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Char.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Char.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Char.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Char.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Char.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Char.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Char.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Char.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Char.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Char.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Char.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Char.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Char.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Char.Types, Torch.Indef.Index as Torch.Char.Index, Torch.Indef.Mask as Torch.Char.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Char, Torch.Sig.Storage as Torch.FFI.TH.Char.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Char.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Char.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Char.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Char.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Char.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Char.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Char.TensorMath),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Short.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Short.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Short.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Short.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Short.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Short.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Short.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Short.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Short.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Short.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Short.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Short.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Short.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Short.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Short.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Short.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Short.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Short.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Short.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Short.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Short.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Short.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Short.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Short.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Short.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Short.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Short.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Short.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Short.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Short.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Short.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Short.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Short.Types, Torch.Indef.Index as Torch.Short.Index, Torch.Indef.Mask as Torch.Short.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Short.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Short.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Short, Torch.Sig.Storage as Torch.FFI.TH.Short.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Short.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Short.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Short.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Short.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Short.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Short.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Short.TensorMath),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Int.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Int.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Int.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Int.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Int.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Int.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Int.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Int.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Int.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Int.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Int.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Int.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Int.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Int.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Int.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Int.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Int.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Int.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Int.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Int.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Int.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Int.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Int.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Int.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Int.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Int.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Int.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Int.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Int.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Int.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Int.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Int.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Int.Types, Torch.Indef.Index as Torch.Int.Index, Torch.Indef.Mask as Torch.Int.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Int.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Int.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Int, Torch.Sig.Storage as Torch.FFI.TH.Int.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Int.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Int.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Int.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Int.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Int.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Int.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Int.TensorMath),- hasktorch-indef-floating (Torch.Indef.Storage as Torch.Indef.Float.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Float.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Float.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Float.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Float.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Float.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Float.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Float.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Float.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Float.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Float.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Float.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Float.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Float.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Float.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Float.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Float.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Float.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Float.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Float.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Float.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Float.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Float.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Float.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Float.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Float.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Float.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Float.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Float.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Float.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Float.Types, Torch.Indef.Index as Torch.Float.Index, Torch.Indef.Mask as Torch.Float.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Blas as Torch.Indef.Float.Dynamic.Tensor.Math.Blas, Torch.Indef.Dynamic.Tensor.Math.Lapack as Torch.Indef.Float.Dynamic.Tensor.Math.Lapack, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Floating, Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating as Torch.Indef.Float.Dynamic.Tensor.Math.Reduce.Floating, Torch.Indef.Dynamic.Tensor.Math.Floating as Torch.Indef.Float.Dynamic.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Math.Blas as Torch.Indef.Float.Tensor.Math.Blas, Torch.Indef.Static.Tensor.Math.Lapack as Torch.Indef.Float.Tensor.Math.Lapack, Torch.Indef.Static.Tensor.Math.Pointwise.Floating as Torch.Indef.Float.Tensor.Math.Pointwise.Floating, Torch.Indef.Static.Tensor.Math.Reduce.Floating as Torch.Indef.Float.Tensor.Math.Reduce.Floating, Torch.Indef.Static.Tensor.Math.Floating as Torch.Indef.Float.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Random.TH as Torch.Indef.Float.Tensor.Random.TH, Torch.Indef.Static.Tensor.Math.Random.TH as Torch.Indef.Float.Tensor.Math.Random.TH, Torch.Indef.Dynamic.Tensor.Random.TH as Torch.Indef.Float.Dynamic.Tensor.Random.TH, Torch.Indef.Dynamic.Tensor.Math.Random.TH as Torch.Indef.Float.Dynamic.Tensor.Math.Random.TH, Torch.Undefined.Tensor.Random.THC as Torch.Undefined.Float.Tensor.Random.THC, Torch.Indef.Storage as Torch.Indef.Float.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Float.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Float.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Float.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Float.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Float.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Float.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Float.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Float.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Float.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Float.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Float.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Float.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Float.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Float.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Float.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Float.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Float.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Float.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Float.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Float.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Float.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Float.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Float.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Float.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Float.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Float.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Float.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Float.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Float.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Float.Types, Torch.Indef.Index as Torch.Float.Index, Torch.Indef.Mask as Torch.Float.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Float.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.NN as Torch.Float.Dynamic.NN, Torch.Indef.Dynamic.NN.Activation as Torch.Float.Dynamic.NN.Activation, Torch.Indef.Dynamic.NN.Pooling as Torch.Float.Dynamic.NN.Pooling, Torch.Indef.Dynamic.NN.Criterion as Torch.Float.Dynamic.NN.Criterion, Torch.Indef.Static.NN as Torch.Float.NN, Torch.Indef.Static.NN as Torch.Float.NN, Torch.Indef.Static.NN.Activation as Torch.Float.NN.Activation, Torch.Indef.Static.NN.Backprop as Torch.Float.NN.Backprop, Torch.Indef.Static.NN.Conv1d as Torch.Float.NN.Conv1d, Torch.Indef.Static.NN.Conv2d as Torch.Float.NN.Conv2d, Torch.Indef.Static.NN.Criterion as Torch.Float.NN.Criterion, Torch.Indef.Static.NN.Layers as Torch.Float.NN.Layers, Torch.Indef.Static.NN.Linear as Torch.Float.NN.Linear, Torch.Indef.Static.NN.Math as Torch.Float.NN.Math, Torch.Indef.Static.NN.Padding as Torch.Float.NN.Padding, Torch.Indef.Static.NN.Pooling as Torch.Float.NN.Pooling, Torch.Indef.Static.NN.Sampling as Torch.Float.NN.Sampling) requires (Torch.Sig.Index.Tensor as Torch.FFI.TH.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.TH.Long.FreeTensor, Torch.Sig.Mask.Tensor as Torch.FFI.TH.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.TH.Byte.FreeTensor, Torch.Sig.Mask.MathReduce as Torch.FFI.TH.Byte.TensorMath, Torch.Sig.State as Torch.Types.TH, Torch.Sig.Types.Global as Torch.Types.TH, Torch.Sig.Types as Torch.Types.TH.Float, Torch.Sig.Storage as Torch.FFI.TH.Float.Storage, Torch.Sig.Storage.Copy as Torch.FFI.TH.Float.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.TH.Float.FreeStorage, Torch.Sig.Tensor as Torch.FFI.TH.Float.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.TH.Float.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.TH.Float.FreeTensor, Torch.Sig.Tensor.Index as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Masked as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Scan as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Mode as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.ScatterGather as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Sort as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.TopK as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Floating as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Blas as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Math.Lapack as Torch.FFI.TH.Float.TensorLapack, Torch.Sig.NN as Torch.FFI.TH.NN.Float, Torch.Sig.Types.NN as Torch.Types.TH, Torch.Sig.Tensor.Math.Random.TH as Torch.FFI.TH.Float.TensorMath, Torch.Sig.Tensor.Random.TH as Torch.FFI.TH.Float.TensorRandom, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Float.Tensor.Random.THC)--library hasktorch-gpu- exposed-modules:- Torch.Cuda.Long- Torch.Cuda.Long.Dynamic- Torch.Cuda.Long.Storage- Torch.Cuda.Double- Torch.Cuda.Double.Dynamic- Torch.Cuda.Double.Storage-- reexported-modules:- Torch.Cuda.Double.NN,- Torch.Cuda.Double.NN.Activation,- Torch.Cuda.Double.NN.Backprop,- Torch.Cuda.Double.NN.Conv1d,- Torch.Cuda.Double.NN.Conv2d,- Torch.Cuda.Double.NN.Criterion,- Torch.Cuda.Double.NN.Layers,- Torch.Cuda.Double.NN.Linear,- Torch.Cuda.Double.NN.Math,- Torch.Cuda.Double.NN.Padding,- Torch.Cuda.Double.NN.Pooling,- Torch.Cuda.Double.NN.Sampling,- Torch.Cuda.Double.Dynamic.NN,- Torch.Cuda.Double.Dynamic.NN.Activation,- Torch.Cuda.Double.Dynamic.NN.Pooling,- Torch.Cuda.Double.Dynamic.NN.Criterion-- cpp-options: -DCUDA -DHASKTORCH_INTERNAL_CUDA- hs-source-dirs: utils src- other-modules:- Torch.Core.Exceptions- Torch.Core.Random- Torch.Core.LogAdd-- default-language: Haskell2010- default-extensions:- LambdaCase DataKinds TypeFamilies TypeSynonymInstances- ScopedTypeVariables FlexibleContexts CPP-- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- dimensions ==1.0 || >1.0,- hasktorch-ffi-th (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-th (==0.0.1 || >0.0.1) && <0.0.2,- safe-exceptions ==0.1.0 || >0.1.0,- singletons ==2.2 || >2.2,- text ==1.2.2 || >1.2.2,- hasktorch-indef-floating,- hasktorch-indef-signed,- hasktorch-ffi-thc (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-types-thc (==0.0.1 || >0.0.1) && <0.0.2-- mixins:- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Cuda.Long.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Long.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Long.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Long.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Long.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Long.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Long.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Long.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Long.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Long.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Long.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Long.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Long.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Long.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Long.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Long.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Long.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Long.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Long.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Long.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Long.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Long.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Long.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Long.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Long.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Long.Types, Torch.Indef.Index as Torch.Cuda.Long.Index, Torch.Indef.Mask as Torch.Cuda.Long.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Long.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Long.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Long, Torch.Sig.Storage as Torch.FFI.THC.Long.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Long.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Long.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Long.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Long.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Long.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Long.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Long.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Long.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Long.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Long.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Long.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Long.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Long.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Long.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Long.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Long.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Long.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Long.TensorMathPointwise),- hasktorch-indef-floating (Torch.Indef.Storage as Torch.Indef.Cuda.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Double.Types, Torch.Indef.Index as Torch.Cuda.Double.Index, Torch.Indef.Mask as Torch.Cuda.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Blas as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Blas, Torch.Indef.Dynamic.Tensor.Math.Lapack as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Lapack, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Floating, Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce.Floating, Torch.Indef.Dynamic.Tensor.Math.Floating as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Floating, Torch.Indef.Static.Tensor.Math.Blas as Torch.Indef.Cuda.Double.Tensor.Math.Blas, Torch.Indef.Static.Tensor.Math.Lapack as Torch.Indef.Cuda.Double.Tensor.Math.Lapack, Torch.Indef.Static.Tensor.Math.Pointwise.Floating as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Floating, Torch.Indef.Static.Tensor.Math.Reduce.Floating as Torch.Indef.Cuda.Double.Tensor.Math.Reduce.Floating, Torch.Indef.Static.Tensor.Math.Floating as Torch.Indef.Cuda.Double.Tensor.Math.Floating, Torch.Undefined.Tensor.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Random.TH, Torch.Undefined.Tensor.Math.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Math.Random.TH, Torch.Indef.Static.Tensor.Random.THC as Torch.Indef.Cuda.Double.Tensor.Random.THC, Torch.Indef.Dynamic.Tensor.Random.THC as Torch.Indef.Cuda.Double.Dynamic.Tensor.Random.THC, Torch.Indef.Storage as Torch.Indef.Cuda.Double.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Double.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Double.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Double.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Double.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Double.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Double.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Double.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Double.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Double.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Double.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Double.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Double.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Double.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Double.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Double.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Double.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Double.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Double.Types, Torch.Indef.Index as Torch.Cuda.Double.Index, Torch.Indef.Mask as Torch.Cuda.Double.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Double.Dynamic.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.NN as Torch.Cuda.Double.Dynamic.NN, Torch.Indef.Dynamic.NN.Activation as Torch.Cuda.Double.Dynamic.NN.Activation, Torch.Indef.Dynamic.NN.Pooling as Torch.Cuda.Double.Dynamic.NN.Pooling, Torch.Indef.Dynamic.NN.Criterion as Torch.Cuda.Double.Dynamic.NN.Criterion, Torch.Indef.Static.NN as Torch.Cuda.Double.NN, Torch.Indef.Static.NN as Torch.Cuda.Double.NN, Torch.Indef.Static.NN.Activation as Torch.Cuda.Double.NN.Activation, Torch.Indef.Static.NN.Backprop as Torch.Cuda.Double.NN.Backprop, Torch.Indef.Static.NN.Conv1d as Torch.Cuda.Double.NN.Conv1d, Torch.Indef.Static.NN.Conv2d as Torch.Cuda.Double.NN.Conv2d, Torch.Indef.Static.NN.Criterion as Torch.Cuda.Double.NN.Criterion, Torch.Indef.Static.NN.Layers as Torch.Cuda.Double.NN.Layers, Torch.Indef.Static.NN.Linear as Torch.Cuda.Double.NN.Linear, Torch.Indef.Static.NN.Math as Torch.Cuda.Double.NN.Math, Torch.Indef.Static.NN.Padding as Torch.Cuda.Double.NN.Padding, Torch.Indef.Static.NN.Pooling as Torch.Cuda.Double.NN.Pooling, Torch.Indef.Static.NN.Sampling as Torch.Cuda.Double.NN.Sampling) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Double, Torch.Sig.Storage as Torch.FFI.THC.Double.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Double.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Double.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Double.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Double.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Double.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Double.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Double.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Double.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Double.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Double.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Double.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Double.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Double.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Double.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Double.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Double.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Double.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Double.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Double.TensorMathPointwise, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.FFI.THC.Double.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.FFI.THC.Double.TensorMathReduce, Torch.Sig.Tensor.Math.Floating as Torch.FFI.THC.Double.TensorMath, Torch.Sig.Tensor.Math.Blas as Torch.FFI.THC.Double.TensorMathBlas, Torch.Sig.Tensor.Math.Lapack as Torch.FFI.THC.Double.TensorMathMagma, Torch.Sig.NN as Torch.FFI.THC.NN.Double, Torch.Sig.Types.NN as Torch.Types.THC, Torch.Sig.Tensor.Math.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Math.Random.TH, Torch.Sig.Tensor.Random.TH as Torch.Undefined.Cuda.Double.Tensor.Random.TH, Torch.Sig.Tensor.Random.THC as Torch.FFI.THC.Double.TensorRandom)-- if flag(lite)-- else- exposed-modules:- Torch.Cuda.Byte- Torch.Cuda.Byte.Dynamic- Torch.Cuda.Byte.Storage- Torch.Cuda.Char- Torch.Cuda.Char.Dynamic- Torch.Cuda.Char.Storage- Torch.Cuda.Short- Torch.Cuda.Short.Dynamic- Torch.Cuda.Short.Storage- Torch.Cuda.Int- Torch.Cuda.Int.Dynamic- Torch.Cuda.Int.Storage-- build-depends: hasktorch-indef-unsigned- mixins:- hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Cuda.Byte.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Byte.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Byte.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Byte.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Byte.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Byte.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Byte.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Byte.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Byte.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Byte.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Byte.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Byte.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Byte.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Byte.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Byte.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Byte.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Byte.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Byte.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Byte.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Byte.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Byte.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Byte.Types, Torch.Indef.Index as Torch.Cuda.Byte.Index, Torch.Indef.Mask as Torch.Cuda.Byte.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Byte, Torch.Sig.Storage as Torch.FFI.THC.Byte.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Byte.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Byte.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Byte.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Byte.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Byte.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Byte.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Byte.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Byte.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Byte.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Byte.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Byte.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Byte.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Byte.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Byte.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Byte.TensorTopK),- hasktorch-indef-unsigned (Torch.Indef.Storage as Torch.Indef.Cuda.Char.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Char.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Char.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Char.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Char.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Char.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Char.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Char.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Char.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Char.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Char.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Char.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Char.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Char.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Char.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Char.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Char.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Char.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Char.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Char.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Char.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Char.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Char.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Char.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Char.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Char.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Char.Types, Torch.Indef.Index as Torch.Cuda.Char.Index, Torch.Indef.Mask as Torch.Cuda.Char.Mask) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Char, Torch.Sig.Storage as Torch.FFI.THC.Char.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Char.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Char.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Char.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Char.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Char.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Char.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Char.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Char.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Char.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Char.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Char.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Char.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Char.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Char.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Char.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Char.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Char.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Char.TensorTopK),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Cuda.Short.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Short.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Short.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Short.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Short.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Short.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Short.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Short.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Short.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Short.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Short.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Short.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Short.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Short.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Short.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Short.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Short.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Short.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Short.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Short.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Short.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Short.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Short.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Short.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Short.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Short.Types, Torch.Indef.Index as Torch.Cuda.Short.Index, Torch.Indef.Mask as Torch.Cuda.Short.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Short.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Short.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Short, Torch.Sig.Storage as Torch.FFI.THC.Short.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Short.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Short.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Short.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Short.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Short.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Short.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Short.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Short.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Short.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Short.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Short.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Short.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Short.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Short.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Short.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Short.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Short.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Short.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Short.TensorMathPointwise),- hasktorch-indef-signed (Torch.Indef.Storage as Torch.Indef.Cuda.Int.Storage, Torch.Indef.Storage.Copy as Torch.Indef.Cuda.Int.Storage.Copy, Torch.Indef.Static.Tensor as Torch.Indef.Cuda.Int.Tensor, Torch.Indef.Static.Tensor.Copy as Torch.Indef.Cuda.Int.Tensor.Copy, Torch.Indef.Static.Tensor.Index as Torch.Indef.Cuda.Int.Tensor.Index, Torch.Indef.Static.Tensor.Masked as Torch.Indef.Cuda.Int.Tensor.Masked, Torch.Indef.Static.Tensor.Math as Torch.Indef.Cuda.Int.Tensor.Math, Torch.Indef.Static.Tensor.Math.Compare as Torch.Indef.Cuda.Int.Tensor.Math.Compare, Torch.Indef.Static.Tensor.Math.CompareT as Torch.Indef.Cuda.Int.Tensor.Math.CompareT, Torch.Indef.Static.Tensor.Math.Pairwise as Torch.Indef.Cuda.Int.Tensor.Math.Pairwise, Torch.Indef.Static.Tensor.Math.Pointwise as Torch.Indef.Cuda.Int.Tensor.Math.Pointwise, Torch.Indef.Static.Tensor.Math.Reduce as Torch.Indef.Cuda.Int.Tensor.Math.Reduce, Torch.Indef.Static.Tensor.Math.Scan as Torch.Indef.Cuda.Int.Tensor.Math.Scan, Torch.Indef.Static.Tensor.Mode as Torch.Indef.Cuda.Int.Tensor.Mode, Torch.Indef.Static.Tensor.ScatterGather as Torch.Indef.Cuda.Int.Tensor.ScatterGather, Torch.Indef.Static.Tensor.Sort as Torch.Indef.Cuda.Int.Tensor.Sort, Torch.Indef.Static.Tensor.TopK as Torch.Indef.Cuda.Int.Tensor.TopK, Torch.Indef.Dynamic.Tensor as Torch.Indef.Cuda.Int.Dynamic.Tensor, Torch.Indef.Dynamic.Tensor.Copy as Torch.Indef.Cuda.Int.Dynamic.Tensor.Copy, Torch.Indef.Dynamic.Tensor.Index as Torch.Indef.Cuda.Int.Dynamic.Tensor.Index, Torch.Indef.Dynamic.Tensor.Masked as Torch.Indef.Cuda.Int.Dynamic.Tensor.Masked, Torch.Indef.Dynamic.Tensor.Math as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math, Torch.Indef.Dynamic.Tensor.Math.Compare as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Compare, Torch.Indef.Dynamic.Tensor.Math.CompareT as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.CompareT, Torch.Indef.Dynamic.Tensor.Math.Pairwise as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pairwise, Torch.Indef.Dynamic.Tensor.Math.Pointwise as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pointwise, Torch.Indef.Dynamic.Tensor.Math.Reduce as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Reduce, Torch.Indef.Dynamic.Tensor.Math.Scan as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Scan, Torch.Indef.Dynamic.Tensor.Mode as Torch.Indef.Cuda.Int.Dynamic.Tensor.Mode, Torch.Indef.Dynamic.Tensor.ScatterGather as Torch.Indef.Cuda.Int.Dynamic.Tensor.ScatterGather, Torch.Indef.Dynamic.Tensor.Sort as Torch.Indef.Cuda.Int.Dynamic.Tensor.Sort, Torch.Indef.Dynamic.Tensor.TopK as Torch.Indef.Cuda.Int.Dynamic.Tensor.TopK, Torch.Indef.Types as Torch.Cuda.Int.Types, Torch.Indef.Index as Torch.Cuda.Int.Index, Torch.Indef.Mask as Torch.Cuda.Int.Mask, Torch.Indef.Static.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Int.Tensor.Math.Pointwise.Signed, Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed as Torch.Indef.Cuda.Int.Dynamic.Tensor.Math.Pointwise.Signed) requires (Torch.Sig.Index.Tensor as Torch.FFI.THC.Long.Tensor, Torch.Sig.Index.TensorFree as Torch.FFI.THC.Long.Tensor, Torch.Sig.Mask.Tensor as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.TensorFree as Torch.FFI.THC.Byte.Tensor, Torch.Sig.Mask.MathReduce as Torch.FFI.THC.Byte.TensorMathReduce, Torch.Sig.State as Torch.FFI.THC.State, Torch.Sig.Types.Global as Torch.Types.THC, Torch.Sig.Types as Torch.Types.THC.Int, Torch.Sig.Storage as Torch.FFI.THC.Int.Storage, Torch.Sig.Storage.Copy as Torch.FFI.THC.Int.StorageCopy, Torch.Sig.Storage.Memory as Torch.FFI.THC.Int.Storage, Torch.Sig.Tensor as Torch.FFI.THC.Int.Tensor, Torch.Sig.Tensor.Copy as Torch.FFI.THC.Int.TensorCopy, Torch.Sig.Tensor.Memory as Torch.FFI.THC.Int.Tensor, Torch.Sig.Tensor.Index as Torch.FFI.THC.Int.TensorIndex, Torch.Sig.Tensor.Masked as Torch.FFI.THC.Int.TensorMasked, Torch.Sig.Tensor.Math as Torch.FFI.THC.Int.TensorMath, Torch.Sig.Tensor.Math.Compare as Torch.FFI.THC.Int.TensorMathCompare, Torch.Sig.Tensor.Math.CompareT as Torch.FFI.THC.Int.TensorMathCompareT, Torch.Sig.Tensor.Math.Pairwise as Torch.FFI.THC.Int.TensorMathPairwise, Torch.Sig.Tensor.Math.Pointwise as Torch.FFI.THC.Int.TensorMathPointwise, Torch.Sig.Tensor.Math.Reduce as Torch.FFI.THC.Int.TensorMathReduce, Torch.Sig.Tensor.Math.Scan as Torch.FFI.THC.Int.TensorMathScan, Torch.Sig.Tensor.Mode as Torch.FFI.THC.Int.TensorMode, Torch.Sig.Tensor.ScatterGather as Torch.FFI.THC.Int.TensorScatterGather, Torch.Sig.Tensor.Sort as Torch.FFI.THC.Int.TensorSort, Torch.Sig.Tensor.TopK as Torch.FFI.THC.Int.TensorTopK, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.FFI.THC.Int.TensorMathPointwise)--library hasktorch-indef-unsigned- reexported-modules:- Torch.Indef.Index,- Torch.Indef.Mask,- Torch.Indef.Types,- Torch.Indef.Storage,- Torch.Indef.Storage.Copy,- Torch.Indef.Dynamic.Print,- Torch.Indef.Dynamic.Tensor,- Torch.Indef.Dynamic.Tensor.Copy,- Torch.Indef.Dynamic.Tensor.Index,- Torch.Indef.Dynamic.Tensor.Masked,- Torch.Indef.Dynamic.Tensor.Math,- Torch.Indef.Dynamic.Tensor.Math.Compare,- Torch.Indef.Dynamic.Tensor.Math.CompareT,- Torch.Indef.Dynamic.Tensor.Math.Pairwise,- Torch.Indef.Dynamic.Tensor.Math.Pointwise,- Torch.Indef.Dynamic.Tensor.Math.Reduce,- Torch.Indef.Dynamic.Tensor.Math.Scan,- Torch.Indef.Dynamic.Tensor.Mode,- Torch.Indef.Dynamic.Tensor.ScatterGather,- Torch.Indef.Dynamic.Tensor.Sort,- Torch.Indef.Dynamic.Tensor.TopK,- Torch.Indef.Static.Tensor,- Torch.Indef.Static.Tensor.Copy,- Torch.Indef.Static.Tensor.Index,- Torch.Indef.Static.Tensor.Masked,- Torch.Indef.Static.Tensor.Math,- Torch.Indef.Static.Tensor.Math.Compare,- Torch.Indef.Static.Tensor.Math.CompareT,- Torch.Indef.Static.Tensor.Math.Pairwise,- Torch.Indef.Static.Tensor.Math.Pointwise,- Torch.Indef.Static.Tensor.Math.Reduce,- Torch.Indef.Static.Tensor.Math.Scan,- Torch.Indef.Static.Tensor.Mode,- Torch.Indef.Static.Tensor.ScatterGather,- Torch.Indef.Static.Tensor.Sort,- Torch.Indef.Static.Tensor.TopK-- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-signatures-partial (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-indef-- mixins:- hasktorch-indef requires (Torch.Sig.NN as Torch.Undefined.NN, Torch.Sig.Types.NN as Torch.Undefined.Types.NN, Torch.Sig.Tensor.Math.Blas as Torch.Undefined.Tensor.Math.Blas, Torch.Sig.Tensor.Math.Floating as Torch.Undefined.Tensor.Math.Floating, Torch.Sig.Tensor.Math.Lapack as Torch.Undefined.Tensor.Math.Lapack, Torch.Sig.Tensor.Math.Pointwise.Signed as Torch.Undefined.Tensor.Math.Pointwise.Signed, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.Undefined.Tensor.Math.Pointwise.Floating, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.Undefined.Tensor.Math.Reduce.Floating, Torch.Sig.Tensor.Math.Random.TH as Torch.Undefined.Tensor.Math.Random.TH, Torch.Sig.Tensor.Random.TH as Torch.Undefined.Tensor.Random.TH, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Tensor.Random.THC)--library hasktorch-indef-signed- reexported-modules:- Torch.Indef.Index,- Torch.Indef.Mask,- Torch.Indef.Types,- Torch.Indef.Storage,- Torch.Indef.Storage.Copy,- Torch.Indef.Dynamic.Print,- Torch.Indef.Dynamic.Tensor,- Torch.Indef.Dynamic.Tensor.Copy,- Torch.Indef.Dynamic.Tensor.Index,- Torch.Indef.Dynamic.Tensor.Masked,- Torch.Indef.Dynamic.Tensor.Math,- Torch.Indef.Dynamic.Tensor.Math.Compare,- Torch.Indef.Dynamic.Tensor.Math.CompareT,- Torch.Indef.Dynamic.Tensor.Math.Pairwise,- Torch.Indef.Dynamic.Tensor.Math.Pointwise,- Torch.Indef.Dynamic.Tensor.Math.Reduce,- Torch.Indef.Dynamic.Tensor.Math.Scan,- Torch.Indef.Dynamic.Tensor.Mode,- Torch.Indef.Dynamic.Tensor.ScatterGather,- Torch.Indef.Dynamic.Tensor.Sort,- Torch.Indef.Dynamic.Tensor.TopK,- Torch.Indef.Static.Tensor,- Torch.Indef.Static.Tensor.Copy,- Torch.Indef.Static.Tensor.Index,- Torch.Indef.Static.Tensor.Masked,- Torch.Indef.Static.Tensor.Math,- Torch.Indef.Static.Tensor.Math.Compare,- Torch.Indef.Static.Tensor.Math.CompareT,- Torch.Indef.Static.Tensor.Math.Pairwise,- Torch.Indef.Static.Tensor.Math.Pointwise,- Torch.Indef.Static.Tensor.Math.Reduce,- Torch.Indef.Static.Tensor.Math.Scan,- Torch.Indef.Static.Tensor.Mode,- Torch.Indef.Static.Tensor.ScatterGather,- Torch.Indef.Static.Tensor.Sort,- Torch.Indef.Static.Tensor.TopK,- Torch.Indef.Static.Tensor.Math.Pointwise.Signed,- Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed-- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-signatures-partial (==0.0.1 || >0.0.1) && <0.0.2,- hasktorch-indef-- mixins:- hasktorch-indef requires (Torch.Sig.NN as Torch.Undefined.NN, Torch.Sig.Types.NN as Torch.Undefined.Types.NN, Torch.Sig.Tensor.Math.Blas as Torch.Undefined.Tensor.Math.Blas, Torch.Sig.Tensor.Math.Floating as Torch.Undefined.Tensor.Math.Floating, Torch.Sig.Tensor.Math.Lapack as Torch.Undefined.Tensor.Math.Lapack, Torch.Sig.Tensor.Math.Pointwise.Floating as Torch.Undefined.Tensor.Math.Pointwise.Floating, Torch.Sig.Tensor.Math.Reduce.Floating as Torch.Undefined.Tensor.Math.Reduce.Floating, Torch.Sig.Tensor.Math.Random.TH as Torch.Undefined.Tensor.Math.Random.TH, Torch.Sig.Tensor.Random.TH as Torch.Undefined.Tensor.Random.TH, Torch.Sig.Tensor.Random.THC as Torch.Undefined.Tensor.Random.THC)--library hasktorch-indef-floating- reexported-modules:- Torch.Indef.Index,- Torch.Indef.Mask,- Torch.Indef.Types,- Torch.Indef.Storage,- Torch.Indef.Storage.Copy,- Torch.Indef.Dynamic.Print,- Torch.Indef.Dynamic.Tensor,- Torch.Indef.Dynamic.Tensor.Copy,- Torch.Indef.Dynamic.Tensor.Index,- Torch.Indef.Dynamic.Tensor.Masked,- Torch.Indef.Dynamic.Tensor.Math,- Torch.Indef.Dynamic.Tensor.Math.Compare,- Torch.Indef.Dynamic.Tensor.Math.CompareT,- Torch.Indef.Dynamic.Tensor.Math.Pairwise,- Torch.Indef.Dynamic.Tensor.Math.Pointwise,- Torch.Indef.Dynamic.Tensor.Math.Reduce,- Torch.Indef.Dynamic.Tensor.Math.Scan,- Torch.Indef.Dynamic.Tensor.Mode,- Torch.Indef.Dynamic.Tensor.ScatterGather,- Torch.Indef.Dynamic.Tensor.Sort,- Torch.Indef.Dynamic.Tensor.TopK,- Torch.Indef.Static.Tensor,- Torch.Indef.Static.Tensor.Copy,- Torch.Indef.Static.Tensor.Index,- Torch.Indef.Static.Tensor.Masked,- Torch.Indef.Static.Tensor.Math,- Torch.Indef.Static.Tensor.Math.Compare,- Torch.Indef.Static.Tensor.Math.CompareT,- Torch.Indef.Static.Tensor.Math.Pairwise,- Torch.Indef.Static.Tensor.Math.Pointwise,- Torch.Indef.Static.Tensor.Math.Reduce,- Torch.Indef.Static.Tensor.Math.Scan,- Torch.Indef.Static.Tensor.Mode,- Torch.Indef.Static.Tensor.ScatterGather,- Torch.Indef.Static.Tensor.Sort,- Torch.Indef.Static.Tensor.TopK,- Torch.Indef.Static.Tensor.Math.Pointwise.Signed,- Torch.Indef.Dynamic.Tensor.Math.Pointwise.Signed,- Torch.Indef.Dynamic.Tensor.Math.Blas,- Torch.Indef.Dynamic.Tensor.Math.Floating,- Torch.Indef.Dynamic.Tensor.Math.Lapack,- Torch.Indef.Dynamic.Tensor.Math.Pointwise.Floating,- Torch.Indef.Dynamic.Tensor.Math.Reduce.Floating,- Torch.Indef.Dynamic.Tensor.Random.TH,- Torch.Indef.Dynamic.Tensor.Random.THC,- Torch.Indef.Dynamic.Tensor.Math.Random.TH,- Torch.Indef.Static.Tensor.Math.Blas,- Torch.Indef.Static.Tensor.Math.Floating,- Torch.Indef.Static.Tensor.Math.Lapack,- Torch.Indef.Static.Tensor.Math.Pointwise.Floating,- Torch.Indef.Static.Tensor.Math.Reduce.Floating,- Torch.Indef.Static.Tensor.Random.TH,- Torch.Indef.Static.Tensor.Random.THC,- Torch.Indef.Static.Tensor.Math.Random.TH,- Torch.Indef.Dynamic.NN,- Torch.Indef.Dynamic.NN.Activation,- Torch.Indef.Dynamic.NN.Pooling,- Torch.Indef.Dynamic.NN.Criterion,- Torch.Indef.Static.NN,- Torch.Indef.Static.NN.Activation,- Torch.Indef.Static.NN.Backprop,- Torch.Indef.Static.NN.Conv1d,- Torch.Indef.Static.NN.Conv2d,- Torch.Indef.Static.NN.Criterion,- Torch.Indef.Static.NN.Layers,- Torch.Indef.Static.NN.Linear,- Torch.Indef.Static.NN.Math,- Torch.Indef.Static.NN.Padding,- Torch.Indef.Static.NN.Pooling,- Torch.Indef.Static.NN.Sampling,- Torch.Undefined.Tensor.Math.Random.TH,- Torch.Undefined.Tensor.Random.TH,- Torch.Undefined.Tensor.Random.THC-- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-indef,- hasktorch-signatures-partial (==0.0.1 || >0.0.1) && <0.0.2--executable isdefinite-cpu- main-is: Noop.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-cpu--executable isdefinite-gpu- main-is: Noop.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch-gpu--executable isdefinite- main-is: Noop.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch--executable memcheck- main-is: Memcheck.hs- hs-source-dirs: exe- default-language: Haskell2010- build-depends:- base (==4.7 || >4.7) && <5,- hasktorch--test-suite spec- type: exitcode-stdio-1.0- main-is: Spec.hs- hs-source-dirs: tests- other-modules:- Orphans- MemorySpec- RawLapackSVDSpec- GarbageCollectionSpec- Torch.Prelude.Extras- Torch.Core.LogAddSpec- Torch.Core.RandomSpec- Torch.Static.NN.AbsSpec- Torch.Static.NN.LinearSpec-- default-language: Haskell2010- default-extensions:- LambdaCase DataKinds TypeFamilies TypeSynonymInstances- ScopedTypeVariables FlexibleContexts CPP-- build-depends:- QuickCheck ==2.11 || >2.11,- backprop ==0.2.5 || >0.2.5,- base (==4.7 || >4.7) && <5,- dimensions ==1.0 || >1.0,- ghc-typelits-natnormalise,- hasktorch,- hspec ==2.4.4 || >2.4.4,- singletons ==2.2 || >2.2,- mtl ==2.2.2 || >2.2.2,- microlens-platform ==0.3.10 || >0.3.10,- monad-loops ==0.4.3 || >0.4.3,- time ==1.8.0 || >1.8.0,- transformers ==0.5.5 || >0.5.5,- generic-lens
@@ -1,11 +0,0 @@-cabal-version: 3.0-name: hidden-main-lib-version: 0-synopsis: main lib have to be visible-build-type: Simple--library- default-language: Haskell2010- exposed-modules: ElseIf- build-depends: base- visibility: private
@@ -1,105 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "hidden-main-lib",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "main lib have to be visible",- testSuites = [],- testedWith = []}}
@@ -1,11 +0,0 @@-hidden-main-lib.cabal:11:3: Unknown field: "visibility"-cabal-version: 3.0-name: hidden-main-lib-version: 0-synopsis: main lib have to be visible-build-type: Simple--library- exposed-modules: ElseIf- default-language: Haskell2010- build-depends: base
− tests/ParserTests/regressions/indentation.cabal
@@ -1,18 +0,0 @@-cabal-version: 3.0-name: indentation-version: 0-description:-- * foo-- * foo-bar-- * foo-baz-- .- .- .- some dots--library- default-language: Haskell2010
− tests/ParserTests/regressions/indentation.expr
@@ -1,106 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["* foo\n",- "\n",- " * foo-bar\n",- "\n",- " * foo-baz\n",- "\n",- ".\n",- ".\n",- ".\n",- "some dots"],- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "indentation",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/indentation.format
@@ -1,17 +0,0 @@-cabal-version: 3.0-name: indentation-version: 0-description:- * foo-- * foo-bar-- * foo-baz-- .- .- .- some dots--library- default-language: Haskell2010
− tests/ParserTests/regressions/indentation2.cabal
@@ -1,9 +0,0 @@-cabal-version: 3.0-name: indentation-version: 0-description: foo- indent2- indent4--library- default-language: Haskell2010
− tests/ParserTests/regressions/indentation2.expr
@@ -1,96 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat ["foo\n", " indent2\n", " indent4"],- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "indentation",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/indentation2.format
@@ -1,10 +0,0 @@-cabal-version: 3.0-name: indentation-version: 0-description:- foo- indent2- indent4--library- default-language: Haskell2010
− tests/ParserTests/regressions/indentation3.cabal
@@ -1,11 +0,0 @@-cabal-version: 3.0-name: indentation-version: 0-description: indent0-- indent2- indent0- indent2--library- default-language: Haskell2010
− tests/ParserTests/regressions/indentation3.expr
@@ -1,101 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["indent0\n",- "\n",- " indent2\n",- "indent0\n",- " indent2"],- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "indentation",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/indentation3.format
@@ -1,12 +0,0 @@-cabal-version: 3.0-name: indentation-version: 0-description:- indent0-- indent2- indent0- indent2--library- default-language: Haskell2010
− tests/ParserTests/regressions/issue-5055.cabal
@@ -1,25 +0,0 @@-name: issue-version: 5055-synopsis: no type in all branches-description: no type in all branches.-license: BSD3-category: Test-build-type: Simple-cabal-version: 2.0--executable flag-test-exe- main-is: FirstMain.hs- build-depends: base >= 4.8 && < 5- default-language: Haskell2010--test-suite flag-cabal-test- -- TODO: fix so `type` can be on the top level- build-depends: base >= 4.8 && < 5- default-language: Haskell2010-- main-is: SecondMain.hs- type: exitcode-stdio-1.0-- if os(windows)- main-is: FirstMain.hs- -- type: exitcode-stdio-1.0
− tests/ParserTests/regressions/issue-5055.expr
@@ -1,246 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "flag-test-exe")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 8]))- (EarlierVersion (mkVersion [5])))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 8]))- (EarlierVersion- (mkVersion- [5])))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "flag-test-exe",- exeScope = ExecutablePublic,- modulePath = "FirstMain.hs"}}],- condForeignLibs = [],- condLibrary = Nothing,- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "flag-cabal-test")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 8]))- (EarlierVersion (mkVersion [5])))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4,- 8]))- (EarlierVersion- (mkVersion- [5])))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "SecondMain.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "Test",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "no type in all branches.",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Right BSD3,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "issue",- pkgVersion = mkVersion [5055]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_0,- stability = "",- subLibraries = [],- synopsis = "no type in all branches",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/issue-5055.format
@@ -1,21 +0,0 @@-cabal-version: 2.0-name: issue-version: 5055-license: BSD3-synopsis: no type in all branches-description: no type in all branches.-category: Test-build-type: Simple--executable flag-test-exe- main-is: FirstMain.hs- default-language: Haskell2010- build-depends: base >=4.8 && <5--test-suite flag-cabal-test- type: exitcode-stdio-1.0- main-is: SecondMain.hs- default-language: Haskell2010- build-depends: base >=4.8 && <5-- if os(windows)
− tests/ParserTests/regressions/issue-5846.cabal
@@ -1,11 +0,0 @@-cabal-version: 3.0-name: issue-version: 5846--library- default-language: Haskell2010- build-depends: lib1:{a,b}- , lib2:c-- build-depends: lib3:d>=1- build-depends: lib4:{a,b}>=1
− tests/ParserTests/regressions/issue-5846.expr
@@ -1,170 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "lib1")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName (UnqualComponentName "a"),- LSubLibName (UnqualComponentName "b")])),- Dependency- (PackageName "lib2")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName (UnqualComponentName "c")])),- Dependency- (PackageName "lib3")- (OrLaterVersion (mkVersion [1]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName (UnqualComponentName "d")])),- Dependency- (PackageName "lib4")- (OrLaterVersion (mkVersion [1]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName (UnqualComponentName "a"),- LSubLibName (UnqualComponentName "b")]))],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "lib1")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "a"),- LSubLibName- (UnqualComponentName- "b")])),- Dependency- (PackageName- "lib2")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "c")])),- Dependency- (PackageName- "lib3")- (OrLaterVersion- (mkVersion- [1]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "d")])),- Dependency- (PackageName- "lib4")- (OrLaterVersion- (mkVersion- [1]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "a"),- LSubLibName- (UnqualComponentName- "b")]))],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "issue",- pkgVersion = mkVersion [5846]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/issue-5846.format
@@ -1,15 +0,0 @@-issue-5846.cabal:11:23: colon specifier is experimental feature (issue #5660)-issue-5846.cabal:10:23: colon specifier is experimental feature (issue #5660)-issue-5846.cabal:7:23: colon specifier is experimental feature (issue #5660)-issue-5846.cabal:8:23: colon specifier is experimental feature (issue #5660)-cabal-version: 3.0-name: issue-version: 5846--library- default-language: Haskell2010- build-depends:- lib1:{a, b},- lib2:c,- lib3:d >=1,- lib4:{a, b} >=1
− tests/ParserTests/regressions/issue-6083-a.cabal
@@ -1,19 +0,0 @@-cabal-version: 3.4-name: issue-version: 6083--library- default-language: Haskell2010- -- This should be parsed as the main lib- build-depends: base, issue:sublib--library sublib- default-language: Haskell2010--executable demo-a- main-is: Main.hs- build-depends: issue, sublib--executable demo-b- main-is: Main.hs- build-depends: issue, issue:sublib
− tests/ParserTests/regressions/issue-6083-a.expr
@@ -1,333 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "demo-a")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "sublib")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "sublib")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "demo-a",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}},- _×_- (UnqualComponentName "demo-b")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName "sublib")]))],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "sublib")]))],- virtualModules = []},- exeName = UnqualComponentName "demo-b",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}}],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName "sublib")]))],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "sublib")]))],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [_×_- (UnqualComponentName "sublib")- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LSubLibName (UnqualComponentName "sublib"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "issue",- pkgVersion = mkVersion [6083]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_4,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/issue-6083-a.format
@@ -1,26 +0,0 @@-issue-6083-a.cabal:19:31: colon specifier is experimental feature (issue #5660)-issue-6083-a.cabal:8:30: colon specifier is experimental feature (issue #5660)-cabal-version: 3.4-name: issue-version: 6083--library- default-language: Haskell2010- build-depends:- base,- issue:sublib--library sublib- default-language: Haskell2010--executable demo-a- main-is: Main.hs- build-depends:- issue,- sublib--executable demo-b- main-is: Main.hs- build-depends:- issue,- issue:sublib
− tests/ParserTests/regressions/issue-6083-b.cabal
@@ -1,19 +0,0 @@-cabal-version: 3.0-name: issue-version: 6083--library- default-language: Haskell2010- -- This should be parsed as the main lib- build-depends: base, sublib--library sublib- default-language: Haskell2010--executable demo-a- main-is: Main.hs- build-depends: issue, sublib--executable demo-b- main-is: Main.hs- build-depends: issue, issue:sublib
− tests/ParserTests/regressions/issue-6083-b.expr
@@ -1,340 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "demo-a")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName "sublib")]))],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "sublib")]))],- virtualModules = []},- exeName = UnqualComponentName "demo-a",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}},- _×_- (UnqualComponentName "demo-b")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName "sublib")]))],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "sublib")]))],- virtualModules = []},- exeName = UnqualComponentName "demo-b",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}}],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName "sublib")]))],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "sublib")]))],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [_×_- (UnqualComponentName "sublib")- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LSubLibName (UnqualComponentName "sublib"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "issue",- pkgVersion = mkVersion [6083]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/issue-6083-b.format
@@ -1,25 +0,0 @@-issue-6083-b.cabal:19:31: colon specifier is experimental feature (issue #5660)-cabal-version: 3.0-name: issue-version: 6083--library- default-language: Haskell2010- build-depends:- base,- sublib--library sublib- default-language: Haskell2010--executable demo-a- main-is: Main.hs- build-depends:- issue,- sublib--executable demo-b- main-is: Main.hs- build-depends:- issue,- sublib
− tests/ParserTests/regressions/issue-6083-c.cabal
@@ -1,11 +0,0 @@-cabal-version: 2.4-name: issue-version: 6083--library- default-language: Haskell2010- -- This should be parsed as the main lib- build-depends: base, sublib--library sublib- default-language: Haskell2010
− tests/ParserTests/regressions/issue-6083-c.expr
@@ -1,181 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "issue")- (OrLaterVersion (mkVersion [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName "sublib")]))],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "issue")- (OrLaterVersion- (mkVersion- [0]))- (NonEmptySet.fromNonEmpty- (NE.fromList- [LSubLibName- (UnqualComponentName- "sublib")]))],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [_×_- (UnqualComponentName "sublib")- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LSubLibName (UnqualComponentName "sublib"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "issue",- pkgVersion = mkVersion [6083]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_4,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/issue-6083-c.format
@@ -1,12 +0,0 @@-cabal-version: 2.4-name: issue-version: 6083--library- default-language: Haskell2010- build-depends:- base,- sublib--library sublib- default-language: Haskell2010
− tests/ParserTests/regressions/issue-6083-pkg-pkg.cabal
@@ -1,9 +0,0 @@-cabal-version: 3.0-name: issue-version: 6083--library- default-language: Haskell2010- -- This should be parsed as the main lib- build-depends: freetype- build-depends: freetype:freetype
− tests/ParserTests/regressions/issue-6083-pkg-pkg.expr
@@ -1,116 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "freetype")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "freetype")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "freetype")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "freetype")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "issue",- pkgVersion = mkVersion [6083]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/issue-6083-pkg-pkg.format
@@ -1,10 +0,0 @@-issue-6083-pkg-pkg.cabal:9:27: colon specifier is experimental feature (issue #5660)-cabal-version: 3.0-name: issue-version: 6083--library- default-language: Haskell2010- build-depends:- freetype,- freetype
− tests/ParserTests/regressions/issue-6288-a.cabal
@@ -1,14 +0,0 @@-cabal-version: >=1.8-name: issue-version: 6288-build-type: Simple-synopsis: default-language optionality-category: Test-description: Field is introduced in 1.10, defaulted in 3.4-license: BSD3-license-file: LICENSE-maintainer: Cabal Contributors--library- default-language: Haskell2010- exposed-modules: Foo
− tests/ParserTests/regressions/issue-6288-a.check
@@ -1,1 +0,0 @@-issue-6288-a.cabal:13:3: The field "default-language" is available only since the Cabal specification version 1.10. This field will be ignored.
− tests/ParserTests/regressions/issue-6288-b.cabal
@@ -1,13 +0,0 @@-cabal-version: >= 1.8-name: issue-version: 6288-build-type: Simple-synopsis: default-language optionality-category: Test-description: Field is introduced in 1.10, defaulted in 3.4-license: BSD3-license-file: LICENSE-maintainer: Cabal Contributors--library- exposed-modules: Foo
− tests/ParserTests/regressions/issue-6288-b.check
− tests/ParserTests/regressions/issue-6288-c.cabal
@@ -1,14 +0,0 @@-cabal-version: >= 1.10-name: issue-version: 6288-build-type: Simple-synopsis: default-language optionality-category: Test-description: Field is introduced in 1.10, defaulted in 3.4-license: BSD3-license-file: LICENSE-maintainer: Cabal Contributors--library- default-language: Haskell2010- exposed-modules: Foo
− tests/ParserTests/regressions/issue-6288-c.check
− tests/ParserTests/regressions/issue-6288-d.cabal
@@ -1,13 +0,0 @@-cabal-version: >=1.10-name: issue-version: 6288-build-type: Simple-synopsis: default-language optionality-category: Test-description: Field is introduced in 1.10, defaulted in 3.4-license: BSD3-license-file: LICENSE-maintainer: Cabal Contributors--library- exposed-modules: Foo
− tests/ParserTests/regressions/issue-6288-d.check
@@ -1,1 +0,0 @@-Packages using 'cabal-version: >= 1.10' and before 'cabal-version: 3.4' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field.
− tests/ParserTests/regressions/issue-6288-e.cabal
@@ -1,13 +0,0 @@-cabal-version: 3.4-name: issue-version: 6288-synopsis: default-language optionality-category: Test-description: Field is introduced in 1.10, defaulted in 3.4-license: BSD-3-Clause-license-file: LICENSE-maintainer: Cabal Contributors--library- default-language: Haskell2010- exposed-modules: Foo
− tests/ParserTests/regressions/issue-6288-e.check
− tests/ParserTests/regressions/issue-6288-f.cabal
@@ -1,13 +0,0 @@-cabal-version: 3.4-name: issue-version: 6288-build-type: Simple-synopsis: default-language optionality-category: Test-description: Field is introduced in 1.10, defaulted in 3.4-license: BSD-3-Clause-license-file: LICENSE-maintainer: Cabal Contributors--library- exposed-modules: Foo
− tests/ParserTests/regressions/issue-6288-f.check
− tests/ParserTests/regressions/issue-774.cabal
@@ -1,21 +0,0 @@-name: issue-version: 744-synopsis: Package description parser interprets curly braces in the description field-description: Here is some C code:- .- > for(i = 0; i < 100; i++) {- > printf("%d\n",i);- > }- .- What does it look like?-build-type: Simple--- we test that check warns about this-cabal-version: >=1.12--library- default-language: Haskell2010- exposed-modules: Issue-- -- Test for round-trip of ghc-options here too- -- See https://github.com/haskell/cabal/issues/2661- ghc-options: -Wall -threaded "-with-rtsopts=-N -s -M1G -c" -rtsopts
− tests/ParserTests/regressions/issue-774.check
@@ -1,7 +0,0 @@-issue-774.cabal:13:22: Packages with 'cabal-version: 1.12' or later should specify a specific version of the Cabal spec of the form 'cabal-version: x.y'. Use 'cabal-version: 1.12'.-No 'category' field.-No 'maintainer' field.-The 'license' field is missing or is NONE.-'ghc-options: -threaded' has no effect for libraries. It should only be used for executables.-'ghc-options: -rtsopts' has no effect for libraries. It should only be used for executables.-'ghc-options: -with-rtsopts' has no effect for libraries. It should only be used for executables.
− tests/ParserTests/regressions/issue-774.expr
@@ -1,108 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [ModuleName "Issue"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall",- "-threaded",- "-with-rtsopts=-N -s -M1G -c",- "-rtsopts"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["Here is some C code:\n",- "\n",- "> for(i = 0; i < 100; i++) {\n",- "> printf(\"%d\\n\",i);\n",- "> }\n",- "\n",- "What does it look like?"],- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "issue",- pkgVersion = mkVersion [744]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV1_12,- stability = "",- subLibraries = [],- synopsis = "Package description parser interprets curly braces in the description field",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/issue-774.format
@@ -1,22 +0,0 @@-issue-774.cabal:13:22: Packages with 'cabal-version: 1.12' or later should specify a specific version of the Cabal spec of the form 'cabal-version: x.y'. Use 'cabal-version: 1.12'.-cabal-version: 1.12-name: issue-version: 744-synopsis:- Package description parser interprets curly braces in the description field--description:- Here is some C code:- .- > for(i = 0; i < 100; i++) {- > printf("%d\n",i);- > }- .- What does it look like?--build-type: Simple--library- exposed-modules: Issue- default-language: Haskell2010- ghc-options: -Wall -threaded "-with-rtsopts=-N -s -M1G -c" -rtsopts
− tests/ParserTests/regressions/jaeger-flamegraph.cabal
@@ -1,70 +0,0 @@-cabal-version: 2.2-name: jaeger-flamegraph-version: 1.0.0-synopsis: Generate flamegraphs from Jaeger .json dumps.-license: BSD-3-Clause-license-file: LICENSE-author: Sam Halliday-maintainer: Sam Halliday-copyright: (c) 2018 Symbiont.io-bug-reports: https://github.com/symbiont-io/jaeger-flamegraph/pulls-tested-with: GHC ^>= 8.4.4 || ^>= 8.6.2-category: Testing-description:- This is a small tool to convert JSON dumps obtained from a Jaeger- server (<https://www.jaegertracing.io/>) into a format consumable- by [FlameGraph](https://github.com/brendangregg/FlameGraph).- .- First download the traces for your SERVICE limiting to LIMIT traces- .- > $ curl http://your-jaeger-installation/api/traces?service=SERVICE&limit=LIMIT > input.json- .- using the [undocumented Jaeger API](https://github.com/jaegertracing/jaeger/issues/456#issuecomment-412560321)- then use @jaeger-flamegraph@ to convert the data and send to @flamegraph.pl@- .- > $ jaeger-flamegraph -f input.json | flamegraph.pl > output.svg- .--source-repository head- type: git- location: https://github.com/symbiont-io/jaeger-flamegraph---- https://www.haskell.org/cabal/users-guide/cabal-projectindex.html--common deps- build-depends: , base ^>= 4.11.1.0 || ^>= 4.12.0.0- ghc-options: -Wall- -Werror=missing-home-modules- default-language: Haskell2010--executable jaeger-flamegraph- import: deps- hs-source-dirs: exe- main-is: Main.hs- build-depends: , jaeger-flamegraph- , bytestring ^>= 0.10.8.2- , containers ^>= 0.6.0.1- , extra ^>= 1.6.13- , aeson ^>= 1.4.1.0- , optparse-applicative ^>= 0.14.3.0- , text ^>= 1.2.3.1- ghc-options: -threaded--library- import: deps- hs-source-dirs: library- exposed-modules: Interval- build-depends: , QuickCheck ^>= 2.12.6.1--test-suite tests- import: deps- hs-source-dirs: test- type: exitcode-stdio-1.0- main-is: Driver.hs- other-modules: IntervalTest- build-depends: , jaeger-flamegraph- , tasty ^>= 1.1.0.4- , tasty-hspec ^>= 1.1.5- , tasty-quickcheck ^>= 0.10- build-tool-depends: tasty-discover:tasty-discover ^>= 4.2.1- ghc-options: -threaded
− tests/ParserTests/regressions/jaeger-flamegraph.expr
@@ -1,471 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "jaeger-flamegraph")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (UnionVersionRanges- (MajorBoundVersion (mkVersion [4, 11, 1, 0]))- (MajorBoundVersion- (mkVersion [4, 12, 0, 0])))- mainLibSet,- Dependency- (PackageName "jaeger-flamegraph")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "bytestring")- (MajorBoundVersion (mkVersion [0, 10, 8, 2]))- mainLibSet,- Dependency- (PackageName "containers")- (MajorBoundVersion (mkVersion [0, 6, 0, 1]))- mainLibSet,- Dependency- (PackageName "extra")- (MajorBoundVersion (mkVersion [1, 6, 13]))- mainLibSet,- Dependency- (PackageName "aeson")- (MajorBoundVersion (mkVersion [1, 4, 1, 0]))- mainLibSet,- Dependency- (PackageName "optparse-applicative")- (MajorBoundVersion (mkVersion [0, 14, 3, 0]))- mainLibSet,- Dependency- (PackageName "text")- (MajorBoundVersion (mkVersion [1, 2, 3, 1]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["exe"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall",- "-Werror=missing-home-modules",- "-threaded"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (UnionVersionRanges- (MajorBoundVersion- (mkVersion- [4,- 11,- 1,- 0]))- (MajorBoundVersion- (mkVersion- [4,- 12,- 0,- 0])))- mainLibSet,- Dependency- (PackageName- "jaeger-flamegraph")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "bytestring")- (MajorBoundVersion- (mkVersion- [0,- 10,- 8,- 2]))- mainLibSet,- Dependency- (PackageName- "containers")- (MajorBoundVersion- (mkVersion- [0,- 6,- 0,- 1]))- mainLibSet,- Dependency- (PackageName- "extra")- (MajorBoundVersion- (mkVersion- [1,- 6,- 13]))- mainLibSet,- Dependency- (PackageName- "aeson")- (MajorBoundVersion- (mkVersion- [1,- 4,- 1,- 0]))- mainLibSet,- Dependency- (PackageName- "optparse-applicative")- (MajorBoundVersion- (mkVersion- [0,- 14,- 3,- 0]))- mainLibSet,- Dependency- (PackageName- "text")- (MajorBoundVersion- (mkVersion- [1,- 2,- 3,- 1]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "jaeger-flamegraph",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}}],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (UnionVersionRanges- (MajorBoundVersion (mkVersion [4, 11, 1, 0]))- (MajorBoundVersion (mkVersion [4, 12, 0, 0])))- mainLibSet,- Dependency- (PackageName "QuickCheck")- (MajorBoundVersion (mkVersion [2, 12, 6, 1]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Interval"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["library"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall",- "-Werror=missing-home-modules"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (UnionVersionRanges- (MajorBoundVersion- (mkVersion- [4,- 11,- 1,- 0]))- (MajorBoundVersion- (mkVersion- [4,- 12,- 0,- 0])))- mainLibSet,- Dependency- (PackageName- "QuickCheck")- (MajorBoundVersion- (mkVersion- [2,- 12,- 6,- 1]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "tests")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (UnionVersionRanges- (MajorBoundVersion (mkVersion [4, 11, 1, 0]))- (MajorBoundVersion (mkVersion [4, 12, 0, 0])))- mainLibSet,- Dependency- (PackageName "jaeger-flamegraph")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "tasty")- (MajorBoundVersion (mkVersion [1, 1, 0, 4]))- mainLibSet,- Dependency- (PackageName "tasty-hspec")- (MajorBoundVersion (mkVersion [1, 1, 5]))- mainLibSet,- Dependency- (PackageName "tasty-quickcheck")- (MajorBoundVersion (mkVersion [0, 10]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [ExeDependency- (PackageName- "tasty-discover")- (UnqualComponentName- "tasty-discover")- (MajorBoundVersion- (mkVersion- [4,- 2,- 1]))],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["test"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall",- "-Werror=missing-home-modules",- "-threaded"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "IntervalTest"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (UnionVersionRanges- (MajorBoundVersion- (mkVersion- [4,- 11,- 1,- 0]))- (MajorBoundVersion- (mkVersion- [4,- 12,- 0,- 0])))- mainLibSet,- Dependency- (PackageName- "jaeger-flamegraph")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "tasty")- (MajorBoundVersion- (mkVersion- [1,- 1,- 0,- 4]))- mainLibSet,- Dependency- (PackageName- "tasty-hspec")- (MajorBoundVersion- (mkVersion- [1,- 1,- 5]))- mainLibSet,- Dependency- (PackageName- "tasty-quickcheck")- (MajorBoundVersion- (mkVersion- [0,- 10]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Driver.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Sam Halliday",- benchmarks = [],- bugReports = "https://github.com/symbiont-io/jaeger-flamegraph/pulls",- buildTypeRaw = Nothing,- category = "Testing",- copyright = "(c) 2018 Symbiont.io",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["This is a small tool to convert JSON dumps obtained from a Jaeger\n",- "server (<https://www.jaegertracing.io/>) into a format consumable\n",- "by [FlameGraph](https://github.com/brendangregg/FlameGraph).\n",- "\n",- "First download the traces for your SERVICE limiting to LIMIT traces\n",- "\n",- "> $ curl http://your-jaeger-installation/api/traces?service=SERVICE&limit=LIMIT > input.json\n",- "\n",- "using the [undocumented Jaeger API](https://github.com/jaegertracing/jaeger/issues/456#issuecomment-412560321)\n",- "then use @jaeger-flamegraph@ to convert the data and send to @flamegraph.pl@\n",- "\n",- "> $ jaeger-flamegraph -f input.json | flamegraph.pl > output.svg\n"],- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Left- (License (ELicense (ELicenseId BSD_3_Clause) Nothing)),- maintainer = "Sam Halliday",- package = PackageIdentifier- {pkgName = PackageName "jaeger-flamegraph",- pkgVersion = mkVersion [1, 0, 0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just- "https://github.com/symbiont-io/jaeger-flamegraph",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV2_2,- stability = "",- subLibraries = [],- synopsis = "Generate flamegraphs from Jaeger .json dumps.",- testSuites = [],- testedWith = [_×_- GHC- (UnionVersionRanges- (MajorBoundVersion (mkVersion [8, 4, 4]))- (MajorBoundVersion (mkVersion [8, 6, 2])))]}}
− tests/ParserTests/regressions/jaeger-flamegraph.format
@@ -1,70 +0,0 @@-cabal-version: 2.2-name: jaeger-flamegraph-version: 1.0.0-license: BSD-3-Clause-license-file: LICENSE-copyright: (c) 2018 Symbiont.io-maintainer: Sam Halliday-author: Sam Halliday-tested-with: ghc ^>=8.4.4 || ^>=8.6.2-bug-reports: https://github.com/symbiont-io/jaeger-flamegraph/pulls-synopsis: Generate flamegraphs from Jaeger .json dumps.-description:- This is a small tool to convert JSON dumps obtained from a Jaeger- server (<https://www.jaegertracing.io/>) into a format consumable- by [FlameGraph](https://github.com/brendangregg/FlameGraph).- .- First download the traces for your SERVICE limiting to LIMIT traces- .- > $ curl http://your-jaeger-installation/api/traces?service=SERVICE&limit=LIMIT > input.json- .- using the [undocumented Jaeger API](https://github.com/jaegertracing/jaeger/issues/456#issuecomment-412560321)- then use @jaeger-flamegraph@ to convert the data and send to @flamegraph.pl@- .- > $ jaeger-flamegraph -f input.json | flamegraph.pl > output.svg- .--category: Testing--source-repository head- type: git- location: https://github.com/symbiont-io/jaeger-flamegraph--library- exposed-modules: Interval- hs-source-dirs: library- default-language: Haskell2010- ghc-options: -Wall -Werror=missing-home-modules- build-depends:- base ^>=4.11.1.0 || ^>=4.12.0.0,- QuickCheck ^>=2.12.6.1--executable jaeger-flamegraph- main-is: Main.hs- hs-source-dirs: exe- default-language: Haskell2010- ghc-options: -Wall -Werror=missing-home-modules -threaded- build-depends:- base ^>=4.11.1.0 || ^>=4.12.0.0,- jaeger-flamegraph,- bytestring ^>=0.10.8.2,- containers ^>=0.6.0.1,- extra ^>=1.6.13,- aeson ^>=1.4.1.0,- optparse-applicative ^>=0.14.3.0,- text ^>=1.2.3.1--test-suite tests- type: exitcode-stdio-1.0- main-is: Driver.hs- build-tool-depends: tasty-discover:tasty-discover ^>=4.2.1- hs-source-dirs: test- other-modules: IntervalTest- default-language: Haskell2010- ghc-options: -Wall -Werror=missing-home-modules -threaded- build-depends:- base ^>=4.11.1.0 || ^>=4.12.0.0,- jaeger-flamegraph,- tasty ^>=1.1.0.4,- tasty-hspec ^>=1.1.5,- tasty-quickcheck ^>=0.10
− tests/ParserTests/regressions/leading-comma-2.cabal
@@ -1,33 +0,0 @@-cabal-version: 3.0-name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--library- default-language: Haskell2010-- -- empty field on purpose- exposed-modules:-- exposed-modules:- , LeadingComma- , LeadingComma2-- exposed-modules:- TrailingComma,- TrailingComma,-- exposed-modules: Comma, InBetween-- exposed-modules: NoCommas NoCommas-- build-depends: base, containers-- build-depends:- deepseq,- transformers,-- build-depends:- , filepath- , directory
− tests/ParserTests/regressions/leading-comma-2.expr
@@ -1,167 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "containers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "deepseq")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "transformers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "filepath")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "directory")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "LeadingComma",- ModuleName "LeadingComma2",- ModuleName "TrailingComma",- ModuleName "TrailingComma",- ModuleName "Comma",- ModuleName "InBetween",- ModuleName "NoCommas",- ModuleName "NoCommas"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "deepseq")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "transformers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "filepath")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "directory")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "leading-comma",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "leading comma, trailing comma, or ordinary",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/leading-comma-2.format
@@ -1,25 +0,0 @@-cabal-version: 3.0-name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--library- exposed-modules:- LeadingComma- LeadingComma2- TrailingComma- TrailingComma- Comma- InBetween- NoCommas- NoCommas-- default-language: Haskell2010- build-depends:- base,- containers,- deepseq,- transformers,- filepath,- directory
− tests/ParserTests/regressions/leading-comma.cabal
@@ -1,19 +0,0 @@-cabal-version: 2.2-name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--library- default-language: Haskell2010- exposed-modules: LeadingComma-- build-depends: base, containers-- build-depends:- deepseq,- transformers,-- build-depends:- , filepath- , directory
− tests/ParserTests/regressions/leading-comma.expr
@@ -1,160 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "containers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "deepseq")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "transformers")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "filepath")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "directory")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "LeadingComma"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "containers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "deepseq")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "transformers")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "filepath")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "directory")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "leading-comma",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_2,- stability = "",- subLibraries = [],- synopsis = "leading comma, trailing comma, or ordinary",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/leading-comma.format
@@ -1,16 +0,0 @@-cabal-version: 2.2-name: leading-comma-version: 0-synopsis: leading comma, trailing comma, or ordinary-build-type: Simple--library- exposed-modules: LeadingComma- default-language: Haskell2010- build-depends:- base,- containers,- deepseq,- transformers,- filepath,- directory
− tests/ParserTests/regressions/libpq1.cabal
@@ -1,81 +0,0 @@-Name: postgresql-libpq-Version: 0.9.4.2-Synopsis: low-level binding to libpq--Description: This is a binding to libpq: the C application- programmer's interface to PostgreSQL. libpq is a- set of library functions that allow client- programs to pass queries to the PostgreSQL- backend server and to receive the results of- these queries.--Homepage: https://github.com/phadej/postgresql-libpq-License: BSD3-License-file: LICENSE-Author: Grant Monroe, Leon P Smith, Joey Adams-Maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-Copyright: (c) 2010 Grant Monroe- (c) 2011 Leon P Smith-Category: Database-Build-type: Custom-Extra-source-files: cbits/noticehandlers.h-Cabal-version: >=1.8-Tested-with:- GHC==7.0.4,- GHC==7.2.2,- GHC==7.4.2,- GHC==7.6.3,- GHC==7.8.4,- GHC==7.10.3,- GHC==8.0.2,- GHC==8.2.2,- GHC==8.4.3,- GHC==8.6.1--extra-source-files:- CHANGELOG.md--Custom-setup- setup-depends:- base >= 4.3 && <5, Cabal >= 1.10 && <2.5---- If true, use pkg-config, otherwise use the pg_config based build--- configuration-Flag use-pkg-config- default: False- manual: True--Library- hs-source-dirs: src- c-sources: cbits/noticehandlers.c- include-dirs: cbits- Exposed-modules: Database.PostgreSQL.LibPQ- Database.PostgreSQL.LibPQ.Internal- Build-depends: base >=4.3 && <4.13- , bytestring >=0.9.1.0 && <0.11-- if !os(windows)- Build-depends: unix >=2.4.2.0 && <2.8-- if os(windows)- Build-depends: Win32 >=2.2.0.2 && <2.7-- GHC-Options: -Wall-- if flag(use-pkg-config)- Pkgconfig-depends: libpq ==9.*- else- if os(windows)- -- Due to https://sourceware.org/bugzilla/show_bug.cgi?id=22948,- -- if we specify pq instead of libpq, then ld might link against- -- libpq.dll directly, which can lead to segfaults. As a temporary hack,- -- we force ld to link against the libpq.lib import library directly- -- by specifying libpq here.- Extra-Libraries: libpq- else- Extra-Libraries: pq- if os(openbsd)- Extra-Libraries: crypto ssl-- -- Other-modules:- Build-tools: hsc2hs
− tests/ParserTests/regressions/libpq1.expr
@@ -1,688 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 4,- 2,- 0]))- (EarlierVersion- (mkVersion- [2,- 8])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 4,- 2,- 0]))- (EarlierVersion- (mkVersion- [2,- 8])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 2,- 0,- 2]))- (EarlierVersion- (mkVersion- [2,- 7])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 2,- 0,- 2]))- (EarlierVersion- (mkVersion- [2,- 7])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "use-pkg-config"))`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS OpenBSD)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = ["crypto",- "ssl"],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = ["pq"],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = ["libpq"],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [PkgconfigDependency- (PkgconfigName- "libpq")- (PcIntersectVersionRanges- (PcOrLaterVersion- (PkgconfigVersion- "9"))- (PcEarlierVersion- (PkgconfigVersion- "10")))],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 3]))- (EarlierVersion (mkVersion [4, 13])))- mainLibSet,- Dependency- (PackageName "bytestring")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 9, 1, 0]))- (EarlierVersion (mkVersion [0, 11])))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Database.PostgreSQL.LibPQ",- ModuleName- "Database.PostgreSQL.LibPQ.Internal"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [LegacyExeDependency- "hsc2hs"- (OrLaterVersion- (mkVersion [0]))],- buildable = True,- cSources = ["cbits/noticehandlers.c"],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["src"],- includeDirs = ["cbits"],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor ["-Wall"] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4, 3]))- (EarlierVersion- (mkVersion- [4,- 13])))- mainLibSet,- Dependency- (PackageName- "bytestring")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 9,- 1,- 0]))- (EarlierVersion- (mkVersion- [0,- 11])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [MkPackageFlag- {flagDefault = False,- flagDescription = "",- flagManual = True,- flagName = FlagName "use-pkg-config"}],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Grant Monroe, Leon P Smith, Joey Adams",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Custom,- category = "Database",- copyright = concat- ["(c) 2010 Grant Monroe\n", "(c) 2011 Leon P Smith"],- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["This is a binding to libpq: the C application\n",- "programmer's interface to PostgreSQL. libpq is a\n",- "set of library functions that allow client\n",- "programs to pass queries to the PostgreSQL\n",- "backend server and to receive the results of\n",- "these queries."],- executables = [],- extraDocFiles = [],- extraSrcFiles = ["cbits/noticehandlers.h", "CHANGELOG.md"],- extraTmpFiles = [],- foreignLibs = [],- homepage = "https://github.com/phadej/postgresql-libpq",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Right BSD3,- maintainer = "Oleg Grenrus <oleg.grenrus@iki.fi>",- package = PackageIdentifier- {pkgName = PackageName "postgresql-libpq",- pkgVersion = mkVersion [0, 9, 4, 2]},- pkgUrl = "",- setupBuildInfo = Just- SetupBuildInfo- {defaultSetupDepends = False,- setupDepends = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion [4, 3]))- (EarlierVersion- (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "Cabal")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion [1, 10]))- (EarlierVersion- (mkVersion [2, 5])))- mainLibSet]},- sourceRepos = [],- specVersion = CabalSpecV1_8,- stability = "",- subLibraries = [],- synopsis = "low-level binding to libpq",- testSuites = [],- testedWith = [_×_ GHC (ThisVersion (mkVersion [7, 0, 4])),- _×_ GHC (ThisVersion (mkVersion [7, 2, 2])),- _×_ GHC (ThisVersion (mkVersion [7, 4, 2])),- _×_ GHC (ThisVersion (mkVersion [7, 6, 3])),- _×_ GHC (ThisVersion (mkVersion [7, 8, 4])),- _×_ GHC (ThisVersion (mkVersion [7, 10, 3])),- _×_ GHC (ThisVersion (mkVersion [8, 0, 2])),- _×_ GHC (ThisVersion (mkVersion [8, 2, 2])),- _×_ GHC (ThisVersion (mkVersion [8, 4, 3])),- _×_ GHC (ThisVersion (mkVersion [8, 6, 1]))]}}
− tests/ParserTests/regressions/libpq1.format
@@ -1,74 +0,0 @@-cabal-version: >=1.8-name: postgresql-libpq-version: 0.9.4.2-license: BSD3-license-file: LICENSE-copyright:- (c) 2010 Grant Monroe- (c) 2011 Leon P Smith--maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-author: Grant Monroe, Leon P Smith, Joey Adams-tested-with:- ghc ==7.0.4 ghc ==7.2.2 ghc ==7.4.2 ghc ==7.6.3 ghc ==7.8.4- ghc ==7.10.3 ghc ==8.0.2 ghc ==8.2.2 ghc ==8.4.3 ghc ==8.6.1--homepage: https://github.com/phadej/postgresql-libpq-synopsis: low-level binding to libpq-description:- This is a binding to libpq: the C application- programmer's interface to PostgreSQL. libpq is a- set of library functions that allow client- programs to pass queries to the PostgreSQL- backend server and to receive the results of- these queries.--category: Database-build-type: Custom-extra-source-files:- cbits/noticehandlers.h- CHANGELOG.md--custom-setup- setup-depends:- base >=4.3 && <5,- Cabal >=1.10 && <2.5--flag use-pkg-config- default: False- manual: True--library- exposed-modules:- Database.PostgreSQL.LibPQ- Database.PostgreSQL.LibPQ.Internal-- build-tools: hsc2hs >=0- c-sources: cbits/noticehandlers.c- hs-source-dirs: src- include-dirs: cbits- ghc-options: -Wall- build-depends:- base >=4.3 && <4.13,- bytestring >=0.9.1.0 && <0.11-- if !os(windows)- build-depends: unix >=2.4.2.0 && <2.8-- if os(windows)- build-depends: Win32 >=2.2.0.2 && <2.7-- if flag(use-pkg-config)- pkgconfig-depends: libpq >=9 && <10-- else- if os(windows)- extra-libraries: libpq-- else- extra-libraries: pq-- if os(openbsd)- extra-libraries:- crypto- ssl
− tests/ParserTests/regressions/libpq2.cabal
@@ -1,81 +0,0 @@-Cabal-version: 3.0-Name: postgresql-libpq-Version: 0.9.4.2-Synopsis: low-level binding to libpq--Description: This is a binding to libpq: the C application- programmer's interface to PostgreSQL. libpq is a- set of library functions that allow client- programs to pass queries to the PostgreSQL- backend server and to receive the results of- these queries.--Homepage: https://github.com/phadej/postgresql-libpq-License: BSD-3-Clause-License-file: LICENSE-Author: Grant Monroe, Leon P Smith, Joey Adams-Maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-Copyright: (c) 2010 Grant Monroe- (c) 2011 Leon P Smith-Category: Database-Build-type: Custom-Extra-source-files: cbits/noticehandlers.h-Tested-with:- GHC==7.0.4,- GHC==7.2.2,- GHC==7.4.2,- GHC==7.6.3,- GHC==7.8.4,- GHC==7.10.3,- GHC==8.0.2,- GHC==8.2.2,- GHC==8.4.3,- GHC==8.6.1--extra-source-files:- CHANGELOG.md--Custom-setup- setup-depends:- base >= 4.3 && <5, Cabal >= 1.10 && <2.5---- If true, use pkg-config, otherwise use the pg_config based build--- configuration-Flag use-pkg-config- default: False- manual: True--Library- hs-source-dirs: src- c-sources: cbits/noticehandlers.c- include-dirs: cbits- Exposed-modules: Database.PostgreSQL.LibPQ- Database.PostgreSQL.LibPQ.Internal- Build-depends: base >=4.3 && <4.13- , bytestring >=0.9.1.0 && <0.11-- if !os(windows)- Build-depends: unix >=2.4.2.0 && <2.8-- if os(windows)- Build-depends: Win32 >=2.2.0.2 && <2.7-- GHC-Options: -Wall-- if flag(use-pkg-config)- Pkgconfig-depends: libpq >=9.3h- else- if os(windows)- -- Due to https://sourceware.org/bugzilla/show_bug.cgi?id=22948,- -- if we specify pq instead of libpq, then ld might link against- -- libpq.dll directly, which can lead to segfaults. As a temporary hack,- -- we force ld to link against the libpq.lib import library directly- -- by specifying libpq here.- Extra-Libraries: libpq- else- Extra-Libraries: pq- if os(openbsd)- Extra-Libraries: crypto ssl-- -- Other-modules:- build-tool-depends: hsc2hs:hsc2hs
− tests/ParserTests/regressions/libpq2.expr
@@ -1,689 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 4,- 2,- 0]))- (EarlierVersion- (mkVersion- [2,- 8])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 4,- 2,- 0]))- (EarlierVersion- (mkVersion- [2,- 8])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "Win32")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 2,- 0,- 2]))- (EarlierVersion- (mkVersion- [2,- 7])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "Win32")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 2,- 0,- 2]))- (EarlierVersion- (mkVersion- [2,- 7])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "use-pkg-config"))`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS Windows)`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (OS OpenBSD)`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = ["crypto",- "ssl"],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = ["pq"],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = ["libpq"],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [PkgconfigDependency- (PkgconfigName- "libpq")- (PcOrLaterVersion- (PkgconfigVersion- "9.3h"))],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 3]))- (EarlierVersion (mkVersion [4, 13])))- mainLibSet,- Dependency- (PackageName "bytestring")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 9, 1, 0]))- (EarlierVersion (mkVersion [0, 11])))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Database.PostgreSQL.LibPQ",- ModuleName- "Database.PostgreSQL.LibPQ.Internal"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [ExeDependency- (PackageName- "hsc2hs")- (UnqualComponentName- "hsc2hs")- (OrLaterVersion- (mkVersion- [0]))],- buildTools = [],- buildable = True,- cSources = ["cbits/noticehandlers.c"],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["src"],- includeDirs = ["cbits"],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor ["-Wall"] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4, 3]))- (EarlierVersion- (mkVersion- [4,- 13])))- mainLibSet,- Dependency- (PackageName- "bytestring")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 9,- 1,- 0]))- (EarlierVersion- (mkVersion- [0,- 11])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [MkPackageFlag- {flagDefault = False,- flagDescription = "",- flagManual = True,- flagName = FlagName "use-pkg-config"}],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Grant Monroe, Leon P Smith, Joey Adams",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Custom,- category = "Database",- copyright = concat- ["(c) 2010 Grant Monroe\n", "(c) 2011 Leon P Smith"],- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["This is a binding to libpq: the C application\n",- "programmer's interface to PostgreSQL. libpq is a\n",- "set of library functions that allow client\n",- "programs to pass queries to the PostgreSQL\n",- "backend server and to receive the results of\n",- "these queries."],- executables = [],- extraDocFiles = [],- extraSrcFiles = ["cbits/noticehandlers.h", "CHANGELOG.md"],- extraTmpFiles = [],- foreignLibs = [],- homepage = "https://github.com/phadej/postgresql-libpq",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Left- (License (ELicense (ELicenseId BSD_3_Clause) Nothing)),- maintainer = "Oleg Grenrus <oleg.grenrus@iki.fi>",- package = PackageIdentifier- {pkgName = PackageName "postgresql-libpq",- pkgVersion = mkVersion [0, 9, 4, 2]},- pkgUrl = "",- setupBuildInfo = Just- SetupBuildInfo- {defaultSetupDepends = False,- setupDepends = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion [4, 3]))- (EarlierVersion- (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "Cabal")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion [1, 10]))- (EarlierVersion- (mkVersion [2, 5])))- mainLibSet]},- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "low-level binding to libpq",- testSuites = [],- testedWith = [_×_ GHC (ThisVersion (mkVersion [7, 0, 4])),- _×_ GHC (ThisVersion (mkVersion [7, 2, 2])),- _×_ GHC (ThisVersion (mkVersion [7, 4, 2])),- _×_ GHC (ThisVersion (mkVersion [7, 6, 3])),- _×_ GHC (ThisVersion (mkVersion [7, 8, 4])),- _×_ GHC (ThisVersion (mkVersion [7, 10, 3])),- _×_ GHC (ThisVersion (mkVersion [8, 0, 2])),- _×_ GHC (ThisVersion (mkVersion [8, 2, 2])),- _×_ GHC (ThisVersion (mkVersion [8, 4, 3])),- _×_ GHC (ThisVersion (mkVersion [8, 6, 1]))]}}
− tests/ParserTests/regressions/libpq2.format
@@ -1,74 +0,0 @@-cabal-version: 3.0-name: postgresql-libpq-version: 0.9.4.2-license: BSD-3-Clause-license-file: LICENSE-copyright:- (c) 2010 Grant Monroe- (c) 2011 Leon P Smith--maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>-author: Grant Monroe, Leon P Smith, Joey Adams-tested-with:- ghc ==7.0.4 ghc ==7.2.2 ghc ==7.4.2 ghc ==7.6.3 ghc ==7.8.4- ghc ==7.10.3 ghc ==8.0.2 ghc ==8.2.2 ghc ==8.4.3 ghc ==8.6.1--homepage: https://github.com/phadej/postgresql-libpq-synopsis: low-level binding to libpq-description:- This is a binding to libpq: the C application- programmer's interface to PostgreSQL. libpq is a- set of library functions that allow client- programs to pass queries to the PostgreSQL- backend server and to receive the results of- these queries.--category: Database-build-type: Custom-extra-source-files:- cbits/noticehandlers.h- CHANGELOG.md--custom-setup- setup-depends:- base >=4.3 && <5,- Cabal >=1.10 && <2.5--flag use-pkg-config- default: False- manual: True--library- exposed-modules:- Database.PostgreSQL.LibPQ- Database.PostgreSQL.LibPQ.Internal-- build-tool-depends: hsc2hs:hsc2hs- c-sources: cbits/noticehandlers.c- hs-source-dirs: src- include-dirs: cbits- ghc-options: -Wall- build-depends:- base >=4.3 && <4.13,- bytestring >=0.9.1.0 && <0.11-- if !os(windows)- build-depends: unix >=2.4.2.0 && <2.8-- if os(windows)- build-depends: Win32 >=2.2.0.2 && <2.7-- if flag(use-pkg-config)- pkgconfig-depends: libpq >=9.3h-- else- if os(windows)- extra-libraries: libpq-- else- extra-libraries: pq-- if os(openbsd)- extra-libraries:- crypto- ssl
− tests/ParserTests/regressions/mixin-1.cabal
@@ -1,11 +0,0 @@-cabal-version: 2.0-name: mixin-version: 0-build-type: Simple--executable str-example- main-is: Main.hs- build-depends: base, str-string, str-bytestring- mixins: str-string (Str as Str.String),- str-bytestring (Str as Str.ByteString)- hs-source-dirs: str-example
− tests/ParserTests/regressions/mixin-1.expr
@@ -1,147 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "str-example")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "str-string")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "str-bytestring")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["str-example"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Str")- (ModuleName- "Str.String")],- includeRequiresRn = DefaultRenaming},- mixinLibraryName = LMainLibName,- mixinPackageName = PackageName- "str-string"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Str")- (ModuleName- "Str.ByteString")],- includeRequiresRn = DefaultRenaming},- mixinLibraryName = LMainLibName,- mixinPackageName = PackageName- "str-bytestring"}],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "str-string")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "str-bytestring")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "str-example",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}}],- condForeignLibs = [],- condLibrary = Nothing,- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "mixin", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/mixin-1.format
@@ -1,16 +0,0 @@-cabal-version: 2.0-name: mixin-version: 0-build-type: Simple--executable str-example- main-is: Main.hs- hs-source-dirs: str-example- build-depends:- base,- str-string,- str-bytestring-- mixins:- str-string (Str as Str.String),- str-bytestring (Str as Str.ByteString)
− tests/ParserTests/regressions/mixin-2.cabal
@@ -1,13 +0,0 @@-cabal-version: 3.0-name: mixin-version: 0---- mixin field:--- in 2.2 we got leading/trailing commas--- in 3.0 we got lax space parsing-executable str-example- main-is: Main.hs- build-depends: base, str-string, str-bytestring- mixins: str-string ( Str as Str.String ),- str-bytestring ( Str as Str.ByteString ),- hs-source-dirs: str-example
− tests/ParserTests/regressions/mixin-2.expr
@@ -1,147 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "str-example")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "str-string")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "str-bytestring")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["str-example"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Str")- (ModuleName- "Str.String")],- includeRequiresRn = DefaultRenaming},- mixinLibraryName = LMainLibName,- mixinPackageName = PackageName- "str-string"},- Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = ModuleRenaming- [_×_- (ModuleName- "Str")- (ModuleName- "Str.ByteString")],- includeRequiresRn = DefaultRenaming},- mixinLibraryName = LMainLibName,- mixinPackageName = PackageName- "str-bytestring"}],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "str-string")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "str-bytestring")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "str-example",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}}],- condForeignLibs = [],- condLibrary = Nothing,- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "mixin", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/mixin-2.format
@@ -1,15 +0,0 @@-cabal-version: 3.0-name: mixin-version: 0--executable str-example- main-is: Main.hs- hs-source-dirs: str-example- build-depends:- base,- str-string,- str-bytestring-- mixins:- str-string (Str as Str.String),- str-bytestring (Str as Str.ByteString)
− tests/ParserTests/regressions/mixin-3.cabal
@@ -1,12 +0,0 @@-cabal-version: 3.0-name: mixin-version: 0---- mixin field:--- in 2.2 we got leading/trailing commas--- in 3.0 we got lax space parsing-executable str-example- main-is: Main.hs- build-depends: base, str-string, str-bytestring- mixins: str hiding ( Foo )- hs-source-dirs: str-example
− tests/ParserTests/regressions/mixin-3.expr
@@ -1,132 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "str-example")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "str-string")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "str-bytestring")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["str-example"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [Mixin- {mixinIncludeRenaming = IncludeRenaming- {includeProvidesRn = HidingRenaming- [ModuleName- "Foo"],- includeRequiresRn = DefaultRenaming},- mixinLibraryName = LMainLibName,- mixinPackageName = PackageName- "str"}],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "str-string")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "str-bytestring")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "str-example",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}}],- condForeignLibs = [],- condLibrary = Nothing,- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "mixin", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/mixin-3.format
@@ -1,13 +0,0 @@-cabal-version: 3.0-name: mixin-version: 0--executable str-example- main-is: Main.hs- hs-source-dirs: str-example- build-depends:- base,- str-string,- str-bytestring-- mixins: str hiding (Foo)
− tests/ParserTests/regressions/monad-param.cabal
@@ -1,25 +0,0 @@-name: monad-param-category: Control-version: 0.0.1-synopsis: Parameterized monads-description: Implements parameterized monads by overloading the monad sugar with more liberal types.-stability: alpha-author: Edward Kmett <ekmett@gmail.com>-maintainer: Edward Kmett <ekmett@gmail.com>-copyright: Copyright (C) 2006-2007, Edward Kmett-homepage: http://comonad.com/haskell/monad-param/dist/doc/html/Control-Monad-Parameterized.html-package-url: http://comonad.com/haskell/monad-param-build-depends: base -any, mtl -any, stm -any-cabal-version: -any-license: BSD3-license-file: LICENSE-buildable: True-extensions: MultiParamTypeClasses- FunctionalDependencies- OverlappingInstances- UndecidableInstances- EmptyDataDecls- NoImplicitPrelude-exposed-modules: Control.Monad.Parameterized-ghc-options: -funbox-strict-fields -threaded -fasm-hs-source-dirs: src
− tests/ParserTests/regressions/monad-param.expr
@@ -1,142 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "mtl")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "stm")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Control.Monad.Parameterized"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [EnableExtension- MultiParamTypeClasses,- EnableExtension- FunctionalDependencies,- EnableExtension- OverlappingInstances,- EnableExtension- UndecidableInstances,- EnableExtension- EmptyDataDecls,- DisableExtension- ImplicitPrelude],- options = PerCompilerFlavor- ["-funbox-strict-fields",- "-threaded",- "-fasm"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "mtl")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "stm")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Edward Kmett <ekmett@gmail.com>",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "Control",- copyright = "Copyright (C) 2006-2007, Edward Kmett",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "Implements parameterized monads by overloading the monad sugar with more liberal types.",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "http://comonad.com/haskell/monad-param/dist/doc/html/Control-Monad-Parameterized.html",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Right BSD3,- maintainer = "Edward Kmett <ekmett@gmail.com>",- package = PackageIdentifier- {pkgName = PackageName "monad-param",- pkgVersion = mkVersion [0, 0, 1]},- pkgUrl = "http://comonad.com/haskell/monad-param",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV1_0,- stability = "alpha",- subLibraries = [],- synopsis = "Parameterized monads",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/monad-param.format
@@ -1,31 +0,0 @@-monad-param.cabal:19:3: Tabs used as indentation at 19:3, 20:3-name: monad-param-version: 0.0.1-license: BSD3-license-file: LICENSE-copyright: Copyright (C) 2006-2007, Edward Kmett-maintainer: Edward Kmett <ekmett@gmail.com>-author: Edward Kmett <ekmett@gmail.com>-stability: alpha-homepage:- http://comonad.com/haskell/monad-param/dist/doc/html/Control-Monad-Parameterized.html--package-url: http://comonad.com/haskell/monad-param-synopsis: Parameterized monads-description:- Implements parameterized monads by overloading the monad sugar with more liberal types.--category: Control--library- exposed-modules: Control.Monad.Parameterized- hs-source-dirs: src- extensions:- MultiParamTypeClasses FunctionalDependencies OverlappingInstances- UndecidableInstances EmptyDataDecls NoImplicitPrelude-- ghc-options: -funbox-strict-fields -threaded -fasm- build-depends:- base,- mtl,- stm
− tests/ParserTests/regressions/multiple-libs-2.cabal
@@ -1,17 +0,0 @@-cabal-version: 2.0-name: multiple-libs-version: 0--synopsis: visible flag only since 3.0-build-type: Simple--library- default-language: Haskell2010- exposed-modules: ElseIf- build-depends: base--library public- default-language: Haskell2010- exposed-modules: ElseIf2- build-depends: base- visibility: public
− tests/ParserTests/regressions/multiple-libs-2.check
@@ -1,6 +0,0 @@-multiple-libs-2.cabal:17:3: The field "visibility" is available only since the Cabal specification version 3.0. This field will be ignored.-No 'category' field.-No 'maintainer' field.-No 'description' field.-The 'license' field is missing or is NONE.-The dependency 'build-depends: base' does not specify an upper bound on the version number. Each major release of the 'base' package changes the API in various ways and most packages will need some changes to compile with it. The recommended practice is to specify an upper bound on the version of the 'base' package. This ensures your package will continue to build when a 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 4.5 and 4.6 then use 'build-depends: base >= 4.5 && < 4.7'.
− tests/ParserTests/regressions/multiple-libs-2.expr
@@ -1,172 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [_×_- (UnqualComponentName "public")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf2"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LSubLibName (UnqualComponentName "public"),- libVisibility = LibraryVisibilityPrivate,- reexportedModules = [],- signatures = []}}],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "multiple-libs",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_0,- stability = "",- subLibraries = [],- synopsis = "visible flag only since 3.0",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/multiple-libs-2.format
@@ -1,16 +0,0 @@-multiple-libs-2.cabal:17:3: The field "visibility" is available only since the Cabal specification version 3.0. This field will be ignored.-cabal-version: 2.0-name: multiple-libs-version: 0-synopsis: visible flag only since 3.0-build-type: Simple--library- exposed-modules: ElseIf- default-language: Haskell2010- build-depends: base--library public- exposed-modules: ElseIf2- default-language: Haskell2010- build-depends: base
− tests/ParserTests/regressions/noVersion.cabal
@@ -1,11 +0,0 @@-name: noVersion-version: 0-synopsis: -none in build-depends-build-type: Simple-cabal-version: 1.22--library- default-language: Haskell2010- exposed-modules: ElseIf-- build-depends: bad-package -none
− tests/ParserTests/regressions/noVersion.expr
@@ -1,105 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "bad-package")- (EarlierVersion (mkVersion [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "ElseIf"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "bad-package")- (EarlierVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "noVersion",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV1_22,- stability = "",- subLibraries = [],- synopsis = "-none in build-depends",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/noVersion.format
@@ -1,10 +0,0 @@-cabal-version: 1.22-name: noVersion-version: 0-synopsis: -none in build-depends-build-type: Simple--library- exposed-modules: ElseIf- default-language: Haskell2010- build-depends: bad-package <0
− tests/ParserTests/regressions/nothing-unicode.cabal
@@ -1,21 +0,0 @@-name: 無-version: 0-synopsis: The canonical non-package 無-build-type: Simple-cabal-version: >=1.10-x-無: 無--source-repository head- Type: git- Location: https://github.com/hvr/-.git--flag 無- description: 無--library- default-language: Haskell2010-- exposed-modules: Ω-- if !flag(無)- buildable:False
− tests/ParserTests/regressions/nothing-unicode.check
@@ -1,6 +0,0 @@-No 'category' field.-No 'maintainer' field.-No 'description' field.-The 'license' field is missing or is NONE.-Suspicious flag names: 無. To avoid ambiguity in command line interfaces, flag shouldn't start with a dash. Also for better compatibility, flag names shouldn't contain non-ascii characters.-Non ascii custom fields: x-無. For better compatibility, custom field names shouldn't contain non-ascii characters.
− tests/ParserTests/regressions/nothing-unicode.expr
@@ -1,170 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (PackageFlag (FlagName "\\28961")))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = False,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [ModuleName "\937"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [MkPackageFlag- {flagDefault = True,- flagDescription = "\28961",- flagManual = False,- flagName = FlagName "\28961"}],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [_×_ "x-\28961" "\28961"],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "\28961", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just "https://github.com/hvr/-.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_10,- stability = "",- subLibraries = [],- synopsis = "The canonical non-package \28961",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/nothing-unicode.format
@@ -1,20 +0,0 @@-cabal-version: >=1.10-name: 無-version: 0-synopsis: The canonical non-package 無-x-無: 無-build-type: Simple--source-repository head- type: git- location: https://github.com/hvr/-.git--flag 無- description: 無--library- exposed-modules: Ω- default-language: Haskell2010-- if !flag(無)- buildable: False
− tests/ParserTests/regressions/pre-1.6-glob.cabal
@@ -1,17 +0,0 @@-cabal-version: >= 1.4-name: pre-1dot6-glob-version: 0-license: BSD3-license-file: pre-1.6-glob.cabal-synopsis: no-description: none-build-type: Simple-category: Test-maintainer: none--extra-source-files:- foo/*.hs--library- exposed-modules:- Foo
− tests/ParserTests/regressions/pre-1.6-glob.check
@@ -1,1 +0,0 @@-In the 'extra-source-files' field: invalid file glob 'foo/*.hs'. Using star wildcards requires 'cabal-version: >= 1.6'. Alternatively if you require compatibility with earlier Cabal versions then list all the files explicitly.
− tests/ParserTests/regressions/pre-2.4-globstar.cabal
@@ -1,19 +0,0 @@-cabal-version: 2.2-name: pre-3dot0-globstar-version: 0-extra-source-files:- foo/**/*.hs-extra-doc-files:- foo/**/*.html-data-files:- foo/**/*.dat-license: BSD-3-Clause-synopsis: no-description: none-category: Test-maintainer: none--library- default-language: Haskell2010- exposed-modules:- Foo
− tests/ParserTests/regressions/pre-2.4-globstar.check
@@ -1,3 +0,0 @@-In the 'data-files' field: invalid file glob 'foo/**/*.dat'. Using the double-star syntax requires 'cabal-version: 2.4' or greater. Alternatively, for compatibility with earlier Cabal versions, list the included directories explicitly.-In the 'extra-source-files' field: invalid file glob 'foo/**/*.hs'. Using the double-star syntax requires 'cabal-version: 2.4' or greater. Alternatively, for compatibility with earlier Cabal versions, list the included directories explicitly.-In the 'extra-doc-files' field: invalid file glob 'foo/**/*.html'. Using the double-star syntax requires 'cabal-version: 2.4' or greater. Alternatively, for compatibility with earlier Cabal versions, list the included directories explicitly.
− tests/ParserTests/regressions/public-multilib-1.cabal
@@ -1,17 +0,0 @@-cabal-version: 3.0-name: public-multilib1-version: 0-synopsis: public-multilibs are not polished enough for Hackage-category: Tests-license: MIT--library- default-language: Haskell2010- build-depends: base ^>=4.14, internal- exposed-modules: Foo--library internal- default-language: Haskell2010- build-depends: base ^>=4.14- visibility: public- exposed-modules: Bar
− tests/ParserTests/regressions/public-multilib-1.check
@@ -1,3 +0,0 @@-public-multilib-1.cabal:16:27: visibility is experimental feature (issue #5660)-No 'maintainer' field.-No 'description' field.
− tests/ParserTests/regressions/public-multilib-2.cabal
@@ -1,14 +0,0 @@-cabal-version: 3.0-name: public-multilib1-version: 0-synopsis: public-multilibs are not polished enough for Hackage-category: Tests-license: MIT--library- default-language: Haskell2010- build-depends:- , base ^>=4.14- , somelib:internal-- exposed-modules: Foo
− tests/ParserTests/regressions/public-multilib-2.check
@@ -1,3 +0,0 @@-public-multilib-2.cabal:12:15: colon specifier is experimental feature (issue #5660)-No 'maintainer' field.-No 'description' field.
− tests/ParserTests/regressions/shake.cabal
@@ -1,405 +0,0 @@-cabal-version: 1.18-build-type: Simple-name: shake-version: 0.15.11-license: BSD3-license-file: LICENSE-category: Development, Shake-author: Neil Mitchell <ndmitchell@gmail.com>-maintainer: Neil Mitchell <ndmitchell@gmail.com>-copyright: Neil Mitchell 2011-2017-synopsis: Build system library, like Make, but more accurate dependencies.-description:- Shake is a Haskell library for writing build systems - designed as a- replacement for @make@. See "Development.Shake" for an introduction,- including an example. Further examples are included in the Cabal tarball,- under the @Examples@ directory. The homepage contains links to a user- manual, an academic paper and further information:- <http://shakebuild.com>- .- To use Shake the user writes a Haskell program- that imports "Development.Shake", defines some build rules, and calls- the 'Development.Shake.shakeArgs' function. Thanks to do notation and infix- operators, a simple Shake build system- is not too dissimilar from a simple Makefile. However, as build systems- get more complex, Shake is able to take advantage of the excellent- abstraction facilities offered by Haskell and easily support much larger- projects. The Shake library provides all the standard features available in other- build systems, including automatic parallelism and minimal rebuilds.- Shake also provides more accurate dependency tracking, including seamless- support for generated files, and dependencies on system information- (e.g. compiler version).-homepage: http://shakebuild.com-bug-reports: https://github.com/ndmitchell/shake/issues-tested-with: GHC==8.0.1, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2-extra-doc-files:- CHANGES.txt- README.md-extra-source-files:- src/Test/C/constants.c- src/Test/C/constants.h- src/Test/C/main.c- src/Test/MakeTutor/Makefile- src/Test/MakeTutor/hellofunc.c- src/Test/MakeTutor/hellomake.c- src/Test/MakeTutor/hellomake.h- src/Test/Tar/list.txt- src/Test/Ninja/*.ninja- src/Test/Ninja/subdir/*.ninja- src/Test/Ninja/*.output- src/Test/Progress/*.prog- src/Test/Tup/hello.c- src/Test/Tup/root.cfg- src/Test/Tup/newmath/root.cfg- src/Test/Tup/newmath/square.c- src/Test/Tup/newmath/square.h- src/Paths.hs- docs/Manual.md- docs/shake-progress.png--data-files:- html/viz.js- html/profile.html- html/progress.html- html/shake.js- docs/manual/build.bat- docs/manual/Build.hs- docs/manual/build.sh- docs/manual/constants.c- docs/manual/constants.h- docs/manual/main.c--source-repository head- type: git- location: https://github.com/ndmitchell/shake.git--flag portable- default: False- manual: True- description: Obtain FileTime using portable functions--library- default-language: Haskell2010- -- dot directory on own row- hs-source-dirs:- .- src- build-depends:- base >= 4.5,- directory,- hashable >= 1.1.2.3,- binary,- filepath,- process >= 1.1,- unordered-containers >= 0.2.1,- bytestring,- utf8-string >= 0.3,- time,- random,- js-jquery,- js-flot,- transformers >= 0.2,- extra >= 1.4.8,- deepseq >= 1.1-- if flag(portable)- cpp-options: -DPORTABLE- if impl(ghc < 7.6)- build-depends: old-time- else- if !os(windows)- build-depends: unix >= 2.5.1- if !os(windows)- build-depends: unix-- exposed-modules:- Development.Shake- Development.Shake.Classes- Development.Shake.Command- Development.Shake.Config- Development.Shake.FilePath- Development.Shake.Forward- Development.Shake.Rule- Development.Shake.Util-- other-modules:- Development.Ninja.Env- Development.Ninja.Lexer- Development.Ninja.Parse- Development.Ninja.Type- Development.Shake.Args- Development.Shake.ByteString- Development.Shake.Core- Development.Shake.CmdOption- Development.Shake.Database- Development.Shake.Demo- Development.Shake.Derived- Development.Shake.Errors- Development.Shake.FileInfo- Development.Shake.FilePattern- Development.Shake.Monad- Development.Shake.Pool- Development.Shake.Profile- Development.Shake.Progress- Development.Shake.Resource- Development.Shake.Rules.Directory- Development.Shake.Rules.File- Development.Shake.Rules.Files- Development.Shake.Rules.Oracle- Development.Shake.Rules.OrderOnly- Development.Shake.Rules.Rerun- Development.Shake.Shake- Development.Shake.Special- Development.Shake.Storage- Development.Shake.Types- Development.Shake.Value- General.Bilist- General.Binary- General.Cleanup- General.Concurrent- General.Extra- General.FileLock- General.Intern- General.Process- General.String- General.Template- General.Timing- Paths_shake---executable shake- default-language: Haskell2010- hs-source-dirs: src- ghc-options: -main-is Run.main- main-is: Run.hs- ghc-options: -rtsopts- -- GHC bug 7646 means -threaded causes errors- if impl(ghc >= 7.8)- ghc-options: -threaded "-with-rtsopts=-I0 -qg -qb"- build-depends:- base == 4.*,- directory,- hashable >= 1.1.2.3,- binary,- filepath,- process >= 1.1,- unordered-containers >= 0.2.1,- bytestring,- utf8-string >= 0.3,- time,- random,- js-jquery,- js-flot,- transformers >= 0.2,- extra >= 1.4.8,- deepseq >= 1.1,- primitive-- if flag(portable)- cpp-options: -DPORTABLE- if impl(ghc < 7.6)- build-depends: old-time- else- if !os(windows)- build-depends: unix >= 2.5.1- if !os(windows)- build-depends: unix-- other-modules:- Development.Make.All- Development.Make.Env- Development.Make.Parse- Development.Make.Rules- Development.Make.Type- Development.Ninja.All- Development.Ninja.Env- Development.Ninja.Lexer- Development.Ninja.Parse- Development.Ninja.Type- Development.Shake- Development.Shake.Args- Development.Shake.ByteString- Development.Shake.Classes- Development.Shake.CmdOption- Development.Shake.Command- Development.Shake.Core- Development.Shake.Database- Development.Shake.Demo- Development.Shake.Derived- Development.Shake.Errors- Development.Shake.FileInfo- Development.Shake.FilePath- Development.Shake.FilePattern- Development.Shake.Forward- Development.Shake.Monad- Development.Shake.Pool- Development.Shake.Profile- Development.Shake.Progress- Development.Shake.Resource- Development.Shake.Rule- Development.Shake.Rules.Directory- Development.Shake.Rules.File- Development.Shake.Rules.Files- Development.Shake.Rules.Oracle- Development.Shake.Rules.OrderOnly- Development.Shake.Rules.Rerun- Development.Shake.Shake- Development.Shake.Special- Development.Shake.Storage- Development.Shake.Types- Development.Shake.Value- General.Bilist- General.Binary- General.Cleanup- General.Concurrent- General.Extra- General.FileLock- General.Intern- General.Process- General.String- General.Template- General.Timing- Paths_shake- Run---test-suite shake-test- default-language: Haskell2010- type: exitcode-stdio-1.0- main-is: Test.hs- hs-source-dirs: src-- ghc-options: -main-is Test.main -rtsopts- if impl(ghc >= 7.6)- -- space leak introduced by -O1 in 7.4, see #445- ghc-options: -with-rtsopts=-K1K- if impl(ghc >= 7.8)- -- GHC bug 7646 (fixed in 7.8) means -threaded causes errors- ghc-options: -threaded-- build-depends:- base == 4.*,- directory,- hashable >= 1.1.2.3,- binary,- filepath,- process >= 1.1,- unordered-containers >= 0.2.1,- bytestring,- utf8-string >= 0.3,- time,- random,- js-jquery,- js-flot,- transformers >= 0.2,- deepseq >= 1.1,- extra >= 1.4.8,- QuickCheck >= 2.0-- if flag(portable)- cpp-options: -DPORTABLE- if impl(ghc < 7.6)- build-depends: old-time- else- if !os(windows)- build-depends: unix >= 2.5.1- if !os(windows)- build-depends: unix-- other-modules:- Development.Make.All- Development.Make.Env- Development.Make.Parse- Development.Make.Rules- Development.Make.Type- Development.Ninja.All- Development.Ninja.Env- Development.Ninja.Lexer- Development.Ninja.Parse- Development.Ninja.Type- Development.Shake- Development.Shake.Args- Development.Shake.ByteString- Development.Shake.Classes- Development.Shake.CmdOption- Development.Shake.Command- Development.Shake.Config- Development.Shake.Core- Development.Shake.Database- Development.Shake.Demo- Development.Shake.Derived- Development.Shake.Errors- Development.Shake.FileInfo- Development.Shake.FilePath- Development.Shake.FilePattern- Development.Shake.Forward- Development.Shake.Monad- Development.Shake.Pool- Development.Shake.Profile- Development.Shake.Progress- Development.Shake.Resource- Development.Shake.Rule- Development.Shake.Rules.Directory- Development.Shake.Rules.File- Development.Shake.Rules.Files- Development.Shake.Rules.Oracle- Development.Shake.Rules.OrderOnly- Development.Shake.Rules.Rerun- Development.Shake.Shake- Development.Shake.Special- Development.Shake.Storage- Development.Shake.Types- Development.Shake.Util- Development.Shake.Value- General.Bilist- General.Binary- General.Cleanup- General.Concurrent- General.Extra- General.FileLock- General.Intern- General.Process- General.String- General.Template- General.Timing- Paths_shake- Run- Test.Assume- Test.Basic- Test.Benchmark- Test.C- Test.Cache- Test.Command- Test.Config- Test.Digest- Test.Directory- Test.Docs- Test.Errors- Test.FileLock- Test.FilePath- Test.FilePattern- Test.Files- Test.Forward- Test.Journal- Test.Lint- Test.Live- Test.Makefile- Test.Manual- Test.Match- Test.Monad- Test.Ninja- Test.Oracle- Test.OrderOnly- Test.Parallel- Test.Pool- Test.Progress- Test.Random- Test.Resources- Test.Self- Test.Tar- Test.Tup- Test.Type- Test.Unicode- Test.Util- Test.Verbosity- Test.Version
− tests/ParserTests/regressions/shake.expr
@@ -1,2506 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "shake")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (Impl GHC (OrLaterVersion (mkVersion [7,8])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-threaded",- "-with-rtsopts=-I0 -qg -qb"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- exeName = UnqualComponentName- "shake",- exeScope = ExecutablePublic,- modulePath = ""}}},- CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "portable"))`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [2,- 5,- 1]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [2,- 5,- 1]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName- "shake",- exeScope = ExecutablePublic,- modulePath = ""}}}],- condTreeConstraints = [],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- exeName = UnqualComponentName- "shake",- exeScope = ExecutablePublic,- modulePath = ""}},- condBranchIfTrue = CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (Impl GHC (EarlierVersion (mkVersion [7,6])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "old-time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "old-time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName- "shake",- exeScope = ExecutablePublic,- modulePath = ""}}}],- condTreeConstraints = [],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = ["-DPORTABLE"],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- exeName = UnqualComponentName- "shake",- exeScope = ExecutablePublic,- modulePath = ""}}},- CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName- "shake",- exeScope = ExecutablePublic,- modulePath = ""}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4]))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "directory")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "hashable")- (OrLaterVersion (mkVersion [1, 1, 2, 3]))- mainLibSet,- Dependency- (PackageName "binary")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "filepath")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "process")- (OrLaterVersion (mkVersion [1, 1]))- mainLibSet,- Dependency- (PackageName "unordered-containers")- (OrLaterVersion (mkVersion [0, 2, 1]))- mainLibSet,- Dependency- (PackageName "bytestring")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "utf8-string")- (OrLaterVersion (mkVersion [0, 3]))- mainLibSet,- Dependency- (PackageName "time")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "random")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "js-jquery")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "js-flot")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "transformers")- (OrLaterVersion (mkVersion [0, 2]))- mainLibSet,- Dependency- (PackageName "extra")- (OrLaterVersion (mkVersion [1, 4, 8]))- mainLibSet,- Dependency- (PackageName "deepseq")- (OrLaterVersion (mkVersion [1, 1]))- mainLibSet,- Dependency- (PackageName "primitive")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-main-is",- "Run.main",- "-rtsopts"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "Development.Make.All",- ModuleName- "Development.Make.Env",- ModuleName- "Development.Make.Parse",- ModuleName- "Development.Make.Rules",- ModuleName- "Development.Make.Type",- ModuleName- "Development.Ninja.All",- ModuleName- "Development.Ninja.Env",- ModuleName- "Development.Ninja.Lexer",- ModuleName- "Development.Ninja.Parse",- ModuleName- "Development.Ninja.Type",- ModuleName- "Development.Shake",- ModuleName- "Development.Shake.Args",- ModuleName- "Development.Shake.ByteString",- ModuleName- "Development.Shake.Classes",- ModuleName- "Development.Shake.CmdOption",- ModuleName- "Development.Shake.Command",- ModuleName- "Development.Shake.Core",- ModuleName- "Development.Shake.Database",- ModuleName- "Development.Shake.Demo",- ModuleName- "Development.Shake.Derived",- ModuleName- "Development.Shake.Errors",- ModuleName- "Development.Shake.FileInfo",- ModuleName- "Development.Shake.FilePath",- ModuleName- "Development.Shake.FilePattern",- ModuleName- "Development.Shake.Forward",- ModuleName- "Development.Shake.Monad",- ModuleName- "Development.Shake.Pool",- ModuleName- "Development.Shake.Profile",- ModuleName- "Development.Shake.Progress",- ModuleName- "Development.Shake.Resource",- ModuleName- "Development.Shake.Rule",- ModuleName- "Development.Shake.Rules.Directory",- ModuleName- "Development.Shake.Rules.File",- ModuleName- "Development.Shake.Rules.Files",- ModuleName- "Development.Shake.Rules.Oracle",- ModuleName- "Development.Shake.Rules.OrderOnly",- ModuleName- "Development.Shake.Rules.Rerun",- ModuleName- "Development.Shake.Shake",- ModuleName- "Development.Shake.Special",- ModuleName- "Development.Shake.Storage",- ModuleName- "Development.Shake.Types",- ModuleName- "Development.Shake.Value",- ModuleName- "General.Bilist",- ModuleName- "General.Binary",- ModuleName- "General.Cleanup",- ModuleName- "General.Concurrent",- ModuleName- "General.Extra",- ModuleName- "General.FileLock",- ModuleName- "General.Intern",- ModuleName- "General.Process",- ModuleName- "General.String",- ModuleName- "General.Template",- ModuleName- "General.Timing",- ModuleName- "Paths_shake",- ModuleName "Run"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4]))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "directory")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "hashable")- (OrLaterVersion- (mkVersion- [1,- 1,- 2,- 3]))- mainLibSet,- Dependency- (PackageName- "binary")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "filepath")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "process")- (OrLaterVersion- (mkVersion- [1, 1]))- mainLibSet,- Dependency- (PackageName- "unordered-containers")- (OrLaterVersion- (mkVersion- [0,- 2,- 1]))- mainLibSet,- Dependency- (PackageName- "bytestring")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "utf8-string")- (OrLaterVersion- (mkVersion- [0, 3]))- mainLibSet,- Dependency- (PackageName- "time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "random")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "js-jquery")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "js-flot")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "transformers")- (OrLaterVersion- (mkVersion- [0, 2]))- mainLibSet,- Dependency- (PackageName- "extra")- (OrLaterVersion- (mkVersion- [1,- 4,- 8]))- mainLibSet,- Dependency- (PackageName- "deepseq")- (OrLaterVersion- (mkVersion- [1, 1]))- mainLibSet,- Dependency- (PackageName- "primitive")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName "shake",- exeScope = ExecutablePublic,- modulePath = "Run.hs"}}],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "portable"))`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [2,- 5,- 1]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [2,- 5,- 1]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condBranchIfTrue = CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (Impl GHC (EarlierVersion (mkVersion [7,6])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "old-time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "old-time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = ["-DPORTABLE"],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}},- CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [4, 5]))- mainLibSet,- Dependency- (PackageName "directory")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "hashable")- (OrLaterVersion (mkVersion [1, 1, 2, 3]))- mainLibSet,- Dependency- (PackageName "binary")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "filepath")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "process")- (OrLaterVersion (mkVersion [1, 1]))- mainLibSet,- Dependency- (PackageName "unordered-containers")- (OrLaterVersion (mkVersion [0, 2, 1]))- mainLibSet,- Dependency- (PackageName "bytestring")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "utf8-string")- (OrLaterVersion (mkVersion [0, 3]))- mainLibSet,- Dependency- (PackageName "time")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "random")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "js-jquery")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "js-flot")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "transformers")- (OrLaterVersion (mkVersion [0, 2]))- mainLibSet,- Dependency- (PackageName "extra")- (OrLaterVersion (mkVersion [1, 4, 8]))- mainLibSet,- Dependency- (PackageName "deepseq")- (OrLaterVersion (mkVersion [1, 1]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Development.Shake",- ModuleName "Development.Shake.Classes",- ModuleName "Development.Shake.Command",- ModuleName "Development.Shake.Config",- ModuleName "Development.Shake.FilePath",- ModuleName "Development.Shake.Forward",- ModuleName "Development.Shake.Rule",- ModuleName "Development.Shake.Util"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [".", "src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "Development.Ninja.Env",- ModuleName- "Development.Ninja.Lexer",- ModuleName- "Development.Ninja.Parse",- ModuleName- "Development.Ninja.Type",- ModuleName- "Development.Shake.Args",- ModuleName- "Development.Shake.ByteString",- ModuleName- "Development.Shake.Core",- ModuleName- "Development.Shake.CmdOption",- ModuleName- "Development.Shake.Database",- ModuleName- "Development.Shake.Demo",- ModuleName- "Development.Shake.Derived",- ModuleName- "Development.Shake.Errors",- ModuleName- "Development.Shake.FileInfo",- ModuleName- "Development.Shake.FilePattern",- ModuleName- "Development.Shake.Monad",- ModuleName- "Development.Shake.Pool",- ModuleName- "Development.Shake.Profile",- ModuleName- "Development.Shake.Progress",- ModuleName- "Development.Shake.Resource",- ModuleName- "Development.Shake.Rules.Directory",- ModuleName- "Development.Shake.Rules.File",- ModuleName- "Development.Shake.Rules.Files",- ModuleName- "Development.Shake.Rules.Oracle",- ModuleName- "Development.Shake.Rules.OrderOnly",- ModuleName- "Development.Shake.Rules.Rerun",- ModuleName- "Development.Shake.Shake",- ModuleName- "Development.Shake.Special",- ModuleName- "Development.Shake.Storage",- ModuleName- "Development.Shake.Types",- ModuleName- "Development.Shake.Value",- ModuleName- "General.Bilist",- ModuleName- "General.Binary",- ModuleName- "General.Cleanup",- ModuleName- "General.Concurrent",- ModuleName- "General.Extra",- ModuleName- "General.FileLock",- ModuleName- "General.Intern",- ModuleName- "General.Process",- ModuleName- "General.String",- ModuleName- "General.Template",- ModuleName- "General.Timing",- ModuleName "Paths_shake"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [4, 5]))- mainLibSet,- Dependency- (PackageName- "directory")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "hashable")- (OrLaterVersion- (mkVersion- [1,- 1,- 2,- 3]))- mainLibSet,- Dependency- (PackageName- "binary")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "filepath")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "process")- (OrLaterVersion- (mkVersion- [1, 1]))- mainLibSet,- Dependency- (PackageName- "unordered-containers")- (OrLaterVersion- (mkVersion- [0, 2, 1]))- mainLibSet,- Dependency- (PackageName- "bytestring")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "utf8-string")- (OrLaterVersion- (mkVersion- [0, 3]))- mainLibSet,- Dependency- (PackageName- "time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "random")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "js-jquery")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "js-flot")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "transformers")- (OrLaterVersion- (mkVersion- [0, 2]))- mainLibSet,- Dependency- (PackageName- "extra")- (OrLaterVersion- (mkVersion- [1, 4, 8]))- mainLibSet,- Dependency- (PackageName- "deepseq")- (OrLaterVersion- (mkVersion- [1, 1]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "shake-test")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (Impl GHC (OrLaterVersion (mkVersion [7,6])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-with-rtsopts=-K1K"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}},- CondBranch- {condBranchCondition = `Var (Impl GHC (OrLaterVersion (mkVersion [7,8])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-threaded"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}},- CondBranch- {condBranchCondition = `Var (PackageFlag (FlagName "portable"))`,- condBranchIfFalse = Just- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [2,- 5,- 1]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [2,- 5,- 1]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}},- condBranchIfTrue = CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (Impl GHC (EarlierVersion (mkVersion [7,6])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "old-time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "old-time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = ["-DPORTABLE"],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}},- CondBranch- {condBranchCondition = `CNot (Var (OS Windows))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- []- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [Dependency- (PackageName- "unix")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4]))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "directory")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "hashable")- (OrLaterVersion (mkVersion [1, 1, 2, 3]))- mainLibSet,- Dependency- (PackageName "binary")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "filepath")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "process")- (OrLaterVersion (mkVersion [1, 1]))- mainLibSet,- Dependency- (PackageName "unordered-containers")- (OrLaterVersion (mkVersion [0, 2, 1]))- mainLibSet,- Dependency- (PackageName "bytestring")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "utf8-string")- (OrLaterVersion (mkVersion [0, 3]))- mainLibSet,- Dependency- (PackageName "time")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "random")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "js-jquery")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "js-flot")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "transformers")- (OrLaterVersion (mkVersion [0, 2]))- mainLibSet,- Dependency- (PackageName "deepseq")- (OrLaterVersion (mkVersion [1, 1]))- mainLibSet,- Dependency- (PackageName "extra")- (OrLaterVersion (mkVersion [1, 4, 8]))- mainLibSet,- Dependency- (PackageName "QuickCheck")- (OrLaterVersion (mkVersion [2, 0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-main-is",- "Test.main",- "-rtsopts"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "Development.Make.All",- ModuleName- "Development.Make.Env",- ModuleName- "Development.Make.Parse",- ModuleName- "Development.Make.Rules",- ModuleName- "Development.Make.Type",- ModuleName- "Development.Ninja.All",- ModuleName- "Development.Ninja.Env",- ModuleName- "Development.Ninja.Lexer",- ModuleName- "Development.Ninja.Parse",- ModuleName- "Development.Ninja.Type",- ModuleName- "Development.Shake",- ModuleName- "Development.Shake.Args",- ModuleName- "Development.Shake.ByteString",- ModuleName- "Development.Shake.Classes",- ModuleName- "Development.Shake.CmdOption",- ModuleName- "Development.Shake.Command",- ModuleName- "Development.Shake.Config",- ModuleName- "Development.Shake.Core",- ModuleName- "Development.Shake.Database",- ModuleName- "Development.Shake.Demo",- ModuleName- "Development.Shake.Derived",- ModuleName- "Development.Shake.Errors",- ModuleName- "Development.Shake.FileInfo",- ModuleName- "Development.Shake.FilePath",- ModuleName- "Development.Shake.FilePattern",- ModuleName- "Development.Shake.Forward",- ModuleName- "Development.Shake.Monad",- ModuleName- "Development.Shake.Pool",- ModuleName- "Development.Shake.Profile",- ModuleName- "Development.Shake.Progress",- ModuleName- "Development.Shake.Resource",- ModuleName- "Development.Shake.Rule",- ModuleName- "Development.Shake.Rules.Directory",- ModuleName- "Development.Shake.Rules.File",- ModuleName- "Development.Shake.Rules.Files",- ModuleName- "Development.Shake.Rules.Oracle",- ModuleName- "Development.Shake.Rules.OrderOnly",- ModuleName- "Development.Shake.Rules.Rerun",- ModuleName- "Development.Shake.Shake",- ModuleName- "Development.Shake.Special",- ModuleName- "Development.Shake.Storage",- ModuleName- "Development.Shake.Types",- ModuleName- "Development.Shake.Util",- ModuleName- "Development.Shake.Value",- ModuleName- "General.Bilist",- ModuleName- "General.Binary",- ModuleName- "General.Cleanup",- ModuleName- "General.Concurrent",- ModuleName- "General.Extra",- ModuleName- "General.FileLock",- ModuleName- "General.Intern",- ModuleName- "General.Process",- ModuleName- "General.String",- ModuleName- "General.Template",- ModuleName- "General.Timing",- ModuleName- "Paths_shake",- ModuleName "Run",- ModuleName- "Test.Assume",- ModuleName- "Test.Basic",- ModuleName- "Test.Benchmark",- ModuleName "Test.C",- ModuleName- "Test.Cache",- ModuleName- "Test.Command",- ModuleName- "Test.Config",- ModuleName- "Test.Digest",- ModuleName- "Test.Directory",- ModuleName- "Test.Docs",- ModuleName- "Test.Errors",- ModuleName- "Test.FileLock",- ModuleName- "Test.FilePath",- ModuleName- "Test.FilePattern",- ModuleName- "Test.Files",- ModuleName- "Test.Forward",- ModuleName- "Test.Journal",- ModuleName- "Test.Lint",- ModuleName- "Test.Live",- ModuleName- "Test.Makefile",- ModuleName- "Test.Manual",- ModuleName- "Test.Match",- ModuleName- "Test.Monad",- ModuleName- "Test.Ninja",- ModuleName- "Test.Oracle",- ModuleName- "Test.OrderOnly",- ModuleName- "Test.Parallel",- ModuleName- "Test.Pool",- ModuleName- "Test.Progress",- ModuleName- "Test.Random",- ModuleName- "Test.Resources",- ModuleName- "Test.Self",- ModuleName- "Test.Tar",- ModuleName- "Test.Tup",- ModuleName- "Test.Type",- ModuleName- "Test.Unicode",- ModuleName- "Test.Util",- ModuleName- "Test.Verbosity",- ModuleName- "Test.Version"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4]))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "directory")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "hashable")- (OrLaterVersion- (mkVersion- [1,- 1,- 2,- 3]))- mainLibSet,- Dependency- (PackageName- "binary")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "filepath")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "process")- (OrLaterVersion- (mkVersion- [1,- 1]))- mainLibSet,- Dependency- (PackageName- "unordered-containers")- (OrLaterVersion- (mkVersion- [0,- 2,- 1]))- mainLibSet,- Dependency- (PackageName- "bytestring")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "utf8-string")- (OrLaterVersion- (mkVersion- [0,- 3]))- mainLibSet,- Dependency- (PackageName- "time")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "random")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "js-jquery")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "js-flot")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "transformers")- (OrLaterVersion- (mkVersion- [0,- 2]))- mainLibSet,- Dependency- (PackageName- "deepseq")- (OrLaterVersion- (mkVersion- [1,- 1]))- mainLibSet,- Dependency- (PackageName- "extra")- (OrLaterVersion- (mkVersion- [1,- 4,- 8]))- mainLibSet,- Dependency- (PackageName- "QuickCheck")- (OrLaterVersion- (mkVersion- [2,- 0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Test.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [MkPackageFlag- {flagDefault = False,- flagDescription = "Obtain FileTime using portable functions",- flagManual = True,- flagName = FlagName "portable"}],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Neil Mitchell <ndmitchell@gmail.com>",- benchmarks = [],- bugReports = "https://github.com/ndmitchell/shake/issues",- buildTypeRaw = Just Simple,- category = "Development, Shake",- copyright = "Neil Mitchell 2011-2017",- customFieldsPD = [],- dataDir = ".",- dataFiles = ["html/viz.js",- "html/profile.html",- "html/progress.html",- "html/shake.js",- "docs/manual/build.bat",- "docs/manual/Build.hs",- "docs/manual/build.sh",- "docs/manual/constants.c",- "docs/manual/constants.h",- "docs/manual/main.c"],- description = concat- ["Shake is a Haskell library for writing build systems - designed as a\n",- "replacement for @make@. See \"Development.Shake\" for an introduction,\n",- "including an example. Further examples are included in the Cabal tarball,\n",- "under the @Examples@ directory. The homepage contains links to a user\n",- "manual, an academic paper and further information:\n",- "<http://shakebuild.com>\n",- "\n",- "To use Shake the user writes a Haskell program\n",- "that imports \"Development.Shake\", defines some build rules, and calls\n",- "the 'Development.Shake.shakeArgs' function. Thanks to do notation and infix\n",- "operators, a simple Shake build system\n",- "is not too dissimilar from a simple Makefile. However, as build systems\n",- "get more complex, Shake is able to take advantage of the excellent\n",- "abstraction facilities offered by Haskell and easily support much larger\n",- "projects. The Shake library provides all the standard features available in other\n",- "build systems, including automatic parallelism and minimal rebuilds.\n",- "Shake also provides more accurate dependency tracking, including seamless\n",- "support for generated files, and dependencies on system information\n",- "(e.g. compiler version)."],- executables = [],- extraDocFiles = ["CHANGES.txt", "README.md"],- extraSrcFiles = ["src/Test/C/constants.c",- "src/Test/C/constants.h",- "src/Test/C/main.c",- "src/Test/MakeTutor/Makefile",- "src/Test/MakeTutor/hellofunc.c",- "src/Test/MakeTutor/hellomake.c",- "src/Test/MakeTutor/hellomake.h",- "src/Test/Tar/list.txt",- "src/Test/Ninja/*.ninja",- "src/Test/Ninja/subdir/*.ninja",- "src/Test/Ninja/*.output",- "src/Test/Progress/*.prog",- "src/Test/Tup/hello.c",- "src/Test/Tup/root.cfg",- "src/Test/Tup/newmath/root.cfg",- "src/Test/Tup/newmath/square.c",- "src/Test/Tup/newmath/square.h",- "src/Paths.hs",- "docs/Manual.md",- "docs/shake-progress.png"],- extraTmpFiles = [],- foreignLibs = [],- homepage = "http://shakebuild.com",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Right BSD3,- maintainer = "Neil Mitchell <ndmitchell@gmail.com>",- package = PackageIdentifier- {pkgName = PackageName "shake",- pkgVersion = mkVersion [0, 15, 11]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just- "https://github.com/ndmitchell/shake.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_18,- stability = "",- subLibraries = [],- synopsis = "Build system library, like Make, but more accurate dependencies.",- testSuites = [],- testedWith = [_×_ GHC (ThisVersion (mkVersion [8, 0, 1])),- _×_ GHC (ThisVersion (mkVersion [7, 10, 3])),- _×_ GHC (ThisVersion (mkVersion [7, 8, 4])),- _×_ GHC (ThisVersion (mkVersion [7, 6, 3])),- _×_ GHC (ThisVersion (mkVersion [7, 4, 2]))]}}
− tests/ParserTests/regressions/shake.format
@@ -1,412 +0,0 @@-cabal-version: 1.18-name: shake-version: 0.15.11-license: BSD3-license-file: LICENSE-copyright: Neil Mitchell 2011-2017-maintainer: Neil Mitchell <ndmitchell@gmail.com>-author: Neil Mitchell <ndmitchell@gmail.com>-tested-with:- ghc ==8.0.1 ghc ==7.10.3 ghc ==7.8.4 ghc ==7.6.3 ghc ==7.4.2--homepage: http://shakebuild.com-bug-reports: https://github.com/ndmitchell/shake/issues-synopsis:- Build system library, like Make, but more accurate dependencies.--description:- Shake is a Haskell library for writing build systems - designed as a- replacement for @make@. See "Development.Shake" for an introduction,- including an example. Further examples are included in the Cabal tarball,- under the @Examples@ directory. The homepage contains links to a user- manual, an academic paper and further information:- <http://shakebuild.com>- .- To use Shake the user writes a Haskell program- that imports "Development.Shake", defines some build rules, and calls- the 'Development.Shake.shakeArgs' function. Thanks to do notation and infix- operators, a simple Shake build system- is not too dissimilar from a simple Makefile. However, as build systems- get more complex, Shake is able to take advantage of the excellent- abstraction facilities offered by Haskell and easily support much larger- projects. The Shake library provides all the standard features available in other- build systems, including automatic parallelism and minimal rebuilds.- Shake also provides more accurate dependency tracking, including seamless- support for generated files, and dependencies on system information- (e.g. compiler version).--category: Development, Shake-build-type: Simple-data-files:- html/viz.js- html/profile.html- html/progress.html- html/shake.js- docs/manual/build.bat- docs/manual/Build.hs- docs/manual/build.sh- docs/manual/constants.c- docs/manual/constants.h- docs/manual/main.c--extra-source-files:- src/Test/C/constants.c- src/Test/C/constants.h- src/Test/C/main.c- src/Test/MakeTutor/Makefile- src/Test/MakeTutor/hellofunc.c- src/Test/MakeTutor/hellomake.c- src/Test/MakeTutor/hellomake.h- src/Test/Tar/list.txt- src/Test/Ninja/*.ninja- src/Test/Ninja/subdir/*.ninja- src/Test/Ninja/*.output- src/Test/Progress/*.prog- src/Test/Tup/hello.c- src/Test/Tup/root.cfg- src/Test/Tup/newmath/root.cfg- src/Test/Tup/newmath/square.c- src/Test/Tup/newmath/square.h- src/Paths.hs- docs/Manual.md- docs/shake-progress.png--extra-doc-files:- CHANGES.txt- README.md--source-repository head- type: git- location: https://github.com/ndmitchell/shake.git--flag portable- description: Obtain FileTime using portable functions- default: False- manual: True--library- exposed-modules:- Development.Shake- Development.Shake.Classes- Development.Shake.Command- Development.Shake.Config- Development.Shake.FilePath- Development.Shake.Forward- Development.Shake.Rule- Development.Shake.Util-- hs-source-dirs: . src- other-modules:- Development.Ninja.Env- Development.Ninja.Lexer- Development.Ninja.Parse- Development.Ninja.Type- Development.Shake.Args- Development.Shake.ByteString- Development.Shake.Core- Development.Shake.CmdOption- Development.Shake.Database- Development.Shake.Demo- Development.Shake.Derived- Development.Shake.Errors- Development.Shake.FileInfo- Development.Shake.FilePattern- Development.Shake.Monad- Development.Shake.Pool- Development.Shake.Profile- Development.Shake.Progress- Development.Shake.Resource- Development.Shake.Rules.Directory- Development.Shake.Rules.File- Development.Shake.Rules.Files- Development.Shake.Rules.Oracle- Development.Shake.Rules.OrderOnly- Development.Shake.Rules.Rerun- Development.Shake.Shake- Development.Shake.Special- Development.Shake.Storage- Development.Shake.Types- Development.Shake.Value- General.Bilist- General.Binary- General.Cleanup- General.Concurrent- General.Extra- General.FileLock- General.Intern- General.Process- General.String- General.Template- General.Timing- Paths_shake-- default-language: Haskell2010- build-depends:- base >=4.5,- directory,- hashable >=1.1.2.3,- binary,- filepath,- process >=1.1,- unordered-containers >=0.2.1,- bytestring,- utf8-string >=0.3,- time,- random,- js-jquery,- js-flot,- transformers >=0.2,- extra >=1.4.8,- deepseq >=1.1-- if flag(portable)- cpp-options: -DPORTABLE-- if impl(ghc <7.6)- build-depends: old-time-- else- if !os(windows)- build-depends: unix >=2.5.1-- if !os(windows)- build-depends: unix--executable shake- main-is: Run.hs- hs-source-dirs: src- other-modules:- Development.Make.All- Development.Make.Env- Development.Make.Parse- Development.Make.Rules- Development.Make.Type- Development.Ninja.All- Development.Ninja.Env- Development.Ninja.Lexer- Development.Ninja.Parse- Development.Ninja.Type- Development.Shake- Development.Shake.Args- Development.Shake.ByteString- Development.Shake.Classes- Development.Shake.CmdOption- Development.Shake.Command- Development.Shake.Core- Development.Shake.Database- Development.Shake.Demo- Development.Shake.Derived- Development.Shake.Errors- Development.Shake.FileInfo- Development.Shake.FilePath- Development.Shake.FilePattern- Development.Shake.Forward- Development.Shake.Monad- Development.Shake.Pool- Development.Shake.Profile- Development.Shake.Progress- Development.Shake.Resource- Development.Shake.Rule- Development.Shake.Rules.Directory- Development.Shake.Rules.File- Development.Shake.Rules.Files- Development.Shake.Rules.Oracle- Development.Shake.Rules.OrderOnly- Development.Shake.Rules.Rerun- Development.Shake.Shake- Development.Shake.Special- Development.Shake.Storage- Development.Shake.Types- Development.Shake.Value- General.Bilist- General.Binary- General.Cleanup- General.Concurrent- General.Extra- General.FileLock- General.Intern- General.Process- General.String- General.Template- General.Timing- Paths_shake- Run-- default-language: Haskell2010- ghc-options: -main-is Run.main -rtsopts- build-depends:- base >=4 && <5,- directory,- hashable >=1.1.2.3,- binary,- filepath,- process >=1.1,- unordered-containers >=0.2.1,- bytestring,- utf8-string >=0.3,- time,- random,- js-jquery,- js-flot,- transformers >=0.2,- extra >=1.4.8,- deepseq >=1.1,- primitive-- if impl(ghc >=7.8)- ghc-options: -threaded "-with-rtsopts=-I0 -qg -qb"-- if flag(portable)- cpp-options: -DPORTABLE-- if impl(ghc <7.6)- build-depends: old-time-- else- if !os(windows)- build-depends: unix >=2.5.1-- if !os(windows)- build-depends: unix--test-suite shake-test- type: exitcode-stdio-1.0- main-is: Test.hs- hs-source-dirs: src- other-modules:- Development.Make.All- Development.Make.Env- Development.Make.Parse- Development.Make.Rules- Development.Make.Type- Development.Ninja.All- Development.Ninja.Env- Development.Ninja.Lexer- Development.Ninja.Parse- Development.Ninja.Type- Development.Shake- Development.Shake.Args- Development.Shake.ByteString- Development.Shake.Classes- Development.Shake.CmdOption- Development.Shake.Command- Development.Shake.Config- Development.Shake.Core- Development.Shake.Database- Development.Shake.Demo- Development.Shake.Derived- Development.Shake.Errors- Development.Shake.FileInfo- Development.Shake.FilePath- Development.Shake.FilePattern- Development.Shake.Forward- Development.Shake.Monad- Development.Shake.Pool- Development.Shake.Profile- Development.Shake.Progress- Development.Shake.Resource- Development.Shake.Rule- Development.Shake.Rules.Directory- Development.Shake.Rules.File- Development.Shake.Rules.Files- Development.Shake.Rules.Oracle- Development.Shake.Rules.OrderOnly- Development.Shake.Rules.Rerun- Development.Shake.Shake- Development.Shake.Special- Development.Shake.Storage- Development.Shake.Types- Development.Shake.Util- Development.Shake.Value- General.Bilist- General.Binary- General.Cleanup- General.Concurrent- General.Extra- General.FileLock- General.Intern- General.Process- General.String- General.Template- General.Timing- Paths_shake- Run- Test.Assume- Test.Basic- Test.Benchmark- Test.C- Test.Cache- Test.Command- Test.Config- Test.Digest- Test.Directory- Test.Docs- Test.Errors- Test.FileLock- Test.FilePath- Test.FilePattern- Test.Files- Test.Forward- Test.Journal- Test.Lint- Test.Live- Test.Makefile- Test.Manual- Test.Match- Test.Monad- Test.Ninja- Test.Oracle- Test.OrderOnly- Test.Parallel- Test.Pool- Test.Progress- Test.Random- Test.Resources- Test.Self- Test.Tar- Test.Tup- Test.Type- Test.Unicode- Test.Util- Test.Verbosity- Test.Version-- default-language: Haskell2010- ghc-options: -main-is Test.main -rtsopts- build-depends:- base >=4 && <5,- directory,- hashable >=1.1.2.3,- binary,- filepath,- process >=1.1,- unordered-containers >=0.2.1,- bytestring,- utf8-string >=0.3,- time,- random,- js-jquery,- js-flot,- transformers >=0.2,- deepseq >=1.1,- extra >=1.4.8,- QuickCheck >=2.0-- if impl(ghc >=7.6)- ghc-options: -with-rtsopts=-K1K-- if impl(ghc >=7.8)- ghc-options: -threaded-- if flag(portable)- cpp-options: -DPORTABLE-- if impl(ghc <7.6)- build-depends: old-time-- else- if !os(windows)- build-depends: unix >=2.5.1-- if !os(windows)- build-depends: unix
− tests/ParserTests/regressions/spdx-1.cabal
@@ -1,9 +0,0 @@-cabal-version: 2.0-name: spdx-version: 0-synopsis: testing positive parsing of spdx identifiers-build-type: Simple-license: BSD3--library- default-language: Haskell2010
− tests/ParserTests/regressions/spdx-1.expr
@@ -1,95 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Right BSD3,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "spdx", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_0,- stability = "",- subLibraries = [],- synopsis = "testing positive parsing of spdx identifiers",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/spdx-1.format
@@ -1,9 +0,0 @@-cabal-version: 2.0-name: spdx-version: 0-license: BSD3-synopsis: testing positive parsing of spdx identifiers-build-type: Simple--library- default-language: Haskell2010
− tests/ParserTests/regressions/spdx-2.cabal
@@ -1,9 +0,0 @@-cabal-version: 2.2-name: spdx-version: 0-synopsis: testing positive parsing of spdx identifiers-build-type: Simple-license: AGPL-1.0--library- default-language: Haskell2010
− tests/ParserTests/regressions/spdx-2.expr
@@ -1,96 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left- (License (ELicense (ELicenseId AGPL_1_0) Nothing)),- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "spdx", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_2,- stability = "",- subLibraries = [],- synopsis = "testing positive parsing of spdx identifiers",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/spdx-2.format
@@ -1,9 +0,0 @@-cabal-version: 2.2-name: spdx-version: 0-license: AGPL-1.0-synopsis: testing positive parsing of spdx identifiers-build-type: Simple--library- default-language: Haskell2010
− tests/ParserTests/regressions/spdx-3.cabal
@@ -1,9 +0,0 @@-cabal-version: 2.4-name: spdx-version: 0-synopsis: testing positive parsing of spdx identifiers-build-type: Simple-license: AGPL-1.0-only--library- default-language: Haskell2010
− tests/ParserTests/regressions/spdx-3.expr
@@ -1,96 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left- (License (ELicense (ELicenseId AGPL_1_0_only) Nothing)),- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "spdx", pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV2_4,- stability = "",- subLibraries = [],- synopsis = "testing positive parsing of spdx identifiers",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/spdx-3.format
@@ -1,9 +0,0 @@-cabal-version: 2.4-name: spdx-version: 0-license: AGPL-1.0-only-synopsis: testing positive parsing of spdx identifiers-build-type: Simple--library- default-language: Haskell2010
− tests/ParserTests/regressions/th-lift-instances.cabal
@@ -1,76 +0,0 @@-name: th-lift-instances-version: 0.1.4-x-revision: 1-license: BSD3-cabal-version: >= 1.10-license-file: LICENSE-author: Benno Fünfstück-maintainer: Benno Fünfstück <benno.fuenfstueck@gmail.com>-stability: experimental-homepage: http://github.com/bennofs/th-lift-instances/-bug-reports: http://github.com/bennofs/th-lift-instances/issues-copyright: Copyright (C) 2013-2014 Benno Fünfstück-synopsis: Lift instances for template-haskell for common data types.-description: Most data types in haskell platform do not have Lift instances. This package provides orphan instances- for containers, text, bytestring and vector.-build-type: Custom-category: Template Haskell--extra-source-files:- .ghci- .gitignore- .travis.yml- .vim.custom- README.md--source-repository head- type: git- location: https://github.com/bennofs/th-lift-instances.git--library- hs-source-dirs: src- default-language: Haskell2010- ghc-options: -Wall -fwarn-tabs- build-depends:- base >= 4.4 && < 5- , template-haskell < 2.10- , th-lift- , containers >= 0.4 && < 0.6- , vector >= 0.9 && < 0.11- , text >= 0.11 && < 1.3- , bytestring >= 0.9 && < 0.11- exposed-modules:- Instances.TH.Lift- other-extensions: TemplateHaskell--test-suite tests- type: exitcode-stdio-1.0- main-is: Main.hs- other-modules:- Data- default-language: Haskell2010- build-depends:- base- , template-haskell <2.10- , containers >= 0.4 && < 0.6- , vector >= 0.9 && < 0.11- , text >= 0.11 && < 1.2- , bytestring >= 0.9 && < 0.11- , th-lift-instances- , QuickCheck >= 2.6 && < 2.8- hs-source-dirs: tests- other-extensions: TemplateHaskell--test-suite doctests- type: exitcode-stdio-1.0- main-is: doctests.hs- default-language: Haskell2010- build-depends:- base- , directory >= 1.0- , doctest >= 0.9.1- , filepath- ghc-options: -Wall -threaded- if impl(ghc<7.6.1)- ghc-options: -Werror- hs-source-dirs: tests
− tests/ParserTests/regressions/th-lift-instances.expr
@@ -1,570 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [4, 4]))- (EarlierVersion (mkVersion [5])))- mainLibSet,- Dependency- (PackageName "template-haskell")- (EarlierVersion (mkVersion [2, 10]))- mainLibSet,- Dependency- (PackageName "th-lift")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "containers")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 4]))- (EarlierVersion (mkVersion [0, 6])))- mainLibSet,- Dependency- (PackageName "vector")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 9]))- (EarlierVersion (mkVersion [0, 11])))- mainLibSet,- Dependency- (PackageName "text")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 11]))- (EarlierVersion (mkVersion [1, 3])))- mainLibSet,- Dependency- (PackageName "bytestring")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 9]))- (EarlierVersion (mkVersion [0, 11])))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Instances.TH.Lift"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["src"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall", "-fwarn-tabs"] [],- otherExtensions = [EnableExtension- TemplateHaskell],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [4, 4]))- (EarlierVersion- (mkVersion- [5])))- mainLibSet,- Dependency- (PackageName- "template-haskell")- (EarlierVersion- (mkVersion- [2, 10]))- mainLibSet,- Dependency- (PackageName- "th-lift")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "containers")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0, 4]))- (EarlierVersion- (mkVersion- [0, 6])))- mainLibSet,- Dependency- (PackageName- "vector")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0, 9]))- (EarlierVersion- (mkVersion- [0,- 11])))- mainLibSet,- Dependency- (PackageName- "text")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0, 11]))- (EarlierVersion- (mkVersion- [1, 3])))- mainLibSet,- Dependency- (PackageName- "bytestring")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0, 9]))- (EarlierVersion- (mkVersion- [0,- 11])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [_×_- (UnqualComponentName "tests")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "template-haskell")- (EarlierVersion (mkVersion [2, 10]))- mainLibSet,- Dependency- (PackageName "containers")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 4]))- (EarlierVersion (mkVersion [0, 6])))- mainLibSet,- Dependency- (PackageName "vector")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 9]))- (EarlierVersion (mkVersion [0, 11])))- mainLibSet,- Dependency- (PackageName "text")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 11]))- (EarlierVersion (mkVersion [1, 2])))- mainLibSet,- Dependency- (PackageName "bytestring")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [0, 9]))- (EarlierVersion (mkVersion [0, 11])))- mainLibSet,- Dependency- (PackageName "th-lift-instances")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "QuickCheck")- (IntersectVersionRanges- (OrLaterVersion (mkVersion [2, 6]))- (EarlierVersion (mkVersion [2, 8])))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["tests"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [EnableExtension- TemplateHaskell],- otherLanguages = [],- otherModules = [ModuleName "Data"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "template-haskell")- (EarlierVersion- (mkVersion- [2,- 10]))- mainLibSet,- Dependency- (PackageName- "containers")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 4]))- (EarlierVersion- (mkVersion- [0,- 6])))- mainLibSet,- Dependency- (PackageName- "vector")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 9]))- (EarlierVersion- (mkVersion- [0,- 11])))- mainLibSet,- Dependency- (PackageName- "text")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 11]))- (EarlierVersion- (mkVersion- [1,- 2])))- mainLibSet,- Dependency- (PackageName- "bytestring")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [0,- 9]))- (EarlierVersion- (mkVersion- [0,- 11])))- mainLibSet,- Dependency- (PackageName- "th-lift-instances")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "QuickCheck")- (IntersectVersionRanges- (OrLaterVersion- (mkVersion- [2,- 6]))- (EarlierVersion- (mkVersion- [2,- 8])))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "Main.hs",- testName = UnqualComponentName ""}},- _×_- (UnqualComponentName "doctests")- CondNode- {condTreeComponents = [CondBranch- {condBranchCondition = `Var (Impl GHC (EarlierVersion (mkVersion [7,6,1])))`,- condBranchIfFalse = Nothing,- condBranchIfTrue = CondNode- {condTreeComponents = [],- condTreeConstraints = [],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Werror"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- []- [],- sharedOptions = PerCompilerFlavor- []- [],- staticOptions = PerCompilerFlavor- []- [],- targetBuildDepends = [],- virtualModules = []},- testInterface = TestSuiteUnsupported- (TestTypeUnknown- ""- (mkVersion- [])),- testName = UnqualComponentName- ""}}}],- condTreeConstraints = [Dependency- (PackageName "base")- (OrLaterVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "directory")- (OrLaterVersion (mkVersion [1, 0]))- mainLibSet,- Dependency- (PackageName "doctest")- (OrLaterVersion (mkVersion [0, 9, 1]))- mainLibSet,- Dependency- (PackageName "filepath")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = TestSuite- {testBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["tests"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor- ["-Wall", "-threaded"]- [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor- [] [],- sharedOptions = PerCompilerFlavor- [] [],- staticOptions = PerCompilerFlavor- [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "directory")- (OrLaterVersion- (mkVersion- [1,- 0]))- mainLibSet,- Dependency- (PackageName- "doctest")- (OrLaterVersion- (mkVersion- [0,- 9,- 1]))- mainLibSet,- Dependency- (PackageName- "filepath")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- testInterface = TestSuiteExeV10- (mkVersion [1, 0]) "doctests.hs",- testName = UnqualComponentName ""}}],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Benno F\252nfst\252ck",- benchmarks = [],- bugReports = "http://github.com/bennofs/th-lift-instances/issues",- buildTypeRaw = Just Custom,- category = "Template Haskell",- copyright = "Copyright (C) 2013-2014 Benno F\252nfst\252ck",- customFieldsPD = [_×_ "x-revision" "1"],- dataDir = ".",- dataFiles = [],- description = concat- ["Most data types in haskell platform do not have Lift instances. This package provides orphan instances\n",- "for containers, text, bytestring and vector."],- executables = [],- extraDocFiles = [],- extraSrcFiles = [".ghci",- ".gitignore",- ".travis.yml",- ".vim.custom",- "README.md"],- extraTmpFiles = [],- foreignLibs = [],- homepage = "http://github.com/bennofs/th-lift-instances/",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Right BSD3,- maintainer = "Benno F\252nfst\252ck <benno.fuenfstueck@gmail.com>",- package = PackageIdentifier- {pkgName = PackageName "th-lift-instances",- pkgVersion = mkVersion [0, 1, 4]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just- "https://github.com/bennofs/th-lift-instances.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_10,- stability = "experimental",- subLibraries = [],- synopsis = "Lift instances for template-haskell for common data types.",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/th-lift-instances.format
@@ -1,77 +0,0 @@-th-lift-instances.cabal:15:9: Tabs used as indentation at 15:9-cabal-version: >=1.10-name: th-lift-instances-version: 0.1.4-license: BSD3-license-file: LICENSE-copyright: Copyright (C) 2013-2014 Benno Fünfstück-maintainer: Benno Fünfstück <benno.fuenfstueck@gmail.com>-author: Benno Fünfstück-stability: experimental-homepage: http://github.com/bennofs/th-lift-instances/-bug-reports: http://github.com/bennofs/th-lift-instances/issues-synopsis: Lift instances for template-haskell for common data types.-description:- Most data types in haskell platform do not have Lift instances. This package provides orphan instances- for containers, text, bytestring and vector.--category: Template Haskell-x-revision: 1-build-type: Custom-extra-source-files:- .ghci- .gitignore- .travis.yml- .vim.custom- README.md--source-repository head- type: git- location: https://github.com/bennofs/th-lift-instances.git--library- exposed-modules: Instances.TH.Lift- hs-source-dirs: src- default-language: Haskell2010- other-extensions: TemplateHaskell- ghc-options: -Wall -fwarn-tabs- build-depends:- base >=4.4 && <5,- template-haskell <2.10,- th-lift,- containers >=0.4 && <0.6,- vector >=0.9 && <0.11,- text >=0.11 && <1.3,- bytestring >=0.9 && <0.11--test-suite tests- type: exitcode-stdio-1.0- main-is: Main.hs- hs-source-dirs: tests- other-modules: Data- default-language: Haskell2010- other-extensions: TemplateHaskell- build-depends:- base,- template-haskell <2.10,- containers >=0.4 && <0.6,- vector >=0.9 && <0.11,- text >=0.11 && <1.2,- bytestring >=0.9 && <0.11,- th-lift-instances,- QuickCheck >=2.6 && <2.8--test-suite doctests- type: exitcode-stdio-1.0- main-is: doctests.hs- hs-source-dirs: tests- default-language: Haskell2010- ghc-options: -Wall -threaded- build-depends:- base,- directory >=1.0,- doctest >=0.9.1,- filepath-- if impl(ghc <7.6.1)- ghc-options: -Werror
− tests/ParserTests/regressions/version-sets.cabal
@@ -1,18 +0,0 @@-cabal-version: 3.0-name: version-sets-version: 0-synopsis: version set notation-tested-with: GHC == { 8.6.3, 8.4.4, 8.2.2, 8.0.2, 7.10.3, 7.8.4, 7.6.3, 7.4.2 }--library- default-language: Haskell2010- build-depends: network ^>= {0}- build-depends: base == {1}, base == { 1 }, base == {1,2}, base == {1.2}, base == {1.2,3.4}- build-depends: ghc == {- 8.6.3- ,- 8.4.4 ,8.2.2 ,- 8.0.2,7.10.3- , 7.8.4, 7.6.3, 7.4.2- }- build-depends: Cabal ^>= { 2.4.1.1, 2.2.0.0 }
− tests/ParserTests/regressions/version-sets.expr
@@ -1,283 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "network")- (MajorBoundVersion (mkVersion [0]))- mainLibSet,- Dependency- (PackageName "base")- (ThisVersion (mkVersion [1]))- mainLibSet,- Dependency- (PackageName "base")- (ThisVersion (mkVersion [1]))- mainLibSet,- Dependency- (PackageName "base")- (UnionVersionRanges- (ThisVersion (mkVersion [1]))- (ThisVersion (mkVersion [2])))- mainLibSet,- Dependency- (PackageName "base")- (ThisVersion (mkVersion [1, 2]))- mainLibSet,- Dependency- (PackageName "base")- (UnionVersionRanges- (ThisVersion (mkVersion [1, 2]))- (ThisVersion (mkVersion [3, 4])))- mainLibSet,- Dependency- (PackageName "ghc")- (UnionVersionRanges- (ThisVersion (mkVersion [8, 6, 3]))- (UnionVersionRanges- (ThisVersion (mkVersion [8, 4, 4]))- (UnionVersionRanges- (ThisVersion (mkVersion [8, 2, 2]))- (UnionVersionRanges- (ThisVersion (mkVersion [8, 0, 2]))- (UnionVersionRanges- (ThisVersion (mkVersion [7, 10, 3]))- (UnionVersionRanges- (ThisVersion (mkVersion [7, 8, 4]))- (UnionVersionRanges- (ThisVersion- (mkVersion [7, 6, 3]))- (ThisVersion- (mkVersion [7, 4, 2])))))))))- mainLibSet,- Dependency- (PackageName "Cabal")- (UnionVersionRanges- (MajorBoundVersion (mkVersion [2, 4, 1, 1]))- (MajorBoundVersion (mkVersion [2, 2, 0, 0])))- mainLibSet],- condTreeData = Library- {exposedModules = [],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Just Haskell2010,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "network")- (MajorBoundVersion- (mkVersion- [0]))- mainLibSet,- Dependency- (PackageName- "base")- (ThisVersion- (mkVersion- [1]))- mainLibSet,- Dependency- (PackageName- "base")- (ThisVersion- (mkVersion- [1]))- mainLibSet,- Dependency- (PackageName- "base")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1]))- (ThisVersion- (mkVersion- [2])))- mainLibSet,- Dependency- (PackageName- "base")- (ThisVersion- (mkVersion- [1, 2]))- mainLibSet,- Dependency- (PackageName- "base")- (UnionVersionRanges- (ThisVersion- (mkVersion- [1, 2]))- (ThisVersion- (mkVersion- [3, 4])))- mainLibSet,- Dependency- (PackageName- "ghc")- (UnionVersionRanges- (ThisVersion- (mkVersion- [8,- 6,- 3]))- (UnionVersionRanges- (ThisVersion- (mkVersion- [8,- 4,- 4]))- (UnionVersionRanges- (ThisVersion- (mkVersion- [8,- 2,- 2]))- (UnionVersionRanges- (ThisVersion- (mkVersion- [8,- 0,- 2]))- (UnionVersionRanges- (ThisVersion- (mkVersion- [7,- 10,- 3]))- (UnionVersionRanges- (ThisVersion- (mkVersion- [7,- 8,- 4]))- (UnionVersionRanges- (ThisVersion- (mkVersion- [7,- 6,- 3]))- (ThisVersion- (mkVersion- [7,- 4,- 2])))))))))- mainLibSet,- Dependency- (PackageName- "Cabal")- (UnionVersionRanges- (MajorBoundVersion- (mkVersion- [2,- 4,- 1,- 1]))- (MajorBoundVersion- (mkVersion- [2,- 2,- 0,- 0])))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "",- benchmarks = [],- bugReports = "",- buildTypeRaw = Nothing,- category = "",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = "",- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = [],- licenseRaw = Left NONE,- maintainer = "",- package = PackageIdentifier- {pkgName = PackageName "version-sets",- pkgVersion = mkVersion [0]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [],- specVersion = CabalSpecV3_0,- stability = "",- subLibraries = [],- synopsis = "version set notation",- testSuites = [],- testedWith = [_×_- GHC- (UnionVersionRanges- (ThisVersion (mkVersion [8, 6, 3]))- (UnionVersionRanges- (ThisVersion (mkVersion [8, 4, 4]))- (UnionVersionRanges- (ThisVersion (mkVersion [8, 2, 2]))- (UnionVersionRanges- (ThisVersion (mkVersion [8, 0, 2]))- (UnionVersionRanges- (ThisVersion (mkVersion [7, 10, 3]))- (UnionVersionRanges- (ThisVersion (mkVersion [7, 8, 4]))- (UnionVersionRanges- (ThisVersion (mkVersion [7, 6, 3]))- (ThisVersion- (mkVersion [7, 4, 2])))))))))]}}
− tests/ParserTests/regressions/version-sets.format
@@ -1,19 +0,0 @@-cabal-version: 3.0-name: version-sets-version: 0-tested-with:- ghc ==8.6.3 || ==8.4.4 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2--synopsis: version set notation--library- default-language: Haskell2010- build-depends:- network ^>=0,- base ==1,- base ==1,- base ==1 || ==2,- base ==1.2,- base ==1.2 || ==3.4,- ghc ==8.6.3 || ==8.4.4 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2,- Cabal ^>=2.4.1.1 || ^>=2.2.0.0
− tests/ParserTests/regressions/wl-pprint-indef.cabal
@@ -1,34 +0,0 @@-Name: wl-pprint-indef-Version: 1.2-Cabal-Version: >=1.6-Synopsis: The Wadler/Leijen Pretty Printer-Category: Text-Description:- This is a pretty printing library based on Wadler's paper "A Prettier- Printer". See the haddocks for full info. This version allows the- library user to declare overlapping instances of the 'Pretty' class.-License: BSD3-License-file: LICENSE-Author: Daan Leijen-Maintainer: Noam Lewis <jones.noamle@gmail.com>-Build-Type: Simple--Executable wl-pprint-string-example- Main-is: Main.hs- Hs-Source-Dirs: example-string- Other-Modules: StringImpl- Build-Depends: base < 5,- str-string >= 0.1.0.0,- wl-pprint-indef- Mixins: wl-pprint-indef requires (Text.PrettyPrint.Leijen.Str as StringImpl)--Library- Exposed-Modules: Text.PrettyPrint.Leijen- Signatures: Text.PrettyPrint.Leijen.Str- Mixins: str-sig requires (Str as Text.PrettyPrint.Leijen.Str)- Build-Depends: base < 5,- str-sig >= 0.1.0.0--source-repository head- type: git- location: git@github.com:danidiaz/wl-pprint-indef.git
− tests/ParserTests/regressions/wl-pprint-indef.expr
@@ -1,218 +0,0 @@-GenericPackageDescription- {condBenchmarks = [],- condExecutables = [_×_- (UnqualComponentName "wl-pprint-string-example")- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (EarlierVersion (mkVersion [5]))- mainLibSet,- Dependency- (PackageName "str-string")- (OrLaterVersion (mkVersion [0, 1, 0, 0]))- mainLibSet,- Dependency- (PackageName "wl-pprint-indef")- (OrLaterVersion (mkVersion [0]))- mainLibSet],- condTreeData = Executable- {buildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = ["example-string"],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [ModuleName- "StringImpl"],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (EarlierVersion- (mkVersion- [5]))- mainLibSet,- Dependency- (PackageName- "str-string")- (OrLaterVersion- (mkVersion- [0,- 1,- 0,- 0]))- mainLibSet,- Dependency- (PackageName- "wl-pprint-indef")- (OrLaterVersion- (mkVersion- [0]))- mainLibSet],- virtualModules = []},- exeName = UnqualComponentName- "wl-pprint-string-example",- exeScope = ExecutablePublic,- modulePath = "Main.hs"}}],- condForeignLibs = [],- condLibrary = Just- CondNode- {condTreeComponents = [],- condTreeConstraints = [Dependency- (PackageName "base")- (EarlierVersion (mkVersion [5]))- mainLibSet,- Dependency- (PackageName "str-sig")- (OrLaterVersion (mkVersion [0, 1, 0, 0]))- mainLibSet],- condTreeData = Library- {exposedModules = [ModuleName "Text.PrettyPrint.Leijen"],- libBuildInfo = BuildInfo- {asmOptions = [],- asmSources = [],- autogenIncludes = [],- autogenModules = [],- buildToolDepends = [],- buildTools = [],- buildable = True,- cSources = [],- ccOptions = [],- cmmOptions = [],- cmmSources = [],- cppOptions = [],- customFieldsBI = [],- cxxOptions = [],- cxxSources = [],- defaultExtensions = [],- defaultLanguage = Nothing,- extraBundledLibs = [],- extraDynLibFlavours = [],- extraFrameworkDirs = [],- extraGHCiLibs = [],- extraLibDirs = [],- extraLibFlavours = [],- extraLibs = [],- frameworks = [],- hsSourceDirs = [],- includeDirs = [],- includes = [],- installIncludes = [],- jsSources = [],- ldOptions = [],- mixins = [],- oldExtensions = [],- options = PerCompilerFlavor [] [],- otherExtensions = [],- otherLanguages = [],- otherModules = [],- pkgconfigDepends = [],- profOptions = PerCompilerFlavor [] [],- sharedOptions = PerCompilerFlavor [] [],- staticOptions = PerCompilerFlavor [] [],- targetBuildDepends = [Dependency- (PackageName- "base")- (EarlierVersion- (mkVersion- [5]))- mainLibSet,- Dependency- (PackageName- "str-sig")- (OrLaterVersion- (mkVersion- [0,- 1,- 0,- 0]))- mainLibSet],- virtualModules = []},- libExposed = True,- libName = LMainLibName,- libVisibility = LibraryVisibilityPublic,- reexportedModules = [],- signatures = []}},- condSubLibraries = [],- condTestSuites = [],- genPackageFlags = [],- gpdScannedVersion = Nothing,- packageDescription = PackageDescription- {author = "Daan Leijen",- benchmarks = [],- bugReports = "",- buildTypeRaw = Just Simple,- category = "Text",- copyright = "",- customFieldsPD = [],- dataDir = ".",- dataFiles = [],- description = concat- ["This is a pretty printing library based on Wadler's paper \"A Prettier\n",- "Printer\". See the haddocks for full info. This version allows the\n",- "library user to declare overlapping instances of the 'Pretty' class."],- executables = [],- extraDocFiles = [],- extraSrcFiles = [],- extraTmpFiles = [],- foreignLibs = [],- homepage = "",- library = Nothing,- licenseFiles = ["LICENSE"],- licenseRaw = Right BSD3,- maintainer = "Noam Lewis <jones.noamle@gmail.com>",- package = PackageIdentifier- {pkgName = PackageName "wl-pprint-indef",- pkgVersion = mkVersion [1, 2]},- pkgUrl = "",- setupBuildInfo = Nothing,- sourceRepos = [SourceRepo- {repoBranch = Nothing,- repoKind = RepoHead,- repoLocation = Just- "git@github.com:danidiaz/wl-pprint-indef.git",- repoModule = Nothing,- repoSubdir = Nothing,- repoTag = Nothing,- repoType = Just (KnownRepoType Git)}],- specVersion = CabalSpecV1_6,- stability = "",- subLibraries = [],- synopsis = "The Wadler/Leijen Pretty Printer",- testSuites = [],- testedWith = []}}
− tests/ParserTests/regressions/wl-pprint-indef.format
@@ -1,37 +0,0 @@-wl-pprint-indef.cabal:28:3: The field "mixins" is available only since the Cabal specification version 2.0. This field will be ignored.-wl-pprint-indef.cabal:27:3: The field "signatures" is available only since the Cabal specification version 2.0. This field will be ignored.-wl-pprint-indef.cabal:23:3: The field "mixins" is available only since the Cabal specification version 2.0. This field will be ignored.-cabal-version: >=1.6-name: wl-pprint-indef-version: 1.2-license: BSD3-license-file: LICENSE-maintainer: Noam Lewis <jones.noamle@gmail.com>-author: Daan Leijen-synopsis: The Wadler/Leijen Pretty Printer-description:- This is a pretty printing library based on Wadler's paper "A Prettier- Printer". See the haddocks for full info. This version allows the- library user to declare overlapping instances of the 'Pretty' class.--category: Text-build-type: Simple--source-repository head- type: git- location: git@github.com:danidiaz/wl-pprint-indef.git--library- exposed-modules: Text.PrettyPrint.Leijen- build-depends:- base <5,- str-sig >=0.1.0.0--executable wl-pprint-string-example- main-is: Main.hs- hs-source-dirs: example-string- other-modules: StringImpl- build-depends:- base <5,- str-string >=0.1.0.0,- wl-pprint-indef
− tests/ParserTests/warnings/bom.cabal
@@ -1,7 +0,0 @@-name: bom-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/bool.cabal
@@ -1,12 +0,0 @@-name: bool-version: 1-cabal-version: >= 1.8--flag foo- manual: true--library- build-depends: base >= 4.9 && <4.10- if flag(foo)- build-depends: containers- hs-source-dirs: .
− tests/ParserTests/warnings/deprecatedfield.cabal
@@ -1,7 +0,0 @@-name: deprecatedfield-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dir: .
− tests/ParserTests/warnings/doubledash.cabal
@@ -1,9 +0,0 @@-name: bool-version: 1-cabal-version: >= 1.8-extra-source-files:- README.md -- we include it--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/extratestmodule.cabal
@@ -1,11 +0,0 @@-name: extramainis-version: 1-cabal-version: >= 1.6--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .--test-suite tests- type: exitcode-stdio-1.0- test-module: Tests
− tests/ParserTests/warnings/gluedop.cabal
@@ -1,9 +0,0 @@-name: gluedop-version: 1-cabal-version: >= 1.6--library- build-depends: base >= 4.9 && <4.10- if os(windows) &&!impl(ghc)- build-depends: containers- hs-source-dirs: .
− tests/ParserTests/warnings/multiplesingular.cabal
@@ -1,8 +0,0 @@-name: multiplesingular-name: multiplesingular2-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/nbsp.cabal
@@ -1,7 +0,0 @@-name: nbsp-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/newsyntax.cabal
@@ -1,6 +0,0 @@-name: newsyntax-version: 1--library- build-depends: base- hs-source-dirs: .
− tests/ParserTests/warnings/oldsyntax.cabal
@@ -1,6 +0,0 @@-name: oldsyntax-version: 1-cabal-version: >= 1.8--build-depends: base >= 4.9 && <4.10-hs-source-dirs: .
− tests/ParserTests/warnings/operator.cabal
@@ -1,7 +0,0 @@-name: version-operator-version: 1-cabal-version: >= 1.6--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/specversion-a.cabal
@@ -1,7 +0,0 @@-name: specversion-version: 1-cabal-version: >= 1.12--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/specversion-b.cabal
@@ -1,7 +0,0 @@-name: specversion-version: 1-cabal-version: >= 1.10 && <1.11--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/specversion-c.cabal
@@ -1,7 +0,0 @@-name: specversion-version: 1-cabal-version: 1.10--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/subsection.cabal
@@ -1,9 +0,0 @@-name: subsection-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .- iff os(windows)- build-depends: containers
− tests/ParserTests/warnings/tab.cabal
@@ -1,12 +0,0 @@-name: tab-version: 1-cabal-version: >= 1.8--library - build-depends: { base >= 4.9 && <4.10 } - hs-source-dirs: .--test-suite tests { - type: exitcode-stdio-1.0- main-is: Main.hs-}
− tests/ParserTests/warnings/trailingfield.cabal
@@ -1,9 +0,0 @@-name: trailingfield-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .--description: No fields after sections
− tests/ParserTests/warnings/unknownfield.cabal
@@ -1,8 +0,0 @@-name: unknownfield-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .- xfield: x
− tests/ParserTests/warnings/unknownsection.cabal
@@ -1,10 +0,0 @@-name: unknownsection-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .--z- z-field: z
− tests/ParserTests/warnings/utf8.cabal
@@ -1,8 +0,0 @@-name: utf8-author: Oleg Grönroos-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10- hs-source-dirs: .
− tests/ParserTests/warnings/versiontag.cabal
@@ -1,7 +0,0 @@-name: versiontag-version: 1-cabal-version: >= 1.8--library- build-depends: base >= 4.9 && <4.10-rc1- hs-source-dirs: .
− tests/ParserTests/warnings/wildcard.cabal
@@ -1,7 +0,0 @@-name: version-wildcard-version: 1-cabal-version: >= 1.4--library- build-depends: base == 4.*- hs-source-dirs: .
− tests/README.md
@@ -1,5 +0,0 @@-Unit tests-==========--Ordinary unit tests. If you're looking for the package tests,-they live in cabal-testsuite now.
− tests/RPMVerCmp.hs
@@ -1,103 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}-{-# LANGUAGE OverloadedStrings #-}-module Main where--import Foreign.C.String (CString)-import Foreign.C.Types (CInt (..))-import System.IO.Unsafe (unsafePerformIO)-import Data.Bits ((.&.))--import Test.QuickCheck (Arbitrary (..), (===))-import Test.Tasty (defaultMain, testGroup)-import Test.Tasty.HUnit (assertEqual, testCase)-import Test.Tasty.QuickCheck (testProperty)--import Distribution.Pretty (prettyShow)-import Distribution.Types.PkgconfigVersion (rpmvercmp)-import Distribution.Types.Version--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS8------------------------------------------------------------------------------------ C reference implementation----------------------------------------------------------------------------------foreign import ccall unsafe "rpmvercmp" c_rmpvercmp- :: CString -> CString -> CInt--rpmvercmpRef :: BS.ByteString -> BS.ByteString -> Ordering-rpmvercmpRef a b = unsafePerformIO $- BS.useAsCString a $ \a' ->- BS.useAsCString b $ \b' ->- return $ fromInt $ c_rmpvercmp a' b'- where- fromInt = flip compare 0------------------------------------------------------------------------------------ Tests----------------------------------------------------------------------------------main :: IO ()-main = defaultMain $ testGroup "rpmvercmp"- [ testGroup "examples"- [ example "openssl" "1.1.0g" "1.1.0i" LT- , example "openssl" "1.0.2h" "1.1.0" LT-- , example "simple" "1.2.3" "1.2.4" LT- , example "word" "apple" "banana" LT-- , example "corner case" "r" "" GT- , example "corner case" "0" "1" LT- , example "corner case" "1" "0.0" GT- ]- , testGroup "Properties"- [ testProperty "ref reflexive" $ \a ->- rpmvercmpRef (BS.pack a) (BS.pack a) === EQ- , testProperty "pure reflexive" $ \a ->- rpmvercmp (BS.pack a) (BS.pack a) === EQ- , testProperty "ref agrees with Version" $ \a b ->- compare a b === rpmvercmpRef (v2bs a) (v2bs b)- , testProperty "pure agrees with Version" $ \a b ->- compare a b === rpmvercmp (v2bs a) (v2bs b)- ]- , testGroup "Random inputs"- [ testProperty "random" $ \xs ys ->- -- only 7bit numbers, no zero, and non-empty.- let xs' = BS.pack $ unnull $ filter (/= 0) $ map (.&. 0x7f) xs- ys' = BS.pack $ unnull $ filter (/= 0) $ map (.&. 0x7f) ys-- -- ref doesn't really work with empty inputs reliably.- unnull [] = [1]- unnull zs = zs- in rpmvercmpRef xs' ys' === rpmvercmp xs' ys'- ]- ]- where- example n a b c = testCase (n ++ " " ++ BS8.unpack a ++ " <=> " ++ BS8.unpack b) $ do- let ref = rpmvercmpRef a b- let pur = rpmvercmp a b- assertEqual "ref" c ref- assertEqual "pure" c pur------------------------------------------------------------------------------------ Version arbitrary----------------------------------------------------------------------------------newtype V = V Version- deriving (Show, Eq, Ord)--unV :: V -> Version-unV (V x) = x--instance Arbitrary V where- arbitrary = fmap (V . mkVersion_) arbitrary-- shrink = map V . filter (/= version0) . map mkVersion_ . shrink . versionNumbers . unV--mkVersion_ :: [Int] -> Version-mkVersion_ [] = version0-mkVersion_ xs = mkVersion (map abs xs)--v2bs :: V -> BS.ByteString-v2bs (V x) = BS8.pack (prettyShow x)
− tests/Test/Laws.hs
@@ -1,79 +0,0 @@-{-# 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 efficiency--- 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
@@ -1,29 +0,0 @@-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
@@ -1,117 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-module Main- ( main- ) where--import Test.Tasty-import Test.Tasty.Options--import Data.Proxy-import Data.Typeable--import Distribution.Simple.Utils-import Distribution.Verbosity-import Distribution.Compat.Time--import qualified UnitTests.Distribution.Compat.CreatePipe-import qualified UnitTests.Distribution.Compat.Time-import qualified UnitTests.Distribution.Compat.Graph-import qualified UnitTests.Distribution.Simple.Glob-import qualified UnitTests.Distribution.Simple.Program.GHC-import qualified UnitTests.Distribution.Simple.Program.Internal-import qualified UnitTests.Distribution.Simple.Utils-import qualified UnitTests.Distribution.System-import qualified UnitTests.Distribution.Utils.CharSet-import qualified UnitTests.Distribution.Utils.Generic-import qualified UnitTests.Distribution.Utils.NubList-import qualified UnitTests.Distribution.Utils.ShortText-import qualified UnitTests.Distribution.Utils.Structured-import qualified UnitTests.Distribution.Version (versionTests)-import qualified UnitTests.Distribution.PkgconfigVersion (pkgconfigVersionTests)-import qualified UnitTests.Distribution.SPDX (spdxTests)-import qualified UnitTests.Distribution.Described-import qualified UnitTests.Distribution.CabalSpecVersion-import qualified UnitTests.Distribution.Types.GenericPackageDescription--tests :: Int -> TestTree-tests mtimeChangeCalibrated =- askOption $ \(OptionMtimeChangeDelay mtimeChangeProvided) ->- askOption $ \(GhcPath ghcPath) ->- let mtimeChange = if mtimeChangeProvided /= 0- then mtimeChangeProvided- else mtimeChangeCalibrated- in- testGroup "Unit Tests"- [ testGroup "Distribution.Compat.CreatePipe"- UnitTests.Distribution.Compat.CreatePipe.tests- , testGroup "Distribution.Compat.Time"- (UnitTests.Distribution.Compat.Time.tests mtimeChange)- , testGroup "Distribution.Compat.Graph"- UnitTests.Distribution.Compat.Graph.tests- , testGroup "Distribution.Simple.Glob"- UnitTests.Distribution.Simple.Glob.tests- , UnitTests.Distribution.Simple.Program.GHC.tests- , testGroup "Distribution.Simple.Program.Internal"- UnitTests.Distribution.Simple.Program.Internal.tests- , testGroup "Distribution.Simple.Utils" $- UnitTests.Distribution.Simple.Utils.tests ghcPath- , testGroup "Distribution.Utils.Generic"- UnitTests.Distribution.Utils.Generic.tests- , testGroup "Distribution.Utils.NubList"- UnitTests.Distribution.Utils.NubList.tests- , testGroup "Distribution.Utils.ShortText"- UnitTests.Distribution.Utils.ShortText.tests- , testGroup "Distribution.System"- UnitTests.Distribution.System.tests- , testGroup "Distribution.Types.GenericPackageDescription"- UnitTests.Distribution.Types.GenericPackageDescription.tests- , testGroup "Distribution.Version"- UnitTests.Distribution.Version.versionTests- , testGroup "Distribution.Types.PkgconfigVersion(Range)"- UnitTests.Distribution.PkgconfigVersion.pkgconfigVersionTests- , testGroup "Distribution.SPDX"- UnitTests.Distribution.SPDX.spdxTests- , UnitTests.Distribution.Utils.CharSet.tests- , UnitTests.Distribution.Utils.Structured.tests- , UnitTests.Distribution.Described.tests- , UnitTests.Distribution.CabalSpecVersion.tests- ]--extraOptions :: [OptionDescription]-extraOptions =- [ Option (Proxy :: Proxy OptionMtimeChangeDelay)- , Option (Proxy :: Proxy GhcPath)- ]--newtype OptionMtimeChangeDelay = OptionMtimeChangeDelay Int- deriving Typeable--instance IsOption OptionMtimeChangeDelay where- defaultValue = OptionMtimeChangeDelay 0- parseValue = fmap OptionMtimeChangeDelay . safeRead- optionName = return "mtime-change-delay"- optionHelp = return $ "How long to wait before attempting to detect"- ++ "file modification, in microseconds"--newtype GhcPath = GhcPath FilePath- deriving Typeable--instance IsOption GhcPath where- defaultValue = GhcPath "ghc"- optionName = return "with-ghc"- optionHelp = return "The ghc compiler to use"- parseValue = Just . GhcPath--main :: IO ()-main = do- (mtimeChange, mtimeChange') <- calibrateMtimeChangeDelay- let toMillis :: Int -> Double- toMillis x = fromIntegral x / 1000.0- notice normal $ "File modification time resolution calibration completed, "- ++ "maximum delay observed: "- ++ (show . toMillis $ mtimeChange ) ++ " ms. "- ++ "Will be using delay of " ++ (show . toMillis $ mtimeChange')- ++ " for test runs."- defaultMainWithIngredients- (includingOptions extraOptions : defaultIngredients)- (tests mtimeChange')
− tests/UnitTests/Distribution/CabalSpecVersion.hs
@@ -1,42 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-deprecations #-}-module UnitTests.Distribution.CabalSpecVersion (tests) where--import Distribution.Compat.Prelude.Internal-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.FieldGrammar.Newtypes (SpecVersion (..))-import Distribution.Parsec (eitherParsec)-import Distribution.Pretty (prettyShow)--import Test.Tasty-import Test.Tasty.QuickCheck---- instances-import Test.QuickCheck.Instances.Cabal ()--tests :: TestTree-tests = testGroup "Distribution.CabalSpecVersion"- [ testProperty "roundtrip" propRoundtrip- , testProperty "fromVersionDigits . toVersionDigits = Just" propViaVersionDigits- ]- where- -- we test roundtrip here,- -- because Described instance is a small simplification.- propRoundtrip :: SpecVersion -> Property- propRoundtrip x = counterexample (show (res, str)) $ case res of- Right y -> x == y- Left _ -> False- where- str = prettyShow x- res = eitherParsec str-- propViaVersionDigits :: CabalSpecVersion -> Property- propViaVersionDigits csv =- counterexample (show digits) $- lhs === rhs- where- digits = cabalSpecToVersionDigits csv- lhs = cabalSpecFromVersionDigits digits- rhs = Just csv
− tests/UnitTests/Distribution/Compat/CreatePipe.hs
@@ -1,56 +0,0 @@-module UnitTests.Distribution.Compat.CreatePipe (tests) where--import Control.Concurrent.Async (async, wait)-import Control.DeepSeq (force)-import Control.Exception (evaluate)-import System.IO (hClose, hGetContents, hPutStr, hSetEncoding, localeEncoding)-import Test.Tasty (TestTree)-import Test.Tasty.HUnit (Assertion, assertEqual, testCase)--import qualified Data.ByteString as BS--import Distribution.Compat.CreatePipe--tests :: [TestTree]-tests =- [ testCase "Locale Encoding" case_Locale_Encoding- , testCase "Binary ByteStrings are not affected" case_ByteString- ]--case_Locale_Encoding :: Assertion-case_Locale_Encoding = do- let str = "\0252foobar"- (r, w) <- createPipe- hSetEncoding w localeEncoding- hSetEncoding r localeEncoding-- ra <- async $ do- out <- hGetContents r- evaluate (force out)-- wa <- async $ do- hPutStr w str- hClose w-- out <- wait ra- wait wa-- assertEqual "createPipe should support Unicode roundtripping" str out--case_ByteString :: Assertion-case_ByteString = do- let bs = BS.pack[ 1..255]- (r, w) <- createPipe-- ra <- async $ do- out <- BS.hGetContents r- evaluate (force out)-- wa <- async $ do- BS.hPutStr w bs- hClose w-- out <- wait ra- wait wa-- assertEqual "createPipe should support Unicode roundtripping" bs out
− tests/UnitTests/Distribution/Compat/Graph.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module UnitTests.Distribution.Compat.Graph- ( tests- , arbitraryGraph- ) where--import Distribution.Compat.Graph--import qualified Prelude-import Prelude hiding (null)-import Test.Tasty-import Test.Tasty.QuickCheck-import qualified Data.Set as Set-import Control.Monad-import qualified Data.Graph as G-import Data.Array ((!))-import Data.Maybe-import Data.List (sort)--tests :: [TestTree]-tests =- [ testProperty "arbitrary unbroken" (prop_arbitrary_unbroken :: Graph (Node Int ()) -> Bool)- , testProperty "nodes consistent" (prop_nodes_consistent :: Graph (Node Int ()) -> Bool)- , testProperty "edges consistent" (prop_edges_consistent :: Graph (Node Int ()) -> Property)- , testProperty "closure consistent" (prop_closure_consistent :: Graph (Node Int ()) -> Property)- ]---- Our arbitrary instance does not generate broken graphs-prop_arbitrary_unbroken :: Graph a -> Bool-prop_arbitrary_unbroken g = Prelude.null (broken g)---- Every node from 'toList' maps to a vertex which--- is present in the constructed graph, and maps back--- to a node correctly.-prop_nodes_consistent :: (Eq a, IsNode a) => Graph a -> Bool-prop_nodes_consistent g = all p (toList g)- where- (_, vtn, ktv) = toGraph g- p n = case ktv (nodeKey n) of- Just v -> vtn v == n- Nothing -> False---- A non-broken graph has the 'nodeNeighbors' of each node--- equal the recorded adjacent edges in the node graph.-prop_edges_consistent :: IsNode a => Graph a -> Property-prop_edges_consistent g = Prelude.null (broken g) ==> all p (toList g)- where- (gr, vtn, ktv) = toGraph g- p n = sort (nodeNeighbors n)- == sort (map (nodeKey . vtn) (gr ! fromJust (ktv (nodeKey n))))---- Closure is consistent with reachable-prop_closure_consistent :: (Show a, IsNode a) => Graph a -> Property-prop_closure_consistent g =- not (null g) ==>- forAll (elements (toList g)) $ \n ->- Set.fromList (map nodeKey (fromJust (closure g [nodeKey n])))- == Set.fromList (map (nodeKey . vtn) (G.reachable gr (fromJust (ktv (nodeKey n)))))- where- (gr, vtn, ktv) = toGraph g--hasNoDups :: Ord a => [a] -> Bool-hasNoDups = loop Set.empty- where- loop _ [] = True- loop s (x:xs) | s' <- Set.insert x s, Set.size s' > Set.size s- = loop s' xs- | otherwise- = False---- | Produces a graph of size @len@. We sample with 'suchThat'; if we--- dropped duplicate entries our size could be smaller.-arbitraryGraph :: (Ord k, Show k, Arbitrary k, Arbitrary a)- => Int -> Gen (Graph (Node k a))-arbitraryGraph len = do- -- Careful! Assume k is much larger than size.- ks <- vectorOf len arbitrary `suchThat` hasNoDups- ns <- forM ks $ \k -> do- a <- arbitrary- ns <- listOf (elements ks)- -- Allow duplicates!- return (N a k ns)- return (fromDistinctList ns)--instance (Ord k, Show k, Arbitrary k, Arbitrary a)- => Arbitrary (Graph (Node k a)) where- arbitrary = sized $ \n -> do- len <- choose (0, n)- arbitraryGraph len
− tests/UnitTests/Distribution/Compat/Time.hs
@@ -1,49 +0,0 @@-module UnitTests.Distribution.Compat.Time (tests) where--import Control.Concurrent (threadDelay)-import System.FilePath--import Distribution.Simple.Utils (withTempDirectory)-import Distribution.Verbosity--import Distribution.Compat.Time--import Test.Tasty-import Test.Tasty.HUnit--tests :: Int -> [TestTree]-tests mtimeChange =- [ testCase "getModTime has sub-second resolution" $ getModTimeTest mtimeChange- , testCase "getCurTime works as expected" $ getCurTimeTest mtimeChange- ]--getModTimeTest :: Int -> Assertion-getModTimeTest mtimeChange =- withTempDirectory silent "." "getmodtime-" $ \dir -> do- let fileName = dir </> "foo"- writeFile fileName "bar"- t0 <- getModTime fileName- threadDelay mtimeChange- writeFile fileName "baz"- t1 <- getModTime fileName- assertBool "expected different file mtimes" (t1 > t0)---getCurTimeTest :: Int -> Assertion-getCurTimeTest mtimeChange =- withTempDirectory silent "." "getmodtime-" $ \dir -> do- let fileName = dir </> "foo"- writeFile fileName "bar"- t0 <- getModTime fileName- threadDelay mtimeChange- t1 <- getCurTime- assertBool("expected file mtime (" ++ show t0- ++ ") to be earlier than current time (" ++ show t1 ++ ")")- (t0 < t1)-- threadDelay mtimeChange- writeFile fileName "baz"- t2 <- getModTime fileName- assertBool ("expected current time (" ++ show t1- ++ ") to be earlier than file mtime (" ++ show t2 ++ ")")- (t1 < t2)
− tests/UnitTests/Distribution/Described.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -fno-warn-deprecations #-}-module UnitTests.Distribution.Described where--import Distribution.Compat.Prelude.Internal-import Prelude ()--import Distribution.Described (testDescribed)-import Test.Tasty (TestTree, testGroup)--import Distribution.Compiler (CompilerFlavor, CompilerId)-import Distribution.ModuleName (ModuleName)-import Distribution.System (Arch, OS)-import Distribution.Types.Dependency (Dependency)-import Distribution.Types.Flag (FlagAssignment, FlagName)-import Distribution.Types.IncludeRenaming (IncludeRenaming)-import Distribution.Types.Mixin (Mixin)-import Distribution.Types.ModuleRenaming (ModuleRenaming)-import Distribution.Types.PackageId (PackageIdentifier)-import Distribution.Types.PackageName (PackageName)-import Distribution.Types.PackageVersionConstraint (PackageVersionConstraint)-import Distribution.Types.Version (Version)-import Distribution.Types.VersionRange (VersionRange)-import Distribution.Verbosity (Verbosity)---- instances-import Test.QuickCheck.Instances.Cabal ()--tests :: TestTree-tests = testGroup "Described"- [ testDescribed (Proxy :: Proxy Dependency)- , testDescribed (Proxy :: Proxy PackageName)- , testDescribed (Proxy :: Proxy PackageIdentifier)- , testDescribed (Proxy :: Proxy PackageVersionConstraint)- , testDescribed (Proxy :: Proxy Version)- , testDescribed (Proxy :: Proxy VersionRange)- , testDescribed (Proxy :: Proxy FlagName)- , testDescribed (Proxy :: Proxy FlagAssignment)- , testDescribed (Proxy :: Proxy ModuleName)- , testDescribed (Proxy :: Proxy OS)- , testDescribed (Proxy :: Proxy Arch)- , testDescribed (Proxy :: Proxy CompilerFlavor)- , testDescribed (Proxy :: Proxy CompilerId)- , testDescribed (Proxy :: Proxy ModuleRenaming)- , testDescribed (Proxy :: Proxy IncludeRenaming)- , testDescribed (Proxy :: Proxy Mixin)- , testDescribed (Proxy :: Proxy Verbosity)- ]
− tests/UnitTests/Distribution/PkgconfigVersion.hs
@@ -1,21 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE StandaloneDeriving #-}-module UnitTests.Distribution.PkgconfigVersion (pkgconfigVersionTests) where--import Test.Tasty-import Test.Tasty.QuickCheck--import Distribution.Parsec (eitherParsec)-import Distribution.Pretty-import Distribution.Types.PkgconfigVersionRange--import Test.QuickCheck.Instances.Cabal ()--pkgconfigVersionTests :: [TestTree]-pkgconfigVersionTests =- [ testProperty "simpleParsec . prettyShow = Just" prop_parse_disp- ]--prop_parse_disp :: PkgconfigVersionRange -> Property-prop_parse_disp vr = counterexample (show (prettyShow vr)) $- eitherParsec (prettyShow vr) === Right vr
− tests/UnitTests/Distribution/SPDX.hs
@@ -1,180 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-deprecations #-}-module UnitTests.Distribution.SPDX (spdxTests) where--import Distribution.Compat.Prelude.Internal-import Prelude ()--import Distribution.SPDX-import Distribution.Parsec (eitherParsec)-import Distribution.Pretty (prettyShow)--import Test.Tasty-import Test.Tasty.QuickCheck--#if MIN_VERSION_binary(0,7,0)-import qualified Data.Binary as Binary-import qualified Data.Binary.Get as Binary-import qualified Data.Binary.Put as Binary-import qualified Data.ByteString.Lazy as LBS-import GHC.Generics (to, from)-#endif--import Test.QuickCheck.Instances.Cabal ()--spdxTests :: [TestTree]-spdxTests =- [ testProperty "LicenseId roundtrip" licenseIdRoundtrip-#if MIN_VERSION_binary(0,7,0)- , testProperty "LicenseId Binary.put" licenseIdBinaryPut- , testProperty "LicenseId Binary.get" licenseIdBinaryGet-#endif- , testProperty "LicenseExceptionId roundtrip" licenseExceptionIdRoundtrip-#if MIN_VERSION_binary(0,7,0)- , testProperty "LicenseExceptionId Binary.put" licenseExceptionIdBinaryPut- , testProperty "LicenseExceptionId Binary.get" licenseExceptionIdBinaryGet-#endif- , testProperty "LicenseRef roundtrip" licenseRefRoundtrip- , testProperty "SimpleLicenseExpression roundtrip" simpleLicenseExpressionRoundtrip- , testProperty "LicenseExpression roundtrip" licenseExpressionRoundtrip- , testProperty "isAcceptableLicense l = True" shouldAcceptProp- , testProperty "isAcceptableLicense l = False" shouldRejectProp- ]--licenseIdRoundtrip :: LicenseId -> Property-licenseIdRoundtrip x =- counterexample (prettyShow x) $- Right x === eitherParsec (prettyShow x)--#if MIN_VERSION_binary(0,7,0)-licenseIdBinaryPut :: LicenseId -> Property-licenseIdBinaryPut x =- Binary.runPut (Binary.put x)- ===- Binary.runPut (Binary.gput (from x))--licenseIdBinaryGet :: Word8 -> Word8 -> Property-licenseIdBinaryGet w0 w1 =- stripMsg id (Binary.runGetOrFail Binary.get bs)- ===- stripMsg to (Binary.runGetOrFail Binary.gget bs)- where- bs = LBS.pack [w0, w1]-- stripMsg- :: (a -> LicenseId)- -> Either (x, y, String) (x, y, a)- -> Either (x, y) (x, y, LicenseId)- stripMsg _ (Left (x,y,_)) = Left (x,y)- stripMsg f (Right (x,y,t)) = Right (x,y,f t)-#endif--licenseExceptionIdRoundtrip :: LicenseExceptionId -> Property-licenseExceptionIdRoundtrip x =- counterexample (prettyShow x) $- Right x === eitherParsec (prettyShow x)--#if MIN_VERSION_binary(0,7,0)-licenseExceptionIdBinaryPut :: LicenseExceptionId -> Property-licenseExceptionIdBinaryPut x =- Binary.runPut (Binary.put x)- ===- Binary.runPut (Binary.gput (from x))--licenseExceptionIdBinaryGet :: Word8 -> Property-licenseExceptionIdBinaryGet w0 =- stripMsg id (Binary.runGetOrFail Binary.get bs)- ===- stripMsg to (Binary.runGetOrFail Binary.gget bs)- where- bs = LBS.pack [w0]-- stripMsg- :: (a -> LicenseExceptionId)- -> Either (x, y, String) (x, y, a)- -> Either (x, y) (x, y, LicenseExceptionId)- stripMsg _ (Left (x,y,_)) = Left (x,y)- stripMsg f (Right (x,y,t)) = Right (x,y,f t)-#endif--licenseRefRoundtrip :: LicenseRef -> Property-licenseRefRoundtrip x =- counterexample (prettyShow x) $- Right x === eitherParsec (prettyShow x)--simpleLicenseExpressionRoundtrip :: SimpleLicenseExpression -> Property-simpleLicenseExpressionRoundtrip x =- counterexample (prettyShow x) $- Right x === eitherParsec (prettyShow x)--licenseExpressionRoundtrip :: LicenseExpression -> Property-licenseExpressionRoundtrip x =- counterexample (prettyShow x) $- Right (reassoc x) === eitherParsec (prettyShow x)---- Parser produces right biased trees of and/or expressions-reassoc :: LicenseExpression -> LicenseExpression-reassoc (EOr a b) = case reassoc a of- EOr x y -> EOr x (reassoc (EOr y b))- x -> EOr x (reassoc b)-reassoc (EAnd a b) = case reassoc a of- EAnd x y -> EAnd x (reassoc (EAnd y b))- x -> EAnd x (reassoc b)-reassoc l = l------------------------------------------------------------------------------------ isAcceptableLicence----------------------------------------------------------------------------------shouldAccept :: [License]-shouldAccept = map License- [ simpleLicenseExpression GPL_2_0_only- , simpleLicenseExpression GPL_2_0_or_later- , simpleLicenseExpression BSD_2_Clause- , simpleLicenseExpression BSD_3_Clause- , simpleLicenseExpression MIT- , simpleLicenseExpression ISC- , simpleLicenseExpression MPL_2_0- , simpleLicenseExpression Apache_2_0- , simpleLicenseExpression CC0_1_0- , simpleLicenseExpression BSD_4_Clause `EOr` simpleLicenseExpression MIT- ]--shouldReject :: [License]-shouldReject = map License- [ simpleLicenseExpression BSD_4_Clause- , simpleLicenseExpression BSD_4_Clause `EAnd` simpleLicenseExpression MIT- ]---- | A sketch of what Hackage could accept------ * NONE is rejected------ * "or later" syntax (+ postfix) is rejected------ * "WITH exc" exceptions are rejected------ * There should be a way to interpert license as (conjunction of)--- OSI-accepted licenses or CC0----isAcceptableLicense :: License -> Bool-isAcceptableLicense NONE = False-isAcceptableLicense (License expr) = goExpr expr- where- goExpr (EAnd a b) = goExpr a && goExpr b- goExpr (EOr a b) = goExpr a || goExpr b- goExpr (ELicense _ (Just _)) = False -- Don't allow exceptions- goExpr (ELicense s Nothing) = goSimple s-- goSimple (ELicenseRef _) = False -- don't allow referenced licenses- goSimple (ELicenseIdPlus _) = False -- don't allow + licenses (use GPL-3.0-or-later e.g.)- goSimple (ELicenseId CC0_1_0) = True -- CC0 isn't OSI approved, but we allow it as "PublicDomain", this is eg. PublicDomain in http://hackage.haskell.org/package/string-qq-0.0.2/src/LICENSE- goSimple (ELicenseId lid) = licenseIsOsiApproved lid -- allow only OSI approved licenses.--shouldAcceptProp :: Property-shouldAcceptProp = conjoin $- map (\l -> counterexample (prettyShow l) (isAcceptableLicense l)) shouldAccept--shouldRejectProp :: Property-shouldRejectProp = conjoin $- map (\l -> counterexample (prettyShow l) (not $ isAcceptableLicense l)) shouldReject
− tests/UnitTests/Distribution/Simple/Glob.hs
@@ -1,164 +0,0 @@-module UnitTests.Distribution.Simple.Glob- ( tests- ) where--import Control.Monad-import Data.Foldable (for_)-import Data.Function (on)-import Data.List (sort)-import Data.Maybe (mapMaybe)-import Distribution.Simple.Glob-import qualified Distribution.Verbosity as Verbosity-import Distribution.CabalSpecVersion-import System.Directory (createDirectoryIfMissing)-import System.FilePath ((</>), splitFileName, normalise)-import System.IO.Temp (withSystemTempDirectory)-import Test.Tasty-import Test.Tasty.HUnit--sampleFileNames :: [FilePath]-sampleFileNames =- [ "a"- , "a.html"- , "b.html"- , "b.html.gz"- , "foo/.blah.html"- , "foo/.html"- , "foo/a"- , "foo/a.html"- , "foo/a.html.gz"- , "foo/a.tex"- , "foo/a.tex.gz"- , "foo/b.html"- , "foo/b.html.gz"- , "foo/x.gz"- , "foo/bar/.html"- , "foo/bar/a.html"- , "foo/bar/a.html.gz"- , "foo/bar/a.tex"- , "foo/bar/a.tex.gz"- , "foo/bar/b.html"- , "foo/bar/b.html.gz"- , "foo/c.html/blah"- , "xyz/foo/a.html"- ]--makeSampleFiles :: FilePath -> IO ()-makeSampleFiles dir = for_ sampleFileNames $ \filename -> do- let (dir', name) = splitFileName filename- createDirectoryIfMissing True (dir </> dir')- writeFile (dir </> dir' </> name) $ "This is " ++ filename--compatibilityTests :: CabalSpecVersion -> [TestTree]-compatibilityTests version =- [ testCase "literal match" $- testMatches "foo/a" [GlobMatch "foo/a"]- , testCase "literal no match on prefix" $- testMatches "foo/c.html" []- , testCase "literal no match on suffix" $- testMatches "foo/a.html" [GlobMatch "foo/a.html"]- , testCase "literal no prefix" $- testMatches "a" [GlobMatch "a"]- , testCase "literal multiple prefix" $- testMatches "foo/bar/a.html" [GlobMatch "foo/bar/a.html"]- , testCase "glob" $- testMatches "*.html" [GlobMatch "a.html", GlobMatch "b.html"]- , testCase "glob in subdir" $- testMatches "foo/*.html" [GlobMatch "foo/a.html", GlobMatch "foo/b.html"]- , testCase "glob multiple extensions" $- testMatches "foo/*.html.gz" [GlobMatch "foo/a.html.gz", GlobMatch "foo/b.html.gz"]- , testCase "glob in deep subdir" $- testMatches "foo/bar/*.tex" [GlobMatch "foo/bar/a.tex"]- , testCase "star in directory" $- testFailParse "blah/*/foo" StarInDirectory- , testCase "star plus text in segment" $- testFailParse "xyz*/foo" StarInDirectory- , testCase "star in filename plus text" $- testFailParse "foo*.bar" StarInFileName- , testCase "no extension on star" $- testFailParse "foo/*" NoExtensionOnStar- , testCase "star in extension" $- testFailParse "foo.*.gz" StarInExtension- ]- where- testMatches = testMatchesVersion version- testFailParse = testFailParseVersion version---- For efficiency reasons, matchDirFileGlob isn't a simple call to--- getDirectoryContentsRecursive and then a filter with--- fileGlobMatches. So test both that naive approach and the actual--- approach to make sure they are both correct.------ TODO: Work out how to construct the sample tree once for all tests,--- rather than once for each test.-testMatchesVersion :: CabalSpecVersion -> FilePath -> [GlobResult FilePath] -> Assertion-testMatchesVersion version pat expected = do- globPat <- case parseFileGlob version pat of- Left _ -> assertFailure "Couldn't compile the pattern."- Right globPat -> return globPat- checkPure globPat- checkIO globPat- where- isEqual = (==) `on` (sort . fmap (fmap normalise))- checkPure globPat = do- let actual = mapMaybe (fileGlobMatches globPat) sampleFileNames- unless (sort expected == sort actual) $- assertFailure $ "Unexpected result (pure matcher): " ++ show actual- checkIO globPat =- withSystemTempDirectory "globstar-sample" $ \tmpdir -> do- makeSampleFiles tmpdir- actual <- runDirFileGlob Verbosity.normal tmpdir globPat- unless (isEqual actual expected) $- assertFailure $ "Unexpected result (impure matcher): " ++ show actual--testFailParseVersion :: CabalSpecVersion -> FilePath -> GlobSyntaxError -> Assertion-testFailParseVersion version pat expected =- case parseFileGlob version pat of- Left err -> unless (expected == err) $- assertFailure $ "Unexpected error: " ++ show err- Right _ -> assertFailure "Unexpected success in parsing."--globstarTests :: [TestTree]-globstarTests =- [ testCase "fails to parse on early spec version" $- testFailParseVersion CabalSpecV2_2 "**/*.html" VersionDoesNotSupportGlobStar- , testCase "out-of-place double star" $- testFailParse "blah/**/blah/*.foo" StarInDirectory- , testCase "multiple double star" $- testFailParse "blah/**/**/*.foo" StarInDirectory- , testCase "fails with literal filename" $- testFailParse "**/a.html" LiteralFileNameGlobStar- , testCase "with glob filename" $- testMatches "**/*.html" [GlobMatch "a.html", GlobMatch "b.html", GlobMatch "foo/a.html", GlobMatch "foo/b.html", GlobMatch "foo/bar/a.html", GlobMatch "foo/bar/b.html", GlobMatch "xyz/foo/a.html"]- , testCase "glob with prefix" $- testMatches "foo/**/*.html" [GlobMatch "foo/a.html", GlobMatch "foo/b.html", GlobMatch "foo/bar/a.html", GlobMatch "foo/bar/b.html"]- ]- where- testFailParse = testFailParseVersion CabalSpecV2_4- testMatches = testMatchesVersion CabalSpecV2_4--multiDotTests :: [TestTree]-multiDotTests =- [ testCase "pre-2.4 single extension not matching multiple" $- testMatchesVersion CabalSpecV2_2 "foo/*.gz" [GlobWarnMultiDot "foo/a.html.gz", GlobWarnMultiDot "foo/a.tex.gz", GlobWarnMultiDot "foo/b.html.gz", GlobMatch "foo/x.gz"]- , testCase "doesn't match literal" $- testMatches "foo/a.tex" [GlobMatch "foo/a.tex"]- , testCase "works" $- testMatches "foo/*.gz" [GlobMatch "foo/a.html.gz", GlobMatch "foo/a.tex.gz", GlobMatch "foo/b.html.gz", GlobMatch "foo/x.gz"]- , testCase "works with globstar" $- testMatches "foo/**/*.gz" [GlobMatch "foo/a.html.gz", GlobMatch "foo/a.tex.gz", GlobMatch "foo/b.html.gz", GlobMatch "foo/x.gz", GlobMatch "foo/bar/a.html.gz", GlobMatch "foo/bar/a.tex.gz", GlobMatch "foo/bar/b.html.gz"]- ]- where- testMatches = testMatchesVersion CabalSpecV2_4--tests :: [TestTree]-tests =- [ testGroup "pre-2.4 compatibility" $- compatibilityTests CabalSpecV2_2- , testGroup "post-2.4 compatibility" $- compatibilityTests CabalSpecV2_4- , testGroup "globstar" globstarTests- , testCase "pre-1.6 rejects globbing" $- testFailParseVersion CabalSpecV1_4 "foo/*.bar" VersionDoesNotSupportGlob- , testGroup "multi-dot globbing" multiDotTests- ]
− tests/UnitTests/Distribution/Simple/Program/GHC.hs
@@ -1,172 +0,0 @@-module UnitTests.Distribution.Simple.Program.GHC (tests) where--import Data.Algorithm.Diff (PolyDiff (..), getDiff)-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit--import Distribution.PackageDescription (emptyPackageDescription)-import Distribution.Simple.Program.GHC (normaliseGhcArgs)-import Distribution.Version (mkVersion)--tests :: TestTree-tests = testGroup "Distribution.Simple.Program.GHC"- [ testGroup "normaliseGhcArgs"- [ testCase "options added in GHC-8.8" $ do- let flags :: [String]- flags = normaliseGhcArgs- (Just $ mkVersion [8,8,1])- emptyPackageDescription- options_8_8_all-- assertListEquals flags options_8_8_affects-- , testCase "options added in GHC-8.10" $ do- let flags :: [String]- flags = normaliseGhcArgs- (Just $ mkVersion [8,10,1])- emptyPackageDescription- options_8_10_all-- assertListEquals flags options_8_10_affects-- , testCase "options added in GHC-9.0" $ do- let flags :: [String]- flags = normaliseGhcArgs- (Just $ mkVersion [9,0,1])- emptyPackageDescription- options_9_0_all-- assertListEquals flags options_9_0_affects- ]- ]--assertListEquals :: (Eq a, Show a) => [a] -> [a] -> Assertion-assertListEquals xs ys- | xs == ys = return ()- | otherwise = assertFailure $ unlines $- "Lists are not equal" :- [ case d of- First x -> "- " ++ show x- Second y -> "+ " ++ show y- Both x _ -> " " ++ show x- | d <- getDiff xs ys- ]------------------------------------------------------------------------------------ GHC 8.8------------------------------------------------------------------------------------ | Options added in GHC-8.8, to generate:------ @--- ghc-8.6.5 --show-options | sort > 8.6.5.txt--- ghc-8.8.1 --show-options | sort > 8.8.1.txt--- diff -u 8.6.5 8.8.1--- @------ - remove -W(no-)error=, -W(no-)warn flags.--- - split into all and flags which may affect artifacts-options_8_8_all :: [String]-options_8_8_all =- [ "-ddump-cfg-weights"- , "-dno-suppress-stg-exts"- , "-dsuppress-stg-exts"- , "-Wmissed-extra-shared-lib"- , "-Wmissing-deriving-strategies"- , "-Wmissing-space-after-bang"- , "-Wno-missed-extra-shared-lib"- , "-Wno-missing-deriving-strategies"- , "-Wno-missing-space-after-bang"- , "-fno-show-docs-of-hole-fits"- , "-fshow-docs-of-hole-fits"- ] ++ options_8_8_affects--options_8_8_affects :: [String]-options_8_8_affects =- [ "-fblock-layout-cfg"- , "-fblock-layout-weightless"- , "-fblock-layout-weights"- , "-fclear-plugins"- , "-fkeep-cafs"- , "-fno-block-layout-cfg"- , "-fno-block-layout-weightless"- , "-fno-keep-cafs"- , "-fno-safe-haskell"- , "-fno-stg-lift-lams"- , "-fno-stg-lift-lams-known"- , "-fno-validate-ide-info"- , "-fno-write-ide-info"- , "-fstg-lift-lams"- , "-fstg-lift-lams-known"- , "-fstg-lift-lams-non-rec-args"- , "-fstg-lift-lams-non-rec-args-any"- , "-fstg-lift-lams-rec-args"- , "-fstg-lift-lams-rec-args-any"- , "-fvalidate-ide-info"- , "-fwrite-ide-info"- , "-hiedir"- , "-hiesuf"- , "-keep-hscpp-file"- , "-keep-hscpp-files"- ]------------------------------------------------------------------------------------ GHC 8.10----------------------------------------------------------------------------------options_8_10_all :: [String]-options_8_10_all =- [ "-ddump-cmm-verbose-by-proc"- , "-ddump-stg-final"- , "-ddump-stg-unarised"- , "-Wderiving-defaults"- , "-Winferred-safe-imports"- , "-Wmissing-safe-haskell-mode"- , "-Wno-deriving-defaults"- , "-Wno-inferred-safe-imports"- , "-Wno-missing-safe-haskell-mode"- , "-Wno-prepositive-qualified-module"- , "-Wno-redundant-record-wildcards"- , "-Wno-unused-packages"- , "-Wno-unused-record-wildcards"- , "-Wprepositive-qualified-module"- , "-Wredundant-record-wildcards"- , "-Wunused-packages"- , "-Wunused-record-wildcards"- , "-fdefer-diagnostics"- , "-fkeep-going"- , "-fprint-axiom-incomps"- , "-fno-defer-diagnostics"- , "-fno-keep-going"- , "-fno-print-axiom-incomps"- ] ++ options_8_10_affects--options_8_10_affects :: [String]-options_8_10_affects =- [ "-dno-typeable-binds"- , "-fbinary-blob-threshold"- , "-fmax-pmcheck-models"- , "-fplugin-trustworthy"- , "-include-cpp-deps"- , "-optcxx"- ]------------------------------------------------------------------------------------ GHC-9.0----------------------------------------------------------------------------------options_9_0_all :: [String]-options_9_0_all =- [ "-ddump-cmm-opt"- , "-ddump-cpranal"- , "-ddump-cpr-signatures"- , "-ddump-hie"- -- NOTE: we filter out -dlinear-core-lint- -- we filter, -dcore-lint, -dstg-lint etc.- , "-dlinear-core-lint"- ] ++ options_9_0_affects--options_9_0_affects :: [String]-options_9_0_affects =- [ "-fcmm-static-pred"- ]
− tests/UnitTests/Distribution/Simple/Program/Internal.hs
@@ -1,36 +0,0 @@-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
@@ -1,110 +0,0 @@-{-# LANGUAGE GADTs #-}-module UnitTests.Distribution.Simple.Utils- ( tests- ) where--import Distribution.Simple.BuildPaths ( exeExtension )-import Distribution.Simple.Utils-import Distribution.System ( buildPlatform )-import Distribution.Verbosity--import Data.IORef-import System.Directory ( doesDirectoryExist, doesFileExist- , getTemporaryDirectory- , removeDirectoryRecursive, removeFile )-import System.FilePath ( (<.>) )-import System.IO (hClose, localeEncoding, hPutStrLn)-import System.IO.Error-import qualified Control.Exception as Exception--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--rawSystemStdInOutTextDecodingTest :: FilePath -> Assertion-rawSystemStdInOutTextDecodingTest ghcPath- -- We can only get this exception when the locale encoding is UTF-8- -- so skip the test if it's not.- | show localeEncoding /= "UTF-8" = return ()- | otherwise = do- tempDir <- getTemporaryDirectory- res <- withTempFile tempDir ".hs" $ \filenameHs handleHs -> do- withTempFile tempDir ".exe" $ \filenameExe handleExe -> do- -- Small program printing not utf8- hPutStrLn handleHs "import Data.ByteString"- hPutStrLn handleHs "main = Data.ByteString.putStr (Data.ByteString.pack [32, 32, 255])"- hClose handleHs-- -- We need to close exe handle as well, otherwise compilation (writing) may fail- hClose handleExe-- -- Compile- (resOutput, resErrors, resExitCode) <- rawSystemStdInOut normal- ghcPath ["-o", filenameExe, filenameHs]- Nothing Nothing Nothing- IODataModeText- print (resOutput, resErrors, resExitCode)-- -- Execute- Exception.try $ do- rawSystemStdInOut normal- filenameExe []- Nothing Nothing Nothing- IODataModeText -- not binary mode output, ie utf8 text mode so try to decode- case res of- Right (x1, x2, x3) -> assertFailure $ "expected IO decoding exception: " ++ show (x1,x2,x3)- Left err | isDoesNotExistError err -> Exception.throwIO err -- no ghc!- | otherwise -> return ()--dropExeExtensionTest :: Assertion-dropExeExtensionTest =- assertBool "dropExeExtension didn't drop exeExtension!" $- dropExeExtension ("foo" <.> exeExtension buildPlatform) == "foo"---tests :: FilePath -> [TestTree]-tests ghcPath =- [ 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- , testCase "rawSystemStdInOut reports text decoding errors" $- rawSystemStdInOutTextDecodingTest ghcPath- , testCase "dropExeExtension drops exe extension" $- dropExeExtensionTest- ]
− tests/UnitTests/Distribution/System.hs
@@ -1,30 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-module UnitTests.Distribution.System- ( tests- ) where--import Control.Monad (liftM2)-import Distribution.Parsec-import Distribution.Pretty-import Distribution.System-import Test.Tasty-import Test.Tasty.QuickCheck--textRoundtrip :: (Show a, Eq a, Pretty a, Parsec a) => a -> Property-textRoundtrip x = simpleParsec (prettyShow 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/Types/GenericPackageDescription.hs
@@ -1,37 +0,0 @@-{-# OPTIONS_GHC -fno-warn-deprecations #-} -- for importing "Distribution.Compat.Prelude.Internal"--module UnitTests.Distribution.Types.GenericPackageDescription where--import Prelude ()-import Distribution.Compat.Prelude.Internal-import Distribution.Types.GenericPackageDescription--import Test.Tasty-import Test.Tasty.HUnit-import qualified Control.Exception as C--tests :: [TestTree]-tests =- [ testCase "GenericPackageDescription deepseq" gpdDeepseq- ]--gpdFields :: [(String, GenericPackageDescription -> GenericPackageDescription)]-gpdFields =- [ ("packageDescription", \gpd -> gpd { packageDescription = undefined })- , ("genPackageFlags", \gpd -> gpd { genPackageFlags = undefined })- , ("condLibrary", \gpd -> gpd { condLibrary = undefined })- , ("condSubLibraries", \gpd -> gpd { condSubLibraries = undefined })- , ("condForeignLibs", \gpd -> gpd { condForeignLibs = undefined })- , ("condExecutables", \gpd -> gpd { condExecutables = undefined })- , ("condTestSuites", \gpd -> gpd { condTestSuites = undefined })- , ("condBenchmarks", \gpd -> gpd { condBenchmarks = undefined })- ]--gpdDeepseq :: Assertion-gpdDeepseq = sequence_- [ throwsUndefined msg (f emptyGenericPackageDescription) | (msg, f) <- gpdFields ]--throwsUndefined :: NFData a => String -> a -> Assertion-throwsUndefined field a =- C.catch (C.evaluate (rnf a) >> assertFailure ("Deepseq failed to evaluate " ++ show field))- (\(C.ErrorCall _) -> return ())
− tests/UnitTests/Distribution/Utils/CharSet.hs
@@ -1,27 +0,0 @@-{-# LANGUAGE CPP #-}--- isAlpha and isAlphaNum definitions change from base to base-#if MIN_VERSION_base(4,12,0) && !MIN_VERSION_base(4,13,0)-#define HAS_TESTS-#endif-module UnitTests.Distribution.Utils.CharSet where--import Data.Char (isAlpha, isAlphaNum)-import Data.List (foldl')-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit (testCase, (@?=))--import qualified Distribution.Utils.CharSet as CS--tests :: TestTree-tests = testGroup "Distribution.Utils.CharSet"- [ testCase "alphanum" $- CS.alphanum @?= foldl' (flip CS.insert) CS.empty- [ c | c <- [ minBound .. maxBound ], isAlphaNum c ]-- , testCase "alpha" $- CS.alpha @?= foldl' (flip CS.insert) CS.empty- [ c | c <- [ minBound .. maxBound ], isAlpha c ]-- , testCase "alpha is subset of alphanum" $- CS.union CS.alpha CS.alphanum @?= CS.alphanum- ]
− tests/UnitTests/Distribution/Utils/Generic.hs
@@ -1,71 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- to suppress WARNING in "Distribution.Compat.Prelude.Internal"-{-# OPTIONS_GHC -fno-warn-deprecations #-}--module UnitTests.Distribution.Utils.Generic ( tests ) where--import Prelude ()-import Distribution.Compat.Prelude.Internal--import Distribution.Utils.Generic--import qualified Data.ByteString.Char8 as BS-import qualified Data.Text as T-import qualified Data.Text.Encoding as T--import Test.Tasty-import Test.Tasty.HUnit-import Test.Tasty.QuickCheck--tests :: [TestTree]-tests =- [ -- fromUTF8BS / toUTF8BS- testCase "fromUTF8BS mempty" testFromUTF8BSEmpty- , testCase "toUTF8BS mempty" testToUTF8BSEmpty- , testCase "toUTF8BS [U+D800..U+DFFF]" testToUTF8BSSurr- , testCase "toUTF8BS [U+0000..U+7F]" testToUTF8BSAscii- , testCase "toUTF8BS [U+0000..U+10FFFF]" testToUTF8BSText- , testCase "fromUTF8BS.toUTF8BS [U+0000..U+10FFFF]" testToFromUTF8BS-- , testProperty "fromUTF8BS.toUTF8BS == id" prop_toFromUTF8BS- , testProperty "toUTF8BS == encodeUtf8" prop_toUTF8BS-- , testProperty "Nothing = validateUtf8 (encodeUtf8 x)" prop_validateUtf8- ]--testFromUTF8BSEmpty :: Assertion-testFromUTF8BSEmpty = mempty @=? fromUTF8BS mempty--testToUTF8BSEmpty :: Assertion-testToUTF8BSEmpty = mempty @=? toUTF8BS mempty--testToUTF8BSSurr :: Assertion-testToUTF8BSSurr = BS.concat (replicate 2048 u_fffd) @=? toUTF8BS surrogates- where- surrogates = ['\xD800'..'\xDFFF']- u_fffd = "\xEF\xBF\xBD"--testToUTF8BSText :: Assertion-testToUTF8BSText = T.encodeUtf8 (T.pack txt) @=? toUTF8BS txt- where- txt = ['\x00'..'\x10FFFF']--testToUTF8BSAscii :: Assertion-testToUTF8BSAscii = BS.pack txt @=? toUTF8BS txt- where- txt = ['\x00'..'\x7F']--testToFromUTF8BS :: Assertion-testToFromUTF8BS = txt @=? (fromUTF8BS . toUTF8BS) txt- where- txt = ['\x0000'..'\xD7FF'] ++ ['\xE000'..'\x10FFFF']--prop_toFromUTF8BS :: [Char] -> Property-prop_toFromUTF8BS txt = txt === (fromUTF8BS . toUTF8BS) txt--prop_toUTF8BS :: [Char] -> Property-prop_toUTF8BS txt = T.encodeUtf8 (T.pack txt) === toUTF8BS txt--prop_validateUtf8 :: [Char] -> Property-prop_validateUtf8 txt = Nothing === validateUTF8 (toUTF8BS txt)
− tests/UnitTests/Distribution/Utils/NubList.hs
@@ -1,76 +0,0 @@--- to suppress WARNING in "Distribution.Compat.Prelude.Internal"-{-# OPTIONS_GHC -fno-warn-deprecations #-}-module UnitTests.Distribution.Utils.NubList- ( tests- ) where--import Prelude ()-import Distribution.Compat.Prelude.Internal--import Distribution.Utils.NubList-import Test.Tasty-import Test.Tasty.HUnit-import Test.Tasty.QuickCheck--tests :: [TestTree]-tests =- [ testCase "NubList retains ordering example" testOrdering- , testCase "NubList removes duplicates example" testDeDupe- , testProperty "NubList retains ordering" prop_Ordering- , testProperty "NubList removes duplicates" prop_DeDupe- , testProperty "fromNubList . toNubList = nub" prop_Nub- , testProperty "Monoid NubList Identity" prop_Identity- , testProperty "Monoid NubList Associativity" prop_Associativity- -- NubListR- , testProperty "NubListR removes duplicates from the right" prop_DeDupeR- ]--someIntList :: [Int]--- This list must not have duplicate entries.-someIntList = [ 1, 3, 4, 2, 0, 7, 6, 5, 9, -1 ]--testOrdering :: Assertion-testOrdering =- assertBool "Maintains element ordering:" $- fromNubList (toNubList someIntList) == someIntList--testDeDupe :: Assertion-testDeDupe =- assertBool "De-duplicates a list:" $- fromNubList (toNubList (someIntList ++ someIntList)) == someIntList---- ------------------------------------------------------------------------------ QuickCheck properties for NubList--prop_Ordering :: [Int] -> Property-prop_Ordering xs =- mempty <> toNubList xs' === toNubList xs' <> mempty- where- xs' = nub xs--prop_DeDupe :: [Int] -> Property-prop_DeDupe xs =- fromNubList (toNubList (xs' ++ xs)) === xs' -- Note, we append primeless xs- where- xs' = nub xs--prop_DeDupeR :: [Int] -> Property-prop_DeDupeR xs =- fromNubListR (toNubListR (xs ++ xs')) === xs' -- Note, we prepend primeless xs- where- xs' = nub xs--prop_Nub :: [Int] -> Property-prop_Nub xs = rhs === lhs- where- rhs = fromNubList (toNubList xs)- lhs = nub xs--prop_Identity :: [Int] -> Bool-prop_Identity xs =- mempty `mappend` toNubList xs == toNubList xs `mappend` mempty--prop_Associativity :: [Int] -> [Int] -> [Int] -> Bool-prop_Associativity xs ys zs =- (toNubList xs `mappend` toNubList ys) `mappend` toNubList zs- == toNubList xs `mappend` (toNubList ys `mappend` toNubList zs)
− tests/UnitTests/Distribution/Utils/ShortText.hs
@@ -1,33 +0,0 @@-module UnitTests.Distribution.Utils.ShortText- ( tests- ) where--import Data.Monoid as Mon-import Test.Tasty-import Test.Tasty.QuickCheck--import Distribution.Compat.Binary (encode, decode)--import Distribution.Utils.ShortText--prop_ShortTextOrd :: String -> String -> Bool-prop_ShortTextOrd a b = compare a b == compare (toShortText a) (toShortText b)--prop_ShortTextMonoid :: String -> String -> Bool-prop_ShortTextMonoid a b = Mon.mappend a b == fromShortText (mappend (toShortText a) (toShortText b))--prop_ShortTextId :: String -> Bool-prop_ShortTextId a = (fromShortText . toShortText) a == a--prop_ShortTextBinaryId :: String -> Bool-prop_ShortTextBinaryId a = (decode . encode) a' == a'- where- a' = toShortText a--tests :: [TestTree]-tests =- [ testProperty "ShortText Id" prop_ShortTextId- , testProperty "ShortText Ord" prop_ShortTextOrd- , testProperty "ShortText Monoid" prop_ShortTextMonoid- , testProperty "ShortText BinaryId" prop_ShortTextBinaryId- ]
− tests/UnitTests/Distribution/Utils/Structured.hs
@@ -1,30 +0,0 @@-{-# LANGUAGE CPP #-}-module UnitTests.Distribution.Utils.Structured (tests) where--import Data.Proxy (Proxy (..))-import Distribution.Utils.MD5 (md5FromInteger)-import Distribution.Utils.Structured (structureHash)-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit (testCase, (@?=))--import Distribution.SPDX.License (License)-import Distribution.Types.VersionRange (VersionRange)--#if MIN_VERSION_base(4,7,0)-import Distribution.Types.GenericPackageDescription (GenericPackageDescription)-import Distribution.Types.LocalBuildInfo (LocalBuildInfo)-#endif--import UnitTests.Orphans ()--tests :: TestTree-tests = testGroup "Distribution.Utils.Structured"- -- This test also verifies that structureHash doesn't loop.- [ testCase "VersionRange" $ structureHash (Proxy :: Proxy VersionRange) @?= md5FromInteger 0x39396fc4f2d751aaa1f94e6d843f03bd- , testCase "SPDX.License" $ structureHash (Proxy :: Proxy License) @?= md5FromInteger 0xd3d4a09f517f9f75bc3d16370d5a853a- -- The difference is in encoding of newtypes-#if MIN_VERSION_base(4,7,0)- , testCase "GenericPackageDescription" $ structureHash (Proxy :: Proxy GenericPackageDescription) @?= md5FromInteger 0x2f869c09d0cd2288d55b0455830e5a61- , testCase "LocalBuildInfo" $ structureHash (Proxy :: Proxy LocalBuildInfo) @?= md5FromInteger 0x2d64c99467083bef4a894162a121c467-#endif- ]
− tests/UnitTests/Distribution/Version.hs
@@ -1,656 +0,0 @@-{-# LANGUAGE StandaloneDeriving, DeriveDataTypeable #-}-{-# OPTIONS_GHC -fno-warn-incomplete-patterns- -fno-warn-deprecations- -fno-warn-unused-binds #-} --FIXME-module UnitTests.Distribution.Version (versionTests) where--import Distribution.Compat.Prelude.Internal-import Prelude ()--import Distribution.Version-import Distribution.Types.VersionRange.Internal-import Distribution.Parsec (simpleParsec)-import Distribution.Pretty-import Distribution.Utils.Generic--import Data.Typeable (typeOf)-import Math.NumberTheory.Logarithms (intLog2)-import Text.PrettyPrint as Disp (text, render, hcat- ,punctuate, int, char)-import Test.Tasty-import Test.Tasty.QuickCheck-import qualified Test.Laws as Laws--import Test.QuickCheck.Instances.Cabal ()--import Data.Maybe (fromJust)--versionTests :: [TestTree]-versionTests =- -- test 'Version' type- [ tp "versionNumbers . mkVersion = id @[NonNegative Int]" prop_VersionId- , tp "versionNumbers . mkVersion = id @Base.Version" prop_VersionId2- , tp "(==) = (==) `on` versionNumbers" prop_VersionEq- , tp "(==) = (==) `on` mkVersion" prop_VersionEq2- , tp "compare = compare `on` versionNumbers" prop_VersionOrd- , tp "compare = compare `on` mkVersion" prop_VersionOrd2-- , tp "readMaybe . show = Just" prop_ShowRead- , tp "read example" prop_ShowRead_example-- , tp "normaliseVersionRange involutive" prop_normalise_inv- , tp "parsec . prettyShow involutive" prop_parsec_disp_inv-- , tp "simpleParsec . prettyShow = Just" prop_parse_disp- ]-- ++- zipWith- (\n (rep, p) -> testProperty ("Range Property " ++ show n ++ " (" ++ show rep ++ ")") p)- [1::Int ..]- -- properties to validate the test framework- [ typProperty prop_nonNull- , typProperty prop_gen_intervals1- , typProperty prop_gen_intervals2- --, typProperty prop_equivalentVersionRange --FIXME: runs out of test cases- , typProperty prop_intermediateVersion-- , typProperty prop_anyVersion- , typProperty prop_noVersion- , typProperty prop_thisVersion- , typProperty prop_notThisVersion- , typProperty prop_laterVersion- , typProperty prop_orLaterVersion- , typProperty prop_earlierVersion- , typProperty prop_orEarlierVersion- , typProperty prop_unionVersionRanges- , typProperty prop_intersectVersionRanges- , typProperty prop_differenceVersionRanges- , typProperty prop_invertVersionRange- , typProperty prop_withinVersion- , typProperty prop_foldVersionRange-- -- the semantic query functions- --, typProperty prop_isAnyVersion1 --FIXME: runs out of test cases- --, typProperty prop_isAnyVersion2 --FIXME: runs out of test cases- --, typProperty prop_isNoVersion --FIXME: runs out of test cases- --, typProperty prop_isSpecificVersion1 --FIXME: runs out of test cases- --, typProperty prop_isSpecificVersion2 --FIXME: runs out of test cases- , typProperty prop_simplifyVersionRange1- , typProperty prop_simplifyVersionRange1'- --, typProperty prop_simplifyVersionRange2 --FIXME: runs out of test cases- --, typProperty prop_simplifyVersionRange2' --FIXME: runs out of test cases- --, typProperty prop_simplifyVersionRange2'' --FIXME: actually wrong-- -- converting between version ranges and version intervals- , typProperty prop_to_intervals- --, typProperty prop_to_intervals_canonical --FIXME: runs out of test cases- --, typProperty prop_to_intervals_canonical' --FIXME: runs out of test cases- , typProperty prop_from_intervals- , typProperty prop_to_from_intervals- , typProperty prop_from_to_intervals- , typProperty prop_from_to_intervals'-- -- union and intersection of version intervals- , typProperty prop_unionVersionIntervals- , typProperty prop_unionVersionIntervals_idempotent- , typProperty prop_unionVersionIntervals_commutative- , typProperty prop_unionVersionIntervals_associative- , typProperty prop_intersectVersionIntervals- , typProperty prop_intersectVersionIntervals_idempotent- , typProperty prop_intersectVersionIntervals_commutative- , typProperty prop_intersectVersionIntervals_associative- , typProperty prop_union_intersect_distributive- , typProperty prop_intersect_union_distributive-- -- inversion of version intervals- , typProperty prop_invertVersionIntervals- , typProperty prop_invertVersionIntervalsTwice- ]- where- tp :: Testable p => String -> p -> TestTree- tp = testProperty-- typProperty p = (typeOf p, property p)----- 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--- ]--newtype VersionArb = VersionArb [Int]- deriving (Eq,Ord,Show)---- | 'Version' instance as used by QC 2.9-instance Arbitrary VersionArb where- arbitrary = sized $ \n ->- do k <- choose (0, log2 n)- xs <- vectorOf (k+1) arbitrarySizedNatural- return (VersionArb xs)- where- log2 :: Int -> Int- log2 n | n <= 1 = 0- | otherwise = 1 + log2 (n `div` 2)-- shrink (VersionArb xs) =- [ VersionArb xs'- | xs' <- shrink xs- , length xs' > 0- , all (>=0) xs'- ]-------------------------- Version properties-----prop_VersionId :: [NonNegative Int] -> Bool-prop_VersionId lst0 =- (versionNumbers . mkVersion) lst == lst- where- lst = map getNonNegative lst0--prop_VersionId2 :: VersionArb -> Bool-prop_VersionId2 (VersionArb lst) =- (versionNumbers . mkVersion) lst == lst--prop_VersionEq :: Version -> Version -> Bool-prop_VersionEq v1 v2 = (==) v1 v2 == ((==) `on` versionNumbers) v1 v2--prop_VersionEq2 :: VersionArb -> VersionArb -> Bool-prop_VersionEq2 (VersionArb v1) (VersionArb v2) =- (==) v1 v2 == ((==) `on` mkVersion) v1 v2--prop_VersionOrd :: Version -> Version -> Bool-prop_VersionOrd v1 v2 =- compare v1 v2 == (compare `on` versionNumbers) v1 v2--prop_VersionOrd2 :: VersionArb -> VersionArb -> Bool-prop_VersionOrd2 (VersionArb v1) (VersionArb v2) =- (==) v1 v2 == ((==) `on` mkVersion) v1 v2--prop_ShowRead :: Version -> Property-prop_ShowRead v = Just v === readMaybe (show v)--prop_ShowRead_example :: Bool-prop_ShowRead_example = show (mkVersion [1,2,3]) == "mkVersion [1,2,3]"-------------------------------- VersionRange properties-----prop_normalise_inv :: VersionRange -> Property-prop_normalise_inv vr =- normaliseVersionRange vr === normaliseVersionRange (normaliseVersionRange vr)--prop_nonNull :: Version -> Bool-prop_nonNull = (/= nullVersion)--prop_anyVersion :: Version -> Bool-prop_anyVersion v' =- withinRange v' anyVersion--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_differenceVersionRanges :: VersionRange -> VersionRange -> Version -> Bool-prop_differenceVersionRanges vr1 vr2 v' =- withinRange v' (differenceVersionRanges vr1 vr2)- == (withinRange v' vr1 && not (withinRange v' vr2))--prop_invertVersionRange :: VersionRange -> Version -> Bool-prop_invertVersionRange vr v' =- withinRange v' (invertVersionRange vr)- == not (withinRange v' vr)--prop_withinVersion :: Version -> Version -> Property-prop_withinVersion v v' =- withinRange v' (withinVersion v)- ===- (v' >= v && v' < upper v)- where- upper = alterVersion $ \numbers -> case unsnoc numbers of- Nothing -> []- Just (xs, x) -> xs ++ [x + 1]--prop_foldVersionRange :: VersionRange -> Property-prop_foldVersionRange range =- expandVR range- === foldVersionRange anyVersion thisVersion- laterVersion earlierVersion- unionVersionRanges intersectVersionRanges- range- where- expandVR (MajorBoundVersion v) =- intersectVersionRanges (expandVR (orLaterVersion v)) (earlierVersion (majorUpperBound v))- expandVR (OrEarlierVersion v) =- unionVersionRanges (thisVersion v) (earlierVersion v)- expandVR (OrLaterVersion v) =- unionVersionRanges (thisVersion v) (laterVersion v)- expandVR (UnionVersionRanges v1 v2) =- UnionVersionRanges (expandVR v1) (expandVR v2)- expandVR (IntersectVersionRanges v1 v2) =- IntersectVersionRanges (expandVR v1) (expandVR v2)- expandVR v = v-- upper = alterVersion $ \numbers -> case unsnoc numbers of- Nothing -> []- Just (xs, x) -> xs ++ [x + 1]--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 x xs = and (zipWith (==) (x:xs) 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'---- | Check that our VersionIntervals' arbitrary instance generates intervals--- that satisfies the invariant.----prop_gen_intervals1 :: VersionIntervals -> Property-prop_gen_intervals1 i- = label ("length i ≈ 2 ^ " ++ show metric ++ " - 1")- $ xs === ys- where- metric = intLog2 (length xs + 1)-- xs = versionIntervals i- ys = versionIntervals (mkVersionIntervals 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 -> Property-prop_gen_intervals2 intervals =- toVersionIntervals (fromVersionIntervals intervals) === 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 = mkVersion [0]- maxPoint | null allVersionsUsed = minPoint- | otherwise = alterVersion (++[1]) (maximum allVersionsUsed)- 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 v1 v2 =- mkVersion (intermediateList (versionNumbers v1) (versionNumbers 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 ver1 ver2 = v1 ++ [0] == v2 || v2 ++ [0] == v1- where- v1 = versionNumbers ver1- v2 = versionNumbers ver2------------------------------------- Parsing and pretty printing----prop_parsec_disp_inv :: VersionRange -> Property-prop_parsec_disp_inv vr =- parseDisp vr === (parseDisp vr >>= parseDisp)- where- parseDisp = simpleParsec . prettyShow--prop_parse_disp :: VersionRange -> Property-prop_parse_disp vr = counterexample (show (prettyShow vr')) $- fmap s (simpleParsec (prettyShow vr')) === Just vr'- where- -- we have to strip parens, because arbitrary 'VersionRange' may have- -- too little parens constructors.- s = stripParensVersionRange- vr' = s vr--prop_parse_disp1 :: VersionRange -> Bool-prop_parse_disp1 vr =- simpleParsec (prettyShow vr) == Just (normaliseVersionRange vr)--prop_parse_disp2 :: VersionRange -> Property-prop_parse_disp2 vr =- let b = fmap (prettyShow :: VersionRange -> String) (simpleParsec (prettyShow vr))- a = Just (prettyShow 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 (prettyShow vr)- b = fmap displayRaw (simpleParsec (prettyShow 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 = (simpleParsec (prettyShow 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 = simpleParsec (displayRaw vr)- in- counterexample ("Expected: " ++ show a) $- counterexample ("But got: " ++ show b) $- b == a--displayRaw :: VersionRange -> String-displayRaw =- Disp.render- . cataVersionRange alg . normaliseVersionRange- where-- -- precedence:- -- All the same as the usual pretty printer, except for the parens- alg (ThisVersionF v) = Disp.text "==" <<>> pretty v- alg (LaterVersionF v) = Disp.char '>' <<>> pretty v- alg (EarlierVersionF v) = Disp.char '<' <<>> pretty v- alg (OrLaterVersionF v) = Disp.text ">=" <<>> pretty v- alg (OrEarlierVersionF v) = Disp.text "<=" <<>> pretty v- alg (MajorBoundVersionF v) = Disp.text "^>=" <<>> pretty v- alg (UnionVersionRangesF r1 r2) = r1 <+> Disp.text "||" <+> r2- alg (IntersectVersionRangesF r1 r2) = r1 <+> Disp.text "&&" <+> r2-- dispWild v =- Disp.hcat (Disp.punctuate (Disp.char '.')- (map Disp.int (versionNumbers v)))- <<>> Disp.text ".*"
− tests/UnitTests/Orphans.hs
@@ -1,10 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module UnitTests.Orphans where--#if !MIN_VERSION_base(4,7,0)-import GHC.Fingerprint (Fingerprint (..))--deriving instance Show Fingerprint-#endif
− tests/cbits/rpmvercmp.c
@@ -1,141 +0,0 @@-/*- * This code is taken from the RPM package manager.- *- * RPM is Copyright (c) 1998 by Red Hat Software, Inc.,- * and may be distributed under the terms of the GPL and LGPL.- * See http://rpm.org/gitweb?p=rpm.git;a=blob_plain;f=COPYING;hb=HEAD- *- * The code should follow upstream as closely as possible.- * See http://rpm.org/gitweb?p=rpm.git;a=blob_plain;f=lib/rpmvercmp.c;hb=HEAD- *- * Currently the only difference as a policy is that upstream uses C99- * features and pkg-config does not require a C99 compiler yet.- */--#ifdef HAVE_CONFIG_H-#include "config.h"-#endif--#include <string.h>-#include <ctype.h>-#include <stdlib.h>--/* macros to help code look more like upstream */-#define rstreq(a, b) (strcmp(a, b) == 0)-#define risalnum(c) isalnum((char)(c))-#define risdigit(c) isdigit((char)(c))-#define risalpha(c) isalpha((char)(c))--int rmpvercmp_impl(const char *a, const char *b, char *buf1, char *buf2);--/* compare alpha and numeric segments of two versions */-/* return 1: a is newer than b */-/* 0: a and b are the same version */-/* -1: b is newer than a */-int rpmvercmp(const char * a, const char * b)-{- /* easy comparison to see if versions are identical */- if (rstreq(a, b)) return 0;-- char *buf1 = malloc(strlen(a) + 1);- char *buf2 = malloc(strlen(b) + 1);- - if (!buf1 || !buf2) return 0; // arbitrary-- int r = rmpvercmp_impl(a, b, buf1, buf2);-- free(buf1);- free(buf2);-- return r;-}--int rmpvercmp_impl(const char *a, const char *b, char *str1, char *str2) {- char oldch1, oldch2;- char * one, * two;- int rc;- int isnum;-- strcpy(str1, a);- strcpy(str2, b);-- one = str1;- two = str2;-- /* loop through each version segment of str1 and str2 and compare them */- while (*one && *two) {- while (*one && !risalnum(*one)) one++;- while (*two && !risalnum(*two)) two++;-- /* If we ran to the end of either, we are finished with the loop */- if (!(*one && *two)) break;-- str1 = one;- str2 = two;-- /* grab first completely alpha or completely numeric segment */- /* leave one and two pointing to the start of the alpha or numeric */- /* segment and walk str1 and str2 to end of segment */- if (risdigit(*str1)) {- while (*str1 && risdigit(*str1)) str1++;- while (*str2 && risdigit(*str2)) str2++;- isnum = 1;- } else {- while (*str1 && risalpha(*str1)) str1++;- while (*str2 && risalpha(*str2)) str2++;- isnum = 0;- }-- /* save character at the end of the alpha or numeric segment */- /* so that they can be restored after the comparison */- oldch1 = *str1;- *str1 = '\0';- oldch2 = *str2;- *str2 = '\0';-- /* this cannot happen, as we previously tested to make sure that */- /* the first string has a non-null segment */- if (one == str1) return -1; /* arbitrary */-- /* take care of the case where the two version segments are */- /* different types: one numeric, the other alpha (i.e. empty) */- /* numeric segments are always newer than alpha segments */- /* XXX See patch #60884 (and details) from bugzilla #50977. */- if (two == str2) return (isnum ? 1 : -1);-- if (isnum) {- /* this used to be done by converting the digit segments */- /* to ints using atoi() - it's changed because long */- /* digit segments can overflow an int - this should fix that. */-- /* throw away any leading zeros - it's a number, right? */- while (*one == '0') one++;- while (*two == '0') two++;-- /* whichever number has more digits wins */- if (strlen(one) > strlen(two)) return 1;- if (strlen(two) > strlen(one)) return -1;- }-- /* strcmp will return which one is greater - even if the two */- /* segments are alpha or if they are numeric. don't return */- /* if they are equal because there might be more segments to */- /* compare */- rc = strcmp(one, two);- if (rc) return (rc < 1 ? -1 : 1);-- /* restore character that was replaced by null above */- *str1 = oldch1;- one = str1;- *str2 = oldch2;- two = str2;- }-- /* this catches the case where all numeric and alpha segments have */- /* compared identically but the segment sepparating characters were */- /* different */- if ((!*one) && (!*two)) return 0;-- /* whichever version still has characters left over wins */- if (!*one) return -1; else return 1;-}
− tests/custom-setup/CabalDoctestSetup.hs
@@ -1,498 +0,0 @@--- This is Distribution.Extra.Doctest module from cabal-doctest-1.0.4--- This isn't technically a Custom-Setup script, but it /was/.--{---Copyright (c) 2017, Oleg Grenrus--All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:-- * Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above- copyright notice, this list of conditions and the following- disclaimer in the documentation and/or other materials provided- with the distribution.-- * Neither the name of Oleg Grenrus nor the names of other- contributors may be used to endorse or promote products derived- from this software without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.---}--{-# LANGUAGE CPP #-}-{-# LANGUAGE OverloadedStrings #-}--- | The provided 'generateBuildModule' generates 'Build_doctests' module.--- That module exports enough configuration, so your doctests could be simply------ @--- module Main where------ import Build_doctests (flags, pkgs, module_sources)--- import Data.Foldable (traverse_)--- import Test.Doctest (doctest)------ main :: IO ()--- main = do--- traverse_ putStrLn args -- optionally print arguments--- doctest args--- where--- args = flags ++ pkgs ++ module_sources--- @------ To use this library in the @Setup.hs@, you should specify a @custom-setup@--- section in the cabal file, for example:------ @--- custom-setup--- setup-depends:--- base >= 4 && <5,--- cabal-doctest >= 1 && <1.1--- @------ /Note:/ you don't need to depend on @Cabal@ if you use only--- 'defaultMainWithDoctests' in the @Setup.hs@.----module CabalDoctestSetup (- defaultMainWithDoctests,- defaultMainAutoconfWithDoctests,- addDoctestsUserHook,- doctestsUserHooks,- generateBuildModule,- ) where---- Hacky way to suppress few deprecation warnings.-#if MIN_VERSION_Cabal(1,24,0)-#define InstalledPackageId UnitId-#endif--import Control.Monad- (when)-import Data.List- (nub)-import Data.Maybe- (maybeToList, mapMaybe)-import Data.String- (fromString)-import qualified Data.Foldable as F- (for_)-import qualified Data.Traversable as T- (traverse)-import Distribution.Package- (InstalledPackageId)-import Distribution.Package- (Package (..), PackageId, packageVersion)-import Distribution.PackageDescription- (BuildInfo (..), Executable (..), Library (..),- PackageDescription (), TestSuite (..))-import Distribution.Simple- (UserHooks (..), autoconfUserHooks, defaultMainWithHooks, simpleUserHooks)-#if !MIN_VERSION_Cabal(1,25,0)-import Distribution.Simple.BuildPaths- (autogenModulesDir)-#endif-import Distribution.Simple.Compiler- (PackageDB (..), showCompilerId)-import Distribution.Simple.LocalBuildInfo- (ComponentLocalBuildInfo (componentPackageDeps), LocalBuildInfo (),- compiler, withExeLBI, withLibLBI, withPackageDB, withTestLBI)-import Distribution.Simple.Setup- (BuildFlags (buildDistPref, buildVerbosity), fromFlag)-import Distribution.Simple.Utils- (createDirectoryIfMissingVerbose)-import Distribution.Text- (display, simpleParse)-import System.FilePath- ((</>))--import Data.IORef (newIORef, modifyIORef, readIORef)--#if MIN_VERSION_Cabal(1,25,0)-import Distribution.Simple.BuildPaths- (autogenComponentModulesDir)-#endif-#if MIN_VERSION_Cabal(2,0,0)-import Distribution.Types.MungedPackageId- (MungedPackageId)-import Distribution.Types.UnqualComponentName- (unUnqualComponentName)-#endif--#if MIN_VERSION_Cabal(3,0,0)-import Distribution.Simple.Utils- (findFileEx)-#else-import Distribution.Simple.Utils- (findFile)-#endif--#if MIN_VERSION_Cabal(2,5,0)-import Distribution.Types.LibraryName- (libraryNameString)-#endif--#if MIN_VERSION_directory(1,2,2)-import System.Directory- (makeAbsolute)-#else-import System.Directory- (getCurrentDirectory)-import System.FilePath- (isAbsolute)--makeAbsolute :: FilePath -> IO FilePath-makeAbsolute p | isAbsolute p = return p- | otherwise = do- cwd <- getCurrentDirectory- return $ cwd </> p-#endif--#if !MIN_VERSION_Cabal(3,0,0)-findFileEx :: Verbosity- -> [FilePath] -- ^search locations- -> FilePath -- ^File Name- -> IO FilePath-findFileEx _verbosity = findFile-#endif----- | A default main with doctests:------ @--- import Distribution.Extra.Doctest--- (defaultMainWithDoctests)------ main :: IO ()--- main = defaultMainWithDoctests "doctests"--- @-defaultMainWithDoctests- :: String -- ^ doctests test-suite name- -> IO ()-defaultMainWithDoctests = defaultMainWithHooks . doctestsUserHooks---- | Like 'defaultMainWithDoctests', for 'build-type: Configure' packages.------ @since 1.0.2-defaultMainAutoconfWithDoctests- :: String -- ^ doctests test-suite name- -> IO ()-defaultMainAutoconfWithDoctests n =- defaultMainWithHooks (addDoctestsUserHook n autoconfUserHooks)---- | 'simpleUserHooks' with 'generateBuildModule' prepended to the 'buildHook'.-doctestsUserHooks- :: String -- ^ doctests test-suite name- -> UserHooks-doctestsUserHooks testsuiteName =- addDoctestsUserHook testsuiteName simpleUserHooks---- |------ @since 1.0.2-addDoctestsUserHook :: String -> UserHooks -> UserHooks-addDoctestsUserHook testsuiteName uh = uh- { buildHook = \pkg lbi hooks flags -> do- generateBuildModule testsuiteName flags pkg lbi- buildHook uh pkg lbi hooks flags- }--data Name = NameLib (Maybe String) | NameExe String deriving (Eq, Show)--nameToString :: Name -> String-nameToString n = case n of- NameLib x -> maybe "" (("_lib_" ++) . map fixchar) x- NameExe x -> "_exe_" ++ map fixchar x- where- -- Taken from Cabal:- -- https://github.com/haskell/cabal/blob/20de0bfea72145ba1c37e3f500cee5258cc18e51/Cabal/Distribution/Simple/Build/Macros.hs#L156-L158- --- -- Needed to fix component names with hyphens in them, as hyphens aren't- -- allowed in Haskell identifier names.- fixchar :: Char -> Char- fixchar '-' = '_'- fixchar c = c--data Component = Component Name [String] [String] [String]- deriving Show---- | Generate a build module for the test suite.------ @--- import Distribution.Simple--- (defaultMainWithHooks, UserHooks(..), simpleUserHooks)--- import Distribution.Extra.Doctest--- (generateBuildModule)------ main :: IO ()--- main = defaultMainWithHooks simpleUserHooks--- { buildHook = \pkg lbi hooks flags -> do--- generateBuildModule "doctests" flags pkg lbi--- buildHook simpleUserHooks pkg lbi hooks flags--- }--- @-generateBuildModule- :: String -- ^ doctests test-suite name- -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()-generateBuildModule testSuiteName flags pkg lbi = do- let verbosity = fromFlag (buildVerbosity flags)- let distPref = fromFlag (buildDistPref flags)-- -- Package DBs- let dbStack = withPackageDB lbi ++ [ SpecificPackageDB $ distPref </> "package.conf.inplace" ]- let dbFlags = "-hide-all-packages" : packageDbArgs dbStack-- withTestLBI pkg lbi $ \suite suitecfg -> when (testName suite == fromString testSuiteName) $ do-#if MIN_VERSION_Cabal(1,25,0)- let testAutogenDir = autogenComponentModulesDir lbi suitecfg-#else- let testAutogenDir = autogenModulesDir lbi-#endif-- createDirectoryIfMissingVerbose verbosity True testAutogenDir-- let buildDoctestsFile = testAutogenDir </> "Build_doctests.hs"-- -- First, we create the autogen'd module Build_doctests.- -- Initially populate Build_doctests with a simple preamble.- writeFile buildDoctestsFile $ unlines- [ "module Build_doctests where"- , ""- , "import Prelude"- , ""- , "data Name = NameLib (Maybe String) | NameExe String deriving (Eq, Show)"- , "data Component = Component Name [String] [String] [String] deriving (Eq, Show)"- , ""- ]-- -- we cannot traverse, only traverse_- -- so we use IORef to collect components- componentsRef <- newIORef []-- let testBI = testBuildInfo suite-- -- TODO: `words` is not proper parser (no support for quotes)- let additionalFlags = maybe [] words- $ lookup "x-doctest-options"- $ customFieldsBI testBI-- let additionalModules = maybe [] words- $ lookup "x-doctest-modules"- $ customFieldsBI testBI-- let additionalDirs' = maybe [] words- $ lookup "x-doctest-source-dirs"- $ customFieldsBI testBI-- additionalDirs <- mapM (fmap ("-i" ++) . makeAbsolute) additionalDirs'-- -- Next, for each component (library or executable), we get to Build_doctests- -- the sets of flags needed to run doctest on that component.- let getBuildDoctests withCompLBI mbCompName compExposedModules compMainIs compBuildInfo =- withCompLBI pkg lbi $ \comp compCfg -> do- let compBI = compBuildInfo comp-- -- modules- let modules = compExposedModules comp ++ otherModules compBI- -- it seems that doctest is happy to take in module names, not actual files!- let module_sources = modules-- -- We need the directory with the component's cabal_macros.h!-#if MIN_VERSION_Cabal(1,25,0)- let compAutogenDir = autogenComponentModulesDir lbi compCfg-#else- let compAutogenDir = autogenModulesDir lbi-#endif-- -- Lib sources and includes- iArgsNoPrefix- <- mapM makeAbsolute- $ compAutogenDir -- autogenerated files- : (distPref ++ "/build") -- preprocessed files (.hsc -> .hs); "build" is hardcoded in Cabal.- : hsSourceDirs compBI- includeArgs <- mapM (fmap ("-I"++) . makeAbsolute) $ includeDirs compBI- -- We clear all includes, so the CWD isn't used.- let iArgs' = map ("-i"++) iArgsNoPrefix- iArgs = "-i" : iArgs'-- -- default-extensions- let extensionArgs = map (("-X"++) . display) $ defaultExtensions compBI-- -- CPP includes, i.e. include cabal_macros.h- let cppFlags = map ("-optP"++) $- [ "-include", compAutogenDir ++ "/cabal_macros.h" ]- ++ cppOptions compBI-- -- Unlike other modules, the main-is module of an executable is not- -- guaranteed to share a module name with its filepath name. That is,- -- even though the main-is module is named Main, its filepath might- -- actually be Something.hs. To account for this possibility, we simply- -- pass the full path to the main-is module instead.- mainIsPath <- T.traverse (findFileEx verbosity iArgsNoPrefix) (compMainIs comp)-- let all_sources = map display module_sources- ++ additionalModules- ++ maybeToList mainIsPath-- let component = Component- (mbCompName comp)- (formatDeps $ testDeps compCfg suitecfg)- (concat- [ iArgs- , additionalDirs- , includeArgs- , dbFlags- , cppFlags- , extensionArgs- , additionalFlags- ])- all_sources-- -- modify IORef, append component- modifyIORef componentsRef (\cs -> cs ++ [component])-- -- For now, we only check for doctests in libraries and executables.- getBuildDoctests withLibLBI mbLibraryName exposedModules (const Nothing) libBuildInfo- getBuildDoctests withExeLBI (NameExe . executableName) (const []) (Just . modulePath) buildInfo-- components <- readIORef componentsRef- F.for_ components $ \(Component name pkgs flags' sources) -> do- let compSuffix = nameToString name- pkgs_comp = "pkgs" ++ compSuffix- flags_comp = "flags" ++ compSuffix- module_sources_comp = "module_sources" ++ compSuffix-- -- write autogen'd file- appendFile buildDoctestsFile $ unlines- [ -- -package-id etc. flags- pkgs_comp ++ " :: [String]"- , pkgs_comp ++ " = " ++ show pkgs- , ""- , flags_comp ++ " :: [String]"- , flags_comp ++ " = " ++ show flags'- , ""- , module_sources_comp ++ " :: [String]"- , module_sources_comp ++ " = " ++ show sources- , ""- ]-- -- write enabled components, i.e. x-doctest-components- -- if none enabled, pick library- let enabledComponents = maybe [NameLib Nothing] (mapMaybe parseComponentName . words)- $ lookup "x-doctest-components"- $ customFieldsBI testBI-- let components' =- filter (\(Component n _ _ _) -> n `elem` enabledComponents) components- appendFile buildDoctestsFile $ unlines- [ "-- " ++ show enabledComponents- , "components :: [Component]"- , "components = " ++ show components'- ]-- where- parseComponentName :: String -> Maybe Name- parseComponentName "lib" = Just (NameLib Nothing)- parseComponentName ('l' : 'i' : 'b' : ':' : x) = Just (NameLib (Just x))- parseComponentName ('e' : 'x' : 'e' : ':' : x) = Just (NameExe x)- parseComponentName _ = Nothing-- -- we do this check in Setup, as then doctests don't need to depend on Cabal- isOldCompiler = maybe False id $ do- a <- simpleParse $ showCompilerId $ compiler lbi- b <- simpleParse "7.5"- return $ packageVersion (a :: PackageId) < b-- formatDeps = map formatOne- formatOne (installedPkgId, pkgId)- -- The problem is how different cabal executables handle package databases- -- when doctests depend on the library- --- -- If the pkgId is current package, we don't output the full package-id- -- but only the name- --- -- Because of MungedPackageId we compare display version of identifiers- -- not the identifiers themfselves.- | display (packageId pkg) == display pkgId = "-package=" ++ display pkgId- | otherwise = "-package-id=" ++ display installedPkgId-- -- From Distribution.Simple.Program.GHC- packageDbArgs :: [PackageDB] -> [String]- packageDbArgs | isOldCompiler = packageDbArgsConf- | otherwise = packageDbArgsDb-- -- GHC <7.6 uses '-package-conf' instead of '-package-db'.- packageDbArgsConf :: [PackageDB] -> [String]- packageDbArgsConf dbstack = case dbstack of- (GlobalPackageDB:UserPackageDB:dbs) -> concatMap specific dbs- (GlobalPackageDB:dbs) -> ("-no-user-package-conf")- : concatMap specific dbs- _ -> ierror- where- 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://gitlab.haskell.org/ghc/ghc/-/issues/5977- packageDbArgsDb :: [PackageDB] -> [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-- mbLibraryName :: Library -> Name-#if MIN_VERSION_Cabal(2,5,0)- -- Cabal-2.5 library's name is LibraryName- mbLibraryName = NameLib . fmap display . libraryNameString . libName-#elif MIN_VERSION_Cabal(2,0,0)- -- Cabal-2.0 introduced internal libraries, which are named.- mbLibraryName = NameLib . fmap display . libName-#else- -- Before that, there was only ever at most one library per- -- .cabal file, which has no name.- mbLibraryName _ = NameLib Nothing-#endif-- executableName :: Executable -> String-#if MIN_VERSION_Cabal(2,0,0)- executableName = unUnqualComponentName . exeName-#else- executableName = exeName-#endif---- | In compat settings it's better to omit the type-signature-testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo-#if MIN_VERSION_Cabal(2,0,0)- -> [(InstalledPackageId, MungedPackageId)]-#else- -> [(InstalledPackageId, PackageId)]-#endif-testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys
− tests/custom-setup/CustomSetupTests.hs
@@ -1,8 +0,0 @@--- This test-suite verifies some custom-setup scripts compile ok--- so we don't break them by accident, i.e. when breakage can be prevented.-module Main (main) where-import CabalDoctestSetup ()-import IdrisSetup ()--main :: IO ()-main = return ()
− tests/custom-setup/IdrisSetup.hs
@@ -1,388 +0,0 @@--- This is Setup.hs script from idris-1.1.1--{---Copyright (c) 2011 Edwin Brady- School of Computer Science, University of St Andrews-All rights reserved.--This code is derived from software written by Edwin Brady-(eb@cs.st-andrews.ac.uk).--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions-are met:-1. Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.-2. Redistributions in binary form must reproduce the above copyright- notice, this list of conditions and the following disclaimer in the- documentation and/or other materials provided with the distribution.-3. None of the names of the copyright holders may be used to endorse- or promote products derived from this software without specific- prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN-IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.--*** End of disclaimer. ***---}--{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -w #-}-module IdrisSetup (main) where--#if !defined(MIN_VERSION_Cabal)-# define MIN_VERSION_Cabal(x,y,z) 0-#endif--#if !defined(MIN_VERSION_base)-# define MIN_VERSION_base(x,y,z) 0-#endif--import Control.Monad-import Data.IORef-import Control.Exception (SomeException, catch)-import Data.String (fromString)--import Distribution.Simple-import Distribution.Simple.BuildPaths-import Distribution.Simple.InstallDirs as I-import Distribution.Simple.LocalBuildInfo as L-import qualified Distribution.Simple.Setup as S-import qualified Distribution.Simple.Program as P-import Distribution.Simple.Utils (createDirectoryIfMissingVerbose, notice, installOrdinaryFiles)-import Distribution.Simple.Utils (rewriteFileEx)-import Distribution.Compiler-import Distribution.PackageDescription-import Distribution.Text--import System.Environment-import System.Exit-import System.FilePath ((</>), splitDirectories,isAbsolute)-import System.Directory-import qualified System.FilePath.Posix as Px-import System.Process---- This is difference from vanilla idris-1.1.1-configConfigurationsFlags :: S.ConfigFlags -> [(FlagName, Bool)]-#if MIN_VERSION_Cabal(2,1,0)-configConfigurationsFlags = unFlagAssignment . S.configConfigurationsFlags-#else-configConfigurationsFlags = S.configConfigurationsFlags-#endif--#if !MIN_VERSION_base(4,6,0)-lookupEnv :: String -> IO (Maybe String)-lookupEnv v = lookup v `fmap` getEnvironment-#endif---- After Idris is built, we need to check and install the prelude and other libs---- -------------------------------------------------------------------------------- Idris Command Path---- make on mingw32 exepects unix style separators-#ifdef mingw32_HOST_OS-(<//>) = (Px.</>)-idrisCmd local = Px.joinPath $ splitDirectories $ ".." <//> ".." <//> buildDir local <//> "idris" <//> "idris"-#else-idrisCmd local = ".." </> ".." </> buildDir local </> "idris" </> "idris"-#endif---- -------------------------------------------------------------------------------- Make Commands---- use GNU make on FreeBSD-#if defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS)\- || defined(openbsd_HOST_OS) || defined(netbsd_HOST_OS)-mymake = "gmake"-#else-mymake = "make"-#endif-make verbosity =- P.runProgramInvocation verbosity . P.simpleProgramInvocation mymake--#ifdef mingw32_HOST_OS-windres verbosity = P.runProgramInvocation verbosity . P.simpleProgramInvocation "windres"-#endif--- -------------------------------------------------------------------------------- Flags--usesGMP :: S.ConfigFlags -> Bool-usesGMP flags =- case lookup (mkFlagName "gmp") (configConfigurationsFlags flags) of- Just True -> True- Just False -> False- Nothing -> False--execOnly :: S.ConfigFlags -> Bool-execOnly flags =- case lookup (mkFlagName "execonly") (configConfigurationsFlags flags) of- Just True -> True- Just False -> False- Nothing -> False--isRelease :: S.ConfigFlags -> Bool-isRelease flags =- case lookup (mkFlagName "release") (configConfigurationsFlags flags) of- Just True -> True- Just False -> False- Nothing -> False--isFreestanding :: S.ConfigFlags -> Bool-isFreestanding flags =- case lookup (mkFlagName "freestanding") (configConfigurationsFlags flags) of- Just True -> True- Just False -> False- Nothing -> False--#if !(MIN_VERSION_Cabal(2,0,0))-mkFlagName :: String -> FlagName-mkFlagName = FlagName-#endif---- -------------------------------------------------------------------------------- Clean--idrisClean _ flags _ _ = cleanStdLib- where- verbosity = S.fromFlag $ S.cleanVerbosity flags-- cleanStdLib = makeClean "libs"-- makeClean dir = make verbosity [ "-C", dir, "clean", "IDRIS=idris" ]---- -------------------------------------------------------------------------------- Configure--gitHash :: IO String-gitHash = do h <- Control.Exception.catch (readProcess "git" ["rev-parse", "--short", "HEAD"] "")- (\e -> let e' = (e :: SomeException) in return "PRE")- return $ takeWhile (/= '\n') h---- Put the Git hash into a module for use in the program--- For release builds, just put the empty string in the module-generateVersionModule verbosity dir release = do- hash <- gitHash- let versionModulePath = dir </> "Version_idris" Px.<.> "hs"- putStrLn $ "Generating " ++ versionModulePath ++- if release then " for release" else " for prerelease " ++ hash- createDirectoryIfMissingVerbose verbosity True dir- rewriteFileEx verbosity versionModulePath (versionModuleContents hash)-- where versionModuleContents h = "module Version_idris where\n\n" ++- "gitHash :: String\n" ++- if release- then "gitHash = \"\"\n"- else "gitHash = \"git:" ++ h ++ "\"\n"---- Generate a module that contains the lib path for a freestanding Idris-generateTargetModule verbosity dir targetDir = do- let absPath = isAbsolute targetDir- let targetModulePath = dir </> "Target_idris" Px.<.> "hs"- putStrLn $ "Generating " ++ targetModulePath- createDirectoryIfMissingVerbose verbosity True dir- rewriteFileEx verbosity targetModulePath (versionModuleContents absPath targetDir)- where versionModuleContents absolute td = "module Target_idris where\n\n" ++- "import System.FilePath\n" ++- "import System.Environment\n" ++- "getDataDir :: IO String\n" ++- if absolute- then "getDataDir = return \"" ++ td ++ "\"\n"- else "getDataDir = do \n" ++- " expath <- getExecutablePath\n" ++- " execDir <- return $ dropFileName expath\n" ++- " return $ execDir ++ \"" ++ td ++ "\"\n"- ++ "getDataFileName :: FilePath -> IO FilePath\n"- ++ "getDataFileName name = do\n"- ++ " dir <- getDataDir\n"- ++ " return (dir ++ \"/\" ++ name)"---- a module that has info about existence and location of a bundled toolchain-generateToolchainModule verbosity srcDir toolDir = do- let commonContent = "module Tools_idris where\n\n"- let toolContent = case toolDir of- Just dir -> "hasBundledToolchain = True\n" ++- "getToolchainDir = \"" ++ dir ++ "\"\n"- Nothing -> "hasBundledToolchain = False\n" ++- "getToolchainDir = \"\""- let toolPath = srcDir </> "Tools_idris" Px.<.> "hs"- createDirectoryIfMissingVerbose verbosity True srcDir- rewriteFileEx verbosity toolPath (commonContent ++ toolContent)--idrisConfigure _ flags pkgdesc local = do- configureRTS- withLibLBI pkgdesc local $ \_ libcfg -> do- let libAutogenDir = autogenComponentModulesDir local libcfg- generateVersionModule verbosity libAutogenDir (isRelease (configFlags local))- if isFreestanding $ configFlags local- then do- toolDir <- lookupEnv "IDRIS_TOOLCHAIN_DIR"- generateToolchainModule verbosity libAutogenDir toolDir- targetDir <- lookupEnv "IDRIS_LIB_DIR"- case targetDir of- Just d -> generateTargetModule verbosity libAutogenDir d- Nothing -> error $ "Trying to build freestanding without a target directory."- ++ " Set it by defining IDRIS_LIB_DIR."- else- generateToolchainModule verbosity libAutogenDir Nothing- where- verbosity = S.fromFlag $ S.configVerbosity flags- version = pkgVersion . package $ localPkgDescr local-- -- This is a hack. I don't know how to tell cabal that a data file needs- -- installing but shouldn't be in the distribution. And it won't make the- -- distribution if it's not there, so instead I just delete- -- the file after configure.- configureRTS = make verbosity ["-C", "rts", "clean"]--#if !(MIN_VERSION_Cabal(2,0,0))- autogenComponentModulesDir lbi _ = autogenModulesDir lbi-#endif--#if !MIN_VERSION_Cabal(3,0,0)-idrisPreSDist args flags = do- let dir = S.fromFlag (S.sDistDirectory flags)- let verb = S.fromFlag (S.sDistVerbosity flags)- generateVersionModule verb "src" True- generateTargetModule verb "src" "./libs"- generateToolchainModule verb "src" Nothing- preSDist simpleUserHooks args flags--idrisSDist sdist pkgDesc bi hooks flags = do- pkgDesc' <- addGitFiles pkgDesc- sdist pkgDesc' bi hooks flags- where- addGitFiles :: PackageDescription -> IO PackageDescription- addGitFiles pkgDesc = do- files <- gitFiles- return $ pkgDesc { extraSrcFiles = extraSrcFiles pkgDesc ++ files}- gitFiles :: IO [FilePath]- gitFiles = liftM lines (readProcess "git" ["ls-files"] "")--idrisPostSDist args flags desc lbi = do- Control.Exception.catch (do let file = "src" </> "Version_idris" Px.<.> "hs"- let targetFile = "src" </> "Target_idris" Px.<.> "hs"- putStrLn $ "Removing generated modules:\n "- ++ file ++ "\n" ++ targetFile- removeFile file- removeFile targetFile)- (\e -> let e' = (e :: SomeException) in return ())- postSDist simpleUserHooks args flags desc lbi-#endif---- -------------------------------------------------------------------------------- Build--getVersion :: Args -> S.BuildFlags -> IO HookedBuildInfo-getVersion args flags = do- hash <- gitHash- let buildinfo = (emptyBuildInfo { cppOptions = ["-DVERSION="++hash] }) :: BuildInfo- return (Just buildinfo, [])--idrisPreBuild args flags = do-#ifdef mingw32_HOST_OS- createDirectoryIfMissingVerbose verbosity True dir- windres verbosity ["icons/idris_icon.rc","-o", dir++"/idris_icon.o"]- return (Nothing, [(fromString "idris", emptyBuildInfo { ldOptions = [dir ++ "/idris_icon.o"] })])- where- verbosity = S.fromFlag $ S.buildVerbosity flags- dir = S.fromFlagOrDefault "dist" $ S.buildDistPref flags-#else- return (Nothing, [])-#endif--idrisBuild _ flags _ local- = if (execOnly (configFlags local)) then buildRTS- else do buildStdLib- buildRTS- where- verbosity = S.fromFlag $ S.buildVerbosity flags-- buildStdLib = do- putStrLn "Building libraries..."- makeBuild "libs"- where- makeBuild dir = make verbosity [ "-C", dir, "build" , "IDRIS=" ++ idrisCmd local]-- buildRTS = make verbosity (["-C", "rts", "build"] ++- gmpflag (usesGMP (configFlags local)))-- gmpflag False = []- gmpflag True = ["GMP=-DIDRIS_GMP"]---- -------------------------------------------------------------------------------- Copy/Install--idrisInstall verbosity copy pkg local- = if (execOnly (configFlags local)) then installRTS- else do installStdLib- installRTS- installManPage- where- target = datadir $ L.absoluteInstallDirs pkg local copy-- installStdLib = do- let target' = target -- </> "libs"- putStrLn $ "Installing libraries in " ++ target'- makeInstall "libs" target'-- installRTS = do- let target' = target </> "rts"- putStrLn $ "Installing run time system in " ++ target'- makeInstall "rts" target'-- installManPage = do- let mandest = mandir (L.absoluteInstallDirs pkg local copy) ++ "/man1"- notice verbosity $ unwords ["Copying man page to", mandest]- installOrdinaryFiles verbosity mandest [("man", "idris.1")]-- makeInstall src target =- make verbosity [ "-C", src, "install" , "TARGET=" ++ target, "IDRIS=" ++ idrisCmd local]---- -------------------------------------------------------------------------------- Test---- There are two "dataDir" in cabal, and they don't relate to each other.--- When fetching modules, idris uses the second path (in the pkg record),--- which by default is the root folder of the project.--- We want it to be the install directory where we put the idris libraries.-fixPkg pkg target = pkg { dataDir = target }--idrisTestHook args pkg local hooks flags = do- let target = datadir $ L.absoluteInstallDirs pkg local NoCopyDest- testHook simpleUserHooks args (fixPkg pkg target) local hooks flags---- -------------------------------------------------------------------------------- Main---- Install libraries during both copy and install--- See https://github.com/haskell/cabal/issues/709-main = defaultMainWithHooks $ simpleUserHooks- { postClean = idrisClean- , postConf = idrisConfigure- , preBuild = idrisPreBuild- , postBuild = idrisBuild- , postCopy = \_ flags pkg local ->- idrisInstall (S.fromFlag $ S.copyVerbosity flags)- (S.fromFlag $ S.copyDest flags) pkg local- , postInst = \_ flags pkg local ->- idrisInstall (S.fromFlag $ S.installVerbosity flags)- NoCopyDest pkg local-#if !MIN_VERSION_Cabal(3,0,0)- , preSDist = idrisPreSDist- , sDistHook = idrisSDist (sDistHook simpleUserHooks)- , postSDist = idrisPostSDist-#endif- , testHook = idrisTestHook- }
− tests/hackage/check.sh
@@ -1,25 +0,0 @@-#!/bin/sh--base_version=1.4.0.2-test_version=1.5.6--for setup in archive/*/*/Setup.hs archive/*/*/Setup.lhs; do-- pkgname=$(basename ${setup})- - if test $(wc -w < ${setup}) -gt 21; then- if ghc -package Cabal-${base_version} -S ${setup} -o /dev/null 2> /dev/null; then-- if ghc -package Cabal-${test_version} -S ${setup} -o /dev/null 2> /dev/null; then- echo "OK ${setup}"- else- echo "FAIL ${setup} does not compile with Cabal-${test_version}" - fi- else- echo "OK ${setup} (does not compile with Cabal-${base_version})" - fi- else- echo "trivial ${setup}"- fi--done
− tests/hackage/download.sh
@@ -1,19 +0,0 @@-#!/bin/sh--if test ! -f archive/archive.tar; then-- wget http://hackage.haskell.org/cgi-bin/hackage-scripts/archive.tar- mkdir -p archive- mv archive.tar archive/- tar -C archive -xf archive/archive.tar --fi--if test ! -f archive/00-index.tar.gz; then-- wget http://hackage.haskell.org/packages/archive/00-index.tar.gz- mkdir -p archive- mv 00-index.tar.gz archive/- tar -C archive -xzf archive/00-index.tar.gz--fi
− tests/hackage/unpack.sh
@@ -1,16 +0,0 @@-#!/bin/sh--for tarball in archive/*/*/*.tar.gz; do-- pkgdir=$(dirname ${tarball})- pkgname=$(basename ${tarball} .tar.gz)-- if tar -tzf ${tarball} ${pkgname}/Setup.hs 2> /dev/null; then- tar -xzf ${tarball} ${pkgname}/Setup.hs -O > ${pkgdir}/Setup.hs- elif tar -tzf ${tarball} ${pkgname}/Setup.lhs 2> /dev/null; then- tar -xzf ${tarball} ${pkgname}/Setup.lhs -O > ${pkgdir}/Setup.lhs- else- echo "${pkgname} has no Setup.hs or .lhs at all!!?!"- fi--done
− tests/misc/ghc-supported-languages.hs
@@ -1,97 +0,0 @@--- | A test program to check that ghc has got all of its extensions registered----module Main where--import Language.Haskell.Extension-import Distribution.Text-import Distribution.Simple.Utils-import Distribution.Verbosity--import Data.List ((\\))-import Data.Maybe-import Control.Applicative-import Control.Monad-import System.Environment-import System.Exit---- | A list of GHC extensions that are deliberately not registered,--- e.g. due to being experimental and not ready for public consumption----exceptions = map readExtension []--checkProblems :: [Extension] -> [String]-checkProblems implemented =-- let unregistered =- [ ext | ext <- implemented -- extensions that ghc knows about - , not (registered ext) -- but that are not registered- , ext `notElem` exceptions ] -- except for the exceptions-- -- check if someone has forgotten to update the exceptions list...-- -- exceptions that are not implemented- badExceptions = exceptions \\ implemented- - -- exceptions that are now registered- badExceptions' = filter registered exceptions- - in catMaybes- [ check unregistered $ unlines- [ "The following extensions are known to GHC but are not in the "- , "extension registry in Language.Haskell.Extension."- , " " ++ intercalate "\n " (map display unregistered)- , "If these extensions are ready for public consumption then they "- , "should be registered. If they are still experimental and you "- , "think they are not ready to be registered then please add them "- , "to the exceptions list in this test program along with an "- , "explanation."- ]- , check badExceptions $ unlines- [ "Error in the extension exception list. The following extensions"- , "are listed as exceptions but are not even implemented by GHC:"- , " " ++ intercalate "\n " (map display badExceptions)- , "Please fix this test program by correcting the list of"- , "exceptions."- ]- , check badExceptions' $ unlines- [ "Error in the extension exception list. The following extensions"- , "are listed as exceptions to registration but they are in fact"- , "now registered in Language.Haskell.Extension:"- , " " ++ intercalate "\n " (map display badExceptions')- , "Please fix this test program by correcting the list of"- , "exceptions."- ]- ]- where- registered (UnknownExtension _) = False- registered _ = True-- check [] _ = Nothing - check _ i = Just i---main = topHandler $ do- [ghcPath] <- getArgs- exts <- getExtensions ghcPath- let problems = checkProblems exts- putStrLn (intercalate "\n" problems)- if null problems- then exitSuccess- else exitFailure--getExtensions :: FilePath -> IO [Extension]-getExtensions ghcPath =- map readExtension . lines- <$> rawSystemStdout normal ghcPath ["--supported-languages"]--readExtension :: String -> Extension-readExtension str = handleNoParse $ do- -- GHC defines extensions in a positive way, Cabal defines them- -- relative to H98 so we try parsing ("No" ++ extName) first- ext <- simpleParse ("No" ++ str)- case ext of- UnknownExtension _ -> simpleParse str- _ -> return ext- where- handleNoParse :: Maybe Extension -> Extension- handleNoParse = fromMaybe (error $ "unparsable extension " ++ show str)