Support circular Requires loops

After the packages are parsed, pkg-config recurses through all the
required packages to generate one list. Before descending another level,
check to see if the package has already been handled and skip it. This
allows packages to require each other circularly by breaking the loop.

A test has been added resolving a two level deep circular dependency.

Freedesktop #7331
This commit is contained in:
Dan Nicholson 2012-05-09 05:55:47 -07:00
parent 3f1f6e79b7
commit 6d6dd43e75
6 changed files with 64 additions and 1 deletions

View file

@ -8,6 +8,7 @@ TESTS = \
check-define-variable \
check-libs-private \
check-requires-private \
check-circular-requires \
check-includedir \
check-conflicts \
check-missing \
@ -45,4 +46,7 @@ EXTRA_DIST = \
requires-version-2.pc \
requires-version-3.pc \
non-l.pc \
non-l-required.pc
non-l-required.pc \
circular-1.pc \
circular-2.pc \
circular-3.pc

8
check/check-circular-requires Executable file
View file

@ -0,0 +1,8 @@
#! /bin/sh
set -e
. ${srcdir}/common
RESULT="-lcirc1 -lcirc2 -lcirc3"
run_test --libs circular-1

11
check/circular-1.pc Normal file
View file

@ -0,0 +1,11 @@
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/circ1
Name: Circular Requires test 1
Description: Dummy package for testing circular Requires
Version: 1.0.0
Requires: circular-2
Libs: -lcirc1
Cflags: -I${includedir}

11
check/circular-2.pc Normal file
View file

@ -0,0 +1,11 @@
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/circ2
Name: Circular Requires test 2
Description: Dummy package for testing circular Requires
Version: 1.0.0
Requires: circular-3
Libs: -lcirc2
Cflags: -I${includedir}

11
check/circular-3.pc Normal file
View file

@ -0,0 +1,11 @@
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/circ3
Name: Circular Requires test 3
Description: Dummy package for testing circular Requires
Version: 1.0.0
Requires: circular-1
Libs: -lcirc3
Cflags: -I${includedir}

18
pkg.c
View file

@ -626,6 +626,7 @@ static void
recursive_fill_list (Package *pkg, GetListFunc func, GSList **listp)
{
GSList *tmp;
static GSList *chain = NULL;
/*
* This function should only be called to resolve Requires or
@ -633,10 +634,27 @@ recursive_fill_list (Package *pkg, GetListFunc func, GSList **listp)
*/
g_assert (func == get_requires || func == get_requires_private);
/*
* If the package is one of the parents, we can skip it. This allows
* circular requires loops to be broken.
*/
if (g_slist_find (chain, pkg) != NULL)
{
debug_spew ("Package %s already in requires chain, skipping\n",
pkg->key);
return;
}
/* record this package in the dependency chain */
chain = g_slist_prepend (chain, pkg);
for (tmp = (*func) (pkg); tmp != NULL; tmp = g_slist_next (tmp))
recursive_fill_list (tmp->data, func, listp);
*listp = g_slist_prepend (*listp, pkg);
/* remove this package from the dependency chain now that we've unwound */
chain = g_slist_remove (chain, pkg);
}
static void