Subject: bug#18247: Cyclic dependencies in (gnu package *) modules

From: Mark H Weaver <[email-masked]>
Date: Mon, 11 Aug 2014 19:59:37 -0400

[email-masked] (Ludovic Courtès) writes:

> [email-masked] skribis:
>
>> I'm currently unable to compile guix from git, with error messages that
>> suggest cyclic dependencies between the modules.
>
> Indeed.  That is fixed by reverting c5d8376.  Can you confirm?

Yes, that solves the problem for me.

>> I just computed the strongly connected components of the (gnu package
>> *) modules.  The non-trivial ones are listed below.
>>
>> There are three cycles of size 2:
>>
>> ((gnu packages emacs)  (gnu packages version-control))
>> ((gnu packages flex)   (gnu packages bison))
>> ((gnu packages python) (gnu packages zip))
>>
>> And one large strongly-connected component containing 51 modules:
>
> Ouch.
>
> Well, that is not really a problem per se.  The real problem is when
> top-level bindings refer to each other, of course.

To be more precise, the relevant question is: which bindings from other
modules are needed when a module is _loaded_.  In other words, we need
to worry about cycles in a graph, but a different graph than the one my
script computed.

I think the graph we need to consider is one that contains one vertex
per module, and an directed edge from module A to B if and only if
loading module A requires looking up a binding from module B.

Does that sound right to you?

Unfortunately, it seems to me that the most common kinds of cross-module
references between (gnu packages *) modules are references in 'inputs'
or 'native-inputs' fields, and those need to be looked up at module load
time, right?

> But anyway, I agree we need tooling or something to help deal with this
> kind of issues.  Perhaps something like the script you posted, but that
> would look at the set of bindings referenced from the top-level of a
> module?  Or can we do better?
>
> If Guile supported phases, such circular references would not be a
> problem since it would not have to evaluate all of the imported modules
> at expansion phase, just the ‘define-module’ clause.

I'd very much like to add phases to Guile's macro expander at some
point, but it would have to be done between major releases.  It would
likely break a lot of existing code.

    Thanks,
      Mark