Разделы
Но CMake позволяет также удобно подключать зависимости (сторонние библиотеки) к проекту. И здесь CMake предоставляет ряд возможностей, которые я хочу кратко рассмотреть.
Поиск библиотек
Если файл с именем имя_заголовочного_файла будет найден, то в переменную ПЕРЕМЕННАЯ1 будет записан полный путь к директории, где этот файл лежит. Если файл с именем имя_библиотеки будет найден, то в переменную ПЕРЕМЕННАЯ2 будет записан полный путь к этому файлу.
После этого эти переменные можно будет подключить к цели сборки:
Но вот только где CMake будет производить поиск? Можно указать несколько стандартных путей, например так:
Это хорошо работает под Линуксом, где все библиотеки обычно лежат по нескольким стандартным путям. Под Windows хуже: нужная библиотека может располагаться, где угодно.
Можно договориться, что при установке библиотеки на компьютер путь к ней будет прописываться в переменную окружения ПЕРЕМЕННАЯ_ОКРУЖЕНИЯ, тогда CMake сможет это использовать:
Если ничего не помогло, то пользователю придется вручную вводить в интерфейсе CMake нужные пути.
Упрощение поиска
Для сложных сторонних библиотек с кучей модулей и версий может понадобиться большое нагромождение команд find_path и find_library. Для удобства эти команды можно выделить в отдельный скрипт с именем FindБИБЛИОТЕКА.cmake.
После этого можно вызывать скрипт командой find_package:
(и не забыть прописать в переменной CMAKE_MODULE_PATH путь к папке со скриптами).
Это серьезно упрощает структуру корневого файла CMakeLists.txt. Также для популярных библиотек уже существуют скрипты для поиска, которые устанавливаются вместе с CMake. Под Линуксом такие скрипты лежат в папке /usr/share/cmake/Modules, а под Windows в папке C:\Program Files (x86)\CMake\share\cmake-3.2\Modules.
Также некоторые библиотеки предоставляют такие скрипты для поиска самих себя. В этом случае его нужно скопировать себе в проект из репозитория сторонней библиотеки.
Импорт целей сборки
Помимо путей к заголовочным файлам и библиотекам бывает необходима информация об опциях компилятора, об определениях препроцессора, о зависимостях зависимостей и т.д. Было бы удобно работать со сторонними библиотеками как с обычными целями сборки.
CMake позволяет это. Для этого необходимо создать «виртуальную» цель сборки и описать её свойства. В терминологии CMake такая цель сборки называется импортированная.
Создать и описать импортированную цель сборки можно с помощью ключевого слова IMPORTED. Пример:
После этого можно подключить эту внешюю цель сборки к нашей цели:
При сборки нашего проекта автоматически будут прописаны пути к заголовочным файлам и библиотеке, определение препроцессора. Этот способ является альтернативным использованию функций find_library и find_path.
Описание импортированной цели сборки удобно вынести в отдельный скрипт. Но лучше, если сама внешняя библиотека сгенерирует этот скрипт за нас. Здесь описано как генерировать такой скрипт автоматически.
Тогда нашему проекту достаточно будет подключить готовый скрипт:
Сборка зависимостей
Но что, если в системе не установлена нужная зависимость? Можно попросить пользователя установить её, либо поручить это CMake-скрипту.
Есть 2 основные стратегии в зависимости от размера внешней библиотеки.
Исходный код маленькой библиотеки можно просто добавить в дерево исходников нашего проекта, например, в подпапку 3rdParty. Далее библиотеку можно подключить в из корневого файла CMakeLists.txt с помощью команды add_subdirectory:
Тогда эта библиотека будет скомпилирована вместе с нашим проектом, и будут доступны её цели сборки.
Если внешняя библиотека слишком большая, то можно использовать команду ExternalProject_Add. Например:
Команда имеет множество параметров. Она позволяет скачать архив из интернета и распаковать его, либо клонировать репозиторий, вызвать отдельный экземпляр CMake для создания проектов Visual Studio или Makefiles. Такой многофункциональный комбайн.
Однако, команда имеет и недостатки. Дело в том, что конфигурирование и сборка внешней библиотеки происходят не во время ExternalProject_Add. Они происходят одновременно со сборкой нашего проекта, а значит до начала сборки ни самих библиотек, ни заголовочных файлов, ни скриптов не существует. А это значит, что команды find_library, find_path будут выдавать ошибки при конфигурировании в CMake. Цели сборки внешней библиотеки будут недоступны…
Поэтому команда ExternalProject_Add не является панацеей и её нужно использовать осторожно.
Суперсборка
В обсуждениях в интернете встретил подход к сборке проекта, основанный на ExternalProject_Add, который назвали «суперсборкой».
Идея в том, что и сторонние библиотеки, и наш проект собирать с помощью ExternalProject_Add. Корневой CMakeLists.txt просто содержит вызовы этой команды и всё.
В этом случае скачивание и конфигурирование происходит во время сборки. Когда мы вызываем команду make под Линуксом или запускаем сборку в Visual Studio под Windows, то происходит следующее:
GitLab Useful Variables
You are now on the CMake community wiki. Many pages are now DEPRECATED and sometimes even considered bad practice. Those are only kept as reference for previous CMake versions. The documentation for the latest version is available here: CMake Documentation.
CMake uses and defines many variables, which can be used in CMakeLists.txt files.
NOTE: As of CMake 2.6.0 many of these variables have been officially documented in TXT and HTML files released with CMake. You may still see some useful variables here that haven’t yet been documented in the official documentation, although the number of these diminishes with every release. This page, in either case, is more of a distilled list of some of the more important variables. The official documentation is home of the authoritative guide to all CMake variables, commands, and properties.
Locations
Environment Variables
These are environment variables which effect cmake behaviour.
System & Compiler Information
CMake will create by default the following variables when using a single-configuration generator:
If you are using the Makefile generator, you can create your own build type like this:
Note that CMAKE_BUILD_TYPE is not initialized with a readable value at configuration time. This is because the user is free to select a build type at build time. Use CMAKE_CFG_INTDIR if you need a variable that evaluates to the correct build time directory.
Prefixes, Suffixes (Postfixes), and Extensions
Variables not listed here
CMake has many more variables than are listed above. Documenting all of them is an ongoing project. We need everyone’s help with this. If you know of a CMake variable that is not listed here, please edit the wiki and add it. Don’t worry about whether you have a precise description for it. This is a wiki, and other people can provide a better description as time goes on.
When a CMake dashboard is run, a «SystemInformation test» is usually run as well. Among other things, it lists the names and values of all of the CMake variables that are in use when the test is run. The script looks at the SystemInformation test output, and uses regular expressions to find the start and end of the «AllVariables.txt» section. It prints the results out in the form of XML.
Logging code
This code may be placed in a CMakelists.txt file to create status messages that log a number of the variables documented above. It is not a complete list, however. The variables are not auto-generated from the wiki, it is just sample code. Add whatever variables you are interested in.
This page was initially populated by conversion from its original location in another wiki.
cmake(1)В¶
SynopsisВ¶
DescriptionВ¶
The cmake executable is the command-line interface of the cross-platform buildsystem generator CMake. The above Synopsis lists various actions the tool can perform as described in sections below.
To build a software project with CMake, Generate a Project Buildsystem. Optionally use cmake to Build a Project, Install a Project or just run the corresponding build tool (e.g. make ) directly. cmake can also be used to View Help.
The other actions are meant for use by software developers writing scripts in the CMake language to support their builds.
For more information on CMake at large, see also the links at the end of this manual.
Introduction to CMake BuildsystemsВ¶
To generate a buildsystem with CMake, the following must be selected:
The top-level directory in which buildsystem files and build output artifacts (e.g. executables and libraries) are to be stored. CMake will write a CMakeCache.txt file to identify the directory as a build tree and store persistent information such as buildsystem configuration options.
To maintain a pristine source tree, perform an out-of-source build by using a separate dedicated build tree. An in-source build in which the build tree is placed in the same directory as the source tree is also supported, but discouraged.
Generate a Project BuildsystemВ¶
Run CMake with one of the following command signatures to specify the source and build trees and generate a buildsystem:
Uses the current working directory as the build tree, and
as the source tree. The specified path may be absolute or relative to the current working directory. The source tree must contain a CMakeLists.txt file and must not contain a CMakeCache.txt file because the latter identifies an existing build tree. For example:
as the build tree, and loads the path to the source tree from its CMakeCache.txt file, which must have already been generated by a previous run of CMake. The specified path may be absolute or relative to the current working directory. For example:
as the build tree and
as the source tree. The specified paths may be absolute or relative to the current working directory. The source tree must contain a CMakeLists.txt file. The build tree will be created automatically if it does not already exist. For example:
In all cases the may be zero or more of the Options below.
After generating a buildsystem one may use the corresponding native build tool to build the project. For example, after using the Unix Makefiles generator one may run make directly:
Alternatively, one may use cmake to Build a Project by automatically choosing and invoking the appropriate native build tool.
OptionsВ¶
Path to root directory of the CMake project to build.
Path to directory which CMake will use as the root of build directory.
If the directory doesn’t already exist CMake will make it.
Pre-load a script to populate the cache.
When CMake is first run in an empty build tree, it creates a CMakeCache.txt file and populates it with customizable settings for the project. This option may be used to specify a file from which to load cache entries before the first pass through the project’s CMake listfiles. The loaded entries take priority over the project’s default values. The given file should be a CMake script containing set() commands that use the CACHE option, not a cache-format file.
References to CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR within the script evaluate to the top-level source and build tree.
Create or update a CMake CACHE entry.
When CMake is first run in an empty build tree, it creates a CMakeCache.txt file and populates it with customizable settings for the project. This option may be used to specify a setting that takes priority over the project’s default value. The option may be repeated for as many CACHE entries as desired.
If the : portion is given it must be one of the types specified by the set() command documentation for its CACHE signature. If the : portion is omitted the entry will be created with no type if it does not exist with a type already. If a command in the project sets the type to PATH or FILEPATH then the will be converted to an absolute path.
Use with care, you can make your CMakeCache.txt non-working.
Specify a build system generator.
CMake may support multiple native build systems on certain platforms. A generator is responsible for generating a particular build system. Possible generator names are specified in the cmake-generators(7) manual.
If not specified, CMake checks the CMAKE_GENERATOR environment variable and otherwise falls back to a builtin default selection.
Toolset specification for the generator, if supported.
Some CMake generators support a toolset specification to tell the native build system how to choose a compiler. See the CMAKE_GENERATOR_TOOLSET variable for details.
Specify platform name if supported by generator.
Some CMake generators support a platform name to be given to the native build system to choose a compiler or SDK. See the CMAKE_GENERATOR_PLATFORM variable for details.
Specify the cross compiling toolchain file, equivalent to setting CMAKE_TOOLCHAIN_FILE variable.
Specify the installation directory, used by the CMAKE_INSTALL_PREFIX variable. Must be an absolute path.
Suppress developer warnings.
Suppress warnings that are meant for the author of the CMakeLists.txt files. By default this will also turn off deprecation warnings.
Enable developer warnings.
Enable warnings that are meant for the author of the CMakeLists.txt files. By default this will also turn on deprecation warnings.
Make developer warnings errors.
Make warnings that are meant for the author of the CMakeLists.txt files errors. By default this will also turn on deprecated warnings as errors.
Make developer warnings not errors.
Make warnings that are meant for the author of the CMakeLists.txt files not errors. By default this will also turn off deprecated warnings as errors.
Enable deprecated functionality warnings.
Enable warnings for usage of deprecated functionality, that are meant for the author of the CMakeLists.txt files.
Suppress deprecated functionality warnings.
Suppress warnings for usage of deprecated functionality, that are meant for the author of the CMakeLists.txt files.
Make deprecated macro and function warnings errors.
Make warnings for usage of deprecated macros and functions, that are meant for the author of the CMakeLists.txt files, errors.
Make deprecated macro and function warnings not errors.
Make warnings for usage of deprecated macros and functions, that are meant for the author of the CMakeLists.txt files, not errors.
List non-advanced cached variables.
Only load the cache. Do not actually run configure and generate steps.
Generate graphviz of dependencies, see CMakeGraphVizOptions for more.
Generate a graphviz input file that will contain all the library and executable dependencies in the project. See the documentation for CMakeGraphVizOptions for more details.
Dump information about this system.
Dump a wide range of information about the current system. If run from the top of a binary tree for a CMake project it will dump additional information such as the cache, log files etc.
To make a log level persist between CMake runs, set CMAKE_MESSAGE_LOG_LEVEL as a cache variable instead. If both the command line option and the variable are given, the command line option takes precedence.
Enable the message() command outputting context attached to each message.
This option turns on showing context for the current CMake run only. To make showing the context persistent for all subsequent CMake runs, set CMAKE_MESSAGE_CONTEXT_SHOW as a cache variable instead. When this command line option is given, CMAKE_MESSAGE_CONTEXT_SHOW is ignored.
Do not delete the try_compile() build tree. Only useful on one try_compile() at a time.
Do not delete the files and directories created for try_compile() calls. This is useful in debugging failed try_compiles. It may however change the results of the try-compiles as old junk from a previous try-compile may cause a different test to either pass or fail incorrectly. This option is best used for one try-compile at a time, and only when debugging.
Put cmake in a debug mode.
Print extra information during the cmake run like stack traces with message(SEND_ERROR) calls.
Put cmake find commands in a debug mode.
Print extra find call information during the cmake run to standard error. Output is designed for human consumption and not for parsing. See also the CMAKE_FIND_DEBUG_MODE variable for debugging a more local part of the project.
Put cmake in trace mode.
Print a trace of all calls made and from where.
Put cmake in trace mode.
I need to install to a different prefix (for example, to /usr ).
7 Answers 7
You can pass in any CMake variable on the command line, or edit cached variables using ccmake/cmake-gui. On the command line,
Would configure the project, build all targets and install to the /usr prefix. The type (PATH) is not strictly necessary, but would cause the Qt based cmake-gui to present the directory chooser dialog.
Some minor additions as comments make it clear that providing a simple equivalence is not enough for some. Best practice would be to use an external build directory, i.e. not the source directly. Also to use more generic CMake syntax abstracting the generator.
The «:PATH» part in the accepted answer can be omitted. This syntax may be more memorable:
. as used in the answers here.
Note that in both CMake and Autotools you don’t always have to set the installation path at configure time. You can use DESTDIR at install time (see also here) instead as in:
This is intended for staged installs and to allow for storing programs in a different location from where they are run e.g. /etc/alternatives via symbolic links.
However, if your package is relocatable and doesn’t need any hard-coded (prefix) paths set via the configure stage you may be able to skip it. So instead of:
The way I build CMake projects cross platform is the following:
Afterwards I use the installed files to create packages or include them in other projects.
Starting with CMake 3.15, the correct way of achieving this would be using:
Regarding Bruce Adams answer:
Your answer creates dangerous confusion. DESTDIR is intended for installs out of the root tree. It allows one to see what would be installed in the root tree if one did not specify DESTDIR. PREFIX is the base directory upon which the real installation is based.
Importing and Exporting GuideВ¶
IntroductionВ¶
In this guide, we will present the concept of IMPORTED targets and demonstrate how to import existing executable or library files from disk into a CMake project. We will then show how CMake supports exporting targets from one CMake-based project and importing them into another. Finally, we will demonstrate how to package a project with a configuration file to allow for easy integration into other CMake projects. This guide and the complete example source code can be found in the Help/guide/importing-exporting directory of the CMake source code tree.
Importing TargetsВ¶
IMPORTED targets are used to convert files outside of a CMake project into logical targets inside of the project. IMPORTED targets are created using the IMPORTED option of the add_executable() and add_library() commands. No build files are generated for IMPORTED targets. Once imported, IMPORTED targets may be referenced like any other target within the project and provide a convenient, flexible reference to outside executables and libraries.
By default, the IMPORTED target name has scope in the directory in which it is created and below. We can use the GLOBAL option to extended visibility so that the target is accessible globally in the build system.
Importing ExecutablesВ¶
To start, we will walk through a simple example that creates an IMPORTED executable target and then references it from the add_custom_command() command.
Next, set the IMPORTED_LOCATION property of the target using the set_property() command. This will tell CMake the location of the target on disk. The location may need to be adjusted to the location> specified in the previous step.
We can now reference this IMPORTED target just like any target built within the project. In this instance, let’s imagine that we want to use the generated source file in our project. Use the IMPORTED target in the add_custom_command() command:
As COMMAND specifies an executable target name, it will automatically be replaced by the location of the executable given by the IMPORTED_LOCATION property above.
Finally, use the output from add_custom_command() :
Importing LibrariesВ¶
In a similar manner, libraries from other projects may be accessed through IMPORTED targets.
Note: The full source code for the examples in this section is not provided and is left as an exercise for the reader.
In the CMakeLists file, add an IMPORTED library and specify its location on disk:
Then use the IMPORTED library inside of our project:
A library with multiple configurations may be imported with a single target:
The generated build system will link myexe to m.lib when built in the release configuration, and md.lib when built in the debug configuration.
Exporting TargetsВ¶
While IMPORTED targets on their own are useful, they still require that the project that imports them knows the locations of the target files on disk. The real power of IMPORTED targets is when the project providing the target files also provides a CMake file to help import them. A project can be setup to produce the necessary information so that it can easily be used by other CMake projects be it from a build directory, a local install or when packaged.
In the remaining sections, we will walk through a set of example projects step-by-step. The first project will create and install a library and corresponding CMake configuration and package files. The second project will use the generated package.
Let’s start by looking at the MathFunctions project in the Help/guide/importing-exporting/MathFunctions directory. Here we have a header file MathFunctions.h that declares a sqrt function:
And a corresponding source file MathFunctions.cxx :
Don’t worry too much about the specifics of the C++ files, they are just meant to be a simple example that will compile and run on many build systems.
Now we can create a CMakeLists.txt file for the MathFunctions project. Start by specifying the cmake_minimum_required() version and project() name:
The GNUInstallDirs module is included in order to provide the project with the flexibility to install into different platform layouts by making the directories available as cache variables.
Create a library called MathFunctions with the add_library() command:
And then use the target_include_directories() command to specify the include directories for the target:
We need to tell CMake that we want to use different include directories depending on if we’re building the library or using it from an installed location. If we don’t do this, when CMake creates the export information it will export a path that is specific to the current build directory and will not be valid for other projects. We can use generator expressions to specify that if we’re building the library include the current source directory. Otherwise, when installed, include the include directory. See the Creating Relocatable Packages section for more details.
The install(TARGETS) and install(EXPORT) commands work together to install both targets (a library in our case) and a CMake file designed to make it easy to import the targets into another CMake project.
First, in the install(TARGETS) command we will specify the target, the EXPORT name and the destinations that tell CMake where to install the targets.
Note, we have not asked CMake to install the export yet.
We don’t want to forget to install the MathFunctions.h header file with the install(FILES) command. The header file should be installed to the include directory, as specified by the target_include_directories() command above.
The NAMESPACE option will prepend MathFunctions:: to the target names as they are written to the export file. This convention of double-colons gives CMake a hint that the name is an IMPORTED target when it is used by downstream projects. This way, CMake can issue a diagnostic message if the package providing it was not found.
The generated export file contains code that creates an IMPORTED library.
An outside project may load this file with the include() command and reference the MathFunctions library from the installation tree as if it were built in its own tree. For example:
Line 1 loads the target CMake file. Although we only exported a single target, this file may import any number of targets. Their locations are computed relative to the file location so that the install tree may be easily moved. Line 3 references the imported MathFunctions library. The resulting build system will link to the library from its installed location.
Executables may also be exported and imported using the same process.
Any number of target installations may be associated with the same export name. Export names are considered global so any directory may contribute a target installation. The install(EXPORT) command only needs to be called once to install a file that references all targets. Below is an example of how multiple exports may be combined into a single export file, even if they are in different subdirectories of the project.
Creating PackagesВ¶
At this point, the MathFunctions project is exporting the target information required to be used by other projects. We can make this project even easier for other projects to use by generating a configuration file so that the CMake find_package() command can find our project.
To start, we will need to make a few additions to the CMakeLists.txt file. First, include the CMakePackageConfigHelpers module to get access to some helper functions for creating config files.
Then we will create a package configuration file and a package version file.
Creating a Package Configuration FileВ¶
Use the configure_package_config_file() command provided by the CMakePackageConfigHelpers to generate the package configuration file. Note that this command should be used instead of the plain configure_file() command. It helps to ensure that the resulting package is relocatable by avoiding hardcoded paths in the installed configuration file. The path given to INSTALL_DESTINATION must be the destination where the MathFunctionsConfig.cmake file will be installed. We will examine the contents of the package configuration file in the next section.
Install the generated configuration files with the INSTALL(files) command. Both MathFunctionsConfigVersion.cmake and MathFunctionsConfig.cmake are installed to the same location, completing the package.
Now we need to create the package configuration file itself. In this case, the Config.cmake.in file is very simple but sufficient to allow downstreams to use the IMPORTED targets.
The check_required_components helper macro ensures that all requested, non-optional components have been found by checking the
_ _FOUND variables for all required components. This macro should be called at the end of the package configuration file even if the package does not have any components. This way, CMake can make sure that the downstream project hasn’t specified any non-existent components. If check_required_components fails, the
_FOUND variable is set to FALSE, and the package is considered to be not found.
The set_and_check() macro should be used in configuration files instead of the normal set() command for setting directories and file locations. If a referenced file or directory does not exist, the macro will fail.
If any macros should be provided by the MathFunctions package, they should be in a separate file which is installed to the same location as the MathFunctionsConfig.cmake file, and included from there.
All required dependencies of a package must also be found in the package configuration file. Let’s imagine that we require the Stats library in our project. In the CMakeLists file, we would add:
Exercise: Add a required library to the MathFunctions project.
Creating a Package Version FileВ¶
The CMakePackageConfigHelpers module provides the write_basic_package_version_file() command for creating a simple package version file. This file is read by CMake when find_package() is called to determine the compatibility with the requested version, and to set some version-specific variables such as
Exporting Targets from the Build TreeВ¶
Typically, projects are built and installed before being used by an outside project. However, in some cases, it is desirable to export targets directly from a build tree. The targets may then be used by an outside project that references the build tree with no installation involved. The export() command is used to generate a file exporting targets from a project build tree.
If we want our example project to also be used from a build directory we only have to add the following to CMakeLists.txt :
Here we use the export() command to generate the export targets for the build tree. In this case, we’ll create a file called MathFunctionsTargets.cmake in the cmake subdirectory of the build directory. The generated file contains the required code to import the target and may be loaded by an outside project that is aware of the project build tree. This file is specific to the build-tree, and is not relocatable.
It is possible to create a suitable package configuration file and package version file to define a package for the build tree which may be used without installation. Consumers of the build tree can simply ensure that the CMAKE_PREFIX_PATH contains the build directory, or set the MathFunctions_DIR to /MathFunctions in the cache.
An example application of this feature is for building an executable on a host platform when cross-compiling. The project containing the executable may be built on the host platform and then the project that is being cross-compiled for another platform may load it.
Building and Installing a PackageВ¶
At this point, we have generated a relocatable CMake configuration for our project that can be used after the project has been installed. Let’s try to build the MathFunctions project:
In the build directory, notice that the file MathFunctionsTargets.cmake has been created in the cmake subdirectory.
Now install the project:
Creating Relocatable PackagesВ¶
Packages created by install(EXPORT) are designed to be relocatable, using paths relative to the location of the package itself. They must not reference absolute paths of files on the machine where the package is built that will not exist on the machines where the package may be installed.
The referenced variables may contain the absolute paths to libraries and include directories as found on the machine the package was made on. This would create a package with hard-coded paths to dependencies not suitable for relocation.
Ideally such dependencies should be used through their own IMPORTED targets that have their own IMPORTED_LOCATION and usage requirement properties such as INTERFACE_INCLUDE_DIRECTORIES populated appropriately. Those imported targets may then be used with the target_link_libraries() command for MathFunctions :






