Homebrew / homebrew-core

🍻 Default formulae for the missing package manager for macOS (or Linux)
https://brew.sh
BSD 2-Clause "Simplified" License
13.58k stars 12.33k forks source link

GHC fails on Ubuntu 24.04 LTS because it is trying to run gcc-11 #182739

Closed notfirefox closed 1 day ago

notfirefox commented 2 weeks ago

brew gist-logs <formula> link OR brew config AND brew doctor output

$ brew config
HOMEBREW_VERSION: 4.3.18
ORIGIN: https://github.com/Homebrew/brew
HEAD: abc0584215659c5a8716d0798ea2801388d01368
Last commit: 2 days ago
Core tap JSON: 28 Aug 12:54 UTC
HOMEBREW_PREFIX: /home/linuxbrew/.linuxbrew
HOMEBREW_CASK_OPTS: []
HOMEBREW_DISPLAY: :0
HOMEBREW_MAKE_JOBS: 4
Homebrew Ruby: 3.3.4 => /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/3.3.4_1/bin/ruby
CPU: quad-core 64-bit haswell
Clang: N/A
Git: 2.43.0 => /bin/git
Curl: 8.5.0 => /bin/curl
Kernel: Linux 6.8.0-41-generic x86_64 GNU/Linux
OS: Ubuntu 24.04 LTS (noble)
Host glibc: 2.39
/usr/bin/gcc: 13.2.0
/usr/bin/ruby: N/A
glibc: N/A
gcc@11: N/A
gcc: N/A
xorg: N/A
$ brew doctor
Your system is ready to brew.

Verification

What were you trying to do (and why)?

Tried to install ghc on Ubuntu 24.04 LTS and compile simple Haskell program.

What happened (include all command output)?

The Haskell compiler was not able to compile the program.

Main.hs file:

main = do
  putStrLn "Hello World"

Compile the program:

$ ghc Main.hs
[1 of 2] Compiling Main             ( Main.hs, Main.o )
<no location info>: error: could not execute: gcc-11

What did you expect to happen?

The GHC compiler compiles the file.

Step-by-step reproduction instructions (by running brew commands)

1. Install Ubuntu 24.04 LTS Desktop
2. Update Ubuntu repositories: `sudo apt update`
3. Install requires packages: `sudo apt-get install build-essential procps curl file git`
4. Install Homebrew: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
5. Add Homebrew to path: 
  a) `(echo; echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"') >> ~/.bashrc`
  b) `eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"`
6. Install `ghc` using Homebrew: `brew install ghc`
7. Create simple `Main.hs` file: `echo -e "main = do\n  putStrLn \"Hello World\"" > Main.hs`
8. Compile `Main.hs` file: `ghc Main.hs`
carlocab commented 2 weeks ago

Does doing brew install gcc@11 help?

notfirefox commented 2 weeks ago

@carlocab

It does, but gcc@11 is not listed as a hard requirement for ghc as of right now, right? So one might want to consider adding gcc@11 as a dependency to the ghc package.

But I'm questioning whether ghc depends on gcc@11 or just on gcc in general. There is a settings file for GHC where the C and C++ compiler is specified (shortened for brevity):

$ cat /home/linuxbrew/.linuxbrew/Cellar/ghc/9.10.1/lib/ghc-9.10.1/lib/settings
[("C compiler command", "gcc-11")
,("C compiler flags", "")
,("C++ compiler command", "g++-11")
,("C++ compiler flags", "")
...
]

I am bringing this up, because the Homebrew documentation recommends installing build tools on the Linux host system, i.e. the following packages on Ubuntu/Debian:

sudo apt-get install build-essential procps curl file git

Same goes for Fedora, CentOS, or Red Hat and Arch Linux, so most likely gcc is installed on the Linux host system. Therefore I was wondering if it might make sense for the ghc formula to configure ghc in a way that it looks for gcc instead of gcc-11 on Linux x86.

carlocab commented 2 weeks ago

Therefore I was wondering if it might make sense for the ghc formula to configure ghc in a way that it looks for gcc instead of gcc-11 on Linux x86.

