Is it possible to merge one flake's devShell into another flake's devShell?

I have made a bunch of flakes that are useful for solana development.

❯ ls
cargo-build-bpf  flake.lock  flake.nix  solana-bpf-tools  solana-cli

Here’s what the toplevel flake.nix looks like:

{
  description = "Solana";
  inputs = {
    solana-bpf-tools.url = "path:./solana-bpf-tools";
    solana-cli.url = "path:./solana-cli";
    cargo-build-bpf.url = "path:./cargo-build-bpf";
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  outputs = inputs: 
  {
    devShells.x86_64-linux.default = with import inputs.nixpkgs { 
      system = "x86_64-linux";
    }; mkShell {
      BPF_SDK_PATH = "${inputs.cargo-build-bpf.packages.x86_64-linux.default}";
      buildInputs = [
        inputs.cargo-build-bpf.packages.x86_64-linux.default
        inputs.solana-cli.packages.x86_64-linux.default
        (hiPrio inputs.cargo-build-bpf.packages.x86_64-linux.default)
      ];
    };
  };
}

I want to somehow include the above flake.nix file in my projects’ flake.nix to automatically get the same devShell configuration - the buildInputs and the BPF_SDK env var.

I tried doing:

{
  # myproject/flake.nix
  
  inputs = { solana.url = "path:./solana" };
  outputs = inputs: {
     devShells.x86_64-linux.default = {
       buildInputs = [
         inputs.solana.devShells.x86_64-linux.default
       ];
     };
  };
}

But the stuff that are available in the $PATH of solana's devShell did not become available in the project’s devShell.

Is it possible to do this in Nix?

1 Like

Unless you create a shell for cross compilation, you shouldn’t use buildInputs directly. Instead prefer packages.

Also “combining” two shells should work using the inputsFrom argument.

https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell

4 Likes

Could you elaborate this a little bit more?
Do you mean I shouldn’t put the devShell of another flake in the buildInputs of this flake’s devShell?
Or do you mean I should never use buildInputs in general?

You shouldn’t use the buildInputs argument in general, but packages instead.

And for composition inputsFrom would be correct, as in the example from the posted link.

1 Like

Here’s solana-flake/flake.nix:

{
  description = "Solana";
  inputs = {
    solana-bpf-tools.url = "path:./solana-bpf-tools";
    solana-cli.url = "path:./solana-cli";
    cargo-build-bpf.url = "path:./cargo-build-bpf";
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  outputs = inputs: 
  {
    devShells.x86_64-linux.default = with import inputs.nixpkgs { 
      system = "x86_64-linux";
    }; mkShellNoCC {
      BPF_SDK_PATH = "${inputs.cargo-build-bpf.packages.x86_64-linux.default}";
      packages = [
        inputs.cargo-build-bpf.packages.x86_64-linux.default
        inputs.solana-cli.packages.x86_64-linux.default
        (hiPrio inputs.cargo-build-bpf.packages.x86_64-linux.default)
      ];
    };
  };
}

Here’s my-solana-project/flake.nix:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.solana.url = "path:/home/farseen/Projects/solana-flake";

  outputs = inputs: with import inputs.nixpkgs {
    system = "x86_64-linux";
  }; {
      devShells.${system}.default = mkShellNoCC {
        packages  = [ pkgs.bashInteractive ];
        inputsFrom = [ inputs.solana.devShells.${system}.default ];
      };
  };
}

This brings in everything in $PATH.
But it doesn’t set the BPF_SDK_PATH env var which I had in the other devShell.

2 Likes

I usually include my devShell from an overlay, in that case you would just apply the overlay and pull out the devShell.

2 Likes

Looking at mkShell derivation it preserves shellHook from inputsFrom so you can propagate BPF_SDK_PATH using shellHook at least.

Note that this is one of the main benefits of https://devenv.sh - it composes well :slight_smile:

1 Like