-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFindPythonInterpreter.cmake
More file actions
131 lines (104 loc) · 5.15 KB
/
FindPythonInterpreter.cmake
File metadata and controls
131 lines (104 loc) · 5.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# Copyright 2021, Robert Adam. All rights reserved.
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file at the root of the
# source tree.
cmake_minimum_required(VERSION 3.5)
function(find_python_interpreter)
set(options REQUIRED EXACT)
set(oneValueArgs VERSION INTERPRETER_OUT_VAR VERSION_OUT_VAR)
set(multiValueArgs HINTS)
cmake_parse_arguments(FIND_PYTHON_INTERPRETER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# Error handling
if (FIND_PYTHON_INTERPRETER_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unrecognized arguments to find_python_interpreter: \"${FIND_PYTHON_INTERPRETER_UNPARSED_ARGUMENTS}\"")
endif()
if (NOT FIND_PYTHON_INTERPRETER_INTERPRETER_OUT_VAR)
message(FATAL_ERROR "Called find_python_interpreter without the INTERPRETER_OUT_VAR parameter!")
endif()
if (FIND_PYTHON_INTERPRETER_EXACT AND NOT FIND_PYTHON_INTERPRETER_VERSION)
message(FATAL_ERROR "Specified EXACT but did not specify VERSION!")
endif()
# Defaults
if (NOT FIND_PYTHON_INTERPRETER_VERSION)
set(FIND_PYTHON_INTERPRETER_VERSION "0.0.0")
endif()
if (NOT FIND_PYTHON_INTERPRETER_HINTS)
set(FIND_PYTHON_INTERPRETER_HINTS "")
endif()
# Validate
if (NOT FIND_PYTHON_INTERPRETER_VERSION MATCHES "^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$")
message(FATAL_ERROR "Invalid VERSION \"FIND_PYTHON_INTERPRETER_VERSION\" - must follow RegEx \"^[0-9]+(\.[0-9]+(\.[0-9]+)?)?$\"")
endif()
# "parse" version (first append 0.0.0 in case only a part of the version scheme was set by the user)
string(CONCAT VERSION_HELPER "${FIND_PYTHON_INTERPRETER_VERSION}" ".0.0.0")
string(REPLACE "." ";" VERSION_LIST "${VERSION_HELPER}")
list(GET VERSION_LIST 0 FIND_PYTHON_INTERPRETER_VERSION_MAJOR)
list(GET VERSION_LIST 1 FIND_PYTHON_INTERPRETER_VERSION_MINOR)
list(GET VERSION_LIST 1 FIND_PYTHON_INTERPRETER_VERSION_PATCH)
# Create names for the interpreter to search for
set(INTERPRETER_NAMES "")
if (FIND_PYTHON_INTERPRETER_VERSION_MAJOR STREQUAL "0")
# Search for either Python 2 or 3
list(APPEND INTERPRETER_NAMES "python3")
list(APPEND INTERPRETER_NAMES "python")
list(APPEND INTERPRETER_NAMES "python2")
else()
# Search for specified version
list(APPEND INTERPRETER_NAMES "python${FIND_PYTHON_INTERPRETER_VERSION_MAJOR}")
list(APPEND INTERPRETER_NAMES "python")
if (NOT FIND_PYTHON_INTERPRETER_VERSION_MINOR EQUAL 0)
list(PREPEND INTERPRETER_NAMES "python${FIND_PYTHON_INTERPRETER_VERSION_MAJOR}.${FIND_PYTHON_INTERPRETER_VERSION_MINOR}")
if (NOT FIND_PYTHON_INTERPRETER_VERSION_PATCH EQUAL 0)
list(PREPEND INTERPRETER_NAMES
"python${FIND_PYTHON_INTERPRETER_VERSION_MAJOR}.${FIND_PYTHON_INTERPRETER_VERSION_MINOR}.${FIND_PYTHON_INTERPRETER_VERSION_PATCH}")
endif()
endif()
endif()
# Start by trying to search for a python executable in PATH and HINTS
find_program(PYTHON_INTERPRETER NAMES ${INTERPRETER_NAMES} HINTS ${FIND_PYTHON_INTERPRETER_HINTS})
if (NOT PYTHON_INTERPRETER)
# Fall back to find_package
message(VERBOSE "Can't find Python interpreter in PATH -> Falling back to find_package")
if (FIND_PYTHON_INTERPRETER_VERSION_MAJOR EQUAL 0)
# Search arbitrary version
find_package(Python COMPONENTS Interpreter QUIET)
set(PYTHON_INTERPRETER "${Python_EXECUTABLE}")
else()
# Search specific version (Python 2 or 3)
find_package(Python${FIND_PYTHON_INTERPRETER_VERSION_MAJOR} COMPONENTS Interpreter QUIET)
set(PYTHON_INTERPRETER "${Python${FIND_PYTHON_INTERPRETER_VERSION_MAJOR}_EXECUTABLE}")
endif()
endif()
if (PYTHON_INTERPRETER)
# Verify that the version found is the one that is wanted
execute_process(
COMMAND ${PYTHON_INTERPRETER} "--version"
OUTPUT_VARIABLE PYTHON_INTERPRETER_VERSION
ERROR_VARIABLE PYTHON_INTERPRETER_VERSION # Python 2 reports the version on stderr
)
# Remove leading "Python " from version information
string(REPLACE "Python " "" PYTHON_INTERPRETER_VERSION "${PYTHON_INTERPRETER_VERSION}")
string(STRIP "${PYTHON_INTERPRETER_VERSION}" PYTHON_INTERPRETER_VERSION)
if (PYTHON_INTERPRETER_VERSION VERSION_LESS FIND_PYTHON_INTERPRETER_VERSION)
message(STATUS "Found Python version ${PYTHON_INTERPRETER_VERSION} but required at least ${FIND_PYTHON_INTERPRETER_VERSION}")
set(PYTHON_INTERPRETER "NOTFOUND")
set(PYTHON_INTERPRETER_VERSION "NOTFOUND")
elseif(PYTHON_INTERPRETER_VERSION VERSION_GREATER FIND_PYTHON_INTERPRETER_VERSION AND FIND_PYTHON_INTERPRETER_EXACT)
message(STATUS "Found Python interpreter version ${PYTHON_INTERPRETER_VERSION} but required exactly ${FIND_PYTHON_INTERPRETER_VERSION}")
set(PYTHON_INTERPRETER "NOTFOUND")
set(PYTHON_INTERPRETER_VERSION "NOTFOUND")
else()
message(STATUS "Found Python interpreter version ${PYTHON_INTERPRETER_VERSION}")
endif()
else()
set(PYTHON_INTERPRETER_VERSION "NOTFOUND")
endif()
# Set "return" values
set(${FIND_PYTHON_INTERPRETER_INTERPRETER_OUT_VAR} "${PYTHON_INTERPRETER}" PARENT_SCOPE)
if (FIND_PYTHON_INTERPRETER_VERSION_OUT_VAR)
set(${FIND_PYTHON_INTERPRETER_VERSION_OUT_VAR} "${PYTHON_INTERPRETER_VERSION}" PARENT_SCOPE)
endif()
if (NOT PYTHON_INTERPRETER AND FIND_PYTHON_INTERPRETER_REQUIRED)
message(FATAL_ERROR "Did NOT find Python interpreter")
endif()
endfunction()