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?
Related
I know when building Java programs, we can use maven-shade-plugin to resolve dependency confliction.
For example, if B depends on library A(version 1) and C depends on library A(version 2), both B and C can't build with the given version of library A, like the following
Though there doesn't exists one version A that satisfy both B and C, we can pacakge diffenrent versions of A into one executive. For example, we can rename library A of version 1 to A_v1, so if A.x exists in library A, it can be referred as A_v1.x. We can do the same to library A of version 2 by renaming it to A_v2.
Then, I find C/C++'s compile/link building procedure has similar aspects because it will also define and search symbols, so I am wondering if there are some ways to enable multiple version of one library be linked into one executive, by renaming tokens.
I will take the C library as an example. The function printf can be firstly renamed into version_2_12_0_printf or version_2_13_0_printf before linking, and the linker can somehow find location of the correct version of printf and link.
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 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.
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.
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.
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.
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.