Hello,
I am reading about target_link_libraries and the PUBLIC contract. I have this specific situation:
project/
├── CMakeLists.txt (1)
├── dir1/
│ ├── subdir1/
│ │ └── CMakeLists.txt (2)
│ └── src/
│ └── main.c
In CMakeLists.txt (1), I just do this:
add_subdirectory(“dir1/subdir1/”)
In CMakeLists.txt (2), I am pulling an external_project:
include(ExternalProject)
ExternalProject_Add(projectA
GIT_REPOSITORY
GIT_TAG
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=“new-build/deps”
-DCMAKE_BUILD_TYPE=Release
BUILD_ALWAYS TRUE
GIT_PROGRESS TRUE
TEST_COMMAND “”
)
set(gen_libs libA libB) # these are coming from projectA
set(srcs
src/main.c)
add_executable(test ${srcs})
add_dependencies(test projectA)
target_include_directories(test PRIVATE new-build/deps/include)
target_link_directories(test PRIVATE new-build/deps/lib)
target_link_libraries(test PRIVATE gen_libs)
include(GNUInstallDirs)
install(TARGETS test
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
In project A, I am essentially generating libA and libB. Each of these libs depends on other libraries that are generated in projectA dependencies. However, nothing from libA and libB dependencies is directly used in test. If I do not explicitly link the sub dependencies to “test” target, the build fails with undefined references.
Note that I do see all the relevant libs in the new-build/deps/lib and that is the only folder where it exists. The sub-dependencies of libA and libB are linked as:
target_link_libraries(
libA
PUBLIC
libC)
target_link_libraries(
libB
PUBLIC
libC
libD)
install(TARGETS libA libB
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(DIRECTORY ${src}/src/include/
DESTINATION include
)
What am I missing? I thought PUBLIC handles transitive dependencies but maybe I am misunderstanding it. How do I build test executable without having to link to libC and libD? Note that to build, I am creating build
directory in root project directory and running cmake … inside that