6

Quite often I am using third party snippets of C code that uses a Unix/Linux C library, an example #include <glib.h>, #include <net/if.h>. And they require me to know the specific library file name or pkg-config name, an example -lglib-2.0, -lbluetooth, pkg-config --libs dbus-1. Note that a lot of them differ from the header file having a '2.0', '1' so you just can't guess it.

How the heck can I find out the exact name of the library file an API/library has? Using my examples above; how do I find that #include <glib.h>'s library file is called -lglib-2.0? It's quite frustrating that the online references for Glib/dbus/all of them don't just say "the name of the library file is glib-2.0".

Are there any terminal commands I can use to find this out? Are there utilities I can use to find this out? Online API/Library references are really bad for finding this out.

If I want to find where hci.h is located I can easily just go locate hci.h and find its location. Is there anything like a terminal command for finding out the library name?

2 Answers 2

1

There's no general way to know which library is required to use a particular function. You need to look at the documentation of that library. A well-written tutorial or API reference should tell you, that's its job.

You can at least get an idea of what library package is required: it's the same library package that contains the header file. How to determine which package contains the header file depends on the distribution, for example dpkg -S /usr/include/glib-2.0/glib.h on Debian/Ubuntu/Mint/…, rpm -qf /usr/include/glib-2.0/glib.h on RHEL/CentOS/Fedora/…, etc. Once you know the library package, list its contents to find what .so files it contains, e.g.

dpkg -L libglib2.0-dev | grep '\.so$'
rpm -qlf /usr/include/glib-2.0/glib.h | grep '\.so$'

With Glib, there are several .so files, and there's no automatic way to tell which ones are required for a particular function (there may be more than one).

If the library uses pkg-config, you should use it rather than hard-coding header and library paths. Not all libraries use it however. You can normally tell because your distribution's library package should depend on its pkg-config package (e.g. dpkg -s libglib2.0-dev |grep '^Depends:.*pkg-config').

If the documentation is really bad, try listing the symbols defined by the library:

nm -D /usr/lib/x86_64-linux-gnu/libgio-2.0.so |awk '$2=="T" {print $3}'

This isn't a sure-fire way because it won't tell you if some other library is needed as well.

1
  • +1 however even when using pkg-config, it's sometimes hard to guess the pkg-config identifier (e.g. that glib.h is provided by glib-2.0 rather than, say, glib) - for this, I often resort to grepping the output of pkg-config --list-all Jun 11, 2016 at 14:05
0

The #include directives are expanded by the C preprocessor. The search path is controlled by the compiler (e.g. the -I<dir> flag). These provide the symbols in the resulting object file.

Then the linker maps those symbols to archive/object files using a convention: given a flag like -l<namespec>, the linker will search the directories in its library path for lib<namespec>.a or lib<namespec>.so. The linker includes those filenames in the resulting binary, which the dynamic linker uses at runtime to resolve symbols to their actual implementations.

You can find the search directories for the compiler's linker with ld --verbose | grep SEARCH_DIR. For example, this roughly emulates how the linker maps a library name to an .so file:

$ libname=glib-2.0; ld --verbose |  grep SEARCH_DIR |  tr -s ' ;' '\n' |  sed 's/SEARCH_DIR("=\?\(.*\)")/\1/g' |  xargs -I{} find {} -maxdepth 1 2>/dev/null | grep lib${libname}.so
/usr/lib/libglib-2.0.so.0.7000.0
/usr/lib/libglib-2.0.so
/usr/lib/libglib-2.0.so.0

(Those are all symlinks to the same file.)

You can find what package in your package manager provides that file, e.g. with yum:

$ yum whatprovides /usr/lib64/libglib-2.0.so.0

glib2-2.68.1-1.fc34.x86_64 : A library of handy utility functions
Repo        : fedora
Matched from:
Filename    : /usr/lib64/libglib-2.0.so.0

glib2-2.68.4-1.fc34.x86_64 : A library of handy utility functions
Repo        : @System
Matched from:
Filename    : /usr/lib64/libglib-2.0.so.0

glib2-2.68.4-1.fc34.x86_64 : A library of handy utility functions
Repo        : updates
Matched from:
Filename    : /usr/lib64/libglib-2.0.so.0

You can see what symbols are in these with nm:

$ nm -D --defined-only /usr/lib/libglib-2.0.so.0
0000000000070000 T g_access
000000000001d600 T g_allocator_free
000000000001d5f0 T g_allocator_new
0000000000022810 T g_array_append_vals
000000000001e3a0 T g_array_binary_search
...

The linker convention is documented in man ld.

So finally to answer your question: these mechanisms are designed to decouple header files from actual implementations, so there's no general way to map a header file to the object/archive files, by design. Ultimately you have to find the .so file that implements the symbols you #include. As the other answer said, this is ad-hoc.

It is greatly aided by your package manager though, since often the package that provides the header files is <package>-devel and the package <package> provides the shared objects. E.g. with yum you can use this to find the devel package:

$ yum provides '*/glib.h'

glib-devel-1:1.2.10-62.fc34.i686 : Libraries and header files for glib development
Repo        : fedora
Matched from:
Filename    : /usr/include/glib-1.2/glib.h

glib-devel-1:1.2.10-62.fc34.x86_64 : Libraries and header files for glib development
Repo        : fedora
Matched from:
Filename    : /usr/include/glib-1.2/glib.h

glib2-devel-2.68.1-1.fc34.i686 : A library of handy utility functions
Repo        : fedora
Matched from:
Filename    : /usr/include/glib-2.0/glib.h

...

You can see that the header file is provided by the glib2-devel package. So the glib2 package provides the .so file, and from that filename, you can know what to use with the -l flag.

$ repoquery -l glib2 | grep '.so'

/usr/lib/libgio-2.0.so.0
/usr/lib/libgio-2.0.so.0.6800.4
/usr/lib/libglib-2.0.so.0
/usr/lib/libglib-2.0.so.0.6800.4
...

So you can see, given glib.h, you should at least use -lglib-2.0.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .