[Major rewrite of specification
simonpj@microsoft.com**20040429163552] {
hunk ./doc/libraryInfrastructure.sgml 86
-
- What we are trying to achieve
hunk ./doc/libraryInfrastructure.sgml 87
- On a high level, we say that we want the system to help the
- user to install packages (whether they be libraries or applications)
- and their dependencies. The system should work
- with operating-system-level package managers
- (such as &dpkg;, &rpm;, and FreeBSD's Ports system) rather than
- replacing them. For operating systems without the luxury of a
- package manager, we propose to add a Haskell-specific package
- manager.
-
- To accomplish this, we propose a system similar to Python's
- &distutils; () where each
- Haskell tool is distributed with a script () that has a standard command-line
- interface. This script will provide a familiar user interface
- () for compiling, installing, and
- removing packages and their dependencies.
-
- For instance, to install the &hunit; package, the user might
- install it with their package manager, if available
- (apt-get install hunit-hugs for instance) or
- download the source code from the web site, change into the &hunit;
- directory, and type ./Setup.lhs install default,
- which would build and install the &hunit; package for the default
- compiler. Similarly, he might type ./Setup.lhs install
- nhc to install the package for &nhc;.
-
- Other tasks might be necessary to make the package known to
- the system, such as registering it with the &impl; of interest
- (). Such tasks would also be
- performed by this Setup program.
-
-
- Issues Facing Developers
-
- There are a number of issues facing developers of Haskell
- software when they decide to deploy their work.
-
-
-
- Binary incompatibility between Haskell
- Implementations and between versions of some implementations make it
- very difficult to distribute binary libraries: if they are expected
- to work together, all of the libraries on a user's system need to be
- built with the same compiler. This makes it a virtual necessity
- that the source code for a Haskell library be distributed to the end
- user of that library, although other options exist for systems like
- Debian () which have
- auto-builders.
-
- Compilation is difficult: It was noted above that it
- is usually necessary to distribute the source code for Haskell tools
- to the end user. The end user has to compile each Haskell tool they
- use, but the task of compilation is complicated by a plethora of
- preprocessors (such as arrowp and greencard) and interfaces with
- non-Haskell libraries (such as Java, X, C, and GTK). Further, there
- is no way to formally express dependencies between Haskell tools, so
- the users have to visit the home pages of the projects they're
- interested in and find the dependencies.
-
- The &impls; are not completely compatible either:
- They support different extensions, different libraries, different
- binary formats, different flags, and different packaging
- systems.
-
- Given that compilation is difficult in and of
- itself, it is further complicated by a wide variety of target
- platforms that it is desirable to support. These systems may treat
- files differently (copying of files, path names) or have different
- defaults for where to put compiled files or source code to make them
- available to the user. The variety of &impls; and target platforms
- make writing of a generic build system that "just works" very
- difficult.
-
- Having managed to compile and install all of the
- Haskell software they need, if a user installs a new compiler (or
- version thereof), all this work needs to be redone. All of the
- libraries on the system will have to be recompiled to match the
- version of that compiler (this is apparently a bigger problem with
- GHC than with NHC, and not much of a problem with
- Hugs.)
-
-
-
- Compare this to the experience of installing a typical library
- or tool written in C or C++ on a Debian GNU/Linux system: The user
- consults a database of known programs (which is stored on her
- computer) and runs a single command to install that package. The
- package management tool figures out the dependencies, downloads all
- dependencies downloads the package, and installs them in the proper
- order. The packages are already compiled by a set of central
- servers. In fact, there is no reason that this kind of interface
- can't be available to the end user except for the difficulty of
- creating binary packages. (See )
-
- Issues Facing Packagers
-
- There are roughly speaking, three different kinds of
- operating-system package systems: source distributions (FreeBSD,
- Gentoo), binary distributions (Debian, RPM), and language-specific
- distributions (CPAN, XEmacs). What we are proposing to create is a
- language-specific distribution that assists in the creation of both
- source and binary packages for other operating systems.
-
- As mentioned above, it is possible to create an operating
- system package for a Haskell library. Indeed, its no harder to
- create a Haskell package than any other kind of package; Haskell
- packages are harder to maintain, however. For instance, in the
- Debian GNU/Linux system (),
- which is a binary distribution, there is currently no way to express
- that a library needs to be recompiled when a new compiler is
- uploaded to the autobuilders. Currently, the only solution is to
- re-upload library packages to the autobuilders at the same time you
- upload a new &impl;. Similarly for Redhat, binary packages have to
- include the version number for &ghc; that they were compiled
- with.
-
- In a source distribution like FreeBSD (), this isn't a problem, since the
- end user compiles all of their software themselves. However, when the
- end user compiles and installs a new &impl;, all of the libraries
- compiled with the old &impl; will no longer work and need to be
- recompiled. As I understand it, there is currently no means of
- performing this operation automatically.
-
- Emacs / XEmacs presents packagers with some of the same
- issues; they are both, practically speaking, Lisp compilers, and
- incompatible, much like different versions of &impls;. When an
- elisp package is installed on Debian, it gets compiled automatically
- (on the end user's machine) for each version of Emacs / XEmacs that
- is installed. This procedure is orthogonal to the XEmacs Packaging
- System () and is a duplication
- of effort in some cases, but that is really the only way to make it
- work with Debian. This has some ugly properties from Debian's
- standpoint: once compiled, there are files in the operating system
- that the packaging system doesn't know about. These are similar to
- issues that Haskell packagers for Debian will have to face.
-
-
-
- Why We Should Solve This
-
-
-
- We need to evolve a decentralized way of
- distributing libraries. The current model of distributing them with
- the &impls; puts too much strain upon the &impl; authors, and is not
- sustainable in the long-term. If this continues, availability and
- reliability of libraries will suffer, and Haskell itself will suffer
- in the long-term as a rich set of libraries is becoming the standard
- for successful programming languages.
-
- If we can help operating system packagers build
- packages (Debian, RPM, etc.), then we'll have more happy end
- users.
-
- If we lower the cost of evaluating Haskell and
- Haskell tools, more people might try them out.
-
- Many Haskell programs are developed as research
- prototypes and abandoned. The subsequent bitrot makes it difficult
- for the community to take over the projects. Formally specifying
- versioned dependencies and creating a central repository for Haskell
- tools can help solve this problem.
-
- Active participation with the rest of the Free
- Software community (inclusion of Haskell in OS distributions,
- interoperability between Haskell tools and external libraries) can
- bring attention to Haskell and perhaps bring more talented
- developers into The Flock.
-
-
-
-
-
-
-
-
-
-
-
hunk ./doc/libraryInfrastructure.sgml 89
-The Haskell Library Infrastructure
+The Haskell Library Infrastructure: goals
hunk ./doc/libraryInfrastructure.sgml 91
-The Haskell Library Infrastructure (HLI) is a framework and supporting
-code aimed at the above problem. It is Haskell-specific, but independent of
-any particular Haskell implementation (Hugs, GHC, etc) or platform (Unix, Windows, etc).
+The Haskell Library Infrastructure (HLI) has the following main goal:
+to specify a standard way in which a Haskell library can be packaged, so that it is
+easy for consumers to use it, or re-package it,
+regardless of the Haskell implementation or installation platform.
hunk ./doc/libraryInfrastructure.sgml 96
-We use the term ``compiler'' to mean GHC, Hugs, nhc, hbc, etc. Even though
-Hugs isn't really a compiler, the term is less clumsy than ``Haskell implementation''.
+The HLI also
+supports library authors by providing an instrastructure that automates the
+process of building and packaging simple libraries. It is not necessary to use
+this code --- indeed complex libraries may exceed its abilities --- but it should
+handle 75% of the cases with no trouble.
hunk ./doc/libraryInfrastructure.sgml 102
-Packages
-
-A package is the unit of distribution.
-A package has explicit dependencies on other packages.
-
-
-
-What the compilers must implement
-
-The HLI requires that the Haskell implementations be somewhat package-aware.
-This section documents those requirements
-
-Registering a package
-
-Installing a package ultimately involves these steps:
+The HLI serves a number of different people:
hunk ./doc/libraryInfrastructure.sgml 104
-
- Compiling the source files, by invoking the compiler. Even Hugs may require
- some processing (e.g running cpp)
-
+
+ Joe User is simply a Haskell user. He does not download new pacakges. Nevertheless,
+he needs to know about his Haskell compiler's -package flag .
+
+
+
+ Bob the Builder and Sam Sysadmin both download, build,
+ and install new pacakges. The only difference between the two is that Sam has root permission,
+ and can install pacakges in more globally-visible places.
+
+
+
+ Roland RPM, Donald Debian, and Willie Windows
+ build Linux RPM, Debian, and Windows installer packages respectively. (This list is not exhaustive.)
+ They do this as a service for Angela Author, and may know little or nothing about the internal details
+ of the Haskell packages they are wrapping up.
+
+
+
+ Angela Author wants to write a simple Haskell library, and distribute it with
+minimum fuss, in such a way that all the above folk can easily use it.
+
+
+
+ Marcus Makefile is like Angela, but more sophisticated. He has a complicated library,
+and uses makefiles. Still, he wants to arrange that Roland, Donald, Bob, Sam, and Joe don't need to know
+about his internal complexity.
+
+
+
+We describe Angela and Marcus as producers of their packages, and all the others
+as package consumers.
+
+
hunk ./doc/libraryInfrastructure.sgml 139
-
- Copying the compiled files into some place. Typically the compiler
- places no pre-conditions on where "some place" is; instead one
- usually follows the conventions of the host operating system.
-
hunk ./doc/libraryInfrastructure.sgml 140
-
- Registering the package: telling the compiler about the
- existence of the package, and where its files are.
-
-
-In step (c), the compiler records the package information in some
-implementation-specific way; how it does so is not constrained by the HLI.
-To register the package one invokes a compiler-specific program (ghc-pkg,
-hugs-pkg etc), passing it a file describing the package. The format of this
-file is independent of the compiler.
+The Haskell Library Infrastructure: overview
hunk ./doc/libraryInfrastructure.sgml 142
-It must be possible to register many versions of the same package.
+This section summarises the vocabulary and main features of the Haskell Library Infrastructure.
hunk ./doc/libraryInfrastructure.sgml 144
-A complete program
-can include more than one version of the same package. For example, the user might use
-package A:2.1 and B:1.0; but B might use A:1.9.
-
+Packages
hunk ./doc/libraryInfrastructure.sgml 146
-Module imports
-
-
-Installing a package means that subsequent invocations of the compiler will use a module namespace
-augmented by the newly-installed package.
-
-
-By default, the module namespace is populated only by the latest version of a particular package.
-This can be overridden using the -package flag. (Question: what does -package hunit:1.2 -package hunit:1.3 do?
-Does the second override the first? Or are they both in scope? I think the former.)
-
-
-An attempt to import a module that is defined by more than one installed package yields an ambiguous-import
-error, rather like an attempt to use an identifier that is defined by more than one imported module.
-(Comment: there ought be some way to resolve such ambiguities. Per-import qualification? -disable-package X?
--package Y specifies winner?)
-
-
-
-The interface to X-pkg
-
-Each Haskell implementation X must provide an associated program X-pkg which
-allows a user to make a new package known to the compiler, and to ask what packages it knows.
+A package is the unit of distribution for HLI.
+Each package has a package description (PD)
+that consists of:
hunk ./doc/libraryInfrastructure.sgml 150
-X-pkg register hunit-config
-or
- X-pkg register < hunit-config.
-
- The syntax of the package install configuration, here hunit-config, is given below.
+A globally-unique package name, containing no spaces. Chaos will result
+if two distinct packages with the same name are installed on the same system.We need a
+global web server where authors can claim and record package names.
hunk ./doc/libraryInfrastructure.sgml 154
-
-
- X-pkg query "hunit"
-
- returns the version(s) of all hunit packages, latest version first.
+A version, consisting of a sequence of one or more integers.
hunk ./doc/libraryInfrastructure.sgml 158
-X-pkg query "hunit" 4.3.1
-
- returns the package install configuration of hunit 4.3.1, in the same syntax
- understood by X-pkg register, if it exists; or
- the empty string otherwise.
-
-
-
+A list of explicit dependencies on other packages. These are typically not exact; e.g. "I need hunit version
+greater than 2.4".
+
+
+
+A list of exposed modules. Not all of the modules that comprise a package implementation are necessarily
+exposed to a pacakge client.
+The ability to expose some, but not all, of the modules making up a package
+is rather like using an explicit export list on a Haskell module.
+
+
+More detailed information about the make-up of the package and how to build it.
+The full details are given in .
+
+
+The first two components can be combined to form a single text string called the package ID,
+using a hyphen to separate the version
+from the name, and dots to separate the version components. For example, "hunit-2.3".
+
hunk ./doc/libraryInfrastructure.sgml 178
-Syntax of package install configuration
+
hunk ./doc/libraryInfrastructure.sgml 180
-...include the list of ``externally visible modules''.
-
-
+Package distributions
hunk ./doc/libraryInfrastructure.sgml 182
-
-Installing a package: the end user viewpoint
-
-Joe User wants to install a new Haskell library, say HUnit, for GHC. How he does this depends on
-how the library is packaged:
-
-Debian:
- Joe says:
-
- apt-get install hunit-ghc
-
-And that's all.
-Any packages that hunit-ghc depends on are automatically installed as well.
-
-
-Linux RPM:
- Joe says:
-...
-(Dependencies?)
-
-
-Windows installer:
-
-Joe downloads hunit-ghc.msi, and double-clicks on it.
-(Dependencies?)
-
-
-Binary tar-ball:
-
-A binary tarball is a bunch of files, already precompiled and ready to install.
-Joe downloads hunit-ghc.tar, unpacks the tarball in some temporary location, cd's to the root directory
-and says
-
- ./setup.hs install
-
-or
-
- runhugs setup.hs install
-
-(or whatever is necessary to run the setup.hs Haskell script).
-The script setup.hs does whatever is necessary to install the library.
-
-
-(Dependencies?)
-
-
-Source tar-ball:
-
-A source tarball contains the library sources, which may need to be
+A HLI package can be distributed in several forms:
+
+
+A HLI source distribution is a tree of files (tar-ball, zip file etc)
+containing the library sources, which may need to be
hunk ./doc/libraryInfrastructure.sgml 188
-Haskell implementations. Joe downloads and unpacks the tarball hunit-src.tar, and then says
-
- ./setup.hs configure ghc
- ./setup.hs build
- ./setup.hs install
-
-The configuration step checks at least that (a) the package author indeed intends the package to be buildable
-with GHC, and that a sufficiently up-to-date GHC is available, and (b) checks that the packages on which
-hunit depends are already installed for GHC. After that the build and install steps know what
-compiler they are using.
-
-Question: can you abbreviate to setup install ghc?
-
-
-
+Haskell implementations.
+
+A source distribution may contain fewer files than appear in the developer's CVS repository; for example,
+design notes may be omitted. It may also contain some derived files, that do not appear in the
+the developer's repository; for example, ones made by a somewhat exotic pre-processor where it
+seems simpler to ship the derived file than to ensure that all consumers have the pre-processor.
+
+
+A HLI binary distribution is a tree of files that contains a pre-compiled library, ready
+for installation. The pre-compilation means that the distribution will be Haskell-compiler-specific.
+
+
+
+The library may be packaged as an RPM, Debian distribution,
+or Windows installer. (This list is not exhaustive.)
+In that case, the way it is installed is prescribed by the respective distribution mechanism;
+the only role of the HLI is to make it easy to construct such distributions. All three are
+compiler-specific binary distributions.
+
+
+
+
hunk ./doc/libraryInfrastructure.sgml 211
-setup targets
+Compilers
hunk ./doc/libraryInfrastructure.sgml 213
-
-Here is a specification of the complete command-line interface for the setup.hs program
-that must be delivered with a package:
+We use the term ``compiler'' to mean GHC, Hugs, nhc, hbc, etc. (Even though
+Hugs isn't really a compiler, the term is less clumsy than ``Haskell implementation''.)
+
+ The
+HLI requires that a conforming Haskell compiler is somewhat package aware.
+In summary, the requirements are these:
hunk ./doc/libraryInfrastructure.sgml 220
-
-setup configure
- --with-compiler=ghc/hugs/nhc
- --with-compiler-flags=-O
- --prefix = xxx
- -- what else?
+Each compiler hc must provide an associated package-management
+program hc-pkg. A compiler user installs a package by placing the package's
+supporting files somewhere, and then using hc-pkg to make the compiler aware
+of the new package.
hunk ./doc/libraryInfrastructure.sgml 225
-
-
-setup build
+Subsequent invocations of hc will include modules from the
+new package in the module name space (i.e. visible to imnport statements).
hunk ./doc/libraryInfrastructure.sgml 228
-
hunk ./doc/libraryInfrastructure.sgml 229
-setup install
+The compiler should support a -package flag for finer-grain control
+of package visibility.
hunk ./doc/libraryInfrastructure.sgml 233
-It is expected that setup.hs will record the results of setup configure
-in a file (and in a format) of its choosing.
-
-
+A complete specification of these requirements is given in .
+
+
hunk ./doc/libraryInfrastructure.sgml 237
-Building a package: the author's viewpoint
+The Setup script
hunk ./doc/libraryInfrastructure.sgml 239
-Angela Author has written a bunch of Haskell modules that she wants to package as a library.
-What does she have to do?
-She must simply build a package that can be installed as described above: nothing else is prescribed.
-However, the HLI provides support for library authors to make it easy to fulfil these requirements.
-
+The key question is this: how should Angela Author present her HLI package so that her consumers (from
+Bob, Sam, Willie, etc) can conveniently use it?
hunk ./doc/libraryInfrastructure.sgml 242
-The Makefile route
-
-If Angela is happy with make, then she can build the library entirely using make.
-
-To support this, HLI provides a trivial implementation of setup.hs, setup-make.hs, which
-simply parses the command line arguments and shells out into make. Thus,
+Answer: she provides a tree of files, with the file Setup.lhs in the
+root directory of the tree. Setup.lhs is an executable Haskell program
+which conforms to a particular specification, given in detail in .
+In summary, though, Setup.lhs allows a consumer to configure, build,
+install, register, and un-register a package.
+ For example, consider a package hunit-2.3.
+Bob the Builder downloads and unpacks a source tar-ball into a temporary directory,
+cd's to root directory, and
hunk ./doc/libraryInfrastructure.sgml 251
- setup configure --with-compiler=ghc
+ ./Setup.lhs configure --ghc
+ ./Setup.lhs build
+ ./Setup.lhs install
hunk ./doc/libraryInfrastructure.sgml 255
-invokes
-
- make configure HC=ghc
-
-Similarly
-setup build
-invokes
-make build And so on.
+The configuration step checks, for example, that the package author indeed intends the package to be buildable
+with GHC, that a sufficiently up-to-date GHC is available, that the packages on which
+hunit-2.3 depends are already installed for GHC, and so on.
+After that the build and install steps know what
+compiler they are using.
+
+Question: can you abbreviate to Setup install ghc?
+
+In principle, the Setup program
+could be written in any language; see for why we use Haskell.
+
hunk ./doc/libraryInfrastructure.sgml 267
-Angela simply arranges that when her makefiles build a distribution, they include this simple setup.hs in
-the root of the distribution, where the Joe User expects to find it.
-
+
hunk ./doc/libraryInfrastructure.sgml 269
-The simple build infrastructure
+Help for building packages
hunk ./doc/libraryInfrastructure.sgml 271
-
-In many cases, though, a Haskell package will consist of nothing more than a bunch of Haskell modules,
-with perhaps the odd C file. In that case, the HLI provides a simple build infrastructure that
-completely replaces make. (Think hmake.) The emphasis is on ``simple'': it deals with the 90\% case only.
-If you want something more elaborate, you can (a) modify the simple build infrastructure (which is written in Haskell)
-(b) use makefiles, or (c) implement something else entirely.
-
-The simple build infrastructure works as follows. Angela puts the following Hasell file setup.hs in the
-root of her tree:
+The HLI allows a package author to write the setup script in any way she pleases, provided
+it conforms to the speciication of . However, many Haskell packages consist
+of little more than a bunch of Haskell modules, and for these the HLI provides a library that does
+all the work.
+For example, suppose Angela Author has a bunch of Haskell modules Angela.Set,
+Angela.Bag, and Angela.Internals, that she wants to
+turn into a package. All she need do is write the setup script
hunk ./doc/libraryInfrastructure.sgml 279
- module Main where
- import Distribution.Setup.Simple
+ #! runhugs
+ import Distribution.Simple
+
+ pkgDescr = PD { name = "angela",
+ version = [1],
+ modules = ["Angela.Set", "Angela.Bag"] }
hunk ./doc/libraryInfrastructure.sgml 286
- pkgInfo :: PkgInfo
- pkgInfo = ....
-
- main = setup pkgInfo
+ main = setup pkgDescr
hunk ./doc/libraryInfrastructure.sgml 288
-Here PkgInfo is a data structure that describes the package: its name, version, dependencies, and so on (Section ...).
-It is not the same as the package install configuration described in Section XXX; the latter describes a particular
-installation (e.g. where the files are), while PkgInfo gives only installation-independent information.
-
-Now Angela can build her package by saying
-
- setup.hs build
-
-She can even install it on her ownn machine by saying
-
- setup.hs install
-
-She can build a source tarball:
-
- setup.hs source-tarball
-
-The full details are given in Section YYYY.
-
-It is no coincidence that the interface is very similar to that described for a package tarball (Section ZZZ).
-In fact, Distribution.Setup.Simple.setup conforms to the specification of Section ZZZ, and when it builds
-a tarball, it includes ./setup.hs in the tarball, ready to be run by Joe User.
-However, Distribution.Setup.Simple.setup of course implements a richer interface than that required by
-Section ZZZ, becuase it's intended to support Angela as well as Joe.
-The full specification is in Section SSSS.
+She tar's it up and that's her source distribution.
hunk ./doc/libraryInfrastructure.sgml 290
+The details of Distribution.Simple are given in .
+
+
hunk ./doc/libraryInfrastructure.sgml 294
-PkgInfo
hunk ./doc/libraryInfrastructure.sgml 295
-...describe PkgInfo...
-
-Which compiler flags does she put in the compiler-flags part of PkgInfo, and which does she
-pass to setup configure? Answer: the package should compile in a sensible way using only the
-former. The latter are just for build-specific modification (e.g. make a debug build).
-
-
-Distribution.Setup.Simpl.setup
-
-Command line interface to the simple build infrastructure.
-
-
-
-
-RPMs and Debian packages
-
-How do we build these?
-
-
-
-
-
- A Solution for Haskell in Haskell
-
- As mentioned above, the foremost user interface for this
- system will be a Haskell program to be executed by the default
- &impl;. This Haskell program, Setup.lhs, will
- perform the tasks of building the package (where necessary),
- installing the package, and making the package available to the
- system.
-
-
- The Module Design
- I propose a set of modules based on these three major tasks:
-
-
-
- &DistBuild;: For tasks of preparing the package for
- installation, including tasking compilers and creating packages for
- systems like Debian ().
-
- &DistInstall;: For moving the distribution files
- into place ().
-
- &DistPackage;: For
- accessing the database of installed packages, versions, etc. Might
- also be responsible for removing packages ().
-
- &DistConfigure;: For discovering details about the
- configuration of the target system not covered by the database of
- installed packages. These are tasks typically performed by tools
- such as &autoconf; ().
-
- Distribution: For general
- purpose elements that don't fit into any of the above
- categories.
-
-
-
hunk ./doc/libraryInfrastructure.sgml 296
- But Why Should We Use Haskell?
+ But Why Should We Use Haskell?
hunk ./doc/libraryInfrastructure.sgml 298
-It is very appropriate that this solution be implemented in
-Haskell:
-
+The setup script, Setup.lhs, is written in Haskell. Why?
hunk ./doc/libraryInfrastructure.sgml 331
-
+It is convenient for consumers to execute Setup.lhs directly, thus:
+
+ ./Setup.lhs ...
+
+This can be achieved by starting Setup.lhs with "#! runhugs".
+Since it's a literate Haskell script (.lhs file), the Haskell compiler will ignore
+this line.
+However, nothing stops a consumer from running the script interactively, or compiling it and running
+the compiled binary. Any implementation of Haskell should suffice to run the script, provided
+the implementation has the HLI libraries installed.
+
+ We should provide runghc.
+
+
hunk ./doc/libraryInfrastructure.sgml 346
-
- Setup.lhs Command-Line Interface
+
hunk ./doc/libraryInfrastructure.sgml 348
- The purpose of the Setup script is to provide a standard
- interface to end users and layered tools. For any particular
- application, the script may be implemented in a variety of ways:
- For pure Haskell applications, the &distMod; should perform all
- of the heavy lifting, requiring only a few lines of code from the
- developer. For applications that feel they need a complete and
- robust make-based system, the Setup script can wrap such a
- system.
+Package consumers and the setup script
hunk ./doc/libraryInfrastructure.sgml 350
- One of the early design tasks of this project should be to decide
- on a format for the command-line interface of the Setup script,
- but here is an example of how it might behave:
-
-
Setup.lhs interface
+
+The sole requirement of an HLI package is that it should contain a setup script, Setup.lhs,
+in the root of its file structure. This section
+specifies the complete command-line interface for the setup script, and how it satisfies the needs of
+package consumers.
hunk ./doc/libraryInfrastructure.sgml 356
+The setup script specification
+
+Here is the command-line interface the setup script must satisfy.
+
setup.lhs interface
+
hunk ./doc/libraryInfrastructure.sgml 364
- Output package configuration
- information
+ Output the package description.
+
hunk ./doc/libraryInfrastructure.sgml 368
- ./Setup.lhs build all
- Compile / prepare this package for
- all installed &impls;
+ ./Setup.lhs configure
+ Prepare to build the package. Typically, this step checks
+ that the target platform is capable of building the package, and
+ discovers platform-specific features that are needed during the build.
+
hunk ./doc/libraryInfrastructure.sgml 375
- ./Setup.lhs build default
- Compile / prepare this package for
- the default &impl;
+ ./Setup.lhs build
+ Build the package, ready for installation. For a true compiler,
+ this step involves compiling the Haskell source code. Even for an interpreter, however,
+ it may involve running a pre-processor.
hunk ./doc/libraryInfrastructure.sgml 380
- ./Setup.lhs build {&nhc;,&ghc;,&hugs;, ...}
-
hunk ./doc/libraryInfrastructure.sgml 381
- Compile / prepare this package for
- the given &impl;
+ ./Setup.lhs install
+ Copy the files into the install locations, and register
+ the package with the compiler.
hunk ./doc/libraryInfrastructure.sgml 385
- ./Setup.lhs install {all,default,&nhc;,&ghc;,&hugs;,...}
- Install this package.
+
+ ./Setup.lhs register
+ ./Setup.lhs unregister
+
+
+ Register (or un-register) this package with the
+ compiler. (NB: registration is also done automatically by install.)
+
hunk ./doc/libraryInfrastructure.sgml 394
- ./Setup.lhs register
- {all,default,&nhc;,&ghc;,&hugs;,...}
- Register this package with the
- package management system (making it available to
- the given &impl;.)
-
- ./Setup.lhs bdist_{deb,rpm,...}
- Create a binary distribution package
- for Debian, RPM, etc.
-
- ./Setup.lhs sdist
- Create a source distribution
- archive.
-
hunk ./doc/libraryInfrastructure.sgml 399
+
hunk ./doc/libraryInfrastructure.sgml 401
- Other commands may be available, and it is important to
- anticipate commands that may some day be desirable.
+setup info
hunk ./doc/libraryInfrastructure.sgml 403
-
+The command ./Setup.lhs info outputs the package description on the
+standard output, in the format given below. This the only concrete way in which the package
+descrption appears in the HLI: Angela Author does not write a file containing the package description.
+
+Insert package desription syntax here.
+
+NB: the package descrpition is not the same as an installed package description ();
+the latter describes a particular
+installation (e.g. where the files are), while PkgDescr gives only installation-independent information.
+
hunk ./doc/libraryInfrastructure.sgml 414
-
+
hunk ./doc/libraryInfrastructure.sgml 416
- An Example Setup.lhs Script
+setup configure
hunk ./doc/libraryInfrastructure.sgml 418
- Here's what the setup script might look like for HUnit, which
- has no complex dependencies.
+The command ./Setup.lhs configure prepares
+to build the package. For sophisticated packages, the configure step
+may perform elaborate checks, to gather information about the target
+system. It may write a file to record its results, but the name and
+format of the file are not part of the specification.
+
+
+All flags are optional. The flags are these:
+
+--with-compiler=path,
+--ghc,
+--nhc,
+--hugs:
+specifies which compiler to use. At most one of these flags may be specified.
+The configure step checks
+that the compiler is available, in a sufficiently up-to-date form for the package, and that the package
+expects to work with that compiler. If the compiler name
+is not specified, setup will choose one; some packages will come with one compiler baked in.
+
+
+--prefix=path: specifies where the installed files
+for the package should be installed. Typically on Unix this will be /usr/local and
+on Windows it will be Program Files. The setup script will use a sensible default
+(often platform-specific) if the flag is not specified.
+
+
+
+It is OK for these flags to be "baked into" the compiled library. In particular, the build system may
+bake the installation path into the compiled files. There is no provision for installing the compiled
+files anywhere other than the place specified in the configure step.
+
+
hunk ./doc/libraryInfrastructure.sgml 451
-#!/usr/bin/env haskell
-import Distribution.Core
-import Distribution.Package
+setup build
hunk ./doc/libraryInfrastructure.sgml 453
-toolInfo = (defaultPackage "HUnit"
- (NumberedVersion 1 0 0))
- {haskellSources=[
- "HUnitLang98.lhs","HUnitLangExc.lhs", "Info.lhs",
- "Terminal.lhs", "HUnitTest98.lhs", "TerminalTest.lhs",
- "HUnit.lhs", "HUnitTestBase.lhs", "HUnitBase.lhs",
- "HUnitTestExc.lhs", "HUnitLang.lhs", "HUnitText.lhs",
- "Setup.lhs"],
- docs = ["Example.hs", "Guide.html", "License", "README"]}
+The command ./Setup.lhs build builds the
+package, ready for installation. It takes no flags.
hunk ./doc/libraryInfrastructure.sgml 456
-main = defaultMain toolInfo id id
--- Those last to parameters might be pre-install and post-install functions
-
+
hunk ./doc/libraryInfrastructure.sgml 458
-defaultMain would implement all of the
-standard command-line flags, and defaultPackage is a template with
-sane default values for most fields.
+setup install
hunk ./doc/libraryInfrastructure.sgml 460
-
+The command ./Setup.lhs install copies files from the built package to
+the right location for installed files, specified in the configure step. Then it registers the new package with
+the compiler, using the hc-pkg command.
+
+--install-prefix=path has three effects.
+First, it over-rides the --prefix flag specified in the configure step,
+providing an alternative location. Second, it does not call hc-pkg to register the package.
+Instead, third, it creates an installed package description file, installed-pkg-descr,
+which can later be fed to hc-pkg.
+
+The reason for all this is that Roland RPM wants to create an exact installation tree, all ready
+to bundle up for the target machine, but in a temporary location. He cannot use
+this location for --prefix in the configure step, because that
+might bake the wrong path into some compiled files. Nor does he want to register this temporary tree with the compiler
+on his machine. Instead, he bundles up the temporary installation tree, plus the installed-pkg-descr,
+and ships them all to the target machine. When they are installed there, the post-installation script runs
+hc-pkg on the installed-pkg-descr file.
+
+
hunk ./doc/libraryInfrastructure.sgml 480
-
+--shared: if present, this flag is passed to hc-pkg
+so that the package is registed as shared. This flag has no effect if --install-prefix is
+used, because in that case hc-pkg is not called.
+
+
+
hunk ./doc/libraryInfrastructure.sgml 487
- Distribution Module
+
hunk ./doc/libraryInfrastructure.sgml 489
-
+
hunk ./doc/libraryInfrastructure.sgml 491
-&DistBuild;
+setup register and setup unregister
hunk ./doc/libraryInfrastructure.sgml 493
-The basic strategy we will take for the actual task of building
-Haskell tools is as follows:
-
+The command ./Setup.lhs register registers the now-installed package with the compiler.
+Similarly, ./Setup.lhs unregister un-registers the package.
hunk ./doc/libraryInfrastructure.sgml 496
+--shared: registers/un-registers a shared package as shared.
+The default is to treat the package as a user package.
+
+
+
hunk ./doc/libraryInfrastructure.sgml 502
- For simple tools like Haskell modules, leverage
- &hmake;'s () abilities and create a Haskell-based
- system (which will evolve to do more complex
- tasks.)
+
+
hunk ./doc/libraryInfrastructure.sgml 505
- Tools that require something more complex can use
- ``fptools'' or Yale's Make-based system (), or use their own build
- system.
+Bob the Builder and Sam Sysadmin
hunk ./doc/libraryInfrastructure.sgml 507
- All systems will be wrapped in a common veneer
- () so they look the same to the average
- user and to layered tools ()
- and so that once &DistBuild; evolves to be a more robust tool,
- packages can transition to using it without effecting the interface
- to their build system.
+Bob the Builder can install a HLI source distribution thus.
+He downloads the source distribution and unpacks it into a temporary directory,
+cd's to that directory, and says
+
+ ./Setup.lhs configure --ghc
+ ./Setup.lhs build
+ ./Setup.lhs install
+
+Similarly, Sam Sysadmin does exactly the same, except that he says
+
+ ./Setup.lhs install --shared
+
+in the final step, so that the package is installed where all users will see it.
+
+For a binary distribution, both Bob and Sam would omit the first two steps, and just do the install step.
+
hunk ./doc/libraryInfrastructure.sgml 524
-
+System packagers (Debian, RPM etc)
+
+System packagers, such as Donald Debian, will run the configure and build steps just like Bob and Sam.
+A that point, Donald will say
+
+ ./Setup.lhs install --install-prefix=/tmp/donald
+
+to construct a ready-to-zip tree of all the installed files, plus a file installed-pkg-descr
+that describes the installed package. He arranges to deliver both these components to the target machine,
+and then feed installed-pkg-descr to hc-pkg on the target machine.
+
hunk ./doc/libraryInfrastructure.sgml 536
-Since it is obviously the compilers that do the actual compilation,
-the task of &DistBuild; is more one of coordination among tools
-outside the compiler. We hope to offer support for preprocessors
-(both existing and those yet to come). &DistBuild; will handle the
-task of compiling for a particular &impl;, or for all installed
-&impls;, and help to abstract-away differences between command-line
-flags.
+The file installed-pkg-descr also contains information he needs for building
+his Debian distribution, namely the
+package name, version, and (exact) dependencies.
+
+
+
hunk ./doc/libraryInfrastructure.sgml 543
-&DistBuild; could also be used to recompile all of the installed
-libraries once a new &impl; is installed. This is an important
-function, as it solves the problem of binary incompatibility between
-&impls; and versions thereof. Another very useful function that
-&DistBuild; could offer is the implementation of a generic
-/usr/bin/haskell that either executes a Haskell
-program using the default compiler or throws the user into the default
-interpreter, depending upon how it is invoked. This allows Haskell
-scripts (such as Setup.lhs) to be distributed with a
-#!/usr/bin/env haskell annotation that has reasonable
-behavior.
+HLI support for building a package: the author's viewpoint
hunk ./doc/libraryInfrastructure.sgml 545
-
+Angela Author has written a bunch of Haskell modules that she wants to package as a library.
+What does she have to do?
+She must simply build a package that can be installed as described above: nothing else is prescribed.
+However, the HLI provides support for library authors to make it easy to fulfil these requirements.
+
hunk ./doc/libraryInfrastructure.sgml 551
-
- &DistInstall;
+The Makefile route
hunk ./doc/libraryInfrastructure.sgml 553
- The &DistInstall; module performs the task of moving files
- into place. Presumably, this is the last task before package
- registration. &DistInstall; will have to understand configuration
- options for the operating systems that Haskell modules are being
- installed on. (For instance, different operating systems have different
- policies for where to put documentation, source code, binary files,
- and libraries.) Such information will most likely be read from a
- file that can be edited by the system administrator ().
+Marcus Makefile is happy with make,
+and he can build the library entirely using make.
hunk ./doc/libraryInfrastructure.sgml 556
- Not only will this module have to support standards on
- different operating systems, but it must have access to filesystem
- functionality like copy and
- move, as well as permission-related operations.
- Such functions should be offered by a library such as
- System.Posix.Files and
- System.Directory, but the
- System.Posix module is not available on all
- operating systems. To some extent, &DistInstall; should handle the
- differences between operating systems (file permissions for
- instance), but Haskell should offer a more robust set of file
- operations in order to encourage the use of Haskell for common
- scripting tasks. (One issue that the author has noticed is that
- System.Directory.renameDirectory is not
- implemented the same in GHC and Hugs, which forces &DistInstall; to
- find a way to abstract the differences.)
+To support this, HLI provides a trivial setup library Distribution.Make, which
+simply parses the command line arguments and shells out into make. Marcus uses the following
+Setup.lhs
+
+ module Main where
+ import Distribution.Make
+ main = setup
+
+All the package description information is assumed to be known to the makefile system, and so does not
+appear in the setup script.
+Thus,
+
+ setup configure --ghc
+
+invokes
+
+ ./configure --with-hc=ghc
+
+Similarly
+setup build
+invokes
+make all And so on.
hunk ./doc/libraryInfrastructure.sgml 579
-
+Marcus simply arranges that when his makefiles build a distribution, they include this simple setup script in
+the root of the distribution, where the Bob the Builder expects to find it.
+
hunk ./doc/libraryInfrastructure.sgml 583
-
- &DistPackage;
+The simple build infrastructure
hunk ./doc/libraryInfrastructure.sgml 585
- The complex task of packaging requires a lot of attention.
- The proposed solution is not only a module to access the packaging
- information, but also an application to assist external systems with
- the same task:
+
+In many cases, though, a Haskell package will consist of nothing more than a bunch of Haskell modules,
+with perhaps the odd C file. In that case, the HLI provides a simple build infrastructure that
+completely replaces make. (Think hmake.) The emphasis is on ``simple'': it deals with the 90% case only.
+If you want something more elaborate, you can (a) modify the simple build infrastructure (which is written in Haskell)
+(b) use makefiles, or (c) implement something else entirely.
+
+The simple build infrastructure works as follows. Angela puts the following Hasell file setup.hs in the
+root of her tree:
+
+ module Main where
+ import Distribution.Simple
hunk ./doc/libraryInfrastructure.sgml 598
- The main features of this system are:
+ pkgDescr :: PkgDescr
+ pkgDescr = ....
hunk ./doc/libraryInfrastructure.sgml 601
-
+ main = setup pkgDescr
+
+Here PkgDescr is a Haskell data structure that describes the package: its name, version, dependencies.
+It contains precisely the information that is output by setup info -- see .
+
+Now Angela can build her package by saying
+
+ setup.hs build
+
+She can even install it on her ownn machine by saying
+
+ setup.hs install
+
+She can build a HLI source distribution:
+
+ setup.hs source-dist
+
+The full details are given in .
+
+It is no coincidence that the interface is very similar to that for the setup script
+for an HLI package distribution ().
+In fact, Distribution.Simple.setup conforms to the specification of , and when it builds
+a distribution, it includes ./Setup.lhs in the tarball, ready to be run by Bob the Builder.
+However, Distribution.Simple.setup of course implements a richer interface than that required by
+, becuase it's intended to support Angela as well as Bob.
+The full specification is in .
+
hunk ./doc/libraryInfrastructure.sgml 629
- To let the &impls; know how to use a package,
- whether its available by default (or whether it requires a -package
- flag), and where the root of its hierarchy is.
+PkgInfo
hunk ./doc/libraryInfrastructure.sgml 631
- To store other information about a package,
- including information such as its license, home page, version
- number, and dependencies, to be used by other tools in the
- Distribution hierarchy.
+...describe PkgInfo...
+Which compiler flags does she put in the compiler-flags part of PkgInfo, and which does she
+pass to setup configure? Answer: the package should compile in a sensible way using only the
+former. The latter are just for build-specific modification (e.g. make a debug build).
hunk ./doc/libraryInfrastructure.sgml 636
- All information will be made available through the
- &DistPackage; module. The information can be made available to
- non-haskell tools by way of a command-line tool, &haskellConfig;
- () with easily parsable output
- (similar to package-config)
- though a different solution may be necessary for
- windows.
+
hunk ./doc/libraryInfrastructure.sgml 638
-
+Distribution.Simple.setup
hunk ./doc/libraryInfrastructure.sgml 640
-Some secondary features are:
+Command line interface to the simple build infrastructure.
+
hunk ./doc/libraryInfrastructure.sgml 643
-Let other tools, such as debuggers and
- editors know where the source code for a module / package
- is.
+
hunk ./doc/libraryInfrastructure.sgml 645
- When new Haskell implementations are installed,
- allow them to find the source code and import it into their own
- library tree (perhaps through other features of the
- L.I.P.)
+
hunk ./doc/libraryInfrastructure.sgml 647
- For Haskell implementations that don't conform to
- the new packaging interface, implement a wrapper so that it can
- still utilize other important features of the Library
- Infrastructure Project.
+
hunk ./doc/libraryInfrastructure.sgml 649
-The information would be held in a file, such as
-/etc/haskell/packages.confor
-/usr/local/etc/haskell/packages.conf or wherever the
-default location for config files is. and
-~/.haskell/packages.conf.
+What the compilers must implement
hunk ./doc/libraryInfrastructure.sgml 651
-PackageConfig Data Structure
+The HLI requires that the Haskell implementations be somewhat package-aware.
+This section documents those requirements
hunk ./doc/libraryInfrastructure.sgml 654
-The package data structure might look something like this (based
-on GHC's Package class)
+Registering a package
hunk ./doc/libraryInfrastructure.sgml 656
-data PkgIdentifier
- = PkgIdentifier {pkgName::String, pkgVersion::Version}
-{- ^Often need name and version since multiple versions of a single
- package can exist on a system. -}
+Installing a package ultimately involves these steps:
+
+
+ Compiling the source files, by invoking the compiler. Even Hugs may require
+ some processing (e.g running cpp).
+
hunk ./doc/libraryInfrastructure.sgml 663
-data PackageConfig
- = Package {
- pkgIdent :: PkgIdentifier,
- license :: License,
- auto :: Bool,
+
+ Copying the compiled files into some place. Typically the compiler
+ places no pre-conditions on where "some place" is; instead one
+ usually follows the conventions of the host operating system.
+
hunk ./doc/libraryInfrastructure.sgml 669
+
+ Registering the package: telling the compiler about the
+ existence of the package, and where its files are.
+ To register the package one invokes a compiler-specific program hc-pkg (i.e. ghc-pkg,
+ hugs-pkg etc), passing it an installed package description (IPD)
+ describing the package.
+
+
+
+It must be possible to register many versions of the same package.
hunk ./doc/libraryInfrastructure.sgml 680
- import_dirs :: [FilePath],
- source_dirs :: [FilePath],
- library_dirs :: [FilePath],
- include_dirs :: [FilePath],
- hs_libraries :: [String],
- extra_libraries :: [String],
- c_includes :: [String],
- build_deps :: [Dependency], -- build dependencies
- depends :: [Dependency], -- use dependencies
-
- extra_cc_opts :: [String],
- extra_ld_opts :: [String],
- framework_dirs :: [String],
- haddock_html_root :: String,
- haddock_interface :: String,
- default_grafting_point :: String,
--- ^Related to new packages proposal
- vars :: [(String, String)],
--- ^Variable, value pairs, whatever author wants here
- extra_frameworks:: [String]}
+Shared packages and user packages
hunk ./doc/libraryInfrastructure.sgml 682
-data Version = DateVersion {versionYear :: Integer,
- versionMonth :: Month,
- versionDay :: Integer}
- | NumberedVersion {versionMajor :: Integer,
- versionMinor :: Integer,
- versionPatchLevel :: Integer}
+
+A package can be registered either as a shared package or as a user package.
+The former means that anyone invoking hc will see the new package. The latter means
+that only the user who installed the package will see it.
+
+
+User packages shadow shared packages, in the following sense:
+
+ A Haskell import for module M will seek M in a user package first.
+
+
+ The hc-pkg commands that take package IDs will look for a user package first.
+
+
+
+Hmm. If there are several ghc's around, can their user packages get mixed up? I hope not.
hunk ./doc/libraryInfrastructure.sgml 699
-data License = GPL | LGPL | BSD | {- ... | -} OtherLicense FilePath
+
hunk ./doc/libraryInfrastructure.sgml 701
-data Dependency = Dependency String VersionRange
+Exposed packages and hidden packages
hunk ./doc/libraryInfrastructure.sgml 703
-data VersionRange
- = AnyVersion
- | OrLaterVersion Version
- | ExactlyThisVersion Version
- | OrEarlierVersion Version
+
+An installed package can be exposed or hidden. An exposed package
+populates the module name space, while a hidden package does not. Hidden packages are nevertheless necessary.
+For example, the user might use
+package A-2.1 and B-1.0;
+but B-1.0 might depend on A-1.9. So the latter must be installed (else B-1.0 could not be), but
+should be hidden, so that user imports see A-2.1.
+The registration program hc-pkg provides operations to expose or hide an
+already-installed package.
+
+
hunk ./doc/libraryInfrastructure.sgml 715
-type PackageMap = FiniteMap PkgIdentifier PackageConfig
-
+Registration invariants
hunk ./doc/libraryInfrastructure.sgml 717
-But perhaps we'll need to be even more flexible: some
-implementations might not be interested in certain fields, and others
-might want their own fields. I propose that implementation-specific
-fields be prepended with the implementation name:
-ghc_interpreter_flags,
-hugs_interpreter_flags, etc. In general it would
-certainly be desirable to have a flexible parser so that we can add
-more fields later and maintain backward compatibility.
-
-The &DistPackage; API might look like so:
-
-userPkgConfigLocation :: FilePath
-systemPkgConfigLocation :: FilePath
-getSystemPkgConfig :: IO [PackageMap] -- ^Query /etc/haskell/packages.conf
-getUserPkgConfig :: IO [PackageMap] -- ^Query ~/.haskell/packages.conf
-getPkgConfig :: FilePath -> IO [PackageMap]
-addUserPackage :: PackageConfig -> IO ()
-addSystemPackage :: PackageConfig -> IO ()
-delUserPackage :: PkgIdentifier -> IO ()
-delSystemPackage :: PkgIdentifier -> IO ()
-basicPackage :: PackageConfig -- provides sensible defaults
-checkLicense :: PackageConfig -> Bool
-{- Just for fun, check to see if the licences that this package uses
- conflicts with any of the licences of the packages it depends on -}
-
-
-
-
-
-
-
- &haskellConfig; Command-line
- interface
-
-The &haskellConfig; Because of the confusion
-between different kinds of configuration (the kinds offered by
-&DistPackage; and &DistConfigure;) I am torn about the name of this
-program. There is the further confusion between package management
-(the actual installation and removal of the programs themselves) and
-interfacing with the packaging system. Further there is one more bit
-of confusion between packages in the Haskell system (i.e. a set of
-modules distributed together by an author) and a package on the
-operating system. If anyone has an idea to straighten all of this
-out, I'd be glad to hear it :) tool is a
-command-line interface to the packaging system. It will presumably be
-written in Haskell and import the &DistPackage; module. The purpose
-of this tool is to give non-Haskell systems the ability to interact
-with the packaging system, since they won't be able to import
-&DistPackage;. This tool serves a purpose similar to ghc-pkg and
-package-config.
-
-% haskell-config [--user] register < packageFile
-% haskell-config [--user] unregister packageName
-# add or remove packages from the package database. --user indicates
-# that we should add it to the package database in the user's home
-# directory, not to the system-wide package database.
-
-% haskell-config packageName c_includes
-# would output this list in a way that a C compiler could use directly
-
-% haskell-config list-packages
-% haskell-config list-user-packages
-% haskell-config list-system-packages
-# Query the database in a variety of ways
-
-
-
-
-
-
- haskell-pkg?
-
- The &haskellConfig; tool brings up an interesting question.
- Should the functionality of &DistInstall; also be made available as
- a command-line tool, perhaps called haskell-pkg
- ("Haskell package")? In this sense, "package" would refer to that
- word in the sense that dpkg and the 'P'
- in RPM mean it:
- haskell-pkg could be used for installing and
- removing Haskell programs when supplied with the package metadata
- that is defined by &DistPackage;. This would conflict with &ghc;'s
- terminology for ghc-pkg.
-
-
-
- &DistConfigure;
-
- The information available through the &DistPackage; module is
- not all of the information that could possibly be needed to prepare
- a package for installation. Typically, tools such as &autoconf; are
- used to discover useful information about the system. The author
- has not given a lot of thought to the configuration problem, but he
- sees a few possible paths:
-
-
-
- A module, &DistConfigure; can act as an interface to
- configuration information. This is the approach that Python has
- taken.
-
- Some information can be written by the end user or
- maintained on the system in a standard file format. The file could
- reside, for example in
- ~/.haskell/distributionConfig,
- /etc/haskell/distributionConfig, and
- distributionConfig within the package
- directory. This information can be made available through the
- &DistConfigure; module.
-
- Certain pieces of information are available when the
- &impls; themselves are installed. This information can be made
- available to installing scripts once again through the
- distributionConfig file.
-
- Shortcomings in the &DistConfigure; module can be
- made up by using &autoconf; itself, which can output information to
- the above mentioned distributionConfig
- file.
-
-
-
-
-
-
- Use Cases
-
- End User: The end user has identified a
- Haskell package (tool or library) that she wants to use.
-
- The end user installs packages with a
- operating-system-specific package management system like RPM, dpkg,
- or FreeBSD's Ports collection.
-
- If no such packaging system is available on her
- system, she, can run ./Setup.lhs install nhc or
- ./Setup.lhs install hugs to build, install, and
- register an &nhc; or &hugs; version of the program (for
- instance).
-
-
-
-Packager: A packager is someone who makes
-operating-system-specific packages so that an end-user can have an
-easier time installing them on her own system. For each platform,
-there should be one or more packager.
-
-The packager can run
- ./Setup.lhs bdist_deb to build a skeleton Debian
- package (for instance) for each of the installed &impls;. This
- might generate Debian packages like hunit-hugs,
- hunit-ghc, hunit-prof-ghc,
- hunit-prof-nhc.
-
-
-
-3rd Party Author: A 3rd party author is a
-Haskell developer (distinct from the &impl; authors or end users) who
-wishes to distribute a library or application that he has developed in
-Haskell.
-
-The 3rd Party Author writes a
- Setup.lhs program. Setup.lhs
- imports elements from the &distMod; which does most of the hard
- work. A very common case, which should be our first priority, is a
- pure Haskell 98 module that needn't interface with any external
- systems. In this case the author only has to include the name of
- the program, the version, and the source files. He can then call
- Distribution.defaultMain to create an
- executable script with the proper command-line flags that knows how
- to interface with the &DistPackage; module.
-
-Should he have a more complex program (one which
- perhaps depends on systems external to Haskell), then the &distMod;
- could output a Makefile to be used in 'fptools' or Yale's system
- (see ).
-
-Should he not want to migrate from his own build
- system, he could write a Setup.lhs script to wrap
- the build system so that it conforms to the standard command-line
- interface.
-
-
-
-&impl; Authors:
-
-&impl; authors must conform to an
- agreed-upon &DistPackage; interface.
-
- This may include writing functionality so the
- compiler can be asked questions about itself.
-
- This may also include altering compilers to read
- /etc/haskellPackages.conf (for instance) to
- discover what packages are installed or where to look for
- imports.
-
-Include the &distMod; with the &impls; (in exchange, we
- can hopefully remove some libraries that are currently included with
- the &impls;).
-
-Random Haskell Programmer:
-
-A random Haskell programmer can use the
- &distMod; as a means to create layered tools that download, build,
- or install packages. For instance:
-
-
- &haskellConfig; is an example of a layered tool which interfaces with
- the &distMod;. This tool gives the end user access to the database
- of installed applications.
-
- A Graphical User Interface could be layered on top
- of the Setup script to give installation a better look-and-feel
- according to the target platform.
-
- The &distMod; could be augmented with an online
- repository of libraries (see ), and a layered tool might
- perform the searching and downloading functionality of the
- installation process.
-
- Debuggers often need to locate the source code to a
- library module in order to instrument them.
-
- Source code editors or browsers could benefit from
- being able to locate related source code on the user's
- system.
-
-
-
+The registration program hc-pkg checks the following invariants:
+
+
+Before registering a package P, check all the packages that P depends on are already registered.
+If P is being registered as a shared package, P's dependencies must also be shared packages.
hunk ./doc/libraryInfrastructure.sgml 723
+
+Before registering an exposed user package P, check that the modules that are exposed by P do not have the same
+names (in the hierarchical module name space) as any other module in an exposed user package Q. Similarly
+for system packages. (However, a system package may expose a module with the same name as a user package.
+
+
+Before un-registering a package P, check that no package that depends on P is registered.
+The exception is that when un-registering a shared package, hc-pkg cannot
+check that no user has a user package depending on P.
+
+
+
+
+
+The -package compiler flag
hunk ./doc/libraryInfrastructure.sgml 740
-
+
+Registering a package means that subsequent invocations of the compiler will use a module namespace
+augmented by the newly-installed package.
hunk ./doc/libraryInfrastructure.sgml 744
-
+
+By default, the module namespace is populated only by the latest version of a particular package.
+This can be overridden using the -package flag.
+Question: what does -package hunit-1.2 -package hunit-1.3 do?
+Does the second override the first? Or are they both in scope? I think the former.
+
+An attempt to import a module that is defined by more than one installed package yields an ambiguous-import
+error, rather like an attempt to use an identifier that is defined by more than one imported module.
+(Comment: there ought be some way to resolve such ambiguities. Per-import qualification? -disable-package X?
+-package Y specifies winner?)
+
+
hunk ./doc/libraryInfrastructure.sgml 757
- Means of Distribution
- and Layered Tools
+The interface to X-pkg
hunk ./doc/libraryInfrastructure.sgml 759
- Most of the discussion here has been about giving the user
- tools to build, install, and manage libraries and tools written in
- Haskell. There is another important component to this which
- deserves attention, and that is the distribution of these tools.
-
+Registering a package with a compiler records the package information in some
+implementation-specific way; how it does so is not constrained by the HLI.
+Much of an IPD is independent of the compiler, but it may also include compiler-specific
+fields.
hunk ./doc/libraryInfrastructure.sgml 764
-
- For C++ and Perl (and likely many other programming languages) there
- are central repositories of libraries and tools (). In a way, Haskell has this
- also, bit it is centrally maintained rather than being a
- free-for-all where nearly anyone can get their package distributed.
- The author feels that both approaches are appropriate, and libraries
- can graduate from one to the other.
+Each Haskell implementation hc must provide an associated program hc-pkg which
+allows a user to make a new package known to the compiler, and to ask what packages it knows. Here is a summary of its interface
hunk ./doc/libraryInfrastructure.sgml 767
- Having a standard interface for installing packages allows us
- to layer tools upon it. For instance, it would be nice to be able
- to download and install Haskell libraries and all their dependencies
- with one command. For Perl (by virtue of CPAN) this is already
- possible. Other layered tools are discussed in the Use Cases ().
+
hc-pkg interface
hunk ./doc/libraryInfrastructure.sgml 769
-
+
hunk ./doc/libraryInfrastructure.sgml 771
-
-Development Plan
+ hc-pkg register
+ filename
+
+
+
+ Register the package using the specified installed package description.
+ The syntax for the latter is given in .
hunk ./doc/libraryInfrastructure.sgml 779
-On a high level, this is the order in which we should approach
-the tasks:
hunk ./doc/libraryInfrastructure.sgml 780
-
+ hc-pkg unregister
+ pkg-id
+
+ Unregister the specified package.
hunk ./doc/libraryInfrastructure.sgml 785
-We should agree first on the high-level design of the
-packaging system (), since this will require a consensus from
-the &impl; authors. Details such as the format of the database and
-the exact API will evolve over the course of the project. The author
-views this as the top priority.
+ hc-pkg expose
+ pkg-id
+
+ Expose the specified package.
hunk ./doc/libraryInfrastructure.sgml 790
-In parallel, we should decide on the command-line interface for the
-Setup script (), and the particulars of
-how it is invoked on various systems.
+ hc-pkg hide
+ pkg-id
+
+ Hide the specified package.
hunk ./doc/libraryInfrastructure.sgml 795
-The first priority for Build and Install support
-should be pure Haskell modules, and reasonable support for wrapping
-make-based systems that are currently more highly evolved.
+ hc-pkg list
+ List all registered packages, both shared and user, hidden and exposed.
hunk ./doc/libraryInfrastructure.sgml 798
-At this point, it may be possible to collect
-libraries, convert them to use the Library Infrastructure Project, and
-make them available at a central repository.
hunk ./doc/libraryInfrastructure.sgml 799
-The next priority should be tools to assist in the
-creation and maintenance of operating-system packages (Debian and RPM
-for instance).
+ hc-pkg describepkg-id
+
+ Give the registered description for the specified package.
+ The description is returned in precisely the syntax required by
+ hc-pkg register.
+
hunk ./doc/libraryInfrastructure.sgml 806
-Once these features are in place, it makes sense to
-augment the &distMod; with more complex tool support like
-preprocessors and external libraries.
+ hc-pkg fieldpkg-id
+ field
+
hunk ./doc/libraryInfrastructure.sgml 810
-Now we can add more fun features like GUI front-ends,
-downloading tools, package security tools, etc.
+ Extract the specifed field of the package description for the specified package.
+
hunk ./doc/libraryInfrastructure.sgml 813
-
+
+
+A pkg argument can be a package ID, such as "hunit-2.3", or just a package name,
+such as "hunit". To determine which package is meant, hc-pkg searches first the
+registered user packages and then the shared packages. If no such package exists, the command fails; that is, it does nothing,
+returning a non-zero error code.
+If only a name is specified, hc-pkg fails
+unless the name identifies a unique package among the user packages, or among the shared pacakges. As usual, the
+user packages win.
+
+Can we give the flag to hide, expose,
+describe? Can we register a package that is already registered? What if it's registered
+as a shared package and we register it as a user package?
+
+
hunk ./doc/libraryInfrastructure.sgml 829
-The author has implemented a "toy" prototype system that fulfills
-many of the features outlined above. It uses &hmake; by running it as
-an external command. It can build Debian packages and interfaces with
-the Common Debian Build System. It can prepare installations for Hugs
-and GHC. The author decided to stop implementation, however, until
-details about the Packaging system ()
-are worked through.
+Syntax of installed package description
hunk ./doc/libraryInfrastructure.sgml 831
-
+...include the list of ``externally visible modules''.
+
+
}