Version range support write_basic_config_version_file() may be too restrictive

@marc.chevrier When we added the support for version ranges in MR 5226, using any compatibility mode other than AnyNewerVersion generates an author warning when any sort of version range is given to a find_package() call that evaluates the generated config version file. Now that I’m looking to update the details about this in my book, I’m wondering why that restriction is in place. On the face of it, it seems like the other compatibility modes should be able to support at least a subset of version ranges that make sense for them. As long as the lower and upper ends don’t span more than the compatibility mode covers, it should be allowed.

For example, if a find_package() call uses a version range like 2.3...2.9 or even 2.3...<3, then this could be safely satisfied by a SameMajorVersion compatibility mode. I didn’t consider this during the review. Can you clarify why we issue a warning in this case? This seems like an oversight, but maybe I’m forgetting some detail.

I choose to add a warning for all other modes except AnyNewerVersion to avoid ambiguity between constraints given by the range and the semantics of the various modes.
For example, SameMajorMode imply a constaint only on major mode. But using a range will imply another kind of restriction which is in conflict with the initial constraint. If you generate a config file with value ‘2’ and after use find_package with range 2.2...2.5, it is not possible to guaranty the constraint is respected because only major item is checked.

That’s not the case, and I made the same incorrect assessment myself in the past. :wink: The SameMajorVersion and SameMinorVersion compatibility modes both contain the following check:

if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
  set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
  ...

And the ExactVersion compatibility mode has other logic to check the equality requirement. For the SameMajorVersion and SameMinorVersion at least, a find_package() call can request a version range that could be satisfied by a package, so it seems incorrect to be issuing a warning for those at least. Maybe it still makes sense for ExactVersion, but again the caller might genuinely know that they can work with any version in the range that they specify (they might adapt to the version found).

Except that it is perfectly legal to specify only major version to generate the config version file:

write_basic_package_version_file(MyVersion VERSION 2 COMPATIBILITY SameMajorVersion)

In this case, the constraint expressed by the range cannot be enforced…
And the same is true for SameMinorVersion.

My feeling is that, even in the current form, the write_basic_config_version_file() command has not a very well-defined behavior so adding a layer of blur seems not a good idea.

If the package only defines a major version, the minor and patch parts are assumed to be zero. That’s pretty standard behavior for CMake version comparisons. If the caller of find_package() then specifies a range with the lower end > 2.0.0, it should fail because the package doesn’t satisfy that requirement. But if their lower end is 2 then it should succeed as long as the upper end of their range is < 3. It satisfies both the version range and the SameMajorVersion requirements. One can construct a similar scenario for SameMinorVersion.

The behavior of write_basic_config_version_file() seems unambiguous to me. I think we just haven’t implemented the required logic that should be present to support version ranges for the SameMajorVersion and SameMinorVersion cases. That isn’t adding a layer of blur, the checks should be very well-defined.

1 Like

Let me think a little about that…