Toward a Unified Packaging System

Isaac Jones
Thu Sep 11 05:32:39 EDT 2003

As part of the Library Infrastructure Project [1], there is the need
for a way to let the system and perhaps Haskell compilers and
interpreters know about packages (libraries and other tools) which are
being installed.  It would be very useful, therefore, to have a
unified packaging system agreed upon by the Haskell Implementors.  I
talked about this a bit at the Haskell Implementor's Meeting.

The main features of this system would be:

1) To let the compiler / interpreter 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.

2) To store other information about a package, including stuff like
   its license, home page, version number, and dependencies, to be
   used by other tools in the "Distribution" hierarchy.

3) All information will be made available through a Haskell Module,
   whose proposed name is Distribution.Package.  The information can
   be made available to non-haskell tools by way of a command-line
   tool, haskell-config with easily parsable output (similar to
   package-config [2]) though a different solution may be necessary
   for windows.  Any thoughts?

Some secondary features would be:

1) Let other tools, such as debuggers and editors, know where the
   source code for a module / package is.

2) 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.)

3) For Haskell implementations which don't conform to the new
   packaging interface, implement a wrapper so that it can still
   utilize other important features of the Library Infrastructure

The information would be held in a file, such as
/etc/haskell/packages.conf and ~/.haskell/packages.conf.

In practice, version information would also be of importance to some
of the below functions, as the system intends to allow multiple
versions of a package to coexist on the system.

The package data structure might look something like this (based on
GHC's Package class)

data PackageConfig
   = Package {
        name            :: String,
        version         :: Version,
        license         :: License,
        auto            :: Bool,
        provides        :: [String]

-- might indicate that this package provides functionality which other
   packages also provide, such as a compiler or GUI framework, and
   upon which other packages might depend.. [3]

        isDefault       :: Bool,
-- might indicate if this is the default compiler or GUI framework.

        import_dirs     :: [String],
        source_dirs     :: [String],
        library_dirs    :: [String],
        hs_libraries    :: [String],
        extra_libraries :: [String],
        include_dirs    :: [String],
        c_includes      :: [String],
        build_deps      :: [String], -- build dependencies
        depends         :: [String], -- use dependencies

-- In practice, the dependency types will probably have to be a bit
   more complex so as to allow for version information.

        extra_ghc_opts  :: [String],
        extra_cc_opts   :: [String],
        extra_ld_opts   :: [String],
        framework_dirs  :: [String],
        extra_frameworks:: [String]

data Version = ...
data License = GPL | LGPL | BSD | ... | (OtherLicense FilePath)

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.  It would certainly be desirable to have a flexible parser
so that we can add more fields later and maintain backward

The Distribution.Package API might look like so:

getSystemConfig  :: IO [Package]
getUserConfig    :: IO [Package]
addUserPackage   :: Package -> IO ()
addSystemPackage :: Package -> IO ()
delUserPackage   :: String  -> IO () -- might need more info, like version
delSystemPackage :: String  -> IO ()
basicPackage     :: Package          -- provides sensible defaults
checkLicense     :: Package -> Bool

-- Just for fun, check to see if the licences that this package uses
   conflicts with any of the packages it depends on

The command-line tool might be invoked like so:

% haskell-pkg --add-package < packageFile

% haskell-package hunit c_includes
# would output this list in a way that a C compiler could use directly

% haskell-pkg --list-packages
% haskell-pkg --list-user-packages
% haskell-pkg --list-system-packages

What would Haskell Implementations need to do to conform (at minimum):

1) Include Distribution.Package with your libraries

2) Add the packages marked "auto" to the search-path for imports

3) Allow a -package flag to add non-auto packages to the search-path

So my question to you is, would the authors of the Haskell
implementations add something like this to their systems, and help to
port the Distribution.Package library?  Are there major things I'm
missing, or is there anything here which would make this overly hard
for any particular implementation?






[3] For a library, Provides would indicate that they conform to a
pretty standard interface, for an application, they would only have to
be roughly equivalent.

More information about the Libraries mailing list