Re: the meaning of pkgconfig's Libs fields

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

 




Dne 31. 01. 22 v 14:09 Zbigniew Jędrzejewski-Szmek napsal(a):
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?


Shouldn't this be somehow clarified with pkg-config upstream first, where pkg-config could clean this field? And accompanied by BRP policy? Also, this being generic issue, maybe the BRP policy should not check just the pkg-config files but generally look for the build flags and replace them with ext flags.


Vít


Attachment: OpenPGP_signature
Description: OpenPGP digital signature

_______________________________________________
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