Compare commits

...

15 Commits

Author SHA1 Message Date
Ariadne Conill f86bdf3f7c pkgconf 2.2.0 2024-03-27 11:34:36 -07:00
Ariadne Conill a3d7ecb31b Use libpkgconf.so.5 due to ABI changes 2024-03-27 11:31:48 -07:00
Kai Pastor e2a8080cbf Reuse static solution for general solution 2024-03-27 11:15:04 -07:00
Kai Pastor 883b57df47 Cache packages from explicit file requests 2024-03-27 11:15:04 -07:00
Kai Pastor 194dde096b Update expected test results 2024-03-27 11:15:04 -07:00
Kai Pastor 78d53ea012 Revise serials, traversal, flattening
Remove the 'traverse_serial' fields which were added in 2.1.1.
Use the 'serial' field to track the current traversal.
Stop using 'identifier' to sort packages in the flattened solution.
Directly construct the flattened solution by a specific walk which
also preserves the relative order in Requires and Requires.private.
The topological sort is a single list, so don't fill requires_private.
Purely private dependencies are marked in dependency flags.
The ancestor flag is a pkg property, not a client property.
2024-03-27 11:15:04 -07:00
Kai Pastor 4090ba3e0d Clarify tracing messages 2024-03-27 11:15:04 -07:00
Kai Pastor 5eb79f6651 Add tests for lib order 2024-03-27 11:15:04 -07:00
Kai Pastor e7c9bdb317 Don't print 'required by <VIRTUAL-PACKAGE>' 2024-03-27 11:09:16 -07:00
Kai Pastor 4e01010d6f Mark user input in error message 2024-03-27 11:09:16 -07:00
Kai Pastor 6219af9a0a Color private-reachable nodes gray 2024-03-27 11:06:30 -07:00
Kai Pastor eaf1a2d804 Resolve user request for digraph 2024-03-27 11:06:30 -07:00
Kai Pastor d6753888b8 Update test expected results 2024-03-27 11:06:30 -07:00
Kai Pastor f95e8d4428 Print digraph for user request perspective 2024-03-27 11:06:30 -07:00
Kai Pastor db63c8ee0b Show edges for flattened order 2024-03-27 11:06:30 -07:00
11 changed files with 248 additions and 188 deletions

View File

@ -159,7 +159,7 @@ libpkgconf_la_SOURCES = \
libpkgconf/path.c \
libpkgconf/personality.c \
libpkgconf/parser.c
libpkgconf_la_LDFLAGS = -no-undefined -version-info 4:0:0 -export-symbols-regex '^pkgconf_'
libpkgconf_la_LDFLAGS = -no-undefined -version-info 5:0:0 -export-symbols-regex '^pkgconf_'
dist_man_MANS = \
man/pkgconf.1 \

View File

@ -39,7 +39,7 @@ all: pkgconf-lite
libpkgconf/config.h:
@echo '#define PACKAGE_NAME "pkgconf-lite"' >> $@
@echo '#define PACKAGE_BUGREPORT "https://git.dereferenced.org/pkgconf/pkgconf/issues"' >> $@
@echo '#define PACKAGE_VERSION "2.1.1"' >> $@
@echo '#define PACKAGE_VERSION "2.2.0"' >> $@
@echo '#define PACKAGE PACKAGE_NAME " " PACKAGE_VERSION' >> $@
@echo '#define HAVE_STRLCPY' >> $@
@echo '#define HAVE_STRLCAT' >> $@

18
NEWS
View File

@ -1,6 +1,24 @@
Changes from previous version of pkgconf
========================================
Changes from 2.1.1 to 2.2.0:
----------------------------
* libpkgconf SOVERSION is now 5.
* Significant solver rework to flatten both requires and requires.private
dependencies in a single pass. Improves performance slightly and ensures
proper dependency order.
Patches by Kai Pastor.
* Improve `--digraph` output to reflect more of the solver's state in the
rendered dependency graph.
Patches by Kai Pastor.
* Do not reference the graph root by name when presenting error messages about
directly requested dependency nodes.
Patch by Kai Pastor.
Changes from 2.1.0 to 2.1.1:
----------------------------

View File

