On Fri, 03 Jul 2020 at 21:16:44 +0300, Michael Tokarev wrote:
> On Fri, 03 Jul 2020 18:45:07 +0900 Mike Hommey <mh+report...@glandium.org> 
> wrote:
> ..
> > Arguably, freetype2.pc shouldn't depend on libbrotlidec.pc except with a
> > Required.private, assuming one doesn't actually need to include
> > libbrotli headers or link against libbrotli library (presumably, that's
> > the case).
> 
> The thing is that libbrotli *is* in Requires.private, and pkg-config still
> insists on it to exist.

This is because there are three possible "weights" of dependency, and only
two dependency lists in a .pc file, so the dependency lists cannot possibly
be 100% correct for all three "weights".

In decreasing order of "weight":

1. Public dependency: depending on A guarantees availability of B because
   they are inextricably linked, and you can't use A without B (for example
   GTK depends on GLib like this). This is Requires.

   pkg-config --cflags A includes B.
   pkg-config --libs A includes B.
   pkg-config --static --cflags A includes B.
   pkg-config --static --libs A includes B.
   A-dev must depend on B-dev.

2. Use of data structures: some header files from A include header files,
   macros, data structures from B; it is possible to use A without directly
   linking to B, but you can't successfully #include all the headers of
   A unless you have B-dev installed (for example GTK depends on Pango
   like this, I think). This is Requires.private.

   pkg-config --cflags A includes B.
   pkg-config --libs A does not include B.
   pkg-config --static --cflags A includes B.
   pkg-config --static --libs A includes B.
   A-dev must depend on B-dev, even if you don't care about static linking.

3. Implementation detail: A uses B internally, but does not mention it in
   its header files at all. It is possible to use A without having B-dev,
   *unless* you are linking statically (for example GTK depends on epoxy
   like this).

   pkg-config does not have a representation for this at the moment,
   although a new Requires.internal was proposed in 2018
   (<https://bugs.freedesktop.org/show_bug.cgi?id=105572>).
   Requires.private behaved like this before 2007 (#390132), but we have
   had 13 years of packages depending on Requires.private's new meaning,
   so reverting that change would be harmful.

   Ideally the behaviour here would be:
   pkg-config --cflags A should not include B.
   pkg-config --libs A should not include B.
   pkg-config --static --cflags A should not include B.
   pkg-config --static --libs A should include B.
   A-dev does not need to depend on B-dev unless you care about static
   linking (so maybe weakening it to a Recommends or Suggests would be OK).

Known workarounds for the nonexistence of Requires.internal are:

* Don't mention B in A.pc at all. Statically linking A will not work.
  This is perhaps the least bad solution if A or one of its dependencies
  is shared-only and does not support static linking, for example
  Mesa or libsystemd, but it's difficult to make that decision in practice.
  For example, libdbus conditionally depends on libsystemd, so it cannot
  easily be statically linked *in Debian* - but I think the same upstream
  source code *can* be statically linked in Devuan or on non-Linux, where
  the libsystemd dependency is disabled, so it is not straightforward for
  the upstream developer to know whether static linking is supported when
  generating the .pc file.

* Put B and all its recursive dependencies in Libs.private, which is not
  great because it requires hard-coding part of the information you
  got from B.pc into A.pc, meaning A.pc can be out of date if B.pc has
  changed (for example gaining a dependency) since A was built.

* Strengthen the dependency to Requires.private. This is what usually
  happens in practice (as in this case), and means you need B-dev installed
  even though in principle shared linking shouldn't need it.

    smcv

Reply via email to