mirror of
https://github.com/nix-community/dream2nix.git
synced 2024-11-23 09:04:37 +03:00
improve electron support
This commit is contained in:
parent
a08f5eb25a
commit
013dc86524
@ -116,12 +116,20 @@ in
|
||||
|
||||
build = {
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.rsync
|
||||
];
|
||||
electronAppDir = "src";
|
||||
|
||||
buildScript = ''
|
||||
npm run build-linux
|
||||
preBuild = { outputs, ... }: ''
|
||||
# link dependencies of subpackage
|
||||
ln -s \
|
||||
${outputs.subPackages.edex-ui-subpackage.packages.edex-ui-subpackage}/lib/node_modules/edex-ui-subpackage/node_modules \
|
||||
./src/node_modules
|
||||
|
||||
# transform symlinked subpackage 'node-pty' to copies,
|
||||
# in order to allow re-building
|
||||
mv src/node_modules src/node_modules.bac
|
||||
mkdir src/node_modules
|
||||
cp -r src/node_modules.bac/* src/node_modules/
|
||||
symlinksToCopies ./src/node_modules/node-pty
|
||||
'';
|
||||
};
|
||||
};
|
||||
@ -131,7 +139,7 @@ in
|
||||
|
||||
mkElectron =
|
||||
pkgs.callPackage
|
||||
"${pkgs.path}/pkgs/development/tools/electron/generic.nix"
|
||||
./electron/generic.nix
|
||||
{};
|
||||
|
||||
nixpkgsElectrons =
|
||||
@ -139,7 +147,6 @@ in
|
||||
(version: hashes:
|
||||
(mkElectron version hashes).overrideAttrs (old: {
|
||||
dontStrip = true;
|
||||
fixupPhase = old.postFixup;
|
||||
}))
|
||||
hashes;
|
||||
|
||||
@ -227,6 +234,15 @@ in
|
||||
aarch64-darwin = "0db2c021a047a4cd5b28eea16490e16bc82592e3f8a4b96fbdc72a292ce13f50";
|
||||
headers = "1idam1xirxqxqg4g7n33kdx2skk0r351m00g59a8yx9z82g06ah9";
|
||||
};
|
||||
"13.0.0" = {
|
||||
armv7l-linux = "51ddcd8c92da5dd84a6bab8304a0df6114153a884f7f185ebfc65843caa30e76";
|
||||
aarch64-linux = "5b36e5bcb36cf1b90c38b346d3eae970a2aa41cb585df493bb90d86dc2e88b0a";
|
||||
x86_64-linux = "ff89df221293f7253e2a29eb3028014549286179e3d91402e4911b2d086377bb";
|
||||
i686-linux = "6fd7eca44302762a97c205b1a08a4178247bea89354ce84c747e09ebeb9f245b";
|
||||
x86_64-darwin = "f3b9e45a442f82f06da8dd6cbdccd8031a191f3ba73e2886572f6472160d1f2d";
|
||||
aarch64-darwin = "9c26405efd126d4e076fa8068e9003463be62b449182632babd5445f633712b6";
|
||||
headers = "0glv92hhzg5f0fycrgv2g2b1avcw4jcrmpxxz4rpn91gd1v4n4fn";
|
||||
};
|
||||
"13.2.3" = {
|
||||
x86_64-linux = "495b0c96427c63f6f4d08c5b58d6379f9ee3c6c81148fbbe8a7a6a872127df6d";
|
||||
x86_64-darwin = "c02f116484a5e1495d9f7451638bc0d3dea8fa2fde2e4c9c88a17cff98192ddc";
|
||||
@ -287,6 +303,11 @@ in
|
||||
echo -n $version > ./dist/version
|
||||
echo -n "electron" > ./path.txt
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
mkdir -p $out/lib
|
||||
ln -s $(realpath ./dist) $out/lib/electron
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -294,17 +315,50 @@ in
|
||||
# TODO: fix electron-builder call or find alternative
|
||||
element-desktop = {
|
||||
build = {
|
||||
postPatch = ''
|
||||
ls tsconfig.json
|
||||
cp ${./element-desktop/tsconfig.json} ./tsconfig.json
|
||||
'';
|
||||
buildScript = ''
|
||||
|
||||
# TODO: build rust extensions to enable searching encrypted messages
|
||||
# TODO: create lower case symlinks for all i18n strings
|
||||
buildScript = { outputs, ... }: ''
|
||||
npm run build:ts
|
||||
npm run i18n
|
||||
npm run build:res
|
||||
# electron-builder
|
||||
|
||||
# build rust extensions
|
||||
# npm run hak
|
||||
|
||||
ln -s ${outputs.subPackages.element-web.packages.element-web}/lib/node_modules/element-web/webapp ./webapp
|
||||
|
||||
# ln -s ./lib/i18n/strings/en{-US,}.json
|
||||
ln -s \
|
||||
$(realpath ./lib/i18n/strings/en_US.json) \
|
||||
$(realpath ./lib/i18n/strings/en-us.json)
|
||||
'';
|
||||
|
||||
# buildInputs = old: old ++ [
|
||||
# pkgs.rustc
|
||||
# ];
|
||||
};
|
||||
};
|
||||
|
||||
element-web = {
|
||||
|
||||
build = {
|
||||
installMethod = "copy";
|
||||
|
||||
# TODO: file upstream issue because of non-reproducible jitsi api file
|
||||
buildScript = ''
|
||||
# install jitsi api
|
||||
mkdir webapp
|
||||
cp ${./element-web/external_api.min.js} webapp/external_api.min.js
|
||||
|
||||
# set version variables
|
||||
export DIST_VERSION=$version
|
||||
export VERSION=$version
|
||||
|
||||
npm run reskindex
|
||||
npm run build:res
|
||||
npm run build:bundle
|
||||
'';
|
||||
nativeBuildInputs = [pkgs.breakpointHook];
|
||||
b = "${pkgs.busybox}/bin/busybox";
|
||||
};
|
||||
};
|
||||
|
||||
@ -419,7 +473,7 @@ in
|
||||
cp -r ./node_modules/electron/dist $TMP/dist
|
||||
chmod -R +w $TMP/dist
|
||||
|
||||
# required if electron-buidler is used
|
||||
# required if electron-builder is used
|
||||
# mv $TMP/dist/electron $TMP/dist/electron-wrapper
|
||||
# mv $TMP/dist/.electron-wrapped $TMP/dist/electron
|
||||
|
||||
@ -491,6 +545,12 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
quill = {
|
||||
disable-build = {
|
||||
runBuild = false;
|
||||
};
|
||||
};
|
||||
|
||||
rollup = {
|
||||
preserve-symlinks = {
|
||||
postPatch = ''
|
||||
@ -675,4 +735,13 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
"@sentry/cli" = {
|
||||
add-binary = {
|
||||
buildScript = ''
|
||||
ln -s ${pkgs.sentry-cli}/bin $out/bin
|
||||
exit
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
136
overrides/nodejs/electron/generic.nix
Normal file
136
overrides/nodejs/electron/generic.nix
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
lib
|
||||
, autoPatchelfHook
|
||||
, alsa-lib
|
||||
, stdenv
|
||||
, libXScrnSaver
|
||||
, makeWrapper
|
||||
, fetchurl
|
||||
, wrapGAppsHook
|
||||
, glib
|
||||
, glibc
|
||||
, gtk3
|
||||
, unzip
|
||||
, atomEnv
|
||||
, libuuid
|
||||
, at-spi2-atk
|
||||
, at-spi2-core
|
||||
, libdrm
|
||||
, mesa
|
||||
, libxkbcommon
|
||||
, libappindicator-gtk3
|
||||
, libxshmfence
|
||||
, libXdamage
|
||||
, nss
|
||||
}:
|
||||
|
||||
version: hashes:
|
||||
let
|
||||
name = "electron-${version}";
|
||||
|
||||
meta = with lib; {
|
||||
description = "Cross platform desktop application shell";
|
||||
homepage = "https://github.com/electron/electron";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ travisbhartwell manveru prusnak ];
|
||||
platforms = [ "x86_64-darwin" "x86_64-linux" "i686-linux" "armv7l-linux" "aarch64-linux" ]
|
||||
++ optionals (versionAtLeast version "11.0.0") [ "aarch64-darwin" ];
|
||||
knownVulnerabilities = optional (versionOlder version "12.0.0") "Electron version ${version} is EOL";
|
||||
};
|
||||
|
||||
fetcher = vers: tag: hash: fetchurl {
|
||||
url = "https://github.com/electron/electron/releases/download/v${vers}/electron-v${vers}-${tag}.zip";
|
||||
sha256 = hash;
|
||||
};
|
||||
|
||||
headersFetcher = vers: hash: fetchurl {
|
||||
url = "https://atom.io/download/electron/v${vers}/node-v${vers}-headers.tar.gz";
|
||||
sha256 = hash;
|
||||
};
|
||||
|
||||
tags = {
|
||||
i686-linux = "linux-ia32";
|
||||
x86_64-linux = "linux-x64";
|
||||
armv7l-linux = "linux-armv7l";
|
||||
aarch64-linux = "linux-arm64";
|
||||
x86_64-darwin = "darwin-x64";
|
||||
aarch64-darwin = "darwin-arm64";
|
||||
};
|
||||
|
||||
get = as: platform: as.${platform.system} or
|
||||
"Unsupported system: ${platform.system}";
|
||||
|
||||
common = platform: {
|
||||
inherit name version meta;
|
||||
src = fetcher version (get tags platform) (get hashes platform);
|
||||
passthru.headers = headersFetcher version hashes.headers;
|
||||
};
|
||||
|
||||
electronLibs = with lib;
|
||||
[
|
||||
alsa-lib
|
||||
at-spi2-atk
|
||||
at-spi2-core
|
||||
glibc
|
||||
libappindicator-gtk3
|
||||
libuuid
|
||||
libXdamage
|
||||
libXScrnSaver
|
||||
nss
|
||||
]
|
||||
++ optionals (! versionOlder version "9.0.0") [ libdrm mesa ]
|
||||
++ optionals (! versionOlder version "11.0.0") [ libxkbcommon ]
|
||||
++ optionals (! versionOlder version "12.0.0") [ libxshmfence ];
|
||||
|
||||
electronLibPath = with lib; makeLibraryPath electronLibs;
|
||||
|
||||
linux = {
|
||||
buildInputs =
|
||||
[ glib gtk3 ]
|
||||
++ (builtins.map (p: lib.getOutput "lib" p) electronLibs);
|
||||
|
||||
nativeBuildInputs = [
|
||||
# autoPatchelfHook
|
||||
unzip
|
||||
makeWrapper
|
||||
wrapGAppsHook
|
||||
];
|
||||
|
||||
dontWrapGApps = true; # electron is in lib, we need to wrap it manually
|
||||
|
||||
dontUnpack = true;
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/lib/electron $out/bin
|
||||
unzip -d $out/lib/electron $src
|
||||
ln -s $out/lib/electron/electron $out/bin
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
patchelf \
|
||||
--set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
|
||||
--set-rpath "${electronLibPath}:${atomEnv.libPath}:$out/lib/electron" \
|
||||
$out/lib/electron/electron
|
||||
|
||||
wrapProgram $out/lib/electron/electron \
|
||||
"''${gappsWrapperArgs[@]}"
|
||||
'';
|
||||
};
|
||||
|
||||
darwin = {
|
||||
nativeBuildInputs = [ unzip ];
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out/Applications
|
||||
unzip $src
|
||||
mv Electron.app $out/Applications
|
||||
mkdir -p $out/bin
|
||||
ln -s $out/Applications/Electron.app/Contents/MacOS/Electron $out/bin/electron
|
||||
'';
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation (
|
||||
(common stdenv.hostPlatform) //
|
||||
(if stdenv.isDarwin then darwin else linux)
|
||||
)
|
@ -1,22 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2016",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false,
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"lib": [
|
||||
"es2019",
|
||||
"dom"
|
||||
],
|
||||
"preserveSymlinks": true
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts"
|
||||
]
|
||||
}
|
4
overrides/nodejs/element-web/external_api.min.js
vendored
Normal file
4
overrides/nodejs/element-web/external_api.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -54,6 +54,10 @@ let
|
||||
|
||||
nodejsVersion = subsystemAttrs.nodejsVersion;
|
||||
|
||||
isMainPackage = name: version:
|
||||
name == mainPackageName
|
||||
&& version == mainPackageVersion;
|
||||
|
||||
nodejs =
|
||||
if args ? nodejs then
|
||||
args.nodejs
|
||||
@ -81,12 +85,25 @@ let
|
||||
inherit defaultPackage packages;
|
||||
};
|
||||
|
||||
# only gets executed if package has electron dependency
|
||||
electron-rebuild = electron: ''
|
||||
# This is only executed for electron based packages.
|
||||
# Electron ships its own version of node, requiring a rebuild of native
|
||||
# extensions.
|
||||
# Theoretically this requires headers for the exact electron version in use,
|
||||
# but we use the headers from nixpkgs' electron instead which might have a
|
||||
# different minor version.
|
||||
# Alternatively the headers can be specified via `electronHeaders`.
|
||||
# Also a custom electron version can be specified via `electronPackage`
|
||||
electron-rebuild = ''
|
||||
# prepare node headers for electron
|
||||
ver="v${electron.version}"
|
||||
if [ -n "$electronPackage" ]; then
|
||||
export electronDist="$electronPackage/lib/electron"
|
||||
else
|
||||
export electronDist="$nodeModules/$packageName/node_modules/electron/dist"
|
||||
fi
|
||||
local ver
|
||||
ver="v$(cat $electronDist/version | tr -d '\n')"
|
||||
mkdir $TMP/$ver
|
||||
cp ${electron.headers} $TMP/$ver/node-$ver-headers.tar.gz
|
||||
cp $electronHeaders $TMP/$ver/node-$ver-headers.tar.gz
|
||||
|
||||
# calc checksums
|
||||
cd $TMP/$ver
|
||||
@ -97,13 +114,11 @@ let
|
||||
python -m http.server 45034 --directory $TMP &
|
||||
|
||||
# copy electron distribution
|
||||
cp -r ./node_modules/electron/dist $TMP/dist
|
||||
chmod -R +w $TMP/dist
|
||||
# mv $TMP/dist/electron $TMP/dist/electron-wrapper
|
||||
# mv $TMP/dist/.electron-wrapped $TMP/dist/electron
|
||||
cp -r $electronDist $TMP/electron
|
||||
chmod -R +w $TMP/electron
|
||||
|
||||
# configure electron toolchain
|
||||
${pkgs.jq}/bin/jq ".build.electronDist = \"$TMP/dist\"" package.json \
|
||||
${pkgs.jq}/bin/jq ".build.electronDist = \"$TMP/electron\"" package.json \
|
||||
| ${pkgs.moreutils}/bin/sponge package.json
|
||||
|
||||
${pkgs.jq}/bin/jq ".build.linux.target = \"dir\"" package.json \
|
||||
@ -122,10 +137,12 @@ let
|
||||
fi
|
||||
'';
|
||||
|
||||
electron-wrap = electron: ''
|
||||
# Only executed for electron based packages.
|
||||
# Creates an executable script under /bin starting the electron app
|
||||
electron-wrap = ''
|
||||
mkdir -p $out/bin
|
||||
makeWrapper \
|
||||
${electron}/bin/electron \
|
||||
$electronDist/electron \
|
||||
$out/bin/$(basename "$packageName") \
|
||||
--add-flags "$(realpath $electronAppDir)"
|
||||
'';
|
||||
@ -147,31 +164,35 @@ let
|
||||
(dep: lib.nameValuePair dep.name dep.version)
|
||||
deps));
|
||||
|
||||
electronPackage =
|
||||
let
|
||||
electronDep =
|
||||
lib.findFirst
|
||||
(dep: dep.name == "electron")
|
||||
null
|
||||
deps;
|
||||
|
||||
in
|
||||
if electronDep == null then
|
||||
electronDep =
|
||||
if ! isMainPackage name version then
|
||||
null
|
||||
else
|
||||
lib.findFirst
|
||||
(dep: dep.name == "electron")
|
||||
null
|
||||
else
|
||||
let
|
||||
electronVersionMajor =
|
||||
if electronDep == null then
|
||||
null
|
||||
else
|
||||
lib.versions.major electronDep.version;
|
||||
in
|
||||
pkgs."electron_${electronVersionMajor}";
|
||||
deps;
|
||||
|
||||
electronVersionMajor =
|
||||
lib.versions.major electronDep.version;
|
||||
|
||||
electronHeaders =
|
||||
if electronDep == null then
|
||||
null
|
||||
else
|
||||
pkgs."electron_${electronVersionMajor}".headers;
|
||||
|
||||
|
||||
pkg =
|
||||
produceDerivation name (stdenv.mkDerivation rec {
|
||||
|
||||
inherit dependenciesJson nodeDeps nodeSources version;
|
||||
inherit
|
||||
dependenciesJson
|
||||
electronHeaders
|
||||
nodeDeps
|
||||
nodeSources
|
||||
version
|
||||
;
|
||||
|
||||
packageName = name;
|
||||
|
||||
@ -182,9 +203,7 @@ let
|
||||
electronAppDir = ".";
|
||||
|
||||
# only run build on the main package
|
||||
runBuild =
|
||||
packageName == mainPackageName
|
||||
&& version == mainPackageVersion;
|
||||
runBuild = isMainPackage name version;
|
||||
|
||||
src = getSource name version;
|
||||
|
||||
@ -195,7 +214,7 @@ let
|
||||
# prevents running into ulimits
|
||||
passAsFile = [ "dependenciesJson" "nodeDeps" ];
|
||||
|
||||
preConfigurePhases = [ "d2nPatchPhase" ];
|
||||
preConfigurePhases = [ "d2nLoadFuncsPhase" "d2nPatchPhase" ];
|
||||
|
||||
# can be overridden to define alternative install command
|
||||
# (defaults to 'npm run postinstall')
|
||||
@ -205,9 +224,36 @@ let
|
||||
# (see comments below on d2nPatchPhase)
|
||||
fixPackage = "${./fix-package.py}";
|
||||
|
||||
# script to install (symlink or copy) dependencies.
|
||||
installDeps = "${./install-deps.py}";
|
||||
|
||||
# costs performance and doesn't seem beneficial in most scenarios
|
||||
dontStrip = true;
|
||||
|
||||
# declare some useful shell functions
|
||||
d2nLoadFuncsPhase = ''
|
||||
# function to resolve symlinks to copies
|
||||
symlinksToCopies() {
|
||||
local dir="$1"
|
||||
|
||||
echo "transforming symlinks to copies..."
|
||||
for f in $(find -L "$dir" -xtype l); do
|
||||
if [ -f $f ]; then
|
||||
continue
|
||||
fi
|
||||
echo "copying $f"
|
||||
chmod +wx $(dirname "$f")
|
||||
mv "$f" "$f.bak"
|
||||
mkdir "$f"
|
||||
if [ -n "$(ls -A "$f.bak/")" ]; then
|
||||
cp -r "$f.bak"/* "$f/"
|
||||
chmod -R +w $f
|
||||
fi
|
||||
rm "$f.bak"
|
||||
done
|
||||
}
|
||||
'';
|
||||
|
||||
# TODO: upstream fix to nixpkgs
|
||||
# example which requires this:
|
||||
# https://registry.npmjs.org/react-window-infinite-loader/-/react-window-infinite-loader-1.0.7.tgz
|
||||
@ -295,68 +341,27 @@ let
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# configure typescript
|
||||
if [ -f tsconfig.json ]; then
|
||||
${pkgs.jq}/bin/jq ".compilerOptions.preserveSymlinks = true" tsconfig.json \
|
||||
| ${pkgs.moreutils}/bin/sponge tsconfig.json
|
||||
fi
|
||||
'';
|
||||
|
||||
# - links all direct node dependencies into the node_modules directory
|
||||
# - installs dependencies into the node_modules directory
|
||||
# - adds executables of direct node module dependencies to PATH
|
||||
# - adds the current node module to NODE_PATH
|
||||
# - sets HOME=$TMPDIR, as this is required by some npm scripts
|
||||
# TODO: don't install dev dependencies. Load into NODE_PATH instead
|
||||
# TODO: move all linking to python script, as `ln` calls perform badly
|
||||
configurePhase = ''
|
||||
runHook preConfigure
|
||||
|
||||
# symlink dependency packages into node_modules
|
||||
for dep in $(cat $nodeDepsPath); do
|
||||
# add bin to PATH
|
||||
if [ -d "$dep/bin" ]; then
|
||||
export PATH="$PATH:$dep/bin"
|
||||
fi
|
||||
|
||||
if [ -e $dep/lib/node_modules ]; then
|
||||
for module in $(ls $dep/lib/node_modules); do
|
||||
if [[ $module == @* ]]; then
|
||||
for submodule in $(ls $dep/lib/node_modules/$module); do
|
||||
mkdir -p $nodeModules/$packageName/node_modules/$module
|
||||
echo "installing: $module/$submodule"
|
||||
ln -s $(realpath $dep/lib/node_modules/$module/$submodule) $nodeModules/$packageName/node_modules/$module/$submodule
|
||||
done
|
||||
else
|
||||
mkdir -p $nodeModules/$packageName/node_modules/
|
||||
echo "installing: $module"
|
||||
ln -s $(realpath $dep/lib/node_modules/$module) $nodeModules/$packageName/node_modules/$module
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# symlink sub dependencies as well as this imitates npm better
|
||||
python ${./symlink-deps.py}
|
||||
python $installDeps
|
||||
|
||||
# resolve symlinks to copies
|
||||
symlinksToCopies() {
|
||||
local dir="$1"
|
||||
|
||||
echo "transforming symlinks to copies..."
|
||||
for f in $(find -L "$dir" -xtype l); do
|
||||
if [ -f $f ]; then
|
||||
continue
|
||||
fi
|
||||
echo "copying $f"
|
||||
chmod +wx $(dirname "$f")
|
||||
mv "$f" "$f.bak"
|
||||
mkdir "$f"
|
||||
if [ -n "$(ls -A "$f.bak/")" ]; then
|
||||
cp -r "$f.bak"/* "$f/"
|
||||
chmod -R +w $f
|
||||
fi
|
||||
rm "$f.bak"
|
||||
done
|
||||
}
|
||||
|
||||
if [ "$installMethod" == "copy" ]; then
|
||||
symlinksToCopies .
|
||||
fi
|
||||
# add bin path entries collected by python script
|
||||
export PATH="$PATH:$(cat $TMP/ADD_BIN_PATH)"
|
||||
|
||||
# add dependencies to NODE_PATH
|
||||
export NODE_PATH="$NODE_PATH:$nodeModules/$packageName/node_modules"
|
||||
@ -372,8 +377,9 @@ let
|
||||
runHook preBuild
|
||||
|
||||
# execute electron-rebuild
|
||||
${lib.optionalString (electronPackage != null)
|
||||
(electron-rebuild electronPackage)}
|
||||
if [ -n "$electronHeaders" ]; then
|
||||
${electron-rebuild}
|
||||
fi
|
||||
|
||||
# execute install command
|
||||
if [ -n "$buildScript" ]; then
|
||||
@ -422,8 +428,10 @@ let
|
||||
fi
|
||||
|
||||
# wrap electron app
|
||||
${lib.optionalString (electronPackage != null)
|
||||
(electron-wrap electronPackage)}
|
||||
# execute electron-rebuild
|
||||
if [ -n "$electronHeaders" ]; then
|
||||
${electron-wrap}
|
||||
fi
|
||||
'';
|
||||
});
|
||||
in
|
||||
|
174
src/builders/nodejs/granular/install-deps.py
Normal file
174
src/builders/nodejs/granular/install-deps.py
Normal file
@ -0,0 +1,174 @@
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess as sp
|
||||
import sys
|
||||
|
||||
|
||||
out = os.environ.get('out')
|
||||
pname = os.environ.get('packageName')
|
||||
version = os.environ.get('version')
|
||||
root = f"{os.path.abspath('.')}/node_modules"
|
||||
package_json_cache = {}
|
||||
satisfaction_cache = {}
|
||||
|
||||
|
||||
with open(os.environ.get("nodeDepsPath")) as f:
|
||||
nodeDeps = f.read().split()
|
||||
|
||||
def get_package_json(path):
|
||||
if path not in package_json_cache:
|
||||
with open(f"{path}/package.json") as f:
|
||||
package_json_cache[path] = json.load(f)
|
||||
return package_json_cache[path]
|
||||
|
||||
def install_direct_dependencies():
|
||||
add_to_bin_path = []
|
||||
if not os.path.isdir(root):
|
||||
os.mkdir(root)
|
||||
with open(os.environ.get('nodeDepsPath')) as f:
|
||||
deps = f.read().split()
|
||||
for dep in deps:
|
||||
# check for bin directory
|
||||
if os.path.isdir(f"{dep}/bin"):
|
||||
add_to_bin_path.append(f"{dep}/bin")
|
||||
if os.path.isdir(f"{dep}/lib/node_modules"):
|
||||
for module in os.listdir(f"{dep}/lib/node_modules"):
|
||||
# ignore hidden directories
|
||||
if module[0] == ".":
|
||||
continue
|
||||
if module[0] == '@':
|
||||
for submodule in os.listdir(f"{dep}/lib/node_modules/{module}"):
|
||||
pathlib.Path(f"{root}/{module}").mkdir(exist_ok=True)
|
||||
print(f"installing: {module}/{submodule}")
|
||||
origin =\
|
||||
os.path.realpath(f"{dep}/lib/node_modules/{module}/{submodule}")
|
||||
os.symlink(origin, f"{root}/{module}/{submodule}")
|
||||
else:
|
||||
print(f"installing: {module}")
|
||||
origin = os.path.realpath(f"{dep}/lib/node_modules/{module}")
|
||||
os.symlink(origin, f"{root}/{module}")
|
||||
|
||||
return add_to_bin_path
|
||||
|
||||
|
||||
def collect_dependencies(root, depth):
|
||||
if not os.path.isdir(root):
|
||||
return []
|
||||
dirs = os.listdir(root)
|
||||
|
||||
currentDeps = []
|
||||
for d in dirs:
|
||||
if d.rpartition('/')[-1].startswith('@'):
|
||||
subdirs = os.listdir(f"{root}/{d}")
|
||||
for sd in subdirs:
|
||||
cur_dir = f"{root}/{d}/{sd}"
|
||||
currentDeps.append(f"{cur_dir}")
|
||||
else:
|
||||
cur_dir = f"{root}/{d}"
|
||||
currentDeps.append(cur_dir)
|
||||
|
||||
if depth == 0:
|
||||
return currentDeps
|
||||
else:
|
||||
depsOfDeps =\
|
||||
map(lambda dep: collect_dependencies(f"{dep}/node_modules", depth - 1), currentDeps)
|
||||
result = []
|
||||
for deps in depsOfDeps:
|
||||
result += deps
|
||||
return result
|
||||
|
||||
|
||||
def symlink_sub_dependencies():
|
||||
for dep in collect_dependencies(root, 1):
|
||||
# compute module path
|
||||
d1, d2 = dep.split('/')[-2:]
|
||||
if d1.startswith('@'):
|
||||
path = f"{root}/{d1}/{d2}"
|
||||
else:
|
||||
path = f"{root}/{d2}"
|
||||
|
||||
# check for collision
|
||||
if os.path.isdir(path):
|
||||
continue
|
||||
|
||||
# create parent dir
|
||||
pathlib.Path(os.path.dirname(path)).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# symlink dependency
|
||||
os.symlink(os.path.realpath(dep), path)
|
||||
|
||||
|
||||
# checks if dependency is already installed in the current or parent dir.
|
||||
def dependency_satisfied(root, pname, version):
|
||||
if (root, pname, version) in satisfaction_cache:
|
||||
return satisfaction_cache[(root, pname, version)]
|
||||
|
||||
if root == "/nix/store":
|
||||
return False
|
||||
|
||||
parent = os.path.dirname(root)
|
||||
|
||||
if os.path.isdir(f"{root}/{pname}"):
|
||||
package_json_file = f"{root}/{pname}/package.json"
|
||||
if os.path.isfile(package_json_file):
|
||||
if version == get_package_json(f"{root}/{pname}")['version']:
|
||||
satisfaction_cache[(root, pname, version)] = True
|
||||
return True
|
||||
|
||||
satisfaction_cache[(root, pname, version)] =\
|
||||
dependency_satisfied(parent, pname, version)
|
||||
|
||||
return satisfaction_cache[(root, pname, version)]
|
||||
|
||||
|
||||
# transforms symlinked dependencies into real copies
|
||||
def symlinks_to_copies(root):
|
||||
sp.run(f"chmod +wx {root}".split())
|
||||
for dep in collect_dependencies(root, 0):
|
||||
|
||||
# only handle symlinks to directories
|
||||
if not os.path.islink(dep) or os.path.isfile(dep):
|
||||
continue
|
||||
|
||||
version = get_package_json(dep)['version']
|
||||
d1, d2 = dep.split('/')[-2:]
|
||||
if d1[0] == '@':
|
||||
pname = f"{d1}/{d2}"
|
||||
sp.run(f"chmod +wx {root}/{d1}".split())
|
||||
else:
|
||||
pname = d2
|
||||
|
||||
if dependency_satisfied(os.path.dirname(root), pname, version):
|
||||
os.remove(dep)
|
||||
continue
|
||||
|
||||
print(f"copying {dep}")
|
||||
os.rename(dep, f"{dep}.bac")
|
||||
os.mkdir(dep)
|
||||
contents = os.listdir(f"{dep}.bac")
|
||||
if contents != []:
|
||||
for node in contents:
|
||||
if os.path.isdir(f"{dep}.bac/{node}"):
|
||||
shutil.copytree(f"{dep}.bac/{node}", f"{dep}/{node}", symlinks=True)
|
||||
if os.path.isdir(f"{dep}/node_modules"):
|
||||
symlinks_to_copies(f"{dep}/node_modules")
|
||||
else:
|
||||
shutil.copy(f"{dep}.bac/{node}", f"{dep}/{node}")
|
||||
os.remove(f"{dep}.bac")
|
||||
|
||||
|
||||
# install direct deps
|
||||
add_to_bin_path = install_direct_dependencies()
|
||||
|
||||
# dump bin paths
|
||||
with open(f"{os.environ.get('TMP')}/ADD_BIN_PATH", 'w') as f:
|
||||
f.write(':'.join(add_to_bin_path))
|
||||
|
||||
# symlink non-colliding deps
|
||||
symlink_sub_dependencies()
|
||||
|
||||
# symlinks to copies
|
||||
if os.environ.get('installMethod') == 'copy':
|
||||
symlinks_to_copies(root)
|
@ -1,69 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
|
||||
out = os.environ.get('out')
|
||||
pname = os.environ.get('packageName')
|
||||
version = os.environ.get('version')
|
||||
root = f"{out}/lib/node_modules/{pname}/node_modules"
|
||||
|
||||
if not os.path.isdir(root):
|
||||
exit()
|
||||
|
||||
|
||||
with open(os.environ.get("nodeDepsPath")) as f:
|
||||
nodeDeps = f.read().split()
|
||||
|
||||
def getDependencies(root, depth):
|
||||
if not os.path.isdir(root):
|
||||
return []
|
||||
dirs = os.listdir(root)
|
||||
|
||||
currentDeps = []
|
||||
for d in dirs:
|
||||
if d.rpartition('/')[-1].startswith('@'):
|
||||
subdirs = os.listdir(f"{root}/{d}")
|
||||
for sd in subdirs:
|
||||
cur_dir = f"{root}/{d}/{sd}"
|
||||
currentDeps.append(f"{cur_dir}")
|
||||
else:
|
||||
cur_dir = f"{root}/{d}"
|
||||
currentDeps.append(cur_dir)
|
||||
|
||||
if depth == 0:
|
||||
return currentDeps
|
||||
else:
|
||||
depsOfDeps =\
|
||||
map(lambda dep: getDependencies(f"{dep}/node_modules", depth - 1), currentDeps)
|
||||
result = []
|
||||
for deps in depsOfDeps:
|
||||
result += deps
|
||||
return result
|
||||
|
||||
deps = getDependencies(root, 1)
|
||||
|
||||
# symlink deps non-colliding deps
|
||||
for dep in deps:
|
||||
|
||||
# compute module path
|
||||
d1, d2 = dep.split('/')[-2:]
|
||||
if d1.startswith('@'):
|
||||
path = f"{root}/{d1}/{d2}"
|
||||
else:
|
||||
path = f"{root}/{d2}"
|
||||
|
||||
# check for collision
|
||||
if os.path.isdir(path):
|
||||
continue
|
||||
|
||||
# create parent dir
|
||||
pathlib.Path(os.path.dirname(path)).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# symlink dependency
|
||||
os.symlink(os.path.realpath(dep), path)
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user