[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 <function>X-pkg</function> - -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 -
<function>setup</function> 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 -
<function>PkgInfo</function> 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). -
- -
<function>Distribution.Setup.Simpl.setup</function> - -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. +<function>setup info</function> 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 +<function>setup configure</function> 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 +<function>setup build</function> 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. +<function>setup install</function> 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; +<function>setup register</function> and <function>setup unregister</function> 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. +<function>PkgInfo</function> 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 - +<function>Distribution.Simple.setup</function> 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 <function>-package</function> 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 <function>X-pkg</function> 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 (). +
<function>hc-pkg</function> 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 describe pkg-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 field pkg-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''. + + }