Impossible to install transitive dependencies
Consider a simple case. A project defines a default target, Main
, which depends on some shared libraries and executables defined by a very large dependency (perhaps obtained by https://github.com/cpm-cmake/CPM.cmake). The subdirectory is added with EXCLUDE_FROM_ALL
because it has perhaps thousands of unused targets; the required dependencies are transitively built by target_link_libraries(Main ...)
.
Simplistic example code:
# /CMakeLists.txt
cmake_minimum_required(VERSION 3.27)
project(
Main
VERSION 1.0
LANGUAGES CXX
)
add_subdirectory(Foo EXCLUDE_FROM_ALL)
set(CMAKE_INSTALL_RPATH "@executable_path")
add_executable(Main main.cpp)
target_link_libraries(Main Foo_1)
install(TARGETS
Main
# RUNTIME_DEPENDENCIES
# ARCHIVE DESTINATION bin
# RUNTIME DESTINATION bin
# LIBRARY DESTINATION bin
# FRAMEWORK DESTINATION bin
)
#install(FILES $<TARGET_RUNTIME_DLLS:Main> TYPE BIN)
# /Foo/CMakeLists.txt
project(Foo CXX)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
add_library(Foo_1 foo1.cpp foo1.h)
target_include_directories(Foo_1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(Foo_1 PUBLIC Foo_42) # arbitrary transitive dependencies
#install(TARGETS
# Foo_1
# LIBRARY DESTINATION bin
# RUNTIME DESTINATION bin
#)
# ...
add_library(Foo_999 foo999.cpp foo999.h)
target_include_directories(Foo_999 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
#install(TARGETS
# Foo_999
# LIBRARY DESTINATION bin
# RUNTIME DESTINATION bin
#)
Problem: it's basically impossible to install
the dependencies of my target that are built by CMake.
The GET_RUNTIME_DEPENDENCIES
hack just scans the binary, returns hundreds of shared libraries that CMake didn't even build, and doesn't reliably work on macOS. $<TARGET_RUNTIME_DLLS:Main>
is better, but only works on DLL platforms, and requires install(FILES)
which violates the modern "everything is a target" approach.
This is madness. CMake knows my target's link dependencies. CMake literally built them. Why is there no way to transitively install them?