YCM-MODULES(7)

πŸ“¦
version 0.13.0 Β· 2 versions
, in ubuntu noble, ubuntu questing

✨ NAME ✨

so bestie, welcome to ycm-modules β€” the YCM Modules Reference πŸ’– it's section 7 of the YCM manual and it's literally the glow-up guide to all the modules YCM ships with. grab a strawberry drink πŸ“, this is a long one.


πŸŽ€ GENERIC MODULES πŸŽ€

okay so these are the main-character modules, no cap πŸ‘‘

πŸ’… ExtractVersion

pulls version numbers straight out of a version string, iconic:

extract_version (<name> [REVERSE_NAME])

it tries to extract these variables (and btw, the second version gets used if you pass REVERSE_NAME as an argument, iykyk):

  • <name>_MAJOR_VERSION or <name>_VERSION_MAJOR β€” <name> major version
  • <name>_MINOR_VERSION or <name>_VERSION_MINOR β€” <name> minor version
  • <name>_PATCH_VERSION or <name>_VERSION_PATCH β€” <name> patch version
  • <name>_TWEAK_VERSION or <name>_VERSION_TWEAK β€” <name> tweak version
  • <name>_VERSION_COUNT β€” number of version components, 0 to 4

πŸ¦‹ GetAllCMakeProperties

returns a list containing the names of all known CMake Properties. the range? unmatched πŸ’…

lowkey important caveat tho: only properties returned by cmake --help-property-list are returned β€” custom properties will not be on the returned list, sorry babe 😭

and properties containing <CONFIG> or <LANG> get expanded to the correct property name ✨


🌸 GitInfo

extracts information from a git repository. the way this module snoops through your repo history… main character energy fr fr πŸ•΅οΈβ™€οΈπŸ’–

git_commit_info

extract information about one commit from one git repository in SOURCE DIR:

git_commit_info([SOURCE DIR <dir>]
                [PREFIX <prefix>]
                [REVISION <rev>]
                [FATAL])

if SOURCE_DIR is a git repository, it checks the given REVISION and sets the following variables πŸ‘‡

  • <PREFIX>_GIT_COMMIT_DESCRIBE β€” The output of git describe <ref>.
  • <PREFIX>_GIT_COMMIT_DESCRIBE_CONTAINS β€” The output of git describe --contains <ref>.
  • <PREFIX>_GIT_COMMIT_TAG β€” The most recent tag that is reachable from a commit.
  • <PREFIX>_GIT_COMMIT_REVISION β€” The number of commits since the beginning of the git history.
  • <PREFIX>_GIT_COMMIT_TAG_REVISION β€” The number of commits since the last tag.
  • <PREFIX>_GIT_COMMIT_DATE_REVISION β€” The number of commits since the beginning of the day.
  • <PREFIX>_GIT_COMMIT_AUTHOR_DATE β€” The commit author date.
  • <PREFIX>_GIT_COMMIT_AUTHOR_TIME β€” The commit author time.
  • <PREFIX>_GIT_COMMIT_AUTHOR_TZ β€” The commit author time zone.
  • <PREFIX>_GIT_COMMIT_AUTHOR_NAME β€” The commit author name.
  • <PREFIX>_GIT_COMMIT_AUTHOR_EMAIL β€” The commit author e-mail.
  • <PREFIX>_GIT_COMMIT_COMMITTER_DATE β€” The commit committer date.
  • <PREFIX>_GIT_COMMIT_COMMITTER_TIME β€” The commit author time.
  • <PREFIX>_GIT_COMMIT_COMMITTER_TZ β€” The commit author time zone.
  • <PREFIX>_GIT_COMMIT_COMMITTER_NAME β€” The commit committer name.
  • <PREFIX>_GIT_COMMIT_COMMITTER_EMAIL β€” The commit committer email.
  • <PREFIX>_GIT_COMMIT_HASH β€” The commit hash.
  • <PREFIX>_GIT_COMMIT_HASH_SHORT β€” The abbreviated commit hash.
  • <PREFIX>_GIT_COMMIT_SUBJECT β€” The commit log message subject line.
  • <PREFIX>_GIT_COMMIT_BODY β€” The commit log message body.

if SOURCE_DIR isn't set, then the PROJECT_SOURCE_DIR cmake variable is used 🫢

if PREFIX isn't set, then the PROJECT_NAME cmake variable is used ✨

REVISION can be a commit hash, a tag, a branch, or literally anything that git can parse as a revision. if REVISION isn't set, then HEAD is used πŸ’…

if FATAL is set, a fatal error is emitted when the source dir is not a git repository, or when git was not found. this is disabled by default to allow downloads from non-git sources (archives, wrappers, etc.), but can be enabled if required. so like, drama only when you ask for it πŸŽ€

git_wt_info

extract information about the current working tree from one git repository in SOURCE DIR:

git_wt_info([SOURCE DIR <dir>]
            [PREFIX <prefix>]
            [FATAL])

if SOURCE_DIR is a git repository, it checks the current revision and sets the following variables πŸ‘‡

  • <PREFIX>_GIT_WT_DESCRIBE β€” The output of git describe HEAD.
  • <PREFIX>_GIT_WT_DESCRIBE_CONTAINS β€” The output of git describe --contains HEAD.
  • <PREFIX>_GIT_WT_TAG β€” The most recent tag that is reachable from current commit.
  • <PREFIX>_GIT_WT_REVISION β€” The number of commits since the beginning of the git history.
  • <PREFIX>_GIT_WT_TAG_REVISION β€” The number of commits since the last tag.
  • <PREFIX>_GIT_WT_DATE_REVISION β€” The number of commits since the beginning of the day.
  • <PREFIX>_GIT_WT_AUTHOR_DATE β€” The current commit author date.
  • <PREFIX>_GIT_WT_AUTHOR_TIME β€” The current commit author time.
  • <PREFIX>_GIT_WT_AUTHOR_TZ β€” The current commit author time zone.
  • <PREFIX>_GIT_WT_AUTHOR_NAME β€” The current commit author name.
  • <PREFIX>_GIT_WT_AUTHOR_EMAIL β€” The current commit author e-mail.
  • <PREFIX>_GIT_WT_COMMITTER_DATE β€” The current commit committer date.
  • <PREFIX>_GIT_WT_COMMITTER_TIME β€” The current commit author time.
  • <PREFIX>_GIT_WT_COMMITTER_TZ β€” The current commit author time zone.
  • <PREFIX>_GIT_WT_COMMITTER_NAME β€” The current commit committer name.
  • <PREFIX>_GIT_WT_COMMITTER_EMAIL β€” The current commit committer email.
  • <PREFIX>_GIT_WT_HASH β€” The current commit hash.
  • <PREFIX>_GIT_WT_HASH_SHORT β€” The abbreviated commit hash.
  • <PREFIX>_GIT_WT_SUBJECT β€” The current commit log message subject line.
  • <PREFIX>_GIT_WT_BODY β€” The current commit log message body.
  • <PREFIX>_GIT_WT_DIRTY β€” Whether the current working tree is clean or not.

if SOURCE_DIR isn't set, then the PROJECT_SOURCE_DIR cmake variable is used 🫢

if PREFIX isn't set, then the PROJECT_NAME cmake variable is used ✨

if FATAL is set, a fatal error is emitted when the source dir is not a git repository, or when git was not found. this is disabled by default to allow downloads from non-git sources (archives, wrappers, etc.), but can be enabled if required. same vibe as above, no cap πŸ’…


🧚 IncludeUrl

adds the include_url() command that's useful to download and include other CMake modules from a given url. it's giving "grab it from the internet and just use it" 😌🌈

include_url

downloads a file from a given url and includes it:

include_url(<url>                 # Url to be downloaded
   [DESTINATION <destination>]    # Where the file will be saved
   [EXPECTED_HASH <ALGO=value>]   # Verify downloaded file's hash
   [EXPECTED_MD5 <sum>]           # Short-hand for "EXPECTED_HASH MD5=sum"
   [DOWNLOAD_ONCE]                # Download the file only once
   [DOWNLOAD_ALWAYS]              # Download the file every time
   [OPTIONAL]                     # Do not fail file cannot be included
   [RESULT_VARIABLE <variable>]   # The local path for the file included
   [RETRIES <retries>]            # Try download <retries> times (default 3)
   [QUIET]                        # Don't print anything
  #--Download arguments-----------
   [INACTIVITY_TIMEOUT <timeout>] # Timeout after <timeout> seconds of inactivity
   [TIMEOUT <timeout>]            # Timeout after <timeout> seconds
   [STATUS <status>]              # Download status variable
   [LOG <log>]                    # Download log variable
   [SHOW_PROGRESS]                # Show download progress
   [TLS_VERIFY <on|off>]          # Check certificates
   [TLS_CAINFO <file>]            # Custom Certificate Authority file
  #--Include arguments------------
   [NO_POLICY_SCOPE]              # Do not manage a new policy entry
   )

the include_url macro downloads a file from a given url and includes it. it works both in -P script mode and when configuring a CMakeLists.txt file. versatile queen πŸ‘‘

if DESTINATION is specified, the file is saved at the given location β€” with the original file name, if <destination> is a directory, or with the given file name, if <destination> is a file name. so you get to choose the vibe πŸŽ€

