feat: use devshell for rust devshells (#302)

This commit is contained in:
Yusuf Bera Ertan 2022-09-20 22:25:09 +03:00 committed by GitHub
parent 0f3b6c5dd1
commit 0503a1272d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 154 additions and 45 deletions

View File

@ -108,6 +108,22 @@
"pkgs/installCargoArtifactsHook.sh"
"LICENSE"
];
devshell = [
"modules/back-compat.nix"
"modules/commands.nix"
"modules/default.nix"
"modules/devshell.nix"
"modules/env.nix"
"modules/modules.nix"
"modules/modules-docs.nix"
"nix/ansi.nix"
"nix/mkNakedShell.nix"
"nix/source.nix"
"nix/strOrPackage.nix"
"nix/writeDefaultShellScript.nix"
"extra/language/c.nix"
"LICENSE"
];
};
# create a directory containing the files listed in externalPaths

View File

@ -121,6 +121,10 @@ in let
subsystems = callPackageDream ./subsystems {};
externals = {
devshell = {
makeShell = import "${externalSources.devshell}/modules" pkgs;
imports.c = "${externalSources.devshell}/extra/language/c.nix";
};
crane = let
importLibFile = name: import "${externalSources.crane}/lib/${name}.nix";

View File

@ -5,6 +5,7 @@
lib,
dlib,
pkgs,
callPackageDream,
...
} @ topArgs: {
subsystemAttrs,
@ -48,9 +49,10 @@
cargoTestFlags = cargoBuildFlags;
cargoVendorDir = "../nix-vendor";
dream2nixVendorDir = vendoring.vendoredDependencies;
postUnpack = ''
${vendoring.copyVendorDir "./nix-vendor"}
${vendoring.copyVendorDir "$dream2nixVendorDir" "./nix-vendor"}
export CARGO_HOME=$(pwd)/.cargo_home
'';
@ -66,16 +68,7 @@
});
mkShellForPkg = pkg:
pkg.overrideAttrs (old: {
buildInputs =
(old.buildInputs or [])
++ (
with pkg.passthru.rustToolchain; [
cargo
rustc
]
);
});
callPackageDream ../devshell.nix {drv = pkg;};
allPackages =
l.mapAttrs

View File

