Skip to content

Commit

Permalink
Rework material on library components
Browse files Browse the repository at this point in the history
  • Loading branch information
mpilgrem committed Oct 26, 2023
1 parent a86ca8c commit a076f5c
Showing 1 changed file with 78 additions and 96 deletions.
174 changes: 78 additions & 96 deletions doc/cabal-package.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ Package Description
===================

The Cabal package is the unit of distribution. When installed, its
purpose is to make available:
purpose is to make available one or more:

- One or more Haskell programs (executables).
- Haskell programs (executables); and/or

- One or more libraries, exposing a number of Haskell modules.
- libraries, exposing a number of Haskell modules.

However having both a library and executables in a package does not work
very well; if the executables depend on the library, they must
Executables can declare a library in the same package as a dependency, and
Cabal will treat them as if they were in another package that depended on the
library. The alternative, which applied before Cabal 1.8.0.4, is that if the
executables depend on the library in the same package, they must
explicitly list all the modules they directly or indirectly import from
that library. Fortunately, starting with Cabal 1.8.0.4, executables can
also declare the package that they are in as a dependency, and Cabal
will treat them as if they were in another package that depended on the
library.
that library.

Internally, the package may consist of much more than a bunch of Haskell
modules: it may also have C source code and header files, source code
Expand Down Expand Up @@ -801,18 +800,45 @@ Library

Build information for libraries.

A package can have one default library, which is identified by omitting the
``name`` argument.
A package can include zero or more library components, being an optional
'main' unnamed library (which is identified by having no ``name`` argument)
and/or zero or more 'subsidiary' or 'ancilliary' named libraries (referred
to as 'sublibraries', which are identified by their ``name`` argument). A
sublibrary cannot have the same name as its package.

Starting with Cabal 2.0, sub-library components can be defined by setting
the ``name`` field to a name different from the current package's name; see
section on :ref:`Sublibraries <sublibs>` for more information. By
default, these sub-libraries are private and internal. Since Cabal 3.0,
these sub-libraries can also be exposed and used by other packages. See the
:pkg-field:`library:visibility` field and :ref:`Multiple Public Libraries
<publicsublibs>` for more information.
A sublibrary has a 'visibility' which can be 'public' or 'private' (the
default) - see the :pkg-field:`library:visibility` field. The 'main'
unnamed library is always public. A private sublibrary may be referred to as
an 'internal' library, because other packages cannot depend upon it.

The library section should contain the following fields:
Before Cabal 3.0, all sublibraries were internal libraries. Before Cabal 2.0
a package could not include sublibraries.

A package being able to include more than one public library separates the
unit of distribution (the package) from the unit of buildable code (the
library). This is useful for Haskell projects with many libraries that are
distributed together as it avoids duplication and potential inconsistencies.

See :ref:`Sublibraries - Examples <sublibs>` for examples.

A library section should contain the following fields:

.. pkg-field:: visibility: visibility specifiers

:since: 3.0

:default:
``private`` for sublibraries. Cannot be set for the 'main' unnamed
library, which is always public.

Can be set to ``public`` or ``private``. If set to ``public``, other
components of the package that provide the library and components of other
packages are able to depend on the library. If set to ``private``, only
other components of the package that provide it are able to depend upon it;
components of other packages are not able to depend upon it.

See the :pkg-field:`build-depends` field for the syntax to specify a 'main'
unnamed library or a sublibrary in a ``build-depends:``.

.. pkg-field:: exposed-modules: identifier list

Expand Down Expand Up @@ -847,23 +873,6 @@ The library section should contain the following fields:
that use a flat module namespace or where it is known that the
exposed modules would clash with other common modules.

.. pkg-field:: visibility: visibility specifiers

:since: 3.0

:default:
``private`` for sublibraries. Cannot be set for main
(unnamed) library, which is always public.

Can be ``public`` or ``private``.
Makes it possible to have multiple public libraries in a single package.
If set to ``public``, depending on this library from another package is
allowed. If set to ``private``, depending on this library is allowed only
from the same package.

See section on :ref:`Sublibraries <sublibs>` for examples and more
information.

.. pkg-field:: reexported-modules: exportlist
:since: 1.22

Expand Down Expand Up @@ -903,22 +912,21 @@ section on `build information`_).

.. _sublibs:

**Sublibraries**
**Sublibraries - Examples**

Cabal 2.0 and later support "sublibraries", which are extra named
libraries (as opposed to the usual unnamed library section). For
example, suppose that your test suite needs access to some internal
modules in your library, which you do not otherwise want to export. You
could put these modules in a sublibrary, which the main library
and the test suite :pkg-field:`build-depends` upon. Then your Cabal file might
look something like this:
An example of the use of an internal library (that is, a 'private' sublibrary)
is a test suite that needs access to some internal modules in your 'main'
unnamed library, which you do not otherwise want to expose. You could put those
modules in an internal library, which the 'main' unnamed library and the test
suite :pkg-field:`build-depends` upon. Your Cabal file might then look something
like this:

::

cabal-version: 2.0
cabal-version: 3.4
name: foo
version: 0.1.0.0
license: BSD3
license: BSD-3-Clause
license-file: LICENSE
build-type: Simple

Expand All @@ -931,34 +939,26 @@ look something like this:

library
exposed-modules: Foo.Public
build-depends: foo-internal, base >= 4.3 && < 5
build-depends: foo:foo-internal, base >= 4.3 && < 5
default-language: Haskell2010

test-suite test-foo
type: exitcode-stdio-1.0
main-is: test-foo.hs
-- NOTE: no constraints on 'foo-internal' as same-package
-- dependencies implicitly refer to the same package instance
build-depends: foo-internal, base
build-depends: foo:foo-internal, base
default-language: Haskell2010

Sublibraries are also useful for packages that define multiple
executables, but do not define a publicly accessible library. Internal
libraries are only visible internally in the package (so they can only
be added to the :pkg-field:`build-depends` of same-package libraries,
executables, test suites, etc.) Sublibraries locally shadow any
packages which have the same name; consequently, don't name an internal
library with the same name as an external dependency if you need to be
able to refer to the external dependency in a
:pkg-field:`build-depends` declaration.
Another example of the use of internal libraries is a package that includes one
or more executables but does not include a public library.

Shadowing can be used to vendor an external dependency into a package
and thus emulate *private dependencies*. Below is an example based on
a real-world use case:
Internal libraries can be used to incorporate an external dependency into a
package, effectively simulating *private dependencies*. Below is an example:

::

cabal-version: 3.0
cabal-version: 3.4
name: haddock-library
version: 1.6.0
license: BSD-3-Clause
Expand All @@ -973,7 +973,7 @@ a real-world use case:
hs-source-dirs: src

-- internal sub-lib
build-depends: attoparsec
build-depends: haddock-library:attoparsec

exposed-modules:
Documentation.Haddock
Expand Down Expand Up @@ -1001,25 +1001,6 @@ a real-world use case:

default-language: Haskell2010

.. note::
For packages using ``cabal-version: 3.4`` or higher, the syntax to
specify a sublibrary in a ``build-depends:`` section is
``package-name:internal-library-name``.

.. _publicsublibs:

**Multiple Public Libraries**

Cabal 3.0 and later support exposing multiple libraries from a single package
through the field :pkg-field:`library:visibility`.
Having multiple public libraries is useful for separating the unit of
distribution (package) from the unit of buildable code (library).
For more information about the rationale and some examples, see
`this blog post <https://fgaz.me/posts/2019-11-14-cabal-multiple-libraries/>`__.

..
TODO inline the blog post
Executables
^^^^^^^^^^^

Expand Down Expand Up @@ -1454,24 +1435,25 @@ system-dependent values for these fields.

.. pkg-field:: build-depends: library list

Declares the *library* dependencies required to build the current
package component; see :pkg-field:`build-tool-depends` for
declaring build-time *tool* dependencies. External library
dependencies should be annotated with a version constraint.
Declares the *library* dependencies (from the same package or other
packages) required to build the current package component. See
:pkg-field:`build-tool-depends` for declaring build-time *tool*
dependencies. Dependencies on libraries from another package should be
annotated with a version constraint.

**Library Names**

External libraries are identified by the package's name they're
provided by, optionally followed by a colon and the library name
(available from ``cabal-version: 3.0``).
If the library name is absent, the main (unnamed) library will be used.
To refer to the main (unnamed) library explicitly, use the name of the
package (``foo:foo``).
Multiple libraries from the same package can be specified with the shorthand
syntax ``pkg:{lib1,lib2}```.

See section on :ref:`Multiple Public Libraries <publicsublibs>` for examples and more
information.
A library is identified by the name of the package that provides it,
optionally followed by a colon and the library's name (available from
``cabal-version: 3.0``). If a library name is omitted, the package's 'main'
unnamed library will be used. To refer expressly to a package's 'main'
unnamed library, use the name of the package as the library name (for
example, ``my-package:my-package``). More than one library from the same
package can be specified with the shorthand syntax ``pkg:{lib1,lib2}``.

See the section on :pkg-section:`library` for more information about how
a package can specify library components for use by other components of the
same package or by other packages.

**Version Constraints**

Expand Down

0 comments on commit a076f5c

Please sign in to comment.