Skip to content
This repository

build dependencies for custom Setup.hs #948

Open
kowey opened this Issue May 31, 2012 · 5 comments

5 participants

Eric Kow Rogan Creswick Duncan Coutts Jason Dagit Mikhail Glushenkov
Eric Kow
kowey commented May 31, 2012

Projects often require custom Setup.hs files which in turn may rely on Haskell packages. Those packages may in turn depend on Cabal, perhaps without being too fussy about which version of Cabal they want.

It might be useful to be able to express the idea that the Setup script itself has dependencies. Rogan Creswick suggested maybe something that looks like

   CustomBuild
        Setup-is: Setup.hs
        Build-Depends:  ...
        Build-tools:    ...
        ...

Here was my musing about it: https://plus.google.com/114991347543804898741/posts/2Wpy3WWvGyH (not sure if I understood correctly, and my user claims that upping the cabal-version constraint [which should be unnecessary in that case] fixes it for them)

This appears to have come up for several projects:

  • GUI programmers on Mac might use a cabal-macosx package to help create application bundles for their executables
  • Pandoc's Setup.hs at one point needed something from a new version of the process package
  • Rogan Creswick filed this GSoC suggestion http://hackage.haskell.org/trac/summer-of-code/ticket/1602
  • Rogan also commented something about cabal-dev (which I didn't fully process, sorry, Rogan!)

To ensure that these packages are present, I sometimes abuse the build-depends for my executable, which appears to be insufficient because when a Haskell-naive user upgrades from one version of Cabal to another, you get into a kind of messy situation where the Setup.hs file wants to use one version of Cabal but it relies on the package which assumes another version of Cabal. It's the kind of thing that a Haskeller can just sort of muddle/bulldoze through, but for somebody who knows enough to type cabal install type commands but isn't otherwise a Haskeller, it can be seriously confusing.

Rogan Creswick

Cabal-dev's sandbox abstraction breaks a little because we can't specify explicit Setup.hs dependencies.

Specifically, when cabal builds the Setup.hs to generate a build tool that compiles the rest of the project, it uses the user and global package databases, without acknowledging any package-db path settings/flags (which is how cabal-dev controls the sandbox). Thus, when building setup.hs, cabal is unaware of the cabal-dev sandbox. Presumably, a fix to this would also enable the Setup.hs compilation step to use a custom package database. (I could see that being a separate issue, too.)

One of the common hacks to get around the absence of setup.hs dependencies is to put those deps. in the standard build-depends for your library/executable. Cabal-install will install them first, then build setup.hs. This often works if you are not using a sandbox, because those deps go into either the user or global package db. However, this does not work with cabal-dev (it may work with virthualenv, I haven't tried).

This also introduces other potential issues, as the dependencies for Setup.hs really have no relationship to the dependencies for your actual program/library, so spurious conflicts can incorrectly cause build failures, although that's somewhat of a separate bug... (each build artifact sortof needs it's own sandbox, at least morally.)

I encourage anyone reading this to look at the summer of code ticket Erik linked too, as it outlines other benefits of explicit Setup.hs dependencies (such as sharing complex extensions to Cabal via hackage).

Duncan Coutts
Owner

So I'm starting work on this.

I've been pondering the question of whether we should go for a "maximal" or "minimal" approach. By maximal I mean we treat the Setup a like other executables in the package, allowing all or almost all the options/fields allowed for executables. The minimal approach would be to allow the minimum necessary set of fields.

While maximal seems attractive at first, here's this issue: building the Setup.hs is the first thing any build/packaging system needs to do. Remember it is not just cabal-install that builds Setup.hs, it's also the scripts for distros and other custom build/package systems.

At the moment the Cabal spec makes clear that the primary interface to the package build system is the Setup.hs and that it's expected to be able to just be run directly. This proposed feature changes that: it means that the .cabal file must be consulted first. Tools will have to look at the .cabal file and see what build instructions are needed to build the Setup.hs and then do that.

While I think it's ok for the Setup.hs interface to become primarily a machine interface rather than a user interface (we've been moving in this direction for some time), we do still need to keep in mind that there are multiple implementations that need to build and then invoke the Setup.hs.

So that suggests we should go for a minimal approach. What is the minimum we can get away with / what is the most we can reasonably expect bash scripts invoking Setup.hs to do?

I propose:

  • build-depends (ie Haskell packages)
  • CPP macros to let the Setup.hs do conditional compilation based on the versions of packages its being built against (e.g. Cabal lib version)

and that's it. The build-depends is obviously the minimum we could consider, that's the main point. The CPP one is perhaps a bit of a burden on build/package tools (we'll see if we can minimise that by making it as simple as possible) but it's also another big pain point for custom Setup.hs.

The "Simple" build system already provides some quite nice package version macro support, creating a .h file like:

#define MIN_VERSION_filepath(major1,major2,minor) (\
  (major1) <  1 || \
  (major1) == 1 && (major2) <  3 || \
  (major1) == 1 && (major2) == 3 && (minor) <= 0)

I think this is probably a bit much to expect every tool to do. So I'm thinking of something simpler like:

ghc Setup.hs -cpp -DVERSION_filepath=010300

Rogan Creswick

@dcoutts fantastic!

I'm ok with the minimalistic approach. I think it's still generally a bad idea to have a really complex Setup.hs--that complexity should be moved into "real" packages, which you can specify in the build-depends.

The maximal approach does seem ideal, and I'd like to see that eventually, but I don't think it's strictly necessary. (The biggest real drawback I see to the minimal approach is that people may expect to have the same expressiveness in a setup build stanza as in an executable or libraries stanza, but that's more an annoyance than a real problem, and it may not actually be an issue at all in practice.)

Thanks!

Jason Dagit
dagit commented April 10, 2014

@dcoutts Thanks for taking a stab at this!

Mikhail Glushenkov
Owner

@dcoutts Awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.