CMake/Tutorials/Packaging: Difference between revisions
(Add explicit preformat markup) |
(Remove leading space rectangles from preformatted blocks) |
||
Line 15: | Line 15: | ||
<pre> | <pre> | ||
<prefix>/include/foo-1.2/foo.h | |||
<prefix>/lib/foo-1.2/libfoo.a | |||
</pre> | </pre> | ||
Line 22: | Line 22: | ||
<pre> | <pre> | ||
<prefix>/lib/foo-1.2/foo-config.cmake | |||
</pre> | </pre> | ||
Line 28: | Line 28: | ||
<pre> | <pre> | ||
# ... | |||
# (compute PREFIX relative to file location) | |||
# ... | |||
set(foo_INCLUDE_DIRS ${PREFIX}/include/foo-1.2) | |||
set(foo_LIBRARY ${PREFIX}/lib/foo-1.2/libfoo.a) | |||
</pre> | </pre> | ||
Line 41: | Line 41: | ||
<pre> | <pre> | ||
find_package(Foo) | |||
</pre> | </pre> | ||
Line 49: | Line 49: | ||
<pre> | <pre> | ||
<prefix>/lib/Foo*/ | |||
</pre> | </pre> | ||
Line 65: | Line 65: | ||
<pre> | <pre> | ||
add_library(mylib STATIC mylib.c mylib.h) | |||
install(FILES mylib.h DESTINATION include/myproj) | |||
install(TARGETS mylib EXPORT mylib-targets DESTINATION lib/myproj) | |||
install(EXPORT mylib-targets DESTINATION lib/myproj) | |||
install(FILES myproj-config.cmake DESTINATION lib/myproj) | |||
</pre> | </pre> | ||
Line 75: | Line 75: | ||
<pre> | <pre> | ||
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) | |||
include(${SELF_DIR}/mylib-targets.cmake) | |||
get_filename_component(myproj_INCLUDE_DIRS "${SELF_DIR}/../../include/myproj" ABSOLUTE) | |||
</pre> | </pre> | ||
Line 83: | Line 83: | ||
<pre> | <pre> | ||
find_package(myproj REQUIRED) | |||
include_directories(${myproj_INCLUDE_DIRS}) | |||
add_executable(myexe myexe.c) | |||
target_link_libraries(myexe mylib) | |||
</pre> | </pre> | ||
Line 94: | Line 94: | ||
<pre> | <pre> | ||
find_package(Foo 1.2) | |||
find_package(Bar 4.2 EXACT) | |||
</pre> | </pre> | ||
Line 109: | Line 109: | ||
<pre> | <pre> | ||
<prefix>/lib/foo-1.3/foo-config.cmake | |||
<prefix>/lib/foo-1.3/foo-config-version.cmake | |||
</pre> | </pre> | ||
Line 116: | Line 116: | ||
<pre> | <pre> | ||
<prefix>/lib/bar-4.2/BarConfig.cmake | |||
<prefix>/lib/bar-4.2/BarConfigVersion.cmake | |||
</pre> | </pre> | ||
Line 152: | Line 152: | ||
<pre> | <pre> | ||
PACKAGE_VERSION = full provided version string | |||
PACKAGE_VERSION_EXACT = true if version is exact match | |||
PACKAGE_VERSION_COMPATIBLE = true if version is compatible | |||
PACKAGE_VERSION_UNSUITABLE = true if unsuitable as any version (CMake >= 2.6.3) | |||
</pre> | </pre> | ||
Line 161: | Line 161: | ||
<pre> | <pre> | ||
set(PACKAGE_VERSION 1.3) | |||
if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 1) | |||
set(PACKAGE_VERSION_COMPATIBLE 1) # compatible with any version 1.x | |||
if("${PACKAGE_FIND_VERSION_MINOR}" EQUAL 3) | |||
set(PACKAGE_VERSION_EXACT 1) # exact match for version 1.3 | |||
endif("${PACKAGE_FIND_VERSION_MINOR}" EQUAL 3) | |||
endif("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 1) | |||
</pre> | </pre> | ||
Revision as of 18:33, 24 April 2018
This page documents creation and use of packages that help projects locate each other. These features are distinct from CPack which is meant for creating source and binary distributions and installers.
The find_package
command has been enhanced with features to help find packages without the use of "find" modules (FindXXX.cmake files).
Projects that are aware of CMake may provide a "package configuration file" inside their installation trees.
Naming the file correctly and installing it in a suitable location will allow the find_package
command to find it easily.
See also the CMake Package Registry to help find_package
find packages in arbitrary locations.
Package Configuration Files
Consider a project "Foo" that installs the following files:
<prefix>/include/foo-1.2/foo.h <prefix>/lib/foo-1.2/libfoo.a
It may also provide a CMake package configuration file
<prefix>/lib/foo-1.2/foo-config.cmake
with content such as
# ... # (compute PREFIX relative to file location) # ... set(foo_INCLUDE_DIRS ${PREFIX}/include/foo-1.2) set(foo_LIBRARY ${PREFIX}/lib/foo-1.2/libfoo.a)
If another project wishes to use Foo it need only to locate the foo-config.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 configuration file:
find_package(Foo)
This command (assuming no FindFoo.cmake
module exists) 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, but one place it looks is
<prefix>/lib/Foo*/
where "Foo*
" is a case-insensitive globbing expression.
In our example the globbing expression will match "<prefix>/lib/foo-1.2
" and the configuration file will be found.
Note: If your project does not already have a <prefix>/lib/Foo*/
directory you may prefer to put the package file in <prefix>/lib/cmake/Foo*/
to keep the lib
directory clean. However, CMake 2.6.2 and lower do not search there. CMake 2.6.3 and above do.
Once found, a package configuration file is immediately loaded. It contains all the information the project needs to use the package.
Packaging and Exporting
Package configuration files may also work in conjunction with Exporting and Importing Targets. For example, a project might write
add_library(mylib STATIC mylib.c mylib.h) install(FILES mylib.h DESTINATION include/myproj) install(TARGETS mylib EXPORT mylib-targets DESTINATION lib/myproj) install(EXPORT mylib-targets DESTINATION lib/myproj) install(FILES myproj-config.cmake DESTINATION lib/myproj)
where myproj-config.cmake
contains something like
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) include(${SELF_DIR}/mylib-targets.cmake) get_filename_component(myproj_INCLUDE_DIRS "${SELF_DIR}/../../include/myproj" ABSOLUTE)
After the project is built and installed, an outside project may use it by writing
find_package(myproj REQUIRED) include_directories(${myproj_INCLUDE_DIRS}) add_executable(myexe myexe.c) target_link_libraries(myexe mylib)
Package Version Files
The find_package
command offers a version request argument. One might write
find_package(Foo 1.2) find_package(Bar 4.2 EXACT)
in order to get a version of package Foo
that is compatible with version 1.2 and exactly package Bar
version 4.2.
CMake does not attempt to define any convention for the compatibility or exactness of version numbers for a package.
It also does not try to map the version number to a directory or file name.
Instead packages must provide "version" files next to their package configuration files.
This allows maximum flexibility for project authors and package maintainers.
A package version file is placed next to the package configuration file.
Its name matches that of the configuration file but has either "-version
" or "Version
" appended to the name before the ".cmake
" extension.
For example, the files
<prefix>/lib/foo-1.3/foo-config.cmake <prefix>/lib/foo-1.3/foo-config-version.cmake
and
<prefix>/lib/bar-4.2/BarConfig.cmake <prefix>/lib/bar-4.2/BarConfigVersion.cmake
are each pairs of package configuration files and corresponding version files.
When the find_package
command finds a candidate package configuration file it looks next to it for a version file.
The version file is loaded to test whether the package version is an acceptable match for the version requested.
If the version file claims compatibility the configuration file is accepted. Otherwise it is ignored.
When the find_package
command loads a version file it first sets the following variables:
CMake 2.6.2 and Above | CMake 2.6.0 and 2.6.1 |
---|---|
PACKAGE_FIND_NAME = the <package> name PACKAGE_FIND_VERSION = full requested version string PACKAGE_FIND_VERSION_MAJOR = major version if requested, else 0 PACKAGE_FIND_VERSION_MINOR = minor version if requested, else 0 PACKAGE_FIND_VERSION_PATCH = patch version if requested, else 0 PACKAGE_FIND_VERSION_TWEAK = tweak version if requested, else 0 PACKAGE_FIND_VERSION_COUNT = number of version components, 0 to 4 |
PACKAGE_FIND_NAME = the <package> name PACKAGE_FIND_VERSION = full requested version string PACKAGE_FIND_VERSION_MAJOR = requested major version, if any PACKAGE_FIND_VERSION_MINOR = requested minor version, if any PACKAGE_FIND_VERSION_PATCH = requested patch version, if any |
The version file must use these variables to check whether it is compatible or an exact match for the requested version. It sets the following variables with results:
PACKAGE_VERSION = full provided version string PACKAGE_VERSION_EXACT = true if version is exact match PACKAGE_VERSION_COMPATIBLE = true if version is compatible PACKAGE_VERSION_UNSUITABLE = true if unsuitable as any version (CMake >= 2.6.3)
For example, foo-config-version.cmake
might contain
set(PACKAGE_VERSION 1.3) if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 1) set(PACKAGE_VERSION_COMPATIBLE 1) # compatible with any version 1.x if("${PACKAGE_FIND_VERSION_MINOR}" EQUAL 3) set(PACKAGE_VERSION_EXACT 1) # exact match for version 1.3 endif("${PACKAGE_FIND_VERSION_MINOR}" EQUAL 3) endif("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 1)
if it is compatible with all "1.x
" versions of Foo and exactly matches version "1.3
".
Note that the input variable names all start in "PACKAGE_FIND_
" and the output variable names all start in "PACKAGE_
".
The names are fixed and do not vary with the package name.
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:
CMake 2.6.2 and Above | CMake 2.6.0 and 2.6.1 |
---|---|
<package>_VERSION = full provided version string <package>_VERSION_MAJOR = major version if provided, else 0 <package>_VERSION_MINOR = minor version if provided, else 0 <package>_VERSION_PATCH = patch version if provided, else 0 <package>_VERSION_TWEAK = tweak version if provided, else 0 <package>_VERSION_COUNT = number of version components, 0 to 4 |
<package>_VERSION = package version (major[.minor[.patch]]) <package>_VERSION_MAJOR = major from major[.minor[.patch]], if any <package>_VERSION_MINOR = minor from major[.minor[.patch]], if any <package>_VERSION_PATCH = patch from major[.minor[.patch]], if any |
The variables report the version of the package that was actually found.
The "<package>
" part of their name matches the argument given to the find_package
command.