diff --git a/bin/ruby-build b/bin/ruby-build index 1c121c4c..58588e45 100755 --- a/bin/ruby-build +++ b/bin/ruby-build @@ -18,7 +18,7 @@ # -6, --ipv6 Resolve names to IPv6 addresses only # -RUBY_BUILD_VERSION="20260917" +RUBY_BUILD_VERSION="20261023" OLDIFS="$IFS" @@ -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,37 @@ 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 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 + 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. @@ -1297,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/script/update-cruby b/script/update-cruby index bc65a50f..d42ca676 100755 --- a/script/update-cruby +++ b/script/update-cruby @@ -36,11 +36,20 @@ else exit 1 fi -major_version=$(echo ${version} | cut -d '.' -f 1) +IFS=.- read -r major_version minor_version patch_version _prerelease <<< "$version" +openssl_upper_bound="3.x.x" +# These releases include Ruby/OpenSSL 3.2.4, 3.3.3, and 4.0.2, respectively. +if (( (major_version == 3 && minor_version == 3 && patch_version >= 12) || + (major_version == 3 && minor_version == 4 && patch_version >= 10) || + (major_version == 4 && (minor_version >= 1 || patch_version >= 6)) || + major_version > 4 )); then + openssl_upper_bound="4.x.x" +fi + if [ "$major_version" -ge 4 ]; then - needs_openssl="needs_openssl:1.1.1-3.x.x" + needs_openssl="needs_openssl:1.1.1-${openssl_upper_bound}" else - needs_openssl="needs_openssl:1.0.2-3.x.x" + needs_openssl="needs_openssl:1.0.2-${openssl_upper_bound}" fi cat > "$file" <> 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 <