at 24.11-pre 14 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, cargo, rustPlatform, rustc 6, makeBinaryWrapper, buildRubyGem, defaultGemConfig, removeReferencesTo 7, openssl 8, linuxPackages, libsystemtap 9} @ args: 10 11let 12 op = lib.optional; 13 ops = lib.optionals; 14 opString = lib.optionalString; 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, hash, cargoHash ? null }: let 22 ver = version; 23 atLeast31 = lib.versionAtLeast ver.majMin "3.1"; 24 atLeast32 = lib.versionAtLeast ver.majMin "3.2"; 25 # https://github.com/ruby/ruby/blob/v3_2_2/yjit.h#L21 26 yjitSupported = atLeast32 && (stdenv.hostPlatform.isx86_64 || (!stdenv.hostPlatform.isWindows && stdenv.hostPlatform.isAarch64)); 27 rubyDrv = lib.makeOverridable ( 28 { stdenv, buildPackages, lib 29 , fetchurl, fetchpatch, fetchFromSavannah, fetchFromGitHub 30 , rubygemsSupport ? true 31 , zlib, zlibSupport ? true 32 , openssl, opensslSupport ? true 33 , gdbm, gdbmSupport ? true 34 , ncurses, readline, cursesSupport ? true 35 , groff, docSupport ? true 36 , libyaml, yamlSupport ? true 37 , libffi, fiddleSupport ? true 38 , jemalloc, jemallocSupport ? false 39 , linuxPackages, systemtap ? linuxPackages.systemtap, libsystemtap, dtraceSupport ? false 40 # By default, ruby has 3 observed references to stdenv.cc: 41 # 42 # - If you run: 43 # ruby -e "puts RbConfig::CONFIG['configure_args']" 44 # - In: 45 # $out/${passthru.libPath}/${stdenv.hostPlatform.system}/rbconfig.rb 46 # Or (usually): 47 # $(nix-build -A ruby)/lib/ruby/2.6.0/x86_64-linux/rbconfig.rb 48 # - In $out/lib/libruby.so and/or $out/lib/libruby.dylib 49 , removeReferencesTo, jitSupport ? yjitSupport 50 , cargo, rustPlatform, rustc, yjitSupport ? yjitSupported 51 , autoreconfHook, bison, autoconf 52 , buildEnv, bundler, bundix 53 , libiconv, libobjc, libunwind, Foundation 54 , makeBinaryWrapper, buildRubyGem, defaultGemConfig 55 , baseRuby ? buildPackages.ruby.override { 56 docSupport = false; 57 rubygemsSupport = false; 58 } 59 , useBaseRuby ? stdenv.hostPlatform != stdenv.buildPlatform 60 }: 61 stdenv.mkDerivation ( finalAttrs: { 62 pname = "ruby"; 63 inherit version; 64 65 src = fetchurl { 66 url = "https://cache.ruby-lang.org/pub/ruby/${ver.majMin}/ruby-${ver}.tar.gz"; 67 inherit hash; 68 }; 69 70 # Have `configure' avoid `/usr/bin/nroff' in non-chroot builds. 71 NROFF = if docSupport then "${groff}/bin/nroff" else null; 72 73 outputs = [ "out" ] ++ lib.optional docSupport "devdoc"; 74 75 strictDeps = true; 76 77 nativeBuildInputs = [ autoreconfHook bison removeReferencesTo ] 78 ++ (op docSupport groff) 79 ++ (ops (dtraceSupport && stdenv.isLinux) [ systemtap libsystemtap ]) 80 ++ ops yjitSupport [ rustPlatform.cargoSetupHook cargo rustc ] 81 ++ op useBaseRuby baseRuby; 82 buildInputs = [ autoconf ] 83 ++ (op fiddleSupport libffi) 84 ++ (ops cursesSupport [ ncurses readline ]) 85 ++ (op zlibSupport zlib) 86 ++ (op opensslSupport openssl) 87 ++ (op gdbmSupport gdbm) 88 ++ (op yamlSupport libyaml) 89 # Looks like ruby fails to build on darwin without readline even if curses 90 # support is not enabled, so add readline to the build inputs if curses 91 # support is disabled (if it's enabled, we already have it) and we're 92 # running on darwin 93 ++ op (!cursesSupport && stdenv.isDarwin) readline 94 ++ ops stdenv.isDarwin [ libiconv libobjc libunwind Foundation ]; 95 propagatedBuildInputs = op jemallocSupport jemalloc; 96 97 enableParallelBuilding = true; 98 # /build/ruby-2.7.7/lib/fileutils.rb:882:in `chmod': 99 # No such file or directory @ apply2files - ...-ruby-2.7.7-devdoc/share/ri/2.7.0/system/ARGF/inspect-i.ri (Errno::ENOENT) 100 # make: *** [uncommon.mk:373: do-install-all] Error 1 101 enableParallelInstalling = false; 102 103 patches = op (lib.versionOlder ver.majMin "3.1") ./do-not-regenerate-revision.h.patch 104 ++ op useBaseRuby ( 105 if atLeast32 then ./do-not-update-gems-baseruby-3.2.patch 106 else ./do-not-update-gems-baseruby.patch 107 ) 108 ++ ops (ver.majMin == "3.0") [ 109 # Ruby 3.0 adds `-fdeclspec` to $CC instead of $CFLAGS. Fixed in later versions. 110 (fetchpatch { 111 url = "https://github.com/ruby/ruby/commit/0acc05caf7518cd0d63ab02bfa036455add02346.patch"; 112 hash = "sha256-43hI9L6bXfeujgmgKFVmiWhg7OXvshPCCtQ4TxqK1zk="; 113 }) 114 ] 115 ++ ops atLeast31 [ 116 # When using a baseruby, ruby always sets "libdir" to the build 117 # directory, which nix rejects due to a reference in to /build/ in 118 # the final product. Removing this reference doesn't seem to break 119 # anything and fixes cross compliation. 120 ./dont-refer-to-build-dir.patch 121 ]; 122 123 cargoRoot = opString yjitSupport "yjit"; 124 125 cargoDeps = if yjitSupport then rustPlatform.fetchCargoTarball { 126 inherit (finalAttrs) src; 127 sourceRoot = "${finalAttrs.pname}-${version}/${finalAttrs.cargoRoot}"; 128 hash = assert cargoHash != null; cargoHash; 129 } else null; 130 131 postUnpack = opString rubygemsSupport '' 132 rm -rf $sourceRoot/{lib,test}/rubygems* 133 cp -r ${rubygems}/lib/rubygems* $sourceRoot/lib 134 ''; 135 136 postPatch = '' 137 sed -i configure.ac -e '/config.guess/d' 138 cp --remove-destination ${config}/config.guess tool/ 139 cp --remove-destination ${config}/config.sub tool/ 140 ''; 141 142 configureFlags = [ 143 (lib.enableFeature (!stdenv.hostPlatform.isStatic) "shared") 144 (lib.enableFeature true "pthread") 145 (lib.withFeatureAs true "soname" "ruby-${version}") 146 (lib.withFeatureAs useBaseRuby "baseruby" "${baseRuby}/bin/ruby") 147 (lib.enableFeature dtraceSupport "dtrace") 148 (lib.enableFeature jitSupport "jit-support") 149 (lib.enableFeature yjitSupport "yjit") 150 (lib.enableFeature docSupport "install-doc") 151 (lib.withFeature jemallocSupport "jemalloc") 152 (lib.withFeatureAs docSupport "ridir" "${placeholder "devdoc"}/share/ri") 153 # ruby enables -O3 for gcc, however our compiler hardening wrapper 154 # overrides that by enabling `-O2` which is the minimum optimization 155 # needed for `_FORTIFY_SOURCE`. 156 ] ++ lib.optional stdenv.cc.isGNU "CFLAGS=-O3" ++ [ 157 ] ++ ops stdenv.isDarwin [ 158 # on darwin, we have /usr/include/tk.h -- so the configure script detects 159 # that tk is installed 160 "--with-out-ext=tk" 161 # on yosemite, "generating encdb.h" will hang for a very long time without this flag 162 "--with-setjmp-type=setjmp" 163 ]; 164 165 preConfigure = opString docSupport '' 166 # rdoc creates XDG_DATA_DIR (defaulting to $HOME/.local/share) even if 167 # it's not going to be used. 168 export HOME=$TMPDIR 169 ''; 170 171 # fails with "16993 tests, 2229489 assertions, 105 failures, 14 errors, 89 skips" 172 # mostly TZ- and patch-related tests 173 # TZ- failures are caused by nix sandboxing, I didn't investigate others 174 doCheck = false; 175 176 preInstall = '' 177 # Ruby installs gems here itself now. 178 mkdir -pv "$out/${finalAttrs.passthru.gemPath}" 179 export GEM_HOME="$out/${finalAttrs.passthru.gemPath}" 180 ''; 181 182 installFlags = lib.optional docSupport "install-doc"; 183 # Bundler tries to create this directory 184 postInstall = '' 185 rbConfig=$(find $out/lib/ruby -name rbconfig.rb) 186 # Remove references to the build environment from the closure 187 sed -i '/^ CONFIG\["\(BASERUBY\|SHELL\|GREP\|EGREP\|MKDIR_P\|MAKEDIRS\|INSTALL\)"\]/d' $rbConfig 188 # Remove unnecessary groff reference from runtime closure, since it's big 189 sed -i '/NROFF/d' $rbConfig 190 ${ 191 lib.optionalString (!jitSupport) '' 192 # Get rid of the CC runtime dependency 193 remove-references-to \ 194 -t ${stdenv.cc} \ 195 $out/lib/libruby* 196 remove-references-to \ 197 -t ${stdenv.cc} \ 198 $rbConfig 199 sed -i '/CC_VERSION_MESSAGE/d' $rbConfig 200 '' 201 } 202 203 # Allow to override compiler. This is important for cross compiling as 204 # we need to set a compiler that is different from the build one. 205 sed -i "$rbConfig" \ 206 -e 's/CONFIG\["CC"\] = "\(.*\)"/CONFIG["CC"] = if ENV["CC"].nil? || ENV["CC"].empty? then "\1" else ENV["CC"] end/' \ 207 -e 's/CONFIG\["CXX"\] = "\(.*\)"/CONFIG["CXX"] = if ENV["CXX"].nil? || ENV["CXX"].empty? then "\1" else ENV["CXX"] end/' 208 209 # Remove unnecessary external intermediate files created by gems 210 extMakefiles=$(find $out/${finalAttrs.passthru.gemPath} -name Makefile) 211 for makefile in $extMakefiles; do 212 make -C "$(dirname "$makefile")" distclean 213 done 214 find "$out/${finalAttrs.passthru.gemPath}" \( -name gem_make.out -o -name mkmf.log \) -delete 215 # Bundler tries to create this directory 216 mkdir -p $out/nix-support 217 cat > $out/nix-support/setup-hook <<EOF 218 addGemPath() { 219 addToSearchPath GEM_PATH \$1/${finalAttrs.passthru.gemPath} 220 } 221 addRubyLibPath() { 222 addToSearchPath RUBYLIB \$1/lib/ruby/site_ruby 223 addToSearchPath RUBYLIB \$1/lib/ruby/site_ruby/${ver.libDir} 224 addToSearchPath RUBYLIB \$1/lib/ruby/site_ruby/${ver.libDir}/${stdenv.hostPlatform.system} 225 } 226 227 addEnvHooks "$hostOffset" addGemPath 228 addEnvHooks "$hostOffset" addRubyLibPath 229 EOF 230 '' + opString docSupport '' 231 # Prevent the docs from being included in the closure 232 sed -i "s|\$(DESTDIR)$devdoc|\$(datarootdir)/\$(RI_BASE_NAME)|" $rbConfig 233 sed -i "s|'--with-ridir=$devdoc/share/ri'||" $rbConfig 234 235 # Add rbconfig shim so ri can find docs 236 mkdir -p $devdoc/lib/ruby/site_ruby 237 cp ${./rbconfig.rb} $devdoc/lib/ruby/site_ruby/rbconfig.rb 238 '' + opString useBaseRuby '' 239 # Prevent the baseruby from being included in the closure. 240 remove-references-to \ 241 -t ${baseRuby} \ 242 $rbConfig $out/lib/libruby* 243 ''; 244 245 installCheckPhase = '' 246 overriden_cc=$(CC=foo $out/bin/ruby -rrbconfig -e 'puts RbConfig::CONFIG["CC"]') 247 if [[ "$overriden_cc" != "foo" ]]; then 248 echo "CC cannot be overwritten: $overriden_cc != foo" >&2 249 false 250 fi 251 252 fallback_cc=$(unset CC; $out/bin/ruby -rrbconfig -e 'puts RbConfig::CONFIG["CC"]') 253 if [[ "$fallback_cc" != "$CC" ]]; then 254 echo "CC='$fallback_cc' should be '$CC' by default" >&2 255 false 256 fi 257 ''; 258 doInstallCheck = true; 259 260 disallowedRequisites = op (!jitSupport) stdenv.cc 261 ++ op useBaseRuby baseRuby; 262 263 meta = with lib; { 264 description = "An object-oriented language for quick and easy programming"; 265 homepage = "https://www.ruby-lang.org/"; 266 license = licenses.ruby; 267 maintainers = with maintainers; [ vrthra manveru ]; 268 platforms = platforms.all; 269 knownVulnerabilities = op (lib.versionOlder ver.majMin "3.0") "This Ruby release has reached its end of life. See https://www.ruby-lang.org/en/downloads/branches/."; 270 }; 271 272 passthru = rec { 273 version = ver; 274 rubyEngine = "ruby"; 275 libPath = "lib/${rubyEngine}/${ver.libDir}"; 276 gemPath = "lib/${rubyEngine}/gems/${ver.libDir}"; 277 devEnv = import ./dev.nix { 278 inherit buildEnv bundler bundix; 279 ruby = finalAttrs.finalPackage; 280 }; 281 282 inherit rubygems; 283 inherit (import ../../ruby-modules/with-packages { 284 inherit lib stdenv makeBinaryWrapper buildRubyGem buildEnv; 285 gemConfig = defaultGemConfig; 286 ruby = finalAttrs.finalPackage; 287 }) withPackages buildGems gems; 288 } // lib.optionalAttrs useBaseRuby { 289 inherit baseRuby; 290 }; 291 } ) 292 ) args; in rubyDrv; 293 294in { 295 mkRubyVersion = rubyVersion; 296 mkRuby = generic; 297 298 ruby_3_1 = generic { 299 version = rubyVersion "3" "1" "5" ""; 300 hash = "sha256-NoXFHu7hNSwx6gOXBtcZdvU9AKttdzEt5qoauvXNosU="; 301 }; 302 303 ruby_3_2 = generic { 304 version = rubyVersion "3" "2" "4" ""; 305 hash = "sha256-xys8XDBILcoYsPhoyQdfP0fYFo6vYm1OaCzltZyFhpI="; 306 cargoHash = "sha256-6du7RJo0DH+eYMOoh3L31F3aqfR5+iG1iKauSV1uNcQ="; 307 }; 308 309 ruby_3_3 = generic { 310 version = rubyVersion "3" "3" "1" ""; 311 hash = "sha256-jcKvKALMcAzRgtVDByY4jM+IWz8KFPzWoPIf8knJqpk="; 312 cargoHash = "sha256-GeelTMRFIyvz1QS2L+Q3KAnyQy7jc0ejhx3TdEFVEbk="; 313 }; 314 315}