-
Notifications
You must be signed in to change notification settings - Fork 237
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
Use unit id for package key #2239
Conversation
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This reverts commit 081da23.
e8122db
to
278df11
Compare
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.
It looks like old code paths and new code paths are merged together and separated by conditionals. This makes it quite complex to follow. Would it possible to have, rather than a top level switch, separate entrypoints for the two code paths? Then common code will be available as functions to call (or modules to import). I can try to see what that would look like.
Why do we need addPackageKeys
everywhere?
Am I understanding correctly that we are going back to using plan.json rather than integrating with cabal-install at the Haskell level? There are many details that are not available in plan.json (e.g. documentation, profiling, etc).
type = listOf str; | ||
default = []; | ||
}; | ||
packages = if !config.use-package-keys |
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.
Uh, is this changing the type of packages based on a configured value? Maybe config
is from a different module? This seems a bit scary to me, it might lead to recursion issues that will be hard to debug.
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.
Why do we need
addPackageKeys
everywhere?
I had to change the type of packages
to make pkgs.lib.modules.mkAliasDefinitions
work here:
value = pkgs.lib.modules.mkAliasDefinitions (options.packages.${p.pkg-name}); |
This means we need to know the list of all the keys for packages
when creating the type.
If you add an override for a package in the plan it should work fine, because we include every package id and name in package-keys
here:
package-keys = map (p: p.pkg-name) config.plan-json.install-plan ++ map (p: p.id) config.plan-json.install-plan; |
If you try to override a package that is not in the plan it will now raise an error. This might actually be quite a nice feature.
However we often want to include overrides that only apply to some plans (for instance packages only included for a given platform). In those cases we can either try to duplicate the logic that determines if the package will be in the plan and only include the override when it is, or we can add it to package-keys
.
To make that second option a little easier, addPackageKeys
takes the attrNames
for packages
and includes them in package-keys
(it can only do this for packages
and not config.packages
to avoid infinite recursion).
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.
it might lead to recursion issues that will be hard to debug
It scares me too, but I think it might be fairly safe. Do you have a concrete example of something that might fail?
I'm not too worried about use-package-keys
since it is not something anyone should need to use directly (perhaps we could call it is-cabal-project
or something).
package-keys
is like a way of forward declaring the packages you are going to override. One thing does not work due to infinite recursion is getting addPackageKeys
from the module arguments in any way.
{modules = [({haskellLib, ...}: haskellLib.addPackageKeys { package.x.flags.y = false; })];}
However that is not really related to the addPackageKeys
function. You get the same infinite recursion issue if you reference any of the module args at the top level. It even happens if you try to look up a non existent function, for instance this fails with the same error: infinite recursion encountered
:
{modules = [({haskellLib, ...}: haskellLib.foo {})];}
These alternatives all work:
{modules = [(haskellLib.addPackageKeys {packages.x.flags.y = false;})];} # Where haskellLib is in scope
{modules = [(rec {package-keys = builtins.attrNames packages; packages.x.flags.y = false;})];}
{modules = [((x: x // {package-keys = builtins.attrNames x.packages;}) {packages.x.flags.y = false;})];}
This PR fixes the worst of duplicate package issues in haskell.nix. It is still using the I did add the "available targets" information to They are used to populate the haskell.nix/modules/install-plan/redirect.nix Lines 1 to 51 in a479589
|
The error if a named package is not in the plan (and not added to
|
Currently haskell.nix uses the package name as the key for
hsPkgs
. This means that only one package with a given name can exist for a given plan. When the cabal planner makes a plan it often includes more than one version of a given package. For instance if a package is needed for abuild-tool-depends
it is likely that it may have requirements that do not match the rest of the project.When there are two versions of the same package in the plan haskell.nix currently chooses the most recent one. This is often the correct choice for the main plan (though it may not always be), but it can sometimes be the wrong choice for the
build-tool-depends
.This PR aims to resolve this issue by using the unit ID from the
plan.json
file as the key forhsPkgs
. This means that we can much more closely match the plan.plan.json
as much as possible (including dependencies and cabal flag settings).plan.json
.hsPkgs.${pkg-name}
to unit ID based entries.packages.${pkg-name}...
(these are applied to all the versions of the package).pre-existing
packages based on theplan.json
dependencies.