Add 'contrib/pkgconf/' from commit '6294b6ab217a2d5f1d2bc23a64505a228294c508'
git-subtree-dir: contrib/pkgconf git-subtree-mainline:45827f9ad2git-subtree-split:6294b6ab21
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
A. Wilcox <AWilcox@Wilcox-Tech.com>
|
||||
Alexander Tsoy <alexander@tsoy.me>
|
||||
Alexpux <alexey.pawlow@gmail.com>
|
||||
Alon Bar-Lev <alon.barlev@gmail.com>
|
||||
Alyx <alyx@malkier.net>
|
||||
Ariadne Conill <ariadne@dereferenced.org>
|
||||
Baptiste Daroussin <bapt@FreeBSD.org>
|
||||
Baptiste Daroussin <bapt@gandi.net>
|
||||
Bryan Drewery <bryan@shatow.net>
|
||||
Dag-Erling Smørgrav <des@des.no>
|
||||
Dan Kegel <dank@kegel.com>
|
||||
Dan Kegel <dank@oblong.com>
|
||||
Dan Nicholson <dbn.lists@gmail.com>
|
||||
David Michael <fedora.dm0@gmail.com>
|
||||
Emil Renner Berthing <esmil@mailme.dk>
|
||||
Fabian Groffen <grobian@gentoo.org>
|
||||
Graham Ollis <plicease@cpan.org>
|
||||
Gregor Richards <Richards@codu.org>
|
||||
Ignacio Casal Quinteiro <qignacio@amazon.com>
|
||||
Igor Gnatenko <ignatenko@redhat.com>
|
||||
Issam Maghni <concatime@users.noreply.github.com>
|
||||
JD Horelick <jdhore1@gmail.com>
|
||||
Jason Dusek <jason.dusek@gmail.com>
|
||||
Javier Viguera <javier.viguera@digi.com>
|
||||
Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
|
||||
John Hein <jhgit@users.github.com>
|
||||
Jussi Pakkanen <jpakkane@gmail.com>
|
||||
Leorize <alaviss@users.noreply.github.com>
|
||||
Luca Barbato <lu_zero@gentoo.org>
|
||||
Marcin Wojdyr <wojdyr@gmail.com>
|
||||
Maxin B. John <maxinbjohn@users.noreply.github.com>
|
||||
Michał Górny <mgorny@gentoo.org>
|
||||
Mike Frysinger <vapier@gentoo.org>
|
||||
Seungha Yang <seungha.yang@navercorp.com>
|
||||
TingPing <tingping@tingping.se>
|
||||
Tobias Kortkamp <t6@users.noreply.github.com>
|
||||
Tony Theodore <tonyt@logyst.com>
|
||||
Volker Braun <vbraun.name@gmail.com>
|
||||
Yu Kobayashi <yukoba@accelart.jp>
|
||||
orbea <orbea@fredslev.dk>
|
||||
✈ Graham ✈ <plicease@cpan.org>
|
||||
@@ -0,0 +1,27 @@
|
||||
# pkgconf Code of Conduct
|
||||
|
||||
We invite and encourage everybody to express their opinions on relevant
|
||||
topics. All participants should at all times feel at ease to do so without
|
||||
fearing any form of attack, reprisal or harassment. We ask everybody to be
|
||||
respectful and considerate towards each other, especially when attempting
|
||||
to provide constructive criticism.
|
||||
|
||||
To foster tolerance, respect and hospitality in our community, we agree not
|
||||
to engage in discriminatory, disparaging or offensive speech or actions,
|
||||
including as to (but not limited to) gender, sexuality, race, nationality,
|
||||
religion or profession. We are a community of many different nationalities
|
||||
and backgrounds, and we cherish our strength in diversity.
|
||||
|
||||
|
||||
## Reporting incidents
|
||||
|
||||
Please report any incidents which may be perceived as violations to
|
||||
`ariadne+conduct@dereferenced.org`. Incidents will be investigated and,
|
||||
if warranted, acted upon.
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
This CoC is derived from the [FSFE Code of Conduct][fsfe-coc].
|
||||
|
||||
[fsfe-coc]: https://fsfe.org/about/codeofconduct.en.html
|
||||
@@ -0,0 +1,10 @@
|
||||
Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||||
pkgconf authors (see AUTHORS file in source directory).
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,5 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite('pkgconf')
|
||||
|
||||
include('tests/Kyuafile')
|
||||
@@ -0,0 +1,217 @@
|
||||
libdir = @libdir@
|
||||
datarootdir = @datarootdir@
|
||||
datadir = @datadir@
|
||||
includedir = @includedir@
|
||||
system_includedir = @SYSTEM_INCLUDEDIR@
|
||||
system_libdir = @SYSTEM_LIBDIR@
|
||||
pkg_default_dir = @PKG_DEFAULT_PATH@
|
||||
personality_dir = @PERSONALITY_PATH@
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
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)\"
|
||||
|
||||
bin_PROGRAMS = pkgconf bomtool
|
||||
lib_LTLIBRARIES = libpkgconf.la
|
||||
|
||||
EXTRA_DIST = pkg.m4 \
|
||||
meson.build \
|
||||
meson_options.txt \
|
||||
pkgconf.wxs.in \
|
||||
txt2rtf.py \
|
||||
libpkgconf/meson.build \
|
||||
libpkgconf/config.h.meson \
|
||||
libpkgconf/win-dirent.h \
|
||||
tests/lib-relocatable/lib/pkgconfig/foo.pc \
|
||||
tests/lib1/argv-parse-2.pc \
|
||||
tests/lib1/billion-laughs.pc \
|
||||
tests/lib1/dos-lineendings.pc \
|
||||
tests/lib1/paren-quoting.pc \
|
||||
tests/lib1/argv-parse-3.pc \
|
||||
tests/lib1/foo.pc \
|
||||
tests/lib1/foobar.pc \
|
||||
tests/lib1/unavailable-provider.pc \
|
||||
tests/lib1/prefix-foo1.pc \
|
||||
tests/lib1/argv-parse.pc \
|
||||
tests/lib1/framework-1.pc \
|
||||
tests/lib1/prefix-foo2.pc \
|
||||
tests/lib1/bar.pc \
|
||||
tests/lib1/framework-2.pc \
|
||||
tests/lib1/private-libs-duplication.pc \
|
||||
tests/lib1/baz.pc \
|
||||
tests/lib1/incomplete.pc \
|
||||
tests/lib1/quotes.pc \
|
||||
tests/lib1/case-sensitivity.pc \
|
||||
tests/lib1/intermediary-1.pc \
|
||||
tests/lib1/static-archive-libs.pc \
|
||||
tests/lib1/cflags-libs-only.pc \
|
||||
tests/lib1/intermediary-2.pc \
|
||||
tests/lib1/static-libs.pc \
|
||||
tests/lib1/circular-1.pc \
|
||||
tests/lib1/missing-require.pc \
|
||||
tests/lib1/sysroot-dir.pc \
|
||||
tests/lib1/circular-2.pc \
|
||||
tests/lib1/multiline.pc \
|
||||
tests/lib1/multiline-bogus.pc \
|
||||
tests/lib1/tilde-quoting.pc \
|
||||
tests/lib1/circular-3.pc \
|
||||
tests/lib1/no-trailing-newline.pc \
|
||||
tests/lib1/tilde.pc \
|
||||
tests/lib1/comments-in-fields.pc \
|
||||
tests/lib1/nocflag.pc \
|
||||
tests/lib1/typelibdir.pc \
|
||||
tests/lib2/foo.pc \
|
||||
tests/lib1/comments.pc \
|
||||
tests/lib1/nolib.pc \
|
||||
tests/lib3/bar.pc \
|
||||
tests/lib1/conflicts.pc \
|
||||
tests/lib1/omg-uninstalled.pc \
|
||||
tests/lib1/omg-sysroot-uninstalled.pc \
|
||||
tests/lib1/isystem.pc \
|
||||
tests/lib1/idirafter.pc \
|
||||
tests/lib1/idirafter-ordering.pc \
|
||||
tests/lib1/depgraph-break.pc \
|
||||
tests/lib1/cflags-whitespace.pc \
|
||||
tests/lib1/cflags-whitespace-trailing.pc \
|
||||
tests/lib1/provides.pc \
|
||||
tests/lib1/provides-request-simple.pc \
|
||||
tests/lib1/flag-order-1.pc \
|
||||
tests/lib1/flag-order-3.pc \
|
||||
tests/lib1/variable-whitespace.pc \
|
||||
tests/lib1/fragment-collision.pc \
|
||||
tests/lib1/fragment-collision-intermediary.pc \
|
||||
tests/lib1/fragment-collision-1.pc \
|
||||
tests/lib1/fragment-collision-2.pc \
|
||||
tests/lib1/fragment-comment.pc \
|
||||
tests/lib1/fragment-escaping-1.pc \
|
||||
tests/lib1/fragment-escaping-2.pc \
|
||||
tests/lib1/fragment-escaping-3.pc \
|
||||
tests/lib1/fragment-quoting.pc \
|
||||
tests/lib1/fragment-quoting-2.pc \
|
||||
tests/lib1/fragment-quoting-3.pc \
|
||||
tests/lib1/fragment-quoting-5.pc \
|
||||
tests/lib1/fragment-quoting-7.pc \
|
||||
tests/lib1/fragment-groups.pc \
|
||||
tests/lib1/fragment-groups-2.pc \
|
||||
tests/lib1/fragment-group-a.pc \
|
||||
tests/lib1/fragment-group-b.pc \
|
||||
tests/lib1/fragment-group-c.pc \
|
||||
tests/lib1/malformed-1.pc \
|
||||
tests/lib1/malformed-quoting.pc \
|
||||
tests/lib1/malformed-version.pc \
|
||||
tests/lib1/metapackage.pc \
|
||||
tests/lib1/metapackage-1.pc \
|
||||
tests/lib1/metapackage-2.pc \
|
||||
tests/lib1/metapackage-3.pc \
|
||||
tests/lib1/explicit-sysroot.pc \
|
||||
tests/lib1/escaped-backslash.pc \
|
||||
tests/lib1/cflags-internal.pc \
|
||||
tests/lib1/requires-internal.pc \
|
||||
tests/lib1/requires-internal-2.pc \
|
||||
tests/lib1/requires-internal-missing.pc \
|
||||
tests/lib1/requires-internal-collision.pc \
|
||||
tests/lib1/tuple-quoting.pc \
|
||||
tests/lib1/empty-tuple.pc \
|
||||
tests/lib1/orphaned-requires-private.pc \
|
||||
tests/lib1/pcfiledir.pc \
|
||||
tests/lib1/sysroot-dir-2.pc \
|
||||
tests/lib1/sysroot-dir-3.pc \
|
||||
tests/lib1/sysroot-dir-4.pc \
|
||||
tests/lib1/sysroot-dir-5.pc \
|
||||
tests/lib1/child-prefix/pkgconfig/child-prefix-1.pc \
|
||||
tests/lib1/cflags-libs-private-a.pc \
|
||||
tests/lib1/cflags-libs-private-b.pc \
|
||||
tests/lib1/cflags-libs-private-c.pc \
|
||||
tests/lib1/truncated.pc \
|
||||
tests/lib1/c-comment.pc \
|
||||
tests/meson.build \
|
||||
$(test_scripts) \
|
||||
doc/conf.py \
|
||||
doc/extract.py \
|
||||
doc/index.rst \
|
||||
doc/libpkgconf.rst \
|
||||
doc/libpkgconf-argvsplit.rst \
|
||||
doc/libpkgconf-audit.rst \
|
||||
doc/libpkgconf-cache.rst \
|
||||
doc/libpkgconf-client.rst \
|
||||
doc/libpkgconf-dependency.rst \
|
||||
doc/libpkgconf-fragment.rst \
|
||||
doc/libpkgconf-path.rst \
|
||||
doc/libpkgconf-pkg.rst \
|
||||
doc/libpkgconf-queue.rst \
|
||||
doc/libpkgconf-tuple.rst
|
||||
|
||||
test_scripts= tests/basic.sh \
|
||||
tests/builtins.sh \
|
||||
tests/conflicts.sh \
|
||||
tests/framework.sh \
|
||||
tests/parser.sh \
|
||||
tests/provides.sh \
|
||||
tests/regress.sh \
|
||||
tests/requires.sh \
|
||||
tests/symlink.sh \
|
||||
tests/sysroot.sh \
|
||||
tests/version.sh
|
||||
|
||||
test_sh = $(test_scripts)
|
||||
check_SCRIPTS = ${test_sh:.sh=}
|
||||
|
||||
SUFFIXES= .sh
|
||||
|
||||
nobase_pkginclude_HEADERS = libpkgconf/bsdstubs.h libpkgconf/iter.h libpkgconf/libpkgconf.h libpkgconf/stdinc.h libpkgconf/libpkgconf-api.h
|
||||
libpkgconf_la_SOURCES = \
|
||||
libpkgconf/audit.c \
|
||||
libpkgconf/buffer.c \
|
||||
libpkgconf/cache.c \
|
||||
libpkgconf/client.c \
|
||||
libpkgconf/pkg.c \
|
||||
libpkgconf/bsdstubs.c \
|
||||
libpkgconf/fragment.c \
|
||||
libpkgconf/argvsplit.c \
|
||||
libpkgconf/fileio.c \
|
||||
libpkgconf/tuple.c \
|
||||
libpkgconf/dependency.c \
|
||||
libpkgconf/queue.c \
|
||||
libpkgconf/path.c \
|
||||
libpkgconf/personality.c \
|
||||
libpkgconf/parser.c
|
||||
libpkgconf_la_LDFLAGS = -no-undefined -version-info 7:0:0 -export-symbols-regex '^pkgconf_'
|
||||
|
||||
dist_man_MANS = \
|
||||
man/bomtool.1 \
|
||||
man/pkgconf.1 \
|
||||
man/pkg.m4.7 \
|
||||
man/pc.5 \
|
||||
man/pkgconf-personality.5
|
||||
|
||||
pkgconf_LDADD = libpkgconf.la
|
||||
pkgconf_SOURCES = \
|
||||
cli/main.c \
|
||||
cli/getopt_long.c \
|
||||
cli/renderer-msvc.c
|
||||
pkgconf_CPPFLAGS = -I$(top_srcdir)/libpkgconf -I$(top_srcdir)/cli
|
||||
noinst_HEADERS = \
|
||||
cli/getopt_long.h \
|
||||
cli/renderer-msvc.h
|
||||
|
||||
bomtool_LDADD = libpkgconf.la
|
||||
bomtool_SOURCES = \
|
||||
cli/bomtool/main.c \
|
||||
cli/getopt_long.c
|
||||
bomtool_CPPFLAGS = -I$(top_srcdir)/libpkgconf -I$(top_srcdir)/cli -I$(top_srcdir)/cli/bomtool
|
||||
|
||||
dist_doc_DATA = README.md AUTHORS
|
||||
|
||||
m4datadir = $(datadir)/aclocal
|
||||
m4data_DATA = pkg.m4
|
||||
|
||||
CLEANFILES = $(EXTRA_PROGRAMS) \
|
||||
$(check_SCRIPTS)
|
||||
|
||||
check: pkgconf $(check_SCRIPTS)
|
||||
kyua --config=none test --kyuafile='$(top_builddir)/Kyuafile' \
|
||||
--build-root='$(top_builddir)'
|
||||
|
||||
.sh:
|
||||
install -m 755 $< $@
|
||||
@@ -0,0 +1,77 @@
|
||||
# Copyright (c) 2019 William Pitcock <nenolod@dereferenced.org>
|
||||
#
|
||||
# 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.
|
||||
|
||||
# pkgconf-lite is a staticly-linked version of pkgconf that does not include
|
||||
# all features, notably it does not include cross-compile support and MSVC
|
||||
# support. It does not include the libpkgconf library.
|
||||
|
||||
SRCS = \
|
||||
libpkgconf/argvsplit.c \
|
||||
libpkgconf/audit.c \
|
||||
libpkgconf/bsdstubs.c \
|
||||
libpkgconf/cache.c \
|
||||
libpkgconf/client.c \
|
||||
libpkgconf/dependency.c \
|
||||
libpkgconf/fileio.c \
|
||||
libpkgconf/fragment.c \
|
||||
libpkgconf/parser.c \
|
||||
libpkgconf/path.c \
|
||||
libpkgconf/personality.c \
|
||||
libpkgconf/pkg.c \
|
||||
libpkgconf/queue.c \
|
||||
libpkgconf/tuple.c \
|
||||
cli/getopt_long.c \
|
||||
cli/main.c
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
CFLAGS = ${STATIC} -DPKGCONF_LITE -I. -Ilibpkgconf -Icli -DSYSTEM_LIBDIR=\"${SYSTEM_LIBDIR}\" -DSYSTEM_INCLUDEDIR=\"${SYSTEM_INCLUDEDIR}\" -DPKG_DEFAULT_PATH=\"${PKG_DEFAULT_PATH}\"
|
||||
STATIC =
|
||||
STRIP = strip
|
||||
|
||||
all: pkgconf-lite
|
||||
|
||||
libpkgconf/config.h:
|
||||
@echo '#define PACKAGE_NAME "pkgconf-lite"' >> $@
|
||||
@echo '#define PACKAGE_BUGREPORT "https://git.dereferenced.org/pkgconf/pkgconf/issues"' >> $@
|
||||
@echo '#define PACKAGE_VERSION "2.5.1"' >> $@
|
||||
@echo '#define PACKAGE PACKAGE_NAME " " PACKAGE_VERSION' >> $@
|
||||
@echo '#define HAVE_STRLCPY' >> $@
|
||||
@echo '#define HAVE_STRLCAT' >> $@
|
||||
@echo '#define HAVE_STRNDUP' >> $@
|
||||
|
||||
pkgconf-lite: preflight libpkgconf/config.h ${OBJS}
|
||||
${CC} ${STATIC} -o $@ ${OBJS}
|
||||
${STRIP} $@
|
||||
|
||||
clean:
|
||||
rm -f libpkgconf/config.h
|
||||
rm -f ${OBJS}
|
||||
rm -f pkgconf-lite
|
||||
|
||||
preflight: preflight-system-libdir preflight-system-includedir preflight-pkg-default-path
|
||||
|
||||
preflight-system-libdir:
|
||||
@if test -z "${SYSTEM_LIBDIR}"; then \
|
||||
echo "SYSTEM_LIBDIR not set."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
preflight-system-includedir:
|
||||
@if test -z "${SYSTEM_INCLUDEDIR}"; then \
|
||||
echo "SYSTEM_INCLUDEDIR not set."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
preflight-pkg-default-path:
|
||||
@if test -z "${PKG_DEFAULT_PATH}"; then \
|
||||
echo "PKG_DEFAULT_PATH not set."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: preflight preflight-system-libdir preflight-system-includedir preflight-pkg-default-path clean
|
||||
@@ -0,0 +1,943 @@
|
||||
Changes from previous version of pkgconf
|
||||
========================================
|
||||
|
||||
Changes from 2.5.0 to 2.5.1:
|
||||
----------------------------
|
||||
|
||||
* Fix processing of empty dependency lists.
|
||||
|
||||
Changes from 2.4.3 to 2.5.0:
|
||||
----------------------------
|
||||
|
||||
* Added a manual page for bomtool.
|
||||
|
||||
* Add support for preloaded packages.
|
||||
These are modules which are preloaded into the package database
|
||||
and preferred over searching the module search path when present.
|
||||
|
||||
* Refactor Windows registry PKG_CONFIG_PATH support so that it
|
||||
augments the main directory search list instead of being treated
|
||||
as a special case.
|
||||
|
||||
* Processing of `--with-path` arguments by the pkgconf CLI is
|
||||
now deferred until libpkgconf is fully initialized, effectively
|
||||
aligning behavior with PKG_CONFIG_PATH processing.
|
||||
|
||||
* Fix several minor memory safety bugs which were identified by
|
||||
the GCC 15 static analyzer.
|
||||
|
||||
* Added support for pledge(2) and unveil(2) on systems where
|
||||
this functionality is available.
|
||||
|
||||
* Significant improvements to pkgconf's manual pages.
|
||||
Patches by Ingo Schwarze and Jonathan Gray (OpenBSD).
|
||||
|
||||
* Remove questionable default-static assumption on Windows that
|
||||
was inherited from the original pkg-config. Most distributions
|
||||
of pkgconf on Windows were already patching this out.
|
||||
Patch by Kai Pastor.
|
||||
|
||||
* Add -D_POSIX_C_SOURCE=200809L to the build definitions, which
|
||||
is needed for readlinkat on glibc.
|
||||
Patch by Filipe Laíns.
|
||||
|
||||
Changes from 2.4.2 to 2.4.3:
|
||||
----------------------------
|
||||
|
||||
* Fix additional logic errors relating to the new fragment trees
|
||||
functionality.
|
||||
|
||||
Changes from 2.4.1 to 2.4.2:
|
||||
----------------------------
|
||||
|
||||
* Fix several logic errors in the pkg-config file parser that were
|
||||
surfaced by recent refactoring work.
|
||||
|
||||
* Fix BSD make compatibility so that it generates the test data
|
||||
before running kyua on BSD make implementations.
|
||||
|
||||
Changes from 2.4.0 to 2.4.1:
|
||||
----------------------------
|
||||
|
||||
* Ensure the full DAG is solved for all query types.
|
||||
|
||||
Changes from 2.3.0 to 2.4.0:
|
||||
----------------------------
|
||||
|
||||
* Allow multiple package names in solution-based queries such as
|
||||
`--print-requires`, `--print-requires-private` and `--print-provides`.
|
||||
|
||||
* Use `_DEFAULT_SOURCE` where appropriate on Meson.
|
||||
|
||||
* Add an abstract buffer type and use it when loading files from disk
|
||||
instead of a 64KB buffer. This ensures large pkg-config files are
|
||||
not truncated.
|
||||
|
||||
* Disable graph recursion in `--variable` queries as it was generating
|
||||
duplicate output.
|
||||
|
||||
* Add infrastructure for tracking fragment group relations and convert
|
||||
storage of fragments to use a tree-like structure instead of string
|
||||
concatenation.
|
||||
|
||||
* Add support for tracking linker groups, e.g.
|
||||
|
||||
-Wl,--start-group -la -lb -lc -Wl,--end-group
|
||||
|
||||
as fragment groups.
|
||||
|
||||
* Properly contextualize the sysroot directory when processing package
|
||||
information, ensuring packages where ${pc_sysrootdir} does not match
|
||||
the default are properly processed.
|
||||
|
||||
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:
|
||||
----------------------------
|
||||
|
||||
* Fix incorrect assumptions involving the use of ctype(3) functions.
|
||||
Patch by Taylor R Campbell.
|
||||
|
||||
* Fix detection of provided functions on autoconf.
|
||||
Patches by Harmen Stoppels.
|
||||
|
||||
* Fix deletion of tests/meson.build by the autoconf build system.
|
||||
Patch by h30032433.
|
||||
|
||||
* Fix quoting rules in argvsplit.c.
|
||||
Patch by huyubiao.
|
||||
|
||||
* Update libpkgconf documentation and documentation building scripts.
|
||||
Patches by Andrew Shadura.
|
||||
|
||||
* Enforce maximum package count correctly for --modversion.
|
||||
|
||||
Changes from 1.9.3 to 1.9.4:
|
||||
----------------------------
|
||||
|
||||
* Fix a buffer overflow vulnerability involving very large variable expansions.
|
||||
CVE-2023-24056
|
||||
|
||||
* Fix a bunch of minor regressions with the solver.
|
||||
|
||||
* Create separate solutions for `--cflags` and `--libs` when `--static` is not
|
||||
used.
|
||||
|
||||
* Remove final trailing whitespace in pkgconf_fragment_render_buf().
|
||||
|
||||
* Revert broken pkg.m4 change involving querying module versions in
|
||||
PKG_CHECK_MODULES.
|
||||
|
||||
* Fix handling of tildes in version strings.
|
||||
|
||||
* Various C99 formatting string fixes involving SIZE_FMT_SPECIFIER.
|
||||
|
||||
Changes from 1.9.2 to 1.9.3:
|
||||
----------------------------
|
||||
|
||||
* Fix a bunch of minor code issues pointed out using Clang static analyzer.
|
||||
|
||||
* New API: pkgconf_solution_free(), which frees a compiled solution graph.
|
||||
|
||||
* Fix behavior when overriding global variables with `--define-variable`.
|
||||
|
||||
Changes from 1.9.1 to 1.9.2:
|
||||
----------------------------
|
||||
|
||||
* Do not try to break dependency cycles across dependency lists. This causes
|
||||
the solved graph to sometimes miss required dependency nodes because the
|
||||
solver detected an incorrect dependency cycle.
|
||||
|
||||
* New API: pkgconf_queue_solve(), which replaces pkgconf_queue_apply().
|
||||
pkgconf_queue_apply is now deprecated and should not be used in new code.
|
||||
|
||||
Changes from 1.9.0 to 1.9.1:
|
||||
----------------------------
|
||||
|
||||
* Skip graph flattening and traversal for query types which only make sense
|
||||
for a single pkg-config module.
|
||||
|
||||
The old solver walked these graphs with --maximum-traverse-depth=1 in
|
||||
these cases, but this is no longer helpful because the graph is flattened
|
||||
by the new solver.
|
||||
|
||||
Changes from 1.8.0 to 1.9.0:
|
||||
----------------------------
|
||||
|
||||
* pkgconf 1.9.0 is the first testing release in the pkgconf 2.0 development
|
||||
series. While it is believed to be suitable for production, there may be
|
||||
bugs due to the overall redesign of the solver and other initiatives.
|
||||
Additionally, a future release of pkgconf plans will have additional ABI
|
||||
breaks for the libpkgconf library before the pkgconf 2.0 release is cut.
|
||||
|
||||
* There is now a new solver that is designed to provide higher performance
|
||||
with complicated graphs, which works by flattening the dependency graph
|
||||
into a smaller set of dependencies. This graph can then be evaluated
|
||||
instead of the original dependency graph without having to visit every
|
||||
edge in the graph.
|
||||
|
||||
NOTE: This solver, while providing significant performance improvements,
|
||||
does so, at the cost of changed behavior for some edge cases (such as
|
||||
circular dependencies).
|
||||
|
||||
* Bug fixes:
|
||||
- Resolved several memory leaks with edge cases when using libpkgconf
|
||||
directly.
|
||||
- pkgconf CLI now consistently frees libpkgconf resources under all
|
||||
circumstances.
|
||||
- SYSROOT rules are no longer applied to `-uninstalled` packages by
|
||||
default. Use `PKG_CONFIG_PKGCONF1_SYSROOT_RULES` for legacy behavior.
|
||||
|
||||
* A new `--license` selector has been added to the pkgconf CLI. This uses
|
||||
SPDX expressions which can be set as the `License` field in `.pc` files.
|
||||
See the `pc(5)` manpage for more information.
|
||||
|
||||
* The canonical location for pkgconf maintenance going forward is
|
||||
<https://gitea.treehouse.systems/ariadne/pkgconf>. This is presently
|
||||
mirrored to GitHub for user convenience, but that mirroring will
|
||||
be terminated at some point (due to GitHub Copilot).
|
||||
|
||||
Changes from 1.7.4 to 1.8.0:
|
||||
----------------------------
|
||||
|
||||
* This is the last planned maintenance branch. I see pkgconf as basically
|
||||
a finished tool at this point, and very few people were ultimately interested
|
||||
in libpkgconf. So, from here on out, it will just be bug fixes only and
|
||||
very minor enhancements.
|
||||
|
||||
* Bug fixes:
|
||||
- Improved path handling on Windows to conform to what the MSYS2
|
||||
and Cygwin teams were already modifying pkgconf to do.
|
||||
Patches by Christoph Reiter.
|
||||
- Fix a minor memory leak relating to cross-personalities.
|
||||
Patch by Stone Tickle.
|
||||
- Fix static builds for Windows on Meson.
|
||||
Patch by Alexander Neumann.
|
||||
- Fix some edge cases with --redefine-prefix.
|
||||
Patch by midipix.
|
||||
- Do not prepend sysroot_dir if the .pc file does not exist in the
|
||||
sysroot.
|
||||
Patch by Sandro Mani.
|
||||
- Do not perform path filtering on default system include and library
|
||||
path lists. This fixes consistency with other mechanisms that modify
|
||||
these path lists.
|
||||
|
||||
* Enhancements:
|
||||
- Document the --validate option in the manpage.
|
||||
Patch by orbea.
|
||||
|
||||
Changes from 1.7.3 to 1.7.4:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fix null-dereference crash when pulling a malformed 'uninstalled'
|
||||
.pc file into a dependency tree. Patch by Tobias Stöckmann.
|
||||
- Fix truncation of comment characters when quoted.
|
||||
- Fix handling of .pc module names in --list-all on Windows.
|
||||
Patch by Ryan Scott.
|
||||
- Handle platforms where realpath(3) requires a pre-allocated buffer.
|
||||
Patch by Fabian Groffen.
|
||||
- Fix version whitespace warning.
|
||||
Patch by Christoph Reiter.
|
||||
|
||||
* Enhancements:
|
||||
- Rewrite DOS paths on native Windows builds that don't use
|
||||
Cygwin/MSYS.
|
||||
- Add WantDefaultPure cross-compiler personality option.
|
||||
- Prefer --static --pure linking on Windows.
|
||||
- Add PKG_CONFIG_DONT_DEFINE_PREFIX environment variable.
|
||||
Patch by Jeff Moguillansky.
|
||||
- Many improvements when building pkgconf with Meson.
|
||||
Patches by Christoph Reiter.
|
||||
|
||||
Changes from 1.7.2 to 1.7.3:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fix a possible out of boundary write when evaluating dependencies.
|
||||
Patch by Tobias Stöckmann.
|
||||
- Fix escaping logic on Windows. Patch by Vincent Torri.
|
||||
- Fix out of boundary reads and writes with a malformed fragment.
|
||||
Patches by Tobias Stöckmann.
|
||||
- Fix a possible out of boundary write when evaluating tuples.
|
||||
Patch by Tobias Stöckmann.
|
||||
|
||||
Changes from 1.7.1 to 1.7.2:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fix a windows-specific crash relating to path fixups.
|
||||
|
||||
Changes from 1.7.0 to 1.7.1:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fix a possible out of boundary access in the parser for the
|
||||
cross-compile database. Patch by Tobias Stöckmann.
|
||||
- Missing files for building with Meson are now included in the
|
||||
tarball. Patch by Neal Gompa.
|
||||
- Fix calculation of package atoms on Windows with paths that
|
||||
use both directory separator characters.
|
||||
|
||||
Changes from 1.6.3 to 1.7.0:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fix a possible buffer overflow involving newline escaping.
|
||||
Patch by Tobias Stöckmann.
|
||||
- Fix an out of boundary access in the parser.
|
||||
Patch by Tobias Stöckmann.
|
||||
- Fix leakage of strcmp() result value in pkgconf_compare_version()
|
||||
responses.
|
||||
- Return the default personality if loading a cross-compile
|
||||
personality file failed.
|
||||
- Do not complain about newlines when validating package versions.
|
||||
- Properly detect strndup() on Windows when building with Meson.
|
||||
|
||||
* Enhancements:
|
||||
- A new --shared option and WantDefaultStatic cross-compile
|
||||
configuration option have been added. This allows for toolchains
|
||||
to specify that static linking should be used by default.
|
||||
- Support for the PKG_CONFIG_MSVC_SYNTAX environment variable has
|
||||
been added. Patch by Dan Kegel.
|
||||
- Support for the PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS
|
||||
client flag which disables emulation of freedesktop.org pkg-config
|
||||
fragment merging semantics has been added.
|
||||
Patch by Karen Arutyunov.
|
||||
|
||||
Changes from 1.6.2 to 1.6.3:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Properly tokenize versions. Versions cannot logically contain
|
||||
whitespace, as dependency-lists would not properly tokenize if
|
||||
they could. A diagnostic is generated for malformed version
|
||||
strings containing whitespace when --validate is used.
|
||||
|
||||
* Enhancements:
|
||||
- CMake support has been dropped. Use Meson to build on Windows.
|
||||
|
||||
Changes from 1.6.1 to 1.6.2:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fixed a memory leak when deduplicating paths.
|
||||
- Fixed strndup-related build regression on Windows.
|
||||
|
||||
* Enhancements:
|
||||
- Added pkgconf-lite variant. pkgconf-lite is a stripped down
|
||||
variant of pkgconf that only includes pkg-config features.
|
||||
- Added --modversion description to pkgconf(1) man page.
|
||||
|
||||
Changes from 1.6.0 to 1.6.1:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fixed an issue where a personality may not be properly selected
|
||||
due to argv[0] containing a full path.
|
||||
- Fixed a regression where having an empty PKG_CONFIG_LIBDIR
|
||||
environment variable would not eliminate the default search
|
||||
paths.
|
||||
- Use POSIX realpath(3) instead of readlink() for deduplicating the
|
||||
search path. Use _fullpath() on Windows for the same purpose.
|
||||
- The dequoting logic for tuples has been improved to ensure that
|
||||
quotes *inside* a value remain quoted when necessary.
|
||||
|
||||
Changes from 1.5.4 to 1.6.0:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Fixed issue where packages which referenced missing packages in
|
||||
Requires.private may have crashed due to memory corruption issues
|
||||
in some circumstances.
|
||||
- Fixed warnings reported by GCC 8 diagnostics.
|
||||
|
||||
* Enhancements:
|
||||
- Add LIBPKGCONF_VERSION and LIBPKGCONF_VERSION_STR macros for
|
||||
determining libpkgconf version.
|
||||
- Add pkgconf_fragment_copy_list() to copy a fragment list to
|
||||
another fragment list.
|
||||
|
||||
Changes from 1.5.3 to 1.5.4:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- fix build on Windows with Meson
|
||||
- fix edge cases for path canonicalization (especially on Windows)
|
||||
|
||||
Changes from 1.5.2 to 1.5.3:
|
||||
----------------------------
|
||||
|
||||
* Security fixes:
|
||||
- Fix edge cases involving dequoting zero-length tuples that can lead to a
|
||||
buffer overflow under the right circumstances. Thanks to A. Wilcox for
|
||||
reporting and supplying a patch. (MR 3)
|
||||
|
||||
Changes from 1.5.1 to 1.5.2:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- Ensure environment variables override values learned from personality files
|
||||
or built-in defaults.
|
||||
|
||||
* Documentation enhancements:
|
||||
- Add pkgconf-personality(5) manpage documenting the personality file format.
|
||||
|
||||
Changes from 1.5.0 to 1.5.1:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- fixed a crash with some invalid multi-line .pc files
|
||||
|
||||
Changes from 1.4.2 to 1.5.0:
|
||||
---------------------------
|
||||
|
||||
* Administrative:
|
||||
- The git repository has moved to <https://git.dereferenced.org/pkgconf/pkgconf>,
|
||||
due to the acquisition of GitHub by Microsoft.
|
||||
|
||||
* Overall enhancements:
|
||||
- pkgconf now supports the proposed Requires.internal pkg-config extension,
|
||||
by merging it with the Requires.private list (there is no functional difference
|
||||
between the two in our resolver implementation)
|
||||
- Support for cross-compilation personalities have been added. To make use of this
|
||||
functionality, create a file in the new personality.d directory that sits inside
|
||||
the pkgconfig directory. The personality file format is described in
|
||||
pc-personality(5). (github #166)
|
||||
- Support for Haiku has been added, including interpretation of BELIBRARIES and
|
||||
other toolchain specifics. (github #180)
|
||||
- Testsuite support can be disabled when building with Meson. (github #175)
|
||||
|
||||
* Bug fixes:
|
||||
- tuples are now appropriately dequoted when added by the parser (github #186).
|
||||
|
||||
* Various Windows enhancements:
|
||||
- CMake supports building with GCC on Windows. (github #179)
|
||||
- Prefix rewriting has been improved. (github #177)
|
||||
- PKGCONF_API support has been implemented when building with Meson,
|
||||
allowing Meson to be used to build pkgconf on Windows. (github #174)
|
||||
|
||||
* Documentation fixes:
|
||||
- The manpages have been linted and fixed. (github #181, #182, #183)
|
||||
- The description of pkgconf --exists has been corrected. (github #173)
|
||||
|
||||
Changes from 1.4.1 to 1.4.2:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- ensure pkgconf_dependency_t nodes have a solution marked when satisfied
|
||||
by an indirect provider (github #172)
|
||||
|
||||
Changes from 1.4.0 to 1.4.1:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- revert some quoting changes because they don't work well with certain
|
||||
GCC edge cases (github #168)
|
||||
|
||||
* Enhancements:
|
||||
- add limited support for --cflags with --msvc-syntax
|
||||
|
||||
Changes from 1.3.7 to 1.4.0:
|
||||
----------------------------
|
||||
|
||||
* Notable libpkgconf API changes:
|
||||
- pkgconf_pkg_t.requires has been renamed to pkgconf_pkg_t.required for
|
||||
C++20 compatibility.
|
||||
|
||||
* Enhancements:
|
||||
- pkgconf and libpkgconf has been ported to Windows as native binaries.
|
||||
- improved compatibility with freedesktop.org pkg-config's ${pc_sysrootdir}
|
||||
usage pattern.
|
||||
- do not mention PKG_CONFIG_SKIP_CONFLICTS environmental variable when
|
||||
simplified errors are requested, as with PKG_CONFIG_PATH.
|
||||
- the dependency solver now stores solutions to dependency graph elements
|
||||
it visits, allowing for the dependency graph to be incrementally solved.
|
||||
this improves dependency solving time by an order of magnitude in most
|
||||
cases.
|
||||
- new --env option allows for exporting cflags/libs fragments as export
|
||||
variables
|
||||
- new support for building pkgconf with CMake and Meson
|
||||
- improved compiler warning flag detection on autoconf and CMake
|
||||
- removed PKGCONF_BUFSIZE allocations from the stack where possible
|
||||
- allow for customizing the way fragment lists are rendered using a callback API
|
||||
- new support for --msvc-syntax output using the new fragment rendering callbacks
|
||||
- fragments are now quoted according to POSIX literal rules
|
||||
- new variables on the pkg-config builtin:
|
||||
- ${pc_system_includedirs}: the system includedir search path known by pkgconf
|
||||
- ${pc_system_libdirs}: the system libdir search path known by pkgconf
|
||||
- new manpages:
|
||||
- pc(5) describing pkgconf's interpretation of pkg-config .pc files
|
||||
- pkg.m4(7) describing the autotools macros bundled with pkgconf
|
||||
|
||||
* Bug fixes:
|
||||
- fix pkgconf_pkg_t.id generation on native Windows where either \ or / are usable
|
||||
as path separator.
|
||||
- add missing --modversion to --help output
|
||||
- do not evaluate module paths for modules that are not actually on disk
|
||||
- ensure we work on a zeroed buffer prior to calling realpath(2) with it
|
||||
- fix path deduplication edge case when cache-inodes feature is unavailable
|
||||
- fix path rewriting regression with PKG_CONFIG_SYSROOT_DIR when
|
||||
PKG_CONFIG_SYSROOT_DIR is set to /
|
||||
- fix crash in edge case where a .pc file has misquoting in a fragment list.
|
||||
- fix logic edge case when comparing relocated paths
|
||||
|
||||
Changes from 1.3.6 to 1.3.7:
|
||||
----------------------------
|
||||
|
||||
* Enhancements:
|
||||
- improved diagnostics for malformed packages.
|
||||
|
||||
* Bug fixes:
|
||||
- reject packages which contain incomplete metadata in post-parse phase.
|
||||
|
||||
Changes from 1.3.5 to 1.3.6:
|
||||
----------------------------
|
||||
|
||||
* Enhancements:
|
||||
- add many cflags to the protected set: -Wa, -Wl, -Wp, -ansi, -std=, -stdlib=,
|
||||
-pedantic, -pthread, -trigraphs, -nostdinc, -nostdlibinc, -nobuiltininc.
|
||||
|
||||
* Bug fixes:
|
||||
- handle -include cflag fragments properly.
|
||||
|
||||
Changes from 1.3.4 to 1.3.5:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- fix --variable output for compatibility some broken configure scripts when they
|
||||
request the same variable from multiple packages
|
||||
|
||||
Changes from 1.3.3 to 1.3.4:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- fix a quoting issue exposed by the Go testsuite
|
||||
|
||||
Changes from 1.3.2 to 1.3.3:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- back out disabling the dependency resolver for single-package queries, it caused
|
||||
too many regressions.
|
||||
|
||||
* Enhancements:
|
||||
- allow explicitly disabling the dependency resolver via new environment variable,
|
||||
PKG_CONFIG_MINIMUM_TRAVERSE_DEPTH=1. while pkgconf could already do this using
|
||||
--minimum-traverse-depth=1, other pkg-config implementations do not have this
|
||||
option, so adding an environment variable allows to make better use of this
|
||||
feature (other implementations won't error due to unknown option this way)
|
||||
|
||||
Changes from 1.3.1 to 1.3.2:
|
||||
----------------------------
|
||||
|
||||
* Bug fixes:
|
||||
- rewrite handling of --modversion, --print-variables and --variable to not require
|
||||
the dependency resolver
|
||||
- ensure we disable the dependency resolver in all cases where it is a single-package
|
||||
query (1.3.1 did not go far enough)
|
||||
|
||||
Changes from 1.3.0 to 1.3.1:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- implement --short-errors
|
||||
|
||||
* Bug fixes:
|
||||
- only consider a single package at a time with --print-requires, --print-requires-private,
|
||||
--print-provides, --modversion, --print-variable and --print-variables
|
||||
|
||||
* Enhancements:
|
||||
- synchronized latest freedesktop.org changes to pkg.m4
|
||||
- improve error reporting with legacy --atleast-version and similar flags.
|
||||
|
||||
Changes from 1.2.0 to 1.3.0:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- pkgconf --debug now provides a facility for tracing most relevant libpkgconf operations
|
||||
- libpkgconf: add warn and trace handlers for warnings
|
||||
- replace realpath() with faster, lighter weight path normalization function (github #112)
|
||||
- pkgconf CLI now emulates pkg-config quoting rules precisely, while allowing direct access
|
||||
to the actual fragments via libpkgconf
|
||||
|
||||
* Bug fixes:
|
||||
- pkg: properly separate static and virtual packages so they are not inappropriately
|
||||
optimized out of the dependency graph (github #108)
|
||||
- argvsplit: do not consider ' and " to have similar rules to escape sequences (github #111)
|
||||
- pkg: strip trailing whitespace when parsing .pc files
|
||||
|
||||
* Enhancements:
|
||||
- argvsplit basically rewritten from scratch
|
||||
- many code fixes spotted by coverity
|
||||
- add PKG_CONFIG_DONT_RELOCATE_PATHS and --dont-relocate-paths environment variables to
|
||||
disable path relocation feature if needed
|
||||
- remove extra whitespace that was present for compatibility with older pkg-config releases
|
||||
(github #113)
|
||||
|
||||
Changes from 1.1.0 to 1.2.0:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- new --path option lists the .pc files which provided the requested dependencies
|
||||
- new path relocation API: pkgconf_path_relocate(), which wraps functions such as
|
||||
realpath() and cygwin_conv_path().
|
||||
- new --with-path option adds a path to the search list
|
||||
- new --define-prefix and --dont-define-prefix features enable automatic prefix
|
||||
detection for relocatable SDKs. this is mostly useful on windows.
|
||||
|
||||
* Bug fixes:
|
||||
- fragments: fix even more edge cases involving token concatenation
|
||||
- path lists: don't attempt to collect path inodes if the filter is disabled
|
||||
- path lists: explicitly avoid uninitialised data for the path inode cache
|
||||
- client: properly handle --keep-system-cflags and --keep-system-libs
|
||||
|
||||
* Enhancements:
|
||||
- windows: build libpkgconf as a DLL
|
||||
- fragments: only munge fragments if sysroot_dir is actually set
|
||||
- overall API: resolver flags have been moved to being a client-object setting
|
||||
instead of used for every function invocation
|
||||
|
||||
Changes from 1.0.1 to 1.1.0:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- new Provides system allows alternate .pc files to provide a dependency
|
||||
- stable library API (with documentation): http://pkgconf.readthedocs.io/
|
||||
|
||||
* Enhancements:
|
||||
- make it possible to programmatically declare dependencies instead of just using the parser
|
||||
- testsuite migrated to run under kyua
|
||||
- provide a libpkgconf.pc file for consumers to use
|
||||
- pkgconf client: new --pure flag to enable dependency graph optimization in --static mode
|
||||
- significant .pc parser speedups using bsearch(3).
|
||||
- handle -idirafter in the same way as -isystem CFLAGS
|
||||
- learn toolchain "system" paths from GCC environment variables, if present
|
||||
- filter duplicate PKG_CONFIG_PATH (and other) entries by inode
|
||||
|
||||
* Bug fixes:
|
||||
- fragments: fix another edge case involving empty tokens being concatenated onto previous tokens
|
||||
(github #99)
|
||||
- libpkgconf: remove dependencies on config.h in public headers
|
||||
|
||||
Changes from 1.0.0 to 1.0.1:
|
||||
----------------------------
|
||||
|
||||
* Enhancements:
|
||||
- new stub implementation of --print-provides (github #95)
|
||||
|
||||
* Bug fixes:
|
||||
- fragments: fix an edge case involving path-only fragments and PKG_CONFIG_SYSROOT_DIR (github #94)
|
||||
|
||||
Changes from 0.9.12 to 1.0.0:
|
||||
-----------------------------
|
||||
|
||||
* Features:
|
||||
- new library: libpkgconf
|
||||
|
||||
* Enhancements:
|
||||
- testsuite: use an explicit prefix on all tests
|
||||
- build: switch to automake
|
||||
|
||||
* Bug fixes:
|
||||
- cast all usage of ctype(3) functions
|
||||
- do not expand variables passed via --define-variable for compatibility with pkg-config 0.29
|
||||
- let the CFLAGS being user settable
|
||||
|
||||
Changes from 0.9.11 to 0.9.12:
|
||||
------------------------------
|
||||
|
||||
* Features:
|
||||
- add --list-package-names
|
||||
|
||||
* Enhancements:
|
||||
- ensure -I and -L are never pushed back
|
||||
|
||||
* Bug fixes:
|
||||
- fix implicit conversion warnings with variables over 31bits
|
||||
|
||||
Changes from 0.9.10 to 0.9.11:
|
||||
------------------------------
|
||||
|
||||
* Features:
|
||||
- add --validate
|
||||
|
||||
* Enhancements:
|
||||
- add large file support checks in autoconf
|
||||
|
||||
* Bug fixes:
|
||||
- fix private lib deduplication
|
||||
- handle --static correctly in some more esoteric scenarios
|
||||
|
||||
Changes from 0.9.9 to 0.9.10:
|
||||
-----------------------------
|
||||
|
||||
* Features:
|
||||
|
||||
* Enhancements:
|
||||
|
||||
* Bug fixes:
|
||||
- Fix parser when dealing with commented lines
|
||||
|
||||
Changes from 0.9.8 to 0.9.9:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- add a sub out --print-provides
|
||||
|
||||
* Enhancements:
|
||||
|
||||
* Bug fixes:
|
||||
- Fix parser when dealing with comments in fields
|
||||
|
||||
Changes from 0.9.7 to 0.9.8:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
|
||||
* Enhancements:
|
||||
- Convert manpages to mdoc(7)
|
||||
|
||||
* Bug fixes:
|
||||
- Fix parsing multiline fields
|
||||
|
||||
Changes from 0.9.6 to 0.9.7:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
|
||||
* Enhancements:
|
||||
- Convert manpages to mdoc(7)
|
||||
|
||||
* Bug fixes:
|
||||
- Fix parsing multiline fields
|
||||
|
||||
Changes from 0.9.5 to 0.9.6:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- add a sub --debug
|
||||
|
||||
* Enhancements:
|
||||
- Do not hardcode non-posix install(1)
|
||||
|
||||
* Bug fixes:
|
||||
- fix --with-system-includedir and --with-system-libdir behaviour
|
||||
|
||||
Changes from 0.9.4 to 0.9.5:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
|
||||
* Enhancements:
|
||||
- Make all variables but CFLAGS and LIBS case sensitive
|
||||
|
||||
* Bug fixes:
|
||||
|
||||
Changes from 0.9.3 to 0.9.4:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- Add a pkgconf(1) manpage
|
||||
|
||||
* Enhancements:
|
||||
- Improve support for MacOS -framework
|
||||
|
||||
* Bug fixes:
|
||||
|
||||
Changes from 0.9.2 to 0.9.3:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
- Add support for CFLAGS.private
|
||||
|
||||
* Enhancements:
|
||||
- Support out of source build
|
||||
- Improved private libs deduplication
|
||||
|
||||
* Bug fixes:
|
||||
|
||||
Changes from 0.9.1 to 0.9.2:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
|
||||
* Enhancements:
|
||||
|
||||
* Bug fixes:
|
||||
- Fix PKG_CONFIG_PATH being ignored when a .pc is directly supplied from
|
||||
command line
|
||||
|
||||
Changes from 0.9.0 to 0.9.1:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
|
||||
* Enhancements:
|
||||
- --simulate: print depgraph operations
|
||||
- --simulate: print bytecode program as a human-readable AST
|
||||
|
||||
* Bug fixes:
|
||||
- reset parser state on new package atom
|
||||
|
||||
Changes from 0.8.12 to 0.9.0:
|
||||
----------------------------
|
||||
|
||||
* Features:
|
||||
|
||||
* Enhancements:
|
||||
- Rework the internal cache API
|
||||
- Rework the internal code to use the new pkg_list_t framework
|
||||
- Rework PKG_CONFIG_PATH handling code
|
||||
|
||||
* Bug fixes:
|
||||
- fix multi-recursion with -framework
|
||||
@@ -0,0 +1,130 @@
|
||||
# pkgconf [](https://github.com/pkgconf/pkgconf/actions/workflows/test.yml)
|
||||
|
||||
`pkgconf` is a program which helps to configure compiler and linker flags for
|
||||
development libraries. It is a superset of the functionality provided by
|
||||
pkg-config from freedesktop.org, but does not provide bug-compatibility with
|
||||
the original pkg-config.
|
||||
|
||||
`libpkgconf` is a library which provides access to most of `pkgconf`'s functionality,
|
||||
to allow other tooling such as compilers and IDEs to discover and use libraries
|
||||
configured by pkgconf.
|
||||
|
||||
## release tarballs
|
||||
|
||||
Release tarballs are available on [distfiles.ariadne.space][distfiles].
|
||||
|
||||
[distfiles]: https://distfiles.ariadne.space/pkgconf/
|
||||
|
||||
## build system setup
|
||||
|
||||
If you would like to use the git sources directly, or a snapshot of the
|
||||
sources from GitHub, you will need to regenerate the autotools build
|
||||
system artifacts yourself, or use Meson instead. For example, on Alpine:
|
||||
|
||||
$ apk add autoconf automake libtool build-base
|
||||
$ sh ./autogen.sh
|
||||
|
||||
## pkgconf-lite
|
||||
|
||||
If you only need the original pkg-config functionality, there is also pkgconf-lite,
|
||||
which builds the `pkgconf` frontend and relevant portions of `libpkgconf` functionality
|
||||
into a single binary:
|
||||
|
||||
$ make -f Makefile.lite
|
||||
|
||||
## why `pkgconf` over original `pkg-config`?
|
||||
|
||||
pkgconf builds a flattened directed dependency graph, which allows for more insight
|
||||
into relationships between dependencies, allowing for some link-time dependency
|
||||
optimization, which allows for the user to more conservatively link their binaries,
|
||||
which may be helpful in some environments, such as when prelink(1) is being used.
|
||||
|
||||
The solver is also optimized to handle large dependency graphs with hundreds of
|
||||
thousands of edges, which can be seen in any project using the Abseil frameworks
|
||||
for example.
|
||||
|
||||
In addition, pkgconf has full support for virtual packages, while the original
|
||||
pkg-config does not, as well as fully supporting `Conflicts` at dependency
|
||||
resolution time, which is more efficient than checking for `Conflicts` while
|
||||
walking the dependency graph.
|
||||
|
||||
## linker flags optimization
|
||||
|
||||
pkgconf, when used effectively, can make optimizations to avoid overlinking binaries.
|
||||
|
||||
This functionality depends on the pkg-config module properly declaring its dependency
|
||||
tree instead of using `Libs` and `Cflags` fields to directly link against other modules
|
||||
which have pkg-config metadata files installed.
|
||||
|
||||
The practice of using `Libs` and `Cflags` to describe unrelated dependencies is
|
||||
not recommended in [Dan Nicholson's pkg-config tutorial][fd-tut] for this reason.
|
||||
|
||||
[fd-tut]: http://people.freedesktop.org/~dbn/pkg-config-guide.html
|
||||
|
||||
## bug compatibility with original pkg-config
|
||||
|
||||
In general, we do not provide bug-level compatibility with pkg-config.
|
||||
|
||||
What that means is, if you feel that there is a legitimate regression versus pkg-config,
|
||||
do let us know, but also make sure that the .pc files are valid and follow the rules of
|
||||
the [pkg-config tutorial][fd-tut], as most likely fixing them to follow the specified
|
||||
rules will solve the problem.
|
||||
|
||||
## debug output
|
||||
|
||||
Please use only the stable interfaces to query pkg-config. Do not screen-scrape the
|
||||
output from `--debug`: this is sent to `stderr` for a reason, it is not intended to be
|
||||
scraped. The `--debug` output is **not** a stable interface, and should **never** be
|
||||
depended on as a source of information. If you need a stable interface to query pkg-config
|
||||
which is not covered, please get in touch.
|
||||
|
||||
## compiling `pkgconf` and `libpkgconf` on UNIX
|
||||
|
||||
pkgconf is basically compiled the same way any other autotools-based project is
|
||||
compiled:
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
If you are installing pkgconf into a custom prefix, such as `/opt/pkgconf`, you will
|
||||
likely want to define the default system includedir and libdir for your toolchain.
|
||||
To do this, use the `--with-system-includedir` and `--with-system-libdir` configure
|
||||
flags like so:
|
||||
|
||||
$ ./configure \
|
||||
--prefix=/opt/pkgconf \
|
||||
--with-system-libdir=/lib:/usr/lib \
|
||||
--with-system-includedir=/usr/include
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
## compiling `pkgconf` and `libpkgconf` with Meson (usually for Windows)
|
||||
|
||||
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
|
||||
much earlier than Meson.
|
||||
|
||||
$ meson setup build -Dtests=disabled
|
||||
$ meson compile -C build
|
||||
$ meson install -C build
|
||||
|
||||
There are a few defines such as `SYSTEM_LIBDIR`, `PKGCONFIGDIR` and `SYSTEM_INCLUDEDIR`.
|
||||
However, on Windows, the default `PKGCONFIGDIR` value is usually overridden at runtime based
|
||||
on path relocation.
|
||||
|
||||
## pkg-config symlink
|
||||
|
||||
If you want pkgconf to be used when you invoke `pkg-config`, you should install a
|
||||
symlink for this. We do not do this for you, as we believe it is better for vendors
|
||||
to make this determination themselves.
|
||||
|
||||
$ ln -sf pkgconf /usr/bin/pkg-config
|
||||
|
||||
## contacts
|
||||
|
||||
You can report bugs at <https://github.com/pkgconf/pkgconf/issues>.
|
||||
|
||||
There is a mailing list at <https://lists.sr.ht/~kaniini/pkgconf>.
|
||||
|
||||
You can contact us via IRC at `#pkgconf` at `irc.oftc.net`.
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#! /bin/sh
|
||||
|
||||
TOP_DIR=$(dirname $0)
|
||||
LAST_DIR=$PWD
|
||||
|
||||
if test ! -f $TOP_DIR/configure.ac ; then
|
||||
echo "You must execute this script from the top level directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AUTOCONF=${AUTOCONF:-autoconf}
|
||||
ACLOCAL=${ACLOCAL:-aclocal}
|
||||
AUTOHEADER=${AUTOHEADER:-autoheader}
|
||||
AUTOMAKE=${AUTOMAKE:-automake}
|
||||
LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
|
||||
|
||||
dump_help_screen ()
|
||||
{
|
||||
echo "Usage: $0 [options]"
|
||||
echo
|
||||
echo "options:"
|
||||
echo " -n skip CVS changelog creation"
|
||||
echo " -h,--help show this help screen"
|
||||
echo
|
||||
exit 0
|
||||
}
|
||||
|
||||
parse_options ()
|
||||
{
|
||||
while test "$1" != "" ; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
dump_help_screen
|
||||
;;
|
||||
-n)
|
||||
SKIP_CVS_CHANGELOG=yes
|
||||
;;
|
||||
*)
|
||||
echo Invalid argument - $1
|
||||
dump_help_screen
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
run_or_die ()
|
||||
{
|
||||
COMMAND=$1
|
||||
|
||||
# check for empty commands
|
||||
if test -z "$COMMAND" ; then
|
||||
echo "*warning* no command specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
shift;
|
||||
|
||||
OPTIONS="$@"
|
||||
|
||||
# print a message
|
||||
echo -n "*info* running $COMMAND"
|
||||
if test -n "$OPTIONS" ; then
|
||||
echo " ($OPTIONS)"
|
||||
else
|
||||
echo
|
||||
fi
|
||||
|
||||
# run or die
|
||||
$COMMAND $OPTIONS ; RESULT=$?
|
||||
if test $RESULT -ne 0 ; then
|
||||
echo "*error* $COMMAND failed. (exit code = $RESULT)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
parse_options "$@"
|
||||
|
||||
cd $TOP_DIR
|
||||
|
||||
run_or_die $ACLOCAL
|
||||
run_or_die $AUTOHEADER
|
||||
run_or_die $AUTOCONF
|
||||
run_or_die $LIBTOOLIZE --install
|
||||
run_or_die $AUTOMAKE --add-missing
|
||||
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* bomtool/main.c
|
||||
* main() routine, printer functions
|
||||
*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "libpkgconf/config.h"
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
#include "getopt_long.h"
|
||||
|
||||
#define PKG_VERSION (((uint64_t) 1) << 1)
|
||||
#define PKG_ABOUT (((uint64_t) 1) << 2)
|
||||
#define PKG_HELP (((uint64_t) 1) << 3)
|
||||
|
||||
static const char *spdx_version = "SPDX-2.2";
|
||||
static const char *bom_license = "CC0-1.0";
|
||||
static const char *document_ref = "SPDXRef-DOCUMENT";
|
||||
|
||||
static pkgconf_client_t pkg_client;
|
||||
static uint64_t want_flags;
|
||||
static size_t maximum_package_count = 0;
|
||||
static int maximum_traverse_depth = 2000;
|
||||
FILE *error_msgout = NULL;
|
||||
|
||||
static bool
|
||||
error_handler(const char *msg, const pkgconf_client_t *client, void *data)
|
||||
{
|
||||
(void) client;
|
||||
(void) data;
|
||||
fprintf(error_msgout, "%s", msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *
|
||||
sbom_spdx_identity(pkgconf_pkg_t *pkg)
|
||||
{
|
||||
static char buf[PKGCONF_ITEM_SIZE];
|
||||
|
||||
snprintf(buf, sizeof buf, "%sC64%s", pkg->id, pkg->version);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *
|
||||
sbom_name(pkgconf_pkg_t *world)
|
||||
{
|
||||
static char buf[PKGCONF_BUFSIZE];
|
||||
pkgconf_node_t *node;
|
||||
|
||||
pkgconf_strlcpy(buf, "SBOM-SPDX", sizeof buf);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(world->required.head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_pkg_t *match = dep->match;
|
||||
|
||||
if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY)
|
||||
continue;
|
||||
|
||||
if (!dep->match)
|
||||
continue;
|
||||
|
||||
pkgconf_strlcat(buf, "-", sizeof buf);
|
||||
pkgconf_strlcat(buf, sbom_spdx_identity(match), sizeof buf);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
write_sbom_header(pkgconf_client_t *client, pkgconf_pkg_t *world)
|
||||
{
|
||||
(void) client;
|
||||
(void) world;
|
||||
|
||||
printf("SPDXVersion: %s\n", spdx_version);
|
||||
printf("DataLicense: %s\n", bom_license);
|
||||
printf("SPDXID: %s\n", document_ref);
|
||||
printf("DocumentName: %s\n", sbom_name(world));
|
||||
printf("DocumentNamespace: https://spdx.org/spdxdocs/bomtool-%s\n", PACKAGE_VERSION);
|
||||
printf("Creator: Tool: bomtool %s\n", PACKAGE_VERSION);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
static const char *
|
||||
sbom_identity(pkgconf_pkg_t *pkg)
|
||||
{
|
||||
static char buf[PKGCONF_ITEM_SIZE];
|
||||
|
||||
snprintf(buf, sizeof buf, "%s@%s", pkg->id, pkg->version);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
write_sbom_package(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
|
||||
{
|
||||
(void) client;
|
||||
(void) unused;
|
||||
|
||||
if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
|
||||
return;
|
||||
|
||||
printf("##### Package: %s\n\n", sbom_identity(pkg));
|
||||
|
||||
printf("PackageName: %s\n", sbom_identity(pkg));
|
||||
printf("SPDXID: SPDXRef-Package-%s\n", sbom_spdx_identity(pkg));
|
||||
printf("PackageVersion: %s\n", pkg->version);
|
||||
printf("PackageDownloadLocation: NOASSERTION\n");
|
||||
printf("PackageVerificationCode: NOASSERTION\n");
|
||||
|
||||
/* XXX: What about projects? */
|
||||
if (pkg->maintainer != NULL)
|
||||
printf("PackageSupplier: Person: %s\n", pkg->maintainer);
|
||||
|
||||
if (pkg->url != NULL)
|
||||
printf("PackageHomePage: %s\n", pkg->url);
|
||||
|
||||
printf("PackageLicenseDeclared: %s\n", pkg->license != NULL ? pkg->license : "NOASSERTION");
|
||||
|
||||
if (pkg->copyright != NULL)
|
||||
printf("PackageCopyrightText: <text>%s</text>\n", pkg->copyright);
|
||||
|
||||
if (pkg->description != NULL)
|
||||
printf("PackageSummary: <text>%s</text>\n", pkg->description);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
static void
|
||||
write_sbom_relationships(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
|
||||
{
|
||||
(void) client;
|
||||
(void) unused;
|
||||
|
||||
char baseref[PKGCONF_ITEM_SIZE];
|
||||
pkgconf_node_t *node;
|
||||
|
||||
if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
|
||||
return;
|
||||
|
||||
snprintf(baseref, sizeof baseref, "SPDXRef-Package-%sC64%s", pkg->id, pkg->version);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_pkg_t *match = dep->match;
|
||||
|
||||
if (!dep->match)
|
||||
continue;
|
||||
|
||||
printf("Relationship: %s DEPENDS_ON SPDXRef-Package-%s\n", baseref, sbom_spdx_identity(match));
|
||||
printf("Relationship: SPDXRef-Package-%s DEPENDENCY_OF %s\n", sbom_spdx_identity(match), baseref);
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_pkg_t *match = dep->match;
|
||||
|
||||
if (!dep->match)
|
||||
continue;
|
||||
|
||||
printf("Relationship: %s DEPENDS_ON SPDXRef-Package-%s\n", baseref, sbom_spdx_identity(match));
|
||||
printf("Relationship: SPDXRef-Package-%s DEV_DEPENDENCY_OF %s\n", sbom_spdx_identity(match), baseref);
|
||||
}
|
||||
|
||||
if (pkg->required.head != NULL || pkg->requires_private.head != NULL)
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
static bool
|
||||
generate_sbom_from_world(pkgconf_client_t *client, pkgconf_pkg_t *world)
|
||||
{
|
||||
int eflag;
|
||||
pkgconf_node_t *node;
|
||||
|
||||
write_sbom_header(client, world);
|
||||
|
||||
eflag = pkgconf_pkg_traverse(client, world, write_sbom_package, NULL, maximum_traverse_depth, 0);
|
||||
if (eflag != PKGCONF_PKG_ERRF_OK)
|
||||
return false;
|
||||
|
||||
eflag = pkgconf_pkg_traverse(client, world, write_sbom_relationships, NULL, maximum_traverse_depth, 0);
|
||||
if (eflag != PKGCONF_PKG_ERRF_OK)
|
||||
return false;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(world->required.head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_pkg_t *match = dep->match;
|
||||
|
||||
if (!dep->match)
|
||||
continue;
|
||||
|
||||
printf("Relationship: %s DESCRIBES SPDXRef-Package-%s\n", document_ref, sbom_spdx_identity(match));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
version(void)
|
||||
{
|
||||
printf("bomtool %s\n", PACKAGE_VERSION);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
about(void)
|
||||
{
|
||||
printf("bomtool (%s %s)\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
printf("Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021\n");
|
||||
printf(" pkgconf authors (see AUTHORS in documentation directory).\n\n");
|
||||
printf("Permission to use, copy, modify, and/or distribute this software for any\n");
|
||||
printf("purpose with or without fee is hereby granted, provided that the above\n");
|
||||
printf("copyright notice and this permission notice appear in all copies.\n\n");
|
||||
printf("This software is provided 'as is' and without any warranty, express or\n");
|
||||
printf("implied. In no event shall the authors be liable for any damages arising\n");
|
||||
printf("from the use of this software.\n\n");
|
||||
printf("Report bugs at <%s>.\n", PACKAGE_BUGREPORT);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: bomtool [--flags] [modules]\n");
|
||||
|
||||
printf("\nbasic options:\n\n");
|
||||
|
||||
printf(" --help this message\n");
|
||||
printf(" --about print bomtool version and license to stdout\n");
|
||||
printf(" --version print bomtool version to stdout\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ret = EXIT_SUCCESS;
|
||||
pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER;
|
||||
unsigned int want_client_flags = PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
|
||||
pkgconf_cross_personality_t *personality = pkgconf_cross_personality_default();
|
||||
pkgconf_pkg_t world = {
|
||||
.id = "virtual:world",
|
||||
.realname = "virtual world package",
|
||||
.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
|
||||
};
|
||||
|
||||
error_msgout = stderr;
|
||||
|
||||
struct pkg_option options[] = {
|
||||
{ "version", no_argument, &want_flags, PKG_VERSION, },
|
||||
{ "about", no_argument, &want_flags, PKG_ABOUT, },
|
||||
{ "help", no_argument, &want_flags, PKG_HELP, },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
while ((ret = pkg_getopt_long_only(argc, argv, "", options, NULL)) != -1)
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case '?':
|
||||
case ':':
|
||||
return EXIT_FAILURE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pkgconf_client_init(&pkg_client, error_handler, NULL, personality);
|
||||
|
||||
/* we have determined what features we want most likely. in some cases, we override later. */
|
||||
pkgconf_client_set_flags(&pkg_client, want_client_flags);
|
||||
|
||||
/* at this point, want_client_flags should be set, so build the dir list */
|
||||
pkgconf_client_dir_list_build(&pkg_client, personality);
|
||||
|
||||
if ((want_flags & PKG_ABOUT) == PKG_ABOUT)
|
||||
return about();
|
||||
|
||||
if ((want_flags & PKG_VERSION) == PKG_VERSION)
|
||||
return version();
|
||||
|
||||
if ((want_flags & PKG_HELP) == PKG_HELP)
|
||||
return usage();
|
||||
|
||||
while (1)
|
||||
{
|
||||
const char *package = argv[pkg_optind];
|
||||
|
||||
if (package == NULL)
|
||||
break;
|
||||
|
||||
/* check if there is a limit to the number of packages allowed to be included, if so and we have hit
|
||||
* the limit, stop adding packages to the queue.
|
||||
*/
|
||||
if (maximum_package_count > 0 && pkgq.length > maximum_package_count)
|
||||
break;
|
||||
|
||||
while (isspace((unsigned char)package[0]))
|
||||
package++;
|
||||
|
||||
/* skip empty packages */
|
||||
if (package[0] == '\0') {
|
||||
pkg_optind++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1])))
|
||||
{
|
||||
pkgconf_queue_push(&pkgq, package);
|
||||
pkg_optind++;
|
||||
}
|
||||
else
|
||||
{
|
||||
char packagebuf[PKGCONF_BUFSIZE];
|
||||
|
||||
snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]);
|
||||
pkg_optind += 3;
|
||||
|
||||
pkgconf_queue_push(&pkgq, packagebuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (pkgq.head == NULL)
|
||||
{
|
||||
fprintf(stderr, "Please specify at least one package name on the command line.\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
|
||||
if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth))
|
||||
{
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!generate_sbom_from_world(&pkg_client, &world))
|
||||
{
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
pkgconf_solution_free(&pkg_client, &world);
|
||||
pkgconf_queue_free(&pkgq);
|
||||
pkgconf_cross_personality_deinit(personality);
|
||||
pkgconf_client_deinit(&pkg_client);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,643 @@
|
||||
/* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */
|
||||
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "getopt_long.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define PKGCONF_HACK_LOGICAL_OR_ALL_VALUES
|
||||
|
||||
int pkg_opterr = 1; /* if error message should be printed */
|
||||
int pkg_optind = 1; /* index into parent argv vector */
|
||||
int pkg_optopt = '?'; /* character checked for validity */
|
||||
int pkg_optreset; /* reset getopt */
|
||||
char *pkg_optarg; /* argument associated with option */
|
||||
|
||||
#define PRINT_ERROR ((pkg_opterr) && (*options != ':'))
|
||||
|
||||
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
|
||||
|
||||
/* return values */
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||
#define INORDER (int)1
|
||||
|
||||
/* add some padding to EMSG to avoid overrun */
|
||||
#define EMSG "\0\0\0\0"
|
||||
|
||||
#ifdef GNU_COMPATIBLE
|
||||
#define NO_PREFIX (-1)
|
||||
#define D_PREFIX 0
|
||||
#define DD_PREFIX 1
|
||||
#define W_PREFIX 2
|
||||
#endif
|
||||
|
||||
static int getopt_internal(int, char * const *, const char *,
|
||||
const struct pkg_option *, int *, int);
|
||||
static int parse_long_options(char * const *, const char *,
|
||||
const struct pkg_option *, int *, int, int);
|
||||
static int gcd(int, int);
|
||||
static void permute_args(int, int, int, char * const *);
|
||||
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
|
||||
/* XXX: set pkg_optreset to 1 rather than these two */
|
||||
static int nonopt_start = -1; /* first non option argument (for permute) */
|
||||
static int nonopt_end = -1; /* first option after non options (for permute) */
|
||||
|
||||
/* Error messages */
|
||||
static const char recargchar[] = "option requires an argument -- %c";
|
||||
static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
|
||||
#ifdef GNU_COMPATIBLE
|
||||
static int dash_prefix = NO_PREFIX;
|
||||
static const char gnuoptchar[] = "invalid option -- %c";
|
||||
|
||||
static const char recargstring[] = "option `%s%s' requires an argument";
|
||||
static const char ambig[] = "option `%s%.*s' is ambiguous";
|
||||
static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
|
||||
static const char illoptstring[] = "unrecognized option `%s%s'";
|
||||
#else
|
||||
static const char recargstring[] = "option requires an argument -- %s";
|
||||
static const char ambig[] = "ambiguous option -- %.*s";
|
||||
static const char noarg[] = "option doesn't take an argument -- %.*s";
|
||||
static const char illoptstring[] = "unknown option -- %s";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compute the greatest common divisor of a and b.
|
||||
*/
|
||||
static int
|
||||
gcd(int a, int b)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = a % b;
|
||||
while (c != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
}
|
||||
|
||||
return (b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exchange the block from nonopt_start to nonopt_end with the block
|
||||
* from nonopt_end to opt_end (keeping the same order of arguments
|
||||
* in each block).
|
||||
*/
|
||||
static void
|
||||
permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||
char * const *nargv)
|
||||
{
|
||||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||
char *swap;
|
||||
|
||||
/*
|
||||
* compute lengths of blocks and number and size of cycles
|
||||
*/
|
||||
nnonopts = panonopt_end - panonopt_start;
|
||||
nopts = opt_end - panonopt_end;
|
||||
ncycle = gcd(nnonopts, nopts);
|
||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||
|
||||
for (i = 0; i < ncycle; i++) {
|
||||
cstart = panonopt_end+i;
|
||||
pos = cstart;
|
||||
for (j = 0; j < cyclelen; j++) {
|
||||
if (pos >= panonopt_end)
|
||||
pos -= nnonopts;
|
||||
else
|
||||
pos += nopts;
|
||||
swap = nargv[pos];
|
||||
/* LINTED const cast */
|
||||
((char **) nargv)[pos] = nargv[cstart];
|
||||
/* LINTED const cast */
|
||||
((char **)nargv)[cstart] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_long_options --
|
||||
* Parse long options in argc/argv argument vector.
|
||||
* Returns -1 if short_too is set and the option does not match long_options.
|
||||
*/
|
||||
static int
|
||||
parse_long_options(char * const *nargv, const char *options,
|
||||
const struct pkg_option *long_options, int *idx, int short_too, int flags)
|
||||
{
|
||||
char *current_argv, *has_equal;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
char *current_dash;
|
||||
#endif
|
||||
size_t current_argv_len;
|
||||
int i, match, exact_match, second_partial_match;
|
||||
|
||||
current_argv = place;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
switch (dash_prefix) {
|
||||
case D_PREFIX:
|
||||
current_dash = "-";
|
||||
break;
|
||||
case DD_PREFIX:
|
||||
current_dash = "--";
|
||||
break;
|
||||
case W_PREFIX:
|
||||
current_dash = "-W ";
|
||||
break;
|
||||
default:
|
||||
current_dash = "";
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
match = -1;
|
||||
exact_match = 0;
|
||||
second_partial_match = 0;
|
||||
|
||||
pkg_optind++;
|
||||
|
||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||
/* argument found (--option=arg) */
|
||||
current_argv_len = has_equal - current_argv;
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = strlen(current_argv);
|
||||
|
||||
for (i = 0; long_options[i].name; i++) {
|
||||
/* find matching long option */
|
||||
if (strncmp(current_argv, long_options[i].name,
|
||||
current_argv_len))
|
||||
continue;
|
||||
|
||||
if (strlen(long_options[i].name) == current_argv_len) {
|
||||
/* exact match */
|
||||
match = i;
|
||||
exact_match = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If this is a known short option, don't allow
|
||||
* a partial match of a single character.
|
||||
*/
|
||||
if (short_too && current_argv_len == 1)
|
||||
continue;
|
||||
|
||||
if (match == -1) /* first partial match */
|
||||
match = i;
|
||||
else if ((flags & FLAG_LONGONLY) ||
|
||||
long_options[i].has_arg !=
|
||||
long_options[match].has_arg ||
|
||||
long_options[i].flag != long_options[match].flag ||
|
||||
long_options[i].val != long_options[match].val)
|
||||
second_partial_match = 1;
|
||||
}
|
||||
if (!exact_match && second_partial_match) {
|
||||
/* ambiguous abbreviation */
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, ambig,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
#endif
|
||||
(int)current_argv_len,
|
||||
current_argv);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
pkg_optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (match != -1) { /* option found */
|
||||
if (long_options[match].has_arg == no_argument
|
||||
&& has_equal) {
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, noarg,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
#endif
|
||||
(int)current_argv_len,
|
||||
current_argv);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
/*
|
||||
* XXX: GNU sets pkg_optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
pkg_optopt = (int)long_options[match].val;
|
||||
else
|
||||
pkg_optopt = 0;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
return (BADCH);
|
||||
#else
|
||||
return (BADARG);
|
||||
#endif
|
||||
}
|
||||
if (long_options[match].has_arg == required_argument ||
|
||||
long_options[match].has_arg == optional_argument) {
|
||||
if (has_equal)
|
||||
pkg_optarg = has_equal;
|
||||
else if (long_options[match].has_arg ==
|
||||
required_argument) {
|
||||
/*
|
||||
* optional argument doesn't use next nargv
|
||||
*/
|
||||
pkg_optarg = nargv[pkg_optind++];
|
||||
}
|
||||
}
|
||||
if ((long_options[match].has_arg == required_argument)
|
||||
&& (pkg_optarg == NULL)) {
|
||||
/*
|
||||
* Missing argument; leading ':' indicates no error
|
||||
* should be generated.
|
||||
*/
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, recargstring,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
#endif
|
||||
current_argv);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
/*
|
||||
* XXX: GNU sets pkg_optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
pkg_optopt = (int)long_options[match].val;
|
||||
else
|
||||
pkg_optopt = 0;
|
||||
--pkg_optind;
|
||||
return (BADARG);
|
||||
}
|
||||
} else { /* unknown option */
|
||||
if (short_too) {
|
||||
--pkg_optind;
|
||||
return (-1);
|
||||
}
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, illoptstring,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
#endif
|
||||
current_argv);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
pkg_optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (idx)
|
||||
*idx = match;
|
||||
if (long_options[match].flag) {
|
||||
#ifdef PKGCONF_HACK_LOGICAL_OR_ALL_VALUES
|
||||
*long_options[match].flag |= long_options[match].val;
|
||||
#else
|
||||
*long_options[match].flag = long_options[match].val;
|
||||
#endif
|
||||
return (0);
|
||||
} else
|
||||
return ((int)long_options[match].val);
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_internal --
|
||||
* Parse argc/argv argument vector. Called by user level routines.
|
||||
*/
|
||||
static int
|
||||
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||
const struct pkg_option *long_options, int *idx, int flags)
|
||||
{
|
||||
char *oli; /* option letter list index */
|
||||
int optchar, short_too;
|
||||
int posixly_correct; /* no static, can be changed on the fly */
|
||||
|
||||
if (options == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||
* string begins with a '+'.
|
||||
*/
|
||||
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||
#ifdef GNU_COMPATIBLE
|
||||
if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
else if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
#else
|
||||
if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
else if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
#endif
|
||||
|
||||
if (*options == '+' || *options == '-')
|
||||
options++;
|
||||
|
||||
/*
|
||||
* XXX Some GNU programs (like cvs) set pkg_optind to 0 instead of
|
||||
* XXX using pkg_optreset. Work around this braindamage.
|
||||
*/
|
||||
if (pkg_optind == 0)
|
||||
pkg_optind = pkg_optreset = 1;
|
||||
|
||||
pkg_optarg = NULL;
|
||||
if (pkg_optreset)
|
||||
nonopt_start = nonopt_end = -1;
|
||||
start:
|
||||
if (pkg_optreset || !*place) { /* update scanning pointer */
|
||||
pkg_optreset = 0;
|
||||
if (pkg_optind >= nargc) { /* end of argument vector */
|
||||
place = EMSG;
|
||||
if (nonopt_end != -1) {
|
||||
/* do permutation, if we have to */
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
pkg_optind, nargv);
|
||||
pkg_optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
else if (nonopt_start != -1) {
|
||||
/*
|
||||
* If we skipped non-options, set pkg_optind
|
||||
* to the first of them.
|
||||
*/
|
||||
pkg_optind = nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
if (*(place = nargv[pkg_optind]) != '-' ||
|
||||
#ifdef GNU_COMPATIBLE
|
||||
place[1] == '\0') {
|
||||
#else
|
||||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
||||
#endif
|
||||
place = EMSG; /* found non-option */
|
||||
if (flags & FLAG_ALLARGS) {
|
||||
/*
|
||||
* GNU extension:
|
||||
* return non-option as argument to option 1
|
||||
*/
|
||||
pkg_optarg = nargv[pkg_optind++];
|
||||
return (INORDER);
|
||||
}
|
||||
if (!(flags & FLAG_PERMUTE)) {
|
||||
/*
|
||||
* If no permutation wanted, stop parsing
|
||||
* at first non-option.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
/* do permutation */
|
||||
if (nonopt_start == -1)
|
||||
nonopt_start = pkg_optind;
|
||||
else if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
pkg_optind, nargv);
|
||||
nonopt_start = pkg_optind -
|
||||
(nonopt_end - nonopt_start);
|
||||
nonopt_end = -1;
|
||||
}
|
||||
pkg_optind++;
|
||||
/* process next argument */
|
||||
goto start;
|
||||
}
|
||||
if (nonopt_start != -1 && nonopt_end == -1)
|
||||
nonopt_end = pkg_optind;
|
||||
|
||||
/*
|
||||
* If we have "-" do nothing, if "--" we are done.
|
||||
*/
|
||||
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||
pkg_optind++;
|
||||
place = EMSG;
|
||||
/*
|
||||
* We found an option (--), so if we skipped
|
||||
* non-options, we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
pkg_optind, nargv);
|
||||
pkg_optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check long options if:
|
||||
* 1) we were passed some
|
||||
* 2) the arg is not just "-"
|
||||
* 3) either the arg starts with -- we are getopt_long_only()
|
||||
*/
|
||||
if (long_options != NULL && place != nargv[pkg_optind] &&
|
||||
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||
short_too = 0;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
dash_prefix = D_PREFIX;
|
||||
#endif
|
||||
if (*place == '-') {
|
||||
place++; /* --foo long option */
|
||||
#ifdef GNU_COMPATIBLE
|
||||
dash_prefix = DD_PREFIX;
|
||||
#endif
|
||||
} else if (*place != ':' && strchr(options, *place) != NULL)
|
||||
short_too = 1; /* could be short option too */
|
||||
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, short_too, flags);
|
||||
if (optchar != -1) {
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
}
|
||||
|
||||
if ((optchar = (int)*place++) == (int)':' ||
|
||||
(optchar == (int)'-' && *place != '\0') ||
|
||||
(oli = strchr(options, optchar)) == NULL) {
|
||||
/*
|
||||
* If the user specified "-" and '-' isn't listed in
|
||||
* options, return -1 (non-option) as per POSIX.
|
||||
* Otherwise, it is an unknown option character (or ':').
|
||||
*/
|
||||
if (optchar == (int)'-' && *place == '\0')
|
||||
return (-1);
|
||||
if (!*place)
|
||||
++pkg_optind;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, posixly_correct ? illoptchar : gnuoptchar,
|
||||
optchar);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#else
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, illoptchar, optchar);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
pkg_optopt = optchar;
|
||||
return (BADCH);
|
||||
}
|
||||
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||
/* -W long-option */
|
||||
if (*place) /* no space */
|
||||
/* NOTHING */;
|
||||
else if (++pkg_optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, recargchar, optchar);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
pkg_optopt = optchar;
|
||||
return (BADARG);
|
||||
} else /* white space */
|
||||
place = nargv[pkg_optind];
|
||||
#ifdef GNU_COMPATIBLE
|
||||
dash_prefix = W_PREFIX;
|
||||
#endif
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, 0, flags);
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
if (*++oli != ':') { /* doesn't take argument */
|
||||
if (!*place)
|
||||
++pkg_optind;
|
||||
} else { /* takes (optional) argument */
|
||||
pkg_optarg = NULL;
|
||||
if (*place) /* no white space */
|
||||
pkg_optarg = place;
|
||||
else if (oli[1] != ':') { /* arg not optional */
|
||||
if (++pkg_optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR) {
|
||||
fprintf(stderr, "pkgconf: ");
|
||||
fprintf(stderr, recargchar, optchar);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
pkg_optopt = optchar;
|
||||
return (BADARG);
|
||||
} else
|
||||
pkg_optarg = nargv[pkg_optind];
|
||||
}
|
||||
place = EMSG;
|
||||
++pkg_optind;
|
||||
}
|
||||
/* dump back option letter */
|
||||
return (optchar);
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*
|
||||
* [eventually this will replace the BSD getopt]
|
||||
*/
|
||||
int
|
||||
pkg_getopt(int nargc, char * const *nargv, const char *options)
|
||||
{
|
||||
|
||||
/*
|
||||
* We don't pass FLAG_PERMUTE to getopt_internal() since
|
||||
* the BSD getopt(3) (unlike GNU) has never done this.
|
||||
*
|
||||
* Furthermore, since many privileged programs call getopt()
|
||||
* before dropping privileges it makes sense to keep things
|
||||
* as simple (and bug-free) as possible.
|
||||
*/
|
||||
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_long --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
pkg_getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
const struct pkg_option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE));
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_long_only --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
pkg_getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||
const struct pkg_option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE|FLAG_LONGONLY));
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _GETOPT_LONG_H_
|
||||
#define _GETOPT_LONG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
|
||||
* getopt() is declared here too for GNU programs.
|
||||
*/
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
struct pkg_option {
|
||||
/* name of long option */
|
||||
const char *name;
|
||||
/*
|
||||
* one of no_argument, required_argument, and optional_argument:
|
||||
* whether option takes an argument
|
||||
*/
|
||||
int has_arg;
|
||||
/* if not NULL, set *flag to val when option found */
|
||||
uint64_t *flag;
|
||||
/* if flag not NULL, value to set *flag to; else return value */
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
int pkg_getopt_long(int, char * const *, const char *,
|
||||
const struct pkg_option *, int *);
|
||||
int pkg_getopt_long_only(int, char * const *, const char *,
|
||||
const struct pkg_option *, int *);
|
||||
int pkg_getopt(int, char * const [], const char *);
|
||||
|
||||
extern char *pkg_optarg; /* getopt(3) external variables */
|
||||
extern int pkg_optind, pkg_opterr, pkg_optopt;
|
||||
extern int pkg_optreset; /* getopt(3) external variable */
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* renderer-msvc.c
|
||||
* MSVC library syntax renderer
|
||||
*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
#include "renderer-msvc.h"
|
||||
|
||||
static inline bool
|
||||
fragment_should_quote(const pkgconf_fragment_t *frag)
|
||||
{
|
||||
const char *src;
|
||||
|
||||
if (frag->data == NULL)
|
||||
return false;
|
||||
|
||||
for (src = frag->data; *src; src++)
|
||||
{
|
||||
if (((*src < ' ') ||
|
||||
(*src >= (' ' + (frag->children.head != NULL ? 1 : 0)) && *src < '$') ||
|
||||
(*src > '$' && *src < '(') ||
|
||||
(*src > ')' && *src < '+') ||
|
||||
(*src > ':' && *src < '=') ||
|
||||
(*src > '=' && *src < '@') ||
|
||||
(*src > 'Z' && *src < '^') ||
|
||||
(*src == '`') ||
|
||||
(*src > 'z' && *src < '~') ||
|
||||
(*src > '~')))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
fragment_len(const pkgconf_fragment_t *frag)
|
||||
{
|
||||
size_t len = 1;
|
||||
|
||||
if (frag->type)
|
||||
len += 2;
|
||||
|
||||
if (frag->data != NULL)
|
||||
{
|
||||
len += strlen(frag->data);
|
||||
|
||||
if (fragment_should_quote(frag))
|
||||
len += 2;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
allowed_fragment(const pkgconf_fragment_t *frag)
|
||||
{
|
||||
return !(!frag->type || frag->data == NULL || strchr("DILl", frag->type) == NULL);
|
||||
}
|
||||
|
||||
static size_t
|
||||
msvc_renderer_render_len(const pkgconf_list_t *list, bool escape)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
size_t out = 1; /* trailing nul */
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
const pkgconf_fragment_t *frag = node->data;
|
||||
|
||||
if (!allowed_fragment(frag))
|
||||
continue;
|
||||
|
||||
switch (frag->type)
|
||||
{
|
||||
case 'L':
|
||||
out += 9; /* "/libpath:" */
|
||||
break;
|
||||
case 'l':
|
||||
out += 4; /* ".lib" */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out += fragment_len(frag);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void
|
||||
msvc_renderer_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape)
|
||||
{
|
||||
pkgconf_node_t *node;
|
||||
char *bptr = buf;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
const pkgconf_fragment_t *frag = node->data;
|
||||
size_t buf_remaining = buflen - (bptr - buf);
|
||||
size_t cnt;
|
||||
|
||||
if (!allowed_fragment(frag))
|
||||
continue;
|
||||
|
||||
if (fragment_len(frag) > buf_remaining)
|
||||
break;
|
||||
|
||||
switch(frag->type) {
|
||||
case 'D':
|
||||
case 'I':
|
||||
*bptr++ = '/';
|
||||
*bptr++ = frag->type;
|
||||
break;
|
||||
case 'L':
|
||||
cnt = pkgconf_strlcpy(bptr, "/libpath:", buf_remaining);
|
||||
bptr += cnt;
|
||||
buf_remaining -= cnt;
|
||||
break;
|
||||
}
|
||||
|
||||
escape = fragment_should_quote(frag);
|
||||
|
||||
if (escape)
|
||||
*bptr++ = '"';
|
||||
|
||||
cnt = pkgconf_strlcpy(bptr, frag->data, buf_remaining);
|
||||
bptr += cnt;
|
||||
buf_remaining -= cnt;
|
||||
|
||||
if (frag->type == 'l')
|
||||
{
|
||||
cnt = pkgconf_strlcpy(bptr, ".lib", buf_remaining);
|
||||
bptr += cnt;
|
||||
}
|
||||
|
||||
if (escape)
|
||||
*bptr++ = '"';
|
||||
|
||||
*bptr++ = ' ';
|
||||
}
|
||||
|
||||
*bptr = '\0';
|
||||
}
|
||||
|
||||
static const pkgconf_fragment_render_ops_t msvc_renderer_ops = {
|
||||
.render_len = msvc_renderer_render_len,
|
||||
.render_buf = msvc_renderer_render_buf
|
||||
};
|
||||
|
||||
const pkgconf_fragment_render_ops_t *
|
||||
msvc_renderer_get(void)
|
||||
{
|
||||
return &msvc_renderer_ops;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* renderer-msvc.h
|
||||
* MSVC library syntax renderer header
|
||||
*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef RENDERER_MSVC_H
|
||||
#define RENDERER_MSVC_H
|
||||
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
const pkgconf_fragment_render_ops_t *msvc_renderer_get(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
dnl configure.ac
|
||||
dnl m4 preprocessor script for autotools
|
||||
dnl
|
||||
dnl Copyright (c) 2011, 2012, 2013, 2014 pkgconf authors (see AUTHORS).
|
||||
dnl
|
||||
dnl Permission to use, copy, modify, and/or distribute this software for any
|
||||
dnl purpose with or without fee is hereby granted, provided that the above
|
||||
dnl copyright notice and this permission notice appear in all copies.
|
||||
dnl
|
||||
dnl This software is provided 'as is' and without any warranty, express or
|
||||
dnl implied. In no event shall the authors be liable for any damages arising
|
||||
dnl from the use of this software.
|
||||
|
||||
AC_PREREQ([2.71])
|
||||
AC_INIT([pkgconf],[2.5.1],[https://github.com/pkgconf/pkgconf/issues/new])
|
||||
AC_CONFIG_SRCDIR([cli/main.c])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wextra], [CFLAGS="$CFLAGS -Wextra"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wformat=2], [CFLAGS="$CFLAGS -Wformat=2"])
|
||||
AX_CHECK_COMPILE_FLAG([-std=gnu99], [CFLAGS="$CFLAGS -std=gnu99"], [
|
||||
AX_CHECK_COMPILE_FLAG([-std=c99], [CFLAGS="$CFLAGS -std=c99"])
|
||||
])
|
||||
AC_CONFIG_HEADERS([libpkgconf/config.h])
|
||||
AC_CHECK_DECLS([strlcpy, strlcat, strndup], [], [], [[#include <string.h>]])
|
||||
AC_CHECK_DECLS([pledge, unveil], [], [], [[#include <unistd.h>]])
|
||||
AC_CHECK_DECLS([reallocarray])
|
||||
AC_CHECK_HEADERS([sys/stat.h])
|
||||
AM_INIT_AUTOMAKE([foreign dist-xz subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
LT_INIT
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_ARG_WITH([personality-dir],[AS_HELP_STRING([--with-personality-dir],[specify
|
||||
the place where cross-compile personality files will be found])],
|
||||
PERSONALITY_PATH="$withval",
|
||||
PERSONALITY_PATH="${datadir}/pkgconfig/personality.d:${sysconfdir}/pkgconfig/personality.d")
|
||||
|
||||
AC_SUBST([PERSONALITY_PATH])
|
||||
|
||||
AC_ARG_WITH([pkg-config-dir],[AS_HELP_STRING([--with-pkg-config-dir],[specify
|
||||
the place where pc files will be found])],PKG_DEFAULT_PATH="$withval",
|
||||
PKG_DEFAULT_PATH="${libdir}/pkgconfig:${datadir}/pkgconfig")
|
||||
|
||||
AC_SUBST([PKG_DEFAULT_PATH])
|
||||
|
||||
AC_ARG_WITH([system-libdir],[AS_HELP_STRING([--with-system-libdir],[specify the
|
||||
system library directory (default LIBDIR)])],
|
||||
SYSTEM_LIBDIR="$withval", SYSTEM_LIBDIR="${libdir}")
|
||||
|
||||
AC_SUBST([SYSTEM_LIBDIR])
|
||||
|
||||
AC_ARG_WITH([system-includedir],[AS_HELP_STRING([--with-system-includedir],[specify the
|
||||
system include directory (default INCLUDEDIR)])],
|
||||
SYSTEM_INCLUDEDIR="$withval", SYSTEM_INCLUDEDIR="${includedir}")
|
||||
|
||||
AC_SUBST([SYSTEM_INCLUDEDIR])
|
||||
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
|
||||
AC_CONFIG_FILES([Makefile Kyuafile libpkgconf.pc tests/Kyuafile tests/test_env.sh])
|
||||
AC_OUTPUT
|
||||
@@ -0,0 +1,339 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# pkgconf documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Dec 10 16:54:40 2016.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'pkgconf'
|
||||
copyright = '2016, pkgconf authors'
|
||||
author = 'pkgconf authors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '1.1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.1.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = 'en'
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#
|
||||
# today = ''
|
||||
#
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#
|
||||
# default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
# keep_warnings = False
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents.
|
||||
# "<project> v<release> documentation" by default.
|
||||
#
|
||||
# html_title = 'pkgconf v1.1.0'
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#
|
||||
# html_logo = None
|
||||
|
||||
# The name of an image file (relative to this directory) to use as a favicon of
|
||||
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#
|
||||
# html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#
|
||||
# html_extra_path = []
|
||||
|
||||
# If not None, a 'Last updated on:' timestamp is inserted at every page
|
||||
# bottom, using the given strftime format.
|
||||
# The empty string is equivalent to '%b %d, %Y'.
|
||||
#
|
||||
# html_last_updated_fmt = None
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#
|
||||
# html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = None
|
||||
|
||||
# Language to be used for generating the HTML full-text search index.
|
||||
# Sphinx supports the following languages:
|
||||
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
|
||||
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh'
|
||||
#
|
||||
# html_search_language = 'en'
|
||||
|
||||
# A dictionary with options for the search language support, empty by default.
|
||||
# 'ja' uses this config value.
|
||||
# 'zh' user can custom change `jieba` dictionary path.
|
||||
#
|
||||
# html_search_options = {'type': 'default'}
|
||||
|
||||
# The name of a javascript file (relative to the configuration directory) that
|
||||
# implements a search results scorer. If empty, the default will be used.
|
||||
#
|
||||
# html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pkgconfdoc'
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'pkgconf.tex', 'pkgconf Documentation',
|
||||
'pkgconf authors', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#
|
||||
# latex_appendices = []
|
||||
|
||||
# It false, will not define \strong, \code, itleref, \crossref ... but only
|
||||
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
|
||||
# packages.
|
||||
#
|
||||
# latex_keep_old_macro_names = True
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'pkgconf', 'pkgconf Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'pkgconf', 'pkgconf Documentation',
|
||||
author, 'pkgconf', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#
|
||||
# texinfo_no_detailmenu = False
|
||||
@@ -0,0 +1,149 @@
|
||||
# derived from https://github.com/jeanralphaviles/comment_parser/blob/master/comment_parser/parsers/c_parser.py
|
||||
# MIT license - https://github.com/jeanralphaviles/comment_parser/blob/master/LICENSE
|
||||
|
||||
|
||||
class Comment:
|
||||
def __init__(self, comment, line, multiline):
|
||||
self.comment = comment
|
||||
self.line = line
|
||||
self.multiline = multiline
|
||||
|
||||
def __repr__(self):
|
||||
return "Comment(comment=%r, line=%r, multiline=%r)" % (self.comment, self.line, self.multiline)
|
||||
|
||||
@property
|
||||
def clean_text(self):
|
||||
if not self.multiline:
|
||||
return self.comment.strip()
|
||||
|
||||
lines = self.comment.splitlines()
|
||||
cleanlines = []
|
||||
for line in lines:
|
||||
if line[0:3] == ' * ':
|
||||
cleanlines.append(line[3:])
|
||||
elif len(line) == 2:
|
||||
cleanlines.append('')
|
||||
return '\n'.join(cleanlines)
|
||||
|
||||
@property
|
||||
def doc_text(self):
|
||||
text = self.clean_text
|
||||
if '!doc' in text[0:4]:
|
||||
return text[5:]
|
||||
return None
|
||||
|
||||
|
||||
class FileError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class UnterminatedCommentError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def extract_comments(filename):
|
||||
"""Extracts a list of comments from the given C family source file.
|
||||
Comments are represented with the Comment class found in the common module.
|
||||
C family comments come in two forms, single and multi-line comments.
|
||||
- Single-line comments begin with '//' and continue to the end of line.
|
||||
- Multi-line comments begin with '/*' and end with '*/' and can span
|
||||
multiple lines of code. If a multi-line comment does not terminate
|
||||
before EOF is reached, then an exception is raised.
|
||||
Note that this doesn't take language-specific preprocessor directives into
|
||||
consideration.
|
||||
Args:
|
||||
filename: String name of the file to extract comments from.
|
||||
Returns:
|
||||
Python list of Comment objects in the order that they appear in the file.
|
||||
Raises:
|
||||
FileError: File was unable to be open or read.
|
||||
UnterminatedCommentError: Encountered an unterminated multi-line
|
||||
comment.
|
||||
"""
|
||||
try:
|
||||
with open(filename, 'r') as source_file:
|
||||
state = 0
|
||||
current_comment = ''
|
||||
comments = []
|
||||
line_counter = 1
|
||||
comment_start = 1
|
||||
while True:
|
||||
char = source_file.read(1)
|
||||
if not char:
|
||||
if state == 3 or state == 4:
|
||||
raise UnterminatedCommentError()
|
||||
if state == 2:
|
||||
# Was in single line comment. Create comment.
|
||||
comment = Comment(current_comment, line_counter, False)
|
||||
comments.append(comment)
|
||||
return comments
|
||||
if state == 0:
|
||||
# Waiting for comment start character or beginning of
|
||||
# string.
|
||||
if char == '/':
|
||||
state = 1
|
||||
elif char == '"':
|
||||
state = 5
|
||||
elif state == 1:
|
||||
# Found comment start character, classify next character and
|
||||
# determine if single or multiline comment.
|
||||
if char == '/':
|
||||
state = 2
|
||||
elif char == '*':
|
||||
comment_start = line_counter
|
||||
state = 3
|
||||
else:
|
||||
state = 0
|
||||
elif state == 2:
|
||||
# In single line comment, read characters until EOL.
|
||||
if char == '\n':
|
||||
comment = Comment(current_comment, line_counter, False)
|
||||
comments.append(comment)
|
||||
current_comment = ''
|
||||
state = 0
|
||||
else:
|
||||
current_comment += char
|
||||
elif state == 3:
|
||||
# In multi-line comment, add characters until '*'
|
||||
# encountered.
|
||||
if char == '*':
|
||||
state = 4
|
||||
else:
|
||||
current_comment += char
|
||||
elif state == 4:
|
||||
# In multi-line comment with asterisk found. Determine if
|
||||
# comment is ending.
|
||||
if char == '/':
|
||||
comment = Comment(
|
||||
current_comment, comment_start, True)
|
||||
comments.append(comment)
|
||||
current_comment = ''
|
||||
state = 0
|
||||
else:
|
||||
current_comment += '*'
|
||||
# Care for multiple '*' in a row
|
||||
if char != '*':
|
||||
current_comment += char
|
||||
state = 3
|
||||
elif state == 5:
|
||||
# In string literal, expect literal end or escape char.
|
||||
if char == '"':
|
||||
state = 0
|
||||
elif char == '\\':
|
||||
state = 6
|
||||
elif state == 6:
|
||||
# In string literal, escaping current char.
|
||||
state = 5
|
||||
if char == '\n':
|
||||
line_counter += 1
|
||||
except OSError as exception:
|
||||
raise FileError(str(exception))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
from pprint import pprint
|
||||
|
||||
comments = [comment for comment in extract_comments(sys.argv[1]) if comment.doc_text]
|
||||
for comment in comments:
|
||||
print(comment.doc_text)
|
||||
@@ -0,0 +1,14 @@
|
||||
pkgconf
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
libpkgconf
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
libpkgconf `argvsplit` module
|
||||
=============================
|
||||
|
||||
This is a lowlevel module which provides parsing of strings into argument vectors,
|
||||
similar to what a shell would do.
|
||||
|
||||
.. c:function:: void pkgconf_argv_free(char **argv)
|
||||
|
||||
Frees an argument vector.
|
||||
|
||||
:param char** argv: The argument vector to free.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: int pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||
|
||||
Splits a string into an argument vector.
|
||||
|
||||
:param char* src: The string to split.
|
||||
:param int* argc: A pointer to an integer to store the argument count.
|
||||
:param char*** argv: A pointer to a pointer for an argument vector.
|
||||
:return: 0 on success, -1 on error.
|
||||
:rtype: int
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
libpkgconf `audit` module
|
||||
=========================
|
||||
|
||||
The libpkgconf `audit` module contains the functions related to attaching an audit log file
|
||||
to a ``pkgconf_client_t`` object.
|
||||
|
||||
The audit log format is the same as the output generated by the ``PKG_CONFIG_LOG`` environment
|
||||
variable.
|
||||
|
||||
.. c:function:: void pkgconf_audit_set_log(pkgconf_client_t *client, FILE *auditf)
|
||||
|
||||
Sets the audit log file pointer on `client` to `auditf`.
|
||||
The callee is responsible for closing any previous log files.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to modify.
|
||||
:param FILE* auditf: The file pointer for the already open log file.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_audit_log(pkgconf_client_t *client, const char *format, ...)
|
||||
|
||||
Logs a message to the opened audit log (if any).
|
||||
|
||||
:param pkgconf_client_t* client: The client object the log message is for.
|
||||
:param char* format: The format string to use for the log messages.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pkgconf_pkg_t *dep, const pkgconf_dependency_t *depnode)
|
||||
|
||||
Convenience function which logs a dependency node to the opened audit log (if any).
|
||||
|
||||
:param pkgconf_client_t* client: The client object the log message is for.
|
||||
:param pkgconf_pkg_t* dep: The dependency package object being logged.
|
||||
:param pkgconf_dependency_t* depnode: The dependency object itself being logged.
|
||||
:return: nothing
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
libpkgconf `cache` module
|
||||
=========================
|
||||
|
||||
The libpkgconf `cache` module manages a package/module object cache, allowing it to
|
||||
avoid loading duplicate copies of a package/module.
|
||||
|
||||
A cache is tied to a specific pkgconf client object, so package objects should not
|
||||
be shared across threads.
|
||||
|
||||
.. c:function:: pkgconf_pkg_t *pkgconf_cache_lookup(const pkgconf_client_t *client, const char *id)
|
||||
|
||||
Looks up a package in the cache given an `id` atom,
|
||||
such as ``gtk+-3.0`` and returns the already loaded version
|
||||
if present.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to access.
|
||||
:param char* id: The package atom to look up in the client object's cache.
|
||||
:return: A package object if present, else ``NULL``.
|
||||
:rtype: pkgconf_pkg_t *
|
||||
|
||||
.. c:function:: void pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
|
||||
Adds an entry for the package to the package cache.
|
||||
The cache entry must be removed if the package is freed.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to modify.
|
||||
:param pkgconf_pkg_t* pkg: The package object to add to the client object's cache.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
|
||||
Deletes a package from the client object's package cache.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to modify.
|
||||
:param pkgconf_pkg_t* pkg: The package object to remove from the client object's cache.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_cache_free(pkgconf_client_t *client)
|
||||
|
||||
Releases all resources related to a client object's package cache.
|
||||
This function should only be called to clear a client object's package cache,
|
||||
as it may release any package in the cache.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to modify.
|
||||
@@ -0,0 +1,212 @@
|
||||
|
||||
libpkgconf `client` module
|
||||
==========================
|
||||
|
||||
The libpkgconf `client` module implements the `pkgconf_client_t` "client" object.
|
||||
Client objects store all necessary state for libpkgconf allowing for multiple instances to run
|
||||
in parallel.
|
||||
|
||||
Client objects are not thread safe, in other words, a client object should not be shared across
|
||||
thread boundaries.
|
||||
|
||||
.. c:function:: void pkgconf_client_dir_list_build(pkgconf_client_t *client)
|
||||
|
||||
Bootstraps the package search paths. If the ``PKGCONF_PKG_PKGF_ENV_ONLY`` `flag` is set on the client,
|
||||
then only the ``PKG_CONFIG_PATH`` environment variable will be used, otherwise both the
|
||||
``PKG_CONFIG_PATH`` and ``PKG_CONFIG_LIBDIR`` environment variables will be used.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to bootstrap.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
|
||||
Initialise a pkgconf client object.
|
||||
|
||||
:param pkgconf_client_t* client: The client to initialise.
|
||||
:param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
|
||||
:param void* error_handler_data: user data passed to optional error handler
|
||||
:param pkgconf_cross_personality_t* personality: the cross-compile personality to use for defaults
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_client_t* pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
|
||||
Allocate and initialise a pkgconf client object.
|
||||
|
||||
:param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
|
||||
:param void* error_handler_data: user data passed to optional error handler
|
||||
:param pkgconf_cross_personality_t* personality: cross-compile personality to use
|
||||
:return: A pkgconf client object.
|
||||
:rtype: pkgconf_client_t*
|
||||
|
||||
.. c:function:: void pkgconf_client_deinit(pkgconf_client_t *client)
|
||||
|
||||
Release resources belonging to a pkgconf client object.
|
||||
|
||||
:param pkgconf_client_t* client: The client to deinitialise.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_client_free(pkgconf_client_t *client)
|
||||
|
||||
Release resources belonging to a pkgconf client object and then free the client object itself.
|
||||
|
||||
:param pkgconf_client_t* client: The client to deinitialise and free.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: const char *pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client)
|
||||
|
||||
Retrieves the client's sysroot directory (if any).
|
||||
|
||||
:param pkgconf_client_t* client: The client object being accessed.
|
||||
:return: A string containing the sysroot directory or NULL.
|
||||
:rtype: const char *
|
||||
|
||||
.. c:function:: void pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir)
|
||||
|
||||
Sets or clears the sysroot directory on a client object. Any previous sysroot directory setting is
|
||||
automatically released if one was previously set.
|
||||
|
||||
Additionally, the global tuple ``$(pc_sysrootdir)`` is set as appropriate based on the new setting.
|
||||
|
||||
:param pkgconf_client_t* client: The client object being modified.
|
||||
:param char* sysroot_dir: The sysroot directory to set or NULL to unset.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: const char *pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client)
|
||||
|
||||
Retrieves the client's buildroot directory (if any).
|
||||
|
||||
:param pkgconf_client_t* client: The client object being accessed.
|
||||
:return: A string containing the buildroot directory or NULL.
|
||||
:rtype: const char *
|
||||
|
||||
.. c:function:: void pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir)
|
||||
|
||||
Sets or clears the buildroot directory on a client object. Any previous buildroot directory setting is
|
||||
automatically released if one was previously set.
|
||||
|
||||
Additionally, the global tuple ``$(pc_top_builddir)`` is set as appropriate based on the new setting.
|
||||
|
||||
:param pkgconf_client_t* client: The client object being modified.
|
||||
:param char* buildroot_dir: The buildroot directory to set or NULL to unset.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: bool pkgconf_error(const pkgconf_client_t *client, const char *format, ...)
|
||||
|
||||
Report an error to a client-registered error handler.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to report the error to.
|
||||
:param char* format: A printf-style format string to use for formatting the error message.
|
||||
:return: true if the error handler processed the message, else false.
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: bool pkgconf_warn(const pkgconf_client_t *client, const char *format, ...)
|
||||
|
||||
Report an error to a client-registered warn handler.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to report the error to.
|
||||
:param char* format: A printf-style format string to use for formatting the warning message.
|
||||
:return: true if the warn handler processed the message, else false.
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: bool pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t len, const char *funcname, const char *format, ...)
|
||||
|
||||
Report a message to a client-registered trace handler.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to report the trace message to.
|
||||
:param char* filename: The file the function is in.
|
||||
:param size_t lineno: The line number currently being executed.
|
||||
:param char* funcname: The function name to use.
|
||||
:param char* format: A printf-style format string to use for formatting the trace message.
|
||||
:return: true if the trace handler processed the message, else false.
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: bool pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, const void *data)
|
||||
|
||||
The default pkgconf error handler.
|
||||
|
||||
:param char* msg: The error message to handle.
|
||||
:param pkgconf_client_t* client: The client object the error originated from.
|
||||
:param void* data: An opaque pointer to extra data associated with the client for error handling.
|
||||
:return: true (the function does nothing to process the message)
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: unsigned int pkgconf_client_get_flags(const pkgconf_client_t *client)
|
||||
|
||||
Retrieves resolver-specific flags associated with a client object.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to retrieve the resolver-specific flags from.
|
||||
:return: a bitfield of resolver-specific flags
|
||||
:rtype: uint
|
||||
|
||||
.. c:function:: void pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags)
|
||||
|
||||
Sets resolver-specific flags associated with a client object.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to set the resolver-specific flags on.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: const char *pkgconf_client_get_prefix_varname(const pkgconf_client_t *client)
|
||||
|
||||
Retrieves the name of the variable that should contain a module's prefix.
|
||||
In some cases, it is necessary to override this variable to allow proper path relocation.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to retrieve the prefix variable name from.
|
||||
:return: the prefix variable name as a string
|
||||
:rtype: const char *
|
||||
|
||||
.. c:function:: void pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname)
|
||||
|
||||
Sets the name of the variable that should contain a module's prefix.
|
||||
If the variable name is ``NULL``, then the default variable name (``prefix``) is used.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to set the prefix variable name on.
|
||||
:param char* prefix_varname: The prefix variable name to set.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_client_get_warn_handler(const pkgconf_client_t *client)
|
||||
|
||||
Returns the warning handler if one is set, else ``NULL``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to get the warn handler from.
|
||||
:return: a function pointer to the warn handler or ``NULL``
|
||||
|
||||
.. c:function:: pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data)
|
||||
|
||||
Sets a warn handler on a client object or uninstalls one if set to ``NULL``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to set the warn handler on.
|
||||
:param pkgconf_error_handler_func_t warn_handler: The warn handler to set.
|
||||
:param void* warn_handler_data: Optional data to associate with the warn handler.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_client_get_error_handler(const pkgconf_client_t *client)
|
||||
|
||||
Returns the error handler if one is set, else ``NULL``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to get the error handler from.
|
||||
:return: a function pointer to the error handler or ``NULL``
|
||||
|
||||
.. c:function:: pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data)
|
||||
|
||||
Sets a warn handler on a client object or uninstalls one if set to ``NULL``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to set the error handler on.
|
||||
:param pkgconf_error_handler_func_t error_handler: The error handler to set.
|
||||
:param void* error_handler_data: Optional data to associate with the error handler.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_client_get_trace_handler(const pkgconf_client_t *client)
|
||||
|
||||
Returns the error handler if one is set, else ``NULL``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to get the error handler from.
|
||||
:return: a function pointer to the error handler or ``NULL``
|
||||
|
||||
.. c:function:: pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data)
|
||||
|
||||
Sets a warn handler on a client object or uninstalls one if set to ``NULL``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object to set the error handler on.
|
||||
:param pkgconf_error_handler_func_t trace_handler: The error handler to set.
|
||||
:param void* trace_handler_data: Optional data to associate with the error handler.
|
||||
:return: nothing
|
||||
@@ -0,0 +1,90 @@
|
||||
|
||||
libpkgconf `dependency` module
|
||||
==============================
|
||||
|
||||
The `dependency` module provides support for building `dependency lists` (the basic component of the overall `dependency graph`) and
|
||||
`dependency nodes` which store dependency information.
|
||||
|
||||
.. c:function:: pkgconf_dependency_t *pkgconf_dependency_add(pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare)
|
||||
|
||||
Adds a parsed dependency to a dependency list as a dependency node.
|
||||
|
||||
:param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to.
|
||||
:param pkgconf_list_t* list: The dependency list to add a dependency node to.
|
||||
:param char* package: The package `atom` to set on the dependency node.
|
||||
:param char* version: The package `version` to set on the dependency node.
|
||||
:param pkgconf_pkg_comparator_t compare: The comparison operator to set on the dependency node.
|
||||
:param uint flags: Any flags to attach to the dependency node.
|
||||
:return: A dependency node.
|
||||
:rtype: pkgconf_dependency_t *
|
||||
|
||||
.. c:function:: void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail)
|
||||
|
||||
Adds a dependency node to a pre-existing dependency list.
|
||||
|
||||
:param pkgconf_list_t* list: The dependency list to add a dependency node to.
|
||||
:param pkgconf_dependency_t* tail: The dependency node to add to the tail of the dependency list.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_dependency_free_one(pkgconf_dependency_t *dep)
|
||||
|
||||
Frees a dependency node.
|
||||
|
||||
:param pkgconf_dependency_t* dep: The dependency node to free.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_dependency_t *pkgconf_dependency_ref(pkgconf_client_t *owner, pkgconf_dependency_t *dep)
|
||||
|
||||
Increases a dependency node's refcount.
|
||||
|
||||
:param pkgconf_client_t* owner: The client object which owns the memory of this dependency node.
|
||||
:param pkgconf_dependency_t* dep: The dependency to increase the refcount of.
|
||||
:return: the dependency node on success, else NULL
|
||||
|
||||
.. c:function:: void pkgconf_dependency_unref(pkgconf_client_t *owner, pkgconf_dependency_t *dep)
|
||||
|
||||
Decreases a dependency node's refcount and frees it if necessary.
|
||||
|
||||
:param pkgconf_client_t* owner: The client object which owns the memory of this dependency node.
|
||||
:param pkgconf_dependency_t* dep: The dependency to decrease the refcount of.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_dependency_free(pkgconf_list_t *list)
|
||||
|
||||
Release a dependency list and its child dependency nodes.
|
||||
|
||||
:param pkgconf_list_t* list: The dependency list to release.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_dependency_parse_str(pkgconf_list_t *deplist_head, const char *depends)
|
||||
|
||||
Parse a dependency declaration into a dependency list.
|
||||
Commas are counted as whitespace to allow for constructs such as ``@SUBSTVAR@, zlib`` being processed
|
||||
into ``, zlib``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to.
|
||||
:param pkgconf_list_t* deplist_head: The dependency list to populate with dependency nodes.
|
||||
:param char* depends: The dependency data to parse.
|
||||
:param uint flags: Any flags to attach to the dependency nodes.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends)
|
||||
|
||||
Preprocess dependency data and then process that dependency declaration into a dependency list.
|
||||
Commas are counted as whitespace to allow for constructs such as ``@SUBSTVAR@, zlib`` being processed
|
||||
into ``, zlib``.
|
||||
|
||||
:param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to.
|
||||
:param pkgconf_pkg_t* pkg: The package object that owns this dependency list.
|
||||
:param pkgconf_list_t* deplist: The dependency list to populate with dependency nodes.
|
||||
:param char* depends: The dependency data to parse.
|
||||
:param uint flags: Any flags to attach to the dependency nodes.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_dependency_t *pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *dep)
|
||||
|
||||
Copies a dependency node to a new one.
|
||||
|
||||
:param pkgconf_client_t* client: The client object that will own this dependency.
|
||||
:param pkgconf_dependency_t* dep: The dependency node to copy.
|
||||
:return: a pointer to a new dependency node, else NULL
|
||||
@@ -0,0 +1,116 @@
|
||||
|
||||
libpkgconf `fragment` module
|
||||
============================
|
||||
|
||||
The `fragment` module provides low-level management and rendering of fragment lists. A
|
||||
`fragment list` contains various `fragments` of text (such as ``-I /usr/include``) in a matter
|
||||
which is composable, mergeable and reorderable.
|
||||
|
||||
.. c:function:: void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string, unsigned int flags)
|
||||
|
||||
Adds a `fragment` of text to a `fragment list`, possibly modifying the fragment if a sysroot is set.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
:param pkgconf_list_t* list: The fragment list.
|
||||
:param char* string: The string of text to add as a fragment to the fragment list.
|
||||
:param uint flags: Parsing-related flags for the package.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag)
|
||||
|
||||
Checks if a `fragment` contains a `system path`. System paths are detected at compile time and optionally overridden by
|
||||
the ``PKG_CONFIG_SYSTEM_INCLUDE_PATH`` and ``PKG_CONFIG_SYSTEM_LIBRARY_PATH`` environment variables.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object the fragment belongs to.
|
||||
:param pkgconf_fragment_t* frag: The fragment being checked.
|
||||
:return: true if the fragment contains a system path, else false
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private)
|
||||
|
||||
Copies a `fragment` to another `fragment list`, possibly removing a previous copy of the `fragment`
|
||||
in a process known as `mergeback`.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
:param pkgconf_list_t* list: The list the fragment is being added to.
|
||||
:param pkgconf_fragment_t* base: The fragment being copied.
|
||||
:param bool is_private: Whether the fragment list is a `private` fragment list (static linking).
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base)
|
||||
|
||||
Copies a `fragment list` to another `fragment list`, possibly removing a previous copy of the fragments
|
||||
in a process known as `mergeback`.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
:param pkgconf_list_t* list: The list the fragments are being added to.
|
||||
:param pkgconf_list_t* base: The list the fragments are being copied from.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func)
|
||||
|
||||
Copies a `fragment list` to another `fragment list` which match a user-specified filtering function.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
:param pkgconf_list_t* dest: The destination list.
|
||||
:param pkgconf_list_t* src: The source list.
|
||||
:param pkgconf_fragment_filter_func_t filter_func: The filter function to use.
|
||||
:param void* data: Optional data to pass to the filter function.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
|
||||
Calculates the required memory to store a `fragment list` when rendered as a string.
|
||||
|
||||
:param pkgconf_list_t* list: The `fragment list` being rendered.
|
||||
:param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
:param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
:return: the amount of bytes required to represent the `fragment list` when rendered
|
||||
:rtype: size_t
|
||||
|
||||
.. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
|
||||
Renders a `fragment list` into a buffer.
|
||||
|
||||
:param pkgconf_list_t* list: The `fragment list` being rendered.
|
||||
:param char* buf: The buffer to render the fragment list into.
|
||||
:param size_t buflen: The length of the buffer.
|
||||
:param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
:param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: char *pkgconf_fragment_render(const pkgconf_list_t *list)
|
||||
|
||||
Allocate memory and render a `fragment list` into it.
|
||||
|
||||
:param pkgconf_list_t* list: The `fragment list` being rendered.
|
||||
:param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
:param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
:return: An allocated string containing the rendered `fragment list`.
|
||||
:rtype: char *
|
||||
|
||||
.. c:function:: void pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node)
|
||||
|
||||
Delete a `fragment node` from a `fragment list`.
|
||||
|
||||
:param pkgconf_list_t* list: The `fragment list` to delete from.
|
||||
:param pkgconf_fragment_t* node: The `fragment node` to delete.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_fragment_free(pkgconf_list_t *list)
|
||||
|
||||
Delete an entire `fragment list`.
|
||||
|
||||
:param pkgconf_list_t* list: The `fragment list` to delete.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value)
|
||||
|
||||
Parse a string into a `fragment list`.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
:param pkgconf_list_t* list: The `fragment list` to add the fragment entries to.
|
||||
:param pkgconf_list_t* vars: A list of variables to use for variable substitution.
|
||||
:param uint flags: Any parsing flags to be aware of.
|
||||
:param char* value: The string to parse into fragments.
|
||||
:return: true on success, false on parse error
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
libpkgconf `path` module
|
||||
========================
|
||||
|
||||
The `path` module provides functions for manipulating lists of paths in a cross-platform manner. Notably,
|
||||
it is used by the `pkgconf client` to parse the ``PKG_CONFIG_PATH``, ``PKG_CONFIG_LIBDIR`` and related environment
|
||||
variables.
|
||||
|
||||
.. c:function:: void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist)
|
||||
|
||||
Adds 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
|
||||
|
||||
.. c:function:: size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist)
|
||||
|
||||
Splits a given text input and inserts paths into a path list.
|
||||
|
||||
:param char* text: The path text to split and add as path nodes.
|
||||
:param pkgconf_list_t* dirlist: The path list to have the path nodes added to.
|
||||
:param bool filter: Whether to perform duplicate filtering.
|
||||
:return: number of path nodes added to the path list
|
||||
:rtype: size_t
|
||||
|
||||
.. c:function:: size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist)
|
||||
|
||||
Adds the paths specified in an environment variable to a path list. If the environment variable is not set,
|
||||
an optional default set of paths is added.
|
||||
|
||||
:param char* envvarname: The environment variable to look up.
|
||||
:param char* fallback: The fallback paths to use if the environment variable is not set.
|
||||
:param pkgconf_list_t* dirlist: The path list to add the path nodes to.
|
||||
:param bool filter: Whether to perform duplicate filtering.
|
||||
:return: number of path nodes added to the path list
|
||||
:rtype: size_t
|
||||
|
||||
.. c:function:: bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist)
|
||||
|
||||
Checks whether a path has a matching prefix in a path list.
|
||||
|
||||
:param char* path: The path to check against a path list.
|
||||
:param pkgconf_list_t* dirlist: The path list to check the path against.
|
||||
:return: true if the path list has a matching prefix, otherwise false
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: void pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
|
||||
Copies a path list to another path list.
|
||||
|
||||
:param pkgconf_list_t* dst: The path list to copy to.
|
||||
:param pkgconf_list_t* src: The path list to copy from.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_path_free(pkgconf_list_t *dirlist)
|
||||
|
||||
Releases any path nodes attached to the given path list.
|
||||
|
||||
:param pkgconf_list_t* dirlist: The path list to clean up.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: bool pkgconf_path_relocate(char *buf, size_t buflen)
|
||||
|
||||
Relocates a path, possibly calling normpath() on it.
|
||||
|
||||
:param char* buf: The path to relocate.
|
||||
:param size_t buflen: The buffer length the path is contained in.
|
||||
:return: true on success, false on error
|
||||
:rtype: bool
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
libpkgconf `personality` module
|
||||
=========================
|
||||
|
||||
.. c:function:: const pkgconf_cross_personality_t *pkgconf_cross_personality_default(void)
|
||||
|
||||
Returns the default cross-compile personality.
|
||||
|
||||
Not thread safe.
|
||||
|
||||
:rtype: pkgconf_cross_personality_t*
|
||||
:return: the default cross-compile personality
|
||||
|
||||
.. c:function:: void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *)
|
||||
|
||||
Decrements the count of default cross personality instances.
|
||||
|
||||
Not thread safe.
|
||||
|
||||
:rtype: void
|
||||
|
||||
.. c:function:: pkgconf_cross_personality_t *pkgconf_cross_personality_find(const char *triplet)
|
||||
|
||||
Attempts to find a cross-compile personality given a triplet.
|
||||
|
||||
:rtype: pkgconf_cross_personality_t*
|
||||
:return: the default cross-compile personality
|
||||
@@ -0,0 +1,154 @@
|
||||
|
||||
libpkgconf `pkg` module
|
||||
=======================
|
||||
|
||||
The `pkg` module provides dependency resolution services and the overall `.pc` file parsing
|
||||
routines.
|
||||
|
||||
.. c:function:: pkgconf_pkg_t *pkgconf_pkg_new_from_file(const pkgconf_client_t *client, const char *filename, FILE *f, unsigned int flags)
|
||||
|
||||
Parse a .pc file into a pkgconf_pkg_t object structure.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param char* filename: The filename of the package file (including full path).
|
||||
:param FILE* f: The file object to read from.
|
||||
:param uint flags: The flags to use when parsing.
|
||||
:returns: A ``pkgconf_pkg_t`` object which contains the package data.
|
||||
:rtype: pkgconf_pkg_t *
|
||||
|
||||
.. c:function:: void pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
|
||||
Releases all releases for a given ``pkgconf_pkg_t`` object.
|
||||
|
||||
:param pkgconf_client_t* client: The client which owns the ``pkgconf_pkg_t`` object, `pkg`.
|
||||
:param pkgconf_pkg_t* pkg: The package to free.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_pkg_t *pkgconf_pkg_ref(const pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
|
||||
Adds an additional reference to the package object.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object which owns the package being referenced.
|
||||
:param pkgconf_pkg_t* pkg: The package object being referenced.
|
||||
:return: The package itself with an incremented reference count.
|
||||
:rtype: pkgconf_pkg_t *
|
||||
|
||||
.. c:function:: void pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
|
||||
Releases a reference on the package object. If the reference count is 0, then also free the package.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object which owns the package being dereferenced.
|
||||
:param pkgconf_pkg_t* pkg: The package object being dereferenced.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_pkg_t *pkgconf_scan_all(pkgconf_client_t *client, void *data, pkgconf_pkg_iteration_func_t func)
|
||||
|
||||
Iterates over all packages found in the `package directory list`, running ``func`` on them. If ``func`` returns true,
|
||||
then stop iteration and return the last iterated package.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param void* data: An opaque pointer to data to provide the iteration function with.
|
||||
:param pkgconf_pkg_iteration_func_t func: A function which is called for each package to determine if the package matches,
|
||||
always return ``false`` to iterate over all packages.
|
||||
:return: A package object reference if one is found by the scan function, else ``NULL``.
|
||||
:rtype: pkgconf_pkg_t *
|
||||
|
||||
.. c:function:: pkgconf_pkg_t *pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
|
||||
|
||||
Search for a package.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param char* name: The name of the package `atom` to use for searching.
|
||||
:return: A package object reference if the package was found, else ``NULL``.
|
||||
:rtype: pkgconf_pkg_t *
|
||||
|
||||
.. c:function:: int pkgconf_compare_version(const char *a, const char *b)
|
||||
|
||||
Compare versions using RPM version comparison rules as described in the LSB.
|
||||
|
||||
:param char* a: The first version to compare in the pair.
|
||||
:param char* b: The second version to compare in the pair.
|
||||
:return: -1 if the first version is less than, 0 if both versions are equal, 1 if the second version is less than.
|
||||
:rtype: int
|
||||
|
||||
.. c:function:: pkgconf_pkg_t *pkgconf_builtin_pkg_get(const char *name)
|
||||
|
||||
Looks up a built-in package. The package should not be freed or dereferenced.
|
||||
|
||||
:param char* name: An atom corresponding to a built-in package to search for.
|
||||
:return: the built-in package if present, else ``NULL``.
|
||||
:rtype: pkgconf_pkg_t *
|
||||
|
||||
.. c:function:: const char *pkgconf_pkg_get_comparator(const pkgconf_dependency_t *pkgdep)
|
||||
|
||||
Returns the comparator used in a depgraph dependency node as a string.
|
||||
|
||||
:param pkgconf_dependency_t* pkgdep: The depgraph dependency node to return the comparator for.
|
||||
:return: A string matching the comparator or ``"???"``.
|
||||
:rtype: char *
|
||||
|
||||
.. c:function:: pkgconf_pkg_comparator_t pkgconf_pkg_comparator_lookup_by_name(const char *name)
|
||||
|
||||
Look up the appropriate comparator bytecode in the comparator set (defined
|
||||
in ``pkg.c``, see ``pkgconf_pkg_comparator_names`` and ``pkgconf_pkg_comparator_impls``).
|
||||
|
||||
:param char* name: The comparator to look up by `name`.
|
||||
:return: The comparator bytecode if found, else ``PKGCONF_CMP_ANY``.
|
||||
:rtype: pkgconf_pkg_comparator_t
|
||||
|
||||
.. c:function:: pkgconf_pkg_t *pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags)
|
||||
|
||||
Verify a pkgconf_dependency_t node in the depgraph. If the dependency is solvable,
|
||||
return the appropriate ``pkgconf_pkg_t`` object, else ``NULL``.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_dependency_t* pkgdep: The dependency graph node to solve.
|
||||
:param uint* eflags: An optional pointer that, if set, will be populated with an error code from the resolver.
|
||||
:return: On success, the appropriate ``pkgconf_pkg_t`` object to solve the dependency, else ``NULL``.
|
||||
:rtype: pkgconf_pkg_t *
|
||||
|
||||
.. c:function:: unsigned int pkgconf_pkg_verify_graph(pkgconf_client_t *client, pkgconf_pkg_t *root, int depth)
|
||||
|
||||
Verify the graph dependency nodes are satisfiable by walking the tree using
|
||||
``pkgconf_pkg_traverse()``.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_pkg_t* root: The root entry in the package dependency graph which should contain the top-level dependencies to resolve.
|
||||
:param int depth: The maximum allowed depth for dependency resolution.
|
||||
:return: On success, ``PKGCONF_PKG_ERRF_OK`` (0), else an error code.
|
||||
:rtype: unsigned int
|
||||
|
||||
.. c:function:: unsigned int pkgconf_pkg_traverse(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_pkg_traverse_func_t func, void *data, int maxdepth, unsigned int skip_flags)
|
||||
|
||||
Walk and resolve the dependency graph up to `maxdepth` levels.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_pkg_t* root: The root of the dependency graph.
|
||||
:param pkgconf_pkg_traverse_func_t func: A traversal function to call for each resolved node in the dependency graph.
|
||||
:param void* data: An opaque pointer to data to be passed to the traversal function.
|
||||
:param int maxdepth: The maximum depth to walk the dependency graph for. -1 means infinite recursion.
|
||||
:param uint skip_flags: Skip over dependency nodes containing the specified flags. A setting of 0 skips no dependency nodes.
|
||||
:return: ``PKGCONF_PKG_ERRF_OK`` on success, else an error code.
|
||||
:rtype: unsigned int
|
||||
|
||||
.. c:function:: int pkgconf_pkg_cflags(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth)
|
||||
|
||||
Walks a dependency graph and extracts relevant ``CFLAGS`` fragments.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_pkg_t* root: The root of the dependency graph.
|
||||
:param pkgconf_list_t* list: The fragment list to add the extracted ``CFLAGS`` fragments to.
|
||||
:param int maxdepth: The maximum allowed depth for dependency resolution. -1 means infinite recursion.
|
||||
:return: ``PKGCONF_PKG_ERRF_OK`` if successful, otherwise an error code.
|
||||
:rtype: unsigned int
|
||||
|
||||
.. c:function:: int pkgconf_pkg_libs(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth)
|
||||
|
||||
Walks a dependency graph and extracts relevant ``LIBS`` fragments.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_pkg_t* root: The root of the dependency graph.
|
||||
:param pkgconf_list_t* list: The fragment list to add the extracted ``LIBS`` fragments to.
|
||||
:param int maxdepth: The maximum allowed depth for dependency resolution. -1 means infinite recursion.
|
||||
:return: ``PKGCONF_PKG_ERRF_OK`` if successful, otherwise an error code.
|
||||
:rtype: unsigned int
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
libpkgconf `queue` module
|
||||
=========================
|
||||
|
||||
The `queue` module provides an interface that allows easily building a dependency graph from an
|
||||
arbitrary set of dependencies. It also provides support for doing "preflight" checks on the entire
|
||||
dependency graph prior to working with it.
|
||||
|
||||
Using the `queue` module functions is the recommended way of working with dependency graphs.
|
||||
|
||||
.. c:function:: void pkgconf_queue_push(pkgconf_list_t *list, const char *package)
|
||||
|
||||
Pushes a requested dependency onto the dependency resolver's queue.
|
||||
|
||||
:param pkgconf_list_t* list: the dependency resolution queue to add the package request to.
|
||||
:param char* package: the dependency atom requested
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list)
|
||||
|
||||
Compile a dependency resolution queue into a dependency resolution problem if possible, otherwise report an error.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_pkg_t* world: The designated root of the dependency graph.
|
||||
:param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
:return: true if the built dependency resolution problem is consistent, else false
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: void pkgconf_queue_free(pkgconf_list_t *list)
|
||||
|
||||
Release any memory related to a dependency resolution queue.
|
||||
|
||||
:param pkgconf_list_t* list: The dependency resolution queue to release.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth)
|
||||
|
||||
Removes references to package nodes contained in a solution.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_pkg_t* world: The root for the generated dependency graph. Should have PKGCONF_PKG_PROPF_VIRTUAL flag.
|
||||
:returns: nothing
|
||||
|
||||
.. c:function:: bool pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_t *world, int maxdepth)
|
||||
|
||||
Solves and flattens the dependency graph for the supplied dependency list.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
:param pkgconf_pkg_t* world: The root for the generated dependency graph, provided by the caller. Should have PKGCONF_PKG_PROPF_VIRTUAL flag.
|
||||
:param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
|
||||
:returns: true if the dependency resolver found a solution, otherwise false.
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: void pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
|
||||
|
||||
Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem and
|
||||
feed the solution to a callback function if a complete dependency graph is found.
|
||||
|
||||
This function should not be used in new code. Use pkgconf_queue_solve instead.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
:param pkgconf_queue_apply_func_t func: The callback function to call if a solution is found by the dependency resolver.
|
||||
:param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
|
||||
:param void* data: An opaque pointer which is passed to the callback function.
|
||||
:returns: true if the dependency resolver found a solution, otherwise false.
|
||||
:rtype: bool
|
||||
|
||||
.. c:function:: void pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
|
||||
|
||||
Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
:param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
:param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
|
||||
:returns: true if the dependency resolver found a solution, otherwise false.
|
||||
:rtype: bool
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
libpkgconf `tuple` module
|
||||
=========================
|
||||
|
||||
The `tuple` module provides key-value mappings backed by a linked list. The key-value
|
||||
mapping is mainly used for variable substitution when parsing .pc files.
|
||||
|
||||
There are two sets of mappings: a ``pkgconf_pkg_t`` specific mapping, and a `global` mapping.
|
||||
The `tuple` module provides convenience wrappers for managing the `global` mapping, which is
|
||||
attached to a given client object.
|
||||
|
||||
.. c:function:: void pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value)
|
||||
|
||||
Defines a global variable, replacing the previous declaration if one was set.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to modify.
|
||||
:param char* key: The key for the mapping (variable name).
|
||||
:param char* value: The value for the mapped entry.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key)
|
||||
|
||||
Looks up a global variable.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
:param char* key: The key or variable name to look up.
|
||||
:return: the contents of the variable or ``NULL``
|
||||
:rtype: char *
|
||||
|
||||
.. c:function:: void pkgconf_tuple_free_global(pkgconf_client_t *client)
|
||||
|
||||
Delete all global variables associated with a pkgconf client object.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to modify.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv)
|
||||
|
||||
Parse and define a global variable.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to modify.
|
||||
:param char* kv: The variable in the form of ``key=value``.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key, const char *value, bool parse)
|
||||
|
||||
Optionally parse and then define a variable.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
:param pkgconf_list_t* list: The variable list to add the new variable to.
|
||||
:param char* key: The name of the variable being added.
|
||||
:param char* value: The value of the variable being added.
|
||||
:param bool parse: Whether or not to parse the value for variable substitution.
|
||||
:return: a variable object
|
||||
:rtype: pkgconf_tuple_t *
|
||||
|
||||
.. c:function:: char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key)
|
||||
|
||||
Look up a variable in a variable list.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
:param pkgconf_list_t* list: The variable list to search.
|
||||
:param char* key: The variable name to search for.
|
||||
:return: the value of the variable or ``NULL``
|
||||
:rtype: char *
|
||||
|
||||
.. c:function:: char *pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *vars, const char *value, unsigned int flags)
|
||||
|
||||
Parse an expression for variable substitution.
|
||||
|
||||
:param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
:param pkgconf_list_t* list: The variable list to search for variables (along side the global variable list).
|
||||
:param char* value: The ``key=value`` string to parse.
|
||||
:param uint flags: Any flags to consider while parsing.
|
||||
:return: the variable data with any variables substituted
|
||||
:rtype: char *
|
||||
|
||||
.. c:function:: void pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list)
|
||||
|
||||
Deletes a variable object, removing it from any variable lists and releasing any memory associated
|
||||
with it.
|
||||
|
||||
:param pkgconf_tuple_t* tuple: The variable object to release.
|
||||
:param pkgconf_list_t* list: The variable list the variable object is attached to.
|
||||
:return: nothing
|
||||
|
||||
.. c:function:: void pkgconf_tuple_free(pkgconf_list_t *list)
|
||||
|
||||
Deletes a variable list and any variables attached to it.
|
||||
|
||||
:param pkgconf_list_t* list: The variable list to delete.
|
||||
:return: nothing
|
||||
@@ -0,0 +1,17 @@
|
||||
libpkgconf - an API for managing `pkg-config` modules
|
||||
=====================================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
libpkgconf-argvsplit
|
||||
libpkgconf-audit
|
||||
libpkgconf-cache
|
||||
libpkgconf-client
|
||||
libpkgconf-dependency
|
||||
libpkgconf-fragment
|
||||
libpkgconf-path
|
||||
libpkgconf-personality
|
||||
libpkgconf-pkg
|
||||
libpkgconf-queue
|
||||
libpkgconf-tuple
|
||||
@@ -0,0 +1,12 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=${prefix}
|
||||
includedir=@includedir@
|
||||
libdir=@libdir@
|
||||
|
||||
Name: libpkgconf
|
||||
Description: a library for accessing and manipulating development framework configuration
|
||||
URL: https://gitea.treehouse.systems/ariadne/pkgconf
|
||||
License: ISC
|
||||
Version: @PACKAGE_VERSION@
|
||||
CFlags: -I${includedir}/pkgconf
|
||||
Libs: -L${libdir} -lpkgconf
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* argvsplit.c
|
||||
* argv_split() routine
|
||||
*
|
||||
* Copyright (c) 2012, 2017 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `argvsplit` module
|
||||
* =============================
|
||||
*
|
||||
* This is a lowlevel module which provides parsing of strings into argument vectors,
|
||||
* similar to what a shell would do.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_argv_free(char **argv)
|
||||
*
|
||||
* Frees an argument vector.
|
||||
*
|
||||
* :param char** argv: The argument vector to free.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_argv_free(char **argv)
|
||||
{
|
||||
free(argv[0]);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: int pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||
*
|
||||
* Splits a string into an argument vector.
|
||||
*
|
||||
* :param char* src: The string to split.
|
||||
* :param int* argc: A pointer to an integer to store the argument count.
|
||||
* :param char*** argv: A pointer to a pointer for an argument vector.
|
||||
* :return: 0 on success, -1 on error.
|
||||
* :rtype: int
|
||||
*/
|
||||
int
|
||||
pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||
{
|
||||
char *buf = calloc(1, strlen(src) + 1);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
const char *src_iter;
|
||||
char *dst_iter;
|
||||
int argc_count = 0;
|
||||
int argv_size = 5;
|
||||
char quote = 0;
|
||||
bool escaped = false;
|
||||
|
||||
src_iter = src;
|
||||
dst_iter = buf;
|
||||
|
||||
*argv = calloc(argv_size, sizeof (void *));
|
||||
if (*argv == NULL)
|
||||
{
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*argv)[argc_count] = dst_iter;
|
||||
|
||||
while (*src_iter)
|
||||
{
|
||||
if (escaped)
|
||||
{
|
||||
/* POSIX: only \CHAR is special inside a double quote if CHAR is {$, `, ", \, newline}. */
|
||||
if (quote == '"')
|
||||
{
|
||||
if (!(*src_iter == '$' || *src_iter == '`' || *src_iter == '"' || *src_iter == '\\'))
|
||||
*dst_iter++ = '\\';
|
||||
|
||||
*dst_iter++ = *src_iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst_iter++ = *src_iter;
|
||||
}
|
||||
|
||||
escaped = false;
|
||||
}
|
||||
else if (quote)
|
||||
{
|
||||
if (*src_iter == quote)
|
||||
quote = 0;
|
||||
else if (*src_iter == '\\' && quote != '\'')
|
||||
escaped = true;
|
||||
else
|
||||
*dst_iter++ = *src_iter;
|
||||
}
|
||||
else if (isspace((unsigned char)*src_iter))
|
||||
{
|
||||
if ((*argv)[argc_count] != NULL)
|
||||
{
|
||||
argc_count++, dst_iter++;
|
||||
|
||||
if (argc_count == argv_size)
|
||||
{
|
||||
argv_size += 5;
|
||||
*argv = realloc(*argv, sizeof(void *) * argv_size);
|
||||
}
|
||||
|
||||
(*argv)[argc_count] = dst_iter;
|
||||
}
|
||||
}
|
||||
else switch(*src_iter)
|
||||
{
|
||||
case '\\':
|
||||
escaped = true;
|
||||
break;
|
||||
|
||||
case '\"':
|
||||
case '\'':
|
||||
quote = *src_iter;
|
||||
break;
|
||||
|
||||
default:
|
||||
*dst_iter++ = *src_iter;
|
||||
break;
|
||||
}
|
||||
|
||||
src_iter++;
|
||||
}
|
||||
|
||||
if (escaped || quote)
|
||||
{
|
||||
free(*argv);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen((*argv)[argc_count]))
|
||||
{
|
||||
argc_count++;
|
||||
}
|
||||
|
||||
*argc = argc_count;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* audit.c
|
||||
* package audit log functions
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `audit` module
|
||||
* =========================
|
||||
*
|
||||
* The libpkgconf `audit` module contains the functions related to attaching an audit log file
|
||||
* to a ``pkgconf_client_t`` object.
|
||||
*
|
||||
* The audit log format is the same as the output generated by the ``PKG_CONFIG_LOG`` environment
|
||||
* variable.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_audit_set_log(pkgconf_client_t *client, FILE *auditf)
|
||||
*
|
||||
* Sets the audit log file pointer on `client` to `auditf`.
|
||||
* The callee is responsible for closing any previous log files.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to modify.
|
||||
* :param FILE* auditf: The file pointer for the already open log file.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_audit_set_log(pkgconf_client_t *client, FILE *auditf)
|
||||
{
|
||||
client->auditf = auditf;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_audit_log(pkgconf_client_t *client, const char *format, ...)
|
||||
*
|
||||
* Logs a message to the opened audit log (if any).
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object the log message is for.
|
||||
* :param char* format: The format string to use for the log messages.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_audit_log(pkgconf_client_t *client, const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
if (client->auditf == NULL)
|
||||
return;
|
||||
|
||||
va_start(va, format);
|
||||
vfprintf(client->auditf, format, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pkgconf_pkg_t *dep, const pkgconf_dependency_t *depnode)
|
||||
*
|
||||
* Convenience function which logs a dependency node to the opened audit log (if any).
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object the log message is for.
|
||||
* :param pkgconf_pkg_t* dep: The dependency package object being logged.
|
||||
* :param pkgconf_dependency_t* depnode: The dependency object itself being logged.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_audit_log_dependency(pkgconf_client_t *client, const pkgconf_pkg_t *dep, const pkgconf_dependency_t *depnode)
|
||||
{
|
||||
if (client->auditf == NULL)
|
||||
return;
|
||||
|
||||
fprintf(client->auditf, "%s ", dep->id);
|
||||
if (depnode->version != NULL && depnode->compare != PKGCONF_CMP_ANY)
|
||||
{
|
||||
fprintf(client->auditf, "%s %s ", pkgconf_pkg_get_comparator(depnode), depnode->version);
|
||||
}
|
||||
|
||||
fprintf(client->auditf, "[%s]\n", dep->version);
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
|
||||
/* $OpenBSD: strlcat.c,v 1.12 2005/03/30 20:13:52 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <libpkgconf/bsdstubs.h>
|
||||
#include <libpkgconf/config.h>
|
||||
|
||||
#if !HAVE_DECL_STRLCPY
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
static inline size_t
|
||||
strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0) {
|
||||
while (--n != 0) {
|
||||
if ((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_STRLCAT
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
static inline size_t
|
||||
strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !HAVE_DECL_STRNDUP
|
||||
/*
|
||||
* Creates a memory buffer and copies at most 'len' characters to it.
|
||||
* If 'len' is less than the length of the source string, truncation occured.
|
||||
*/
|
||||
static inline char *
|
||||
strndup(const char *src, size_t len)
|
||||
{
|
||||
char *out = malloc(len + 1);
|
||||
pkgconf_strlcpy(out, src, len + 1);
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_PLEDGE
|
||||
static inline int
|
||||
pledge(const char *promises, const char *execpromises)
|
||||
{
|
||||
(void) promises;
|
||||
(void) execpromises;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_UNVEIL
|
||||
static inline int
|
||||
unveil(const char *path, const char *permissions)
|
||||
{
|
||||
(void) path;
|
||||
(void) permissions;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t
|
||||
pkgconf_strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
return strlcpy(dst, src, siz);
|
||||
}
|
||||
|
||||
size_t
|
||||
pkgconf_strlcat(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
return strlcat(dst, src, siz);
|
||||
}
|
||||
|
||||
char *
|
||||
pkgconf_strndup(const char *src, size_t len)
|
||||
{
|
||||
return strndup(src, len);
|
||||
}
|
||||
|
||||
#if !HAVE_DECL_REALLOCARRAY
|
||||
void *
|
||||
reallocarray(void *ptr, size_t m, size_t n)
|
||||
{
|
||||
if (n && m > -1 / n)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return realloc(ptr, m * n);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *
|
||||
pkgconf_reallocarray(void *ptr, size_t m, size_t n)
|
||||
{
|
||||
return reallocarray(ptr, m, n);
|
||||
}
|
||||
|
||||
int
|
||||
pkgconf_pledge(const char *promises, const char *execpromises)
|
||||
{
|
||||
return pledge(promises, execpromises);
|
||||
}
|
||||
|
||||
int
|
||||
pkgconf_unveil(const char *path, const char *permissions)
|
||||
{
|
||||
return unveil(path, permissions);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* bsdstubs.h
|
||||
* Header for stub BSD function prototypes if unavailable on a specific platform.
|
||||
*
|
||||
* Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LIBPKGCONF_BSDSTUBS_H
|
||||
#define LIBPKGCONF_BSDSTUBS_H
|
||||
|
||||
#include <libpkgconf/libpkgconf-api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
PKGCONF_API extern size_t pkgconf_strlcpy(char *dst, const char *src, size_t siz);
|
||||
PKGCONF_API extern size_t pkgconf_strlcat(char *dst, const char *src, size_t siz);
|
||||
PKGCONF_API extern char *pkgconf_strndup(const char *src, size_t len);
|
||||
PKGCONF_API extern void *pkgconf_reallocarray(void *ptr, size_t m, size_t n);
|
||||
PKGCONF_API extern int pkgconf_pledge(const char *promises, const char *execpromises);
|
||||
PKGCONF_API extern int pkgconf_unveil(const char *path, const char *permissions);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* buffer.c
|
||||
* dynamically-managed buffers
|
||||
*
|
||||
* Copyright (c) 2024 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `buffer` module
|
||||
* ==========================
|
||||
*
|
||||
* The libpkgconf `buffer` module contains the functions related to managing
|
||||
* dynamically-allocated buffers.
|
||||
*/
|
||||
|
||||
static inline size_t
|
||||
target_allocation_size(size_t target_size)
|
||||
{
|
||||
return 4096 + (4096 * (target_size / 4096));
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_append(pkgconf_buffer_t *buffer, const char *text)
|
||||
{
|
||||
size_t needed = strlen(text) + 1;
|
||||
size_t newsize = pkgconf_buffer_len(buffer) + needed;
|
||||
|
||||
char *newbase = realloc(buffer->base, target_allocation_size(newsize));
|
||||
|
||||
/* XXX: silently failing here is antisocial */
|
||||
if (newbase == NULL)
|
||||
return;
|
||||
|
||||
char *newend = newbase + pkgconf_buffer_len(buffer);
|
||||
pkgconf_strlcpy(newend, text, needed);
|
||||
|
||||
buffer->base = newbase;
|
||||
buffer->end = newend + needed;
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_push_byte(pkgconf_buffer_t *buffer, char byte)
|
||||
{
|
||||
size_t newsize = pkgconf_buffer_len(buffer) + 1;
|
||||
char *newbase = realloc(buffer->base, target_allocation_size(newsize));
|
||||
|
||||
/* XXX: silently failing here remains antisocial */
|
||||
if (newbase == NULL)
|
||||
return;
|
||||
|
||||
char *newend = newbase + newsize;
|
||||
*(newend - 1) = byte;
|
||||
*newend = '\0';
|
||||
|
||||
buffer->base = newbase;
|
||||
buffer->end = newend;
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_trim_byte(pkgconf_buffer_t *buffer)
|
||||
{
|
||||
size_t newsize = pkgconf_buffer_len(buffer) - 1;
|
||||
char *newbase = realloc(buffer->base, target_allocation_size(newsize));
|
||||
|
||||
buffer->base = newbase;
|
||||
buffer->end = newbase + newsize;
|
||||
*(buffer->end) = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_finalize(pkgconf_buffer_t *buffer)
|
||||
{
|
||||
free(buffer->base);
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* cache.c
|
||||
* package object cache
|
||||
*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `cache` module
|
||||
* =========================
|
||||
*
|
||||
* The libpkgconf `cache` module manages a package/module object cache, allowing it to
|
||||
* avoid loading duplicate copies of a package/module.
|
||||
*
|
||||
* A cache is tied to a specific pkgconf client object, so package objects should not
|
||||
* be shared across threads.
|
||||
*/
|
||||
|
||||
static int
|
||||
cache_member_cmp(const void *a, const void *b)
|
||||
{
|
||||
const char *key = a;
|
||||
const pkgconf_pkg_t *pkg = *(void **) b;
|
||||
|
||||
return strcmp(key, pkg->id);
|
||||
}
|
||||
|
||||
static int
|
||||
cache_member_sort_cmp(const void *a, const void *b)
|
||||
{
|
||||
const pkgconf_pkg_t *pkgA = *(void **) a;
|
||||
const pkgconf_pkg_t *pkgB = *(void **) b;
|
||||
|
||||
if (pkgA == NULL)
|
||||
return 1;
|
||||
|
||||
if (pkgB == NULL)
|
||||
return -1;
|
||||
|
||||
return strcmp(pkgA->id, pkgB->id);
|
||||
}
|
||||
|
||||
static void
|
||||
cache_dump(const pkgconf_client_t *client)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
PKGCONF_TRACE(client, "dumping package cache contents");
|
||||
|
||||
for (i = 0; i < client->cache_count; i++)
|
||||
{
|
||||
const pkgconf_pkg_t *pkg = client->cache_table[i];
|
||||
|
||||
PKGCONF_TRACE(client, SIZE_FMT_SPECIFIER": %p(%s)",
|
||||
i, pkg, pkg == NULL ? "NULL" : pkg->id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_pkg_t *pkgconf_cache_lookup(const pkgconf_client_t *client, const char *id)
|
||||
*
|
||||
* Looks up a package in the cache given an `id` atom,
|
||||
* such as ``gtk+-3.0`` and returns the already loaded version
|
||||
* if present.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to access.
|
||||
* :param char* id: The package atom to look up in the client object's cache.
|
||||
* :return: A package object if present, else ``NULL``.
|
||||
* :rtype: pkgconf_pkg_t *
|
||||
*/
|
||||
pkgconf_pkg_t *
|
||||
pkgconf_cache_lookup(pkgconf_client_t *client, const char *id)
|
||||
{
|
||||
if (client->cache_table == NULL)
|
||||
return NULL;
|
||||
|
||||
pkgconf_pkg_t **pkg;
|
||||
|
||||
pkg = bsearch(id, client->cache_table,
|
||||
client->cache_count, sizeof (void *),
|
||||
cache_member_cmp);
|
||||
|
||||
if (pkg != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "found: %s @%p", id, *pkg);
|
||||
return pkgconf_pkg_ref(client, *pkg);
|
||||
}
|
||||
|
||||
PKGCONF_TRACE(client, "miss: %s", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
*
|
||||
* Adds an entry for the package to the package cache.
|
||||
* The cache entry must be removed if the package is freed.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to modify.
|
||||
* :param pkgconf_pkg_t* pkg: The package object to add to the client object's cache.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
{
|
||||
if (pkg == NULL)
|
||||
return;
|
||||
|
||||
pkgconf_pkg_ref(client, pkg);
|
||||
|
||||
PKGCONF_TRACE(client, "added @%p to cache", pkg);
|
||||
|
||||
/* mark package as cached */
|
||||
pkg->flags |= PKGCONF_PKG_PROPF_CACHED;
|
||||
|
||||
++client->cache_count;
|
||||
client->cache_table = pkgconf_reallocarray(client->cache_table,
|
||||
client->cache_count, sizeof (void *));
|
||||
client->cache_table[client->cache_count - 1] = pkg;
|
||||
|
||||
qsort(client->cache_table, client->cache_count,
|
||||
sizeof(void *), cache_member_sort_cmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
*
|
||||
* Deletes a package from the client object's package cache.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to modify.
|
||||
* :param pkgconf_pkg_t* pkg: The package object to remove from the client object's cache.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
{
|
||||
if (client->cache_table == NULL)
|
||||
return;
|
||||
|
||||
if (pkg == NULL)
|
||||
return;
|
||||
|
||||
if (!(pkg->flags & PKGCONF_PKG_PROPF_CACHED))
|
||||
return;
|
||||
|
||||
PKGCONF_TRACE(client, "removed @%p from cache", pkg);
|
||||
|
||||
pkgconf_pkg_t **slot;
|
||||
|
||||
slot = bsearch(pkg->id, client->cache_table,
|
||||
client->cache_count, sizeof (void *),
|
||||
cache_member_cmp);
|
||||
|
||||
if (slot == NULL)
|
||||
return;
|
||||
|
||||
(*slot)->flags &= ~PKGCONF_PKG_PROPF_CACHED;
|
||||
pkgconf_pkg_unref(client, *slot);
|
||||
*slot = NULL;
|
||||
|
||||
qsort(client->cache_table, client->cache_count,
|
||||
sizeof(void *), cache_member_sort_cmp);
|
||||
|
||||
if (client->cache_table[client->cache_count - 1] != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "end of cache table refers to %p, not NULL",
|
||||
client->cache_table[client->cache_count - 1]);
|
||||
cache_dump(client);
|
||||
abort();
|
||||
}
|
||||
|
||||
client->cache_count--;
|
||||
if (client->cache_count > 0)
|
||||
{
|
||||
client->cache_table = pkgconf_reallocarray(client->cache_table,
|
||||
client->cache_count, sizeof(void *));
|
||||
}
|
||||
else
|
||||
{
|
||||
free(client->cache_table);
|
||||
client->cache_table = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_cache_free(pkgconf_client_t *client)
|
||||
*
|
||||
* Releases all resources related to a client object's package cache.
|
||||
* This function should only be called to clear a client object's package cache,
|
||||
* as it may release any package in the cache.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to modify.
|
||||
*/
|
||||
void
|
||||
pkgconf_cache_free(pkgconf_client_t *client)
|
||||
{
|
||||
if (client->cache_table == NULL)
|
||||
return;
|
||||
|
||||
while (client->cache_count > 0)
|
||||
pkgconf_cache_remove(client, client->cache_table[0]);
|
||||
|
||||
free(client->cache_table);
|
||||
client->cache_table = NULL;
|
||||
client->cache_count = 0;
|
||||
|
||||
PKGCONF_TRACE(client, "cleared package cache");
|
||||
}
|
||||
@@ -0,0 +1,817 @@
|
||||
/*
|
||||
* client.c
|
||||
* libpkgconf consumer lifecycle management
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/config.h>
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `client` module
|
||||
* ==========================
|
||||
*
|
||||
* The libpkgconf `client` module implements the `pkgconf_client_t` "client" object.
|
||||
* Client objects store all necessary state for libpkgconf allowing for multiple instances to run
|
||||
* in parallel.
|
||||
*
|
||||
* Client objects are not thread safe, in other words, a client object should not be shared across
|
||||
* thread boundaries.
|
||||
*/
|
||||
|
||||
static void
|
||||
trace_path_list(const pkgconf_client_t *client, const char *desc, pkgconf_list_t *list)
|
||||
{
|
||||
const pkgconf_node_t *n;
|
||||
|
||||
PKGCONF_TRACE(client, "%s:", desc);
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, n)
|
||||
{
|
||||
const pkgconf_path_t *p = n->data;
|
||||
|
||||
PKGCONF_TRACE(client, " - '%s'", p->path);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_dir_list_build(pkgconf_client_t *client)
|
||||
*
|
||||
* Bootstraps the package search paths. If the ``PKGCONF_PKG_PKGF_ENV_ONLY`` `flag` is set on the client,
|
||||
* then only the ``PKG_CONFIG_PATH`` environment variable will be used, otherwise both the
|
||||
* ``PKG_CONFIG_PATH`` and ``PKG_CONFIG_LIBDIR`` environment variables will be used.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to bootstrap.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality)
|
||||
{
|
||||
pkgconf_path_build_from_environ("PKG_CONFIG_PATH", NULL, &client->dir_list, true);
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_ENV_ONLY))
|
||||
{
|
||||
pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER;
|
||||
const pkgconf_list_t *prepend_list = &personality->dir_list;
|
||||
|
||||
#ifdef _WIN32
|
||||
(void) pkgconf_path_build_from_registry(HKEY_CURRENT_USER, &client->dir_list, true);
|
||||
(void) pkgconf_path_build_from_registry(HKEY_LOCAL_MACHINE, &client->dir_list, true);
|
||||
#endif
|
||||
|
||||
if (getenv("PKG_CONFIG_LIBDIR") != NULL)
|
||||
{
|
||||
/* PKG_CONFIG_LIBDIR= should empty the search path entirely. */
|
||||
(void) pkgconf_path_build_from_environ("PKG_CONFIG_LIBDIR", NULL, &dir_list, true);
|
||||
prepend_list = &dir_list;
|
||||
}
|
||||
|
||||
pkgconf_path_copy_list(&client->dir_list, prepend_list);
|
||||
pkgconf_path_free(&dir_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
*
|
||||
* Initialise a pkgconf client object.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client to initialise.
|
||||
* :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
|
||||
* :param void* error_handler_data: user data passed to optional error handler
|
||||
* :param pkgconf_cross_personality_t* personality: the cross-compile personality to use for defaults
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
{
|
||||
client->error_handler_data = error_handler_data;
|
||||
client->error_handler = error_handler;
|
||||
client->auditf = NULL;
|
||||
client->cache_table = NULL;
|
||||
client->cache_count = 0;
|
||||
|
||||
#ifndef PKGCONF_LITE
|
||||
if (client->trace_handler == NULL)
|
||||
pkgconf_client_set_trace_handler(client, NULL, NULL);
|
||||
#endif
|
||||
|
||||
if (client->unveil_handler == NULL)
|
||||
pkgconf_client_set_unveil_handler(client, NULL);
|
||||
|
||||
pkgconf_client_set_error_handler(client, error_handler, error_handler_data);
|
||||
pkgconf_client_set_warn_handler(client, NULL, NULL);
|
||||
|
||||
pkgconf_client_set_sysroot_dir(client, personality->sysroot_dir);
|
||||
pkgconf_client_set_buildroot_dir(client, NULL);
|
||||
pkgconf_client_set_prefix_varname(client, NULL);
|
||||
|
||||
if(getenv("PKG_CONFIG_SYSTEM_LIBRARY_PATH") == NULL)
|
||||
pkgconf_path_copy_list(&client->filter_libdirs, &personality->filter_libdirs);
|
||||
else
|
||||
pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_LIBRARY_PATH", NULL, &client->filter_libdirs, false);
|
||||
|
||||
if(getenv("PKG_CONFIG_SYSTEM_INCLUDE_PATH") == NULL)
|
||||
pkgconf_path_copy_list(&client->filter_includedirs, &personality->filter_includedirs);
|
||||
else
|
||||
pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
|
||||
/* GCC uses these environment variables to define system include paths, so we should check them. */
|
||||
#ifdef __HAIKU__
|
||||
pkgconf_path_build_from_environ("BELIBRARIES", NULL, &client->filter_libdirs, false);
|
||||
#else
|
||||
pkgconf_path_build_from_environ("LIBRARY_PATH", NULL, &client->filter_libdirs, false);
|
||||
#endif
|
||||
pkgconf_path_build_from_environ("CPATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ("C_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ("CPLUS_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ("OBJC_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* also use the path lists that MSVC uses on windows */
|
||||
pkgconf_path_build_from_environ("INCLUDE", NULL, &client->filter_includedirs, false);
|
||||
#endif
|
||||
|
||||
PKGCONF_TRACE(client, "initialized client @%p", client);
|
||||
|
||||
trace_path_list(client, "filtered library paths", &client->filter_libdirs);
|
||||
trace_path_list(client, "filtered include paths", &client->filter_includedirs);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_t* pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
*
|
||||
* Allocate and initialise a pkgconf client object.
|
||||
*
|
||||
* :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
|
||||
* :param void* error_handler_data: user data passed to optional error handler
|
||||
* :param pkgconf_cross_personality_t* personality: cross-compile personality to use
|
||||
* :return: A pkgconf client object.
|
||||
* :rtype: 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_t *out = calloc(1, sizeof(pkgconf_client_t));
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
pkgconf_client_init(out, error_handler, error_handler_data, personality);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void
|
||||
unref_preload_list(pkgconf_client_t *client)
|
||||
{
|
||||
pkgconf_node_t *n, *tn;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(client->preloaded_pkgs.head, n, tn)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = n->data;
|
||||
pkgconf_pkg_unref(client, pkg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_deinit(pkgconf_client_t *client)
|
||||
*
|
||||
* Release resources belonging to a pkgconf client object.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client to deinitialise.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_deinit(pkgconf_client_t *client)
|
||||
{
|
||||
PKGCONF_TRACE(client, "deinit @%p", client);
|
||||
|
||||
unref_preload_list(client);
|
||||
|
||||
if (client->prefix_varname != NULL)
|
||||
free(client->prefix_varname);
|
||||
|
||||
if (client->sysroot_dir != NULL)
|
||||
free(client->sysroot_dir);
|
||||
|
||||
if (client->buildroot_dir != NULL)
|
||||
free(client->buildroot_dir);
|
||||
|
||||
pkgconf_path_free(&client->filter_libdirs);
|
||||
pkgconf_path_free(&client->filter_includedirs);
|
||||
|
||||
pkgconf_tuple_free_global(client);
|
||||
pkgconf_path_free(&client->dir_list);
|
||||
pkgconf_cache_free(client);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_free(pkgconf_client_t *client)
|
||||
*
|
||||
* Release resources belonging to a pkgconf client object and then free the client object itself.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client to deinitialise and free.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_free(pkgconf_client_t *client)
|
||||
{
|
||||
pkgconf_client_deinit(client);
|
||||
free(client);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const char *pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client)
|
||||
*
|
||||
* Retrieves the client's sysroot directory (if any).
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object being accessed.
|
||||
* :return: A string containing the sysroot directory or NULL.
|
||||
* :rtype: const char *
|
||||
*/
|
||||
const char *
|
||||
pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->sysroot_dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir)
|
||||
*
|
||||
* Sets or clears the sysroot directory on a client object. Any previous sysroot directory setting is
|
||||
* automatically released if one was previously set.
|
||||
*
|
||||
* Additionally, the global tuple ``$(pc_sysrootdir)`` is set as appropriate based on the new setting.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object being modified.
|
||||
* :param char* sysroot_dir: The sysroot directory to set or NULL to unset.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir)
|
||||
{
|
||||
if (client->sysroot_dir != NULL)
|
||||
free(client->sysroot_dir);
|
||||
|
||||
client->sysroot_dir = sysroot_dir != NULL ? strdup(sysroot_dir) : NULL;
|
||||
|
||||
PKGCONF_TRACE(client, "set sysroot_dir to: %s", client->sysroot_dir != NULL ? client->sysroot_dir : "<default>");
|
||||
|
||||
pkgconf_tuple_add_global(client, "pc_sysrootdir", client->sysroot_dir != NULL ? client->sysroot_dir : "/");
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const char *pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client)
|
||||
*
|
||||
* Retrieves the client's buildroot directory (if any).
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object being accessed.
|
||||
* :return: A string containing the buildroot directory or NULL.
|
||||
* :rtype: const char *
|
||||
*/
|
||||
const char *
|
||||
pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->buildroot_dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir)
|
||||
*
|
||||
* Sets or clears the buildroot directory on a client object. Any previous buildroot directory setting is
|
||||
* automatically released if one was previously set.
|
||||
*
|
||||
* Additionally, the global tuple ``$(pc_top_builddir)`` is set as appropriate based on the new setting.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object being modified.
|
||||
* :param char* buildroot_dir: The buildroot directory to set or NULL to unset.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir)
|
||||
{
|
||||
if (client->buildroot_dir != NULL)
|
||||
free(client->buildroot_dir);
|
||||
|
||||
client->buildroot_dir = buildroot_dir != NULL ? strdup(buildroot_dir) : NULL;
|
||||
|
||||
PKGCONF_TRACE(client, "set buildroot_dir to: %s", client->buildroot_dir != NULL ? client->buildroot_dir : "<default>");
|
||||
|
||||
pkgconf_tuple_add_global(client, "pc_top_builddir", client->buildroot_dir != NULL ? client->buildroot_dir : "$(top_builddir)");
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_error(const pkgconf_client_t *client, const char *format, ...)
|
||||
*
|
||||
* Report an error to a client-registered error handler.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to report the error to.
|
||||
* :param char* format: A printf-style format string to use for formatting the error message.
|
||||
* :return: true if the error handler processed the message, else false.
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_error(const pkgconf_client_t *client, const char *format, ...)
|
||||
{
|
||||
char *errbuf;
|
||||
ssize_t msgsize = 0;
|
||||
bool ret;
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
msgsize = vsnprintf(NULL, 0, format, va);
|
||||
va_end(va);
|
||||
|
||||
if (msgsize < 0)
|
||||
return false;
|
||||
|
||||
msgsize++;
|
||||
|
||||
errbuf = calloc(1, msgsize);
|
||||
if (errbuf == NULL)
|
||||
return false;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, msgsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
ret = client->error_handler(errbuf, client, client->error_handler_data);
|
||||
free(errbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_warn(const pkgconf_client_t *client, const char *format, ...)
|
||||
*
|
||||
* Report an error to a client-registered warn handler.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to report the error to.
|
||||
* :param char* format: A printf-style format string to use for formatting the warning message.
|
||||
* :return: true if the warn handler processed the message, else false.
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_warn(const pkgconf_client_t *client, const char *format, ...)
|
||||
{
|
||||
char *errbuf;
|
||||
ssize_t msgsize = 0;
|
||||
bool ret;
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
msgsize = vsnprintf(NULL, 0, format, va);
|
||||
va_end(va);
|
||||
|
||||
if (msgsize < 0)
|
||||
return false;
|
||||
|
||||
msgsize++;
|
||||
|
||||
errbuf = calloc(1, msgsize);
|
||||
if (errbuf == NULL)
|
||||
return false;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, msgsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
ret = client->warn_handler(errbuf, client, client->warn_handler_data);
|
||||
free(errbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t len, const char *funcname, const char *format, ...)
|
||||
*
|
||||
* Report a message to a client-registered trace handler.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to report the trace message to.
|
||||
* :param char* filename: The file the function is in.
|
||||
* :param size_t lineno: The line number currently being executed.
|
||||
* :param char* funcname: The function name to use.
|
||||
* :param char* format: A printf-style format string to use for formatting the trace message.
|
||||
* :return: true if the trace handler processed the message, else false.
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t lineno, const char *funcname, const char *format, ...)
|
||||
{
|
||||
char prefix[PKGCONF_ITEM_SIZE];
|
||||
char *errbuf = NULL;
|
||||
ssize_t errlen;
|
||||
char *finalbuf = NULL;
|
||||
ssize_t finallen;
|
||||
bool ret;
|
||||
va_list va;
|
||||
|
||||
if (client == NULL || client->trace_handler == NULL)
|
||||
return false;
|
||||
|
||||
snprintf(prefix, sizeof prefix, "%s:" SIZE_FMT_SPECIFIER " [%s]:", filename, lineno, funcname);
|
||||
|
||||
va_start(va, format);
|
||||
errlen = vsnprintf(NULL, 0, format, va);
|
||||
va_end(va);
|
||||
|
||||
if (errlen < 0)
|
||||
return false;
|
||||
|
||||
errlen++;
|
||||
errbuf = calloc(1, errlen);
|
||||
if (errbuf == NULL)
|
||||
return false;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, errlen, format, va);
|
||||
va_end(va);
|
||||
|
||||
finallen = snprintf(NULL, 0, "%s %s\n", prefix, errbuf);
|
||||
if (finallen < 0)
|
||||
return false;
|
||||
|
||||
finallen++;
|
||||
finalbuf = calloc(1, finallen);
|
||||
if (finalbuf == NULL)
|
||||
return false;
|
||||
|
||||
snprintf(finalbuf, finallen, "%s %s\n", prefix, errbuf);
|
||||
ret = client->trace_handler(finalbuf, client, client->trace_handler_data);
|
||||
free(errbuf);
|
||||
free(finalbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, const void *data)
|
||||
*
|
||||
* The default pkgconf error handler.
|
||||
*
|
||||
* :param char* msg: The error message to handle.
|
||||
* :param pkgconf_client_t* client: The client object the error originated from.
|
||||
* :param void* data: An opaque pointer to extra data associated with the client for error handling.
|
||||
* :return: true (the function does nothing to process the message)
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, void *data)
|
||||
{
|
||||
(void) msg;
|
||||
(void) client;
|
||||
(void) data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
default_unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions)
|
||||
{
|
||||
(void) client;
|
||||
(void) path;
|
||||
(void) permissions;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: unsigned int pkgconf_client_get_flags(const pkgconf_client_t *client)
|
||||
*
|
||||
* Retrieves resolver-specific flags associated with a client object.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to retrieve the resolver-specific flags from.
|
||||
* :return: a bitfield of resolver-specific flags
|
||||
* :rtype: uint
|
||||
*/
|
||||
unsigned int
|
||||
pkgconf_client_get_flags(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags)
|
||||
*
|
||||
* Sets resolver-specific flags associated with a client object.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the resolver-specific flags on.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags)
|
||||
{
|
||||
client->flags = flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const char *pkgconf_client_get_prefix_varname(const pkgconf_client_t *client)
|
||||
*
|
||||
* Retrieves the name of the variable that should contain a module's prefix.
|
||||
* In some cases, it is necessary to override this variable to allow proper path relocation.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to retrieve the prefix variable name from.
|
||||
* :return: the prefix variable name as a string
|
||||
* :rtype: const char *
|
||||
*/
|
||||
const char *
|
||||
pkgconf_client_get_prefix_varname(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->prefix_varname;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname)
|
||||
*
|
||||
* Sets the name of the variable that should contain a module's prefix.
|
||||
* If the variable name is ``NULL``, then the default variable name (``prefix``) is used.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the prefix variable name on.
|
||||
* :param char* prefix_varname: The prefix variable name to set.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname)
|
||||
{
|
||||
if (prefix_varname == NULL)
|
||||
prefix_varname = "prefix";
|
||||
|
||||
if (client->prefix_varname != NULL)
|
||||
free(client->prefix_varname);
|
||||
|
||||
client->prefix_varname = strdup(prefix_varname);
|
||||
|
||||
PKGCONF_TRACE(client, "set prefix_varname to: %s", client->prefix_varname);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_get_warn_handler(const pkgconf_client_t *client)
|
||||
*
|
||||
* Returns the warning handler if one is set, else ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to get the warn handler from.
|
||||
* :return: a function pointer to the warn handler or ``NULL``
|
||||
*/
|
||||
pkgconf_error_handler_func_t
|
||||
pkgconf_client_get_warn_handler(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->warn_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data)
|
||||
*
|
||||
* Sets a warn handler on a client object or uninstalls one if set to ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the warn handler on.
|
||||
* :param pkgconf_error_handler_func_t warn_handler: The warn handler to set.
|
||||
* :param void* warn_handler_data: Optional data to associate with the warn handler.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data)
|
||||
{
|
||||
client->warn_handler = warn_handler;
|
||||
client->warn_handler_data = warn_handler_data;
|
||||
|
||||
if (client->warn_handler == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "installing default warn handler");
|
||||
client->warn_handler = pkgconf_default_error_handler;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_get_error_handler(const pkgconf_client_t *client)
|
||||
*
|
||||
* Returns the error handler if one is set, else ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to get the error handler from.
|
||||
* :return: a function pointer to the error handler or ``NULL``
|
||||
*/
|
||||
pkgconf_error_handler_func_t
|
||||
pkgconf_client_get_error_handler(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->error_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data)
|
||||
*
|
||||
* Sets a warn handler on a client object or uninstalls one if set to ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the error handler on.
|
||||
* :param pkgconf_error_handler_func_t error_handler: The error handler to set.
|
||||
* :param void* error_handler_data: Optional data to associate with the error handler.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data)
|
||||
{
|
||||
client->error_handler = error_handler;
|
||||
client->error_handler_data = error_handler_data;
|
||||
|
||||
if (client->error_handler == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "installing default error handler");
|
||||
client->error_handler = pkgconf_default_error_handler;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_get_unveil_handler(const pkgconf_client_t *client)
|
||||
*
|
||||
* Returns the unveil handler if one is set, else ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to get the unveil handler from.
|
||||
* :return: a function pointer to the error handler or ``NULL``
|
||||
*/
|
||||
pkgconf_unveil_handler_func_t
|
||||
pkgconf_client_get_unveil_handler(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->unveil_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler)
|
||||
*
|
||||
* Sets an unveil handler on a client object or uninstalls one if set to ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the error handler on.
|
||||
* :param pkgconf_unveil_handler_func_t unveil_handler: The unveil handler to set.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler)
|
||||
{
|
||||
client->unveil_handler = unveil_handler;
|
||||
|
||||
if (client->unveil_handler == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "installing default unveil handler");
|
||||
client->unveil_handler = default_unveil_handler;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PKGCONF_LITE
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_get_trace_handler(const pkgconf_client_t *client)
|
||||
*
|
||||
* Returns the error handler if one is set, else ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to get the error handler from.
|
||||
* :return: a function pointer to the error handler or ``NULL``
|
||||
*/
|
||||
pkgconf_error_handler_func_t
|
||||
pkgconf_client_get_trace_handler(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->trace_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data)
|
||||
*
|
||||
* Sets a warn handler on a client object or uninstalls one if set to ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the error handler on.
|
||||
* :param pkgconf_error_handler_func_t trace_handler: The error handler to set.
|
||||
* :param void* trace_handler_data: Optional data to associate with the error handler.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data)
|
||||
{
|
||||
client->trace_handler = trace_handler;
|
||||
client->trace_handler_data = trace_handler_data;
|
||||
|
||||
if (client->trace_handler == NULL)
|
||||
{
|
||||
client->trace_handler = pkgconf_default_error_handler;
|
||||
PKGCONF_TRACE(client, "installing default trace handler");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_client_preload_path(pkgconf_client_t *client, const char *path)
|
||||
*
|
||||
* Loads a pkg-config file into the preloaded packages set.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object for preloading.
|
||||
* :param char* path: The path to the pkg-config file to preload.
|
||||
* :return: true on success, false on error
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_client_preload_path(pkgconf_client_t *client, const char *path)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = pkgconf_pkg_new_from_path(client, path, PKGCONF_PKG_PROPF_PRELOADED);
|
||||
if (pkg == NULL)
|
||||
return false;
|
||||
|
||||
pkgconf_pkg_ref(client, pkg);
|
||||
pkgconf_node_insert_tail(&pkg->preload_node, pkg, &client->preloaded_pkgs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env)
|
||||
*
|
||||
* Loads zero or more pkg-config files specified in the given environmental
|
||||
* variable.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object for preloading.
|
||||
* :param char* environ: The environment variable to use for preloading.
|
||||
* :return: true on success, false on error
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env)
|
||||
{
|
||||
const char *data;
|
||||
pkgconf_list_t pathlist = PKGCONF_LIST_INITIALIZER;
|
||||
pkgconf_node_t *n;
|
||||
bool ret;
|
||||
|
||||
data = getenv(env);
|
||||
if (data == NULL)
|
||||
return true;
|
||||
|
||||
pkgconf_path_split(data, &pathlist, true);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(pathlist.head, n)
|
||||
{
|
||||
pkgconf_path_t *pn = n->data;
|
||||
|
||||
ret = pkgconf_client_preload_path(client, pn->path);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
|
||||
pkgconf_path_free(&pathlist);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* libpkgconf/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
#mesondefine HAVE_STRLCAT
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#mesondefine HAVE_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the `strndup' function. */
|
||||
#mesondefine HAVE_STRNDUP
|
||||
|
||||
/* Define to 1 if you have the `reallocarray' function. */
|
||||
#mesondefine HAVE_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
#mesondefine HAVE_DECL_STRLCAT
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#mesondefine HAVE_DECL_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the `strndup' function. */
|
||||
#mesondefine HAVE_DECL_STRNDUP
|
||||
|
||||
/* Define to 1 if you have the `reallocarray' function. */
|
||||
#mesondefine HAVE_DECL_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the `pledge' function. */
|
||||
#mesondefine HAVE_DECL_PLEDGE
|
||||
|
||||
/* Define to 1 if you have the `unveil' function. */
|
||||
#mesondefine HAVE_DECL_UNVEIL
|
||||
|
||||
/* Name of package */
|
||||
#mesondefine PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#mesondefine PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#mesondefine PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#mesondefine PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#mesondefine PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#mesondefine PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#mesondefine PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#mesondefine STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#mesondefine VERSION
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#mesondefine _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#mesondefine _LARGE_FILES
|
||||
|
||||
#mesondefine PKG_DEFAULT_PATH
|
||||
#mesondefine SYSTEM_INCLUDEDIR
|
||||
#mesondefine SYSTEM_LIBDIR
|
||||
#mesondefine PERSONALITY_PATH
|
||||
|
||||
/* Enable Solaris extensions. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# define __EXTENSIONS__ 1
|
||||
#endif
|
||||
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* dependency.c
|
||||
* dependency parsing and management
|
||||
*
|
||||
* Copyright (c) 2011, 2012, 2013 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `dependency` module
|
||||
* ==============================
|
||||
*
|
||||
* The `dependency` module provides support for building `dependency lists` (the basic component of the overall `dependency graph`) and
|
||||
* `dependency nodes` which store dependency information.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
OUTSIDE_MODULE = 0,
|
||||
INSIDE_MODULE_NAME = 1,
|
||||
BEFORE_OPERATOR = 2,
|
||||
INSIDE_OPERATOR = 3,
|
||||
AFTER_OPERATOR = 4,
|
||||
INSIDE_VERSION = 5
|
||||
} parse_state_t;
|
||||
|
||||
#define DEBUG_PARSE 0
|
||||
|
||||
static const char *
|
||||
dependency_to_str(const pkgconf_dependency_t *dep, char *buf, size_t buflen)
|
||||
{
|
||||
pkgconf_strlcpy(buf, dep->package, buflen);
|
||||
if (dep->version != NULL)
|
||||
{
|
||||
pkgconf_strlcat(buf, " ", buflen);
|
||||
pkgconf_strlcat(buf, pkgconf_pkg_get_comparator(dep), buflen);
|
||||
pkgconf_strlcat(buf, " ", buflen);
|
||||
pkgconf_strlcat(buf, dep->version, buflen);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* find a colliding dependency that is coloured differently */
|
||||
static inline pkgconf_dependency_t *
|
||||
find_colliding_dependency(const pkgconf_dependency_t *dep, const pkgconf_list_t *list)
|
||||
{
|
||||
const pkgconf_node_t *n;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, n)
|
||||
{
|
||||
pkgconf_dependency_t *dep2 = n->data;
|
||||
|
||||
if (strcmp(dep->package, dep2->package))
|
||||
continue;
|
||||
|
||||
if (dep->flags != dep2->flags)
|
||||
return dep2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline pkgconf_dependency_t *
|
||||
add_or_replace_dependency_node(pkgconf_client_t *client, pkgconf_dependency_t *dep, pkgconf_list_t *list)
|
||||
{
|
||||
char depbuf[PKGCONF_ITEM_SIZE];
|
||||
pkgconf_dependency_t *dep2 = find_colliding_dependency(dep, list);
|
||||
|
||||
/* there is already a node in the graph which describes this dependency */
|
||||
if (dep2 != NULL)
|
||||
{
|
||||
char depbuf2[PKGCONF_ITEM_SIZE];
|
||||
|
||||
PKGCONF_TRACE(client, "dependency collision: [%s/%x] -- [%s/%x]",
|
||||
dependency_to_str(dep, depbuf, sizeof depbuf), dep->flags,
|
||||
dependency_to_str(dep2, depbuf2, sizeof depbuf2), dep2->flags);
|
||||
|
||||
/* prefer the uncoloured node, either dep or dep2 */
|
||||
if (dep->flags && dep2->flags == 0)
|
||||
{
|
||||
PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf, dep);
|
||||
|
||||
pkgconf_dependency_unref(dep->owner, dep);
|
||||
return NULL;
|
||||
}
|
||||
else if (dep2->flags && dep->flags == 0)
|
||||
{
|
||||
PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf2, dep2);
|
||||
|
||||
pkgconf_node_delete(&dep2->iter, list);
|
||||
pkgconf_dependency_unref(dep2->owner, dep2);
|
||||
}
|
||||
else
|
||||
/* If both dependencies have equal strength, we keep both, because of situations like:
|
||||
* Requires: foo > 1, foo < 3
|
||||
*
|
||||
* If the situation is that both dependencies are literally equal, it is still harmless because
|
||||
* fragment deduplication will handle the excessive fragments.
|
||||
*/
|
||||
PKGCONF_TRACE(client, "keeping both dependencies (harmless)");
|
||||
}
|
||||
|
||||
PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", dependency_to_str(dep, depbuf, sizeof depbuf), list, dep->flags);
|
||||
pkgconf_node_insert_tail(&dep->iter, pkgconf_dependency_ref(dep->owner, dep), list);
|
||||
|
||||
/* This dependency is intentionally unowned.
|
||||
*
|
||||
* Internally we have no use for the returned type, and usually just
|
||||
* discard it. However, there is a publig pkgconf_dependency_add
|
||||
* function, which references this return value before returning it,
|
||||
* giving ownership at that point.
|
||||
*/
|
||||
return dep;
|
||||
}
|
||||
|
||||
static inline pkgconf_dependency_t *
|
||||
pkgconf_dependency_addraw(pkgconf_client_t *client, pkgconf_list_t *list, const char *package, size_t package_sz, const char *version, size_t version_sz, pkgconf_pkg_comparator_t compare, unsigned int flags)
|
||||
{
|
||||
pkgconf_dependency_t *dep;
|
||||
|
||||
dep = calloc(1, sizeof(pkgconf_dependency_t));
|
||||
if (dep == NULL)
|
||||
return NULL;
|
||||
|
||||
dep->package = pkgconf_strndup(package, package_sz);
|
||||
|
||||
if (version_sz != 0)
|
||||
dep->version = pkgconf_strndup(version, version_sz);
|
||||
|
||||
dep->compare = compare;
|
||||
dep->flags = flags;
|
||||
dep->owner = client;
|
||||
dep->refcount = 0;
|
||||
|
||||
return add_or_replace_dependency_node(client, dep, list);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_dependency_t *pkgconf_dependency_add(pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare)
|
||||
*
|
||||
* Adds a parsed dependency to a dependency list as a dependency node.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to.
|
||||
* :param pkgconf_list_t* list: The dependency list to add a dependency node to.
|
||||
* :param char* package: The package `atom` to set on the dependency node.
|
||||
* :param char* version: The package `version` to set on the dependency node.
|
||||
* :param pkgconf_pkg_comparator_t compare: The comparison operator to set on the dependency node.
|
||||
* :param uint flags: Any flags to attach to the dependency node.
|
||||
* :return: A dependency node.
|
||||
* :rtype: pkgconf_dependency_t *
|
||||
*/
|
||||
pkgconf_dependency_t *
|
||||
pkgconf_dependency_add(pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare, unsigned int flags)
|
||||
{
|
||||
pkgconf_dependency_t *dep;
|
||||
dep = pkgconf_dependency_addraw(client, list, package, strlen(package), version,
|
||||
version != NULL ? strlen(version) : 0, compare, flags);
|
||||
return pkgconf_dependency_ref(dep->owner, dep);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail)
|
||||
*
|
||||
* Adds a dependency node to a pre-existing dependency list.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The dependency list to add a dependency node to.
|
||||
* :param pkgconf_dependency_t* tail: The dependency node to add to the tail of the dependency list.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail)
|
||||
{
|
||||
pkgconf_node_insert_tail(&tail->iter, tail, list);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_dependency_free_one(pkgconf_dependency_t *dep)
|
||||
*
|
||||
* Frees a dependency node.
|
||||
*
|
||||
* :param pkgconf_dependency_t* dep: The dependency node to free.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_dependency_free_one(pkgconf_dependency_t *dep)
|
||||
{
|
||||
if (dep->match != NULL)
|
||||
pkgconf_pkg_unref(dep->match->owner, dep->match);
|
||||
|
||||
if (dep->package != NULL)
|
||||
free(dep->package);
|
||||
|
||||
if (dep->version != NULL)
|
||||
free(dep->version);
|
||||
|
||||
free(dep);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_dependency_t *pkgconf_dependency_ref(pkgconf_client_t *owner, pkgconf_dependency_t *dep)
|
||||
*
|
||||
* Increases a dependency node's refcount.
|
||||
*
|
||||
* :param pkgconf_client_t* owner: The client object which owns the memory of this dependency node.
|
||||
* :param pkgconf_dependency_t* dep: The dependency to increase the refcount of.
|
||||
* :return: the dependency node on success, else NULL
|
||||
*/
|
||||
pkgconf_dependency_t *
|
||||
pkgconf_dependency_ref(pkgconf_client_t *client, pkgconf_dependency_t *dep)
|
||||
{
|
||||
if (client != dep->owner)
|
||||
return NULL;
|
||||
|
||||
dep->refcount++;
|
||||
PKGCONF_TRACE(client, "%s refcount@%p: %d", dep->package, dep, dep->refcount);
|
||||
return dep;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_dependency_unref(pkgconf_client_t *owner, pkgconf_dependency_t *dep)
|
||||
*
|
||||
* Decreases a dependency node's refcount and frees it if necessary.
|
||||
*
|
||||
* :param pkgconf_client_t* owner: The client object which owns the memory of this dependency node.
|
||||
* :param pkgconf_dependency_t* dep: The dependency to decrease the refcount of.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_dependency_unref(pkgconf_client_t *client, pkgconf_dependency_t *dep)
|
||||
{
|
||||
if (client != dep->owner)
|
||||
return;
|
||||
|
||||
--dep->refcount;
|
||||
PKGCONF_TRACE(client, "%s refcount@%p: %d", dep->package, dep, dep->refcount);
|
||||
|
||||
if (dep->refcount <= 0)
|
||||
pkgconf_dependency_free_one(dep);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_dependency_free(pkgconf_list_t *list)
|
||||
*
|
||||
* Release a dependency list and its child dependency nodes.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The dependency list to release.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_dependency_free(pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_t *node, *next;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
|
||||
pkgconf_node_delete(&dep->iter, list);
|
||||
pkgconf_dependency_unref(dep->owner, dep);
|
||||
}
|
||||
|
||||
pkgconf_list_zero(list);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_dependency_parse_str(pkgconf_list_t *deplist_head, const char *depends)
|
||||
*
|
||||
* Parse a dependency declaration into a dependency list.
|
||||
* Commas are counted as whitespace to allow for constructs such as ``@SUBSTVAR@, zlib`` being processed
|
||||
* into ``, zlib``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to.
|
||||
* :param pkgconf_list_t* deplist_head: The dependency list to populate with dependency nodes.
|
||||
* :param char* depends: The dependency data to parse.
|
||||
* :param uint flags: Any flags to attach to the dependency nodes.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags)
|
||||
{
|
||||
parse_state_t state = OUTSIDE_MODULE;
|
||||
pkgconf_pkg_comparator_t compare = PKGCONF_CMP_ANY;
|
||||
char cmpname[PKGCONF_ITEM_SIZE];
|
||||
size_t package_sz = 0, version_sz = 0, buf_sz = 0;
|
||||
char *buf;
|
||||
char *start = NULL;
|
||||
char *ptr = NULL;
|
||||
char *vstart = NULL;
|
||||
char *package = NULL, *version = NULL;
|
||||
char *cnameptr = cmpname;
|
||||
char *cnameend = cmpname + PKGCONF_ITEM_SIZE - 1;
|
||||
|
||||
if (!*depends)
|
||||
return;
|
||||
|
||||
memset(cmpname, '\0', sizeof cmpname);
|
||||
|
||||
buf_sz = strlen(depends) * 2;
|
||||
buf = calloc(1, buf_sz);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
pkgconf_strlcpy(buf, depends, buf_sz);
|
||||
pkgconf_strlcat(buf, " ", buf_sz);
|
||||
|
||||
start = ptr = buf;
|
||||
|
||||
while (*ptr)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case OUTSIDE_MODULE:
|
||||
if (!PKGCONF_IS_MODULE_SEPARATOR(*ptr))
|
||||
state = INSIDE_MODULE_NAME;
|
||||
|
||||
break;
|
||||
|
||||
case INSIDE_MODULE_NAME:
|
||||
if (isspace((unsigned char)*ptr))
|
||||
{
|
||||
const char *sptr = ptr;
|
||||
|
||||
while (*sptr && isspace((unsigned char)*sptr))
|
||||
sptr++;
|
||||
|
||||
if (*sptr == '\0')
|
||||
state = OUTSIDE_MODULE;
|
||||
else if (PKGCONF_IS_MODULE_SEPARATOR(*sptr))
|
||||
state = OUTSIDE_MODULE;
|
||||
else if (PKGCONF_IS_OPERATOR_CHAR(*sptr))
|
||||
state = BEFORE_OPERATOR;
|
||||
else
|
||||
state = OUTSIDE_MODULE;
|
||||
}
|
||||
else if (PKGCONF_IS_MODULE_SEPARATOR(*ptr))
|
||||
state = OUTSIDE_MODULE;
|
||||
else if (*(ptr + 1) == '\0')
|
||||
{
|
||||
ptr++;
|
||||
state = OUTSIDE_MODULE;
|
||||
}
|
||||
|
||||
if (state != INSIDE_MODULE_NAME && start != ptr)
|
||||
{
|
||||
char *iter = start;
|
||||
|
||||
while (PKGCONF_IS_MODULE_SEPARATOR(*iter))
|
||||
iter++;
|
||||
|
||||
package = iter;
|
||||
package_sz = ptr - iter;
|
||||
start = ptr;
|
||||
}
|
||||
|
||||
if (state == OUTSIDE_MODULE)
|
||||
{
|
||||
pkgconf_dependency_addraw(client, deplist_head, package, package_sz, NULL, 0, compare, flags);
|
||||
|
||||
compare = PKGCONF_CMP_ANY;
|
||||
package_sz = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BEFORE_OPERATOR:
|
||||
if (PKGCONF_IS_OPERATOR_CHAR(*ptr))
|
||||
{
|
||||
state = INSIDE_OPERATOR;
|
||||
if (cnameptr < cnameend)
|
||||
*cnameptr++ = *ptr;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case INSIDE_OPERATOR:
|
||||
if (PKGCONF_IS_OPERATOR_CHAR(*ptr))
|
||||
{
|
||||
if (cnameptr < cnameend)
|
||||
*cnameptr++ = *ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
state = AFTER_OPERATOR;
|
||||
compare = pkgconf_pkg_comparator_lookup_by_name(cmpname);
|
||||
// fallthrough
|
||||
|
||||
case AFTER_OPERATOR:
|
||||
if (!isspace((unsigned char)*ptr))
|
||||
{
|
||||
vstart = ptr;
|
||||
state = INSIDE_VERSION;
|
||||
}
|
||||
break;
|
||||
|
||||
case INSIDE_VERSION:
|
||||
if (PKGCONF_IS_MODULE_SEPARATOR(*ptr) || *(ptr + 1) == '\0')
|
||||
{
|
||||
version = vstart;
|
||||
version_sz = ptr - vstart;
|
||||
state = OUTSIDE_MODULE;
|
||||
|
||||
pkgconf_dependency_addraw(client, deplist_head, package, package_sz, version, version_sz, compare, flags);
|
||||
|
||||
compare = PKGCONF_CMP_ANY;
|
||||
cnameptr = cmpname;
|
||||
memset(cmpname, 0, sizeof cmpname);
|
||||
package_sz = 0;
|
||||
}
|
||||
|
||||
if (state == OUTSIDE_MODULE)
|
||||
start = ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends)
|
||||
*
|
||||
* Preprocess dependency data and then process that dependency declaration into a dependency list.
|
||||
* Commas are counted as whitespace to allow for constructs such as ``@SUBSTVAR@, zlib`` being processed
|
||||
* into ``, zlib``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to.
|
||||
* :param pkgconf_pkg_t* pkg: The package object that owns this dependency list.
|
||||
* :param pkgconf_list_t* deplist: The dependency list to populate with dependency nodes.
|
||||
* :param char* depends: The dependency data to parse.
|
||||
* :param uint flags: Any flags to attach to the dependency nodes.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_dependency_parse(pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends, unsigned int flags)
|
||||
{
|
||||
char *kvdepends = pkgconf_tuple_parse(client, &pkg->vars, depends, pkg->flags);
|
||||
|
||||
pkgconf_dependency_parse_str(client, deplist, kvdepends, flags);
|
||||
free(kvdepends);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_dependency_t *pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *dep)
|
||||
*
|
||||
* Copies a dependency node to a new one.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object that will own this dependency.
|
||||
* :param pkgconf_dependency_t* dep: The dependency node to copy.
|
||||
* :return: a pointer to a new dependency node, else NULL
|
||||
*/
|
||||
pkgconf_dependency_t *
|
||||
pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *dep)
|
||||
{
|
||||
pkgconf_dependency_t *new_dep;
|
||||
|
||||
new_dep = calloc(1, sizeof(pkgconf_dependency_t));
|
||||
if (new_dep == NULL)
|
||||
return NULL;
|
||||
|
||||
new_dep->package = strdup(dep->package);
|
||||
|
||||
if (dep->version != NULL)
|
||||
new_dep->version = strdup(dep->version);
|
||||
|
||||
new_dep->compare = dep->compare;
|
||||
new_dep->flags = dep->flags;
|
||||
new_dep->owner = client;
|
||||
new_dep->refcount = 0;
|
||||
|
||||
if (dep->match != NULL)
|
||||
new_dep->match = pkgconf_pkg_ref(client, dep->match);
|
||||
|
||||
return pkgconf_dependency_ref(client, new_dep);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* fileio.c
|
||||
* File reading utilities
|
||||
*
|
||||
* Copyright (c) 2012, 2025 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
bool
|
||||
pkgconf_fgetline(pkgconf_buffer_t *buffer, FILE *stream)
|
||||
{
|
||||
bool quoted = false;
|
||||
int c = '\0', c2;
|
||||
|
||||
while ((c = getc(stream)) != EOF)
|
||||
{
|
||||
if (c == '\\' && !quoted)
|
||||
{
|
||||
quoted = true;
|
||||
continue;
|
||||
}
|
||||
else if (c == '#')
|
||||
{
|
||||
if (!quoted) {
|
||||
/* Skip the rest of the line */
|
||||
do {
|
||||
c = getc(stream);
|
||||
} while (c != '\n' && c != EOF);
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
break;
|
||||
}
|
||||
else
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
|
||||
quoted = false;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
if (quoted)
|
||||
{
|
||||
/* Trim spaces */
|
||||
do {
|
||||
c2 = getc(stream);
|
||||
} while (c2 == '\t' || c2 == ' ');
|
||||
|
||||
ungetc(c2, stream);
|
||||
|
||||
quoted = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (c == '\r')
|
||||
{
|
||||
pkgconf_buffer_push_byte(buffer, '\n');
|
||||
|
||||
if ((c2 = getc(stream)) == '\n')
|
||||
{
|
||||
if (quoted)
|
||||
{
|
||||
quoted = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ungetc(c2, stream);
|
||||
|
||||
if (quoted)
|
||||
{
|
||||
quoted = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quoted) {
|
||||
pkgconf_buffer_push_byte(buffer, '\\');
|
||||
quoted = false;
|
||||
}
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Remove newline character. */
|
||||
if (pkgconf_buffer_lastc(buffer) == '\n')
|
||||
pkgconf_buffer_trim_byte(buffer);
|
||||
|
||||
if (pkgconf_buffer_lastc(buffer) == '\r')
|
||||
pkgconf_buffer_trim_byte(buffer);
|
||||
|
||||
return !(c == EOF || ferror(stream));
|
||||
}
|
||||
@@ -0,0 +1,803 @@
|
||||
/*
|
||||
* fragment.c
|
||||
* Management of fragment lists.
|
||||
*
|
||||
* Copyright (c) 2012, 2013, 2014 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `fragment` module
|
||||
* ============================
|
||||
*
|
||||
* The `fragment` module provides low-level management and rendering of fragment lists. A
|
||||
* `fragment list` contains various `fragments` of text (such as ``-I /usr/include``) in a matter
|
||||
* which is composable, mergeable and reorderable.
|
||||
*/
|
||||
|
||||
struct pkgconf_fragment_check {
|
||||
char *token;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_unmergeable(const char *string)
|
||||
{
|
||||
static const struct pkgconf_fragment_check check_fragments[] = {
|
||||
{"-framework", 10},
|
||||
{"-isystem", 8},
|
||||
{"-idirafter", 10},
|
||||
{"-pthread", 8},
|
||||
{"-Wa,", 4},
|
||||
{"-Wl,", 4},
|
||||
{"-Wp,", 4},
|
||||
{"-trigraphs", 10},
|
||||
{"-pedantic", 9},
|
||||
{"-ansi", 5},
|
||||
{"-std=", 5},
|
||||
{"-stdlib=", 8},
|
||||
{"-include", 8},
|
||||
{"-nostdinc", 9},
|
||||
{"-nostdlibinc", 12},
|
||||
{"-nobuiltininc", 13},
|
||||
{"-nodefaultlibs", 14},
|
||||
};
|
||||
|
||||
if (*string != '-')
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < PKGCONF_ARRAY_SIZE(check_fragments); i++)
|
||||
if (!strncmp(string, check_fragments[i].token, check_fragments[i].len))
|
||||
return true;
|
||||
|
||||
/* only one pair of {-flag, arg} may be merged together */
|
||||
if (strchr(string, ' ') != NULL)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_should_munge(const char *string, const char *sysroot_dir)
|
||||
{
|
||||
if (*string != '/')
|
||||
return false;
|
||||
|
||||
if (sysroot_dir != NULL && strncmp(sysroot_dir, string, strlen(sysroot_dir)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_groupable(const char *string)
|
||||
{
|
||||
static const struct pkgconf_fragment_check check_fragments[] = {
|
||||
{"-Wl,--start-group", 17},
|
||||
{"-framework", 10},
|
||||
{"-isystem", 8},
|
||||
{"-idirafter", 10},
|
||||
{"-include", 8},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < PKGCONF_ARRAY_SIZE(check_fragments); i++)
|
||||
if (!strncmp(string, check_fragments[i].token, check_fragments[i].len))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_terminus(const char *string)
|
||||
{
|
||||
static const struct pkgconf_fragment_check check_fragments[] = {
|
||||
{"-Wl,--end-group", 15},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < PKGCONF_ARRAY_SIZE(check_fragments); i++)
|
||||
if (!strncmp(string, check_fragments[i].token, check_fragments[i].len))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_special(const char *string)
|
||||
{
|
||||
if (*string != '-')
|
||||
return true;
|
||||
|
||||
if (!strncmp(string, "-lib:", 5))
|
||||
return true;
|
||||
|
||||
return pkgconf_fragment_is_unmergeable(string);
|
||||
}
|
||||
|
||||
static inline void
|
||||
pkgconf_fragment_munge(const pkgconf_client_t *client, char *buf, size_t buflen, const char *source, const char *sysroot_dir, unsigned int flags)
|
||||
{
|
||||
*buf = '\0';
|
||||
|
||||
if (!(flags & PKGCONF_PKG_PROPF_UNINSTALLED) || (client->flags & PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES))
|
||||
{
|
||||
if (sysroot_dir == NULL)
|
||||
sysroot_dir = pkgconf_tuple_find_global(client, "pc_sysrootdir");
|
||||
|
||||
if (sysroot_dir != NULL && pkgconf_fragment_should_munge(source, sysroot_dir))
|
||||
pkgconf_strlcat(buf, sysroot_dir, buflen);
|
||||
}
|
||||
|
||||
pkgconf_strlcat(buf, source, buflen);
|
||||
|
||||
if (*buf == '/' && !(client->flags & PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS))
|
||||
pkgconf_path_relocate(buf, buflen);
|
||||
}
|
||||
|
||||
static inline char *
|
||||
pkgconf_fragment_copy_munged(const pkgconf_client_t *client, const char *source, unsigned int flags)
|
||||
{
|
||||
char mungebuf[PKGCONF_ITEM_SIZE];
|
||||
pkgconf_fragment_munge(client, mungebuf, sizeof mungebuf, source, client->sysroot_dir, flags);
|
||||
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
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string, unsigned int flags)
|
||||
*
|
||||
* Adds a `fragment` of text to a `fragment list`, possibly modifying the fragment if a sysroot is set.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param pkgconf_list_t* list: The fragment list.
|
||||
* :param char* string: The string of text to add as a fragment to the fragment list.
|
||||
* :param uint flags: Parsing-related flags for the package.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string, unsigned int flags)
|
||||
{
|
||||
pkgconf_list_t *target = list;
|
||||
pkgconf_fragment_t *frag;
|
||||
|
||||
if (*string == '\0')
|
||||
return;
|
||||
|
||||
if (list->tail != NULL && list->tail->data != NULL &&
|
||||
!(client->flags & PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS))
|
||||
{
|
||||
pkgconf_fragment_t *parent = list->tail->data;
|
||||
|
||||
/* only attempt to merge 'special' fragments together */
|
||||
if (!parent->type && parent->data != NULL &&
|
||||
pkgconf_fragment_is_unmergeable(parent->data) &&
|
||||
!(parent->flags & PKGCONF_PKG_FRAGF_TERMINATED))
|
||||
{
|
||||
if (pkgconf_fragment_is_groupable(parent->data))
|
||||
target = &parent->children;
|
||||
|
||||
if (pkgconf_fragment_is_terminus(string))
|
||||
parent->flags |= PKGCONF_PKG_FRAGF_TERMINATED;
|
||||
|
||||
PKGCONF_TRACE(client, "adding fragment as child to list @%p", target);
|
||||
}
|
||||
}
|
||||
|
||||
frag = calloc(1, sizeof(pkgconf_fragment_t));
|
||||
if (frag == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "failed to add new fragment due to allocation failure to list @%p", target);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(string) > 1 && !pkgconf_fragment_is_special(string))
|
||||
{
|
||||
frag->type = *(string + 1);
|
||||
frag->data = pkgconf_fragment_copy_munged(client, string + 2, flags);
|
||||
|
||||
PKGCONF_TRACE(client, "added fragment {%c, '%s'} to list @%p", frag->type, frag->data, list);
|
||||
}
|
||||
else
|
||||
{
|
||||
frag->type = 0;
|
||||
frag->data = pkgconf_fragment_copy_munged(client, string, flags);
|
||||
|
||||
PKGCONF_TRACE(client, "created special fragment {'%s'} in list @%p", frag->data, target);
|
||||
}
|
||||
|
||||
pkgconf_node_insert_tail(&frag->iter, frag, target);
|
||||
}
|
||||
|
||||
static inline pkgconf_fragment_t *
|
||||
pkgconf_fragment_lookup(pkgconf_list_t *list, const pkgconf_fragment_t *base)
|
||||
{
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_REVERSE(list->tail, node)
|
||||
{
|
||||
pkgconf_fragment_t *frag = node->data;
|
||||
|
||||
if (base->type != frag->type)
|
||||
continue;
|
||||
|
||||
if (!strcmp(base->data, frag->data))
|
||||
return frag;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_can_merge_back(const pkgconf_fragment_t *base, unsigned int flags, bool is_private)
|
||||
{
|
||||
(void) flags;
|
||||
|
||||
if (base->type == 'l')
|
||||
{
|
||||
if (is_private)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (base->type == 'F')
|
||||
return false;
|
||||
if (base->type == 'L')
|
||||
return false;
|
||||
if (base->type == 'I')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_can_merge(const pkgconf_fragment_t *base, unsigned int flags, bool is_private)
|
||||
{
|
||||
(void) flags;
|
||||
|
||||
if (is_private)
|
||||
return false;
|
||||
|
||||
if (base->children.head != NULL)
|
||||
return false;
|
||||
|
||||
return pkgconf_fragment_is_unmergeable(base->data);
|
||||
}
|
||||
|
||||
static inline pkgconf_fragment_t *
|
||||
pkgconf_fragment_exists(pkgconf_list_t *list, const pkgconf_fragment_t *base, unsigned int flags, bool is_private)
|
||||
{
|
||||
if (!pkgconf_fragment_can_merge_back(base, flags, is_private))
|
||||
return NULL;
|
||||
|
||||
if (!pkgconf_fragment_can_merge(base, flags, is_private))
|
||||
return NULL;
|
||||
|
||||
return pkgconf_fragment_lookup(list, base);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_should_merge(const pkgconf_fragment_t *base)
|
||||
{
|
||||
const pkgconf_fragment_t *parent;
|
||||
|
||||
/* if we are the first fragment, that means the next fragment is the same, so it's always safe. */
|
||||
if (base->iter.prev == NULL)
|
||||
return true;
|
||||
|
||||
/* this really shouldn't ever happen, but handle it */
|
||||
parent = base->iter.prev->data;
|
||||
if (parent == NULL)
|
||||
return true;
|
||||
|
||||
switch (parent->type)
|
||||
{
|
||||
case 'l':
|
||||
case 'L':
|
||||
case 'I':
|
||||
return true;
|
||||
default:
|
||||
return !base->type || parent->type == base->type;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag)
|
||||
*
|
||||
* Checks if a `fragment` contains a `system path`. System paths are detected at compile time and optionally overridden by
|
||||
* the ``PKG_CONFIG_SYSTEM_INCLUDE_PATH`` and ``PKG_CONFIG_SYSTEM_LIBRARY_PATH`` environment variables.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object the fragment belongs to.
|
||||
* :param pkgconf_fragment_t* frag: The fragment being checked.
|
||||
* :return: true if the fragment contains a system path, else false
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag)
|
||||
{
|
||||
const pkgconf_list_t *check_paths = NULL;
|
||||
|
||||
switch (frag->type)
|
||||
{
|
||||
case 'L':
|
||||
check_paths = &client->filter_libdirs;
|
||||
break;
|
||||
case 'I':
|
||||
check_paths = &client->filter_includedirs;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return pkgconf_path_match_list(frag->data, check_paths);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private)
|
||||
*
|
||||
* Copies a `fragment` to another `fragment list`, possibly removing a previous copy of the `fragment`
|
||||
* in a process known as `mergeback`.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param pkgconf_list_t* list: The list the fragment is being added to.
|
||||
* :param pkgconf_fragment_t* base: The fragment being copied.
|
||||
* :param bool is_private: Whether the fragment list is a `private` fragment list (static linking).
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_fragment_t *base, bool is_private)
|
||||
{
|
||||
pkgconf_fragment_t *frag;
|
||||
|
||||
if ((frag = pkgconf_fragment_exists(list, base, client->flags, is_private)) != NULL)
|
||||
{
|
||||
if (pkgconf_fragment_should_merge(frag))
|
||||
pkgconf_fragment_delete(list, frag);
|
||||
}
|
||||
else if (!is_private && !pkgconf_fragment_can_merge_back(base, client->flags, is_private) && (pkgconf_fragment_lookup(list, base) != NULL))
|
||||
return;
|
||||
|
||||
frag = calloc(1, sizeof(pkgconf_fragment_t));
|
||||
|
||||
frag->type = base->type;
|
||||
pkgconf_fragment_copy_list(client, &frag->children, &base->children);
|
||||
if (base->data != NULL)
|
||||
frag->data = strdup(base->data);
|
||||
|
||||
pkgconf_node_insert_tail(&frag->iter, frag, list);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base)
|
||||
*
|
||||
* Copies a `fragment list` to another `fragment list`, possibly removing a previous copy of the fragments
|
||||
* in a process known as `mergeback`.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param pkgconf_list_t* list: The list the fragments are being added to.
|
||||
* :param pkgconf_list_t* base: The list the fragments are being copied from.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_copy_list(const pkgconf_client_t *client, pkgconf_list_t *list, const pkgconf_list_t *base)
|
||||
{
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(base->head, node)
|
||||
{
|
||||
pkgconf_fragment_t *frag = node->data;
|
||||
|
||||
pkgconf_fragment_copy(client, list, frag, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func)
|
||||
*
|
||||
* Copies a `fragment list` to another `fragment list` which match a user-specified filtering function.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param pkgconf_list_t* dest: The destination list.
|
||||
* :param pkgconf_list_t* src: The source list.
|
||||
* :param pkgconf_fragment_filter_func_t filter_func: The filter function to use.
|
||||
* :param void* data: Optional data to pass to the filter function.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func, void *data)
|
||||
{
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(src->head, node)
|
||||
{
|
||||
pkgconf_fragment_t *frag = node->data;
|
||||
|
||||
if (filter_func(client, frag, data))
|
||||
pkgconf_fragment_copy(client, dest, frag, true);
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *
|
||||
fragment_quote(const pkgconf_fragment_t *frag)
|
||||
{
|
||||
const char *src = frag->data;
|
||||
ssize_t outlen = strlen(src) + 10;
|
||||
char *out, *dst;
|
||||
|
||||
if (frag->data == NULL)
|
||||
return NULL;
|
||||
|
||||
out = dst = calloc(1, outlen);
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
for (; *src; src++)
|
||||
{
|
||||
if (((*src < ' ') ||
|
||||
(*src >= (' ' + (frag->children.head != NULL ? 1 : 0)) && *src < '$') ||
|
||||
(*src > '$' && *src < '(') ||
|
||||
(*src > ')' && *src < '+') ||
|
||||
(*src > ':' && *src < '=') ||
|
||||
(*src > '=' && *src < '@') ||
|
||||
(*src > 'Z' && *src < '\\') ||
|
||||
#ifndef _WIN32
|
||||
(*src == '\\') ||
|
||||
#endif
|
||||
(*src > '\\' && *src < '^') ||
|
||||
(*src == '`') ||
|
||||
(*src > 'z' && *src < '~') ||
|
||||
(*src > '~')))
|
||||
*dst++ = '\\';
|
||||
|
||||
*dst++ = *src;
|
||||
|
||||
if ((ptrdiff_t)(dst - out) + 2 > outlen)
|
||||
{
|
||||
ptrdiff_t offset = dst - out;
|
||||
outlen *= 2;
|
||||
|
||||
char *newout = realloc(out, outlen);
|
||||
if (newout == NULL)
|
||||
{
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = newout;
|
||||
dst = out + offset;
|
||||
}
|
||||
}
|
||||
|
||||
*dst = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
pkgconf_fragment_len(const pkgconf_fragment_t *frag)
|
||||
{
|
||||
size_t len = 1;
|
||||
|
||||
if (frag->type)
|
||||
len += 2;
|
||||
|
||||
if (frag->data != NULL)
|
||||
{
|
||||
pkgconf_node_t *iter;
|
||||
|
||||
char *quoted = fragment_quote(frag);
|
||||
len += strlen(quoted);
|
||||
free(quoted);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(frag->children.head, iter)
|
||||
{
|
||||
const pkgconf_fragment_t *child_frag = iter->data;
|
||||
len += pkgconf_fragment_len(child_frag) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t
|
||||
fragment_render_len(const pkgconf_list_t *list, bool escape)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
size_t out = 1; /* trailing nul */
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
const pkgconf_fragment_t *frag = node->data;
|
||||
out += pkgconf_fragment_len(frag);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
fragment_render_item(const pkgconf_fragment_t *frag, char *bptr, size_t bufremain)
|
||||
{
|
||||
const pkgconf_node_t *iter;
|
||||
char *base = bptr;
|
||||
|
||||
char *quoted = fragment_quote(frag);
|
||||
if (quoted == NULL)
|
||||
return 0;
|
||||
|
||||
if (strlen(quoted) > bufremain)
|
||||
{
|
||||
free(quoted);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (frag->type)
|
||||
{
|
||||
*bptr++ = '-';
|
||||
*bptr++ = frag->type;
|
||||
}
|
||||
|
||||
if (quoted != NULL)
|
||||
{
|
||||
bptr += pkgconf_strlcpy(bptr, quoted, bufremain - (bptr - base));
|
||||
free(quoted);
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(frag->children.head, iter)
|
||||
{
|
||||
const pkgconf_fragment_t *child_frag = iter->data;
|
||||
|
||||
*bptr++ = ' ';
|
||||
bptr += fragment_render_item(child_frag, bptr, bufremain - (bptr - base));
|
||||
}
|
||||
|
||||
return bptr - base;
|
||||
}
|
||||
|
||||
static void
|
||||
fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
pkgconf_node_t *node;
|
||||
char *bptr = buf;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
const pkgconf_fragment_t *frag = node->data;
|
||||
size_t buf_remaining = buflen - (bptr - buf);
|
||||
size_t written = fragment_render_item(frag, bptr, buf_remaining);
|
||||
|
||||
bptr += written;
|
||||
|
||||
if (node->next != NULL)
|
||||
*bptr++ = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
static const pkgconf_fragment_render_ops_t default_render_ops = {
|
||||
.render_len = fragment_render_len,
|
||||
.render_buf = fragment_render_buf
|
||||
};
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
*
|
||||
* Calculates the required memory to store a `fragment list` when rendered as a string.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The `fragment list` being rendered.
|
||||
* :param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
* :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
* :return: the amount of bytes required to represent the `fragment list` when rendered
|
||||
* :rtype: size_t
|
||||
*/
|
||||
size_t
|
||||
pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
ops = ops != NULL ? ops : &default_render_ops;
|
||||
return ops->render_len(list, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
*
|
||||
* Renders a `fragment list` into a buffer.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The `fragment list` being rendered.
|
||||
* :param char* buf: The buffer to render the fragment list into.
|
||||
* :param size_t buflen: The length of the buffer.
|
||||
* :param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
* :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
ops = ops != NULL ? ops : &default_render_ops;
|
||||
ops->render_buf(list, buf, buflen, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *pkgconf_fragment_render(const pkgconf_list_t *list)
|
||||
*
|
||||
* Allocate memory and render a `fragment list` into it.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The `fragment list` being rendered.
|
||||
* :param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
* :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
* :return: An allocated string containing the rendered `fragment list`.
|
||||
* :rtype: char *
|
||||
*/
|
||||
char *
|
||||
pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
size_t buflen = pkgconf_fragment_render_len(list, true, ops);
|
||||
char *buf = calloc(1, buflen);
|
||||
|
||||
pkgconf_fragment_render_buf(list, buf, buflen, true, ops);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node)
|
||||
*
|
||||
* Delete a `fragment node` from a `fragment list`.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The `fragment list` to delete from.
|
||||
* :param pkgconf_fragment_t* node: The `fragment node` to delete.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_t *node)
|
||||
{
|
||||
pkgconf_node_delete(&node->iter, list);
|
||||
|
||||
free(node->data);
|
||||
free(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_free(pkgconf_list_t *list)
|
||||
*
|
||||
* Delete an entire `fragment list`.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The `fragment list` to delete.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_free(pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_t *node, *next;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node)
|
||||
{
|
||||
pkgconf_fragment_t *frag = node->data;
|
||||
|
||||
pkgconf_fragment_free(&frag->children);
|
||||
free(frag->data);
|
||||
free(frag);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value)
|
||||
*
|
||||
* Parse a string into a `fragment list`.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param pkgconf_list_t* list: The `fragment list` to add the fragment entries to.
|
||||
* :param pkgconf_list_t* vars: A list of variables to use for variable substitution.
|
||||
* :param uint flags: Any parsing flags to be aware of.
|
||||
* :param char* value: The string to parse into fragments.
|
||||
* :return: true on success, false on parse error
|
||||
*/
|
||||
bool
|
||||
pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_list_t *vars, const char *value, unsigned int flags)
|
||||
{
|
||||
int i, ret, argc;
|
||||
char **argv;
|
||||
char *repstr = pkgconf_tuple_parse(client, vars, value, flags);
|
||||
|
||||
PKGCONF_TRACE(client, "post-subst: [%s] -> [%s]", value, repstr);
|
||||
|
||||
ret = pkgconf_argv_split(repstr, &argc, &argv);
|
||||
if (ret < 0)
|
||||
{
|
||||
PKGCONF_TRACE(client, "unable to parse fragment string [%s]", repstr);
|
||||
free(repstr);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
PKGCONF_TRACE(client, "processing %s", argv[i]);
|
||||
|
||||
if (argv[i] == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "parsed fragment string is inconsistent: argc = %d while argv[%d] == NULL", argc, i);
|
||||
pkgconf_argv_free(argv);
|
||||
free(repstr);
|
||||
return false;
|
||||
}
|
||||
|
||||
pkgconf_fragment_add(client, list, argv[i], flags);
|
||||
}
|
||||
|
||||
pkgconf_argv_free(argv);
|
||||
free(repstr);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* iter.h
|
||||
* Linked lists and iterators.
|
||||
*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef LIBPKGCONF_ITER_H
|
||||
#define LIBPKGCONF_ITER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct pkgconf_node_ pkgconf_node_t;
|
||||
|
||||
struct pkgconf_node_ {
|
||||
pkgconf_node_t *prev, *next;
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
pkgconf_node_t *head, *tail;
|
||||
size_t length;
|
||||
} pkgconf_list_t;
|
||||
|
||||
#define PKGCONF_LIST_INITIALIZER { NULL, NULL, 0 }
|
||||
|
||||
static inline void
|
||||
pkgconf_list_zero(pkgconf_list_t *list)
|
||||
{
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
list->length = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pkgconf_node_insert(pkgconf_node_t *node, void *data, pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_t *tnode;
|
||||
|
||||
node->data = data;
|
||||
|
||||
if (list->head == NULL)
|
||||
{
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
list->length = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
tnode = list->head;
|
||||
|
||||
node->next = tnode;
|
||||
tnode->prev = node;
|
||||
|
||||
list->head = node;
|
||||
list->length++;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pkgconf_node_insert_tail(pkgconf_node_t *node, void *data, pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_t *tnode;
|
||||
|
||||
node->data = data;
|
||||
|
||||
if (list->tail == NULL)
|
||||
{
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
list->length = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
tnode = list->tail;
|
||||
|
||||
node->prev = tnode;
|
||||
tnode->next = node;
|
||||
|
||||
list->tail = node;
|
||||
list->length++;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pkgconf_node_delete(pkgconf_node_t *node, pkgconf_list_t *list)
|
||||
{
|
||||
list->length--;
|
||||
|
||||
if (node->prev == NULL)
|
||||
list->head = node->next;
|
||||
else
|
||||
node->prev->next = node->next;
|
||||
|
||||
if (node->next == NULL)
|
||||
list->tail = node->prev;
|
||||
else
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef LIBPKGCONF_LIBPKGCONF_API_H
|
||||
#define LIBPKGCONF_LIBPKGCONF_API_H
|
||||
|
||||
/* Makefile.am specifies visibility using the libtool option -export-symbols-regex '^pkgconf_'
|
||||
* Unfortunately, that is not available when building with meson, so use attributes instead.
|
||||
*/
|
||||
#if defined(PKGCONFIG_IS_STATIC)
|
||||
# define PKGCONF_API
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
# if defined(LIBPKGCONF_EXPORT) || defined(DLL_EXPORT)
|
||||
# define PKGCONF_API __declspec(dllexport)
|
||||
# else
|
||||
# define PKGCONF_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define PKGCONF_API __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
* libpkgconf.h
|
||||
* Global include file for everything in libpkgconf.
|
||||
*
|
||||
* Copyright (c) 2011, 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef LIBPKGCONF__LIBPKGCONF_H
|
||||
#define LIBPKGCONF__LIBPKGCONF_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <libpkgconf/libpkgconf-api.h>
|
||||
#include <libpkgconf/iter.h>
|
||||
#include <libpkgconf/bsdstubs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* pkg-config uses ';' on win32 as ':' is part of path */
|
||||
#ifdef _WIN32
|
||||
#define PKG_CONFIG_PATH_SEP_S ";"
|
||||
#else
|
||||
#define PKG_CONFIG_PATH_SEP_S ":"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PKG_DIR_SEP_S '\\'
|
||||
#else
|
||||
#define PKG_DIR_SEP_S '/'
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
|
||||
#endif
|
||||
|
||||
#define PKGCONF_BUFSIZE (65535)
|
||||
|
||||
typedef enum {
|
||||
PKGCONF_CMP_NOT_EQUAL,
|
||||
PKGCONF_CMP_ANY,
|
||||
PKGCONF_CMP_LESS_THAN,
|
||||
PKGCONF_CMP_LESS_THAN_EQUAL,
|
||||
PKGCONF_CMP_EQUAL,
|
||||
PKGCONF_CMP_GREATER_THAN,
|
||||
PKGCONF_CMP_GREATER_THAN_EQUAL
|
||||
} pkgconf_pkg_comparator_t;
|
||||
|
||||
#define PKGCONF_CMP_COUNT 7
|
||||
|
||||
typedef struct pkgconf_pkg_ pkgconf_pkg_t;
|
||||
typedef struct pkgconf_dependency_ pkgconf_dependency_t;
|
||||
typedef struct pkgconf_tuple_ pkgconf_tuple_t;
|
||||
typedef struct pkgconf_fragment_ pkgconf_fragment_t;
|
||||
typedef struct pkgconf_path_ pkgconf_path_t;
|
||||
typedef struct pkgconf_client_ pkgconf_client_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_FOREACH_LIST_ENTRY(head, value) \
|
||||
for ((value) = (head); (value) != NULL; (value) = (value)->next)
|
||||
|
||||
#define PKGCONF_FOREACH_LIST_ENTRY_SAFE(head, nextiter, value) \
|
||||
for ((value) = (head), (nextiter) = (head) != NULL ? (head)->next : NULL; (value) != NULL; (value) = (nextiter), (nextiter) = (nextiter) != NULL ? (nextiter)->next : NULL)
|
||||
|
||||
#define PKGCONF_FOREACH_LIST_ENTRY_REVERSE(tail, value) \
|
||||
for ((value) = (tail); (value) != NULL; (value) = (value)->prev)
|
||||
|
||||
#define LIBPKGCONF_VERSION 20501
|
||||
#define LIBPKGCONF_VERSION_STR "2.5.1"
|
||||
|
||||
struct pkgconf_queue_ {
|
||||
pkgconf_node_t iter;
|
||||
char *package;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct pkgconf_fragment_ {
|
||||
pkgconf_node_t iter;
|
||||
|
||||
char type;
|
||||
char *data;
|
||||
|
||||
pkgconf_list_t children;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define PKGCONF_PKG_FRAGF_TERMINATED 0x1
|
||||
|
||||
struct pkgconf_dependency_ {
|
||||
pkgconf_node_t iter;
|
||||
|
||||
char *package;
|
||||
pkgconf_pkg_comparator_t compare;
|
||||
char *version;
|
||||
pkgconf_pkg_t *parent;
|
||||
pkgconf_pkg_t *match;
|
||||
|
||||
unsigned int flags;
|
||||
|
||||
int refcount;
|
||||
pkgconf_client_t *owner;
|
||||
};
|
||||
|
||||
struct pkgconf_tuple_ {
|
||||
pkgconf_node_t iter;
|
||||
|
||||
char *key;
|
||||
char *value;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define PKGCONF_PKG_TUPLEF_OVERRIDE 0x1
|
||||
|
||||
struct pkgconf_path_ {
|
||||
pkgconf_node_t lnode;
|
||||
|
||||
char *path;
|
||||
void *handle_path;
|
||||
void *handle_device;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define PKGCONF_PKG_PROPF_NONE 0x00
|
||||
#define PKGCONF_PKG_PROPF_STATIC 0x01
|
||||
#define PKGCONF_PKG_PROPF_CACHED 0x02
|
||||
#define PKGCONF_PKG_PROPF_UNINSTALLED 0x08
|
||||
#define PKGCONF_PKG_PROPF_VIRTUAL 0x10
|
||||
#define PKGCONF_PKG_PROPF_ANCESTOR 0x20
|
||||
#define PKGCONF_PKG_PROPF_VISITED_PRIVATE 0x40
|
||||
#define PKGCONF_PKG_PROPF_PRELOADED 0x80
|
||||
|
||||
struct pkgconf_pkg_ {
|
||||
int refcount;
|
||||
char *id;
|
||||
char *filename;
|
||||
char *realname;
|
||||
char *version;
|
||||
char *description;
|
||||
char *url;
|
||||
char *pc_filedir;
|
||||
char *license;
|
||||
char *maintainer;
|
||||
char *copyright;
|
||||
char *why;
|
||||
|
||||
pkgconf_list_t libs;
|
||||
pkgconf_list_t libs_private;
|
||||
pkgconf_list_t cflags;
|
||||
pkgconf_list_t cflags_private;
|
||||
|
||||
pkgconf_list_t required; /* this used to be requires but that is now a reserved keyword */
|
||||
pkgconf_list_t requires_private;
|
||||
pkgconf_list_t conflicts;
|
||||
pkgconf_list_t provides;
|
||||
|
||||
pkgconf_list_t vars;
|
||||
|
||||
unsigned int flags;
|
||||
|
||||
pkgconf_client_t *owner;
|
||||
|
||||
/* these resources are owned by the package and do not need special management,
|
||||
* under no circumstance attempt to allocate or free objects belonging to these pointers
|
||||
*/
|
||||
pkgconf_tuple_t *orig_prefix;
|
||||
pkgconf_tuple_t *prefix;
|
||||
|
||||
uint64_t serial;
|
||||
uint64_t identifier;
|
||||
|
||||
pkgconf_node_t preload_node;
|
||||
};
|
||||
|
||||
typedef bool (*pkgconf_pkg_iteration_func_t)(const pkgconf_pkg_t *pkg, void *data);
|
||||
typedef void (*pkgconf_pkg_traverse_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data);
|
||||
typedef bool (*pkgconf_queue_apply_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth);
|
||||
typedef bool (*pkgconf_error_handler_func_t)(const char *msg, const pkgconf_client_t *client, void *data);
|
||||
typedef void (*pkgconf_unveil_handler_func_t)(const pkgconf_client_t *client, const char *path, const char *permissions);
|
||||
|
||||
struct pkgconf_client_ {
|
||||
pkgconf_list_t dir_list;
|
||||
|
||||
pkgconf_list_t filter_libdirs;
|
||||
pkgconf_list_t filter_includedirs;
|
||||
|
||||
pkgconf_list_t global_vars;
|
||||
|
||||
void *error_handler_data;
|
||||
void *warn_handler_data;
|
||||
void *trace_handler_data;
|
||||
|
||||
pkgconf_error_handler_func_t error_handler;
|
||||
pkgconf_error_handler_func_t warn_handler;
|
||||
pkgconf_error_handler_func_t trace_handler;
|
||||
|
||||
FILE *auditf;
|
||||
|
||||
char *sysroot_dir;
|
||||
char *buildroot_dir;
|
||||
|
||||
unsigned int flags;
|
||||
|
||||
char *prefix_varname;
|
||||
|
||||
bool already_sent_notice;
|
||||
|
||||
uint64_t serial;
|
||||
uint64_t identifier;
|
||||
|
||||
pkgconf_pkg_t **cache_table;
|
||||
size_t cache_count;
|
||||
|
||||
pkgconf_unveil_handler_func_t unveil_handler;
|
||||
|
||||
pkgconf_list_t preloaded_pkgs;
|
||||
};
|
||||
|
||||
struct pkgconf_cross_personality_ {
|
||||
char *name;
|
||||
|
||||
pkgconf_list_t dir_list;
|
||||
|
||||
pkgconf_list_t filter_libdirs;
|
||||
pkgconf_list_t filter_includedirs;
|
||||
|
||||
char *sysroot_dir;
|
||||
|
||||
bool want_default_static;
|
||||
bool want_default_pure;
|
||||
};
|
||||
|
||||
/* client.c */
|
||||
PKGCONF_API void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality);
|
||||
PKGCONF_API pkgconf_client_t * pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality);
|
||||
PKGCONF_API void pkgconf_client_deinit(pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_free(pkgconf_client_t *client);
|
||||
PKGCONF_API const char *pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir);
|
||||
PKGCONF_API const char *pkgconf_client_get_buildroot_dir(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot_dir);
|
||||
PKGCONF_API unsigned int pkgconf_client_get_flags(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_flags(pkgconf_client_t *client, unsigned int flags);
|
||||
PKGCONF_API const char *pkgconf_client_get_prefix_varname(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_prefix_varname(pkgconf_client_t *client, const char *prefix_varname);
|
||||
PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_warn_handler(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_warn_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t warn_handler, void *warn_handler_data);
|
||||
PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_error_handler(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data);
|
||||
PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_trace_handler(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data);
|
||||
PKGCONF_API pkgconf_unveil_handler_func_t pkgconf_client_get_unveil_handler(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler);
|
||||
PKGCONF_API void pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality);
|
||||
PKGCONF_API bool pkgconf_client_preload_path(pkgconf_client_t *client, const char *path);
|
||||
PKGCONF_API bool pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env);
|
||||
|
||||
/* personality.c */
|
||||
PKGCONF_API pkgconf_cross_personality_t *pkgconf_cross_personality_default(void);
|
||||
PKGCONF_API pkgconf_cross_personality_t *pkgconf_cross_personality_find(const char *triplet);
|
||||
PKGCONF_API void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *personality);
|
||||
|
||||
#define PKGCONF_IS_MODULE_SEPARATOR(c) ((c) == ',' || isspace ((unsigned char)(c)))
|
||||
#define PKGCONF_IS_OPERATOR_CHAR(c) ((c) == '<' || (c) == '>' || (c) == '!' || (c) == '=')
|
||||
|
||||
#define PKGCONF_PKG_PKGF_NONE 0x0000
|
||||
#define PKGCONF_PKG_PKGF_SEARCH_PRIVATE 0x0001
|
||||
#define PKGCONF_PKG_PKGF_ENV_ONLY 0x0002
|
||||
#define PKGCONF_PKG_PKGF_NO_UNINSTALLED 0x0004
|
||||
#define PKGCONF_PKG_PKGF_SKIP_ROOT_VIRTUAL 0x0008
|
||||
#define PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS 0x0010
|
||||
#define PKGCONF_PKG_PKGF_SKIP_CONFLICTS 0x0020
|
||||
#define PKGCONF_PKG_PKGF_NO_CACHE 0x0040
|
||||
#define PKGCONF_PKG_PKGF_SKIP_ERRORS 0x0080
|
||||
#define PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE 0x0100
|
||||
#define PKGCONF_PKG_PKGF_SKIP_PROVIDES 0x0200
|
||||
#define PKGCONF_PKG_PKGF_REDEFINE_PREFIX 0x0400
|
||||
#define PKGCONF_PKG_PKGF_DONT_RELOCATE_PATHS 0x0800
|
||||
#define PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS 0x1000
|
||||
#define PKGCONF_PKG_PKGF_DONT_FILTER_INTERNAL_CFLAGS 0x2000
|
||||
#define PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS 0x4000
|
||||
#define PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES 0x8000
|
||||
#define PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES 0x10000
|
||||
|
||||
#define PKGCONF_PKG_DEPF_INTERNAL 0x1
|
||||
#define PKGCONF_PKG_DEPF_PRIVATE 0x2
|
||||
#define PKGCONF_PKG_DEPF_QUERY 0x4
|
||||
|
||||
#define PKGCONF_PKG_ERRF_OK 0x0
|
||||
#define PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND 0x1
|
||||
#define PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH 0x2
|
||||
#define PKGCONF_PKG_ERRF_PACKAGE_CONFLICT 0x4
|
||||
#define PKGCONF_PKG_ERRF_DEPGRAPH_BREAK 0x8
|
||||
|
||||
#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
|
||||
# define PRINTFLIKE(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (gnu_printf, fmtarg, firstvararg)))
|
||||
#elif defined(__clang__) || defined(__INTEL_COMPILER) || __GNUC__ > 2 || (_GNUC__ == 2 && __GNUC_MINOR__ >= 5)
|
||||
# define PRINTFLIKE(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#else
|
||||
# define PRINTFLIKE(fmtarg, firstvararg)
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__INTEL_COMPILER) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
# define DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
# define DEPRECATED
|
||||
#endif
|
||||
|
||||
/* parser.c */
|
||||
typedef void (*pkgconf_parser_operand_func_t)(void *data, const size_t lineno, const char *key, const char *value);
|
||||
typedef void (*pkgconf_parser_warn_func_t)(void *data, const char *fmt, ...);
|
||||
|
||||
PKGCONF_API void pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, const char *filename);
|
||||
|
||||
/* pkg.c */
|
||||
PKGCONF_API bool pkgconf_error(const pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3);
|
||||
PKGCONF_API bool pkgconf_warn(const pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3);
|
||||
PKGCONF_API bool pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t lineno, const char *funcname, const char *format, ...) PRINTFLIKE(5, 6);
|
||||
PKGCONF_API bool pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, void *data);
|
||||
|
||||
#ifndef PKGCONF_LITE
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
#define PKGCONF_TRACE(client, ...) do { \
|
||||
pkgconf_trace(client, __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define PKGCONF_TRACE(client, ...) do { \
|
||||
pkgconf_trace(client, __FILE__, __LINE__, __func__, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define PKGCONF_TRACE(client, ...)
|
||||
#endif
|
||||
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_ref(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
|
||||
PKGCONF_API void pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
|
||||
PKGCONF_API void pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_find(pkgconf_client_t *client, const char *name);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_traverse(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_pkg_traverse_func_t func, void *data, int maxdepth, unsigned int skip_flags);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_verify_graph(pkgconf_client_t *client, pkgconf_pkg_t *root, int depth);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags);
|
||||
PKGCONF_API const char *pkgconf_pkg_get_comparator(const pkgconf_dependency_t *pkgdep);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_cflags(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_libs(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth);
|
||||
PKGCONF_API pkgconf_pkg_comparator_t pkgconf_pkg_comparator_lookup_by_name(const char *name);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_builtin_pkg_get(const char *name);
|
||||
|
||||
PKGCONF_API int pkgconf_compare_version(const char *a, const char *b);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_scan_all(pkgconf_client_t *client, void *ptr, pkgconf_pkg_iteration_func_t func);
|
||||
|
||||
/* parse.c */
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_new_from_path(pkgconf_client_t *client, const char *path, unsigned int flags);
|
||||
PKGCONF_API void pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags);
|
||||
PKGCONF_API void pkgconf_dependency_parse(pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags);
|
||||
PKGCONF_API void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail);
|
||||
PKGCONF_API void pkgconf_dependency_free(pkgconf_list_t *list);
|
||||
PKGCONF_API void pkgconf_dependency_free_one(pkgconf_dependency_t *dep);
|
||||
PKGCONF_API pkgconf_dependency_t *pkgconf_dependency_add(pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare, unsigned int flags);
|
||||
PKGCONF_API pkgconf_dependency_t *pkgconf_dependency_ref(pkgconf_client_t *client, pkgconf_dependency_t *dep);
|
||||
PKGCONF_API void pkgconf_dependency_unref(pkgconf_client_t *client, pkgconf_dependency_t *dep);
|
||||
PKGCONF_API pkgconf_dependency_t *pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *dep);
|
||||
|
||||
/* argvsplit.c */
|
||||
PKGCONF_API int pkgconf_argv_split(const char *src, int *argc, char ***argv);
|
||||
PKGCONF_API void pkgconf_argv_free(char **argv);
|
||||
|
||||
/* fragment.c */
|
||||
typedef struct pkgconf_fragment_render_ops_ {
|
||||
size_t (*render_len)(const pkgconf_list_t *list, bool escape);
|
||||
void (*render_buf)(const pkgconf_list_t *list, char *buf, size_t len, bool escape);
|
||||
} pkgconf_fragment_render_ops_t;
|
||||
|
||||
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 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_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_delete(pkgconf_list_t *list, pkgconf_fragment_t *node);
|
||||
PKGCONF_API void pkgconf_fragment_free(pkgconf_list_t *list);
|
||||
PKGCONF_API void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func, void *data);
|
||||
PKGCONF_API size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops);
|
||||
PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t len, bool escape, const pkgconf_fragment_render_ops_t *ops);
|
||||
PKGCONF_API char *pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops);
|
||||
PKGCONF_API bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag);
|
||||
|
||||
/* tuple.c */
|
||||
PKGCONF_API pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *parent, const char *key, const char *value, bool parse, unsigned int flags);
|
||||
PKGCONF_API char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key);
|
||||
PKGCONF_API char *pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *list, const char *value, unsigned int flags);
|
||||
PKGCONF_API void pkgconf_tuple_free(pkgconf_list_t *list);
|
||||
PKGCONF_API void pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list);
|
||||
PKGCONF_API void pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value);
|
||||
PKGCONF_API char *pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key);
|
||||
PKGCONF_API void pkgconf_tuple_free_global(pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv);
|
||||
|
||||
/* queue.c */
|
||||
PKGCONF_API void pkgconf_queue_push(pkgconf_list_t *list, const char *package);
|
||||
PKGCONF_API bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list);
|
||||
PKGCONF_API bool pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_t *world, int maxdepth);
|
||||
PKGCONF_API void pkgconf_queue_free(pkgconf_list_t *list);
|
||||
PKGCONF_API bool pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data);
|
||||
PKGCONF_API bool pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, int maxdepth);
|
||||
PKGCONF_API void pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world);
|
||||
|
||||
/* cache.c */
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_cache_lookup(pkgconf_client_t *client, const char *id);
|
||||
PKGCONF_API void pkgconf_cache_add(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
|
||||
PKGCONF_API void pkgconf_cache_remove(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
|
||||
PKGCONF_API void pkgconf_cache_free(pkgconf_client_t *client);
|
||||
|
||||
/* audit.c */
|
||||
PKGCONF_API void pkgconf_audit_set_log(pkgconf_client_t *client, FILE *auditf);
|
||||
PKGCONF_API void pkgconf_audit_log(pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3);
|
||||
PKGCONF_API void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pkgconf_pkg_t *dep, const pkgconf_dependency_t *depnode);
|
||||
|
||||
/* path.c */
|
||||
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_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter);
|
||||
#ifdef _WIN32
|
||||
PKGCONF_API size_t pkgconf_path_build_from_registry(/* HKEY -> HANDLE -> PVOID */ void *hKey, pkgconf_list_t *dirlist, bool filter);
|
||||
#endif
|
||||
PKGCONF_API bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist);
|
||||
PKGCONF_API void pkgconf_path_free(pkgconf_list_t *dirlist);
|
||||
PKGCONF_API bool pkgconf_path_relocate(char *buf, size_t buflen);
|
||||
PKGCONF_API void pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src);
|
||||
PKGCONF_API void pkgconf_path_prepend_list(pkgconf_list_t *dst, const pkgconf_list_t *src);
|
||||
|
||||
/* buffer.c */
|
||||
typedef struct pkgconf_buffer_ {
|
||||
char *base;
|
||||
char *end;
|
||||
} pkgconf_buffer_t;
|
||||
|
||||
PKGCONF_API void pkgconf_buffer_append(pkgconf_buffer_t *buffer, const char *text);
|
||||
PKGCONF_API void pkgconf_buffer_push_byte(pkgconf_buffer_t *buffer, char byte);
|
||||
PKGCONF_API void pkgconf_buffer_trim_byte(pkgconf_buffer_t *buffer);
|
||||
PKGCONF_API void pkgconf_buffer_finalize(pkgconf_buffer_t *buffer);
|
||||
static inline const char *pkgconf_buffer_str(const pkgconf_buffer_t *buffer) {
|
||||
return buffer->base;
|
||||
}
|
||||
|
||||
static inline size_t pkgconf_buffer_len(const pkgconf_buffer_t *buffer) {
|
||||
return (size_t)(ptrdiff_t)(buffer->end - buffer->base);
|
||||
}
|
||||
|
||||
static inline char pkgconf_buffer_lastc(const pkgconf_buffer_t *buffer) {
|
||||
if (buffer->base == buffer->end)
|
||||
return '\0';
|
||||
|
||||
return *(buffer->end - 1);
|
||||
}
|
||||
|
||||
#define PKGCONF_BUFFER_INITIALIZER { NULL, NULL }
|
||||
|
||||
static inline void pkgconf_buffer_reset(pkgconf_buffer_t *buffer) {
|
||||
pkgconf_buffer_finalize(buffer);
|
||||
buffer->base = buffer->end = NULL;
|
||||
}
|
||||
|
||||
/* fileio.c */
|
||||
PKGCONF_API bool pkgconf_fgetline(pkgconf_buffer_t *buffer, FILE *stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
configure_file(input : 'config.h.meson',
|
||||
output : 'config.h',
|
||||
configuration : cdata)
|
||||
|
||||
|
||||
install_headers('libpkgconf.h',
|
||||
'stdinc.h',
|
||||
'iter.h',
|
||||
'bsdstubs.h',
|
||||
'libpkgconf-api.h',
|
||||
subdir : 'pkgconf/libpkgconf')
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* parser.c
|
||||
* rfc822 message parser
|
||||
*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/config.h>
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_pkg_t *pkgconf_pkg_new_from_file(const pkgconf_client_t *client, const char *filename, FILE *f)
|
||||
*
|
||||
* Parse a .pc file into a pkgconf_pkg_t object structure.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
* :param char* filename: The filename of the package file (including full path).
|
||||
* :param FILE* f: The file object to read from.
|
||||
* :returns: A ``pkgconf_pkg_t`` object which contains the package data.
|
||||
* :rtype: pkgconf_pkg_t *
|
||||
*/
|
||||
void
|
||||
pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, const char *filename)
|
||||
{
|
||||
pkgconf_buffer_t readbuf = PKGCONF_BUFFER_INITIALIZER;
|
||||
size_t lineno = 0;
|
||||
bool continue_reading = true;
|
||||
|
||||
while (continue_reading)
|
||||
{
|
||||
char op, *p, *key, *value;
|
||||
bool warned_key_whitespace = false, warned_value_whitespace = false;
|
||||
|
||||
continue_reading = pkgconf_fgetline(&readbuf, f);
|
||||
lineno++;
|
||||
|
||||
p = readbuf.base;
|
||||
if (p == NULL)
|
||||
continue;
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (*p && p != readbuf.base)
|
||||
{
|
||||
warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: whitespace encountered while parsing key section\n",
|
||||
filename, lineno);
|
||||
warned_key_whitespace = true;
|
||||
}
|
||||
key = p;
|
||||
while (*p && (isalpha((unsigned char)*p) || isdigit((unsigned char)*p) || *p == '_' || *p == '.'))
|
||||
p++;
|
||||
|
||||
if (!isalpha((unsigned char)*key) &&
|
||||
!isdigit((unsigned char)*p))
|
||||
{
|
||||
pkgconf_buffer_reset(&readbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
{
|
||||
if (!warned_key_whitespace)
|
||||
{
|
||||
warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: whitespace encountered while parsing key section\n",
|
||||
filename, lineno);
|
||||
warned_key_whitespace = true;
|
||||
}
|
||||
|
||||
/* set to null to avoid trailing spaces in key */
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
op = *p;
|
||||
if (*p != '\0')
|
||||
{
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
p++;
|
||||
|
||||
value = p;
|
||||
p = value + (strlen(value) - 1);
|
||||
while (*p && isspace((unsigned char) *p) && p > value)
|
||||
{
|
||||
if (!warned_value_whitespace && op == '=')
|
||||
{
|
||||
warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: trailing whitespace encountered while parsing value section\n",
|
||||
filename, lineno);
|
||||
warned_value_whitespace = true;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
p--;
|
||||
}
|
||||
if (ops[(unsigned char) op])
|
||||
ops[(unsigned char) op](data, lineno, key, value);
|
||||
|
||||
pkgconf_buffer_reset(&readbuf);
|
||||
}
|
||||
|
||||
pkgconf_buffer_finalize(&readbuf);
|
||||
}
|
||||
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
* path.c
|
||||
* filesystem path management
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/config.h>
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
#if defined(HAVE_SYS_STAT_H) && ! defined(_WIN32)
|
||||
# include <sys/stat.h>
|
||||
# define PKGCONF_CACHE_INODES
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define PKG_CONFIG_REG_KEY "Software\\pkgconfig\\PKG_CONFIG_PATH"
|
||||
#endif
|
||||
|
||||
static bool
|
||||
#ifdef PKGCONF_CACHE_INODES
|
||||
path_list_contains_entry(const char *text, pkgconf_list_t *dirlist, struct stat *st)
|
||||
#else
|
||||
path_list_contains_entry(const char *text, pkgconf_list_t *dirlist)
|
||||
#endif
|
||||
{
|
||||
pkgconf_node_t *n;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(dirlist->head, n)
|
||||
{
|
||||
pkgconf_path_t *pn = n->data;
|
||||
|
||||
#ifdef PKGCONF_CACHE_INODES
|
||||
if (pn->handle_device == (void *)(intptr_t)st->st_dev && pn->handle_path == (void *)(intptr_t)st->st_ino)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (!strcmp(text, pn->path))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `path` module
|
||||
* ========================
|
||||
*
|
||||
* The `path` module provides functions for manipulating lists of paths in a cross-platform manner. Notably,
|
||||
* it is used by the `pkgconf client` to parse the ``PKG_CONFIG_PATH``, ``PKG_CONFIG_LIBDIR`` and related environment
|
||||
* 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));
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
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
|
||||
*
|
||||
* .. c:function:: void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist)
|
||||
*
|
||||
* Adds 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_add(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_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
|
||||
*
|
||||
* .. c:function:: size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist)
|
||||
*
|
||||
* Splits a given text input and inserts paths into a path list.
|
||||
*
|
||||
* :param char* text: The path text to split and add as path nodes.
|
||||
* :param pkgconf_list_t* dirlist: The path list to have the path nodes added to.
|
||||
* :param bool filter: Whether to perform duplicate filtering.
|
||||
* :return: number of path nodes added to the path list
|
||||
* :rtype: size_t
|
||||
*/
|
||||
size_t
|
||||
pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter)
|
||||
{
|
||||
size_t count = 0;
|
||||
char *workbuf, *p, *iter;
|
||||
|
||||
if (text == NULL)
|
||||
return 0;
|
||||
|
||||
iter = workbuf = strdup(text);
|
||||
while ((p = strtok(iter, PKG_CONFIG_PATH_SEP_S)) != NULL)
|
||||
{
|
||||
pkgconf_path_add(p, dirlist, filter);
|
||||
|
||||
count++, iter = NULL;
|
||||
}
|
||||
free(workbuf);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist)
|
||||
*
|
||||
* Adds the paths specified in an environment variable to a path list. If the environment variable is not set,
|
||||
* an optional default set of paths is added.
|
||||
*
|
||||
* :param char* envvarname: The environment variable to look up.
|
||||
* :param char* fallback: The fallback paths to use if the environment variable is not set.
|
||||
* :param pkgconf_list_t* dirlist: The path list to add the path nodes to.
|
||||
* :param bool filter: Whether to perform duplicate filtering.
|
||||
* :return: number of path nodes added to the path list
|
||||
* :rtype: size_t
|
||||
*/
|
||||
size_t
|
||||
pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter)
|
||||
{
|
||||
const char *data;
|
||||
|
||||
data = getenv(envvarname);
|
||||
if (data != NULL)
|
||||
return pkgconf_path_split(data, dirlist, filter);
|
||||
|
||||
if (fallback != NULL)
|
||||
return pkgconf_path_split(fallback, dirlist, filter);
|
||||
|
||||
/* no fallback and no environment variable, thusly no nodes added */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist)
|
||||
*
|
||||
* Checks whether a path has a matching prefix in a path list.
|
||||
*
|
||||
* :param char* path: The path to check against a path list.
|
||||
* :param pkgconf_list_t* dirlist: The path list to check the path against.
|
||||
* :return: true if the path list has a matching prefix, otherwise false
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist)
|
||||
{
|
||||
pkgconf_node_t *n = NULL;
|
||||
char relocated[PKGCONF_ITEM_SIZE];
|
||||
const char *cpath = path;
|
||||
|
||||
pkgconf_strlcpy(relocated, path, sizeof relocated);
|
||||
if (pkgconf_path_relocate(relocated, sizeof relocated))
|
||||
cpath = relocated;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(dirlist->head, n)
|
||||
{
|
||||
pkgconf_path_t *pnode = n->data;
|
||||
|
||||
if (!strcmp(pnode->path, cpath))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
*
|
||||
* Copies a path list to another path list.
|
||||
*
|
||||
* :param pkgconf_list_t* dst: The path list to copy to.
|
||||
* :param pkgconf_list_t* src: The path list to copy from.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
{
|
||||
pkgconf_node_t *n;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(src->head, n)
|
||||
{
|
||||
pkgconf_path_t *srcpath = n->data, *path;
|
||||
|
||||
path = calloc(1, sizeof(pkgconf_path_t));
|
||||
if (path == NULL)
|
||||
continue;
|
||||
|
||||
path->path = strdup(srcpath->path);
|
||||
|
||||
#ifdef PKGCONF_CACHE_INODES
|
||||
path->handle_path = srcpath->handle_path;
|
||||
path->handle_device = srcpath->handle_device;
|
||||
#endif
|
||||
|
||||
pkgconf_node_insert_tail(&path->lnode, path, dst);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_path_prepend_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
*
|
||||
* Copies a path list to another path list.
|
||||
*
|
||||
* :param pkgconf_list_t* dst: The path list to copy to.
|
||||
* :param pkgconf_list_t* src: The path list to copy from.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_path_prepend_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
{
|
||||
pkgconf_node_t *n;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(src->head, n)
|
||||
{
|
||||
pkgconf_path_t *srcpath = n->data, *path;
|
||||
|
||||
path = calloc(1, sizeof(pkgconf_path_t));
|
||||
if (path == NULL)
|
||||
continue;
|
||||
|
||||
path->path = strdup(srcpath->path);
|
||||
|
||||
#ifdef PKGCONF_CACHE_INODES
|
||||
path->handle_path = srcpath->handle_path;
|
||||
path->handle_device = srcpath->handle_device;
|
||||
#endif
|
||||
|
||||
pkgconf_node_insert(&path->lnode, path, dst);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_path_free(pkgconf_list_t *dirlist)
|
||||
*
|
||||
* Releases any path nodes attached to the given path list.
|
||||
*
|
||||
* :param pkgconf_list_t* dirlist: The path list to clean up.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_path_free(pkgconf_list_t *dirlist)
|
||||
{
|
||||
pkgconf_node_t *n, *tn;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(dirlist->head, tn, n)
|
||||
{
|
||||
pkgconf_path_t *pnode = n->data;
|
||||
|
||||
free(pnode->path);
|
||||
free(pnode);
|
||||
}
|
||||
|
||||
pkgconf_list_zero(dirlist);
|
||||
}
|
||||
|
||||
static char *
|
||||
normpath(const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
char *copy = strdup(path);
|
||||
if (NULL == copy)
|
||||
return NULL;
|
||||
char *ptr = copy;
|
||||
|
||||
for (int ii = 0; copy[ii]; ii++)
|
||||
{
|
||||
*ptr++ = path[ii];
|
||||
if ('/' == path[ii])
|
||||
{
|
||||
ii++;
|
||||
while ('/' == path[ii])
|
||||
ii++;
|
||||
ii--;
|
||||
}
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_path_relocate(char *buf, size_t buflen)
|
||||
*
|
||||
* Relocates a path, possibly calling normpath() on it.
|
||||
*
|
||||
* :param char* buf: The path to relocate.
|
||||
* :param size_t buflen: The buffer length the path is contained in.
|
||||
* :return: true on success, false on error
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_path_relocate(char *buf, size_t buflen)
|
||||
{
|
||||
char *tmpbuf;
|
||||
|
||||
if ((tmpbuf = normpath(buf)) != NULL)
|
||||
{
|
||||
size_t tmpbuflen = strlen(tmpbuf);
|
||||
if (tmpbuflen > buflen)
|
||||
{
|
||||
free(tmpbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
pkgconf_strlcpy(buf, tmpbuf, buflen);
|
||||
free(tmpbuf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_path_build_from_registry(HKEY hKey, pkgconf_list_t *dir_list, bool filter)
|
||||
*
|
||||
* Adds paths to a directory list discovered from a given registry key.
|
||||
*
|
||||
* :param HKEY hKey: The registry key to enumerate.
|
||||
* :param pkgconf_list_t* dir_list: The directory list to append enumerated paths to.
|
||||
* :param bool filter: Whether duplicate paths should be filtered.
|
||||
* :return: number of path nodes added to the list
|
||||
* :rtype: size_t
|
||||
*/
|
||||
size_t
|
||||
pkgconf_path_build_from_registry(void *hKey, pkgconf_list_t *dir_list, bool filter)
|
||||
{
|
||||
HKEY key;
|
||||
int i = 0;
|
||||
size_t added = 0;
|
||||
|
||||
char buf[16384]; /* per registry limits */
|
||||
DWORD bufsize = sizeof buf;
|
||||
if (RegOpenKeyEx(hKey, PKG_CONFIG_REG_KEY,
|
||||
0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
return 0;
|
||||
|
||||
while (RegEnumValue(key, i++, buf, &bufsize, NULL, NULL, NULL, NULL)
|
||||
== ERROR_SUCCESS)
|
||||
{
|
||||
char pathbuf[PKGCONF_ITEM_SIZE];
|
||||
DWORD type;
|
||||
DWORD pathbuflen = sizeof pathbuf;
|
||||
|
||||
if (RegQueryValueEx(key, buf, NULL, &type, (LPBYTE) pathbuf, &pathbuflen)
|
||||
== ERROR_SUCCESS && type == REG_SZ)
|
||||
{
|
||||
pkgconf_path_add(pathbuf, dir_list, filter);
|
||||
added++;
|
||||
}
|
||||
|
||||
bufsize = sizeof buf;
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
return added;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* personality.c
|
||||
* libpkgconf cross-compile personality database
|
||||
*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/config.h>
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `personality` module
|
||||
* =========================
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Increment each time the default personality is inited, decrement each time
|
||||
* it's deinited. Whenever it is 0, then the deinit frees the personality. In
|
||||
* that case an additional call to init will create it anew.
|
||||
*/
|
||||
static unsigned default_personality_init = 0;
|
||||
|
||||
static pkgconf_cross_personality_t default_personality = {
|
||||
.name = "default",
|
||||
};
|
||||
|
||||
static inline void
|
||||
build_default_search_path(pkgconf_list_t* dirlist)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char namebuf[MAX_PATH];
|
||||
char outbuf[MAX_PATH];
|
||||
char *p;
|
||||
|
||||
int sizepath = GetModuleFileName(NULL, namebuf, sizeof namebuf);
|
||||
char * winslash;
|
||||
namebuf[sizepath] = '\0';
|
||||
while ((winslash = strchr (namebuf, '\\')) != NULL)
|
||||
{
|
||||
*winslash = '/';
|
||||
}
|
||||
p = strrchr(namebuf, '/');
|
||||
if (p == NULL)
|
||||
pkgconf_path_split(PKG_DEFAULT_PATH, dirlist, true);
|
||||
|
||||
*p = '\0';
|
||||
pkgconf_strlcpy(outbuf, namebuf, sizeof outbuf);
|
||||
pkgconf_strlcat(outbuf, "/", sizeof outbuf);
|
||||
pkgconf_strlcat(outbuf, "../lib/pkgconfig", sizeof outbuf);
|
||||
pkgconf_path_add(outbuf, dirlist, true);
|
||||
pkgconf_strlcpy(outbuf, namebuf, sizeof outbuf);
|
||||
pkgconf_strlcat(outbuf, "/", sizeof outbuf);
|
||||
pkgconf_strlcat(outbuf, "../share/pkgconfig", sizeof outbuf);
|
||||
pkgconf_path_add(outbuf, dirlist, true);
|
||||
#elif __HAIKU__
|
||||
char **paths;
|
||||
size_t count;
|
||||
if (find_paths(B_FIND_PATH_DEVELOP_LIB_DIRECTORY, "pkgconfig", &paths, &count) == B_OK) {
|
||||
for (size_t i = 0; i < count; i++)
|
||||
pkgconf_path_add(paths[i], dirlist, true);
|
||||
free(paths);
|
||||
paths = NULL;
|
||||
}
|
||||
if (find_paths(B_FIND_PATH_DATA_DIRECTORY, "pkgconfig", &paths, &count) == B_OK) {
|
||||
for (size_t i = 0; i < count; i++)
|
||||
pkgconf_path_add(paths[i], dirlist, true);
|
||||
free(paths);
|
||||
paths = NULL;
|
||||
}
|
||||
#else
|
||||
pkgconf_path_split(PKG_DEFAULT_PATH, dirlist, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const pkgconf_cross_personality_t *pkgconf_cross_personality_default(void)
|
||||
*
|
||||
* Returns the default cross-compile personality.
|
||||
*
|
||||
* Not thread safe.
|
||||
*
|
||||
* :rtype: pkgconf_cross_personality_t*
|
||||
* :return: the default cross-compile personality
|
||||
*/
|
||||
pkgconf_cross_personality_t *
|
||||
pkgconf_cross_personality_default(void)
|
||||
{
|
||||
if (default_personality_init) {
|
||||
++default_personality_init;
|
||||
return &default_personality;
|
||||
}
|
||||
|
||||
build_default_search_path(&default_personality.dir_list);
|
||||
|
||||
pkgconf_path_split(SYSTEM_LIBDIR, &default_personality.filter_libdirs, false);
|
||||
pkgconf_path_split(SYSTEM_INCLUDEDIR, &default_personality.filter_includedirs, false);
|
||||
|
||||
++default_personality_init;
|
||||
return &default_personality;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *)
|
||||
*
|
||||
* Destroys a cross personality object and/or decreases the reference count on the
|
||||
* default cross personality object.
|
||||
*
|
||||
* Not thread safe.
|
||||
*
|
||||
* :rtype: void
|
||||
*/
|
||||
void
|
||||
pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *personality)
|
||||
{
|
||||
/* allow NULL parameter for API backwards compatibility */
|
||||
if (personality == NULL)
|
||||
return;
|
||||
|
||||
/* XXX: this hack is rather ugly, but it works for now... */
|
||||
if (personality == &default_personality && --default_personality_init > 0)
|
||||
return;
|
||||
|
||||
pkgconf_path_free(&personality->dir_list);
|
||||
pkgconf_path_free(&personality->filter_libdirs);
|
||||
pkgconf_path_free(&personality->filter_includedirs);
|
||||
|
||||
if (personality->sysroot_dir != NULL)
|
||||
free(personality->sysroot_dir);
|
||||
|
||||
if (personality == &default_personality)
|
||||
return;
|
||||
|
||||
if (personality->name != NULL)
|
||||
free(personality->name);
|
||||
|
||||
free(personality);
|
||||
}
|
||||
|
||||
#ifndef PKGCONF_LITE
|
||||
static bool
|
||||
valid_triplet(const char *triplet)
|
||||
{
|
||||
const char *c = triplet;
|
||||
|
||||
for (; *c; c++)
|
||||
if (!isalnum((unsigned char)*c) && *c != '-' && *c != '_')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef void (*personality_keyword_func_t)(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value);
|
||||
typedef struct {
|
||||
const char *keyword;
|
||||
const personality_keyword_func_t func;
|
||||
const ptrdiff_t offset;
|
||||
} personality_keyword_pair_t;
|
||||
|
||||
static void
|
||||
personality_bool_func(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
|
||||
bool *dest = (bool *)((char *) p + offset);
|
||||
*dest = strcasecmp(value, "true") || strcasecmp(value, "yes") || *value == '1';
|
||||
}
|
||||
|
||||
static void
|
||||
personality_copy_func(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
|
||||
char **dest = (char **)((char *) p + offset);
|
||||
*dest = strdup(value);
|
||||
}
|
||||
|
||||
static void
|
||||
personality_fragment_func(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
|
||||
pkgconf_list_t *dest = (pkgconf_list_t *)((char *) p + offset);
|
||||
pkgconf_path_split(value, dest, false);
|
||||
}
|
||||
|
||||
/* keep in alphabetical order! */
|
||||
static const personality_keyword_pair_t personality_keyword_pairs[] = {
|
||||
{"DefaultSearchPaths", personality_fragment_func, offsetof(pkgconf_cross_personality_t, dir_list)},
|
||||
{"SysrootDir", personality_copy_func, offsetof(pkgconf_cross_personality_t, sysroot_dir)},
|
||||
{"SystemIncludePaths", personality_fragment_func, offsetof(pkgconf_cross_personality_t, filter_includedirs)},
|
||||
{"SystemLibraryPaths", personality_fragment_func, offsetof(pkgconf_cross_personality_t, filter_libdirs)},
|
||||
{"Triplet", personality_copy_func, offsetof(pkgconf_cross_personality_t, name)},
|
||||
{"WantDefaultPure", personality_bool_func, offsetof(pkgconf_cross_personality_t, want_default_pure)},
|
||||
{"WantDefaultStatic", personality_bool_func, offsetof(pkgconf_cross_personality_t, want_default_static)},
|
||||
};
|
||||
|
||||
static int
|
||||
personality_keyword_pair_cmp(const void *key, const void *ptr)
|
||||
{
|
||||
const personality_keyword_pair_t *pair = ptr;
|
||||
return strcasecmp(key, pair->keyword);
|
||||
}
|
||||
|
||||
static void
|
||||
personality_keyword_set(pkgconf_cross_personality_t *p, const size_t lineno, const char *keyword, char *value)
|
||||
{
|
||||
const personality_keyword_pair_t *pair = bsearch(keyword,
|
||||
personality_keyword_pairs, PKGCONF_ARRAY_SIZE(personality_keyword_pairs),
|
||||
sizeof(personality_keyword_pair_t), personality_keyword_pair_cmp);
|
||||
|
||||
if (pair == NULL || pair->func == NULL)
|
||||
return;
|
||||
|
||||
pair->func(p, keyword, lineno, pair->offset, value);
|
||||
}
|
||||
|
||||
static const pkgconf_parser_operand_func_t personality_parser_ops[256] = {
|
||||
[':'] = (pkgconf_parser_operand_func_t) personality_keyword_set
|
||||
};
|
||||
|
||||
static void personality_warn_func(void *p, const char *fmt, ...) PRINTFLIKE(2, 3);
|
||||
|
||||
static void
|
||||
personality_warn_func(void *p, const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
(void) p;
|
||||
|
||||
va_start(va, fmt);
|
||||
vfprintf(stderr, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static pkgconf_cross_personality_t *
|
||||
load_personality_with_path(const char *path, const char *triplet, bool datadir)
|
||||
{
|
||||
char pathbuf[PKGCONF_ITEM_SIZE];
|
||||
FILE *f;
|
||||
pkgconf_cross_personality_t *p;
|
||||
|
||||
/* if triplet is null, assume that path is a direct path to the personality file */
|
||||
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);
|
||||
|
||||
p = calloc(1, sizeof(pkgconf_cross_personality_t));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
if (triplet != NULL)
|
||||
p->name = strdup(triplet);
|
||||
|
||||
f = fopen(pathbuf, "r");
|
||||
if (f == NULL) {
|
||||
pkgconf_cross_personality_deinit(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkgconf_parser_parse(f, p, personality_parser_ops, personality_warn_func, pathbuf);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_cross_personality_t *pkgconf_cross_personality_find(const char *triplet)
|
||||
*
|
||||
* Attempts to find a cross-compile personality given a triplet.
|
||||
*
|
||||
* :rtype: pkgconf_cross_personality_t*
|
||||
* :return: the default cross-compile personality
|
||||
*/
|
||||
pkgconf_cross_personality_t *
|
||||
pkgconf_cross_personality_find(const char *triplet)
|
||||
{
|
||||
pkgconf_list_t plist = PKGCONF_LIST_INITIALIZER;
|
||||
pkgconf_node_t *n;
|
||||
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);
|
||||
if (out != NULL)
|
||||
return out;
|
||||
|
||||
if (!valid_triplet(triplet))
|
||||
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_FOREACH_LIST_ENTRY(plist.head, n)
|
||||
{
|
||||
pkgconf_path_t *pn = n->data;
|
||||
|
||||
out = load_personality_with_path(pn->path, triplet, false);
|
||||
if (out != NULL)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
finish:
|
||||
pkgconf_path_free(&plist);
|
||||
return out != NULL ? out : pkgconf_cross_personality_default();
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* queue.c
|
||||
* compilation of a list of packages into a world dependency set
|
||||
*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `queue` module
|
||||
* =========================
|
||||
*
|
||||
* The `queue` module provides an interface that allows easily building a dependency graph from an
|
||||
* arbitrary set of dependencies. It also provides support for doing "preflight" checks on the entire
|
||||
* dependency graph prior to working with it.
|
||||
*
|
||||
* Using the `queue` module functions is the recommended way of working with dependency graphs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_queue_push(pkgconf_list_t *list, const char *package)
|
||||
*
|
||||
* Pushes a requested dependency onto the dependency resolver's queue.
|
||||
*
|
||||
* :param pkgconf_list_t* list: the dependency resolution queue to add the package request to.
|
||||
* :param char* package: the dependency atom requested
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_queue_push(pkgconf_list_t *list, const char *package)
|
||||
{
|
||||
pkgconf_queue_t *pkgq = calloc(1, sizeof(pkgconf_queue_t));
|
||||
|
||||
pkgq->package = strdup(package);
|
||||
pkgconf_node_insert_tail(&pkgq->iter, pkgq, list);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list)
|
||||
*
|
||||
* Compile a dependency resolution queue into a dependency resolution problem if possible, otherwise report an error.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
* :param pkgconf_pkg_t* world: The designated root of the dependency graph.
|
||||
* :param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
* :return: true if the built dependency resolution problem is consistent, else false
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_t *iter;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, iter)
|
||||
{
|
||||
pkgconf_queue_t *pkgq;
|
||||
|
||||
pkgq = iter->data;
|
||||
pkgconf_dependency_parse(client, world, &world->required, pkgq->package, PKGCONF_PKG_DEPF_QUERY);
|
||||
}
|
||||
|
||||
return (world->required.head != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_queue_free(pkgconf_list_t *list)
|
||||
*
|
||||
* Release any memory related to a dependency resolution queue.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The dependency resolution queue to release.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_queue_free(pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_t *node, *tnode;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, tnode, node)
|
||||
{
|
||||
pkgconf_queue_t *pkgq = node->data;
|
||||
|
||||
free(pkgq->package);
|
||||
free(pkgq);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pkgconf_queue_mark_public(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
|
||||
{
|
||||
if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE)
|
||||
{
|
||||
pkgconf_list_t *list = data;
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
if (dep->match == pkg)
|
||||
dep->flags &= ~PKGCONF_PKG_DEPF_PRIVATE;
|
||||
}
|
||||
|
||||
pkg->flags &= ~PKGCONF_PKG_PROPF_VISITED_PRIVATE;
|
||||
|
||||
PKGCONF_TRACE(client, "%s: updated, public", pkg->id);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client,
|
||||
pkgconf_pkg_t *root,
|
||||
void *data,
|
||||
int maxdepth);
|
||||
|
||||
static inline unsigned int
|
||||
pkgconf_queue_collect_dependencies_walk(pkgconf_client_t *client,
|
||||
pkgconf_list_t *deplist,
|
||||
void *data,
|
||||
int depth)
|
||||
{
|
||||
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
|
||||
pkgconf_node_t *node;
|
||||
pkgconf_pkg_t *world = data;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_REVERSE(deplist->tail, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_dependency_t *flattened_dep;
|
||||
pkgconf_pkg_t *pkg = dep->match;
|
||||
|
||||
if (*dep->package == '\0')
|
||||
continue;
|
||||
|
||||
if (pkg == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pkg->serial == client->serial)
|
||||
continue;
|
||||
|
||||
if (client->flags & PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE)
|
||||
pkg->flags |= PKGCONF_PKG_PROPF_VISITED_PRIVATE;
|
||||
else
|
||||
pkg->flags &= ~PKGCONF_PKG_PROPF_VISITED_PRIVATE;
|
||||
|
||||
eflags |= pkgconf_queue_collect_dependencies_main(client, pkg, data, depth - 1);
|
||||
|
||||
flattened_dep = pkgconf_dependency_copy(client, dep);
|
||||
pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required);
|
||||
}
|
||||
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client,
|
||||
pkgconf_pkg_t *root,
|
||||
void *data,
|
||||
int maxdepth)
|
||||
{
|
||||
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
|
||||
|
||||
if (maxdepth == 0)
|
||||
return eflags;
|
||||
|
||||
/* Short-circuit if we have already visited this node.
|
||||
*/
|
||||
if (root->serial == client->serial)
|
||||
return eflags;
|
||||
|
||||
root->serial = client->serial;
|
||||
|
||||
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
|
||||
pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth)
|
||||
{
|
||||
unsigned int result;
|
||||
const unsigned int saved_flags = client->flags;
|
||||
pkgconf_pkg_t initial_world = {
|
||||
.id = "user:request",
|
||||
.realname = "virtual world package",
|
||||
.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
|
||||
};
|
||||
|
||||
if (!pkgconf_queue_compile(client, &initial_world, list))
|
||||
{
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
return PKGCONF_PKG_ERRF_DEPGRAPH_BREAK;
|
||||
}
|
||||
|
||||
PKGCONF_TRACE(client, "solving");
|
||||
result = pkgconf_pkg_traverse(client, &initial_world, NULL, NULL, maxdepth, 0);
|
||||
if (result != PKGCONF_PKG_ERRF_OK)
|
||||
{
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
return result;
|
||||
}
|
||||
|
||||
PKGCONF_TRACE(client, "flattening");
|
||||
result = pkgconf_queue_collect_dependencies(client, &initial_world, world, maxdepth);
|
||||
if (result != PKGCONF_PKG_ERRF_OK)
|
||||
{
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
|
||||
{
|
||||
PKGCONF_TRACE(client, "marking public deps");
|
||||
client->flags &= ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
|
||||
client->flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS;
|
||||
result = pkgconf_pkg_traverse(client, &initial_world, pkgconf_queue_mark_public, &world->required, maxdepth, 0);
|
||||
client->flags = saved_flags;
|
||||
if (result != PKGCONF_PKG_ERRF_OK)
|
||||
{
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* free the initial solution */
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
|
||||
return PKGCONF_PKG_ERRF_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth)
|
||||
*
|
||||
* Removes references to package nodes contained in a solution.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
* :param pkgconf_pkg_t* world: The root for the generated dependency graph. Should have PKGCONF_PKG_PROPF_VIRTUAL flag.
|
||||
* :returns: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world)
|
||||
{
|
||||
(void) client;
|
||||
|
||||
if (world->flags & PKGCONF_PKG_PROPF_VIRTUAL)
|
||||
{
|
||||
pkgconf_dependency_free(&world->required);
|
||||
pkgconf_dependency_free(&world->requires_private);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_t *world, int maxdepth)
|
||||
*
|
||||
* Solves and flattens the dependency graph for the supplied dependency list.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
* :param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
* :param pkgconf_pkg_t* world: The root for the generated dependency graph, provided by the caller. Should have PKGCONF_PKG_PROPF_VIRTUAL flag.
|
||||
* :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
|
||||
* :returns: true if the dependency resolver found a solution, otherwise false.
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_t *world, int maxdepth)
|
||||
{
|
||||
/* if maxdepth is one, then we will not traverse deeper than our virtual package. */
|
||||
if (!maxdepth)
|
||||
maxdepth = -1;
|
||||
|
||||
unsigned int flags = client->flags;
|
||||
client->flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
|
||||
|
||||
unsigned int ret = pkgconf_queue_verify(client, world, list, maxdepth);
|
||||
client->flags = flags;
|
||||
|
||||
return ret == PKGCONF_PKG_ERRF_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
|
||||
*
|
||||
* Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem and
|
||||
* feed the solution to a callback function if a complete dependency graph is found.
|
||||
*
|
||||
* This function should not be used in new code. Use pkgconf_queue_solve instead.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
* :param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
* :param pkgconf_queue_apply_func_t func: The callback function to call if a solution is found by the dependency resolver.
|
||||
* :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
|
||||
* :param void* data: An opaque pointer which is passed to the callback function.
|
||||
* :returns: true if the dependency resolver found a solution, otherwise false.
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
|
||||
{
|
||||
bool ret = false;
|
||||
pkgconf_pkg_t world = {
|
||||
.id = "virtual:world",
|
||||
.realname = "virtual world package",
|
||||
.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
|
||||
};
|
||||
|
||||
/* if maxdepth is one, then we will not traverse deeper than our virtual package. */
|
||||
if (!maxdepth)
|
||||
maxdepth = -1;
|
||||
|
||||
if (!pkgconf_queue_solve(client, list, &world, maxdepth))
|
||||
goto cleanup;
|
||||
|
||||
/* the world dependency set is flattened after it is returned from pkgconf_queue_verify */
|
||||
if (!func(client, &world, data, maxdepth))
|
||||
goto cleanup;
|
||||
|
||||
ret = true;
|
||||
|
||||
cleanup:
|
||||
pkgconf_pkg_free(client, &world);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
|
||||
*
|
||||
* Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
* :param pkgconf_list_t* list: The list of dependency requests to consider.
|
||||
* :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
|
||||
* :returns: true if the dependency resolver found a solution, otherwise false.
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, int maxdepth)
|
||||
{
|
||||
bool retval = true;
|
||||
pkgconf_pkg_t world = {
|
||||
.id = "virtual:world",
|
||||
.realname = "virtual world package",
|
||||
.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
|
||||
};
|
||||
|
||||
/* if maxdepth is one, then we will not traverse deeper than our virtual package. */
|
||||
if (!maxdepth)
|
||||
maxdepth = -1;
|
||||
|
||||
if (pkgconf_queue_verify(client, &world, list, maxdepth) != PKGCONF_PKG_ERRF_OK)
|
||||
retval = false;
|
||||
|
||||
pkgconf_pkg_free(client, &world);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* stdinc.h
|
||||
* pull in standard headers (including portability hacks)
|
||||
*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef LIBPKGCONF_STDINC_H
|
||||
#define LIBPKGCONF_STDINC_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <malloc.h>
|
||||
# define PATH_DEV_NULL "nul"
|
||||
# ifdef _WIN64
|
||||
# ifndef __MINGW32__
|
||||
# define SIZE_FMT_SPECIFIER "%I64u"
|
||||
# else
|
||||
# define SIZE_FMT_SPECIFIER "%llu"
|
||||
# endif
|
||||
# else
|
||||
# define SIZE_FMT_SPECIFIER "%u"
|
||||
# endif
|
||||
# ifndef ssize_t
|
||||
# ifndef __MINGW32__
|
||||
# include <BaseTsd.h>
|
||||
# else
|
||||
# include <basetsd.h>
|
||||
# endif
|
||||
# define ssize_t SSIZE_T
|
||||
# endif
|
||||
# ifndef __MINGW32__
|
||||
# include "win-dirent.h"
|
||||
# else
|
||||
# include <dirent.h>
|
||||
# endif
|
||||
# define PKGCONF_ITEM_SIZE (_MAX_PATH + 1024)
|
||||
#else
|
||||
# define PATH_DEV_NULL "/dev/null"
|
||||
# define SIZE_FMT_SPECIFIER "%zu"
|
||||
# ifdef __HAIKU__
|
||||
# include <FindDirectory.h>
|
||||
# endif
|
||||
# include <dirent.h>
|
||||
# include <unistd.h>
|
||||
# include <limits.h>
|
||||
# include <strings.h>
|
||||
# ifdef PATH_MAX
|
||||
# define PKGCONF_ITEM_SIZE (PATH_MAX + 1024)
|
||||
# else
|
||||
# define PKGCONF_ITEM_SIZE (4096 + 1024)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* tuple.c
|
||||
* management of key->value tuples
|
||||
*
|
||||
* Copyright (c) 2011, 2012 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.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `tuple` module
|
||||
* =========================
|
||||
*
|
||||
* The `tuple` module provides key-value mappings backed by a linked list. The key-value
|
||||
* mapping is mainly used for variable substitution when parsing .pc files.
|
||||
*
|
||||
* There are two sets of mappings: a ``pkgconf_pkg_t`` specific mapping, and a `global` mapping.
|
||||
* The `tuple` module provides convenience wrappers for managing the `global` mapping, which is
|
||||
* attached to a given client object.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value)
|
||||
*
|
||||
* Defines a global variable, replacing the previous declaration if one was set.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to modify.
|
||||
* :param char* key: The key for the mapping (variable name).
|
||||
* :param char* value: The value for the mapped entry.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_tuple_add_global(pkgconf_client_t *client, const char *key, const char *value)
|
||||
{
|
||||
pkgconf_tuple_add(client, &client->global_vars, key, value, false, 0);
|
||||
}
|
||||
|
||||
static pkgconf_tuple_t *
|
||||
lookup_global_tuple(const pkgconf_client_t *client, const char *key)
|
||||
{
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(client->global_vars.head, node)
|
||||
{
|
||||
pkgconf_tuple_t *tuple = node->data;
|
||||
|
||||
if (!strcmp(tuple->key, key))
|
||||
return tuple;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key)
|
||||
*
|
||||
* Looks up a global variable.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
* :param char* key: The key or variable name to look up.
|
||||
* :return: the contents of the variable or ``NULL``
|
||||
* :rtype: char *
|
||||
*/
|
||||
char *
|
||||
pkgconf_tuple_find_global(const pkgconf_client_t *client, const char *key)
|
||||
{
|
||||
pkgconf_tuple_t *tuple;
|
||||
|
||||
tuple = lookup_global_tuple(client, key);
|
||||
if (tuple == NULL)
|
||||
return NULL;
|
||||
|
||||
return tuple->value;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_tuple_free_global(pkgconf_client_t *client)
|
||||
*
|
||||
* Delete all global variables associated with a pkgconf client object.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to modify.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_tuple_free_global(pkgconf_client_t *client)
|
||||
{
|
||||
pkgconf_tuple_free(&client->global_vars);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv)
|
||||
*
|
||||
* Parse and define a global variable.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to modify.
|
||||
* :param char* kv: The variable in the form of ``key=value``.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_tuple_define_global(pkgconf_client_t *client, const char *kv)
|
||||
{
|
||||
char *workbuf = strdup(kv);
|
||||
char *value;
|
||||
pkgconf_tuple_t *tuple;
|
||||
|
||||
value = strchr(workbuf, '=');
|
||||
if (value == NULL)
|
||||
goto out;
|
||||
|
||||
*value++ = '\0';
|
||||
|
||||
tuple = pkgconf_tuple_add(client, &client->global_vars, workbuf, value, false, 0);
|
||||
if (tuple != NULL)
|
||||
tuple->flags = PKGCONF_PKG_TUPLEF_OVERRIDE;
|
||||
|
||||
out:
|
||||
free(workbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
pkgconf_tuple_find_delete(pkgconf_list_t *list, const char *key)
|
||||
{
|
||||
pkgconf_node_t *node, *next;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node)
|
||||
{
|
||||
pkgconf_tuple_t *tuple = node->data;
|
||||
|
||||
if (!strcmp(tuple->key, key))
|
||||
{
|
||||
pkgconf_tuple_free_entry(tuple, list);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
dequote(const char *value)
|
||||
{
|
||||
char *buf = calloc(1, (strlen(value) + 1) * 2);
|
||||
char *bptr = buf;
|
||||
const char *i;
|
||||
char quote = 0;
|
||||
|
||||
if (*value == '\'' || *value == '"')
|
||||
quote = *value;
|
||||
|
||||
for (i = value; *i != '\0'; i++)
|
||||
{
|
||||
if (*i == '\\' && quote && *(i + 1) == quote)
|
||||
{
|
||||
i++;
|
||||
*bptr++ = *i;
|
||||
}
|
||||
else if (*i != quote)
|
||||
*bptr++ = *i;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *
|
||||
find_sysroot(const pkgconf_client_t *client, pkgconf_list_t *vars)
|
||||
{
|
||||
const char *sysroot_dir;
|
||||
|
||||
sysroot_dir = pkgconf_tuple_find(client, vars, "pc_sysrootdir");
|
||||
if (sysroot_dir == NULL)
|
||||
sysroot_dir = client->sysroot_dir;
|
||||
|
||||
return sysroot_dir;
|
||||
}
|
||||
|
||||
static bool
|
||||
should_rewrite_sysroot(const pkgconf_client_t *client, pkgconf_list_t *vars, const char *buf, unsigned int flags)
|
||||
{
|
||||
const char *sysroot_dir;
|
||||
|
||||
if (flags & PKGCONF_PKG_PROPF_UNINSTALLED && !(client->flags & PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES))
|
||||
return false;
|
||||
|
||||
sysroot_dir = find_sysroot(client, vars);
|
||||
if (sysroot_dir == NULL)
|
||||
return false;
|
||||
|
||||
if (*buf != '/')
|
||||
return false;
|
||||
|
||||
if (!strcmp(sysroot_dir, "/"))
|
||||
return false;
|
||||
|
||||
if (strlen(buf) <= strlen(sysroot_dir))
|
||||
return false;
|
||||
|
||||
if (strstr(buf + strlen(sysroot_dir), sysroot_dir) == NULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key, const char *value, bool parse)
|
||||
*
|
||||
* Optionally parse and then define a variable.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
* :param pkgconf_list_t* list: The variable list to add the new variable to.
|
||||
* :param char* key: The name of the variable being added.
|
||||
* :param char* value: The value of the variable being added.
|
||||
* :param bool parse: Whether or not to parse the value for variable substitution.
|
||||
* :return: a variable object
|
||||
* :rtype: pkgconf_tuple_t *
|
||||
*/
|
||||
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)
|
||||
{
|
||||
char *dequote_value;
|
||||
pkgconf_tuple_t *tuple = calloc(1, sizeof(pkgconf_tuple_t));
|
||||
|
||||
pkgconf_tuple_find_delete(list, key);
|
||||
|
||||
dequote_value = dequote(value);
|
||||
|
||||
tuple->key = strdup(key);
|
||||
if (parse)
|
||||
tuple->value = pkgconf_tuple_parse(client, list, dequote_value, flags);
|
||||
else
|
||||
tuple->value = strdup(dequote_value);
|
||||
|
||||
PKGCONF_TRACE(client, "adding tuple to @%p: %s => %s (parsed? %d)", list, key, tuple->value, parse);
|
||||
|
||||
pkgconf_node_insert(&tuple->iter, tuple, list);
|
||||
|
||||
free(dequote_value);
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key)
|
||||
*
|
||||
* Look up a variable in a variable list.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
* :param pkgconf_list_t* list: The variable list to search.
|
||||
* :param char* key: The variable name to search for.
|
||||
* :return: the value of the variable or ``NULL``
|
||||
* :rtype: char *
|
||||
*/
|
||||
char *
|
||||
pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key)
|
||||
{
|
||||
pkgconf_node_t *node;
|
||||
pkgconf_tuple_t *global_tuple;
|
||||
|
||||
global_tuple = lookup_global_tuple(client, key);
|
||||
if (global_tuple != NULL && global_tuple->flags & PKGCONF_PKG_TUPLEF_OVERRIDE)
|
||||
return global_tuple->value;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
pkgconf_tuple_t *tuple = node->data;
|
||||
|
||||
if (!strcmp(tuple->key, key))
|
||||
return tuple->value;
|
||||
}
|
||||
|
||||
if (global_tuple != NULL)
|
||||
return global_tuple->value;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *vars, const char *value, unsigned int flags)
|
||||
*
|
||||
* Parse an expression for variable substitution.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to access.
|
||||
* :param pkgconf_list_t* list: The variable list to search for variables (along side the global variable list).
|
||||
* :param char* value: The ``key=value`` string to parse.
|
||||
* :param uint flags: Any flags to consider while parsing.
|
||||
* :return: the variable data with any variables substituted
|
||||
* :rtype: char *
|
||||
*/
|
||||
char *
|
||||
pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *vars, const char *value, unsigned int flags)
|
||||
{
|
||||
char buf[PKGCONF_BUFSIZE];
|
||||
const char *ptr;
|
||||
char *bptr = buf;
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES) &&
|
||||
(!(flags & PKGCONF_PKG_PROPF_UNINSTALLED) || (client->flags & PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES)))
|
||||
{
|
||||
if (*value == '/' && client->sysroot_dir != NULL && strncmp(value, client->sysroot_dir, strlen(client->sysroot_dir)))
|
||||
bptr += pkgconf_strlcpy(buf, client->sysroot_dir, sizeof buf);
|
||||
}
|
||||
|
||||
for (ptr = value; *ptr != '\0' && bptr - buf < PKGCONF_BUFSIZE; ptr++)
|
||||
{
|
||||
if (*ptr != '$' || (*ptr == '$' && *(ptr + 1) != '{'))
|
||||
*bptr++ = *ptr;
|
||||
else if (*(ptr + 1) == '{')
|
||||
{
|
||||
char varname[PKGCONF_ITEM_SIZE];
|
||||
char *vend = varname + PKGCONF_ITEM_SIZE - 1;
|
||||
char *vptr = varname;
|
||||
const char *pptr;
|
||||
char *kv, *parsekv;
|
||||
|
||||
*vptr = '\0';
|
||||
|
||||
for (pptr = ptr + 2; *pptr != '\0'; pptr++)
|
||||
{
|
||||
if (*pptr != '}')
|
||||
{
|
||||
if (vptr < vend)
|
||||
*vptr++ = *pptr;
|
||||
else
|
||||
{
|
||||
*vptr = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*vptr = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PKGCONF_TRACE(client, "lookup tuple %s", varname);
|
||||
|
||||
size_t remain = PKGCONF_BUFSIZE - (bptr - buf);
|
||||
ptr += (pptr - ptr);
|
||||
kv = pkgconf_tuple_find_global(client, varname);
|
||||
if (kv != NULL)
|
||||
{
|
||||
size_t nlen = pkgconf_strlcpy(bptr, kv, remain);
|
||||
if (nlen > remain)
|
||||
{
|
||||
pkgconf_warn(client, "warning: truncating very long variable to 64KB\n");
|
||||
|
||||
bptr = buf + (PKGCONF_BUFSIZE - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
bptr += nlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
kv = pkgconf_tuple_find(client, vars, varname);
|
||||
|
||||
if (kv != NULL)
|
||||
{
|
||||
size_t nlen;
|
||||
|
||||
parsekv = pkgconf_tuple_parse(client, vars, kv, flags);
|
||||
nlen = pkgconf_strlcpy(bptr, parsekv, remain);
|
||||
free(parsekv);
|
||||
|
||||
if (nlen > remain)
|
||||
{
|
||||
pkgconf_warn(client, "warning: truncating very long variable to 64KB\n");
|
||||
|
||||
bptr = buf + (PKGCONF_BUFSIZE - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
bptr += nlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*bptr = '\0';
|
||||
|
||||
/*
|
||||
* Sigh. Somebody actually attempted to use freedesktop.org pkg-config's broken sysroot support,
|
||||
* which was written by somebody who did not understand how sysroots are supposed to work. This
|
||||
* results in an incorrect path being built as the sysroot will be prepended twice, once explicitly,
|
||||
* and once by variable expansion (the pkgconf approach). We could simply make ${pc_sysrootdir} blank,
|
||||
* but sometimes it is necessary to know the explicit sysroot path for other reasons, so we can't really
|
||||
* do that.
|
||||
*
|
||||
* As a result, we check to see if ${pc_sysrootdir} is prepended as a duplicate, and if so, remove the
|
||||
* prepend. This allows us to handle both our approach and the broken freedesktop.org implementation's
|
||||
* approach. Because a path can be shorter than ${pc_sysrootdir}, we do some checks first to ensure it's
|
||||
* safe to skip ahead in the string to scan for our sysroot dir.
|
||||
*
|
||||
* Finally, we call pkgconf_path_relocate() to clean the path of spurious elements.
|
||||
*
|
||||
* New in 1.9: Only attempt to rewrite the sysroot if we are not processing an uninstalled package.
|
||||
*/
|
||||
if (should_rewrite_sysroot(client, vars, buf, flags))
|
||||
{
|
||||
char cleanpath[PKGCONF_ITEM_SIZE];
|
||||
const char *sysroot_dir = find_sysroot(client, vars);
|
||||
|
||||
pkgconf_strlcpy(cleanpath, buf + strlen(sysroot_dir), sizeof cleanpath);
|
||||
pkgconf_path_relocate(cleanpath, sizeof cleanpath);
|
||||
|
||||
return strdup(cleanpath);
|
||||
}
|
||||
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list)
|
||||
*
|
||||
* Deletes a variable object, removing it from any variable lists and releasing any memory associated
|
||||
* with it.
|
||||
*
|
||||
* :param pkgconf_tuple_t* tuple: The variable object to release.
|
||||
* :param pkgconf_list_t* list: The variable list the variable object is attached to.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_tuple_free_entry(pkgconf_tuple_t *tuple, pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_delete(&tuple->iter, list);
|
||||
|
||||
free(tuple->key);
|
||||
free(tuple->value);
|
||||
free(tuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_tuple_free(pkgconf_list_t *list)
|
||||
*
|
||||
* Deletes a variable list and any variables attached to it.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The variable list to delete.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_tuple_free(pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_node_t *node, *next;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, next, node)
|
||||
pkgconf_tuple_free_entry(node->data, list);
|
||||
|
||||
pkgconf_list_zero(list);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check whether the given FLAG works with the current language's compiler
|
||||
# or gives an error. (Warnings, however, are ignored)
|
||||
#
|
||||
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
||||
# success/failure.
|
||||
#
|
||||
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
||||
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
||||
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
||||
# force the compiler to issue an error when a bad flag is given.
|
||||
#
|
||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
||||
#
|
||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
||||
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 6
|
||||
|
||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
||||
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
||||
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
|
||||
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
||||
[AS_VAR_SET(CACHEVAR,[no])])
|
||||
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
||||
AS_VAR_IF(CACHEVAR,yes,
|
||||
[m4_default([$2], :)],
|
||||
[m4_default([$3], :)])
|
||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
||||
])dnl AX_CHECK_COMPILE_FLAGS
|
||||
@@ -0,0 +1,100 @@
|
||||
.\" Copyright (c) 2025 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.
|
||||
.Dd June 4, 2025
|
||||
.Dt BOMTOOL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm bomtool
|
||||
.Nd a tool for generating SPDX-based software bills of material
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar options
|
||||
.Ar module ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a program which generates a textual SPDX 2.0 software bill of
|
||||
materials (SBOM) for a given set of pkg-config modules.
|
||||
The output of this tool can then be translated into other SBOM
|
||||
formats as necessary.
|
||||
.Pp
|
||||
The
|
||||
.Ar options
|
||||
are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl -about
|
||||
Print the version number, the Copyright notice, and the license of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -version
|
||||
Print the version number of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width indent
|
||||
.It Ev PKG_CONFIG_DEBUG_SPEW
|
||||
If set, print debugging messages to stderr.
|
||||
.It Ev PKG_CONFIG_IGNORE_CONFLICTS
|
||||
If set, ignore
|
||||
.Ic Conflicts
|
||||
rules in modules.
|
||||
Has the same effect as the
|
||||
.Fl -ignore-conflicts
|
||||
option in
|
||||
.Xr pkgconf 1
|
||||
.
|
||||
.It Ev PKG_CONFIG_LIBDIR
|
||||
A colon-separated list of low-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
The module search path is constructed by appending this list to
|
||||
.Ev PKG_CONFIG_PATH ,
|
||||
which enjoys higher priority.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv PKG_DEFAULT_PATH
|
||||
preprocessor macro is appended instead.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is defined but empty, nothing is appended.
|
||||
.It Ev PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH
|
||||
Impose a limit on the allowed depth in the dependency graph.
|
||||
.It Ev PKG_CONFIG_PATH
|
||||
A colon-separated list of high-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
.It Ev PKG_CONFIG_PRELOADED_FILES
|
||||
Colon-separated list of
|
||||
.Xr pc 5
|
||||
files which are loaded before any other pkg-config files.
|
||||
These packages are given highest priority over any other
|
||||
.Xr pc 5
|
||||
files that would otherwise provide a given package.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
Generating an SBOM for the package named foo:
|
||||
.Dl $ bomtool foo
|
||||
.Dl SPDXVersion: SPDX-2.2
|
||||
.Dl DataLicense: CC0-1.0
|
||||
.Dl SPDXID: SPDXRef-DOCUMENT
|
||||
.Dl DocumentName: SBOM-SPDX-fooC641.2.3
|
||||
.Dl DocumentNamespace: https://spdx.org/spdxdocs/bomtool-2.4.3
|
||||
.Dl Creator: Tool: bomtool 2.4.3
|
||||
.Dl [...]
|
||||
.Sh SEE ALSO
|
||||
.Xr pc 5 ,
|
||||
.Xr pkgconf 1
|
||||
@@ -0,0 +1,178 @@
|
||||
.\" Copyright (c) 2017 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.
|
||||
.Dd December 15, 2017
|
||||
.Dt PC 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm file.pc
|
||||
.Nd pkg-config file format
|
||||
.Sh DESCRIPTION
|
||||
pkg-config files provide a useful mechanism for storing various information
|
||||
about libraries and packages on a given system.
|
||||
Information stored by
|
||||
.Nm .pc
|
||||
files include compiler and linker flags necessary to use a given library, as
|
||||
well as any other relevant metadata.
|
||||
.Pp
|
||||
These
|
||||
.Nm .pc
|
||||
files are processed by a utility called
|
||||
.Nm pkg-config ,
|
||||
of which
|
||||
.Nm pkgconf
|
||||
is an implementation.
|
||||
.\"
|
||||
.Ss FILE SYNTAX
|
||||
The
|
||||
.Nm .pc
|
||||
file follows a format inspired by RFC822.
|
||||
Comments are prefixed by a pound sign, hash sign or octothorpe (#), and variable
|
||||
assignment is similar to POSIX shell.
|
||||
Properties are defined using RFC822-style stanzas.
|
||||
.\"
|
||||
.Ss VARIABLES
|
||||
.\"
|
||||
Variable definitions start with an alphanumeric string, followed by an equal sign,
|
||||
and then the value the variable should contain.
|
||||
.Pp
|
||||
Variable references are always written as "${variable}".
|
||||
It is possible to escape literal "${" as "$${".
|
||||
.\"
|
||||
.Ss PROPERTIES
|
||||
.\"
|
||||
Properties are set using RFC822-style stanzas which consist of a keyword, followed
|
||||
by a colon (:) and then the value the property should be set to.
|
||||
Variable substitution is always performed regardless of property type.
|
||||
.Pp
|
||||
There are three types of property:
|
||||
.\"
|
||||
.Bl -tag -width indent
|
||||
.\"
|
||||
.It Literal
|
||||
The property will be set to the text of the value.
|
||||
.\"
|
||||
.It Dependency List
|
||||
The property will be set to a list of dependencies parsed from the
|
||||
text.
|
||||
Dependency lists are defined by this ABNF syntax:
|
||||
.Bd -literal
|
||||
package-list = *WSP *( package-spec *( package-sep ) )
|
||||
package-sep = WSP / ","
|
||||
.\"
|
||||
package-spec = package-key [ ver-op package-version ]
|
||||
ver-op = "<" / "<=" / "=" / "!=" / ">=" / ">"
|
||||
.Ed
|
||||
.\"
|
||||
.It Fragment List
|
||||
The property will be set to a list of fragments parsed from the text.
|
||||
The input text must be in a format that is suitable for passing to a POSIX
|
||||
shell without any shell expansions after variable substitution has been done.
|
||||
.\"
|
||||
.El
|
||||
.Ss PROPERTY KEYWORDS
|
||||
.Bl -tag -width indent
|
||||
.\"
|
||||
.It Name
|
||||
The displayed name of the package.
|
||||
(mandatory; literal)
|
||||
.It Version
|
||||
The version of the package.
|
||||
(mandatory; literal)
|
||||
.It Description
|
||||
A description of the package.
|
||||
(mandatory; literal)
|
||||
.It URL
|
||||
A URL to a webpage for the package.
|
||||
This is used to recommend where newer versions of the package can be acquired.
|
||||
(mandatory; literal)
|
||||
.It Cflags
|
||||
Required compiler flags.
|
||||
These flags are always used, regardless of whether static compilation is requested.
|
||||
(optional; fragment list)
|
||||
.It Cflags.private
|
||||
Required compiler flags for static compilation.
|
||||
(optional; fragment list; pkgconf extension)
|
||||
.It Copyright
|
||||
A copyright attestation statement.
|
||||
(optional; literal; pkgconf extension)
|
||||
.It Libs
|
||||
Required linking flags for this package.
|
||||
Libraries this package depends on for linking against it, which are not
|
||||
described as dependencies should be specified here.
|
||||
(optional; fragment list)
|
||||
.It Libs.private
|
||||
Required linking flags for this package that are only required when linking
|
||||
statically.
|
||||
Libraries this package depends on for linking against it statically, which are
|
||||
not described as dependencies should be specified here.
|
||||
(optional; fragment list)
|
||||
.It License
|
||||
The asserted SPDX license tag that should be applied to the given package.
|
||||
(optional; literal; pkgconf extension)
|
||||
.It Maintainer
|
||||
The preferred contact for the maintainer. This should be in the format of a
|
||||
name followed by an e-mail address or website.
|
||||
(optional; literal; pkgconf extension)
|
||||
.It Requires
|
||||
Required dependencies that must be met for the package to be usable.
|
||||
All dependencies must be satisfied or the pkg-config implementation must not use
|
||||
the package.
|
||||
(optional; dependency list)
|
||||
.It Requires.private
|
||||
Required dependencies that must be met for the package to be usable for header
|
||||
inclusion and static linking.
|
||||
All dependencies must be satisfied or the pkg-config implementation must not use
|
||||
the package for header inclusion and static linking.
|
||||
(optional; dependency list)
|
||||
.It Conflicts
|
||||
Dependencies that must not be met for the package to be usable.
|
||||
If any package in the proposed dependency solution match any dependency in the
|
||||
Conflicts list, the package being considered is not usable.
|
||||
(optional; dependency list)
|
||||
.It Provides
|
||||
Dependencies that may be provided by an alternate package.
|
||||
If a package cannot be found, the entire package collection is scanned for
|
||||
providers which can match the requested dependency.
|
||||
(optional; dependency list; pkgconf extension)
|
||||
.El
|
||||
.Ss EXTENSIONS
|
||||
Features that have been marked as a pkgconf extension are only guaranteed to work
|
||||
with the pkgconf implementation of pkg-config.
|
||||
Other implementations may or may not support the extensions.
|
||||
.Pp
|
||||
Accordingly, it is suggested that
|
||||
.Nm .pc
|
||||
files which absolutely depend on these extensions declare a requirement on the
|
||||
pkgconf virtual.
|
||||
.Sh EXAMPLES
|
||||
An example .pc file:
|
||||
.Bd -literal
|
||||
# This is a comment
|
||||
prefix=/home/kaniini/pkg # this defines a variable
|
||||
exec_prefix=${prefix} # defining another variable with a substitution
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: libfoo # human-readable name
|
||||
Description: an example library called libfoo # human-readable description
|
||||
Copyright: Copyright (c) 2022 pkgconf project authors
|
||||
License: Apache-2.0
|
||||
Maintainer: the pkgconf project <http://www.pkgconf.org>
|
||||
Version: 1.0
|
||||
URL: http://www.pkgconf.org
|
||||
Requires: libbar > 2.0.0
|
||||
Conflicts: libbaz <= 3.0.0
|
||||
Libs: -L${libdir} -lfoo
|
||||
Libs.private: -lm
|
||||
Cflags: -I${includedir}/libfoo
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr pkgconf 1 ,
|
||||
.Xr pkg.m4 7
|
||||
@@ -0,0 +1,143 @@
|
||||
.\" Copyright (c) 2017 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.
|
||||
.Dd December 5, 2017
|
||||
.Dt PKG.M4 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pkg.m4
|
||||
.Nd autoconf macros for using pkgconf
|
||||
.Sh SYNOPSIS
|
||||
.Nm PKG_PREREQ
|
||||
.Nm PKG_PROG_PKG_CONFIG
|
||||
.Nm PKG_CHECK_MODULES
|
||||
.Nm PKG_CHECK_MODULES_STATIC
|
||||
.Nm PKG_INSTALLDIR
|
||||
.Nm PKG_NOARCH_INSTALLDIR
|
||||
.Nm PKG_CHECK_VAR
|
||||
.Nm PKG_WITH_MODULES
|
||||
.Nm PKG_HAVE_WITH_MODULES
|
||||
.Nm PKG_HAVE_DEFINE_WITH_MODULES
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a collection of autoconf macros which help to configure compiler and linker
|
||||
flags for development libraries.
|
||||
This allows build systems to detect other dependencies and use them with the
|
||||
system toolchain.
|
||||
.Sh "AUTOCONF MACROS"
|
||||
.Ss "PKG_PREREQ(MIN-VERSION)"
|
||||
Checks that the version of the
|
||||
.Nm
|
||||
autoconf macros in use is at least MIN-VERSION.
|
||||
This can be used to ensure a particular
|
||||
.Nm
|
||||
macro will be available.
|
||||
.Ss "PKG_PROG_PKG_CONFIG([MIN-VERSION])"
|
||||
Checks for an implementation of
|
||||
.Nm pkg-config
|
||||
which is at least MIN-VERSION or newer.
|
||||
.Ss "PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]])"
|
||||
.Ss "PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]])"
|
||||
Checks whether a given module set exists, and if so, defines
|
||||
.Nm CFLAGS
|
||||
and
|
||||
.Nm LIBS
|
||||
variables prefixed by
|
||||
.Nm VARIABLE-PREFIX
|
||||
with the output from
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
respectively.
|
||||
.Pp
|
||||
The optional
|
||||
.Nm ACTION-IF-FOUND
|
||||
and
|
||||
.Nm ACTION-IF-NOT-FOUND
|
||||
arguments are shell fragments that should be executed if the module set is
|
||||
found or not found.
|
||||
.Pp
|
||||
If
|
||||
.Nm $PKG_CONFIG
|
||||
is not defined, the
|
||||
.Nm PKG_PROG_PKG_CONFIG
|
||||
macro will be executed to locate a
|
||||
.Nm pkg-config
|
||||
implementation.
|
||||
.Pp
|
||||
The
|
||||
.Nm PKG_CHECK_MODULES_STATIC
|
||||
macro provides the same behaviour as
|
||||
.Nm PKG_CHECK_MODULES
|
||||
with static linking enabled via the
|
||||
.Fl -static
|
||||
flag.
|
||||
.Ss "PKG_INSTALLDIR(DIRECTORY)"
|
||||
Defines the variable $pkgconfigdir as the location where a package
|
||||
should install pkg-config .pc files.
|
||||
.Pp
|
||||
By default the directory is $libdir/pkgconfig, but the default can
|
||||
be changed by passing the
|
||||
.Nm DIRECTORY
|
||||
parameter.
|
||||
.Pp
|
||||
This value can be overridden with the
|
||||
.Fl -with-pkgconfigdir
|
||||
configure parameter.
|
||||
.Ss "PKG_NOARCH_INSTALLDIR(DIRECTORY)"
|
||||
Defines the variable $noarch_pkgconfigdir as the location where a package
|
||||
should install pkg-config .pc files.
|
||||
.Pp
|
||||
By default the directory is $datadir/pkgconfig, but the default can
|
||||
be changed by passing the
|
||||
.Nm DIRECTORY
|
||||
parameter.
|
||||
.Pp
|
||||
This value can be overridden with the
|
||||
.Fl -with-noarch-pkgconfigdir
|
||||
configure parameter.
|
||||
.Ss "PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])"
|
||||
Retrieves the value of the
|
||||
.Nm pkg-config
|
||||
variable
|
||||
.Nm CONFIG-VARIABLE
|
||||
from
|
||||
.Nm MODULE
|
||||
and stores it in the
|
||||
.Nm VARIABLE
|
||||
variable.
|
||||
.Pp
|
||||
Note that repeated usage of
|
||||
.Nm VARIABLE
|
||||
is not recommended as the check will be skipped if the variable is
|
||||
already set.
|
||||
.Ss "PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], [DESCRIPTION], [DEFAULT])"
|
||||
Prepares a "--with-" configure option using the lowercase
|
||||
.Nm VARIABLE-PREFIX
|
||||
name, merging the behaviour of
|
||||
.Nm AC_ARG_WITH
|
||||
and
|
||||
.Nm PKG_CHECK_MODULES
|
||||
in a single macro.
|
||||
.Ss "PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, [DESCRIPTION], [DEFAULT])"
|
||||
Convenience macro to trigger
|
||||
.Nm AM_CONDITIONAL
|
||||
after a
|
||||
.Nm PKG_WITH_MODULES check.\&
|
||||
.Nm VARIABLE-PREFIX
|
||||
is exported as a make variable.
|
||||
.Ss "PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, [DESCRIPTION], [DEFAULT])"
|
||||
Convenience macro to trigger
|
||||
.Nm AM_CONDITIONAL
|
||||
and
|
||||
.Nm AC_DEFINE
|
||||
after a
|
||||
.Nm PKG_WITH_MODULES check.\&
|
||||
.Nm VARIABLE-PREFIX
|
||||
is exported as a make variable.
|
||||
@@ -0,0 +1,100 @@
|
||||
.\" Copyright (c) 2018 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.
|
||||
.Dd July 19, 2018
|
||||
.Dt PKGCONF-PERSONALITY 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm file.personality
|
||||
.Nd pkgconf cross-compile personality file format
|
||||
.Sh DESCRIPTION
|
||||
pkgconf cross-compile personality files provide a useful mechanism for storing
|
||||
various information about system toolchains.
|
||||
Information stored by
|
||||
.Nm .personality
|
||||
files include information about paths used by a cross-compile toolchain, such as
|
||||
the sysroot directory and default include and library paths. pkgconf uses this
|
||||
information to determine what information is necessary to use libraries.
|
||||
.\"
|
||||
.Ss FILE SYNTAX
|
||||
The
|
||||
.Nm .personality
|
||||
file follows a format inspired by RFC822.
|
||||
Comments are prefixed by a pound sign, hash sign or octothorpe (#), and variable
|
||||
assignment is similar to POSIX shell.
|
||||
Properties are defined using RFC822-style stanzas.
|
||||
.\"
|
||||
.Ss PROPERTIES
|
||||
.\"
|
||||
Properties are set using RFC822-style stanzas which consist of a keyword, followed
|
||||
by a colon (:) and then the value the property should be set to.
|
||||
Variable substitution is always performed regardless of property type.
|
||||
.Pp
|
||||
There are three types of property:
|
||||
.\"
|
||||
.Bl -tag -width indent
|
||||
.\"
|
||||
.It Literal
|
||||
The property will be set to the text of the value.
|
||||
.\"
|
||||
.It Fragment List
|
||||
The property will be set to a list of fragments parsed from the text.
|
||||
The input text must be in a format that is suitable for passing to a POSIX
|
||||
shell without any shell expansions after variable substitution has been done.
|
||||
Elements are delimited with a colon.
|
||||
.\"
|
||||
.It Boolean
|
||||
The property will be set to true if the value is one of: true, yes or 1.
|
||||
Otherwise it will be set to false.
|
||||
.\"
|
||||
.El
|
||||
.Ss PROPERTY KEYWORDS
|
||||
.Bl -tag -width indent
|
||||
.\"
|
||||
.It Triplet
|
||||
The triplet used by the cross-compile toolchain.
|
||||
(mandatory; literal)
|
||||
.It SysrootDir
|
||||
The directory used by the system root of the cross-compile toolchain.
|
||||
(mandatory; literal)
|
||||
.It DefaultSearchPaths
|
||||
A list of directories to look for
|
||||
.Xr pc 5
|
||||
files in.
|
||||
(mandatory; fragment list)
|
||||
.It SystemIncludePaths
|
||||
A list of directories that are included by default in the search path for
|
||||
include files.
|
||||
(mandatory; fragment list)
|
||||
.It SystemLibraryPaths
|
||||
A list of directories that are included by default in the search path for
|
||||
libraries.
|
||||
(mandatory; fragment list)
|
||||
.It WantDefaultPure
|
||||
If true, pkgconf will default to preferring a pure dependency graph.
|
||||
(optional; boolean; default is false)
|
||||
.It WantDefaultStatic
|
||||
If true, pkgconf will default to operating in static linking mode.
|
||||
(optional; boolean; default is false)
|
||||
.\"
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
An example .personality file:
|
||||
.Bd -literal
|
||||
# This is a comment
|
||||
Triplet: x86_64-pc-linux-gnu
|
||||
SysrootDir: /home/kaniini/sysroot/x86_64-pc-linux-gnu
|
||||
DefaultSearchPaths: /home/kaniini/sysroot/x86_64-pc-linux-gnu/lib/pkgconfig:/home/kaniini/sysroot/x86_64-pc-linux-gnu/share/pkgconfig
|
||||
SystemIncludePaths: /home/kaniini/sysroot/x86_64-pc-linux-gnu/include
|
||||
SystemLibraryPaths: /home/kaniini/sysroot/x86_64-pc-linux-gnu/lib
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr pkgconf 1 ,
|
||||
.Xr pc 5 ,
|
||||
.Xr pkg.m4 7
|
||||
@@ -0,0 +1,758 @@
|
||||
.\" Copyright (c) 2011, 2012, 2013, 2014, 2015, 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.
|
||||
.Dd November 15, 2016
|
||||
.Dt PKGCONF 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pkgconf
|
||||
.Nd a system for configuring build dependency information
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar options
|
||||
.Ar module ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
program retrieves configuration information related to the
|
||||
.Ar module
|
||||
arguments from
|
||||
.Xr pc 5
|
||||
files installed on the system and prints parts of the retrieved
|
||||
information depending on the specified
|
||||
.Ar options .
|
||||
The most common use is printing the compiler and linker flags needed
|
||||
to build software that uses the libraries given by the
|
||||
.Ar module
|
||||
arguments.
|
||||
.Pp
|
||||
The
|
||||
.Xr pc 5
|
||||
files are searched for along a path constructed from the
|
||||
.Fl -with-path
|
||||
option, the
|
||||
.Ev PKG_CONFIG_PATH
|
||||
and
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
environment variables, and some compiled-in default directories.
|
||||
The
|
||||
.Ar module
|
||||
arguments correspond to the file names, but without the
|
||||
.Pa .pc
|
||||
filename extension.
|
||||
.Pp
|
||||
Several of the
|
||||
.Ar options
|
||||
cause immediate exit.
|
||||
If multiple of these options are given, only the option with the
|
||||
highest priority takes effect and those with lower priority are
|
||||
silently ignored.
|
||||
These options are, ordered by descending priority:
|
||||
.Bl -enum
|
||||
.It
|
||||
No-module options:
|
||||
.Fl -relocate ,
|
||||
.Fl -dump-personality ,
|
||||
.Fl -about ,
|
||||
.Fl -version ,
|
||||
.Fl -help ,
|
||||
.Fl -atleast-pkgconfig-version ,
|
||||
.Fl -list-all ,
|
||||
and
|
||||
.Fl -list-package-names :
|
||||
These options cause all arguments to be ignored.
|
||||
.It
|
||||
Argument-only options:
|
||||
.Fl -atleast-version ,
|
||||
.Fl -exact-version ,
|
||||
and
|
||||
.Fl -max-version :
|
||||
These options only inspect modules explicitly specified on the
|
||||
command line and do not look at dependencies.
|
||||
.It
|
||||
Limited-output options:
|
||||
.Fl -validate ,
|
||||
.Fl -license ,
|
||||
.Fl -uninstalled ,
|
||||
and
|
||||
.Fl -env :
|
||||
These options perform dependency resolution, but exit after printing
|
||||
the information requested by the highest-priority option,
|
||||
ignoring other output options that may have been specified.
|
||||
.El
|
||||
.Pp
|
||||
Several other options require at least one
|
||||
.Ar module
|
||||
argument, produce output, do not cause early exit, can be combined
|
||||
with each other, but override and disable all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
options:
|
||||
.Bl -enum
|
||||
.It
|
||||
Single-module output options:
|
||||
.Fl -path ,
|
||||
.Fl -print-variables ,
|
||||
.Fl -variable :
|
||||
If any of these options is specified, only the first
|
||||
.Ar module
|
||||
argument is used, all other arguments are silently ignored,
|
||||
and no dependency resolution is attempted.
|
||||
.It
|
||||
Depth-one output options:
|
||||
.Fl -print-provides ,
|
||||
.Fl -modversion ,
|
||||
.Fl -print-requires ,
|
||||
and
|
||||
.Fl -print-requires-private :
|
||||
If any of these options is specified, only modules
|
||||
explicitly specified on the command line are inspected
|
||||
and no dependency resolution is attempted.
|
||||
.It
|
||||
General output options:
|
||||
.Fl -simulate ,
|
||||
.Fl -digraph ,
|
||||
.Fl -solution ,
|
||||
.Fl -fragment-tree :
|
||||
These options do not limit dependency resolution.
|
||||
.El
|
||||
.Pp
|
||||
The most important output options
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
can be combined with each other, but are overridden and ignored if
|
||||
any of the options listed above are specified.
|
||||
.Pp
|
||||
The complete list of
|
||||
.Ar options
|
||||
is as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl -about
|
||||
Print the version number, the Copyright notice, and the license of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -atleast-pkgconfig-version Ns = Ns Ar version
|
||||
Exit with error if the requested
|
||||
.Ar version
|
||||
number is greater than the version number of the
|
||||
.Nm
|
||||
program, or with success otherwise.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -atleast-version Ns = Ns Ar version
|
||||
Check the
|
||||
.Ar module
|
||||
arguments in the given order.
|
||||
Exit with error as soon as a
|
||||
.Ar module
|
||||
does not exist, and exit with success as soon as the version number of a
|
||||
.Ar module
|
||||
is greater than or equal to the requested
|
||||
.Ar version
|
||||
number.
|
||||
Exit with error if the version number of each
|
||||
.Ar module
|
||||
is less than the requested
|
||||
.Ar version
|
||||
number.
|
||||
.It Fl -cflags , Fl -cflags-only-I , Fl -cflags-only-other
|
||||
Print all compiler flags required to compile against the
|
||||
.Ar module ,
|
||||
or only the include path
|
||||
.Pq Fl I
|
||||
flags, or only the compiler flags that are not include path flags,
|
||||
respectively.
|
||||
These options imply
|
||||
.Fl -print-errors .
|
||||
.It Fl -debug
|
||||
Print some non-fatal warning messages to standard error output
|
||||
that would otherwise silently be ignored.
|
||||
This option also implies
|
||||
.Fl -print-errors .
|
||||
If
|
||||
.Nm
|
||||
was compiled without defining the preprocessor macro
|
||||
.Dv PKGCONF_LITE ,
|
||||
this option also prints many debugging messages to standard error output.
|
||||
.It Fl -define-prefix
|
||||
Attempts to determine the prefix variable to use for CFLAGS and LIBS entry relocations.
|
||||
This is mainly useful for platforms where framework SDKs are relocatable, such as Windows.
|
||||
.It Fl -define-variable Ns = Ns Ar varname Ns = Ns Ar value
|
||||
Define
|
||||
.Ar varname
|
||||
as
|
||||
.Ar value .
|
||||
Variables are used in query output, and some modules' results may change based
|
||||
on the presence of a variable definition.
|
||||
.It Fl -digraph
|
||||
Dump the dependency resolver's solution as a graphviz
|
||||
.Sq dot
|
||||
file.
|
||||
This can be used with graphviz to visualize module interdependencies.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -dont-define-prefix
|
||||
Disables the
|
||||
.Sq define-prefix
|
||||
feature.
|
||||
.It Fl -dont-relocate-paths
|
||||
Disables the path relocation feature.
|
||||
.It Fl -dump-personality
|
||||
Print some default settings to standard output, in particular
|
||||
the default module search path that is used when
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is not defined, the default list of include paths that are filtered out when
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH
|
||||
is not defined,
|
||||
and the default list of library paths that are filtered out when
|
||||
.Ev PKG_CONFIG_SYSTEM_LIBRARY_PATH
|
||||
is not defined, and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -env Ns = Ns Ar varname
|
||||
Print the requested values as variable declarations in a similar format as the
|
||||
.Xr env 1
|
||||
command.
|
||||
.It Fl -env-only
|
||||
Initialize the module search path from
|
||||
.Fl -with-path
|
||||
and
|
||||
.Ev PKG_CONFIG_PATH
|
||||
only, ignoring
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
and the compiled-in default directories.
|
||||
.It Fl -errors-to-stdout
|
||||
Print all error, warning, and debugging messages to standard output
|
||||
instead of to standard error output.
|
||||
.It Fl -exact-version Ns = Ns Ar version
|
||||
Check the
|
||||
.Ar module
|
||||
arguments in the given order.
|
||||
Exit with error as soon as a
|
||||
.Ar module
|
||||
does not exist, and exit with success as soon as the version number of a
|
||||
.Ar module
|
||||
is exactly the requested
|
||||
.Ar version
|
||||
number.
|
||||
Exit with error if the version number of each
|
||||
.Ar module
|
||||
differs from the requested
|
||||
.Ar version
|
||||
number.
|
||||
.It Fl -exists
|
||||
Exit with a non-zero exit status
|
||||
if the dependency resolver is unable to find all of the requested
|
||||
.Ar module Ns s .
|
||||
This option is active by default and cannot be disabled.
|
||||
However, various other options cause
|
||||
.Nm
|
||||
to exit and report success or failure before all arguments have been inspected.
|
||||
.It Fl -fragment-filter Ns = Ns Ar types
|
||||
Filter the fragment lists for the specified
|
||||
.Ar types .
|
||||
.It Fl -help
|
||||
Print a usage summary on standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -ignore-conflicts
|
||||
Ignore
|
||||
.Sq Conflicts
|
||||
rules in modules.
|
||||
.It Fl -keep-system-cflags , Fl -keep-system-libs
|
||||
Keep CFLAGS or linker flag fragments that would be filtered due to being
|
||||
included by default in the compiler.
|
||||
.It Fl -libs , Fl -libs-only-L , Fl -libs-only-l , Fl -libs-only-other
|
||||
Print all linker flags required to link against the
|
||||
.Ar module ,
|
||||
or only the library path
|
||||
.Pq Fl L
|
||||
flags, or only the library
|
||||
.Pq Fl l
|
||||
flags, or only the linker flags that are neither library path
|
||||
nor library flags, respectively.
|
||||
These options imply
|
||||
.Fl -print-errors .
|
||||
.It Fl -list-all
|
||||
Walk the module search path in the order of descending priority.
|
||||
For each
|
||||
.Xr pc 5
|
||||
file found, print one line to standard output,
|
||||
containing the basename of the file without the extension, the
|
||||
.Ic Name
|
||||
property, a dash
|
||||
.Pq Sq \- ,
|
||||
and the
|
||||
.Ic Description
|
||||
property.
|
||||
This option implies
|
||||
.Fl -print-errors .
|
||||
All command line arguments are ignored.
|
||||
.It Fl -list-package-names
|
||||
Perform the same search as
|
||||
.Fl -list-all ,
|
||||
but only print the basename of each
|
||||
.Xr pc 5
|
||||
file without the extension, not the module name and the description.
|
||||
This option implies
|
||||
.Fl -print-errors .
|
||||
All command line arguments are ignored.
|
||||
.It Fl -log-file Ns = Ns Ar file
|
||||
Set the name of the output
|
||||
.Ar file
|
||||
where information about selected modules is logged,
|
||||
both about those selected by arguments and as dependencies.
|
||||
For each selected module, one line is printed,
|
||||
containing the basename of the
|
||||
.Xr pc 5
|
||||
file without the extension, optionally an operator and version number
|
||||
describing the desired range of versions, and either the actual version
|
||||
number in square brackets or the string
|
||||
.Qq NOT-FOUND .
|
||||
If this option is not provided, the name of the output file
|
||||
is instead taken from the
|
||||
.Ev PKG_CONFIG_LOG
|
||||
environment variable, and if that is not provided either,
|
||||
this kind of logging is disabled.
|
||||
.It Fl -max-version Ns = Ns Ar version
|
||||
Check the
|
||||
.Ar module
|
||||
arguments in the given order.
|
||||
Exit with error as soon as a
|
||||
.Ar module
|
||||
does not exist, and exit with success as soon as the version number of a
|
||||
.Ar module
|
||||
is less than or equal to the requested
|
||||
.Ar version
|
||||
number.
|
||||
Exit with error if the version number of each
|
||||
.Ar module
|
||||
is greater than the requested
|
||||
.Ar version
|
||||
number.
|
||||
.It Fl -maximum-traverse-depth Ns = Ns Ar depth
|
||||
Impose a limit on the allowed depth in the dependency graph.
|
||||
For example, a
|
||||
.Ar depth
|
||||
of 2 restricts the resolver from acting on child
|
||||
dependencies of modules added to the resolver's solution.
|
||||
This option is overridden by the
|
||||
.Ev PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH
|
||||
environment variable and by the options
|
||||
.Fl -modversion ,
|
||||
.Fl -path ,
|
||||
.Fl -print-provides ,
|
||||
.Fl -print-requires ,
|
||||
.Fl -print-requires-private ,
|
||||
.Fl -print-variables ,
|
||||
and
|
||||
.Fl -variable .
|
||||
.It Fl -modversion
|
||||
For each specified
|
||||
.Ar module ,
|
||||
print the version number to standard output.
|
||||
If the
|
||||
.Fl -verbose
|
||||
option is also specified, the name of the respective
|
||||
.Ar module
|
||||
and a colon is printed before each version number.
|
||||
This option implies
|
||||
.Fl -print-errors
|
||||
and
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -msvc-syntax
|
||||
Use MSVC syntax for
|
||||
.Fl -cflags ,
|
||||
.Fl -env ,
|
||||
and
|
||||
.Fl -libs
|
||||
output.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -no-cache
|
||||
Skip caching packages when they are loaded into the internal resolver.
|
||||
This may result in an alternate dependency graph being computed.
|
||||
.It Fl -no-provides
|
||||
Ignore
|
||||
.Sq Provides
|
||||
rules in modules when resolving dependencies.
|
||||
.It Fl -no-uninstalled
|
||||
Forbids the dependency resolver from considering 'uninstalled' modules as part
|
||||
of a solution.
|
||||
.It Fl -path
|
||||
For the first
|
||||
.Ar module
|
||||
given on the command line, let the dependency resolver find the
|
||||
.Xr pc 5
|
||||
file describing that module, print the absolute pathname of that file
|
||||
to standard output, and exit immediately,
|
||||
ignoring most other options and all other arguments.
|
||||
.It Fl -prefix-variable Ns = Ns Ar variable
|
||||
Sets the
|
||||
.Sq prefix
|
||||
variable used by the
|
||||
.Sq define-prefix
|
||||
feature.
|
||||
.It Fl -print-errors
|
||||
Print some messages about fatal errors to standard error output
|
||||
that would otherwise be omitted.
|
||||
This option is implied by many other options, but not by all.
|
||||
It can be overridden with
|
||||
.Fl -silence-errors .
|
||||
.It Fl -print-provides
|
||||
For each specified
|
||||
.Ar module ,
|
||||
print one line to standard output containing the
|
||||
.Ic Name
|
||||
property, an equal sign
|
||||
.Pq Sq = ,
|
||||
and the
|
||||
.Ic Version
|
||||
property.
|
||||
If the
|
||||
.Ar module
|
||||
contains one or more
|
||||
.Ic Provides
|
||||
properties, print additional lines in dependency list format, one name
|
||||
per line, each name optionally followed by an operator and a version.
|
||||
This option implies
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -print-requires , Fl -print-requires-private
|
||||
For each specified
|
||||
.Ar module ,
|
||||
print the
|
||||
.Ic Requires
|
||||
or
|
||||
.Ic Requires.private
|
||||
properties, respectively, in dependency list format to standard output.
|
||||
Both of these options imply
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and override and disable all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -print-variables
|
||||
For the first
|
||||
.Ar module
|
||||
given on the command line, print the names of all seen variables
|
||||
to standard output, one per line.
|
||||
Any subsequent arguments are silently ignored.
|
||||
This option implies
|
||||
.Fl -print-errors
|
||||
and
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -pure
|
||||
Treats the computed dependency graph as if it were pure.
|
||||
This is mainly intended for use with the
|
||||
.Fl -static
|
||||
flag and has no effect if
|
||||
.Fl -shared
|
||||
is also specified.
|
||||
.It Fl -relocate Ns = Ns Ar path
|
||||
Relocates a path using the pkgconf_path_relocate API.
|
||||
This is mainly used by the testsuite to provide a guaranteed interface
|
||||
to the system's path relocation backend.
|
||||
.It Fl -shared
|
||||
Compute a simple dependency graph that is only suitable for shared linking.
|
||||
This option overrides
|
||||
.Fl -static .
|
||||
.It Fl -short-errors
|
||||
When printing error messages about modules that are not found
|
||||
or conflict with each other, avoid printing additional, verbose
|
||||
instructions explaining potential methods for solving the problem.
|
||||
.It Fl -silence-errors
|
||||
Do not print any error, warning, or debugging messages at all.
|
||||
Overrides all of
|
||||
.Fl -debug ,
|
||||
.Fl -errors-to-stdout ,
|
||||
and
|
||||
.Fl -print-errors .
|
||||
This option is overridden and disabled if the
|
||||
.Ev PKG_CONFIG_DEBUG_SPEW
|
||||
environment variable is set.
|
||||
.It Fl -simulate
|
||||
Simulates resolving a dependency graph based on the requested modules on the
|
||||
command line.
|
||||
Dumps a series of trees denoting pkgconf's resolver state.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -solution
|
||||
Print the names of the modules requested with
|
||||
.Ar module
|
||||
arguments and their dependencies to standard output.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -static
|
||||
Compute a deeper dependency graph and use compiler/linker flags intended for
|
||||
static linking.
|
||||
This option is overridden by
|
||||
.Fl -shared .
|
||||
.It Fl -uninstalled
|
||||
Exit with a non-zero result if the dependency resolver uses an
|
||||
.Sq uninstalled
|
||||
module as part of its solution.
|
||||
.It Fl -validate Ar package ...
|
||||
Validate specific
|
||||
.Sq .pc
|
||||
files for correctness.
|
||||
This option implies
|
||||
.Fl -print-errors
|
||||
and
|
||||
.Fl -errors-to-stdout .
|
||||
.It Fl -variable Ns = Ns Ar varname
|
||||
For the first
|
||||
.Ar module
|
||||
given on the command line, print the value of the variable with the name
|
||||
.Ar varname
|
||||
to standard output.
|
||||
Any subsequent arguments are silently ignored.
|
||||
This option implies
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -verbose
|
||||
This option only has an effect if
|
||||
.Fl -modversion
|
||||
is also specified.
|
||||
It prints the name of the respective
|
||||
.Ar module
|
||||
and a colon before each version number.
|
||||
.It Fl -version
|
||||
Print the version number of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -with-path Ns = Ns Ar path
|
||||
Prepend the directory
|
||||
.Ar path
|
||||
to the module search path,
|
||||
giving it priority over all other directories including those from
|
||||
.Ev PKG_CONFIG_PATH
|
||||
and
|
||||
.Ev PKG_CONFIG_LIBDIR .
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width indent
|
||||
.It Ev CPATH
|
||||
First supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev CPLUS_INCLUDE_PATH
|
||||
Third supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev C_INCLUDE_PATH
|
||||
Second supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev DESTDIR
|
||||
If set to the same value as
|
||||
.Ev PKG_CONFIG_SYSROOT_DIR ,
|
||||
behave in the same way as if
|
||||
.Ev PKG_CONFIG_FDO_SYSROOT_RULES
|
||||
is set.
|
||||
If
|
||||
.Ev PKG_CONFIG_SYSROOT_DIR
|
||||
is not set or set to a different value,
|
||||
.Ev DESTDIR
|
||||
is ignored.
|
||||
.It Ev LIBRARY_PATH
|
||||
Supplementary colon-separated list of library paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_LIBRARY_PATH .
|
||||
.It Ev OBJC_INCLUDE_PATH
|
||||
Fourth supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev PKG_CONFIG_ALLOW_SYSTEM_CFLAGS
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -keep-system-cflags
|
||||
option.
|
||||
.It Ev PKG_CONFIG_ALLOW_SYSTEM_LIBS
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -keep-system-libs
|
||||
option.
|
||||
.It Ev PKG_CONFIG_DEBUG_SPEW
|
||||
If set, override and disable the
|
||||
.Fl -silence-errors
|
||||
option.
|
||||
.It Ev PKG_CONFIG_DISABLE_UNINSTALLED
|
||||
If set, enables the same behaviour as the
|
||||
.Fl -no-uninstalled
|
||||
flag.
|
||||
.It Ev PKG_CONFIG_DONT_DEFINE_PREFIX
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -dont-define-prefix
|
||||
option.
|
||||
.It Ev PKG_CONFIG_DONT_RELOCATE_PATHS
|
||||
If set, disables the path relocation feature.
|
||||
.It Ev PKG_CONFIG_FDO_SYSROOT_RULES
|
||||
If set, follow the sysroot prefixing rules that freedesktop.org pkg-config uses.
|
||||
.It Ev PKG_CONFIG_IGNORE_CONFLICTS
|
||||
If set, ignore
|
||||
.Ic Conflicts
|
||||
rules in modules.
|
||||
Has the same effect as the
|
||||
.Fl -ignore-conflicts
|
||||
option.
|
||||
.It Ev PKG_CONFIG_LIBDIR
|
||||
A colon-separated list of low-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
The module search path is constructed by appending this list to
|
||||
.Ev PKG_CONFIG_PATH ,
|
||||
which enjoys higher priority.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv PKG_DEFAULT_PATH
|
||||
preprocessor macro is appended instead.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is defined but empty, nothing is appended.
|
||||
.It Ev PKG_CONFIG_LOG
|
||||
If set, log information about selected modules
|
||||
to the file with the name stored in this variable.
|
||||
For more details, see the
|
||||
.Fl -log-file
|
||||
command line option, which overrides this variable.
|
||||
.It Ev PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH
|
||||
Impose a limit on the allowed depth in the dependency graph.
|
||||
This variable overrides the
|
||||
.Fl -maximum-traverse-depth
|
||||
option, but is overridden by the other options mentioned there.
|
||||
.It Ev PKG_CONFIG_MSVC_SYNTAX
|
||||
If set, use MSVC syntax for
|
||||
.Fl -cflags ,
|
||||
.Fl -env ,
|
||||
and
|
||||
.Fl -libs
|
||||
output.
|
||||
This variable has the same effect as the
|
||||
.Fl -msvc-syntax
|
||||
option.
|
||||
If the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was defined during compilation, this variable is ignored.
|
||||
.It Ev PKG_CONFIG_PATH
|
||||
A colon-separated list of high-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
The module search path is constructed
|
||||
by prepending the directory specified with
|
||||
.Fl -with-path ,
|
||||
if any, and unless
|
||||
.Fl -env-only
|
||||
is specified, by appending either
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
or the compiled-in default directories with lower priority.
|
||||
.It Ev PKG_CONFIG_PRELOADED_FILES
|
||||
Colon-separated list of
|
||||
.Xr pc 5
|
||||
files which are loaded before any other pkg-config files.
|
||||
These packages are given highest priority over any other
|
||||
.Xr pc 5
|
||||
files that would otherwise provide a given package.
|
||||
.It Ev PKG_CONFIG_PURE_DEPGRAPH
|
||||
If set, enables the same behaviour as the
|
||||
.Fl -pure
|
||||
flag.
|
||||
.It Ev PKG_CONFIG_RELOCATE_PATHS
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -define-prefix
|
||||
option.
|
||||
.It Ev PKG_CONFIG_SYSROOT_DIR
|
||||
If set, this variable defines a
|
||||
.Sq sysroot
|
||||
directory, which will be prepended to every path variable
|
||||
beginning with the prefix variable in a given
|
||||
.Xr pc 5
|
||||
file.
|
||||
Useful for cross compilation.
|
||||
The value of this environment variable is also copied into the global variable
|
||||
.Va pc_sysrootdir .
|
||||
.It Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH
|
||||
Colon-separated list of include paths that are filtered out
|
||||
and not printed by the
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -cflags-only-I
|
||||
options because they are considered system include paths.
|
||||
If not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv SYSTEM_INCLUDEDIR
|
||||
preprocessor macro is used instead.
|
||||
This variable is a pkgconf-specific extension.
|
||||
Any directories listed in the environment variables
|
||||
.Ev CPATH ,
|
||||
.Ev C_INCLUDE_PATH ,
|
||||
.Ev CPLUS_INCLUDE_PATH ,
|
||||
and
|
||||
.Ev OBJC_INCLUDE_PATH
|
||||
are also filtered out.
|
||||
.It Ev PKG_CONFIG_SYSTEM_LIBRARY_PATH
|
||||
Colon-separated list of library paths that are filtered out
|
||||
and not printed by the
|
||||
.Fl -libs
|
||||
and
|
||||
.Fl -libs-only-L
|
||||
options because they are considered system library paths.
|
||||
If not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv SYSTEM_LIBDIR
|
||||
preprocessor macro is used instead.
|
||||
This variable is a pkgconf-specific extension.
|
||||
.It Ev PKG_CONFIG_TOP_BUILD_DIR
|
||||
The value of the
|
||||
.Va pc_top_builddir
|
||||
global variable.
|
||||
If this environment variable is not defined, the string
|
||||
.Qq $(top_builddir)
|
||||
is used as the value of
|
||||
.Va pc_top_builddir .
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
Displaying the CFLAGS of a package:
|
||||
.Dl $ pkgconf --cflags foo
|
||||
.Dl -fPIC -I/usr/include/foo
|
||||
.Sh SEE ALSO
|
||||
.Xr pc 5 ,
|
||||
.Xr pkg.m4 7
|
||||
@@ -0,0 +1,199 @@
|
||||
project('pkgconf', 'c',
|
||||
version : '2.5.1',
|
||||
license : 'ISC',
|
||||
default_options : ['c_std=c99'],
|
||||
meson_version: '>=0.52',
|
||||
)
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
add_project_arguments(
|
||||
'-D_BSD_SOURCE',
|
||||
'-D_DEFAULT_SOURCE',
|
||||
'-D_POSIX_C_SOURCE=200809L',
|
||||
cc.get_supported_arguments(
|
||||
'-Wimplicit-function-declaration',
|
||||
'-Wmisleading-indentation',
|
||||
),
|
||||
language : 'c',
|
||||
)
|
||||
|
||||
cdata = configuration_data()
|
||||
|
||||
check_functions = [
|
||||
['strlcat', 'string.h'],
|
||||
['strlcpy', 'string.h'],
|
||||
['strndup', 'string.h'],
|
||||
['strdup', 'string.h'],
|
||||
['strncasecmp', 'strings.h'],
|
||||
['strcasecmp', 'strings.h'],
|
||||
['reallocarray', 'stdlib.h'],
|
||||
['pledge', 'unistd.h'],
|
||||
['unveil', 'unistd.h'],
|
||||
]
|
||||
|
||||
foreach f : check_functions
|
||||
name = f[0].to_upper().underscorify()
|
||||
if cc.has_function(f[0], prefix : '#define _BSD_SOURCE\n#define _DEFAULT_SOURCE\n#define _POSIX_C_SOURCE 200809L\n#include <@0@>'.format(f[1])) and cc.has_header_symbol(f[1], f[0], prefix : '#define _BSD_SOURCE\n#define _DEFAULT_SOURCE\n#define _POSIX_C_SOURCE 200809L')
|
||||
cdata.set('HAVE_@0@'.format(name), 1)
|
||||
cdata.set('HAVE_DECL_@0@'.format(name), 1)
|
||||
else
|
||||
cdata.set('HAVE_DECL_@0@'.format(name), 0)
|
||||
endif
|
||||
endforeach
|
||||
|
||||
default_path = []
|
||||
foreach f : ['libdir', 'datadir']
|
||||
default_path += [join_paths(get_option('prefix'), get_option(f), 'pkgconfig')]
|
||||
endforeach
|
||||
|
||||
personality_path = []
|
||||
foreach f : ['libdir', 'datadir']
|
||||
personality_path += [join_paths(get_option('prefix'), get_option(f), 'pkgconfig', 'personality.d')]
|
||||
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')))
|
||||
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')))
|
||||
endif
|
||||
cdata.set_quoted('PKG_DEFAULT_PATH', ':'.join(default_path))
|
||||
cdata.set_quoted('PERSONALITY_PATH', ':'.join(personality_path))
|
||||
cdata.set_quoted('PACKAGE_NAME', meson.project_name())
|
||||
cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
cdata.set_quoted('PACKAGE_BUGREPORT', 'https://todo.sr.ht/~kaniini/pkgconf')
|
||||
cdata.set('abs_top_srcdir', meson.current_source_dir())
|
||||
cdata.set('abs_top_builddir', meson.current_build_dir())
|
||||
|
||||
|
||||
subdir('libpkgconf')
|
||||
|
||||
libtype = get_option('default_library')
|
||||
if libtype == 'static'
|
||||
build_static = '-DPKGCONFIG_IS_STATIC'
|
||||
else
|
||||
build_static = '-DPKGCONFIG_IS_NOT_STATIC'
|
||||
endif
|
||||
|
||||
libpkgconf = library('pkgconf',
|
||||
'libpkgconf/argvsplit.c',
|
||||
'libpkgconf/audit.c',
|
||||
'libpkgconf/buffer.c',
|
||||
'libpkgconf/bsdstubs.c',
|
||||
'libpkgconf/cache.c',
|
||||
'libpkgconf/client.c',
|
||||
'libpkgconf/dependency.c',
|
||||
'libpkgconf/fileio.c',
|
||||
'libpkgconf/fragment.c',
|
||||
'libpkgconf/parser.c',
|
||||
'libpkgconf/path.c',
|
||||
'libpkgconf/personality.c',
|
||||
'libpkgconf/pkg.c',
|
||||
'libpkgconf/queue.c',
|
||||
'libpkgconf/tuple.c',
|
||||
c_args: ['-DLIBPKGCONF_EXPORT', build_static],
|
||||
install : true,
|
||||
version : '7.0.0',
|
||||
soversion : '7',
|
||||
)
|
||||
|
||||
# For other projects using libpkgconfig as a subproject
|
||||
dep_libpkgconf = declare_dependency(
|
||||
link_with : libpkgconf,
|
||||
include_directories : include_directories('.'),
|
||||
)
|
||||
|
||||
# If we have a new enough meson override the dependency so that only
|
||||
# `dependency('libpkgconf')` is required from the consumer
|
||||
if meson.version().version_compare('>= 0.54.0')
|
||||
meson.override_dependency('libpkgconf', dep_libpkgconf)
|
||||
endif
|
||||
|
||||
pkg = import('pkgconfig')
|
||||
pkg.generate(libpkgconf,
|
||||
name : 'libpkgconf',
|
||||
description : 'a library for accessing and manipulating development framework configuration',
|
||||
url: 'http://github.com/pkgconf/pkgconf',
|
||||
filebase : 'libpkgconf',
|
||||
subdirs: ['pkgconf'],
|
||||
extra_cflags : build_static
|
||||
)
|
||||
|
||||
cli_include = include_directories('cli')
|
||||
|
||||
pkgconf_exe = executable('pkgconf',
|
||||
'cli/main.c',
|
||||
'cli/getopt_long.c',
|
||||
'cli/renderer-msvc.c',
|
||||
link_with : libpkgconf,
|
||||
c_args : build_static,
|
||||
include_directories : cli_include,
|
||||
install : true)
|
||||
|
||||
bomtool_exe = executable('bomtool',
|
||||
'cli/bomtool/main.c',
|
||||
'cli/getopt_long.c',
|
||||
link_with : libpkgconf,
|
||||
c_args : build_static,
|
||||
include_directories : cli_include,
|
||||
install : true)
|
||||
|
||||
with_tests = get_option('tests')
|
||||
kyua_exe = find_program('kyua', required : with_tests, disabler : true, native : true)
|
||||
atf_sh_exe = find_program('atf-sh', required : with_tests, disabler : true, native : true)
|
||||
kyuafile = configure_file(input : 'Kyuafile.in', output : 'Kyuafile', configuration : cdata)
|
||||
test('kyua', kyua_exe, args : ['--config=none', 'test', '--kyuafile', kyuafile, '--build-root', meson.current_build_dir()])
|
||||
subdir('tests')
|
||||
|
||||
install_man('man/bomtool.1')
|
||||
install_man('man/pkgconf.1')
|
||||
install_man('man/pkg.m4.7')
|
||||
install_man('man/pc.5')
|
||||
install_man('man/pkgconf-personality.5')
|
||||
install_data('pkg.m4', install_dir: 'share/aclocal')
|
||||
install_data('AUTHORS', install_dir: 'share/doc/pkgconf')
|
||||
install_data('README.md', install_dir: 'share/doc/pkgconf')
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
conf_data = configuration_data()
|
||||
conf_data.set('VERSION', meson.project_version())
|
||||
conf_data.set('EXE', pkgconf_exe.full_path())
|
||||
conf_data.set('DLL', libpkgconf.full_path())
|
||||
if host_machine.cpu() != 'x86_64'
|
||||
wixl_arch = 'x86'
|
||||
else
|
||||
wixl_arch = 'x64'
|
||||
endif
|
||||
conf_data.set('WIXL_ARCH', wixl_arch)
|
||||
|
||||
python = find_program('python3')
|
||||
wixl = find_program('wixl', required: false, version: '>= 0.105')
|
||||
msi_filename = 'pkgconf-@0@-@1@.msi'.format(wixl_arch, meson.project_version())
|
||||
|
||||
wxsfile = configure_file(input: 'pkgconf.wxs.in', output: 'pkgconf.wxs', configuration: conf_data)
|
||||
|
||||
if wixl.found()
|
||||
licensefile = custom_target(
|
||||
'License.rtf',
|
||||
input: 'COPYING',
|
||||
output: 'License.rtf',
|
||||
command: [python, files('txt2rtf.py'), '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
|
||||
msi = custom_target(
|
||||
msi_filename,
|
||||
input: [wxsfile, licensefile, pkgconf_exe],
|
||||
output: msi_filename,
|
||||
command: [wixl, '--arch', wixl_arch, '--ext', 'ui', '-o', msi_filename, wxsfile],
|
||||
)
|
||||
|
||||
alias_target('msi', msi)
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,19 @@
|
||||
option(
|
||||
'tests',
|
||||
type: 'feature',
|
||||
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})'
|
||||
)
|
||||
@@ -0,0 +1,350 @@
|
||||
# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*-
|
||||
# serial 13 (pkgconf)
|
||||
|
||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||
dnl
|
||||
dnl This program is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 2 of the License, or
|
||||
dnl (at your option) any later version.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful, but
|
||||
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
dnl General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
dnl along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
dnl
|
||||
dnl As a special exception to the GNU General Public License, if you
|
||||
dnl distribute this file as part of a program that contains a
|
||||
dnl configuration script generated by Autoconf, you may include it under
|
||||
dnl the same distribution terms that you use for the rest of that
|
||||
dnl program.
|
||||
|
||||
dnl PKG_PREREQ(MIN-VERSION)
|
||||
dnl -----------------------
|
||||
dnl Since: 0.29
|
||||
dnl
|
||||
dnl Verify that the version of the pkg-config macros are at least
|
||||
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
|
||||
dnl installed version of pkg-config, this checks the developer's version
|
||||
dnl of pkg.m4 when generating configure.
|
||||
dnl
|
||||
dnl To ensure that this macro is defined, also add:
|
||||
dnl m4_ifndef([PKG_PREREQ],
|
||||
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
|
||||
dnl
|
||||
dnl See the "Since" comment for each macro you use to see what version
|
||||
dnl of the macros you require.
|
||||
m4_defun([PKG_PREREQ],
|
||||
[m4_define([PKG_MACROS_VERSION], [0.29.2])
|
||||
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])])
|
||||
])dnl PKG_PREREQ
|
||||
|
||||
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND])
|
||||
dnl ---------------------------------------------------------
|
||||
dnl Since: 0.16
|
||||
dnl
|
||||
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
|
||||
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 used since that's the first version where most current features of
|
||||
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],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
|
||||
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
|
||||
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
|
||||
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi
|
||||
if test -z "$PKG_CONFIG"; then
|
||||
m4_default([$2], [AC_MSG_ERROR([pkg-config not found])])
|
||||
fi[]dnl
|
||||
])dnl PKG_PROG_PKG_CONFIG
|
||||
|
||||
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl -------------------------------------------------------------------
|
||||
dnl Since: 0.18
|
||||
dnl
|
||||
dnl Check to see whether a particular set of modules exists. Similar to
|
||||
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
dnl
|
||||
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
dnl only at the first occurrence in configure.ac, so if the first place
|
||||
dnl it's called might be skipped (such as if it is within an "if", you
|
||||
dnl have to call PKG_CHECK_EXISTS manually
|
||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||
m4_default([$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
dnl ---------------------------------------------
|
||||
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
|
||||
dnl pkg_failed based on the result.
|
||||
m4_define([_PKG_CONFIG],
|
||||
[if test -n "$$1"; then
|
||||
pkg_cv_[]$1="$$1"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
PKG_CHECK_EXISTS([$3],
|
||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes ],
|
||||
[pkg_failed=yes])
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi[]dnl
|
||||
])dnl _PKG_CONFIG
|
||||
|
||||
dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||
dnl ---------------------------
|
||||
dnl Internal check to see if pkg-config supports short errors.
|
||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
dnl [ACTION-IF-NOT-FOUND])
|
||||
dnl --------------------------------------------------------------
|
||||
dnl Since: 0.4.0
|
||||
dnl
|
||||
dnl Note that if there is a possibility the first call to
|
||||
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
AC_DEFUN([PKG_CHECK_MODULES],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
pkg_failed=no
|
||||
AC_MSG_CHECKING([for $2])
|
||||
|
||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
AC_MSG_RESULT([no])
|
||||
_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
||||
else
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
m4_default([$4], [AC_MSG_ERROR(
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_PKG_TEXT])[]dnl
|
||||
])
|
||||
elif test $pkg_failed = untried; then
|
||||
AC_MSG_RESULT([no])
|
||||
m4_default([$4], [AC_MSG_FAILURE(
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
|
||||
])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
$3
|
||||
fi[]dnl
|
||||
])dnl PKG_CHECK_MODULES
|
||||
|
||||
|
||||
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
dnl [ACTION-IF-NOT-FOUND])
|
||||
dnl ---------------------------------------------------------------------
|
||||
dnl Since: 0.29
|
||||
dnl
|
||||
dnl Checks for existence of MODULES and gathers its build flags with
|
||||
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
|
||||
dnl and VARIABLE-PREFIX_LIBS from --libs.
|
||||
dnl
|
||||
dnl Note that if there is a possibility the first call to
|
||||
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
|
||||
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
|
||||
dnl configure.ac.
|
||||
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
_save_PKG_CONFIG=$PKG_CONFIG
|
||||
PKG_CONFIG="$PKG_CONFIG --static"
|
||||
PKG_CHECK_MODULES($@)
|
||||
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
|
||||
])dnl PKG_CHECK_MODULES_STATIC
|
||||
|
||||
|
||||
dnl PKG_INSTALLDIR([DIRECTORY])
|
||||
dnl -------------------------
|
||||
dnl Since: 0.27
|
||||
dnl
|
||||
dnl Substitutes the variable pkgconfigdir as the location where a module
|
||||
dnl should install pkg-config .pc files. By default the directory is
|
||||
dnl $libdir/pkgconfig, but the default can be changed by passing
|
||||
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
|
||||
dnl parameter.
|
||||
AC_DEFUN([PKG_INSTALLDIR],
|
||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
||||
m4_pushdef([pkg_description],
|
||||
[pkg-config installation directory @<:@]pkg_default[@:>@])
|
||||
AC_ARG_WITH([pkgconfigdir],
|
||||
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
|
||||
[with_pkgconfigdir=]pkg_default)
|
||||
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
||||
m4_popdef([pkg_default])
|
||||
m4_popdef([pkg_description])
|
||||
])dnl PKG_INSTALLDIR
|
||||
|
||||
|
||||
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
|
||||
dnl --------------------------------
|
||||
dnl Since: 0.27
|
||||
dnl
|
||||
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
|
||||
dnl module should install arch-independent pkg-config .pc files. By
|
||||
dnl default the directory is $datadir/pkgconfig, but the default can be
|
||||
dnl changed by passing DIRECTORY. The user can override through the
|
||||
dnl --with-noarch-pkgconfigdir parameter.
|
||||
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
||||
m4_pushdef([pkg_description],
|
||||
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
|
||||
AC_ARG_WITH([noarch-pkgconfigdir],
|
||||
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
|
||||
[with_noarch_pkgconfigdir=]pkg_default)
|
||||
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
||||
m4_popdef([pkg_default])
|
||||
m4_popdef([pkg_description])
|
||||
])dnl PKG_NOARCH_INSTALLDIR
|
||||
|
||||
|
||||
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
||||
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl -------------------------------------------
|
||||
dnl Since: 0.28
|
||||
dnl
|
||||
dnl Retrieves the value of the pkg-config variable for the given module.
|
||||
AC_DEFUN([PKG_CHECK_VAR],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
||||
|
||||
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||
|
||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||
])dnl PKG_CHECK_VAR
|
||||
|
||||
dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------
|
||||
dnl
|
||||
dnl Prepare a "--with-" configure option using the lowercase
|
||||
dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
|
||||
dnl PKG_CHECK_MODULES in a single macro.
|
||||
AC_DEFUN([PKG_WITH_MODULES],
|
||||
[
|
||||
m4_pushdef([with_arg], m4_tolower([$1]))
|
||||
|
||||
m4_pushdef([description],
|
||||
[m4_default([$5], [build with ]with_arg[ support])])
|
||||
|
||||
m4_pushdef([def_arg], [m4_default([$6], [auto])])
|
||||
m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
|
||||
m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
|
||||
|
||||
m4_case(def_arg,
|
||||
[yes],[m4_pushdef([with_without], [--without-]with_arg)],
|
||||
[m4_pushdef([with_without],[--with-]with_arg)])
|
||||
|
||||
AC_ARG_WITH(with_arg,
|
||||
AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
|
||||
[AS_TR_SH([with_]with_arg)=def_arg])
|
||||
|
||||
AS_CASE([$AS_TR_SH([with_]with_arg)],
|
||||
[yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
|
||||
[auto],[PKG_CHECK_MODULES([$1],[$2],
|
||||
[m4_n([def_action_if_found]) $3],
|
||||
[m4_n([def_action_if_not_found]) $4])])
|
||||
|
||||
m4_popdef([with_arg])
|
||||
m4_popdef([description])
|
||||
m4_popdef([def_arg])
|
||||
|
||||
])dnl PKG_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl -----------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
|
||||
dnl check._[VARIABLE-PREFIX] is exported as make variable.
|
||||
AC_DEFUN([PKG_HAVE_WITH_MODULES],
|
||||
[
|
||||
PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
|
||||
|
||||
AM_CONDITIONAL([HAVE_][$1],
|
||||
[test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
|
||||
])dnl PKG_HAVE_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
|
||||
dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
|
||||
dnl and preprocessor variable.
|
||||
AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
|
||||
[
|
||||
PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
|
||||
|
||||
AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
|
||||
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
|
||||
])dnl PKG_HAVE_DEFINE_WITH_MODULES
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
|
||||
<?define Arch = "@WIXL_ARCH@"?>
|
||||
<?if $(var.Arch) = "x64"?>
|
||||
<?define GLIB_ARCH = "win64"?>
|
||||
<?define ArchString = "64-bit"?>
|
||||
<?define ArchProgramFilesFolder = "ProgramFiles64Folder"?>
|
||||
<?define Win64 = "yes"?>
|
||||
<?else?>
|
||||
<?define GLIB_ARCH = "win32"?>
|
||||
<?define ArchString = "32-bit"?>
|
||||
<?define ArchProgramFilesFolder = "ProgramFilesFolder"?>
|
||||
<?define Win64 = "no"?>
|
||||
<?endif?>
|
||||
|
||||
|
||||
<Product Id="*"
|
||||
Name="pkgconf @VERSION@ ($(var.ArchString))"
|
||||
Language="1033"
|
||||
Version="@VERSION@"
|
||||
Manufacturer="pkgconf"
|
||||
UpgradeCode="4faedad2-3f9d-45cc-89a7-3732ad2db0f7">
|
||||
|
||||
<Package InstallerVersion="200"
|
||||
Compressed="yes"
|
||||
InstallScope="perMachine" />
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Feature Id="ProductFeature" Title="pkgconf" Level="1">
|
||||
<ComponentGroupRef Id="ProductComponents" />
|
||||
</Feature>
|
||||
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="$(var.ArchProgramFilesFolder)">
|
||||
<Directory Id="INSTALLFOLDER" Name="pkgconf @VERSION@" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
|
||||
<Component Id="PkgconfExe" Guid="*" Win64="$(var.Win64)">
|
||||
<File Id="PkgconfExeFile"
|
||||
Source="@EXE@"
|
||||
KeyPath="yes" />
|
||||
<File Id="PkgconfigExeFile"
|
||||
Name="pkg-config.exe"
|
||||
Source="@EXE@"/>
|
||||
<File Id="PkgconfDllFile"
|
||||
Source="@DLL@"/>
|
||||
<Environment Id="PATH"
|
||||
Name="PATH"
|
||||
Value="[INSTALLFOLDER]"
|
||||
Permanent="no"
|
||||
Part="last"
|
||||
Action="set"
|
||||
System="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
<UIRef Id="WixUI_Minimal" />
|
||||
</Product>
|
||||
</Wix>
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite('pkgconf')
|
||||
|
||||
atf_test_program{name='basic'}
|
||||
atf_test_program{name='requires'}
|
||||
atf_test_program{name='regress'}
|
||||
atf_test_program{name='parser'}
|
||||
atf_test_program{name='sysroot'}
|
||||
atf_test_program{name='conflicts'}
|
||||
atf_test_program{name='version'}
|
||||
atf_test_program{name='framework'}
|
||||
atf_test_program{name='provides'}
|
||||
atf_test_program{name='symlink'}
|
||||
Executable
+391
@@ -0,0 +1,391 @@
|
||||
#!/usr/bin/env atf-sh
|
||||
|
||||
. $(atf_get_srcdir)/test_env.sh
|
||||
|
||||
tests_init \
|
||||
noargs \
|
||||
libs \
|
||||
libs_cflags \
|
||||
libs_cflags_version \
|
||||
libs_cflags_version_multiple \
|
||||
libs_cflags_version_alt \
|
||||
libs_cflags_version_different \
|
||||
libs_cflags_version_different_bad \
|
||||
libs_env \
|
||||
exists_nonexitent \
|
||||
nonexitent \
|
||||
exists_version \
|
||||
exists_version_bad \
|
||||
exists_version_bad2 \
|
||||
exists_version_bad3 \
|
||||
exists \
|
||||
exists2 \
|
||||
exists3 \
|
||||
exists_version_alt \
|
||||
exists_cflags \
|
||||
exists_cflags_env \
|
||||
uninstalled_bad \
|
||||
uninstalled \
|
||||
libs_intermediary \
|
||||
libs_circular1 \
|
||||
libs_circular2 \
|
||||
libs_circular_directpc \
|
||||
libs_static \
|
||||
libs_static_ordering \
|
||||
libs_metapackage \
|
||||
license_isc \
|
||||
license_noassertion \
|
||||
modversion_noflatten \
|
||||
pkg_config_path \
|
||||
nolibs \
|
||||
nocflags \
|
||||
arbitary_path \
|
||||
with_path \
|
||||
relocatable \
|
||||
single_depth_selectors \
|
||||
print_variables_env \
|
||||
variable_env \
|
||||
variable_no_recurse
|
||||
|
||||
noargs_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check -s exit:1 -e ignore pkgconf
|
||||
}
|
||||
|
||||
libs_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lfoo\n" \
|
||||
pkgconf --libs foo
|
||||
}
|
||||
|
||||
libs_cflags_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-fPIC -I/test/include/foo -L/test/lib -lfoo\n" \
|
||||
pkgconf --cflags --libs foo
|
||||
}
|
||||
|
||||
atf_test_case basic_libs_cflags_version
|
||||
libs_cflags_version_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-fPIC -I/test/include/foo -L/test/lib -lfoo\n" \
|
||||
pkgconf --cflags --libs 'foo > 1.2'
|
||||
}
|
||||
|
||||
libs_cflags_version_multiple_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-fPIC -I/test/include/foo -L/test/lib -lbar -lfoo\n" \
|
||||
pkgconf --cflags --libs 'foo > 1.2 bar >= 1.3'
|
||||
}
|
||||
|
||||
libs_cflags_version_multiple_coma_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-fPIC -I/test/include/foo -L/test/lib -lbar -lfoo\n" \
|
||||
pkgconf --cflags --libs 'foo > 1.2,bar >= 1.3'
|
||||
}
|
||||
|
||||
libs_cflags_version_alt_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-fPIC -I/test/include/foo -L/test/lib -lfoo\n" \
|
||||
pkgconf --cflags --libs 'foo' '>' '1.2'
|
||||
}
|
||||
|
||||
libs_cflags_version_different_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-fPIC -I/test/include/foo -L/test/lib -lfoo\n" \
|
||||
pkgconf --cflags --libs 'foo' '!=' '1.3.0'
|
||||
}
|
||||
|
||||
atf_test_case basic_libs_cflags_version_different_bad
|
||||
libs_cflags_version_different_bad_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-s exit:1 \
|
||||
-e inline:"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" \
|
||||
pkgconf --cflags --libs 'foo' '!=' '1.2.3'
|
||||
}
|
||||
|
||||
exists_nonexitent_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-s exit:1 \
|
||||
pkgconf --exists nonexistant
|
||||
}
|
||||
|
||||
nonexitent_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-s exit:1 \
|
||||
pkgconf nonexistant
|
||||
}
|
||||
|
||||
exists_version_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
pkgconf --exists 'foo > 1.2'
|
||||
}
|
||||
|
||||
exists_version_bad_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-s exit:1 \
|
||||
pkgconf --exists 'foo > 1.2.3'
|
||||
}
|
||||
|
||||
exists_version_alt_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
pkgconf --exists 'foo' '>' '1.2'
|
||||
}
|
||||
|
||||
uninstalled_bad_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-s exit:1 \
|
||||
pkgconf --uninstalled 'foo'
|
||||
}
|
||||
|
||||
uninstalled_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
pkgconf --uninstalled 'omg'
|
||||
}
|
||||
|
||||
exists_version_bad2_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-s exit:1 \
|
||||
pkgconf --exists 'foo >= '
|
||||
}
|
||||
|
||||
exists_version_bad3_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-s exit:1 \
|
||||
pkgconf --exists 'tilde >= 1.0.0'
|
||||
}
|
||||
|
||||
exists_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
pkgconf --exists 'tilde = 1.0.0~rc1'
|
||||
}
|
||||
|
||||
exists2_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
pkgconf --exists 'tilde <= 1.0.0'
|
||||
}
|
||||
|
||||
exists3_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
pkgconf --exists '' 'foo'
|
||||
}
|
||||
|
||||
libs_intermediary_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-lintermediary-1 -lintermediary-2 -lfoo -lbar -lbaz\n" \
|
||||
pkgconf --libs intermediary-1 intermediary-2
|
||||
}
|
||||
|
||||
libs_circular2_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"circular-1: breaking circular reference (circular-1 -> circular-2 -> circular-1)\n" \
|
||||
pkgconf circular-2 --validate
|
||||
}
|
||||
|
||||
libs_circular1_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"circular-3: breaking circular reference (circular-3 -> circular-1 -> circular-3)\n" \
|
||||
pkgconf circular-1 --validate
|
||||
}
|
||||
|
||||
libs_circular_directpc_body()
|
||||
{
|
||||
atf_check \
|
||||
-o inline:"-lcircular-3 -lcircular-1 -lcircular-2\n" \
|
||||
pkgconf --libs ${selfdir}/lib1/circular-3.pc
|
||||
}
|
||||
|
||||
libs_static_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"/libfoo.a -pthread\n" \
|
||||
pkgconf --libs static-archive-libs
|
||||
}
|
||||
|
||||
libs_static_ordering_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lbar -lfoo\n" \
|
||||
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()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1${PATH_SEP}${selfdir}/lib2"
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lfoo\n" \
|
||||
pkgconf --libs foo
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lbar -lfoo\n" \
|
||||
pkgconf --libs bar
|
||||
}
|
||||
|
||||
with_path_body()
|
||||
{
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lfoo\n" \
|
||||
pkgconf --with-path=${selfdir}/lib1 --with-path=${selfdir}/lib2 --libs foo
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lbar -lfoo\n" \
|
||||
pkgconf --with-path=${selfdir}/lib1 --with-path=${selfdir}/lib2 --libs bar
|
||||
}
|
||||
|
||||
nolibs_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"\n" \
|
||||
pkgconf --libs nolib
|
||||
}
|
||||
|
||||
nocflags_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"\n" \
|
||||
pkgconf --cflags nocflag
|
||||
}
|
||||
|
||||
arbitary_path_body()
|
||||
{
|
||||
cp ${selfdir}/lib1/foo.pc .
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lfoo\n" \
|
||||
pkgconf --libs foo.pc
|
||||
}
|
||||
|
||||
relocatable_body()
|
||||
{
|
||||
basedir=$(pkgconf --relocate ${selfdir})
|
||||
atf_check \
|
||||
-o inline:"${basedir}/lib-relocatable\n" \
|
||||
pkgconf --define-prefix --variable=prefix ${basedir}/lib-relocatable/lib/pkgconfig/foo.pc
|
||||
}
|
||||
|
||||
single_depth_selectors_body()
|
||||
{
|
||||
export PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH=1
|
||||
atf_check \
|
||||
-o inline:"foo\n" \
|
||||
pkgconf --with-path=${selfdir}/lib3 --print-requires bar
|
||||
}
|
||||
|
||||
license_isc_body()
|
||||
{
|
||||
atf_check \
|
||||
-o inline:"foo: ISC\n" \
|
||||
pkgconf --with-path=${selfdir}/lib1 --license foo
|
||||
}
|
||||
|
||||
license_noassertion_body()
|
||||
{
|
||||
atf_check \
|
||||
-o inline:"bar: NOASSERTION\nfoo: ISC\n" \
|
||||
pkgconf --with-path=${selfdir}/lib1 --license bar
|
||||
}
|
||||
|
||||
modversion_noflatten_body()
|
||||
{
|
||||
atf_check \
|
||||
-o inline:"1.3\n" \
|
||||
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
|
||||
}
|
||||
|
||||
variable_no_recurse_body()
|
||||
{
|
||||
atf_check \
|
||||
-o inline:"/test/include\n" \
|
||||
pkgconf --with-path=${selfdir}/lib1 --variable=includedir bar
|
||||
}
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env atf-sh
|
||||
|
||||
. $(atf_get_srcdir)/test_env.sh
|
||||
|
||||
tests_init \
|
||||
modversion \
|
||||
variable \
|
||||
define_variable \
|
||||
global_variable
|
||||
|
||||
modversion_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"1.0.1 \n" \
|
||||
pkgconf --modversion pkg-config
|
||||
}
|
||||
|
||||
variable_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"/test \n" \
|
||||
pkgconf --variable=prefix foo
|
||||
}
|
||||
|
||||
define_variable_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"/test2 \n" \
|
||||
pkgconf --define-variable=prefix=/test2 --variable=prefix foo
|
||||
}
|
||||
|
||||
global_variable_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"${selfdir}/lib1 \n"
|
||||
pkgconf --exists -foo
|
||||
}
|
||||
|
||||
argv_parse_3_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-llib-1 -pthread /test/lib/lib2.so \n" \
|
||||
pkgconf --libs argv-parse-3
|
||||
}
|
||||
|
||||
tilde_quoting_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-L~ -ltilde \n" \
|
||||
pkgconf --libs tilde-quoting
|
||||
atf_check \
|
||||
-o inline:"-I~ \n" \
|
||||
pkgconf --cflags tilde-quoting
|
||||
}
|
||||
|
||||
paren_quoting_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-L\$(libdir) -ltilde \n" \
|
||||
pkgconf --libs paren-quoting
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env atf-sh
|
||||
|
||||
. $(atf_get_srcdir)/test_env.sh
|
||||
|
||||
tests_init \
|
||||
libs \
|
||||
ignore
|
||||
|
||||
libs_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lconflicts\n" \
|
||||
pkgconf --libs conflicts
|
||||
}
|
||||
|
||||
ignore_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-L/test/lib -lconflicts\n" \
|
||||
pkgconf --ignore-conflicts --libs conflicts
|
||||
}
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env atf-sh
|
||||
|
||||
. $(atf_get_srcdir)/test_env.sh
|
||||
|
||||
tests_init \
|
||||
libs
|
||||
|
||||
libs_body()
|
||||
{
|
||||
export PKG_CONFIG_PATH="${selfdir}/lib1"
|
||||
atf_check \
|
||||
-o inline:"-F/test/lib -framework framework-1\n" \
|
||||
pkgconf --libs framework-1
|
||||
atf_check \
|
||||
-o inline:"-F/test/lib -framework framework-2 -framework framework-1\n" \
|
||||
pkgconf --libs framework-2
|
||||
atf_check \
|
||||
-o inline:"-F/test/lib -framework framework-2 -framework framework-1\n" \
|
||||
pkgconf --libs framework-1 framework-2
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: foo
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -L${libdir} -lfoo
|
||||
Cflags: -fPIC -I${includedir}/foo
|
||||
Cflags.private: -DFOO_STATIC
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: argv-parse-2
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -llib-1 -pthread ${libdir}/lib2.so
|
||||
Cflags:
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: argv-parse-3
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -llib-1 \
|
||||
-pthread ${libdir}/lib2.so
|
||||
Cflags:
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: argv-parse
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -llib-3 -llib-1 -llib-2 -lpthread
|
||||
Cflags:
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: bar
|
||||
Description: Another pkg-config test
|
||||
Version: 1.3
|
||||
Libs: -L${libdir} -lbar
|
||||
Requires: foo
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: bar
|
||||
Description: Another pkg-config test (with private Requires, ha!)
|
||||
Version: 1.3
|
||||
Libs: -L${libdir} -lbaz
|
||||
Libs.private: -L${libdir} -lzee
|
||||
Requires.private: foo
|
||||
@@ -0,0 +1,13 @@
|
||||
v9=lol
|
||||
v8=${v9}${v9}${v9}${v9}${v9}${v9}${v9}${v9}${v9}${v9}
|
||||
v7=${v8}${v8}${v8}${v8}${v8}${v8}${v8}${v8}${v8}${v8}
|
||||
v6=${v7}${v7}${v7}${v7}${v7}${v7}${v7}${v7}${v7}${v7}
|
||||
v5=${v6}${v6}${v6}${v6}${v6}${v6}${v6}${v6}${v6}${v6}
|
||||
v4=${v5}${v5}${v5}${v5}${v5}${v5}${v5}${v5}${v5}${v5}
|
||||
v3=${v4}${v4}${v4}${v4}${v4}${v4}${v4}${v4}${v4}${v4}
|
||||
v2=${v3}${v3}${v3}${v3}${v3}${v3}${v3}${v3}${v3}${v3}
|
||||
v1=${v2}${v2}${v2}${v2}${v2}${v2}${v2}${v2}${v2}${v2}
|
||||
v0=${v1}${v1}${v1}${v1}${v1}${v1}${v1}${v1}${v1}${v1}
|
||||
Name: One Billion Laughs
|
||||
Version: ${v0}
|
||||
Description: Don't install this!
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
This is a C-style comment, which technically isn't allowed, but
|
||||
some pkg-config files use them.
|
||||
*/
|
||||
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: c-comment
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -L${libdir} -lfoo
|
||||
Cflags: -fPIC -I${includedir}/foo
|
||||
Cflags.private: -DFOO_STATIC
|
||||
License: ISC
|
||||
@@ -0,0 +1,7 @@
|
||||
foo=3
|
||||
Foo=4
|
||||
|
||||
Name: case-sensitivity
|
||||
Description: Package for testing case-sensitivity
|
||||
Version: 1
|
||||
Requires: foo < ${foo}
|
||||
@@ -0,0 +1,9 @@
|
||||
prefix=/test/local
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: cflags-internal
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Cflags: -I${includedir}/foo
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=/test/local
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: cflags-libs-only
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -L${libdir} -lfoo
|
||||
Cflags: -I${includedir}/foo
|
||||
@@ -0,0 +1,7 @@
|
||||
Name: cflags-libs-private-a
|
||||
Version: 1
|
||||
Description: test case for issue #370
|
||||
Cflags:
|
||||
Libs:
|
||||
Requires.private: cflags-libs-private-b
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
Name: cflags-libs-private-b
|
||||
Version: 1
|
||||
Description: test case for issue #370
|
||||
Cflags:
|
||||
Libs:
|
||||
Requires: cflags-libs-private-c
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Name: cflags-libs-private-c
|
||||
Version: 1
|
||||
Description: test case for issue #370
|
||||
Cflags:
|
||||
Libs: -lc
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Name: CFlags Trailing Whitespace Bug
|
||||
Description: Demonstrates problems with -I with spaces
|
||||
Version: 1
|
||||
Cflags: -I/usr/include -I/usr/include/foo
|
||||
@@ -0,0 +1,4 @@
|
||||
Name: CFlags Whitespace Bug
|
||||
Description: Demonstrates problems with -I with spaces and sysroot munging
|
||||
Version: 1
|
||||
Cflags: -I /opt/bad/include
|
||||
@@ -0,0 +1,11 @@
|
||||
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
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: circular-1
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -lcircular-1
|
||||
Requires: circular-2
|
||||
Cflags:
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: circular-2
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -lcircular-2
|
||||
Requires: circular-3
|
||||
Cflags:
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: circular-3
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -lcircular-3
|
||||
Requires: circular-1
|
||||
Cflags:
|
||||
@@ -0,0 +1,9 @@
|
||||
Name: comments-in-fields
|
||||
Description: Comments in fields test case
|
||||
URL: http://pkgconf.org/
|
||||
Version: 0
|
||||
Requires: # foo
|
||||
Requires.private: foo
|
||||
Libs: -lfoo # -lbar
|
||||
Libs.private: -lbar
|
||||
Cflags: -I${includedir}
|
||||
@@ -0,0 +1,6 @@
|
||||
Name: comments
|
||||
Description: Portable CD-ROM I/O library
|
||||
Version: 0
|
||||
#Requires: bar-2.0
|
||||
Libs: -lfoo
|
||||
Cflags: -I${includedir}
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: conflicts
|
||||
Description: A testing pkg-config file
|
||||
Conflicts: foo <= 1.3
|
||||
Version: 1.2.3
|
||||
Libs: -L${libdir} -lconflicts
|
||||
Cflags: -fPIC -I${includedir}/conflicts
|
||||
@@ -0,0 +1,12 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: depgraph-break
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -L${libdir} -lfoo
|
||||
Cflags: -fPIC -I${includedir}/foo
|
||||
Cflags.private: -DFOO_STATIC
|
||||
Requires: nonexistant
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: dos-lineendings
|
||||
Description: A testing pkg-config file
|
||||
Version: 1.2.3
|
||||
Libs: -L${libdir}/dos-lineendings -ldos-lineendings
|
||||
Cflags: -fPIC -I${includedir}/dos-lineendings
|
||||
@@ -0,0 +1,6 @@
|
||||
xcflags=
|
||||
|
||||
Name: empty-tuple
|
||||
Description: testing file
|
||||
Version: 1
|
||||
CFlags: ${xcflags}
|
||||
@@ -0,0 +1,4 @@
|
||||
Name: escaped-backslash
|
||||
Version: 1
|
||||
Description: test package for backslash escape scenario
|
||||
Cflags: -IC:\\A
|
||||
@@ -0,0 +1,7 @@
|
||||
prefix=/usr
|
||||
datarootdir=${prefix}/share
|
||||
pkgdatadir=${pc_sysrootdir}/${datarootdir}/test
|
||||
|
||||
Name: Test
|
||||
Description: Testing pc_sysrootdir auto-expansion
|
||||
Version: 1.0
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
cflags=-I${includedir}
|
||||
|
||||
Name: flag order 1
|
||||
Description: test for flag ordering
|
||||
Version: 1
|
||||
Libs: -L${libdir} -Bdynamic -lfoo -Bstatic -lbar
|
||||
@@ -0,0 +1,10 @@
|
||||
prefix=/test
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
cflags=-I${includedir}
|
||||
|
||||
Name: flag order 3
|
||||
Description: test for flag ordering
|
||||
Version: 1
|
||||
Libs: -L${libdir} -Wl,--start-group -lfoo -lbar -Wl,--end-group
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user