Skip to content

Restructure Getting Started docs to get to a running program faster. #7551

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

Merged

Conversation

Mikolaj
Copy link
Member

@Mikolaj Mikolaj commented Aug 16, 2021

Rebased (with resolved conflicts) version of #6157 by @m-renaud .

Edit: we can't afford to maintain different documentation for different branches, so the documentation follows the state (in particular of cabal init) on branch master. This, sadly, means that this commit won't be backported to 3.6. The upside is that we can wait until @m-renaud returns and reviews.

I've squashed all changes for easier rebasing. The diff between #6157 and the version in this PR is the following:

diff --git a/doc/developing-packages.rst b/doc/developing-packages.rst
index b1e5369..4295e5d 100644
--- a/doc/developing-packages.rst
+++ b/doc/developing-packages.rst
@@ -4,52 +4,57 @@ 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
        4) Test suite
     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
@@ -66,25 +71,55 @@ and executable; or: test suite) cabal asks us a number of questions starting wit
 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...
+
+Use the ``ls`` command to see the creaed files:
+
+::
+
+   $ ls
+   CHANGELOG.md  Main.hs  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.
+
+Running the program
+-------------------
+
+Now that we have our Haskell code and the extra files that Cabal needs we
+can build and run our application.
 
 ::
 
-    Generating LICENSE...
-    Generating Setup.hs...
-    Generating proglet.cabal...
+   $ 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:
 
-    You may want to edit the .cabal file and add a Description field.
+-  ``proglet.cabal``: contains package metadata and build information.
 
-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.
 
 Editing the .cabal file
 -----------------------
@@ -93,33 +128,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
@@ -135,9 +179,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
@@ -145,12 +197,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
 ------------------------------------
@@ -173,23 +219,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
@@ -211,7 +257,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
 --------------------
@@ -223,14 +270,20 @@ which also downloads and builds all required dependencies:
 
     $ cabal build
 
-If the package contains an executable, it can be installed:
+If the package contains an executable, you can run it with:
+
+.. code-block:: console
+
+   $ cabal run
+
+and the executable can also be installed for convenince:
 
 .. code-block:: console
 
     $ cabal install
 
-The executable program lands in a special directory for binaries
-that may or may not already be on your system's ``$PATH``.
+When installed, the executable program lands in a special directory
+for binaries that may or may not already be on your system's ``$PATH``.
 If it is, the executable can be run by typing its filename on commandline.
 For installing libraries see the :ref:`adding-libraries` section.
 
@@ -246,6 +299,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
 ================
 
@@ -302,7 +356,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*
@@ -367,9 +421,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.

@Mikolaj Mikolaj requested review from m-renaud and ptkato August 16, 2021 12:48
@Mikolaj
Copy link
Member Author

Mikolaj commented Aug 16, 2021

@ptkato: i'm afraid this may be breaking your changes regarding cabal init and others, which is understandable, given that you both worked independently on the same text. I've fixed breakage with respect to my changes in 'Building the package' section --- you can leave it as is. However, all the other changes may potentially spoil your work, so pretty please, review them carefully.


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

@emilypi emilypi Aug 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**TL;DR;** ``mkdir proglet && cd proglet && cabal init && cabal run proglet``
**TL;DR;** ``mkdir proglet && cd proglet && cabal init --simple --exe && cabal run proglet``

@ptkato - this fails on the following:

λ athena proglet  cabal run proglet
Resolving dependencies...
Build profile: -w ghc-8.10.4 -O1
In order, the following will be built (use -v for more details):
 - proglet-0.1.0.0 (exe:proglet) (first run)
Configuring executable 'proglet' for proglet-0.1.0.0..
Preprocessing executable 'proglet' for proglet-0.1.0.0..
Building executable 'proglet' for proglet-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, /home/tapas/haskell/proglet/dist-newstyle/build/x86_64-linux/ghc-8.10.4/proglet-0.1.0.0/x/proglet/build/proglet/proglet-tmp/Main.o )

app/Main.hs:1:8: error:
    Could not load module Prelude
    It is a member of the hidden package base-4.14.1.0’.
    Perhaps you need to add base to the build-depends in your .cabal file.
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.
  |
1 | module Main where
  |        ^^^^

It looks like the dependency heuristic is not finding base in the exe case for Simple type builds. Do you mind fixing? (Edit: turns out we forgot to do this on all of the Simple ones)

Copy link
Member

@emilypi emilypi Aug 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #7552. You can now run the following and it will build with output:

mkdir proglet && cd proglet && cabal init --simple --exe && cabal run proglet

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (both doc tweak and approval of PR).

@Mikolaj Mikolaj requested a review from ptkato August 16, 2021 21:59
@Mikolaj
Copy link
Member Author

Mikolaj commented Aug 16, 2021

We can't afford to maintain different documentation for different branches, so the documentation follows the state (in particular of cabal init) on branch master. This, sadly, means that this commit won't be backported to 3.6. The upside is that we can wait until @m-renaud returns and reviews.

@Mikolaj
Copy link
Member Author

Mikolaj commented Aug 27, 2021

@m-renaud: would you like to review?

@Mikolaj
Copy link
Member Author

Mikolaj commented Aug 29, 2021

@m-renaud: BTW, by mistake (git commit --amend --author="Matt Renaud [edit: removed email to foil bots]" from bash history, originally used to ascribe to you this PR's commit), I've made you an author of another commit for a roguelike ASCII game: LambdaHack/LambdaHack@8c50113. I hope you don't mind the extra fame (that's master branch, I can't force- push to fix it without annoying collaborators). :D

@Mikolaj
Copy link
Member Author

Mikolaj commented Sep 6, 2021

@m-renaud: would you like to conclude your review so that I can merge? Or backport these changes to your original PR and merge yourself?

Copy link
Collaborator

@m-renaud m-renaud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Mikolaj Mikolaj merged commit 55c426f into haskell:master Sep 6, 2021
@Mikolaj
Copy link
Member Author

Mikolaj commented Sep 6, 2021

@m-renaud: thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants