Search code examples
c++linuxg++ld

Why does ld need library that my executable depends on?


I'm trying to build my executable (that depends on library utils.so) using the following command

g++ -L/path/to/libutils -lutils -I/path/to/utils_headers executable.cpp -o executable

Actually I don't have utils.so - only the header files of utils library.

I'm getting the error:

ld: cannot find -lutils

Does linker really need to access all the libraries my executable depends on in order to build my executable? If it does then I'd like to know why it needs to access them.

My executable is a shared library. I'm sure that header files of the utils lib are enough to build it (i.e without having utils.so).


Solution

  • The linkage option -lutils by default directs the linker to search, first in the specified library search directories (-Ldir) and then in its default search directories, for either of the files libutils.so ( shared library) or libutils.a (static library), preferring libutils.so if both of them are found in the same search directory.

    If such a file is found, the linker stops searching and adds that file to the input files of the linkage, whether or not it resolves any references in the linkage. The linker cannot know whether the file resolves any references if it does not input the file.

    If no such file is found, the linker gives the error: cannot find -lutils. Because you told it to find libutils.{so|a} and it could not.

    You say:

    My executable is a shared library

    But it isn't. Your compile-and-link command:

    $ g++ -L/path/to/libutils -lutils -I/path/to/utils_headers executable.cpp -o executable
    

    is not an attempt to link a shared library. It is an attempt to link a program.1

    This would be an attempt to link a shared library:

    $ g++ -shared -I/path/to/utils_headers -o libexecutable.so executable.cpp -L/path/to/libutils -lutils
    

    You cannot link a program with unresolved references. But you can link a shared library with unresolved references.

    So, you could link a libexecutable.so like that, or you could link it simply like:

    $ g++ -shared -I/path/to/utils_headers -o libexecutable.so executable.cpp
    

    These are two different linkages: if they succeed they produce different output files.

    In the first linkage, some symbols will (let's assume) be resolved to definitions provided in libutils.so or libutils.a (whichever one is found), and this will be reflected by:

    • libutils.so is found: The .dynamic section of libexecutable.so contains a DT_NEEDED structure that expresses a runtime dependency on libutils.so. libutils.so will need to be included in any linkage that includes libexecutable.so, but the output file of such a linkage will itself contain a runtime dependency only on libexecutable.so.

    • libutils.a is found: libexecutable.so itself contains the definitions for all the symbols it uses that are defined by object files in libutils.a.2 libexecutable.so may be included in subsequent linkages with no need for libutils.{so|a}.

    In the second linkage, the .dynamic section of libexecutable.so will not express a runtime dependency on libutils.so nor will the file contain definitions of any symbols provided by libutils.{so|a}. libutils.so will (again) need to be included in an subsequent linkage that includes libexecutable.so, but the output file of such a linkage will acquire independent runtime dependencies on both libexecutable.so and libutils.so.

    But, if you specify -lutils in the linkage - or any linkage - and the linker cannot find libutils.{so|a} in any of its search directories, then you get the error you observe, because you told the linker to input a file, whose effects on the linkage can only be determined and implemented if that file is found - and it cannot be found.


    [1] An attempt that is likely to fail, because it consumes libraries before the object files that refer to them

    [2] See static-libraries to understand why.