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