input-output-hk / haskell.nix

Alternative Haskell Infrastructure for Nixpkgs
https://input-output-hk.github.io/haskell.nix
Apache License 2.0
556 stars 240 forks source link

Capitalised Cabal stanzas ignored (e.g. `Library`) #415

Closed Warbo closed 1 year ago

Warbo commented 4 years ago

I was getting some errors from haskell.nix about a configFiles parameter being missing in some of my projects. I think I've tracked it down to a dependency on the lazysmallcheck2012 package: when I use cabalProject on that repo the resulting components has no library attr, and the tests, benchmarks, exes, etc. attrs are all empty. I think it may be due to the .cabal file using capitalised stanzas, e.g.

Library
  Default-Language:    Haskell2010
  Exposed-modules:     Test.LazySmallCheck2012
                     , Test.LazySmallCheck2012.Core
                     , Test.LazySmallCheck2012.FunctionalValues
                     , Test.LazySmallCheck2012.FunctionalValues.Instances
                     , Test.LazySmallCheck2012.Instances
                     , Test.LazySmallCheck2012.Stats
                     , Test.LazySmallCheck2012.TH
                     , Test.PartialValues
  Build-depends:       base >= 4 && < 5
                     , deepseq >= 1.4 && < 1.5
                     , ghc >= 8 && < 9
                     , syb >= 0.7 && < 0.8
                     , template-haskell >= 2.11 && < 2.15
                     , uniplate >= 1.6 && < 1.7

Expected

The components to contain a library entry, a tests.functionality entry and a benchmarks.performance entry.

Got

No library, empty tests and empty benchmarks.

Reproducing

