commercialhaskell / stack

The Haskell Tool Stack
http://haskellstack.org
BSD 3-Clause "New" or "Revised" License
3.99k stars 845 forks source link

Cabal/Stack does not distinguish powerpc64 and powerpc64le architectures #6379

Open juhp opened 10 months ago

juhp commented 10 months ago

I am building Unison for Fedora (here) using stack. Today seems the first time I used stack on ppc64le without setup of ghc.

So it fails for me with

+ stack --system-ghc install
:
I don't know how to install GHC for (Linux,PPC64), please install manually

Full build.log from https://copr.fedorainfracloud.org/coprs/petersen/unison/build/6759906/

Naively it feels like Stack.Setup is trying too hard here... Well I have a workaround using my stack-symlink-distro-ghc script. However I would like to add PPC64 and S390X Linux in the Setup module, I am guessing they should map to linux-ppc64 and linux-s390x.

Though in this case I already told stack to use the system ghc..

juhp commented 10 months ago

Actually I don't have a workaround currently (unless there's some way to force it to proceed). ie Even after setting up the system ghc as a stack program, it still refuses to proceed. Interesting since I previously used stack on s390x to build cabal-install for example: Maybe it's because it doesn't like that /usr/bin/ghc is missing perhaps...

juhp commented 10 months ago

I am testing a patch in Fedora Rawhide first: if that looks good I will open a PR later.

mpilgrem commented 10 months ago

Are you asking (via your snapshot) for a different version of GHC than your system provides? If so, you also need to specify --no-install-ghc to stop Stack from trying to fetch a version of GHC that you have requested.

mpilgrem commented 10 months ago

What binary distributions of GHC would linux-ppc64 and linux-s390x link to? I can't see any reference to those architectures on the GHC developers' download page, eg for GHC 9.4.8: https://www.haskell.org/ghc/download_ghc_9_4_8.html

juhp commented 10 months ago

Unison requires lts-20.26 which is ghc-9.2.8 which is what I am pulling in through my rpm spec file.

So AFAICT stack is (over)checking despite the system ghc satisfying the requirement.

(Yes there are no upstream binaries for ppc64le or s390x, but I need to prevent stack choking - fixing/improving the logic would be better of course.)

juhp commented 10 months ago

For completeness I tried with --no-install-ghc and additionally /usr/bin/ghc but then it fails with:

Error: [S-6362]
No compiler found, expected minor version match with ghc-9.2.8 (ppc64-tinfo6) (based on resolver setting in /builddir/build/BUILD/unison-release-0.5.11/stack.yaml).
To install the correct GHC into /builddir/.stack/programs/ppc64-linux/, try running 'stack setup' or use the '--install-ghc' flag. To use your system GHC installation, run 'stack config set system-ghc --global true', or use the '--system-ghc' flag.

It looks to me like it is looking for Big-endian ppc64 rather than Little-endian ppc64le, and hence failing.

This may be why stack appears to work on s390x, since it is probably detected correctly.

juhp commented 10 months ago

So okay thanks to this - I found a workaround:

mv $HOME/.stack/programs/{$(arch),ppc64}-linux

Perhaps this issue should renamed "detect ppc64le correctly".

mpilgrem commented 10 months ago

I understand that the machine architecture is not 'detected', it is hard-coded into the base package based on the content of the HOST_ARCH environment variable when it is compiled - see: https://hackage.haskell.org/package/base-4.19.0.0/docs/src/System.Info.html#arch. Cabal-syntax maps both powerpc64 and powerpc64le to the PPC64 data constructor - see https://hackage.haskell.org/package/Cabal-syntax-3.10.2.0/docs/src/Distribution.System.html#archAliases. If that is a bug, it is upstream of Stack. EDIT: I've asked a question in the Matrix 'Cabal and Hackage' room.

gbaz commented 10 months ago

how exactly does stack's detection work?

mpilgrem commented 10 months ago

@gbaz, Stack depends on Distribution.System.buildPlatform from the Cabal-syntax package. In respect of architecture, that in turn, ultimately, depends on System.Info.arch from the base package, with the exception that powerpc64 and powerpc64le are both mapped to PPC64. System.Info.arch depends on the content of the HOST_ARCH environment variable when the base package is compiled.

hasufell commented 10 months ago

You can detect endianness via

#include <ghcautoconf.h>

isBigEndian :: Bool
#ifdef WORDS_BIGENDIAN
isBigEndian = True
#else
isBigEndian = False
#endif
mpilgrem commented 10 months ago

My instinct is that the 'cost' Stack having a different machine architecture schema to that of Cabal (the library) would outweigh the benefits, partly informed by Cabal's own Haddock documentation, namely:

For parsing OS and arch names in .cabal files we really want everyone to be referring to the same or arch by the same name. Variety is not a virtue in this case. We don't mind about case though.

The same documentation also states:

For the System.Info.os/arch different Haskell implementations ... tend to distinguish versions of an OS/arch which we just don't care about.

Presumably Cabal 'just does not care' about the difference between powerpc64 and powerpc64le because making sure the correct GHC is available is outwith Cabal's concerns - but it seems it would be helpful if Cabal did care in this instance.

I am hoping my pull request https://github.com/haskell/cabal/pull/9535 will be adopted (once I've ironed out the CI).

mpilgrem commented 10 months ago

The discussion at https://github.com/haskell/cabal/pull/9535 has developed beyond Cabal and the endianness of PowerPC architectures and now encompasses GHC issue #24283.

juhp commented 10 months ago

