Good you’ve mentioned you are using NixOS (because my method won’t work with plain Nix)
My recipe for this is to install extensions imperatively. In those rare cases when it is not possible (cpptools requires some native libs, lucky it is packaged in Nixpkgs), use this module:
vscode.nix
{ config, pkgs, lib, ... }: {
options = {
vscode.extensions = lib.mkOption { default = []; };
vscode.user = lib.mkOption { }; # <- Must be supplied
vscode.homeDir = lib.mkOption { }; # <- Must be supplied
nixpkgs.latestPackages = lib.mkOption { default = []; };
};
config = {
###
# DIRTY HACK
# This will fetch latest packages on each rebuild, whatever channel you are at
nixpkgs.overlays = [
(self: super:
let latestPkgs = import (fetchTarball https://github.com/nixos/nixpkgs-channels/archive/nixpkgs-unstable.tar.gz) {
config.allowUnfree = true;
};
in lib.genAttrs config.nixpkgs.latestPackages (pkg: latestPkgs."${pkg}")
)
];
# END DIRTY HACK
###
environment.systemPackages = [ pkgs.vscode ];
system.activationScripts.fix-vscode-extensions = {
text = ''
EXT_DIR=${config.vscode.homeDir}/.vscode/extensions
mkdir -p $EXT_DIR
chown ${config.vscode.user}:users $EXT_DIR
for x in ${lib.concatMapStringsSep " " toString config.vscode.extensions}; do
ln -sf $x/share/vscode/extensions/* $EXT_DIR/
done
chown -R ${config.vscode.user}:users $EXT_DIR
'';
deps = [];
};
};
}
Then in configuration.nix
you add lines:
imports = [
...
./vscode.nix
];
vscode.user = "danbst";
vscode.homeDir = "/home/danbst";
vscode.extensions = with pkgs.vscode-extensions; [
ms-vscode.cpptools
];
nixpkgs.latestPackages = [
"vscode"
"vscode-extensions"
];
And rebuild. What it does:
- fetches latest
nixpkgs-unstable
channel on each rebuild - uses vscode and extensions from that channel, so up-to-date ASAP
- links
cpptools
directly into~/.vscode/extensions
, which fools VScode to think it actually installed this ext