the arguments EXPECTED_HASH, EXPECTED_MD5 are used to ensure that the file included is the one expected. if the <url> is a local file (i.e. starts with file://) the hash check is performed also on the file converted to the non-native end-of-line style. see the documentation of the file() command for further information about these arguments. trust but verify, bestie πŸ”

if the DOWNLOAD_ONCE option is specified, the file is not downloaded if the file already exists and the hash is correct. if the DOWNLOAD_ALWAYS option is specified, the file is downloaded at every CMake execution, and an error is raised on failure. if none of these two options is specified, the default behaviour is to try to download the file at every CMake execution, but no error is raised if the download fails if a version of the file already exists. this is useful when CMake should try to update the file to the latest version, before including it. so like, "try to refresh but don't crash if wifi said no" πŸ“ΆπŸ˜­

if the OPTIONAL option is specified, no error will be caused if for any reason the file cannot be downloaded or included. if RESULT_VARIABLE is given, the variable will be set to the full filename which has been downloaded and included or NOTFOUND if it failed. see the documentation of the file() command for further information about these arguments 🫢

if the RETRIES option is specified, the download will be tried. if the QUIET option is specified, the command will emit no output. 🀫

the arguments INACTIVITY_TIMEOUT, TIMEOUT, STATUS, LOG, SHOW_PROGRESS, TLS_VERIFY, and TLS_CAINFO are passed to the file(DOWNLOAD) command. see the documentation of the file() command for a detailed description of these arguments ✨

the argument NO_POLICY_SCOPE is passed to the include() command. see the documentation of the include() and cmake_policy() commands for a detailed description of this argument πŸ’…


πŸ’œ ReplaceImportedTargets

adds the replace_imported_targets() command that's useful to replace paths with imported targets in link variables (like <FOO>_LIBRARIES) and targets. glow-up for your link variables, periodt πŸ’…βœ¨

replace_imported_targets

replace imported targets in a list of and targets and paths:

replace_imported_targets(<var> [target [target [...]]])

okay so literally every path in var that matches one of the targets gets swapped out for the target it corresponds to πŸ’… and while it's doing that, it also yeets the relative optimized and debug keywords, because those were never the vibe.

And for each target that actually exists in var, it goes digging through these properties looking for imported locations of targets, and if they're set, it replaces them the exact same way:

  • IMPORTED_LINK_DEPENDENT_LIBRARIES
  • IMPORTED_LINK_DEPENDENT_LIBRARIES_<CONFIG>
  • IMPORTED_LINK_INTERFACE_LIBRARIES
  • IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>
  • INTERFACE_LINK_LIBRARIES
  • LINK_INTERFACE_LIBRARIES
  • LINK_INTERFACE_LIBRARIES_<CONFIG>
  • LINK_LIBRARIES

✨ StandardFindModule ✨

bestie the whole mission here is: try to find a package using a cmake config file, or pkgconfig 🫢 that's it, that's the assignment.

standard_find_module(<name>
                     <pkgconfig name>
                     [NOT_REQUIRED]
                     [QUIET]
                     [SKIP_CMAKE_CONFIG]
                     [SKIP_PKG_CONFIG]
                     [TARGET <target>]
                     [REPLACE_TARGETS <target> [...]]
)

If the package gets found, these variables pop into existence (where possible, no promises πŸ‘‘):

  • <name>_FOUND β€” System has <name>
  • <name>_INCLUDE_DIRS β€” <name> include directory
  • <name>_LIBRARIES β€” <name> libraries
  • <name>_DEFINITIONS β€” Additional compiler flags for <name>
  • <name>_VERSION β€” <name> version
  • <name>_MAJOR_VERSION β€” <name> major version
  • <name>_MINOR_VERSION β€” <name> minor version
  • <name>_PATCH_VERSION β€” <name> patch version
  • <name>_TWEAK_VERSION β€” <name> tweak version
  • <name>_VERSION_COUNT β€” Number of version components, 0 to 4

And for every library that actually needs to be linked (i.e. -llib), it makes these:

  • <name>_<LIB>_LIBRARY_RELEASE (cached, advanced)
  • <name>_<LIB>_LIBRARY_DEBUG (cached, advanced, and empty by default)
  • <name>_<LIB>_LIBRARY
  • <name>_<LIB>_LIBRARY_FOUND

In a FindXXX.cmake module you can drop this macro right at the beginning, main character energy fr fr. The NOT_REQUIRED can be added so it doesn't fail if the package wasn't found, but pkg-config is installed. The QUIET argument hides the output from find_package_handle_standard_args β€” quiet, demure, mindful πŸŽ€ If <name>_FOUND is FALSE at the end, you can go do more β€œcustom” searches (for windows, etc.).

If SKIP_CMAKE_CONFIG or SKIP_PKG_CONFIG are set, that relative step just gets skipped, no thoughts.

If TARGET is specified, then in pkg-config mode an imported target gets created using the first library returned by pkg-config as the imported location.

REPLACE_TARGETS is for handing over a list of imported targets that will be detected inside variables and target properties, and then replaced with the corresponding target. slay.

If one of STANDARD_FIND_MODULE_USE_IMPORTED_TARGET or STANDARD_FIND_MODULE_USE_IMPORTED_TARGET_<name> are enabled, and a TARGET is specified, then the content of the <name>_LIBRARIES variable gets replaced with the imported target. πŸ’…

And if one of the variables STANDARD_FIND_MODULE_DEBUG or STANDARD_FIND_MODULE_DEBUG_<name> is enabled, it prints more useful debug output β€” perfect for when you're like "why is this not working 😭"


πŸŽ€ PACKAGING HELPER MODULES πŸŽ€

InstallBasicPackageFiles

A helper module to make your package easier to be found by other projects. iconic behaviour, honestly ✨

install_basic_package_files

Create and install a basic version of cmake config files for your project:

install_basic_package_files(<Name>
                            COMPATIBILITY <compatibility>
                            [VERSION <version>]
                            [ARCH_INDEPENDENT]
                            [NO_EXPORT | EXPORT <export>] # (default = "EXPORT <Name>")
                            [NO_SET_AND_CHECK_MACRO]
                            [NO_CHECK_REQUIRED_COMPONENTS_MACRO]
                            [VARS_PREFIX <prefix>] # (default = "<Name>")
                            [EXPORT_DESTINATION <destination>]
                            [INSTALL_DESTINATION <destination>]
                            [NAMESPACE <namespace>] # (default = "<Name>::")
                            [EXTRA_PATH_VARS_SUFFIX path1 [path2 ...]]
                            [CONFIG_TEMPLATE <file>]
                            [UPPERCASE_FILENAMES | LOWERCASE_FILENAMES]
                            [DEPENDENCIES <dependency1> "<dependency2> [...]" ...]
                            [PRIVATE_DEPENDENCIES <dependency1> "<dependency2> [...]" ...]
                            [INCLUDE_FILE <file> | INCLUDE_CONTENT <content>]
                            [COMPONENT <component>] # (default = "<Name>")
                           )

Depending on whether you set UPPERCASE_FILENAMES or LOWERCASE_FILENAMES, this function generates 3 whole files:

  • <Name>ConfigVersion.cmake or <name>-config-version.cmake
  • <Name>Config.cmake or <name>-config.cmake
  • <Name>Targets.cmake or <name>-targets.cmake

If you set neither UPPERCASE_FILENAMES nor LOWERCASE_FILENAMES, it goes looking for a <Name>Config.cmake.in or <name>-config.cmake.in file, and picks whichever convention matches the file it found. And if it found no file at all? then the uppercase convention is used, periodt.

The DEPENDENCIES argument sets a list of dependencies that get searched using the find_dependency() command from the CMakeFindDependencyMacro module. Dependencies can be followed by any of the possible find_dependency() arguments. In that case, all the arguments must be specified inside double quotes (e.g. "<dependency> 1.0.0 EXACT", or "<dependency> CONFIG"). The PRIVATE_DEPENDENCIES argument is like DEPENDENCIES, except these dependencies are only included when BUILD_SHARED_LIBS is OFF. And heads up bestie: if a library is declared STATIC, OBJECT or INTERFACE, and they link to some dependency, those should be added using the DEPENDENCIES argument, because PRIVATE_DEPENDENCIES would only work when BUILD_SHARED_LIBS is disabled. πŸ¦‹

When you're using a custom template file, the @PACKAGE_DEPENDENCIES@ string gets replaced with the code that checks for the dependencies specified by these two arguments.

If the ARCH_INDEPENDENT option is enabled, the installed package version will be considered compatible even if it was built for a different architecture than the requested one. architecture? never heard of her πŸ’…

Each file is generated twice β€” one for the build directory and one for the installation directory. The INSTALL_DESTINATION argument can be passed to install the files somewhere other than the default spot (${CMAKE_INSTALL_DATADIR}/cmake/${Name} if the ARCH_INDEPENDENT option is enabled, ${CMAKE_INSTALL_LIBDIR}/cmake/${Name} otherwise). The EXPORT_DESTINATION argument can be passed to generate the files in the build tree somewhere other than the default (CMAKE_BINARY_DIR). And if it's a relative path, it's considered relative to the CMAKE_CURRENT_BINARY_DIR directory.

The build directory gets exported to the CMake user package registry if the build option CMAKE_EXPORT_PACKAGE_REGISTRY is set.

The <Name>ConfigVersion.cmake file is generated using write_basic_package_version_file(). The VERSION, COMPATIBILITY, and ARCH_INDEPENDENT arguments are passed straight to that function.

VERSION shall be in the form <major>[.<minor>[.<patch>[.<tweak>]]]]. If no VERSION is given, the PROJECT_VERSION variable is used. And if that hasn't been set either β€” it errors out 😭 The VERSION argument is also used to replace the @PACKAGE_VERSION@ string in the configuration file.

COMPATIBILITY shall be any of the options accepted by the write_basic_package_version_file() command (AnyNewerVersion, SameMajorVersion, SameMinorVersion [CMake 3.11], or ExactVersion). Those options are explained in the write_basic_package_version_file() command documentation. And if your project has more elaborate version matching rules, you'll need to write your own custom ConfigVersion.cmake file instead of using this macro. no shortcuts bestie πŸ™ˆ

The <Name>Config.cmake file is generated using configure_package_config_file(). The NO_SET_AND_CHECK_MACRO, NO_CHECK_REQUIRED_COMPONENTS_MACRO, and arguments are passed to this function.

By default install_basic_package_files() also generates the two helper macros set_and_check() and check_required_components() into the <Name>Config.cmake file. set_and_check() should be used instead of the normal set() command for setting directories and file locations. On top of setting the variable, it also checks that the referenced file or directory actually exists and fails with a FATAL_ERROR otherwise β€” so dramatic, so necessary πŸ’€ This makes sure the <Name>Config.cmake file you created doesn't contain wrong references. When you use NO_SET_AND_CHECK_MACRO, this macro is not generated into the <Name>Config.cmake file.

By default, install_basic_package_files() appends a call to check_required_components(<Name>) in the <Name>Config.cmake file if the package supports components. This macro checks whether all requested, non-optional components have been found, and if they haven't, it sets the <Name>_FOUND variable to FALSE, so the package is considered not found. It does that by testing the <Name>_<Component>_FOUND variables for all requested required components. When you use the NO_CHECK_REQUIRED_COMPONENTS_MACRO option, this macro is not generated into the <Name>Config.cmake file.

Finally β€” and this is the cute part β€” the files in the build directory and the install directory are exactly the same ✨

See the documentation of CMakePackageConfigHelpers module for further information and references therein.

If the CONFIG_TEMPLATE argument is passed, that specified file is used as the template for generating the configuration file. Otherwise this module expects to find a <Name>Config.cmake.in or <name>-config.cmake.in file in the current source directory. If the file doesn't exist, a very basic file is created. we improvise 🫢

A set of variables gets checked and passed to configure_package_config_file() as PATH_VARS. For each of the SUFFIX considered, if one of these variables:

<VARS_PREFIX>_(BUILD|INSTALL)_<SUFFIX>
(BUILD|INSTALL)_<VARS_PREFIX>_<SUFFIX>

is defined, then the <VARS_PREFIX>_<SUFFIX> variable will be defined before configuring the package. To use that variable in the config file, you have to add a line:

set_and_check(<VARS_PREFIX>_<SUFFIX> "@PACKAGE_<VARS_PREFIX>_<SUFFIX>@")

if the path must exist, or just:

set(<VARS_PREFIX>_<SUFFIX> "@PACKAGE_<VARS_PREFIX>_<SUFFIX>@")

if the path could be missing.

These variables will have different values depending on whether you're using the package from the build tree or from the install directory. And also these files will contain only relative paths, meaning you can move the whole installation and the CMake files will still work. portable queen behaviour πŸ‘‘

Default PATH_VARS suffixes are:

...and here's the rest of the path-vars roster, bestie β€” every single one, no skips πŸ’–

BINDIR          BIN_DIR
SBINDIR         SBIN_DIR
LIBEXECDIR      LIBEXEC_DIR
SYSCONFDIR      SYSCONF_DIR
SHAREDSTATEDIR  SHAREDSTATE_DIR
LOCALSTATEDIR   LOCALSTATE_DIR
LIBDIR          LIB_DIR
INCLUDEDIR      INCLUDE_DIR
OLDINCLUDEDIR   OLDINCLUDE_DIR
DATAROOTDIR     DATAROOT_DIR
DATADIR         DATA_DIR
INFODIR         INFO_DIR
LOCALEDIR       LOCALE_DIR
MANDIR          MAN_DIR
DOCDIR          DOC_DIR

And if that lineup isn't enough for you (iconic behaviour honestly), you can pile on more suffixes using the EXTRA_PATH_VARS_SUFFIX argument. Go off ✨

