Skip to content

Drop hpack, make it easier to use cabal-install#3933

Merged
hdgarrood merged 7 commits intopurescript:masterfrom
hdgarrood:no-hpack
Mar 18, 2021
Merged

Drop hpack, make it easier to use cabal-install#3933
hdgarrood merged 7 commits intopurescript:masterfrom
hdgarrood:no-hpack

Conversation

@hdgarrood
Copy link
Copy Markdown
Contributor

Stack offers a relatively poor developer experience on this repository
right now. The main issue is that build products are invalidated far
more often than they should be. cabal-install is better at this, but
using cabal-install together with hpack is a bit awkward.

Additionally, hpack isn't really pulling its weight these days. Current
versions of stack recommend that you check your generated cabal file in,
which is a huge pain as you have to explain to contributors to please
leave the cabal file alone and edit package.yaml instead (the comment
saying the file is auto-generated is quite easy to miss).

Current versions of Cabal also solve the issues which made hpack
appealing in the first place, namely:

  • common stanzas mean you don't have to repeat yourself for things like
    -Wall or dependencies
  • tests are run from inside a source distribution by default, which
    means that if you forget to include something in extra-source-files
    you find out when you run the tests locally, rather than having to
    wait for CI to fail
  • the globbing syntax is slightly more powerful (admittedly not quite as
    powerful as hpack's, but you can use globs like tests/**/*.purs now,
    which gets us close enough to hpack that the difference is basically
    negligible).

We do still need to manually maintain exposed-modules lists, but I am
happy to take that in exchange for the build tool not invalidating our
build products all the time.

This PR drops hpack in favour of manually-maintained Cabal files. It
also introduces a cabal.project file and a cabal.project.freeze file
which make it easier to use cabal-install as a build tool when working
on this repo. Stack still works, and the CI, contributing, and
installation docs still use Stack.

Since the npm installer uses Stack when building from source, it would
be difficult for us to drop support for Stack entirely, and so I don't
intend to work towards dropping Stack support. If this PR is merged, I
will probably start using cabal-install as my main build tool when
working on the compiler locally, and I might also update the
installation and contributing docs to do the same.

Stack works a little better now than it used to, because I think one of
the causes of unnecessary rebuilds was us specifying optimization flags
in the Cabal file. (Newer versions of Cabal warn you not to do this, so
I think this might be a known issue). To ensure that release builds are
built with -O2, I've updated the CI script to specify that advanced
optimizations should be used via the CLI (see ci/build.sh).

@rhendric
Copy link
Copy Markdown
Member

For a developer wanting to test the impact of a change on compiler performance, does this mean that they now have to explicitly run stack build --ghc-options=-O2 to get an appropriately optimized build? That seems like it might be easy to forget to do. Should we maybe add a Makefile target for this purpose?

@hdgarrood
Copy link
Copy Markdown
Contributor Author

Right, that's a good point. There's an implicit assumption which I forgot to draw attention to, which is that I think disabling optimizations is the most appropriate default for local development, since it saves so much time and most changes aren't specifically related to performance. At the moment with what's in this PR, cabal build will build with -O0 (because of the optimization: False in cabal.project), and stack build will build with -O1 (because it's not specified anywhere and -O1 is the default). That's not ideal; they should probably be the same. I think we can add ghc-options: "$locals": -O0 to give Stack the same default behaviour, according to https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-options.

I'm not too worried about people forgetting to enable optimizations, since a) performance work is a relatively small proportion of the work people do on the compiler, and b) even for performance work I'd probably want to spend most of my time with optimizations disabled; I'd only want them on when I'm actually benchmarking. I think it would be fairly obvious if someone did accidentally create a build without optimizations and benchmarked it against an optimized build. Adding a makefile target with stack build --ghc-options=-O2 does sound like a good idea.

@hdgarrood
Copy link
Copy Markdown
Contributor Author

I've just realised that disabling optimizations by default may not be such a good idea, as it means that people who are creating distributions of the compiler where they build it from source are likely to end up creating unoptimized builds. In particular, I think this would affect homebrew and the npm installer (which builds from source when it can't find a prebuilt binary for the current platform, or if the prebuilt binary it downloads doesn't work).

Stack offers a relatively poor developer experience on this repository
right now. The main issue is that build products are invalidated far
more often than they should be. cabal-install is better at this, but
using cabal-install together with hpack is a bit awkward.

Additionally, hpack isn't really pulling its weight these days. Current
versions of stack recommend that you check your generated cabal file in,
which is a huge pain as you have to explain to contributors to please
leave the cabal file alone and edit package.yaml instead (the comment
saying the file is auto-generated is quite easy to miss).

Current versions of Cabal also solve the issues which made hpack
appealing in the first place, namely:

- common stanzas mean you don't have to repeat yourself for things like
  -Wall or dependencies
- tests are run from inside a source distribution by default, which
  means that if you forget to include something in extra-source-files
  you find out when you run the tests locally, rather than having to
  wait for CI to fail
- the globbing syntax is slightly more powerful (admittedly not quite as
  powerful as hpack's, but you can use globs like tests/**/*.purs now,
  which gets us close enough to hpack that the difference is basically
  negligible).

We do still need to manually maintain exposed-modules lists, but I am
happy to take that in exchange for the build tool not invalidating our
build products all the time.

This PR drops hpack in favour of manually-maintained Cabal files. It
also introduces a cabal.project file and a cabal.project.freeze file
which make it easier to use cabal-install as a build tool when working
on this repo. Stack still works, and the CI, contributing, and
installation docs still use Stack.

Since the npm installer uses Stack when building from source, it would
be difficult for us to drop support for Stack entirely, and so I don't
intend to work towards dropping Stack support. If this PR is merged, I
will probably start using cabal-install as my main build tool when
working on the compiler locally, and I might also update the
installation and contributing docs to do the same.

Stack works a little better now than it used to, because I think one of
the causes of unnecessary rebuilds was us specifying optimization flags
in the Cabal file. (Newer versions of Cabal warn you not to do this, so
I think this might be a known issue). To ensure that release builds are
built with -O2, I've updated the CI script to specify that advanced
optimizations should be used via the CLI (see ci/build.sh).
@hdgarrood
Copy link
Copy Markdown
Contributor Author

After some discussion in Slack with @kritzcreek I've changed this to move back to only supporting Stack as a build tool by removing the cabal-install-specific configuration files, namely cabal.project and cabal.project.freeze, for two reasons: firstly, having config for two separate build tools means we have to maintain both of them (by running both in CI), or one of them will bitrot, and secondly, Stack still makes more sense as the default build tool because the Windows experience with cabal-install still leaves a bit to be desired. I think this PR now accomplishes the following:

  • moving the optimization flags out of the cabal file means less unnecessary rebuilding when switching between building and testing
  • moving away from hpack means that we are ready for when Stack drops support for our current setup of having package.yaml checked in and purescript.cabal ignored.

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.

3 participants