Difference between revisions of "Development environment with nix-shell"

From NixOS Wiki
Jump to: navigation, search
(Add direnv wiki link)
(Added note about Building locally in a nix-shell)
Line 64: Line 64:
  
 
More explanation and configuration tweak can be found in the Direnv wiki [https://github.com/direnv/direnv/wiki/Nix]
 
More explanation and configuration tweak can be found in the Direnv wiki [https://github.com/direnv/direnv/wiki/Nix]
 +
 +
== Troubleshooting ==
 +
 +
When compiling software which links against local files (e.g. when compiling with rust's cargo), you may encounter the following problem:
 +
<syntaxHighlight lang=bash>
 +
= note: impure path `/[...]' used in link
 +
</syntaxHighlight>
 +
This happens due to a specialty in nix: <code>ld</code> is wrapped in a shell script which refuses to link against files not residing in the nix store, to ensure purity of builds. Obviously this is not useful when building locally, for example in your home directory. To disable this behavior simply set
 +
<syntaxHighlight lang=bash>
 +
NIX_ENFORCE_PURITY=0
 +
</syntaxHighlight>
 +
in the nix-shell.

Revision as of 07:44, 27 June 2019

Nix can be used to provides some kind of virtual environment through the nix-shell command.

If you already have a nix package definition of you project it's easy: Just use nix-shell instead of nix-build and you will end up in a bash shell that reproduce the build environment of your package. You can also override[1] your package in a shell.nix 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 shell.nix file at root of your repository. For example, if you want to have Ruby 2.3 and not the one of your system you can write:

{ pkgs ? import <nixpkgs> {} }:
  pkgs.mkShell {
    buildInputs = [ pkgs.ruby_2_3 ];
}

Then just run:

$ nix-shell

Or, to be more explicit:

$ nix-shell shell.nix

Now you got ruby 2.3 in available in your shell:

$ ruby --version
ruby 2.3.7p456 (2018-03-28) [x86_64-linux]

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 --pure option.

Using Direnv

One of the limitation of nix-shell is that you can't use an other shell then bash. Hopefully there is Direnv [[2]] with the support of Nix[[3]] to overcome this limitation. Also Direnv provides some nice features like loading the environment automatically when you enter your project directory and show the loaded variables to you (explicit is always better;-)).

First, install Direnv:

nix-env -i direnv

Now, you need to add one more file in the root of your repository named .envrc that contains only this:

use_nix

Then depending on the shell you are using, you need to add a line in your configuration file. See the Setup section of the doc[4]. For example, for Zsh put in your ~/.zshrc.local:

eval "$(direnv hook zsh)"

Then, still at the root of your repository, run:

$ direnv allow .
direnv: loading .envrc
direnv: using nix
[...]
 +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +TEMP +TEMPDIR +TMP +TMPDIR +_PATH +buildInputs +builder +checkPhase +cmakeFlags +configureFlags +doCheck +enableParallelBuilding +name +nativeBuildInputs +out +postCheck +preCheck +preConfigure +propagatedBuildInputs +propagatedNativeBuildInputs +shell +src +stdenv +system +testInputs +version ~PATH

In bonus, you can see all the variables set by the nix-shell :)

No you can leave your project and the environment will be unloaded:

$ cd ..
direnv: unloading

No need to use direnv allow anymore, the next time you go to your project the environment will be loaded!

More explanation and configuration tweak can be found in the Direnv wiki [5]

Troubleshooting

When compiling software which links against local files (e.g. when compiling with rust's cargo), you may encounter the following problem:

= note: impure path `/[...]' used in link

This happens due to a specialty in nix: ld is wrapped in a shell script which refuses to link against files not residing in the nix store, to ensure purity of builds. Obviously this is not useful when building locally, for example in your home directory. To disable this behavior simply set

NIX_ENFORCE_PURITY=0

in the nix-shell.