Distribution.Package

Cabal-1.22.5.0: A framework for packaging Haskell software

Copyright | Isaac Jones 2003-2004
License | BSD3
Maintainer | cabal-devel@haskell.org
Portability | portable
Safe Haskell | Safe
Language | Haskell98

Distribution.Package

Contents

- Package ids
- Installed package identifiers
- Package keys (used for linker symbols and library name)
- Package source dependencies
- Package classes

Description

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"`.

Synopsis

- newtype PackageName = PackageName {
  - unPackageName :: String
  }
- data PackageIdentifier = PackageIdentifier {
  - pkgName :: PackageName
  - pkgVersion :: Version
  }
- type PackageId = PackageIdentifier
- newtype InstalledPackageId = InstalledPackageId String
- data PackageKey
  - = PackageKey !String !Word64 !Word64
  - | OldPackageKey !PackageId
- mkPackageKey :: Bool -> PackageId -> [PackageKey] -> [(ModuleName, (PackageKey, ModuleName))] -> PackageKey
- packageKeyHash :: PackageKey -> String
- packageKeyLibraryName :: PackageId -> PackageKey -> String
- data Dependency = Dependency PackageName VersionRange
- thisPackageVersion :: PackageIdentifier -> Dependency
- notThisPackageVersion :: PackageIdentifier -> Dependency
- simplifyDependency :: Dependency -> Dependency
- class Package pkg where
  - packageId :: pkg -> PackageIdentifier
- packageName :: Package pkg => pkg -> PackageName
- packageVersion :: Package pkg => pkg -> Version
- class Package pkg => PackageFixedDeps pkg where
  - depends :: pkg -> [PackageIdentifier]
- class Package pkg => PackageInstalled pkg where
  - installedPackageId :: pkg -> InstalledPackageId
  - installedDepends :: pkg -> [InstalledPackageId]

# Package ids

newtype PackageName

Constructors

PackageName |
Fields unPackageName :: String

Instances

Eq PackageName |
Data PackageName |
Ord PackageName |
Read PackageName |
Show PackageName |
Generic PackageName |
Binary PackageName |
NFData PackageName |
Text PackageName |
type Rep PackageName |

data PackageIdentifier

The name and version of a package.

Constructors

PackageIdentifier |
Fields pkgName :: PackageName The name of this package, eg. foo pkgVersion :: Version the version of this package, eg 1.2

Instances

Eq PackageIdentifier |
Data PackageIdentifier |
Ord PackageIdentifier |
Read PackageIdentifier |
Show PackageIdentifier |
Generic PackageIdentifier |
Binary PackageIdentifier |
NFData PackageIdentifier |
Text PackageIdentifier |
Package PackageIdentifier |
type Rep PackageIdentifier |

type PackageId = PackageIdentifier

Type alias so we can use the shorter name PackageId.

# Installed package identifiers

newtype InstalledPackageId

An InstalledPackageId uniquely identifies an instance of an installed package. There can be at most one package with a given `InstalledPackageId` in a package database, or overlay of databases.

Constructors

InstalledPackageId String |

Instances

Eq InstalledPackageId |
Data InstalledPackageId |
Ord InstalledPackageId |
Read InstalledPackageId |
Show InstalledPackageId |
Generic InstalledPackageId |
Binary InstalledPackageId |
Text InstalledPackageId |
type Rep InstalledPackageId |

# Package keys (used for linker symbols and library name)

data PackageKey

A `PackageKey` is the notion of "package ID" which is visible to the compiler. Why is this not a `PackageId`? The `PackageId` is a user-visible concept written explicity in Cabal files; on the other hand, a `PackageKey` may contain, for example, information about the transitive dependency tree of a package. Why is this not an `InstalledPackageId`? A `PackageKey` affects the ABI because it is used for linker symbols; however, an `InstalledPackageId` can be used to distinguish two ABI-compatible versions of a library.

The key is defined to be a 128-bit MD5 hash, separated into two 64-bit components (the most significant component coming first) which are individually base-62 encoded (A-Z, a-z, 0-9).

         key         ::= hash64 hash64
         hash64      ::= [A-Za-z0-9]{11}

The string that is hashed is specified as raw_key:

         raw_key     ::= package_id "n"
                         holes_nl
                         depends_nl
         package_id  ::= package_name "-" package_version
         holes_nl    ::= ""
                       | hole_inst "n" holes_nl
         hole_inst   ::= modulename " " key ":" modulename
         depends_nl  ::= ""
                       | depend "n" depends_nl
         depend      ::= key

The holes list MUST be sorted by the first modulename; the depends list MUST be sorted by the key. holes describes the backing implementations of all holes in the package; depends describes all of the build-depends of a package. A package key MAY be used in holes even if it is not mentioned in depends: depends contains STRICTLY packages which are textually mentioned in the package description.

The trailing newline is MANDATORY.

There is also a variant of package key which is prefixed by a informational string. This key MUST NOT be used in the computation of the hash proper, but it is useful for human-readable consumption.

         infokey     ::= infostring "_" key
         infostring  ::= [A-Za-z0-9-]+

For example, Cabal provides a key with the first five characters of the package name for linker symbols.

Constructors

PackageKey !String !Word64 !Word64 | Modern package key which is a hash of the PackageId and the transitive dependency key. Manually inline it here so we can get the instances we need. Also contains a short informative string
OldPackageKey !PackageId | Old-style package key which is just a `PackageId`. Required because old versions of GHC assume that the `sourcePackageId` recorded for an installed package coincides with the package key it was compiled with.

Instances

Eq PackageKey |
Data PackageKey |
Ord PackageKey |
Read PackageKey |
Show PackageKey |
Generic PackageKey |
Binary PackageKey |
NFData PackageKey |
Text PackageKey |
type Rep PackageKey |

mkPackageKey :: Bool -> PackageId -> [PackageKey] -> [(ModuleName, (PackageKey, ModuleName))] -> PackageKey

Generates a `PackageKey` from a `PackageId`, sorted package keys of the immediate dependencies.

packageKeyHash :: PackageKey -> String

packageKeyLibraryName :: PackageId -> PackageKey -> String

# Package source dependencies

data Dependency

Describes a dependency on a source package (API)

Constructors

Dependency PackageName VersionRange |

Instances

Eq Dependency |
Data Dependency |
Read Dependency |
Show Dependency |
Generic Dependency |
Binary Dependency |
Text Dependency |
type Rep Dependency |

thisPackageVersion :: PackageIdentifier -> Dependency

notThisPackageVersion :: PackageIdentifier -> Dependency

simplifyDependency :: Dependency -> Dependency

Simplify the `VersionRange` expression in a `Dependency`. See `simplifyVersionRange`.

# Package classes

class Package pkg where

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.

Methods

packageId :: pkg -> PackageIdentifier

Instances

Package PackageIdentifier |
Package GenericPackageDescription |
Package PackageDescription |
Package (InstalledPackageInfo_ str) |

packageName :: Package pkg => pkg -> PackageName

packageVersion :: Package pkg => pkg -> Version

class Package pkg => PackageFixedDeps pkg where

Subclass of packages that have specific versioned dependencies.

So for example a not-yet-configured package has dependencies on version ranges, not specific versions. A configured or an already installed package depends on exact versions. Some operations or data structures (like dependency graphs) only make sense on this subclass of package types.

Methods

depends :: pkg -> [PackageIdentifier]

class Package pkg => PackageInstalled pkg where

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`.

Methods

installedPackageId :: pkg -> InstalledPackageId

installedDepends :: pkg -> [InstalledPackageId]

Instances

PackageInstalled (InstalledPackageInfo_ str) |