Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ruby: fix building from source with brewed glibc #114313

Closed
wants to merge 1 commit into from

Conversation

XuehaiPan
Copy link
Contributor

  • Have you followed the guidelines for contributing?
  • Have you ensured that your commits follow the commit style guide?
  • Have you checked that there aren't other open pull requests for the same formula update/change?
  • Have you built your formula locally with brew install --build-from-source <formula>, where <formula> is the name of the formula you're submitting?
  • Is your test running fine brew test <formula>, where <formula> is the name of the formula you're submitting?
  • Does your build pass brew audit --strict <formula> (after doing brew install --build-from-source <formula>)? If this is a new formula, does it pass brew audit --new <formula>?

Fixes #110558

@XuehaiPan
Copy link
Contributor Author

XuehaiPan commented Oct 31, 2022

This change only affects Linux with glibc<2.35. Require labels linux-only and CI-skip-dependents.

@XuehaiPan
Copy link
Contributor Author

XuehaiPan commented Dec 5, 2022

Some facts:

  1. The bottle ruby built on Ubuntu 22.04 (without brewed glibc) is installable on Ubuntu 20.04 (with brewed glibc).

    Command line output
    $ docker run -it --rm -h ubuntu --pull always ghcr.io/homebrew/ubuntu20.04:latest
    latest: Pulling from homebrew/ubuntu20.04
    eaead16dc43b: Already exists
    8d909ccf3fc4: Pull complete
    136c2bdef2ae: Pull complete
    ca5755e6d806: Pull complete
    Digest: sha256:2f5d867dea0fbef08c1130fe34c7cd19e228433d0c10a1565c88c36bf63bfa8b
    Status: Downloaded newer image for ghcr.io/homebrew/ubuntu20.04:latest
    linuxbrew@ubuntu:~$ brew install --only-dependencies ruby
    linuxbrew@ubuntu:~$ brew install ruby
    ==> Downloading https://ghcr.io/v2/homebrew/core/ruby/manifests/3.1.3
    ######################################################################## 100.0%
    ==> Downloading https://ghcr.io/v2/homebrew/core/ruby/blobs/sha256:a58222567efff5c6ad0de722edc0655ceee85f3ecc0bad60a50ae51d158ff109
    ==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:a58222567efff5c6ad0de722edc0655ceee85f3ecc0bad60a50ae51d15
    ######################################################################## 100.0%
    ==> Pouring ruby--3.1.3.x86_64_linux.bottle.tar.gz
    ==> Caveats
    By default, binaries installed by gem will be placed into:
      /home/linuxbrew/.linuxbrew/lib/ruby/gems/3.1.0/bin
    
    You may want to add this to your PATH.
    
    Emacs Lisp files have been installed to:
      /home/linuxbrew/.linuxbrew/share/emacs/site-lisp/ruby
    ==> Summary
    🍺  /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3: 16,152 files, 49.4MB
    ==> Running `brew cleanup ruby`...
    Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
    Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
    linuxbrew@ubuntu:~$ which -a ruby
    /home/linuxbrew/.linuxbrew/bin/ruby
    linuxbrew@ubuntu:~$ ruby -e 'puts "Hello world!"'
    Hello world!
  2. brew test ruby failed on Ubuntu 20.04 for bottled ruby which is built on Ubuntu 22.04. The dependencies and configure arguments need to be updated.

    Command line output
    linuxbrew@ubuntu:~$ brew test ruby --verbose
    ==> Testing ruby
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/bin/ruby -e 'puts :hello'
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/bin/gem install json
    Building native extensions. This could take a while...
    ERROR:  Error installing json:
            ERROR: Failed to build gem native extension.
    
        current directory: /tmp/ruby-test-20221205-8772-z9b38l/gems/json-2.6.3/ext/json/ext/generator
    /home/linuxbrew/.linuxbrew/opt/ruby/bin/ruby -I /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/lib/ruby/3.1.0 -r ./siteconf20221205-8801-xd4z3c.rb extconf.rb
    creating Makefile
    
    current directory: /tmp/ruby-test-20221205-8772-z9b38l/gems/json-2.6.3/ext/json/ext/generator
    make DESTDIR\= clean
    
    current directory: /tmp/ruby-test-20221205-8772-z9b38l/gems/json-2.6.3/ext/json/ext/generator
    make DESTDIR\=
    compiling generator.c
    make: gcc-11: Command not found
    make: *** [Makefile:246: generator.o] Error 127
    
    make failed, exit code 2
    
    Gem files will remain installed in /tmp/ruby-test-20221205-8772-z9b38l/gems/json-2.6.3 for inspection.
    Results logged to /tmp/ruby-test-20221205-8772-z9b38l/extensions/x86_64-linux/3.1.0/json-2.6.3/gem_make.out
    Error: ruby: failed
    An exception occurred within a child process:
      BuildError: Failed executing: /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/bin/gem install json
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2510:in `block in system'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2446:in `open'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2446:in `system'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/ruby.rb:249:in `block in <class:Ruby>'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2285:in `block (3 levels) in run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/utils.rb:605:in `with_env'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2284:in `block (2 levels) in run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:967:in `with_logging'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2283:in `block in run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/mktemp.rb:77:in `block in run'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/mktemp.rb:77:in `chdir'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/mktemp.rb:77:in `run'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2561:in `mktemp'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2277:in `run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/test.rb:45:in `block in <main>'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:93:in `block in timeout'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:33:in `block in catch'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:33:in `catch'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:33:in `catch'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:108:in `timeout'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/test.rb:50:in `<main>'
    linuxbrew@ubuntu:~$ brew install gcc@11
    ==> Downloading https://ghcr.io/v2/homebrew/core/gcc/11/manifests/11.3.0-1
    ######################################################################## 100.0%
    ==> Downloading https://ghcr.io/v2/homebrew/core/gcc/11/blobs/sha256:4aa2521ece6b78eb7937a86bb184024db6954ac17f9d6be67b3634abe5b2c495
    ==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:4aa2521ece6b78eb7937a86bb184024db6954ac17f9d6be67b3634abe5
    ######################################################################## 100.0%
    ==> Pouring [email protected]_64_linux.bottle.1.tar.gz
    ==> Creating the GCC specs file: /home/linuxbrew/.linuxbrew/Cellar/gcc@11/11.3.0/bin/../lib/gcc/11/gcc/x86_64-pc-linux-gnu/11/specs
    🍺  /home/linuxbrew/.linuxbrew/Cellar/gcc@11/11.3.0: 2,190 files, 347.5MB
    ==> Running `brew cleanup gcc@11`...
    Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
    Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
    linuxbrew@ubuntu:~$ brew test ruby --verbose
    ==> Testing ruby
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/bin/ruby -e 'puts :hello'
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/bin/gem install json
    Building native extensions. This could take a while...
    ERROR:  Error installing json:
            ERROR: Failed to build gem native extension.
    
        current directory: /tmp/ruby-test-20221205-10204-4o3796/gems/json-2.6.3/ext/json/ext/generator
    /home/linuxbrew/.linuxbrew/opt/ruby/bin/ruby -I /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/lib/ruby/3.1.0 -r ./siteconf20221205-10233-7wacfs.rb extconf.rb
    creating Makefile
    
    current directory: /tmp/ruby-test-20221205-10204-4o3796/gems/json-2.6.3/ext/json/ext/generator
    make DESTDIR\= clean
    
    current directory: /tmp/ruby-test-20221205-10204-4o3796/gems/json-2.6.3/ext/json/ext/generator
    make DESTDIR\=
    compiling generator.c
    as: unrecognized option '--gdwarf-5'
    make: *** [Makefile:246: generator.o] Error 1
    
    make failed, exit code 2
    
    Gem files will remain installed in /tmp/ruby-test-20221205-10204-4o3796/gems/json-2.6.3 for inspection.
    Results logged to /tmp/ruby-test-20221205-10204-4o3796/extensions/x86_64-linux/3.1.0/json-2.6.3/gem_make.out
    Error: ruby: failed
    An exception occurred within a child process:
      BuildError: Failed executing: /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.2_1/bin/gem install json
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2510:in `block in system'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2446:in `open'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2446:in `system'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/ruby.rb:249:in `block in <class:Ruby>'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2285:in `block (3 levels) in run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/utils.rb:605:in `with_env'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2284:in `block (2 levels) in run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:967:in `with_logging'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2283:in `block in run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/mktemp.rb:77:in `block in run'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/mktemp.rb:77:in `chdir'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/mktemp.rb:77:in `run'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2561:in `mktemp'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/formula.rb:2277:in `run_test'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/test.rb:45:in `block in <main>'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:93:in `block in timeout'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:33:in `block in catch'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:33:in `catch'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:33:in `catch'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/lib/ruby/2.6.0/timeout.rb:108:in `timeout'
    /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/test.rb:50:in `<main>'

    Ideally, we need a new CI to run brew test <formula> on an older Linux distribution.

  3. Formula ruby fails to build from source on Ubuntu 20.04.

    Command line output
    linuxbrew@ubuntu:~$ brew uninstall ruby
    Uninstalling /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3... (16,152 files, 49.4MB)
    linuxbrew@ubuntu:~$ brew install --build-from-source ruby
    ==> Downloading https://ghcr.io/v2/homebrew/core/pkg-config/manifests/0.29.2_3
    ######################################################################## 100.0%
    ==> Downloading https://ghcr.io/v2/homebrew/core/pkg-config/blobs/sha256:3d9b8bf9b7b4bd08086be1104e3e18afb1c437dfaca03e6e7df8f2710b9c1c1a
    ==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:3d9b8bf9b7b4bd08086be1104e3e18afb1c437dfaca03e6e7df8f2710b
    ######################################################################## 100.0%
    ==> Downloading https://rubygems.org/rubygems/rubygems-3.3.26.tgz
    ######################################################################## 100.0%
    ==> Downloading https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.3.tar.gz
    ######################################################################## 100.0%
    ==> Installing dependencies for ruby: pkg-config
    ==> Installing ruby dependency: pkg-config
    ==> Pouring pkg-config--0.29.2_3.x86_64_linux.bottle.tar.gz
    🍺  /home/linuxbrew/.linuxbrew/Cellar/pkg-config/0.29.2_3: 11 files, 744.6KB
    ==> Installing ruby
    ==> ./configure --prefix=/home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3 --enable-shared --with-sitedir=/home/linuxbrew/.linuxbrew/lib/ruby/site_r
    ==> make
    ==> make install
    Last 15 lines from /home/linuxbrew/.cache/Homebrew/Logs/ruby/03.make:
            from /tmp/ruby-20221205-10654-40jlfz/ruby-3.1.3/lib/rubygems/ext/builder.rb:205:in `block in build_extensions'
            from /tmp/ruby-20221205-10654-40jlfz/ruby-3.1.3/lib/rubygems/ext/builder.rb:202:in `each'
            from /tmp/ruby-20221205-10654-40jlfz/ruby-3.1.3/lib/rubygems/ext/builder.rb:202:in `build_extensions'
            from /tmp/ruby-20221205-10654-40jlfz/ruby-3.1.3/lib/rubygems/installer.rb:843:in `build_extensions'
            from /tmp/ruby-20221205-10654-40jlfz/ruby-3.1.3/lib/rubygems/installer.rb:326:in `install'
            from ./tool/rbinstall.rb:899:in `block in install'
            from ./tool/rbinstall.rb:713:in `no_write'
            from ./tool/rbinstall.rb:899:in `install'
            from ./tool/rbinstall.rb:1060:in `block (2 levels) in <main>'
            from ./tool/rbinstall.rb:1044:in `foreach'
            from ./tool/rbinstall.rb:1044:in `block in <main>'
            from ./tool/rbinstall.rb:1116:in `block in <main>'
            from ./tool/rbinstall.rb:1113:in `each'
            from ./tool/rbinstall.rb:1113:in `<main>'
    make: *** [uncommon.mk:384: do-install-all] Error 1
    
    READ THIS: https://docs.brew.sh/Troubleshooting
    
    These open issues may also help:
    ruby: fix building from source with brewed glibc https://github.com/Homebrew/homebrew-core/pull/114313
    ruby: failed to build from source on Ubuntu 20.04 LTS https://github.com/Homebrew/homebrew-core/issues/110558
  4. Formula ruby is able to build from source on Ubuntu 20.04 by disabling the bundled gems with C code (which uses the brewed build system).

    Command line output
    linuxbrew@ubuntu:~$ curl -fsSL https://raw.githubusercontent.com/XuehaiPan/homebrew-core/ruby/Formula/ruby.rb > "$(brew --repo homebrew/core)"/Formula/ruby.rb
    linuxbrew@ubuntu:~$ brew install --build-from-source ruby
    ==> Downloading https://rubygems.org/rubygems/rubygems-3.3.26.tgz
    Already downloaded: /home/linuxbrew/.cache/Homebrew/downloads/09bad7ea75386abac73edfe33067fcead5f0f3f30eaf396531ec346c76901167--rubygems-3.3.26.tgz
    ==> Downloading https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.3.tar.gz
    Already downloaded: /home/linuxbrew/.cache/Homebrew/downloads/50d16b95798778a3b52fa0557043d9e0d97460e9d4ae30af9ae2d6c3d3acbc82--ruby-3.1.3.tar.gz
    ==> ./configure --prefix=/home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3 --enable-shared --with-sitedir=/home/linuxbrew/.linuxbrew/lib/ruby/site_r
    ==> make
    ==> make install
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/ruby setup.rb --prefix=/tmp/ruby-20221205-24574-1ajp9mf/ruby-3.1.3/vendor_gem
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/gem build rbs-2.7.0.gemspec
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/gem install --no-document rbs-2.7.0.gem
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/gem build debug-1.6.3.gemspec
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/gem install --no-document debug-1.6.3.gem
    ==> Caveats
    By default, binaries installed by gem will be placed into:
      /home/linuxbrew/.linuxbrew/lib/ruby/gems/3.1.0/bin
    
    You may want to add this to your PATH.
    
    Emacs Lisp files have been installed to:
      /home/linuxbrew/.linuxbrew/share/emacs/site-lisp/ruby
    ==> Summary
    🍺  /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3: 16,155 files, 48.8MB, built in 2 minutes 27 seconds
    ==> Running `brew cleanup ruby`...
    Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
    Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
    linuxbrew@ubuntu:~$ brew test ruby --verbose
    ==> Testing ruby
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/ruby -e 'puts :hello'
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/gem install json
    Building native extensions. This could take a while...
    Successfully installed json-2.6.3
    Parsing documentation for json-2.6.3
    Installing ri documentation for json-2.6.3
    Done installing documentation for json after 0 seconds
    1 gem installed
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/bundle exec ls
    Gemfile
    Library
    build_info
    cache
    doc
    extensions
    gems
    json-2.6.3.gem
    plugins
    specifications
    ==> /home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3/bin/bundle install --binstubs=/tmp/ruby-test-20221206-2975681-fwx3eh/bin
    [DEPRECATED] The --binstubs option will be removed in favor of `bundle binstubs --all`
    Fetching gem metadata from https://rubygems.org/......
    Resolving dependencies...
    Using bundler 2.3.26
    Fetching github-markup 4.0.1
    Installing github-markup 4.0.1
    Bundle complete! 1 Gemfile dependency, 2 gems now installed.
    Use `bundle info [gemname]` to see where a bundled gem is installed.

