doc: Add new 'Circular Module Dependencies' section.
* doc/contributing.texi (Circular Module Dependencies): New subsection. Series-version: 2 Series-to: 65860@debbugs.gnu.org Patch-cc: mhw@netris.org Cover-letter: Resolve a circular module dependencies in embedded modules This series is the culmination of at least a day of effort tracking down the source of a module dependency cycle (!). The last commit adds some guidelines in the hope to avoid a repeat (perhaps 'lint' could be taught to automate these checks). END
parent
35c1df5bd6
commit
c428246bcd
|
@ -518,6 +518,7 @@ needed is to review and apply the patch.
|
|||
* Version Numbers:: When the name is not enough.
|
||||
* Synopses and Descriptions:: Helping users find the right package.
|
||||
* Snippets versus Phases:: Whether to use a snippet, or a build phase.
|
||||
* Cyclic Module Dependencies:: Going full circle.
|
||||
* Emacs Packages:: Your Elisp fix.
|
||||
* Python Modules:: A touch of British comedy.
|
||||
* Perl Modules:: Little pearls.
|
||||
|
@ -789,6 +790,61 @@ embed store items in the sources; such patching should rather be done
|
|||
using build phases. Refer to the @code{origin} record documentation for
|
||||
more information (@pxref{origin Reference}).
|
||||
|
||||
@node Cyclic Module Dependencies
|
||||
@subsection Cyclic Module Dependencies
|
||||
|
||||
While there cannot be circular dependencies between packages, Guile's
|
||||
lax module loading mechanism allows circular dependencies between Guile
|
||||
modules, which doesn't cause problems as long as the following
|
||||
conditions are followed for two modules part of a dependency cycle:
|
||||
|
||||
@cindex rules to cope with circular module dependencies
|
||||
@enumerate
|
||||
@item
|
||||
Macros are not shared between the co-dependent modules
|
||||
@item
|
||||
Top-level variables are only referenced in delayed (@i{thunked}) package
|
||||
fields: @code{arguments}, @code{native-inputs}, @code{inputs},
|
||||
@code{propagated-inputs} or @code{replacement}
|
||||
@item
|
||||
Procedures referencing top-level variables from another module are not
|
||||
called at the top level of a module themselves.
|
||||
@end enumerate
|
||||
|
||||
Straying away from the above rules may work while there are no
|
||||
dependency cycles between modules, but given such cycles are confusing
|
||||
and difficult to troubleshoot, it is best to follow the rules to avoid
|
||||
introducing problems down the line.
|
||||
|
||||
@noindent
|
||||
Here is a common trap to avoid:
|
||||
|
||||
@lisp
|
||||
(define-public avr-binutils
|
||||
(package
|
||||
(inherit (cross-binutils "avr"))
|
||||
(name "avr-binutils")))
|
||||
@end lisp
|
||||
|
||||
In the above example, the @code{avr-binutils} package was defined in the
|
||||
module @code{(gnu packages avr)}, and the @code{cross-binutils}
|
||||
procedure in @code{(gnu packages cross-base)}. Because the
|
||||
@code{inherit} field is not delayed (thunked), it is evaluated at the
|
||||
top level at load time, which is problematic in the presence of module
|
||||
dependency cycles. This could be resolved by turning the package into a
|
||||
procedure instead, like:
|
||||
|
||||
@lisp
|
||||
(define (make-avr-binutils)
|
||||
(package
|
||||
(inherit (cross-binutils "avr"))
|
||||
(name "avr-binutils")))
|
||||
@end lisp
|
||||
|
||||
Care would need to be taken to ensure the above procedure is only ever
|
||||
used in a package delayed fields or within another procedure also not
|
||||
called at the top level.
|
||||
|
||||
@node Emacs Packages
|
||||
@subsection Emacs Packages
|
||||
|
||||
|
|
Reference in New Issue