FindPythonModules.cmake
Go to the documentation of this file.
00001 ############################################################################## 00002 # @file FindPythonModules.cmake 00003 # @brief Find Python modules. 00004 # 00005 # @par Input/Output variables: 00006 # <table border="0"> 00007 # <tr> 00008 # @tp @b PythonModules_DIR @endtp 00009 # <td>List of directories where Python modules are installed.</td> 00010 # </tr> 00011 # </table> 00012 00013 # @par Input variables: 00014 # <table border="0"> 00015 # <tr> 00016 # @tp @b PythonModules_FIND_COMPONENTS @endtp 00017 # <td>The @c COMPONENTS argument(s) of the find_package() command specifies 00018 # the names of the Python modules to look for.</td> 00019 # </tr> 00020 # <tr> 00021 # @tp @b PythonModules_FIND_OPTIONAL_COMPONENTS @endtp 00022 # <td>The @c OPTIONAL_COMPONENTS argument(s) of the find_package() command 00023 # specifies the names of the Python modules which are not necessarily 00024 # required, but should be searched as well.</td> 00025 # </tr> 00026 # <tr> 00027 # @tp @b PYTHON_EXECUTABLE @endtp 00028 # <td>Path to the Python interpreter. Should be set by first looking 00029 # for the Python interpreter, i.e., find_packages(PythonInterp). 00030 # If set, this module first tries to execute the Python interpreter, 00031 # import the respective Python module, and then derive the search path 00032 # from the @c __file__ attribute of the loaded Python module. 00033 # Otherwise, or if this fails, it looks either for a package 00034 # @c __init__.py file inside a subdirectory named after the specified 00035 # Python module or a @c .py module file in each directory listed in 00036 # the @c PYTHONPATH.</td> 00037 # </tr> 00038 # <tr> 00039 # @tp @b PYTHONPATH @endtp 00040 # <td>Search path for Python modules. If this CMake variable is undefined, 00041 # the corresponding environment variable is used instead if set. 00042 # Only absolute paths in the @c PYTHONPATH are considered.</td> 00043 # </tr> 00044 # </table> 00045 # 00046 # @par Output variables: 00047 # <table border="0"> 00048 # <tr> 00049 # @tp @b PythonModules_FOUND @endtp 00050 # <td>Whether all specified Python modules were found.</td> 00051 # </tr> 00052 # <tr> 00053 # @tp @b PythonModules_<module>_FOUND @endtp 00054 # <td>Whether the Python module <module%gt; was found.</td> 00055 # </tr> 00056 # <tr> 00057 # @tp @b PythonModules_<module>_PATH @endtp 00058 # <td>Absolute path of the directory containing the Python module named <module%gt;.</td> 00059 # </tr> 00060 # <tr> 00061 # @tp @b PythonModules_<module> @endtp 00062 # <td>Import target for module named <module>. The location of the 00063 # target is @c PythonModules_<module>_PATH.</tr> 00064 # </tr> 00065 # <tr> 00066 # @tp @b PythonModules_PYTHONPATH @endtp 00067 # <td>The @c PYTHONPATH setting required for the found Python module(s), i.e., 00068 # The directories that have to be added to the Python search path. 00069 # To support the use of this CMake module more than once with different 00070 # arguments to the find_package() command, e.g., with and without the 00071 # @c REQUIRED argument, the directories containing the found Python 00072 # modules are appended to any existing directories in 00073 # @c PythonModules_PYTHONPATH if not already listed.</td> 00074 # </tr> 00075 # </table> 00076 # 00077 # @ingroup CMakeFindModules 00078 ############################################################################## 00079 00080 include (CMakeParseArguments) 00081 00082 # ---------------------------------------------------------------------------- 00083 ## @brief Find Python module. 00084 # 00085 # If the @c PYTHON_EXECUTABLE variable is set, this function at first tries 00086 # to launch the Python interpreter, import the named Python module, and then 00087 # determines the search path for the Python module from the @c __file__ 00088 # attribute of the loaded module. Otherwise, or if this fails, it looks for 00089 # the Python module in the directories listed in the @c PYTHONPATH variable 00090 # if defined. If this variable is not defined, the @c PYTHONPATH environment 00091 # variable is used instead. 00092 # 00093 # @param [in] CACHEVAR Name of CMake cache variable which stores path of 00094 # directory of the Python module. If not set or if 00095 # the cache entry contains space characters only or 00096 # ends in the string NOTFOUND, this function looks for 00097 # the specified Python module. Otherwise, it does nothing 00098 # and leaves the cache entry unmodified. 00099 # @param [in] ARGN The remaining arguments are parsed and the following 00100 # options extract: 00101 # @par 00102 # <table border=0> 00103 # <tr> 00104 # @tp @b NAME module @endtp 00105 # <td>Name of the Python module.</td> 00106 # </tr> 00107 # <tr> 00108 # @tp @b PYTHON_EXECUTABLE python @endtp 00109 # <td>Full path of the Python interpreter executable. If not specified 00110 # the global PYTHON_EXECUTABLE CMake variable/cache entry is used.</td> 00111 # </tr> 00112 # <tr> 00113 # @tp @b PATH dir1 [dir2...] @endtp 00114 # <td>Directories where to look for Python module.</td> 00115 # </tr> 00116 # <tr> 00117 # @tp @b NO_PYTHONPATH @endtp 00118 # <td>Do not consider the @c PYTHONPATH environment variable.</td> 00119 # </tr> 00120 # <tr> 00121 # @tp @b NO_DEFAULT_PATH @endtp 00122 # <td>Do not look in any default path such as the directories listed by the 00123 # @c PYTHONPATH environment variable.</td> 00124 # </tr> 00125 # </table> 00126 # 00127 # @returns Sets the named cache variable of type @c PATH to the absolute path 00128 # of the directory containing the specified Python @p MODULE if found, 00129 # or the string "<MODULE%gt;-NOTFOUND" otherwise. 00130 function (basis_find_python_module CACHEVAR) 00131 # do nothing if path of module already known from previous run 00132 if (DEFINED ${CACHEVAR} AND NOT ${CACHEVAR} MATCHES "NOTFOUND$") 00133 return () 00134 endif () 00135 # parse arguments 00136 CMAKE_PARSE_ARGUMENTS ( 00137 ARGN 00138 "NO_DEFAULT_PATH;NO_PYTHONPATH" 00139 "PYTHON_EXECUTABLE;NAME" 00140 "PATH" 00141 ${ARGN} 00142 ) 00143 if (NOT ARGN_NAME) 00144 message ("basis_find_python_module(): Missing NAME argument!") 00145 endif () 00146 if (ARGN_UNPARSED_ARGUMENTS) 00147 message ("basis_find_python_module(): Invalid arguments: ${ARGN_UNPARSED_ARGUMENTS}") 00148 endif () 00149 if (NOT ARGN_PYTHON_EXECUTABLE) 00150 set (ARGN_PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}") 00151 endif () 00152 if (ARGN_NO_DEFAULT_PATH) 00153 set (ARGN_NO_PYTHONPATH TRUE) 00154 set (ARGN_PYTHON_EXECUTABLE) 00155 endif () 00156 # set initial value of cache entry 00157 if (${CACHEVAR} MATCHES "^ *$") 00158 set (${CACHEVAR} "${ARGN_NAME}-NOTFOUND" CACHE PATH "Directory containing ${ARGN_NAME} Python module/package." FORCE) 00159 else () 00160 set (${CACHEVAR} "${ARGN_NAME}-NOTFOUND" CACHE PATH "Directory containing ${ARGN_NAME} Python module/package.") 00161 endif () 00162 # 1. search specified paths 00163 foreach (P ${ARGN_PATH}) # ignore empty entries 00164 if (IS_ABSOLUTE "${P}") 00165 if (EXISTS "${P}/${ARGN_NAME}.py" OR EXISTS "${P}/${ARGN_NAME}/__init__.py" OR 00166 EXISTS "${P}/${ARGN_NAME}.pyc" OR EXISTS "${P}/${ARGN_NAME}/__init__.pyc") 00167 set_property (CACHE ${CACHEVAR} PROPERTY VALUE "${P}") 00168 return () 00169 endif () 00170 endif () 00171 endforeach () 00172 # 2. get __file__ attribute of module loaded in Python 00173 if (ARGN_PYTHON_EXECUTABLE) 00174 set (IMPORT_SITE_ERROR FALSE) 00175 # 2a. try it with -E option -- the preferred way to run Python 00176 execute_process ( 00177 COMMAND "${ARGN_PYTHON_EXECUTABLE}" -E -c "import ${ARGN_NAME}; print ${ARGN_NAME}.__file__" 00178 RESULT_VARIABLE STATUS 00179 OUTPUT_VARIABLE P 00180 ERROR_VARIABLE ERROR 00181 OUTPUT_STRIP_TRAILING_WHITESPACE 00182 ) 00183 if (ERROR MATCHES "'import site' failed|ImportError: No module named site") 00184 set (IMPORT_SITE_ERROR TRUE) 00185 endif () 00186 # 2b. try it without -E option 00187 if (NOT STATUS EQUAL 0) 00188 execute_process ( 00189 COMMAND "${ARGN_PYTHON_EXECUTABLE}" -c "import ${ARGN_NAME}; print ${ARGN_NAME}.__file__" 00190 RESULT_VARIABLE STATUS 00191 OUTPUT_VARIABLE P 00192 ERROR_VARIABLE ERROR 00193 OUTPUT_STRIP_TRAILING_WHITESPACE 00194 ) 00195 if (ERROR MATCHES "'import site' failed|ImportError: No module named site") 00196 set (IMPORT_SITE_ERROR TRUE) 00197 endif () 00198 if (NOT STATUS EQUAL 0 AND ERROR MATCHES "ImportError: No module named site") 00199 set (PYTHONHOME "$ENV{PYTHONHOME}") 00200 unset (ENV{PYTHONHOME}) 00201 execute_process ( 00202 COMMAND "${ARGN_PYTHON_EXECUTABLE}" -c "import ${ARGN_NAME}; print ${ARGN_NAME}.__file__" 00203 RESULT_VARIABLE STATUS 00204 OUTPUT_VARIABLE P 00205 ERROR_VARIABLE ERROR 00206 OUTPUT_STRIP_TRAILING_WHITESPACE 00207 ) 00208 if (ERROR MATCHES "'import site' failed|ImportError: No module named site") 00209 set (IMPORT_SITE_ERROR TRUE) 00210 endif () 00211 set (ENV{PYTHONHOME} "${PYTHONHOME}") 00212 endif () 00213 endif () 00214 if (STATUS EQUAL 0) 00215 if (P MATCHES "__init__\\.pyc?$") 00216 get_filename_component (P "${P}" PATH) 00217 get_filename_component (P "${P}" PATH) 00218 else () 00219 get_filename_component (P "${P}" PATH) 00220 endif () 00221 set_property (CACHE ${CACHEVAR} PROPERTY VALUE "${P}") 00222 return () 00223 elseif (IMPORT_SITE_ERROR) 00224 message (WARNING "Import of site module failed when running Python interpreter ${ARGN_PYTHON_EXECUTABLE}" 00225 " with and without -E option. Make sure that the Python interpreter is installed properly" 00226 " and that the PYTHONHOME environment variable is either not set (recommended) or at" 00227 " least set correctly for this Python installation. Maybe you need to enable this Python" 00228 " version first somehow if more than one version of Python is installed on your system?" 00229 " Otherwise, set PYTHON_EXECUTABLE to the right Python interpreter executable (python).") 00230 endif () 00231 endif () 00232 # 3. search PYTHONPATH 00233 if (NOT ARGN_NO_PYTHONPATH) 00234 string (REPLACE ":" ";" PYTHONPATH "$ENV{PYTHONPATH}") 00235 foreach (P ${PYTHONPATH}) # ignore empty entries 00236 if (IS_ABSOLUTE "${P}") 00237 if (EXISTS "${P}/${ARGN_NAME}.py" OR EXISTS "${P}/${ARGN_NAME}/__init__.py" OR 00238 EXISTS "${P}/${ARGN_NAME}.pyc" OR EXISTS "${P}/${ARGN_NAME}/__init__.pyc") 00239 set_property (CACHE ${CACHEVAR} PROPERTY VALUE "${P}") 00240 return () 00241 endif () 00242 endif () 00243 endforeach () 00244 endif () 00245 endfunction () 00246 00247 # ---------------------------------------------------------------------------- 00248 # find Python modules 00249 if (NOT PythonModules_FIND_COMPONENTS AND NOT PythonModules_FIND_OPTIONAL_COMPONENTS) 00250 message (FATAL_ERROR "PythonModules: No (OPTIONAL_)COMPONENTS (i.e., Python module names) specified!") 00251 endif () 00252 if (NOT DEFINED PythonModules_PYTHONPATH) 00253 set (PythonModules_PYTHONPATH) # PYTHONPATH of all found modules 00254 endif () 00255 # helper macro 00256 macro (_PythonModules_find_python_modules ALL_FOUND) 00257 set (${ALL_FOUND} TRUE) 00258 foreach (_PythonModules_MODULE ${ARGN}) 00259 set (_PythonModules_VAR "PythonModules_${_PythonModules_MODULE}_PATH") 00260 set (_PythonModules_TGT "PythonModules_${_PythonModules_MODULE}") 00261 if (PythonModules_DIR) 00262 basis_find_python_module ( 00263 ${_PythonModules_VAR} 00264 NAME "${_PythonModules_MODULE}" 00265 PATH "${PythonModules_DIR}" 00266 NO_DEFAULT_PATH 00267 ) 00268 else () 00269 basis_find_python_module ( 00270 ${_PythonModules_VAR} 00271 NAME "${_PythonModules_MODULE}" 00272 PATH "${PythonModules_DIR}" 00273 ) 00274 endif () 00275 mark_as_advanced (${_PythonModules_VAR}) 00276 if (${_PythonModules_VAR} MATCHES "(^ *|NOTFOUND)$") 00277 set (${ALL_FOUND} FALSE) 00278 set (PythonModules_${_PythonModules_MODULE}_FOUND FALSE) 00279 else () 00280 if (NOT TARGET ${_PythonModules_TGT}) 00281 add_library (${_PythonModules_TGT} UNKNOWN IMPORTED) 00282 set_target_properties ( 00283 ${_PythonModules_TGT} 00284 PROPERTIES 00285 BASIS_TYPE "SCRIPT_LIBRARY" 00286 IMPORTED_LOCATION "${${_PythonModules_VAR}}" 00287 ) 00288 endif () 00289 set (PythonModules_${_PythonModules_MODULE}_FOUND TRUE) 00290 list (APPEND PythonModules_PYTHONPATH "${${_PythonModules_VAR}}") 00291 endif () 00292 endforeach () 00293 endmacro () 00294 # optional first, as PythonModules_FOUND shall be reset to TRUE afterwards 00295 _PythonModules_find_python_modules (PythonModules_FOUND ${PythonModules_FIND_OPTIONAL_COMPONENTS}) 00296 _PythonModules_find_python_modules (PythonModules_FOUND ${PythonModules_FIND_COMPONENTS}) 00297 # remove duplicate paths in PYTHONPATH 00298 if (PythonModules_PYTHONPATH) 00299 list (REMOVE_DUPLICATES PythonModules_PYTHONPATH) 00300 endif () 00301 00302 # ---------------------------------------------------------------------------- 00303 # handle standard QUIET and REQUIRED arguments 00304 if (NOT PythonModules_FOUND) 00305 # list of modules that were not found 00306 set (_PythonModules_MISSING) 00307 foreach (_PythonModules_MODULE ${PythonModules_FIND_COMPONENTS}) 00308 if (NOT PythonModules_${_PythonModules_MODULE}_FOUND) 00309 list (APPEND _PythonModules_MISSING "${_PythonModules_MODULE}") 00310 endif () 00311 endforeach () 00312 # hint on how to help finding the Python modules 00313 set (_PythonModules_HINT) 00314 if (PYTHON_EXECUTABLE) 00315 set (_PythonModules_HINT "Check if executing ${PYTHON_EXECUTABLE} -c \"import <module>\" works") 00316 else () 00317 set (_PythonModules_HINT "Set PYTHON_EXECUTABLE, e.g., by searching for Python interpreter first") 00318 endif () 00319 if (_PythonModules_HINT) 00320 set (_PythonModules_HINT "${_PythonModules_HINT} or set") 00321 else () 00322 set (_PythonModules_HINT "Set") 00323 endif () 00324 set (_PythonModules_HINT "${_PythonModules_HINT} the PythonModules_DIR variable. Alternatively,") 00325 set (_PythonModules_HINT "${_PythonModules_HINT} set the PythonModules_<module>_PATH variable(s)") 00326 set (_PythonModules_HINT "${_PythonModules_HINT} instead or the PYTHONPATH environment variable.") 00327 set (_PythonModules_HINT "${_PythonModules_HINT} Unset PythonModules_DIR if you chose an alternative") 00328 set (_PythonModules_HINT "${_PythonModules_HINT} option and before rerunning CMake again.") 00329 # error message 00330 string (REPLACE ";" ", " ${_PythonModules_MISSING} "${_PythonModules_MISSING}") 00331 message (FATAL_ERROR "Could NOT find the following Python modules:\n${_PythonModules_MISSING}\n${_PythonModules_HINT}") 00332 endif () 00333 00334 # ---------------------------------------------------------------------------- 00335 # common <Pkg>_DIR variable 00336 if (NOT PythonModules_DIR) 00337 set ( 00338 PythonModules_DIR 00339 "${PythonModules_PYTHONPATH}" 00340 CACHE PATH 00341 "Directory or list of directories separated by ; of installed Python modules." 00342 FORCE 00343 ) 00344 endif () 00345 00346 # ---------------------------------------------------------------------------- 00347 # clean up 00348 unset (_PythonModules_MODULE) 00349 unset (_PythonModules_VAR) 00350 unset (_PythonModules_VARS)