cabal2nix
cabal2nix copied to clipboard
Make implicit flag configuration explicit?
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.
- Package that sets flag to
True
by default is automatically built with this flag disabled (example: hakyll in nixpkgs) -
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.
- 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.
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.
- 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.
- Thanks for explanation now I see the reasoning and agree current behaviour is best what can be done.
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.
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.