mirror of
https://github.com/serokell/haskell-nix-weeder.git
synced 2024-09-11 09:05:30 +03:00
Implement a library for running weeder in haskell.nix projects
This commit is contained in:
parent
d9843f63e1
commit
9867f52596
74
README.md
Normal file
74
README.md
Normal file
@ -0,0 +1,74 @@
|
||||
A bunch of hacks making [weeder](https://github.com/ndmitchell/weeder) work for projects built with [haskell.nix](https://github.com/input-output-hk/haskell.nix/)
|
||||
|
||||
### Usage example
|
||||
|
||||
Suppose you have a project with three packages in a layout like this (note that package name and directory name may differ):
|
||||
|
||||
```
|
||||
super-project
|
||||
|-- stack.yaml
|
||||
|-- super-package.cabal
|
||||
|-- …
|
||||
|-- prelude
|
||||
|-- super-prelude.cabal
|
||||
|-- …
|
||||
|-- super-tool
|
||||
|-- super-tool.cabal
|
||||
|-- …
|
||||
```
|
||||
|
||||
Import this library, providing nixpkgs package set:
|
||||
|
||||
```nix
|
||||
weeder-hacks = import (builtins.fetchTarball https://github.com/serokell/haskell-nix-weeder/archive/master.tar.gz) { pkgs = import <nixpkgs> {}; };
|
||||
```
|
||||
|
||||
In the call to `haskell-nix.stackProject` add options for each package to generate .dump-hi files used by weeder and save them to the build output:
|
||||
|
||||
```nix
|
||||
hs-pkgs = haskell-nix.stackProject {
|
||||
…
|
||||
modules = [{
|
||||
packages.super-package = {
|
||||
# tell the compiler to generate '.dump-hi' files
|
||||
package.ghcOptions = "-ddump-to-file -ddump-hi";
|
||||
|
||||
# save '.dump-hi' files to $out
|
||||
postInstall = weeder-hacks.collect-dump-hi-files;
|
||||
};
|
||||
|
||||
packages.super-prelude = {
|
||||
package.ghcOptions = "-ddump-to-file -ddump-hi";
|
||||
postInstall = weeder-hacks.collect-dump-hi-files;
|
||||
};
|
||||
|
||||
packages.super-tool = {
|
||||
package.ghcOptions = "-ddump-to-file -ddump-hi";
|
||||
postInstall = weeder-hacks.collect-dump-hi-files;
|
||||
};
|
||||
}];
|
||||
};
|
||||
```
|
||||
|
||||
Invoke `weeder-script` derivation which generates a script for running weeder. Provide `hs-pkgs` and `local-packages` parameters:
|
||||
|
||||
```nix
|
||||
weeder-script = weeder-hacks.weeder-script {
|
||||
# package set returned by `haskell-nix.stackProject`
|
||||
hs-pkgs = hs-pkgs;
|
||||
|
||||
# names and subdirectories of local packages
|
||||
local-packages = [
|
||||
{ name = "super-package"; subdirectory = "."; }
|
||||
{ name = "super-prelude"; subdirectory = "prelude"; }
|
||||
{ name = "super-tool"; subdirectory = "super-tool"; }
|
||||
];
|
||||
};
|
||||
```
|
||||
|
||||
Run nix-build on the `weeder-script` derivation to generate the script, running the script will run weeder. Note that running the script will copy '.dump-hi' files locally, polluting your local directory.
|
||||
|
||||
``` shell
|
||||
$ nix-build -A weeder-script -o run-weeder.sh # generates the script
|
||||
$ ./run-weeder.sh # runs weeder
|
||||
```
|
15
default.nix
Normal file
15
default.nix
Normal file
@ -0,0 +1,15 @@
|
||||
{ pkgs # nixpkgs package set
|
||||
}:
|
||||
|
||||
{
|
||||
# script to collect all *.dump-hi files produced by the compiler
|
||||
# into $out/dist-hi directory, preserving directory structure
|
||||
collect-dump-hi-files = ''
|
||||
mkdir $out/dist-hi
|
||||
cd dist
|
||||
find . -type f -name '*.dump-hi' -print0 | ${pkgs.cpio}/bin/cpio --pass-through --null --make-directories $out/dist-hi
|
||||
'';
|
||||
|
||||
# generates a script for running weeder
|
||||
weeder-script = { local-packages, hs-pkgs }: import ./weeder-script.nix { inherit pkgs local-packages hs-pkgs; };
|
||||
}
|
63
weeder-script.nix
Normal file
63
weeder-script.nix
Normal file
@ -0,0 +1,63 @@
|
||||
{ pkgs, # nixpkgs package set
|
||||
local-packages, # list of local haskell packages in the project and their subdirectories
|
||||
hs-pkgs # package set returned by `haskell-nix.stackProject`
|
||||
}:
|
||||
|
||||
with rec {
|
||||
# returns a list of all components (library + exes + tests + benchmarks) for a package
|
||||
get-package-components = pkg: with pkgs.lib;
|
||||
optional (pkg ? library) pkg.library
|
||||
++ attrValues pkg.exes
|
||||
++ attrValues pkg.tests
|
||||
++ attrValues pkg.benchmarks;
|
||||
|
||||
# script code that collects 'dist-hi' directories from the listed components and puts them to ${dir}/dist-hi
|
||||
get-package-dist-hi = components: dir: pkgs.lib.concatStringsSep "\n" (
|
||||
[ "mkdir -p ${dir}/dist-hi" ]
|
||||
++ builtins.map (cmp: ''
|
||||
cp -r ${cmp}/dist-hi/. ${dir}/dist-hi/
|
||||
chmod -R u+w ${dir}/dist-hi/ # make directories writeable because subsequent components may copy to the same directories
|
||||
'') components
|
||||
);
|
||||
|
||||
# a script that collects 'dist-hi' directories from all local packages
|
||||
# and puts them into corresponding subdirectories
|
||||
get-project-dist-hi = pkgs.lib.concatStringsSep "\n" (
|
||||
map ({ name, subdirectory }:
|
||||
get-package-dist-hi (get-package-components hs-pkgs.${name}.components) subdirectory
|
||||
) local-packages
|
||||
);
|
||||
|
||||
|
||||
# local package list mimicking the output of `stack query locals`
|
||||
local-packages-list = pkgs.writeText "locals" (builtins.toJSON (pkgs.lib.listToAttrs (
|
||||
map ({ name, subdirectory }:
|
||||
{ name = name; value = { path = subdirectory; }; }
|
||||
) local-packages
|
||||
)));
|
||||
|
||||
# fake stack binary to be used be weeder, which gives `stack query locals` output.
|
||||
# real stack would also start fetching indexes and dependencies, we use this script to avoid that
|
||||
fake-stack = pkgs.writeShellScriptBin "stack" ''
|
||||
if [ "$1" != "query" -o "$2" != "locals" ]; then
|
||||
echo "error: fake stack called with unexpected arguments:" "$@" > /dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
cat ${local-packages-list}
|
||||
'';
|
||||
|
||||
|
||||
# derivation which generates the final script for running weeder
|
||||
weeder-script = pkgs.writeScript "run-weeder.sh" ''
|
||||
# copy directories with '*.dump-hi' files to the package subdirectories
|
||||
${get-project-dist-hi}
|
||||
|
||||
# add fake stack to the path, it will be called by weeder to get local package list
|
||||
export PATH="${fake-stack}/bin:$PATH"
|
||||
|
||||
# run weeder
|
||||
${pkgs.haskellPackages.weeder}/bin/weeder stack.yaml --dist dist-hi
|
||||
'';
|
||||
};
|
||||
|
||||
weeder-script
|
Loading…
Reference in New Issue
Block a user