diff --git a/doc/developing-packages.rst b/doc/developing-packages.rst index 2c7f08a2bbe..a1d93c3963e 100644 --- a/doc/developing-packages.rst +++ b/doc/developing-packages.rst @@ -4,85 +4,111 @@ Quickstart .. TIP:: If this is your first time using `cabal` you should check out the `Getting Started guide `__. -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 ----------------------- @@ -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 @@ -133,9 +168,17 @@ 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 @@ -143,12 +186,6 @@ 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 ------------------------------------ @@ -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 && = 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 @@ -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 -------------------- @@ -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 @@ -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 ---------- @@ -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 ================ @@ -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 `__; however, for packages intended to be -distributed via Hackage Haskell's `Package Versioning Policy `_ applies +distributed via Hackage Haskell's `Package Versioning Policy`_ applies (see also the `PVP/SemVer FAQ section `__). The combination of package name and version is called the *package ID* @@ -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.