@ -254,39 +254,71 @@ apply_provides(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int
#ifndef PKGCONF_LITE
static void
print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
{
pkgconf_node_t *node;
(void) client;
(void) unused;
pkgconf_pkg_t **last_seen = data;
printf("\"%s\" [fontname=Sans fontsize=8]\n", pkg->id);
if(pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
return;
if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE)
printf("\"%s\" [fontname=Sans fontsize=8 fontcolor=gray color=gray]\n", pkg->id);
else
printf("\"%s\" [fontname=Sans fontsize=8]\n", pkg->id);
if (last_seen != NULL)
{
if (*last_seen != NULL)
printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=red]\n", (*last_seen)->id, pkg->id);
*last_seen = pkg;
}
PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
{
pkgconf_dependency_t *dep = node->data;
const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package;
printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8]\n", pkg->id, dep->package);
if ((dep->flags & PKGCONF_PKG_DEPF_PRIVATE) == 0)
printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8]\n", pkg->id, dep_id);
else
printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id);
}
PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
{
pkgconf_dependency_t *dep = node->data;
const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package;
printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep->package);
printf("\"%s\" -> \"%s\" [fontname=Sans fontsize=8 color=gray]\n", pkg->id, dep_id);
}
}
static bool
apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth)
{
int eflag;
pkgconf_list_t *list = data;
pkgconf_pkg_t *last_seen = NULL;
pkgconf_node_t *iter;
printf("digraph deptree {\n");
printf("edge [color=blue len=7.5 fontname=Sans fontsize=8]\n");
printf("node [fontname=Sans fontsize=8]\n");
printf("\"user:request\" [fontname=Sans fontsize=8]\n");
eflag = pkgconf_pkg_traverse(client, world, print_digraph_node, unused, maxdepth, 0);
PKGCONF_FOREACH_LIST_ENTRY(list->head, iter)
{
pkgconf_queue_t *pkgq = iter->data;
pkgconf_pkg_t *pkg = pkgconf_pkg_find(client, pkgq->package);
printf("\"user:request\" -> \"%s\" [fontname=Sans fontsize=8]\n", pkg == NULL ? pkgq->package : pkg->id);
if (pkg != NULL)
pkgconf_pkg_unref(client, pkg);
}
eflag = pkgconf_pkg_traverse(client, world, print_digraph_node, &last_seen, maxdepth, 0);
if (eflag != PKGCONF_PKG_ERRF_OK)
return false;
@ -1482,7 +1514,7 @@ cleanup3:
if ((want_flags & PKG_DIGRAPH) == PKG_DIGRAPH)
{
want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
apply_digraph(&pkg_client, &world, NULL, 2);
apply_digraph(&pkg_client, &world, &pkgq, 2);
}
if ((want_flags & PKG_SOLUTION) == PKG_SOLUTION)
@ -1544,20 +1576,8 @@ cleanup3:
printf(" ");
if (!(want_flags & PKG_STATIC))
{
pkgconf_client_set_flags(&pkg_client, pkg_client.flags & ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE);
/* redo the solution for the library set: free the solution itself, and any cached graph nodes */
pkgconf_solution_free(&pkg_client, &world);
pkgconf_cache_free(&pkg_client);
if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth))
{
ret = EXIT_FAILURE;
goto out;
}
}
apply_libs(&pkg_client, &world, NULL, 2);
}

View File

