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
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; };
18 # Contains the ruby version heuristics
19 rubyVersion = import ./ruby-version.nix { inherit lib; };
21 generic = { version, sha256 }: let
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:
40 # ruby -e "puts RbConfig::CONFIG['configure_args']"
42 # $out/${passthru.libPath}/${stdenv.hostPlatform.system}/rbconfig.rb
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;
54 rubygemsSupport = false;
56 , useBaseRuby ? stdenv.hostPlatform != stdenv.buildPlatform || useRailsExpress
58 stdenv.mkDerivation rec {
63 url = "https://cache.ruby-lang.org/pub/ruby/${ver.majMin}/ruby-${ver}.tar.gz";
67 # Have `configure' avoid `/usr/bin/nroff' in non-chroot builds.
68 NROFF = if docSupport then "${groff}/bin/nroff" else null;
70 outputs = [ "out" ] ++ lib.optional docSupport "devdoc";
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
87 ++ op (!cursesSupport && stdenv.isDarwin) readline
88 ++ ops stdenv.isDarwin [ libiconv libobjc libunwind Foundation ];
89 propagatedBuildInputs = op jemallocSupport jemalloc;
91 enableParallelBuilding = true;
94 (import ./patchsets.nix {
95 inherit patchSet useRailsExpress ops fetchpatch;
96 patchLevel = ver.patchLevel;
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
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
111 url = "https://github.com/ruby/ruby/commit/261d8dd20afd26feb05f00a560abd99227269c1c.patch";
112 sha256 = "0wrii25cxcz2v8bgkrf7ibcanjlxwclzhayin578bf0qydxdm9qy";
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
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'
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
149 # on yosemite, "generating encdb.h" will hang for a very long time without this flag
150 "--with-setjmp-type=setjmp"
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.
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
165 # Ruby installs gems here itself now.
166 mkdir -pv "$out/${passthru.gemPath}"
167 export GEM_HOME="$out/${passthru.gemPath}"
170 installFlags = lib.optional docSupport "install-doc";
171 # Bundler tries to create this directory
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
179 lib.optionalString (!jitSupport) ''
180 # Get rid of the CC runtime dependency
181 ${removeReferencesTo}/bin/remove-references-to \
184 ${removeReferencesTo}/bin/remove-references-to \
187 sed -i '/CC_VERSION_MESSAGE/d' $rbConfig
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
195 # Bundler tries to create this directory
196 mkdir -p $out/nix-support
197 cat > $out/nix-support/setup-hook <<EOF
199 addToSearchPath GEM_PATH \$1/${passthru.gemPath}
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}
207 addEnvHooks "$hostOffset" addGemPath
208 addEnvHooks "$hostOffset" addRubyLibPath
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
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 \
222 $rbConfig $out/lib/libruby*
225 disallowedRequisites = op (!jitSupport) stdenv.cc.cc
226 ++ op useBaseRuby baseRuby;
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;
239 libPath = "lib/${rubyEngine}/${ver.libDir}";
240 gemPath = "lib/${rubyEngine}/gems/${ver.libDir}";
241 devEnv = import ./dev.nix {
242 inherit buildEnv bundler bundix;
246 inherit (import ../../ruby-modules/with-packages {
247 inherit lib stdenv makeWrapper buildRubyGem buildEnv;
248 gemConfig = defaultGemConfig;
250 }) withPackages gems;
252 } // lib.optionalAttrs useBaseRuby {
259 mkRubyVersion = rubyVersion;
263 version = rubyVersion "2" "7" "6" "";
264 sha256 = "042xrdk7hsv4072bayz3f8ffqh61i8zlhvck10nfshllq063n877";
268 version = rubyVersion "3" "0" "4" "";
269 sha256 = "0avj4g3s2839b2y4m6pk8kid74r8nj7k0qm2rsdcwjzhg8h7rd3h";
273 version = rubyVersion "3" "1" "2" "";
274 sha256 = "0gm84ipk6mrfw94852w5h7xxk2lqrxjbnlwb88svf0lz70933131";