How to detect using too new features in CMake?

Viewed 33

Prepare the following (erroneous) CMakeLists.txt file:

cmake_minimum_required(VERSION 3.10)
project(foo)
add_executable(foo foo.cpp)
add_compile_definitions(BAR=123)

add_compile_definitions is new in CMake 3.12, so processing the above file in CMake 3.10 will result in an error.

CMake Error at CMakeLists.txt:4 (add_compile_definitions):
  Unknown CMake command "add_compile_definitions".

However, using CMake 3.12 or later, no errors or warnings are output. Therefore, as long as you are using CMake 3.12 or later, you will not notice the error.

(In this case, we can use add_compile_options instead of add_compile_definitions, but that is not the main issue.)

You may say, "you shouldn't write cmake_minimum_required(VERSION 3.10) because you are not using CMake 3.10, you should write the version you are actually using". However, there may be cases where modifications are made to an existing code base.

Is there any way to realize that when you do so, you inadvertently write something that is not usable in the specified version? For example, is there a tool like lint that can check for features that are not available in a given version?

Currently, is the only way to do this is to install the specified version of CMake?

2 Answers

You have to test with the minimum required version. But even if no error occurs, your test might be incomplete, because you only test these parts of the code, that you are actually running. If your setup does not provide an optional dependency or you did not set a flag, the code executed for this dependency or flag will not be tested.

Depending on your setup, it makes sense to have a continuous testing (GitLab, Jenkins, GitHub actions) that runs your CMake code with CMake in the minimum required version. Then you get early warning that someone added code that is above the required CMake version and you should revert it or increase the requirements.

It is really not a satisfying answer and in general not a satisfying situation.

usr1234567 wrote a good answer, but let me add an additional point:

I think you (and many others; you're in good company) are misunderstanding the guarantee made by cmake_minimum_required(VERSION X). Many people believe it means the following:

This project will build with version X.

That is not the case at all. What it actually promises is:

If this project builds with version X, then it will build on versions Y > X.

That is to say, it is a backwards compatibility guarantee, not a forwards compatibility guarantee. You cannot author a project with a newer version of CMake and expect it to work with older versions without testing it.

Related