@ -12,7 +12,7 @@ dnl implied. In no event shall the authors be liable for any damages arising
dnl from the use of this software.
AC_PREREQ([2.71])
AC_INIT([pkgconf],[2.1.1],[https://github.com/pkgconf/pkgconf/issues/new])
AC_INIT([pkgconf],[2.2.0],[https://github.com/pkgconf/pkgconf/issues/new])
AC_CONFIG_SRCDIR([cli/main.c])
AC_CONFIG_MACRO_DIR([m4])
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"])

View File

@ -81,8 +81,8 @@ typedef struct pkgconf_queue_ pkgconf_queue_t;
#define PKGCONF_FOREACH_LIST_ENTRY_REVERSE(tail, value) \
for ((value) = (tail); (value) != NULL; (value) = (value)->prev)
#define LIBPKGCONF_VERSION 20101
#define LIBPKGCONF_VERSION_STR "2.1.1"
#define LIBPKGCONF_VERSION 20200
#define LIBPKGCONF_VERSION_STR "2.2.0"
struct pkgconf_queue_ {
pkgconf_node_t iter;
@ -137,7 +137,7 @@ struct pkgconf_path_ {
#define PKGCONF_PKG_PROPF_CACHED 0x02
#define PKGCONF_PKG_PROPF_UNINSTALLED 0x08
#define PKGCONF_PKG_PROPF_VIRTUAL 0x10
#define PKGCONF_PKG_PROPF_VISITED 0x20
#define PKGCONF_PKG_PROPF_ANCESTOR 0x20
#define PKGCONF_PKG_PROPF_VISITED_PRIVATE 0x40
struct pkgconf_pkg_ {
@ -178,7 +178,6 @@ struct pkgconf_pkg_ {
uint64_t serial;
uint64_t identifier;
uint64_t traverse_serial;
};
typedef bool (*pkgconf_pkg_iteration_func_t)(const pkgconf_pkg_t *pkg, void *data);
@ -215,7 +214,6 @@ struct pkgconf_client_ {
uint64_t serial;
uint64_t identifier;
uint64_t traverse_serial;
pkgconf_pkg_t **cache_table;
size_t cache_count;
@ -282,7 +280,6 @@ PKGCONF_API void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *p
#define PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS 0x4000
#define PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES 0x8000
#define PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES 0x10000
#define PKGCONF_PKG_PKGF_ANCESTOR 0x20000
#define PKGCONF_PKG_DEPF_INTERNAL 0x1
#define PKGCONF_PKG_DEPF_PRIVATE 0x2

View File

@ -775,15 +775,13 @@ pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
{
if ((f = fopen(name, "r")) != NULL)
{
pkgconf_pkg_t *pkg;
PKGCONF_TRACE(client, "%s is a file", name);
pkg = pkgconf_pkg_new_from_file(client, name, f, 0);
if (pkg != NULL)
{
pkgconf_path_add(pkg->pc_filedir, &client->dir_list, true);
return pkg;
goto out;
}
}
}
@ -1456,7 +1454,11 @@ pkgconf_pkg_report_graph_error(pkgconf_client_t *client, pkgconf_pkg_t *parent,
client->already_sent_notice = true;
}
pkgconf_error(client, "Package '%s', required by '%s', not found\n", node->package, parent->id);
if (parent->flags & PKGCONF_PKG_PROPF_VIRTUAL)
pkgconf_error(client, "Package '%s' not found\n", node->package);
else
pkgconf_error(client, "Package '%s', required by '%s', not found\n", node->package, parent->id);
pkgconf_audit_log(client, "%s NOT-FOUND\n", node->package);
}
else if (eflags & PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH)
@ -1487,7 +1489,7 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
pkgconf_node_t *node, *next;
parent->flags |= PKGCONF_PKG_PKGF_ANCESTOR;
parent->flags |= PKGCONF_PKG_PROPF_ANCESTOR;
PKGCONF_FOREACH_LIST_ENTRY_SAFE(deplist->head, next, node)
{
@ -1509,10 +1511,8 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
if (pkgdep == NULL)
continue;
if((pkgdep->flags & PKGCONF_PKG_PKGF_ANCESTOR) != 0)
if((pkgdep->flags & PKGCONF_PKG_PROPF_ANCESTOR) != 0)
{
pkgdep->identifier = ++client->identifier;
/* In this case we have a circular reference.
* We break that by deleteing the circular node from the
* the list, so that we dont create a situation where
@ -1540,14 +1540,12 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
pkgconf_audit_log_dependency(client, pkgdep, depnode);
pkgdep->identifier = ++client->identifier;
pkgdep->serial = client->serial;
eflags |= pkgconf_pkg_traverse_main(client, pkgdep, func, data, depth - 1, skip_flags);
next:
pkgconf_pkg_unref(client, pkgdep);
}
parent->flags &= ~PKGCONF_PKG_PKGF_ANCESTOR;
parent->flags &= ~PKGCONF_PKG_PROPF_ANCESTOR;
return eflags;
}
@ -1624,27 +1622,19 @@ pkgconf_pkg_traverse_main(pkgconf_client_t *client,
unsigned int skip_flags)
{
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
unsigned int visited_flag = (client->flags & PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE) ? PKGCONF_PKG_PROPF_VISITED_PRIVATE : PKGCONF_PKG_PROPF_VISITED;
if (maxdepth == 0)
return eflags;
/* If we have already visited this node, check if we have done so as a Requires or Requires.private
* query as appropriate, and short-circuit if so.
/* Short-circuit if we have already visited this node.
*/
if ((root->flags & PKGCONF_PKG_PROPF_VIRTUAL) == 0 && root->traverse_serial == client->traverse_serial)
{
if (root->flags & visited_flag)
return eflags;
}
else
{
root->traverse_serial = client->traverse_serial;
root->flags &= ~(PKGCONF_PKG_PROPF_VISITED|PKGCONF_PKG_PROPF_VISITED_PRIVATE);
}
if (root->serial == client->serial)
return eflags;
/* Update this node to indicate how we've visited it so far. */
root->flags |= visited_flag;
root->serial = client->serial;
if (root->identifier == 0)
root->identifier = ++client->identifier;
PKGCONF_TRACE(client, "%s: level %d, serial %"PRIu64, root->id, maxdepth, client->serial);
@ -1654,21 +1644,23 @@ pkgconf_pkg_traverse_main(pkgconf_client_t *client,
func(client, root, data);
}
if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_CONFLICTS))
if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_CONFLICTS) && root->conflicts.head != NULL)
{
PKGCONF_TRACE(client, "%s: walking 'Conflicts' list", root->id);
eflags = pkgconf_pkg_walk_conflicts_list(client, root, &root->conflicts);
if (eflags != PKGCONF_PKG_ERRF_OK)
return eflags;
}
PKGCONF_TRACE(client, "%s: walking requires list", root->id);
PKGCONF_TRACE(client, "%s: walking 'Requires' list", root->id);
eflags = pkgconf_pkg_walk_list(client, root, &root->required, func, data, maxdepth, skip_flags);
if (eflags != PKGCONF_PKG_ERRF_OK)
return eflags;
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
{
PKGCONF_TRACE(client, "%s: walking requires.private list", root->id);
PKGCONF_TRACE(client, "%s: walking 'Requires.private' list", root->id);
/* XXX: ugly */
client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
@ -1693,7 +1685,8 @@ pkgconf_pkg_traverse(pkgconf_client_t *client,
if (root->flags & PKGCONF_PKG_PROPF_VIRTUAL)
client->serial++;
client->traverse_serial++;
if ((client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE) == 0)
skip_flags |= PKGCONF_PKG_DEPF_PRIVATE;
return pkgconf_pkg_traverse_main(client, root, func, data, maxdepth, skip_flags);
}

View File

@ -103,134 +103,134 @@ pkgconf_queue_free(pkgconf_list_t *list)
}
static void
pkgconf_queue_collect_dependents(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
pkgconf_queue_mark_public(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
{
if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE)
{
pkgconf_list_t *list = data;
pkgconf_node_t *node;
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
{
pkgconf_dependency_t *dep = node->data;
if (dep->match == pkg)
dep->flags &= ~PKGCONF_PKG_DEPF_PRIVATE;
}
pkg->flags &= ~PKGCONF_PKG_PROPF_VISITED_PRIVATE;
PKGCONF_TRACE(client, "%s: updated, public", pkg->id);
}
}
static unsigned int
pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client,
pkgconf_pkg_t *root,
void *data,
int maxdepth);
static inline unsigned int
pkgconf_queue_collect_dependencies_walk(pkgconf_client_t *client,
pkgconf_pkg_t *parent,
pkgconf_list_t *deplist,
void *data,
int depth)
{
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
pkgconf_node_t *node;
pkgconf_pkg_t *world = data;
if (pkg == world)
return;
PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
{
pkgconf_dependency_t *parent_dep = node->data;
pkgconf_dependency_t *flattened_dep;
flattened_dep = pkgconf_dependency_copy(client, parent_dep);
if ((client->flags & PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE) != PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE)
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required);
else
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->requires_private);
}
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
{
PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
{
pkgconf_dependency_t *parent_dep = node->data;
pkgconf_dependency_t *flattened_dep;
flattened_dep = pkgconf_dependency_copy(client, parent_dep);
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->requires_private);
}
}
}
static int
dep_sort_cmp(const void *a, const void *b)
{
const pkgconf_dependency_t *depA = *(void **) a;
const pkgconf_dependency_t *depB = *(void **) b;
return depB->match->identifier - depA->match->identifier;
}
static inline void
flatten_dependency_set(pkgconf_client_t *client, pkgconf_list_t *list)
{
pkgconf_node_t *node, *next;
pkgconf_dependency_t **deps = NULL;
size_t dep_count = 0, i;
PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node)
PKGCONF_FOREACH_LIST_ENTRY_REVERSE(deplist->tail, node)
{
pkgconf_dependency_t *dep = node->data;
pkgconf_pkg_t *pkg = pkgconf_pkg_verify_dependency(client, dep, NULL);
pkgconf_dependency_t *flattened_dep;
pkgconf_pkg_t *pkg = dep->match;
if (pkg == NULL)
if (*dep->package == '\0')
continue;
if (pkg->serial == client->serial)
{
pkgconf_node_delete(node, list);
pkgconf_dependency_unref(client, dep);
goto next;
}
if (dep->match == NULL)
if (pkg == NULL)
{
PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package);
abort();
}
/* for virtuals, we need to check to see if there are dupes */
for (i = 0; i < dep_count; i++)
{
pkgconf_dependency_t *other_dep = deps[i];
PKGCONF_TRACE(client, "dedup %s = %s?", dep->package, other_dep->package);
if (!strcmp(dep->package, other_dep->package))
{
PKGCONF_TRACE(client, "skipping, "SIZE_FMT_SPECIFIER" deps", dep_count);
goto next;
}
}
pkg->serial = client->serial;
/* copy to the deps table */
dep_count++;
deps = pkgconf_reallocarray(deps, dep_count, sizeof (void *));
deps[dep_count - 1] = dep;
PKGCONF_TRACE(client, "added %s to dep table", dep->package);
next:
pkgconf_pkg_unref(client, pkg);
}
if (deps == NULL)
return;
qsort(deps, dep_count, sizeof (void *), dep_sort_cmp);
/* zero the list and start readding */
pkgconf_list_zero(list);
for (i = 0; i < dep_count; i++)
{
pkgconf_dependency_t *dep = deps[i];
if (dep->match == NULL)
if (pkg->serial == client->serial)
continue;
memset(&dep->iter, '\0', sizeof (dep->iter));
pkgconf_node_insert(&dep->iter, dep, list);
if (client->flags & PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE)
pkg->flags |= PKGCONF_PKG_PROPF_VISITED_PRIVATE;
else
pkg->flags &= ~PKGCONF_PKG_PROPF_VISITED_PRIVATE;
PKGCONF_TRACE(client, "slot "SIZE_FMT_SPECIFIER": dep %s matched to %p<%s> id %"PRIu64, i, dep->package, dep->match, dep->match->id, dep->match->identifier);
eflags |= pkgconf_queue_collect_dependencies_main(client, pkg, data, depth - 1);
flattened_dep = pkgconf_dependency_copy(client, dep);
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required);
}
free(deps);
return eflags;
}
static unsigned int
pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client,
pkgconf_pkg_t *root,
void *data,
int maxdepth)
{
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
if (maxdepth == 0)
return eflags;
/* Short-circuit if we have already visited this node.
*/
if (root->serial == client->serial)
return eflags;
root->serial = client->serial;
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
{
PKGCONF_TRACE(client, "%s: collecting private dependencies, level %d", root->id, maxdepth);
/* XXX: ugly */
const unsigned int saved_flags = client->flags;
client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
eflags = pkgconf_queue_collect_dependencies_walk(client, root, &root->requires_private, data, maxdepth);
client->flags = saved_flags;
if (eflags != PKGCONF_PKG_ERRF_OK)
return eflags;
}
PKGCONF_TRACE(client, "%s: collecting public dependencies, level %d", root->id, maxdepth);
eflags = pkgconf_queue_collect_dependencies_walk(client, root, &root->required, data, maxdepth);
if (eflags != PKGCONF_PKG_ERRF_OK)
return eflags;
PKGCONF_TRACE(client, "%s: finished, %s", root->id, (root->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) ? "private" : "public");
return eflags;
}
static inline unsigned int
pkgconf_queue_collect_dependencies(pkgconf_client_t *client,
pkgconf_pkg_t *root,
void *data,
int maxdepth)
{
++client->serial;
return pkgconf_queue_collect_dependencies_main(client, root, data, maxdepth);
}
static inline unsigned int
pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth)
{
unsigned int result;
const unsigned int saved_flags = client->flags;
pkgconf_pkg_t initial_world = {
.id = "virtual:world",
.id = "user:request",
.realname = "virtual world package",
.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
};
@ -241,31 +241,39 @@ pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_lis
return PKGCONF_PKG_ERRF_DEPGRAPH_BREAK;
}
/* collect all the dependencies */
result = pkgconf_pkg_traverse(client, &initial_world, pkgconf_queue_collect_dependents, world, maxdepth, 0);
PKGCONF_TRACE(client, "solving");
result = pkgconf_pkg_traverse(client, &initial_world, NULL, NULL, maxdepth, 0);
if (result != PKGCONF_PKG_ERRF_OK)
{
pkgconf_solution_free(client, &initial_world);
return result;
}
PKGCONF_TRACE(client, "flattening");
result = pkgconf_queue_collect_dependencies(client, &initial_world, world, maxdepth);
if (result != PKGCONF_PKG_ERRF_OK)
{
pkgconf_solution_free(client, &initial_world);
return result;
}
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
{
PKGCONF_TRACE(client, "marking public deps");
client->flags &= ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
client->flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS;
result = pkgconf_pkg_traverse(client, &initial_world, pkgconf_queue_mark_public, &world->required, maxdepth, 0);
client->flags = saved_flags;
if (result != PKGCONF_PKG_ERRF_OK)
{
pkgconf_solution_free(client, &initial_world);
return result;
}
}
/* free the initial solution */
pkgconf_solution_free(client, &initial_world);
/* flatten the dependency set using serials.
* we copy the dependencies to a vector, and then erase the list.
* then we copy them back to the list.
*/
++client->serial;
PKGCONF_TRACE(client, "flattening requires deps");
flatten_dependency_set(client, &world->required);
++client->serial;
PKGCONF_TRACE(client, "flattening requires.private deps");
flatten_dependency_set(client, &world->requires_private);
return PKGCONF_PKG_ERRF_OK;
}