Perhaps I should open a separate issue, but I do feel stack is misbehaving anyway, if I tell it explicitly stack --no-install-ghc --system-ghc install and it still tries to attempt a installGhcBindist (generating Error: [S-6362]) in this case.

mpilgrem commented 10 months ago

If you are passing --no-install-ghc and Stack is seeking to install GHC, something is wrong somewhere. The only thing I can think of is: have you overrriden Stack's installation logic by using GHCUp's hooks: https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation. EDIT: However, a 'hook' script should not run if --system-ghc is set.

EDIT: However, S-6362 is not an 'Stack tried to install' error; it is a 'you've asked for a version of GHC that is not available' error.

EDIT2: So, if I experiment on my Windows system with:

> stack --arch powerpc64 --no-install-ghc path

I get the message:

Warning: Unknown value for architecture setting: powerpc64.

Warning: Continuing despite missing tool: msys2
Error: [S-6362]
No compiler found, expected minor version match with ghc-9.6.3 (powerpc64) (based on resolver setting in D:\Users\mike\Code\GitHub\commercialhaskell\stack\stack.yaml).
To install the correct GHC into C:\Users\mike\AppData\Local\Programs\stack\powerpc64-windows\, try running 'stack setup' or use the '--install-ghc' flag. To use your system GHC installation, run 'stack config set system-ghc --global true', or use the '--system-ghc' flag.

The first warning is because powerpc64 is not the name (ignoring case) of a nullary constructor of Cabal-syntax's Distribution.System.Arch type.

The S-6362 error is because I've asked for GHC 9.6.3 (powerpc64) and no such version of GHC is available to Stack.

juhp commented 10 months ago

Okay but AFAICT the CompilerVersionMismatch exception is only thrown by installGhcBindist?

juhp commented 10 months ago

https://hackage.haskell.org/package/base-4.19.0.0/docs/System-Info.html#v:arch seems close to what is wanted, though a String

mpilgrem commented 10 months ago

the CompilerVersionMismatch exception is only thrown by installGhcBindist

That is correct. However, installGhCBindist does not always seek to install a GHC binary distribution (despite the name of the function). There is this guard:

      | soptsInstallIfMissing sopts -> do

which has its origins in configInstallGHC which, in turn, has its origins in the --[no-]install-ghc configuration option.

mpilgrem commented 10 months ago

https://hackage.haskell.org/package/base-4.19.0.0/docs/System-Info.html#v:arch seems close to what is wanted...

That is what Cabal is parsing. The 'problem' is that Cabal parses both powerpc64 (big-endian) and powerpc64le (little-endian) to PPC64. (Unlike GHC's ghc-platform package, which has constructor ArchPPC_64 PPC_64ABI, where

-- | PowerPC 64-bit ABI
data PPC_64ABI
   = ELF_V1 -- ^ PowerPC64
   | ELF_V2 -- ^ PowerPC64 LE
   deriving (Read, Show, Eq, Ord)

).

A couple of things arose from a call with the Cabal developers: (1) they see fixing Cabal as a 'breaking change', so it will not happen before the next major version of Cabal; and (2) there is a sort-of-plan to see if (a version of) GHC's Arch type can be treated as 'canonical' and used by Cabal (and hence Stack). There is no appetite for Stack creating its own version of an Arch type.

hasufell commented 10 months ago

@mpilgrem did you consider the solution I posted https://github.com/commercialhaskell/stack/issues/6379#issuecomment-1859306464

You wouldn't create your own arch type, but complement it e.g. in a record type with an endianness field.

mpilgrem commented 10 months ago

@juhp, I suggest the following workaround.

Configure Stack to use arch with a suitable value (I suggest ppc64le). I'll also assume that Stack is set up not to look for a GHC on the PATH and not to try to install GHC:

arch: ppc64le
system-ghc: false # Don't use GHC on the PATH
install-ghc: false # Don't try to install GHC

Stack will then look for the desired version of GHC in a ppc64le-linux subdirectory (assuming the OS is Linux) of Stack's programs directory.

Assuming GHC 9.6.3, and that tinfo6 is detected, Stack will expect to find that version of GHC in a subdirectory ghc-tinfo6-9.6.3 and a text file named ghc-tinfo6-9.6.3.installed with contents installed to exist (this flags to Stack that the version of GHC is installed).

If one is not found there, Stack will currently complain and advise:

Error: [S-6362]
No compiler found, expected minor version match with ghc-9.6.3 (ppc64le-tinfo6) (based on resolver setting in /home/mpilgrem/code/haskell/foo/stack.yaml).
To install the correct GHC into /home/mpilgrem/.stack/programs/ppc64le-linux/, try running 'stack setup' or use the '--install-ghc' flag. To use your system GHC installation, run 'stack config set system-ghc --global true', or use the '--system-ghc' flag.

(I think that message and/or the message for S-1852 could be more informative.)

The downside of the workaround is that Stack will warn that ppc64le is an unknown value for the architecture setting, but it is only a warning.

mpilgrem commented 10 months ago

@hasufell, thanks for the advice. Given:

(a) the existence of the arch: <value> mechanism above - which can deal with distinct machine architectures that Cabal (the library) does not recognise or recognise as being distinct (hopefully augmented soon by better in-app and online help); and

(b) Stack will only automatically install GHC on Linux platforms for I386, X86_64, AArch64, Arm and Sparc (which GHC's Arch type does not recognise), so a Stack user on powerpc64 or powerpc64le will be doing something 'manual' in any event;

my preference is to stick with the current approach.