about summary refs log tree commit diff
path: root/pkgs/development/web
diff options
context:
space:
mode:
authorJaka Hudoklin <jakahudoklin@gmail.com>2015-02-23 13:27:37 +0100
committerJaka Hudoklin <jakahudoklin@gmail.com>2015-02-23 13:29:50 +0100
commitb2fdcf801ce08bf0c44e63bafe8ae2c720704da7 (patch)
treebbb9388cff1f6da9b60bfb215b796494843097f6 /pkgs/development/web
parent60993d7716c51a246935545f7a3e2ce7952e133e (diff)
downloadnixlib-b2fdcf801ce08bf0c44e63bafe8ae2c720704da7.tar
nixlib-b2fdcf801ce08bf0c44e63bafe8ae2c720704da7.tar.gz
nixlib-b2fdcf801ce08bf0c44e63bafe8ae2c720704da7.tar.bz2
nixlib-b2fdcf801ce08bf0c44e63bafe8ae2c720704da7.tar.lz
nixlib-b2fdcf801ce08bf0c44e63bafe8ae2c720704da7.tar.xz
nixlib-b2fdcf801ce08bf0c44e63bafe8ae2c720704da7.tar.zst
nixlib-b2fdcf801ce08bf0c44e63bafe8ae2c720704da7.zip
nodePackages: add platform support, fix a lot of bugs
Diffstat (limited to 'pkgs/development/web')
-rw-r--r--pkgs/development/web/nodejs/build-node-package.nix165
1 files changed, 106 insertions, 59 deletions
diff --git a/pkgs/development/web/nodejs/build-node-package.nix b/pkgs/development/web/nodejs/build-node-package.nix
index 7d166a87e6a6..048b53f00052 100644
--- a/pkgs/development/web/nodejs/build-node-package.nix
+++ b/pkgs/development/web/nodejs/build-node-package.nix
@@ -1,22 +1,30 @@
 { stdenv, runCommand, nodejs, neededNatives}:
 
 {
-  name, src,
+  name, version ? "", src,
 
   # 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
   deps ? {},
 
   # 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
-  bin ? null,
+  bin ? false,
 
-  # Flags passed to npm install
-  flags ? [],
+  # Additional flags passed to npm install
+  flags ? "",
 
   # Command to be run before shell hook
   preShellHook ? "",
@@ -24,6 +32,12 @@
   # Command to be run after shell hook
   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),
   # for avoiding infinite recursion
   resolvedDeps ? {},
@@ -34,42 +48,67 @@
 with stdenv.lib;
 
 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
-    # Pass resolved dependencies to dependencies of this package
-    deps = map (
-      dep: dep.override {
-        resolvedDeps = resolvedDeps // { "${name}" = self; };
-      }
-    ) (attrValues requiredDeps);
+    sources = runCommand "node-sources" {} ''
+      tar --no-same-owner --no-same-permissions -xf ${nodejs.src}
+      mv $(find . -type d -mindepth 1 -maxdepth 1) $out
+    '';
+
+    platforms = fold (entry: platforms:
+      let
+        filterPlatforms = attrByPath [(removePrefix "!" entry)] [] stdenv.lib.platforms;
+      in
+        if hasPrefix "!" entry then
+          filter (p: any (f: p != f) filterPlatforms) platforms
+        else
+          filter (p: any (f: p == f) filterPlatforms) platforms
+    ) 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:
+      any (platform: stdenv.system == platform) dep.meta.platforms &&
+      all (d: d != 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: ''
-        node=`type -p node`
-        coffee=`type -p coffee || true`
-        find -L ${dir} -type f -print0 | xargs -0 grep -Il . | \
-        xargs sed --follow-symlinks -i \
-            -e 's@#!/usr/bin/env node@#!'"$node"'@' \
-            -e 's@#!/usr/bin/env coffee@#!'"$coffee"'@' \
-            -e 's@#!/.*/node@#!'"$node"'@' \
-            -e 's@#!/.*/coffee@#!'"$coffee"'@' || true
+      node=`type -p node`
+      coffee=`type -p coffee || true`
+      find -L ${dir} -type f -print0 | xargs -0 grep -Il . | \
+      xargs sed --follow-symlinks -i \
+          -e 's@#!/usr/bin/env node@#!'"$node"'@' \
+          -e 's@#!/usr/bin/env coffee@#!'"$coffee"'@' \
+          -e 's@#!/.*/node@#!'"$node"'@' \
+          -e 's@#!/.*/coffee@#!'"$coffee"'@' || true
     '';
 
   in stdenv.mkDerivation ({
@@ -147,9 +186,9 @@ let
       # We do not handle shrinkwraps yet
       rm npm-shrinkwrap.json 2>/dev/null || true
 
-      mkdir build-dir
+      mkdir ../build-dir
       (
-        cd build-dir
+        cd ../build-dir
         mkdir node_modules
 
         # Symlink or copy dependencies for node modules
@@ -161,12 +200,7 @@ let
           '' else ''
             cp -R ${dep}/lib/node_modules/${dep.pkgName} node_modules/
           ''
-        ) deps}
-
-        # Symlink peer dependencies
-        ${concatMapStrings (dep: ''
-          ln -sv ${dep}/lib/node_modules/${dep.pkgName} node_modules/
-        '') peerDeps}
+        ) (attrValues requiredDependencies)}
 
         # Create shims for recursive dependenceies
         ${concatMapStrings (dep: ''
@@ -177,10 +211,10 @@ let
               "version": "${getVersion dep}"
           }
           EOF
-        '') (attrValues recursiveDeps)}
+        '') (attrValues recursiveDependencies)}
       )
 