View File

@ -1,5 +1,5 @@
project('pkgconf', 'c',
version : '2.1.1',
version : '2.2.0',
license : 'ISC',
meson_version : '>=0.49',
default_options : ['c_std=c99'],
@ -96,8 +96,8 @@ libpkgconf = library('pkgconf',
'libpkgconf/tuple.c',
c_args: ['-DLIBPKGCONF_EXPORT', build_static],
install : true,
version : '4.0.0',
soversion : '4',
version : '5.0.0',
soversion : '5',
)
# For other projects using libpkgconfig as a subproject

View File

@ -231,7 +231,7 @@ libs_circular1_body()
libs_circular_directpc_body()
{
atf_check \
-o inline:"-lcircular-2 -lcircular-3 -lcircular-1\n" \
-o inline:"-lcircular-3 -lcircular-1 -lcircular-2\n" \
pkgconf --libs ${selfdir}/lib1/circular-3.pc
}

View File

@ -11,6 +11,9 @@ tests_init \
static_cflags \
private_duplication \
private_duplication_digraph \
foo_bar \
bar_foo \
foo_metapackage_3 \
libs_static2 \
missing \
requires_internal \
@ -38,7 +41,7 @@ libs_static_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o inline:"-L/test/lib -lbaz -L/test/lib -lzee -L/test/lib -lfoo\n" \
-o inline:"-L/test/lib -lbaz -L/test/lib -lzee -lfoo\n" \
pkgconf --static --libs baz
}
@ -46,7 +49,7 @@ libs_static_pure_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o inline:"-L/test/lib -lbaz -L/test/lib -lfoo\n" \
-o inline:"-L/test/lib -lbaz -lfoo\n" \
pkgconf --static --pure --libs baz
}
@ -70,7 +73,7 @@ private_duplication_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o inline:"-lprivate -lbaz -lzee -lbar -lfoo -lfoo\n" \
-o inline:"-lprivate -lbaz -lzee -lbar -lfoo\n" \
pkgconf --static --libs-only-l private-libs-duplication
}
@ -78,10 +81,7 @@ private_duplication_digraph_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o 'match:"virtual:world" -> "private-libs-duplication"' \
-o 'match:"virtual:world" -> "bar"' \
-o 'match:"virtual:world" -> "baz"' \
-o 'match:"virtual:world" -> "foo"' \
-o 'match:"user:request" -> "private-libs-duplication"' \
-o 'match:"private-libs-duplication" -> "bar"' \
-o 'match:"private-libs-duplication" -> "baz"' \
-o 'match:"bar" -> "foo"' \
@ -89,6 +89,30 @@ private_duplication_digraph_body()
pkgconf --static --libs-only-l private-libs-duplication --digraph
}
bar_foo_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o inline:"-lbar -lfoo\n" \
pkgconf --static --libs-only-l bar foo
}
foo_bar_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o inline:"-lbar -lfoo\n" \
pkgconf --static --libs-only-l foo bar
}
foo_metapackage_3_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o inline:"-lbar -lfoo\n" \
pkgconf --static --libs-only-l foo metapackage-3
}
libs_static2_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"