Compare commits

..

5 Commits

Author SHA1 Message Date
Dylan Baker 0ce072cb64 wip 2023-06-08 16:25:37 -07:00
Dylan Baker 1961be9a0e wip 2023-06-08 16:10:36 -07:00
Dylan Baker 77904819f2 tests: Add a python runner for tests that doesn't rely on ATF 2023-06-08 15:32:59 -07:00
Dylan Baker 68e3f24000 fragment: Mingw needs to use POSIX handling for `\\`
Otherwise it won't correctly escape things like spaces, and can print
out the `\` literal escaping nothing, which causes most shell lexers to
choke.

Fixes: #238
2023-06-08 12:02:28 -07:00
Dylan Baker 5c545fc9dc tests: Add a test for an escaped space 2023-06-05 11:52:47 -07:00
36 changed files with 591 additions and 1104 deletions

49
.gitignore vendored
View File

@ -1,19 +1,13 @@
Makefile
Makefile.in
.dirstamp
stamp-h*
*.h.in~ *.h.in~
*.o *.o
*.og *.og
*.op *.op
*.lo
*.gcno *.gcno
*.gcda *.gcda
*.gcov *.gcov
core core
.gdb_history .gdb_history
.libs
.deps .deps
*.exe *.exe
@ -22,8 +16,8 @@ core
*.orig *.orig
*.patch *.patch
*.rej *.rej
/tests/run.sh
# autoconf stuff
/aclocal.m4 /aclocal.m4
/autom4te.cache/ /autom4te.cache/
/buildsys.mk /buildsys.mk
@ -32,47 +26,8 @@ core
/config.log /config.log
/config.status /config.status
/configure /configure
/compile
/config.guess
/config.sub
/depcomp
/install-sh
/missing
# programs
/bomtool
/pkgconf /pkgconf
/pkgconf-gcov /pkgconf-gcov
/pkgconf-profile /pkgconf-profile
# libtool Makefile
/libtool
/ltmain.sh
/libpkgconf.la
/m4/libtool.m4
/m4/lt~obsolete.m4
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
# pkgconfig file
/libpkgconf.pc
# autoheader
/libpkgconf/config.h
/libpkgconf/config.h.in
# tests
/Kyuafile
/tests/Kyuafile
/tests/basic
/tests/builtins
/tests/conflicts
/tests/framework
/tests/parser
/tests/provides
/tests/regress
/tests/requires
/tests/sysroot
/tests/test_env.sh
/tests/version

View File

@ -9,7 +9,6 @@ personality_dir = @PERSONALITY_PATH@
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
nodist_pkgconfig_DATA = libpkgconf.pc nodist_pkgconfig_DATA = libpkgconf.pc
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = -DPERSONALITY_PATH=\"$(personality_dir)\" -DPKG_DEFAULT_PATH=\"$(pkg_default_dir)\" -DSYSTEM_INCLUDEDIR=\"$(system_includedir)\" -DSYSTEM_LIBDIR=\"$(system_libdir)\" AM_CFLAGS = -DPERSONALITY_PATH=\"$(personality_dir)\" -DPKG_DEFAULT_PATH=\"$(pkg_default_dir)\" -DSYSTEM_INCLUDEDIR=\"$(system_includedir)\" -DSYSTEM_LIBDIR=\"$(system_libdir)\"
bin_PROGRAMS = pkgconf bomtool bin_PROGRAMS = pkgconf bomtool
@ -28,8 +27,6 @@ EXTRA_DIST = pkg.m4 \
tests/lib1/paren-quoting.pc \ tests/lib1/paren-quoting.pc \
tests/lib1/argv-parse-3.pc \ tests/lib1/argv-parse-3.pc \
tests/lib1/foo.pc \ tests/lib1/foo.pc \
tests/lib1/foobar.pc \
tests/lib1/unavailable-provider.pc \
tests/lib1/prefix-foo1.pc \ tests/lib1/prefix-foo1.pc \
tests/lib1/argv-parse.pc \ tests/lib1/argv-parse.pc \
tests/lib1/framework-1.pc \ tests/lib1/framework-1.pc \
@ -96,9 +93,9 @@ EXTRA_DIST = pkg.m4 \
tests/lib1/metapackage.pc \ tests/lib1/metapackage.pc \
tests/lib1/metapackage-1.pc \ tests/lib1/metapackage-1.pc \
tests/lib1/metapackage-2.pc \ tests/lib1/metapackage-2.pc \
tests/lib1/metapackage-3.pc \
tests/lib1/explicit-sysroot.pc \ tests/lib1/explicit-sysroot.pc \
tests/lib1/escaped-backslash.pc \ tests/lib1/escaped-backslash.pc \
tests/lib1/escaped-space.pc \
tests/lib1/cflags-internal.pc \ tests/lib1/cflags-internal.pc \
tests/lib1/requires-internal.pc \ tests/lib1/requires-internal.pc \
tests/lib1/requires-internal-2.pc \ tests/lib1/requires-internal-2.pc \
@ -111,7 +108,6 @@ EXTRA_DIST = pkg.m4 \
tests/lib1/sysroot-dir-3.pc \ tests/lib1/sysroot-dir-3.pc \
tests/lib1/sysroot-dir-4.pc \ tests/lib1/sysroot-dir-4.pc \
tests/lib1/sysroot-dir-5.pc \ tests/lib1/sysroot-dir-5.pc \
tests/lib1/child-prefix/pkgconfig/child-prefix-1.pc \
$(test_scripts) \ $(test_scripts) \
doc/conf.py \ doc/conf.py \
doc/extract.py \ doc/extract.py \
@ -161,7 +157,7 @@ libpkgconf_la_SOURCES = \
libpkgconf/path.c \ libpkgconf/path.c \
libpkgconf/personality.c \ libpkgconf/personality.c \
libpkgconf/parser.c libpkgconf/parser.c
libpkgconf_la_LDFLAGS = -no-undefined -version-info 5:0:0 -export-symbols-regex '^pkgconf_' libpkgconf_la_LDFLAGS = -no-undefined -version-info 4:0:0 -export-symbols-regex '^pkgconf_'
dist_man_MANS = \ dist_man_MANS = \
man/pkgconf.1 \ man/pkgconf.1 \

View File

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

151
NEWS
View File

@ -1,157 +1,6 @@
Changes from previous version of pkgconf Changes from previous version of pkgconf
======================================== ========================================
Changes from 2.2.0 to 2.3.0:
----------------------------
* Fix compile with Meson on Solaris by defining __EXTENSIONS__.
* Add support for the PKG_CONFIG_RELOCATE_PATHS environmental variable.
When set, the program will act as if --define-prefix is always enabled.
* Color solution nodes that were part of the original query, and use
that coloring to skip over dependencies when generating DocumentNames
in bomtool.
* Enhance --env option to support variables with both --variable=varname
and --print-variables.
* Add --exists-cflags option which creates synthetic preprocessor
definition flags for every queried dependency when found.
* Document that Requires.private is always used for header paths.
Patch by Petr Písař.
* Fix minor documentation typos.
Patch by Pierce.
* Ensure string comparisons using <ctype.h> functions are done with
unsigned bytes to avoid undefined behavior.
Patch by Taylor R Campbell.
* Fix parsing edge-case bugs with dependency versions.
Patch by Kai Pastor.
* Change PKG_PROG_PKG_CONFIG autoconf macro to add a customizable
failure handler if pkg-config is not found.
Patch by Ismael Luceno.
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:
----------------------------
* Documentation fixes from Sam James and Stefan Weil.
* Fix --modversion with constraints.
Patch by Kai Pastor.
* Reintroduce an optimization to the dependency graph walker which avoids
revisiting already visited nodes.
Patch by Yi Chou with some modifications.
* Add a regression test to check that the dependency flattener is working
as expected.
Patch by Kai Pastor.
Changes from 2.0.3 to 2.1.0:
----------------------------
* Do not flatten the solver solution into the original world used as
input to the solver.
Patches by Kai Pastor.
* Fix warnings with GCC 14 -Walloc-size.
Patch by Sam James.
* Add --solution to the pkgconf CLI to dump the solver state.
* Improve the --digraph output to clarify cancelled edges in a given
solution.
* Demote requires dependencies to requires.private when a parent
dependency is pulled in via requires.private.
* Trim trailing whitespace when processing package arguments.
Patch by Colin Gillespie.
* Avoid strncmp() in --modversion version comparison.
Patch by Colin Gillespie.
* Update autoconf compile flag checking macro.
Patch by Peter Kokot.
* Add system default path configuration to Meson.
Patch by L. E. Segovia.
* Fix order of PKG_CONFIG_LIBDIR and PKG_CONFIG_PATH element processing.
Changes from 2.0.2 to 2.0.3:
----------------------------
* Fix some edge-cases with the new `--modversion` implementation
and add additional regression tests.
Patch by Colin Gillespie.
* Fix some format specifiers to use PRIu64 in debug tracing.
Changes from 2.0.1 to 2.0.2:
----------------------------
* Fix long-standing bug where package identifiers for "uninstalled"
packages incorrectly included the "-uninstalled" suffix.
This was exposed by the recent change to `--modversion` in 2.0.1.
Changes from 2.0.0 to 2.0.1:
----------------------------
* The behavior of --modversion was largely reverted back to the traditional
pkg-config behavior, but still operates on a solved dependency graph.
The order of --modversion output is based on the dependency resolution
queue which is passed to the solver, which itself generally maps to the
order of the constrants provided on the command line.
* A new flag, --verbose, has been added. When used with `--modversion`, it
is possible to disambiguate which version belongs to which module:
% pkgconf --modversion --verbose foo bar
foo: 1.2.3
bar: 1.3
Changes from 1.9.5 to 2.0.0:
----------------------------
* When flattening the dependency graph, retain the latest seen edges
rather than the earliest.
* Fix a long-standing bug where the dependency resolution queue was
evaluated in reverse. This bug masked the aforementioned dependency
flattening bug in many cases.
* Fix handling of --with-path, which was appending paths to the search
list rather than prepending them as intended.
* Error when --modversion is requested with more than one package, as
the output is ambiguous.
Changes from 1.9.4 to 1.9.5: Changes from 1.9.4 to 1.9.5:
---------------------------- ----------------------------

View File

@ -50,7 +50,7 @@ As previously mentioned, pkgconf makes optimizations to the linker flags in both
case of static and shared linking in order to avoid overlinking binaries and also case of static and shared linking in order to avoid overlinking binaries and also
simplifies the `CFLAGS` and `LIBS` output of the pkgconf tool for improved readability. simplifies the `CFLAGS` and `LIBS` output of the pkgconf tool for improved readability.
This functionality depends on the pkg-config module properly declaring its dependency This functionality depends on the pkg-config module properly declaring it's dependency
tree instead of using `Libs` and `Cflags` fields to directly link against other modules tree instead of using `Libs` and `Cflags` fields to directly link against other modules
which have pkg-config metadata files installed. which have pkg-config metadata files installed.
@ -116,7 +116,7 @@ flags like so:
pkgconf is compiled using [Meson](https://mesonbuild.com) on Windows. In theory, you could also use pkgconf is compiled using [Meson](https://mesonbuild.com) on Windows. In theory, you could also use
Meson to build on UNIX, but this is not recommended at this time as pkgconf is typically built Meson to build on UNIX, but this is not recommended at this time as it pkgconf is typically built
much earlier than Meson. much earlier than Meson.
$ meson setup build -Dtests=disabled $ meson setup build -Dtests=disabled
@ -137,8 +137,8 @@ to make this determination themselves.
## release tarballs ## release tarballs
Release tarballs are available at <https://distfiles.ariadne.space/pkgconf/>. Release tarballs are available at <https://distfiles.dereferenced.org/pkgconf/>.
Please only use the tarballs from distfiles.ariadne.space. Please only use the tarballs from distfiles.dereferenced.org.
## contacts ## contacts

View File

@ -65,9 +65,6 @@ sbom_name(pkgconf_pkg_t *world)
pkgconf_dependency_t *dep = node->data; pkgconf_dependency_t *dep = node->data;
pkgconf_pkg_t *match = dep->match; pkgconf_pkg_t *match = dep->match;
if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY)
continue;
if (!dep->match) if (!dep->match)
continue; continue;

View File

@ -71,14 +71,11 @@
#define PKG_DUMP_PERSONALITY (((uint64_t) 1) << 43) #define PKG_DUMP_PERSONALITY (((uint64_t) 1) << 43)
#define PKG_SHARED (((uint64_t) 1) << 44) #define PKG_SHARED (((uint64_t) 1) << 44)
#define PKG_DUMP_LICENSE (((uint64_t) 1) << 45) #define PKG_DUMP_LICENSE (((uint64_t) 1) << 45)
#define PKG_SOLUTION (((uint64_t) 1) << 46)
#define PKG_EXISTS_CFLAGS (((uint64_t) 1) << 47)
static pkgconf_client_t pkg_client; static pkgconf_client_t pkg_client;
static const pkgconf_fragment_render_ops_t *want_render_ops = NULL; static const pkgconf_fragment_render_ops_t *want_render_ops = NULL;
static uint64_t want_flags; static uint64_t want_flags;
static int verbosity = 0;
static int maximum_traverse_depth = 2000; static int maximum_traverse_depth = 2000;
static size_t maximum_package_count = 0; static size_t maximum_package_count = 0;
@ -255,71 +252,32 @@ apply_provides(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int
#ifndef PKGCONF_LITE #ifndef PKGCONF_LITE
static void static void
print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) print_digraph_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
{ {
pkgconf_node_t *node; pkgconf_node_t *node;
(void) client; (void) client;
pkgconf_pkg_t **last_seen = data; (void) unused;
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); 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_FOREACH_LIST_ENTRY(pkg->required.head, node)
{ {
pkgconf_dependency_t *dep = node->data; pkgconf_dependency_t *dep = node->data;
const char *dep_id = (dep->match != NULL) ? dep->match->id : dep->package;
if ((dep->flags & PKGCONF_PKG_DEPF_PRIVATE) == 0) printf("\"%s\" -- \"%s\" [fontname=Sans fontsize=8]\n", dep->package, pkg->id);
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_id);
} }
} }
static bool static bool
apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
{ {
int eflag; int eflag;
pkgconf_list_t *list = data;
pkgconf_pkg_t *last_seen = NULL;
pkgconf_node_t *iter;
printf("digraph deptree {\n"); printf("graph deptree {\n");
printf("edge [color=blue len=7.5 fontname=Sans fontsize=8]\n"); printf("edge [color=blue len=7.5 fontname=Sans fontsize=8]\n");
printf("node [fontname=Sans fontsize=8]\n"); printf("node [fontname=Sans fontsize=8]\n");
printf("\"user:request\" [fontname=Sans fontsize=8]\n");
PKGCONF_FOREACH_LIST_ENTRY(list->head, iter) eflag = pkgconf_pkg_traverse(client, world, print_digraph_node, unused, maxdepth, 0);
{
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) if (eflag != PKGCONF_PKG_ERRF_OK)
return false; return false;
@ -327,64 +285,25 @@ apply_digraph(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int ma
printf("}\n"); printf("}\n");
return true; return true;
} }
static void
print_solution_node(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
{
(void) client;
(void) unused;
printf("%s (%"PRIu64")\n", pkg->id, pkg->identifier);
}
static bool
apply_print_solution(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
{
int eflag;
eflag = pkgconf_pkg_traverse(client, world, print_solution_node, unused, maxdepth, 0);
return eflag == PKGCONF_PKG_ERRF_OK;
}
#endif #endif
static bool static bool
apply_modversion(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth) apply_modversion(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int maxdepth)
{ {
pkgconf_node_t *queue_iter; pkgconf_node_t *iter;
pkgconf_list_t *pkgq = data;
(void) client; (void) client;
(void) unused;
(void) maxdepth; (void) maxdepth;
PKGCONF_FOREACH_LIST_ENTRY(pkgq->head, queue_iter) PKGCONF_FOREACH_LIST_ENTRY(world->required.head, iter)
{ {
pkgconf_node_t *world_iter; pkgconf_dependency_t *dep = iter->data;
pkgconf_queue_t *queue_node = queue_iter->data;
PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter)
{
pkgconf_dependency_t *dep = world_iter->data;
pkgconf_pkg_t *pkg = dep->match; pkgconf_pkg_t *pkg = dep->match;
const size_t name_len = strlen(pkg->why); if (pkg->version != NULL)
if (name_len > strlen(queue_node->package) ||
strncmp(pkg->why, queue_node->package, name_len) ||
(queue_node->package[name_len] != 0 &&
!isspace((unsigned char)queue_node->package[name_len]) &&
!PKGCONF_IS_OPERATOR_CHAR(queue_node->package[name_len])))
continue;
if (pkg->version != NULL) {
if (verbosity)
printf("%s: ", pkg->id);
printf("%s\n", pkg->version); printf("%s\n", pkg->version);
} }
break;
}
}
return true; return true;
} }
@ -454,8 +373,7 @@ apply_variable(pkgconf_client_t *client, pkgconf_pkg_t *world, void *variable, i
static bool static bool
apply_env_var(const char *prefix, pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth, apply_env_var(const char *prefix, pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth,
unsigned int (*collect_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth), unsigned int (*collect_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth),
bool (*filter_fn)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data), bool (*filter_fn)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data))
void (*postprocess_fn)(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list))
{ {
pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER; pkgconf_list_t unfiltered_list = PKGCONF_LIST_INITIALIZER;
pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER; pkgconf_list_t filtered_list = PKGCONF_LIST_INITIALIZER;
@ -468,9 +386,6 @@ apply_env_var(const char *prefix, pkgconf_client_t *client, pkgconf_pkg_t *world
pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_fn, NULL); pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_fn, NULL);
if (postprocess_fn != NULL)
postprocess_fn(client, world, &filtered_list);
if (filtered_list.head == NULL) if (filtered_list.head == NULL)
goto out; goto out;
@ -485,94 +400,6 @@ out:
return true; return true;
} }
static void
maybe_add_module_definitions(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *fragment_list)
{
pkgconf_node_t *world_iter;
if ((want_flags & PKG_EXISTS_CFLAGS) != PKG_EXISTS_CFLAGS)
return;
PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter)
{
pkgconf_dependency_t *dep = world_iter->data;
char havebuf[PKGCONF_ITEM_SIZE];
char *p;
if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY)
continue;
if (dep->match == NULL)
continue;
snprintf(havebuf, sizeof havebuf, "HAVE_%s", dep->match->id);
for (p = havebuf; *p; p++)
{
switch (*p)
{
case ' ':
case '-':
*p = '_';
break;
default:
*p = toupper((unsigned char) *p);
}
}
pkgconf_fragment_insert(client, fragment_list, 'D', havebuf, false);
}
}
static void
apply_env_variables(pkgconf_client_t *client, pkgconf_pkg_t *world, const char *env_prefix)
{
(void) client;
pkgconf_node_t *world_iter;
PKGCONF_FOREACH_LIST_ENTRY(world->required.head, world_iter)
{
pkgconf_dependency_t *dep = world_iter->data;
pkgconf_pkg_t *pkg = dep->match;
pkgconf_node_t *tuple_iter;
if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY)
continue;
if (dep->match == NULL)
continue;
PKGCONF_FOREACH_LIST_ENTRY(pkg->vars.head, tuple_iter)
{
pkgconf_tuple_t *tuple = tuple_iter->data;
char havebuf[PKGCONF_ITEM_SIZE];
char *p;
if (want_variable != NULL && strcmp(want_variable, tuple->key))
continue;
snprintf(havebuf, sizeof havebuf, "%s_%s", env_prefix, tuple->key);
for (p = havebuf; *p; p++)
{
switch (*p)
{
case ' ':
case '-':
*p = '_';
break;
default:
*p = toupper((unsigned char) *p);
}
}
printf("%s='%s'\n", havebuf, tuple->value);
}
}
}
static bool static bool
apply_env(pkgconf_client_t *client, pkgconf_pkg_t *world, void *env_prefix_p, int maxdepth) apply_env(pkgconf_client_t *client, pkgconf_pkg_t *world, void *env_prefix_p, int maxdepth)
{ {
@ -585,16 +412,13 @@ apply_env(pkgconf_client_t *client, pkgconf_pkg_t *world, void *env_prefix_p, in
return false; return false;
snprintf(workbuf, sizeof workbuf, "%s_CFLAGS", want_env_prefix); snprintf(workbuf, sizeof workbuf, "%s_CFLAGS", want_env_prefix);
if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_cflags, filter_cflags, maybe_add_module_definitions)) if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_cflags, filter_cflags))
return false; return false;
snprintf(workbuf, sizeof workbuf, "%s_LIBS", want_env_prefix); snprintf(workbuf, sizeof workbuf, "%s_LIBS", want_env_prefix);
if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_libs, filter_libs, NULL)) if (!apply_env_var(workbuf, client, world, maxdepth, pkgconf_pkg_libs, filter_libs))
return false; return false;
if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES || want_variable != NULL)
apply_env_variables(client, world, want_env_prefix);
return true; return true;
} }
@ -612,7 +436,6 @@ apply_cflags(pkgconf_client_t *client, pkgconf_pkg_t *world, void *unused, int m
return false; return false;
pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_cflags, NULL); pkgconf_fragment_filter(client, &filtered_list, &unfiltered_list, filter_cflags, NULL);
maybe_add_module_definitions(client, world, &filtered_list);
if (filtered_list.head == NULL) if (filtered_list.head == NULL)
goto out; goto out;
@ -820,7 +643,6 @@ usage(void)
printf(" --help this message\n"); printf(" --help this message\n");
printf(" --about print pkgconf version and license to stdout\n"); printf(" --about print pkgconf version and license to stdout\n");
printf(" --version print supported pkg-config version to stdout\n"); printf(" --version print supported pkg-config version to stdout\n");
printf(" --verbose print additional information\n");
printf(" --atleast-pkgconfig-version check whether or not pkgconf is compatible\n"); printf(" --atleast-pkgconfig-version check whether or not pkgconf is compatible\n");
printf(" with a specified pkg-config version\n"); printf(" with a specified pkg-config version\n");
printf(" --errors-to-stdout print all errors on stdout instead of stderr\n"); printf(" --errors-to-stdout print all errors on stdout instead of stderr\n");
@ -887,7 +709,6 @@ usage(void)
printf(" --print-variables print all known variables in module to stdout\n"); printf(" --print-variables print all known variables in module to stdout\n");
#ifndef PKGCONF_LITE #ifndef PKGCONF_LITE
printf(" --digraph print entire dependency graph in graphviz 'dot' format\n"); printf(" --digraph print entire dependency graph in graphviz 'dot' format\n");
printf(" --solution print dependency graph solution in a simple format\n");
#endif #endif
printf(" --keep-system-cflags keep -I%s entries in cflags output\n", SYSTEM_INCLUDEDIR); printf(" --keep-system-cflags keep -I%s entries in cflags output\n", SYSTEM_INCLUDEDIR);
printf(" --keep-system-libs keep -L%s entries in libs output\n", SYSTEM_LIBDIR); printf(" --keep-system-libs keep -L%s entries in libs output\n", SYSTEM_LIBDIR);
@ -895,14 +716,12 @@ usage(void)
printf(" --modversion print the specified module's version to stdout\n"); printf(" --modversion print the specified module's version to stdout\n");
printf(" --internal-cflags do not filter 'internal' cflags from output\n"); printf(" --internal-cflags do not filter 'internal' cflags from output\n");
printf(" --license print the specified module's license to stdout if known\n"); printf(" --license print the specified module's license to stdout if known\n");
printf(" --exists-cflags add -DHAVE_FOO fragments to cflags for each found module\n");
printf("\nfiltering output:\n\n"); printf("\nfiltering output:\n\n");
#ifndef PKGCONF_LITE #ifndef PKGCONF_LITE
printf(" --msvc-syntax print translatable fragments in MSVC syntax\n"); printf(" --msvc-syntax print translatable fragments in MSVC syntax\n");
#endif #endif
printf(" --fragment-filter=types filter output fragments to the specified types\n"); printf(" --fragment-filter=types filter output fragments to the specified types\n");
printf(" --env=prefix print output as shell-compatible environmental variables\n");
printf("\nreport bugs to <%s>.\n", PACKAGE_BUGREPORT); printf("\nreport bugs to <%s>.\n", PACKAGE_BUGREPORT);
} }
@ -1042,7 +861,6 @@ main(int argc, char *argv[])
{ "print-variables", no_argument, &want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, }, { "print-variables", no_argument, &want_flags, PKG_VARIABLES|PKG_PRINT_ERRORS, },
#ifndef PKGCONF_LITE #ifndef PKGCONF_LITE
{ "digraph", no_argument, &want_flags, PKG_DIGRAPH, }, { "digraph", no_argument, &want_flags, PKG_DIGRAPH, },
{ "solution", no_argument, &want_flags, PKG_SOLUTION, },
#endif #endif
{ "help", no_argument, &want_flags, PKG_HELP, }, { "help", no_argument, &want_flags, PKG_HELP, },
{ "env-only", no_argument, &want_flags, PKG_ENV_ONLY, }, { "env-only", no_argument, &want_flags, PKG_ENV_ONLY, },
@ -1091,8 +909,6 @@ main(int argc, char *argv[])
{ "personality", required_argument, NULL, 53 }, { "personality", required_argument, NULL, 53 },
#endif #endif
{ "license", no_argument, &want_flags, PKG_DUMP_LICENSE }, { "license", no_argument, &want_flags, PKG_DUMP_LICENSE },
{ "verbose", no_argument, NULL, 55 },
{ "exists-cflags", no_argument, &want_flags, PKG_EXISTS_CFLAGS },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
@ -1133,7 +949,7 @@ main(int argc, char *argv[])
logfile_arg = pkg_optarg; logfile_arg = pkg_optarg;
break; break;
case 42: case 42:
pkgconf_path_prepend(pkg_optarg, &dir_list, true); pkgconf_path_add(pkg_optarg, &dir_list, true);
break; break;
case 43: case 43:
pkgconf_client_set_prefix_varname(&pkg_client, pkg_optarg); pkgconf_client_set_prefix_varname(&pkg_client, pkg_optarg);
@ -1152,9 +968,6 @@ main(int argc, char *argv[])
personality = pkgconf_cross_personality_find(pkg_optarg); personality = pkgconf_cross_personality_find(pkg_optarg);
break; break;
#endif #endif
case 55:
verbosity++;
break;
case '?': case '?':
case ':': case ':':
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
@ -1282,7 +1095,7 @@ main(int argc, char *argv[])
/* On Windows we want to always redefine the prefix by default /* On Windows we want to always redefine the prefix by default
* but allow that behavior to be manually disabled */ * but allow that behavior to be manually disabled */
#if !defined(_WIN32) && !defined(_WIN64) #if !defined(_WIN32) && !defined(_WIN64)
if ((want_flags & PKG_DEFINE_PREFIX) == PKG_DEFINE_PREFIX || getenv("PKG_CONFIG_RELOCATE_PATHS") != NULL) if ((want_flags & PKG_DEFINE_PREFIX) == PKG_DEFINE_PREFIX)
#endif #endif
want_client_flags |= PKGCONF_PKG_PKGF_REDEFINE_PREFIX; want_client_flags |= PKGCONF_PKG_PKGF_REDEFINE_PREFIX;
@ -1298,24 +1111,21 @@ main(int argc, char *argv[])
if ((want_flags & PKG_INTERNAL_CFLAGS) == PKG_INTERNAL_CFLAGS) if ((want_flags & PKG_INTERNAL_CFLAGS) == PKG_INTERNAL_CFLAGS)
want_client_flags |= PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS; want_client_flags |= PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS;
/* if these selectors are used, it means that we are querying metadata. /* if these selectors are used, it means that we are inquiring about a single package.
* so signal to libpkgconf that we only want to walk the flattened dependency set. * so signal to libpkgconf that we do not want to use the dependency resolver for more than one level,
* and also limit the SAT problem to a single package.
*/ */
if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION || if (((want_flags & PKG_REQUIRES) == PKG_REQUIRES ||
(want_flags & PKG_REQUIRES) == PKG_REQUIRES ||
(want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE || (want_flags & PKG_REQUIRES_PRIVATE) == PKG_REQUIRES_PRIVATE ||
(want_flags & PKG_PROVIDES) == PKG_PROVIDES || (want_flags & PKG_PROVIDES) == PKG_PROVIDES ||
(want_flags & PKG_VARIABLES) == PKG_VARIABLES || (want_flags & PKG_VARIABLES) == PKG_VARIABLES ||
(want_flags & PKG_PATH) == PKG_PATH) (want_flags & PKG_MODVERSION) == PKG_MODVERSION ||
maximum_traverse_depth = 1;
/* if we are asking for a variable, path or list of variables, this only makes sense
* for a single package.
*/
if ((want_flags & PKG_VARIABLES) == PKG_VARIABLES ||
(want_flags & PKG_PATH) == PKG_PATH || (want_flags & PKG_PATH) == PKG_PATH ||
want_variable != NULL) want_variable != NULL))
{
maximum_package_count = 1; maximum_package_count = 1;
maximum_traverse_depth = 1;
}
if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL) if (getenv("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") != NULL)
want_flags |= PKG_KEEP_SYSTEM_CFLAGS; want_flags |= PKG_KEEP_SYSTEM_CFLAGS;
@ -1507,8 +1317,7 @@ cleanup3:
while (1) while (1)
{ {
char *package = argv[pkg_optind]; const char *package = argv[pkg_optind];
char *end;
if (package == NULL) if (package == NULL)
break; break;
@ -1528,24 +1337,11 @@ cleanup3:
continue; continue;
} }
end = package + strlen(package) - 1;
while(end > package && isspace((unsigned char)end[0])) end--;
end[1] = '\0';
if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1]))) if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1])))
{ {
pkgconf_queue_push(&pkgq, package); pkgconf_queue_push(&pkgq, package);
pkg_optind++; pkg_optind++;
} }
else if (argv[pkg_optind + 2] == NULL)
{
char packagebuf[PKGCONF_BUFSIZE];
snprintf(packagebuf, sizeof packagebuf, "%s %s", package, argv[pkg_optind + 1]);
pkg_optind += 2;
pkgconf_queue_push(&pkgq, packagebuf);
}
else else
{ {
char packagebuf[PKGCONF_BUFSIZE]; char packagebuf[PKGCONF_BUFSIZE];
@ -1601,7 +1397,7 @@ cleanup3:
if (want_env_prefix != NULL) if (want_env_prefix != NULL)
{ {
apply_env(&pkg_client, &world, want_env_prefix, 2); apply_env(&pkg_client, &world, want_env_prefix, 2);
goto out; want_flags = 0;
} }
if ((want_flags & PKG_PROVIDES) == PKG_PROVIDES) if ((want_flags & PKG_PROVIDES) == PKG_PROVIDES)
@ -1614,20 +1410,14 @@ cleanup3:
if ((want_flags & PKG_DIGRAPH) == PKG_DIGRAPH) if ((want_flags & PKG_DIGRAPH) == PKG_DIGRAPH)
{ {
want_flags &= ~(PKG_CFLAGS|PKG_LIBS); want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
apply_digraph(&pkg_client, &world, &pkgq, 2); apply_digraph(&pkg_client, &world, NULL, 2);
}
if ((want_flags & PKG_SOLUTION) == PKG_SOLUTION)
{
want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
apply_print_solution(&pkg_client, &world, NULL, 2);
} }
#endif #endif
if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION) if ((want_flags & PKG_MODVERSION) == PKG_MODVERSION)
{ {
want_flags &= ~(PKG_CFLAGS|PKG_LIBS); want_flags &= ~(PKG_CFLAGS|PKG_LIBS);
apply_modversion(&pkg_client, &world, &pkgq, 2); apply_modversion(&pkg_client, &world, NULL, 2);
} }
if ((want_flags & PKG_PATH) == PKG_PATH) if ((want_flags & PKG_PATH) == PKG_PATH)
@ -1676,8 +1466,20 @@ cleanup3:
printf(" "); printf(" ");
if (!(want_flags & PKG_STATIC)) if (!(want_flags & PKG_STATIC))
{
pkgconf_client_set_flags(&pkg_client, pkg_client.flags & ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE); 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); 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. dnl from the use of this software.
AC_PREREQ([2.71]) AC_PREREQ([2.71])
AC_INIT([pkgconf],[2.3.0],[https://github.com/pkgconf/pkgconf/issues/new]) AC_INIT([pkgconf],[1.9.5],[https://github.com/pkgconf/pkgconf/issues/new])
AC_CONFIG_SRCDIR([cli/main.c]) AC_CONFIG_SRCDIR([cli/main.c])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"]) AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"])

View File

@ -51,7 +51,7 @@ The `dependency` module provides support for building `dependency lists` (the ba
.. c:function:: void pkgconf_dependency_free(pkgconf_list_t *list) .. c:function:: void pkgconf_dependency_free(pkgconf_list_t *list)
Release a dependency list and its child dependency nodes. Release a dependency list and it's child dependency nodes.
:param pkgconf_list_t* list: The dependency list to release. :param pkgconf_list_t* list: The dependency list to release.
:return: nothing :return: nothing

View File

@ -72,7 +72,7 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
memset(buf, 0, strlen(src) + 1); memset(buf, 0, strlen(src) + 1);
*argv = calloc(argv_size, sizeof (void *)); *argv = calloc(sizeof (void *), argv_size);
(*argv)[argc_count] = dst_iter; (*argv)[argc_count] = dst_iter;
while (*src_iter) while (*src_iter)

View File

@ -161,7 +161,7 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
pkgconf_client_t * pkgconf_client_t *
pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality) pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
{ {
pkgconf_client_t *out = calloc(1, sizeof(pkgconf_client_t)); pkgconf_client_t *out = calloc(sizeof(pkgconf_client_t), 1);
pkgconf_client_init(out, error_handler, error_handler_data, personality); pkgconf_client_init(out, error_handler, error_handler_data, personality);
return out; return out;
} }

View File

@ -66,8 +66,3 @@
#mesondefine SYSTEM_INCLUDEDIR #mesondefine SYSTEM_INCLUDEDIR
#mesondefine SYSTEM_LIBDIR #mesondefine SYSTEM_LIBDIR
#mesondefine PERSONALITY_PATH #mesondefine PERSONALITY_PATH
/* Enable Solaris extensions. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif

View File

@ -130,7 +130,7 @@ pkgconf_dependency_addraw(pkgconf_client_t *client, pkgconf_list_t *list, const
{ {
pkgconf_dependency_t *dep; pkgconf_dependency_t *dep;
dep = calloc(1, sizeof(pkgconf_dependency_t)); dep = calloc(sizeof(pkgconf_dependency_t), 1);
dep->package = pkgconf_strndup(package, package_sz); dep->package = pkgconf_strndup(package, package_sz);
if (version_sz != 0) if (version_sz != 0)
@ -262,7 +262,7 @@ pkgconf_dependency_unref(pkgconf_client_t *client, pkgconf_dependency_t *dep)
* *
* .. c:function:: void pkgconf_dependency_free(pkgconf_list_t *list) * .. c:function:: void pkgconf_dependency_free(pkgconf_list_t *list)
* *
* Release a dependency list and its child dependency nodes. * Release a dependency list and it's child dependency nodes.
* *
* :param pkgconf_list_t* list: The dependency list to release. * :param pkgconf_list_t* list: The dependency list to release.
* :return: nothing * :return: nothing
@ -386,16 +386,15 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
break; break;
case INSIDE_OPERATOR: case INSIDE_OPERATOR:
if (PKGCONF_IS_OPERATOR_CHAR(*ptr)) if (!PKGCONF_IS_OPERATOR_CHAR(*ptr))
{ {
if (cnameptr < cnameend)
*cnameptr++ = *ptr;
break;
}
state = AFTER_OPERATOR; state = AFTER_OPERATOR;
compare = pkgconf_pkg_comparator_lookup_by_name(cmpname); compare = pkgconf_pkg_comparator_lookup_by_name(cmpname);
// fallthrough }
else if (cnameptr < cnameend)
*cnameptr++ = *ptr;
break;
case AFTER_OPERATOR: case AFTER_OPERATOR:
if (!isspace((unsigned char)*ptr)) if (!isspace((unsigned char)*ptr))
@ -470,7 +469,7 @@ pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *de
{ {
pkgconf_dependency_t *new_dep; pkgconf_dependency_t *new_dep;
new_dep = calloc(1, sizeof(pkgconf_dependency_t)); new_dep = calloc(sizeof(pkgconf_dependency_t), 1);
new_dep->package = strdup(dep->package); new_dep->package = strdup(dep->package);
if (dep->version != NULL) if (dep->version != NULL)

View File

@ -120,38 +120,6 @@ pkgconf_fragment_copy_munged(const pkgconf_client_t *client, const char *source,
return strdup(mungebuf); return strdup(mungebuf);
} }
/*
* !doc
*
* .. c:function:: void pkgconf_fragment_insert(const pkgconf_client_t *client, pkgconf_list_t *list, char type, const char *data, bool tail)
*
* Adds a `fragment` of text to a `fragment list` directly without interpreting it.
*
* :param pkgconf_client_t* client: The pkgconf client being accessed.
* :param pkgconf_list_t* list: The fragment list.
* :param char type: The type of the fragment.
* :param char* data: The data of the fragment.
* :param bool tail: Whether to place the fragment at the beginning of the list or the end.
* :return: nothing
*/
void
pkgconf_fragment_insert(const pkgconf_client_t *client, pkgconf_list_t *list, char type, const char *data, bool tail)
{
pkgconf_fragment_t *frag;
frag = calloc(1, sizeof(pkgconf_fragment_t));
frag->type = type;
frag->data = pkgconf_fragment_copy_munged(client, data, 0);
if (tail)
{
pkgconf_node_insert_tail(&frag->iter, frag, list);
return;
}
pkgconf_node_insert(&frag->iter, frag, list);
}
/* /*
* !doc * !doc
* *
@ -175,7 +143,7 @@ pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const
if (strlen(string) > 1 && !pkgconf_fragment_is_special(string)) if (strlen(string) > 1 && !pkgconf_fragment_is_special(string))
{ {
frag = calloc(1, sizeof(pkgconf_fragment_t)); frag = calloc(sizeof(pkgconf_fragment_t), 1);
frag->type = *(string + 1); frag->type = *(string + 1);
frag->data = pkgconf_fragment_copy_munged(client, string + 2, flags); frag->data = pkgconf_fragment_copy_munged(client, string + 2, flags);
@ -224,7 +192,7 @@ pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const
} }
} }
frag = calloc(1, sizeof(pkgconf_fragment_t)); frag = calloc(sizeof(pkgconf_fragment_t), 1);
frag->type = 0; frag->type = 0;
frag->data = strdup(string); frag->data = strdup(string);
@ -385,7 +353,7 @@ pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, cons
else if (!is_private && !pkgconf_fragment_can_merge_back(base, client->flags, is_private) && (pkgconf_fragment_lookup(list, base) != NULL)) else if (!is_private && !pkgconf_fragment_can_merge_back(base, client->flags, is_private) && (pkgconf_fragment_lookup(list, base) != NULL))
return; return;
frag = calloc(1, sizeof(pkgconf_fragment_t)); frag = calloc(sizeof(pkgconf_fragment_t), 1);
frag->type = base->type; frag->type = base->type;
frag->merged = base->merged; frag->merged = base->merged;
@ -459,7 +427,7 @@ fragment_quote(const pkgconf_fragment_t *frag)
if (frag->data == NULL) if (frag->data == NULL)
return NULL; return NULL;
out = dst = calloc(1, outlen); out = dst = calloc(outlen, 1);
for (; *src; src++) for (; *src; src++)
{ {
@ -470,7 +438,7 @@ fragment_quote(const pkgconf_fragment_t *frag)
(*src > ':' && *src < '=') || (*src > ':' && *src < '=') ||
(*src > '=' && *src < '@') || (*src > '=' && *src < '@') ||
(*src > 'Z' && *src < '\\') || (*src > 'Z' && *src < '\\') ||
#ifndef _WIN32 #ifndef _MSC_VER
(*src == '\\') || (*src == '\\') ||
#endif #endif
(*src > '\\' && *src < '^') || (*src > '\\' && *src < '^') ||

View File

@ -16,7 +16,6 @@
#ifndef LIBPKGCONF__LIBPKGCONF_H #ifndef LIBPKGCONF__LIBPKGCONF_H
#define LIBPKGCONF__LIBPKGCONF_H #define LIBPKGCONF__LIBPKGCONF_H
#include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
@ -68,7 +67,6 @@ typedef struct pkgconf_fragment_ pkgconf_fragment_t;
typedef struct pkgconf_path_ pkgconf_path_t; typedef struct pkgconf_path_ pkgconf_path_t;
typedef struct pkgconf_client_ pkgconf_client_t; typedef struct pkgconf_client_ pkgconf_client_t;
typedef struct pkgconf_cross_personality_ pkgconf_cross_personality_t; typedef struct pkgconf_cross_personality_ pkgconf_cross_personality_t;
typedef struct pkgconf_queue_ pkgconf_queue_t;
#define PKGCONF_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #define PKGCONF_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
@ -81,13 +79,8 @@ typedef struct pkgconf_queue_ pkgconf_queue_t;
#define PKGCONF_FOREACH_LIST_ENTRY_REVERSE(tail, value) \ #define PKGCONF_FOREACH_LIST_ENTRY_REVERSE(tail, value) \
for ((value) = (tail); (value) != NULL; (value) = (value)->prev) for ((value) = (tail); (value) != NULL; (value) = (value)->prev)
#define LIBPKGCONF_VERSION 20300 #define LIBPKGCONF_VERSION 10905
#define LIBPKGCONF_VERSION_STR "2.3.0" #define LIBPKGCONF_VERSION_STR "1.9.5"
struct pkgconf_queue_ {
pkgconf_node_t iter;
char *package;
};
struct pkgconf_fragment_ { struct pkgconf_fragment_ {
pkgconf_node_t iter; pkgconf_node_t iter;
@ -137,8 +130,6 @@ struct pkgconf_path_ {
#define PKGCONF_PKG_PROPF_CACHED 0x02 #define PKGCONF_PKG_PROPF_CACHED 0x02
#define PKGCONF_PKG_PROPF_UNINSTALLED 0x08 #define PKGCONF_PKG_PROPF_UNINSTALLED 0x08
#define PKGCONF_PKG_PROPF_VIRTUAL 0x10 #define PKGCONF_PKG_PROPF_VIRTUAL 0x10
#define PKGCONF_PKG_PROPF_ANCESTOR 0x20
#define PKGCONF_PKG_PROPF_VISITED_PRIVATE 0x40
struct pkgconf_pkg_ { struct pkgconf_pkg_ {
int refcount; int refcount;
@ -152,7 +143,6 @@ struct pkgconf_pkg_ {
char *license; char *license;
char *maintainer; char *maintainer;
char *copyright; char *copyright;
char *why;
pkgconf_list_t libs; pkgconf_list_t libs;
pkgconf_list_t libs_private; pkgconf_list_t libs_private;
@ -177,7 +167,8 @@ struct pkgconf_pkg_ {
pkgconf_tuple_t *prefix; pkgconf_tuple_t *prefix;
uint64_t serial; uint64_t serial;
uint64_t identifier;
size_t hits;
}; };
typedef bool (*pkgconf_pkg_iteration_func_t)(const pkgconf_pkg_t *pkg, void *data); typedef bool (*pkgconf_pkg_iteration_func_t)(const pkgconf_pkg_t *pkg, void *data);
@ -213,7 +204,6 @@ struct pkgconf_client_ {
bool already_sent_notice; bool already_sent_notice;
uint64_t serial; uint64_t serial;
uint64_t identifier;
pkgconf_pkg_t **cache_table; pkgconf_pkg_t **cache_table;
size_t cache_count; size_t cache_count;
@ -283,7 +273,6 @@ PKGCONF_API void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *p
#define PKGCONF_PKG_DEPF_INTERNAL 0x1 #define PKGCONF_PKG_DEPF_INTERNAL 0x1
#define PKGCONF_PKG_DEPF_PRIVATE 0x2 #define PKGCONF_PKG_DEPF_PRIVATE 0x2
#define PKGCONF_PKG_DEPF_QUERY 0x4
#define PKGCONF_PKG_ERRF_OK 0x0 #define PKGCONF_PKG_ERRF_OK 0x0
#define PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND 0x1 #define PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND 0x1
@ -367,7 +356,6 @@ typedef struct pkgconf_fragment_render_ops_ {
typedef bool (*pkgconf_fragment_filter_func_t)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data); typedef bool (*pkgconf_fragment_filter_func_t)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data);
PKGCONF_API bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value, unsigned int flags); PKGCONF_API bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value, unsigned int flags);
PKGCONF_API void pkgconf_fragment_insert(const pkgconf_client_t *client, pkgconf_list_t *list, char type, const char *data, bool tail);
PKGCONF_API void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string, unsigned int flags); PKGCONF_API void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string, unsigned int flags);
PKGCONF_API void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private); PKGCONF_API void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private);
PKGCONF_API void pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base); PKGCONF_API void pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base);
@ -415,7 +403,6 @@ PKGCONF_API void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pk
/* path.c */ /* path.c */
PKGCONF_API void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter); PKGCONF_API void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API void pkgconf_path_prepend(const char *text, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter); PKGCONF_API size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter); PKGCONF_API size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist); PKGCONF_API bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist);

View File

@ -58,51 +58,6 @@ path_list_contains_entry(const char *text, pkgconf_list_t *dirlist)
* variables. * variables.
*/ */
static pkgconf_path_t *
prepare_path_node(const char *text, pkgconf_list_t *dirlist, bool filter)
{
pkgconf_path_t *node;
char path[PKGCONF_ITEM_SIZE];
pkgconf_strlcpy(path, text, sizeof path);
pkgconf_path_relocate(path, sizeof path);
#ifdef PKGCONF_CACHE_INODES
struct stat st;
if (filter)
{
if (lstat(path, &st) == -1)
return NULL;
if (S_ISLNK(st.st_mode))
{
char pathbuf[PKGCONF_ITEM_SIZE * 4];
char *linkdest = realpath(path, pathbuf);
if (linkdest != NULL && stat(linkdest, &st) == -1)
return NULL;
}
if (path_list_contains_entry(path, dirlist, &st))
return NULL;
}
#else
if (filter && path_list_contains_entry(path, dirlist))
return NULL;
#endif
node = calloc(1, sizeof(pkgconf_path_t));
node->path = strdup(path);
#ifdef PKGCONF_CACHE_INODES
if (filter) {
node->handle_path = (void *)(intptr_t) st.st_ino;
node->handle_device = (void *)(intptr_t) st.st_dev;
}
#endif
return node;
}
/* /*
* !doc * !doc
* *
@ -118,35 +73,48 @@ prepare_path_node(const char *text, pkgconf_list_t *dirlist, bool filter)
void void
pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter) pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter)
{ {
pkgconf_path_t *node = prepare_path_node(text, dirlist, filter); pkgconf_path_t *node;
if (node == NULL) char path[PKGCONF_ITEM_SIZE];
pkgconf_strlcpy(path, text, sizeof path);
pkgconf_path_relocate(path, sizeof path);
#ifdef PKGCONF_CACHE_INODES
struct stat st;
if (filter)
{
if (lstat(path, &st) == -1)
return; return;
if (S_ISLNK(st.st_mode))
{
char pathbuf[PKGCONF_ITEM_SIZE * 4];
char *linkdest = realpath(path, pathbuf);
if (linkdest != NULL && stat(linkdest, &st) == -1)
return;
}
if (path_list_contains_entry(path, dirlist, &st))
return;
}
#else
if (filter && path_list_contains_entry(path, dirlist))
return;
#endif
node = calloc(sizeof(pkgconf_path_t), 1);
node->path = strdup(path);
#ifdef PKGCONF_CACHE_INODES
if (filter) {
node->handle_path = (void *)(intptr_t) st.st_ino;
node->handle_device = (void *)(intptr_t) st.st_dev;
}
#endif
pkgconf_node_insert_tail(&node->lnode, node, dirlist); pkgconf_node_insert_tail(&node->lnode, node, dirlist);
} }
/*
* !doc
*
* .. c:function:: void pkgconf_path_prepend(const char *text, pkgconf_list_t *dirlist)
*
* Prepends a path node to a path list. If the path is already in the list, do nothing.
*
* :param char* text: The path text to add as a path node.
* :param pkgconf_list_t* dirlist: The path list to add the path node to.
* :param bool filter: Whether to perform duplicate filtering.
* :return: nothing
*/
void
pkgconf_path_prepend(const char *text, pkgconf_list_t *dirlist, bool filter)
{
pkgconf_path_t *node = prepare_path_node(text, dirlist, filter);
if (node == NULL)
return;
pkgconf_node_insert(&node->lnode, node, dirlist);
}
/* /*
* !doc * !doc
* *
@ -266,7 +234,7 @@ pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
{ {
pkgconf_path_t *srcpath = n->data, *path; pkgconf_path_t *srcpath = n->data, *path;
path = calloc(1, sizeof(pkgconf_path_t)); path = calloc(sizeof(pkgconf_path_t), 1);
path->path = strdup(srcpath->path); path->path = strdup(srcpath->path);
#ifdef PKGCONF_CACHE_INODES #ifdef PKGCONF_CACHE_INODES

View File

@ -38,13 +38,8 @@ static unsigned default_personality_init = 0;
static pkgconf_cross_personality_t default_personality = { static pkgconf_cross_personality_t default_personality = {
.name = "default", .name = "default",
#ifdef _WIN32 #ifdef _WIN32
/* PE/COFF uses a different linking model than ELF and Mach-O, where
* all transitive dependency references must be processed by the linker
* when linking the final executable image, even if those dependencies
* are pulled in as DLLs.
* This translates to always using --static on Windows targets.
*/
.want_default_static = true, .want_default_static = true,
.want_default_pure = true,
#endif #endif
}; };
@ -246,25 +241,23 @@ personality_warn_func(void *p, const char *fmt, ...)
} }
static pkgconf_cross_personality_t * static pkgconf_cross_personality_t *
load_personality_with_path(const char *path, const char *triplet, bool datadir) load_personality_with_path(const char *path, const char *triplet)
{ {
char pathbuf[PKGCONF_ITEM_SIZE]; char pathbuf[PKGCONF_ITEM_SIZE];
FILE *f; FILE *f;
pkgconf_cross_personality_t *p; pkgconf_cross_personality_t *p;
/* if triplet is null, assume that path is a direct path to the personality file */ /* if triplet is null, assume that path is a direct path to the personality file */
if (triplet == NULL) if (triplet != NULL)
pkgconf_strlcpy(pathbuf, path, sizeof pathbuf);
else if (datadir)
snprintf(pathbuf, sizeof pathbuf, "%s/pkgconfig/personality.d/%s.personality", path, triplet);
else
snprintf(pathbuf, sizeof pathbuf, "%s/%s.personality", path, triplet); snprintf(pathbuf, sizeof pathbuf, "%s/%s.personality", path, triplet);
else
pkgconf_strlcpy(pathbuf, path, sizeof pathbuf);
f = fopen(pathbuf, "r"); f = fopen(pathbuf, "r");
if (f == NULL) if (f == NULL)
return NULL; return NULL;
p = calloc(1, sizeof(pkgconf_cross_personality_t)); p = calloc(sizeof(pkgconf_cross_personality_t), 1);
if (triplet != NULL) if (triplet != NULL)
p->name = strdup(triplet); p->name = strdup(triplet);
pkgconf_parser_parse(f, p, personality_parser_ops, personality_warn_func, pathbuf); pkgconf_parser_parse(f, p, personality_parser_ops, personality_warn_func, pathbuf);
@ -288,51 +281,21 @@ pkgconf_cross_personality_find(const char *triplet)
pkgconf_list_t plist = PKGCONF_LIST_INITIALIZER; pkgconf_list_t plist = PKGCONF_LIST_INITIALIZER;
pkgconf_node_t *n; pkgconf_node_t *n;
pkgconf_cross_personality_t *out = NULL; pkgconf_cross_personality_t *out = NULL;
#if ! defined(_WIN32) && ! defined(__HAIKU__)
char pathbuf[PKGCONF_ITEM_SIZE];
const char *envvar;
#endif
out = load_personality_with_path(triplet, NULL, false); out = load_personality_with_path(triplet, NULL);
if (out != NULL) if (out != NULL)
return out; return out;
if (!valid_triplet(triplet)) if (!valid_triplet(triplet))
return NULL; return NULL;
#if ! defined(_WIN32) && ! defined(__HAIKU__)
envvar = getenv("XDG_DATA_HOME");
if (envvar != NULL)
pkgconf_path_add(envvar, &plist, true);
else {
envvar = getenv("HOME");
if (envvar != NULL) {
pkgconf_strlcpy(pathbuf, envvar, sizeof pathbuf);
pkgconf_strlcat(pathbuf, "/.local/share", sizeof pathbuf);
pkgconf_path_add(pathbuf, &plist, true);
}
}
pkgconf_path_build_from_environ("XDG_DATA_DIRS", "/usr/local/share" PKG_CONFIG_PATH_SEP_S "/usr/share", &plist, true);
PKGCONF_FOREACH_LIST_ENTRY(plist.head, n)
{
pkgconf_path_t *pn = n->data;
out = load_personality_with_path(pn->path, triplet, true);
if (out != NULL)
goto finish;
}
pkgconf_path_free(&plist);
#endif
pkgconf_path_split(PERSONALITY_PATH, &plist, true); pkgconf_path_split(PERSONALITY_PATH, &plist, true);
PKGCONF_FOREACH_LIST_ENTRY(plist.head, n) PKGCONF_FOREACH_LIST_ENTRY(plist.head, n)
{ {
pkgconf_path_t *pn = n->data; pkgconf_path_t *pn = n->data;
out = load_personality_with_path(pn->path, triplet, false); out = load_personality_with_path(pn->path, triplet);
if (out != NULL) if (out != NULL)
goto finish; goto finish;
} }

View File

@ -250,7 +250,7 @@ determine_prefix(const pkgconf_pkg_t *pkg, char *buf, size_t buflen)
static char * static char *
convert_path_to_value(const char *path) convert_path_to_value(const char *path)
{ {
char *buf = calloc(1, (strlen(path) + 1) * 2); char *buf = calloc((strlen(path) + 1) * 2, 1);
char *bptr = buf; char *bptr = buf;
const char *i; const char *i;
@ -419,7 +419,7 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
pkgconf_pkg_t *pkg; pkgconf_pkg_t *pkg;
char *idptr; char *idptr;
pkg = calloc(1, sizeof(pkgconf_pkg_t)); pkg = calloc(sizeof(pkgconf_pkg_t), 1);
pkg->owner = client; pkg->owner = client;
pkg->filename = strdup(filename); pkg->filename = strdup(filename);
pkg->pc_filedir = pkg_get_parent_dir(pkg); pkg->pc_filedir = pkg_get_parent_dir(pkg);
@ -457,13 +457,6 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
if (idptr) if (idptr)
*idptr = '\0'; *idptr = '\0';
if (pkg->flags & PKGCONF_PKG_PROPF_UNINSTALLED)
{
idptr = strrchr(pkg->id, '-');
if (idptr)
*idptr = '\0';
}
pkgconf_parser_parse(f, pkg, pkg_parser_funcs, (pkgconf_parser_warn_func_t) pkg_warn_func, pkg->filename); pkgconf_parser_parse(f, pkg, pkg_parser_funcs, (pkgconf_parser_warn_func_t) pkg_warn_func, pkg->filename);
if (!pkgconf_pkg_validate(client, pkg)) if (!pkgconf_pkg_validate(client, pkg))
@ -546,9 +539,6 @@ pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
if (pkg->copyright != NULL) if (pkg->copyright != NULL)
free(pkg->copyright); free(pkg->copyright);
if (pkg->why != NULL)
free(pkg->why);
free(pkg); free(pkg);
} }
@ -775,13 +765,15 @@ pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
{ {
if ((f = fopen(name, "r")) != NULL) if ((f = fopen(name, "r")) != NULL)
{ {
pkgconf_pkg_t *pkg;
PKGCONF_TRACE(client, "%s is a file", name); PKGCONF_TRACE(client, "%s is a file", name);
pkg = pkgconf_pkg_new_from_file(client, name, f, 0); pkg = pkgconf_pkg_new_from_file(client, name, f, 0);
if (pkg != NULL) if (pkg != NULL)
{ {
pkgconf_path_add(pkg->pc_filedir, &client->dir_list, true); pkgconf_path_add(pkg->pc_filedir, &client->dir_list, true);
goto out; return pkg;
} }
} }
} }
@ -1399,10 +1391,9 @@ pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pk
return NULL; return NULL;
} }
pkg = pkgconf_pkg_scan_providers(client, pkgdep, eflags); return pkgconf_pkg_scan_providers(client, pkgdep, eflags);
} }
else
{
if (pkg->id == NULL) if (pkg->id == NULL)
pkg->id = strdup(pkgdep->package); pkg->id = strdup(pkgdep->package);
@ -1413,10 +1404,6 @@ pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pk
} }
else else
pkgdep->match = pkgconf_pkg_ref(client, pkg); pkgdep->match = pkgconf_pkg_ref(client, pkg);
}
if (pkg != NULL && pkg->why == NULL)
pkg->why = strdup(pkgdep->package);
return pkg; return pkg;
} }
@ -1454,11 +1441,7 @@ pkgconf_pkg_report_graph_error(pkgconf_client_t *client, pkgconf_pkg_t *parent,
client->already_sent_notice = true; client->already_sent_notice = true;
} }
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_error(client, "Package '%s', required by '%s', not found\n", node->package, parent->id);
pkgconf_audit_log(client, "%s NOT-FOUND\n", node->package); pkgconf_audit_log(client, "%s NOT-FOUND\n", node->package);
} }
else if (eflags & PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH) else if (eflags & PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH)
@ -1489,8 +1472,6 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
unsigned int eflags = PKGCONF_PKG_ERRF_OK; unsigned int eflags = PKGCONF_PKG_ERRF_OK;
pkgconf_node_t *node, *next; pkgconf_node_t *node, *next;
parent->flags |= PKGCONF_PKG_PROPF_ANCESTOR;
PKGCONF_FOREACH_LIST_ENTRY_SAFE(deplist->head, next, node) PKGCONF_FOREACH_LIST_ENTRY_SAFE(deplist->head, next, node)
{ {
unsigned int eflags_local = PKGCONF_PKG_ERRF_OK; unsigned int eflags_local = PKGCONF_PKG_ERRF_OK;
@ -1511,8 +1492,10 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
if (pkgdep == NULL) if (pkgdep == NULL)
continue; continue;
if((pkgdep->flags & PKGCONF_PKG_PROPF_ANCESTOR) != 0) if (pkgdep->serial == client->serial && !(parent->flags & PKGCONF_PKG_PROPF_VIRTUAL))
{ {
pkgdep->hits++;
/* In this case we have a circular reference. /* In this case we have a circular reference.
* We break that by deleteing the circular node from the * We break that by deleteing the circular node from the
* the list, so that we dont create a situation where * the list, so that we dont create a situation where
@ -1540,13 +1523,13 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
pkgconf_audit_log_dependency(client, pkgdep, depnode); pkgconf_audit_log_dependency(client, pkgdep, depnode);
pkgdep->hits++;
pkgdep->serial = client->serial;
eflags |= pkgconf_pkg_traverse_main(client, pkgdep, func, data, depth - 1, skip_flags); eflags |= pkgconf_pkg_traverse_main(client, pkgdep, func, data, depth - 1, skip_flags);
next: next:
pkgconf_pkg_unref(client, pkgdep); pkgconf_pkg_unref(client, pkgdep);
} }
parent->flags &= ~PKGCONF_PKG_PROPF_ANCESTOR;
return eflags; return eflags;
} }
@ -1626,17 +1609,7 @@ pkgconf_pkg_traverse_main(pkgconf_client_t *client,
if (maxdepth == 0) if (maxdepth == 0)
return eflags; return eflags;
/* Short-circuit if we have already visited this node. PKGCONF_TRACE(client, "%s: level %d, serial %lu", root->id, maxdepth, client->serial);
*/
if (root->serial == client->serial)
return eflags;
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);
if ((root->flags & PKGCONF_PKG_PROPF_VIRTUAL) != PKGCONF_PKG_PROPF_VIRTUAL || (client->flags & PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL) != PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL) if ((root->flags & PKGCONF_PKG_PROPF_VIRTUAL) != PKGCONF_PKG_PROPF_VIRTUAL || (client->flags & PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL) != PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL)
{ {
@ -1644,23 +1617,21 @@ pkgconf_pkg_traverse_main(pkgconf_client_t *client,
func(client, root, data); func(client, root, data);
} }
if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_CONFLICTS) && root->conflicts.head != NULL) if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_CONFLICTS))
{ {
PKGCONF_TRACE(client, "%s: walking 'Conflicts' list", root->id);
eflags = pkgconf_pkg_walk_conflicts_list(client, root, &root->conflicts); eflags = pkgconf_pkg_walk_conflicts_list(client, root, &root->conflicts);
if (eflags != PKGCONF_PKG_ERRF_OK) if (eflags != PKGCONF_PKG_ERRF_OK)
return eflags; 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); eflags = pkgconf_pkg_walk_list(client, root, &root->required, func, data, maxdepth, skip_flags);
if (eflags != PKGCONF_PKG_ERRF_OK) if (eflags != PKGCONF_PKG_ERRF_OK)
return eflags; return eflags;
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE) 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 */ /* XXX: ugly */
client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE; client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
@ -1685,9 +1656,6 @@ pkgconf_pkg_traverse(pkgconf_client_t *client,
if (root->flags & PKGCONF_PKG_PROPF_VIRTUAL) if (root->flags & PKGCONF_PKG_PROPF_VIRTUAL)
client->serial++; client->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); return pkgconf_pkg_traverse_main(client, root, func, data, maxdepth, skip_flags);
} }

View File

@ -29,6 +29,11 @@
* Using the `queue` module functions is the recommended way of working with dependency graphs. * Using the `queue` module functions is the recommended way of working with dependency graphs.
*/ */
typedef struct {
pkgconf_node_t iter;
char *package;
} pkgconf_queue_t;
/* /*
* !doc * !doc
* *
@ -43,10 +48,10 @@
void void
pkgconf_queue_push(pkgconf_list_t *list, const char *package) pkgconf_queue_push(pkgconf_list_t *list, const char *package)
{ {
pkgconf_queue_t *pkgq = calloc(1, sizeof(pkgconf_queue_t)); pkgconf_queue_t *pkgq = calloc(sizeof(pkgconf_queue_t), 1);
pkgq->package = strdup(package); pkgq->package = strdup(package);
pkgconf_node_insert_tail(&pkgq->iter, pkgq, list); pkgconf_node_insert(&pkgq->iter, pkgq, list);
} }
/* /*
@ -72,7 +77,7 @@ pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_li
pkgconf_queue_t *pkgq; pkgconf_queue_t *pkgq;
pkgq = iter->data; pkgq = iter->data;
pkgconf_dependency_parse(client, world, &world->required, pkgq->package, PKGCONF_PKG_DEPF_QUERY); pkgconf_dependency_parse(client, world, &world->required, pkgq->package, 0);
} }
return (world->required.head != NULL); return (world->required.head != NULL);
@ -103,175 +108,149 @@ pkgconf_queue_free(pkgconf_list_t *list)
} }
static void static void
pkgconf_queue_mark_public(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data) pkgconf_queue_collect_dependents(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_list_t *deplist,
void *data,
int depth)
{
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
pkgconf_node_t *node; pkgconf_node_t *node;
pkgconf_pkg_t *world = data; pkgconf_pkg_t *world = data;
PKGCONF_FOREACH_LIST_ENTRY_REVERSE(deplist->tail, node) if (pkg == world)
return;
PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
{
pkgconf_dependency_t *flattened_dep;
flattened_dep = pkgconf_dependency_copy(client, node->data);
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required);
}
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
{
PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
{
pkgconf_dependency_t *flattened_dep;
flattened_dep = pkgconf_dependency_copy(client, node->data);
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->hits - depA->match->hits;
}
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_dependency_t *dep = node->data; pkgconf_dependency_t *dep = node->data;
pkgconf_dependency_t *flattened_dep; pkgconf_pkg_t *pkg = pkgconf_pkg_verify_dependency(client, dep, NULL);
pkgconf_pkg_t *pkg = dep->match;
if (*dep->package == '\0')
continue;
if (pkg == NULL) if (pkg == NULL)
continue;
if (pkg->serial == client->serial)
{
pkgconf_node_delete(node, list);
pkgconf_dependency_unref(client, dep);
goto next;
}
if (dep->match == NULL)
{ {
PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package); PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package);
abort(); abort();
} }
if (pkg->serial == client->serial) /* 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)
continue; continue;
if (client->flags & PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE) memset(&dep->iter, '\0', sizeof (dep->iter));
pkg->flags |= PKGCONF_PKG_PROPF_VISITED_PRIVATE; pkgconf_node_insert(&dep->iter, dep, list);
else
pkg->flags &= ~PKGCONF_PKG_PROPF_VISITED_PRIVATE;
eflags |= pkgconf_queue_collect_dependencies_main(client, pkg, data, depth - 1); PKGCONF_TRACE(client, "slot "SIZE_FMT_SPECIFIER": dep %s matched to %p<%s> hits "SIZE_FMT_SPECIFIER, i, dep->package, dep->match, dep->match->id, dep->match->hits);
flattened_dep = pkgconf_dependency_copy(client, dep);
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required);
} }
return eflags; free(deps);
}
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->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->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 static inline unsigned int
pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth) pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth)
{ {
unsigned int result; unsigned int result;
const unsigned int saved_flags = client->flags;
pkgconf_pkg_t initial_world = {
.id = "user:request",
.realname = "virtual world package",
.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
};
if (!pkgconf_queue_compile(client, &initial_world, list)) if (!pkgconf_queue_compile(client, world, list))
{
pkgconf_solution_free(client, &initial_world);
return PKGCONF_PKG_ERRF_DEPGRAPH_BREAK; return PKGCONF_PKG_ERRF_DEPGRAPH_BREAK;
}
PKGCONF_TRACE(client, "solving"); /* collect all the dependencies */
result = pkgconf_pkg_traverse(client, &initial_world, NULL, NULL, maxdepth, 0); result = pkgconf_pkg_traverse(client, world, pkgconf_queue_collect_dependents, world, maxdepth, 0);
if (result != PKGCONF_PKG_ERRF_OK) if (result != PKGCONF_PKG_ERRF_OK)
{
pkgconf_solution_free(client, &initial_world);
return result; return result;
}
PKGCONF_TRACE(client, "flattening"); /* flatten the dependency set using serials.
result = pkgconf_queue_collect_dependencies(client, &initial_world, world, maxdepth); * we copy the dependencies to a vector, and then erase the list.
if (result != PKGCONF_PKG_ERRF_OK) * then we copy them back to the list.
{ */
pkgconf_solution_free(client, &initial_world); ++client->serial;
return result;
}
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE) PKGCONF_TRACE(client, "flattening requires deps");
{ flatten_dependency_set(client, &world->required);
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 */ ++client->serial;
pkgconf_solution_free(client, &initial_world);
PKGCONF_TRACE(client, "flattening requires.private deps");
flatten_dependency_set(client, &world->requires_private);
return PKGCONF_PKG_ERRF_OK; return PKGCONF_PKG_ERRF_OK;
} }

View File

@ -156,7 +156,7 @@ pkgconf_tuple_find_delete(pkgconf_list_t *list, const char *key)
static char * static char *
dequote(const char *value) dequote(const char *value)
{ {
char *buf = calloc(1, (strlen(value) + 1) * 2); char *buf = calloc((strlen(value) + 1) * 2, 1);
char *bptr = buf; char *bptr = buf;
const char *i; const char *i;
char quote = 0; char quote = 0;
@ -236,7 +236,7 @@ pkgconf_tuple_t *
pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key, const char *value, bool parse, unsigned int flags) pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key, const char *value, bool parse, unsigned int flags)
{ {
char *dequote_value; char *dequote_value;
pkgconf_tuple_t *tuple = calloc(1, sizeof(pkgconf_tuple_t)); pkgconf_tuple_t *tuple = calloc(sizeof(pkgconf_tuple_t), 1);
pkgconf_tuple_find_delete(list, key); pkgconf_tuple_find_delete(list, key);

View File

@ -29,12 +29,33 @@
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> # Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> # Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
# #
# Copying and distribution of this file, with or without modification, are # This program is free software: you can redistribute it and/or modify it
# permitted in any medium without royalty provided the copyright notice # under the terms of the GNU General Public License as published by the
# and this notice are preserved. This file is offered as-is, without any # Free Software Foundation, either version 3 of the License, or (at your
# warranty. # option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 6 #serial 5
AC_DEFUN([AX_CHECK_COMPILE_FLAG], AC_DEFUN([AX_CHECK_COMPILE_FLAG],
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF

View File

@ -126,10 +126,9 @@ All dependencies must be satisfied or the pkg-config implementation must not use
the package. the package.
(optional; dependency list) (optional; dependency list)
.It Requires.private .It Requires.private
Required dependencies that must be met for the package to be usable for header Required dependencies that must be met for the package to be usable for static linking.
inclusion and static linking.
All dependencies must be satisfied or the pkg-config implementation must not use All dependencies must be satisfied or the pkg-config implementation must not use
the package for header inclusion and static linking. the package for static linking.
(optional; dependency list) (optional; dependency list)
.It Conflicts .It Conflicts
Dependencies that must not be met for the package to be usable. Dependencies that must not be met for the package to be usable.

View File

@ -1,5 +1,5 @@
project('pkgconf', 'c', project('pkgconf', 'c',
version : '2.3.0', version : '1.9.5',
license : 'ISC', license : 'ISC',
meson_version : '>=0.49', meson_version : '>=0.49',
default_options : ['c_std=c99'], default_options : ['c_std=c99'],
@ -31,7 +31,7 @@ check_functions = [
foreach f : check_functions foreach f : check_functions
name = f[0].to_upper().underscorify() name = f[0].to_upper().underscorify()
if cc.has_function(f[0], prefix : '#define _BSD_SOURCE\n#define _DEFAULT_SOURCE\n#include <@0@>'.format(f[1])) and cc.has_header_symbol(f[1], f[0], prefix : '#define _BSD_SOURCE\n#define _DEFAULT_SOURCE') if cc.has_function(f[0], prefix : '#define _BSD_SOURCE\n#include <@0@>'.format(f[1])) and cc.has_header_symbol(f[1], f[0], prefix : '#define _BSD_SOURCE')
cdata.set('HAVE_@0@'.format(name), 1) cdata.set('HAVE_@0@'.format(name), 1)
cdata.set('HAVE_DECL_@0@'.format(name), 1) cdata.set('HAVE_DECL_@0@'.format(name), 1)
else else
@ -49,18 +49,8 @@ foreach f : ['libdir', 'datadir']
personality_path += [join_paths(get_option('prefix'), get_option(f), 'pkgconfig', 'personality.d')] personality_path += [join_paths(get_option('prefix'), get_option(f), 'pkgconfig', 'personality.d')]
endforeach endforeach
SYSTEM_LIBDIR = get_option('with-system-libdir')
if SYSTEM_LIBDIR != ''
cdata.set_quoted('SYSTEM_LIBDIR', SYSTEM_LIBDIR)
else
cdata.set_quoted('SYSTEM_LIBDIR', join_paths(get_option('prefix'), get_option('libdir'))) cdata.set_quoted('SYSTEM_LIBDIR', join_paths(get_option('prefix'), get_option('libdir')))
endif
SYSTEM_INCLUDEDIR = get_option('with-system-includedir')
if SYSTEM_INCLUDEDIR != ''
cdata.set_quoted('SYSTEM_INCLUDEDIR', SYSTEM_INCLUDEDIR)
else
cdata.set_quoted('SYSTEM_INCLUDEDIR', join_paths(get_option('prefix'), get_option('includedir'))) cdata.set_quoted('SYSTEM_INCLUDEDIR', join_paths(get_option('prefix'), get_option('includedir')))
endif
cdata.set_quoted('PKG_DEFAULT_PATH', ':'.join(default_path)) cdata.set_quoted('PKG_DEFAULT_PATH', ':'.join(default_path))
cdata.set_quoted('PERSONALITY_PATH', ':'.join(personality_path)) cdata.set_quoted('PERSONALITY_PATH', ':'.join(personality_path))
cdata.set_quoted('PACKAGE_NAME', meson.project_name()) cdata.set_quoted('PACKAGE_NAME', meson.project_name())
@ -96,8 +86,8 @@ libpkgconf = library('pkgconf',
'libpkgconf/tuple.c', 'libpkgconf/tuple.c',
c_args: ['-DLIBPKGCONF_EXPORT', build_static], c_args: ['-DLIBPKGCONF_EXPORT', build_static],
install : true, install : true,
version : '5.0.0', version : '4.0.0',
soversion : '5', soversion : '4',
) )
# For other projects using libpkgconfig as a subproject # For other projects using libpkgconfig as a subproject

View File

@ -3,17 +3,3 @@ option(
type: 'feature', type: 'feature',
description: 'Build tests which depends upon the kyua framework', description: 'Build tests which depends upon the kyua framework',
) )
option(
'with-system-libdir',
type: 'string',
value: '',
description: 'Specify the system library directory (default {prefix}/{libdir})'
)
option(
'with-system-includedir',
type: 'string',
value: '',
description: 'Specify the system include directory (default {prefix}/{includedir})'
)

13
pkg.m4
View File

@ -46,8 +46,8 @@ m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ ])dnl PKG_PREREQ
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND]) dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
dnl --------------------------------------------------------- dnl ----------------------------------
dnl Since: 0.16 dnl Since: 0.16
dnl dnl
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
@ -55,12 +55,6 @@ dnl first found in the path. Checks that the version of pkg-config found
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
dnl used since that's the first version where most current features of dnl used since that's the first version where most current features of
dnl pkg-config existed. dnl pkg-config existed.
dnl
dnl If pkg-config is not found or older than specified, it will result
dnl in an empty PKG_CONFIG variable. To avoid widespread issues with
dnl scripts not checking it, ACTION-IF-NOT-FOUND defaults to aborting.
dnl You can specify [PKG_CONFIG=false] as an action instead, which would
dnl result in pkg-config tests failing, but no bogus error messages.
AC_DEFUN([PKG_PROG_PKG_CONFIG], AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) [m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
@ -81,9 +75,6 @@ if test -n "$PKG_CONFIG"; then
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
PKG_CONFIG="" PKG_CONFIG=""
fi fi
fi
if test -z "$PKG_CONFIG"; then
m4_default([$2], [AC_MSG_ERROR([pkg-config not found])])
fi[]dnl fi[]dnl
])dnl PKG_PROG_PKG_CONFIG ])dnl PKG_PROG_PKG_CONFIG

View File

@ -11,7 +11,6 @@ tests_init \
libs_cflags_version_alt \ libs_cflags_version_alt \
libs_cflags_version_different \ libs_cflags_version_different \
libs_cflags_version_different_bad \ libs_cflags_version_different_bad \
libs_env \
exists_nonexitent \ exists_nonexitent \
nonexitent \ nonexitent \
exists_version \ exists_version \
@ -22,8 +21,6 @@ tests_init \
exists2 \ exists2 \
exists3 \ exists3 \
exists_version_alt \ exists_version_alt \
exists_cflags \
exists_cflags_env \
uninstalled_bad \ uninstalled_bad \
uninstalled \ uninstalled \
libs_intermediary \ libs_intermediary \
@ -32,7 +29,6 @@ tests_init \
libs_circular_directpc \ libs_circular_directpc \
libs_static \ libs_static \
libs_static_ordering \ libs_static_ordering \
libs_metapackage \
license_isc \ license_isc \
license_noassertion \ license_noassertion \
modversion_noflatten \ modversion_noflatten \
@ -42,9 +38,7 @@ tests_init \
arbitary_path \ arbitary_path \
with_path \ with_path \
relocatable \ relocatable \
single_depth_selectors \ single_depth_selectors
print_variables_env \
variable_env
noargs_body() noargs_body()
{ {
@ -236,7 +230,7 @@ libs_circular1_body()
libs_circular_directpc_body() libs_circular_directpc_body()
{ {
atf_check \ atf_check \
-o inline:"-lcircular-3 -lcircular-1 -lcircular-2\n" \ -o inline:"-lcircular-2 -lcircular-3 -lcircular-1\n" \
pkgconf --libs ${selfdir}/lib1/circular-3.pc pkgconf --libs ${selfdir}/lib1/circular-3.pc
} }
@ -256,14 +250,6 @@ libs_static_ordering_body()
pkgconf --libs foo bar pkgconf --libs foo bar
} }
libs_metapackage_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o inline:"-L/test/lib -lbar -lfoo\n" \
pkgconf --static --libs metapackage-3
}
pkg_config_path_body() pkg_config_path_body()
{ {
export PKG_CONFIG_PATH="${selfdir}/lib1${PATH_SEP}${selfdir}/lib2" export PKG_CONFIG_PATH="${selfdir}/lib1${PATH_SEP}${selfdir}/lib2"
@ -345,39 +331,3 @@ modversion_noflatten_body()
-o inline:"1.3\n" \ -o inline:"1.3\n" \
pkgconf --with-path=${selfdir}/lib1 --modversion bar pkgconf --with-path=${selfdir}/lib1 --modversion bar
} }
exists_cflags_body()
{
atf_check \
-o inline:"-DHAVE_FOO\n" \
pkgconf --with-path=${selfdir}/lib1 --cflags --exists-cflags --fragment-filter=D foo
}
exists_cflags_env_body()
{
atf_check \
-o inline:"FOO_CFLAGS='-DHAVE_FOO'\n" \
pkgconf --with-path=${selfdir}/lib1 --cflags --exists-cflags --fragment-filter=D --env=FOO foo
}
libs_env_body()
{
atf_check \
-o inline:"FOO_LIBS='-L/test/lib -lfoo'\n" \
pkgconf --with-path=${selfdir}/lib1 --libs --env=FOO foo
}
print_variables_env_body()
{
atf_check \
-o inline:"FOO_CFLAGS='-fPIC -I/test/include/foo'\nFOO_LIBS='-L/test/lib -lfoo'\nFOO_INCLUDEDIR='/test/include'\nFOO_LIBDIR='/test/lib'\nFOO_EXEC_PREFIX='/test'\nFOO_PREFIX='/test'\nFOO_PCFILEDIR='${selfdir}/lib1'\n" \
pkgconf --with-path=${selfdir}/lib1 --env=FOO --print-variables --cflags --libs foo
}
variable_env_body()
{
atf_check \
-o inline:"FOO_INCLUDEDIR='/test/include'\n" \
pkgconf --with-path=${selfdir}/lib1 --env=FOO --variable=includedir foo
}

137
tests/basic.toml Normal file
View File

@ -0,0 +1,137 @@
[noargs]
exitcode = 1
[libs]
stdout = "-L/test/lib -lfoo\n"
args = ["--libs", "foo"]
[libs.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[lib_cflags]
stdout = "-fPIC -I/test/include/foo -L/test/lib -lfoo\n"
args = ["--cflags", "--libs", "foo"]
[lib_cflags.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[lib_cflags_version]
stdout = "-fPIC -I/test/include/foo -L/test/lib -lfoo\n"
args = ["--cflags", "--libs", "foo > 1.2"]
[lib_cflags_version.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[lib_cflags_version_multiple]
stdout = "-fPIC -I/test/include/foo -L/test/lib -lbar -lfoo\n"
args = ["--cflags", "--libs", "foo > 1.2 bar >= 1.3"]
[lib_cflags_version_multiple.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[lib_cflags_version_multiple_comma]
stdout = "-fPIC -I/test/include/foo -L/test/lib -lbar -lfoo\n"
args = ["--cflags", "--libs", "foo > 1.2,bar >= 1.3"]
[lib_cflags_version_multiple_comma.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[lib_cflags_version_alt]
stdout = "-fPIC -I/test/include/foo -L/test/lib -lfoo\n"
args = ["--cflags", "--libs", "foo", ">", "1.2"]
[lib_cflags_version_alt.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[lib_cflags_version_different]
stdout = "-fPIC -I/test/include/foo -L/test/lib -lfoo\n"
args = ["--cflags", "--libs", "foo", "!=", "1.3"]
[lib_cflags_version_different.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[lib_cflags_version_different_bad]
exitcode = 1
stderr = "Package dependency requirement 'foo != 1.2.3' could not be satisfied.\nPackage 'foo' has version '1.2.3', required version is '!= 1.2.3'\n"
args = ["--cflags", "--libs", "foo", "!=", "1.2.3"]
[lib_cflags_version_different_bad.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists_nonexistent]
exitcode = 1
args = ["--exists", "nonexistant"]
[exists_nonexistent.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[nonexistent]
exitcode = 1
args = ["nonexistant"]
[nonexistent.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists_version]
args = ["--exists", "foo > 1.2"]
[exists_version.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists_version_alt]
args = ["--exists", "foo", ">", "1.2"]
[exists_version_alt.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists_version_bad]
exitcode = 1
args = ["--exists", "foo > 1.2.3"]
[exists_version_bad.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[uninstalled_bad]
exitcode = 1
args = ["--uninstalled", "foo"]
[uninstalled_bad.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[uninstalled]
args = ["--uninstalled", "omg"]
[uninstalled.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists_version_bad2]
exitcode = 1
args = ["--exists", "foo >= "]
[exists_version_bad2.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists_version_bad3]
exitcode = 1
args = ["--exists", "tilde >= 1.0.0"]
[exists_version_bad3.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists]
args = ["--exists", "tilde >= 1.0.0"]
[exists.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists2]
args = ["--exists", "tilde >= 1.0.0~rc1"]
[exists2.env]
PKG_CONFIG_PATH="{test_root}/lib1"
[exists3]
args = ["--exists", "", "foo"]
[exists3.env]
PKG_CONFIG_PATH="{test_root}/lib1"

View File

@ -1,11 +0,0 @@
prefix=/usr
exec_prefix=/usr
libdir=${prefix}/lib64
includedir=${prefix}/include
Name: child-prefix-1
Description: child prefix 1 test data
Requires:
Version: 1.0
Libs: -L${libdir} -lchild-prefix-1
Cflags: -I${includedir}/child-prefix-1

View File

@ -0,0 +1,4 @@
Name: escaped-space
Version: 1
Description: test package for backslash escape of spaces
Cflags: -IC:\\A\ space

View File

@ -1,12 +0,0 @@
prefix=/test
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: foobar
Description: A testing pkg-config file
Version: 3.2.1
Libs: -L${libdir} -lfoobar
Cflags: -fPIC -I${includedir}/foobar
Cflags.private: -DFOOBAR_STATIC
License: ISC

View File

@ -1,4 +0,0 @@
Name: metapackage-3
Version: 0.1
Description: metapackage for testing purposes
Requires.private: bar

View File

@ -1,11 +0,0 @@
prefix=/test
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: unavailable_provider
Description: Provides an otherwise unavailable package
Version: 1.2.3
Provides: unavailable = 1.2.3
Libs: -lunavailable
Cflags:

View File

@ -138,6 +138,14 @@ escaped_backslash_body()
pkgconf --with-path=${selfdir}/lib1 --cflags escaped-backslash pkgconf --with-path=${selfdir}/lib1 --cflags escaped-backslash
} }
escaped_space_body()
{
atf_check \
-e ignore \
-o inline:"-IC:\\\\\\\\A space\n" \
pkgconf --with-path=${selfdir}/lib1 --cflags escaped-space
}
quoted_body() quoted_body()
{ {
export PKG_CONFIG_PATH="${selfdir}/lib1" export PKG_CONFIG_PATH="${selfdir}/lib1"

View File

@ -23,15 +23,6 @@ tests_init \
idirafter_munge_order \ idirafter_munge_order \
idirafter_munge_sysroot \ idirafter_munge_sysroot \
idirafter_ordering \ idirafter_ordering \
modversion_common_prefix \
modversion_fullpath \
modversion_provides \
modversion_uninstalled \
modversion_one_word_expression \
modversion_two_word_expression \
modversion_three_word_expression \
modversion_one_word_expression_no_space \
modversion_one_word_expression_no_space_zero \
pcpath \ pcpath \
virtual_variable \ virtual_variable \
fragment_collision \ fragment_collision \
@ -41,8 +32,7 @@ tests_init \
empty_tuple \ empty_tuple \
solver_requires_private_debounce \ solver_requires_private_debounce \
billion_laughs \ billion_laughs \
define_prefix_child_prefix_1 \ maximum_package_depth_off_by_one
define_prefix_child_prefix_1_env
# sysroot_munge \ # sysroot_munge \
@ -285,70 +275,8 @@ billion_laughs_body()
pkgconf --with-path="${selfdir}/lib1" --validate billion-laughs pkgconf --with-path="${selfdir}/lib1" --validate billion-laughs
} }
modversion_common_prefix_body() maximum_package_depth_off_by_one_body()
{
atf_check -o inline:"foo: 1.2.3\nfoobar: 3.2.1\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion --verbose foo foobar
}
modversion_fullpath_body()
{ {
atf_check -o inline:"1.2.3\n" \ atf_check -o inline:"1.2.3\n" \
pkgconf --modversion "${selfdir}/lib1/foo.pc" pkgconf --with-path="${selfdir}/lib1" --modversion foo bar baz
}
modversion_provides_body()
{
atf_check -o inline:"1.2.3\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion unavailable
}
modversion_uninstalled_body()
{
atf_check -o inline:"1.2.3\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion omg
}
modversion_one_word_expression_body()
{
atf_check -o inline:"1.2.3\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion "foo > 1.0"
}
modversion_two_word_expression_body()
{
atf_check -o inline:"1.2.3\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion foo "> 1.0"
}
modversion_three_word_expression_body()
{
atf_check -o inline:"1.2.3\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion foo ">" 1.0
}
modversion_one_word_expression_no_space_body()
{
atf_check -o inline:"1.2.3\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion "foo >1.0"
}
modversion_one_word_expression_no_space_zero_body()
{
atf_check -o inline:"1.2.3\n" \
pkgconf --with-path="${selfdir}/lib1" --modversion "foo >0.5"
}
define_prefix_child_prefix_1_body()
{
atf_check -o inline:"-I${selfdir}/lib1/include/child-prefix-1 -L${selfdir}/lib1/lib64 -lchild-prefix-1\n" \
pkgconf --with-path="${selfdir}/lib1/child-prefix/pkgconfig" --define-prefix --cflags --libs child-prefix-1
}
define_prefix_child_prefix_1_env_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1/child-prefix/pkgconfig"
export PKG_CONFIG_RELOCATE_PATHS=1
atf_check -o inline:"-I${selfdir}/lib1/include/child-prefix-1 -L${selfdir}/lib1/lib64 -lchild-prefix-1\n" \
pkgconf --cflags --libs child-prefix-1
} }

View File

@ -10,10 +10,6 @@ tests_init \
argv_parse2 \ argv_parse2 \
static_cflags \ static_cflags \
private_duplication \ private_duplication \
private_duplication_digraph \
foo_bar \
bar_foo \
foo_metapackage_3 \
libs_static2 \ libs_static2 \
missing \ missing \
requires_internal \ requires_internal \
@ -41,7 +37,7 @@ libs_static_body()
{ {
export PKG_CONFIG_PATH="${selfdir}/lib1" export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \ atf_check \
-o inline:"-L/test/lib -lbaz -L/test/lib -lzee -lfoo\n" \ -o inline:"-L/test/lib -lbaz -L/test/lib -lzee -L/test/lib -lfoo\n" \
pkgconf --static --libs baz pkgconf --static --libs baz
} }
@ -49,7 +45,7 @@ libs_static_pure_body()
{ {
export PKG_CONFIG_PATH="${selfdir}/lib1" export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \ atf_check \
-o inline:"-L/test/lib -lbaz -lfoo\n" \ -o inline:"-L/test/lib -lbaz -L/test/lib -lfoo\n" \
pkgconf --static --pure --libs baz pkgconf --static --pure --libs baz
} }
@ -73,46 +69,10 @@ private_duplication_body()
{ {
export PKG_CONFIG_PATH="${selfdir}/lib1" export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \ atf_check \
-o inline:"-lprivate -lbaz -lzee -lbar -lfoo\n" \ -o inline:"-lprivate -lbaz -lzee -lbar -lfoo -lfoo\n" \
pkgconf --static --libs-only-l private-libs-duplication pkgconf --static --libs-only-l private-libs-duplication
} }
private_duplication_digraph_body()
{
export PKG_CONFIG_PATH="${selfdir}/lib1"
atf_check \
-o 'match:"user:request" -> "private-libs-duplication"' \
-o 'match:"private-libs-duplication" -> "bar"' \
-o 'match:"private-libs-duplication" -> "baz"' \
-o 'match:"bar" -> "foo"' \
-o 'match:"baz" -> "foo"' \
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() libs_static2_body()
{ {
export PKG_CONFIG_PATH="${selfdir}/lib1" export PKG_CONFIG_PATH="${selfdir}/lib1"

125
tests/runner.py Normal file
View File

@ -0,0 +1,125 @@
#!/usr/bin/env python3
# Copyright (c) 2016 pkgconf authors (see AUTHORS).
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# This software is provided 'as is' and without any warranty, express or
# implied. In no event shall the authors be liable for any damages arising
# from the use of this software.
"""Simple runner for test cases."""
from __future__ import annotations
import argparse
import asyncio
import dataclasses
import os
import sys
import typing
try:
import tomllib
except ImportError:
import tomli as tomllib
if typing.TYPE_CHECKING:
class TestDefinition(typing.TypedDict, total=False):
exitcode: int
stdout: str
stderr: str
args: typing.List[str]
env: typing.Dict[str, str]
class Arguments(typing.Protocol):
suites: typing.List[str]
pkgconf: str
verbose: bool
TEST_ROOT = os.path.dirname(os.path.abspath(__file__))
@dataclasses.dataclass
class Result:
name: str
success: bool = False
reason: typing.Optional[str] = None
def interpolate(input: str) -> str:
return input.format(
test_root=TEST_ROOT,
)
async def run_test(pkgconf: str, name: str, test: TestDefinition, verbose: bool) -> Result:
env: typing.Dict[str, str] = {}
if (renv := test.get('env', None)) is not None:
env = {k: interpolate(v) for k, v in renv.items()}
proc = await asyncio.create_subprocess_exec(
pkgconf, *test.get('args', []),
stdout=asyncio.subprocess.PIPE if 'stdout' in test is not None else asyncio.subprocess.DEVNULL,
stderr=asyncio.subprocess.PIPE if 'stderr' in test is not None else asyncio.subprocess.DEVNULL,
env=env)
rout, rerr = await proc.communicate()
out = rout.decode() if rout is not None else ''
err = rerr.decode() if rerr is not None else ''
result = Result(name)
if (ret := test.get('exitcode', 0)) and proc.returncode != ret:
result.reason = f"Return code was {proc.returncode}, but expected {ret}"
elif (exp := test.get('stdout')) is not None and out != exp:
result.reason = f"Stdout was {out}, but expected {exp}"
elif (exp := test.get('stderr')) is not None and err != exp:
result.reason = f"Stdout was {err}, but expected {err}"
else:
result.success = True
if verbose:
if result.success:
print(f"{name}: passed")
else:
print(f"{name}: failed\n reason: {result.reason}")
return result
async def run(args: Arguments) -> None:
tests: typing.List[typing.Coroutine[typing.Any, typing.Any, Result]] = []
for suite in args.suites:
with open(suite, 'rb') as f:
suite: typing.Dict[str, TestDefinition] = tomllib.load(f)
tests.extend(
[run_test(args.pkgconf, n, s, args.verbose) for n, s in suite.items()])
results = await asyncio.gather(*tests)
return all(r.success for r in results)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('pkgconf', help="Path to built pkgconf executable")
parser.add_argument('suites', nargs="+", help="One or more toml test suite definition")
parser.add_argument('-v', '--verbose', action='store_true',
help="Print more information while running")
args: Arguments = parser.parse_args()
loop = asyncio.new_event_loop()
success = loop.run_until_complete(run(args))
sys.exit(int(not success))
if __name__ == "__main__":
main()