split nodejs builder into different phases

This commit is contained in:
DavHau 2021-10-31 21:43:45 +07:00
parent 0d1e36f770
commit cd6095406b
5 changed files with 102 additions and 70 deletions

View File

@ -49,9 +49,9 @@ in
remove-webpack-cli-check = {
_condition = pkg: pkg.version == "5.41.1";
ignoreScripts = false;
installScript = ''
patch ./bin/webpack.js < ${./webpack/remove-webpack-cli-check.patch}
'';
patches = [
./webpack/remove-webpack-cli-check.patch
];
};
};
@ -59,9 +59,9 @@ in
remove-webpack-check = {
_condition = pkg: pkg.version == "4.7.2";
ignoreScripts = false;
installScript = ''
patch ./bin/cli.js < ${./webpack-cli/remove-webpack-check.patch}
'';
patches = [
./webpack-cli/remove-webpack-check.patch
];
};
};

View File

@ -1,7 +1,6 @@
diff --git a/packages/webpack-cli/bin/cli.js b/packages/webpack-cli/bin/cli.js
index d62a6258..9d5683c7 100755
--- a/packages/webpack-cli/bin/cli.js
+++ b/packages/webpack-cli/bin/cli.js
--- a/bin/cli.js
+++ b/bin/cli.js
@@ -21,7 +21,7 @@ if (!process.env.WEBPACK_CLI_SKIP_IMPORT_LOCAL) {
process.title = "webpack";

View File

@ -1,5 +1,4 @@
diff --git a/bin/webpack.js b/bin/webpack.js
index fead38bf4..0bd13d3eb 100755
--- a/bin/webpack.js
+++ b/bin/webpack.js
@@ -87,7 +87,7 @@ const cli = {

View File

@ -40,11 +40,10 @@ let
b = builtins;
# tells if a dependency introduces a cycle
# -> needs to be built in a combined derivation
isCyclic = name: version:
b.elem name standalonePackageNames
||
(cyclicDependencies ? "${name}"
&& cyclicDependencies."${name}" ? "${version}");
cyclicDependencies ? "${name}"."${version}";
mainPackageKey =
"${mainPackageName}#${mainPackageVersion}";
@ -68,7 +67,8 @@ let
lib.genAttrs
versions
(version:
if isCyclic name version then
if isCyclic name version
|| b.elem name standalonePackageNames then
makeCombinedPackage name version
else
makePackage name version))
@ -89,6 +89,7 @@ let
in
built.defaultPackage;
# Generates a derivation for a specific package name + version
makePackage = name: version:
let
@ -118,34 +119,37 @@ let
buildInputs = [ jq nodejs nodejs.python ];
# prevents running into ulimits
passAsFile = [ "dependenciesJson" "nodeDeps" ];
ignoreScripts = true;
preBuildPhases = [ "d2nPatchPhase" "d2nInstallDependenciesPhase" ];
dontUnpack = true;
preFixupPhases = [ "d2nPostInstallPhase" ];
# not used by default but can be enabled if needed
dontConfigure = true;
dontBuild = true;
dontNpmInstall = false;
# can be overridden to define alternative install command
# (defaults to 'npm run postinstall')
installScript = null;
# python script to modify some metadata to support installation
# (see comments below on d2nPatchPhase)
fixPackage = "${./fix-package.py}";
# costs performance and doesn't seem beneficial in most scenarios
dontStrip = true;
# not using the default unpackPhase,
# as it fails setting the permissions sometimes
installPhase = ''
runHook preInstall
# The default unpackPhase seemed to fail on setting permissions
# for some packages.
# TODO: debug nixpkgs unpackPhase and upstream improvement.
unpackPhase = ''
runHook preUnpack
nodeModules=$out/lib/node_modules
mkdir -p $nodeModules
cd $TMPDIR
export sourceRoot="$nodeModules/$packageName"
unpackFile $src
@ -156,30 +160,68 @@ let
if [ -f "$src" ]
then
# Figure out what directory has been unpacked
packageDir="$(find . -maxdepth 1 -type d | tail -1)"
export packageDir="$(find . -maxdepth 1 -type d | tail -1)"
# Restore write permissions
find "$packageDir" -type d -exec chmod u+x {} \;
chmod -R u+w "$packageDir"
# Move the extracted tarball into the output folder
mv "$packageDir" "$nodeModules/$packageName"
mv "$packageDir" "$sourceRoot"
elif [ -d "$src" ]
then
strippedName="$(stripHash $src)"
export strippedName="$(stripHash $src)"
# Restore write permissions
chmod -R u+w "$strippedName"
# Move the extracted directory into the output folder
mv "$strippedName" "$nodeModules/$packageName"
mv "$strippedName" "$sourceRoot"
fi
runHook postUnpack
'';
# The python script wich is executed in this phase:
# - ensures that the package is compatible to the current system
# - ensures the main version in package.json matches the expected
# - deletes "devDependencies" and "peerDependencies" from package.json
# (might block npm install in case npm install is used)
# - pins dependency versions in package.json
# - creates symlinks for executables declared in package.json
# Apart from that:
# - Any usage of 'link:' in package.json is replaced with 'file:'
# - If package-lock.json exists, it is deleted, as it might conflict
# with the parent package-lock.json.
d2nPatchPhase = ''
# delete package-lock.json as it can lead to conflicts
rm -f package-lock.json
# repair 'link:' -> 'file:'
mv $nodeModules/$packageName/package.json $nodeModules/$packageName/package.json.old
cat $nodeModules/$packageName/package.json.old | sed 's!link:!file\:!g' > $nodeModules/$packageName/package.json
rm $nodeModules/$packageName/package.json.old
# run python script (see commend above):
cp package.json package.json.bak
python $fixPackage \
|| \
# exit code 3 -> the package is incompatible to the current platform
# -> Let the build succeed, but don't create lib/node_packages
if [ "$?" == "3" ]; then
rm -r $out/*
echo "Not compatible with system $system" > $out/error
exit 0
else
exit 1
fi
'';
# - links all direct node dependencies into the node_modules directory
# - adds executables of direct node dependencies to PATH
# - adds the current node module to NODE_PATH
# - sets HOME=$TMPDIR, as this is required by some npm scripts
d2nInstallDependenciesPhase = ''
# symlink dependency packages into node_modules
for dep in $(cat $nodeDepsPath); do
# add bin to PATH
@ -192,12 +234,12 @@ let
if [[ $module == @* ]]; then
for submodule in $(ls $dep/lib/node_modules/$module); do
mkdir -p $nodeModules/$packageName/node_modules/$module
echo "ln -s $dep/lib/node_modules/$module/$submodule $nodeModules/$packageName/node_modules/$module/$submodule"
echo -e "creating link: $dep/lib/node_modules/$module/$submodule\n -> $nodeModules/$packageName/node_modules/$module/$submodule"
ln -s $dep/lib/node_modules/$module/$submodule $nodeModules/$packageName/node_modules/$module/$submodule
done
else
mkdir -p $nodeModules/$packageName/node_modules/
echo "ln -s $dep/lib/node_modules/$module $nodeModules/$packageName/node_modules/$module"
echo -e "creating link: $dep/lib/node_modules/$module\n -> $nodeModules/$packageName/node_modules/$module"
ln -s $dep/lib/node_modules/$module $nodeModules/$packageName/node_modules/$module
fi
done
@ -206,39 +248,30 @@ let
export NODE_PATH="$NODE_PATH:$nodeModules/$packageName/node_modules"
cd "$nodeModules/$packageName"
export HOME=$TMPDIR
'';
# delete package-lock.json as it can lead to conflicts
rm -f package-lock.json
# Run the install command which defaults to 'npm run postinstall'.
# Set alternative install command by overriding 'installScript'.
installPhase = ''
runHook preInstall
# pin dependency versions in package.json
cp package.json package.json.bak
python $fixPackage \
|| \
# exit code 3 -> the package is incompatible to the current platform
if [ "$?" == "3" ]; then
rm -r $out/*
echo "Not compatible with system $system" > $out/error
exit 0
else
exit 1
fi
# execute installation command
# execute install command
if [ -n "$installScript" ]; then
if [ -f "$installScript" ]; then
exec $installScript
else
echo "$installScript" | bash
fi
elif [ -z "$dontNpmInstall" ]; then
if [ "$(jq '.scripts.postinstall' ./package.json)" != "null" ]; then
npm --production --offline --nodedir=$nodeSources run postinstall
fi
elif [ "$(jq '.scripts.postinstall' ./package.json)" != "null" ]; then
npm --production --offline --nodedir=$nodeSources run postinstall
fi
runHook postInstall
'';
# Symlinks executables and manual pages to correct directories
d2nPostInstallPhase = ''
# Create symlink to the deployed executable folder, if applicable
if [ -d "$nodeModules/.bin" ]
then
@ -249,21 +282,20 @@ let
# Create symlinks to the deployed manual page folders, if applicable
if [ -d "$nodeModules/$packageName/man" ]
then
mkdir -p $out/share
for dir in "$nodeModules/$packageName/man/"*
mkdir -p $out/share
for dir in "$nodeModules/$packageName/man/"*
do
mkdir -p $out/share/man/$(basename "$dir")
for page in "$dir"/*
do
mkdir -p $out/share/man/$(basename "$dir")
for page in "$dir"/*
do
ln -s $page $out/share/man/$(basename "$dir")
done
ln -s $page $out/share/man/$(basename "$dir")
done
done
fi
runHook postInstall
'';
};
in
# apply packageOverrides to current derivation
(utils.applyOverridesToPackage packageOverrides pkg name);

View File

@ -29,7 +29,9 @@ if 'os' in package_json:
version = os.environ.get("version")
if package_json['version'] != version:
print(
"WARNING: Replacing version in package.json: "
"WARNING: The version of this package defined by its package.json "
"doesn't match the version expected by dream2nix."
"\n -> Replacing version in package.json: "
f"{package_json['version']} -> {version}",
file=sys.stderr
)
@ -40,7 +42,7 @@ if package_json['version'] != version:
# We rely on dream.lock having the correct dependencies specified
if 'devDependencies' in package_json:
print(
f"Removing devDependencies from package.json",
f"package.json: removed all devDependencies",
file=sys.stderr
)
changed = True
@ -50,7 +52,7 @@ if 'devDependencies' in package_json:
# We rely on dream.lock instead
if 'peerDependencies' in package_json:
print(
f"Removing peerDependencies from package.json",
f"package.json: removed all peerDependencies",
file=sys.stderr
)
changed = True
@ -65,8 +67,8 @@ if 'dependencies' in package_json:
package_json['dependencies'][pname] = actual_deps[pname]
changed = True
print(
f"Replacing loose version '{version}' with '{actual_deps[pname]}'"
f" for dependency '{pname}' in package.json",
f"package.json: Pinning version '{version}' to '{actual_deps[pname]}'"
f" for dependency '{pname}'",
file=sys.stderr
)