Homebrew/linuxbrew-core

`brew install gcc` requires gcc

aryairani opened this issue · 13 comments

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

arya@timing1:~$ brew gist-logs gcc
Error: No developer tools installed.
Install Clang or run `brew install gcc`.
arya@timing1:~$ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: Some installed formulae are deprecated or disabled.
You should find replacements for the following formulae:
  isl@0.18

Warning: No developer tools installed.
Install Clang or run `brew install gcc`.

  • I ran brew update and am still able to reproduce my issue.
  • I have resolved all warnings from brew doctor and that did not fix my problem.

What were you trying to do (and why)?

I'm trying to install linuxbrew on Ubuntu 21.04.

When I brew install gcc, I get a post-install failure. brew postinstall gcc --debug reveals that I actually need cc to postinstall, which I don't have.

What happened (include all command output)?

arya@timing1:~$ brew reinstall gcc
==> Downloading https://ghcr.io/v2/linuxbrew/core/gcc/manifests/11.1.0_1
Already downloaded: /home/arya/.cache/Homebrew/downloads/ad7bfe11c97fd11b926e1ab7ebba83223ea95394feaa7b4ab5082612a08eec3b--gcc-11.1.0_1.bottle_manifest.json
==> Downloading https://ghcr.io/v2/linuxbrew/core/gcc/blobs/sha256:7a2f47441a55ad77374ad67674d89fca5def4f9585ada08352d6498a1771f361
Already downloaded: /home/arya/.cache/Homebrew/downloads/c22097ffef17ea1fb4dab8bd71a8eb0eeb0977c7fb7b0da4b3dfc2bac4b3f734--gcc--11.1.0_1.x86_64_linux.bottle.tar.gz
==> Reinstalling gcc 
==> Pouring gcc--11.1.0_1.x86_64_linux.bottle.tar.gz
Warning: The post-install step did not complete successfully
You can try again using:
  brew postinstall gcc
==> Summary
🍺  /home/linuxbrew/.linuxbrew/Cellar/gcc/11.1.0_1: 2,182 files, 347.8MB
arya@timing1:~$

Ok:

arya@timing1:~$ brew postinstall gcc
==> Postinstalling gcc
Warning: The post-install step did not complete successfully
You can try again using:
  brew postinstall gcc

Hmm... <learn about debugging brew formula>

arya@timing1:~$ brew postinstall gcc --debug
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.rb (Formulary::FormulaLoader): loading /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/gcc.rb
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/shims/scm/git --version
==> Postinstalling gcc
Warning: The post-install step did not complete successfully
You can try again using:
  brew postinstall gcc
==> An exception occurred within a child process:
  ErrorDuringExecution: Failure while executing; `/usr/bin/cc -print-file-name=crti.o` exited with 127. Here's the output:


