Hello Everyone, I hope you’re all doing well!
While i have some experience developing, i’m still trying to get familiar with CMake and trying to come up with a practical layout for a kinda-large library i’m working on. It’s intended to be an open-source (not yet public though) library, ideally built statically, but allowing the end users to build dynamically as well.
The project will consist on:
- A main library (that should build either static or shared)
- Bindings for python and other languages
- Probably a native app that will use such library
The library is currently structured as follows:
/CMakeLists.txt
/include/main.hpp
/src/main.cpp
/basics/CMakeLists.txt
/basics/libA/CMakeLists.txt
/basics/libA/include/basics/libA
/basics/libA/src
/basics/libB/CMakeLists.txt
/basics/libB/include/basics/libB
/basics/libB/src
…
/examples/CMakeLists.txt
/examples/ex01.cpp
the Main library depends on libA which in turn depends on libB (both built as OBJECT libraries).
Code looks somewhat like this:
/basic/libA/CMakeLists.txt
add_library(A OBJECT)
target_include_directories(A include/)
target_sources(A PRIVATE src/a.cpp)
/basic/libB/CMakeLists.txt
add_library(B OBJECT)
target_include_directories(B include/)
target_sources(B PRIVATE src/b.cpp)
target_link_libraries(B PUBLIC A)
/basics/CMakeLists.txt
add_subdirectory(libA)
add_subdirectory(libB)
/CMakeLists.txt
add_library(main)
target_include_directories(main include/)
target_sources(main PRIVATE src/main.cpp)
target_link_libraries(main
PUBLIC A
PUBLIC B)
/examples/CMakeLists.txt
add_executable(ex01 ex01.cpp)
target_link_libraries(ex01 main)
So far I was mostly working on writing logic, and unit tests. Since I’m linking the tests directly with object libs, everything was working smoothly. Now, when I decided to build an actual example using the library, things didn’t work unless I linked the example directly with ALL object libraries as well.
When I build my example and link against my Main library, it fails to link because of unresolved symbols in libB.
Inspecting the static lib with nm
confirms this, showing an U
next to the symbols for which the linker complains.
Now, i’ve done some reading and I see that object libraries don’t propagate transitively, only the usage requirements from them do (at least when using only target_link_libraries).
Is there any way for OBJECT libraries to expose their build requirements and dependencies as well? I’ve read about using the TARGET_OBJECTS generator inside the add_library
directive, but my understanding was that it only propagated the objects, and not the usage/interface requirements.
Is it possible (and convenient) to have this degree of modularization?
Are object libraries intended to be used this way?
Sorry for the long post, and my english, and thank you very much in advance for taking the time to read!