cabal2nix icon indicating copy to clipboard operation
cabal2nix copied to clipboard

Make implicit flag configuration explicit?

Open turboMaCk opened this issue 4 years ago • 4 comments

EDIT: The thread starts matching the subject at https://github.com/NixOS/cabal2nix/issues/442#issuecomment-595954664. The prior messages are about a concrete error that lead to this conversation. I'll leave the original bug report in place below.


Given the package that uses Cabal Flags I've observed the following behavior.

  1. Package that sets flag to True by default is automatically built with this flag disabled (example: hakyll in nixpkgs)
  2. jailbreak doesn't remove versions constraints for dependencies under conditional flag.

Example

Given cabal file like this:

Flag watchServer
  Description: Include the watch server
  Default:     True

Build-Depends:
    base                 >= 4.8      && < 5

  If flag(watchServer)
    Build-depends:
      fsnotify        >= 0.2   && < 0.4

using cabal2nix and building the package binary is built with watchServer disabled.

When watch server is manually enabled:

 configureFlags = "-f watchServer"

jailbreak does remove the constrain for base but does not for fsnotify it seems.

Workaround

It's possible to set flags using configureFlags and apply patch using paches for instance to "jailbreak" conditional dependecies.

Related issues

  • https://github.com/NixOS/cabal2nix/issues/217

Note

This is based on observed behaviour, I did not dig deeper into this. I'm willing to dig deeper into this if you want to.

turboMaCk avatar Feb 20 '20 10:02 turboMaCk

  1. Package that sets flag to True by default is automatically built with this flag disabled (example: hakyll in nixpkgs)

I'm not sure what you mean. cabal2nix let's Cabal make all decisions about flag values, so its behavior should be pretty much identical to cabal-install. If a default value is specified as true, then the flag will almost always come out as true unless there are other constraints involved. In any case, you can simply specify desired flag assignments on the cabal2nix command-line if you're unhappy with the default choice.

  1. jailbreak doesn't remove versions constraints for dependencies under conditional flag.

Please see the discussion at https://github.com/peti/jailbreak-cabal/issues/7#issuecomment-87445882.

peti avatar Feb 29 '20 20:02 peti

  1. Steps to reproduce:
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.hakyll])
$ hakyll-init my-site
$ cd my-site
$ cabal run site -- watch
PREVIEW SERVER

The preview server is not enabled in the version of Hakyll. To
enable it, set the flag to True and recompile Hakyll.
Alternatively, use an external tool to serve your site directory.


$  ghc-pkg list | grep hakyll
    hakyll-4.13.0.1

This indicates the version of hakyll in nixpkgs is not built with previewServer flag but this flag is True by defaul. I didin't find any override disabling this explicitly in nixpkgs. I can't explain this behaviour.

As mentioned above, overrideAttrs and adding configureFlags = "-f previewServer -f watchServer" fixes this problem.

  1. Thanks for explanation now I see the reasoning and agree current behaviour is best what can be done.

turboMaCk avatar Feb 29 '20 21:02 turboMaCk

cabal2nix determines a set of flags that it expects the build to enable at configure time. That flag set determines, among other things, which dependencies are enabled and included in the build environment. Now, at compile time Cabal might decide that it cannot use that particular set of flags, e.g. because the dependencies we've passed don't satisfy the configured version constraints. In that case, Cabal decides on the fly to disable the affected flag.

Now, this means that the resulting binaries will be configured differently than we expected them to be. Furthermore, the build has probably been run with dependencies included in the environment that were never used. And, of course, you'll never get an error message for the dependency that didn't fit into the version constraints and thus never realize the "default flags" are actually not used for that build.

One solution to avoid this issue to make all implicit flag configuration explicit, i.e. cabal2nix should explicitly list all flags it expects to be enabled (or disabled) in the configureFlags attribute to force Cabal to use that configuration or fail.

peti avatar Mar 06 '20 20:03 peti

Thanks for taking the time to reproduce this and explain the issue on stream @peti. I was unaware that cabal can simply decide to ignore flag if it can't satisfy dependencies scoped to that flag.

turboMaCk avatar Mar 06 '20 20:03 turboMaCk