cabal icon indicating copy to clipboard operation
cabal copied to clipboard

Regression over 3.6 concerning `ghc-options` `-pgmP` `-optP`

Open andreasabel opened this issue 2 years ago • 7 comments

Phenomenon: The following incantation works on macOS with cabal-install 3.6, but not with the version from master:

$ brew install cpp
$ cabal-3.6 install -w ghc-8.8.4 fudgets

With master this gives an error about a rejected option -traditional to the C compiler.

cc1: error: command-line option '-traditional' is valid for the  driver but not for C
`gcc-11' failed in phase `C Compiler'. (Exit code: 1)

fugets.cabal contains the following configuration line:

ghc-options: -pgmP cpp-11 -optP -traditional

This option might be propagated to the wrong place.

It should be investigated if this regression was caused by:

  • #4439 (PRs: #7874 #7900)

andreasabel avatar Mar 22 '22 09:03 andreasabel

I cannot reproduce this on Ubuntu, I think this is cpp-11 (clang, not gcc?) not working as the other variants, GCC doesn't seem to barf about -traditional.

Which is weird, as there is no cpp-11 on my machine.

I don't know what fudgets tries to do, but I'd blame them for doing something weird.

EDIT: I see, the whole snippet from fudgets.cabal is

  if os(darwin)
    Extra-lib-dirs: /opt/X11/lib 
    Include-dirs: /opt/X11/include
    -- Run 'brew install gcc', then you should have gcc-11 and cpp-11, or
    -- possibly another version, in which case you need to adapt the line below:
    if impl(ghc<8.10.3)
      -- Use the -pgmP in ghc<8.10.3
      ghc-options: -pgmP cpp-11 -optP -traditional
    --else
      -- Unfortunately -pgmP doesn't work in ghc>=8.10.3, so you need to
      -- change a line in $PREFIX/lib/ghc-*/lib/settings insead:
      -- ,("Haskell CPP command", "gcc-11")

phadej avatar Mar 22 '22 21:03 phadej

You could try whether

touch foo.c
ghc  -optP -traditional -v3 -c -o foo.o foo.c 
# or/and
ghc  -pgmP cpp-11 -optP -traditional -v3 -c -o foo.o foo.c 

works on your machine.

phadej avatar Mar 22 '22 21:03 phadej

I'm tempted to close this as "fudgets.cabal" is broken.

Why they need to change c preprocessor and specify it to traditional? When compiling Haskell CPP is run in -traditional by GHC (as otherwise it wouldn't work, cause standard CPP lexer is strict / non-compatible with Haskell). And C code can for sure be updated to not require -traditional?

phadej avatar Mar 22 '22 21:03 phadej

Thinking a bit more: GHC ought should have different flags for Haskell CPP and C CPP. Now they are the same pgmP and optP.

So I don't see how this can be fixed so "ghc-options are respected when compiling C sources" and "fudgets author can specify CPP flags for Haskell code only". (The person who mentions that Cabal would invoke C compiler directly may try to discuss that with GHC developers, IIRC its a bad idea).

phadej avatar Mar 22 '22 21:03 phadej

I figured the problem. It's indeed GHC-8.8.4 (and later, 8.10, 9.0, 9.2) issue.

ghc-8.8.4 -optP -traditional -v3 -c -o foo.o foo.c
*** C Compiler:
gcc -DTABLES_NEXT_TO_CODE -x c foo.c -o /tmp/ghc130297_0/ghc_1.s -no-pie -fno-PIC -Wimplicit -S -include /opt/ghc/8.8.4/lib/ghc-8.8.4/include/ghcversion.h -I/opt/ghc/8.8.4/lib/ghc-8.8.4/base-4.13.0.0/include -I/opt/ghc/8.8.4/lib/ghc-8.8.4/integer-gmp-1.0.2.0/include -I/opt/ghc/8.8.4/lib/ghc-8.8.4/include -Xpreprocessor -traditional
cc1: error: command line option ‘-traditional’ is valid for the driver but not for C

i.e. it passes optP flags to GCC, ghc-8.6.5 didn't do that. So in away this a regression in GHC, but more precisely it's an issue I pointed in my previous comment.

I'd suggest @andreasabel to open GHC issue about this.

phadej avatar Mar 22 '22 22:03 phadej

Great analysis, @phadej!

touch foo.c
ghc  -optP -traditional -v3 -c -o foo.o foo.c 
# or/and
ghc  -pgmP cpp-11 -optP -traditional -v3 -c -o foo.o foo.c 

I can confirm that this works up to GHC 8.6, e.g.

*** C Compiler:
gcc ... -x c foo.c ...

But it breaks from GHC 8.8 upward, e.g.:

** C Compiler:
gcc -x c foo.c ... -Xpreprocessor -traditional
error: unknown argument: '-traditional'

I can also confirm that

 cabal install -w ghc-8.6.5 fudgets

works even with cabal-install from master.

So the summary about cabal install fudgets on macOS seems to be:

  • With GHC 8.6 and below: works with "any" cabal-install
  • With GHC 8.8: works with 3.6 but not master
  • With GHC 8.10 and above: doesn't work with either cabal-install. (The author describes manual fixes that I haven't tried/am not interested in.)

andreasabel avatar Mar 23 '22 07:03 andreasabel

I'd suggest @andreasabel to open GHC issue about this.

I found an upstream issue that looks related enough: https://gitlab.haskell.org/ghc/ghc/-/issues/17185

Here is a relevant comment from the discussion there (by @bgamari):

FWIW, @phadej and @hvr have considered changing cabal check such that it will warn on any .cabal file that defines a cpp-option (i.e., an -optP flag) besides -D<VAR_NAME>=<VAR_VALUE>.

That sounds a bit too heavy-handed to me. However, it would be reasonable to specifically forbid -traditional, for instance.

andreasabel avatar Mar 23 '22 08:03 andreasabel

If that's mostly likely an upstream issue, let me remove the alarming label.

Mikolaj avatar Feb 09 '23 17:02 Mikolaj

Fine with me. I think I put regression in 3.8 because of this item:

  • With GHC 8.8: works with 3.6 but not master

andreasabel avatar Feb 09 '23 20:02 andreasabel