3.4. Version and policies

Like any other piece of software CMake evolves, effectively introducing new features and deprecating dangerous or confusing behavior.

There are two entities that help you to manage difference between old and new versions of CMake:

If you just want to experiment without worrying about backward compatibility, policies, warnings, etc. just set first line of CMakeLists.txt to cmake_minimum_required(VERSION a.b.c) where a.b.c is a current version of CMake you’re using:

> cmake --version
cmake version 3.5.2

> cat CMakeLists.txt
cmake_minimum_required(VERSION 3.5.2)

3.4.1. cmake_minimum_required

CMake documentation

What version to put into this command is mostly an executive decision. You need to know:

  • what version is installed on users hosts?

  • is it appropriate to ask them to install newer version?

  • what features do they need?

  • do you need to be backward compatible for one users and have fresh features for another?

The last case will fit most of them but will harder to maintain for developer and probably will require automatic testing system with good coverage.

For example the code with version 2.8 as a minimum one and with 3.0 features will look like:

cmake_minimum_required(VERSION 2.8)

if(NOT CMAKE_VERSION VERSION_LESS "3.0") # means 'NOT version < 3.0', i.e. 'version >= 3.0'
  # Code with 3.0 features
endif()

Command cmake_minimum_required must be the first command in your CMakeLists.txt. If you’re planning to support several versions of CMake then you need to put the smallest one in cmake_minimum_required and call it in the first line of CMakeLists.txt.

Even if some commands look harmless, they might not be. For example, project is the place where a lot of checks happens and where the toolchain is loaded. If you run this example on Cygwin platform:

project(foo) # BAD CODE! You should check version first!
cmake_minimum_required(VERSION 3.0)

message("Using CMake version ${CMAKE_VERSION}")

CMake will think that you’re running code with old policies and warns you:

[minimum-required-example]> cmake -Hbad -B_builds/bad
-- The C compiler identification is GNU 4.9.3
-- The CXX compiler identification is GNU 4.9.3
CMake Warning at /.../share/cmake-3.3.1/Modules/Platform/CYGWIN.cmake:15 (message):
  CMake no longer defines WIN32 on Cygwin!

  (1) If you are just trying to build this project, ignore this warning or
  quiet it by setting CMAKE_LEGACY_CYGWIN_WIN32=0 in your environment or in
  the CMake cache.  If later configuration or build errors occur then this
  project may have been written under the assumption that Cygwin is WIN32.
  In that case, set CMAKE_LEGACY_CYGWIN_WIN32=1 instead.

  (2) If you are developing this project, add the line

    set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required

  at the top of your top-level CMakeLists.txt file or set the minimum
  required version of CMake to 2.8.4 or higher.  Then teach your project to
  build on Cygwin without WIN32.
Call Stack (most recent call first):
  /.../share/cmake-3.3.1/Modules/CMakeSystemSpecificInformation.cmake:36 (include)
  CMakeLists.txt:1 (project)
...
-- Detecting CXX compile features - done
Using CMake version 3.3.1
...

Fixed version:

cmake_minimum_required(VERSION 3.0)
project(foo)

message("Using CMake version ${CMAKE_VERSION}")

with no warnings:

[minimum-required-example]> cmake -Hgood -B_builds/good
-- The C compiler identification is GNU 4.9.3
-- The CXX compiler identification is GNU 4.9.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++.exe
-- Check for working CXX compiler: /usr/bin/c++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Using CMake version 3.3.1
-- Configuring done
-- Generating done
-- Build files have been written to: /.../minimum-required-example/_builds/good

Examples on GitHub

3.4.2. CMake policies

CMake documentation

When a new version of CMake is released, there may be a list of policies describing cases when behavior changed comparing to the previous CMake version.

Let’s see how it works in practice. In CMake 3.0 policy CMP0038 was introduced. Before version 3.0, a target could be linked to itself, which make no sense and definitely is a bug:

cmake_minimum_required(VERSION 2.8)
project(foo)

add_library(foo foo.cpp)

target_link_libraries(foo foo) # BAD CODE! Make no sense

Examples on GitHub

Works fine for CMake before 3.0:

[policy-examples]> cmake --version
cmake version 2.8.12.2
[policy-examples]> rm -rf _builds
[policy-examples]> cmake -Hbug-2.8 -B_builds
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /.../policy-examples/_builds

For CMake version >= 3.0 warning will be reported:

[policy-examples]> cmake --version
cmake version 3.5.2
[policy-examples]> rm -rf _builds
[policy-examples]> cmake -Hbug-2.8 -B_builds
...
-- Configuring done
CMake Warning (dev) at CMakeLists.txt:4 (add_library):
  Policy CMP0038 is not set: Targets may not link directly to themselves.
  Run "cmake --help-policy CMP0038" for policy details.  Use the cmake_policy
  command to set the policy and suppress this warning.

  Target "foo" links to itself.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Generating done
-- Build files have been written to: /.../policy-examples/_builds

Assume you want to drop support for the old version and more to some new 3.0 features. When you set cmake_minimum_required(VERSION 3.0)

