1{ lib, ruby, rubygemsFun, fetchurl, makeWrapper, git } @ defs:
2
3lib.makeOverridable (
4
5{ name
6, ruby ? defs.ruby
7, rubygems ? (rubygemsFun ruby)
8, stdenv ? ruby.stdenv
9, namePrefix ? "${ruby.name}" + "-"
10, buildInputs ? []
11, doCheck ? false
12, dontBuild ? true
13, meta ? {}
14, gemPath ? []
15, ...} @ attrs:
16
17stdenv.mkDerivation (attrs // {
18 inherit ruby rubygems;
19 inherit doCheck;
20
21 buildInputs = [ ruby rubygems makeWrapper git ] ++ buildInputs;
22
23 name = namePrefix + name;
24
25 src = if attrs ? src
26 then attrs.src
27 else fetchurl {
28 url = "http://rubygems.org/downloads/${attrs.name}.gem";
29 inherit (attrs) sha256;
30 };
31
32 phases = [ "unpackPhase" "patchPhase" "buildPhase" "checkPhase" "installPhase" "fixupPhase" ];
33
34 # The source is expected to either be a gem package or a directory.
35 #
36 # - Gem packages are already built, so they don't even need to be unpacked.
37 # They will skip the buildPhase.
38 # - A directory containing the sources will need to go through all of the
39 # usual phases.
40 unpackPhase= ''
41 gemRegex="\.gem"
42 if [[ $src =~ $gemRegex ]]
43 then
44 runHook preUnpack
45 echo "source is a gem package, won't unpack"
46 gempkg=$src
47 dontBuild=1
48 runHook postUnpack
49 else
50 # Fall back to the original thing for everything else.
51 unpackPhase
52 fi
53 '';
54
55 checkPhase = "true";
56
57 buildPhase = ''
58 runHook preBuild
59
60 # TODO: Investigate. The complete working tree is touched by fetchgit.
61 if [ -d .git ]; then
62 git reset
63 fi
64
65 gemspec=$(find . -name '*.gemspec')
66 echo "found the following gemspecs:"
67 echo "$gemspec"
68
69 gemspec=$(echo "$gemspec" | head -n1)
70 echo "building $gemspec"
71
72 exec 3>&1
73 output=$(gem build $gemspec | tee >(cat - >&3))
74 exec 3>&-
75
76 gempkg=$(echo "$output" | grep -oP 'File: \K(.*)')
77
78 echo "gem package built: $gempkg"
79
80 runHook postBuild
81 '';
82
83 installPhase = ''
84 runHook preInstall
85
86 # NOTE: This does NOT build the unpacked gem, but installs $src directly.
87 # Gems that have not been downloaded from rubygems.org may need a
88 # separate buildPhase.
89 # --ignore-dependencies is necessary as rubygems otherwise always
90 # connects to the repository, thus breaking pure builds.
91 GEM_HOME=$out/${ruby.gemPath} \
92 gem install \
93 --local \
94 --force \
95 --http-proxy "http://nodtd.invalid" \
96 --ignore-dependencies \
97 --build-root "/" \
98 --backtrace \
99 $gempkg $gemFlags -- $buildFlags
100
101 # Yes, we really do need the $out/${ruby.gemPath}/cache.
102 # This is very important in order for many parts of RubyGems/Bundler to not blow up.
103 # See https://github.com/bundler/bundler/issues/3327
104
105 mkdir -p $out/bin
106 for prog in $out/${ruby.gemPath}/gems/*/bin/*; do
107 makeWrapper $prog $out/bin/$(basename $prog) \
108 --prefix GEM_PATH : "$out/${ruby.gemPath}:$GEM_PATH" \
109 --prefix RUBYLIB : "${rubygems}/lib" \
110 $extraWrapperFlags ''${extraWrapperFlagsArray[@]}
111 done
112 #--prefix RUBYOPT rubygems \
113
114 # looks like useless files which break build repeatability and consume space
115 rm -fv $out/${ruby.gemPath}/doc/*/*/created.rid || true
116 rm -fv $out/${ruby.gemPath}/gems/*/ext/*/mkmf.log || true
117
118 mkdir -p $out/nix-support
119
120 cat > $out/nix-support/setup-hook <<EOF
121 if [[ "\$GEM_PATH" != *$out* ]]; then
122 addToSearchPath GEM_PATH $out/${ruby.gemPath}
123 fi
124 EOF
125
126 runHook postInstall
127 '';
128
129 propagatedBuildInputs = gemPath;
130 propagatedUserEnvPkgs = gemPath;
131
132 passthru.isRubyGem = true;
133 inherit meta;
134})
135
136)