I made static library A, the library is using another static library B.
And in order to use library A in code C, i added library A and header A but B.
Because i have known that static library is combined in compile time, so library B is already contained within A.
But When i compile code C, it seem to require that i add library B also showing undefined reference error.
And when i add library B also, the error disappear.
Why ?
You'll need to add both A and B.
When static lib A uses static lib B, B is absolutely NOT combined in A. That is impossible since when generating static libraries there is no link step.
This is the difference between shared and static libraries on Linux.
If your library is written well, you may not need to add B headers in code C, but when linking, (executable or shared library or even DLL in windows) you'll need all used static libraries.
Related
In Linux when I load shared library using dlopen() from executable (or shared library) I expect that undefined symbols in this library will be automatically resolved, of course as long as executable (or shared library) defines these symbols.
For example, I have library A with these header and source files:
#pragma once
int funcA();
#include "A/header.h"
int funcA() {}
also I have library B with this source file:
#include "A/header.h"
void funcB() {
funcA();
}
for library B I specify path to header of library A, but I don't link library A to library B.
In this case, if I load library B from library A by calling dlopen(), then undefined symbol funcA in library B will be resolved, so library B will be able to call funcA.
Is it also true for Windows, or I have to manually find addresses for all symbols I need?
After researching already answered questions on Stack Overflow:
External symbol resolving in a dll
Compile to .dll with some undefined references with MinGW
I realized that if I want to make something similar work on Windows, I have to create some import library for my shared library A.
At first I thought it's needed only for MSVC, but looks like MinGW needs import library too, because it's how things work on Windows. Correct me if I miss something.
For me it's big no-no, so probably I will change a way how I work with shared libraries to explicitly retrieve every symbol I need via additional interface. Fortunately, there are not so many of them.
This might be a weird / beginners question for someone. However I have the following situation.
In my code, I am creating three libraries, lets say A,B and C. In library B i am linking library A, so something like target_link_libraries(... A).
My C library is linking against B. So I have:
B -> A
C -> B.
Should it then be possible, that I use methods, enums whatever defined in library A also in C? Although C is not linking A explicitly? I was using an enum defined in library A in C, A::someClass::someEnum and it compiled and showed correct value entries.
Should it then be possible, that I use methods, enums whatever defined in library A also in C?
Does your C library uses these methods/enums/etc. via including a header from the library A or from the library B?
If C directly includes the header from the library A, then it should be linked with the library A explicitly:
# A is a private linkage of B.
target_link_libraries(B PRIVATE A)
# C needs to be linked with A
target_link_libraries(C B A)
If C includes the header from the library B, which in turn includes the header from the library A, then A library should be a part of the B interface:
# B links with A and this linkage is an interface of B
target_link_libraries(B PUBLIC A)
# C may link with B only
target_link_libraries(C B)
These approaches assume "modern" (target-oriented) CMake to be used. But using these approaches one would get most scalable solution.
Remember that linkage dependency and compilation dependency are not the same thing.
It's quite possible that the sources of library C use definitions from headers associated with library A... irrespective of whether C depends on A when linking.
Now, in CMake, we use target_link_libraries() not only for linking. This CMake command makes sure that the library's headers are available to the dependent target, for compilation, and that its libraries are available for linking.
It's also possible for library C to require library A for linking - to have the definitions of, say, functions or variables from library A. Libraries can theoretically have circular link dependencies (which means that you need to either link against the entire circle, or no part of it).
I have a dependency problem. Library A depends on dynamic library B and C. But B depends on D ver1, while C depends on D ver2. I do not have the source for C.
How can I create a self-contained shared library containing C and D ver1, such that A can link to this new library, B, and D ver 1, and therefore avoid a conflict between D ver1 and D ver2?
You mentioned that you do not have the source of library C, but what about library A and library B? If you have those sources, update library B to depend on library D ver2 instead of library D ver1?
I would also consider merging library A and B. That would remove the dependency diamond. If you can duplicate the functionality of C, then you bring it down to a simple singular dependency on D ver2.
You can statically link your dependencies - is one option.
Or you could just stop being fixated on shipping a "self contained" library and ship your dependencies along with it. What bother is a few extra files?
Sorry about the vague question title, I just want to ascertain some things.
Static libraries don't link with other static libraries, right?
So when I write a slib: A, that uses functionality of another: B, all I have to provide are the headers of B to A, and only those, even if A actually uses functionality from B?
Yes?
As long as exe: X, which uses A,has B.lib specified as linker input?
So that at link time, the linker takes A.lib, which basically only knows that a function of B was called somewhere inside its code, and somehow fills that information from B.lib, making A.lib 'whole', before X gets linked with the now working parts of it?
The motivation behind these questions is to get rid of some linker warnings 4006 and discarded double definitions, and I think that should do the trick, if this is actually a valid way of doing it.
Yes, you have got it pretty much right. Executables (and DLLs) which depend on static libraries cannot be created without those dependencies being resolved, but static libraries that contain dependencies on other static libraries do not require those dependencies to be resolved at static library creation time. In fact, the process of creating a static library does not involve the linker at all.
Can't really add the Neils answer except to say that a static library is really just a whole bunch of object (.o) files collected into a single indexed file. So what works for a .o file will work for a static library.
I have a static lib A, which also uses static libs B, C and D.
I then have applications X and Y which both use A, but not B, C or D.
Is there some way to make it so X and Y will automatically see that A used B, C and D and link them, so that I don't need to keep track for the entire dependency tree so I can explicitly pass every static lib (quite a lot with things like Windows, Boost, etc)?
Static libraries do not link with other static libraries. Only when building the executable (or shared library/DLL) is linkage performed, and the way to keep track of this is (of course) to use make.
I think, conceptually, you might be able to merge libs together to achieve what you want - they are after simply collections of symbols ready made for the linker. Having said that, I've never seen a tool to do it. The binary format of a lib is a compiler matter, so it would have to be a mingw or gcc specific tool.
In terms of knowing which version of Boost lib A uses, there isn't really much for it but to find the documentation for A.
The easy way is to always offer the particular libraries A, B, C, and D to be linked. For a true library, the linker only retrieves the modules needed.
The key problem with A having some implicit linkage to other libraries is that they aren't necessarily uniquely identifiable. For example, should it use version 2.0 or 3.1? The one in /usr/share/lib or the one in /usr/lib/X11/xdm/share/lib? Etc.