Multiple versions of Python available in shell.nix environment - nix

I can also run interpreter of Python 3.9 which installed in system using environment.systemPackages.
with import <nixpkgs>{};
let
in pkgs.mkShell {
buildInputs = with pkgs; [
ccls
clang-tools
cmake
gdb
gcc
fish
mono
python37Full
tcl
tk
];
inputsFrom = with pkgs; [
];
runScript = "fish";
}

Related

Failed when `nix-build hello.nix`

I followed the steps on http://lethalman.blogspot.com/2014/08/nix-pill-8-generic-builders.html to build GNU Hello, and here is the files I used to build GNU hello 2.9:
$ wget -c http://ftp.gnu.org/gnu/hello/hello-2.9.tar.gz
hello.nix:
$ cat hello.nix
let
pkgs = import <nixpkgs> {};
mkDerivation = import ./autotools.nix pkgs;
in mkDerivation {
name = "hello";
src = ./hello-2.9.tar.gz;
}
autotools.nix:
$ cat autotools.nix
pkgs: attrs:
with pkgs;
let defaultAttrs = {
builder = "${bash}/bin/bash";
args = [ ./builder.sh ];
baseInputs = [ gnutar gzip gnumake gcc binutils coreutils gawk gnused gnugrep ];
buildInputs = [];
system = builtins.currentSystem;
};
in
derivation (defaultAttrs // attrs)
builder.sh:
$ cat builder.sh
set -e
unset PATH
for p in $buildInputs; do
export PATH=$p/bin${PATH:+:}$PATH
done
tar -xf $src
for d in *; do
if [ -d "$d" ]; then
cd "$d"
break
fi
done
./configure --prefix=$out
make
make install
Error messages:
$ nix-build hello.nix
these derivations will be built:
/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv
building '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv'...
/nix/store/vv3xqdggviqqbvym25jf2pwv575y9j1r-builder.sh: line 7: tar: No such file or directory
builder for '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv' failed with exit code 127
error: build of '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv' failed
It seems there is gnutar in the autotools.nix but builder still complains tar: No such file or directory, why is this?
The problem is probably that gnutar is in the baseInputs list, while the buildInputs list you are building your PATH from is totally empty so nothing will be on your PATH. Try changing the for line in your shell script so that it uses the concatentation of both lists to build the path:
for p in $baseInputs $buildInputs; do
You can add echo $PATH to your builder script to debug issues like this.
That is what the blog post author was asking you to do in this sentence from the post:
Complete the new builder.sh by adding $baseInputs in the for loop together with $buildInputs.

How to install a latest / unstable Haskell package executable in Nixos?

I'm trying to get the latest version of ghcid installed.
I've installed ghcid via adding haskellPackages.ghcid in my nix config like so:
{ config, pkgs, ... }:
let
unstable = import <unstable> {};
in
{
environment.systemPackages = with pkgs; [
haskellPackages.ghcid
];
}
I thought possibly it would be available as a specific package but I can't seem to find anything:
nix-env -v -qaP haskellPackages.ghcid
And
nix-env -v -qaP ghcid
Return ...matches no derivations
Surprisingly simple:
unstable.haskellPackages.ghcid

node2nix override; wrapProgram: command not found

I'm packaging a node script with an external dependency (GraphicsMagick), and when attempting to override the derivation generated from node2nix I get the error:
wrapProgram: command not found
The following text goes into detail of what I've tried to solve this error.
Reproducing the problem from scratch
I've created a minimal git repository that reproduces this problem if you'd just like to take a look there. Else, the steps to reproduce the problem are below.
Initial Shell Session:
In an empty directory, run:
npm init -y
npm install --save gm
curl https://i.imgur.com/addSfQi.jpg > image.png
(npm version: 5.6.0 & node version v8.9.4)
Create index.js
#!/usr/bin/env node
const path = require("path"); // node.js builtin
const gm = require("gm"); // GraphicsMagick module
const imagePath = path.join(__dirname, "image.png");
// Flip image horizontally and write to disk
gm(imagePath)
.flop()
.write(imagePath, error => {
console.log("error:", error);
});
Add a "bin" section to package.json:
"bin": "index.js"
Generate *.nix files with node2nix
node2nix -8 -l package-lock.json
Create override.nix
{ pkgs ? import <nixpkgs> {}
, system ? builtins.currentSystem
}:
let
nodePackages = import ./default.nix {
inherit pkgs system;
};
in
nodePackages // {
package = nodePackages.package.override (oldAttrs: {
postInstall = ''
wrapProgram "$out/bin/test-nodejs-gm-nixpkg" --prefix PATH : "${pkgs.graphicsmagick}/bin"
'';
});
}
Build nix package
nix-build override.nix -A package
The above fails with:
/nix/store/*/setup: line 95: wrapProgram: command not found
Helpful Resources
node2nix git repository - includes some basic examples.
example override in nixpkgs - example of how nixpkgs uses wrapProgram in postInstall with files generated by node2nix.
wrapProgram is contained within the makeWrapper package.
nativeBuildInputs = oldAttrs.nativeBuildInputs or [] ++ [ pkgs.makeWrapper ];
As mentioned by #ppb in the comments.

How to install PostGIS within a Nix environment

I have the following shell.nix (to setup my development environment, no NixOS):
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "my-shiny-project";
buildInputs = [
jq
nodejs-6_x
#postgis {version="2.3.1";}
#postgis ("2.3.1")
#postgis "2.3.1"
postgresql96
zsh
];
shellHook = ''
export SHELL=zsh
export PATH="$PWD/node_modules/.bin/:$PATH"
'';
}
PostGIS expects a version parameter. I'm not sure how to pass that parameter along. Whether I use postgis{version="2.3.1";}, postgis("2.3.1") or postgis "2.3.1", I receive the following error:
error: cannot coerce a set to a string, at /nix/store/0rj9y7gvzzahp93cvdmrwc2v2aznh61p-nixpkgs-18.03pre118061.69607d7662/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:98:11
In the Nameless and single parameter section of functions and imports Nix pill, I see the syntax for calling a function is simply NAME PARAM.
What do I have to add to buildInputs to get PostGIS installed for that specific version of PostgreSQL?
Recently it became possible to use postgresql.withPackages:
with import <nixpkgs> {};
mkShell {
buildInputs = [
jq
nodejs
( postgresql11.withPackages (p: [ p.postgis ]) )
zsh
];
shellHook = ''
export SHELL=${zsh}/bin/zsh
export PATH="${builtins.toPath ./.}/node_modules/.bin/:$PATH"
export PGDATA=${builtins.toPath ./.}/pg
export PGHOST=$PGDATA
pg_ctl initdb
pg_ctl -o "-p 5555 -k $PGDATA" start
psql -p 5555 postgres -c 'create extension postgis' || true
'';
}
This is truly a stab in the dark given that postgresql is designed to be used as a service, but it's only available to you as a package since you're not on NixOS. But try this:
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "my-shiny-project";
buildInputs = [
jq
nodejs-6_x
postgis.v_2_3_1
postgresql96
zsh
];
shellHook = ''
export SHELL=zsh
export PATH="$PWD/node_modules/.bin/:$PATH"
'';
}
Explanation
The postgis package doesn't produce a derivation, so it's output cannot be used directly. Instead it produces a set with attributes for two versions: 2.3.1 and 2.4.0.
Caveat
The above may not work at all. The issue is that postgis is normally provided to postgresql via the extraPlugins attribute like so:
services.postgresql.extraPlugins = [ (pkgs.postgis.override { postgresql = pkgs.postgresql95; }).v_2_3_1 ];
This causes postgresql to be installed in such a way that it can see the postgis library. However, this is done at the service level, not the package leve, and services are only available to NixOS. So if the above doesn't work, try this hunk of code:
with import <nixpkgs> {};
let
pg = postgresql96;
postgresqlWithPlugins =
buildEnv {
name = "postgresql-and-plugins-${(builtins.parseDrvName pg.name).version}";
paths = [ pg pg.lib (postgis.override { postgresql = pg; }).v_2_3_1) ];
buildInputs = [ makeWrapper ];
postBuild =
''
mkdir -p $out/bin
rm $out/bin/{pg_config,postgres,pg_ctl}
cp --target-directory=$out/bin ${pg}/bin/{postgres,pg_config,pg_ctl}
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
'';
};
in
stdenv.mkDerivation {
name = "my-shiny-project";
buildInputs = [
jq
nodejs-6_x
postgresqlWithPlugins
zsh
];
shellHook = ''
export SHELL=zsh
export PATH="$PWD/node_modules/.bin/:$PATH"
'';
}
Basically, this is an untested port of the extraPlugins implementation.

Trouble Understanding With Statement in Nix Expression

From Section 12.5 of Nix Pills:
Finish the expression for graphviz with gd support (note the use of the with expression in buildInputs to avoid repeating pkgs):
let
pkgs = import <nixpkgs> {};
mkDerivation = import ./autotools.nix pkgs;
in mkDerivation {
name = "graphviz";
src = ./graphviz-2.38.0.tar.gz;
buildInputs = with pkgs; [ gd fontconfig libjpeg bzip2 ];
}
Question: Why is the the with pkgs needed at the end of the code snippet in buildInputs? I thought pkgs was already in scope through the let binding at the top?
Yes, pkgs is in scope, but that doesn't automatically put it's attributes into scope.
pkgs is a Nix set containing attributes such as gd, fontconfig... If you drop with pkgs then the list of buildInputs will not be able to resolve the aforementioned attributes. Using your example, the following two expressions are semantically identical:
buildInputs = with pkgs; [ gd fontconfig libjpeg bzip2 ];
buildInputs = [ pkgs.gd pkgs.fontconfig pkgs.libjpeg pkgs.bzip2 ];
Here's another example which is also semantically identical:
let
pkgs = import <nixpkgs> {};
mkDerivation = import ./autotools.nix pkgs;
gd = pkgs.gd;
fontconfig = pkgs.fontconfig;
libjpeg = pkgs.libjpeg;
bzip2 = pkgs.bzip2;
in mkDerivation {
name = "graphviz";
src = ./graphviz-2.38.0.tar.gz;
buildInputs = [ gd fontconfig libjpeg bzip2 ];
}
In the last example, gd, fontconfig... are brought into scope in the first part of the let expression, and then used in buildInputs without the with pkgs.
Hopefully that will help you intuit what with pkgs is doing.

Resources