I have a Visual studio solution with 5 projects
- Main: application
- A,B,C,D: static libraries
Main depends on A,B. A depends on C,D.
I have a fragile understanding of the build process.
The libs were building alone fine, especially A; I did not feel I was linking C and D to A.
And to build the Main application, I had to have A,B,C and D as input libraries even though Main only directly depends on A,B.
Now I am trying to build he whole thing on Linux with CMake, and I find myself exposed to these linking again. This time I don’t want to use brute force and would prefer to understand how this links together.
Should I just build A,B,C and D as .a static libraries and have the Main include them all?
How is it possible for A to build without the symbols from C and D?
Advertisement
Answer
Static libraries are merely archives containing object files (i. e. separately compiled source files). For this reason, when building a static library you don’t “link” it, but “archive” it.
Symbols have to be resolved when linking an executable or a shared library. At this point linker tries to resolve all symbols, at if it cannot, you get undefined reference
errors. But, again, this pertains to linking. Static libraries do not need to have all symbols defined within them.
In your case, if A
, B
, C
and D
are static libs, they will be built independently from each other. The only thing you need to build A
from C
and D
are header files, which are needed by the compiler.
When you are building an executable, you need to specify all static libraries, even if Main
doesn’t “directly” reference symbols from C
or D
.
Now, even though static libraries cannot implicitly depend on other libraries, CMake provides a way to express such dependencies on build system level. You can do the following
add_library(C STATIC ${B_SOURCES}) add_library(D STATIC ${D_SOURCES}) add_library(A STATIC ${A_SOURCES}) target_link_libraries(A PUBLIC C D)
target_link_libraries
command above does not cause A
to be linked with C
and D
– as I wrote, that’s not have static libs work. Instead, it informs CMake that when linking an executable with A
, it has to link it with C
and D
too:
add_executable(Main ${MAIN_SOURCES}) target_link_libraries(Main PRIVATE A)
Even though target_link_libraries
includes only A
, Makefile generated by CMake will also link C
and D
– because they were specified as dependencies of A
.
dllexport and dllimport
These two attributes pertain only to shared libraries (DLLs). They control which symbols are exported from a DLL (i. e. accessible from an executable which links to that DLL). Here’s a link describing the idea and equivalent on Linux.