ECM-FIND-MODULES(7)

✨ NAME ✨

ecm-find-modules β€” the ECM Find Modules Reference, bestie. It lives in the Extra CMake Modules (ECM) manual, and today we're going through every single find module in it, no skips, no cap πŸ’…


🌸 INTRODUCTION 🌸

okay so. Find modules are the little helpers that CMake's find_package command uses to go hunting for packages that don't ship their own CMake package config files. CMake already comes with a whole buffet of find modules, and Extra CMake Modules (ECM) just adds more on top πŸŽ€

To use ECM's find modules, you gotta tell CMake to find the ECM package first, and then add either ${ECM_MODULE_PATH} or ${ECM_FIND_MODULE_DIR} to the CMAKE_MODULE_PATH variable:

find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_FIND_MODULE_DIR})

Heads up: if you use ${ECM_MODULE_PATH} instead, you also make the modules that are meant for direct use by CMake scripts available β€” see ecm-modules(7) and ecm-kde-modules(7) πŸ¦‹

You can also make local copies of find modules using the ecm_use_find_modules function from ECMUseFindModules, which gets automatically included when ECM is found:

find_package(ECM REQUIRED NO_MODULE)
ecm_use_find_modules(
    DIR "${CMAKE_BINARY_DIR}/cmake"
    MODULES FindEGL.cmake
)
set(CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}/cmake")

This is the move when you want selective use of ECM's find modules πŸ‘‘ and the NO_OVERRIDE argument is there so that if CMake ships its own version of that find module, CMake's version gets used instead 🫢


πŸ’– ALL FIND MODULES πŸ’–

⭐ Find7Zip

Try to find 7-Zip, bestie πŸ—‚οΈ

If the 7-Zip executable is not in your PATH, you can provide an alternative name or a full path location with the 7Zip_EXECUTABLE variable.

This will define the following variables:

  • 7Zip_FOUND β€” TRUE if 7-Zip is available
  • 7Zip_EXECUTABLE β€” path to the 7-Zip executable

If 7Zip_FOUND is TRUE, it will also define the following imported target:

  • 7Zip::7Zip β€” path to the 7-Zip executable
Note: it will see to only find the original 7-Zip, not one of the p7zip forks πŸ™ˆ

Since 5.113.0.


⭐ Find7z

Try to find 7z πŸ—œοΈ

If the 7z executable is not in your PATH, you can provide an alternative name or a full path location with the 7z_EXECUTABLE variable.

This will define the following variables:

  • 7z_FOUND β€” TRUE if 7z is available
  • 7z_EXECUTABLE β€” path to the 7z executable

If 7z_FOUND is TRUE, it will also define the following imported target:

  • 7z::7z β€” path to the 7z executable
Note: only works on Windows πŸ’€
Deprecated: since 5.113, use Find7Zip.

Since 5.85.0.


⭐ FindCanberra

Try to find the Canberra event sound library πŸ”Šβœ¨

This will define the following variables:

  • Canberra_FOUND β€” true if (the requested version of) Canberra is available
  • Canberra_VERSION β€” the version of Canberra
  • Canberra_LIBRARIES β€” the libraries of Canberra, for use with target_link_libraries()
  • Canberra_INCLUDE_DIRS β€” the include dirs of Canberra, for use with target_include_directories()

If Canberra_FOUND is TRUE, it will also define the following imported target:

  • Canberra::Canberra β€” the Canberra library

In general we recommend using the imported target, because it's easier to use 🫢 Bear in mind, however, that if the target is in the link interface of an exported library, it must be made available by the package config file. (yeah, that part matters, don't skip it)

Since 5.56.0.


⭐ FindEGL

Try to find EGL 🎨

This will define the following variables:

  • EGL_FOUND β€” true if (the requested version of) EGL is available
  • EGL_VERSION β€” the version of EGL; note that this is the API version defined in the headers, rather than the version of the implementation (eg: Mesa) β€” very much not the same thing, iykyk
  • EGL_LIBRARIES β€” this can be passed to target_link_libraries() instead of the EGL::EGL target
  • EGL_INCLUDE_DIRS β€” this should be passed to target_include_directories() if the target is not used for linking
  • EGL_DEFINITIONS β€” this should be passed to target_compile_options() if the target is not used for linking

