使用 Nix,如何在启用分析的情况下指定 Haskell 依赖项?
With Nix, how can I specify Haskell dependencies with profiling enabled?
我最初是这样尝试的:
nix-shell -p "haskell.packages.ghc821.ghcWithPackages (p: with p; [text hspec lens])" -j4 --run 'ghc Main.hs -prof
然后GHC告诉我
Main.hs:4:1: error:
Could not find module ‘Control.Lens’
Perhaps you haven't installed the profiling libraries for package ‘lens-4.15.4’?
Use -v to see a list of the files searched for.
在网上搜索我发现了这个:https://github.com/NixOS/nixpkgs/issues/22340
看来我无法从缓存中下载。但没关系,如果至少我可以在本地构建配置文件变体。
我可以通过稍微修改给 -p
的 nix 表达式来做到这一点吗?
然后在写这个问题的时候,我想起了这个资源:https://github.com/NixOS/nixpkgs/blob/bd6ba7/pkgs/development/haskell-modules/lib.nix
我在哪里找到 enableLibraryProfiling
。所以我尝试了:
nix-shell -p "haskell.packages.ghc821.ghcWithPackages (p: with p; [text hspec (haskell.lib.enableLibraryProfiling lens)])" -j4 --run 'ghc Main.hs -prof'
这让我遇到了一个新错误:
src/Control/Lens/Internal/Getter.hs:26:1: error:
Could not find module ‘Data.Functor.Contravariant’
Perhaps you haven't installed the profiling libraries for package ‘contravariant-1.4’?
Use -v to see a list of the files searched for.
|
26 | import Data.Functor.Contravariant
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
因此,如果我可以将所有包映射到它们上面的 enableLibraryProfiling
,那么我想这可行。但目前我的 nix 知识还没有扩展到那么远。我怎么能那样做?这是正确的追求路径吗?
通过进一步了解 nix-repl
以及来自 ElvishJerricco 在 FreeNode 的 #reflex-frp 上的一些有用的指示,我能够构建这个,这似乎有效:
$ nix-shell -p "(haskell.packages.ghc821.extend (self: super: {mkDerivation = expr: super.mkDerivation (expr // { enableLibraryProfiling = true; });})).ghcWithPackages (p: with p; [text hspec lens])" -j4 --run 'ghc Main.hs -prof'
我想出了一个简单的方法,我正在为一个最大的博客 post 使用 Nix 进行 Haskell 开发。现在,这里只是分析部分的文本:
Nix 使这相当容易。首先,我们将以下内容添加到 ~/.config/nixpkgs/config.nix
:
{
packageOverrides = super: let self = super.pkgs; in
{
profiledHaskellPackages = self.haskellPackages.override {
overrides = self: super: {
mkDerivation = args: super.mkDerivation (args // {
enableLibraryProfiling = true;
});
};
};
};
}
现在在我们要分析的项目中,我们创建一个新的 profiling-shell.nix
:
let nixpkgs = import <nixpkgs> {};
orig = nixpkgs.pkgs.profiledHaskellPackages.callPackage ./default.nix {};
in (nixpkgs.pkgs.haskell.lib.doBenchmark orig).env
几乎与我们的正常 shell.nix
相同,除了我们刚刚全局定义的 profiledHaskellPackages
的用法。现在,调用 nix-shell profiling-shell.nix
将在启用分析的情况下重建我们项目中的 每个 依赖项。第一次这样做需要相当长的时间。幸运的是,这不会破坏我们的 Nix 存储 - 香草 nix-shell
似乎再次向我们展示了我们的常规依赖项,而无需重新下载或重建。
警告: nix-collect-garbage -d
将从我们的 Nix 商店中删除所有自定义构建的库,如果它们是,我们将不得不重新构建它们需要。
如果我们正在编写一个库,我们手头上最接近的可执行文件将是我们的基准套件。为此:
- 将
-prof
和 -fprof-auto
添加到我们基准测试的 GHC 选项中
- 重新生成
default.nix
- 输入我们的分析shell:
nix-shell profiling-shell.nix
cabal configure --enable-library-profiling --enable-benchmarks
cabal build
dist/build/projname/projname-bench +RTS -p
- 查看生成的
projname-bench.prof
文件
根据结果,我们可以更改代码,删除分析选项,重新生成 default.nix
,并像往常一样在我们的 Nix Shell.
中进行基准测试
我最初是这样尝试的:
nix-shell -p "haskell.packages.ghc821.ghcWithPackages (p: with p; [text hspec lens])" -j4 --run 'ghc Main.hs -prof
然后GHC告诉我
Main.hs:4:1: error:
Could not find module ‘Control.Lens’
Perhaps you haven't installed the profiling libraries for package ‘lens-4.15.4’?
Use -v to see a list of the files searched for.
在网上搜索我发现了这个:https://github.com/NixOS/nixpkgs/issues/22340
看来我无法从缓存中下载。但没关系,如果至少我可以在本地构建配置文件变体。
我可以通过稍微修改给 -p
的 nix 表达式来做到这一点吗?
然后在写这个问题的时候,我想起了这个资源:https://github.com/NixOS/nixpkgs/blob/bd6ba7/pkgs/development/haskell-modules/lib.nix
我在哪里找到 enableLibraryProfiling
。所以我尝试了:
nix-shell -p "haskell.packages.ghc821.ghcWithPackages (p: with p; [text hspec (haskell.lib.enableLibraryProfiling lens)])" -j4 --run 'ghc Main.hs -prof'
这让我遇到了一个新错误:
src/Control/Lens/Internal/Getter.hs:26:1: error:
Could not find module ‘Data.Functor.Contravariant’
Perhaps you haven't installed the profiling libraries for package ‘contravariant-1.4’?
Use -v to see a list of the files searched for.
|
26 | import Data.Functor.Contravariant
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
因此,如果我可以将所有包映射到它们上面的 enableLibraryProfiling
,那么我想这可行。但目前我的 nix 知识还没有扩展到那么远。我怎么能那样做?这是正确的追求路径吗?
通过进一步了解 nix-repl
以及来自 ElvishJerricco 在 FreeNode 的 #reflex-frp 上的一些有用的指示,我能够构建这个,这似乎有效:
$ nix-shell -p "(haskell.packages.ghc821.extend (self: super: {mkDerivation = expr: super.mkDerivation (expr // { enableLibraryProfiling = true; });})).ghcWithPackages (p: with p; [text hspec lens])" -j4 --run 'ghc Main.hs -prof'
我想出了一个简单的方法,我正在为一个最大的博客 post 使用 Nix 进行 Haskell 开发。现在,这里只是分析部分的文本:
Nix 使这相当容易。首先,我们将以下内容添加到 ~/.config/nixpkgs/config.nix
:
{
packageOverrides = super: let self = super.pkgs; in
{
profiledHaskellPackages = self.haskellPackages.override {
overrides = self: super: {
mkDerivation = args: super.mkDerivation (args // {
enableLibraryProfiling = true;
});
};
};
};
}
现在在我们要分析的项目中,我们创建一个新的 profiling-shell.nix
:
let nixpkgs = import <nixpkgs> {};
orig = nixpkgs.pkgs.profiledHaskellPackages.callPackage ./default.nix {};
in (nixpkgs.pkgs.haskell.lib.doBenchmark orig).env
几乎与我们的正常 shell.nix
相同,除了我们刚刚全局定义的 profiledHaskellPackages
的用法。现在,调用 nix-shell profiling-shell.nix
将在启用分析的情况下重建我们项目中的 每个 依赖项。第一次这样做需要相当长的时间。幸运的是,这不会破坏我们的 Nix 存储 - 香草 nix-shell
似乎再次向我们展示了我们的常规依赖项,而无需重新下载或重建。
警告: nix-collect-garbage -d
将从我们的 Nix 商店中删除所有自定义构建的库,如果它们是,我们将不得不重新构建它们需要。
如果我们正在编写一个库,我们手头上最接近的可执行文件将是我们的基准套件。为此:
- 将
-prof
和-fprof-auto
添加到我们基准测试的 GHC 选项中 - 重新生成
default.nix
- 输入我们的分析shell:
nix-shell profiling-shell.nix
cabal configure --enable-library-profiling --enable-benchmarks
cabal build
dist/build/projname/projname-bench +RTS -p
- 查看生成的
projname-bench.prof
文件
根据结果,我们可以更改代码,删除分析选项,重新生成 default.nix
,并像往常一样在我们的 Nix Shell.