--- /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/bug-2.8/CMakeLists.txt
+++ /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/set-3.0/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.0)
 project(foo)
 
 add_library(foo foo.cpp)

warning turns into error:

[policy-examples]> rm -rf _builds
[policy-examples]> cmake -Hset-3.0 -B_builds
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
CMake Error at CMakeLists.txt:4 (add_library):
  Target "foo" links to itself.


-- Generating done
-- Build files have been written to: /.../policy-examples/_builds
[policy-examples]> echo $?
1

Two cases will be shown below. In the first case we want to keep support of version 2.8 so it will work with both CMake 2.8 and CMake 3.0+. In the second case we decide to drop support of version 2.8 and move to CMake 3.0+. We’ll see how it affects the policies. It will be shown that without using new features from CMake 3.0, it doesn’t make sense to change cmake_minimum_required.

3.4.2.1. Keep using old

Our project works fine with CMake 2.8 however CMake 3.0+ emits warning. We don’t want to fix the error now but want only to suppress warning and explain to CMake that it should behaves like CMake 2.8.

Note

This approach described in documentation:

It is possible to disable the warning by explicitly requesting the OLD, or
backward compatible behavior using the cmake_policy() command

Let’s add cmake_policy:

cmake_minimum_required(VERSION 2.8)
project(foo)

cmake_policy(SET CMP0038 OLD)

add_library(foo foo.cpp)

target_link_libraries(foo foo) # BAD CODE! Make no sense

Looks good for CMake 3.0+:

[policy-examples]> cmake --version
cmake version 3.5.2
[policy-examples]> rm -rf _builds
[policy-examples]> cmake -Hunknown-2.8 -B_builds
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done

Are we done? No, CMP0038 is introduced since CMake 3.0 so CMake 2.8 have no idea what this policy is about:

> cmake --version
cmake version 2.8.12.2
> rm -rf _builds
> cmake -Hunknown-2.8 -B_builds
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMake Error at CMakeLists.txt:4 (cmake_policy):
  Policy "CMP0038" is not known to this version of CMake.

-- Configuring incomplete, errors occurred!

We should protect new code with if(POLICY CMP0038) condition:

cmake_minimum_required(VERSION 2.8)
project(foo)

if(POLICY CMP0038)
  # Policy CMP0038 introduced since CMake 3.0 so if we want to be compatible
  # with 2.8 (see cmake_minimum_required) we should put 'cmake_policy' under
  # condition.
  cmake_policy(SET CMP0038 OLD)
endif()

add_library(foo foo.cpp)

target_link_libraries(foo foo) # BAD CODE! Make no sense

Of course you should find the time, apply real fix and remove policy logic since it will not be needed anymore:

--- /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/suppress-2.8/CMakeLists.txt
+++ /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/fix-2.8/CMakeLists.txt
@@ -1,13 +1,4 @@
 cmake_minimum_required(VERSION 2.8)
 project(foo)
 
-if(POLICY CMP0038)
-  # Policy CMP0038 introduced since CMake 3.0 so if we want to be compatible
-  # with 2.8 (see cmake_minimum_required) we should put 'cmake_policy' under
-  # condition.
-  cmake_policy(SET CMP0038 OLD)
-endif()
-
 add_library(foo foo.cpp)
-
-target_link_libraries(foo foo) # BAD CODE! Make no sense

Final version:

cmake_minimum_required(VERSION 2.8)
project(foo)

add_library(foo foo.cpp)

3.4.2.2. Moving to new version

With cmake_minimum_required updated to 3.0, the warning turns into an error. As a temporary solution, the error can be suppressed by adding a cmake_policy directive:

cmake_minimum_required(VERSION 3.0)
project(foo)

cmake_policy(SET CMP0038 OLD)

add_library(foo foo.cpp)

target_link_libraries(foo foo) # BAD CODE! Make no sense

Note

We don’t need to protect cmake_policy with if(POLICY) condition since cmake_minimum_required(VERSION 3.0) guarantee us that we are using CMake 3.0+.

This policy can then be removed once a better solution is found:

--- /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/suppress-3.0/CMakeLists.txt
+++ /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/fix-3.0/CMakeLists.txt
@@ -1,8 +1,4 @@
 cmake_minimum_required(VERSION 3.0)
 project(foo)
 
-cmake_policy(SET CMP0038 OLD)
-
 add_library(foo foo.cpp)
-
-target_link_libraries(foo foo) # BAD CODE! Make no sense

Final version:

cmake_minimum_required(VERSION 3.0)
project(foo)

add_library(foo foo.cpp)

You may notice that final version for both cases differs only in cmake_minimum_required:

--- /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/fix-2.8/CMakeLists.txt
+++ /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/policy-examples/fix-3.0/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.0)
 project(foo)
 
 add_library(foo foo.cpp)

It means that there is no much sense in changing cmake_minimum_required without using any new features.

3.4.3. Summary

  • Policies can be used to control CMake behavior

  • Policies can be used to suppress warnings/errors

  • cmake_minimum_required describe features you use in CMake code

  • For backward compatibility new features can be protected with if(CMAKE_VERSION ...) directive