about summary refs log tree commit diff
path: root/third_party/bazel/rules_haskell/docs
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2019-07-04T10·18+0100
committerVincent Ambo <tazjin@google.com>2019-07-04T10·18+0100
commitf723b8b878a3c4a4687b9e337a875500bebb39b1 (patch)
treee85204cf042c355e90cff61c111e7d8cd15df311 /third_party/bazel/rules_haskell/docs
parent2eb1dc26e42ffbdc168f05ef744bd4b4f3e4c36f (diff)
feat(third_party/bazel): Check in rules_haskell from Tweag r/17
Diffstat (limited to 'third_party/bazel/rules_haskell/docs')
-rw-r--r--third_party/bazel/rules_haskell/docs/.gitignore1
-rw-r--r--third_party/bazel/rules_haskell/docs/BUILD.bazel46
-rw-r--r--third_party/bazel/rules_haskell/docs/conf.py41
-rw-r--r--third_party/bazel/rules_haskell/docs/haskell-use-cases.rst283
-rw-r--r--third_party/bazel/rules_haskell/docs/haskell.rst364
-rw-r--r--third_party/bazel/rules_haskell/docs/index.rst23
-rw-r--r--third_party/bazel/rules_haskell/docs/why-bazel.rst102
7 files changed, 860 insertions, 0 deletions
diff --git a/third_party/bazel/rules_haskell/docs/.gitignore b/third_party/bazel/rules_haskell/docs/.gitignore
new file mode 100644
index 000000000000..e35d8850c968
--- /dev/null
+++ b/third_party/bazel/rules_haskell/docs/.gitignore
@@ -0,0 +1 @@
+_build
diff --git a/third_party/bazel/rules_haskell/docs/BUILD.bazel b/third_party/bazel/rules_haskell/docs/BUILD.bazel
new file mode 100644
index 000000000000..e21093c8ec6c
--- /dev/null
+++ b/third_party/bazel/rules_haskell/docs/BUILD.bazel
@@ -0,0 +1,46 @@
+load("@io_bazel_skydoc//skylark:skylark.bzl", "skylark_doc")
+
+genrule(
+    name = "guide_html",
+    srcs = ["conf.py"] + glob(["*.rst"]),
+    outs = ["guide_html.zip"],
+    cmd = """
+    set -euo pipefail
+    # Nixpkgs_rules are pointing to every bins individually. Here
+    # we are extracting the /bin dir path to append it to the $$PATH.
+    CWD=`pwd`
+    sphinxBinDir=$${CWD}/$$(echo $(locations @sphinx//:bin) | cut -d ' ' -f 1 | xargs dirname)
+    dotBinDir=$${CWD}/$$(echo $(locations @graphviz//:bin) | cut -d ' ' -f 1 | xargs dirname)
+    zipBinDir=$${CWD}/$$(echo $(locations @zip//:bin) | cut -d ' ' -f 1 | xargs dirname)
+    PATH=$${PATH}:$${sphinxBinDir}:$${dotBinDir}:$${zipBinDir}
+    sourcedir=$$(dirname $(location conf.py))
+    builddir=$$(mktemp -d rules_haskell_docs.XXXX)
+    sphinx-build -M html $$sourcedir $$builddir -W -N -q
+    (cd $$builddir/html && zip -q -r $$CWD/$@ .)
+    rm -rf $$builddir
+    """,
+    tools = [
+        "@graphviz//:bin",
+        "@sphinx//:bin",
+        "@zip//:bin",
+    ],
+)
+
+skylark_doc(
+    name = "api_html",
+    srcs = [
+
+        # The order of these files defines the order in which the corresponding
+        # sections are presented in the docs.
+        "//haskell:haskell.bzl",
+        "//haskell:haddock.bzl",
+        "//haskell:lint.bzl",
+        "//haskell:toolchain.bzl",
+        "//haskell:protobuf.bzl",
+        "//haskell:cc.bzl",
+        "//haskell:repositories.bzl",
+        "//haskell:ghc_bindist.bzl",
+        "//haskell:nixpkgs.bzl",
+    ],
+    format = "html",
+)
diff --git a/third_party/bazel/rules_haskell/docs/conf.py b/third_party/bazel/rules_haskell/docs/conf.py
new file mode 100644
index 000000000000..acfe5dc7af88
--- /dev/null
+++ b/third_party/bazel/rules_haskell/docs/conf.py
@@ -0,0 +1,41 @@
+project = 'rules_haskell'
+
+copyright = '2018, The rules_haskell authors'
+
+source_suffix = '.rst'
+
+extensions = [
+    'sphinx.ext.graphviz',
+    'sphinx.ext.todo',
+]
+
+master_doc = 'index'
+
+language = None
+
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+pygments_style = 'sphinx'
+
+html_theme = 'alabaster'
+
+html_theme_options = {
+    'show_powered_by': False,
+    'github_user': 'tweag',
+    'github_repo': 'rules_haskell',
+    'github_banner': True,
+    'github_type': "star",
+    'show_related': False,
+    'note_bg': '#FFF59C',
+}
+
+html_show_sphinx = False
+
+todo_include_todos = True
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass).
+latex_documents = [
+    (master_doc, 'rules_haskell.tex', 'rules\\_haskell Documentation',
+     'Tweag I/O', 'manual'),
+]
diff --git a/third_party/bazel/rules_haskell/docs/haskell-use-cases.rst b/third_party/bazel/rules_haskell/docs/haskell-use-cases.rst
new file mode 100644
index 000000000000..a8c4340cf70f
--- /dev/null
+++ b/third_party/bazel/rules_haskell/docs/haskell-use-cases.rst
@@ -0,0 +1,283 @@
+.. _use-cases:
+
+Common Haskell Build Use Cases
+==============================
+
+Picking a compiler
+------------------
+
+Unlike Bazel's native C++ rules, rules_haskell does not auto-detect
+a Haskell compiler toolchain from the environment. This is by design.
+We require that you declare a compiler to use in your ``WORKSPACE``
+file.
+
+There are two common sources for a compiler. One is to use the
+official binary distributions from `haskell.org`_. This is done using
+the `ghc_bindist`_ rule.
+
+The compiler can also be pulled from Nixpkgs_, a set of package
+definitions for the `Nix package manager`_. Pulling the compiler from
+Nixpkgs makes the build more hermetic, because the transitive closure
+of the compiler and all its dependencies is precisely defined in the
+``WORKSPACE`` file. Use `rules_nixpkgs`_ to do so (where ``X.Y.Z``
+stands for any recent release)::
+
+  load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+  http_archive(
+      name = "io_tweag_rules_nixpkgs",
+      strip_prefix = "rules_nixpkgs-X.Y.Z",
+      urls = ["https://github.com/tweag/rules_nixpkgs/archive/vX.Y.Z.tar.gz"],
+  )
+
+  load(
+      "@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl",
+      "nixpkgs_git_repository",
+      "nixpkgs_package"
+  )
+
+  nixpkgs_git_repository(
+      name = "nixpkgs",
+      revision = "18.09", # Any tag or commit hash
+  )
+
+  nixpkgs_package(
+      name = "ghc",
+      repositories = { "nixpkgs": "@nixpkgs//:default.nix" }
+      attribute_path = "haskell.compiler.ghc843", # Any compiler version
+      build_file = "@io_tweag_rules_haskell//haskell:ghc.BUILD",
+  )
+
+  register_toolchains("//:ghc")
+
+This workspace description specifies which Nixpkgs version to use,
+then exposes a Nixpkgs package containing the GHC compiler. The
+description assumes that there exists a ``BUILD`` file at the root of
+the repository that includes the following::
+
+  haskell_toolchain(
+    name = "ghc",
+    # Versions here and in WORKSPACE must match.
+    version = "8.4.3",
+    # Use binaries from @ghc//:bin to define //:ghc toolchain.
+    tools = ["@ghc//:bin"],
+  )
+
+.. _Bazel+Nix blog post: https://www.tweag.io/posts/2018-03-15-bazel-nix.html
+.. _Nix package manager: https://nixos.org/nix
+.. _Nixpkgs: https://nixos.org/nixpkgs/manual/
+.. _ghc_bindist: http://api.haskell.build/haskell/ghc_bindist.html#ghc_bindist
+.. _haskell.org: https://haskell.org
+.. _haskell_binary: http://api.haskell.build/haskell/haskell.html#haskell_binary
+.. _haskell_library: http://api.haskell.build/haskell/haskell.html#haskell_library
+.. _rules_nixpkgs: https://github.com/tweag/rules_nixpkgs
+
+Loading targets in a REPL
+-------------------------
+
+Rebuilds are currently not incremental *within* a binary or library
+target (rebuilds are incremental across targets of course). Any change
+in any source file will trigger a rebuild of all source files listed
+in a target. In Bazel, it is conventional to decompose libraries into
+small units. In this way, libraries require less work to rebuild.
+Still, for interactive development full incrementality and fast
+recompilation times are crucial for a good developer experience. We
+recommend making all development REPL-driven for fast feedback when
+source files change.
+
+Every `haskell_binary`_ and every `haskell_library`_ target has an
+optional executable output that can be run to drop you into an
+interactive session. If the target's name is ``foo``, then the REPL
+output is called ``foo@repl``.
+
+Consider the following binary target::
+
+  haskell_binary(
+      name = "hello",
+      srcs = ["Main.hs", "Other.hs"],
+      deps = ["//lib:some_lib"],
+  )
+
+The target above also implicitly defines ``hello@repl``. You can call
+the REPL like this (requires Bazel 0.15 or later)::
+
+  $ bazel run //:hello@repl
+
+This works for any ``haskell_binary`` or ``haskell_library`` target.
+Modules of all libraries will be loaded in interpreted mode and can be
+reloaded using the ``:r`` GHCi command when source files change.
+
+Building code with Hackage dependencies (using Nix)
+---------------------------------------------------
+
+Each Haskell library or binary needs a simple build description to
+tell Bazel what source files to use and what the dependencies are, if
+any. Packages on Hackage don't usually ship with `BUILD.bazel` files.
+So if your code depends on them, you either need to write a build
+description for each package, generate one (see next section), or
+decide not to use Bazel to build packages published on Hackage. This
+section documents one way to do the latter.
+
+Nix is a package manager. The set of package definitions is called
+Nixpkgs. This repository contains definitions for most actively
+maintained Cabal packages published on Hackage. Where these packages
+depend on system libraries like zlib, ncurses or libpng, Nixpkgs also
+contains package descriptions for those, and declares those as
+dependencies of the Cabal packages. Since these definitions already
+exist, we can reuse them instead of rewriting these definitions as
+build definitions in Bazel. See the `Bazel+Nix blog post`_ for a more
+detailed rationale.
+
+To use Nixpkgs in Bazel, we need `rules_nixpkgs`_. See `Picking
+a compiler`_ for how to import Nixpkgs rules into your workspace and
+how to use a compiler from Nixpkgs. To use Cabal packages from
+Nixpkgs, replace the compiler definition with the following::
+
+  nixpkgs_package(
+      name = "ghc",
+      repositories = { "nixpkgs": "@nixpkgs//:default.nix" },
+      nix_file = "//:ghc.nix",
+      build_file = "@io_tweag_rules_haskell//haskell:ghc.BUILD",
+  )
+
+This definition assumes a ``ghc.nix`` file at the root of the
+repository. In this file, you can use the Nix expression language to
+construct a compiler with all the packages you depend on in scope::
+
+  with (import <nixpkgs> {});
+
+  haskellPackages.ghcWithPackages (p: with p; [
+    containers
+    lens
+    text
+  ])
+
+Each package mentioned in ``ghc.nix`` can then be imported using
+`haskell_toolchain_library`_ in ``BUILD`` files.
+
+.. _haskell_toolchain_library: http://api.haskell.build/haskell/haskell.html#haskell_toolchain_library
+
+Building code with Hackage dependencies (using Hazel)
+-----------------------------------------------------
+
+.. todo::
+
+   Explain how to use Hazel instead of Nix
+
+Generating API documentation
+----------------------------
+
+The `haskell_doc`_ rule can be used to build API documentation for
+a given library (using Haddock). Building a target called
+``//my/pkg:mylib_docs`` would make the documentation available at
+``bazel-bin/my/pkg/mylib_docs/index/index.html``.
+
+Alternatively, you can use the
+``@io_tweag_rules_haskell//haskell:haskell.bzl%haskell_doc_aspect``
+aspect to ask Bazel from the command-line to build documentation for
+any given target (or indeed all targets), like in the following:
+
+.. code-block:: console
+
+  $ bazel build //my/pkg:mylib \
+      --aspects @io_tweag_rules_haskell//haskell:haskell.bzl%haskell_doc_aspect
+
+.. _haskell_doc: http://api.haskell.build/haskell/haddock.html#haskell_doc
+
+Linting your code
+-----------------
+
+The `haskell_lint`_ rule does not build code but runs the GHC
+typechecker on all listed dependencies. Warnings are treated as
+errors.
+
+Alternatively, you can directly check a target using
+
+.. code-block:: console
+
+  $ bazel build //my/haskell:target \
+      --aspects @io_tweag_rules_haskell//haskell:haskell.bzl%haskell_lint_aspect
+
+.. _haskell_lint: http://api.haskell.build/haskell/lint.html#haskell_lint
+
+Checking code coverage
+----------------------
+
+"Code coverage" is the name given to metrics that describe how much source 
+code is covered by a given test suite.  A specific code coverage metric 
+implemented here is expression coverage, or the number of expressions in 
+the source code that are explored when the tests are run.
+
+Haskell's ``ghc`` compiler has built-in support for code coverage analysis, 
+through the hpc_ tool. The Haskell rules allow the use of this tool to analyse 
+``haskell_library`` coverage by ``haskell_test`` rules. To do so, you have a 
+few options. You can add 
+``expected_covered_expressions_percentage=<some integer between 0 and 100>`` to
+the attributes of a ``haskell_test``, and if the expression coverage percentage
+is lower than this amount, the test will fail. Alternatively, you can add
+``expected_uncovered_expression_count=<some integer greater or equal to 0>`` to
+the attributes of a ``haskell_test``, and instead the test will fail if the
+number of uncovered expressions is greater than this amount. Finally, you could
+do both at once, and have both of these checks analyzed by the coverage runner.
+To see the coverage details of the test suite regardless of if the test passes
+or fails, add ``--test_output=all`` as a flag when invoking the test, and there 
+will be a report in the test output. You will only see the report if you
+required a certain level of expression coverage in the rule attributes.
+
+For example, your BUILD file might look like this: ::
+
+  haskell_library(
+    name = "lib",
+    srcs = ["Lib.hs"],
+    deps = [
+        "//tests/hackage:base",
+    ],
+  )
+
+  haskell_test(
+    name = "test",
+    srcs = ["Main.hs"],
+    deps = [
+        ":lib",
+        "//tests/hackage:base",
+    ],
+    expected_covered_expressions_percentage = 80,
+    expected_uncovered_expression_count = 10,
+  )
+
+And if you ran ``bazel coverage //somepackage:test --test_output=all``, you 
+might see a result like this: ::
+
+  INFO: From Testing //somepackage:test:
+  ==================== Test output for //somepackage:test:
+  Overall report
+  100% expressions used (9/9)
+  100% boolean coverage (0/0)
+      100% guards (0/0)
+      100% 'if' conditions (0/0)
+      100% qualifiers (0/0)
+  100% alternatives used (0/0)
+  100% local declarations used (0/0)
+  100% top-level declarations used (3/3)
+  =============================================================================
+
+Here, the test passes because it actually has 100% expression coverage and 0
+uncovered expressions, which is even better than we expected on both counts.
+
+There is an optional ``haskell_test`` attribute called
+``strict_coverage_analysis``, which is a boolean that changes the coverage
+analysis such that even having better coverage than expected fails the test.
+This can be used to enforce that developers must upgrade the expected test
+coverage when they improve it. On the other hand, it requires changing the
+expected coverage for almost any change.
+
+There a couple of notes regarding the coverage analysis functionality:
+
+- Coverage analysis currently is scoped to all source files and all
+  locally-built Haskell dependencies (both direct and transitive) for a given
+  test rule.
+- Coverage-enabled build and execution for ``haskell_test`` targets may take
+  longer than regular. However, this has not effected regular ``run`` /
+  ``build`` / ``test`` performance.
+
+.. _hpc: <http://hackage.haskell.org/package/hpc>
diff --git a/third_party/bazel/rules_haskell/docs/haskell.rst b/third_party/bazel/rules_haskell/docs/haskell.rst
new file mode 100644
index 000000000000..353561111a21
--- /dev/null
+++ b/third_party/bazel/rules_haskell/docs/haskell.rst
@@ -0,0 +1,364 @@
+.. _guide:
+
+Introduction to Bazel: Building a Haskell project
+=================================================
+
+In this tutorial, you'll learn the basics of building Haskell
+applications with Bazel. You will set up your workspace and build
+a simple Haskell project that illustrates key Bazel concepts, such as
+targets and ``BUILD.bazel`` files. After completing this tutorial, take
+a look at :ref:`Common Haskell build use cases <use-cases>` for
+information on more advanced concepts such as writing and running
+Haskell tests.
+
+What you'll learn
+-----------------
+
+In this tutorial you'll learn how to:
+
+* build a target,
+* visualize the project's dependencies,
+* split the project into multiple targets and packages,
+* control target visibility across packages,
+* reference targets through labels.
+
+Before you begin
+----------------
+
+To prepare for the tutorial, first `install Bazel`_ if you don't have
+it installed already. Then, retrieve the ``rules_haskell`` GitHub
+repository::
+
+  git clone https://github.com/tweag/rules_haskell/
+
+The sample project for this tutorial is in the ``tutorial``
+directory and is structured as follows::
+
+  rules_haskell
+  └── tutorial
+     ├── WORKSPACE
+     ├── main
+     │  ├── BUILD.bazel
+     │  └── Main.hs
+     └── lib
+        ├── BUILD.bazel
+        └── Bool.hs
+
+The first thing to do is to::
+
+  $ cd tutorial
+
+Build with Bazel
+----------------
+
+Set up the workspace
+^^^^^^^^^^^^^^^^^^^^
+
+Before you can build a project, you need to set up its workspace.
+A workspace is a directory that holds your project's source files and
+Bazel's build outputs. It also contains files that Bazel recognizes as
+special:
+
+* the ``WORKSPACE`` file, which identifies the directory and its
+  contents as a Bazel workspace and lives at the root of the project's
+  directory structure,
+
+* one or more ``BUILD.bazel`` files, which tell Bazel how to build different
+  parts of the project. (A directory within the workspace that
+  contains a ``BUILD.bazel`` file is a *package*. You will learn about
+  packages later in this tutorial.)
+
+To designate a directory as a Bazel workspace, create an empty file
+named ``WORKSPACE`` in that directory.
+
+When Bazel builds the project, all inputs and dependencies must be in
+the same workspace. Files residing in different workspaces are
+independent of one another unless linked, which is beyond the scope of
+this tutorial.
+
+Understand the BUILD file
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is recommended to use a ``.bazel`` extension for each ``BUILD`` file to
+avoid clashing with files or folders already using that name.
+
+A ``BUILD.bazel`` file contains several different types of instructions for
+Bazel. The most important type is the *build rule*, which tells Bazel
+how to build the desired outputs, such as executable binaries or
+libraries. Each instance of a build rule in the ``BUILD.bazel`` file is
+called a *target* and points to a specific set of source files and
+dependencies. A target can also point to other targets.
+
+Take a look at the ``BUILD.bazel`` file in the ``tutorial/lib`` directory::
+
+  haskell_library(
+      name = "booleans",
+      srcs = ["Bool.hs"],
+  )
+
+In our example, the ``booleans`` target instantiates the
+`haskell_library`_ rule. The rule tells Bazel to build a reusable
+(statically or dynamically linked) library from the ``Bool.hs`` source
+file with no dependencies.
+
+The attributes in the target explicitly state its dependencies and
+options. While the ``name`` attribute is mandatory, many are optional.
+For example, in the ``booleans`` target, ``name`` is self-explanatory,
+and ``srcs`` specifies the source file(s) from which Bazel builds the
+target.
+
+Build the project
+^^^^^^^^^^^^^^^^^
+
+Let's build your sample project. Run the following command::
+
+  $ bazel build //lib:booleans
+
+Notice the target label - the ``//lib:`` part is the location of our
+``BUILD.bazel`` file relative to the root of the workspace, and ``booleans``
+is what we named that target in the ``BUILD.bazel`` file. (You will learn
+about target labels in more detail at the end of this tutorial.)
+
+Bazel produces output similar to the following::
+
+  INFO: Found 1 target...
+  Target //lib:booleans up-to-date:
+    bazel-bin/lib/libZSbooleans/libZSbooleans.conf
+    bazel-bin/lib/libZSbooleans/package.cache
+  INFO: Elapsed time: 2.288s, Critical Path: 0.68s
+
+Congratulations, you just built your first Bazel target! Bazel places
+build outputs in the ``bazel-bin`` directory at the root of the
+workspace. Browse through its contents to get an idea for Bazel's
+output structure.
+
+Review the dependency graph
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A successful build has all of its dependencies explicitly stated in
+the ``BUILD.bazel`` file. Bazel uses those statements to create the
+project's dependency graph, which enables accurate incremental builds.
+
+Let's visualize our sample project's dependencies. First, generate
+a text representation of the dependency graph (run the command at the
+workspace root)::
+
+  bazel query --nohost_deps --noimplicit_deps \
+    'deps(//lib:booleans)' --output graph
+
+The above command tells Bazel to look for all dependencies for the
+target ``//lib:booleans`` (excluding host and implicit dependencies)
+and format the output as a graph.
+
+Then, paste the text into GraphViz_.
+
+On Ubuntu, you can view the graph locally by installing GraphViz and the xdot
+Dot Viewer::
+
+  sudo apt update && sudo apt install graphviz xdot
+
+Then you can generate and view the graph by piping the text output above
+straight to xdot::
+
+  xdot <(bazel query --nohost_deps --noimplicit_deps \
+           'deps(//lib:booleans)' --output graph)
+
+As you can see, the first stage of the sample project has a single
+target that builds a single source file with no additional
+dependencies:
+
+.. digraph:: booleans
+
+   node [shape=box];
+   "//lib:booleans"
+   "//lib:booleans" -> "//lib:Bool.hs"
+   "//lib:Bool.hs"
+
+Now that you have set up your workspace, built your project, and
+examined its dependencies, let's add some complexity.
+
+Refine your Bazel build
+-----------------------
+
+While a single target is sufficient for small projects, you may want
+to split larger projects into multiple targets and packages to allow
+for fast incremental builds (that is, only rebuild what's changed) and
+to speed up your builds by building multiple parts of a project at
+once.
+
+Specify multiple build targets
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Let's split our sample project build into two targets. Take a look at
+the ``BUILD.bazel`` files in the ``tutorial/lib`` and ``tutorial/main``
+directories. The contents of both files could have been kept in
+a single ``BUILD.bazel`` as follows::
+
+  haskell_library(
+      name = "booleans",
+      srcs = ["Bool.hs"],
+  )
+
+  haskell_toolchain_library(name = "base")
+
+  haskell_binary(
+      name = "demorgan",
+      srcs = ["Main.hs"],
+      compiler_flags = ["-threaded"],
+      deps = [":base", ":booleans"],
+  )
+
+With this single ``BUILD.bazel`` file, Bazel first builds the ``booleans``
+library (using the `haskell_library`_ rule), then the ``demorgan``
+binary (which as an example uses the ``booleans`` library to check one
+of the De Morgan laws). The ``deps`` attribute in the ``demorgan``
+target tells Bazel that the ``:booleans`` library is required to build
+the ``demorgan`` binary. The binary also requires the ``base``
+built-in library that ships with GHC, to perform I/O among other
+things. Libraries like ``base``, ``bytestring`` and others that ship
+with GHC are special in that they are prebuilt outside of Bazel. To
+import them as regular targets, we use the `haskell_toolchain_library`_ rule.
+
+Let's build this new version of our project::
+
+  $ bazel build //main:demorgan
+
+Bazel produces output similar to the following::
+
+  INFO: Found 1 target...
+  Target //main:demorgan up-to-date:
+    bazel-bin/main/demorgan
+  INFO: Elapsed time: 2.728s, Critical Path: 1.23s
+
+Now test your freshly built binary::
+
+  $ bazel-bin/main/demorgan
+
+Or alternatively::
+
+  $ bazel run //main:demorgan
+
+If you now modify ``Bool.hs`` and rebuild the project, Bazel will
+usually only recompile that file.
+
+Looking at the dependency graph:
+
+.. digraph:: demorgan
+
+  node [shape=box];
+  "//main:demorgan"
+  "//main:demorgan" -> "//main:base\n//main:Main.hs"
+  "//main:demorgan" -> "//lib:booleans"
+  "//lib:booleans"
+  "//lib:booleans" -> "//lib:Bool.hs"
+  "//lib:Bool.hs"
+  "//main:base\n//main:Main.hs"
+
+You have now built the project with two targets. The ``demorgan``
+target builds one source file and depends on one other target
+(``//lib:booleans``), which builds one additional source file.
+
+Use multiple packages
+^^^^^^^^^^^^^^^^^^^^^
+
+Let’s now split the project into multiple packages.
+
+Notice that we actually have two sub-directories, and each contains
+a ``BUILD.bazel`` file. Therefore, to Bazel, the workspace contains two
+packages, ``lib`` and ``main``.
+
+Take a look at the ``lib/BUILD.bazel`` file::
+
+  haskell_library(
+      name = "booleans",
+      srcs = ["Bool.hs"],
+      visibility = ["//main:__pkg__"],
+  )
+
+And at the ``main/BUILD.bazel`` file::
+
+  haskell_toolchain_library(name = "base")
+
+  haskell_binary(
+      name = "demorgan",
+      srcs = ["Main.hs"],
+      compiler_flags = ["-threaded"],
+      deps = [":base", "//lib:booleans"],
+  )
+
+As you can see, the ``demorgan`` target in the ``main`` package
+depends on the ``booleans`` target in the ``lib`` package (hence the
+target label ``//lib:booleans``) - Bazel knows this through the
+``deps`` attribute.
+
+Notice that for the build to succeed, we make the ``//lib:booleans``
+target in ``lib/BUILD.bazel`` explicitly visible to targets in
+``main/BUILD.bazel`` using the ``visibility`` attribute. This is because by
+default targets are only visible to other targets in the same
+``BUILD.bazel`` file. (Bazel uses target visibility to prevent issues such
+as libraries containing implementation details leaking into public
+APIs.)
+
+You have built the project as two packages with three targets and
+understand the dependencies between them.
+
+Use labels to reference targets
+-------------------------------
+
+In ``BUILD.bazel`` files and at the command line, Bazel uses *labels* to
+reference targets - for example, ``//main:demorgan`` or
+``//lib:booleans``. Their syntax is::
+
+  //path/to/package:target-name
+
+If the target is a rule target, then ``path/to/package`` is the path
+to the directory containing the ``BUILD.bazel`` file, and ``target-name`` is
+what you named the target in the ``BUILD.bazel`` file (the ``name``
+attribute). If the target is a file target, then ``path/to/package``
+is the path to the root of the package, and ``target-name`` is the
+name of the target file, including its full path.
+
+When referencing targets within the same package, you can skip the
+package path and just use ``//:target-name``. When referencing targets
+within the same ``BUILD.bazel`` file, you can even skip the ``//`` workspace
+root identifier and just use ``:target-name``.
+
+Further reading
+---------------
+
+Congratulations! You now know the basics of building a Haskell project
+with Bazel. Next, read up on the most common :ref:`Common Haskell
+build use cases <use-cases>`. Then, check out the following:
+
+* `External Dependencies`_ to learn more about working with local and
+   remote repositories.
+
+* The `Build Encyclopedia`_ to learn more about Bazel.
+
+* The `C++ build tutorial`_ to get started with building C++
+  applications with Bazel.
+
+* The `Java build tutorial`_ to get started with building Java
+  applications with Bazel.
+
+* The `Android application tutorial`_ to get started with building
+  mobile applications for Android with Bazel.
+
+* The `iOS application tutorial`_ to get started with building mobile
+  applications for iOS with Bazel.
+
+Happy building!
+
+.. note:: This tutorial is adapted from the Bazel `C++ build tutorial`_.
+
+.. _install Bazel: https://docs.bazel.build/versions/master/install.html
+.. _haskell_binary: http://api.haskell.build/haskell/haskell.html#haskell_binary
+.. _haskell_toolchain_library: http://api.haskell.build/haskell/haskell.html#haskell_toolchain_library
+.. _haskell_library: http://api.haskell.build/haskell/haskell.html#haskell_library
+.. _graphviz: https://www.graphviz.org/
+.. _external dependencies: https://docs.bazel.build/versions/master/external.html
+.. _build encyclopedia: https://docs.bazel.build/versions/master/be/overview.html
+.. _C++ build tutorial: https://docs.bazel.build/versions/master/tutorial/cpp.html
+.. _Java build tutorial: https://docs.bazel.build/versions/master/tutorial/java.html
+.. _Android application tutorial: https://docs.bazel.build/versions/master/tutorial/android-app.html
+.. _iOS application tutorial: https://docs.bazel.build/versions/master/tutorial/ios-app.html
diff --git a/third_party/bazel/rules_haskell/docs/index.rst b/third_party/bazel/rules_haskell/docs/index.rst
new file mode 100644
index 000000000000..f9292871ef55
--- /dev/null
+++ b/third_party/bazel/rules_haskell/docs/index.rst
@@ -0,0 +1,23 @@
+.. meta::
+   :description: User guide for building Haskell code with Bazel.
+
+Build Haskell Using Bazel
+=========================
+
+Bazel_ is a tool for automating the *building* and the *testing* of
+software. Follow :ref:`this guide <guide>` to get started building
+small Haskell projects using Bazel. For a deeper dive and solutions to
+more advanced use cases, see :ref:`Common Haskell Build Use Cases
+<use-cases>`. Refer to the `Bazel documentation`_ for more about
+Bazel.
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+   why-bazel
+   haskell
+   haskell-use-cases
+
+.. _Bazel: https://bazel.build
+.. _Bazel documentation: https://docs.bazel.build/versions/master/getting-started.html
diff --git a/third_party/bazel/rules_haskell/docs/why-bazel.rst b/third_party/bazel/rules_haskell/docs/why-bazel.rst
new file mode 100644
index 000000000000..2ad4bc598be3
--- /dev/null
+++ b/third_party/bazel/rules_haskell/docs/why-bazel.rst
@@ -0,0 +1,102 @@
+.. _why-bazel:
+
+Is Bazel right for me?
+======================
+
+Nearly as many build tools exist as there are programming languages
+out there. C++ has Autotools_/Make_, CMake_ and many others. Java has
+Ant_, Maven_, Gradle_ and several more. Haskell has Cabal_, Stack_,
+Shake_ and several more. Each of these originated in a given language
+community but are in some cases generic enough to support building any
+language. Are any of them the right choice for your use case? Should
+you be combining several systems? That's what this document should
+help you answer.
+
+Rule of thumb
+-------------
+
+If a combination of the following apply, then you're better off using
+Cabal_ or Stack_:
+
+* your project is an independently publishable single library, or
+  small set of libraries;
+* your project is open source code and has at most small static
+  assets (hence publishable on Hackage);
+* your project is nearly entirely Haskell code with perhaps a little
+  bit of C;
+* your project has many dependencies on other packages found on
+  Hackage but few if any system dependencies (like zlib, libpng etc);
+
+Bazel works well for the following use cases:
+
+* projects that cannot be hosted on Hackage (games with large static
+  assets, proprietary code etc);
+* projects with a very large amount of code hosted in a single
+  repository;
+* projects in which you or your team are writing code in two or more
+  languages (e.g. Haskell/PureScript, or Haskell/Java, or
+  Haskell/C++/FORTRAN);
+
+Rationale
+---------
+
+For all the benefits it can bring, Bazel also has an upfront cost.
+Don't pay that cost if the benefits don't justify it.
+
+If you don't have much code to build, any build tool will do. Build
+issues like lack of complete reproducibility are comparatively easier
+to debug, and working around build system bugs by wiping the entire
+build cache first is entirely viable in this particular case. So might
+as well use low-powered Haskell-native build tools that ship with GHC.
+You won't *need* sandboxed build actions to guarantee build system
+correctness, completely hermetic builds for good reproducibility,
+build caching, test result caching or distributed builds for faster
+build and test times. Those features start to matter for larger
+projects, and become essential for very large monorepos_.
+
+Why exactly do these features matter?
+
+* **Hermetic builds** are builds that do not take any part of the
+  host's system configuration (set of installed system libraries and
+  their versions, content of ``/etc``, OS version, etc) as an input.
+  If all build actions are deterministic, hermeticity guarantees that
+  builds are reproducible anywhere, anytime. More developers on
+  a project means more subtly different system configurations to cope
+  with. The more system configurations, the more likely that the build
+  will fail in one of these configurations but not in others... Unless
+  the build is completely hermetic.
+* **Sandboxing build actions** guarantees that all inputs to all build
+  actions are properly declared. This helps prevent build system
+  correctness bugs, which are surprisingly and exceedingly common in
+  most non-sandboxing build systems, especially as the build system
+  becomes more complex. When a build system *might* be incorrect,
+  users regularly have to wipe the entire build cache to work around
+  issues. As the codebase becomes very large, rebuilding from scratch
+  can cost a lot of CPU time.
+* **Distributed build caches** make building the code from a fresh
+  checkout trivially fast. Continuous integration populates the build
+  cache at every branch push, so that building all artifacts from
+  fresh checkouts seldom needs to actually build anything at all
+  locally. In the common case, builds become network-bound instead of
+  CPU-bound.
+* **Distributed build action execution** mean that average build times
+  can stay constant even as the codebase grows, because you can
+  seamlessly distribute the build on more machines.
+* **Test result caching** is the key to keeping continuous
+  integration times very low. Only those tests that depend on code
+  that was modified need be rerun.
+
+On their own hermetic and sandboxed builds can already save quite
+a few headaches. But crucially, without them one can't even hope to
+have any of the other features that follow them above.
+
+.. _Autotools: https://en.wikipedia.org/wiki/GNU_Build_System
+.. _Make: https://en.wikipedia.org/wiki/Make_(software)
+.. _CMake: https://cmake.org/
+.. _Ant: https://ant.apache.org/
+.. _Maven: https://maven.apache.org/index.html
+.. _Gradle: https://gradle.org/
+.. _Cabal: https://www.haskell.org/cabal/
+.. _Stack: http://haskellstack.org/
+.. _Shake: https://shakebuild.com/
+.. _monorepos: https://en.wikipedia.org/wiki/Monorepo