Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructure Quickstart docs to get from zero to hacking faster. #6157

Closed
wants to merge 10 commits into from
213 changes: 130 additions & 83 deletions doc/developing-packages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,85 +4,111 @@ Quickstart
.. TIP::
If this is your first time using `cabal` you should check out the `Getting Started guide <getting-started.html>`__.

Let's assume we have created a project directory and already have a
Haskell module or two.
Starting from scratch, we're going to walk you through creating a simple
Haskell application.

Every project needs a name, we'll call this example "proglet".
**TL;DR;** ``mkdir proglet && cd proglet && cabal init && cabal run proglet``


Introduction
------------

Every application needs a name, we'll call ours "proglet" and start by
creating an empty directory.

.. highlight:: console

::

$ mkdir proglet
$ cd proglet/
$ ls
Proglet.hs

It is assumed that (apart from external dependencies) all the files that
make up a package live under a common project root directory. This
simple example has all the project files in one directory, but most
packages will use one or more subdirectories.

To turn this into a Cabal package we need two extra files in the
project's root directory:
Using ``cabal init``
--------------------

- ``proglet.cabal``: containing package metadata and build information.
The ``cabal init`` command creates the necessary files for a Cabal package,
it has both an ``--interactive`` and ``--non-interactive`` (default)
mode. The interactive mode will walk you through many of the package
options and metadata, the non-interactive mode will simply pick reasonable
defaults which is sufficient if you're just trying something out.

- ``Setup.hs``: usually containing a few standardized lines of code,
but can be customized if necessary.
.. highlight:: console

We can create both files manually or we can use ``cabal init`` to create
them for us.
::

Using "cabal init"
------------------
$ cabal init --non-interactive
# You can also use -n which is the short version of --non-interactive

The ``cabal init --interactive`` command is interactive. If we answer
"no" to using the "sensible defaults" it asks a number of questions.
If you want, you can also try out the interactive mode, for now chose
"Executable" when asked what type of package you want to build.

.. highlight:: console

::

$ cabal init --interactive
Should I generate a simple project with sensible defaults? [default: y] n
...
What does the package build:
1) Executable
2) Library
3) Library and Executable
1) Executable
2) Library
3) Library and Executable
Your choice?
...

One of the important questions is whether the package contains a library
and/or an executable. Libraries are collections of Haskell modules that
can be re-used by other Haskell libraries and programs, while executables
are standalone programs.

For the moment these are the only choices. For more complex packages
(e.g. a library and multiple executables or test suites) the ``.cabal``
file can be edited afterwards.
This will create the ``Main.hs`` Haskell file and a few others that are
part of all Cabal packages. By default ``cabal init`` will create an
executable in the top level directory.

After you make your selection (executable; library; or: library
and executable) cabal asks us a number of questions starting with
which version of the cabal specification to use, our package's name
(for example, "proglet"), and our package's version.
::

It also asks questions about various other bits of package metadata. For
a package that you never intend to distribute to others, these fields
can be left blank.
Generating CHANGELOG.md...
Generating Main.hs...
Generating proglet.cabal...

Finally, ``cabal init --interactive`` creates the initial ``proglet.cabal``
and ``Setup.hs`` files, and depending on your choice of license, a
``LICENSE`` file as well.
Use the ``ls`` command to see the creaed files:

::

Generating LICENSE...
Generating Setup.hs...
Generating proglet.cabal...
$ ls
CHANGELOG.md Main.hs proglet.cabal

You may want to edit the .cabal file and add a Description field.

At this stage the ``proglet.cabal`` is not quite complete and before you
are able to build the package you will need to edit the file and add
some build information about the library or executable.
Running the program
-------------------

Now that we have our Haskell code and the extra files that Cabal needs we
can build and run our application.

::

$ cabal build
Resolving dependencies...
...
Linking /path/to/proglet ...

$ cabal run proglet
...
Hello, Haskell!

