CMake Error: install(EXPORT "ProjectTargets" ...) includes target "xxx" which requires target "yyy" that is not in any export set.

Why does my project with static libs NOT work, but with shared libs it works?

clausklein$ cmake --version
cmake version 3.25.0

bash-3.2$ make build
cmake -B ../build-agent++-4.5.1-x86_64-Debug -S . -G Ninja -D BUILD_SHARED_LIBS=NO
-- agent++ Version 4.5.1
-- Found AGENTPP_OPAQUE_PTHREAD_T: long
-- snmp++ Version 3.4.7
-- Found int64_t: int64_t
-- Found uint64_t: uint64_t
-- CPM: snmp_pp: adding package project_options@0.26.3 (v0.26.3 at /Users/clausklein/.cache/CPM/project_options/14755ed2f1a70e93687929554b166873eba6ebc1)
-- Found OpenSSL (include: /usr/local/opt/openssl/include, library: /usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib)
-- The default CMAKE_C_STANDARD used by external targets and tools is not set yet. Using the latest supported C standard that is 17
-- /usr/local/bin/ccache found and enabled
-- CPM: snmp_pp: adding package PackageProject.cmake@1.10.0 (v1.10.0 at /Users/clausklein/.cache/CPM/packageproject.cmake/41b1a5028ad2c8d2c6bb64eb6beff8b090d304e5)
-- CPM: adding package snmp_pp@0 (fba56ad02f6609c4940f1eb0f47b7c0ac43cb326 at /Users/clausklein/.cache/CPM/snmp_pp/f4ab8c03c0d58410763233c4975837896ba64680)
-- The default CMAKE_C_STANDARD used by external targets and tools is not set yet. Using the latest supported C standard that is 17
-- /usr/local/bin/ccache found and enabled
-- Configuring done
CMake Error: install(EXPORT "agent_ppTargets" ...) includes target "agent_pp" which requires target "agent_pp_project_options" that is not in any export set.
CMake Error: install(EXPORT "agent_ppTargets" ...) includes target "agent_pp" which requires target "agent_pp_project_warnings" that is not in any export set.
CMake Error: install(EXPORT "snmp_ppTargets" ...) includes target "snmp_pp" which requires target "snmp_pp_project_options" that is not in any export set.
CMake Error: install(EXPORT "snmp_ppTargets" ...) includes target "snmp_pp" which requires target "snmp_pp_project_warnings" that is not in any export set.
-- Generating done
CMake Generate step failed.  Build files cannot be regenerated correctly.
make: *** [../build-agent++-4.5.1-x86_64-Debug/compile_commands.json] Error 1
bash-3.2$ make build
cmake -B ../build-agent++-4.5.1-x86_64-Debug -S . -G Ninja -D BUILD_SHARED_LIBS=YES
-- agent++ Version 4.5.1
-- Found AGENTPP_OPAQUE_PTHREAD_T: long
-- snmp++ Version 3.4.7
-- Found int64_t: int64_t
-- Found uint64_t: uint64_t
-- CPM: snmp_pp: adding package project_options@0.26.3 (v0.26.3 at /Users/clausklein/.cache/CPM/project_options/14755ed2f1a70e93687929554b166873eba6ebc1)
-- Found OpenSSL (include: /usr/local/opt/openssl/include, library: /usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib)
-- The default CMAKE_C_STANDARD used by external targets and tools is not set yet. Using the latest supported C standard that is 17
-- /usr/local/bin/ccache found and enabled
-- CPM: snmp_pp: adding package PackageProject.cmake@1.10.0 (v1.10.0 at /Users/clausklein/.cache/CPM/packageproject.cmake/41b1a5028ad2c8d2c6bb64eb6beff8b090d304e5)
-- CPM: adding package snmp_pp@0 (fba56ad02f6609c4940f1eb0f47b7c0ac43cb326 at /Users/clausklein/.cache/CPM/snmp_pp/f4ab8c03c0d58410763233c4975837896ba64680)
-- The default CMAKE_C_STANDARD used by external targets and tools is not set yet. Using the latest supported C standard that is 17
-- /usr/local/bin/ccache found and enabled
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/clausklein/Downloads/Software/agentpp/build-agent++-4.5.1-x86_64-Debug
bash-3.2$ 
``

