summary refs log tree commit diff
path: root/third_party/bazel/rules_haskell/docs/haskell.rst
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/bazel/rules_haskell/docs/haskell.rst')
-rw-r--r--third_party/bazel/rules_haskell/docs/haskell.rst364
1 files changed, 364 insertions, 0 deletions
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