at 23.05-pre 276 lines 12 kB view raw
1{ stdenv, buildPackages, lib 2, fetchurl, fetchpatch, fetchFromSavannah, fetchFromGitHub 3, zlib, gdbm, ncurses, readline, groff, libyaml, libffi, jemalloc, autoreconfHook, bison 4, autoconf, libiconv, libobjc, libunwind, Foundation 5, buildEnv, bundler, bundix 6, makeWrapper, buildRubyGem, defaultGemConfig, removeReferencesTo 7, openssl, openssl_1_1 8} @ args: 9 10let 11 op = lib.optional; 12 ops = lib.optionals; 13 opString = lib.optionalString; 14 patchSet = import ./rvm-patchsets.nix { inherit fetchFromGitHub; }; 15 config = import ./config.nix { inherit fetchFromSavannah; }; 16 rubygems = import ./rubygems { inherit stdenv lib fetchurl; }; 17 18 # Contains the ruby version heuristics 19 rubyVersion = import ./ruby-version.nix { inherit lib; }; 20 21 generic = { version, sha256 }: let 22 ver = version; 23 atLeast30 = lib.versionAtLeast ver.majMin "3.0"; 24 self = lib.makeOverridable ( 25 { stdenv, buildPackages, lib 26 , fetchurl, fetchpatch, fetchFromSavannah, fetchFromGitHub 27 , useRailsExpress ? true 28 , rubygemsSupport ? true 29 , zlib, zlibSupport ? true 30 , openssl, openssl_1_1, opensslSupport ? true 31 , gdbm, gdbmSupport ? true 32 , ncurses, readline, cursesSupport ? true 33 , groff, docSupport ? true 34 , libyaml, yamlSupport ? true 35 , libffi, fiddleSupport ? true 36 , jemalloc, jemallocSupport ? false 37 # By default, ruby has 3 observed references to stdenv.cc: 38 # 39 # - If you run: 40 # ruby -e "puts RbConfig::CONFIG['configure_args']" 41 # - In: 42 # $out/${passthru.libPath}/${stdenv.hostPlatform.system}/rbconfig.rb 43 # Or (usually): 44 # $(nix-build -A ruby)/lib/ruby/2.6.0/x86_64-linux/rbconfig.rb 45 # - In $out/lib/libruby.so and/or $out/lib/libruby.dylib 46 , removeReferencesTo, jitSupport ? false 47 , autoreconfHook, bison, autoconf 48 , buildEnv, bundler, bundix 49 , libiconv, libobjc, libunwind, Foundation 50 , makeWrapper, buildRubyGem, defaultGemConfig 51 , baseRuby ? buildPackages.ruby_3_1.override { 52 useRailsExpress = false; 53 docSupport = false; 54 rubygemsSupport = false; 55 } 56 , useBaseRuby ? stdenv.hostPlatform != stdenv.buildPlatform || useRailsExpress 57 }: 58 stdenv.mkDerivation rec { 59 pname = "ruby"; 60 inherit version; 61 62 src = fetchurl { 63 url = "https://cache.ruby-lang.org/pub/ruby/${ver.majMin}/ruby-${ver}.tar.gz"; 64 inherit sha256; 65 }; 66 67 # Have `configure' avoid `/usr/bin/nroff' in non-chroot builds. 68 NROFF = if docSupport then "${groff}/bin/nroff" else null; 69 70 outputs = [ "out" ] ++ lib.optional docSupport "devdoc"; 71 72 nativeBuildInputs = [ autoreconfHook bison ] 73 ++ (op docSupport groff) 74 ++ op useBaseRuby baseRuby; 75 buildInputs = [ autoconf ] 76 ++ (op fiddleSupport libffi) 77 ++ (ops cursesSupport [ ncurses readline ]) 78 ++ (op zlibSupport zlib) 79 ++ (op (lib.versionOlder ver.majMin "3.0" && opensslSupport) openssl_1_1) 80 ++ (op (atLeast30 && opensslSupport) openssl_1_1) 81 ++ (op gdbmSupport gdbm) 82 ++ (op yamlSupport libyaml) 83 # Looks like ruby fails to build on darwin without readline even if curses 84 # support is not enabled, so add readline to the build inputs if curses 85 # support is disabled (if it's enabled, we already have it) and we're 86 # running on darwin 87 ++ op (!cursesSupport && stdenv.isDarwin) readline 88 ++ ops stdenv.isDarwin [ libiconv libobjc libunwind Foundation ]; 89 propagatedBuildInputs = op jemallocSupport jemalloc; 90 91 enableParallelBuilding = true; 92 93 patches = 94 (import ./patchsets.nix { 95 inherit patchSet useRailsExpress ops fetchpatch; 96 patchLevel = ver.patchLevel; 97 }).${ver.majMinTiny} 98 ++ op (lib.versionOlder ver.majMin "3.1") ./do-not-regenerate-revision.h.patch 99 ++ op (atLeast30 && useBaseRuby) ./do-not-update-gems-baseruby.patch 100 ++ ops (!atLeast30 && rubygemsSupport) [ 101 # We upgrade rubygems to a version that isn't compatible with the 102 # ruby 2.7 installer. Backport the upstream fix. 103 ./rbinstall-new-rubygems-compat.patch 104 105 # Ruby prior to 3.0 has a bug the installer (tools/rbinstall.rb) but 106 # the resulting error was swallowed. Newer rubygems no longer swallows 107 # this error. We upgrade rubygems when rubygemsSupport is enabled, so 108 # we have to fix this bug to prevent the install step from failing. 109 # See https://github.com/ruby/ruby/pull/2930 110 (fetchpatch { 111 url = "https://github.com/ruby/ruby/commit/261d8dd20afd26feb05f00a560abd99227269c1c.patch"; 112 sha256 = "0wrii25cxcz2v8bgkrf7ibcanjlxwclzhayin578bf0qydxdm9qy"; 113 }) 114 ]; 115 116 postUnpack = opString rubygemsSupport '' 117 rm -rf $sourceRoot/{lib,test}/rubygems* 118 cp -r ${rubygems}/lib/rubygems* $sourceRoot/lib 119 cp -r ${rubygems}/test/rubygems $sourceRoot/test 120 ''; 121 122 postPatch = '' 123 sed -i configure.ac -e '/config.guess/d' 124 cp --remove-destination ${config}/config.guess tool/ 125 cp --remove-destination ${config}/config.sub tool/ 126 '' + opString (!atLeast30) '' 127 # Make the build reproducible for ruby <= 2.7 128 # See https://github.com/ruby/io-console/commit/679a941d05d869f5e575730f6581c027203b7b26#diff-d8422f096931c58d4463e2489f62a228b0f24f0492950ba88c8c89a0d741cfe6 129 sed -i ext/io/console/io-console.gemspec -e '/s\.date/d' 130 ''; 131 132 configureFlags = [ 133 (lib.enableFeature (!stdenv.hostPlatform.isStatic) "shared") 134 (lib.enableFeature true "pthread") 135 (lib.withFeatureAs true "soname" "ruby-${version}") 136 (lib.withFeatureAs useBaseRuby "baseruby" "${baseRuby}/bin/ruby") 137 (lib.enableFeature jitSupport "jit-support") 138 (lib.enableFeature docSupport "install-doc") 139 (lib.withFeature jemallocSupport "jemalloc") 140 (lib.withFeatureAs docSupport "ridir" "${placeholder "devdoc"}/share/ri") 141 # ruby enables -O3 for gcc, however our compiler hardening wrapper 142 # overrides that by enabling `-O2` which is the minimum optimization 143 # needed for `_FORTIFY_SOURCE`. 144 ] ++ lib.optional stdenv.cc.isGNU "CFLAGS=-O3" ++ [ 145 ] ++ ops stdenv.isDarwin [ 146 # on darwin, we have /usr/include/tk.h -- so the configure script detects 147 # that tk is installed 148 "--with-out-ext=tk" 149 # on yosemite, "generating encdb.h" will hang for a very long time without this flag 150 "--with-setjmp-type=setjmp" 151 ]; 152 153 preConfigure = opString docSupport '' 154 # rdoc creates XDG_DATA_DIR (defaulting to $HOME/.local/share) even if 155 # it's not going to be used. 156 export HOME=$TMPDIR 157 ''; 158 159 # fails with "16993 tests, 2229489 assertions, 105 failures, 14 errors, 89 skips" 160 # mostly TZ- and patch-related tests 161 # TZ- failures are caused by nix sandboxing, I didn't investigate others 162 doCheck = false; 163 164 preInstall = '' 165 # Ruby installs gems here itself now. 166 mkdir -pv "$out/${passthru.gemPath}" 167 export GEM_HOME="$out/${passthru.gemPath}" 168 ''; 169 170 installFlags = lib.optional docSupport "install-doc"; 171 # Bundler tries to create this directory 172 postInstall = '' 173 rbConfig=$(find $out/lib/ruby -name rbconfig.rb) 174 # Remove references to the build environment from the closure 175 sed -i '/^ CONFIG\["\(BASERUBY\|SHELL\|GREP\|EGREP\|MKDIR_P\|MAKEDIRS\|INSTALL\)"\]/d' $rbConfig 176 # Remove unnecessary groff reference from runtime closure, since it's big 177 sed -i '/NROFF/d' $rbConfig 178 ${ 179 lib.optionalString (!jitSupport) '' 180 # Get rid of the CC runtime dependency 181 ${removeReferencesTo}/bin/remove-references-to \ 182 -t ${stdenv.cc} \ 183 $out/lib/libruby* 184 ${removeReferencesTo}/bin/remove-references-to \ 185 -t ${stdenv.cc} \ 186 $rbConfig 187 sed -i '/CC_VERSION_MESSAGE/d' $rbConfig 188 '' 189 } 190 # Remove unnecessary external intermediate files created by gems 191 extMakefiles=$(find $out/lib/ruby/gems -name Makefile) 192 for makefile in $extMakefiles; do 193 make -C "$(dirname "$makefile")" distclean 194 done 195 # Bundler tries to create this directory 196 mkdir -p $out/nix-support 197 cat > $out/nix-support/setup-hook <<EOF 198 addGemPath() { 199 addToSearchPath GEM_PATH \$1/${passthru.gemPath} 200 } 201 addRubyLibPath() { 202 addToSearchPath RUBYLIB \$1/lib/ruby/site_ruby 203 addToSearchPath RUBYLIB \$1/lib/ruby/site_ruby/${ver.libDir} 204 addToSearchPath RUBYLIB \$1/lib/ruby/site_ruby/${ver.libDir}/${stdenv.hostPlatform.system} 205 } 206 207 addEnvHooks "$hostOffset" addGemPath 208 addEnvHooks "$hostOffset" addRubyLibPath 209 EOF 210 '' + opString docSupport '' 211 # Prevent the docs from being included in the closure 212 sed -i "s|\$(DESTDIR)$devdoc|\$(datarootdir)/\$(RI_BASE_NAME)|" $rbConfig 213 sed -i "s|'--with-ridir=$devdoc/share/ri'||" $rbConfig 214 215 # Add rbconfig shim so ri can find docs 216 mkdir -p $devdoc/lib/ruby/site_ruby 217 cp ${./rbconfig.rb} $devdoc/lib/ruby/site_ruby/rbconfig.rb 218 '' + opString useBaseRuby '' 219 # Prevent the baseruby from being included in the closure. 220 ${removeReferencesTo}/bin/remove-references-to \ 221 -t ${baseRuby} \ 222 $rbConfig $out/lib/libruby* 223 ''; 224 225 disallowedRequisites = op (!jitSupport) stdenv.cc.cc 226 ++ op useBaseRuby baseRuby; 227 228 meta = with lib; { 229 description = "An object-oriented language for quick and easy programming"; 230 homepage = "https://www.ruby-lang.org/"; 231 license = licenses.ruby; 232 maintainers = with maintainers; [ vrthra manveru marsam ]; 233 platforms = platforms.all; 234 }; 235 236 passthru = rec { 237 version = ver; 238 rubyEngine = "ruby"; 239 libPath = "lib/${rubyEngine}/${ver.libDir}"; 240 gemPath = "lib/${rubyEngine}/gems/${ver.libDir}"; 241 devEnv = import ./dev.nix { 242 inherit buildEnv bundler bundix; 243 ruby = self; 244 }; 245 246 inherit (import ../../ruby-modules/with-packages { 247 inherit lib stdenv makeWrapper buildRubyGem buildEnv; 248 gemConfig = defaultGemConfig; 249 ruby = self; 250 }) withPackages gems; 251 252 } // lib.optionalAttrs useBaseRuby { 253 inherit baseRuby; 254 }; 255 } 256 ) args; in self; 257 258in { 259 mkRubyVersion = rubyVersion; 260 mkRuby = generic; 261 262 ruby_2_7 = generic { 263 version = rubyVersion "2" "7" "6" ""; 264 sha256 = "042xrdk7hsv4072bayz3f8ffqh61i8zlhvck10nfshllq063n877"; 265 }; 266 267 ruby_3_0 = generic { 268 version = rubyVersion "3" "0" "4" ""; 269 sha256 = "0avj4g3s2839b2y4m6pk8kid74r8nj7k0qm2rsdcwjzhg8h7rd3h"; 270 }; 271 272 ruby_3_1 = generic { 273 version = rubyVersion "3" "1" "2" ""; 274 sha256 = "0gm84ipk6mrfw94852w5h7xxk2lqrxjbnlwb88svf0lz70933131"; 275 }; 276}