mb1*_*b14 33 haskell cabal nix
据我所知,Nix是cabal沙箱的替代品.我终于设法安装了Nix,但我仍然不明白它如何取代沙盒.
我知道你不需要使用Nix和封装版GHC的cabal; 但是如果你想发布一个软件包,你需要在某个时候用cabal打包它.因此,您需要能够在NIX中编写和测试您的cabal配置.你是怎样做的?
理想情况下,我想要一个类似于cabal沙箱但在NIX中"包含"的环境,这可能吗?事实上,我真正想要的是等效的嵌套沙箱 - 因为我通常使用由多个包组成的项目.
目前我在2或3个独立项目(P1,P2,P3)上工作,每个项目由2或3个cabal模块/包组成,假设P1:L11,L12(库)和E11(可执行文件).E11取决于L12,它取决于L11.我主要是从库中拆分可执行文件,因为它们是私有的,并保存在私有git仓库中.
理论上,每个项目都可以拥有自己的沙箱(在其子模块之间共享).我尝试过(有一个L11 L12和E11的普通沙箱),但它很快就会烦人,因为如果修改L11,你就无法重建它,因为E11依赖它,所以我必须首先卸载E11重新编译L11.情况可能并非如此,但我遇到了类似的问题.如果我偶尔修改L11,这样会好的,但在实践中,我更改了E11.
由于共享沙箱不起作用,所以我回到了每个包解决方案的一个沙箱.它工作但不太理想.主要问题是如果我修改L11,我需要编译两次(一次在L11中,然后再在E11中).此外,每次我开始一个新的沙箱时,每个人都知道,我需要等待一段时间才能让所有包下载并重新编译.
因此,通过使用Nix,我正在努力为每个项目设置单独的cabal"环境",这解决了上述所有问题.
希望这更清楚.
och*_*les 47
这些天我使用Nix和cabal完成所有开发工作,我很高兴地说它们很好地协调工作.我当前的工作流程是非常新的,因为它依赖于nixpkgs刚刚到达主分支的功能.因此,您需要做的第一件事是nixpkgs从Github 克隆:
cd ~
git clone git://github.com/nixos/nixpkgs
Run Code Online (Sandbox Code Playgroud)
(将来这不是必要的,但现在是这样).
现在我们有了一个nixpkgs克隆,我们可以开始使用haskellng包集了.haskellng是我们如何在Nix中打包东西的重写,我们感兴趣的是更可预测(包名称与Hackage包名称相匹配)并且更易于配置.首先,我们将安装该cabal2nix工具,它可以为我们自动化一些东西,我们还将安装cabal-install以提供cabal可执行文件:
nix-env -f ~/nixpkgs -i -A haskellngPackages.cabal2nix -A haskellngPackages.cabal-install
Run Code Online (Sandbox Code Playgroud)
从这一点来看,这一切都非常明确.
如果您正在开始一个新项目,您可以cabal init像往常一样调用新目录.准备好构建时,可以将此.cabal文件转换为开发环境:
cabal init
# answer the questions
cabal2nix --shell my-project.cabal > shell.nix
Run Code Online (Sandbox Code Playgroud)
这为您提供了一个shell.nix可以使用的文件nix-shell.你不需要经常使用它 - 你经常使用它的唯一时间是cabal configure:
nix-shell -I ~ --command 'cabal configure'
Run Code Online (Sandbox Code Playgroud)
cabal configure缓存所有内容的绝对路径,所以现在当你想要构建时,你只需cabal build正常使用:
cabal build
Run Code Online (Sandbox Code Playgroud)
每当您的.cabal文件发生更改时,您都需要重新生成shell.nix- 只需运行上面的命令,然后再运行cabal configure.
这种方法很好地适用于多个项目,但它需要更多的手动工作来将所有内容"粘合"在一起.为了演示这是如何工作的,让我们考虑我的socket-io库.这个库依赖于engine-io,我通常同时开发这两个库.
Nix-ifying这个项目的第一步是在default.nix每个单独的.cabal文件旁边生成表达式:
cabal2nix engine-io/engine-io.cabal > engine-io/default.nix
cabal2nix socket-io/socket-io.cabal > socket-io/default.nix
Run Code Online (Sandbox Code Playgroud)
这些default.nix表达式是函数,所以我们现在做不了多少.要调用这些函数,我们编写自己的shell.nix文件来解释如何组合所有内容.因为engine-io/shell.nix,我们不需要做任何特别聪明的事情:
with (import <nixpkgs> {}).pkgs;
(haskellngPackages.callPackage ./. {}).env
Run Code Online (Sandbox Code Playgroud)
因为socket-io,我们需要依赖engine-io:
with (import <nixpkgs> {}).pkgs;
let modifiedHaskellPackages = haskellngPackages.override {
overrides = self: super: {
engine-io = self.callPackage ../engine-io {};
socket-io = self.callPackage ./. {};
};
};
in modifiedHaskellPackages.socket-io.env
Run Code Online (Sandbox Code Playgroud)
现在我们shell.nix在每个环境中都有,所以我们可以cabal configure像以前一样使用.
这里的关键观察是,无论何时engine-io发生变化,我们都需要重新配置socket-io以检测这些变化.这就像跑步一样简单
cd socket-io; nix-shell -I ~ --command 'cabal configure'
Run Code Online (Sandbox Code Playgroud)
Nix会注意到../engine-io已更改,并在运行之前重建它cabal configure.