-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
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
haskellPackages.shellFor: Fix ghc calls #46453
Conversation
I think I had a similar problem domenkozar/hie-nix#27. even though I didn't use shellFor |
Great work! Now I wonder, can't we use Not that that's a prerequisite for merging this PR. I think we should merge this now and see how to DRY it later. |
@basvandijk Hmm, I usually don't like introducing bad code into nixpkgs. I'll see if I can refactor it in the next couple days. If I can't, then we should probably merge this, as it clearly fixes a bug and potentially lots of frustration. Also this might need backporting Also pinging @ElvishJerricco who introduced the function originally in #36393 |
This is not the only place this logic is duplicated in the haskell infra, IIRC. We really need a generic solution to this... |
e6dd03d
to
b6b7236
Compare
@basvandijk @peti @ElvishJerricco Please take another look, I cleaned up most of the duplication |
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 like the idea of defining haskellDrv.env
in terms of shellFor
!
haskellDrv = callPackageWithScope defaultScope drv args; | ||
in haskellDrv // { | ||
env = self.shellFor { packages = p: [ haskellDrv ]; }; | ||
}; |
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 think this will break if you try to use (overrideCabal haskellDrv ...).env
. It's probably easiest to either declare this in passthru
in generic-builder.nix
, or to use overrideCabal
here to add it to passthru
. I'd prefer the former.
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.
The problem with the former is that shellFor
doesn't work with a "raw" derivation, because it depends on .overrideCabal
being available, which is only added with callPackage
.
I'll test if this really breaks it.
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.
Ah. Then yea adding with passthru
and overrideCabal
is important. As is, any use of overrideCabal
will wipe out this env
.
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.
@infinisil Actually, I dunno if there's a way to fix this at all. We always want to refer to the final version of the derivation. But overrideCabal
doesn't give you that. So even if we manage to preserve env
via overrideCabal
, it'll be the wrong env
as soon as anyone does overrideCabal
again; i.e. if they add a dependency, it won't be added to env
.
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.
So maybe we need to invert the control here: put the source of truth in generic-builder
and define shellFor
in terms of that.
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.
Actually, how about putting the extractBuildInputs
thing as a generic-builder
passthru, define it in terms of that. I think that's the only thing that depends on overrideCabal
.
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.
@infinisil Yep, sounds good. Eliminating overrideCabal
entirely from the equation for extracting build inputs sounds like a really good thing.
# If `packages = [ a b ]` and `a` depends on `b`, don't build `b`, such | ||
# that `a` will take the `b` dependency from the cabal.project file. | ||
# This allows changing `b` while in the shell and have `a` use the | ||
# changes directly. |
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.
cabal new-build
is happy to ignore any installed b
actually. The real reason for this is to avoid building b
with Nix at all, so that entering the nix shell doesn't require rebuilding b
every time it changes when you're just going to ignore that version of b
.
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.
Ahh good point, will adjust that message
mkDrvArgs = builtins.removeAttrs args ["packages" "withHoogle"]; | ||
in pkgs.stdenv.mkDerivation (mkDrvArgs // { | ||
name = "ghc-shell-for-packages"; | ||
nativeBuildInputs = [(withPackages (_: haskellInputs))] ++ mkDrvArgs.nativeBuildInputs or []; | ||
name = "interactive-${pkgs.lib.concatMapStringsSep "-" (p: p.name) selected}-environment"; |
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.
Hm this naming could be a bit much. I think it'll be common for selected
to have quite a few packages, e.g. 10+
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.
Yeah, I think maybe just "interactive-${name}-environment"
if it's a single package and "interactive-multi-package-environment"
or so if it's more than one would be better.
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'd prefer just having a generic name, but allowing mkDrvArgs
to override the name however the user likes; but it doesn't matter very much
${if ghc.isHaLVM or false | ||
then ''export NIX_${ghcCommandCaps}_LIBDIR="${ghcEnv}/lib/HaLVM-${ghc.version}"'' | ||
else ''export NIX_${ghcCommandCaps}_LIBDIR="${ghcEnv}/lib/${ghcCommand}-${ghc.version}"''} | ||
${mkDrvArgs.shellHook or ""} |
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 like adding these environment variables, but I'm pretty sure it needn't be done in a shellHook
. Maybe I'm being picky, but I think it seems nicer to just set them as mkDerivation
arguments to me :P
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.
Oh, that's a good point, I just copied it from before, but that sounds much better, will change.
// optionalAttrs (hardeningDisable != []) { inherit hardeningDisable; } | ||
// optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive"; } | ||
) | ||
} |
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.
Recommended to hide whitespace changes (Click on Diff settings above).
I don't see any other way than this to add .env
to passthru. Because it itself depends on the thing.
_getBuildInputs = extractBuildInputs p.compiler args; | ||
}; | ||
}))._getBuildInputs; | ||
getBuildInputs = p: p.getBuildInputs; |
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 change very slightly changes the results of this function, namely that setupHaskellDepends
is not in haskellBuildInputs
anymore. It is in the derivations nativeBuildInputs
though, and therefore included in nix-shells.
|
||
assert allPkgconfigDepends != [] -> pkgconfig != null; | ||
|
||
stdenv.mkDerivation ({ |
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.
Is there any way to avoid re-indenting everything? Makes it harder to review and kills git blame.
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.
Maybe we can just do fix (drv: stdenv.mkDerivation ({
and add a paren at the end?
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.
You could add -w
to git diff
or git blame
:)
I guess the github blame's won't work with this though. I could of course just not indent it, but then it's kinda ugly
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.
Or fix
, yeah that sounds better
in | ||
drv // { | ||
env = buildHaskellPackages.shellFor { | ||
packages = p: [ drv ]; |
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.
Is this a duplicate of line 432? We should only have the passthru
one.
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.
Oh yeah good point, will remove
"NIX_${ghcCommandCaps}_DOCDIR" = "${ghcEnv}/share/doc/ghc/html"; | ||
"NIX_${ghcCommandCaps}_LIBDIR" = if ghc.isHaLVM or false | ||
then ''export NIX_${ghcCommandCaps}_LIBDIR="${ghcEnv}/lib/HaLVM-${ghc.version}"'' | ||
else ''export NIX_${ghcCommandCaps}_LIBDIR="${ghcEnv}/lib/${ghcCommand}-${ghc.version}"''; |
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.
export
?
}; | ||
|
||
env = buildHaskellPackages.shellFor { | ||
packages = p: [ drv ]; |
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 don't think buildHaskellPackages
is right.
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.
Hmm right, I guess it doesn't matter much though, because the p
is ignored anyways, so no dependencies come from that set anyways. It was the easiest way to get access to 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.
@infinisil Does it control where GHC comes from? This will get the GHC for targeting the build platform.
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.
Ah you're right, will have to do something about this then
d968c56
to
c16f1bc
Compare
c16f1bc
to
8f1def5
Compare
Cleaned up all the commits, very tidy now |
else ''export NIX_${ghcCommandCaps}_LIBDIR="${ghcEnv}/lib/${ghcCommand}-${ghc.version}"''} | ||
${shellHook} | ||
''; | ||
env = buildHaskellPackages.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.
@infinisil In the case of cross compilation, this will give you a shell with a native GHC rather than a cross compiling GHC, won't it?
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.
Maybe it'd be better to have a haskellLib
function for shellFor
that takes GHC and a list of packages as arguments. Then haskellPackages.shellFor
can be a convenience for plugging in GHC automatically and letting packages
be a function for convenient access to the package set as an argument.
@@ -46,6 +46,7 @@ let | |||
inherit buildHaskellPackages; | |||
inherit (self) ghc; | |||
inherit (buildHaskellPackages) jailbreak-cabal; | |||
inherit (extensible-self) 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.
Passing it like this now
594f7dd
to
3d251e1
Compare
Rebased, fixed conflicts, and now using |
@peti If I understand correctly, |
3d251e1
to
7d7215d
Compare
I have tested this myself successfully on my nixbot consisting of two subprojects, and just running Unrelated: I think |
c77ce53
to
a4badb2
Compare
- Now correctly sets NIX_GHC* env vars
7d7215d
to
51267d3
Compare
@peti Rebased to fix conflicts, didn't make any changes. Would like to get this merged. |
Is there a chance we could backport this to 18.09? Who would be able to make that decision? |
Motivation for this change
This cost me a couple hours to figure out. The original error was
from ghc-mod via HIE. After a very long time of debugging, I finally figured out that the reason was that
shellFor
doesn't run anyshellHook
that sets up the correctNIX_GHC*
env vars to have it find stuff. This PR just does a dirty fast fix by copying part of the logic ingeneric-builder.nix
, please don't merge it like this.Ping @peti @ryantm @basvandijk @domenkozar (Ping the people I annoyed for hours in #haskell-ide-engine because of this: @alanz @DanielG)
Things done
sandbox
innix.conf
on non-NixOS)nix-shell -p nox --run "nox-review wip"
./result/bin/
)nix path-info -S
before and after)