So like, <Name>Targets.cmake gets generated with export(EXPORT) in the build tree and install(EXPORT) over in the installation directory. The targets get exported using whatever you passed as the NAMESPACE argument, and that whole export can be handed over with the EXPORT argument. If you're not using an export at all (say, for a CMake script library), just pass NO_EXPORT and we move on 🫢

Now β€” if you pass the INCLUDE_FILE argument, the content of that file (which might contain @variables@, cute) gets appended to the generated <Name>Config.cmake file. Same energy with INCLUDE_CONTENT: whatever content you specified (again, may contain @variables@) gets appended to the generated <Name>Config.cmake. And when a CONFIG_TEMPLATE is passed, or a <Name>ConfigVersion.cmake.in or a <name>-config-version.cmake.in file is just there, these 2 arguments get used to replace the @INCLUDED_CONTENT@ string in that file. Why do you care? Because it lets you inject custom code into that file β€” super useful for stuff like setting extra variables that downstream projects will load. Very giving-custom-code-to-the-people of you πŸ’…

Heads up though: anything you put in INCLUDE_FILE or INCLUDE_CONTENT cannot reference any of the PATH_VARS, because that content is not expanded by configure_package_config_file(). It's giving unexpanded, bestie 😭

And if you pass the COMPONENT argument, it gets forwarded to the install() commands. Otherwise, <Name> is used. Periodt.


AddUninstallTarget πŸ’€

Adds the β€œuninstall” target to your project, which is honestly such a mood:

include(AddUninstallTarget)

This will create a file cmake_uninstall.cmake in the build directory and add a custom target uninstall (or UNINSTALL on Visual Studio and Xcode, because of course they have to be different πŸ™ˆ) that will remove the files installed by your package β€” using install_manifest.txt, bestie. It's the "nvm actually take it back" target. See also https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake πŸ”₯

