[CMake] Finding Python3

Michael Hertling mhertling at online.de
Mon Jul 19 18:51:56 EDT 2010


On 07/18/2010 10:14 PM, Alan W. Irwin wrote:
> On 2010-07-18 12:07-0700 Branan Purvine-Riley wrote:
> 
>> Unfortunately, I can't think of a way to get out of using hardcoded version
>> lists, since python is often in specific locations (or has a specific executable
>> name) based on its version number.
> 
> I haven't read through the new "Find Python" work up to now so my
> apologies in advance if you do this already, but let me suggest what I
> believe is the simplest versioning approach possible. I have two
> underlying assumptions:
> 
> (1) http://public.kitware.com/Bug/view.php?id=10718 is fixed.  In my
> view this bug has been the source of much CMake find trouble for a long
> time, and I hope the CMake developers make it a high priority to fix
> it for CMake-2.8.3.

Personally, I'm in doubt if 10718 should be considered as a bug. IMO,
the NAMES option of the find commands is meant to denote alternative
names of the file/path/program/library to be found but not different
versions. Instead, specifying different versions is a misuse of the
NAMES option, and that's the actual source of trouble with the find
commands in this regard. E.g., if you say

FIND_PROGRAM(PYTHON3_EXECUTABLE NAMES python3.1 python3.0 python3 ...)

you express that the version doesn't matter to you, so you can't
complain later that the interpreter's version doesn't match the
libraries' one as this means the version does matter after all.
The correct usage would be to respect the version passed in by
FIND_PACKAGE() and search for the appropriate executable, i.e.
"python" if no version is specified, "python3.1" for version
"3.1" etc., and that's the responsibility of the find module
but not the responsibility of FIND_PROGRAM() et al.

> (2) The user is smart enough to put the python executable that they
> want to use first on their (super-)PATH.
> 
> Once those two assumptions are fulfilled, the rest is straightforward.
> 
> Use find_program with a list (this is the inescapable maintenance
> issue) of the names of all possible python excutable names (with
> python at the top of that list and then after that in descending
> version order).  If assumption (1) is correct, the order of this list
> of alternative names for the python executable only matters if various
> versions of python all occur within the first directory on the
> super-PATH that contains any python executable at all.

As I've just replied to Branan, I think it's unnecessary to hardcode
versions in a FindPython.cmake, and it is this in junction with the
wrong usage of the find commands' NAMES option which I blame for the
problems finding the interpreter and the libraries. How to find the
interpreter without hardcoded versions is outlined above, and how to
find the libraries without querying an already found interpreter I
outlined in my reply to Branan, see GET_PYTHON_VERSION() with
PYTHON_ROOT.

> The find_program approach will work most of the time since the python
> executable name will either be python or some versioned name that is
> located in a unique directory high on the super-path
> with no other versioned possibilites in
> that same directory. However, sometimes you may have the case where
> python refers to, say, /usr/bin/python2.6, but the version the user
> wants is /usr/bin/python2.5, and you are not running Debian where you
> can easily switch between the two using the update-alternatives
> --config command.  Or the CMake developers may have trouble fixing bug
> 10718 in a timely manner. For that special case where CMake appears
> unable to find the python executable the user wants, there should be a
> CMake mechanism to allow the user to pick exactly the python
> executable they want.

E.g. FIND_PACKAGE(Python 3.1 EXACT REQUIRED interpreter).

> Once the python executable has been determined, its exact version can
> be found by running, e.g.,
> 
> # Get the Python version.
>    execute_process(
>      COMMAND
>      ${PYTHON_EXECUTABLE} -c "import sys; print sys.version.split()[0]"
>      OUTPUT_VARIABLE PYTHON_version_output
>      OUTPUT_STRIP_TRAILING_WHITESPACE
>      )
>    SET(PYTHON_VERSION ${PYTHON_version_output} CACHE STRING "Python version")
> 
> (We use this approach currently in PLplot.)  One caveat is the result of
> the above sometimes has trailing information that needs to be trimmed
> off.  For example, on my current system the result is "2.6.5+".
> 
> Once you have determined the python version number triplet this way
> from the python executable specified by the user, then enforcing
> version consistency for everything else should become completely
> straightforward with no further version lists to be maintained.

Of course, querying the interpreter is quite attractive for gathering
information, but you must be prepared for an interpreter being absent
or not able to run on your host system, so one of the challenges of a
generally usable FindPython.cmake is how to find the python libraries
without using an interpreter. For this reason I suggested an external
flag PYTHON_NATIVE the user can indicate with if the interpreter may
run to reveal the python installation's secrets.

Regards,

Michael


More information about the CMake mailing list