Clone that repo and add the following default.nix (this pins a fork of haskell.nix which adds i686 support; I assume that's irrelevant for this issue):

with builtins;
with rec {
  nixpkgsSrc = fetchTarball {
    name   = "nixpkgs1909";
    url    = https://github.com/NixOS/nixpkgs/archive/19.09.tar.gz;
    sha256 = "0mhqhq21y5vrr1f30qd2bvydv4bbbslvyzclhw0kdxmkgg3z4c92";
  };

  # TODO: Point this at IOHK's repo once i686 support is included
  # See https://github.com/angerman/old-ghc-nix/pull/4
  haskellNixSrc = fetchTarball {
    name   = "haskell-nix";
    url    = https://github.com/Warbo/haskell.nix/archive/499a761.tar.gz;
    sha256 = "1pnkywswfa71hgc2c3g2cijfk9nysbpyh6jjh455h810n4yhs522";
  };

  pkgs = import nixpkgsSrc { overlays = import "${haskellNixSrc}/overlays"; };
};
pkgs.haskell-nix.cabalProject {
  src         = pkgs.haskell-nix.haskellLib.cleanGit { src = ./.; };
  ghc         = pkgs.buildPackages.pkgs.haskell-nix.compiler.ghc865;
  index-state = "2020-01-11T00:00:00Z";
}

With that in place, we can inspect the result in nix repl:

$ nix repl
Welcome to Nix version 2.2.2. Type :? for help.

nix-repl> with builtins; with { x = (import ./.).lazysmallcheck2012; }; attrNames x.components
trace: Using index-state: 2020-01-11T00:00:00Z
trace: Get `plan-sha256` with `nix-hash --base32 --type sha256 /nix/store/15r9z00cgl4qrx09vaapkpiacd6kfjld-plan-to-nix-pkgs/`
querying info about missing paths[ "all" "benchmarks" "exes" "foreignlibs" "sublibs" "tests" ]

nix-repl> with builtins; with { x = (import ./.).lazysmallcheck2012; }; attrNames x.components.sublibs
[ ]

nix-repl> with builtins; with { x = (import ./.).lazysmallcheck2012; }; x.components.sublibs
{ }

nix-repl> with builtins; with { x = (import ./.).lazysmallcheck2012; }; x.components.foreignlibs
{ }

nix-repl> with builtins; with { x = (import ./.).lazysmallcheck2012; }; x.components.exes
{ }

nix-repl> with builtins; with { x = (import ./.).lazysmallcheck2012; }; x.components.benchmarks
{ }

nix-repl> with builtins; with { x = (import ./.).lazysmallcheck2012; }; x.components.tests
{ }

Note that my fork of lazysmallcheck2012 only adds support for GHC 8's template-haskell versions; I didn't write the package, or its .cabal file, so I expect there are others out there with such capitalisation.

angerman commented 4 years ago

That is indeed a very curious find and one that should have broken a lot of existing packages already. Can you confirm the does now happen with lowercase names?

Could you also post the output of cabal-to-nix (from the https://github.com/input-output-hk/nix-tools) of the.cabal` file?

Warbo commented 4 years ago

I've played around with this some more, and it looks like the capitalisation of the .cabal filename is the cause, not the contents of the file:

chris@nixos:~/DELETEME/lazysmallcheck2012$ echo ':p (import ./.).lazysmallcheck2012.components' | nix repl
Welcome to Nix version 2.2.2. Type :? for help.

trace: Using index-state: 2020-01-11T00:00:00Z
trace: Get `plan-sha256` with `nix-hash --base32 --type sha256 /nix/store/nxav4z7xf2pgq2h4xkws0q8yw3fahwsn-plan-to-nix-pkgs/`
[1 built, 0.0 MiB DL] building plan-to-nix-pkgs: - criterion-1.5.6.1 (exe:criterion-repo{ all = «error: The option `packages.lazysmallcheck2012.components.all' is used but not defined.»; benchmarks = { }; exes = { }; foreignlibs = { }; sublibs = { }; tests = { }; }

[1 built, 0.0 MiB DL]
chris@nixos:~/DELETEME/lazysmallcheck2012$ mv LazySmallCheck2012.cabal lazysmallcheck2012.cabal
chris@nixos:~/DELETEME/lazysmallcheck2012$ echo ':p (import ./.).lazysmallcheck2012.components' | nix repl
Welcome to Nix version 2.2.2. Type :? for help.

trace: Using index-state: 2020-01-11T00:00:00Z
trace: Get `plan-sha256` with `nix-hash --base32 --type sha256 /nix/store/g74b5jcvsrv6msryw1k9hx9c82qylsxz-plan-to-nix-pkgs/`
[1 built, 0.0 MiB DL] { all = «derivation /nix/store/74w3rw6qrw6l0aqp6bbkglwjanybx9yw-lazysmallcheck2012-1.1.0-all.drv»; benchmarks = { performance = «derivation /nix/store/25qn5bncgg4az8hgvqnlifkwm8qdh8cy-lazysmallcheck2012-1.1.0-bench-performance.drv»; }; exes = { }; foreignlibs = { }; library = «derivation /nix/store/i2ri80s3ddlvxx3icdi7kqvp24mqsl4z-lazysmallcheck2012-1.1.0-lib-lazysmallcheck2012.drv»; sublibs = { }; tests = { functionality = «derivation /nix/store/mf2dhc3bn0fjx7psdajvip4y8x3anp99-lazysmallcheck2012-1.1.0-test-functionality.drv»; }; }

[1 built, 0.0 MiB DL]

Neither capitalised or lowercase contents work for LazySmallCheck2012.cabal; both work for lazysmallcheck2012.cabal I don't know if Cabal enforces a specific choice of filename which this package is violating, but I can imagine such capitalisation coming from Windows.

I haven't tried cabal-to-nix directly yet.

Warbo commented 4 years ago

cabal-to-nix seems to work when given the .cabal file's filename:

$ cabal-to-nix LazySmallCheck2012.cabal 
let
  buildDepError = pkg:
    builtins.throw ''
      The Haskell package set does not contain the package: ${pkg} (build dependency).

      If you are using Stackage, make sure that you are using a snapshot that contains the package. Otherwise you may need to update the Hackage snapshot you are using, usually by updating haskell.nix.
      '';
  sysDepError = pkg:
    builtins.throw ''
      The Nixpkgs package set does not contain the package: ${pkg} (system dependency).

      You may need to augment the system package mapping in haskell.nix so that it can be found.
      '';
  pkgConfDepError = pkg:
    builtins.throw ''
      The pkg-conf packages does not contain the package: ${pkg} (pkg-conf dependency).

      You may need to augment the pkg-conf package mapping in haskell.nix so that it can be found.
      '';
  exeDepError = pkg:
    builtins.throw ''
      The local executable components do not include the component: ${pkg} (executable dependency).
      '';
  legacyExeDepError = pkg:
    builtins.throw ''
      The Haskell package set does not contain the package: ${pkg} (executable dependency).

      If you are using Stackage, make sure that you are using a snapshot that contains the package. Otherwise you may need to update the Hackage snapshot you are using, usually by updating haskell.nix.
      '';
  buildToolDepError = pkg:
    builtins.throw ''
      Neither the Haskell package set or the Nixpkgs package set contain the package: ${pkg} (build tool dependency).

      If this is a system dependency:
      You may need to augment the system package mapping in haskell.nix so that it can be found.

      If this is a Haskell dependency:
      If you are using Stackage, make sure that you are using a snapshot that contains the package. Otherwise you may need to update the Hackage snapshot you are using, usually by updating haskell.nix.
      '';
in { system, compiler, flags, pkgs, hsPkgs, pkgconfPkgs, ... }:
  {
    flags = {};
    package = {
      specVersion = "1.10";
      identifier = { name = "lazysmallcheck2012"; version = "1.1.0"; };
      license = "BSD-3-Clause";
      copyright = "";
      maintainer = "jason at cs.york.ac.uk";
      author = "Jason S. Reich";
      homepage = "https://github.com/UoYCS-plasma/LazySmallCheck2012";
      url = "";
      synopsis = "Lazy SmallCheck with functional values and existentials!";
      description = "A property-based testing library enables users to perform\nlightweight verification of software. This package presents\nimprovements to the Lazy SmallCheck property-based testing\nlibrary. Users can now test properties that quantify over\nfirst-order functional values and nest universal and\nexistential quantifiers in properties. When a property\nfails, Lazy SmallCheck now accurately expresses the\npartiality of the counterexample. The necessary\narchitectural changes to Lazy SmallCheck result in a\nperformance speed-up.";
      buildType = "Simple";
      };
    components = {
      "library" = {
        depends = [
          (hsPkgs."base" or (buildDepError "base"))
          (hsPkgs."deepseq" or (buildDepError "deepseq"))
          (hsPkgs."ghc" or (buildDepError "ghc"))
          (hsPkgs."syb" or (buildDepError "syb"))
          (hsPkgs."template-haskell" or (buildDepError "template-haskell"))
          (hsPkgs."uniplate" or (buildDepError "uniplate"))
          ];
        buildable = true;
        };
      tests = {
        "functionality" = {
          depends = [
            (hsPkgs."base" or (buildDepError "base"))
            (hsPkgs."deepseq" or (buildDepError "deepseq"))
            (hsPkgs."ghc" or (buildDepError "ghc"))
            (hsPkgs."syb" or (buildDepError "syb"))
            (hsPkgs."template-haskell" or (buildDepError "template-haskell"))
            (hsPkgs."uniplate" or (buildDepError "uniplate"))
            ];
          buildable = true;
          };
        };
      benchmarks = {
        "performance" = {
          depends = [
            (hsPkgs."base" or (buildDepError "base"))
            (hsPkgs."criterion" or (buildDepError "criterion"))
            (hsPkgs."deepseq" or (buildDepError "deepseq"))
            (hsPkgs."syb" or (buildDepError "syb"))
            ];
          buildable = true;
          };
        };
      };
    } // rec { src = (pkgs.lib).mkDefault ./.; }
angerman commented 4 years ago

@Warbo I think you've found a legitimate bug in the cabalProject function.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.