The AddUninstallTarget module must be included in your main CMakeLists.txt. If you include it in a subdirectory it does absolutely nothing β€” which is on purpose, so you can safely drop it in your main CMakeLists.txt and then pull your project in with add_subdirectory (like when you're using it with FetchContent). Safe and chill πŸ¦‹

And if the uninstall target already exists? The module just does nothing. No drama, no double-targets, we love a peaceful coexistence ✨


AddInstallRPATHSupport 🌈

Adds support for RPATH during installation, for the project and the targets. Let's get into it:

  • add_install_rpath_support β€” adds support to RPATH during installation to the project.
  • target_append_install_rpath β€” adds extra paths to RPATH for one specific target, i.e. main character treatment:
target_append_install_rpath(<target>
                            <INSTALL_DESTINATION destination>
                            [LIB_DIRS dir [dir]]
                            [DEPENDS condition [condition]])

Arguments, bestie:

  • INSTALL_DESTINATION β€” the path where the target will be installed.
  • LIB_DIRS β€” a list of directories to be added to the RPATH. These directories get added "relative" with respect to the INSTALL_DESTINATION.
  • DEPENDS β€” a list of conditions that should be TRUE to enable RPATH. Like, for example, FOO; NOT BAR.

πŸ”₯ SUPERBUILD HELPER MODULES πŸ”₯

FindOrBuildPackage πŸŽ€

Searches for a package and builds it if it can't be found. Find-or-build, the ultimate "if you can't find it, make it yourself" energy. Very DIY queen.

find_or_build_package

Searches for a package and builds it if it cannot be found:

find_or_build_package(<PackageName> <find_package_args>)

This module tries to locate a package using find_package(). If the package can't be found, it tries to build it, by including Build<package>. That file should contain the instructions to download and build the package (for example using ExternalProject). So like, the whole "fine, I'll do it myself" arc πŸ’…

The arguments you pass to the function get passed straight to the find_package() command. No middleman.

FIXME Figure out how to handle the REQUIRED and QUIET arguments. Not me exposing the to-do in the manpage, but go off, transparency is hot ✨

If the package was found, you can disable the USE_SYSTEM_<PackageName> cached variable to force CMake to build the package instead of using the one it found on the system. And to automatically force CMake to build all the packages that are also found on the system, enable the YCM_DISABLE_SYSTEM_PACKAGES cache variable. One variable, total control, iconic πŸ‘‘

This function sets these variables:

HAVE_SYSTEM_<PackageName> # The package was found on the system
HAVE_<PackageName> # The package is available

You should use the latest one to check if a package is available, instead of checking with <PackageName>_FOUND. Fr fr, that's the move. For example:

FIXME Check uppercase (${_PKG}) and lowercase (${_pkg}) variables
find_or_build_package(Foo)
if(HAVE_Foo)
  ...
endif()

CMAKE_DISABLE_BUILD_PACKAGE_<PackageName>

With this variable, building a package is explicitly forbidden. So therefore, if the package cannot be found on the system, HAVE_<PackageName> will be set to false. Straight up "no, we are NOT building that one" 🚫


YCMEPHelper 🧚

A helper for ExternalProject. Look at this signature, it's giving full wardrobe:

ycm_ep_helper(<name>
  [DOCS]
  [TYPE <type>]
  [STYLE <style>]
  [COMPONENT <component>] (default = "external")
  [FOLDER <folder> (default = "<component>")
  [REPOSITORY <repo>]
  [EXCLUDE_FROM_ALL <0|1>]
 #--Git and Hg only arguments-----------
  [TAG <tag>]
 #--Svn only arguments-----------
  [REVISION <revision>]
  [USERNAME <username>]
  [PASSWORD <password>]
  [TRUST_CERT <0|1>]
 #--CMake arguments---------
  [CMAKE_ARGS]
  [CMAKE_CACHE_ARGS]
  [CMAKE_CACHE_DEFAULT_ARGS]
  [DEPENDS]
  [DOWNLOAD_COMMAND]
  [UPDATE_COMMAND]
  [PATCH_COMMAND]
  [CONFIGURE_COMMAND]
  [BUILD_COMMAND]
  [INSTALL_COMMAND]
  [TEST_COMMAND]
  [CLEAN_COMMAND] (not in ExternalProject)
  [TEST_AFTER_INSTALL]
  [TEST_BEFORE_INSTALL]
  [TEST_EXCLUDE_FROM_MAIN]
  )

And then there's the variable squad that comes with it:

  • YCM_BOOTSTRAP()
  • NON_INTERACTIVE_BUILD
  • YCM_BOOTSTRAP_BASE_ADDRESS
  • YCM_SKIP_HASH_CHECK
  • YCM_BOOTSTRAP_VERBOSE
  • YCM_EP_INSTALL_DIR
  • YCM_EP_ADDITIONAL_CMAKE_ARGS
  • YCM_<COMPONENT>_COLOR
  • YCM_<COMPONENT>_BGCOLOR
  • YCM_<COMPONENT>_NODECOLOR
TODO Add variable YCM_INSTALL_PREFIX. Not yet, bestie, not yet 😭

StyleBITBUCKET

StyleGITHUB

StyleGITLAB_ROBOTOLOGY

StyleGNOME

StyleKDE

StyleLOCAL

StyleNONE

StyleSOURCEFORGE

All the style presets, all in a row like a little lineup of outfits 🌸


πŸ’– FIND PACKAGE MODULES πŸ’–

Findassimp

Find the Open Asset Importer Library (assimp).

Input variables

The following variables may be set to influence this module's behavior:

  • ASSIMP_VERBOSE β€” to output a detailed log of this module.

Imported Targets

This module defines the IMPORTED target assimp::assimp for the library assimp.

Result Variables

This module defines the following variables:

  • assimp_FOUND β€” true if assimp has been found and can be used
  • ASSIMP_ROOT_DIR β€” the root directory where the installation can be found
  • ASSIMP_INCLUDE_DIRS β€” include directories for assimp
  • ASSIMP_LIBRARIES β€” libraries to link against assimp
  • ASSIMP_LIBRARY_DIRS β€” link directories
  • ASSIMP_VERSION β€” ASSIMP version
  • ASSIMP_VERSION_MAJOR β€” ASSIMP major version
  • ASSIMP_VERSION_MINOR β€” ASSIMP minor version
  • ASSIMP_VERSION_REVISION β€” ASSIMP revision version

FindACE

Try to find the ACE library.

Targets set:

ACE::ACE (links the ACE library)
ACE::ACE_INLINE (INTERFACE library for ACE inlines only)

Variables set:

ACE_FOUND           - System has ACE library
ACE_LIBRARIES       - ACE link libraries
ACE_INCLUDE_DIRS    - ACE library include directories
ACE_DEFINITIONS     - Additional compiler flags for ACE library
ACE_VERSION         - ACE library version
ACE_MAJOR_VERSION   - ACE major version
ACE_MINOR_VERSION   - ACE minor version
ACE_BETA_VERSION    - ACE beta version

Options variables:

ACE_INLINE (default ON)
  The ACE::ACE target passes __ACE_INLINE__ by default, this can be
  changed by setting ACE_INLINE = OFF.
  The ACE_DEFINITIONS variable is also influenced by the same option.

FindAtlas

Find the Atlas (and Lapack) libraries. That's the whole vibe 🌈


FindCFW2CANAPI

Created:

CFW2CANAPI_INC_DIRS   - Directories to include to use esdcan api
CFW2CANAPI_LIB        - Default library to link against to use the esdcan API
CFF2CANAPI_FOUND      - If false, don't try to use esdcan API

FindDRAGONFLYAPI

Created:

DRAGONFLYAPI_INC_DIRS   - Directories to include to use dragonfly API
DRAGONFLYAPI_LIB        - Default library to link against to use the dragonfly API
DRAGONFLYAPI_FOUND      - If false, don't try to use dragonfly API

FindESDCANAPI

Created:

ESDCANAPI_INC_DIRS   - Directories to include to use esdcan api
ESDCANAPI_LIB        - Default library to link against to use the esdcan API
ESDCANAPI_FOUND      - If false, don't try to use esdcan API

FindFreenect

Try to find the Freenect library. Once done, this will define the following variables:

Freenect_FOUND         - System has Freenect
Freenect_INCLUDE_DIRS  - Freenect include directory
Freenect_LIBRARIES     - Freenect libraries
Freenect_DEFINITIONS   - Additional compiler flags for Freenect
Freenect_VERSION       - Freenect version
Freenect_MAJOR_VERSION - Freenect major version
Freenect_MINOR_VERSION - Freenect minor version
Freenect_PATCH_VERSION - Freenect patch version

FindFTDI

Try to find ftdi. Once done this will define:

FTDI_FOUND - system has ftdi
FTDI_INCLUDE_DIR - ~ the ftdi include directory
FTDI_LIBRARY - Link these to use ftdi

FindFuse

Try to find the Fuse library. Once done this will define the following variables:

Fuse_FOUND         - System has Fuse
Fuse_INCLUDE_DIRS  - Fuse include directory
Fuse_LIBRARIES     - Fuse libraries
Fuse_DEFINITIONS   - Additional compiler flags for Fuse
Fuse_VERSION       - Fuse version
Fuse_MAJOR_VERSION - Fuse major version
Fuse_MINOR_VERSION - Fuse minor version
Fuse_PATCH_VERSION - Fuse patch version
Fuse_TWEAK_VERSION - Fuse tweak version

FindGLFW3

Find the GLFW3 framework.

IMPORTED Targets

This module defines the IMPORTED target GLFW3::GLFW3, if GLFW3 has been found.

Result Variables

This module defines the following variables:

  • GLFW3_INCLUDE_DIRS β€” include directories for GLFW3 🫢
  • GLFW3_LIBRARIES β€” libraries to link against GLFW3 πŸ”—
  • GLFW3_FOUND β€” true if GLFW3 has been found and can be used πŸ’–

Environment Variables

If the library is not found on system paths, the GLFW3_ROOT environment variable can be used to locate the library. it's giving "where did you put it bestie" energy 🌸


FindGLM

Find the OpenGL Mathematics (glm) ✨

Input variables

The following variables may be set to influence this module's behavior:

  • GLM_VERBOSE β€” to output a detailed log of this module. (yes girl, give us the receipts πŸ’…)

Imported Targets

This module defines the IMPORTED target glm for the library glm.

Result Variables

This module defines the following variables:

  • GLM_FOUND β€” true if assimp has been found and can be used
  • GLM_INCLUDE_DIRS β€” include directories for assimp
  • GLM_VERSION β€” GLM version
  • GLM_VERSION_MAJOR β€” GLM major version
  • GLM_VERSION_MINOR β€” GLM minor version
  • GLM_VERSION_PATCH β€” GLM patch version
okay so lowkey notice that GLM_FOUND and GLM_INCLUDE_DIRS both say assimp and not glm β€” that's literally what the page says, so we're keeping it exactly as written, no editing the lore fr fr πŸ™ˆ

FindGooCanvas

Try to find the GooCanvas library. Once done this will define the following variables:

GooCanvas_FOUND         - System has GooCanvas
GooCanvas_INCLUDE_DIRS  - GooCanvas include directory
GooCanvas_LIBRARIES     - GooCanvas libraries
GooCanvas_DEFINITIONS   - Additional compiler flags for GooCanvas
GooCanvas_VERSION       - GooCanvas version
GooCanvas_MAJOR_VERSION - GooCanvas major version
GooCanvas_MINOR_VERSION - GooCanvas minor version
GooCanvas_PATCH_VERSION - GooCanvas patch version
GooCanvas_TWEAK_VERSION - GooCanvas tweak version

If the library is found, the imported target GooCanvas::goocanvas is created. πŸŽ€


FindGooCanvasMM

Try to find the GooCanvasMM library. Once done this will define the following variables:

GooCanvasMM_FOUND         - System has GooCanvasMM
GooCanvasMM_INCLUDE_DIRS  - GooCanvasMM include directory
GooCanvasMM_LIBRARIES     - GooCanvasMM libraries
GooCanvasMM_DEFINITIONS   - Additional compiler flags for GooCanvasMM
GooCanvasMM_VERSION       - GooCanvasMM version
GooCanvasMM_MAJOR_VERSION - GooCanvasMM major version
GooCanvasMM_MINOR_VERSION - GooCanvasMM minor version
GooCanvasMM_PATCH_VERSION - GooCanvasMM patch version
GooCanvasMM_TWEAK_VERSION - GooCanvasMM tweak version

If the library is found, the imported target GooCanvasMM::goocanvasmm is created. ✨


FindGSL

Try to find GSL library Once run this will define: 🌈

GSL_FOUND
GSL_INCLUDE_DIR
GSL_INCLUDE_DIRS
GSL_LIBRARIES
GSL_LINK_DIRECTORIES
GSLCBLAS_LIBRARY
GSL_LIBRARY

FindGtkDatabox

Try to find the GtkDatabox library. Once done this will define the following variables:

GtkDatabox_FOUND         - System has GtkDatabox
GtkDatabox_INCLUDE_DIRS  - GtkDatabox include directory
GtkDatabox_LIBRARIES     - GtkDatabox libraries
GtkDatabox_DEFINITIONS   - Additional compiler flags for GtkDatabox
GtkDatabox_VERSION       - GtkDatabox version
GtkDatabox_MAJOR_VERSION - GtkDatabox major version
GtkDatabox_MINOR_VERSION - GtkDatabox minor version
GtkDatabox_PATCH_VERSION - GtkDatabox patch version
GtkDatabox_TWEAK_VERSION - GtkDatabox tweak version

If the library is found, the imported target GtkDatabox::gtkdatabox is created. πŸ’œ


FindGtkDataboxMM

Try to find the GtkDataboxMM library. Once done this will define the following variables:

GtkDataboxMM_FOUND         - System has GtkDataboxMM
GtkDataboxMM_INCLUDE_DIRS  - GtkDataboxMM include directory
GtkDataboxMM_LIBRARIES     - GtkDataboxMM libraries
GtkDataboxMM_DEFINITIONS   - Additional compiler flags for GtkDataboxMM
GtkDataboxMM_VERSION       - GtkDataboxMM version
GtkDataboxMM_MAJOR_VERSION - GtkDataboxMM major version
GtkDataboxMM_MINOR_VERSION - GtkDataboxMM minor version
GtkDataboxMM_PATCH_VERSION - GtkDataboxMM patch version
GtkDataboxMM_TWEAK_VERSION - GtkDataboxMM tweak version

If the library is found, the imported target GtkDataboxMM::gtkdataboxmm is created. πŸ¦‹


FindI2C

Find the I2C device library. πŸ“

Once done this will define the following variables:

I2C_INCLUDE_DIRS    - I2C include directory
I2C_LIBRARIES       - I2C libraries
I2C_FOUND           - if false, you cannot build anything that requires I2C
not to be dramatic but if I2C_FOUND is false, you literally cannot build anything that requires I2C. that's not a vibe, that's a wall. 😭

FindIPOPT

Try to locate the IPOPT library πŸ‘‘

On non Windows systems, use pkg-config to try to locate the library, if this fails then try to locate the library in the directory pointed by the IPOPT_DIR environment variable.

On Windows systems, just try to find the library using the IPOPT_DIR environment variable.

Create the following variables:

IPOPT_INCLUDE_DIRS - Directories to include to use IPOPT
IPOPT_LIBRARIES    - Default library to link against to use IPOPT
IPOPT_DEFINITIONS  - Flags to be added to linker's options
IPOPT_LINK_FLAGS   - Flags to be added to linker's options
IPOPT_FOUND        - If false, don't try to use IPOPT
yes bestie IPOPT_DEFINITIONS and IPOPT_LINK_FLAGS have the exact same description on the page. iconic. we keep it. πŸ’…

FindIPP

Try to find the IPP library.

that's it. that's the whole module. short and sweet, main character minimalism. ✨


FindLibdc1394

Try to find the libdc1394 library. Once done this will define the following variables:

Libdc1394_FOUND         - System has libdc1394
Libdc1394_INCLUDE_DIRS  - libdc1394 include directory
Libdc1394_LIBRARIES     - libdc1394 libraries
Libdc1394_DEFINITIONS   - Additional compiler flags for libdc1394
Libdc1394_VERSION       - libdc1394 version
Libdc1394_MAJOR_VERSION - libdc1394 major version
Libdc1394_MINOR_VERSION - libdc1394 minor version
Libdc1394_PATCH_VERSION - libdc1394 patch version

no tweak version here girl, we keep it exactly as it came πŸŽ€


FindLibedit

Try to find NetBSD Editline library (libedit), a Berkeley-style licensed command line editor library provides generic line editing, history, and tokenization functions, similar to those found in GNU Readline. Once done this will define the following variables:

Libedit_FOUND         - System has Editline library
Libedit_INCLUDE_DIRS  - Editline library include directory
Libedit_LIBRARIES     - Editline library libraries
Libedit_DEFINITIONS   - Additional compiler flags for Editline library
Libedit_VERSION       - Editline library version
Libedit_MAJOR_VERSION - Editline library major version
Libedit_MINOR_VERSION - Editline library minor version

Environment variables used to locate the Editline library:

READLINE_DIR - Libedit root directory

Cached variables used to locate the NetBSD Editline library:

Libedit_INCLUDE_DIR - the Libedit include directory
Libedit_LIBRARY_RELEASE - NetBSD Editline library (release)
Libedit_LIBRARY_DEBUG - NetBSD Editline library  (debug)
the double space in Libedit_LIBRARY_DEBUG - NetBSD Editline library (debug)? yeah that's in there. not me noticing it. πŸ™ˆ

FindLibOVR

Find the LibOVR library in Oculus Rift SDK. 🌈

IMPORTED Targets

This module defines the following IMPORTED targets if LibOVR has been found:

LibOVR::OVRKernel
LibOVR::OVR

Result Variables

This module defines the following variables:

LibOVR_FOUND                   - System has LibOVR
LibOVR_VERSION                 - LibOVR version
LibOVR_VERSION_PRODUCT         - LibOVR product version
LibOVR_VERSION_MAJOR           - LibOVR major version
LibOVR_VERSION_MINOR           - LibOVR minor version
LibOVR_VERSION_PATCH           - LibOVR patch version
LibOVR_VERSION_BUILD           - LibOVR build number
LibOVR_VERSION_STRING          - LibOVR version
LibOVR_VERSION_DETAILED_STRING - LibOVR version (including build number)
LibOVR_INCLUDE_DIRS            - Include directories for LibOVR
LibOVR_LIBRARIES               - libraries to link against LibOVR

FindLibusb1

Try to find the libusb-1 library. Once done this will define the following variables:

Libusb1_FOUND         - System has libusb-1
Libusb1_INCLUDE_DIRS  - libusb-1 include directory
Libusb1_LIBRARIES     - libusb-1 libraries
Libusb1_DEFINITIONS   - Additional compiler flags for libusb-1
Libusb1_VERSION       - libusb-1 version
Libusb1_MAJOR_VERSION - libusb-1 major version
Libusb1_MINOR_VERSION - libusb-1 minor version
Libusb1_PATCH_VERSION - libusb-1 patch version

FindLibv4l2

Try to find the libv4l2 library. Once done this will define the following variables:

Libv4l2_FOUND         - System has libv4l2
Libv4l2_INCLUDE_DIRS  - libv4l2 include directory
Libv4l2_LIBRARIES     - libv4l2 libraries
Libv4l2_DEFINITIONS   - Additional compiler flags for libv4l2
Libv4l2_VERSION       - libv4l2 version
Libv4l2_MAJOR_VERSION - libv4l2 major version
Libv4l2_MINOR_VERSION - libv4l2 minor version
Libv4l2_PATCH_VERSION - libv4l2 patch version
Libv4l2_TWEAK_VERSION - libv4l2 tweak version

FindLibv4lconvert

Try to find the libv4lconvert library. Once done this will define the following variables:

Libv4lconvert_FOUND         - System has libv4lconvert
Libv4lconvert_INCLUDE_DIRS  - libv4lconvert include directory
Libv4lconvert_LIBRARIES     - libv4lconvert libraries
Libv4lconvert_DEFINITIONS   - Additional compiler flags for libv4lconvert
Libv4lconvert_VERSION       - libv4lconvert version
Libv4lconvert_MAJOR_VERSION - libv4lconvert major version
Libv4lconvert_MINOR_VERSION - libv4lconvert minor version
Libv4lconvert_PATCH_VERSION - libv4lconvert patch version
Libv4lconvert_TWEAK_VERSION - libv4lconvert tweak version

FindNVIDIACg

Try to find NVIDIACg libraries πŸ’–

that's the whole thing. no variables listed, no targets, just vibes and a mission.


FindODE

Options:

ODE_DOUBLE_PRECISION  -use double precision ode libraries
ODE_STATIC            -link against static libraries
keeping those exactly as they are bestie: -use and -link, hyphens and all. no cap. ✨

On exit create the following variables:

ODE_INCLUDE_DIRS  - Directories to include to use ODE
ODE_LIBRARIES     - Default library to link against to use ODE
ODE_FOUND         - If false, library not found

FindOpenCV

Find OpenCV β€” variables set:

OpenCV_FOUND
OpenCV_LIBRARIES
OpenCV_INCLUDE_DIRS

This script is a combination from multiple sources that use different variable names; the names are reconciled at the end of the script. πŸ¦‹

Todo

Check if this module is still needed with recent CMake releases.

Todo

Check if the license is correct


FindOpenGL

Wrap kitware's original FindOpenGL. Standardize variables. πŸŽ€

In windows require you set OpenGL_DIR

Set:

OpenGL_FOUND
OpenGL_LIBRARIES
OpenGL_INCLUDE_DIRS

Todo

Check if this module is still needed with recent CMake releases.


FindOpenNI

Try to find the OpenNI library. Once done this will define the following variables:

...and here's the rest of that variable roster, bestie, no skips:

  • OpenNI_FOUND β€” system has OpenNI, periodt πŸ’…
  • OpenNI_INCLUDE_DIRS β€” the OpenNI include directory
  • OpenNI_LIBRARIES β€” the OpenNI libraries
  • OpenNI_DEFINITIONS β€” extra compiler flags for OpenNI
  • OpenNI_VERSION β€” the OpenNI version
  • OpenNI_MAJOR_VERSION β€” OpenNI major version
  • OpenNI_MINOR_VERSION β€” OpenNI minor version
  • OpenNI_PATCH_VERSION β€” OpenNI patch version

πŸ¦‹ FindPLXCANAPI

Created:

  • PLXCANAPI_INC_DIRS β€” directories to include to use esdcan api
  • PLXCANAPI_LIB β€” default library to link against to use the esdcan API
  • PLXCANAPI_FOUND β€” if false, don't try to use esdcan API (she said what she said)

🎧 FindPortAudio

Try to find the PortAudio library. That's it, that's the whole vibe 🌸

🧺 FindqpOASES

Try to find the qpOASES library. Once that's done, it defines these little guys:

  • qpOASES_FOUND β€” system has qpOASES
  • qpOASES_INCLUDE_DIRS β€” qpOASES include directory
  • qpOASES_LIBRARIES β€” qpOASES libraries

Okay so here's the tea β˜•: qpOASES does not have an "install" step. The includes live in the source tree, and the libraries live in the build tree. So to find them, the environment and cmake variables qpOASES_SOURCE_DIR and qpOASES_BINARY_DIR get used to locate the includes and libraries. Split custody of the files fr fr 😭

πŸ“– FindReadline

Try to find GNU Readline, a library for easy editing of command lines (yes, the thing that makes your shell line-editing not suck πŸ’–). Once done, this defines:

  • Readline_FOUND β€” system has GNU Readline
  • Readline_INCLUDE_DIRS β€” GNU Readline include directory
  • Readline_LIBRARIES β€” GNU Readline libraries
  • Readline_DEFINITIONS β€” additional compiler flags for GNU Readline
  • Readline_VERSION β€” GNU Readline version
  • Readline_MAJOR_VERSION β€” GNU Readline major version
  • Readline_MINOR_VERSION β€” GNU Readline minor version

Environment variables used to locate the GNU Readline library:

  • READLINE_DIR β€” Readline root directory

Cached variables used to locate the GNU Readline library:

  • Readline_INCLUDE_DIR β€” the Readline include directory
  • Readline_LIBRARY_RELEASE β€” GNU Readline library (release)
  • Readline_LIBRARY_DEBUG β€” GNU Readline library (debug)

πŸ—„οΈ FindSQLite

Try to find the SQLite library. Once done, this defines:

  • SQLite_FOUND β€” system has SQLite
  • SQLite_INCLUDE_DIRS β€” SQLite include directory
  • SQLite_LIBRARIES β€” SQLite libraries
  • SQLite_DEFINITIONS β€” additional compiler flags for SQLite
  • SQLite_VERSION β€” SQLite version
  • SQLite_MAJOR_VERSION β€” SQLite major version
  • SQLite_MINOR_VERSION β€” SQLite minor version
  • SQLite_PATCH_VERSION β€” SQLite patch version
  • SQLite_TWEAK_VERSION β€” SQLite tweak version

🎭 FindStage

Try to find Stage, a library for easy editing of command lines. Once done, this defines:

  • Stage_FOUND β€” system has Stage
  • Stage_INCLUDE_DIRS β€” Stage include directory
  • Stage_LIBRARIES β€” Stage libraries
  • Stage_DEFINITIONS β€” additional compiler flags for Stage
  • Stage_VERSION β€” Stage version
  • Stage_MAJOR_VERSION β€” Stage major version
  • Stage_MINOR_VERSION β€” Stage minor version

🐣 FindTinyXML

Try to find the TinyXML library. Once done, this defines:

  • TinyXML_FOUND β€” system has TinyXML
  • TinyXML_INCLUDE_DIRS β€” TinyXML include directory
  • TinyXML_LIBRARIES β€” TinyXML libraries
  • TinyXML_DEFINITIONS β€” additional compiler flags for TinyXML
  • TinyXML_VERSION β€” TinyXML version
  • TinyXML_MAJOR_VERSION β€” TinyXML major version
  • TinyXML_MINOR_VERSION β€” TinyXML minor version
  • TinyXML_PATCH_VERSION β€” TinyXML patch version

🐍 FindYamlCpp

Try to find the YamlCpp library. Once done, this defines:

  • YamlCpp_FOUND β€” system has YamlCpp
  • YamlCpp_INCLUDE_DIRS β€” YamlCpp include directory
  • YamlCpp_LIBRARIES β€” YamlCpp libraries
  • YamlCpp_DEFINITIONS β€” additional compiler flags for YamlCpp
  • YamlCpp_VERSION β€” YamlCpp version
  • YamlCpp_MAJOR_VERSION β€” YamlCpp major version
  • YamlCpp_MINOR_VERSION β€” YamlCpp minor version
  • YamlCpp_PATCH_VERSION β€” YamlCpp patch version
  • YamlCpp_TWEAK_VERSION β€” YamlCpp tweak version

πŸ”¨ BUILD PACKAGE MODULES πŸ”¨

🧩 BuildECM

ECM β€” extra-cmake-modules (from KDE project) πŸ‘‘

🧩 BuildEigen3

Eigen3

🧩 BuildGazeboYARPPlugins

GazeboYARPPlugins

🧩 BuildGooCanvas

GooCanvas

🧩 BuildGooCanvasMM

GooCanvasMM

🧩 BuildGtkDatabox

GtkDatabox

🧩 BuildGtkDataboxMM

GtkDataboxMM

🧩 BuildICUB

ICUB

🧩 BuildqpOASES

qpOASES

🧩 BuildTinyXML

TinyXML

🧩 BuildYARP

YARP


🌈 CMAKE PROPOSED MODULES 🌈

These modules are patched versions of the ones included in CMake. Not the originals, bestie β€” the glow-ups ✨

πŸ’« ExternalProject

External Project Definition

ExternalProject_Add

The ExternalProject_Add() function creates a custom target to drive the download, update/patch, configure, build, install and test steps of an external project:

ExternalProject_Add(<name> [<option>...])

The individual steps within the process can be driven independently if required (e.g. for CDash submission), and extra custom steps can be defined too, along with the ability to control the step dependencies. The directory structure used for managing the external project can also be customized. The function supports a large number of options which can be used to tailor the external project behavior. So many options. Not me reading all of them though, because we're about to 😌

Directory Options:

Most of the time, the default directory layout is sufficient. It's largely an implementation detail that the main project usually doesn't need to change. In some circumstances, however, control over the directory layout can be useful or necessary. The directory options are potentially more useful from the point of view that the main build can use the ExternalProject_Get_Property() command to retrieve their values, thereby allowing the main project to refer to build artifacts of the external project. Iconic behavior honestly 🫢

  • PREFIX <dir> β€” root directory for the external project. Unless otherwise noted below, all other directories associated with the external project will be created under here.
  • TMP_DIR <dir> β€” directory in which to store temporary files.
  • STAMP_DIR <dir> β€” directory in which to store the timestamps of each step. Log files from individual steps are also created in here unless overriden by LOG_DIR (see Logging Options below).
  • LOG_DIR <dir> β€” directory in which to store the logs of each step.
  • DOWNLOAD_DIR <dir> β€” directory in which to store downloaded files before unpacking them. This directory is only used by the URL download method, all other download methods use SOURCE_DIR directly instead.
  • SOURCE_DIR <dir> β€” source directory into which downloaded contents will be unpacked, or for non-URL download methods, the directory in which the repository should be checked out, cloned, etc. If no download method is specified, this must point to an existing directory where the external project has already been unpacked or cloned/checked out.
⚠️ NOTE: If a download method is specified, any existing contents of the source directory may be deleted. Only the URL download method checks whether this directory is either missing or empty before initiating the download, stopping with an error if it is not empty. All other download methods silently discard any previous contents of the source directory. Bestie. Read that again. It will not ask. It will not warn. It will simply delete πŸ’€
  • BINARY_DIR <dir> β€” specify the build directory location. This option is ignored if BUILD_IN_SOURCE is enabled.
  • INSTALL_DIR <dir> β€” installation prefix to be placed in the <INSTALL_DIR> placeholder. This does not actually configure the external project to install to the given prefix. That must be done by passing appropriate arguments to the external project configuration step, e.g. using <INSTALL_DIR>.

If any of the above ..._DIR options are not specified, their defaults are computed as follows. If the PREFIX option is given or the EP_PREFIX directory property is set, then an external project is built and installed under the specified prefix:

TMP_DIR      = <prefix>/tmp
STAMP_DIR    = <prefix>/src/<name>-stamp
DOWNLOAD_DIR = <prefix>/src
SOURCE_DIR   = <prefix>/src/<name>
BINARY_DIR   = <prefix>/src/<name>-build
INSTALL_DIR  = <prefix>
LOG_DIR      = <STAMP_DIR>

Otherwise, if the EP_BASE directory property is set then components of an external project are stored under the specified base:

TMP_DIR      = <base>/tmp/<name>
STAMP_DIR    = <base>/Stamp/<name>
DOWNLOAD_DIR = <base>/Download/<name>
SOURCE_DIR   = <base>/Source/<name>
BINARY_DIR   = <base>/Build/<name>
INSTALL_DIR  = <base>/Install/<name>
LOG_DIR      = <STAMP_DIR>

If no PREFIX, EP_PREFIX, or EP_BASE is specified, then the default is to set PREFIX to <name>-prefix. Relative paths are interpreted with respect to CMAKE_CURRENT_BINARY_DIR at the point where ExternalProject_Add() is called. Write that down, it's gonna come up πŸ“

Download Step Options:

A download method can be omitted if the SOURCE_DIR option is used to point to an existing non-empty directory. Otherwise, one of the download methods below must be specified (multiple download methods should not be given) or a custom DOWNLOAD_COMMAND provided. Pick one, babes, not all of them πŸ™ˆ

  • DOWNLOAD_COMMAND <cmd>... β€” okay bestie, this one overrides the command used for the download step (and yes, generator expressions are supported πŸ’…). But listen: if you specify this, every other download option gets straight-up ignored. And if you pass an empty string for <cmd>, you effectively disable the download step entirely. it's giving "I'm the only one that matters". no cap.

🌈 URL Download 🌈

  • URL <url1> [<url2>...] β€” the list of paths and/or URL(s) of the external project's source. When you give more than one URL, they get tried in turn until one succeeds. A URL can be a plain ol' path in the local file system β€” in which case it must be the only URL provided β€” or any downloadable URL that file(DOWNLOAD) supports. A local filesystem path may point to an existing directory or to an archive file, whereas a URL is expected to point to a file that can be treated as an archive. When an archive is used, it gets unpacked automatically unless the DOWNLOAD_NO_EXTRACT option is set to prevent it. And the archive type? Determined by inspecting the actual content rather than using logic based on the file extension. iconic.
  • URL_HASH <algo>=<hashValue> β€” the hash of the archive file to be downloaded. The argument should be of the form <algo>=<hashValue> where algo can be any of the hashing algorithms supported by the file() command. Specifying this is strongly recommended for URL downloads, because it ensures the integrity of the downloaded content. It's also used as a check for a previously downloaded file, which means the connection to the remote location can be avoided altogether if the local directory already has a file from an earlier download that matches the specified hash. slay, efficiency queen.
  • URL_MD5 <md5> β€” literally just equivalent to URL_HASH MD5=<md5>. same vibe, shorter name. πŸŽ€
  • DOWNLOAD_NAME <fname> β€” the file name to use for the downloaded file. If you don't give it one, the end of the URL is used to figure out the file name. This option is rarely needed β€” the default name is generally suitable and isn't normally used outside of code internal to the ExternalProject module. so like, don't worry about it bestie.
  • DOWNLOAD_NO_EXTRACT <bool> β€” lets you disable the extraction part of the download step by passing a boolean true value for this option. If this option isn't given, the downloaded contents get unpacked automatically if required. And if extraction has been disabled, the full path to the downloaded file is available as <DOWNLOADED_FILE> in subsequent steps, or as the property DOWNLOADED_FILE with the ExternalProject_Get_Property() command. handy πŸ’…
  • DOWNLOAD_NO_PROGRESS <bool> β€” can be used to disable logging the download progress. If this option isn't given, download progress messages will be logged. your terminal, your choice.
  • TIMEOUT <seconds> β€” maximum time allowed for file download operations. patience has a limit, periodt.
  • HTTP_USERNAME <username> β€” the username for the download operation, if authentication is required.
  • HTTP_PASSWORD <password> β€” the password for the download operation, if authentication is required.
  • HTTP_HEADER <header1> [<header2>...] β€” provides an arbitrary list of HTTP headers for the download operation. This can be useful for accessing content in systems like AWS, etc. πŸ¦‹
  • TLS_VERIFY <bool> β€” specifies whether certificate verification should be performed for https URLs. If this option isn't provided, the default behavior is determined by the CMAKE_TLS_VERIFY variable (see file(DOWNLOAD)). And if that's also not set, certificate verification will not be performed πŸ™ˆ. In situations where URL_HASH can't be provided, this option can be an alternative verification measure.
  • TLS_CAINFO <file> β€” specify a custom certificate authority file to use if TLS_VERIFY is enabled. If this option isn't specified, the value of the CMAKE_TLS_CAINFO variable will be used instead (see file(DOWNLOAD)).
  • NETRC <level> β€” specify whether the .netrc file is to be used for operation. If this option isn't specified, the value of the CMAKE_NETRC variable will be used instead (see file(DOWNLOAD)). The valid levels are:
    • IGNORED β€” the .netrc file is ignored. This is the default.
    • OPTIONAL β€” the .netrc file is optional, and information in the URL is preferred. The file will be scanned to find whichever information is not specified in the URL.
    • REQUIRED β€” the .netrc file is required, and information in the URL is ignored.
  • NETRC_FILE <file> β€” specify an alternative .netrc file to the one in your home directory, if the NETRC level is OPTIONAL or REQUIRED. If this option isn't specified, the value of the CMAKE_NETRC_FILE variable will be used instead (see file(DOWNLOAD)).

πŸ™ Git πŸ™

NOTE: a git version of 1.6.5 or later is required if this download method is used. old git? not invited to the party bestie. πŸ’€
  • GIT_REPOSITORY <url> β€” the URL of the git repository. Any URL understood by the git command may be used.
  • GIT_TAG <tag> β€” a git branch name, tag or commit hash. Note that branch names and tags should generally be specified as remote names (i.e. origin/myBranch rather than simply myBranch). This ensures that if the remote end has its tag moved or branch rebased or history rewritten, the local clone will still be updated correctly. In general, however, specifying a commit hash should be preferred for a number of reasons:
    • If the local clone already has the commit corresponding to the hash, no git fetch needs to be performed to check for changes each time CMake is re-run. This can result in a significant speed up if many external projects are being used.
    • Using a specific git hash ensures that the main project's own history is fully traceable to a specific point in the external project's evolution. If a branch or tag name is used instead, then checking out a specific commit of the main project doesn't necessarily pin the whole build to a specific point in the life of the external project. The lack of such deterministic behavior makes the main project lose traceability and repeatability. 😭

And one more thing β€” if GIT_SHALLOW is enabled, then GIT_TAG works only with branch names and tags. A commit hash is not allowed.

  • GIT_REMOTE_NAME <name> β€” the optional name of the remote. If this option isn't specified, it defaults to origin. the classic.
  • GIT_SUBMODULES <module>... β€” specific git submodules that should also be updated. If this option isn't provided, all git submodules will be updated. go big or go home, i guess. 🫢
  • GIT_SHALLOW <bool> β€” bestie, when you turn this on, the git clone operation gets the --depth 1 option. That's a shallow clone β€” it skips downloading the whole history and just grabs the commit that GIT_TAG points to. So slay, but only if you don't need the past. πŸ’…
  • GIT_PROGRESS <bool> β€” okay so when this is enabled, it tells the git clone operation to report its progress by passing it the --progress option. Without this, the clone step for large projects might look like the build is just stalling, because nothing gets logged until the clone finishes. So this can give you progress to prevent that "omg is it stuck?" vibe, but it can also make the build super noisy if you have lots of external projects. So it's giving trade-off. 😭
  • GIT_CONFIG <option1> [<option2>...] β€” specify a list of config options to pass to git clone. Each option you list gets transformed into its own --config <option> on the git clone command line, and each option has to be in the form key=value. No cap. ✨

Subversion

  • SVN_REPOSITORY <url> β€” the URL of the Subversion repository. That's it. Simple. πŸŽ€
  • SVN_REVISION -r<rev> β€” the revision to checkout from the Subversion repository. Like, which version you want. πŸ¦‹
  • SVN_USERNAME <username> β€” username for the Subversion checkout and update. You know, for when it's private. πŸ”
  • SVN_PASSWORD <password> β€” password for the Subversion checkout and update. Don't share it. πŸ™ˆ
  • SVN_TRUST_CERT <bool> β€” specifies whether to trust the Subversion server site certificate. If enabled, the --trust-server-cert option is passed to the svn checkout and update commands. So like, do you trust it? πŸ‘‘

Mercurial

  • HG_REPOSITORY <url> β€” URL of the mercurial repository. Mercurial, not git. Respect. πŸ’œ
  • HG_TAG <tag> β€” Mercurial branch name, tag or commit id. Pick your fighter. 🌸

CVS

  • CVS_REPOSITORY <cvsroot> β€” CVSROOT of the CVS repository. Old school, but okay. 🧚
  • CVS_MODULE <mod> β€” module to checkout from the CVS repository. πŸ“¦
  • CVS_TAG <tag> β€” tag to checkout from the CVS repository. 🏷️

Update/Patch Step Options:

Whenever CMake is re-run, by default the external project's sources will be updated if the download method supports updates (like, a git repository would be checked if the GIT_TAG does not refer to a specific commit). So it's giving "keep it fresh". ✨

  • UPDATE_COMMAND <cmd>... β€” overrides the download method's update step with a custom command. The command may use generator expressions. So you can do your own thing. πŸ’…
  • UPDATE_DISCONNECTED <bool> β€” when enabled, this option causes the update step to be skipped. It does not, however, prevent the download step. The update step can still be added as a step target (see ExternalProject_Add_StepTargets()) and called manually. This is useful if you want to allow developers to build the project when disconnected from the network (the network may still be needed for the download step though). When this option is present, it is generally advisable to make the value a cache variable under the developer's control rather than hard-coding it. If this option is not present, the default value is taken from the EP_UPDATE_DISCONNECTED directory property. If that is also not defined, updates are performed as normal. The EP_UPDATE_DISCONNECTED directory property is intended as a convenience for controlling the UPDATE_DISCONNECTED behavior for an entire section of a project's directory hierarchy and may be a more convenient method of giving developers control over whether or not to perform updates (assuming the project also provides a cache variable or some other convenient method for setting the directory property). So basically, if you're offline, this is your bestie. πŸ“Ά
  • PATCH_COMMAND <cmd>... β€” specifies a custom command to patch the sources after an update. By default, no patch command is defined. Note that it can be quite difficult to define an appropriate patch command that performs robustly, especially for download methods such as git where changing the GIT_TAG will not discard changes from a previous patch, but the patch command will be called again after updating to the new tag. So like, patch responsibly. 🩹

Configure Step Options:

The configure step is run after the download and update steps. By default, the external project is assumed to be a CMake project, but this can be overridden if required. So it's the main character of the build steps. πŸ‘‘

  • CONFIGURE_COMMAND <cmd>... β€” the default configure command runs CMake with options based on the main project. For non-CMake external projects, the CONFIGURE_COMMAND option must be used to override this behavior (generator expressions are supported). For projects that require no configure step, specify this option with an empty string as the command to execute. So like, if it's not CMake, you gotta tell it. πŸ’
  • CMAKE_COMMAND /.../cmake β€” specify an alternative cmake executable for the configure step (use an absolute path). This is generally not recommended, since it is usually desirable to use the same CMake version throughout the whole build. This option is ignored if a custom configure command has been specified with CONFIGURE_COMMAND. So maybe don't. πŸ™…
  • CMAKE_GENERATOR <gen> β€” override the CMake generator used for the configure step. Without this option, the same generator as the main build will be used. This option is ignored if a custom configure command has been specified with the CONFIGURE_COMMAND option. So it's giving "I want a different generator". πŸ”„
  • CMAKE_GENERATOR_PLATFORM <platform> β€” pass a generator-specific platform name to the CMake command (see CMAKE_GENERATOR_PLATFORM). It is an error to provide this option without the CMAKE_GENERATOR option. So like, you need the generator first. ⚠️
  • CMAKE_GENERATOR_TOOLSET <toolset> β€” pass a generator-specific toolset name to the CMake command (see CMAKE_GENERATOR_TOOLSET). It is an error to provide this option without the CMAKE_GENERATOR option. Same deal. πŸ› οΈ
  • CMAKE_GENERATOR_INSTANCE <instance> β€” pass a generator-specific instance selection to the CMake command (see CMAKE_GENERATOR_INSTANCE). It is an error to provide this option without the CMAKE_GENERATOR option. Again, generator needed. 🎯
  • CMAKE_ARGS <arg>... β€” the specified arguments are passed to the cmake command line. They can be any argument the cmake command understands, not just cache values defined by -D... arguments (see also CMake Options). In addition, arguments may use generator expressions. So like, whatever you want. ✨
  • CMAKE_CACHE_ARGS <arg>... β€” this is an alternate way of specifying cache variables where command line length issues may become a problem. The arguments are expected to be in the form -Dvar:STRING=value, which are then transformed into CMake set() commands with the FORCE option used. These set() commands are written to a pre-load script which is then applied using the cmake -C command line option. Arguments may use generator expressions. So like, for when the command line is too long. πŸ“
  • CMAKE_CACHE_DEFAULT_ARGS <arg>... β€” this is the same as the CMAKE_CACHE_ARGS option except the set() commands do not include the FORCE keyword. This means the values act as initial defaults only and will not override any variables already set from a previous run. Use this option with care, as it can lead to different behavior depending on whether the build starts from a fresh build directory or re-uses previous build contents. So like, be careful. πŸ’€
  • SOURCE_SUBDIR <dir> β€” okay so when you don't hand over a CONFIGURE_COMMAND, the configure step is just gonna assume your external project has a CMakeLists.txt sitting right at the top of its source tree (aka inside SOURCE_DIR, bestie πŸ’…). SOURCE_SUBDIR is your lil' detour: point it at some other directory inside the source tree and that becomes the top of the CMake source tree instead. It has to be a relative path, and it gets read as relative to SOURCE_DIR. And when BUILD_IN_SOURCE 1 is specified, it's the BUILD_COMMAND that's used to point to an alternative directory within the source tree. πŸ¦‹

πŸ› οΈ Build Step Options

so here's the vibe: if the configure step assumed the external project uses CMake as its build system, the build step will too. Otherwise, the build step assumes a Makefile-based build and literally just runs make with no arguments as the default build step. Want something else? Custom build commands, babe. ✨

  • BUILD_COMMAND <cmd>... β€” overrides the default build command (and yes, generator expressions are supported 🫢). If you don't give this option, the default build command gets chosen to integrate with the main build in the most appropriate way (like using recursive make for Makefile generators, or cmake --build if the project uses a CMake build). Plot twist: you can specify this option with an empty string as the command to make the build step do absolutely nothing. πŸ’€
  • BUILD_IN_SOURCE <bool> β€” turn this on and the build gets done directly within the external project's source tree. > bestie, this should generally be avoided β€” a separate build directory is usually preferred β€” but it can be useful when the external project assumes an in-source build. And if you're building in-source, do not specify the BINARY_DIR option.
  • BUILD_ALWAYS <bool> β€” enables this and the build step is forced to always run. This can be the easiest way to robustly ensure the external project's own build dependencies get evaluated, rather than relying on the default success timestamp-based method. Not normally needed unless developers are expected to modify something the external project's build depends on in a way that's not detectable via the step target dependencies (e.g. SOURCE_DIR is used without a download method and developers might modify the sources in SOURCE_DIR). πŸ‘‘
  • BUILD_BYPRODUCTS <file>... β€” lists files that will be generated by the build command but which might or might not have their modification time updated by subsequent builds. These ultimately get passed through as BYPRODUCTS to the build step's own underlying call to add_custom_command(). 🌸

πŸ“¦ Install Step Options

same energy as the build step: if the configure step assumed the external project uses CMake as its build system, the install step will too. Otherwise, the install step assumes a Makefile-based build and simply runs make install as the default build step. Override it with custom install commands if you need. ✨

  • INSTALL_COMMAND <cmd>... β€” the external project's own install step gets invoked as part of the main project's build. It happens after the external project's build step, and it may be before or after the external project's test step (peep the TEST_BEFORE_INSTALL option below πŸ‘€). Heads up though: the external project's install rules are not part of the main project's install rules, so if anything from the external project should be installed as part of the main build, you gotta specify those in the main build as additional install() commands. The default install step builds the install target of the external project, but you can override that with a custom command using this option (generator expressions are supported πŸ’–). Pass an empty string as the <cmd> and the install step does nothing.

πŸ§ͺ Test Step Options

the test step is only defined if at least one of these TEST_... options is provided. no options, no step, periodt. πŸ’…

  • TEST_COMMAND <cmd>... β€” overrides the default test command (generator expressions are supported 🌈). If you don't give this option, the default behavior of the test step is to build the external project's own test target. You can specify this option with <cmd> as an empty string, which lets the test step still be defined but makes it do nothing. > do not specify any of the other TEST_... options if you're providing an empty string as the test command β€” and honestly, prefer to just omit all the TEST_... options altogether if the test step target isn't needed. πŸ™ˆ
  • TEST_BEFORE_INSTALL <bool> β€” enable this and the test step will be executed before the install step. The default behavior is for the test step to run after the install step.
  • TEST_AFTER_INSTALL <bool> β€” this one's mainly useful as a way to say "yes I want the test step, but all the default behavior is sufficient." Specify it with a boolean true value and you're guaranteeing the test step is defined and that it comes after the install step. If both TEST_BEFORE_INSTALL and TEST_AFTER_INSTALL are enabled, the latter is silently ignored. πŸ’€
  • TEST_EXCLUDE_FROM_MAIN <bool> β€” if enabled, the main build's default ALL target will not depend on the test step. Useful lil' move for keeping the test step defined but only invoking it when you manually ask for it. πŸ‘‘

πŸ“ Output Logging Options

each one of these LOG_... options can be used to wrap the relevant step in a script to capture its output into files. The log files get created in LOG_DIR if you supplied it, otherwise in the STAMP_DIR directory, with step-specific file names. πŸŽ€

  • LOG_DOWNLOAD <bool> β€” when enabled, the output of the download step is logged to files.
  • LOG_UPDATE <bool> β€” when enabled, the output of the update step is logged to files.
  • LOG_PATCH <bool> β€” when enabled, the output of the patch step is logged to files.
  • LOG_CONFIGURE <bool> β€” when enabled, the output of the configure step is logged to files.
  • LOG_BUILD <bool> β€” when enabled, the output of the build step is logged to files.
  • LOG_INSTALL <bool> β€” when enabled, the output of the install step is logged to files.
  • LOG_TEST <bool> β€” when enabled, the output of the test step is logged to files.
  • LOG_MERGED_STDOUTERR <bool> β€” when enabled, stdout and stderr will be merged for any step whose output is being logged to files.
  • LOG_OUTPUT_ON_FAILURE <bool> β€” this option only has an effect if at least one of the other LOG_<step> options is enabled. If an error occurs for a step which has logging to file enabled, that step's output will be printed to the console if LOG_OUTPUT_ON_FAILURE is set to true. And for cases where a large amount of output is recorded, just the end of that output may be printed to the console. 😭

πŸ–₯️ Terminal Access Options

Steps can be given direct access to the terminal in some cases. Giving a step access to the terminal may allow it to receive terminal input if required β€” like for authentication details that other options didn't provide. With the Ninja generator, these options place the steps in the console job pool. Each step can be given terminal access individually via these: 🌈

  • USES_TERMINAL_DOWNLOAD <bool> β€” give the download step access to the terminal.
  • USES_TERMINAL_UPDATE <bool> β€” give the update step access to the terminal.
  • USES_TERMINAL_CONFIGURE <bool> β€” give the configure step access to the terminal.
  • USES_TERMINAL_BUILD <bool> β€” give the build step access to the terminal.
  • USES_TERMINAL_INSTALL <bool> β€” give the install step access to the terminal.
  • USES_TERMINAL_TEST <bool> β€” give the test step access to the terminal.

🎯 Target Options

  • DEPENDS <targets>... β€” okay so this is where you tell the build "bestie, this external project is not ready until these other targets are ready first" πŸ’… All those other targets get brought up to date before any of the external project's steps are executed. And here's the tea: because the external project quietly creates its own additional custom targets internally for each step, DEPENDS is genuinely the most convenient way to make all of those steps depend on your other targets. And no, you can't just do add_dependencies(<name> <targets>) and call it a day β€” that will not make any of the steps dependent on <targets>. Not even one. 😭
  • EXCLUDE_FROM_ALL <bool> β€” when this is enabled, the external project gets excluded from the default ALL target of the main build. It's giving "not invited to the group chat" energy 🫢
  • STEP_TARGETS <step-target>... β€” generates custom targets for the steps you name. You need this if those steps have to be triggered manually, or if they need to be used as dependencies of other targets. If you don't specify it, the default value is taken from the EP_STEP_TARGETS directory property. Peep ExternalProject_Add_Step() below for more on what this option actually does ✨
  • INDEPENDENT_STEP_TARGETS <step-target>... β€” same deal, generates custom targets for the steps you name, but ALSO prevents those targets from having the usual dependencies applied to them. If you don't specify it, the default value comes from the EP_INDEPENDENT_STEP_TARGETS directory property. This one is mostly for letting individual steps be driven independently β€” think a CDash setup where each step gets initiated and reported individually instead of as one whole build. Again, ExternalProject_Add_Step() below has the full discussion πŸ”₯

Miscellaneous Options ✨

  • LIST_SEPARATOR <sep> β€” for any of the various ..._COMMAND options, replace ; with <sep> in the specified command lines. This is lowkey so useful when list variables might be handed to commands where they need to end up as space-separated arguments (<sep> would be a single space character string in that case) 🌸
  • COMMAND <cmd>... β€” any of the other ..._COMMAND options can get extra commands appended to them by following them with as many COMMAND ... options as you need (generator expressions are supported, obviously πŸ’). Like so:
ExternalProject_Add(example
  ... # Download options, etc.
  BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $<CONFIG> build"
  COMMAND       ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG>
  COMMAND       ${CMAKE_COMMAND} -E echo "$<CONFIG> build complete"
)

Also worth noting (ngl this one matters): each build step is created via a call to ExternalProject_Add_Step(). Go read that command's docs for the automatic substitutions that are supported for some options πŸ‘‘

Obtaining Project Properties πŸŽ€

ExternalProject_Get_Property

The ExternalProject_Get_Property() function grabs external project target properties for you:

ExternalProject_Get_Property(<name> <prop1> [<prop2>...])

It stores the property values in variables with the same name as the property. The property names match up with the keyword argument names of ExternalProject_Add() β€” iconic, consistent, we love to see it. So for example, you could pull the source directory like this:

ExternalProject_Get_property(myExtProj SOURCE_DIR)
message("Source dir of myExtProj = ${SOURCE_DIR}")

Explicit Step Management πŸ’…

Just calling ExternalProject_Add() on its own is often enough to fold an external project into the main build, fr fr. But some scenarios need extra work to get the behavior you want β€” like adding a custom step, or making steps available as manually triggerable targets. That's where ExternalProject_Add_Step(), ExternalProject_Add_StepTargets() and ExternalProject_Add_StepDependencies come in, giving you the lower-level control needed for all that step-level capability 🌈

ExternalProject_Add_Step

The ExternalProject_Add_Step() function specifies an additional custom step for an external project that was defined by an earlier call to ExternalProject_Add():

ExternalProject_Add_Step(<name> <step> [<option>...])

<name> is the same as the name you passed to the original ExternalProject_Add() call. And heads up β€” the <step> you specify must not be one of the pre-defined steps (mkdir, download, update, skip-update, patch, configure, build, install or test). πŸ™ˆ The supported options are:

  • COMMAND <cmd>... β€” the command line this custom step executes (generator expressions are supported). You can repeat this option multiple times to specify multiple commands, and they'll be executed in order ✨
  • COMMENT "<text>..." β€” the text printed when the custom step executes πŸ’¬
  • DEPENDEES <step>... β€” other steps (custom or pre-defined) that this step depends on.
  • DEPENDERS <step>... β€” other steps (custom or pre-defined) that depend on this new custom step.
  • DEPENDS <file>... β€” files that this custom step depends on.
  • BYPRODUCTS <file>... β€” files that will be generated by this custom step but whose modification time might or might not get updated by subsequent builds. This list of files ultimately gets passed straight through as the BYPRODUCTS option to the add_custom_command() used to implement the custom step internally πŸ”₯
  • ALWAYS <bool> β€” when enabled, this says the custom step should always be run (i.e. it's always considered out of date). She's always booked and busy πŸ’…
  • EXCLUDE_FROM_MAIN <bool> β€” when enabled, this says the external project's main target does not depend on the custom step.
  • WORKING_DIRECTORY <dir> β€” sets the working directory before running the custom step's command. If you don't specify it, the directory is the value of CMAKE_CURRENT_BINARY_DIR at the point where ExternalProject_Add_Step() was called πŸ“
  • LOG <bool> β€” if set, the output from the custom step gets captured to files in the external project's LOG_DIR if supplied, otherwise STAMP_DIR 🫢
  • USES_TERMINAL <bool> β€” if enabled, the custom step gets direct access to the terminal if possible πŸ’»
The command line, comment, working directory and byproducts of every standard and custom step are processed to replace the tokens <SOURCE_DIR>, <SOURCE_SUBDIR>, <BINARY_DIR>, <INSTALL_DIR>, <TMP_DIR>, <DOWNLOAD_DIR> and <DOWNLOADED_FILE> with their corresponding property values defined in the original call to ExternalProject_Add(). Keep those spellings exactly, bestie β€” no typos, no cap ⭐

ExternalProject_Add_StepTargets

The ExternalProject_Add_StepTargets() function generates targets for the steps you list. Each created target gets a name in the form <name>-<step>:

ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] <step1> [<step2>...])

Creating a target for a step lets it be used as a dependency of another target, or triggered manually by hand. Having targets for specific steps also lets them be driven independently of each other by naming targets on build command lines β€” for example, you might be submitting to a sub-project based dashboard where you want to drive the configure portion of the build, then submit to the dashboard, then do the build portion, then the tests. And if you invoke a custom target that depends on a step halfway through the step dependency chain, all the previous steps run too, so everything stays up to date πŸ¦‹

If the NO_DEPENDS option is specified, the step target will not depend on the dependencies of the external project (i.e. on any dependencies of the <name> custom target created by ExternalProject_Add()). This is usually safe for the download, update and patch steps, since they don't typically require the dependencies to be updated and built.

But bestie, listen 😭 β€” using NO_DEPENDS for any of the other pre-defined steps may break parallel builds. Only use NO_DEPENDS where it's certain that the named steps genuinely do not have dependencies. For custom steps, think about whether or not the custom commands actually require the dependencies to be configured, built and installed. Don't just vibe it, check it πŸ’€

Internally, ExternalProject_Add() calls ExternalProject_Add_Step() to create each step. If any STEP_TARGETS or INDEPENDENT_STEP_TARGETS were specified, then ExternalProject_Add_StepTargets() will also be called after ExternalProject_Add_Step(). INDEPENDENT_STEP_TARGETS have the NO_DEPENDS option set, whereas STEP_TARGETS do not. Other than that one difference, both options result in ExternalProject_Add_StepTargets() being called in the same way. And even if a step isn't mentioned in either of those two options, you can still call ExternalProject_Add_StepTargets() later to manually define a target for that step. Main character energy, honestly πŸ‘‘

The STEP_TARGETS and INDEPENDENT_STEP_TARGETS options for ExternalProject_Add() are lowkey the easiest way to make sure targets get created for the specific steps you actually care about ✨. But heads up bestie β€” for custom steps, you have to call ExternalProject_Add_StepTargets() explicitly if you want a target for that custom step too. No shortcuts, no cap.

And if you're out here defining a million external projects with the same step targets over and over? An alternative to those two options is to just populate the EP_STEP_TARGETS and EP_INDEPENDENT_STEP_TARGETS directory properties πŸŽ€. They act as defaults for the step target options, so you can stop typing the same set of step targets like forty times. It's giving efficiency, fr fr.

ExternalProject_Add_StepDependencies πŸ’…

The ExternalProject_Add_StepDependencies() function lets you add dependencies to a step. The dependencies you add must be targets CMake already knows about β€” could be ordinary executable or library targets, custom targets, or even step targets of another external project πŸ‘‘

ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...])

