1{ stdenv, buildPackages, lib
2, fetchurl, fetchpatch, fetchFromSavannah, fetchFromGitHub
3, zlib, openssl, gdbm, ncurses, readline, groff, libyaml, libffi, autoreconfHook, bison
4, autoconf, libiconv, libobjc, libunwind, Foundation
5, buildEnv, bundler, bundix
6} @ args:
7
8let
9 op = lib.optional;
10 ops = lib.optionals;
11 opString = lib.optionalString;
12 patchSet = import ./rvm-patchsets.nix { inherit fetchFromGitHub; };
13 config = import ./config.nix { inherit fetchFromSavannah; };
14 rubygemsSrc = import ./rubygems-src.nix { inherit fetchurl; };
15 rubygemsPatch = fetchpatch {
16 url = "https://github.com/zimbatm/rubygems/compare/v2.6.6...v2.6.6-nix.patch";
17 sha256 = "0297rdb1m6v75q8665ry9id1s74p9305dv32l95ssf198liaihhd";
18 };
19 unpackdir = obj:
20 lib.removeSuffix ".tgz"
21 (lib.removeSuffix ".tar.gz" obj.name);
22
23 # Contains the ruby version heuristics
24 rubyVersion = import ./ruby-version.nix { inherit lib; };
25
26 # Needed during postInstall
27 buildRuby =
28 if stdenv.hostPlatform == stdenv.buildPlatform
29 then "$out/bin/ruby"
30 else "${buildPackages.ruby}/bin/ruby";
31
32 generic = { version, sha256 }: let
33 ver = version;
34 tag = ver.gitTag;
35 atLeast25 = lib.versionAtLeast ver.majMin "2.5";
36 baseruby = self.override { useRailsExpress = false; };
37 self = lib.makeOverridable (
38 { stdenv, buildPackages, lib
39 , fetchurl, fetchpatch, fetchFromSavannah, fetchFromGitHub
40 , useRailsExpress ? true
41 , zlib, zlibSupport ? true
42 , openssl, opensslSupport ? true
43 , gdbm, gdbmSupport ? true
44 , ncurses, readline, cursesSupport ? true
45 , groff, docSupport ? false
46 , libyaml, yamlSupport ? true
47 , libffi, fiddleSupport ? true
48 , autoreconfHook, bison, autoconf
49 , buildEnv, bundler, bundix
50 , libiconv, libobjc, libunwind, Foundation
51 }:
52 let rubySrc =
53 if useRailsExpress then fetchFromGitHub {
54 owner = "ruby";
55 repo = "ruby";
56 rev = tag;
57 sha256 = sha256.git;
58 } else fetchurl {
59 url = "https://cache.ruby-lang.org/pub/ruby/${ver.majMin}/ruby-${ver}.tar.gz";
60 sha256 = sha256.src;
61 };
62 in
63 stdenv.mkDerivation rec {
64 name = "ruby-${version}";
65
66 srcs = [ rubySrc rubygemsSrc ];
67 sourceRoot =
68 if useRailsExpress then
69 rubySrc.name
70 else
71 unpackdir rubySrc;
72
73 # Have `configure' avoid `/usr/bin/nroff' in non-chroot builds.
74 NROFF = if docSupport then "${groff}/bin/nroff" else null;
75
76 nativeBuildInputs = [ autoreconfHook bison ]
77 ++ (op docSupport groff)
78 ++ op (stdenv.buildPlatform != stdenv.hostPlatform) buildPackages.ruby;
79 buildInputs =
80 (op fiddleSupport libffi)
81 ++ (ops cursesSupport [ ncurses readline ])
82 ++ (op zlibSupport zlib)
83 ++ (op opensslSupport openssl)
84 ++ (op gdbmSupport gdbm)
85 ++ (op yamlSupport libyaml)
86 ++ (op atLeast25 autoconf)
87 # Looks like ruby fails to build on darwin without readline even if curses
88 # support is not enabled, so add readline to the build inputs if curses
89 # support is disabled (if it's enabled, we already have it) and we're
90 # running on darwin
91 ++ op (!cursesSupport && stdenv.isDarwin) readline
92 ++ ops stdenv.isDarwin [ libiconv libobjc libunwind Foundation ];
93
94 enableParallelBuilding = true;
95
96 patches =
97 (import ./patchsets.nix {
98 inherit patchSet useRailsExpress ops;
99 patchLevel = ver.patchLevel;
100 })."${ver.majMinTiny}";
101
102 postUnpack = ''
103 cp -r ${unpackdir rubygemsSrc} ${sourceRoot}/rubygems
104 pushd ${sourceRoot}/rubygems
105 patch -p1 < ${rubygemsPatch}
106 popd
107 '';
108
109 postPatch = if atLeast25 then ''
110 sed -i configure.ac -e '/config.guess/d'
111 cp --remove-destination ${config}/config.guess tool/
112 cp --remove-destination ${config}/config.sub tool/
113 ''
114 else opString useRailsExpress ''
115 sed -i configure.in -e '/config.guess/d'
116 cp ${config}/config.guess tool/
117 cp ${config}/config.sub tool/
118 '';
119
120 configureFlags = ["--enable-shared" "--enable-pthread"]
121 ++ op useRailsExpress "--with-baseruby=${baseruby}/bin/ruby"
122 ++ op (!docSupport) "--disable-install-doc"
123 ++ ops stdenv.isDarwin [
124 # on darwin, we have /usr/include/tk.h -- so the configure script detects
125 # that tk is installed
126 "--with-out-ext=tk"
127 # on yosemite, "generating encdb.h" will hang for a very long time without this flag
128 "--with-setjmp-type=setjmp"
129 ]
130 ++ op (stdenv.hostPlatform != stdenv.buildPlatform)
131 "--with-baseruby=${buildRuby}";
132
133 # fails with "16993 tests, 2229489 assertions, 105 failures, 14 errors, 89 skips"
134 # mostly TZ- and patch-related tests
135 # TZ- failures are caused by nix sandboxing, I didn't investigate others
136 doCheck = false;
137
138 preInstall = ''
139 # Ruby installs gems here itself now.
140 mkdir -pv "$out/${passthru.gemPath}"
141 export GEM_HOME="$out/${passthru.gemPath}"
142 '';
143
144 installFlags = stdenv.lib.optionalString docSupport "install-doc";
145 # Bundler tries to create this directory
146 postInstall = ''
147 # Update rubygems
148 pushd rubygems
149 ${buildRuby} setup.rb --destdir $GEM_HOME
150 popd
151
152 # Remove unnecessary groff reference from runtime closure, since it's big
153 sed -i '/NROFF/d' $out/lib/ruby/*/*/rbconfig.rb
154
155 # Bundler tries to create this directory
156 mkdir -p $out/nix-support
157 cat > $out/nix-support/setup-hook <<EOF
158 addGemPath() {
159 addToSearchPath GEM_PATH \$1/${passthru.gemPath}
160 }
161
162 addEnvHooks "$hostOffset" addGemPath
163 EOF
164 '' + opString useRailsExpress ''
165 rbConfig=$(find $out/lib/ruby -name rbconfig.rb)
166
167 # Prevent the baseruby from being included in the closure.
168 sed -i '/^ CONFIG\["BASERUBY"\]/d' $rbConfig
169 sed -i "s|'--with-baseruby=${baseruby}/bin/ruby'||" $rbConfig
170 '';
171
172 meta = with stdenv.lib; {
173 description = "The Ruby language";
174 homepage = http://www.ruby-lang.org/en/;
175 license = licenses.ruby;
176 maintainers = with maintainers; [ vrthra manveru ];
177 platforms = platforms.all;
178 };
179
180 passthru = rec {
181 version = ver;
182 rubyEngine = "ruby";
183 baseRuby = baseruby;
184 libPath = "lib/${rubyEngine}/${ver.libDir}";
185 gemPath = "lib/${rubyEngine}/gems/${ver.libDir}";
186 devEnv = import ./dev.nix {
187 inherit buildEnv bundler bundix;
188 ruby = self;
189 };
190
191 # deprecated 2016-09-21
192 majorVersion = ver.major;
193 minorVersion = ver.minor;
194 teenyVersion = ver.tiny;
195 patchLevel = ver.patchLevel;
196 };
197 }
198 ) args; in self;
199
200in {
201 ruby_2_3 = generic {
202 version = rubyVersion "2" "3" "8" "";
203 sha256 = {
204 src = "1gwsqmrhpx1wanrfvrsj3j76rv888zh7jag2si2r14qf8ihns0dm";
205 git = "0158fg1sx6l6applbq0831kl8kzx5jacfl9lfg0shfzicmjlys3f";
206 };
207 };
208
209 ruby_2_4 = generic {
210 version = rubyVersion "2" "4" "9" "";
211 sha256 = {
212 src = "1bn6n5b920qy3lsx99jr8495jkc3sg89swgb96d5fgd579g6p6zr";
213 git = "066kb1iki7mx7qkm10xhj5b6v8s47wg68v43l3nc36y2hyim1w2c";
214 };
215 };
216
217 ruby_2_5 = generic {
218 version = rubyVersion "2" "5" "8" "";
219 sha256 = {
220 src = "16md4jspjwixjlbhx3pnd5iwpca07p23ghkxkqd82sbchw3xy2vc";
221 git = "19gkk3q9l33cwkfsp5k8f8fipq7gkyqkqirm9farbvy425519rv2";
222 };
223 };
224
225 ruby_2_6 = generic {
226 version = rubyVersion "2" "6" "6" "";
227 sha256 = {
228 src = "1492x795qzgp3zhpl580kd1sdp50n5hfsmpbfhdsq2rnxwyi8jrn";
229 git = "1jr9v99a7awssqmw7531afbx4a8i9x5yfqyffha545g7r4s7kj50";
230 };
231 };
232}