find_package OPTIONAL_COMPONENT

find_package(Qt${QT_VERSION_MAJOR} REQUIRED Concurrent Gui OpenGL Svg Widgets Xml OPTIONAL_COMPONENTS Charts HttpServer WebSockets)

I’m trying to find the Qt package, with some required and some optional components.
The above statement in a CMakeLists.txt produces an error if HttpServer component is not found (e.g. because I specify Qt version 5.15.x, which doesn’t even have this component yet):

CMake Error at C:/Tools/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5/Qt5Config.cmake:28 (find_package):
  Could not find a package configuration file provided by "Qt5HttpServer"
  with any of the following names:

    Qt5HttpServerConfig.cmake
    qt5httpserver-config.cmake

  Add the installation prefix of "Qt5HttpServer" to CMAKE_PREFIX_PATH or set
  "Qt5HttpServer_DIR" to a directory containing one of the above files.  If
  "Qt5HttpServer" provides a separate development package or SDK, be sure it
  has been installed.
Call Stack (most recent call first):
  CMakeLists.txt:122 (find_package)

The documentation of find_package states

Additional optional components may be listed after OPTIONAL_COMPONENTS. If these cannot be satisfied, the package overall can still be considered found, as long as all required components are satisfied.

So why am I getting an error here? Is this a problem with my call to find_package, with Qt 5.15’s cmake configuration, or with CMake?

That doesn’t mean you can pass invalid components. The ambiguous part here is that you don’t know if a component is valid until you know what Qt version it will find. One approach would be to use multiple calls, taking advantage of the fact that the first one that succeeds will effectively turn later ones into no-ops, as long as constraints are still satisfied. Conceptually, something like the following is what I’m thinking:

# NOTE: First call has no REQUIRED keyword but specifies a VERSION
find_package(Qt6
    VERSION 6.5    # Set this to the version the QHttpServer module was added to Qt
    COMPONENTS Concurrent Gui OpenGL Svg Widgets Xml
    OPTIONAL_COMPONENTS Charts HttpServer WebSockets
)
find_package(Qt6
    REQUIRED
    COMPONENTS Concurrent Gui OpenGL Svg Widgets Xml
    OPTIONAL_COMPONENTS Charts WebSockets    # NOTE: No HttpServer here
)

If you want to support the find_package(Qt${QT_VERSION_MAJOR} ...) part, you’d need to tweak the above further. I’ve just assumed Qt6 for simplicity in this example.

1 Like

Makes sense, and thanks for the pointers how to make it work!