importGems now reads attrsets instead of derivations

This commit is contained in:
Alexander Flatter 2014-08-31 19:32:34 +02:00 committed by Charles Strahan
parent 3e499b7b65
commit c786da0569
4 changed files with 149 additions and 225 deletions

View File

@ -0,0 +1,94 @@
# The standard set of gems in nixpkgs including potential fixes.
#
# The gemset is derived from two points of entry:
# - An attrset describing a gem, including version, source and dependencies
# This is just meta data, most probably automatically generated by a tool
# like Bundix (https://github.com/aflatter/bundix).
# {
# name = "bundler";
# version = "1.6.5";
# sha256 = "1s4x0f5by9xs2y24jk6krq5ky7ffkzmxgr4z1nhdykdmpsi2zd0l";
# dependencies = [ "rake" ];
# }
# - An optional derivation that may override how the gem is built. For popular
# gems that don't behave correctly, fixes are already provided in the form of
# derivations.
#
# This seperates "what to build" (the exact gem versions) from "how to build"
# (to make gems behave if necessary).
{ lib, gemset, buildRubyGem, writeScript, ruby, libxml2, libxslt, python, stdenv
, which, postgresql, v8_3_16_14, clang }:
let
v8 = v8_3_16_14;
gems = lib.mapAttrs (name: config:
if (lib.isDerivation config) then config
else (instantiate name config)
) gemset;
instantiate = (name: attrs:
let
# Turn dependency strings into actual derivations.
gemPath = map (name: builtins.getAttr name gems) (attrs.dependencies or []);
fix = if (builtins.hasAttr name fixes)
then (builtins.getAttr name fixes) attrs
else {};
in
buildRubyGem ({
name = attrs.name;
sha256 = attrs.sha256;
inherit gemPath;
# Disable the checkPhase as there no single way to run tests for a given
# gem: https://github.com/rubygems/rubygems/issues/730
checkPhase = ":";
# Gems downloaded from rubygems.org don't need to be built again.
dontBuild = true;
} // fix)
);
fixes = {
bundler = attrs: {
dontPatchShebangs = 1;
};
libv8 = attrs: {
buildFlags = [ "--with-system-v8" ];
buildInputs = [ which v8 python ];
};
nokogiri = attrs: {
buildFlags = [
"--with-xml2-dir=${libxml2}"
"--with-xml2-include=${libxml2}/include/libxml2"
"--with-xslt-dir=${libxslt}"
"--use-system-libraries"
];
};
therubyracer = attrs: {
dontBuild = false;
preBuild = ''
addToSearchPath RUBYLIB "${gems.libv8}/${ruby.gemPath}/gems/libv8-3.16.14.3/lib"
addToSearchPath RUBYLIB "${gems.libv8}/${ruby.gemPath}/gems/libv8-3.16.14.3/ext"
ln -s ${clang}/bin/clang $TMPDIR/gcc
ln -s ${clang}/bin/clang++ $TMPDIR/g++
export PATH=$TMPDIR:$PATH
'';
postInstall = stdenv.lib.optionalString stdenv.isDarwin ''
cat >> $out/nix-support/setup-hook <<EOF
export DYLD_INSERT_LIBRARIES="$DYLD_INSERT_LIBRARIES''${!DYLD_INSERT_LIBRARIES:+:}${v8}/lib/libv8.dylib"
EOF
'';
buildFlags = [
"--with-v8-dir=${v8}" "--with-v8-include=${v8}/include"
"--with-v8-lib=${v8}/lib"
];
};
};
in gems

View File

@ -31,8 +31,12 @@ in ruby.stdenv.mkDerivation (attrs // {
if test -d $src; then
cd $src
else
gem unpack $src --target=gem-build
cd gem-build/*
cp $src ${attrs.name}.gem
gem unpack ${attrs.name}.gem
rm ${attrs.name}.gem
mv ${attrs.name} gem-build
cd gem-build
sourceRoot=`pwd`
fi
'';
@ -44,6 +48,12 @@ in ruby.stdenv.mkDerivation (attrs // {
installPhase = ''
runHook preInstall
# NOTE: This does NOT build the unpacked gem, but installs $src directly.
# Gems that have not been downloaded from rubygems.org may need a
# separate buildPhase.
# --ignore-dependencies is necessary as rubygems otherwise always
# connects to the repository, thus breaking pure builds.
GEM_HOME=$out/${ruby.gemPath} \
gem install \
--local \
@ -70,8 +80,8 @@ in ruby.stdenv.mkDerivation (attrs // {
done
# looks like useless files which break build repeatability and consume space
rm -f $out/${ruby.gemPath}/doc/*/*/created.rid || true
rm -f $out/${ruby.gemPath}/gems/*/ext/*/mkmf.log || true
rm -fv $out/${ruby.gemPath}/doc/*/*/created.rid || true
rm -fv $out/${ruby.gemPath}/gems/*/ext/*/mkmf.log || true
mkdir -p $out/nix-support

View File

@ -10,149 +10,48 @@
{ ruby, callPackage, pkgs }:
let
buildRubyGem = callPackage ./gem.nix { inherit ruby; };
lib = ruby.stdenv.lib;
patchGemsWith = gems: patches:
lib.mapAttrs (gem: drv:
if patches ? "${gem}"
then lib.overrideDerivation drv (oldAttrs:
if oldAttrs ? dontPatch && !(oldAttrs.dontPatch == false || oldAttrs.dontPatch == null) then {}
else patches."${gem}")
else drv) gems;
selfPre = rec {
buildRubyGem = callPackage ./gem.nix { inherit ruby rake; };
# import an attrset full of gems, then override badly behaved ones
# A set of gems that everyone needs.
common = {
bundler = {
name = "bundler-1.6.5";
sha256 = "1s4x0f5by9xs2y24jk6krq5ky7ffkzmxgr4z1nhdykdmpsi2zd0l";
};
rake = {
name = "rake-10.3.2";
sha256 = "0nvpkjrpsk8xxnij2wd1cdn6arja9q11sxx4aq4fz18bc6fss15m";
dependencies = [ "bundler" ];
};
};
fixGems = gemset: callPackage ./fixes.nix { inherit buildRubyGem gemset ruby; };
in
(fixGems common) // {
inherit buildRubyGem;
# Import an attribute set of gems and apply a set of overrides. Nixpkgs fixes
# popular gems that don't behave. If you specify your own override for a gem,
# the one distributed with nixpgks will not be applied.
#
# Example:
#
# importGems ./gems.nix (gemset: {
# pg = buildRubyGem (gemset.pg // {
# buildInputs = [ postgresql ];
# });
# });
importGems = file: args:
let
patches = callPackage ./patches.nix { inherit ruby; self = builtGems; };
preBuilt = callPackage file ({ inherit buildRubyGem; self = builtGems; } // args);
builtGems = self // patchGemsWith preBuilt patches;
in builtGems;
##################################################################
# stuff EVERYONE needs
##################################################################
bundler = buildRubyGem {
name = "bundler-1.6.5";
sha256 = "1s4x0f5by9xs2y24jk6krq5ky7ffkzmxgr4z1nhdykdmpsi2zd0l";
dontPatchShebangs = 1;
checkPhase = ":";
};
rake = buildRubyGem {
name = "rake-10.3.2";
sha256 = "0nvpkjrpsk8xxnij2wd1cdn6arja9q11sxx4aq4fz18bc6fss15m";
gemPath = [ self.bundler ];
checkPhase = ":";
};
##################################################################
# common dependencies
##################################################################
diff_lcs = buildRubyGem {
name = "diff-lcs-1.2.5";
sha256 = "1vf9civd41bnqi6brr5d9jifdw73j9khc6fkhfl1f8r9cpkdvlx1";
doCheck = false; # check depends on rspec!
};
json = buildRubyGem {
name = "json-1.8.1";
sha256 = "0002bsycvizvkmk1jyv8px1hskk6wrjfk4f7x5byi8gxm6zzn6wn";
};
rspec = rspec_3_0;
rspec_3_0 = buildRubyGem {
name = "rspec-3.0.0";
sha256 = "1x94vk8dlk57clqlyb741y5bsmidp8131wyrb1vh00hi5mdb5szy";
gemPath = [
self.diff_lcs self.rspec_core self.rspec_expectations self.rspec_mocks
self.rspec_support
];
};
rspec_2_14 = buildRubyGem {
name = "rspec-2.14.1";
sha256 = "134y4wzk1prninb5a0bhxgm30kqfzl8dg06af4js5ylnhv2wd7sg";
};
rspec_core = buildRubyGem {
name = "rspec-core-3.0.3";
sha256 = "0395m5rfpbh87wm3mx549zvm190gikpzyld0xhlr55qwzp6ny97m";
gemPath = [ self.rspec_support ];
};
rspec_expectations = buildRubyGem {
name = "rspec-expectations-3.0.3";
sha256 = "1mzp3v5r7qy28q8x6dkdib9ymwrxxz81jiq9vfr94jxbmy8rkhn0";
gemPath = [ self.diff_lcs self.rspec_support ];
};
rspec_mocks = buildRubyGem {
name = "rspec-mocks-3.0.3";
sha256 = "0svc5wq8k4w8iamj2r7xw4xwhfczcj09s0ps9wz1mmgy9cvn1lj6";
gemPath = [ self.rspec_support ];
};
rspec_support = buildRubyGem {
name = "rspec-support-3.0.3";
sha256 = "06lxzc4i3cbkm3qc5sdqcg665cyq9hnmmy0qkn355vy4s4vch94l";
};
terminal_notifier = buildRubyGem {
name = "terminal-notifier-1.6.1";
sha256 = "0j14sblviiypzc9vb508ldd78winba4vhnm9nhg3zpq07p3528g7";
};
dotenv_deployment = buildRubyGem {
name = "dotenv-deployment-0.0.2";
sha256 = "1ad66jq9a09qq1js8wsyil97018s7y6x0vzji0dy34gh65sbjz8c";
};
dotenv = buildRubyGem {
name = "dotenv-0.11.1";
gemPath = [ self.dotenv_deployment ];
sha256 = "09z0y0d6bks7i0sqvd8szfqj9i1kkj01anzly7shi83b3gxhrq9m";
};
libv8 = buildRubyGem {
name = "libv8-3.16.14.3";
sha256 = "1arjjbmr9zxkyv6pdrihsz1p5cadzmx8308vgfvrhm380ccgridm";
};
mini_portile = buildRubyGem {
name = "mini_portile-0.6.0";
sha256 = "09kcn4g63xrdirgwxgjikqg976rr723bkc9bxfr29pk22cj3wavn";
};
nokogiri = buildRubyGem {
name = "nokogiri-1.6.3.1";
sha256 = "11958hlfd8i3i9y0wk1b6ck9x0j95l4zdbbixmdnnh1r8ijilxli";
gemPath = [ self.mini_portile ];
};
pg = buildRubyGem {
name = "pg-0.17.1";
sha256 = "19hhlq5cp0cgm9b8daxjn8rkk8fq7bxxv1gd43l2hk0qgy7kx4z7";
};
ref = buildRubyGem {
name = "ref-1.0.5";
sha256 = "19qgpsfszwc2sfh6wixgky5agn831qq8ap854i1jqqhy1zsci3la";
};
therubyracer = buildRubyGem {
name = "therubyracer-0.12.1";
sha256 = "106fqimqyaalh7p6czbl5m2j69z8gv7cm10mjb8bbb2p2vlmqmi6";
gemPath = [ self.libv8 self.ref ];
};
};
# TODO: refactor mutual recursion here
# it looks a lot like the importGems function above, but it's too late at night
# to write a more generic version
boringPatches = callPackage ./patches.nix { inherit ruby self; };
self = patchGemsWith selfPre boringPatches;
in self
# 1. Load set of gem names and versions from a bundix-created expression.
gemset = callPackage file { };
# 2. Allow gems to be overriden by providing a derivation yourself.
config = gemset // (args gemset);
# 3.
gems = fixGems config;
in gems;
}

View File

@ -1,79 +0,0 @@
# build-time overrides for some gems
#
# gems in here generally involve native extensions; there's no way to tell
# based on the gemfile
{ libxml2, libxslt, postgresql, python, ruby, self, v8_3_16_14, which, writeScript
, stdenv }:
let
v8 = v8_3_16_14;
patchUsrBinEnv = writeScript "path-usr-bin-env" ''
#!/bin/sh
echo "==================="
find "$1" -type f -name "*.rb" | xargs sed -i "s@/usr/bin/env@$(type -p env)@g"
find "$1" -type f -name "*.mk" | xargs sed -i "s@/usr/bin/env@$(type -p env)@g"
'';
in
{
barber = { gemFlags = "--ignore-dependencies"; dontBuild = 1; };
ember_data_source = { gemFlags = "--ignore-dependencies"; };
ember_rails = { gemFlags = "--ignore-dependencies"; };
rbtrace = { dontBuild = 1; };
method_source = { dontBuild = 1; };
pg = { buildFlags = ["--with-pg-config=${postgresql}/bin/pg_config"]; };
nokogiri = {
buildInputs = [ libxml2 ];
buildFlags =
[ "--with-xml2-dir=${libxml2} --with-xml2-include=${libxml2}/include/libxml2"
"--with-xslt-dir=${libxslt}" "--use-system-libraries"
];
};
therubyracer = {
preBuild = ''
addToSearchPath RUBYLIB "${self.libv8}/${ruby.gemPath}/gems/libv8-3.16.14.3/lib"
addToSearchPath RUBYLIB "${self.libv8}/${ruby.gemPath}/gems/libv8-3.16.14.3/ext"
'';
postInstall = stdenv.lib.optionalString stdenv.isDarwin ''
cat >> $out/nix-support/setup-hook <<EOF
export DYLD_INSERT_LIBRARIES="$DYLD_INSERT_LIBRARIES''${!DYLD_INSERT_LIBRARIES:+:}${v8}/lib/libv8.dylib"
EOF
'';
buildFlags = [
"--with-v8-dir=${v8}" "--with-v8-include=${v8}/include"
"--with-v8-lib=${v8}/lib"
];
};
libv8 = {
dontBuild = true;
buildFlags = [ "--with-system-v8" ];
};
xrefresh_server =
let
patch = fetchurl {
url = "http://mawercer.de/~nix/xrefresh.diff.gz";
sha256 = "1f7bnmn1pgkmkml0ms15m5lx880hq2sxy7vsddb3sbzm7n1yyicq";
};
in {
propagatedBuildInputs = [ gems.rb_inotify ];
# monitor implementation for Linux
postInstall = ''
cd $out/${ruby.gemPath}/gems/*
zcat ${patch} | patch -p 1
''; # */
};
bundler = { dontPatchShebangs=1; };
}