nix-shell as#! runghc的口译员 [英] nix-shell as #! interpreter for runghc

查看:146
本文介绍了nix-shell as#! runghc的口译员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用nix-shell作为#! runghc的包装,如在联机帮助页中所建议的。但它找不到这些库。根据以下示例,从联机帮助页中删除

 #! / usr / bin / env nix-shell 
#! nix-shell -i runghc -p haskellPackages.HTTP

import Network.HTTP

main = return()

我得到以下结果:

  [〜:0] $ ./nixshelltest 

nixshelltest:4:1:error:
无法加载'Network.HTTP'接口
使用-v查看搜索的文件列表。
[〜:1]

在我看来,这就是nix-shell - p是为了避免。



我做错了什么,错过了点,还是有错误?这是一个nixOS 17.03主机,也是一个在Ubuntu上运行nix 17.09的主机。

谢谢,

解决方案

您用于运行脚本的环境缺少一个步骤。它有一个GHC和一个HTTP包,但编译器不知道这个包。



GHC和库包在nix中的工作方式可能有点内部从你的期望中得到。实际上,您需要安装一个依赖于所需库的编译器,而不是简单地单独安装编译器和库。原因在于GHC被设计为通过修改安装GHC的文件树来添加库包。在只有单个系统GHC安装的可变文件系统上,只要安装了库,就可以修改GHC,但nix不能。 Nix必须能够安装一个永远不会改变的冻结GHC,并且可能会有很多这样的设备。

然后,发生什么事情是你安装了一个小包装,它依赖于底层的原始GHC都会安装所有您想使用的库。这个包装器就像是安装了GHC,它们已经注册了这些库,而实际上并不需要复制整个GHC安装。当你只是自己安装一个库包时,它只是处于惰性状态,没有任何GHC能够通过它存在而找到它。



事实上,你的脚本这里展示的实际上并没有指定它应该安装编译器;它 要求 HTTP 。当我尝试你的脚本时,我找不到命令:runghc runghc 只能在你的系统上运行,因为当你运行它时(可能是因为你的配置文件中已经安装了GHC)它恰好已经在你的路径中了,那GHC没有与 HTTP 包一起安装,因此看不到它。 nix-shell 仅将库添加到环境中并不会有帮助。



您需要做的是是使用这一行:

 #! nix-shell -i runghc -p'ghc.withPackages(ps:[ps.HTTP])'

您不直接安装 ghc HTTP ;而不是 ghc.withPackages 函数计算一个nix包,它安装了一个知道 HTTP Haskell包的GHC包装器。在这种情况下,这取决于没有附加库的原始GHC,也取决于 HTTP 库,并且也会导致安装它们。



如果你使用许多不同的Haskell环境(可能通过像这样的nix-shell脚本,每个都需要一组不同的库),那么你将得到一个独特的在您的系统上安装了包装封装器,用于您使用的每个库组合。但没关系,因为包装本身很小,而且nix能够在所有这些环境之间共享和重用底层GHCs和库包。


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,

解决方案

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.

这篇关于nix-shell as#! runghc的口译员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