[CMake] Finding Python3

Michael Hertling mhertling at online.de
Fri Jul 23 00:29:50 EDT 2010


On 07/22/2010 10:36 AM, Michael Wild wrote:
> 
> On 22. Jul, 2010, at 10:17 , Marcel Loose wrote:
> [...]
>>
>> Hi Michael and others,
>>
>> I mostly agree with what your saying. However, IMHO, you refer to a
>> "perfect world" situation, where all Find modules properly use VERSION
>> to specify a version number and do not abuse NAMES for that.
>>
>> I know that the current discussion focuses on FindPython; hence the
>> subject ;-). However, in the "real world" quite a number of other Find
>> scripts are shipped as part of the CMake distribution that don't follow
>> this "perfect" scheme either.
>>
>> So the real question should be, I guess: Should CMake be fixed by
>> swapping the paths and names loops in the FindXXX() functions (issue
>> 10718)? Or should all abusing Find scripts be fixed?
>>
>> Best regards,
>> Marcel Loose.
> 
> My question is more fundamental:
> 
> How do I find the most recent version? Because that is why NAMES is being "abused" in the first place.

That's a very good point. The simplest approach is probably to rely on
the assumption that the unversioned executable is the most recent one,
but this won't be true in any case, of course. If one doesn't want to
hardcode the possible versions in the correct order after the NAMES
option there has to be a way to teach the find module how to respect
such auxiliary conditions like "take the highest acceptable version".

Earlier in this thread, I presented a function GET_PYTHON_VERSION()
that looks for Python libraries without querying the interpreter and
extracts the version from the first one found; this function can be
modified to return the highest version instead, e.g. as follows:

FUNCTION(GET_PYTHON_VERSION RESULT)
    SET(v)
    FOREACH(i IN LISTS PYTHON_ROOT ARGN)
        FILE(GLOB j "${i}/lib/python*")
        FOREACH(k IN LISTS j)
            IF(k MATCHES "python[0-9].*\$")
                STRING(REGEX REPLACE
                    "^.*python([0-9].*)\$" "\\1" l "${k}"
                )
                IF("${l}" VERSION_GREATER "${v}")
                    SET(v "${l}")
                ENDIF()
            ENDIF()
        ENDFOREACH()
    ENDFOREACH()
    SET("${RESULT}" "${v}" PARENT_SCOPE)
ENDFUNCTION()

Of course, the crucial moment is to provide the directories to search.
Here, the variable PYTHON_ROOT assists, and the directories examined by
FIND_PROGRAM() are known, so it should be possible to visit each Python
installation and figure out the version of the most recent amongst them.
Further refinements may be performed with the globbing expression, e.g.
FILE(GLOB j "${i}/lib/python2.*") to search for Python 2 installations
only, which could in turn be fed by the Python_FIND_VERSION variables.
Finally, the result of GET_PYTHON_VERSION() can be used in subsequent
calls to FIND_PROGRAM() et al. to locate the Python installation with
the most recent version.

Regards,

Michael


More information about the CMake mailing list