|
|
(13 intermediate revisions by 3 users not shown) |
Line 1: |
Line 1: |
| The CMake Policy mechanism provides backwards compatibility as a
| | {{CMake/Template/Moved}} |
| first-class feature.
| |
|
| |
|
| =Motivation=
| | This page has moved [https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Policies here]. |
| | |
| 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 <code>add_definitions</code> 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 <code>configure_file</code> 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 <code>add_definitions</code> 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 "<code>B</code>" is meant to link "<code>/path/to/libB.so</code>". This code is incorrect because it asks CMake to link to <code>B</code> 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
| |
| <code>-L/path/to</code> 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
| |
| <code>/path/to/libA.so</code> directly to the linker as a path. This
| |
| leaves out the <code>-L/path/to</code> 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:
| |
| | |
| # '''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
| |
| # '''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
| |
| # '''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
| |
| # '''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 '''<code>CMP_''NNNN''</code>''' 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 <code>cmake_policy</code>
| |
| command's <code>VERSION</code> 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 <code>cmake_minimum_required</code> 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 "<code>2.6</code>" 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 CMP_0000 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 <code>cmake_minimum_required</code> 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
| |
| <code>cmake_policy</code> command's <code>SET</code> signature may be
| |
| used to explicitly request OLD or NEW behavior for a particular
| |
| policy.
| |
| | |
| For example, CMake 2.6 introduces policy <code>CMP_0002</code> 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 CMP_0002 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 CMP_0002 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
| |
| <code>add_subdirectory</code>) 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
| |
| <code>CMakeLists.txt</code> 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 <code>OtherProject/CMakeLists.txt</code> file contains
| |
| | |
| cmake_policy(VERSION 2.4)
| |
| project(OtherProject)
| |
| # ... code that buidls 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 <code>cmake_policy</code> 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 <code>CMP_0003</code>
| |
| 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 CMP_0003 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 <code>CMAKE_BACKWARDS_COMPATIBILITY</code> 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 <code>CMAKE_BACKWARDS_COMPATIBILITY</code>
| |
| 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 <code>CMP_0001</code> decides whether or not to support
| |
| 2.4-style compatibility. It's OLD behavior is to present
| |
| <code>CMAKE_BACKWARDS_COMPATIBILITY</code> and check for settings
| |
| lower than 2.4. It's NEW behavior is to not add
| |
| <code>CMAKE_BACKWARDS_COMPATIBILITY</code> 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 <code>cmake_policy</code> command's VERSION
| |
| argument may not be lower than 2.4. Similarly,
| |
| <code>cmake_minimum_required</code> 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 <code>CMakeLists.txt</code> 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 <code>CMakeLists.txt</code> 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 <code>CMP_<''NNNN''></code> 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
| |
| <code>CMP_<''NNNN''></code> 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 <code>CMP_<''NNNN''></code> 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
| |
| <code>cmake_policy</code> 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===
| |