jetbrains: switch builder to use extendMkDerivation pattern

This commit does not cause any rebuilds.
This commit is contained in:
Marco "Capypara" Köpcke
2026-02-03 19:10:56 +01:00
parent 41965737c1
commit f55d624a63
6 changed files with 254 additions and 253 deletions
@@ -1,57 +1,60 @@
# Darwin-specific base builder.
# TODO:
# This actually just ignores a lot of options passed to it... (e.g. buildInputs)
# - not entirely sure how this hasn't caused big problems yet.
{
lib,
stdenvNoCC,
undmg,
excludeDrvArgNames,
...
}:
{
meta,
pname,
product,
productShort,
src,
version,
passthru,
lib.extendMkDerivation {
inherit excludeDrvArgNames;
plugins ? [ ],
...
}:
constructDrv = stdenvNoCC.mkDerivation;
let
loname = lib.toLower productShort;
in
stdenvNoCC.mkDerivation {
inherit
pname
src
version
plugins
passthru
;
meta = meta // {
mainProgram = loname;
};
desktopName = product;
dontFixup = true;
installPhase = ''
runHook preInstall
APP_DIR="$out/Applications/${product}.app"
mkdir -p "$APP_DIR"
cp -Tr *.app "$APP_DIR"
mkdir -p "$out/bin"
cat << EOF > "$out/bin/${loname}"
#!${stdenvNoCC.shell}
open -na '$APP_DIR' --args "\$@"
EOF
chmod +x "$out/bin/${loname}"
runHook postInstall
'';
nativeBuildInputs = [ undmg ];
sourceRoot = ".";
extendDrvArgs =
finalAttrs:
{
product,
productShort ? product,
nativeBuildInputs ? [ ],
meta ? { },
...
}:
let
loname = lib.toLower productShort;
in
{
desktopName = product;
dontFixup = true;
plugins = [ ];
installPhase = ''
runHook preInstall
APP_DIR="$out/Applications/${product}.app"
mkdir -p "$APP_DIR"
cp -Tr *.app "$APP_DIR"
mkdir -p "$out/bin"
cat << EOF > "$out/bin/${loname}"
#!${stdenvNoCC.shell}
open -na '$APP_DIR' --args "\$@"
EOF
chmod +x "$out/bin/${loname}"
runHook postInstall
'';
nativeBuildInputs = nativeBuildInputs ++ [ undmg ];
sourceRoot = ".";
meta = meta // {
mainProgram = loname;
};
};
}
@@ -6,82 +6,64 @@
callPackage,
jdk,
fontconfig,
libGL,
libX11,
vmopts ? null,
forceWayland ? false,
}:
let
baseBuilder = if stdenv.hostPlatform.isDarwin then ./darwin.nix else ./linux.nix;
mkJetBrainsProductCore = callPackage baseBuilder { inherit vmopts; };
in
# Makes a JetBrains IDE
{
pname,
src,
version,
buildNumber,
wmClass,
product,
productShort ? product,
meta,
libdbm,
fsnotifier,
extraWrapperArgs ? [ ],
extraLdPath ? [ ],
buildInputs ? [ ],
passthru ? { },
}:
mkJetBrainsProductCore {
inherit
pname
extraLdPath
jdk
src
version
buildNumber
wmClass
product
productShort
libdbm
fsnotifier
;
buildInputs =
buildInputs
++ [ stdenv.cc.cc ]
++ lib.optionals stdenv.hostPlatform.isLinux [
fontconfig
libGL
libX11
lib.extendMkDerivation {
constructDrv = callPackage baseBuilder {
inherit vmopts jdk forceWayland;
# Args to not pass to mkDerivation in the base builders. Since both get the same args
# passed in, both have the same list of args to ignore, even if they don't both use
# all of them.
excludeDrvArgNames = [
"product"
"productShort"
"buildNumber"
"wmClass"
"libdbm"
"fsnotifier"
"extraLdPath"
"extraWrapperArgs"
];
};
extraWrapperArgs =
extraWrapperArgs
++ lib.optionals (stdenv.hostPlatform.isLinux && forceWayland) [
''--add-flags "\''${WAYLAND_DISPLAY:+-Dawt.toolkit.name=WLToolkit}"''
];
extendDrvArgs =
# NOTE: See linux.nix and darwin.nix for additional specific arguments
finalAttrs:
{
buildNumber,
product,
passthru = lib.recursiveUpdate passthru {
inherit
buildNumber
product
libdbm
fsnotifier
;
libdbm,
fsnotifier,
updateScript = ../updater/main.py;
meta ? { },
passthru ? { },
...
}:
{
passthru = passthru // {
inherit
buildNumber
product
libdbm
fsnotifier
;
tests = {
plugins = callPackage ../plugins/tests.nix { ideName = pname; };
updateScript = ../updater/main.py;
tests = {
plugins = callPackage ../plugins/tests.nix { ide = finalAttrs.finalPackage; };
};
};
meta = meta // {
teams = [ lib.teams.jetbrains ];
};
};
};
meta = meta // {
teams = [ lib.teams.jetbrains ];
};
}
@@ -18,163 +18,180 @@
e2fsprogs,
python3,
autoPatchelfHook,
vmopts ? null,
glibcLocales,
fontconfig,
libGL,
libX11,
jdk,
vmopts ? null,
forceWayland ? null,
excludeDrvArgNames,
}:
{
pname,
product,
productShort,
version,
src,
wmClass,
jdk,
meta,
passthru,
lib.extendMkDerivation {
inherit excludeDrvArgNames;
libdbm,
fsnotifier,
constructDrv = stdenv.mkDerivation;
extraLdPath ? [ ],
extraWrapperArgs ? [ ],
buildInputs ? [ ],
...
}@args:
extendDrvArgs =
finalAttrs:
{
pname,
product,
productShort ? product,
wmClass,
let
loName = lib.toLower productShort;
hiName = lib.toUpper productShort;
vmoptsName = loName + lib.optionalString stdenv.hostPlatform.is64bit "64" + ".vmoptions";
in
libdbm,
fsnotifier,
with stdenv;
lib.makeOverridable mkDerivation (
rec {
inherit
pname
version
src
buildInputs
passthru
;
meta = args.meta // {
mainProgram = pname;
};
extraLdPath ? [ ],
extraWrapperArgs ? [ ],
buildInputs ? [ ],
nativeBuildInputs ? [ ],
meta ? { },
postPatch ? "",
...
}:
desktopItem = makeDesktopItem {
name = pname;
exec = pname;
comment = lib.trim (lib.replaceString "\n" " " meta.longDescription);
desktopName = product;
genericName = meta.description;
categories = [ "Development" ];
icon = pname;
startupWMClass = wmClass;
};
let
loName = lib.toLower productShort;
hiName = lib.toUpper productShort;
vmoptsName = loName + lib.optionalString stdenv.hostPlatform.is64bit "64" + ".vmoptions";
finalExtraWrapperArgs =
extraWrapperArgs
++ lib.optionals forceWayland [
''--add-flags "\''${WAYLAND_DISPLAY:+-Dawt.toolkit.name=WLToolkit}"''
];
vmoptsIDE = if hiName == "WEBSTORM" then "WEBIDE" else hiName;
vmoptsFile = lib.optionalString (vmopts != null) (writeText vmoptsName vmopts);
desktopItem = makeDesktopItem {
name = finalAttrs.pname;
exec = finalAttrs.meta.mainProgram;
comment = lib.trim (lib.replaceString "\n" " " finalAttrs.meta.longDescription);
desktopName = product;
genericName = finalAttrs.meta.description;
categories = [ "Development" ];
icon = pname;
startupWMClass = wmClass;
};
nativeBuildInputs = [
makeWrapper
patchelf
unzip
autoPatchelfHook
];
vmoptsIDE = if hiName == "WEBSTORM" then "WEBIDE" else hiName;
vmoptsFile = lib.optionalString (vmopts != null) (writeText vmoptsName vmopts);
in
{
inherit desktopItem vmoptsIDE vmoptsFile;
postPatch = ''
rm -rf jbr
# When using the IDE as a remote backend using gateway, it expects the jbr directory to contain the jdk
ln -s ${jdk.home} jbr
buildInputs = buildInputs ++ [
stdenv.cc.cc
fontconfig
libGL
libX11
];
if [ -d "plugins/remote-dev-server" ]; then
patch -F3 -p1 < ${../patches/jetbrains-remote-dev.patch}
fi
nativeBuildInputs = nativeBuildInputs ++ [
makeWrapper
patchelf
unzip
autoPatchelfHook
];
vmopts_file=bin/linux/${vmoptsName}
if [[ ! -f $vmopts_file ]]; then
vmopts_file=bin/${vmoptsName}
if [[ ! -f $vmopts_file ]]; then
echo "ERROR: $vmopts_file not found"
exit 1
postPatch = ''
rm -rf jbr
# When using the IDE as a remote backend using gateway, it expects the jbr directory to contain the jdk
ln -s ${jdk.home} jbr
if [ -d "plugins/remote-dev-server" ]; then
patch -F3 -p1 < ${../patches/jetbrains-remote-dev.patch}
fi
fi
echo -Djna.library.path=${
lib.makeLibraryPath [
libsecret
e2fsprogs
libnotify
# Required for Help -> Collect Logs
# in at least rider and goland
udev
]
} >> $vmopts_file
'';
installPhase = ''
runHook preInstall
vmopts_file=bin/linux/${vmoptsName}
if [[ ! -f $vmopts_file ]]; then
vmopts_file=bin/${vmoptsName}
if [[ ! -f $vmopts_file ]]; then
echo "ERROR: $vmopts_file not found"
exit 1
fi
fi
echo -Djna.library.path=${
lib.makeLibraryPath [
libsecret
e2fsprogs
libnotify
# Required for Help -> Collect Logs
# in at least rider and goland
udev
]
} >> $vmopts_file
''
+ postPatch;
mkdir -p $out/{bin,$pname,share/pixmaps,share/icons/hicolor/scalable/apps}
cp -a . $out/$pname
[[ -f $out/$pname/bin/${loName}.png ]] && ln -s $out/$pname/bin/${loName}.png $out/share/pixmaps/${pname}.png
[[ -f $out/$pname/bin/${loName}.svg ]] && ln -s $out/$pname/bin/${loName}.svg $out/share/pixmaps/${pname}.svg \
&& ln -s $out/$pname/bin/${loName}.svg $out/share/icons/hicolor/scalable/apps/${pname}.svg
cp ${libdbm}/lib/libdbm.so $out/$pname/bin/libdbm.so
cp ${fsnotifier}/bin/fsnotifier $out/$pname/bin/fsnotifier
installPhase = ''
runHook preInstall
jdk=${jdk.home}
item=${desktopItem}
mkdir -p $out/{bin,$pname,share/pixmaps,share/icons/hicolor/scalable/apps}
cp -a . $out/$pname
[[ -f $out/$pname/bin/${loName}.png ]] && ln -s $out/$pname/bin/${loName}.png $out/share/pixmaps/${pname}.png
[[ -f $out/$pname/bin/${loName}.svg ]] && ln -s $out/$pname/bin/${loName}.svg $out/share/pixmaps/${pname}.svg \
&& ln -s $out/$pname/bin/${loName}.svg $out/share/icons/hicolor/scalable/apps/${pname}.svg
cp ${libdbm}/lib/libdbm.so $out/$pname/bin/libdbm.so
cp ${fsnotifier}/bin/fsnotifier $out/$pname/bin/fsnotifier
needsWrapping=()
jdk=${jdk.home}
item=${desktopItem}
if [ -f "$out/$pname/bin/${loName}" ]; then
needsWrapping+=("$out/$pname/bin/${loName}")
fi
if [ -f "$out/$pname/bin/${loName}.sh" ]; then
needsWrapping+=("$out/$pname/bin/${loName}.sh")
fi
needsWrapping=()
for launcher in "''${needsWrapping[@]}"
do
wrapProgram "$launcher" \
--prefix PATH : "${
lib.makeBinPath [
jdk
coreutils
gnugrep
which
git
]
}" \
--suffix PATH : "${lib.makeBinPath [ python3 ]}" \
--prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath extraLdPath}" \
${lib.concatStringsSep " " extraWrapperArgs} \
--set-default JDK_HOME "$jdk" \
--set-default ANDROID_JAVA_HOME "$jdk" \
--set-default JAVA_HOME "$jdk" \
--set-default JETBRAINS_CLIENT_JDK "$jdk" \
--set-default ${hiName}_JDK "$jdk" \
--set-default LOCALE_ARCHIVE "${glibcLocales}/lib/locale/locale-archive" \
--set-default ${vmoptsIDE}_VM_OPTIONS ${vmoptsFile}
done
if [ -f "$out/$pname/bin/${loName}" ]; then
needsWrapping+=("$out/$pname/bin/${loName}")
fi
if [ -f "$out/$pname/bin/${loName}.sh" ]; then
needsWrapping+=("$out/$pname/bin/${loName}.sh")
fi
launcher="$out/$pname/bin/${loName}"
if [ ! -e "$launcher" ]; then
launcher+=.sh
fi
for launcher in "''${needsWrapping[@]}"
do
wrapProgram "$launcher" \
--prefix PATH : "${
lib.makeBinPath [
jdk
coreutils
gnugrep
which
git
]
}" \
--suffix PATH : "${lib.makeBinPath [ python3 ]}" \
--prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath extraLdPath}" \
${lib.concatStringsSep " " finalExtraWrapperArgs} \
--set-default JDK_HOME "$jdk" \
--set-default ANDROID_JAVA_HOME "$jdk" \
--set-default JAVA_HOME "$jdk" \
--set-default JETBRAINS_CLIENT_JDK "$jdk" \
--set-default ${hiName}_JDK "$jdk" \
--set-default LOCALE_ARCHIVE "${glibcLocales}/lib/locale/locale-archive" \
--set-default ${vmoptsIDE}_VM_OPTIONS ${vmoptsFile}
done
ln -s "$launcher" $out/bin/$pname
rm -rf $out/$pname/plugins/remote-dev-server/selfcontained/
echo -e '#!/usr/bin/env bash\n'"$out/$pname/bin/remote-dev-server.sh"' "$@"' > $out/$pname/bin/remote-dev-server-wrapped.sh
chmod +x $out/$pname/bin/remote-dev-server-wrapped.sh
ln -s "$out/$pname/bin/remote-dev-server-wrapped.sh" $out/bin/$pname-remote-dev-server
ln -s "$item/share/applications" $out/share
launcher="$out/$pname/bin/${loName}"
if [ ! -e "$launcher" ]; then
launcher+=.sh
fi
runHook postInstall
'';
}
// lib.optionalAttrs (!(meta.license.free or true)) {
preferLocalBuild = true;
}
)
ln -s "$launcher" $out/bin/$pname
rm -rf $out/$pname/plugins/remote-dev-server/selfcontained/
echo -e '#!/usr/bin/env bash\n'"$out/$pname/bin/remote-dev-server.sh"' "$@"' > $out/$pname/bin/remote-dev-server-wrapped.sh
chmod +x $out/$pname/bin/remote-dev-server-wrapped.sh
ln -s "$out/$pname/bin/remote-dev-server-wrapped.sh" $out/bin/$pname-remote-dev-server
ln -s "$item/share/applications" $out/share
runHook postInstall
'';
meta = meta // {
mainProgram = pname;
};
}
// lib.optionalAttrs (!(meta.license.free or true)) {
preferLocalBuild = true;
};
}
@@ -47,7 +47,9 @@ mkJetBrainsProduct {
src = fetchurl (urls.${system} or (throw "Unsupported system: ${system}"));
buildInputs = [
# NOTE: This `lib.optionals` is only here because the old Darwin builder ignored `buildInputs`.
# DataSpell may need these, even on Darwin!
buildInputs = lib.optionals stdenv.hostPlatform.isLinux [
libgcc
(runCommand "libR" { } ''
mkdir -p $out/lib
@@ -6,12 +6,12 @@
fetchzip,
fetchurl,
# If not set, all IDEs are tested.
ideName ? null,
ide ? null,
}:
let
ides =
if ideName == null then
if ide == null then
with jetbrains;
[
clion
@@ -31,7 +31,7 @@ let
webstorm
]
else
[ (jetbrains.${ideName}) ];
[ ide ];
in
{
# Check to see if the process for adding plugins is breaking anything, instead of the plugins themselves
@@ -56,9 +56,6 @@ Any comments or other manual changes between these markers will be removed when
- Add it to `default.nix`
### TODO:
- Switch `mkJetbrainsProduct` to use `lib.extendMkDerivation`, see also:
- https://github.com/NixOS/nixpkgs/pull/475183#discussion_r2655305961
- https://github.com/NixOS/nixpkgs/pull/475183#discussion_r2655348886
- move PyCharm overrides to a common place outside of `default.nix`
- package `patchSharedLibs` from `default.nix` as a hook
- cleanup this TODO list, especially the following points, which have been here since 2023