[Nix-dev] The Future of Haskell Packaging in Nix

Nicolas Pierron nicolas.b.pierron at gmail.com
Sun Oct 18 17:45:09 CEST 2015


I think I might have the beginning of an answer for you by addressing
another issue.

One of the problem we have today is that "override" are costly.  They
are costly because the default value that we are expecting are
derivations results.

A while back, when Luis was working on the cross compilation issue, we
decided that having a drv.nativeDrv and drv.crossDrv (or similar)
would be a good way to go.  Then we added extra arguments to the
mkDerivation functions so that we can filter one from the other. What
is interesting in the previous solution (a-part from the fact that it
is not a good solution from distinguishing cross-compiled programs) is
that the top-level returned value, while still being the first-citizen
was no longer the one of interest.

What I suggest, is that derivations, are just one of the potential
*views* of the package evaluation.

What does that mean, in terms of code?
Currently we have something like:

  firefox = callPackage ../application/browser/firefox ;

with a file which looks like this:

{ lib, stdenv, fetchurl, jemalloc […] }:

stdenv.mkDerivation {
  name = "firefox-41.0.2";
  […]
}

Looking at this, currently we have a major view which is provided by
the mkDerivation function.  Most of the inputs are packages provided
by the callPackage function.

So, what would happen if we had more than one view?
Probably the first thing would be that we would need to up-lift the
mkDerivation function above the arguments of the function.

  firefox = callPackageWith context context.stdenv.mkDerivation
../application/browser/firefox ;

and

{ lib, fetchurl, jemalloc […] }:

{
  name = "firefox-41.0.2";
  […]
}

We could remove the need for the argument list, but I will keep it now
to keep this example simple.
So, let make multiple views:

  viewFunctions = rec {
    drv = file: ctx: ctx.drv.stdenv.mkDerivation (raw file ctx);
    function = file: ctx: import file;
    raw = file: ctx: callWithDrv (function file ctx) ctx; //
callWithDrv query the drv attributes of the arguments.
    license = file: ctx: (raw file ctx).meta.license;
    name = file: ctx: (raw file ctx).name;
  };
  firefox = callPackageWith context viewFunctions
../application/browser/firefox ;

Then the evaluation of the above can be evaluated to:

  firefox = {
    inherit context viewFunctions;
    file = ../application/browser/firefox/default.nix;
  } // {
    drv = viewFunctions.drv file context;
    function = viewFunctions.function file context;
    raw = viewFunctions.raw file context;
    license = viewFunctions.license file context;
    name = viewFunctions.name file context;
  };

The benefit of this approach is that extending the context, replacing
the body of a package, and in general making introspection becomes
easier as everything is at the same level.

More over, we do not have to do the evaluation of the mkDerivation
function as the mkOverridable function do today, and we can
potentially dramatically increase the speed of "nix-env" as looking
for packages by name is no longer as costly as iterating over all
packages evaluation.


On Thu, Oct 15, 2015 at 10:21 AM, Peter Simons <simons at cryp.to> wrote:
> Hi William,
>
>  >> We still don't have convincing answers to questions like: how do I
>  >> compile my package with profiling support?
>  >
>  > I thought we already have fairly straightforward support for this via
>  > overrides? I have been using this method:
>  >
>  > https://gist.github.com/jb55/af8b095b3ad97fb3035e
>  >
>  > and then just `nix-shell --arg profiling true` to build with profiling.
>
> yes, you are right, that solution is pretty good.
>
> I guess I'm just concerned about the complexity involved in this
> seemingly simple operation. The average Haskell hacker is not going to
> understand what that Nix code does and how it works, and they'll have a
> hard time coming up with that themselves. Good documentation mitigates
> those issues, no doubt. Still, it would be nice if there was a way to
> simplify this. For example, for every package "foo" we have
>
>   haskell.packages.ghcXYZ.foo.env
>
> to enter an interactive shell environment. Why not define
>
>   haskell.packages.ghcXYZ.foo.profiled
>
> the same way? We could also have every package set contain a variant of
> itself with profiling enabled. Then the names
>
>   haskell.packages.ghcXYZ               -- default choice
>   haskell.packages.ghcXYZ.profiled      -- with profiling
>   haskell.packages.ghcXYZ.vanilla       -- without profiling
>
> would be defined by Nixpkgs -- instead of requiring users to define a
> "profiled" package set themselves.
>
> Best regards,
> Peter
>
> _______________________________________________
> nix-dev mailing list
> nix-dev at lists.science.uu.nl
> http://lists.science.uu.nl/mailman/listinfo/nix-dev



-- 
Nicolas Pierron
http://www.linkedin.com/in/nicolasbpierron - http://nbp.name/


More information about the nix-dev mailing list