buildVscode
pkgs.buildVscode
Functor
Docs pulled from | This Revision | 3 days ago
Contribute
Enhance the ecosystem with your expertise! Contribute to fill the gaps in documentation. Your input can make a difference.
Noogle detected
This is a Functor
Learn about functors
Implementation
The following is the current implementation of this function.
{
# Attributes inherit from specific versions
version,
vscodeVersion ? version,
src,
meta,
sourceRoot,
commandLineArgs,
executableName,
longName,
shortName,
pname,
libraryName ? "vscode",
iconName ? "vs${executableName}",
updateScript,
dontFixup ? false,
rev ? null,
vscodeServer ? null,
sourceExecutableName ? executableName,
useVSCodeRipgrep ? false,
hasVsceSign ? false,
patchVSCodePath ? true,
# Populate passthru.tests
tests,
extraNativeBuildInputs ? [ ],
# Customize FHS environment
# Function that takes default buildFHSEnv arguments and returns modified arguments
customizeFHSEnv ? args: args,
}:
stdenv.mkDerivation (
finalAttrs:
let
# Vscode and variants allow for users to download and use extensions
# which often include the usage of pre-built binaries.
# This has been an on-going painpoint for many users, as
# a full extension update cycle has to be done through nixpkgs
# in order to create or update extensions.
# See: #83288 #91179 #73810 #41189
#
# buildFHSEnv allows for users to use the existing vscode
# extension tooling without significant pain.
fhs =
{
additionalPkgs ? pkgs: [ ],
}:
let
defaultArgs = {
# also determines the name of the wrapped command
pname = executableName;
inherit version;
# additional libraries which are commonly needed for extensions
targetPkgs =
pkgs:
(with pkgs; [
# ld-linux-x86-64-linux.so.2 and others
glibc
# dotnet
curl
icu
libunwind
libuuid
lttng-ust
openssl
zlib
# mono
krb5
# Needed for headless browser-in-vscode based plugins such as
# anything based on Puppeteer https://pptr.dev .
# e.g. Roo Code
glib
nspr
nss
dbus
at-spi2-atk
cups
expat
libxkbcommon
libx11
libxcomposite
libxdamage
libxcb
libxext
libxfixes
libxrandr
cairo
pango
alsa-lib
libgbm
udev
libudev0-shim
])
++ additionalPkgs pkgs;
extraBwrapArgs = [
"--bind-try /etc/nixos/ /etc/nixos/"
"--ro-bind-try /etc/xdg/ /etc/xdg/"
];
# symlink shared assets, including icons and desktop entries
extraInstallCommands = ''
ln -s "${finalAttrs.finalPackage}/share" "$out/"
'';
runScript = "${finalAttrs.finalPackage}/bin/${executableName}";
# vscode likes to kill the parent so that the
# gui application isn't attached to the terminal session
dieWithParent = false;
passthru = {
inherit executableName;
inherit (finalAttrs.finalPackage) pname version; # for home-manager module
};
meta = meta // {
description = "Wrapped variant of ${pname} which launches in a FHS compatible environment, should allow for easy usage of extensions without nix-specific modifications";
};
};
customizedArgs = customizeFHSEnv defaultArgs;
in
buildFHSEnv customizedArgs;
in
{
inherit
pname
version
src
sourceRoot
dontFixup
;
passthru = {
inherit
executableName
longName
tests
updateScript
vscodeVersion
;
fhs = fhs { };
fhsWithPackages = f: fhs { additionalPkgs = f; };
}
// lib.optionalAttrs (vscodeServer != null) {
inherit rev vscodeServer;
};
desktopItems = [
(makeDesktopItem {
name = executableName;
desktopName = longName;
comment = "Code Editing. Redefined.";
genericName = "Text Editor";
exec = "${executableName} %F";
icon = iconName;
startupNotify = true;
startupWMClass = shortName;
categories = [
"Utility"
"TextEditor"
"Development"
"IDE"
];
keywords = [ "vscode" ];
actions.new-empty-window = {
name = "New Empty Window";
exec = "${executableName} --new-window %F";
icon = iconName;
};
})
(makeDesktopItem {
name = executableName + "-url-handler";
desktopName = longName + " - URL Handler";
comment = "Code Editing. Redefined.";
genericName = "Text Editor";
exec = executableName + " --open-url %U";
icon = iconName;
startupNotify = true;
categories = [
"Utility"
"TextEditor"
"Development"
"IDE"
];
mimeTypes = [ "x-scheme-handler/${iconName}" ];
keywords = [ "vscode" ];
noDisplay = true;
})
];
buildInputs = [
libsecret
]
++ lib.optionals (!stdenv.hostPlatform.isDarwin) [
alsa-lib
at-spi2-atk
libgbm
nss
nspr
systemdLibs
webkitgtk_4_1
libxkbfile
];
runtimeDependencies = lib.optionals stdenv.hostPlatform.isLinux [
systemdLibs
fontconfig.lib
libdbusmenu
wayland
libsecret
];
nativeBuildInputs = [
unzip
imagemagick
]
++ extraNativeBuildInputs
++ lib.optionals stdenv.hostPlatform.isLinux [
autoPatchelfHook
asar
copyDesktopItems
jq
# override doesn't preserve splicing https://github.com/NixOS/nixpkgs/issues/132651
# Has to use `makeShellWrapper` from `buildPackages` even though `makeShellWrapper` from the inputs is spliced because `propagatedBuildInputs` would pick the wrong one because of a different offset.
(buildPackages.wrapGAppsHook3.override { makeWrapper = buildPackages.makeShellWrapper; })
];
# autoPatchelfHook cannot index libwebkit2gtk-4.1.so because pyelftools
# fails to parse it (ELFError: String Table not found). Ignore the
# missing dep and add the library path via appendRunpaths so it is still
# available at runtime for libmsalruntime.so (Microsoft Authentication).
autoPatchelfIgnoreMissingDeps = lib.optionals stdenv.hostPlatform.isLinux [
"libwebkit2gtk-4.1.so.0"
];
appendRunpaths = lib.optionals stdenv.hostPlatform.isLinux [
"${webkitgtk_4_1}/lib"
];
dontBuild = true;
dontConfigure = true;
noDumpEnvVars = true;
stripExclude = lib.optional hasVsceSign [
# vsce-sign is a single executable application built with Node.js, and it becomes non-functional if stripped
"lib/vscode/resources/app/node_modules/@vscode/vsce-sign/bin/vsce-sign"
];
installPhase = ''
runHook preInstall
''
+ (
if stdenv.hostPlatform.isDarwin then
''
mkdir -p "$out/Applications/${longName}.app" "$out/bin"
cp -r ./* "$out/Applications/${longName}.app"
ln -s "$out/Applications/${longName}.app/Contents/Resources/app/bin/${sourceExecutableName}" "$out/bin/${executableName}"
''
else
(
''
mkdir -p "$out/lib/${libraryName}" "$out/bin"
cp -r ./* "$out/lib/${libraryName}"
ln -s "$out/lib/${libraryName}/bin/${sourceExecutableName}" "$out/bin/${executableName}"
''
# These are named vscode.png, vscode-insiders.png, etc to match the name in upstream *.deb packages.
+ ''
mkdir -p "$out/share/pixmaps"
icon_file="$out/lib/${libraryName}/resources/app/resources/linux/code.png"
cp "$icon_file" "$out/share/pixmaps/${iconName}.png"
# Dynamically determine size of icon and place in appropriate directory
size=$(identify -format "%wx%h" "$icon_file")
mkdir -p "$out/share/icons/hicolor/$size/apps"
cp "$icon_file" "$out/share/icons/hicolor/$size/apps/${iconName}.png"
''
)
# Override the previously determined VSCODE_PATH with the one we know to be correct
+ (lib.optionalString patchVSCodePath ''
sed -i "/ELECTRON=/iVSCODE_PATH='$out/lib/${libraryName}'" "$out/bin/${executableName}"
grep -q "VSCODE_PATH='$out/lib/${libraryName}'" "$out/bin/${executableName}" # check if sed succeeded
'')
# Remove native encryption code, as it derives the key from the executable path which does not work for us.
# The credentials should be stored in a secure keychain already, so the benefit of this is questionable
# in the first place.
+ ''
rm -rf $out/lib/${libraryName}/resources/app/node_modules/vscode-encrypt
''
)
+ ''
runHook postInstall
'';
preFixup = ''
gappsWrapperArgs+=(
${
# we cannot use runtimeDependencies otherwise libdbusmenu do not work on kde
lib.optionalString stdenv.hostPlatform.isLinux
"--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ libdbusmenu ]}"
}
--prefix PATH : ${
lib.makeBinPath (
[
# for moving files to trash
glib
# for launcher and bundled helper scripts
gawk
gnugrep
gnused
coreutils
which
]
# provides `getconf` for ps-fallback script that only runs on Linux
# https://github.com/microsoft/vscode/blob/97c807618b413805fde466739ba14f77a1f12307/src/vs/base/node/ps.sh#L2
# https://github.com/microsoft/vscode/blob/97c807618b413805fde466739ba14f77a1f12307/src/vs/base/node/ps.ts#L203-L217
++ lib.optional stdenv.hostPlatform.isLinux getconf
)
}
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true --wayland-text-input-version=3}}"
--add-flags ${lib.escapeShellArg commandLineArgs}
)
'';
# See https://github.com/NixOS/nixpkgs/issues/49643#issuecomment-873853897
# linux only because of https://github.com/NixOS/nixpkgs/issues/138729
postPatch =
lib.optionalString stdenv.hostPlatform.isLinux (
# disable update checks
''
tmpProductJson="$(mktemp)"
jq 'del(.updateUrl, .backupUpdateUrl)' resources/app/product.json > "$tmpProductJson"
mv "$tmpProductJson" resources/app/product.json
''
# this is a fix for "save as root" functionality
+ ''
packed="resources/app/node_modules.asar"
unpacked="resources/app/node_modules"
asar extract "$packed" "$unpacked"
substituteInPlace $unpacked/@vscode/sudo-prompt/index.js \
--replace-fail "/usr/bin/pkexec" "/run/wrappers/bin/pkexec" \
--replace-fail "/bin/bash" "${bash}/bin/bash"
rm -rf "$packed"
''
# without this symlink loading JsChardet, the library that is used for auto encoding detection when files.autoGuessEncoding is true,
# fails to load with: electron/js2c/renderer_init: Error: Cannot find module 'jschardet'
# and the window immediately closes which renders VSCode unusable
# see https://github.com/NixOS/nixpkgs/issues/152939 for full log
+ ''
ln -rs "$unpacked" "$packed"
''
)
+ (
let
vscodeRipgrep =
if stdenv.hostPlatform.isDarwin then
if lib.versionAtLeast vscodeVersion "1.94.0" then
"Contents/Resources/app/node_modules/@vscode/ripgrep/bin/rg"
else
"Contents/Resources/app/node_modules.asar.unpacked/@vscode/ripgrep/bin/rg"
else
"resources/app/node_modules/@vscode/ripgrep/bin/rg";
in
if !useVSCodeRipgrep then
''
rm ${vscodeRipgrep}
ln -s ${ripgrep}/bin/rg ${vscodeRipgrep}
''
else
''
chmod +x ${vscodeRipgrep}
''
);
postFixup = lib.optionalString stdenv.hostPlatform.isLinux (
''
patchelf \
--add-needed ${libglvnd}/lib/libGLESv2.so.2 \
--add-needed ${libglvnd}/lib/libGL.so.1 \
--add-needed ${libglvnd}/lib/libEGL.so.1 \
$out/lib/${libraryName}/${executableName}
''
+ (lib.optionalString hasVsceSign ''
patchelf \
--add-needed ${lib.getLib openssl}/lib/libssl.so \
$out/lib/vscode/resources/app/node_modules/@vscode/vsce-sign/bin/vsce-sign
'')
);
inherit meta;
}
)