On Thu, 09 Dec 2021 at 15:24:27 +0100, Alexander Traud wrote:
> if the header included another header, 
> and that header included further headers but was not in the root but in 
> a subfolder, an -I flag *might* be required. For example, the package 
> 'libopusfile-dev' has its header file in '/usr/include/opus/opusfile.h' 
> with #include <opus_multistream.h> which is part of the package 
> 'libopus-dev' and is not within '/usr/include/' but within 
> '/usr/include/opus/'. Therefore,
> $ pkg-config --cflags opusfile
> -I/usr/include/opus

This is deliberate, and is a very large part of the purpose of pkg-config.

Users of libraries should #include the library's headers in whatever
way the library maintainer has documented them to be used. The correct
#include pattern is part of the library's API. For example, for GTK,
the documentation says to always #include <gtk/gtk.h>, and using
<gtk-3.0/gtk/gtk.h> would be wrong. For SDL2, it's correctly <SDL.h>,
not <SDL2/SDL.h>.

GTK has multiple major versions, which are incompatible and
parallel-installable. If your program uses GTK 3, it needs to see GTK 3
headers: using GTK 2 or 4 headers would not work. This is implemented
by keeping the GTK 2, 3 and 4 headers in different non-default
directories, so that you only get the version of <gtk/gtk.h> you asked
for, and not the others. SDL 1.2 and 2 are similar, and there are many
other libraries with a similar design. The canonical text on this is
https://ometer.com/parallel.html (and you can tell how old it is because
it talks about GNOME 2 as though that was a new thing - but it's still
relevant).

Not doing that would give us the situation we have for things like libjpeg,
libcurl and libopenssl, where you can only have one version of the
development files installed system-wide at a time: if you have a program
that needs OpenSSL 1.1, and another program that needs OpenSSL 1.0, you
have to choose which one you can compile (by installing libssl-dev or
libssl1.0-dev), and you cannot compile the other one.

Conversely, if the old and new versions of library are *mostly* compatible
(like the way some SDL programs such as src:quakespasm can compile against
either SDL 1.2 or 2 with a few #ifdefs), we don't want to have to change
every source file to do something like this:

    #ifdef USING_MYLIB_3
    #include <mylib-3/mylib.h>
    #else
    #include <mylib-2/mylib.h>
    #endif

which explains why GTK and SDL have chosen to document <gtk/gtk.h>
and <SDL.h> respectively, instead of a versioned name appearing in the
source code.

For libraries with many smaller headers (popular in C++, e.g. Qt,
because parsing C++ is more expensive than parsing C), instead of one
big meta-header like the one in GTK, you certainly wouldn't want to do:

    #ifdef USING_MYLIB_3
    #include <mylib-3/MyFrobnicator>
    #include <mylib-3/MyTemplate>
    #include <mylib-3/MyWidget>
    ...
    #else
    #include <mylib-2/MyFrobnicator>
    #include <mylib-2/MyTemplate>
    #include <mylib-2/MyWidget>
    ...
    #endif

The other major part of the purpose of pkg-config is that it lets you
use dependencies that are *not* installed system-wide, without having to
make source code changes: if I set the PKG_CONFIG_PATH correctly, it will
find a GTK installation in /opt/gnome-42/{include,lib} and use that,
with my source code still using #include <gtk/gtk.h> as usual.

    smcv

Reply via email to