-      export HOME=$PWD/build-dir
+      export HOME=$PWD/../build-dir
       runHook postConfigure
     '';
 
@@ -189,14 +223,14 @@ let
 
       # If source was a file, repackage it, so npm pre/post publish hooks are not triggered,
       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
       else
         export src=$PWD
       fi
 
       # 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
     '';
@@ -211,7 +245,7 @@ let
         ${concatMapStrings (dep: ''
           rm node_modules/${dep.pkgName}/package.json
           rmdir node_modules/${dep.pkgName}
-        '') (attrValues recursiveDeps)}
+        '') (attrValues recursiveDependencies)}
 
         mkdir -p $out/lib/node_modules
 
@@ -230,10 +264,10 @@ let
           done
         fi
 
-        # Symlink dependencies
+        # Move peer dependencies to node_modules
         ${concatMapStrings (dep: ''
           mv node_modules/${dep.pkgName} $out/lib/node_modules
-        '') peerDeps}
+        '') (attrValues _peerDependencies.requiredDeps)}
 
         # Install binaries and patch shebangs
         mv node_modules/.bin $out/lib/node_modules 2>/dev/null || true
@@ -256,23 +290,36 @@ let
       mkdir -p node_modules
       ${concatMapStrings (dep: ''
         ln -sfv ${dep}/lib/node_modules/${dep.pkgName} node_modules/
-      '') deps}
+      '') (attrValues requiredDependencies)}
       ${postShellHook}
     '';
 
+    # Stipping does not make a lot of sense in node packages
+    dontStrip = true;
+
+    meta = {
+      platforms = platforms;
+      maintainers = [ stdenv.lib.maintainers.offline ];
+    };
+
     passthru.pkgName = pkgName;
-  } // (filterAttrs (n: v: n != "deps" && n != "resolvedDeps") args) // {
+  } // (filterAttrs (n: v: all (k: n != k) ["deps" "resolvedDeps" "optionalDependencies"]) args) // {
     name = "${nodejs.interpreterName}-${name}";
 
     # Run the node setup hook when this package is a build input
     propagatedNativeBuildInputs = (args.propagatedNativeBuildInputs or []) ++ [ nodejs ];
 
-    # Make buildNodePackage useful with --run-env
-    nativeBuildInputs = (args.nativeBuildInputs or []) ++ deps ++ peerDependencies ++ neededNatives;
+    nativeBuildInputs =
+      (args.nativeBuildInputs or []) ++ neededNatives ++
+      (attrValues requiredDependencies);
 
     # Expose list of recursive dependencies upstream, up to the package that
     # 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