/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/utils/popen.rb:12:in `popen_read'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/utils/popen.rb:16:in `safe_popen_read'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/gcc.rb:186:in `post_install'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:1101:in `block (2 levels) in run_post_install'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:924:in `with_logging'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:1100:in `block in run_post_install'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/utils.rb:558:in `with_env'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:1089:in `run_post_install'
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/postinstall.rb:22:in `<main>'
arya@timing1:~$ /usr/bin/cc
-bash: /usr/bin/cc: No such file or directory
arya@timing1:~$ which cc
arya@timing1:~$

So postinstall wants cc, which is what I was trying to install.

arya@timing1:~$ sudo apt install gcc
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Suggested packages:
  gcc-multilib make autoconf automake libtool flex bison gdb gcc-doc
The following NEW packages will be installed:
  gcc
0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded.
Need to get 5212 B of archives.
After this operation, 51.2 kB of additional disk space will be used.
Get:1 http://mirrors.digitalocean.com/ubuntu hirsute/main amd64 gcc amd64 4:10.3.0-1ubuntu1 [5212 B]
Fetched 5212 B in 0s (88.8 kB/s)
Selecting previously unselected package gcc.
(Reading database ... 103138 files and directories currently installed.)
Preparing to unpack .../gcc_4%3a10.3.0-1ubuntu1_amd64.deb ...
Unpacking gcc (4:10.3.0-1ubuntu1) ...
Setting up gcc (4:10.3.0-1ubuntu1) ...
Processing triggers for man-db (2.9.4-2) ...
Scanning processes...                                                                                                                                                                                    
Scanning candidates...                                                                                                                                                                                   
Scanning linux images...                                                                                                                                                                                 

Restarting services...
Service restarts being deferred:
 /etc/needrestart/restart.d/dbus.service
 systemctl restart networkd-dispatcher.service
 systemctl restart systemd-logind.service
 systemctl restart unattended-upgrades.service

No containers need to be restarted.

User sessions running outdated binaries:
 arya @ user manager service: systemd[22731]
 root @ user manager service: systemd[27097]

Now:

arya@timing1:~$ brew postinstall gcc
==> Postinstalling gcc
==> Creating the GCC specs file: /home/linuxbrew/.linuxbrew/Cellar/gcc/11.1.0_1/lib/gcc/11/gcc/x86_64-pc-linux-gnu/11.1.0/specs
arya@timing1:~$ 

Great!

What did you expect to happen?

In retrospect, it would be good if the postinstall failure message would remind me I need to apt install build-essentials since I guess that's the crux of the issue. It's on the website, but I managed to miss it, and brew postinstall gcc was failing silently, and it took me a few frustrated hours trying to understand what was going on.

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

brew postinstall gcc

I fixed the issue with your post so I could read it better. What you've encountered is probably something that should have an additional check that makes sure /usr/bin/cc is actually installed, and prints an error advising the user to install GCC. This one slipped through the cracks because we only call /usr/bin/cc when the system glibc is new enough, and because you are using the default prefix /home/linuxbrew/.linuxbrew, it didn't try to build anything from source during the initial install process. So Homebrew didn't know you didn't have GCC installed until it reached that step.

This should be a simple fix for us - just adding a line that checks for /usr/bin/cc before trying to run that post install step that uses it.

Thanks @danielnachun and everyone!

Actually, doesn’t the gcc formula include a copy of cc? Could postinstall use that one, instead of needing a separate bootstrap installation in /usr/bin?

I doubt it. /usr/bin/cc is used to find your system's C runtime objects, without which Homebrew gcc wouldn't work too well:

    # Symlink crt1.o and friends where gcc can find it.
    crtdir = if glibc_installed
      glibc.opt_lib
    else
      Pathname.new(Utils.safe_popen_read("/usr/bin/cc", "-print-file-name=crti.o")).parent
    end
    ln_sf Dir[crtdir/"*crt?.o"], libgcc

Oh, ha. Alright.

My main takeaway from this is that we probably need to have a check earlier in the install process to make sure a host GCC is actually installed. The compiler runtimes we try to find in that line are actually provided by libc, which is the one dependency that we can be sure will always be installed on Linux.

However, the more serious issue is that many other bottles require runtime libraries which must be provided by GCC (libstdc++, libquadmath, libgomp, etc.). We do have a check during the initial install to see if the host GCC is new enough to decide if we need to install brewed gcc-5, and I guess that might be a good place to throw an error if we can't even find a host GCC. The assumption if we don't install brewed gcc-5 is that the host has GCC 5 or newer already installed. That clearly wasn't true here and it should have given you an informative error as you suggested above telling you to install a host GCC. This is definitely a fixable problem, though it's more of an improvement than a bug fix.

@danielnachun My system is having problems finding /usr/bin/cc for crti.o in not just gcc but also gcc@5 (gcc@5's post-install step fails).

@mikesep Do you mean that you have system GCC installed, but still don't have /usr/bin/cc? Which distro are you using?

@gromgit Sorry, I'll clarify. I'm using RHEL/Centos 8, but without a system GCC installed. I think the Homebrew GCCs function fine despite this error, but the failed post-install causes brew install to return 1, causing my shell script to think that it failed.

The main limitation if you have no system GCC installed at all is that we don't have a way to find your compiler run times that come with the host glibc. Presumably CentOS 8 has glibc > 2.23, so you don't need to install the glibc formula. When we use the host glibc, we need to make sure that we use its compiler runtimes to avoid any weird incompatibilities. When we use brewed glibc, this isn't a problem because we use the compiler runtimes it provides instead.

Is this CentOS system one for which you have no sudo access? Typically those systems are HPC clusters which would definitely have a system GCC installed. If you do have sudo access, things will be a lot simpler as we can use the host GCC if the version is 5 or greater.

In principle we should find a way to locate the compiler runtimes provided by the host glibc without needing a host GCC. But I don't know how difficult that really is to implement.

Sorry for not responding more quickly. 😞

I'm trying to make a fairly self-contained bundle of linuxbrew apps that I can just unpack onto systems where I don't have sudo access. I'm installing formulae into a Docker container, then making a snapshot of /home/linuxbrew/.linuxbrew that I can unpack onto the target systems.

I suppose it might be safest to simply brew install glibc regardless so that I can ensure compatibility of the snapshot across systems. Are there any downsides to doing that other than a little more disk space used?

In principle we should find a way to locate the compiler runtimes provided by the host glibc without needing a host GCC. But I don't know how difficult that really is to implement.

Do we need the runtimes or just the system-installed glibc version? Could we use ldd or libc.so.6 to discover it?

Centos 7
$ docker run --rm centos:7 ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

$ docker run --rm centos:7 /lib64/libc.so.6
GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.5 20150623 (Red Hat 4.8.5-39).
Compiled on a Linux 3.10.0 system on 2020-09-30.
Available extensions:
	The C stubs add-on version 2.1.2.
	crypt add-on version 2.1 by Michael Glad and others
	GNU Libidn by Simon Josefsson
	Native POSIX Threads Library by Ulrich Drepper et al
	BIND-8.2.3-T5B
	RT using linux kernel aio
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
Centos 8
$ docker run --rm centos:8 ldd --version
ldd (GNU libc) 2.28
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

$ docker run --rm centos:8 /lib64/libc.so.6
GNU C Library (GNU libc) stable release version 2.28.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 8.3.1 20191121 (Red Hat 8.3.1-5).
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
Ubuntu 18.04
$ docker run --rm ubuntu:18.04 ldd --version
ldd (Ubuntu GLIBC 2.27-3ubuntu1.4) 2.27
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

$ docker run --rm ubuntu:18.04 /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.4) stable release version 2.27.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 7.5.0.
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
Ubuntu 20.04
$ docker run --rm ubuntu:20.04 ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

$ docker run --rm ubuntu:20.04 /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.2) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 9.3.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

I'm trying to make a fairly self-contained bundle of linuxbrew apps that I can just unpack onto systems where I don't have sudo access. I'm installing formulae into a Docker container, then making a snapshot of /home/linuxbrew/.linuxbrew that I can unpack onto the target systems.

Are you using the same install prefix in Docker as the systems where you want to deploy? If you are using /home/linuxbrew/.linuxbrew, most formulae won't work because they have RPATHs which have to be rewritten when deploying to a new install prefix, and some also contain strings in the binary which reference the install prefix, and these must be rebuilt from source. Eventually Homebrew/brew#10846 will hopefully eliminate the need to rebuild from source but the paths would still have to be patched at deployment.

I suppose it might be safest to simply brew install glibc regardless so that I can ensure compatibility of the snapshot across systems. Are there any downsides to doing that other than a little more disk space used?

I'm not sure it's a good idea to install an older glibc than the one the system uses. If any of the binaries on the host somehow end up using the loader in $HOMEBREW_PREFIX, they wouldn't work because they'd be using an older version of glibc then they were built against. It's best to let Homebrew's install script figure this out.

Do we need the runtimes or just the system-installed glibc version? Could we use ldd or libc.so.6 to discover it?

It's actually not libc.so.6 we need to find, but instead the crt files for the compiler run times. These compiler run times are not dynamically linked into binaries, because they are needed at compile time, not run time. If you were never going to use brewed GCC to compile anything, you actually wouldn't need them - the GCC run time libraries (libstdc++, libgfortran, etc., not the same as the crt files from the glibc compiler run times) are all you need from GCC to run bottles.

I may have misunderstood your intended use case here (please correct me if I got anything wrong), but I will say as a general rule of thumb that bottles built in Homebrew aren't expected to work if they are not deployed by it. There's a lot more I'd like to do to make the initial setup of Homebrew a smoother experience for non-sudo users on older HPC systems, but it's not 100% there yet. Please let me know if I can answer any further questions!

Closing, sorry. If this issue is still relevant: please reopen on homebrew-core.