Revert "Reverts a bunch of commits as a try to fix GC errors."

This reverts commit 1e4ba025c2.

Conflicts:
	pkgs/development/web/nodejs/build-node-package.nix
This commit is contained in:
Jaka Hudoklin 2015-03-21 17:09:38 +01:00
parent 51d465646a
commit f953d77be2
2 changed files with 114 additions and 62 deletions

View file

@ -234,8 +234,8 @@ rec {
in [x] ++ remove x xs; in [x] ++ remove x xs;
# Intersects list 'e' and another list # Intersects list 'e' and another list
intersect = e: filter (x: elem x e); intersectLists = e: filter (x: elem x e);
# Substracts list 'e' from another list # Subtracts list 'e' from another list
substract = e: filter (x: !(elem x e)); subtractLists = e: filter (x: !(elem x e));
} }

View file

@ -1,25 +1,33 @@
{ stdenv, runCommand, nodejs, neededNatives}: { stdenv, runCommand, nodejs, neededNatives}:
{ {
name, src, name, version ? "", src,
# by default name of nodejs interpreter e.g. "nodejs-${name}" # by default name of nodejs interpreter e.g. "nodejs-${name}"
namePrefix ? nodejs.interpreterName + "-", namePrefix ? nodejs.interpreterName + "-",
# Node package name # Node package name
pkgName ? (builtins.parseDrvName name).name, pkgName ?
if version != "" then stdenv.lib.removeSuffix "-${version}" name else
(builtins.parseDrvName name).name,
# List or attribute set of dependencies # List or attribute set of dependencies
deps ? {}, deps ? {},
# List or attribute set of peer depencies # List or attribute set of peer depencies
peerDependencies ? [], peerDependencies ? {},
# List or attribute set of optional dependencies
optionalDependencies ? {},
# List of optional dependencies to skip
skipOptionalDependencies ? [],
# Whether package is binary or library # Whether package is binary or library
bin ? null, bin ? false,
# Flags passed to npm install # Additional flags passed to npm install
flags ? [], flags ? "",
# Command to be run before shell hook # Command to be run before shell hook
preShellHook ? "", preShellHook ? "",
@ -27,6 +35,12 @@
# Command to be run after shell hook # Command to be run after shell hook
postShellHook ? "", postShellHook ? "",
# Same as https://docs.npmjs.com/files/package.json#os
os ? [],
# Same as https://docs.npmjs.com/files/package.json#cpu
cpu ? [],
# Attribute set of already resolved deps (internal), # Attribute set of already resolved deps (internal),
# for avoiding infinite recursion # for avoiding infinite recursion
resolvedDeps ? {}, resolvedDeps ? {},
@ -37,42 +51,72 @@
with stdenv.lib; with stdenv.lib;
let let
npmFlags = concatStringsSep " " (map (v: "--${v}") flags);
sources = runCommand "node-sources" {} ''
tar --no-same-owner --no-same-permissions -xf ${nodejs.src}
mv $(find . -type d -mindepth 1 -maxdepth 1) $out
'';
# Convert deps to attribute set
attrDeps = if isAttrs deps then deps else
(listToAttrs (map (dep: nameValuePair dep.name dep) deps));
# All required node modules, without already resolved dependencies
requiredDeps = removeAttrs attrDeps (attrNames resolvedDeps);
# Recursive dependencies that we want to avoid with shim creation
recursiveDeps = removeAttrs attrDeps (attrNames requiredDeps);
peerDeps = filter (dep: dep.pkgName != pkgName) peerDependencies;
self = let self = let
# Pass resolved dependencies to dependencies of this package sources = runCommand "node-sources" {} ''
deps = map ( tar --no-same-owner --no-same-permissions -xf ${nodejs.src}
dep: dep.override { mv $(find . -type d -mindepth 1 -maxdepth 1) $out
resolvedDeps = resolvedDeps // { "${name}" = self; }; '';
}
) (attrValues requiredDeps); platforms = if os == [] then nodejs.meta.platforms else
fold (entry: platforms:
let
filterPlatforms =
stdenv.lib.platforms.${removePrefix "!" entry} or [];
in
# Ignore unknown platforms
if filterPlatforms == [] then platforms
else
if hasPrefix "!" entry then
subtractLists (intersectLists filterPlatforms nodejs.meta.platforms) platforms
else
platforms ++ (intersectLists filterPlatforms nodejs.meta.platforms)
) [] os;
mapDependencies = deps: f: rec {
# Convert deps to attribute set
attrDeps = if isAttrs deps then deps else
(listToAttrs (map (dep: nameValuePair dep.name dep) deps));
# All required node modules, without already resolved dependencies
# Also override with already resolved dependencies
requiredDeps = mapAttrs (name: dep:
dep.override {
resolvedDeps = resolvedDeps // { "${name}" = self; };
}
) (filterAttrs f (removeAttrs attrDeps (attrNames resolvedDeps)));
# Recursive dependencies that we want to avoid with shim creation
recursiveDeps = filterAttrs f (removeAttrs attrDeps (attrNames requiredDeps));
};
_dependencies = mapDependencies deps (name: dep:
dep.pkgName != pkgName);
_optionalDependencies = mapDependencies optionalDependencies (name: dep:
(builtins.tryEval dep).success &&
!(elem dep.pkgName skipOptionalDependencies)
);
_peerDependencies = mapDependencies peerDependencies (name: dep:
dep.pkgName != pkgName);
requiredDependencies =
_dependencies.requiredDeps //
_optionalDependencies.requiredDeps //
_peerDependencies.requiredDeps;
recursiveDependencies =
_dependencies.recursiveDeps //
_optionalDependencies.recursiveDeps //
_peerDependencies.recursiveDeps;
patchShebangs = dir: '' patchShebangs = dir: ''
node=`type -p node` node=`type -p node`
coffee=`type -p coffee || true` coffee=`type -p coffee || true`
find -L ${dir} -type f -print0 | xargs -0 grep -Il . | \ find -L ${dir} -type f -print0 | xargs -0 grep -Il . | \
xargs sed --follow-symlinks -i \ xargs sed --follow-symlinks -i \
-e 's@#!/usr/bin/env node@#!'"$node"'@' \ -e 's@#!/usr/bin/env node@#!'"$node"'@' \
-e 's@#!/usr/bin/env coffee@#!'"$coffee"'@' \ -e 's@#!/usr/bin/env coffee@#!'"$coffee"'@' \
-e 's@#!/.*/node@#!'"$node"'@' \ -e 's@#!/.*/node@#!'"$node"'@' \
-e 's@#!/.*/coffee@#!'"$coffee"'@' || true -e 's@#!/.*/coffee@#!'"$coffee"'@' || true
''; '';
in stdenv.mkDerivation ({ in stdenv.mkDerivation ({
@ -150,9 +194,9 @@ let
# We do not handle shrinkwraps yet # We do not handle shrinkwraps yet
rm npm-shrinkwrap.json 2>/dev/null || true rm npm-shrinkwrap.json 2>/dev/null || true
mkdir build-dir mkdir ../build-dir
( (
cd build-dir cd ../build-dir
mkdir node_modules mkdir node_modules
# Symlink or copy dependencies for node modules # Symlink or copy dependencies for node modules
@ -164,12 +208,7 @@ let
'' else '' '' else ''
cp -R ${dep}/lib/node_modules/${dep.pkgName} node_modules/ cp -R ${dep}/lib/node_modules/${dep.pkgName} node_modules/
'' ''
) deps} ) (attrValues requiredDependencies)}
# Symlink peer dependencies
${concatMapStrings (dep: ''
ln -sv ${dep}/lib/node_modules/${dep.pkgName} node_modules/
'') peerDeps}
# Create shims for recursive dependenceies # Create shims for recursive dependenceies
${concatMapStrings (dep: '' ${concatMapStrings (dep: ''
@ -180,10 +219,10 @@ let
"version": "${getVersion dep}" "version": "${getVersion dep}"
} }
EOF EOF
'') (attrValues recursiveDeps)} '') (attrValues recursiveDependencies)}
) )
export HOME=$PWD/build-dir export HOME=$PWD/../build-dir
runHook postConfigure runHook postConfigure
''; '';
@ -192,14 +231,14 @@ let
# If source was a file, repackage it, so npm pre/post publish hooks are not triggered, # If source was a file, repackage it, so npm pre/post publish hooks are not triggered,
if [[ -f $src ]]; then if [[ -f $src ]]; then
tar --exclude='build-dir' -czf build-dir/package.tgz ./ GZIP=-1 tar -czf ../build-dir/package.tgz ./
export src=$HOME/package.tgz export src=$HOME/package.tgz
else else
export src=$PWD export src=$PWD
fi fi
# Install package # Install package
(cd $HOME && npm --registry http://www.example.com --nodedir=${sources} install $src ${npmFlags}) (cd $HOME && npm --registry http://www.example.com --nodedir=${sources} install $src --fetch-retries 0 ${flags})
runHook postBuild runHook postBuild
''; '';
@ -214,7 +253,7 @@ let
${concatMapStrings (dep: '' ${concatMapStrings (dep: ''
rm node_modules/${dep.pkgName}/package.json rm node_modules/${dep.pkgName}/package.json
rmdir node_modules/${dep.pkgName} rmdir node_modules/${dep.pkgName}
'') (attrValues recursiveDeps)} '') (attrValues recursiveDependencies)}
mkdir -p $out/lib/node_modules mkdir -p $out/lib/node_modules
@ -233,10 +272,10 @@ let
done done
fi fi
# Symlink dependencies # Move peer dependencies to node_modules
${concatMapStrings (dep: '' ${concatMapStrings (dep: ''
mv node_modules/${dep.pkgName} $out/lib/node_modules mv node_modules/${dep.pkgName} $out/lib/node_modules
'') peerDeps} '') (attrValues _peerDependencies.requiredDeps)}
# Install binaries and patch shebangs # Install binaries and patch shebangs
mv node_modules/.bin $out/lib/node_modules 2>/dev/null || true mv node_modules/.bin $out/lib/node_modules 2>/dev/null || true
@ -259,23 +298,36 @@ let
mkdir -p node_modules mkdir -p node_modules
${concatMapStrings (dep: '' ${concatMapStrings (dep: ''
ln -sfv ${dep}/lib/node_modules/${dep.pkgName} node_modules/ ln -sfv ${dep}/lib/node_modules/${dep.pkgName} node_modules/
'') deps} '') (attrValues requiredDependencies)}
${postShellHook} ${postShellHook}
''; '';
# Stipping does not make a lot of sense in node packages
dontStrip = true;
meta = {
inherit platforms;
maintainers = [ stdenv.lib.maintainers.offline ];
};
passthru.pkgName = pkgName; passthru.pkgName = pkgName;
} // (filterAttrs (n: v: all (k: n != k) ["deps" "resolvedDeps" "optionalDependencies"]) args)// { } // (filterAttrs (n: v: all (k: n != k) ["deps" "resolvedDeps" "optionalDependencies"]) args) // {
name = namePrefix + name; name = namePrefix + name;
# Run the node setup hook when this package is a build input # Run the node setup hook when this package is a build input
propagatedNativeBuildInputs = (args.propagatedNativeBuildInputs or []) ++ [ nodejs ]; propagatedNativeBuildInputs = (args.propagatedNativeBuildInputs or []) ++ [ nodejs ];
# Make buildNodePackage useful with --run-env nativeBuildInputs =
nativeBuildInputs = (args.nativeBuildInputs or []) ++ deps ++ peerDependencies ++ neededNatives; (args.nativeBuildInputs or []) ++ neededNatives ++
(attrValues requiredDependencies);
# Expose list of recursive dependencies upstream, up to the package that # Expose list of recursive dependencies upstream, up to the package that
# caused recursive dependency # caused recursive dependency
recursiveDeps = (flatten (map (d: remove name d.recursiveDeps) deps)) ++ (attrNames recursiveDeps); recursiveDeps =
(flatten (
map (dep: remove name dep.recursiveDeps) (attrValues requiredDependencies)
)) ++
(attrNames recursiveDependencies);
}); });
in self in self