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 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 , buildEnv, bundler, bundix
52 , libiconv, libobjc, libunwind, 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 ++ ops stdenv.isDarwin [ libiconv libobjc libunwind Foundation ];
98
99 enableParallelBuilding = true;
100
101 patches =
102 (import ./patchsets.nix {
103 inherit patchSet useRailsExpress ops;
104 patchLevel = ver.patchLevel;
105 })."${ver.majMinTiny}";
106
107 postUnpack = ''
108 cp -r ${unpackdir rubygemsSrc} ${sourceRoot}/rubygems
109 pushd ${sourceRoot}/rubygems
110 patch -p1 < ${rubygemsPatch}
111 popd
112 '';
113
114 postPatch = if isRuby25 then ''
115 sed -i configure.ac -e '/config.guess/d'
116 cp ${config}/config.guess tool/
117 cp ${config}/config.sub tool/
118 ''
119 else opString useRailsExpress ''
120 sed -i configure.in -e '/config.guess/d'
121 cp ${config}/config.guess tool/
122 cp ${config}/config.sub tool/
123 '';
124
125 configureFlags = ["--enable-shared" "--enable-pthread"]
126 ++ op useRailsExpress "--with-baseruby=${baseruby}/bin/ruby"
127 ++ op (!docSupport) "--disable-install-doc"
128 ++ ops stdenv.isDarwin [
129 # on darwin, we have /usr/include/tk.h -- so the configure script detects
130 # that tk is installed
131 "--with-out-ext=tk"
132 # on yosemite, "generating encdb.h" will hang for a very long time without this flag
133 "--with-setjmp-type=setjmp"
134 ]
135 ++ op (stdenv.hostPlatform != stdenv.buildPlatform)
136 "--with-baseruby=${buildRuby}";
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
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" "7" "";
203 sha256 = {
204 src = "0zvx5kdp1frjs9n95n7ba7dy0alax33wi3nj8034m3ppvnf39k9m";
205 git = "11wbzw2ywwfnvlkg3qjg0as2pzk5zyk63y2iis42d91lg1l2flrk";
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}