Using Derivations
mkShell
Use this attribute(function?) to compose reproducible development shells via the devShells
attribute. As discussed in Using Nix Flakes, it is particularly handy when used in combination with direnv.
inputsFrom
Takes the outputs from another derivation within the Flake (typically a package derivation), and integrates them into the current derivation. This is a good way to abide by the DRY principle.
For example, the mkShell
derivation below will have cmake, gcc12, and pkg-config in its environment.
devShells.default = pkgs.mkShell {
inputsFrom = [self.packages.${system}.default ];
};
packages.default = pkgs.stdenv.mkDerivation {
name = "your-package";
src = ./.;
buildInputs = with pkgs; [
cmake
gcc12
pkg-config
];
};
devShells.default = pkgs.mkShell {
inputsFrom = [self.packages.${system}.default ];
};
packages.default = pkgs.stdenv.mkDerivation {
name = "your-package";
src = ./.;
buildInputs = with pkgs; [
cmake
gcc12
pkg-config
];
};
shellHook
Runs the shell code prior to initializing the environment. For example, the following hook prints the version of NodeJS for the current environment.
shellHook = ''
echo "node ${pkgs.nodejs}/bin/node --version"
''
shellHook = ''
echo "node ${pkgs.nodejs}/bin/node --version"
''
buildInputs
Adds build-related dependencies and inputs to your derivation
For example, the mkShell
derivation below will have docker and docker-compose in its environment.
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShells.default = pkgs.mkShell {
buildInputs = [
pkgs.docker
pkgs.docker-compose
];
};
}
);
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShells.default = pkgs.mkShell {
buildInputs = [
pkgs.docker
pkgs.docker-compose
];
};
}
);
stdenv.mkDerivation
is a key to understanding how to compose derivations in a flake.nix file.
- Use
buildInputs = [ pkgs.foo pkgs.bar ]
to specify the dependencies you want in your environment. - Use
nativeBuildInputs
for packages that would otherwise be available on the base system, but aren't required at runtime, e.g., cmake, gcc, clang, pkg-config, etc - Use
propogatedBuildInputs
for dependencies that you need to propogate to anything using the Flake.