srid / srid/haskell-flake

Near-impossible to specify `extra-libraries` not existing in Nixpkgs

Open
#198 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Nix
Stars
240
Forks
27
PR merge metrics
No merged PRs in 30d

Description

Problem description

The repository JaSpa/haskell-flakes-with-extra-libraries demonstrates the problem.

I want to write a Haskell executable depending on the gvc library distributed with Graphviz. To instruct GHC/cabal about the link-time requirement I add extra-libraries: gvc to the package description in example.cabal.

Main.hs contains a simple executable which calls two functions from the mentioned library and prints their results. The script run-outside-of-nix.sh demonstrates that the executable is functional. It uses the global GHC/cabal and Graphviz obtained through nix.

Broken haskell-flakes setup

Building through the bare-bones haskell-flakes setup does not work (complete error message below). It complains about a required argument gvc which was not provided. But this makes sense. cabal2nix translates the extra-libraries: gvc into an argument { …, gvc }: … but there is no gvc package in Nixpkgs.

nix error message
error: anonymous function at /nix/store/95jn322pl7yhy3ggz04qrcvhgl33y0bc-cabal2nix-example/default.nix:1:1 called without required argument 'gvc'

       at /nix/store/2ayipj5kgy67231fvbl8agsl591kanw8-source/pkgs/development/haskell-modules/make-package-set.nix:97:40:

           96|       # this wraps the `drv` function to add `scope` and `overrideScope` to the result.
           97|       drvScope = allArgs: ensureAttrs (drv allArgs) // {
             |                                        ^
           98|         inherit scope;
(use '--show-trace' to show detailed location information)
cabal2nix output
{ mkDerivation, base, gvc, lib }:
mkDerivation {
  pname = "example";
  version = "0.1.0.0";
  src = ./.;
  isLibrary = false;
  isExecutable = true;
  executableHaskellDepends = [ base ];
  executableSystemDepends = [ gvc ];
  license = "unknown";
  mainProgram = "example";
}

Working ordinary Nixpkgs setup

I defined a flake package “ordinary” in flake.nix which demonstrates that this is not a problem when using the ordinary Nixpkgs infrastructure: callCabal2nix is called with the argument { gvc = pkgs.graphviz; }. nix-build .#ordinary succeeds and produces a runnable binary.

Workaround

There exists a workaround. It is possible to define gvc as an alias for Graphviz using a Nixpkgs overlay. This exists commented out in flake.nix. Enabling these lines allows the haskell-flakes package to build successfully. However, using Nixpkgs overlays is quite un-ergonomic in conjunction with flake-parts.

{
    _module.args.pkgs = import inputs.nixpkgs {
      inherit system;
      overlays = [
        (final: prev: {gvc = final.graphviz;})
      ];
    };
    haskellProjects.default = {};
}

Achieving this through haskell-flakes

Is there a way to achieve this using haskell-flakes? I tried various incantations using either packages or settings but ultimately I don't think this can work with the current version.

https://github.com/srid/haskell-flake/blob/ddc704f3f62d3d3569ced794b534e8fd065c379c/nix/build-haskell-package.nix#L37
The empty { } argument is the place where the { gvc = pkgs.graphviz; } would have to appear.

There are two ways I can imagine how this might work in the future: packages.<name>.custom could specify any kind of package. These packages don't go through callCabal2nix/callHackage but instead are added to the package set as-is. Instead of adding a “global” alias for Graphviz it could then be scoped to haskellProjects:

{
    haskellProjects.default = {
        packages = {
            gvc.custom = pkgs.graphviz;
        };
    };
}

However, this still is quite coarse. Maybe instead there could be a new setting args which takes the place of { } mentioned above. (It's unclear to me if this would fit with haskell-flakes architecture.)

{
    haskellProjects.default = {
        settings.example.args = {
            gvc = pkgs.graphviz;
        };
    };
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with nix/build-haskell-package.nix around line 37 and compare its empty argument set with the working callCabal2nix invocation in flake.nix. Trace how haskellProjects package and settings arguments are assembled, then define the supported configuration boundary. Done means an extra-libraries name such as gvc can be mapped to pkgs.graphviz within a Haskell project without a global overlay.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
build-system
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.