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
Related
I would like to install elementary-terminal. This package is
not in nixpkgs/pkgs/top-level/all-packages.nix and I suppose it is therefore not sufficient to just add elementary-terminal into configuration.nix
What is the recommended way to install such packages?
Some packages are namespaced to group them together or avoid potential conflicting names, in this case it's under pantheon.
{ config, lib, pkgs, ... }:
{
environment.systemPackages =
[ pkgs.pantheon.elementary-terminal
];
}
To figure this out use, nix-env -q, nix search or even nix-index to show the corresponding attribute path of a package.
$ nix-env -f '<nixpkgs>' -qaP elementary-terminal
pantheon.elementary-terminal elementary-terminal-5.3.3
So, finally starting to get a stable nix environment that I can basically do all of my development in. Hooray!
Now I want to make it reproducible, as in yarn.lock (for those familiar with npm/yarn in javascript land) or Pipfile.lock (very similar for Python).
Basically the idea is that I would have a way to generate a similar lock file whenever I run nix-env -if my-env.nix, or after running this command, if that is how it would work. From this lock file, I could then exactly restore my nix profile, down to the exact versions of dependencies and sub-dependencies of the installed profile. This could be checked into git or whatever after testing out new improvements, and so a record of the environment would be maintained.
It seems to me this would be one of the most obvious use cases for Nix, and one of the major advantages over just using Docker (though the two aren't mutually exclusive), so I apologize if I've missed some relevant documentation.
What you're probably looking for is a shell.nix file like this:
let
pkgs = import (fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/696c6bed4e8e2d9fd9b956dea7e5d49531e9d13f.tar.gz";
sha256 = "1v3yrpj542niyxp0h3kffsdjwlrkvj0mg4ljb85d142gyn3sdzd4";
}) {};
in pkgs.mkShell {
buildInputs = with pkgs; [
git
hello
];
}
Upon calling nix-shell (which by default uses the shell.nix file in the current directory), you'll be in an environment with git and hello from the specific given nixpkgs revision. This can be reproduced among all nix users (okay almost*). I can really recommend using shell.nix files for all development.
Alternatively, there's also the lesser known -r flag to nix-env, which states that
--remove-all, -r
Remove all previously installed packages first. This is equivalent to running nix-env -e '.*' first, except that everything happens in a single transaction.
You can effectively use it to replace the stateful ~/.nix-profile/manifest.nix. Create a file env.nix containing:
let
pkgs = import <nixpkgs> {};
in {
inherit (pkgs) git hello;
}
Now running nix-env -ir env.nix will install exactly git and hello and remove everything else, so you can reproduce your nix-env installations with this single file. To install additional things: Add it to the file and run the command again. You can also pin nixpkgs to a specific version as in the file above to not care about your nix-channel setup (which is also stateful).
Edit: It's also possible to get some packages from your channel and some of a specific nixpkgs revision:
let
pkgs = import <nixpkgs> {};
fixed = import (fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/696c6bed4e8e2d9fd9b956dea7e5d49531e9d13f.tar.gz";
sha256 = "1v3yrpj542niyxp0h3kffsdjwlrkvj0mg4ljb85d142gyn3sdzd4";
}) {};
in {
inherit (pkgs) git;
inherit (fixed) hello;
}
*: The nix config, overlays and your system (Linux/Mac) can still influence this. It's a good idea to use import <nixpkgs> { config = {}; overlays = []; } for development to avoid this.
After many suggestions from folks on IRC, I was able to put together the following script, which takes a nix expression as its only argument, and copies the derivation file and records the nixpkgs versions locally while installing the specified environment:
#!/bin/bash
if [ -z "$1" ] || [ "${1: -4}" != ".nix" ] || [ ! -f "$1" ]
then
echo "No .nix file supplied"
exit -1
fi
ENV_DRV=$(nix-instantiate "$1")
cp "$ENV_DRV" ./env_backup.drv
chmod u+rw ./env_backup.drv
nix-env --set "$ENV_DRV"
NIXPKGS_VERSION=$(nix-instantiate --eval '<nixpkgs/lib>' -A version)
NIXOS_VERSION=$(nix-instantiate --eval '<nixos/lib>' -A version)
printf "nixpkgs: %s\\nnixos: %s" "$NIXPKGS_VERSION" "${NIXOS_VERSION}" > .nix_versions
Caveat: your nix expression should have the nix package in it, since we are using nix-env --set.
I haven't tried using a copied .drv file yet, but it somehow needs to be restored into the nix store; I've mainly included it as a last resort and for debugging. The output into .nix_versions should be more helpful, as these contain git commit hashes (after the last ".") that can be used to employ the correct revision of nixpkgs (thanks to infinisil on IRC):
pkgs = import "${(import <nixpkgs> {}).fetchFromGitHub { owner = "NixOS"; repo = "nixpkgs"; rev = "<your revision hash>"; sha256 = "<the hash of the output>"; }}" {}
To fill in the hash, either supply an incorrect hash to get the correct hash back, or just use the following: nix-prefetch-url --unpack github.com/nixos/nixpkgs/archive/<revision>.tar.gz.
Or, if manually checking out nixpkgs, you can just do e.g.:
with import ((builtins.getEnv "HOME") + "/workspace/nixpkgs") { }; # or:
with import "../nixpkgs" { }; # or similar
I haven't tested this sort of thing with nix-shell yet, but hope to do so soon.
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.
When I install the Aspell package with the Aspell dictionary for English into my global env using Nix on Mac OSX:
$ nix-env -iA nixpkgs.aspell nixpkgs.aspellDicts.en
Then Aspell behaves as I would expect:
$ aspell dump dicts
en
en-variant_0
...
However if I install the packages into a nix-shell then the Dictionary does not appear to be correctly installed:
$ nix-shell -p aspell aspellDicts.en --pure
$ aspell dump dicts
# nothing printed
$ echo 'word lister to check' | aspell --list
Error: No word lists can be found for the language "en_US".
Each of the following variations produce the same problem behaviour:
Installing into a nix-shell that is not pure,
Putting the nix expression into a default.nix file and just running nix-shell.
Installing other Aspell dictionaries
Can anyone advise how to get this working?
The aspell binary is wrapped by NixPkgs, to provide the installation paths through ASPELL_CONF environment variable, if not already specified. (For details, cat -v result/bin/aspell)
You can either specify ASPELL_CONF manually, or use the NIX_PROFILES environment variable. For example:
$ nix-build -E 'with import <nixpkgs> {};
buildEnv { name = "aspell-env"; paths = [aspell aspellDicts.en]; }'
$ NIX_PROFILES=./result ./result/bin/aspell dump dicts
en
en-variant_0
[...]
en_US-wo_accents
However, if you want to build a self-contained aspell install with dictionaries, you can use aspellWithDicts:
nix-build -E 'with import <nixpkgs> {}; aspellWithDicts (d: [d.en])'
This will hardcode the ASPELL_CONF, so you don't need to think of those environment variables again.
I've just started using the Nix package manager on OSX and I'm attempting to create my first package for the pass binary (https://www.passwordstore.org) - which is not available in the Nixpkgs repository.
I'm attempting to specify a runtime dependency (getopt), however this doesn't appear to be available when the binary is used.
This is my packages's default.nix:
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
let
version = "1.7.1";
in {
pass = stdenv.mkDerivation rec {
name = "pass-${version}";
src = fetchurl {
url = "https://git.zx2c4.com/password-store/snapshot/password-store-1.7.1.tar.xz";
sha256 = "0scqkpll2q8jhzcgcsh9kqz0gwdpvynivqjmmbzax2irjfaiklpn";
};
buildInputs = [ stdenv makeWrapper];
installPhase = ''
make install PREFIX=$out/artifact
makeWrapper $out/artifact/bin/pass $out/bin/pass \
--set PATH ${stdenv.lib.makeBinPath [ getopt ]}
'';
meta = {
homepage = "https://www.passwordstore.org";
description = "The standard unix password manager";
license = stdenv.lib.licenses.gpl2Plus;
};
};
}
I can successfully build this package (nix-build --show-trace) and install it (nix-env -i ./result).
Listing the runtime dependencies for my package shows getopt listed:
nix-store -qR $(which pass)
...
/nix/store/c5swmygzc0kmvpq6cfkvwm2yz1k57kqy-getopt-1.1.4
However when I come to use the binary (pass init my-key) I get the following error:
/nix/store/...-pass-1.7.1/artifact/bin/pass: line 302:
/usr/local/bin/getopt: No such file or directory
Can anyone advise what I'm doing wrong?
Thanks
It looks like getopt gets a special treatment. The darwin.sh script looks for it using brew and port and falls back to /usr/local. That's why the (correct) wrapper has no effect.
So the solution seems to be, to make it look for getopt in PATH, which is provided by the wrapper script. You can probably make it as simple as GETOPT=getopt (which is similar to openbsd.sh)
For patching source code, see the NixPkgs documentation
After running nix-build, you should run cat result/bin/pass to look at your wrapper script and make sure it looks OK. It should be a shell script that sets the PATH to include getopt and then calls result/artifact/bin/pass.
Then try running the wrapper script. Note that the wrapper should be in result/bin, not result/artifact/bin.