The iteration order of GHashTable changed in GLib 2.59, which broke the
check-print-options test, as it relied on a fixed output order from the
--list-all argument to pkg-config.
Fix that by making print_package_list() output in alphabetical order by
Package.key; and update the test to match. This should work with older
and newer versions of GLib.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Treat -isystem and -idirafter as -I Cflags since they control the
compiler search path. Adjust the sysroot handling so that the arguments
to these options have the sysroot prefixed. However, leave them out of the
system Cflags handling since these directives are explicitly trying to
adjust the compiler's system header search behavior.
The special-flags test case output needs adjustment since all the flags
are now considered -I flags and come out in the order specified in the
pc file.
https://bugs.freedesktop.org/show_bug.cgi?id=97337
Currently pkg-config scans all .pc files from the search path during
initialization. That makes some of the code simpler and works fine when
there are not many .pc files on the system. When there are a lot of .pc
files, then this represents a lot of wasted effort.
Rework the package gathering so that it happens as needed. To support
the --list-all mode, the scanning at initialization can still be done.
https://bugs.freedesktop.org/show_bug.cgi?id=98215
Adds a hash table to the package list expansion to avoid iterating over
the children of package nodes that have already been visited. Without
this, the expansion is exponential. For library sets with a high degree
of dependency, iteration over the tree with revisiting results, in
practice, in significant slow down at best and pkg-config failure due to
memory exhaustion at worst. The resulting algorithm is equivalent to a
topological sort.
The change to unquote values in the --variable output broke users that
had shell special characters in the variable. Instead, only unquote if
the value starts with " or '. A larger fix to do a full unquote, split
and escaping like --cflags/--libs is possible, but that might break the
old semantics even further.
Add a new function, parse_package_variable(), to handle that logic.
https://bugs.freedesktop.org/show_bug.cgi?id=93284
pkg-config allows a way to override package variables through the
--define-prefix interface, but this is very cumbersome to do in a global
way since it always needs to be passed on the command line and the
override cannot be scoped to a single packge.
Allow overriding package variables using environment variables of the
form PKG_CONFIG_$PACKAGE_$VARIABLE. For example, setting
PKG_CONFIG_GLADEUI_2_0_CATALOGDIR will override the variable
"catalogdir" in the "gladeui-2.0" package.
https://bugs.freedesktop.org/show_bug.cgi?id=90917
Port the code to use the GDir APIs from dirent so that we don't have to
depend on a dirent implementation on platforms that do not have it, such
as Visual Studio, so that it is possible to build pkg-config out of the
box on any platform that is supported by GLib (and the bundled GLib).
Since we unquote variables on printing, we want to quote in before adding
to the database. For all other variables defined in .pc files, we assume
that the user has quoted the variable correctly.
This was broken with the fix for bug 67904, but seems to only affect
Windows builds.
Rather than responding to the pcfiledir variable specially, store it
in the hash table with all the other package specific variables. This
does result in pcfiledir showing up in the --print-variables output.
The goal is for pkgname to hold the name without the trailing ".pc"
extension (according to the meaning of EXT_LEN as used in the
ends_in_dotpc() function). But the malloc is hardcoded as 2. If the
extension were to be changed, the number of characters being strncpy'ed
would not match the size of the target buffer. Instead, the malloc
should use the EXT_LEN token (adjusted for the trailing \0).
Freedesktop #80378 (https://bugs.freedesktop.org/show_bug.cgi?id=80378)
This allows the --debug output to follow the actual order of the
directories specified in the path.
$ PKG_CONFIG_PATH=/nosuch1:/nosuch2:/dir-with-foo.pc
$ pkg-config --debug foo
[...]
Path position of 'foo' is 1
With this change, the path position above would be 3, matching the
position in PKG_CONFIG_PATH.
Freedesktop #80380 (https://bugs.freedesktop.org/show_bug.cgi?id=80380)
If a --variable is requested, make sure to remove the quoting since it's
likely the value will be used verbatim in shell command substitution. If
the quotes remain in the value, they'd get embedded in the shell
variable, too.
Freedesktop #67904 (https://bugs.freedesktop.org/show_bug.cgi?id=67904)
pkg-config leaves a trailing space on the flags output as it may have to
do multiple iterations to collect all output and adding the space makes
concatenation simple. However, this leaves a trailing space on the full
returned string unless it's empty. Strip the trailing space after all
the processing is complete.
The rpmvercmp code is taken directly from upstream. Moving it to a
separate file allows it to be diffed and synced easily with the upstream
version. It also becomes really easy to switch to the actual rpmlib
version if that's ever desired.
Instead of keeping of list of packages in the current Requires chain and
searching it repeatedly, just mark each package as part of the chain or
not. This nearly cuts in half the time on a particularly rough torture
test I have.
pkg-config strips all duplicate arguments from the flag output string.
This is done for 2 reasons:
1. When a package shows up twice in the final package list after
resolving all Requires, stripping was used to ensure it's flags only
showed up once at the correct location.
2. An optimization so that the output string is not excessively long.
Since commit c6ec7869, 1. is no longer necessary as the final package
list only contains each package once. 2. causes problems when applied
too aggressively since some arguments have different semantics depending
on the prior or subsequent arguments.
To keep a bit of optimization, the stripping is reduced to only removing
consecutive duplicate arguments. This should ensure that the semantics
are kept intact while removing obviously unnecessary arguments.
The drawback is that some arguments will now appear multiple times in
the output when they previously would have only appeared once. Here we
have to rely on the tools using these arguments to handle the duplicates
appropriately since there is no way for pkg-config to encode all the
semantics of those arguments. Another thing that can help this situation
is if pkg-config is used for all packages in the Requires chain so that
the Libs/Cflags of each package only pertain to itself and don't encode
the compiling/linking rules of a 3rd party package.
Freedesktop #16101 (https://bugs.freedesktop.org/show_bug.cgi?id=16101)
Often other Libs flags have semantics that are based on their context
with -l arguments. For example, the GNU linker options
-Bdynamic/-Bstatic pertain only to the objects or link options that
follow them. So, a valid link command containing these options would get
mangled by pkg-config since it separates -l flags from others..
-Bdynamic -la -Bstatic -lb -> -Bdynamic -Bstatic -la -lb
Instead, output -l and other Libs flags in a single pass so they mantain
their ordering.
Freedesktop #19950 (https://bugs.freedesktop.org/show_bug.cgi?id=19950)
Instead of splitting to -l/-L/other and -I/other, keep the args together
and mark each argument with its type. Then we can maintain order all the
way through.
Outputting other Libs flags such as -Wl,foo just prior to the -l Libs
flags gives a better chance the --libs output will be correct. This
should be no change in the usage of the output since pkg-config
currently groups all flag types together.
Unify the get_multi_merged functions since there are only two valid ways
to do the merging of packages and flags.
1. Packages are sorted by their position in the pkg-config path and then
duplicate flags are stripped from the beginning of the list. This
pertains to -I and -L flags.
2. Packages are sorted by dependency with most required last and then
duplicate flags are stripped from the end of the list. This ensures
that flags that come from packages required by multiple others come
later in the output. This applies to all non-L/I flags.
There were two string list stripping functions, when the only difference
was to operate from the beginning or end of the list. Also, the function
was copying the list and operating on that unnecessarily.
For some flags, pkg-config will sort them by the depth of their .pc path
before outputting. The idea is that flags from a deeper path should come
earlier in the command line. This makes sense for -L and -I flags, but
not for generic linker and compiler flags. For these flags and -l flags,
it makes sense to sort them only by package order.
Commit 428335e changed some hash tables to be used as sets where the key
equals the value since glib has some optimization for that.
Unfortunately, the package list stripping table wasn't fixed corectly.
Prior to commit 6ecf318, the resolved list of required packages was
built in an appending way where each package on the command line or in
Requires would appear in the list in the order they appeared. With
6ecf318, that list building was changed to prepending, which had a
subtle change on the resolved order.
For example, suppose package a has "Requires: b c d". Previously, the
list would be built as a->b->c->d by appending each as they were
encountered. Now, the list is built by walking all the way down the
dependency chain for each package in a depth first manner and prepending
packages while unwinding. This would result in the package ilst being
a->d->c->b. This same effect happens with the command line packages
where previously requesting packages x and y would create a package list
of x->y and now produces a list of y->x.
While technically these should be the same since there are no
interdependencies, it's causes flags to be output in different order
than previously in pkg-config. This can be seen most readily in the
check-gtk test.
Instead, operate on the package lists backwards when building the
resolved package list.
Walking a GSList backwards involved copying and reversing it so that the
the original list could remain undisturbed. This is wasteful with a
GList where we can just start at the end of the list and work backwards.
Makes the resolved package list be correctly serialized with each
package only appearing once. This provides more consistency between the
various flag outputs by ensuring that the flags from each package are
only grabbed once. This makes a difference since the duplicate flag
stripping happens from the end of the output (-l) or the beginning of
the output (-L/-I/other).
Using a doubly-linked list allows it to be easily traversed in both
directions and makes removing nodes in place much simpler. This adds an
extra pointer to each node and associated manipulation during any list
processing, but this trade seems acceptable over the repeated hacks to
work with singly-linked lists.
Using the GSList functions instead of manually adjusting the list
pointers seems safer and allows an easier path to using another glib
list type if necessary.
The Package key member corresponds to the module filename with the .pc
stripped off while the name member corresponds to the Name field in the
.pc file. The latter is almost never used in practice and just makes
debugging more difficult.
Use a bitmask to keep track of what Libs/Cflags to output. This makes it
simple to handle any combination of --cflags and --libs option variants.
A lot of excess code is removed in the process as all the flags options
can now be carried around in a single variable.
Freedesktop #54388 (https://bugs.freedesktop.org/show_bug.cgi?id=54388)
When merging the flags from all the packages together, each flags list
was being copied and then concatenated to then end of the combined list.
This was extremely inefficient because it caused the combined list to be
traversed multiple times to find the end. Instead, nest the copying and
merging of the flags together so the last element is always tracked and
can easily be appended to.
Freedesktop #54716 (https://bugs.freedesktop.org/show_bug.cgi?id=54716)
pkg-config(1) states that installed packages should be appended with
"-uninstalled". However, the code was checking only for trailing
"uninstalled" without the hyphen. Make the code consistent with the
documentation.
Freedesktop #54379
After the packages are parsed, pkg-config recurses through all the
required packages to generate one list. Before descending another level,
check to see if the package has already been handled and skip it. This
allows packages to require each other circularly by breaking the loop.
A test has been added resolving a two level deep circular dependency.
Freedesktop #7331
When the parser encounters Requires or Requires.private, it immediately
tries to sees if we have a parsed package for that entry. If not it
tries to locate the needed file and parse it out. If there's a circular
dependency, this will eventually error opening too many files.
Instead, just store the requires entries so the parsing completes and
the package is added to the database. After parsing, the entries can be
resolved into Packages and any circular requires entries will find the
first package in the database.
This is a partial fix for Freedesktop #7331.
recursive_fill_list() is used to order Requires and Requires.private,
but it relied on fill_one_level() to make the list adjustments as it
descended the package tree. There were two issues with this approach:
1. It added all the dependencies from a package immediately rather than
descending through each dependency first. This made it sort of mix
between depth- and breadth-first resolving.
2. It did not add the requested package to the list, forcing the caller
to add it.
This simplifies the code so that it descends all the way to the least
dependent package and prepends them as it unwinds. This ensures the
ordering will be sorted from most dependent to least dependent package.
Ordering of -l flags is corrected by a later sorting, but this fixes
ordering on non-l flags. Add a new test specifically for non-l Libs
flags.
Freedesktop #34504
The function recursive_fill_list() is designed to descend lists of
packages, so it only makes sense to use with Requires and
Requires.private. Ensure it to make later code additions simpler.