私が理解している限り、Nixはcabal sandboxの代わりになります。ついにNixをインストールできましたが、サンドボックスを置き換える方法がまだわかりません。
NixとラップバージョンのGHCを使用する陰謀団は必要ないことを理解しています。ただし、パッケージを公開する場合は、ある時点でcabalを使用してパッケージ化する必要があります。したがって、NIX内でcabal構成を記述してテストできる必要があります。どうやってそれをしますか?
理想的には、陰謀団のサンドボックスに似ているが、NIX内に「含まれている」環境が欲しいのですが、それは可能ですか?実際、私が本当に望んでいるのは、ネストされたサンドボックスに相当するものです。通常、複数のパッケージで作成されたプロジェクトで作業します。
現在、私は2つまたは3つの独立したプロジェクト(P1、P2、P3)に取り組んでいます。これらは、それぞれ2つまたは3つのcabalモジュール/パッケージで構成されています。たとえば、P1:L11、L12(ライブラリ)、およびE11(実行可能ファイル)です。 E11はL11に依存するL12に依存します。実行可能ファイルはプライベートであり、プライベートgitリポジトリに保持されているため、主にライブラリから実行可能ファイルを分割します。
理論的には、各プロジェクトはこの独自のサンドボックス(サブモジュール間で共有)を持つことができます。私はそれを試しましたが(L11 L12とE11に共通のサンドボックスがあります)、L11を変更すると、E11がそれに依存しているため再構築できないため、すぐに面倒です。そのため、L11を再コンパイルするには最初にE11をアンインストールする必要があります。正確には当てはまらないかもしれませんが、私は同様の問題に遭遇します。たまにL11を変更していれば問題ありませんが、実際にはE11よりも変更しました。
共有サンドボックスが機能しないため、パッケージソリューションごとに1つのサンドボックスに戻りました。動作していますが、理想的とは言えません。主な問題は、L11を変更した場合、2回コンパイルする必要があることです(1回はL11で、次にもう一度E11で)。また、誰もが知っているように、新しいサンドボックスを開始するたびに、すべてのパッケージがダウンロードされて再コンパイルされるまでしばらく待つ必要があります。
したがって、Nixを使用することで、プロジェクトごとに個別の陰謀団の「環境」を設定できるようになり、上記のすべての問題が解決されます。
これがより明確になることを願っています。
最近はNixとcabalを使ってすべての開発を行っていますが、それらは非常にうまく調和していると喜んで言えます。私の現在のワークフローは非常に新しく、マスターブランチに到達したばかりのnixpkgs
の機能に依存しています。そのため、最初に行う必要があるのは、Githubからnixpkgs
を複製することです。
cd ~
git clone git://github.com/nixos/nixpkgs
(将来的にはこれは必要ありませんが、現在は必要です)。
nixpkgs
クローンができたので、haskellng
パッケージセットの使用を開始できます。 haskellng
は、Nixで物事をパッケージ化する方法を書き直したものであり、より予測可能で(パッケージ名がHackageパッケージ名と一致する)、より構成可能であるという点で興味深いものです。まず、いくつかのことを自動化できるcabal2nix
ツールをインストールします。また、cabal-install
をインストールして、cabal
実行可能ファイルを提供します。
nix-env -f ~/nixpkgs -i -A haskellngPackages.cabal2nix -A haskellngPackages.cabal-install
この時点から、それはすべてかなり明確な航海です。
新しいプロジェクトを開始する場合は、通常どおり、新しいディレクトリでcabal init
を呼び出すことができます。ビルドする準備ができたら、この.cabal
ファイルを開発環境に変えることができます。
cabal init
# answer the questions
cabal2nix --Shell my-project.cabal > Shell.nix
これにより、Shell.nix
ファイルが作成されます。このファイルはnix-Shell
で使用できます。ただし、これを頻繁に使用する必要はありません。通常使用するのは、cabal configure
を使用する場合のみです。
nix-Shell -I ~ --command 'cabal configure'
cabal configure
はすべてへの絶対パスをキャッシュするため、ビルドする場合は通常どおりcabal build
を使用します。
cabal build
.cabal
ファイルが変更されるたびに、Shell.nix
を再生成する必要があります。上記のコマンドを実行し、その後cabal configure
を実行します。
このアプローチは複数のプロジェクトにうまく対応できますが、すべてを「接着」するには、もう少し手作業が必要です。これがどのように機能するかを示すために、私の socket-io
ライブラリについて考えてみましょう。このライブラリは engine-io
に依存しており、私は通常両方を同時に開発します。
このプロジェクトをNix化するための最初のステップは、個々のdefault.nix
ファイルの横に.cabal
式を生成することです。
cabal2nix engine-io/engine-io.cabal > engine-io/default.nix
cabal2nix socket-io/socket-io.cabal > socket-io/default.nix
これらのdefault.nix
式は関数であるため、現時点では多くのことを実行できません。関数を呼び出すために、すべてを組み合わせる方法を説明する独自のShell.nix
ファイルを作成します。 engine-io/Shell.nix
の場合、特に賢いことをする必要はありません。
with (import <nixpkgs> {}).pkgs;
(haskellngPackages.callPackage ./. {}).env
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
これで、各環境にShell.nix
があるので、以前と同じようにcabal configure
を使用できます。
ここでの重要な観察は、engine-io
が変更されるたびに、これらの変更を検出するためにsocket-io
を再構成する必要があるということです。これは実行するのと同じくらい簡単です
cd socket-io; nix-Shell -I ~ --command 'cabal configure'
Nixは、../engine-io
が変更されたことを認識し、cabal configure
を実行する前に再構築します。