I had a little look into this and I’m afraid I can’t really see how check_required_components
is meant to work in this context either…
From what I can tell, the way check_required_components
is generated won’t work because of how it looks for the component variables (${comp}_FOUND
). These don’t seem to exist when looking at all variables (only phrases_FOUND=1
is set).
I found this reference which makes more sense and is essentially a manual version of writing the check_required_components
macro.
For the phrases
example, the phrases-config.cmake.in
might look something like this:
@PACKAGE_INIT@
set(_phrases_supported_components greetings farewells)
foreach(component ${@PROJECT_NAME@_FIND_COMPONENTS})
if (NOT ${component} IN_LIST _phrases_supported_components)
set(phrases_FOUND False)
set(phrases_NOT_FOUND_MESSAGE "Unsupported component: ${component}")
else()
include(${CMAKE_CURRENT_LIST_DIR}/${component}-config.cmake)
endif()
endforeach()
Then from the application CMakeLists.txt
, if file you call find_package
with chitchat
(non-existing component):
find_package(phrases REQUIRED CONFIG COMPONENTS greetings farewells chitchat)
You get the error:
CMake Error at CMakeLists.txt:4 (find_package):
Found package configuration file:
/path/to/cmake-example/examples/more/components/library/install/lib/cmake/phrases/phrases-config.cmake
but it set phrases_FOUND to FALSE so package "phrases" is considered to be
NOT FOUND. Reason given by package:
Unsupported component: chitchat
The thing is, if you just try and pass a component that doesn’t exist with the existing code you get:
CMake Error at path/to/cmake-example/examples/more/components/library/install/lib/cmake/phrases/phrases-config.cmake:2 (include):
include could not find requested file:
path/to/cmake-example/examples/more/components/library/install/lib/cmake/phrases/chitchat-config.cmake
Call Stack (most recent call first):
CMakeLists.txt:4 (find_package)
Which maybe isn’t quite as informative, but does give a clue the problem is with chitchat
.
I also hope @craig.scott doesn’t mind me referencing a section from his book, Professional CMake, but on page 527 of the 16th edition there’s this section (emphasis mine):
In the past when all details about a package were provided through variables, it was customary to check whether all required variables were set at the end of the config file before returning. A macro called check_required_components()
was defined for this purpose, but projects that provide imported targets should perform these checks themselves. The imported targets should only be created if all required components will be found. Otherwise, a failed find_package()
call will still leave behind targets, which would interfere with any later call to find_package()
for the same package name but with different arguments (e.g. to search in different locations).) This makes the check_required_components()
macro largely redundant.
I hope this helps, and please let me know if I missed something.