This function is that girl because it takes care to set both target and file level dependencies, and it ensures parallel builds won't break on you 😭. Basically: use this instead of add_dependencies() whenever you're adding a dependency for some of the step targets that the ExternalProject module generated. Periodt.

Examples 🌈

Okay so imagine we want to download and build a hypothetical project called FooBar from github:

include(ExternalProject)
ExternalProject_Add(foobar
  GIT_REPOSITORY    git@github.com:FooCo/FooBar.git
  GIT_TAG           origin/release/1.2.3
)

For the sake of the example, let's also define a second hypothetical external project called SecretSauce, downloaded from a web server πŸ“. We're giving it two URLs so it can use a faster internal network if one's available, with a fallback to a slower external server. This one is a typical Makefile project with no configure step, so some of the default commands get overridden. And the build only needs to build the sauce target:

find_program(MAKE_EXE NAMES gmake nmake make)
ExternalProject_Add(secretsauce
  URL               http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
                    https://www.somecompany.com/downloads/sauce-2.7.zip
  URL_HASH          MD5=d41d8cd98f00b204e9800998ecf8427e
  CONFIGURE_COMMAND ""
  BUILD_COMMAND     ${MAKE_EXE} sauce
)

Now suppose the build step of secretsauce requires that foobar must already be built. We could enforce that like so:

