diff --git a/pills/10-developing-with-nix-shell.xml b/pills/10-developing-with-nix-shell.xml index 0a04232..9542056 100644 --- a/pills/10-developing-with-nix-shell.xml +++ b/pills/10-developing-with-nix-shell.xml @@ -4,5 +4,185 @@ version="5.0" xml:id="developing-with-nix-shell"> -developing with nix shell + Developing with nix shell + + + Welcome to the 10th Nix pill. In the previous + 9th pill we have seen + one of the powerful features of nix, automatic discovery of runtime + dependencies and finalized the GNU hello world package. + + + + In return from vacation, we want to hack a little the GNU hello world + program. The nix-build tool creates an isolated environment for building + the derivation, we want to do the same in order to modify some source + files of the project. + + +
+ What's nix-shell + + + The nix-shell + tool drops us in a shell by setting up the necessary environment + variables to hack a derivation. It does not build the derivation, it + only serves as a preparation so that we can run the build steps manually. + + + + I remind you, in a nix environment you don't have access to libraries and + programs unless you install them with nix-env. However installing + libraries with nix-env is not good practice. We prefer to have isolated + environments for development. + + + + + + First thing to notice, we call nix-shell on a nix + expression which returns a derivation. We then enter a new bash shell, + but it's really useless. We expected to have the GNU hello world build + inputs available in PATH, including GNU make, but it's not the case. + + + + But, we have the environment variables that we set in the derivation, + like $baseInputs, $buildInputs, + $src and so on. + + + + That means we can source our builder.sh, and it will + build the derivation. You may get an error in the installation phase, + because the user may not have the permission to write to + /nix/store: + + + + + + It didn't install, but it built. Things to notice: + + + + + + We sourced builder.sh, therefore it ran all the steps including + setting up the PATH for us. + + + + + The working directory is no more a temp directory created by nix-build, but the current directory. Therefore, hello-2.9 has been unpacked there. + + + + + + We're able to cd into hello-2.9 and type + make, because now it's available. + + + + In other words, nix-shell drops us in a shell with the + same (or almost) environment used to run the builder! + +
+ +
+ A builder for nix-shell + + + The previous steps are a bit annoying of course, but we can improve our + builder to be more nix-shell friendly. + + + + First of all, we were able to source builder.sh + because it was in our current directory, but that's not nice. We want the + builder.sh that is stored in the nix store, the one + that would be used by nix-build. To do so, the right + way is to pass the usual environment variable through the derivation. + + + + Note: $builder is + already defined, but it's the bash executable, not our + builder.sh. Our builder.sh is + an argument to bash. + + + + Second, we don't want to run the whole builder, we only want it to setup + the necessary environment for manually building the project. So we'll + write two files, one for setting up the environment, and the real + builder.sh that runs with + nix-build. + + + + Additionally, we'll wrap the phases in functions, it may be useful, and + move the set -e to the builder instead of the setup. The + set -e is annoying in nix-shell. + + + + The codebase is becoming a little long. You can find all the files in this + nixpill10 gist. + Noteworthy is the setup = ./setup.sh; attribute in the + derivation, which adds setup.sh to the nix store and + as usual, adds a $setup environment variable in the builder. + Thanks to that, we can split builder.sh into + setup.sh and builder.sh. What + builder.sh does is sourcing $setup and + calling the genericBuild function. Everything else is just + some bash changes. + + + + Now back to nix-shell: + + + + + + Now you can run, for example, unpackPhase which unpacks + $src and enters the directory. And you can run commands + like ./configure, make etc. + manually, or run phases with their respective functions. + + + + It's all that straight, nix-shell builds the .drv file + and its input dependencies, then drops into a shell by setting up the + environment variables necessary to build the .drv, in particular those + passed to the derivation function. + +
+ +
+ Conclusion + + + With nix-shell we're able to drop into an isolated + environment for developing a project, with the necessary dependencies + just like nix-build does, except we can build and + debug the project manually, step by step like you would do in any other + operating system. Note that we did never install gcc, + make, etc. system-wide. These tools and libraries are + available per-build. + +
+ +
+ Next pill + + + ...we will clean up the nix store. We wrote and built derivations, added + stuff to nix store, but until now we never worried about cleaning up the + used space in the store. It's time to collect some garbage. + +
diff --git a/pills/10/nix-shell-hello.txt b/pills/10/nix-shell-hello.txt new file mode 100644 index 0000000..a1e5713 --- /dev/null +++ b/pills/10/nix-shell-hello.txt @@ -0,0 +1,5 @@ +$ nix-shell hello.nix +[nix-shell]$ make +bash: make: command not found +[nix-shell]$ echo $baseInputs +/nix/store/jff4a6zqi0yrladx3kwy4v6844s3swpc-gnutar-1.27.1 [...] diff --git a/pills/10/nix-shell-source.txt b/pills/10/nix-shell-source.txt new file mode 100644 index 0000000..870f4e4 --- /dev/null +++ b/pills/10/nix-shell-source.txt @@ -0,0 +1,3 @@ +$ nix-shell hello.nix +[nix-shell]$ source $setup +[nix-shell]$ diff --git a/pills/10/source-builder.txt b/pills/10/source-builder.txt new file mode 100644 index 0000000..fb87b39 --- /dev/null +++ b/pills/10/source-builder.txt @@ -0,0 +1,2 @@ +[nix-shell]$ source builder.sh +...