Subject: Re: bug#30710: guix graph gives duplicate nodes

From: Björn Höfling <[email-masked]>
Date: Fri, 9 Mar 2018 11:09:17 +0100

On Wed, 07 Mar 2018 16:18:51 +0100
[email-masked] (Ludovic Courtès) wrote:

> Hello,
> 
> Hartmut Goebel <[email-masked]> skribis:
> 
> >> This is expected.  Strictly speaking, we’re talking about two
> >> different package objects, hence the different IDs.  
> >
> > I wonder
> >
> > a) whether it is useful to have different graph nodes for the same
> > package.
> >
> > This is about usability of the resulting graph, esp. since this is
> > the default graph output format. Does it help *users* for their
> > analysis? Or is this some *expert* insight?  
> 
> As explained in “Invoking guix graph”, the tool provides different
> graph types, each at its own abstraction level.
> 
> The package graph is high-level, but as a side-effect it has this
> artifact.
> 
> To developers it’s actually useful to see the graph of package
> objects. There are cases where, with functions that return packages,
> you would notice that you’re generating lots of package objects for
> the same underlying derivation, which is super inefficient (in
> particular it defeats memoization).
> 
> Most of the time, there’s exactly one package object for each
> derivation; if not, that’s usually a bug.
> 
> > b) how there can be different package objects for the same package
> >
> > To my understanding, e.g. (gnu packages base) is loaded once,
> > defining package object abcd once and assigning it to a variable.
> > All packages referring to abcd use the some package object. So
> > there should be only *one* package object.  
> 
> (eq? foo (package (inherit foo))) => #false
> 
> Yet, these two packages map to the very same derivation.

This thing really took me a while to think about the graph system in
general and this concrete case.

Speaking about this concrete case: If you inspect the output of 

`guix graph qt` you find these interesting lines:

  "64168128" [label = "autoconf-wrapper-2.69", shape = box, fontname = Helvetica
  "64167936" [label = "autoconf-wrapper-2.69", shape = box, fontname = Helvetica

  "52941184" -> "64168128" [color = darkseagreen];
  "52940800" -> "64167936" [color = blue];

  "52941184" [label = "automake-1.15.1", shape = box, fontname = Helvetica];
  "52940800" [label = "libtool-2.4.6", shape = box, fontname = Helvetica];

If you look into gnu/packages/autotools.scm, you see that
autoconf-wrapper is not a package, but a package-factory:

(define* (autoconf-wrapper #:optional (autoconf autoconf))

Now the package definitions of "automake" and "libtool" each use the
same fragment of code in their native-inputs, but a different "package"
in the eq?-sense, although they basically want the same thing:

 `(("autoconf" ,(autoconf-wrapper))

As ludo stated above: "Most of the time, there’s exactly one package
object for each derivation; if not, that’s usually a bug."

This looks to me like a bug.

Correction:

(define autoconf-wrapper-default (autoconf-wrapper))

And then use this singular package as native-inputs to libtool and automake.

Furthermore, when I search:

find . -name "*.scm" -exec grep -H "autoconf-wrapper" "{}" ";" | less

I find about 10 packages that use the fabrik, but all in the default way.

So instead of:

  #:export (autoconf-wrapper))

We could just 

(define-public autoconf-wrapper-default (autoconf-wrapper))

and use that.

Or, if noone is using this fabrik, just drop that and make a normal package out of it.

WDYT? Reopen this one?

Björn