|
|
The CMake Policy mechanism provides backwards compatibility as a
|
|
|
first-class feature.
|
|
|
|
|
|
This page provides information intended for use by project developers to
|
|
|
help update their projects to deal with new policies.
|
|
|
|
|
|
# Motivation
|
|
|
|
|
|
CMake is an evolving project. The developers strive to support existing
|
|
|
projects as much as possible as changes are made. Unfortunately there
|
|
|
are some cases where it is not possible to fix bugs and preserve
|
|
|
backwards compatibility at the same time. We give some examples here.
|
|
|
|
|
|
## Fixing an Interface Breaks Work-Arounds
|
|
|
|
|
|
Consider the `add_definitions` command:
|
|
|
|
|
|
add_definitions(-DFOO)
|
|
|
|
|
|
When originally introduced the command was intended only to add simple
|
|
|
definitions. Its implementation was simply to pass its arguments on to
|
|
|
the compiler's command line. Since CMake supports configured header
|
|
|
files using the `configure_file` command it is not necessary to pass
|
|
|
complicated definitions on compile command lines. However, some project
|
|
|
authors tried to do so anyway with code like
|
|
|
|
|
|
add_definitions("-DFOO=\"some string\"")
|
|
|
|
|
|
but found that it did not work. The string
|
|
|
|
|
|
-DFOO="some string"
|
|
|
|
|
|
would appear on the command line and the compiler would receive a
|
|
|
definition equivalent to
|
|
|
|
|
|
#define FOO some string
|
|
|
|
|
|
Some authors proceeded to work around the problem by adding escape
|
|
|
sequences manually:
|
|
|
|
|
|
add_definitions("-DFOO=\"\\\"some string\\\"\"")
|
|
|
|
|
|
The escape sequences work for some native build tools (such as Unix
|
|
|
Makefiles) but not others. The proper way to deal with this issue was to
|
|
|
fix the implementation in CMake to actually produce the correct escape
|
|
|
sequences for each native build tool automatically.
|
|
|
|
|
|
Unfortunately introducing the fix would break existing projects that add
|
|
|
their own escape sequences because the escapes themselves would be
|
|
|
escaped. In order to support such projects no fix was introduced for
|
|
|
years. This allowed many more projects to continue to suffer from the
|
|
|
problem and add their own work-arounds which must now also be supported.
|
|
|
|
|
|
This problem with `add_definitions` is an example of a class of
|
|
|
problems: how are we to fix an interface without breaking work-arounds
|
|
|
for the very problem being fixed? The policy mechanism is a solution to
|
|
|
this problem.
|
|
|
|
|
|
## Changing an Implementation Breaks Projects Building Accidentally
|
|
|
|
|
|
When using CMake 2.4 or below projects may write this (wrong) code and
|
|
|
it works by accident:
|
|
|
|
|
|
add_executable(myexe myexe.c)
|
|
|
target_link_libraries(myexe /path/to/libA.so B)
|
|
|
|
|
|
where "`B`" is meant to link "`/path/to/libB.so`". This code is
|
|
|
incorrect because it asks CMake to link to `B` but does not provide the
|
|
|
proper linker search path for it. The correct code would be
|
|
|
|
|
|
link_directories(/path/to)
|
|
|
add_executable(myexe myexe.c)
|
|
|
target_link_libraries(myexe /path/to/libA.so B)
|
|
|
|
|
|
or even better
|
|
|
|
|
|
add_executable(myexe myexe.c)
|
|
|
target_link_libraries(myexe /path/to/libA.so /path/to/libB.so)
|
|
|
|
|
|
CMake 2.4 implemented the link to library A partly by adding
|
|
|
`-L/path/to` to the linker command line. This allowed library B to be
|
|
|
found even though no linker search path was provided for it. CMake 2.6
|
|
|
implements linking to library A by passing `/path/to/libA.so` directly
|
|
|
to the linker as a path. This leaves out the `-L/path/to` which may
|
|
|
prevent library B from being found.
|
|
|
|
|
|
While the code above leading to this problem is technically wrong it
|
|
|
worked with a previous CMake release and needs to be supported.
|
|
|
Therefore CMake 2.6 has support for passing the directories containing
|
|
|
libraries whose full paths are known as linker search paths even though
|
|
|
they are not needed for correct user code. Full compatibility would
|
|
|
require us to support this behavior by default forever. That would allow
|
|
|
new projects to be written with the same bug.
|
|
|
|
|
|
This problem is an example of a class of problems: how are we to fix an
|
|
|
implementation without breaking projects depending on undocumented
|
|
|
details of the original implementation? The policy mechanism is a
|
|
|
solution to this problem.
|
|
|
|
|
|
# Design Goals
|
|
|
|
|
|
The design goals for the CMake Policy mechanism were as follows:
|
|
|
|
|
|
1. **Existing projects should build with versions of CMake newer than
|
|
|
that used by the project authors**
|
|
|
- Users should not need to edit code to get the projects to build
|
|
|
- Warnings may be issued but the projects should build
|
|
|
2. **Correctness of new interfaces or bugs fixed in old ones should not
|
|
|
be inhibited by compatibility requirements**
|
|
|
- Any reduction in correctness of the latest interface is not fair
|
|
|
to new projects
|
|
|
3. **Every change to CMake that may require changes to project code
|
|
|
should be documented**
|
|
|
- Each change should also have a unique identifier that can be
|
|
|
referenced by warning and error messages
|
|
|
- The new behavior is enabled only when the project has somehow
|
|
|
indicated it is supported
|
|
|
4. **We must be able to eventually remove code implementing
|
|
|
compatibility with ancient CMake versions**
|
|
|
- Such removal is necessary to keep the code clean and allow
|
|
|
internal refactoring
|
|
|
- After such removal attempts to build projects written for
|
|
|
ancient versions must fail with an informative message
|
|
|
|
|
|
# Solution
|
|
|
|
|
|
We've introduced the notion of a **policy** for dealing with changes in
|
|
|
CMake behavior. Each policy has
|
|
|
|
|
|
- A name of the form **`CMP`*`NNNN`*** where *NNNN* is an integer
|
|
|
identifier
|
|
|
- **OLD** behavior that preserves compatibility with earlier versions
|
|
|
of CMake
|
|
|
- **NEW** behavior that is considered correct and preferred for use by
|
|
|
new projects
|
|
|
- Documentation detailing the motivation for the change and the OLD
|
|
|
and NEW behaviors
|
|
|
|
|
|
Projects may configure the setting of each policy to request OLD or NEW
|
|
|
behavior. When CMake encounters user code that may be affected by a
|
|
|
particular policy it checks to see whether the project has set the
|
|
|
policy. If the policy has been set (to OLD or NEW) then CMake follows
|
|
|
the behavior specified. If the policy has not been set then the old
|
|
|
behavior is used but a warning is produced telling the project author to
|
|
|
set the policy.
|
|
|
|
|
|
## Setting Policies by CMake Version
|
|
|
|
|
|
In most cases a project release should simply set a *policy version*
|
|
|
corresponding to the release version of CMake for which the project is
|
|
|
written. Setting the policy version requests NEW behavior for all
|
|
|
policies introduced in the corresponding version of CMake or earlier.
|
|
|
Policies introduced in later versions are marked as not set in order to
|
|
|
produce proper warning messages.
|
|
|
|
|
|
The policy version is set using the `cmake_policy` command's `VERSION`
|
|
|
signature. For example, the code
|
|
|
|
|
|
cmake_policy(VERSION 2.6)
|
|
|
|
|
|
will request NEW behavior for all policies introduced in CMake 2.6 or
|
|
|
earlier. The `cmake_minimum_required` command will also set the policy
|
|
|
version which is convenient for use at the top of projects. A project
|
|
|
should typically begin with the lines
|
|
|
|
|
|
cmake_minimum_required(VERSION 2.6)
|
|
|
project(MyProject)
|
|
|
# ...code using CMake 2.6 policies
|
|
|
|
|
|
Of course one should replace "`2.6`" with a higher version as necessary.
|
|
|
|
|
|
When a new version of CMake is released that introduces new policies it
|
|
|
will still build old projects because they do not request NEW behavior
|
|
|
for any of the new policies. When starting a new project one should
|
|
|
always specify the most recent release of CMake to be supported as the
|
|
|
policy version level. This will make sure that the project is written to
|
|
|
work using policies from that version of CMake and not using any old
|
|
|
behavior.
|
|
|
|
|
|
Policy CMP0000 has been introduced to require all projects to specify a
|
|
|
policy version in their top-level CMakeLists.txt file. If no policy
|
|
|
version is set CMake will warn and assume a policy version of 2.4. This
|
|
|
allows existing projects that do not specify `cmake_minimum_required` to
|
|
|
build as they would have with CMake 2.4.
|
|
|
|
|
|
## Setting Policies Individually
|
|
|
|
|
|
Each policy may be set individually to help project authors
|
|
|
incrementally convert their projects to use new behavior or silence
|
|
|
warnings about dependence on old behavior. The `cmake_policy` command's
|
|
|
`SET` signature may be used to explicitly request OLD or NEW behavior
|
|
|
for a particular policy.
|
|
|
|
|
|
For example, CMake 2.6 introduces policy `CMP0002` which requires all
|
|
|
logical target names to be globally unique (duplicate target names
|
|
|
previously worked in some cases by accident but were not diagnosed).
|
|
|
Projects using duplicate target names and working accidentally will
|
|
|
receive warnings referencing the policy. The warnings may be silenced by
|
|
|
the code
|
|
|
|
|
|
cmake_policy(SET CMP0002 OLD)
|
|
|
|
|
|
which explicitly tells CMake to use OLD behavior for the policy
|
|
|
(silently accept duplicate target names). Another option is to use the
|
|
|
code
|
|
|
|
|
|
cmake_policy(SET CMP0002 NEW)
|
|
|
|
|
|
to explicitly tell CMake to use NEW behavior (produce an error when a
|
|
|
duplicate target is created). Once this is added to the project it will
|
|
|
not build until the author removes the duplicate targets.
|
|
|
|
|
|
## Policy Stack
|
|
|
|
|
|
Policy settings are scoped using a stack. A new level of the stack is
|
|
|
pushed when entering a new subdirectory of the project (with
|
|
|
`add_subdirectory`) and popped when leaving it. Therefore setting a
|
|
|
policy in one directory of a project will not affect parent or sibling
|
|
|
directories but will affect subdirectories.
|
|
|
|
|
|
This is useful when a project contains subprojects maintained separately
|
|
|
but built inside the tree. The top-level `CMakeLists.txt` file in a
|
|
|
project may write
|
|
|
|
|
|
cmake_policy(VERSION 2.6)
|
|
|
project(MyProject)
|
|
|
add_subdirectory(OtherProject)
|
|
|
# ... code requiring new behavior as of CMake 2.6 ...
|
|
|
|
|
|
while the `OtherProject/CMakeLists.txt` file contains
|
|
|
|
|
|
cmake_policy(VERSION 2.4)
|
|
|
project(OtherProject)
|
|
|
# ... code that builds with CMake 2.4 ...
|
|
|
|
|
|
This allows the main project to be updated to CMake 2.6 while the
|
|
|
subproject continues to build with CMake 2.4 until its maintainers
|
|
|
update it.
|
|
|
|
|
|
User code may use the `cmake_policy` command to PUSH and POP its own
|
|
|
stack levels as long as every PUSH must be paired with a POP. This is
|
|
|
useful to temporarily request different behavior for a small section of
|
|
|
code. For example, policy `CMP0003` removes extra link directories that
|
|
|
used to be included when NEW behavior is used. While incrementally
|
|
|
updating a project it may be difficult to build a particular target with
|
|
|
the NEW behavior but all other targets are okay. The code
|
|
|
|
|
|
cmake_policy(PUSH)
|
|
|
cmake_policy(SET CMP0003 OLD) # use old-style link directories for now
|
|
|
add_executable(myexe ...)
|
|
|
cmake_policy(POP)
|
|
|
|
|
|
will silence the warning and use the OLD behavior for that target.
|
|
|
|
|
|
## Interaction with Previous Compatibility Mechanisms
|
|
|
|
|
|
CMake 2.4 and below dealt with backwards compatibility by providing the
|
|
|
`CMAKE_BACKWARDS_COMPATIBILITY` variable as a cache entry. The variable
|
|
|
could be set by the user when building a project to tell CMake to try to
|
|
|
support an older version. This allowed users to build older projects but
|
|
|
only if they knew how to set the variable. In some cases CMake could
|
|
|
generate an error about old behavior and tell the user to set the
|
|
|
variable but in other cases it would silently fail or produce errors not
|
|
|
mentioning the variable.
|
|
|
|
|
|
The main problem with the `CMAKE_BACKWARDS_COMPATIBILITY` was that it
|
|
|
did not distinguish between a user trying to build someone else's
|
|
|
project and that project's author. Only project authors should be
|
|
|
required to do anything that changes how their project builds with new
|
|
|
CMake versions. The CMake Policy mechanism addresses this issue.
|
|
|
|
|
|
The CMake Policy mechanism was introduced in version CMake 2.6. For
|
|
|
maximum compatibility CMake does not try to retroactively convert
|
|
|
behavior changes introduced in versions 2.4 or lower into policies.
|
|
|
Instead policy `CMP0001` decides whether or not to support 2.4-style
|
|
|
compatibility. It's OLD behavior is to present
|
|
|
`CMAKE_BACKWARDS_COMPATIBILITY` and check for settings lower than 2.4.
|
|
|
It's NEW behavior is to not add `CMAKE_BACKWARDS_COMPATIBILITY` and not
|
|
|
check its value therefore removing all compatibility with versions lower
|
|
|
than 2.4.
|
|
|
|
|
|
Since all policies are introduced in CMake version 2.6 or later it does
|
|
|
not make sense to allow a policy version lower than 2.4 to be set.
|
|
|
Therefore the `cmake_policy` command's VERSION argument may not be lower
|
|
|
than 2.4. Similarly, `cmake_minimum_required` will never set the policy
|
|
|
version lower than 2.4 no matter what version is specified. This allows
|
|
|
existing projects to automatically build with the old-style
|
|
|
compatibility rules.
|
|
|
|
|
|
# Updating a Project for a new CMake Version
|
|
|
|
|
|
When a CMake release introduces new policies it may generate warnings
|
|
|
for some existing projects. These warnings indicate that changes to the
|
|
|
project may need to be made to deal correctly with the new policies.
|
|
|
While old releases of the project can continue to build with the
|
|
|
warnings the project development tree should be updated to take the new
|
|
|
policies into account.
|
|
|
|
|
|
There are two approaches to updating a tree: one-shot and incremental.
|
|
|
Which one is easier depends on the size of the project and what new
|
|
|
policies produce warnings.
|
|
|
|
|
|
## One-Shot Approach
|
|
|
|
|
|
The simplest approach to updating a project for a new version of CMake
|
|
|
is simply to change the policy version set at the top of the project,
|
|
|
try building with the new CMake version, and fix problems. For example,
|
|
|
to update a project to build with CMake 2.6 one might write
|
|
|
|
|
|
cmake_minimum_required(VERSION 2.6)
|
|
|
|
|
|
at the beginning of the top-level `CMakeLists.txt` file. This tells
|
|
|
CMake to use the NEW behavior for every policy introduced in CMake 2.6
|
|
|
and below. When building this project with CMake 2.6 no warnings will be
|
|
|
produced about policies because it knows of no policies introduced in
|
|
|
later versions. However, if the project was depending on the OLD
|
|
|
behavior of a policy it may not build since CMake now uses the NEW
|
|
|
behavior without warning. It is up to the project author who added the
|
|
|
policy version line to fix these issues.
|
|
|
|
|
|
## Incremental Approach
|
|
|
|
|
|
Another approach to updating a project for a new version of CMake is to
|
|
|
deal with each warning one-by-one. An advantage of this approach is that
|
|
|
the project will continue to build throughout the process so the changes
|
|
|
can be made incrementally.
|
|
|
|
|
|
When CMake encounters a situation where it needs to know whether to use
|
|
|
the OLD or NEW behavior for a policy it checks whether the project has
|
|
|
set the policy. If the policy is set CMake silently uses the
|
|
|
corresponding behavior. If the policy is not set CMake uses the OLD
|
|
|
behavior but warns that the policy is not set.
|
|
|
|
|
|
In many cases the warning message will point at the exact line of code
|
|
|
in the `CMakeLists.txt` files that produces the warning. In some cases
|
|
|
the situation cannot be diagnosed until CMake is generating the native
|
|
|
build system rules for the project so the warning will not include
|
|
|
explicit context information. In these cases CMake will try to provide
|
|
|
some information about where code may need to be changed. The
|
|
|
documentation for these "generation-time" policies should indicate the
|
|
|
point in the project code at which the policy should be set to take
|
|
|
effect.
|
|
|
|
|
|
In order to incrementally update a project one warning should be
|
|
|
addressed at a time. Several cases may occur.
|
|
|
|
|
|
### Silence a Warning When Code is Correct
|
|
|
|
|
|
Many policy warnings may be produced simply because the project has not
|
|
|
set the policy even though the project may work correctly with the NEW
|
|
|
behavior (there is no way for CMake to know the difference). For a
|
|
|
warning about some policy `CMP<`*`NNNN`*`>` one may check whether this
|
|
|
is the case by adding
|
|
|
|
|
|
cmake_policy(SET CMP<''NNNN''> NEW)
|
|
|
|
|
|
to the top of the project and trying to build it. If the project builds
|
|
|
correctly with the new behavior one may move on to the next policy
|
|
|
warning. If the project does not build correctly one of the other cases
|
|
|
may apply.
|
|
|
|
|
|
### Silence a Warning Without Updating Code
|
|
|
|
|
|
One may suppress all instances of a warning `CMP<`*`NNNN`*`>` by adding
|
|
|
|
|
|
cmake_policy(SET CMP<''NNNN''> OLD)
|
|
|
|
|
|
at the top of a project. However, we encourage project authors to update
|
|
|
their code to work with the NEW behavior for all policies. This is
|
|
|
especially important because versions of CMake in the (distant) future
|
|
|
may remove support for the OLD behavior and produce an error for
|
|
|
projects requesting it (which tells the user to get an older CMake to
|
|
|
build the project).
|
|
|
|
|
|
### Silence a Warning by Updating Code
|
|
|
|
|
|
When a project does not work correctly with the NEW behavior for a
|
|
|
policy its code needs to be updated. In order to deal with a warning for
|
|
|
some policy `CMP<`*`NNNN`*`>` one may add
|
|
|
|
|
|
cmake_policy(SET CMP<''NNNN''> NEW)
|
|
|
|
|
|
at the top of the project and then fix the code to work with the NEW
|
|
|
behavior.
|
|
|
|
|
|
If many instances of the warning occur fixing all of them simultaneously
|
|
|
may be too difficult. Instead a developer may fix one at a time. This
|
|
|
may be done using the PUSH/POP signatures of the `cmake_policy` command:
|
|
|
|
|
|
cmake_policy(PUSH)
|
|
|
cmake_policy(SET CMP<''NNNN''> NEW)
|
|
|
# ... code updated for new policy behavior ...
|
|
|
cmake_policy(POP)
|
|
|
|
|
|
This will request NEW behavior for a small region of code that has been
|
|
|
fixed. Other instances of the policy warning may still appear and must
|
|
|
be fixed separately.
|
|
|
|
|
|
### Updating the Project Policy Version
|
|
|
|
|
|
After addressing all policy warnings and getting the project to build
|
|
|
cleanly with the new CMake version one step remains. The policy version
|
|
|
set at the top of the project should now be updated to match the new
|
|
|
CMake version, just as in the one-shot approach above. For example,
|
|
|
after updating a project to build cleanly with CMake 2.6 one may update
|
|
|
the top of the project with the line
|
|
|
|
|
|
cmake_minimum_required(VERSION 2.6)
|
|
|
|
|
|
This will set all policies introduced in CMake 2.6 or below to use NEW
|
|
|
behavior. Then one may sweep through the rest of the code and remove all
|
|
|
the calls to the `cmake_policy` command used to request NEW behavior
|
|
|
incrementally. The end result should look the same as the one-shot
|
|
|
approach above but could be attained step-by-step.
|
|
|
|
|
|
## Supporting Multiple CMake Versions
|
|
|
|
|
|
Some projects may like to support a few releases of CMake
|
|
|
simultaneously. The goal is to build with an older version but also work
|
|
|
with newer versions without warnings.
|
|
|
|
|
|
In order to support both CMake 2.4 and 2.6, one may write code like
|
|
|
|
|
|
cmake_minimum_required(VERSION 2.4)
|
|
|
if(COMMAND cmake_policy)
|
|
|
# policy settings ...
|
|
|
cmake_policy(SET CMP0003 NEW)
|
|
|
endif(COMMAND cmake_policy)
|
|
|
|
|
|
This will set the policies when building with CMake 2.6 and just ignore
|
|
|
them for CMake 2.4.
|
|
|
|
|
|
In order to support both CMake 2.6 and (a currently hypothetical) CMake
|
|
|
2.8, one may write code like
|
|
|
|
|
|
cmake_minimum_required(VERSION 2.6)
|
|
|
if(POLICY CMP1234)
|
|
|
# policies not known to CMake 2.6 ...
|
|
|
cmake_policy(SET CMP1234 NEW)
|
|
|
endif(POLICY CMP1234)
|
|
|
|
|
|
This will set the policies when building with CMake 2.8 and just ignore
|
|
|
them for CMake 2.6. If it is known that the project builds with CMake
|
|
|
2.6 and CMake 2.8's NEW policies one may write
|
|
|
|
|
|
cmake_minimum_required(VERSION 2.6)
|
|
|
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.6)
|
|
|
cmake_policy(VERSION 2.8)
|
|
|
endif("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.6)
|
|
|
|
|
|
----
|
|
|
This page was initially populated by conversion from its [original location](https://public.kitware.com/Wiki/CMake/Policies) in another wiki. |