24

Assuming I want to test if a library is installed and usable by a program. I can use ldconfig -p | grep mylib to find out if it's installed on the system. but what if the library is only known via setting LD_LIBRARY_PATH?

In that case, the program may be able to find the library, but ldconfig won't. How can I check if the library is in the combined linker path?

I'll add that I'm looking for a solution that will work even if I don't actually have the program at hand (e.g. the program isn't compiled yet), I just want to know that a certain library exists in ld's paths.

5
  • 3
    You could use ldd <binary> to check if all libraries linked are in the path. Maybe there is a more elegant way.
    – Thomas
    Commented May 10, 2016 at 9:33
  • @Thomas I think you should make an answer of your comment. ldd serves exactly this purpose.
    – lgeorget
    Commented May 10, 2016 at 9:41
  • 2
    @Thomas - but what if I the program isn't compiled yet, and that library is needed for compilation? Commented May 10, 2016 at 9:41
  • @Igeorget - see my edit / comment Commented May 10, 2016 at 9:44
  • @nbubis: when you need the library for compilation, you normally have to use LIBRARY_PATH environment variable which is looked up e.g. by the gcc compiler. The LIBRARY_PATH environment variable also has a colon seperated list of directories.
    – Thomas
    Commented May 10, 2016 at 10:09

4 Answers 4

21

ldconfig can list all the libraries it has access to. These libraries are also stored in its cache.

/sbin/ldconfig -v -N will crawl all the usual library paths, list all the available libraries, without reconstructing the cache (which is not possible if you're a non-root user). It does NOT take into account libraries in LD_LIBRARY_PATH (contrarily to what this post said before edit) but you can pass additional libraries to the command line by using the line below:

/sbin/ldconfig -N -v $(sed 's/:/ /g' <<< $LD_LIBRARY_PATH)
5
  • ldconfig is a tool from the 1980s that was given up in the 1990s. For this reason, ldconfig is not portable as it only applies to implementations that are based on the SunOS-4.0 a.out based dynamic linker from 1987.
    – schily
    Commented May 10, 2016 at 10:00
  • How does that help listing libs which are only on LD_LIBRARY_PATH? I guess I could write a script to parse that and then read that through ldconfig, but it seems a bit like an over kill. Commented May 10, 2016 at 10:10
  • 1
    @nbubis you can always pass the libraries in LD_LIBRARY_PATH to ldconfig. Like /sbin/ldconfig -N -v $(sed 's/:/ /' <<< $LD_LIBRARY_PATH) not too much of an overkill to my taste.
    – lgeorget
    Commented May 10, 2016 at 10:32
  • @schily Really? It works pretty well with ELF libraries as far as I can tell. And it's still used, ld.so relies on the cache built by ldconfig.
    – lgeorget
    Commented May 10, 2016 at 10:33
  • The Linux people hacked the old Sun linker source-code to support ELF. The new ELF implementation from Sun removed ldconfig in an agreement with AT&T as the linker caching was too sensitive to errors. Sun later added the three stooges: moe, lari and crle as helper programs for ELF management.
    – schily
    Commented May 10, 2016 at 10:52
5

You can compile a simple test program with gcc and link your library. Then you can check the used libraries with ldd. I use something like this:

echo "int main(){}" | gcc -x c++ -Wl,--no-as-needed -lmylib - && ldd a.out | grep mylib

-Wl,--no-as-needed prevents the linker from discarding the library, because no symbols from the library are used.

2

I implemented such a script here:

#!/usr/bin/env python3

"""
Like `type` but for libs.
"""

from __future__ import print_function
from argparse import ArgumentParser
from glob import glob
import sys
import os


def parse_ld_conf_file(fn):
    paths = []
    for l in open(fn).read().splitlines():
        l = l.strip()
        if not l:
            continue
        if l.startswith("#"):
            continue
        if l.startswith("include "):
            for sub_fn in glob(l[len("include "):]):
                paths.extend(parse_ld_conf_file(sub_fn))
            continue
        paths.append(l)
    return paths


def get_ld_paths():
    # To be very correct, see man-page of ld.so.
    # And here: http://unix.stackexchange.com/questions/354295/what-is-the-default-value-of-ld-library-path/354296
    # Short version, not specific to an executable, in this order:
    # - LD_LIBRARY_PATH
    # - /etc/ld.so.cache (instead we will parse /etc/ld.so.conf)
    # - /lib, /usr/lib (or maybe /lib64, /usr/lib64)
    LDPATH = os.getenv("LD_LIBRARY_PATH") 
    PREFIX = os.getenv("PREFIX") # Termux & etc.
    paths = []
    if LDPATH: 
        paths.extend(LDPATH.split(":"))
    if os.path.exists("/etc/ld.so.conf"):
        paths.extend(parse_ld_conf_file("/etc/ld.so.conf"))
    else:
        print('WARNING: file "/etc/ld.so.conf" not found.')
    if PREFIX:
        if os.path.exists(PREFIX + "/etc/ld.so.conf"):
            paths.extend(parse_ld_conf_file(PREFIX + "/etc/ld.so.conf"))
        else:
            print('WARNING: file "' + PREFIX + '/etc/ld.so.conf" not found.')
        paths.extend([PREFIX + "/lib", PREFIX + "/usr/lib", PREFIX + "/lib64", PREFIX + "/usr/lib64"])
    paths.extend(["/lib", "/usr/lib", "/lib64", "/usr/lib64"])
    return paths


def main():
    arg_parser = ArgumentParser()
    arg_parser.add_argument("lib", help="Name of the library (e.g. libncurses.so)")
    args = arg_parser.parse_args()

    paths = get_ld_paths()
    for p in paths:
        fn = "%s/%s" % (p, args.lib)
        if os.path.exists(fn):
            print(fn)
            return

    print("Did not found %r in %r." % (args.lib, paths), file=sys.stderr)
    sys.exit(1)


if __name__ == "__main__":
    main()
1
  • Nice, but not guaranteed to work exactly as the linker does. And I'm not sure if this is Linux-specific: on Mac and maybe other Unixes you would need to check DYLD_LIBRARY_PATH, for example Commented Mar 30, 2023 at 9:47
0
$ gcc --print-file-name=libqdbm.so
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/libqdbm.so

You must log in to answer this question.

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