ExternalProject_Add_StepDependencies(secretsauce build foobar)

Another alternative: create a custom target for foobar's build step, and make secretsauce depend on that instead of the whole foobar project πŸ‘€. This means foobar only needs to be built β€” it does not need to run its install or test steps before secretsauce can be built. Iconic, honestly. And you can define the dependency right along with the secretsauce project:

ExternalProject_Add_StepTargets(foobar build)
ExternalProject_Add(secretsauce
  URL               http://intranet.somecompany.com/artifacts/sauce-2.7.tgz
                    https://www.somecompany.com/downloads/sauce-2.7.zip
  URL_HASH          MD5=d41d8cd98f00b204e9800998ecf8427e
  CONFIGURE_COMMAND ""
  BUILD_COMMAND     ${MAKE_EXE} sauce
  DEPENDS           foobar-build
)

Instead of calling ExternalProject_Add_StepTargets(), you could define the target along with the foobar project itself:

ExternalProject_Add(foobar
  GIT_REPOSITORY git@github.com:FooCo/FooBar.git
  GIT_TAG        origin/release/1.2.3
  STEP_TARGETS   build
)

And if you've got many external projects that should all share the same set of step targets, setting a directory property might be way more convenient πŸ’–. The build step target could get created automatically by setting the EP_STEP_TARGETS directory property before creating the external projects with ExternalProject_Add():

set_property(DIRECTORY PROPERTY EP_STEP_TARGETS build)

Lastly, suppose secretsauce provides a script called makedoc that can generate its own documentation πŸ“. And further suppose that script expects the output directory as its only parameter, and that it should be run from the secretsauce source directory. A custom step plus a custom target to trigger the script can be defined like so:

ExternalProject_Add_Step(secretsauce docs
  COMMAND           <SOURCE_DIR>/makedoc <BINARY_DIR>
  WORKING_DIRECTORY <SOURCE_DIR>
  COMMENT           "Building secretsauce docs"
  ALWAYS            TRUE
  EXCLUDE_FROM_MAIN TRUE
)
ExternalProject_Add_StepTargets(secretsauce docs)

And then the custom step can be triggered from the main build like so:

cmake --build . --target secretsauce-docs

CMakeParseArguments 🧚

Parse arguments given to a macro or a function.

cmake_parse_arguments() is meant to be used inside macros or functions to parse the arguments that got handed to that macro or function. It processes the args and defines a set of variables holding the values of the respective options ✨.

cmake_parse_arguments(<prefix>
                      <options>
                      <one_value_keywords>
                      <multi_value_keywords>
                      [CMAKE_PARSE_ARGUMENTS_SKIP_EMPTY|CMAKE_PARSE_ARGUMENTS_KEEP_EMPTY]
                      args...
                      )