If EGL_FOUND is TRUE, it will also define the following imported target:

  • EGL::EGL β€” the EGL library

In general we recommend using the imported target, as it is easier to use πŸ’œ Bear in mind, however, that if the target is in the link interface of an exported library, it must be made available by the package config file.

Since pre-1.0.0.


⭐ FindFFmpeg

Try to find FFmpeg components 🎬

The following components are available:

AVCODEC  AVFILTER    AVDEVICE  AVFORMAT
AVUTIL   SWRESAMPLE  SWSCALE   POSTPROCESS

If no components are specified in the find_module call, the following ones will be chosen as default:

AVFORMAT AVUTIL AVCODEC

πŸ¦‹ Imported Targets

This module provides the following imported targets, if found:

  • FFmpeg::FFmpeg β€” for all the required FFmpeg components
  • FFmpeg::<component> β€” for each <component> that was found

πŸ¦‹ Result Variables

This will define the following variables:

  • FFMPEG_FOUND β€” system has all the required components.
  • FFMPEG_INCLUDE_DIRS β€” include directory necessary for using the required components headers.
  • FFMPEG_LIBRARIES β€” link these to use the required FFmpeg components.
  • FFMPEG_DEFINITIONS β€” compiler switches required for using the required FFmpeg components.

Additionally, for each of the components, the following variables will be defined:

  • <component>_FOUND β€” true if (the requested version of) <component> is available
  • <component>_INCLUDE_DIRS β€” include directory necessary for using the <component> headers
  • <component>_LIBRARIES β€” link these to use <component>
  • <component>_DEFINITIONS β€” compiler switches required for using <component>
  • <component>_VERSION β€” the component's version (NOTE: always empty on Windows)

Since the versions of the various FFmpeg components differ for a given release, and CMake supports only one common version for all components, use the following to specify required versions for multiple components:

find_package(FFmpeg 57.48 COMPONENTS AVCODEC)
find_package(FFmpeg 57.40 COMPONENTS AVFORMAT)
find_package(FFmpeg 55.27 COMPONENTS AVUTIL)
NOTE: version checking is skipped on Windows 😭

Since 6.20.0.


⭐ FindGLIB2

Try to locate the GLib2 library 🧡 If found, this will define the following variables:

  • GLIB2_FOUND β€” true if the GLib2 library is available
  • GLIB2_INCLUDE_DIRS β€” the GLib2 include directories
  • GLIB2_LIBRARIES β€” the GLib2 libraries for linking
  • GLIB2_INCLUDE_DIR β€” deprecated, use GLIB2_INCLUDE_DIRS
  • GLIB2_LIBRARY β€” deprecated, use GLIB2_LIBRARIES

If GLIB2_FOUND is TRUE, it will also define the following imported targets:

  • GLIB2::GLIB2 β€” the GLIB2 library
  • GLIB2::GTHREAD2 β€” the GThread2 library (since 6.7.0)
  • GLIB2::GOBJECT β€” the GObject library (since 6.7.0)
  • GLIB2::GIO β€” the GIO library (since 6.7.0)

Since 5.41.0.


⭐ FindGperf

Try to find GNU gperf 🧚

If the gperf executable is not in your PATH, you can provide an alternative name or a full path location with the Gperf_EXECUTABLE variable.

This will define the following variables:

  • Gperf_FOUND β€” true if gperf is available.
  • Gperf_EXECUTABLE β€” the gperf executable.
  • Gperf_VERSION β€” the gperf version. (since 5.85)

If Gperf_FOUND is TRUE, it will also define the following imported target:

  • GPerf::Gperf β€” the gperf executable.

and the following public function:

ecm_gperf_generate(<GperfInput> <OutputFile> <OutputVariable(|target (since 5.83))>
                   [GENERATION_FLAGS <flags>])

