-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathkwiver-setup-python.cmake
301 lines (260 loc) · 10.3 KB
/
kwiver-setup-python.cmake
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
###
# Finds the python binaries, libs, include, and site-packages paths
#
# The purpose of this file is to export variables that will be used in
# kwiver/CMake/utils/kwiver-utils-python.cmake and
# kwiver/sprokit/conf/sprokit-macro-python.cmake (the latter will eventually be
# consolidated into the former)
#
# User options defined in this file:
#
# KWIVER_PYTHON_MAJOR_VERSION
# The major python version to target (either 2 or 3)
#
#
# Calls find_packages to on python interpreter/libraries which defines:
#
# PYTHON_EXECUTABLE
# PYTHON_INCLUDE_DIR
# PYTHON_LIBRARY
# PYTHON_LIBRARY_DEBUG
#
# Exported variables used by python utility functions are:
#
# PYTHON_VERSION
# the major/minor python version
#
# PYTHON_ABI_FLAGS
# Python abstract binary interface flags (used internally for defining
# subsequent variables, but settable by the user as an advanced setting)
#
# python_site_packages
# Location where python packages are installed relative to your python
# install directory. For example:
# Windows system install: Lib\site-packages
# Debian system install: lib/python2.7/dist-packages
# Debian virtualenv install: lib/python3.5/site-packages
#
# python_sitename
# The basename of the python_site_packages directory. This is either
# site-packages (in most cases) or dist-packages (if your python was
# configured by a debian package manager). If you are using a python
# virtualenv (you should be) then this will be site-packages
#
# kwiver_python_subdir
# basename of the python lib folder (that contains site-packages).
# Depends on the python major/minor version and the ABI flags
# (e.g. python2.7, python3.5m)
#
# kwiver_python_output_path
# The location in the build tree to copy/symlink python modules Depends on
# the value of `kwiver_python_subdir`.
# (e.g. build/lib/python2.7, build/lib/python3.5m)
#
# kwiver_python_install_path
# The base location in the install tree where python files/modules are
# to be installed.
# (e.g. ${CMAKE_INSTALL_PREFIX}/lib/python3)
#
# sprokit_python_output_path
# Similar to `kwiver_python_output_path`. Used by sprokit to define extra
# python output paths. This may be removed in the future.
# (e.g. build/lib)
#
###
# Private helper function to execute `python -c "<cmd>"`
#
# Runs a python command and populates an outvar with the result of stdout.
# Be careful of indentation if `cmd` is multiline.
#
function(_pycmd outvar cmd)
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" -c "${cmd}"
RESULT_VARIABLE _exitcode
OUTPUT_VARIABLE _output)
if(NOT ${_exitcode} EQUAL 0)
message(ERROR "Failed when running python code: \"\"\"
${cmd}\"\"\"")
message(FATAL_ERROR "Python command failed with error code: ${_exitcode}")
endif()
# Remove supurflous newlines (artifacts of print)
string(STRIP "${_output}" _output)
set(${outvar} "${_output}" PARENT_SCOPE)
endfunction()
###
# Python major version user option
#
# Respect the PYTHON_VERSION_MAJOR version if it is set
if (PYTHON_VERSION_MAJOR)
set(DEFAULT_PYTHON_MAJOR ${PYTHON_VERSION_MAJOR})
else()
set(DEFAULT_PYTHON_MAJOR "3")
endif()
set(KWIVER_PYTHON_MAJOR_VERSION "${DEFAULT_PYTHON_MAJOR}" CACHE STRING "Python version to use: 3 or 2")
set_property(CACHE KWIVER_PYTHON_MAJOR_VERSION PROPERTY STRINGS "3" "2")
###
# Detect major version change (part1)
#
# Clear cached variables when the user changes major python versions.
# When this happens, we need to re-find the bin, include, and libs
#
if (NOT __prev_kwiver_pyversion STREQUAL KWIVER_PYTHON_MAJOR_VERSION)
# but dont clobber initial settings in the instance they are specified via
# commandline (e.g cmake -DPYTHON_EXECUTABLE=/my/special/python)
if (__prev_kwiver_pyversion)
message(STATUS "The Python version changed; refinding the interpreter")
message(STATUS "The previous Python version was: \"${__prev_kwiver_pyversion}\"")
unset(__prev_kwiver_pyversion CACHE)
unset(PYTHON_EXECUTABLE CACHE)
unset(PYTHON_INCLUDE_DIR CACHE)
unset(PYTHON_LIBRARY CACHE)
unset(PYTHON_LIBRARY_DEBUG CACHE)
unset(PYTHON_ABIFLAGS CACHE)
endif()
endif()
###
#
# Mark the previous version so we can determine when python versions change
#
set(__prev_kwiver_pyversion "${KWIVER_PYTHON_MAJOR_VERSION}" CACHE INTERNAL
"allows us to determine if the user changes python version")
###
# Python interpreter and libraries
#
if (KWIVER_PYTHON_MAJOR_VERSION STREQUAL "3")
# note, 3.4 is a minimum version
find_package(Python 3.4 COMPONENTS Interpreter Development REQUIRED)
else()
find_package(Python 2.7 COMPONENTS Interpreter Development REQUIRED)
endif()
set(PYTHON_EXECUTABLE ${Python_EXECUTABLE} CACHE FILEPATH "Path to Python executable")
set(PYTHON_INCLUDE_DIR ${Python_INCLUDE_DIRS} CACHE STRING "Paths to Python include directories")
set(PYTHON_LIBRARY ${Python_LIBRARIES} CACHE STRING "Paths to Python libraries")
set(PYTHON_LIBRARY_DEBUG PYTHON_LIBRARY_DEBUG_NOT_FOUND CACHE FILEPATH "Path to Python debug libraries")
include_directories(SYSTEM ${PYTHON_INCLUDE_DIR})
###
# Python site-packages
#
# Get canonical directory for python site packages (relative to install
# location). It varys from system to system.
#
_pycmd(python_site_packages "from distutils import sysconfig; print(sysconfig.get_python_lib(prefix=''))")
message(STATUS "python_site_packages = ${python_site_packages}")
# Current usage determines most of the path in alternate ways.
# All we need to supply is the '*-packages' directory name.
# Customers could be converted to accept a larger part of the path from this function.
get_filename_component(python_sitename ${python_site_packages} NAME)
###
# Python install path
set(kwiver_python_install_path "${CMAKE_INSTALL_PREFIX}/${python_site_packages}")
message(STATUS "kwiver_python_install_path = ${kwiver_python_install_path}")
###
# Python major/minor version
#
# Use the executable to find the major/minor version.
# If you want to change this, then change the executable.
#
_pycmd(PYTHON_VERSION "import sys; print(sys.version[0:3])")
# assert that the right python version was found
if(NOT PYTHON_VERSION MATCHES "^${KWIVER_PYTHON_MAJOR_VERSION}.*")
message(STATUS "KWIVER_PYTHON_MAJOR_VERSION = ${KWIVER_PYTHON_MAJOR_VERSION}")
message(STATUS "PYTHON_VERSION = ${PYTHON_VERSION}")
message(FATAL_ERROR "Requested python \"${KWIVER_PYTHON_MAJOR_VERSION}\" but got \"${PYTHON_VERSION}\"")
endif()
###
# Python ABI Flags
#
# See PEP 3149 - ABI (application binary interface) version tagged .so files
# https://www.python.org/dev/peps/pep-3149/
#
if (KWIVER_PYTHON_MAJOR_VERSION STREQUAL "3")
# In python 3, we can determine what the ABI flags are
_pycmd(_python_abi_flags "from distutils import sysconfig; print(sysconfig.get_config_var('ABIFLAGS'))")
else()
# Not sure if ABI flags are easilly found (or are even used in python2)
set(_python_abi_flags, "")
endif()
set(PYTHON_ABIFLAGS "${_python_abi_flags}"
CACHE STRING "The ABI flags for the version of Python being used")
mark_as_advanced(PYTHON_ABIFLAGS)
###
# Python dependencies
#
# Add python packages needed to execute the bindings
# to requirements.txt file
#
list(APPEND PYTHON_REQS "numpy>=1.13.0,<=1.19.0" "six>=1.10.0,<=1.13.0")
if(SKBUILD)
list(APPEND PYTHON_REQS "scikit-build<=0.11.1")
endif()
if(KWIVER_ENABLE_PYTORCH)
list(APPEND PYTHON_REQS "opencv-python>=3.4.2.17,<=4.0.0"
"pillow>=7.0.0,<=7.1.2"
"scipy>=1.2,<=1.5"
"torch==1.4.0"
"torchvision==0.5.0"
)
endif()
###
# PyBind11
#
#
#
set(pybind11_library python)
find_package(pybind11)
###
# Python Dependencies
#
# sets the python dependencies defined in python/requirements.txt
# to be a custom command of the python libraries target
# a venv will be created to encapsulate the pip installed dependencies
# from the larger system, while still providing the tests access to their dependencies
#
if (KWIVER_ENABLE_TESTS)
message(STATUS "KWIVER_PYTHON and KWIVER_TESTING enabled.")
message(STATUS "Python tests will be added to CTest.")
message(STATUS "Tests are executed by PYTEST, for sucessful test execution, please install the appropriate pytest for your python distribution.")
message(STATUS "Testing dependencies will be added to Python requirements.")
set(PYTHON_TEST 1)
set(PYTHON_REQS "${PYTHON_REQS};nose>1.2;coverage>=4.4.1,<5.0.0;pytest>=4.6,<=6.0;multimethod>=1.2,<=1.4")
endif()
string(REPLACE ";" "\n" PYTHON_REQS "${PYTHON_REQS}")
file(WRITE ${KWIVER_BINARY_DIR}/python/requirements.txt "${PYTHON_REQS}")
###
# Python package build locations
#
# defines paths used to determine where the kwiver/sprokit/vital python
# packages will be generated in the build tree. (TODO: python modules should
# use a setup.py file to install themselves to the right location)
#
#set(kwiver_python_subdir "python${PYTHON_VERSION}${PYTHON_ABIFLAGS}")
# Instead of contructing the directory with ABIFLAGS just use what python gives us
get_filename_component(python_lib_subdir ${python_site_packages} DIRECTORY)
get_filename_component(python_subdir ${python_lib_subdir} NAME)
set(kwiver_python_subdir ${python_subdir})
set(kwiver_python_output_path "${KWIVER_BINARY_DIR}/${python_lib_subdir}")
# Currently needs to be separate because sprokit may have CONFIGURATIONS that
# are placed between lib and `kwiver_python_subdir`
set(sprokit_python_output_path "${KWIVER_BINARY_DIR}/lib")
set(KWIVER_PYTHON_VERSION "${PYTHON_VERSION}" CACHE STRING "" )
mark_as_advanced(KWIVER_PYTHON_VERSION)
###
# Status string for debugging
#
set(PYTHON_CONFIG_STATUS "
PYTHON_CONFIG_STATUS
* KWIVER_PYTHON_MAJOR_VERSION = \"${KWIVER_PYTHON_MAJOR_VERSION}\"
* PYTHON_EXECUTABLE = \"${PYTHON_EXECUTABLE}\"
* PYTHON_INCLUDE_DIR = \"${PYTHON_INCLUDE_DIR}\"
* PYTHON_LIBRARY = \"${PYTHON_LIBRARY}\"
* PYTHON_LIBRARY_DEBUG = \"${PYTHON_LIBRARY_DEBUG}\"
* PYTHON_ABIFLAGS = \"${PYTHON_ABIFLAGS}\"
* PYTHON_VERSION = \"${PYTHON_VERSION}\"
* python_site_packages = \"${python_site_packages}\"
* python_sitename = \"${python_sitename}\"
* kwiver_python_subdir = \"${kwiver_python_subdir}\"
* kwiver_python_install_path = \"${kwiver_python_install_path}\"
* kwiver_python_output_path = \"${kwiver_python_output_path}\"
* sprokit_python_output_path = \"${sprokit_python_output_path}\"
")
message(STATUS "${PYTHON_CONFIG_STATUS}")