Formula/ruby.rb Outdated Show resolved Hide resolved
@danielnachun
Copy link
Member

I'm not entirely opposed to this idea, but I'd still like to get a better idea of why these gems are failing to build. I strongly suspect there is some shim bypass occurring, and it would be much better if we could fix that issue rather trying to hack around building the gems.

Importantly, now that you've identified the two gems that are responsible for the failures, we know the scope of the problem and can try to track down what is really happening. We may end up being able to solve this with a much simpler inreplace before building the gems rather than having to skip the build and run it later.

@XuehaiPan
Copy link
Contributor Author

I'm not entirely opposed to this idea, but I'd still like to get a better idea of why these gems are failing to build. I strongly suspect there is some shim bypass occurring, and it would be much better if we could fix that issue rather trying to hack around building the gems.

@danielnachun I agree. I tried my best to locate where the bug is but the bug does not make sense to me. It fails when called in a subprocess by make install but works fine from the shell command line in the interactive mode (./ruby -e 'Open3.capture2e(...)').

The failed make command is called by /tmp/BUILD_DIR/lib/rubygems/ext/builder.rb.

Code
  def self.make(dest_path, results, make_dir = Dir.pwd)
    ...

    ['clean', '', 'install'].each do |target|
      # Pass DESTDIR via command line to override what's in MAKEFLAGS
      cmd = [
        *make_program,
        *env,
        target,
      ].reject(&:empty?)
      begin
        run(cmd, results, "make #{target}".rstrip, make_dir)
      rescue Gem::InstallError
        raise unless target == 'clean' # ignore clean failure
      end
    end
  end

  def self.run(command, results, command_name = nil, dir = Dir.pwd)
    verbose = Gem.configuration.really_verbose

    begin
      rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
      if verbose
        puts("current directory: #{dir}")
        p(command)
      end
      results << "current directory: #{dir}"
      require "shellwords"
      results << command.shelljoin

      require "open3"
      # Set $SOURCE_DATE_EPOCH for the subprocess.
      build_env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string}.merge(env)
      output, status = begin
                         Open3.capture2e(build_env, *command, :chdir => dir)
                       rescue => error
                         raise Gem::InstallError, "#{command_name || class_name} failed#{error.message}"
                       end
      if verbose
        puts output
      else
        results << output
      end
    ensure
      ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
    end

    unless status.success?
      results << "Building has failed. See above output for more information on the failure." if verbose
    end

    yield(status, results) if block_given?

    unless status.success?
      exit_reason =
        if status.exited?
          ", exit code #{status.exitstatus}"
        elsif status.signaled?
          ", uncaught signal #{status.termsig}"
        end

      raise Gem::InstallError, "#{command_name || class_name} failed#{exit_reason}"
    end
  end