Run gperf on <GperfInput> to generate <OutputFile>, adding it to the <OutputVariable> variable, which contains the source for the target where <OutputFile> is going to be built or β€” since KF 5.83 β€” if the given argument is a target, to the list of private sources of that target. 🎯 The target must not be an alias. The optional GENERATION_FLAGS argument is needed to pass extra parameters to gperf (note: you cannot override the output file that way, so don't even try πŸ’…).

A simple invocation would be:

ecm_gperf_generate(simple.gperf ${CMAKE_CURRENT_BINARY_DIR}/simple.h MySources)

Since 5.35.0.


⭐ FindGradle

Gives you the ability to build Android AAR libraries using Gradle πŸ€–πŸ“±

This relies on the Qt-provided Gradle, so a Qt for Android installation is required. (yes, required, not optional, sorry bestie)

gradle_add_aar(<target>
               BUIDLFILE build.gradle
               NAME <aar-name>)

This builds an Android AAR library using the given build.gradle file.

gradle_install_aar(<target>
                   DESTINATION <dest>)

Installs an Android AAR library that has been created with gradle_add_aar.

Since 5.76.0.


⭐ FindIcoTool

Try to find icotool πŸ–ΌοΈ

If the icotool executable is not in your PATH, you can provide an alternative name or a full path location with the IcoTool_EXECUTABLE variable.

This will define the following variables:

  • IcoTool_FOUND β€” true if icotool is available.
  • IcoTool_EXECUTABLE β€” the icotool executable.

If IcoTool_FOUND is TRUE, it will also define the following imported target:

  • IcoTool::IcoTool β€” the icotool executable.

Since 5.49.


⭐ FindInotify

Try to find inotify on this system πŸ‘€ This finds:

  • libinotify on Unix-like systems, or
  • the kernel's inotify.

This will define the following variables:

  • Inotify_FOUND β€” true if inotify is available
  • Inotify_LIBRARIES β€” this has to be passed to target_link_libraries()
  • Inotify_INCLUDE_DIRS β€” this has to be passed to target_include_directories()

On some platforms like Linux and SunOS, the libraries and include directories are empty, even though Inotify_FOUND may be set to TRUE. That's not a bug, bestie β€” it's because no special includes or libraries are needed πŸ’€ On other systems these may be needed to use inotify.

Since 5.32.0.


⭐ FindIsoCodes

Try to find iso-codes data files 🌍 Once done, this will define:

  • IsoCodes_FOUND β€” whether the system has iso-codes
  • IsoCodes_PREFIX β€” the location in which the iso-codes data files are found
  • IsoCodes_DOMAINS β€” the available domains provided by iso-codes

Since 5.80.0.


⭐ FindKF5

Find KDE Frameworks 5 with a single find_package() call πŸ‘‘ one call, that's it, iconic

...and it's pulling straight from the package config files that each individual framework ships. Real talk: say you wanna find KArchive, which shows up to CMake as KF5Archive (like, you'd do find_package(KF5Archive) to get it directly) β€” then you do:

find_package(KF5 COMPONENTS Archive)

If all the required components get found (the ones you listed in COMPONENTS, not the ones in OPTIONAL_COMPONENTS), KF5_FOUND gets set to true. Otherwise it's false. Simple as that, bestie. ✨

Since pre-1.0.0.

FindKF6

Find KDE Frameworks 6 in one single find_package() call. One call! Not forty! We love efficiency. πŸŽ€

