- Using Dependencies Guide¶
- Introduction¶
- Libraries providing Config-file packages¶
- Imported Targets from Packages¶
- Libraries not Providing Config-file Packages¶
- Cmake find package linux
- Структура CMakeLists.txt
- Автогенерация проекта для Visual Studio (Windows)
- Зависимости между библиотеками и приложениями
- Выбор стандарта и диалекта C++
- Функции в CMake
- Добавление исходников к цели с target_sources
- Интерфейс к утилитам командной строки
- Функция find_package
- cmake-packages(7)В¶
- Introduction¶
- Using Packages¶
- Config-file Packages¶
- Find-module Packages¶
- Package Layout¶
- Package Configuration File¶
- Creating Packages¶
- Creating a Package Configuration File¶
- Creating a Package Configuration File for the Build Tree¶
- Creating Relocatable Packages¶
- Package Registry¶
- User Package Registry¶
- System Package Registry¶
- Disabling the Package Registry¶
- Package Registry Example¶
- Package Registry Ownership¶
Using Dependencies Guide¶
Introduction¶
For developers wishing to use CMake to consume a third party binary package, there are multiple possibilities regarding how to optimally do so, depending on how CMake-aware the third-party library is.
CMake files provided with a software package contain instructions for finding each build dependency. Some build dependencies are optional in that the build may succeed with a different feature set if the dependency is missing, and some dependencies are required. CMake searches well-known locations for each dependency, and the provided software may supply additional hints or locations to CMake to find each dependency.
If a required dependency is not found by cmake(1) , the cache is populated with an entry which contains a NOTFOUND value. This value can be replaced by specifying it on the command line, or in the ccmake(1) or cmake-gui(1) tool. See the User Interaction Guide for more about setting cache entries.
Libraries providing Config-file packages¶
The most convenient way for a third-party to provide library binaries for use with CMake is to provide Config-file Packages . These packages are text files shipped with the library which instruct CMake how to use the library binaries and associated headers, helper tools and CMake macros provided by the library.
The config files can usually be found in a directory whose name matches the pattern lib/cmake/
, though they may be in other locations instead. The
corresponds to use in CMake code with the find_package() command such as find_package(PackageName REQUIRED) .
directory will contain a file which is either named
-config.cmake . This is the entry point to the package for CMake. A separate optional file named
ConfigVersion.cmake may also exist in the directory. This file is used by CMake to determine whether the version of the third party package satisfies uses of the find_package() command which specify version constraints. It is optional to specify a version when using find_package() , even if a ConfigVersion file is present.
If the Config.cmake file is found and the optionally-specified version is satisfied, then the CMake find_package() command considers the package to be found and the entire library package is assumed to be complete as designed.
There may be additional files providing CMake macros or Imported Targets for you to use. CMake does not enforce any naming convention for these files. They are related to the primary Config file by use of the CMake include() command.
Invoking CMake with the intent of using a package of third party binaries requires that cmake find_package() commands succeed in finding the package. If the location of the package is in a directory known to CMake, the find_package() call should succeed. The directories known to cmake are platform-specific. For example, packages installed on Linux with a standard system package manager will be found in the /usr prefix automatically. Packages installed in Program Files on Windows will similarly be found automatically.
Packages which are not found automatically are in locations not predictable to CMake such as /opt/mylib or $HOME/dev/prefix . This is a normal situation and CMake provides several ways for users to specify where to find such libraries.
The CMAKE_PREFIX_PATH variable may be set when invoking CMake . It is treated as a list of paths to search for Config-file Packages . A package installed in /opt/somepackage will typically install config files such as /opt/somepackage/lib/cmake/somePackage/SomePackageConfig.cmake . In that case, /opt/somepackage should be added to CMAKE_PREFIX_PATH .
The environment variable CMAKE_PREFIX_PATH may also be populated with prefixes to search for packages. Like the PATH environment variable, this is a list and needs to use the platform-specific environment variable list item separator ( : on Unix and ; on Windows).
The CMAKE_PREFIX_PATH variable provides convenience in cases where multiple prefixes need to be specified, or when multiple different package binaries are available in the same prefix. Paths to packages may also be specified by setting variables matching
_DIR , such as SomePackage_DIR . Note that this is not a prefix but should be a full path to a directory containing a config-style package file, such as /opt/somepackage/lib/cmake/SomePackage/ in the above example.
Imported Targets from Packages¶
A third-party package which provides config-file packages may also provide Imported Targets . These will be specified in files containing configuration-specific file paths relevant to the package, such as debug and release versions of libraries.
Often the third-party package documentation will point out the names of imported targets available after a successful find_package for a library. Those imported target names can be used with the target_link_libraries() command.
A complete example which makes a simple use of a third party library might look like:
See cmake-buildsystem(7) for further information about developing a CMake buildsystem.
Libraries not Providing Config-file Packages¶
Third-party libraries which do not provide config-file packages can still be found with the find_package() command, if a FindSomePackage.cmake file is available.
These module-file packages are different to config-file packages in that:
They should not be provided by the third party, except perhaps in the form of documentation
The availability of a Find
.cmake file does not indicate the availability of the binaries themselves.
CMake does not search the CMAKE_PREFIX_PATH for Find
.cmake files. Instead CMake searches for such files in the CMAKE_MODULE_PATH variable. It is common for users to set the CMAKE_MODULE_PATH when running CMake, and it is common for CMake projects to append to CMAKE_MODULE_PATH to allow use of local module-file packages.
CMake ships Find
.cmake files for some third party packages for convenience in cases where the third party does not provide config-file packages directly. These files are a maintenance burden for CMake, so new Find modules are generally not added to CMake anymore. Third-parties should provide config file packages instead of relying on a Find module to be provided by CMake.
Module-file packages may also provide Imported Targets . A complete example which finds such a package might look like:
_ROOT variable is also searched as a prefix for find_package() calls using module-file packages such as FindSomePackage .
Источник
Cmake find package linux
На первом шаге проект нужно сконфигурировать, то есть создать финальный скрипт сборки, запустив cmake в будущем каталоге сборки.
На втором шаге нужно запустить финальный скрипт. Не вызывайте make ! Утилита cmake сделает это сама:
Структура CMakeLists.txt
В начале главного файла CMakeLists.txt ставят метаинформацию о минимальной версии CMake и названии проекта:
Затем следует список инструкций, служащих для вычисления различных переменных, создания целей сборки, подключения проектов из подкаталогов и так далее. Например, подключить дополнительный CMakeLists.txt из подкаталога можно так:
Целью может стать исполняемый файл, собираемый из исходного кода
Целью также может быть библиотека, статическая или динамическая.
Автогенерация проекта для Visual Studio (Windows)
Если используется Visual C++, то путь немного другой: на шаге конфигурирования создаётся проект для Visual Studio, который затем можно собрать из IDE либо так же из командной строки.
Созданный проект Visual Studio нельзя изменять и использовать постоянно, потому что при генерации проекта используются абсолютные пути и другие неприемлемые для постоянной работы вещи.
Если проект был сконфигурирован успешно, то в каталоге ../myapp-build появятся автоматически сгенерированный BUILD_ALL.sln и проекты для Visual Studio. Их можно открыть к IDE, либо собрать из командной строки с помощью cmake. Названия опций говорят сами за себя:
Зависимости между библиотеками и приложениями
Не используйте директивы include_directories , add_definitions , add_compile_options ! Они меняют глобальные настройки для всех целей, это создаёт проблемы при масштабировании.
- Используйте target_link_libraries для добавления статических и динамических библиотек, от которых зависит цель
- Используйте target_include_directories вместо include_directories для добавления путей поиска заголовков, от которых зависит цель
- Используйте target_compile_definitions вместо add_definitions для добавления макросов, с которыми собирается цель
- Используйте target_compile_options для добавления специфичных флагов компилятора, с которыми собирается цель
Вы можете выбирать область видимости настройки:
- PUBLIC делает настройку видимой для текущей цели и для всех зависящих от неё целей
- PRIVATE делает настройку видимой только для текущей цели
- INTERFACE делает настройку видимой только для всех зависящих от неё целей
Пример использования областей видимости:
Схема зависимостей условного проекта:
Выбор стандарта и диалекта C++
Для настройки стандарта и флагов языка C++ не добавляйте флаги напрямую!
В CMake версии 3.8+ вы можете прямо потребовать включить нужный стандарт:
В CMake версии до 3.7 включительно можно использовать set_target_properties (если не работает, то у вас слишком старый CMake):
Для разработчиков библиотек есть более тонкий контроль над возможностями языка:
Функции в CMake
CMake позволяет объявлять функции командами function(name) / endfunction() и макросы командами macro(name) / endmacro() . Предпочитайте функции, а не макросы, т.к. у функций есть своя область видимости переменных, а у макросов — нет.
Добавление исходников к цели с target_sources
Лучше добавлять специфичные исходники с помощью target_sources, а не с помощью дополнительных переменных.
Интерфейс к утилитам командной строки
Функция find_package
Функция find_package принимает имя библиотеки как аргумент и обращается к CMake, чтобы найти скрипт для настройки переменных данной библиотеки. В итоге при сборке либо возникает ошибка из-за того что пакет не найден, либо добавляются переменные, хранящие пути поиска заголовков, имена библиотек для компоновщика и другие параметры.
Пример подключения Boost, вызывающего встроенный в CMake скрипт FindBoost:
Пример подключения библиотеки Bullet с помощью встроенного скрипта FindBullet и компоновки с приложением my_app:
Источник
cmake-packages(7)В¶
Introduction¶
Packages provide dependency information to CMake based buildsystems. Packages are found with the find_package() command. The result of using find_package() is either a set of IMPORTED targets, or a set of variables corresponding to build-relevant information.
Using Packages¶
CMake provides direct support for two forms of packages, Config-file Packages and Find-module Packages. Indirect support for pkg-config packages is also provided via the FindPkgConfig module. In all cases, the basic form of find_package() calls is the same:
In cases where it is known that a package configuration file is provided by upstream, and only that should be used, the CONFIG keyword may be passed to find_package() :
Similarly, the MODULE keyword says to use only a find-module:
Specifying the type of package explicitly improves the error message shown to the user if it is not found.
Both types of packages also support specifying components of a package, either after the REQUIRED keyword:
or as a separate COMPONENTS list:
or as a separate OPTIONAL_COMPONENTS list:
Handling of COMPONENTS and OPTIONAL_COMPONENTS is defined by the package.
variable to TRUE , the
package will not be searched, and will always be NOTFOUND .
Config-file Packages¶
A config-file package is a set of files provided by upstreams for downstreams to use. CMake searches in a number of locations for package configuration files, as described in the find_package() documentation. The most simple way for a CMake user to tell cmake(1) to search in a non-standard prefix for a package is to set the CMAKE_PREFIX_PATH cache variable.
Config-file packages are provided by upstream vendors as part of development packages, that is, they belong with the header files and any other files provided to assist downstreams in using the package.
A set of variables which provide package status information are also set automatically when using a config-file package. The
_FOUND variable is set to true or false, depending on whether the package was found. The
_DIR cache variable is set to the location of the package configuration file.
Find-module Packages¶
A find module is a file with a set of rules for finding the required pieces of a dependency, primarily header files and libraries. Typically, a find module is needed when the upstream is not built with CMake, or is not CMake-aware enough to otherwise provide a package configuration file. Unlike a package configuration file, it is not shipped with upstream, but is used by downstream to find the files by guessing locations of files with platform-specific hints.
Unlike the case of an upstream-provided package configuration file, no single point of reference identifies the package as being found, so the
_FOUND variable is not automatically set by the find_package() command. It can still be expected to be set by convention however and should be set by the author of the Find-module. Similarly there is no
_DIR variable, but each of the artifacts such as library locations and header file locations provide a separate cache variable.
See the cmake-developer(7) manual for more information about creating Find-module files.
Package Layout¶
A config-file package consists of a Package Configuration File and optionally a Package Version File provided with the project distribution.
Package Configuration File¶
Consider a project Foo that installs the following files:
It may also provide a CMake package configuration file:
with content defining IMPORTED targets, or defining variables, such as:
If another project wishes to use Foo it need only to locate the FooConfig.cmake file and load it to get all the information it needs about package content locations. Since the package configuration file is provided by the package installation it already knows all the file locations.
The find_package() command may be used to search for the package configuration file. This command constructs a set of installation prefixes and searches under each prefix in several locations. Given the name Foo , it looks for a file called FooConfig.cmake or foo-config.cmake . The full set of locations is specified in the find_package() command documentation. One place it looks is:
where Foo* is a case-insensitive globbing expression. In our example the globbing expression will match
are each pairs of package configuration files and corresponding package version files.
When the find_package() command loads a version file it first sets the following variables:
Full requested version string
Major version if requested, else 0
Minor version if requested, else 0
Patch version if requested, else 0
Tweak version if requested, else 0
Number of version components, 0 to 4
The version file must use these variables to check whether it is compatible or an exact match for the requested version and set the following variables with results:
Full provided version string
True if version is exact match
True if version is compatible
True if unsuitable as any version
Version files are loaded in a nested scope so they are free to set any variables they wish as part of their computation. The find_package command wipes out the scope when the version file has completed and it has checked the output variables. When the version file claims to be an acceptable match for the requested version the find_package command sets the following variables for use by the project:
Full provided version string
Major version if provided, else 0
Minor version if provided, else 0
Patch version if provided, else 0
Tweak version if provided, else 0
Number of version components, 0 to 4
The variables report the version of the package that was actually found. The
part of their name matches the argument given to the find_package() command.
Creating Packages¶
Usually, the upstream depends on CMake itself and can use some CMake facilities for creating the package files. Consider an upstream which provides a single shared library:
The CMakePackageConfigHelpers module provides a macro for creating a simple ConfigVersion.cmake file. This file sets the version of the package. It is read by CMake when find_package() is called to determine the compatibility with the requested version, and to set some version-specific variables
_VERSION_MINOR etc. The install(EXPORT) command is used to export the targets in the ClimbingStatsTargets export-set, defined previously by the install(TARGETS) command. This command generates the ClimbingStatsTargets.cmake file to contain IMPORTED targets, suitable for use by downstreams and arranges to install it to lib/cmake/ClimbingStats . The generated ClimbingStatsConfigVersion.cmake and a cmake/ClimbingStatsConfig.cmake are installed to the same location, completing the package.
The generated IMPORTED targets have appropriate properties set to define their usage requirements , such as INTERFACE_INCLUDE_DIRECTORIES , INTERFACE_COMPILE_DEFINITIONS and other relevant built-in INTERFACE_ properties. The INTERFACE variant of user-defined properties listed in COMPATIBLE_INTERFACE_STRING and other Compatible Interface Properties are also propagated to the generated IMPORTED targets. In the above case, ClimbingStats_MAJOR_VERSION is defined as a string which must be compatible among the dependencies of any depender. By setting this custom defined user property in this version and in the next version of ClimbingStats , cmake(1) will issue a diagnostic if there is an attempt to use version 3 together with version 4. Packages can choose to employ such a pattern if different major versions of the package are designed to be incompatible.
A NAMESPACE with double-colons is specified when exporting the targets for installation. This convention of double-colons gives CMake a hint that the name is an IMPORTED target when it is used by downstreams with the target_link_libraries() command. This way, CMake can issue a diagnostic if the package providing it has not yet been found.
In this case, when using install(TARGETS) the INCLUDES DESTINATION was specified. This causes the IMPORTED targets to have their INTERFACE_INCLUDE_DIRECTORIES populated with the include directory in the CMAKE_INSTALL_PREFIX . When the IMPORTED target is used by downstream, it automatically consumes the entries from that property.
Creating a Package Configuration File¶
In this case, the ClimbingStatsConfig.cmake file could be as simple as:
As this allows downstreams to use the IMPORTED targets. If any macros should be provided by the ClimbingStats package, they should be in a separate file which is installed to the same location as the ClimbingStatsConfig.cmake file, and included from there.
This can also be extended to cover dependencies:
As the Stats::Types target is a PUBLIC dependency of ClimbingStats , downstreams must also find the Stats package and link to the Stats::Types library. The Stats package should be found in the ClimbingStatsConfig.cmake file to ensure this. The find_dependency macro from the CMakeFindDependencyMacro helps with this by propagating whether the package is REQUIRED , or QUIET etc. All REQUIRED dependencies of a package should be found in the Config.cmake file:
The find_dependency macro also sets ClimbingStats_FOUND to False if the dependency is not found, along with a diagnostic that the ClimbingStats package can not be used without the Stats package.
If COMPONENTS are specified when the downstream uses find_package() , they are listed in the
_FIND_COMPONENTS variable. If a particular component is non-optional, then the
_FIND_REQUIRED_ will be true. This can be tested with logic in the package configuration file:
Here, the ClimbingStats_NOT_FOUND_MESSAGE is set to a diagnosis that the package could not be found because an invalid component was specified. This message variable can be set for any case where the _FOUND variable is set to False , and will be displayed to the user.
Creating a Package Configuration File for the Build Tree¶
The export(EXPORT) command creates an IMPORTED targets definition file which is specific to the build-tree, and is not relocatable. This can similarly be used with 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 ClimbingStats_DIR to /ClimbingStats in the cache.
Creating Relocatable Packages¶
A relocatable package 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.
Packages created by install(EXPORT) are designed to be relocatable, using paths relative to the location of the package itself. When defining the interface of a target for EXPORT , keep in mind that the include directories should be specified as relative paths which are relative to the CMAKE_INSTALL_PREFIX :
The $ generator expression may be used as a placeholder for the install prefix without resulting in a non-relocatable package. This is necessary if complex generator expressions are used:
This also applies to paths referencing external dependencies. It is not advisable to populate any properties which may contain paths, such as INTERFACE_INCLUDE_DIRECTORIES and INTERFACE_LINK_LIBRARIES , with paths relevant to dependencies. For example, this code may not work well for a relocatable package:
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 and 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 ClimbingStats :
With this approach the package references its external dependencies only through the names of IMPORTED targets . When a consumer uses the installed package, the consumer will run the appropriate find_package() commands (via the find_dependency macro described above) to find the dependencies and populate the imported targets with appropriate paths on their own machine.
Unfortunately many modules shipped with CMake do not yet provide IMPORTED targets because their development pre-dated this approach. This may improve incrementally over time. Workarounds to create relocatable packages using such modules include:
When building the package, specify each Foo_LIBRARY cache entry as just a library name, e.g. -DFoo_LIBRARY=foo . This tells the corresponding find module to populate the Foo_LIBRARIES with just foo to ask the linker to search for the library instead of hard-coding a path.
Or, after installing the package content but before creating the package installation binary for redistribution, manually replace the absolute paths with placeholders for substitution by the installation tool when the package is installed.
Package Registry¶
CMake provides two central locations to register packages that have been built or installed anywhere on a system:
The registries are especially useful to help projects find packages in non-standard install locations or directly in their own build trees. A project may populate either the user or system registry (using its own means, see below) to refer to its location. In either case the package should store at the registered location a Package Configuration File (
Config.cmake ) and optionally a Package Version File (
The find_package() command searches the two package registries as two of the search steps specified in its documentation. If it has sufficient permissions it also removes stale package registry entries that refer to directories that do not exist or do not contain a matching package configuration file.
User Package Registry¶
The User Package Registry is stored in a per-user location. The export(PACKAGE) command may be used to register a project build tree in the user package registry. CMake currently provides no interface to add install trees to the user package registry. Installers must be manually taught to register their packages if desired.
On Windows the user package registry is stored in the Windows registry under a key in HKEY_CURRENT_USER .
may appear under registry key:
as a REG_SZ value, with arbitrary name, that specifies the directory containing the package configuration file.
On UNIX platforms the user package registry is stored in the user home directory under
may appear under the directory:
as a file, with arbitrary name, whose content specifies the directory containing the package configuration file.
System Package Registry¶
The System Package Registry is stored in a system-wide location. CMake currently provides no interface to add to the system package registry. Installers must be manually taught to register their packages if desired.
On Windows the system package registry is stored in the Windows registry under a key in HKEY_LOCAL_MACHINE . A
may appear under registry key:
as a REG_SZ value, with arbitrary name, that specifies the directory containing the package configuration file.
There is no system package registry on non-Windows platforms.
Disabling the Package Registry¶
In some cases using the Package Registries is not desirable. CMake allows one to disable them using the following variables:
The export(PACKAGE) command does not populate the user package registry when CMP0090 is set to NEW unless the CMAKE_EXPORT_PACKAGE_REGISTRY variable explicitly enables it. When CMP0090 is not set to NEW then export(PACKAGE) populates the user package registry unless the CMAKE_EXPORT_NO_PACKAGE_REGISTRY variable explicitly disables it.
CMAKE_FIND_USE_PACKAGE_REGISTRY disables the User Package Registry in all the find_package() calls when set to FALSE .
Deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY disables the User Package Registry in all the find_package() calls when set to TRUE . This variable is ignored when CMAKE_FIND_USE_PACKAGE_REGISTRY has been set.
Package Registry Example¶
A simple convention for naming package registry entries is to use content hashes. They are deterministic and unlikely to collide ( export(PACKAGE) uses this approach). The name of an entry referencing a specific directory is simply the content hash of the directory path itself.
If a project arranges for package registry entries to exist, such as:
then the CMakeLists.txt code:
will search the registered locations for package configuration files ( MyPackageConfig.cmake ). The search order among package registry entries for a single package is unspecified and the entry names (hashes in this example) have no meaning. Registered locations may contain package version files ( MyPackageConfigVersion.cmake ) to tell find_package() whether a specific location is suitable for the version requested.
Package Registry Ownership¶
Package registry entries are individually owned by the project installations that they reference. A package installer is responsible for adding its own entry and the corresponding uninstaller is responsible for removing it.
The export(PACKAGE) command populates the user package registry with the location of a project build tree. Build trees tend to be deleted by developers and have no «uninstall» event that could trigger removal of their entries. In order to keep the registries clean the find_package() command automatically removes stale entries it encounters if it has sufficient permissions. CMake provides no interface to remove an entry referencing an existing build tree once export(PACKAGE) has been invoked. However, if the project removes its package configuration file from the build tree then the entry referencing the location will be considered stale.
Источник