Skip to content

Commit

Permalink
Merge branch 'stable'
Browse files Browse the repository at this point in the history
  • Loading branch information
mpilgrem committed Mar 1, 2025
2 parents 8b65c31 + 7d99572 commit d12a032
Showing 1 changed file with 76 additions and 51 deletions.
127 changes: 76 additions & 51 deletions doc/tutorial/cabal_flags_and_ghc_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

# 10. Cabal flags and GHC options

There are two common ways to alter how a package will install: with Cabal flags
and with GHC options.
There are two common ways to affect how a package will be built: with Cabal
flags and with GHC options.

## Cabal flag management
## Cabal flags

To change a Cabal flag setting, we can use the command line `--flag` option. The
`yackage` package has an `upload` flag that is enabled by default. We can
command:
Cabal flags can be set or unset at the command line or as a project-specific
Stack option.

To set or unset a Cabal flag at the command line, we can use the `--flag`
option. The `yackage` package has an `upload` flag that is enabled by default.
We can command:

~~~text
stack build --flag yackage:-upload
Expand Down Expand Up @@ -38,64 +41,84 @@ option documentation.

## GHC options

GHC options follow a similar logic as in managing Cabal flags, with a few
nuances to adjust for common use cases. Let's consider the command:
GHC options can be specified at the command line or as an non-project specific
Stack option.

At the command line, consider the command:

~~~text
stack build --ghc-options="-Wall -Werror"
~~~

This will set the `-Wall -Werror` options for all *local targets*. Note that
this will not affect extra-dep and snapshot packages at all. This design
or, equivalently:

~~~text
stack build --ghc-options=--pedantic
~~~

By default, this will set GHC's `-Wall` and `-Werror` options for all *project
packages*. This will not, however, affect other packages at all. This design
provides us with reproducible and fast builds.

(By the way: the above GHC options have a special convenience flag:
`--pedantic`.)
??? question "Can GHC options for other packages be specified at the command line?"

There's one extra nuance about command line GHC options: Since they only apply
to local targets, if you change your local targets, they will no longer apply
to other packages. Let's play around with an example from the `wai` repository,
which includes the `wai` and `warp` packages, the latter depending on the
former. If we command again:
Yes, GHC options can be specified at the command line for all packages or
only project packages that are targets. For further information, see the
documentation for the
[apply-ghc-options](../configure/yaml/non-project.md#apply-ghc-options)
non-project specific configuration option.

~~~text
stack build --ghc-options=-O0 wai
~~~
??? question "What if GHC options specified at the command line apply only to targets?"

It will build all of the dependencies of `wai`, and then build `wai` with all
optimizations disabled. Now let's add in `warp` as well. Command:
By changing the default using the
[apply-ghc-options](../configure/yaml/non-project.md#apply-ghc-options)
configuration option, it is possble to specify that GHC options at the
command line apply only to project packages that are *targets*. If this is
done and you change your targets, the options will no longer apply to other
project packages.

~~~text
stack build --ghc-options=-O0 wai warp
~~~
Let us consider an example from the `wai` repository, which includes the
`wai` and `warp` packages, the latter depending on the former. If we
command:

This builds the additional dependencies for `warp`, and then builds `warp` with
optimizations disabled. Importantly: it does not rebuild `wai`, since `wai`'s
configuration has not been altered. Now the surprising case. Command:
~~~text
stack build --ghc-options=-O0 wai
~~~

~~~text
stack build --ghc-options=-O0 warp
wai-3.0.3.0-5a49351d03cba6cbaf906972d788e65d: unregistering (flags changed from ["--ghc-options","-O0"] to [])
warp-3.1.3-a91c7c3108f63376877cb3cd5dbe8a7a: unregistering (missing dependencies: wai)
wai-3.0.3.0: configure
~~~
Stack will build all of the dependencies of `wai` (inclduding `warp`) and then
build `wai` with all GHC optimizations disabled.

You may expect this to be a no-op: neither `wai` nor `warp` has changed.
However, Stack will instead recompile `wai` with optimizations enabled again,
and then rebuild `warp` (with optimizations disabled) against this newly built
`wai`. The reason: reproducible builds. If we'd never built `wai` or `warp`
before, trying to build `warp` would necessitate building all of its
dependencies, and it would do so with default GHC options (optimizations
enabled). This dependency would include `wai`. So when we command:
Now let's add `warp` as a target. If we command:

~~~text
stack build --ghc-options=-O0 warp
~~~
~~~text
stack build --ghc-options=-O0 wai warp
~~~

this builds the additional dependencies for `warp`, and then builds `warp`
with GHC optimizations disabled. Importantly, Stack does not rebuild `wai`,
since `wai`'s configuration has not been altered.

Now the surprising case. If we command:

~~~text
stack build --ghc-options=-O0 warp
~~~

you may expect this to do nothing, as neither `wai` nor `warp` has changed.
However, Stack will rebuild `wai` with GHC optimizations enabled again, and
then rebuild `warp` (with optimizations disabled) against this newly-built
`wai`. The reason is reproducible builds. If we had never built `wai` or
`warp` before, trying to build `warp` would require building all of its
dependencies, and it would do so with default GHC options (that is, GHC
optimizations enabled). These dependencies would include `wai`. So when we
command:

~~~text
stack build --ghc-options=-O0 warp
~~~

We want its behavior to be unaffected by any previous build steps we took.
While this specific corner case does catch people by surprise, the overall goal
of reproducible builds is - in the Stack maintainers' views - worth the
confusion.
we want Stack's behavior to be unaffected by any previous build steps we
took.

If you have GHC options that you will be applying regularly when building your
packages, you can add them to your Stack project-level configuration file
Expand All @@ -105,7 +128,9 @@ For more information, see the
[ghc-options](../configure/yaml/non-project.md#ghc-options) non-project specific
configuration option documentation.

!!! note
??? question "Can Stack be configured to specify GHC options for specific packages?"

That's it, the heavy content of this guide is done! Everything from here on
out is simple explanations of commands. Congratulations!
Yes, Stack can be configured to specify GHC options for specific packages,
either globally or at the project level. For more information, see the
[ghc-options](../configure/yaml/non-project.md#ghc-options) non-project
specific configuration option documentation.

0 comments on commit d12a032

Please sign in to comment.