Skip to content

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.

nix
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.

nix
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.