I'm trying to use nix-shell as a #! wrapper for runghc, as suggested in the manpage. But it cannot find the libraries. Given the following example, cut-down from the manpage
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p haskellPackages.HTTP
import Network.HTTP
main = return ()
I get the following result:
[~:0]$ ./nixshelltest
nixshelltest:4:1: error:
Failed to load interface for ‘Network.HTTP’
Use -v to see a list of the files searched for.
[~:1]$
to my mind, that's exactly what nix-shell -p is to avoid.
Am I doing something wrong, missing the point, or is there a bug? This is both on a nixOS 17.03 host, and also a host running nix 17.09 on top of Ubuntu.
Thanks,
Description. The command nix-shell will build the dependencies of the specified derivation, but not the derivation itself. It will then start an interactive shell in which all environment variables defined by the derivation path have been set to their corresponding values, and the script $stdenv/setup has been sourced.
NixOS is a Linux distribution using Nix for managing software in the system, including the Linux kernel.
A flake is (usually) a Git repository that contains a file named flake. nix at top-level. Flakes provide an attribute set of values, such as packages, Nixpkgs overlays, NixOS modules, library functions, Hydra jobs, nix-shell definitions, etc. Flakes can depend on other flakes.
NixOS makes it easier to keep custom packages as part of your OS configuration. Rather than writing custom, imperative install scripts to run when setting up your machine, you can simply list your custom packages in your system's package list, and they will be built automatically.
The environment that you're using to run the script is missing a step. It's got a GHC and a HTTP package, but the compiler doesn't know about the package.
The way GHC and library packages work in nix might be a little "inside out" from what you're expecting. You actually need to install a compiler that "depends on" all of the libraries you want, rather than simply installing the compiler and the library separately. The reason is that GHC is designed to have library packages added by modifying the file tree where GHC is installed. On a mutable file system with only a single system GHC install you would just modify GHC whenever a library was installed, but nix can't. Nix has to be able to install a frozen GHC that never changes, and potentially many of them.
So what happens instead is that you install a tiny wrapper which depends on the both the underlying "raw" GHC install and all of the libraries that you want to use. The wrapper then acts like an install of GHC that had those libraries registered, without actually needing to duplicate an entire GHC install. When you just install a library package on its own it just sits there inert, without any GHC being able to find it just by it existing.
In fact, the script you've shown here doesn't actually specify that it should have a compiler installed at all; it just asks for the HTTP
library. When I tried your script I got command not found: runghc
. The runghc
is only working on your system because it happened to already be in your path when you ran this (perhaps because you have GHC installed in your profile?), and that GHC wasn't installed with the HTTP
package and so can't see it. The nix-shell
adding just the library to the environment doesn't help.
What you need to do instead is use this line:
#! nix-shell -i runghc -p "ghc.withPackages (ps: [ ps.HTTP ])"
You're not installing either ghc
or HTTP
directly; instead the ghc.withPackages
function computes a nix package that installs a GHC wrapper that knows about the HTTP
Haskell package. Under the hood this depends on a "raw" GHC with no additional libraries, and also on the HTTP
library and will cause those to be installed too.
If you use lots of different Haskell environments (possibly via nix-shell scripts like this that each need a different set of libraries), then you will end up with a unique withPackages
wrapper installed on your system for each combination of libraries you ever use. But that's okay because the wrappers themselves are tiny, and nix is able to share and reuse the underlying GHCs and library packages between all of those environments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With