I have three build elements:
- bar (library) provides bar()
- foo (library) provides foo() and uses bar()
- main (exec) uses foo()
I purposely have bar as a PRIVATE library of foo, and expect for main to fail because it doesn’t get the link information for bar, but it does. Why is a PRIVATE library being shared with the consumer?
Here is my simple CMakeLists.txt file.
cmake_minimum_required (VERSION 3.18)
project(Example)
add_library(bar STATIC bar/bar.c bar/bar.h)
target_include_directories(bar PUBLIC "${CMAKE_CURRENT_LIST_DIR}/bar")
add_library(foo STATIC foo/foo.c foo/foo.h)
target_include_directories(foo PUBLIC "${CMAKE_CURRENT_LIST_DIR}/foo")
target_link_libraries(foo PRIVATE bar)
add_executable(main main/main.c)
target_link_libraries(main PRIVATE foo)
The link line I see for this is
[100%] Linking C executable main
/usr/local/bin/cmake -E cmake_link_script CMakeFiles/main.dir/link.txt --verbose=1
/usr/bin/cc CMakeFiles/main.dir/main/main.c.o -o main libfoo.a libbar.a
You may ask, why would you make something that would purposely fail. I did this trying to investigate this problem. We have a scenario where the bar library has information in it’s header files that foo wants to use, but it doesn’t actually use any symbols from bar.
In order for foo to compile it needs a few header files from bar but it doesn’t need bar.a. But when we use this mechanism the consumer of foo now tries to link with bar.a too.