New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more flakes support and getting started guide #972
Conversation
This PR adds a `flake` function to haskell.nix projects. It can be used to transform the outputs of project into a flattened structure that can be used to make a `flake.nix` file for your project. Because the nix code and commands used are different a lot of stuff in the getting-started.md will not work with a `flake.nix`. So instead of trying to add a flake section to that guide this PR adds a new version for Nix Flake users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to comment.
outputs = { self, nixpkgs, haskellNix, flake-utils }: | ||
flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system: | ||
let | ||
pkgs = haskellNix.legacyPackages.${system}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be acomplished through an overlay, instead.
Like: preOverlays = [ devshell.overlay ] ++ haskell-nix.overlays;
(using flake-utils's simpleFlake)
|
||
# This is used by `nix develop .` to open a shell for use with | ||
# `cabal`, `hlint` and `haskell-language-server` | ||
devShell = project.shellFor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: I would appreciate intgration with the more expressive (& upcoming) numtide/devshell
overlays/haskell.nix
Outdated
# let | ||
# pkgs = haskellNix.legacyPackages.${system}; | ||
# project = pkgs.haskell-nix.project' { | ||
# src = ./.; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src = self;
(to teach convention)
This comment has been minimized.
This comment has been minimized.
See also: numtide/flake-utils#17 |
I'm going to be working on #963 then #980 for the next couple of days so feel free to send PRs to this branch if you like. This was my first foray into flakes so feel free to replace/change stuff. I presume those three files would be What is |
I'm still going about the journey of getting this right and will definitly report back (maybe today). I wasn't able to correctly pin nixpkgs, so It built for hours and hours. I'll therefore have a look at #991, too. |
This starts to work: # overlay.nix
{ self, name }: final: prev:
{
"${name}" =
let
thisHaskellProject = (
prev.haskell-nix.project' {
src = prev.haskell-nix.haskellLib.cleanGit {
inherit name;
src = ./.; # parses ./*.cabal
};
compiler-nix-name = "ghc865";
index-state = "2020-12-15T00:00:00Z";
plan-sha256 = "sha256-nekzAgYkCiZD6rO6Hhk3ZBTScAP54be66KFtxaRdXuU=";
}
);
thisHaskellProjectFlake = thisHaskellProject.flake {};
in
{
ghc = thisHaskellProject.ghcWithHoogle (ps: with ps; [
arduino-copilot # why do I need to do this??!? Shouldn't this be preset for thisHaskellProject as per cabal file?
]);
# defaultPackage = prev.callPackage ./nix/buildAndFlash.nix {inherit self;};
checks = thisHaskellProjectFlake.checks;
}
// thisHaskellProjectFlake.packages;
} # flake.nix
{
description = "CashBoxy is an electronic cashier & vault for bank notes";
# nixConfig.substituters = [ "https://hydra.iohk.io" ];
# To update all inputs:
# $ nix flake update --recreate-lock-file
inputs.nixpkgs.url = "github:NixOS/nixpkgs/master";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.devshell.url = "github:numtide/devshell/master";
# inputs.haskell-nix.url = "github:input-output-hk/haskell.nix/master";
# inputs.haskell-nix.url = "github:input-output-hk/haskell.nix?ref=hkm/more-flake-support";
inputs.haskell-nix.url = "github:input-output-hk/haskell.nix?rev=057c5f498d2804930c584a7dffa26a2e504be6c2";
outputs = { self, nixpkgs, flake-utils, devshell, haskell-nix }:
let
name = "CashBoxy";
in flake-utils.lib.simpleFlake {
inherit self name nixpkgs;
preOverlays = [ devshell.overlay haskell-nix.overlay ];
overlay = (import ./overlay.nix) {inherit self name;};
shell = (import ./devshell.nix) {inherit self name;};
};
} # devshell.nix
{ self, name }: { pkgs }:
with pkgs; mkDevShell {
inherit name;
packages = [
CashBoxy.ghc
];
bash = {
extra = ''
git config git-town.code-hosting-driver gitea
git config git-town.code-hosting-origin-hostname git.p1.rocks
git config git-town.main-branch-name master
'';
};
commands = [
{
help = "Spins up a local Hoogle: a Haskell API search engine";
name = "docs";
category = "arduino-copilot";
command = "${CashBoxy.ghc}/bin/hoogle server --local";
}
{
help = platformio.meta.description;
name = "pio";
category = "micro-controllers";
package = platformio;
}
{
help = "UART hex device monitoring";
command = "${platformio}/bin/pio device monitor -f hexlify";
name = "piohexmon";
category = "micro-controllers";
package = platformio;
}
{
help = "Transpile Main to C99, build & upload to board (platformio.ini)";
command = "cd $DEVSHELL_ROOT && ${CashBoxy.ghc}/bin/runghc Main && ${platformio}/bin/pio run -t upload";
name = "run";
category = "micro-controllers";
}
{
help = git-town.meta.description;
name = git-town.pname;
category = "utilities";
package = git-town;
}
];
} Cabal-Version: 2.2
Name: CashBoxy
Version: 0.1.0.0
Description: Please see the README at <https://git.p1.rocks/SideProjects/CashBoxy>
Author: Andres Luque
Maintainer: carlosluq1@hotmail.com
Copyright: 2020 Andres Luque
License: MIT
License-file: LICENSE
Extra-Source-Files:
README.md
ChangeLog.md
Source-Repository head
type: git
location: git@git.p1.rocks:SideProjects/CashBoxy.git
Executable Main
GHC-Options: -Wall -fno-warn-tabs
Default-Language: Haskell2010
Main-Is: Main.hs
Build-Depends:
arduino-copilot -- it's already here ?!
, base >=4.6 && <5 |
Aside: why devshell is cool... $ nix develop
🔨 Welcome to CashBoxy
[arduino-copilot]
docs - Spins up a local Hoogle: a Haskell API search engine
[general commands]
menu - prints this menu
[micro-controllers]
pio - An open source ecosystem for IoT development
piohexmon - UART hex device monitoring
run - Transpile Main to C99, build & upload to board (platformio.ini)
[utilities]
git-town - Generic, high-level git support for git-flow workflows |
# Conflicts: # flake.nix
I tried out simpleFlake, but I had some problems:
I have updated the example to use an overlay in a similar way to The devshell stuff should be in another PR and it would be nice if it could be used in I have also added nixpkgs inputs to this PR as I found it was very handy to be able to use the |
bors try |
tryBuild succeeded: |
This looks fantastic. Thanks! |
Hello! I'm trying to try this out but I've come to an error that I'm not sure how to fix. I have a working { # Fetch the latest haskell.nix and import its default.nix
haskellNix ? import (builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/ef6ca0f431fe3830c25cb2d185367245c1cce894.tar.gz") {}
# haskellNix ? import (builtins.fetchTarball "https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz") {}
# # For LLVM
# , enableLLVMAssertions ? true # TODO: Fix
, compiler ? "ghc884"
}:
let
# haskell.nix provides access to the nixpkgs pins which are used by our CI,
# hence you will be more likely to get cache hits when using these.
# But you can also just use your own, e.g. '<nixpkgs>'.
nixpkgsSrc = haskellNix.sources.nixpkgs-2003;
# haskell.nix provides some arguments to be passed to nixpkgs, including some
# patches and also the haskell.nix functionality itself as an overlay.
nixpkgsArgs = haskellNix.nixpkgsArgs;
telomare_jumper = pkgs.stdenv.mkDerivation {
name = "telomareJumper";
src = ./cbits;
buildInputs = [ pkgs.boehmgc ];
};
telomareOverlays = [ (self: super: {
jumper = telomare_jumper;
gc = self.boehmgc;
llvm-config = self.llvm_9;
alex = self.haskellPackages.alex;
}) ];
# import nixpkgs with overlays
pkgs = (import nixpkgsSrc (nixpkgsArgs // { overlays = nixpkgsArgs.overlays ++ telomareOverlays;}));
in
pkgs.haskell-nix.cabalProject {
src = pkgs.haskell-nix.cleanSourceHaskell {
src = ./.;
name = "telomare";
};
compiler-nix-name = compiler;
pkg-def-extras = with pkgs.haskell.lib; [
(hackage: {
llvm-hs = hackage.llvm-hs."9.0.1".revisions.default;
llvm-hs-pure = hackage.llvm-hs-pure."9.0.0".revisions.default;
})
];
modules = [
{ reinstallableLibGhc = true; }
];
} And now I would really like to turn it into a flake. My unsuccessful attempt is: {
description = "Nix flake for Telomare";
inputs.haskellNix.url = "github:input-output-hk/haskell.nix";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils, haskellNix }:
flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
let
overlays = [ haskellNix.overlay
(final: prev: {
# This overlay adds our project to pkgs
# jumper = telomare_jumper;
jumper = final.stdenv.mkDerivation {
name = "telomareJumper";
src = ./cbits;
buildInputs = [ final.boehmgc ];
};
gc = final.boehmgc;
llvm-config = final.llvm_9;
alex = final.haskellPackages.alex;
telomare = final.haskell-nix.cabalProject {
src = final.haskell-nix.cleanSourceHaskell {
src = ./.;
name = "telomare";
};
compiler-nix-name = "ghc884";
pkg-def-extras = with final.haskell.lib; [
(hackage: {
llvm-hs = hackage.llvm-hs."9.0.1".revisions.default;
llvm-hs-pure = hackage.llvm-hs-pure."9.0.0".revisions.default;
})
];
modules = [
{ reinstallableLibGhc = true; }
];
};
})
];
pkgs = import nixpkgs { inherit system overlays; };
flake = pkgs.telomare.flake {};
in flake // {
# Built by `nix build .`
defaultPackage = flake.packages."telomare:exe:telomare-exe";
# This is used by `nix develop .` to open a shell for use with
# `cabal`, `hlint` and `haskell-language-server`
devShell = pkgs.telomare.shellFor {
tools = {
cabal = "latest";
hlint = "latest";
haskell-language-server = "latest";
};
};
});
} Which errors with This is the full error with trace turned on: ╭─hhefesto@Olimpo ~/src/telomare ‹nix-flake*›
╰─$ nix build --show-trace
warning: Git tree '/home/hhefesto/src/telomare' is dirty
error: --- RestrictedPathError ------------------------------------------------------------------------------------------------------------------------------------------------------- nix
access to path '/nix/store/r4bms7fx16cavkzb8y1kk0zlv0fp6p9k-telomare' is forbidden in restricted mode
--------------------------------------------------------------------------------------- show-trace ---------------------------------------------------------------------------------------
trace: while evaluating 'readIfExists'
at: (2:25) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/lib/call-cabal-project-to-nix.nix
1| { dotCabal, pkgs, runCommand, evalPackages, symlinkJoin, cacert, index-state-hashes, haskellLib, materialize }@defaults:
2| let readIfExists = src: fileName:
| ^
3| let origSrcDir = src.origSrcSubDir or src;
trace: from call site
at: (18:26) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/lib/call-cabal-project-to-nix.nix
17| , cabalProjectFileName ? "cabal.project"
18| , cabalProject ? readIfExists src cabalProjectFileName
| ^
19| , cabalProjectLocal ? readIfExists src "${cabalProjectFileName}.local"
trace: while evaluating anonymous lambda
at: (9:1) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/lib/call-cabal-project-to-nix.nix
8| in
9| { name ? src.name or null # optional name for better error messages
| ^
10| , src
trace: from call site
at: (502:36) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/overlays/haskell.nix
501| args = { caller = "cabalProject'"; } // args';
502| callProjectResults = callCabalProjectToNix args;
| ^
503| in let pkg-set = mkCabalProjectPkgSet
trace: while evaluating anonymous lambda
at: (5:1) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/lib/import-and-filter-project.nix
4| { pkgs, haskellLib }:
5| { projectNix, sourceRepos, src }:
| ^
6| let
trace: from call site
at: (505:31) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/overlays/haskell.nix
504| { inherit compiler-nix-name;
505| plan-pkgs = importAndFilterProject {
| ^
506| inherit (callProjectResults) projectNix sourceRepos src;
trace: while evaluating the attribute 'buildPackages.haskell-nix.compiler."${(((plan-pkgs).pkgs hackage)).compiler.nix-name}".version'
at: (362:7) in file: /nix/store/ydv1dhahymi31sfyy8bpacz3a9xzs46k-source/lib/attrsets.nix
361| inherit name;
362| value = f name (catAttrs name sets);
| ^
363| }) names);
trace: while evaluating 'mkCabalProjectPkgSet'
at: (152:13) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/overlays/haskell.nix
151| mkCabalProjectPkgSet =
152| { plan-pkgs # Path to the output of plan-to-nix
| ^
153| , pkg-def-extras ? []
trace: from call site
at: (503:30) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/overlays/haskell.nix
502| callProjectResults = callCabalProjectToNix args;
503| in let pkg-set = mkCabalProjectPkgSet
| ^
504| { inherit compiler-nix-name;
trace: while evaluating the attribute 'hsPkgs'
at: (518:43) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/overlays/haskell.nix
517| project = addProjectAndPackageAttrs rec {
518| inherit (pkg-set.config) hsPkgs;
| ^
519| inherit pkg-set;
trace: while evaluating the attribute 'hsPkgs'
at: (538:15) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/overlays/haskell.nix
537| in rawProject // rec {
538| hsPkgs = final.lib.mapAttrs (n: package':
| ^
539| if package' == null
trace: while evaluating 'cabalProject'
at: (628:13) in file: /nix/store/di7w1g4s2fyh4b4814sawg7n1pdvjaq9-source/overlays/haskell.nix
627| cabalProject =
628| { src, compiler-nix-name, ... }@args':
| ^
629| let
trace: from call site
at: (28:22) in file: /nix/store/w0hlikdyaq24gmh17ssznyvhhfqzi9as-source/flake.nix
27|
28| telomare = final.haskell-nix.cabalProject {
| ^
29| src = final.haskell-nix.cleanSourceHaskell {
trace: while evaluating the attribute 'telomare.flake'
at: (28:11) in file: /nix/store/w0hlikdyaq24gmh17ssznyvhhfqzi9as-source/flake.nix
27|
28| telomare = final.haskell-nix.cabalProject {
| ^
29| src = final.haskell-nix.cleanSourceHaskell {
trace: while evaluating anonymous lambda
at: (7:68) in file: /nix/store/w0hlikdyaq24gmh17ssznyvhhfqzi9as-source/flake.nix
6| outputs = { self, nixpkgs, flake-utils, haskellNix }:
7| flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
| ^
8| let
trace: from call site
at: (69:17) in file: /nix/store/m3qzm0c5r708l5h8gn7dwrlciib37x0d-source/default.nix
68| let
69| ret = f system;
| ^
70| op = attrs: key:
trace: while evaluating 'op'
at: (67:19) in file: /nix/store/m3qzm0c5r708l5h8gn7dwrlciib37x0d-source/default.nix
66| let
67| op = attrs: system:
| ^
68| let
trace: from call site
at: (79:5) in file: /nix/store/m3qzm0c5r708l5h8gn7dwrlciib37x0d-source/default.nix
78| in
79| builtins.foldl' op { } systems
| ^
80| ;
trace: while evaluating 'eachSystem'
at: (65:25) in file: /nix/store/m3qzm0c5r708l5h8gn7dwrlciib37x0d-source/default.nix
64| #
65| eachSystem = systems: f:
| ^
66| let
trace: from call site
at: (7:5) in file: /nix/store/w0hlikdyaq24gmh17ssznyvhhfqzi9as-source/flake.nix
6| outputs = { self, nixpkgs, flake-utils, haskellNix }:
7| flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
| ^
8| let
trace: while evaluating 'outputs'
at: (6:13) in file: /nix/store/w0hlikdyaq24gmh17ssznyvhhfqzi9as-source/flake.nix
5| inputs.flake-utils.url = "github:numtide/flake-utils";
6| outputs = { self, nixpkgs, flake-utils, haskellNix }:
| ^
7| flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
trace: from call site
at: (45:21) from string
44|
45| outputs = flake.outputs (inputs // { self = result; });
| ^
46|
trace: while evaluating anonymous lambda
at: (10:13) from string
9| builtins.mapAttrs
10| (key: node:
| ^
11| let
trace: from call site
trace: while evaluating the attribute 'root'
trace: while evaluating anonymous lambda
at: (2:23) from string
1|
2| lockFileStr: rootSrc: rootSubdir:
| ^
3|
trace: from call site Any guidance would be very much appreciated. |
Explicitly adding For completeness, this is my flake updated: {
description = "Nix flake for Telomare";
inputs.haskellNix.url = "github:input-output-hk/haskell.nix";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils, haskellNix }:
flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
let
overlays = [ haskellNix.overlay
(final: prev: {
# This overlay adds our project to pkgs
jumper = final.stdenv.mkDerivation {
name = "telomareJumper";
src = ./cbits;
buildInputs = [ final.boehmgc ];
};
gc = final.boehmgc;
llvm-config = final.llvm_9;
alex = final.haskellPackages.alex;
telomare = final.haskell-nix.cabalProject {
# If these null parameters are absent, you get a RestrictedPathError error
# from trying to do readIfExists on cabal.project file
cabalProjectFreeze = null;
cabalProject = null;
cabalProjectLocal = null;
src = final.haskell-nix.cleanSourceHaskell {
src = ./.;
name = "telomare";
};
compiler-nix-name = "ghc884";
pkg-def-extras = with final.haskell.lib; [
(hackage: {
llvm-hs = hackage.llvm-hs."9.0.1".revisions.default;
llvm-hs-pure = hackage.llvm-hs-pure."9.0.0".revisions.default;
})
];
modules = [
{ reinstallableLibGhc = true; }
];
};
})
];
pkgs = import nixpkgs { inherit system overlays; };
flake = pkgs.telomare.flake {};
in flake // {
# Built by `nix build .`
defaultPackage = flake.packages."telomare:exe:telomare-exe";
# This is used by `nix develop .` to open a shell for use with
# `cabal`, `hlint` and `haskell-language-server`
devShell = pkgs.telomare.shellFor {
tools = {
cabal = "latest";
hlint = "latest";
haskell-language-server = "latest";
};
};
});
} |
This PR adds a `flake` function to haskell.nix projects. It can be used to transform the outputs of project into a flattened structure that can be used to make a `flake.nix` file for your project. Because the nix code and commands used are different a lot of stuff in the getting-started.md will not work with a `flake.nix`. So instead of trying to add a flake section to that guide this PR adds a new version for Nix Flake users.
This PR adds a
flake
function to haskell.nix projects. It canbe used to transform the outputs of project into a flattened structure
that can be used to make a
flake.nix
file for your project.Because the nix code and commands used are different a lot of stuff in
the getting-started.md will not work with a
flake.nix
. So insteadof trying to add a flake section to that guide this PR adds a new
version for Nix Flake users.