Reputation: 1084
I would like to target a specific version of CMake that is older than the version I am using myself (related to this question, i.e. correctly using cmake_minimum_required()
), and it would be nice to be able to determine which features to stay away from, for instance.
Is it possible to find the first version that a certain feature (variable, function, property, ...) was introduced in CMake?
As far as I can tell, the CMake documentation does not directly include this information (except for indirectly via the release notes). A great example of how this could work is the Qt API documentation (e.g. see the documentation for QCryptographicHash).
EDIT: I created a git repo with a modified version of the solution provided by Florian: https://github.com/mbitsnbites/cmake-minver
Upvotes: 8
Views: 3064
Reputation: 23294
The issue is a known problem, and there are brave souls that are trying to get the situation improved. CMake 3.19.0, 3.19.1, and the upcoming 3.20.0 got added the CMake version when a feature was introduced. This happened to hundreds of places in the CMake documentation. See one of the commits from Nikita Nemkin, more are linked in the issue above.
In the CMake documentation it looks like the screenshot. Mind the New in version 3.xx and that the screenshot is the currently documentation generated from Git master.
Technically, the version is annotated in the documentation with the Sphinx' builtin command versionadded
.
CMake provides a script, to generate the version added information, in Utilities/Sphinx/stamp_version.py
.
Upvotes: 1
Reputation: 15956
I made a firefox plugin, named CSince
, available in https://addons.mozilla.org/firefox/addon/csince/.
When viewing a page of CMake documentation, it checks since which version the corresponding feature exists, and adds the information to the html contents.
A first checking is performed for versions starting with v3.0: the url pattern is checked for prior versions until a 404 error is returned by the server. For example, considering url for property BINARY_DIR
:
https://cmake.org/cmake/help/latest/prop_dir/BINARY_DIR.html
Here urls are tested replacing latest
with a version string:
https://cmake.org/cmake/help/v3.0/prop_dir/BINARY_DIR.html
https://cmake.org/cmake/help/v3.1/prop_dir/BINARY_DIR.html
https://cmake.org/cmake/help/v3.2/prop_dir/BINARY_DIR.html
...
Versions are tested using a dichotomic approach, to limit requests.
If the first checking process returns v3.0, a second pass is performed for older versions using a less reliable test: the single-page documentation is requested, and the feature string is searched in the text.
This two-passes system allows for example to find the right version for the property BINARY_DIR
: the string BINARY_DIR
obviously exists in CMake documentation v2.6, while it exists as a property only since CMake v3.7.
Any bug report or improvement request are welcome. Code source is available on GitHub under license MIT/X11: https://github.com/wasthishelpful/csince.
Upvotes: 1
Reputation: 42842
After reading the comments here is my CMake
version of a command/property/etc. checker:
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.5)
function(version_required_by)
set(_keywords ${ARGN})
set(_temp_file "${CMAKE_CURRENT_BINARY_DIR}/download.txt")
foreach(_ver IN ITEMS 2.6 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.8.10 2.8.11 2.8.12 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7)
message(STATUS "Check version required: ${_ver}")
if (_ver VERSION_LESS 2.8)
set(_url "https://cmake.org/cmake/help/cmake${_ver}docs.html")
elseif (_ver VERSION_LESS 3.0)
set(_url "https://cmake.org/cmake/help/v${_ver}/cmake.html")
else()
set(_url "https://cmake.org/cmake/help/latest/release/${_ver}.html")
endif()
file(DOWNLOAD "${_url}" "${_temp_file}")
file(READ "${_temp_file}" _help_text)
foreach(_keyword IN LISTS _keywords)
string(FIND "${_help_text}" "${_keyword}" _found)
if (NOT _found EQUAL -1)
message(STATUS "${_keyword} -> v${_ver}")
list(REMOVE_ITEM _keywords "${_keyword}")
endif()
endforeach()
if (NOT _keywords)
message("cmake_minimum_required(VERSION ${_ver} FATAL_ERROR)")
if (NOT CMAKE_MINIMUM_REQUIRED_VERSION)
cmake_minimum_required(VERSION ${_ver} FATAL_ERROR)
endif()
break()
endif()
endforeach()
if (_keywords)
message(FATAL_ERROR "Check version required error: Not found ${_keywords}")
endif()
endfunction()
if (CMAKE_SCRIPT_MODE_FILE)
foreach(_i RANGE 3 ${CMAKE_ARGC})
list(APPEND _args "${CMAKE_ARGV${_i}}")
endforeach()
else()
list(
APPEND _args
"string(FIND"
"target_include_directories"
"BUILDSYSTEM_TARGETS"
)
endif()
version_required_by(${_args})
Would give for those examples I used for testing it:
-- Check version required: 2.6
...
-- Check version required: 2.8.5
-- string(FIND -> v2.8.5
...
-- Check version required: 2.8.11
-- target_include_directories -> v2.8.11
...
-- Check version required: 3.7
-- BUILDSYSTEM_TARGETS -> v3.7
cmake_minimum_required(VERSION 3.7 FATAL_ERROR)
Edit: Or if you e.g. run the above in script mode:
> cmake -P CMakeLists.txt target_include_directories
-- Check version required: 2.6
...
-- Check version required: 2.8.11
-- target_include_directories -> v2.8.11
cmake_minimum_required(VERSION 2.8.11 FATAL_ERROR)
Reference
Upvotes: 5