Skip to content
Advertisement

C++ build process – lib dependencies

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.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement