[Nix-dev] Overriding a Haskell package can't be that hard...
Guillaume Maudoux (Layus)
layus.on at gmail.com
Fri Jun 24 11:52:29 CEST 2016
I have written nix examples in increasing order of complexity.
They should help you understand what is going on behind the scenes. (see
below).
As for your snippets,
|haskellPackages.override { overrides = self: super: { thrift =
self.callPackage /home/cody/sources/thrift/lib/hs {}; }; }; |
performs a deep override of thrift on haskellPackages. This means that
every package using thrift will use your definition of thrift, not the
one bundled with nixpkgs.
The expressions returns this new haskellPackages set.
Now,
|packageOverrides = oldPkgs: { haskellPackages =
oldPkgs.haskellPackages.override { ... }; }; |
is the usual way to make a deep package override on the top-level
packages set.
With this expression, haskellPackages will now refer to your updated
haskellPackges set everywhere in nixpkgs.
You HAVE TO use oldPkgs (or super, as it is called in your examples)
otherwise you get an infinite loop where packages override themselves
(bad :-)).
Now, my interactive examples
You can also look at
https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55#.wby41ssn0.
|# to eval this file, run `nix-instantiate --eval <file name> --strict`.
# Result is always "high depends on low and med depends on low", #
except for the two last ones wihich read "high depends on low and med,
which depends on low". builtins.map (s: (if s ? ps' then s.ps' else
s.ps).high ) [ { # A simple recursive package set (ps). ps = rec { low =
"low"; med = "med depends on ${low}"; high = "high depends on ${low} and
${med}"; }; } rec { # A simple recursive package set, using with instead
of rec. # Note the higher level "rec" to reuse ps in the with clause. ps
= with ps; { low = "low"; med = "med depends on ${low}"; high = "high
depends on ${low} and ${med}"; }; } rec { # Again the same, but with a
function. psFun = self: with self; { low = "low"; med = "med depends on
${low}"; high = "high depends on ${low} and ${med}"; }; ps = psFun ps; #
Look at this fixpoint. # ps is the result of calling psFun on itself. #
This works thanks to lazyness. } rec { # Using with is not always
desirable. # In this case we prefer to use self directly. psFun = self:
{ low = "low"; med = "med depends on ${self.low}"; high = "high depends
on ${self.low} and ${self.med}"; }; ps = psFun ps; } ## The question is:
How do I override a package ? ## 1. Simple answer rec { psFun = self: {
low = "low"; med = "med depends on ${self.low}"; high = "high depends on
${self.low} and ${self.med}"; }; ps = psFun ps; ps' = ps // { med =
"med, which depends on ${ps'.low}"; }; } ## Here ps' contains an updated
med package, but ps'.high does not use the updated package. ## for
proof, the output is unchanged. ## 2. A method that works. ## psFun
thinks it receives itself as an argument, but we may trick it ## by
giving a sligtly different self: rec { psFun = self: { low = "low"; med
= "med depends on ${self.low}"; high = "high depends on ${self.low} and
${self.med}"; }; ps = psFun ps; ps' = (psFun ps') // { med = "med, which
depends on ${ps'.low}"; }; } ## in this case, med is overriden by our
own definition, and any package that ## uses self.med in psFun now uses
our updated package. ## We have effectively replaced med in the whole
hierarchy. ## I am a bit overextending myself here, but haskellPackages
must do something like: rec { psFun = self: { low = "low"; med = "med
depends on ${self.low}"; high = "high depends on ${self.low} and
${self.med}"; }; overrides = pkgs: { med = "med, which depends on
${pkgs.low}"; }; ps = (psFun ps) // (overrides ps); } ] |
Le 24/06/16 à 05:57, Cody Goodman a écrit :
> I was trying to use the cassandra-thrift haskell package and there was
> a bug in one if it's dependencies, thrift. I fixed the bug in thrift
> and then went to the nix haskell guide to find out how to override
> "thrift" with my bugfixed version.
>
> I came up with this from the haskell guide
> (http://nixos.org/nixpkgs/manual/#how-to-build-projects-that-depend-on-each-other):
>
> { pkgs }: {
> packageOverrides = super: let self = super.pkgs; in
> {
> haskellPackages = super.haskellPackages.override {
> overrides = self: super: {
> thrift = self.callPackage /home/cody/sources/thrift/lib/hs {};
> };
> };
> };
>
> allowUnfree = true;
> firefox = {
> enableGoogleTalkPlugin = true;
> enableAdobeFlash = true;
> };
>
> and then finally tried the example from ocharle's wiki on nix/haskell,
> which involved putting the override in shell.nix like below:
>
> with (import <nixpkgs> {}).pkgs;
> let modifiedHaskellPackages = haskellPackages.override {
> overrides = self: super: {
> thrift = self.callPackage /home/cody/sources/thrift/lib/hs {};
> };
> };
> in modifiedHaskellPackages.hscassandra.env
>
> I'm a little dismayed since I even went through all 19 or so of the
> nix
> pills(http://lethalman.blogspot.com/2014/07/nix-pill-1-why-you-should-give-it-try.html)
> thinking I just needed to brush up on nix.
>
> If someone could also explain these snippets and how they work in
> detail or differently than the resources I've looked at many times:
>
> http://nixos.org/nixpkgs/manual/#how-to-build-projects-that-depend-on-each-other
> http://lethalman.blogspot.com/2014/07/nix-pill-1-why-you-should-give-it-try.html
> http://wiki.ocharles.org.uk/Nix#multiple-project-usage
>
> If possible, any example git repositories with multiple haskell
> projects/overrides would be amazing.
>
> Thank you all for your time.
>
> Sincerely,
>
> Cody Goodman
>
>
> _______________________________________________
> nix-dev mailing list
> nix-dev at lists.science.uu.nl
> http://lists.science.uu.nl/mailman/listinfo/nix-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.science.uu.nl/pipermail/nix-dev/attachments/20160624/86e95778/attachment-0001.html>
More information about the nix-dev
mailing list