The Open3.capture2e function fails to call any system command, such as rm, /bin/sh, /bin/bash, /usr/bin/make, with an error message:

/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/libruby.so.3.1.3)
Logs
    current directory: /data/panxuehai/.linuxbrew/Cellar/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/rbs-2.7.0/ext/rbs_extension
/data/panxuehai/.linuxbrew/Cellar/ruby/3.1.3/bin/ruby -I /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib extconf.rb
creating Makefile

current directory: /data/panxuehai/.linuxbrew/Cellar/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/rbs-2.7.0/ext/rbs_extension
/usr/bin/make DESTDIR\\= sitearchdir\\=./.gem.20221209-313579-ti8khl sitelibdir\\=./.gem.20221209-313579-ti8khl clean
/usr/bin/make: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/libruby.so.3.1.3)
/usr/bin/make: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/libruby.so.3.1.3)
/usr/bin/make: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/libruby.so.3.1.3)

current directory: /data/panxuehai/.linuxbrew/Cellar/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/rbs-2.7.0/ext/rbs_extension
/usr/bin/make DESTDIR\\= sitearchdir\\=./.gem.20221209-313579-ti8khl sitelibdir\\=./.gem.20221209-313579-ti8khl
/usr/bin/make: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/libruby.so.3.1.3)
/usr/bin/make: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/libruby.so.3.1.3)
/usr/bin/make: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/libruby.so.3.1.3)

