Background: the Python build backend py-build-cmake
that I maintain needs to invoke CMake to build Python extension modules in user-provided CMake projects. The goal of the build backend is to build these extension modules for a specific version of Python, and if CMake’s FindPython module were to locate the wrong version of Python, this would result in incompatible binaries.
Question: How can I force FindPython to locate this specific version of Python only, and never fall back to e.g. the system-wide Python installation at /usr/bin/python3?
If the user’s CMake project searches for Python using find_package(Python3 COMPONENTS Interpreter Development.Module)
, it looks like setting Python3_EXECUTABLE
does the right thing. However, problems arise when the user only searches for the Development.Module
component without the Interpreter
: in such a case, it is necessary to set Python3_ROOT_DIR
, but this directory may not be unique, it may contain multiple versions of Python, and CMake sometimes picks the wrong one.
For example, if a user installs both Python 3.12 and 3.13 (using make altinstall
) in /usr/local
, the installation tree could look like this:
/usr/local
├── bin
│ ├── python3.12
│ ├── python3.12-config
│ ├── python3.13
│ └── python3.13-config
├── include
│ ├── python3.12
│ └── python3.13
└── lib
├── libpython3.12.so.1.0
├── libpython3.13.so.1.0
├── libpython3.so
├── python3.12
└── python3.13
When setting Python3_ROOT_DIR=/usr/local
, FindPython will always pick Python 3.13, unless I explicitly set all hints, artifacts and result variables such as Python3_INCLUDE_DIR
, Python3_SOABI
, etc.
Is there a way to guarantee that FindPython ignores any other Python versions? Even if the given Python installation does not satisfy the version range provided in the user’s find_package
call, it should not consider any other Python installations that satisfy them, returning NOTFOUND
instead.
Related: https://gitlab.kitware.com/cmake/cmake/-/issues/26505