Yes, probably. My question was just to check that you had a quick workaround for now. A proper fix may take a bit, but PRs are welcome.

carlocab commented 1 week ago

Probably better to avoid hardcoding a particular C compiler at all. Might help to modify this line

https://github.com/Homebrew/homebrew-core/blob/43360f8993db201ce402193ec0dce836e0fe4619/Formula/g/ghc.rb#L104

to point to just "cc" or something.

carlocab commented 5 days ago

Fixed in #183926.

Do brew update && brew reinstall ghc in about ~15 minutes.

notfirefox commented 5 days ago

That indeed fixed the issue. There are a few questions remaining however.

C++ compiler command

In my previous message I have mentioned the /home/linuxbrew/.linuxbrew/Cellar/ghc/9.10.1/lib/ghc-9.10.1/lib/settings file. After the fix the file looks like shown below (shortened for brevity):

$ cat /home/linuxbrew/.linuxbrew/Cellar/ghc/9.10.1/lib/ghc-9.10.1/lib/settings
[("C compiler command", "cc")
,("C compiler flags", "")
,("C++ compiler command", "g++-11")
,("C++ compiler flags", "")
...
]

As you can see the C compiler command now is set to cc which is good. The C++ compiler command is set to g++-11 which might not be good. I am not sure if and how GHC uses the C++ compiler command but one might want to consider setting the CXX and ac_cv_path_CXX environment variable to "c++" on Linux, e.g. something like this:

 ENV["CXX"] = ENV["ac_cv_path_CXX"] = OS.linux? ? "c++" : ENV.cxx

Other versions

Then there would be the question on what to do about the other versions of GHC. There are in total five other versions, three of those are not deprecated or disabled. Maybe it could make sense to apply the same fix to those versions as well?

carlocab commented 5 days ago

I wonder if, instead of setting CC and CXX, we should just be modifying

lib/ghc-9.10.1/lib/settings

at install-time? This way we can use gcc-11 and g++-11 if available, and then fall back to something else if not.

This way we try to ensure we're using a compiler compatible with the one that ghc was built with where available. Using a different one likely doesn't hurt, but I'd rather avoid the risk if possible.

notfirefox commented 4 days ago

I wonder if, instead of setting CC and CXX, we should just be modifying lib/ghc-9.10.1/lib/settings at install-time? This way we can use gcc-11 and g++-11 if available, and then fall back to something else if not.

I'm not sure if that is a good idea. I have taken some time to think about it and came up with two concerns.

Permissions

For one the permissions of the file are set to read-only:

$ ls -l settings 
-r--r--r--. 1 notfirefox notfirefox 1687 May 10 07:18 settings

Possible breakage

Besides that there is also the possibility that this could break in certain scenarios. Consider the following:

An user installs ghc 9.10.1 on Ubuntu 22.04. This system ships with gcc version 11, so the exact same version that ghc 9.10.1 got compiled with, so brew modifies lib/settings at install-time, so that C compiler command and C++ compiler command are set to gcc-11 and g++-11. If the user now upgrades to Ubuntu 24.04 the gcc compiler gets updated to version 13. ghc tries to access gcc-11 which is not available anymore and fails.

notfirefox commented 4 days ago

I found a use case for ghc making use of a C++ compiler using C++ compiler command. The example below currently breaks on Arch Linux, Fedora and Ubuntu 24.04 due to the ghc compiler looking for a g++-11 binary.

Haskell FFI with C++ example

example.cpp

#include <iostream>

extern "C" {
void cppFunction() { std::cout << "Hello from C++!" << std::endl; }
}

Main.hs

{-# LANGUAGE ForeignFunctionInterface #-}

module Main where

import Foreign
import Foreign.C.Types

foreign import ccall "cppFunction" cppFunction :: IO ()

main = do
    cppFunction

One should be able to compile the program using the command shown below. This currently fails as explained above.

$ ghc Main.hs example.cpp -o main -lstdc++
ghc-9.10.1: could not execute: g++-11