|
|
(23 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.
| |
− | | |
− | ==Interface of ADD_DEFINITIONS==
| |
− | | |
− | 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.
| |
− | | |
− | ==Magic Link Directories==
| |
− | | |
− | 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
| |
− | | |
− | =Policies=
| |
− | | |
− | 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.
| |
− | | |
− | ==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. By default a new level of
| |
− | the stack is created for each directory of the project. User code may
| |
− | use the <code>cmake_policy</code> command to PUSH and POP its own
| |
− | stack levels.
| |