Since we have an executable we can use ``cabal run proglet`` which will build
our executable (and re-build it if we've made any changes) and then run the
binary. The ``cabal run`` command works for any ``component-name`` (tests for
example), not just the main executable.


About the Cabal package structure
---------------------------------

It is assumed that all the files that make up a package live under a common
root directory (apart from external dependencies). This simple example has
all the package files in one directory, but most packages use one or more
subdirectories.

Cabal needs one extra file in the package's root directory:

- ``proglet.cabal``: contains package metadata and build information.


Editing the .cabal file
-----------------------
Expand All @@ -91,33 +117,42 @@ Editing the .cabal file

Load up the ``.cabal`` file in a text editor. The first part of the
``.cabal`` file has the package metadata and towards the end of the file
you will find the :pkg-section:`executable` or :pkg-section:`library` section.
you will find the :pkg-section:`executable` or :pkg-section:`library`
section.

You will see that the fields that have yet to be filled in are commented
out. Cabal files use "``--``" Haskell-style comment syntax. (Note that
comments are only allowed on lines on their own. Trailing comments on
other lines are not allowed because they could be confused with program
options.)
out. Cabal files use "``--``" Haskell-style comment syntax.

.. NOTE::
Comments are only allowed on lines on their own. Trailing comments on
other lines are not allowed because they could be confused with program
options.

If you selected earlier to create a library package then your ``.cabal``
file will have a section that looks like this:

::

library
exposed-modules: Proglet
executable proglet
main-is: Main.hs
-- other-modules:
-- build-depends:
-- other-extensions:
build-depends: base >=4.11 && <4.12
-- hs-source-dirs:
default-language: Haskell2010

Alternatively, if you selected an executable then there will be a
section like:

If you selected earlier to create a library package then your ``.cabal``
file will have a section that looks like this:

::

executable proglet
-- main-is:
library
exposed-modules: MyLib
-- other-modules:
-- build-depends:
build-depends: base >=4.11 && <4.12
-- hs-source-dirs:
default-language: Haskell2010


The build information fields listed (but commented out) are just the few
most important and common fields. There are many others that are covered
Expand All @@ -133,22 +168,24 @@ not specified in the library section. Executables often follow the name
of the package too, but this is not required and the name is given
explicitly.


Modules included in the package
-------------------------------

For an executable, ``cabal init`` creates the ``Main.hs`` file which
contains your program's ``Main`` module. It will also fill in the
:pkg-field:`executable:main-is` field with the file name of your program's
``Main`` module, including the ``.hs`` (or ``.lhs``) extension. Other
modules included in the executable should be listed in the
:pkg-field:`other-modules` field.

For a library, ``cabal init`` looks in the project directory for files
that look like Haskell modules and adds all the modules to the
:pkg-field:`library:exposed-modules` field. For modules that do not form part
of your package's public interface, you can move those modules to the
:pkg-field:`other-modules` field. Either way, all modules in the library need
to be listed.

For an executable, ``cabal init`` does not try to guess which file
contains your program's ``Main`` module. You will need to fill in the
:pkg-field:`executable:main-is` field with the file name of your program's
``Main`` module (including ``.hs`` or ``.lhs`` extension). Other modules
included in the executable should be listed in the :pkg-field:`other-modules`
field.

Modules imported from other packages
------------------------------------
Expand All @@ -171,23 +208,23 @@ package, so we must list it:
library
exposed-modules: Proglet
other-modules:
build-depends: containers, base == 4.*
build-depends: containers, base >=4.11 && <4.12

In addition, almost every package also depends on the ``base`` library
package because it exports the standard ``Prelude`` module plus other
basic modules like ``Data.List``.

You will notice that we have listed ``base == 4.*``. This gives a
You will notice that we have listed ``base >=4.11 && <4.12``. This gives a
constraint on the version of the base package that our package will work
with. The most common kinds of constraints are:

- ``pkgname >= n``
- ``pkgname ^>= n`` (since Cabal 2.0)
- ``pkgname >= n && < m``
- ``pkgname == n.*`` (since Cabal 1.6)
- ``pkgname >=n``
- ``pkgname ^>=n`` (since Cabal 2.0)
- ``pkgname >=n && <m``
- ``pkgname ==n.*`` (since Cabal 1.6)

The last is just shorthand, for example ``base == 4.*`` means exactly
the same thing as ``base >= 4 && < 5``. Please refer to the documentation
The last is just shorthand, for example ``base ==4.*`` means exactly
the same thing as ``base >=4 && <5``. Please refer to the documentation
on the :pkg-field:`build-depends` field for more information.

Also, you can factor out shared ``build-depends`` (and other fields such
Expand All @@ -209,7 +246,8 @@ your libraries and executable sections. For example:
Proglet

Note that the ``import`` **must** be the first thing in the stanza. For more
information see the :ref:`common-stanzas` section.
information see the `Common stanzas`_ section.


Building the package
--------------------
Expand All @@ -219,11 +257,18 @@ the package:

.. code-block:: console

$ cabal configure
$ cabal build

As mentioned above, if you have an executable you can also run it with:

.. code-block:: console

$ cabal run

Assuming those two steps worked then you can also install the package:

.. todo:: this might or might not work with v2-install.

.. code-block:: console

$ cabal install
Expand All @@ -232,6 +277,7 @@ For libraries this makes them available for use in GHCi or to be used by
other packages. For executables it installs the program so that you can
run it (though you may first need to adjust your system's ``$PATH``).


Next steps
----------

Expand All @@ -244,6 +290,7 @@ packages and details needed for distributing packages to other people.
The previous chapter covers building and installing packages -- your own
packages or ones developed by other people.


Package concepts
================

Expand Down Expand Up @@ -300,7 +347,7 @@ of digits such as "1.0.1" or "2.0". There are a range of common
conventions for "versioning" packages, that is giving some meaning to
the version number in terms of changes in the package, such as
e.g. `SemVer <http://semver.org>`__; however, for packages intended to be
distributed via Hackage Haskell's `Package Versioning Policy <https://pvp.haskell.org/>`_ applies
distributed via Hackage Haskell's `Package Versioning Policy`_ applies
(see also the `PVP/SemVer FAQ section <https://pvp.haskell.org/faq/#semver>`__).

The combination of package name and version is called the *package ID*
Expand Down Expand Up @@ -365,9 +412,9 @@ Operating system packages
Unit of distribution
--------------------

The Cabal package is the unit of distribution. What this means is that
each Cabal package can be distributed on its own in source or binary
form. Of course there may be dependencies between packages, but there is
The Cabal package is the unit of distribution. This means that
each Cabal package can be distributed on its own, in source or binary
form. There may be dependencies between packages, but there is
usually a degree of flexibility in which versions of packages can work
together so distributing them independently makes sense.

Expand Down