Skip to content

Conversation

@sternenseemann
Copy link
Member

We use resolveInHackageThenNixpkgs for build-tools and build-tool-depends. Since a "nix" package has been uploaded to Hackage on 2025-10-16, this has started to resolve to a Hackage packages which isn't the intent in any of these cases.

The fundamental problem here is that resolveInHackageThenNixpkgs is correct because of the strange semantics of build-tool-depends and build-tools. Both are intended for “A list of Haskell programs needed to build this component”.

build-tool-depends creates a dependency on an executable component of another (Cabal) package.

However, in the case of build-tools Cabal usually won't try to pull in third party dependencies. It uses other executables in the same package or tries looking the executable in a very small table it knows about. Otherwise, the user is expected to make sure that the executable is in PATH.

This allows for abusing this mechanism to depend on non-Haskell executables, as done in e.g. nix-paths. If Cabal doesn't know the executable, it just looks at PATH without enforcing that the program has been built and installed by Cabal.

Consequently, cabal2nix should try its best guessing the package the desired executable comes from or at least generate an attribute that allows users to pass the appropriate package in.

Given that the field is intended for “Haskell programs”, using resolveInHackageThenNixpkgs is the best option. Since this field is deprecated and largely ignored by Cabal, there may be temptation (even on my part) to interpret build-tools as a sort of declaration for dependencies on non-Haskell executables first and foremost. However, overall this is probably not a good idea because, at best, it creates an ad hoc feature that is only supported by cabal2nix, potentially worsening the experience for everyone else.

One thing we could do, is change buildToolNixName in a way that it can explicitly return whether to look for the package in the Hackage or Nixpkgs scope first. The slight problem with this is, of course, that we can't know for all eternity that no “Haskell program” with a clashing name exists.


The only package on Hackage affected by this is nix-paths which got broken by the upload of nix.

-  nix-paths = callPackage (
-    {
-      mkDerivation,
-      base,
-      nix,
-      process,
-    }:
-    mkDerivation {
-      pname = "nix-paths";
-      version = "1.0.1";
-      sha256 = "1y09wl1ihxmc9p926g595f70pdcsx78r3q5n5rna23lpq8xicdxb";
-      libraryHaskellDepends = [
-        base
-        process
-      ];
-      libraryToolDepends = [ nix ];
-      description = "Knowledge of Nix's installation directories";
-      license = lib.licenses.bsd3;
-      maintainers = [ lib.maintainers.peti ];
-    }
-  ) { };
+  nix-paths =
+    callPackage
+      (
+        {
+          mkDerivation,
+          base,
+          nix-build,
+          nix-env,
+          nix-hash,
+          nix-instantiate,
+          nix-store,
+          process,
+        }:
+        mkDerivation {
+          pname = "nix-paths";
+          version = "1.0.1";
+          sha256 = "1y09wl1ihxmc9p926g595f70pdcsx78r3q5n5rna23lpq8xicdxb";
+          libraryHaskellDepends = [
+            base
+            process
+          ];
+          libraryToolDepends = [
+            nix-build
+            nix-env
+            nix-hash
+            nix-instantiate
+            nix-store
+          ];
+          description = "Knowledge of Nix's installation directories";
+          license = lib.licenses.bsd3;
+          maintainers = [ lib.maintainers.peti ];
+        }
+      )
+      {
+        nix-build = null;
+        nix-env = null;
+        nix-hash = null;
+        nix-instantiate = null;
+        nix-store = null;
+      };
 
   nix-serve-ng = callPackage (
     {

We use resolveInHackageThenNixpkgs for build-tools and
build-tool-depends. Since a "nix" package has been uploaded to Hackage
on 2025-10-16, this has started to resolve to a Hackage packages which
isn't the intent in any of these cases.

The fundamental problem here is that resolveInHackageThenNixpkgs is
correct because of the strange semantics of build-tool-depends and
build-tools. _Both_ are intended for “A list of Haskell programs needed
to build this component”.

build-tool-depends creates a dependency on an executable component of
another (Cabal) package.

However, in the case of build-tools Cabal usually won't try to pull in
third party dependencies. It uses other executables in the same package
or tries looking the executable in a very small [table][] it knows
about. Otherwise, the user is expected to make sure that the executable
is in PATH.

This allows for abusing this mechanism to depend on non-Haskell
executables, as done in e.g. nix-paths. If Cabal doesn't know the
executable, it just looks at PATH without enforcing that the program has
been built and installed by Cabal.

Consequently, cabal2nix should try its best guessing the package the
desired executable comes from or at least generate an attribute that
allows users to pass the appropriate package in.

Given that the field is intended for “Haskell programs”, using
resolveInHackageThenNixpkgs is the best option. Since this field is
deprecated and largely ignored by Cabal, there may be temptation (even
on my part) to interpret build-tools as a sort of declaration for
dependencies on non-Haskell executables first and foremost. However,
overall this is probably not a good idea because, at best, it creates an
ad hoc feature that is only supported by cabal2nix, potentially
worsening the experience for everyone else.

One thing we could do, is change buildToolNixName in a way that it can
explicitly return whether to look for the package in the Hackage or
Nixpkgs scope first. The slight problem with this is, of course, that we
can't know for all eternity that no “Haskell program” with a clashing
name exists.

[table]: https://cabal.readthedocs.io/en/stable/cabal-package-description-file.html#buildtoolsmap
Copy link
Contributor

@wolfgangwalther wolfgangwalther left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't claim to understand all the possible implications etc., but your reasoning reads sound.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants