the meaning of pkgconfig's Libs fields

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

various .pc files that we ship contain a lot of stuff in the Libs and
Libs.private field don't make much sense to me. I started looking at
the documentation, and the documentation is very scarce, and what is
there doesn't seem to have been thought out at all. I'm writing my
observations and questions below.

pc(5) says:

     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.

     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.

"described as dependencies" here means "not listed in Requires and
Requires.private fields, which are used to specify dependencies on
other pkgconf projects.

On the face, this seems reasonable, but there's other documentation
that has a different spin. E.g.
https://people.freedesktop.org/~dbn/pkg-config-guide.html says:

      Libs: The link flags specific to this package and any required
            libraries that don't support pkg-config.

      Libs.private: The link flags for private libraries required by
            this package but not exposed to applications. The same
            rule as Cflags applies here.

"required" here refers to using Requires and Requires.private to
list other .pc files.

Neither of the above approaches seems to be consistent with how we
actually use .pc files, and even not much consistent with how they
could be reasonably used:

1. pc(5) talks about "package", as if one would want to link to a
   whole "package" instead one of the specific library files provided
   by a package. Thankfully most .pc files only list one "-l" in Libs.
   (Counterexamples: tbbmalloc_proxy.pc says 'Libs:-ltbbmalloc_proxy -ltbbmalloc',
   and mit-krb5.pc says Libs:-lkrb5 -lk5crypto -lcom_err.)

   The concept of having multiple libs in Libs in itself is borked:
   either the libraries are functional separately, in which case they
   would better have separate .pc files, so that the programs using
   those libraries can link to the one they need, or if they are not
   functional separately, the one that exposes functionality that is
   useful externally should be advertised (the others will be pulled
   in automatically by the linker).

2. In practice, most .pc files that list multiple things in Libs seem to
   be doing exposing their own link dependencies there. For example
   mono-2.pc says 'Libs: -L${libdir} -lmono-2.0 -lm -lm -lpthread',
   and indeed ldd /usr/lib64/libmono-2.0.so says it is linked to libm.so.6.
   Of course this doesn't mean that programs using libmono would need to
   be linked to libm themselves.

Items 1 + 2 are promoting overlinking, i.e. adding either unneeded
libraries, or libraries that are used indirectly, to linker flags for
some object being linked.

If we take the pc(5) definition at its word, the Libs.private lines
are even more broken in Fedora, because we almost never provide static
libraries.

Looking at Requires and Requires.private, there is more strangeness.

pc(5):

     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.

     Requires.private: Required dependencies that must be met for the
             package to be usable for static linking. All dependencies
             must be satisfied or the pkg-config implementation must
             not use the package for static linking.

To a large extent pkgconfig files are duplicating dependency logic
that is already provided by distro packaging (rpm in our case). This
would seem like an OK idea: upstreams specify which libraries they
need and downstreams use it.

It seems not to work in practice: e.g. atk-bridge-2.0.pc specifies

  Requires.private: dbus-1 >= 1.5, atspi-2 >= 2.33.2, atk >= 2.36.0,
      glib-2.0 >= 2.32.0, gmodule-2.0 >= 2.0.0, gobject-2.0 >= 2.0.0

which is translated into:

      $ rpm -qRf /usr/lib64/pkgconfig/atk-bridge-2.0.pc
      /usr/bin/pkg-config
      pkgconfig(atk) >= 2.36.0
      pkgconfig(atspi-2) >= 2.33.2
      pkgconfig(dbus-1) >= 1.5
      pkgconfig(glib-2.0) >= 2.32.0
      pkgconfig(gmodule-2.0) >= 2.0.0
      pkgconfig(gobject-2.0) >= 2.0.0
      ...

Two problems:

3. We autogenerate a dependency on /usr/bin/pkg-config for -devel.
   Logic is reversed here: the -devel package **provides** something
   that it consumed by pkg-config. Dependencies are from a consumer to
   the providing entity.

4. The -devel subpackage pulls in atk-devel, at-spi2-core-devel,
   dbus-devel, glib2-devel, and glib2-devel. Most of those dependencies
   are completely pointless. The only reason why one header package
   would require another header package is when the headers it provides
   #include other headers. at-spi2-atk-devel has a single header file,
   with '#include <glib.h>'. It thus should have a dependency on 'pkgconfig(glib-2.0)',
   and all the other deps generated from Requires.private just inflate
   the build root. (If glib.h or libglib-2.0.so in turn require other
   things for themselves, those dependencies will be specified by glib2.rpm.)

And finally, we get to stuff which is included in Libs:

/usr/lib64/pkgconfig/libresample.pc
Libs: -Wl,-z,relro   -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lresample -lm

/usr/lib64/pkgconfig/libpsx.pc
Libs: -L${libdir} -lpsx -lpthread -Wl,-wrap,pthread_create

/usr/lib64/pkgconfig/ruby.pc
DLDFLAGS=-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld 
Libs: ${DLDFLAGS} ${LIBRUBYARG_SHARED} ${LIBS}

/usr/lib64/pkgconfig/libresample.pc
Libs: -Wl,-z,relro   -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -lresample -lm

/usr/lib64/pkgconfig/socket_wrapper.pc
Libs: lib64/libsocket_wrapper.so

/usr/lib/pkgconfig/gmodule-2.0.pc
Libs: -Wl,--export-dynamic

Those seems to be all errors: redhat-hardened-ld is supposed to be
used in package builds, not exposed for user compilations.
lib64/libsocket_wrapper.so cannot be resolved. And other link flags
that change the resulting binary is not the something that libraries
should specify.

To summarize:
- Re 3: drop the generator for the reversed dep?
- Re 2: flat everything that is not -l, -L, in Libs with rpmlint?

Zbyszek
_______________________________________________
devel mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxx
Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedoraproject.org/archives/list/devel@xxxxxxxxxxxxxxxxxxxxxxx
Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Fedora Announce]     [Fedora Users]     [Fedora Kernel]     [Fedora Testing]     [Fedora Formulas]     [Fedora PHP Devel]     [Kernel Development]     [Fedora Legacy]     [Fedora Maintainers]     [Fedora Desktop]     [PAM]     [Red Hat Development]     [Gimp]     [Yosemite News]

  Powered by Linux