Development environment with nix-shell: Difference between revisions

m Fixed indentation in code block.
Artturin (talk | contribs)
No edit summary
Line 3: Line 3:
If you already have a nix package definition of your project it's easy: Just use <code>nix-shell</code> instead of <code>nix-build</code> and you will end up in a bash shell that reproduce the build-environment of your package. You can also override[https://nixos.org/nixpkgs/manual/#sec-pkg-override] your package in a <code>shell.nix</code> file to add test and coverage dependencies, that are not necessary for the actual build of the package, but that you want for your development environment.
If you already have a nix package definition of your project it's easy: Just use <code>nix-shell</code> instead of <code>nix-build</code> and you will end up in a bash shell that reproduce the build-environment of your package. You can also override[https://nixos.org/nixpkgs/manual/#sec-pkg-override] your package in a <code>shell.nix</code> file to add test and coverage dependencies, that are not necessary for the actual build of the package, but that you want for your development environment.


But, if you don't (or you don't want to) have a package definition you can still use a nix-shell to provide a reproducible development environment. To do so, you have to create a <code>shell.nix</code> file at the root of your repository. For example, if you want to have Ruby 3.2 and not one provided by your system you can write:
But, if you don't (or you don't want to) have a package definition you can still use a nix-shell to provide a reproducible development environment. To do so, you have to create a <code>shell.nix</code> file at the root of your repository. For example, if you want to have rustc with libraries and hello you can write:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{ pkgs ? import <nixpkgs> {} }:
{
pkgs.mkShell {
  pkgs ? import <nixpkgs> { },
  # nativeBuildInputs is usually what you want -- tools you need to run
}:
  nativeBuildInputs = with pkgs.buildPackages; [ ruby_3_2 ];
pkgs.callPackage (
}
  {
    mkShell,
    hello,
    rustc,
    pkg-config,
    openssl,
  }:
  mkShell {
    strictDeps = true;
    # host/target agnostic programs
    depsBuildBuild = [
      hello
    ];
    # compilers & linkers & dependecy finding programs
    nativeBuildInputs = [
      rustc
      pkg-config
    ];
    # libraries
    buildInputs = [
      openssl
    ];
  }
) { }
 
</syntaxhighlight>
</syntaxhighlight>


Line 19: Line 43:


Now you have ruby 3.2 available in your shell:
Now you have ruby 3.2 available in your shell:
<syntaxHighlight lang=bash>
<syntaxhighlight lang="bash">
$ ruby --version
$ rustc --version
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
rustc 1.80.1 (3f5fd8dd4 2024-08-06) (built from a source tarball)
</syntaxHighlight>
</syntaxhighlight>


To be sure that the tools installed on your system will not interfere with the dependencies that you've defined in the shell you can use the <code>--pure</code> option.
To be sure that the tools installed on your system will not interfere with the dependencies that you've defined in the shell you can use the <code>--pure</code> option.


If you'd like to load a local nix expression into a shell you can do it by modifying the earlier example a little bit:
If you'd like to load a local nix expression into a shell you can do it by modifying the earlier example a little bit, see comments in the earlier example for where to put your package:
<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{ pkgs ? import <nixpkgs> {} }:
{
pkgs.mkShell {
  pkgs ? import <nixpkgs> {
  # buildInputs is for dependencies you'd need "at run time",
    overlays = [
   # were you to to use nix-build not nix-shell and build whatever you were working on
      (final: prev: {
   buildInputs = [
        my-packages = prev.callPackage ./my-package.nix { };
    (import ./my-expression.nix { inherit pkgs; })
      })
   ];
    ];
}
  },
</syntaxHighlight>
}:
pkgs.callPackage (
  {
    mkShell,
    my-package
   }:
   mkShell {
    strictDeps = true;
    buildInputs = [
      my-package
    ];
   }
) { }
</syntaxhighlight>


If you want to see how to manually run the various phases of a given derivation from a nix-shell (useful to debug), see [[Nixpkgs/Create_and_debug_packages#Using_nix-shell_for_package_development]].  
If you want to see how to manually run the various phases of a given derivation from a nix-shell (useful to debug), see [[Nixpkgs/Create_and_debug_packages#Using_nix-shell_for_package_development]].  
Line 96: Line 133:
Let's assume you have a <code>default.nix</code> file
Let's assume you have a <code>default.nix</code> file


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{ stdenv, python }:
{ stdenv, python }:
stdenv.mkDerivation {
stdenv.mkDerivation {
   buildInputs = [ python ];
   pname = "some-package";
  name = "some-package";
  strictDeps = true;
  nativeBuildInputs = [ python ];
   version = "0.0.1";
   version = "0.0.1";
   src = /home/yourname/path/to/project; # can be a local path, or fetchFromGitHub, fetchgit, ...
   src = /home/yourname/path/to/project; # can be a local path, or fetchFromGitHub, fetchgit, ...
}
}
</syntaxHighlight>
</syntaxhighlight>


Then you can start a development shell with
Then you can start a development shell with
Line 198: Line 236:
mkShell {
mkShell {
   ...
   ...
  strictDeps = true;
   buildInputs = [ gtk3 ];
   buildInputs = [ gtk3 ];
   shellHook = ''
   shellHook = ''