Question

I have library A where some functionality in it requires library B. library A has two independent classes F and G (i.e. F and G do not know about each other) where G includes headers from library B in its cpp file, thus the dependency of library A on library B because of class G. F does not use any functionality from library B.

I now have an executable E that uses F but not G. Am I required to link against library B even though I am not using any functionality from library A that uses library B? If yes, is there any way to avoid that without splitting up library A into two libraries?

I was under the assumption that you don't have to link against the external library unless you are using its functionality somehow.

Was it helpful?

Solution

No, this is not necessary. A static library is a very simple file format, it is just a bag of .obj files. The linker only pulls in the .obj files that it need to resolve a dependency in your main program. Or an .obj file that was pulled in that in turn requires another one to be used. You only get a linker error when symbols are still unresolved after it looked at the available .obj files.

A sample implementation of the G class I tried to double-check this, in g.cpp:

#include "stdafx.h"
#include "a.h"

void foo();    // Defined in b.lib

G::G() {
    foo();
}

And tested in a program that looked like this:

#include "stdafx.h"
#include "..\a\a.h"


int main()
{
    F obj;
    //G obj2;
    return 0;
}

It linked just fine without linking b.lib. Removing the comment from obj2 produced the expected LNK2019 error for foo().


Plenty of ways that this might not pan-out in practice. Pretty hard to see dependencies with an unaided eye. And the unit of linkage is an object file, g.obj in the above example. So it is important that your F class members are defined in a different source code file than your G class members. In other words, you need a separate f.obj and g.obj file in a.lib.

This can be tinkered with, the /Gy compile option can package individual functions each in a separate section. Which lights up the /OPT:REF linker option, the unit of linkage now becomes an individual function instead of an object file. But that's a pretty high price to pay, it only improves the final size of the executable and doesn't remove the need to still have to link b.lib. And it disables incremental linking and may require tinkering with the original library projects. As long as you need to do that, just easier to keep the code for F and G in separate source files.

The linker's /VERBOSE option can provide insight, it shows you what is being pulled in and which .obj file caused a dependency to be linked. Enter it in the Linker + Command Line, Additional Options box.

OTHER TIPS

When you link to a static library, what the linker does is to pick out of the library the object files defining symbols used by the program. So if you don't reference G, it won't be included in the program. That happens if you add the respective static library when linking or not.

There is an implicit dependency between library A and library B. You may not have to link explicitly depending on the compiler you're using. But there is a fair chance that during its execution it is going to look for library B. In windows, there is an option to delay load a DLL - which means an attempt to load library B is not done unless the code path is hit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top