Same deal as above β€” it uses the package config files that the individual frameworks hand over. Example time: wanna find KArchive, which presents itself to CMake as KF6Archive (ie: you'd do find_package(KF6Archive) to find it directly)? Then:

find_package(KF6 COMPONENTS Archive)

If all the required components (the COMPONENTS ones, not the OPTIONAL_COMPONENTS ones) are found, KF6_FOUND is true. Otherwise false. No cap.

Since 6.0.0.

FindLibExiv2

Tryna find the Exiv2 library? Say less. πŸ’…

This defines these variables for you:

  • LibExiv2_FOUND β€” True if (the requested version of) Exiv2 is available
  • LibExiv2_VERSION β€” the version of Exiv2
  • LibExiv2_INCLUDE_DIRS β€” the include dirs of Exiv2, for use with target_include_directories()
  • LibExiv2_LIBRARIES β€” the Exiv2 library, for use with target_link_libraries(). This can be passed to target_link_libraries() instead of the LibExiv2::LibExiv2 target

And if LibExiv2_FOUND is TRUE, it also defines this imported target:

  • LibExiv2::LibExiv2 β€” the Exiv2 library

In general we recommend using the imported target, because it's easier to use. But bear in mind: if the target is in the link interface of an exported library, it must be made available by the package config file. That's the fine print, don't skip it πŸ‘€

Since 5.53.0.

FindLibGit2

Tryna find libgit2 on a Unix system? This is your girl. πŸ¦‹

Variables it defines:

  • LIBGIT2_FOUND β€” True if (the requested version of) libgit2 is available
  • LIBGIT2_VERSION β€” the version of libgit2
  • LIBGIT2_LIBRARIES β€” this can be passed to target_link_libraries() instead of the LibGit2::LibGit2 target
  • LIBGIT2_INCLUDE_DIRS β€” this should be passed to target_include_directories() if the target isn't used for linking
  • LIBGIT2_DEFINITIONS β€” this should be passed to target_compile_options() if the target isn't used for linking

If LIBGIT2_FOUND is TRUE, you also get this imported target:

  • LibGit2::LibGit2 β€” the libgit2 library

Recommendation, same as ever: use the imported target, it's easier. But fr fr, if the target is in the link interface of an exported library, the package config file has to make it available.

Since 1.3.0.

FindLibMount

Tryna find the libmount library (that's the one that lives inside util-linux)? Once it's done, you get:

  • LibMount_FOUND β€” LibMount was found on the system
  • LibMount_INCLUDE_DIRS β€” the libmount include directory
  • LibMount_LIBRARIES β€” the libmount libraries
  • LibMount_VERSION β€” the libmount version

And if LibMount_FOUND is TRUE, it also defines this imported target:

  • LibMount::LibMount β€” the libmount library

Since 5.83.0

FindLibcap

Tryna find the setcap binary and the cap libraries? Two for one, iconic. πŸ‘‘

This defines:

  • Libcap_FOUND β€” system has the cap library and setcap binary
  • Libcap_LIBRARIES β€” cap libraries to link against
  • SETCAP_EXECUTABLE β€” path of the setcap binary

In addition, the following targets are defined:

  • Libcap::SetCapabilities

Since 5.80.0.

FindOpenEXR

Tryna find the OpenEXR libraries? Here's what you get:

  • OpenEXR_FOUND β€” True if OpenEXR is available
  • OpenEXR_LIBRARIES β€” link to these to use OpenEXR
  • OpenEXR_INCLUDE_DIRS β€” include directory for OpenEXR
  • OpenEXR_DEFINITIONS β€” compiler flags required to link against OpenEXR

Plus these imported targets:

  • OpenEXR::IlmImf β€” the OpenEXR core library

In general we recommend using the imported target, as it is easier to use. Bear in mind, however, that if the target is in the link interface of an exported library, it must be made available by the package config file.

Since pre-1.0.0.

FindPhoneNumber

Tryna find PhoneNumber? 🌸

This is a component-based find module β€” it uses the COMPONENTS and OPTIONAL_COMPONENTS arguments to find_module. These are the components you can ask for:

PhoneNumber  GeoCoding

If you specify no components at all, this module acts like all of them were passed to OPTIONAL_COMPONENTS. Chill of it, honestly.

It defines this variable no matter which components you searched for or found:

  • PhoneNumber_FOUND β€” True if (the requestion version of) PhoneNumber is available

(yes, the manpage really says "requestion" πŸ’€ we're leaving it, it's part of the lore now)

For each searched-for component, PhoneNumber_<component>_FOUND gets set to TRUE if the corresponding library was found, and FALSE otherwise. And if PhoneNumber_<component>_FOUND is TRUE, the imported target PhoneNumber::<component> gets defined. Periodt.

Since 5.54.0.

FindPoppler

Tryna find Poppler? Another component-based one, same deal β€” it uses the COMPONENTS and OPTIONAL_COMPONENTS arguments to find_module. The available components:

Core  Cpp  Qt5  Qt4  Glib

No components specified? Then this module acts like all of them went to OPTIONAL_COMPONENTS. 🫢

These variables get defined regardless of which components you searched for or found:

  • Poppler_FOUND β€” TRUE if (the requested version of) Poppler is available
  • Poppler_VERSION β€” found Poppler version
  • Poppler_TARGETS β€” a list of all targets imported by this module (note that there may be more than the components that were requested)
  • Poppler_LIBRARIES β€” this can be passed to target_link_libraries() instead of the imported targets
  • Poppler_INCLUDE_DIRS β€” this should be passed to target_include_directories() if the targets are not used for linking
  • Poppler_DEFINITIONS β€” this should be passed to target_compile_options() if the targets are not used for linking

For each searched-for component, Poppler_<component>_FOUND gets set to TRUE if the corresponding Poppler library was found, FALSE otherwise. If Poppler_<component>_FOUND is TRUE, the imported target Poppler::<component> gets defined. This module also attempts to figure out Poppler_*_VERSION variables for each imported target β€” though Poppler_VERSION should normally be enough for you. ✨

In general we recommend using the imported targets, as they are easier to use and provide more control. Bear in mind, however, that if any target is in the link interface of an exported library, it must be made available by the package config file.

Since 5.19

FindPulseAudio

Tryna locate the PulseAudio library? πŸ”₯ If it's found, these variables get defined:

  • PulseAudio_FOUND β€” True if the system has the PulseAudio library of at least the minimum version specified by either the version parameter to find_package() or the variable PulseAudio_MINIMUM_VERSION
  • PulseAudio_INCLUDE_DIRS β€” the PulseAudio include directory
  • PulseAudio_LIBRARIES β€” the PulseAudio libraries for linking
  • PulseAudio_MAINLOOP_LIBRARY β€” the libraries needed to use PulseAudio Mainloop
  • PulseAudio_VERSION β€” the version of PulseAudio that was found
  • PulseAudio_INCLUDE_DIR β€” deprecated, use PulseAudio_INCLUDE_DIRS
  • PulseAudio_LIBRARY β€” deprecated, use PulseAudio_LIBRARIES
Those last two are deprecated, okay? Don't be out here using them in fresh code, bestie. Use the plural ones. πŸ™ˆ

If PulseAudio_FOUND is TRUE, it also defines this imported target:

  • PulseAudio::PulseAudio β€” the PulseAudio library

Since 5.41.0.

FindQtWaylandScanner

Tryna find qtwaylandscanner? 🧚

If the qtwaylandscanner executable isn't in your PATH, you can hand over an alternative name or a full path location with the QtWaylandScanner_EXECUTABLE variable. You're welcome.

This defines:

  • QtWaylandScanner_FOUND β€” True if qtwaylandscanner is available
  • QtWaylandScanner_EXECUTABLE β€” the qtwaylandscanner executable

And if QtWaylandScanner_FOUND is TRUE, it also defines this imported target:

  • Wayland::QtScanner β€” the qtwaylandscanner executable

This module also provides the following functions to generate C++ protocol implementations:

  • ecm_add_qtwayland_client_protocol
  • ecm_add_qtwayland_server_protocol

Here's the client one:

ecm_add_qtwayland_client_protocol(<target>
                                  PROTOCOL <xmlfile>
                                  BASENAME <basename>
                                  [PREFIX <prefix>]
                                  [PRIVATE_CODE])

ecm_add_qtwayland_client_protocol(<source_files_var>
                                  PROTOCOL <xmlfile>
                                  BASENAME <basename>
                                  [PREFIX <prefix>]
                                  [PRIVATE_CODE])

It generates a C++ wrapper for Wayland client protocol files from the <xmlfile> XML definition for the <basename> interface, and appends those files to <source_files_var> or <target>. Pass the <prefix> argument if the interface names don't start with qt_ or wl_. PRIVATE_CODE instructs wayland-scanner to hide marshalling code from the compiled DSO, for use in other DSOs. The default is to export this code. πŸ‘‘

WaylandScanner is required and will be searched for.

And the server one:

ecm_add_qtwayland_server_protocol(<target>
                                  PROTOCOL <xmlfile>
                                  BASENAME <basename>
                                  [PREFIX <prefix>]
                                  [PRIVATE_CODE])

ecm_add_qtwayland_server_protocol(<source_files_var>
                                  PROTOCOL <xmlfile>
                                  BASENAME <basename>
                                  [PREFIX <prefix>]
                                  [PRIVATE_CODE])

...so yeah, it generates those wrapper files from the <xmlfile> XML definition for the <basename> interface, then appends them to <source_files_var> or <target>. And bestie, if your interface names don't start with qt_ or wl_, you have to pass the <prefix> argument, okay? 🫢

PRIVATE_CODE tells wayland-scanner to hide the marshalling code from the compiled DSO so it can be used in other DSOs. The default is to export this code. (yes, default = out in the open ✨)

WaylandScanner is required and will be searched for.

Since 1.4.0.


🌸 FindSasl2 🌸

Trying to hunt down the SASL2 library, bestie. πŸ”

It'll define these variables for you:

  • Sasl2_FOUND β€” the system has SASL2. slay.
  • Sasl2_VERSION β€” which version of SASL2 you got.
  • Sasl2_INCLUDE_DIRS β€” pass this to target_include_directories() if you're not using the target for linking.
  • Sasl2_LIBRARIES β€” the actual SASL2 library. You can pass this to target_link_libraries() instead of the Sasl2::Sasl2 target, iykyk.

And if Sasl2_FOUND is TRUE, you also get this imported target:

  • Sasl2::Sasl2 β€” the SASL2 library, iconic.

Since 5.41.0.


πŸ›‘οΈ FindSeccomp πŸ›‘οΈ

Trying to locate the libseccomp library.

Defines these:

  • Seccomp_FOUND β€” true if the seccomp library is available.
  • Seccomp_INCLUDE_DIRS β€” the seccomp include directories.
  • Seccomp_LIBRARIES β€” the seccomp libraries for linking.

If Seccomp_FOUND is TRUE, it also defines this imported target:

  • Seccomp::Seccomp β€” the Seccomp library πŸ’œ

Since 5.44.0.


🐚 FindSharedMimeInfo 🐚

Trying to find the shared-mime-info package.

Variables it defines:

  • SharedMimeInfo_FOUND β€” true if the system has the shared-mime-info package.
  • UPDATE_MIME_DATABASE_EXECUTABLE β€” the update-mime-database executable.

Plus these imported targets:

  • SharedMimeInfo::UpdateMimeDatabase β€” the update-mime-database executable.

And there's this macro available:

update_xdg_mimetypes(<path>)

It updates the XDG mime database at install time β€” unless the $DESTDIR environment variable is set, in which case it's up to package managers to do that task. not us, not today πŸ’…

Since pre-1.0.0.


🎡 FindTaglib 🎡

Trying to find the Taglib library.

Defines:

  • Taglib_FOUND β€” true if the system has the taglib library of at least the minimum version specified by the version parameter to find_package().
  • Taglib_INCLUDE_DIRS β€” the taglib include dirs, for use with target_include_directories.
  • Taglib_LIBRARIES β€” the taglib libraries, for use with target_link_libraries().
  • Taglib_VERSION β€” the version of taglib that was found.

If Taglib_FOUND is TRUE, you also get this imported target:

  • Taglib::Taglib β€” the Taglib library ✨

Since 5.72.0


πŸ”Œ FindUDev πŸ”Œ

Trying to find the UDev library.

Defines:

  • UDev_FOUND β€” system has UDev.
  • UDev_INCLUDE_DIRS β€” the libudev include directory.
  • UDev_LIBRARIES β€” the libudev libraries.
  • UDev_VERSION β€” the libudev version.

If UDev_FOUND is TRUE, it also defines this imported target:

  • UDev::UDev β€” the UDev library πŸ’–

Since 5.57.0.


πŸͺŸ FindWayland πŸͺŸ

Trying to find Wayland.

Okay so this one is a component-based find module β€” it uses the COMPONENTS and OPTIONAL_COMPONENTS arguments to find_module. These are the components available:

Client  Server  Cursor  Egl

If you don't specify any components, this module acts like you passed all of them to OPTIONAL_COMPONENTS. (generous queen πŸ‘‘)

It defines these variables no matter which components you searched for or found:

  • Wayland_FOUND β€” TRUE if (the requested version of) Wayland is available.
  • Wayland_VERSION β€” found Wayland version.
  • Wayland_TARGETS β€” a list of all targets imported by this module. Heads up: there may be more than the components you actually requested πŸ‘€
  • Wayland_LIBRARIES β€” pass this to target_link_libraries() instead of the imported targets.
  • Wayland_INCLUDE_DIRS β€” pass this to target_include_directories() if the targets aren't used for linking.
  • Wayland_DEFINITIONS β€” pass this to target_compile_options() if the targets aren't used for linking.
  • Wayland_DATADIR β€” the core wayland protocols data directory. Since 5.73.0.

For every component you searched for, Wayland_<component>_FOUND gets set to TRUE if the matching Wayland library was found, and FALSE if it wasn't. If Wayland_<component>_FOUND is TRUE, the imported target Wayland::<component> gets defined. This module will also try to figure out Wayland_*_VERSION variables for each imported target, though Wayland_VERSION should normally be enough for you, fr fr.

In general we recommend using the imported targets β€” they're easier to use and give you more control 🫢 But like, bear in mind: if any target is in the link interface of an exported library, it must be made available by the package config file. no exceptions, bestie.

Since pre-1.0.0.


🌈 FindWaylandProtocols 🌈

Trying to find wayland-protocols on a Unix system.

Defines:

  • WaylandProtocols_FOUND β€” true if (the requested version of) wayland-protocols is available.
  • WaylandProtocols_VERSION β€” the version of wayland-protocols.
  • WaylandProtocols_DATADIR β€” the wayland protocols data directory.

🧚 FindWaylandScanner 🧚

Trying to find wayland-scanner.

If the wayland-scanner executable isn't in your PATH, you can hand over an alternative name or a full path location with the WaylandScanner_EXECUTABLE variable. problem solved πŸ’…

Defines:

  • WaylandScanner_FOUND β€” true if wayland-scanner is available.
  • WaylandScanner_EXECUTABLE β€” the wayland-scanner executable.

If WaylandScanner_FOUND is TRUE, it also defines this imported target:

  • Wayland::Scanner β€” the wayland-scanner executable.

This module also provides these functions for generating C protocol implementations:

  • ecm_add_wayland_client_protocol
  • ecm_add_wayland_server_protocol
ecm_add_wayland_client_protocol(<target>
                                PROTOCOL <xmlfile>
                                BASENAME <basename>
                                [PRIVATE_CODE])
ecm_add_wayland_client_protocol(<source_files_var>
                                PROTOCOL <xmlfile>
                                BASENAME <basename>
                                [PRIVATE_CODE])

Generates Wayland client protocol files from the <xmlfile> XML definition for the <basename> interface, then appends those files to <source_files_var> or <target>.

PRIVATE_CODE tells wayland-scanner to hide the marshalling code from the compiled DSO so it can be used in other DSOs. The default is to export this code.

ecm_add_wayland_server_protocol(<target>
                                PROTOCOL <xmlfile>
                                BASENAME <basename>
                                [PRIVATE_CODE])
ecm_add_wayland_server_protocol(<source_files_var>
                                PROTOCOL <xmlfile>
                                BASENAME <basename>
                                [PRIVATE_CODE])

Generates Wayland server protocol files from the <xmlfile> XML definition for the <basename> interface, then appends those files to <source_files_var> or <target>.

PRIVATE_CODE tells wayland-scanner to hide the marshalling code from the compiled DSO so it can be used in other DSOs. The default is to export this code.

Since 1.4.0.


πŸ’€ FindX11_XCB πŸ’€

Trying to find the X11 XCB compatibility library.

Defines:

  • X11_XCB_FOUND β€” true if (the requested version of) libX11-xcb is available.
  • X11_XCB_VERSION β€” the version of libX11-xcb. Ngl, this one is not guaranteed to be set even when X11_XCB_FOUND is true πŸ™ˆ
  • X11_XCB_LIBRARIES β€” pass this to target_link_libraries() instead of the EGL::EGL target. (yes, the page really says EGL::EGL here, we don't make the rules πŸ’€)
  • X11_XCB_INCLUDE_DIR β€” pass this to target_include_directories() if the target isn't used for linking.
  • X11_XCB_DEFINITIONS β€” pass this to target_compile_options() if the target isn't used for linking.

If X11_XCB_FOUND is TRUE, it also defines this imported target:

  • X11::XCB β€” the X11 XCB compatibility library ✨
In general we recommend using the imported target, it's easier to use. But bear in mind: if the target is in the link interface of an exported library, it must be made available by the package config file.

Since pre-1.0.0.


πŸ”₯ FindXCB πŸ”₯

Trying to find XCB.

Another component-based find module β€” uses the COMPONENTS and OPTIONAL_COMPONENTS arguments to find_module. Here's the full menu of components:

XCB
ATOM         AUX          COMPOSITE    CURSOR       DAMAGE
DPMS         DRI2         DRI3         EVENT        EWMH
GLX          ICCCM        IMAGE        KEYSYMS      PRESENT
RANDR        RECORD       RENDER       RENDERUTIL   RES
SCREENSAVER  SHAPE        SHM          SYNC         UTIL
XF86DRI      XFIXES       XINERAMA     XINPUT       XKB
XTEST        XV           XVMC

If you don't specify any components, this module acts like all of them were passed to OPTIONAL_COMPONENTS. But heads up: before 5.82 that excluded XINPUT. Since 5.82, all components are searched for. glow-up πŸ’…

It defines these variables no matter which components you searched for or found:

  • XCB_FOUND β€” true if (the "requestion" version of) xcb is available. not me quoting the typo directly, but it's literally what the page says, iconique 😭
  • XCB_VERSION β€” found xcb version.
  • XCB_TARGETS β€” a list of all targets imported by this module. Again: there may be more than the components you requested πŸ‘€
  • XCB_LIBRARIES β€” pass this to target_link_libraries() instead of the imported targets.
  • XCB_INCLUDE_DIRS β€” pass this to target_include_directories() if the targets aren't used for linking.
  • XCB_DEFINITIONS β€” pass this to target_compile_options() if the targets aren't used for linking.

For each component you searched for, XCB_<component>_FOUND gets set to true if the corresponding xcb library was found, and false if it wasn't. If XCB_<component>_FOUND is true, the imported target XCB::<component> gets defined. This module will also try to determine XCB_*_VERSION variables for each imported target, although XCB_VERSION should normally be sufficient. bestie, just use XCB_VERSION 🫢

okay so general rule, bestie: use the imported targets β€” they're easier to use and give you way more control. πŸ’…

but lowkey remember: if any target is in the link interface of an exported library, it must be made available by the package config file. no skipping that, fr fr.

Since pre-1.0.0.

πŸ§ͺ Findepoxy πŸ§ͺ

Trying to find libepoxy on a Unix system? This module is literally here for that. 🧚✨

This will define the following variables:

  • epoxy_FOUND β€” True if (the requested version of) libepoxy is available πŸ’–
  • epoxy_VERSION β€” The version of libepoxy
  • epoxy_LIBRARIES β€” This should be passed to target_link_libraries() if the target is not used for linking
  • epoxy_INCLUDE_DIRS β€” This should be passed to target_include_directories() if the target is not used for linking
  • epoxy_DEFINITIONS β€” This should be passed to target_compile_options() if the target is not used for linking
  • epoxy_HAS_GLX β€” True if GLX support is available πŸŽ€

If epoxy_FOUND is TRUE, it will also define the following imported target:

  • epoxy::epoxy β€” The epoxy library πŸ‘‘

In general we recommend using the imported target, as it is easier to use. Bear in mind, however, that if the target is in the link interface of an exported library, it must be made available by the package config file.

πŸ“ Findgzip πŸ“

Try to find gzip β€” that's the whole assignment, bestie. 🫢

If the gzip executable is not in your PATH, you can provide an alternative name or full path location with the gzip_EXECUTABLE variable.

This will define the following variables:

  • gzip_FOUND β€” TRUE if gzip is available ✨
  • gzip_EXECUTABLE β€” Path to gzip executable

If gzip_FOUND is TRUE, it will also define the following imported target:

  • gzip::gzip β€” Path to gzip executable πŸŽ€

Since 5.85.0.


πŸ”— SEE ALSO πŸ”—

KDE Developers


that's the teaaa πŸ’… β€” this ECM-FIND-MODULES(7) page is version 6.31, dated Oct 11, 2026, copyright KDE Developers. byeee, go find those modules! 🫢✨🌈

πŸ“¦ where this page comes from