From 13e8b39e0b186739fa1b048fa35ec7efabe88975 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 31 Oct 2026 20:38:49 +0100 Subject: [PATCH 1/5] Build Ruby < 3.2 with GCC 15 everywhere, not only on Fedora GCC 15 defaults to C23, which Ruby < 3.2 can't compile as. Detect the GCC version instead of the OS, so that e.g. Ubuntu 26.04 is handled too. The flag keeps going through the cflags configure variable, except for Ruby 2.6 where it goes on CC, because its MJIT header check runs a bare $(CC) and would otherwise fail. Ported from https://github.com/ruby/ruby-builder/pull/31 Co-Authored-By: Claude Fable 5.1 --- bin/ruby-build | 58 ++++++++++----- test/compiler.bats | 176 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 19 deletions(-) diff --git a/bin/ruby-build b/bin/ruby-build index 800564c7..be666f98 100755 --- a/bin/ruby-build +++ b/bin/ruby-build @@ -208,16 +208,24 @@ is_freebsd() { [ "$(uname -s)" = "FreeBSD" ] } -is_fedora() { - [ -r /etc/os-release ] || return 1 - # shellcheck disable=SC1091 - source /etc/os-release - # Treat Aurora, Bazzite, BlueFin, uCore, and other Fedora variants as "fedora". - if [[ "${ID_LIKE:-$ID}" != "fedora" || ( $# -gt 0 && "${VERSION_ID%%.*}" -lt "$1") ]]; then - return 1 +# The C compiler that Ruby's configure picks: $CC, otherwise gcc if available, otherwise cc. +c_compiler() { + if [ -n "$CC" ]; then + echo "$CC" + elif command -v gcc >/dev/null; then + echo gcc + else + echo cc fi } +# Prints the major version of GCC, or nothing if the given C compiler is not GCC (e.g. Clang). +gcc_major_version() { + # shellcheck disable=SC2086 + $1 -E -dM - /dev/null | + awk '/^#define __clang__ /{clang=1} /^#define __GNUC__ /{gnuc=$3} END{if (!clang) print gnuc}' +} + freebsd_package_prefix() { local package="$1" pkg info --prefix "$package" 2>/dev/null | cut -wf2 @@ -735,24 +743,36 @@ build_package_standard() { fi fi + local cc_override extra_cflags + if [ -z "$CC" ] && is_mac 1010; then + cc_override=clang + elif [[ "$package_var_name" = "RUBY" && "$ruby_semver" -lt 30200 ]]; then + local cc gcc_version + cc="$(c_compiler)" + gcc_version="$(gcc_major_version "$cc")" + if [ "${gcc_version:-0}" -ge 15 ]; then + # GCC 15 changed the default C mode from gnu17 to gnu23: https://gcc.gnu.org/gcc-15/changes.html#c + # Ruby < 3.2 can't compile as C23, where `()` in a declaration means `(void)`. + extra_cflags="-std=gnu17" + fi + if [[ -n "$extra_cflags" && "$ruby_semver" -ge 20600 && "$ruby_semver" -lt 20700 ]]; then + # Ruby 2.6 checks its MJIT header with a bare $(CC), so the flags must be part of CC there. + cc_override="$cc $extra_cflags" + extra_cflags= + fi + fi + ( if [ "${CFLAGS+defined}" ] || [ "${!PACKAGE_CFLAGS+defined}" ]; then export CFLAGS="$CFLAGS ${!PACKAGE_CFLAGS}" fi - if [ -z "$CC" ] && is_mac 1010; then - export CC=clang - elif [[ "$package_var_name" = "RUBY" && "$ruby_semver" -lt 30200 ]] && is_fedora 42; then - # Fedora 42+ has updated to GCC v15. GCC v15 changed the default - # mode from gnu17 to gnu23: https://gcc.gnu.org/gcc-15/changes.html#c - # - # Ruby < 3.2 can't compile on GCC v15 in the default mode of gnu23. - # - # TODO: Consider changing this to check for GCC v15 specifically - # rather than inspecting the OS itself. - + if [ -n "$cc_override" ]; then + export CC="$cc_override" + fi + if [ -n "$extra_cflags" ]; then # Use the cflags configure variable, which Ruby's configure appends to # its default optflags/debugflags/warnflags, unlike CFLAGS which would # override them and notably lose the -O3, producing a -O0 Ruby. - export cflags="-std=gnu17 $cflags" + export cflags="$extra_cflags${cflags:+ $cflags}" fi if [ "$package_var_name" = "RUBY" ] && is_mac && ! is_mac 2700; then # The macOS 27 SDK declares dup3() and pipe2() as available since macOS 27.0. diff --git a/test/compiler.bats b/test/compiler.bats index 14ac4daa..94995b27 100755 --- a/test/compiler.bats +++ b/test/compiler.bats @@ -117,3 +117,179 @@ OUT unstub brew unstub make } + +# Stubs a Linux host with a ./configure that logs CC +stub_linux_build() { + mkdir -p "$INSTALL_ROOT" + cd "$INSTALL_ROOT" || return 1 + + stub_repeated uname '-s : echo Linux' + stub_repeated brew 'false' + # shellcheck disable=SC2016 + stub_repeated make 'echo "make $(inspect_args "$@")" >> build.log' + + cat > ./configure < build.log +echo CC=\${CC-unset} >> build.log +echo cflags=\${cflags-unset} >> build.log +CON + chmod +x ./configure +} + +unstub_linux_build() { + unstub uname + unstub brew + unstub make +} + +# Stubs the given C compiler (default: gcc) to report the given preprocessor defines +stub_cc() { + stub_repeated "${2:-gcc}" "-E -dM - : printf '%s\n' $1" +} + +@test "GCC 15 compiles Ruby < 3.2 as gnu17" { + stub_linux_build + stub_cc '"#define __GNUC__ 15"' + + run_inline_definition <= 2.3" { + stub_linux_build + stub_cc '"#define __GNUC__ 14"' + + run_inline_definition < Date: Sat, 31 Oct 2026 21:15:46 +0100 Subject: [PATCH 2/5] Put -std=gnu17 on CC for Ruby 2.7 too, its configure ignores cflags The configure script of Ruby 2.7.8 is generated by Autoconf 2.71, which runs AC_PROG_CC (setting CFLAGS=-g -O2) before Ruby's own `test -z "${CFLAGS+set}"` check, so the cflags configure variable is silently ignored and Ruby 2.7 was still compiled as C23 on GCC 15. Ruby 3.0+ unset CFLAGS again in that case, and the tarballs of 2.0 to 2.5 ship an Autoconf 2.69 configure which runs the check first. Co-Authored-By: Claude Fable 5.1 --- bin/ruby-build | 5 +++-- test/compiler.bats | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/bin/ruby-build b/bin/ruby-build index be666f98..65b9a65b 100755 --- a/bin/ruby-build +++ b/bin/ruby-build @@ -755,8 +755,9 @@ build_package_standard() { # Ruby < 3.2 can't compile as C23, where `()` in a declaration means `(void)`. extra_cflags="-std=gnu17" fi - if [[ -n "$extra_cflags" && "$ruby_semver" -ge 20600 && "$ruby_semver" -lt 20700 ]]; then - # Ruby 2.6 checks its MJIT header with a bare $(CC), so the flags must be part of CC there. + if [[ -n "$extra_cflags" && "$ruby_semver" -ge 20600 && "$ruby_semver" -lt 20800 ]]; then + # Ruby 2.6 checks its MJIT header with a bare $(CC), and the configure script of Ruby 2.7 + # (generated by Autoconf 2.71) silently ignores cflags, so the flags go on CC for those. cc_override="$cc $extra_cflags" extra_cflags= fi diff --git a/test/compiler.bats b/test/compiler.bats index 94995b27..7632da31 100755 --- a/test/compiler.bats +++ b/test/compiler.bats @@ -190,6 +190,27 @@ OUT unstub_linux_build } +@test "GCC 15 compiles Ruby 2.7 as gnu17 via CC" { + stub_linux_build + stub_cc '"#define __GNUC__ 15"' + + run_inline_definition < Date: Sun, 1 Nov 2026 06:12:04 +0900 Subject: [PATCH 3/5] Build OpenSSL 1.0 without parallel make Two `ar` runs into libcrypto.a can overlap under make -j and drop each other's objects, which breaks every Ruby 2.3 and older build on the ubuntu-26.04 runners. The `-j 1` that used to prevent this stopped taking effect when 3a4d3fb0 moved MAKE_OPTS after the package options, and 6663720f removed it. Co-Authored-By: Claude Opus 5.5 --- bin/ruby-build | 4 ++++ test/build.bats | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/bin/ruby-build b/bin/ruby-build index 65b9a65b..58588e45 100755 --- a/bin/ruby-build +++ b/bin/ruby-build @@ -1318,6 +1318,10 @@ build_package_openssl() { # Disable SSLv2 and Kerberos on older OpenSSL [[ "$1" != openssl-1.0.* ]] || package_option openssl configure no-ssl2 no-krb5 + # OpenSSL 1.0 can't be built in parallel, as two `ar` runs may create libcrypto.a at once and drop each other's objects. + # OPENSSL_MAKE_OPTS goes after MAKE_OPTS on the make command line, and a user's OPENSSL_MAKE_OPTS still goes after this. + [[ "$1" != openssl-1.0.* ]] || local OPENSSL_MAKE_OPTS="-j 1${OPENSSL_MAKE_OPTS:+ $OPENSSL_MAKE_OPTS}" + # Skip building OpenSSL docs, which is slow. local make_target="install_sw install_ssldirs" [[ "$1" != openssl-1.0.* ]] || make_target="install_sw" # OpenSSL 1.0 does not have `install_ssldirs` diff --git a/test/build.bats b/test/build.bats index 8548b987..dd69b5b5 100755 --- a/test/build.bats +++ b/test/build.bats @@ -477,6 +477,32 @@ make install OUT } +@test "bundled OpenSSL 1.0 is built without parallel make" { + cached_tarball "openssl-1.0.2u" config + + mkdir -p "${TMP}/ssl/certs" + touch "${TMP}/ssl/cert.pem" + + stub_repeated uname '-s : echo Linux' + stub openssl "version -d : echo 'OPENSSLDIR: \"${TMP}/ssl\"'" + stub_make_install "install_sw" + + mkdir -p "$INSTALL_ROOT"/openssl/ssl # OPENSSLDIR + run_inline_definition < Date: Thu, 5 Nov 2026 12:04:39 -0800 Subject: [PATCH 4/5] Add JRuby 10.1.3.0 --- share/ruby-build/jruby-10.1.3.0 | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 share/ruby-build/jruby-10.1.3.0 diff --git a/share/ruby-build/jruby-10.1.3.0 b/share/ruby-build/jruby-10.1.3.0 new file mode 100644 index 00000000..0b7ead0d --- /dev/null +++ b/share/ruby-build/jruby-10.1.3.0 @@ -0,0 +1,2 @@ +require_java 21 +install_package "jruby-10.1.3.0" "https://repo1.maven.org/maven2/org/jruby/jruby-dist/10.1.3.0/jruby-dist-10.1.3.0-bin.tar.gz#3d76fe1fce6aa9f56fd7efb1015a9db95a0aa6f95fe9ec868f9e75d9ddc1871c" jruby From 3943d264469fc1c39d49072ea3a51cb2b63acf93 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 5 Nov 2026 16:06:53 -0600 Subject: [PATCH 5/5] JRuby 10.0.8.0 --- share/ruby-build/jruby-10.0.8.0 | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 share/ruby-build/jruby-10.0.8.0 diff --git a/share/ruby-build/jruby-10.0.8.0 b/share/ruby-build/jruby-10.0.8.0 new file mode 100644 index 00000000..a2cfa63f --- /dev/null +++ b/share/ruby-build/jruby-10.0.8.0 @@ -0,0 +1,2 @@ +require_java 21 +install_package "jruby-10.0.8.0" "https://repo1.maven.org/maven2/org/jruby/jruby-dist/10.0.8.0/jruby-dist-10.0.8.0-bin.tar.gz#e33cd86d198d695bd67dc867daf4c31bced385a9f138a00c47f7c12aa1f4e789" jruby