haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.63k stars 697 forks source link

ghc-options mega issue #7998

Open patrickdoc opened 2 years ago

patrickdoc commented 2 years ago

There are a bunch of tickets around some weird behaviors when trying to apply ghc-options. I've linked some below, but there are others that are semi-related as well.

This issue tries to capture most of the problems in a single place to resolve them.

There are a few ways to pass ghc-options (or, more generally ${program}-options for programs like ld, gcc, alex, happy)

cabal.project

In cabal.project:

-- Applies globally, see [1]
program-options
    ghc-options: -fno-full-laziness

-- Applies globally
package *
    ghc-options: -fno-full-laziness

-- Applies only to package foo
package foo
    ghc-options: -fno-full-laziness

[1] The configureCompiler phase pulls the options from the local config, which then gets applied to the entire plan's config, triggering a full rebuild. Reproducer:

cabal clean
cabal build all
# add "program-options" block to cabal.project
cabal build all
# all dependencies get built too

Problematic code: https://github.com/haskell/cabal/blob/65318cc6b82fe25cef6ba3b98feae68369bf4f37/cabal-install/src/Distribution/Client/ProjectPlanning.hs#L464-L515

Related tickets:


Command line

Input from the command line suffers a similar fate:

cabal clean
cabal build all
cabal build --ghc-options=-fno-full-laziness all
# all dependencies get built too

This time it is more intentional: https://github.com/haskell/cabal/blob/65318cc6b82fe25cef6ba3b98feae68369bf4f37/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs#L198-L220

This note indicates that the idea behind applying these options globally is that you want a consistent tool-chain for the entire build. While that seems reasonable for program paths, I can't think of any good examples for program args.

Related tickets:


Caching and Recompilation Avoidance

These problems are complicated by recompilation avoidance. Some flags do not affect output, so are excluded from the package hash. This same logic is used to determine whether or not the config has changed: https://github.com/haskell/cabal/blob/65318cc6b82fe25cef6ba3b98feae68369bf4f37/cabal-install/src/Distribution/Client/ProjectBuilding.hs#L346-L349

This causes some flags to get stuck in the config cache until either a cabal clean or a non-ignored flag is applied. Reproducer:

cabal clean
cabal build --ghc-options=-ddump-simpl all
# -ddump flags are ignored, so don't trigger dependency rebuilds, but are included in fresh builds
# modify a module
cabal build all
# -ddump-simpl still applied

Related tickets:


Proposal

  1. To fix the local flags applying globally, we should be able to just rip out the two linked pieces of code that duplicate the flags. Note that this code correctly constructs the list of flags anyway: https://github.com/haskell/cabal/blob/65318cc6b82fe25cef6ba3b98feae68369bf4f37/cabal-install/src/Distribution/Client/ProjectPlanning.hs#L1969-L1982

This makes only-local flags possible, and the previous functionality is still available with:

package *
    ghc-options: ...
  1. At that point it would probably be best to remove this stanza:

    program-options
    ghc-options: ...

    and make a top-level ghc-options legal to be consistent with all the other package settings. This is technically a breaking change, but the stanza is currently undocumented and broken, so it's unlikely to break too many workflows.

  2. To fix the caching, the best option I can think of is: a. Only cache the normalized config so that we aren't left with a -ddump-simpl that we can't get rid of b. Use the non-normalized config when building so that the user still gets what they want

jneira commented 2 years ago

@patrickdoc hi! could be this closed after #7973?

patrickdoc commented 2 years ago

7973 only addresses the first item under "proposal" (fixing the scope of command line and program-options to be local-only).

Item 2 is mostly just about cleaning up the docs/user interface for using ghc-options in cabal.project, so not a huge deal.

Item 3 is a "gotcha". Some flags (basically any options like -ddump or -Wall) can only be added/removed from a project by first running cabal clean. Not a huge problem because it has a workaround, but probably going to cause a ticket or two in the future.

It can probably be closed because 2 and 3 are not really bugs, just rough edges.

jneira commented 2 years ago

Oh, so i was wrong about #7973 fixing the cache issue and i have to reopen the linked issues (#4247 and #7816) 🤦

@patrickdoc could you confirm those ones should be reopened, please? thanks!

jneira commented 2 years ago

ok I ve reopened the issues related with caching, sorry for the noise!

patrickdoc commented 2 years ago

Closing #4247 seems correct to me. The original purpose of that ticket is achieved. (and is actually the cause of #7816)

7816 is tracking the same issue as the one tracked here under "Caching and Recompilation Avoidance". So either one can be picked as the official one to track the issue.