Discuss the best approach to implementing support for additional version schemes
Summary
There have been a number of proposals to expand versioning in CMake. I like the summary and rationale from #16716.
Required changes
- Commands
cmake_minimum_required
cmake_policy
-
find_package
PACKAGE_FIND_VERSION{,_MAJOR,_MINOR,_PATCH,_TWEAK}
-
write_basic_package_version_file
COMPATIBILITY
argument and associatedBasicConfigVersion-<VERSION_SCHEME>.cmake.in
files -
if
VERSION_{LESS,GREATER,EQUAL,LESS_EQUAL,GREATER_EQUAL}
-
proposed
VERSION_MATCHES
or<VERSION_SCHEME>_MATCHES
-
project
- Sets
PROJECT_VERSION{,_MAJOR,_MINOR,_PATCH,_TWEAK}
and<PROJECT-NAME>_VERSION{,_MAJOR,_MINOR,_PATCH,_TWEAK}
-
proposed
PROJECT_VERSION_SCHEME
and<PROJECT-NAME>_VERSION_SCHEME
- Additional scheme-specific named version components (e.g
PROJECT_VERSION_PRERELEASE
andPROJECT_VERSION_BUILD_IDENTIFIER
for semantic version, orPROJECT_VERSION_LOCAL
for PEP440)?
- Sets
- Generator expressions
VERSION_{LESS,GREATER,EQUAL,LESS_EQUAL,GREATER_EQUAL}
-
proposed
VERSION_MATCHES
or<VERSION_SCHEME>_MATCHES
cmake_minimum_required
and cmake_policy
only require a change if CMake is going to use an expanded version scheme. The stated preference appears to be to ignore prerelease versions, which is the current behavior.
New comparison operator
VERSION_SATISFIES
or VERSION_MATCHES
such that the operation evaluates to TRUE
if the first argument matches the version spec in the second argument. The version spec can be a single version that the first argument must be compatible with or a set of constraints as in PEP440 version specifiers.
There are a couple of ways that this may be done:
MATCHES
/SATISFIES
operator for each scheme
if(<string|expression> <VERSION_SCHEME>_MATCHES <string|expression>)
# Ex
if(1.2.0 SEMVER_MATCHES 1.1.0)
if(1.2.0 PEP440_MATCHES "~=1.1.0 !=1.1.1")
This is the approach that I took in !7387 (closed).
MATCHES
/SATISFIES
Optional scheme argument for If this is feasible, it would make the documentation look a little better. Right now, all of the version comparison operations have essentially identical descriptions (of how CMake's current version precedence system works).
If [VERSION_SCHEME]
is omitted, default to the current behavior (dotted decimal, compare components in order to find a diff, ignore any non-digit, non-. characters and quit immediately if one is found). Allow users to explicitly choose this scheme by specifying SIMPLE
as the scheme?
Infix
if(<string|expression> VERSION_MATCHES [VERSION_SCHEME] <string|expression>)
# Ex
if(1.2.0 VERSION_MATCHES SEMVER 1.1.0)
if(1.2.0 VERSION_MATCHES PEP440 "~=1.1.0 !=1.1.1")
Postfix
if(<string|expression> VERSION_MATCHES <string|expression> [VERSION_SCHEME])
# Ex
if(1.2.0 VERSION_MATCHES 1.1.0 SEMVER)
if(1.2.0 VERSION_MATCHES "~=1.1.0 !=1.1.1" PEP440)
Generator expressions
Again, there a couple ways this might be approached:
New generator expressions for every versioning scheme
$<<SCHEME>_MATCHES:v1,v2>
# Ex
$<VERSION_MATCHES:1.2.0,1.1.0>
$<SEMVER_MATCHES:1.2.0,1.1.0>
$<PEP440_MATCHES:1.2.0,"~=1.1.0 !=1.1.1">
Optional third-argument
$<VERSION_MATCHES:v1,v2[,SCHEME]>
# Ex
$<VERSION_MATCHES:1.2.0,1.1.0>
$<VERSION_MATCHES:1.2.0,1.1.0,SIMPLE>
$<VERSION_MATCHES:1.2.0,1.1.0,SEMVER>
$<VERSION_MATCHES:1.2.0,"~=1.1.0 !=1.1.1",PEP440)
Links to other issues
Previous work (closed, but with an encouraging comment by @brad.king to re-open when the author has time): !985 (closed)
Would require something like #22584 / !7386 (closed) as a prerequisite.
One partial implementation for semantic version is !7387 (closed), but as pointed out there, it might not be the ideal solution to the problem.
Also related to #16656 (closed) and #16716.