@ -4,6 +4,7 @@
lib,
pkgs,
externals,
callPackageDream,
...
} @ topArgs: {
subsystemAttrs,
@ -83,8 +84,9 @@
pnameSuffix = depsNameSuffix;
# Make sure cargo only checks the package we want
cargoCheckCommand = "cargo check --release --package ${pname}";
dream2nixVendorDir = vendoring.vendoredDependencies;
preUnpack = ''
${vendoring.copyVendorDir "$cargoVendorDir"}
${vendoring.copyVendorDir "$dream2nixVendorDir" "$cargoVendorDir"}
'';
# move the vendored dependencies folder to $out for main derivation to use
postInstall = ''
@ -103,7 +105,7 @@
cargoArtifacts = deps;
# link the vendor dir we used earlier to the correct place
preUnpack = ''
ln -sf ${deps}/nix-vendor $cargoVendorDir
${vendoring.copyVendorDir "$cargoArtifacts/nix-vendor" "$cargoVendorDir"}
'';
# write our cargo lock
# note: we don't do this in buildDepsOnly since
@ -123,38 +125,11 @@
# dependencies derivation. this could cause confusion for users.
mkShellForPkg = pkg: let
pkgDeps = pkg.passthru.dependencies;
depsShell = callPackageDream ../devshell.nix {drv = pkgDeps;};
mainShell = callPackageDream ../devshell.nix {drv = pkg;};
shell = depsShell.combineWith mainShell;
in
pkg.overrideAttrs (old: {
# we have to set these to empty because crane uses the phases
# to compile & test. buildRustPackage uses hooks instead so that's
# why build-rust-package doesn't need to do this.
buildPhase = "";
checkPhase = "";
# we have to have some output, so we just record the build inputs
# to a file (like mkShell does). this makes the derivation buildable.
# see https://github.com/NixOS/nixpkgs/pull/153194.
installPhase = "echo >> $out && export >> $out";
# set cargo artifacts to empty string so that dependencies
# derivation doesn't get built when entering devshell.
cargoArtifacts = "";
# merge build inputs from main drv and dependencies drv.
buildInputs = l.unique (
(old.buildInputs or [])
++ (pkgDeps.buildInputs or [])
++ [
(
pkg.passthru.rustToolchain.cargoHostTarget
or pkg.passthru.rustToolchain.cargo
)
]
);
nativeBuildInputs = l.unique (
(old.nativeBuildInputs or [])
++ (pkgDeps.nativeBuildInputs or [])
);
});
shell;
allPackages =
l.mapAttrs

View File

@ -0,0 +1,121 @@
{
# args
drv,
# d2n
externals,
# nixpkgs
lib,
stdenv,
libiconv,
...
}: let
l = lib // builtins;
# function to merge two devshells
mergeShellConfig = base: other: let
c = base.config;
oc = other.config;
i = base.imports;
oi = other.imports;
hasCConfig = config: (config ? language) && (config.language ? c);
in {
config =
c
// oc
// {
packages = l.unique (c.packages ++ oc.packages);
commands = l.unique (c.commands ++ oc.commands);
env = l.unique (c.env ++ oc.env);
}
// l.optionalAttrs (hasCConfig c || hasCConfig oc) {
language.c = let
cConf = c.language.c;
ocConf = oc.language.c;
in {
compiler = ocConf.compiler or cConf.compiler;
libraries =
l.unique ((cConf.libraries or []) ++ (ocConf.libraries or []));
includes =
l.unique ((cConf.includes or []) ++ (ocConf.includes or []));
};
};
imports = l.unique (i ++ oi);
};
# creates a shell from a config
mkShell = config: let
shell = (externals.devshell.makeShell {configuration = config;}).shell;
in
shell
// {
passthru.config = config;
combineWith = other:
mkShell (mergeShellConfig config other.passthru.config);
};
# convenience utils for converting a nix attribute to a shell env
# TODO: we could probably replace this with something from nixpkgs?
toStr = v:
if l.isBool v
then l.boolToString v
else l.toString v;
toShellEnv = v:
if l.isList v
then "( ${l.concatStringsSep " " (l.map (v: ''"${toStr v}"'') v)} )"
else l.toString v;
# illegal env names to be removed and not be added to the devshell
illegalEnvNames = [
"all"
"args"
"drvPath"
"outPath"
"stdenv"
"cargoArtifacts"
"dream2nixVendorDir"
"cargoVendorDir"
];
isIllegalEnv = name: l.any (oname: name == oname) illegalEnvNames;
inputs = (drv.buildInputs or []) ++ (drv.nativeBuildInputs or []);
rustToolchain = drv.passthru.rustToolchain;
# the config we will use
conf = {
config =
{
packages = inputs;
commands = [
{
package = rustToolchain.cargoHostTarget or rustToolchain.cargo;
name = "cargo";
category = "rust";
help = "Rust build tool";
}
];
env =
# filter out attrsets, functions and illegal environment vars
l.filter
(env: (env != null) && (! isIllegalEnv env.name))
(
l.mapAttrsToList
(
n: v:
if ! (l.isAttrs v || l.isFunction v)
then {
name = n;
value = toShellEnv v;
}
else null
)
drv
);
}
# only add c stuff *if* the stdenv has a c compiler
# if the user wants to use stdenvNoCC this allows them to do it easily
// l.optionalAttrs (drv.stdenv ? cc) {
language.c = {
compiler = drv.stdenv.cc;
libraries = inputs ++ (lib.optional stdenv.isDarwin libiconv);
includes = inputs;
};
};
imports = [externals.devshell.imports.c];
};
in
mkShell conf

View File

@ -98,5 +98,5 @@ in rec {
# All dependencies in the Cargo.lock file, vendored
vendoredDependencies = vendorDependencies allDependencies;
copyVendorDir = path: ''cp -rs --no-preserve=mode,ownership ${vendoredDependencies} ${path}'';
copyVendorDir = from: to: ''cp -rs --no-preserve=mode,ownership ${from} ${to}'';
}