-
-
Notifications
You must be signed in to change notification settings - Fork 740
Expand file tree
/
Copy pathITKSetPython3Vars.cmake
More file actions
261 lines (250 loc) · 9.76 KB
/
Copy pathITKSetPython3Vars.cmake
File metadata and controls
261 lines (250 loc) · 9.76 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# If the cmake variable "PYTHON_DEVELOPMENT_REQUIRED" is set to ON
# then the development environments are found.
# CMake will use FindPython3 and can be controlled accordingly (i.e. setting Python3_ROOT_DIR or
# Python3_FIND_REGISTRY (useful if using PATH to specify Python3 version on Windows).
# Additionally, setting Python3_EXECUTABLE can be used to set the Python version explicitly, but
# may become less reliable with newer versions of CMake (as opposed setting FindPython3 HINTS). Current
# implementation gives preference to active virtualenvs.
cmake_policy(SET CMP0094 NEW) # makes FindPython3 prefer activated virtualenv Python to latest version
# Canonical floor; a specified Python3_EXECUTABLE narrows PYTHON_VERSION_MIN below, so keep it separate.
set(ITK_WRAP_PYTHON_MINIMUM_VERSION 3.11)
set(PYTHON_VERSION_MIN ${ITK_WRAP_PYTHON_MINIMUM_VERSION})
set(PYTHON_VERSION_MAX 3.999)
if(DEFINED Python3_EXECUTABLE) # if already specified
set(_specified_Python3_EXECUTABLE ${Python3_EXECUTABLE})
# If a specific Python executable is provided, lock the Python version range
# to the exact version down to the minor release of that executable so FindPython3 searches that version.
execute_process(
COMMAND
"${_specified_Python3_EXECUTABLE}" -c
"import sys; print('{}.{}.{}'.format(sys.version_info[0], sys.version_info[1], sys.version_info[2]))"
OUTPUT_VARIABLE _specified_Python3_VERSION_MM
ERROR_VARIABLE _specified_Python3_VERSION_MM_ERR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(_specified_Python3_VERSION_MM)
# execute_process re-runs every configure, so this also rejects incremental
# reconfigures of a cached below-floor tree, before any wrapping work.
if(
PYTHON_DEVELOPMENT_REQUIRED
AND
_specified_Python3_VERSION_MM
VERSION_LESS
${ITK_WRAP_PYTHON_MINIMUM_VERSION}
)
message(
FATAL_ERROR
"ITK Python wrapping (ITK_WRAP_PYTHON=ON) requires Python >= ${ITK_WRAP_PYTHON_MINIMUM_VERSION}, "
"but the specified Python3_EXECUTABLE=${_specified_Python3_EXECUTABLE} is Python ${_specified_Python3_VERSION_MM}. "
"Provide a Python >= ${ITK_WRAP_PYTHON_MINIMUM_VERSION} interpreter, or set ITK_WRAP_PYTHON=OFF."
)
endif()
set(PYTHON_VERSION_MIN ${_specified_Python3_VERSION_MM})
set(PYTHON_VERSION_MAX ${_specified_Python3_VERSION_MM})
endif()
unset(_specified_Python3_VERSION_MM)
unset(_specified_Python3_VERSION_MM_ERR)
endif()
# Tested in cmake 3.26-4.21. Python3_FIND_ABI causes the Development COMPONENTS to not be found
unset(Python3_FIND_ABI)
if(NOT PYTHON_DEVELOPMENT_REQUIRED)
# if not PYTHON_DEVELOPMENT_REQUIRED, just find some version of
# Python (don't need to be as specific)
find_package(
Python3
${PYTHON_VERSION_MIN}...${PYTHON_VERSION_MAX}
COMPONENTS
Interpreter
)
set(ITK_WRAP_PYTHON_VERSION "ITK_WRAP_PYTHON=OFF")
else()
# Wrapping requires this version and every module is abi3, so the wrapping
# floor and the Limited API floor are the same number. Cached so
# itk_end_wrap_module.cmake can pin USE_SABI to it.
set(
_ITK_MINIMUM_SUPPORTED_LIMITED_API_VERSION
${ITK_WRAP_PYTHON_MINIMUM_VERSION}
CACHE INTERNAL
"Minimum Python minor version for the abi3 / Limited API floor"
)
if(CMAKE_VERSION VERSION_LESS "3.26")
message(
FATAL_ERROR
"CMake version ${CMAKE_VERSION} is too old for Python wrapping: "
"the FindPython Development.SABIModule component requires CMake >= 3.26. "
"Either upgrade CMake or set ITK_WRAP_PYTHON=OFF."
)
endif()
set(
_python_find_components
Interpreter
Development.SABIModule
)
if(BUILD_TESTING)
# NumPy Required for testing ITK PythonTests, prefer to fail early if not installed
list(APPEND _python_find_components NumPy)
endif()
set(_missing_required_component FALSE)
set(_missing_python_components "")
# set(Python3_FIND_REGISTRY LAST) # default is FIRST. Do we need/want this?
find_package(
Python3
${PYTHON_VERSION_MIN}...${PYTHON_VERSION_MAX}
COMPONENTS
# NOTE: dockcross build environments do not supply
# `Development` python-dev resources
${_python_find_components}
)
set(ITK_WRAP_PYTHON_VERSION "${Python3_VERSION}")
# An empty Python3_VERSION means the range found nothing.
if(
NOT
Python3_VERSION
OR
Python3_VERSION
VERSION_LESS
${ITK_WRAP_PYTHON_MINIMUM_VERSION}
)
message(
FATAL_ERROR
"ITK Python wrapping (ITK_WRAP_PYTHON=ON) requires Python >= ${ITK_WRAP_PYTHON_MINIMUM_VERSION}, "
"but no such interpreter was found in range ${PYTHON_VERSION_MIN}...${PYTHON_VERSION_MAX} "
"(resolved version '${Python3_VERSION}', Python3_EXECUTABLE='${Python3_EXECUTABLE}'). "
"Provide a Python >= ${ITK_WRAP_PYTHON_MINIMUM_VERSION} interpreter, or set ITK_WRAP_PYTHON=OFF."
)
endif()
message(STATUS "Python3_FOUND=${Python3_FOUND}")
foreach(_required_component ${_python_find_components})
if(NOT Python3_${_required_component}_FOUND)
message(
STATUS
" o Python3 Missing COMPONENT: Python3_${_required_component}_FOUND: ${Python3_${_required_component}_FOUND}"
)
set(_missing_required_component TRUE)
list(APPEND _missing_python_components ${_required_component})
else()
message(
STATUS
" o Python3 Found COMPONENT: Python3_${_required_component}_FOUND: ${Python3_${_required_component}_FOUND}"
)
endif()
endforeach()
unset(_required_component)
if(_missing_required_component)
set(_missing_component_remedy "")
if(NumPy IN_LIST _missing_python_components)
string(
APPEND
_missing_component_remedy
"
NumPy: ${Python3_EXECUTABLE} -m pip install numpy"
)
endif()
if(Development.SABIModule IN_LIST _missing_python_components)
string(
APPEND
_missing_component_remedy
"
Development: install the development headers matching this interpreter
(Debian/Ubuntu: apt install python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}-dev)"
)
endif()
message(
FATAL_ERROR
"Missing required Python3 COMPONENT(s): ${_missing_python_components}${_missing_component_remedy}
Or set ITK_WRAP_PYTHON=OFF to build without Python wrapping.
---
Searched for : ${_python_find_components}
in range ${PYTHON_VERSION_MIN}...${PYTHON_VERSION_MAX}:
Python3_EXECUTABLE=:${Python3_EXECUTABLE}:
ITK_WRAP_PYTHON_VERSION=:${ITK_WRAP_PYTHON_VERSION}:
Python3_ROOT_DIR=:${Python3_ROOT_DIR}:
---
Python3_FOUND=${Python3_FOUND}
Python3_Interpreter_FOUND=${Python3_Interpreter_FOUND}
Python3_Compiler_FOUND=${Python3_Compiler_FOUND}
Python3_Development_FOUND=${Python3_Development_FOUND}
Python3_Development.SABIModule_FOUND=${Python3_Development.SABIModule_FOUND}
Python3_Development.Embed_FOUND=${Python3_Development.Embed_FOUND}
Python3_NumPy_FOUND=${Python3_NumPy_FOUND}
"
)
unset(_missing_component_remedy)
else()
message(STATUS " o Python3_EXECUTABLE=${Python3_EXECUTABLE}")
message(STATUS " o Python3_ROOT_DIR=${Python3_ROOT_DIR}")
message(STATUS " o ITK_WRAP_PYTHON_VERSION=${ITK_WRAP_PYTHON_VERSION}")
endif()
unset(_missing_required_component)
unset(_missing_python_components)
unset(_python_find_components)
# _ITK_MINIMUM_SUPPORTED_LIMITED_API_VERSION is cached (INTERNAL) and intentionally
# left set so itk_end_wrap_module.cmake can pin USE_SABI to the same floor.
if(DEFINED _specified_Python3_EXECUTABLE)
set(
Python3_EXECUTABLE
${_specified_Python3_EXECUTABLE}
CACHE INTERNAL
"Path to the Python interpreter"
FORCE
)
endif()
if(NOT Python3_EXECUTABLE AND _specified_Python3_EXECUTABLE) # workaround for cases where FindPython3 fails to set correctly
set(
Python3_EXECUTABLE
${_specified_Python3_EXECUTABLE}
CACHE INTERNAL
"Path to the Python interpreter"
FORCE
)
endif()
# If a specific Python3_EXECUTABLE is provided by the user, try to infer
# the corresponding Python3_ROOT_DIR so CMake's FindPython3 locates the
# matching installation or virtual environment.
# This is especially important for virtualenv/venv/conda environments
# and on Windows where FindPython3 may otherwise pick the wrong installation.
if(DEFINED Python3_EXECUTABLE AND NOT DEFINED Python3_ROOT_DIR)
# First, try sys.prefix from the provided interpreter (works for venv/conda)
execute_process(
COMMAND
"${Python3_EXECUTABLE}" -c "import sys; print(sys.prefix)"
OUTPUT_VARIABLE _py_prefix
ERROR_VARIABLE _py_prefix_err
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(_py_prefix)
file(TO_CMAKE_PATH "${_py_prefix}" _py_root_hint)
endif()
# Fallback: parent of the interpreter's bin directory, e.g., /path/to/env
# from /path/to/env/bin/python3
if(NOT _py_root_hint)
get_filename_component(_py_exe_dir "${Python3_EXECUTABLE}" DIRECTORY)
get_filename_component(_py_root_hint "${_py_exe_dir}/.." REALPATH)
endif()
if(_py_root_hint)
set(
Python3_ROOT_DIR
"${_py_root_hint}"
CACHE PATH
"Which installation or virtual environment of Python to use"
FORCE
)
mark_as_advanced(Python3_ROOT_DIR)
endif()
unset(_py_prefix)
unset(_py_prefix_err)
unset(_py_exe_dir)
unset(_py_root_hint)
endif()
if(Python3_ROOT_DIR)
# Add user-visible cache entry if Python3_ROOT_DIR value is set
set(
Python3_ROOT_DIR
${Python3_ROOT_DIR}
CACHE PATH
"Which installation or virtual environment of Python to use"
FORCE
)
mark_as_advanced(Python3_ROOT_DIR)
endif()
endif()