Feature Request: setting find_package versions via env/cmake variables

Hey there,

ArchLinux just rolled out Python 3.10 leading to all sorts of incompatibilities. In one of our project that aggregates multiple other third parties, this leads to lots of havoc. What’s worse, I think I have no alternative to actively editing cmake file by hand to set a version range on all find_package(Python3) calls.

Thus the feature request: It would be great, if we could get something similar to <PackageName>_ROOT, but for setting the VERSION part of the find_package call.

Ideally then, I would be able to do something like this:

cmake -DPython3_FIND_PACKAGE_VERSION="3.7...<3.10" ...

Or similar via an environment variable.

Thanks

Version specification is processed by the find_package command (for example, various variables related to version are already defined when the module is called) so bypassing it with some variable seems not a good idea.

But, maybe, a more general approach can be evaluated: to offer the possibility to specify the version needed by some variable (like <PackageName>_REQUESTED_VERSION, for example) which will be processed by find_package. By this approach, all modules will benefit from this new functionality without any change required.

Yes, that would solve my problem too. I.e. I could then explicitly set Python3_REQUESTED_VERSION=3.9

find_package lets you specify a version range:

find_package(<PackageName> major.minor...<major.minor REQUIRED)

The first match wins over consecutive find_package calls. This means that you have to add this call further up your project (somewhere to make sure it is the first find_package used). You seem to be interested in a single Python version for your entire CMake project, in which case this function should be in the top level CMake list.

If your Python installation is not in the default path you’d also need to manually set the root dir:

cmake -DPython3_ROOT_DIR=$HOME/python/versions/3.9.0 ..

Ah, thanks. That’s good to know as a workaround. I think the problem with Python specifically is that there are so many ways to search for it:

find_package(Python
find_package(Python3
find_package(PythonLibs
find_package(PythonInterp
find_package(PythonModuleGeneration

These are all that get used by the project I’m working on and its dependencies transitively. Obviously it should all just be Python3, but reality is more ugly.

One way or another, I’ll have to ensure that all of these point to the same python version…

It is more than a workaround. For CMake it is the way to go for dependency management.

I haven’t dealt with this situation before but i cannot think why it should be any different. Maybe the following works for you:

project(top)
find_package(Python <version> EXACT)
find_package(Python3 <version> EXACT)
find_package(PythonLibs <version> EXACT)
find_package(PythonInterp <version> EXACT)
find_package(PythonModuleGeneration <version> EXACT)
add_subdirectory(3rdParty)
  add_subdirectory(party1)
    find_package(Python)
  add_subdirectory(party2)
    find_package(Python3)
  add_subdirectory(party3)
    find_package(PythonLibs)
  add_subdirectory(party4)
    find_package(PythonInterp)
  add_subdirectory(party5)
    find_package(PythonModuleGeneration)

of course this is only a sketch. Let me know if it is not clear.

Thank you, I was not aware that this was the recommended way for dependency management. Thinking about it now, it makes a lot of sense.

Cheers

Modules FindPyhtonInterp and FindPythonLibs are deprecated must no longer used. And it make definitively no sense to used them mixed with FindPython* modules.

Moreover, using FindPython with FindPython2 and FindPython3 is also an error.
FindPython is used when the goal is to search for python, regardless the version.

And to finish, all these modules are independent in the sense they set different variables.

And I’ll just note that such behavior was an explicit design decision. (Note that I’m not familiar with PythonModuleGeneration, so I have no idea there.) The major problem with FindPythonInterp and FindPythonLibs is that they did not work together and one could find pythonX.Y, but libpythonW.Z (this was usually witnessed on macOS with HomeBrew and/or SDKs loaded, but anywhere multiple Pythons were “visible”, there was no coordination). The support for separate Python2 and Python3 was also intentional because one project might want to support both at once and a single find module will just end up conflicting with itself when trying to find 2 and 3 at separate points in the build.

Oh, don’t get me wrong - I’m totally with you all on that matter. But the sad reality is simply that when one bundles multiple dependencies in a larger application, it may simply happen that all of these, including the deprecated ones, are used…

For this reason I was thinking it would be nice if there could be a central switch to dictate that all dependencies agree on the same version. But that seems to be possible by using the approach outlined by @hex.