make failed, exit code 1

Gem files will remain installed in /data/panxuehai/.linuxbrew/Cellar/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/rbs-2.7.0 for inspection.
Results logged to /data/panxuehai/.linuxbrew/Cellar/ruby/3.1.3/lib/ruby/gems/3.1.0/extensions/x86_64-linux/3.1.0/rbs-2.7.0/gem_make.out
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:52:in `block in make'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:43:in `each'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:43:in `make'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/ext_conf_builder.rb:42:in `build'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:172:in `build_extension'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:206:in `block in build_extensions'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:203:in `each'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:203:in `build_extensions'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/installer.rb:843:in `build_extensions'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/installer.rb:326:in `install'
        from ./tool/rbinstall.rb:899:in `block in install'
        from ./tool/rbinstall.rb:713:in `no_write'
        from ./tool/rbinstall.rb:899:in `install'
        from ./tool/rbinstall.rb:1060:in `block (2 levels) in <main>'
        from ./tool/rbinstall.rb:1044:in `foreach'
        from ./tool/rbinstall.rb:1044:in `block in <main>'
        from ./tool/rbinstall.rb:1116:in `block in <main>'
        from ./tool/rbinstall.rb:1113:in `each'
        from ./tool/rbinstall.rb:1113:in `<main>'
/tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:103:in `run': make failed, exit code 1 (Gem::InstallError)
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:52:in `block in make'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:43:in `each'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:43:in `make'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/ext_conf_builder.rb:42:in `build'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:172:in `build_extension'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:206:in `block in build_extensions'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:203:in `each'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/ext/builder.rb:203:in `build_extensions'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/installer.rb:843:in `build_extensions'
        from /tmp/ruby-20221209-199323-1vlslds/ruby-3.1.3/lib/rubygems/installer.rb:326:in `install'
        from ./tool/rbinstall.rb:899:in `block in install'
        from ./tool/rbinstall.rb:713:in `no_write'
        from ./tool/rbinstall.rb:899:in `install'
        from ./tool/rbinstall.rb:1060:in `block (2 levels) in <main>'
        from ./tool/rbinstall.rb:1044:in `foreach'
        from ./tool/rbinstall.rb:1044:in `block in <main>'
        from ./tool/rbinstall.rb:1116:in `block in <main>'
        from ./tool/rbinstall.rb:1113:in `each'
        from ./tool/rbinstall.rb:1113:in `<main>'
make: *** [uncommon.mk:384: do-install-all] Error 1

Replacing make with brewed make and changing the Makefile SHELL to brewed bash would not work. Because the gcc@11 shim uses /bin/bash to interpret and fails with the same error above.

However, call Open3.capture2e in the debug shell works fine:

$ ./ruby --disable-gems -e 'require "open3"; puts Open3.capture2e(*["/bin/bash", "-c", "echo Message"])'
Message
pid 335201 exit 0

The call stack: make install -> /bin/sh -> ./miniruby -> ./ruby -> Open3.capture2e.

Untitled

@XuehaiPan
Copy link
Contributor Author

I'm not entirely opposed to this idea, but I'd still like to get a better idea of why these gems are failing to build.

@danielnachun I found a better fix by using the full path of Glibc libraries, and it works.

Replace:

$ patchelf --print-needed libruby.so.3.1.3
libz.so.1
libcrypt.so.2
libm.so.6
libc.so.6
ld-linux-x86-64.so.2

with

$ patchelf --print-needed libruby.so.3.1.3
libz.so.1
libcrypt.so.2
<glibc.opt_lib>/libm.so.6
<glibc.opt_lib>/libc.so.6
ld-linux-x86-64.so.2

Although the bug is fixed, I still have no idea why it would happen.

@sjackman
Copy link
Member

sjackman commented Dec 9, 2022

Thank you for working on this issue, @XuehaiPan!

An anecdotal data point in case it's useful for troubleshooting, I tested this PR on CentOS 7:

$ curl -sLO https://raw.githubusercontent.com/Homebrew/homebrew-core/bda5b1c4c9d9eaca8874e25a9779320917e31f08/Formula/ruby.rb
$ brew install ./ruby.rb

$ grep -m1 -A6 '/usr/include/math.h' /mnt/home/shaun.jackman/.cache/Homebrew/Logs/ruby/02.make
In file included from /usr/include/math.h:223,
                 from /mnt/home/shaun.jackman/.linuxbrew/Cellar/gcc/12.2.0/include/c++/12/cmath:45,
                 from ../../.././include/ruby/missing.h:19,
                 from ../../.././include/ruby/defines.h:79,
                 from ../../.././include/ruby/ruby.h:25,
                 from cxxanyargs.cpp:1:
/mnt/home/shaun.jackman/.linuxbrew/opt/glibc/include/bits/mathcalls-helper-functions.h:20:24: error: '__fpclassify' has not been declared

It fails at this point because it's using the host's /usr/include/math.h rather than brewed Glibc's ~/.linuxbrew/opt/glibc/include/math.h.


brew config

HOMEBREW_VERSION: 3.6.14
ORIGIN: https://github.com/Homebrew/brew
HEAD: 001bacee18c512657e1535dff757c8cfdaefc116
Last commit: 5 days ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: 3f8a401283628ca6bdd1f3a12bc063912f5cd74d
Core tap last commit: 3 hours ago
Core tap branch: master
HOMEBREW_PREFIX: /mnt/home/shaun.jackman/.linuxbrew
HOMEBREW_REPOSITORY: /mnt/home/shaun.jackman/.linuxbrew/Homebrew
HOMEBREW_CELLAR: /mnt/home/shaun.jackman/.linuxbrew/Cellar
HOMEBREW_CASK_OPTS: []
HOMEBREW_EDITOR: vim
HOMEBREW_MAKE_JOBS: 96
HOMEBREW_NO_AUTO_UPDATE: set
HOMEBREW_NO_INSTALL_CLEANUP: set
Homebrew Ruby: 2.6.8 => /mnt/home/shaun.jackman/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/bin/ruby
CPU: 96-core 64-bit skylake
Clang: 15.0.0
Git: 2.37.3 => /mnt/home/shaun.jackman/.linuxbrew/bin/git
Curl: 7.79.1 => /bin/curl
Kernel: Linux 5.10.135-122.509.amzn2.x86_64 x86_64 GNU/Linux
OS: Amazon Linux release 2 (Karoo) (Karoo)
Host glibc: 2.26
/usr/bin/gcc: 7.3.1
/usr/bin/ruby: 2.0.0
glibc: 2.35_1
gcc@11: N/A
gcc: 12.2.0
xorg: N/A

@XuehaiPan
Copy link
Contributor Author

XuehaiPan commented Dec 10, 2022

It fails at this point because it's using the host's /usr/include/math.h rather than brewed Glibc's ~/.linuxbrew/opt/glibc/include/math.h.

@sjackman I cannot find /usr/include/math.h in the build logs on Ubuntu 20.04 docker. Disabling MJIT_CC='/usr/bin/gcc' won't work either.

As I commented:

I tried my best to locate where the bug is but the bug does not make sense to me. It fails when called in a subprocess by make install but works fine from the shell command line in the interactive mode (./ruby -e 'Open3.capture2e(...)').

You can run ./ruby -e 'Open3.capture2e(...)' in the debug shell with brew install --debug --build-from-source ruby. Also, you can disable the gems in make install and then successfully install the gems separately.

$ docker run -it --rm -h ubuntu --pull always ghcr.io/homebrew/ubuntu20.04:latest
linuxbrew@ubuntu:~$ curl -sLO https://raw.githubusercontent.com/Homebrew/homebrew-core/bda5b1c4c9d9eaca8874e25a9779320917e31f08/Formula/ruby.rb
linuxbrew@ubuntu:~$ brew install --build-from-source ./ruby.rb
linuxbrew@ubuntu:~$ grep -r '/usr/' ~/.cache/Homebrew/Logs/ruby
/home/linuxbrew/.cache/Homebrew/Logs/ruby/05.make:./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems -r./x86_64-linux-fake ./tool/rbinstall.rb --make="/usr/bin/make" --dest-dir="" --extout=".ext" --ext-build-dir="./ext" --mflags="-j12 --jobserver-auth=4,5" --make-flags=" -j12 --jobserver-auth=4,5" --data-mode=0644 --prog-mode=0755 --installed-list .installed.list --mantype="man"  --gnumake --install=all --rdoc-output=".ext/rdoc" --html-output=".ext/html"
/home/linuxbrew/.cache/Homebrew/Logs/ruby/01.configure:MJIT_CC=/usr/bin/gcc
/home/linuxbrew/.cache/Homebrew/Logs/ruby/01.configure:checking for /usr/bin/gcc... /usr/bin/gcc
/home/linuxbrew/.cache/Homebrew/Logs/ruby/01.configure:checking for a BSD-compatible install... /usr/bin/install -c
/home/linuxbrew/.cache/Homebrew/Logs/ruby/01.configure:checking for a race-free mkdir -p... /usr/bin/mkdir -p
/home/linuxbrew/.cache/Homebrew/Logs/ruby/01.configure:checking for grep that handles long lines and -e... /usr/bin/grep
/home/linuxbrew/.cache/Homebrew/Logs/ruby/01.configure:checking for egrep... /usr/bin/grep -E
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:  $ ./configure --prefix=/home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3 --enable-shared --disable-silent-rules --with-sitedir=/home/linuxbrew/.linuxbrew/lib/ruby/site_ruby --with-vendordir=/home/linuxbrew/.linuxbrew/lib/ruby/vendor_ruby --with-opt-dir=/home/linuxbrew/.linuxbrew/opt/libyaml:/home/linuxbrew/.linuxbrew/opt/[email protected]:/home/linuxbrew/.linuxbrew/opt/readline --without-gmp MJIT_CC=/usr/bin/gcc
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:/usr/bin/uname -p = x86_64
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:/usr/bin/arch -k       = unknown
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:/usr/convex/getsysinfo = unknown
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:/usr/bin/hostinfo      = unknown
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:/usr/bin/oslevel       = unknown
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:PATH: /usr/bin/
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:PATH: /usr/sbin/
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:configure:9142: checking for /usr/bin/gcc
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:configure:9177: result: /usr/bin/gcc
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:configure:9873: result: /usr/bin/install -c
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:configure:9929: result: /usr/bin/mkdir -p
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:configure:25260: result: /usr/bin/grep
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:configure:25333: result: /usr/bin/grep -E
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:ac_cv_path_EGREP='/usr/bin/grep -E'
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:ac_cv_path_GREP=/usr/bin/grep
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:ac_cv_path_MJIT_CC=/usr/bin/gcc
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:ac_cv_path_install='/usr/bin/install -c'
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:ac_cv_path_mkdir=/usr/bin/mkdir
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:EGREP='/usr/bin/grep -E'
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:GREP='/usr/bin/grep'
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:MAKEDIRS='/usr/bin/mkdir -p'
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:MJIT_CC='/usr/bin/gcc'
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:MKDIR_P='/usr/bin/mkdir -p'
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:configure_args=' '\''--prefix=/home/linuxbrew/.linuxbrew/Cellar/ruby/3.1.3'\'' '\''--enable-shared'\'' '\''--disable-silent-rules'\'' '\''--with-sitedir=/home/linuxbrew/.linuxbrew/lib/ruby/site_ruby'\'' '\''--with-vendordir=/home/linuxbrew/.linuxbrew/lib/ruby/vendor_ruby'\'' '\''--with-opt-dir=/home/linuxbrew/.linuxbrew/opt/libyaml:/home/linuxbrew/.linuxbrew/opt/[email protected]:/home/linuxbrew/.linuxbrew/opt/readline'\'' '\''--without-gmp'\'' '\''MJIT_CC=/usr/bin/gcc'\'' '\''CC=gcc-12'\'' '\''CXX=g++-12'\'''
/home/linuxbrew/.cache/Homebrew/Logs/ruby/config.log:oldincludedir='/usr/include'

@JuPlutonic
Copy link
Contributor

@XuehaiPan, interesting, I would use this linux-onlypatch to fix building ruby with ruby-build on my Ubuntu18.04.

brew install ruby-build # patched
# ... step to initiate rbenv in shell, shell reloading
rbenv install 3.1.3 # also formula, builds with ruby-build 

Copy link
Member

@Bo98 Bo98 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the slow response from me here - I will look into this a bit soon. Hopefully before Christmas but it might be just after.

Comment on lines +114 to +113
if glibc.any_version_installed?
# Change to full path to Homebrew Glibc
%w[libc.so.6 libm.so.6].each do |lib|
system "patchelf", "--replace-needed", lib, "#{glibc.opt_lib}/#{lib}",
"libruby.so.#{version}"
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not using our ld.so symlink? That sounds like the core issue.

Formula/ruby.rb Outdated Show resolved Hide resolved
@XuehaiPan
Copy link
Contributor Author

Fixed by #118926.

@XuehaiPan XuehaiPan closed this Jan 6, 2023
@XuehaiPan XuehaiPan deleted the ruby branch January 6, 2023 12:38
@github-actions github-actions bot added the outdated PR was locked due to age label Feb 6, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated PR was locked due to age
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ruby: failed to build from source on Ubuntu 20.04 LTS
5 participants