A specification for pkg-config

Dan Nicholson dbn.lists at gmail.com
Mon Oct 1 11:48:02 PDT 2012


On Thu, Sep 20, 2012 at 8:11 PM, William Pitcock
<nenolod at dereferenced.org> wrote:
> Hi!
>
> On Wed, Sep 19, 2012 at 8:05 AM, Dan Nicholson <dbn.lists at gmail.com> wrote:
>>
>> Why am I concerned about this now? When I first started poking around
>> pkg-config, Matthias Clasen pointed out what I think is a flaw. It's
>> #3 in the FAQ in the guide I wrote.
>>
>> http://people.freedesktop.org/~dbn/pkg-config-guide.html#faq
>>
>> If you have a package that internally uses another library (in his
>> case it was a gnome library using libgconf internally), you are
>> required to add that package to Requires.private in case someone wants
>> to statically link to your library. However, because we treat Cflags
>> from Requires.private packages as always needed, it means you require
>> the .pc file from the other package all the time. There's still a long
>> bug open about this.
>>
>> https://bugs.freedesktop.org/show_bug.cgi?id=4738
>>
>
> This is an implementation-specific problem; pkgconf does not suffer
> from this particular deficiency when building it's dependency graph.
> The frontend is also not affected: --exists only verifies that
> top-level dependencies are resolvable without looking at .private,
> unless --static is also specified.

Of course, it's trivial to show how this breaks. If you need the
Cflags from a dependency in Requires.private, then --exists will pass
but --cflags will fail if the .pc file is not installed. This
effectively breaks PKG_CHECK_MODULES since it always does --cflags and
--libs. See bug #43149.

>> To me, this actually points to a more general problem where Requires
>> is not specific enough. There are cases where you only need either
>> Cflags or Libs from another package. It would be great if you could
>> not only communicate that, but also ensure that pkg-config could avoid
>> packages where you only need Libs unless --static is specified. I have
>> an idea to fix this I've been kicking around, but I think I requires
>> extending the syntax.
>>
>> Requires: Cflags(foo)
>> Requires.private: Libs(bar)
>>
>
> Yuck.
>
> Also: How would you suggest that --exists without --cflags or --libs
> work in this condition?  The only logical conclusion is that it must
> still evaluate the entire dependency graph for breaks and cycles.
> Also, --exists is technically implied with --cflags and --libs anyway.
>
> Thusly, I think it is not very useful.

I would handle it exactly the way pkg-config handles --exists for
Requires.private now except that if you have Libs(foo), then you can
obviously skip handling foo. The other part this syntax allows is
finer-grained handling for users. The frequent case is that your
library has a private dependency on another libraries symbols but
doesn't expose it's types or macros. In that case, I don't need or
want Cflags from it.

This works the other way, too. If you want to build a mozilla plugin,
you need the definitions from the NPAPI headers, but you don't want to
link to the libraries since you want the plugin to resolve the symbols
implicitly from what the browser has loaded. The way you handle this
now is to have a separate PKG_CHECK_MODULES for mozilla-plugin and
ignore the resulting _LIBS. This is annoying, though. I want to have
one check: PKG_CHECK_MODULES([foo], [Cflags(mozilla-plugin) gtk+-2.0
...]).

>> What this means is that you would only return Cflags from foo and only
>> Libs.private from bar when --static is used. If pkg-config was smart,
>> it could skip bar.pc completely in the exceedingly common case. That
>> effectively means you could have the policy that this library can be
>> used without installing bar-devel if you don't care about static
>> linking. That's what Matthias was after for Fedora and I had to
>> convince him that pkg-config could not work that way with the current
>> setup.
>>
>
> I don't think it can work at all unless inconsistent behaviour is
> allowed, and I do not believe we want inconsistent behaviour in the
> toolchain, even if it is an ancillary component such as pkg-config(1).

Why would it be inconsistent?

--exists: all Requires + generic and Cflags Requires.private
--cflags: generic + Cflags for both Requires and Requires.private
--libs: generic + Libs for Requires

--exists --static: all for both Requires and Requires.private
--cflags --static: generic + Cflags for both Requires and Requires.private
--libs --static: generic + Libs for both Requires and Requires.private

What pkg-config does now:

--exists: all for both Requires and Requires.private
--cflags: all for both Requires and Requires.private
--libs: all for Requires

--exists --static: all for both Requires and Requires.private
--cflags --static: all for both Requires and Requires.private
--libs --static: all for both Requires and Requires.private

That's not drastically different, but it allows you to be more fine-grained.

>> Anyway, supposing this change or some other one to the package format
>> is desired, how would we do that effectively? I'm going to say that
>> the .private method was not ideal and that the only sane way would be
>> a version in the .pc file.
>
> Yes, something along the lines of "Version: $spec-revision" as the
> first line in the pkg-config file, otherwise assume it's a version 1
> file.

Right, except we already have a Version field, so we need something
else. Spec-Version? Pkg-Format? I haven't been able to come up with a
name I liked.

--
Dan


More information about the pkg-config mailing list