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.