Open hvr opened 6 years ago
Can/cannot manual flag default value depend on automatic flag value?
flag old-time
manual : False
default: False
flag other-flag
manual :True
default: flag(old-time)
Concrete motivation for proposal would be good to have too. What existing problems it would solve?
@phadej that's a very good point; I've augmented the spec; a more drastic way would be to simply disallow any use of flag()
within default expressions.
My main use-case for this would be architectural conditionals; e.g. defaults for a manual flag inferred based on architecture or ghc versions (simplest case: a flag portable
which enables a pure Haskell version of an implementation avoiding any platform/compiler specific features), but with the ability for a user to override this default. Another use-case is a flag to enable pkgconfig
-based discoverability; you'd want this default on for some platforms like os(linux)
, but not necessarily on os(windows)
; otoh, some users may still prefer to turn on pkgconfig support on windows regardless. I stumble over this kind of situation every now and then, and keep wishing this had been already implemented...
Yes my use-case is basically ghc version.
My use-case for this is that my project has multiple frontend drivers, including a TUI driver, a gtk+ driver, and a Cocoa driver (and possibly others in the future). The gtk+ driver can in theory build on MacOS, but doing so requires a bunch of native library setup that normally won't be wanted; whereas gtk+ will be the preferred frontend for Linux builds.
I'd like to be able to have a "gtk" flag that defaults to False when os(darwin)
, defaults to True otherwise, and can be manually overridden in either case.
Here's a concrete usecase based on GHC versions.
HLS has a bunch of cabal flags determining whether to try and build in support for some tool or other, say stan
. Now, often we know that stan
will only build on certain GHC versions. We basically have two options:
haskell-language-server +stan
means "build HLS with stan
support, possibly getting build failures if it doesn't work on your GHC version". In this case we probably need to have the default value of the stan
flag be false
, so that HLS works when built from Hackage, which means that users need to manually set a bunch of flags to true
.haskell-language-server +stan
means "build HLS with stan
support, if that will work". In this case we can set the default value of the flag to "true", and put conditional logic in the cabal file to ignore if it we're on a non-working GHC version. Then users don't have to set flags manually, but they might be surprised that the flag is on and they don't get the feature!The ideal situation would be 1, but we can change the default value of the flag based on the GHC version. Then users will get sensible behaviour in all cases, but the flag continues to mean "definitely try and include this functionality".
@michaelpj fwiw, the https://github.com/haskell/cabal/issues/3526 would also solve that in a convenient way. You could have a three way flag, True
, False
, and Auto
.
FWIW, you can encode that today too with two flags, but that's not very user friendly.
This is expanded version of this comment:
Currently, the grammar for the
default
field is limited toThis is perfectly sufficient for properly used automatic flags (i.e.
manual: False
and used in a way which allows the solver to unique determine their value -- there's a separate feature request to have cabal detect "non-functional" uses of automatic flags); however, for manual flags the limitation of allowing only a constant boolean literal indefault:
is rather limiting.Instead, starting with e.g.
cabal-version:3.0
, we should allow an enhanced version ofdefault
and where
<boolean-expression>
would be the expression we already support inif
clauses which currently supports theTrue/0
andFalse/0
,&&/2
,||/2
,!/1
,(
and)
, and theimpl/1
flag/1
arch/1
os/1
Such expression can be statically determined, as the
impl/1
,arch/1
, andos/1
predicates are globally constant for a solver session.The
flag/1
predicate however requires us to impose a limitation though, in order to keep the implementation simple (allow for referential checks during single-pass parsing) and avoid the issue of undecidable flags (e.g. via cyclic references). To that end, the following simple well-formedness rule needs to be added to the specification offlag/1
flag(<flagname>)
may only refer to a<flagname>
which is lexically visible, i.e. completely defined before their use-site (i.e. only after itsFlag
stanza ends, a flag is considered completely defined; this prefents direct self-referential uses offlag/1
from within the same Flag stanza)