|
|
(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.
| |