NOTE: I use the project_options cmake package PRIVATE

project_options(
  PREFIX
  ${PROJECT_NAME}
  ENABLE_CACHE
  ${ENABLE_COVERAGE}
  ${ENABLE_UNITY}
  # ENABLE_SANITIZER_ADDRESS
  # ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
  ENABLE_SANITIZER_THREAD
  # ENABLE_SANITIZER_MEMORY
  # TODO: WARNINGS_AS_ERRORS
)

option(BUILD_SHARED_LIBS "Global flag to cause add_library() to create shared libraries if on." ON)
add_library(${PROJECT_NAME} ${MY_HEADER_FILES} ${MY_HEADER_LIB_FILES} ${CMAKE_CURRENT_BINARY_DIR}/config.h ${MY_SRC_FILES})
target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_project_options ${PROJECT_NAME}_project_warnings)
set_target_properties(${PROJECT_NAME} PROPERTIES UNITY_BUILD ${ENABLE_UNITY})

For static libraries, PRIVATE link dependencies are added to the export set using $<LINK_ONLY:> so that any symbols they provide are given to consumers (since the static library won’t contain them). Starting with CMake 3.25, you can use $<BUILD_LOCAL_INTERFACE:${PROJECT_NAME}_project_options> to hide the target from all exports. Before that, you have $<BUILD_INTERFACE> to at least hide it from the install export (but it still needs to be in the build export).

Do you mean starting with v3.26?
see https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7919/diffs#efc7fdbbaf6edb39bddabbebc78e6d86bd0b3dc0

That is not clear to me!

I use only this now:

set(PROJECT_WARNINGS_CXX -Wall -Wextra -Wno-unused-parameter)
add_library(${PROJECT_NAME}_mywarnings INTERFACE)
target_compile_options(
  ${PROJECT_NAME}_mywarnings
  INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>
)
set(LIST_OF_SANITIZERS address)
add_library(${PROJECT_NAME}_myoptions INTERFACE)
if(NOT MSVC)
  target_compile_options(${PROJECT_NAME}_myoptions INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
  target_link_options(${PROJECT_NAME}_myoptions INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
  target_compile_options(${PROJECT_NAME}_myoptions INTERFACE --coverage -O0 -g)
  target_link_libraries(${PROJECT_NAME}_myoptions INTERFACE --coverage)
endif()

add_library(${PROJECT_NAME} ${MY_HEADER_FILES} ${MY_HEADER_LIB_FILES} ${CMAKE_CURRENT_BINARY_DIR}/config.h ${MY_SRC_FILES})
target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_myoptions ${PROJECT_NAME}_mywarnings)

Err, yes, sorry.

To use it:

target_link_libraries(${PROJECT_NAME}
  PRIVATE
    "$<BUILD_INTERFACE:${PROJECT_NAME}_myoptions>"
    "$<BUILD_INTERFACE:${PROJECT_NAME}_mywarnings>")

Replace BUILD_INTERFACE with BUILD_LOCAL_INTERFACE once you can assume CMake 3.26.

Hi Ben

I am trying to understand a similar issue but with real libraries. I have created a minimal repo to describe the issue: GitHub - LecrisUT/cmake_install_static_issue

Basically I am trying to understand how to design a single CMake project that uses and is used by FetchContent such that it supports both shared and static libraries and optionally it can install itself as shared and static library. The issue occurs when I try to install the static library with basically the same error as before. I have tried to use $<BUILD_INTERFACE> but I get compilation error when it comes to actually using the installed library:

[2/2] Linking CXX executable test
FAILED: test 
: && /usr/bin/c++   CMakeFiles/test.dir/main.cpp.o -o test  /example/install-libB-static/lib64/libB.a && :
/usr/bin/ld: /example/install-libB-static/lib64/libB.a(hi.cpp.o): in function `libB::hi()':
hi.cpp:(.text+0x5): undefined reference to `libA::hello()'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

The error message explains to me why it breaks down, but then:

  • Is there a way to bundle the linked static library dependencies?
  • If the former cannot be done, do I always need to install the dependency along with it?