The <options> argument holds all the options for the respective macro β€” like, keywords you can use when calling the macro without any value following, e.g. the OPTIONAL keyword of the install() command πŸ’….

The <one_value_keywords> argument holds all keywords for this macro that are followed by one value, like e.g. the DESTINATION keyword of the install() command.

The <multi_value_keywords> argument holds all keywords for this macro that can be followed by more than one value, like e.g. the TARGETS or FILES keywords of the install() command πŸ‘‘

When it's done, cmake_parse_arguments() will have defined, for each of the keywords listed in <options>, <one_value_keywords> and <multi_value_keywords>, a variable composed of the given <prefix> followed by "_" and the name of the respective keyword. Those variables then hold the respective value from the argument list πŸŽ€. For the <options> keywords, this will be TRUE or FALSE.

All the remaining arguments get collected in a variable called <prefix>_UNPARSED_ARGUMENTS β€” you can check that afterwards to see whether your macro got called with unrecognized parameters πŸ‘€.

The cmake CMAKE_PARSE_ARGUMENTS_SKIP_EMPTY (old behaviour) and CMAKE_PARSE_ARGUMENTS_KEEP_EMPTY options decide how empty arguments should be handled. If none of these options is set, then β€” for backwards compatibility β€” if CMAKE_MINIMUM_REQUIRED_VERSION < 3.0.0, the default behaviour is to skip empty arguments, otherwise the default behaviour is to keep them. And using the CMAKE_PARSE_ARGUMENTS_DEFAULT_SKIP_EMPTY variable, the user can explicitly set the default behaviour in the current scope πŸ’–.

As an example, here's a my_install() macro that takes similar arguments to the real install() command:

function(MY_INSTALL)
  set(options OPTIONAL FAST)
  set(oneValueArgs DESTINATION RENAME)
  set(multiValueArgs TARGETS CONFIGURATIONS)
  cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}" )
  ...

Assume my_install() got called like this:

my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)

After the cmake_parse_arguments() call, the macro will have set the following variables:

MY_INSTALL_OPTIONAL = TRUE
MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
MY_INSTALL_DESTINATION = "bin"
MY_INSTALL_RENAME = "" (was not used)
MY_INSTALL_TARGETS = "foo;bar"
MY_INSTALL_CONFIGURATIONS = "" (was not used)
MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"

You can then continue and process these variables πŸ’«.

Keywords terminate lists of values β€” e.g. if directly after a one_value_keyword another recognized keyword follows, that gets interpreted as the beginning of the new option. So like my_install(TARGETS foo DESTINATION OPTIONAL) would result in MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefore 🀯.

If the "CMAKE_PARSE_ARGUMENTS_SKIP_EMPTY" option is set, cmake_parse_arguments will not consider empty arguments. Therefore

my_install(DESTINATION "" TARGETS foo "" bar)

Will set

MY_INSTALL_DESTINATION = (unset)
MY_INSTALL_MULTI = "foo;bar"

Using the "CMAKE_PARSE_ARGUMENTS_SKIP_EMPTY" option instead, will set

MY_INSTALL_SINGLE = ""
MY_INSTALL_MULTI = "foo;;bar"

It is also important to note that:

cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}" )
cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

Will behave differently, because in the latter case empty arguments are not passed to cmake_parse_arguments 😭.

DEPRECATED MODULES πŸ’€

WARNING: These modules are deprecated and should not be used in new code.

YCMDefaultDirs


Copyright 2012-2021 Istituto Italiano di Tecnologia (IIT)


And that's a wrap on the whole page, bestie 🫢 that was YCM-MODULES(7), version 0.13., dated Nov 05, 2023 β€” you absolutely ate this entire manpage, no notes, go build something iconic πŸ’…βœ¨

πŸ“¦ where this page comes from