mirror of
https://github.com/JesseTG/melonds-ds.git
synced 2024-11-27 00:30:34 +00:00
373 lines
16 KiB
CMake
Vendored
373 lines
16 KiB
CMake
Vendored
##############################################################################
|
|
# @file FindPythonModules.cmake
|
|
# @brief Find Python modules.
|
|
#
|
|
# @par Input/Output variables:
|
|
# <table border="0">
|
|
# <tr>
|
|
# @tp @b PythonModules_DIR @endtp
|
|
# <td>List of directories where Python modules are installed.</td>
|
|
# </tr>
|
|
# </table>
|
|
|
|
# @par Input variables:
|
|
# <table border="0">
|
|
# <tr>
|
|
# @tp @b PythonModules_FIND_COMPONENTS @endtp
|
|
# <td>The @c COMPONENTS argument(s) of the find_package() command specifies
|
|
# the names of the Python modules to look for.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PythonModules_FIND_OPTIONAL_COMPONENTS @endtp
|
|
# <td>The @c OPTIONAL_COMPONENTS argument(s) of the find_package() command
|
|
# specifies the names of the Python modules which are not necessarily
|
|
# required, but should be searched as well.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PYTHON_EXECUTABLE @endtp
|
|
# <td>Path to the Python interpreter. Should be set by first looking
|
|
# for the Python interpreter, i.e., find_packages(PythonInterp).
|
|
# If set, this module first tries to execute the Python interpreter,
|
|
# import the respective Python module, and then derive the search path
|
|
# from the @c __file__ attribute of the loaded Python module.
|
|
# Otherwise, or if this fails, it looks either for a package
|
|
# @c __init__.py file inside a subdirectory named after the specified
|
|
# Python module or a @c .py module file in each directory listed in
|
|
# the @c PYTHONPATH.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PYTHONPATH @endtp
|
|
# <td>Search path for Python modules. If this CMake variable is undefined,
|
|
# the corresponding environment variable is used instead if set.
|
|
# Only absolute paths in the @c PYTHONPATH are considered.</td>
|
|
# </tr>
|
|
# </table>
|
|
#
|
|
# @par Output variables:
|
|
# <table border="0">
|
|
# <tr>
|
|
# @tp @b PythonModules_FOUND @endtp
|
|
# <td>Whether all specified Python modules were found.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PythonModules_<module>_FOUND @endtp
|
|
# <td>Whether the Python module <module%gt; was found.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PythonModules_<module>_PATH @endtp
|
|
# <td>Absolute path of the directory containing the Python module named <module%gt;.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PythonModules_<module> @endtp
|
|
# <td>Import target for module named <module>. The location of the
|
|
# target is @c PythonModules_<module>_PATH.</tr>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PythonModules_PYTHONPATH @endtp
|
|
# <td>The @c PYTHONPATH setting required for the found Python module(s), i.e.,
|
|
# The directories that have to be added to the Python search path.
|
|
# To support the use of this CMake module more than once with different
|
|
# arguments to the find_package() command, e.g., with and without the
|
|
# @c REQUIRED argument, the directories containing the found Python
|
|
# modules are appended to any existing directories in
|
|
# @c PythonModules_PYTHONPATH if not already listed.</td>
|
|
# </tr>
|
|
# </table>
|
|
#
|
|
# @ingroup CMakeFindModules
|
|
##############################################################################
|
|
|
|
#=============================================================================
|
|
# Copyright 2011-2012 University of Pennsylvania
|
|
# Copyright 2013-2016 Andreas Schuh <andreas.schuh.84@gmail.com>
|
|
#
|
|
# Distributed under the OSI-approved BSD License (the "License");
|
|
# see accompanying file Copyright.txt for details.
|
|
#
|
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
# See the License for more information.
|
|
#=============================================================================
|
|
# (To distribute this file outside of CMake, substitute the full
|
|
# License text for the above reference.)
|
|
|
|
include (CMakeParseArguments)
|
|
|
|
# ----------------------------------------------------------------------------
|
|
## @brief Find Python module.
|
|
#
|
|
# If the @c PYTHON_EXECUTABLE variable is set, this function at first tries
|
|
# to launch the Python interpreter, import the named Python module, and then
|
|
# determines the search path for the Python module from the @c __file__
|
|
# attribute of the loaded module. Otherwise, or if this fails, it looks for
|
|
# the Python module in the directories listed in the @c PYTHONPATH variable
|
|
# if defined. If this variable is not defined, the @c PYTHONPATH environment
|
|
# variable is used instead.
|
|
#
|
|
# @param [in] CACHEVAR Name of CMake cache variable which stores path of
|
|
# directory of the Python module. If not set or if
|
|
# the cache entry contains space characters only or
|
|
# ends in the string NOTFOUND, this function looks for
|
|
# the specified Python module. Otherwise, it does nothing
|
|
# and leaves the cache entry unmodified.
|
|
# @param [in] ARGN The remaining arguments are parsed and the following
|
|
# options extract:
|
|
# @par
|
|
# <table border=0>
|
|
# <tr>
|
|
# @tp @b NAME module @endtp
|
|
# <td>Name of the Python module.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PYTHON_EXECUTABLE python @endtp
|
|
# <td>Full path of the Python interpreter executable. If not specified
|
|
# the global PYTHON_EXECUTABLE CMake variable/cache entry is used.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b PATH dir1 [dir2...] @endtp
|
|
# <td>Directories where to look for Python module.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b NO_PYTHONPATH @endtp
|
|
# <td>Do not consider the @c PYTHONPATH environment variable.</td>
|
|
# </tr>
|
|
# <tr>
|
|
# @tp @b NO_DEFAULT_PATH @endtp
|
|
# <td>Do not look in any default path such as the directories listed by the
|
|
# @c PYTHONPATH environment variable.</td>
|
|
# </tr>
|
|
# </table>
|
|
#
|
|
# @returns Sets the named cache variable of type @c PATH to the absolute path
|
|
# of the directory containing the specified Python @p MODULE if found,
|
|
# or the string "<MODULE%gt;-NOTFOUND" otherwise.
|
|
function (basis_find_python_module CACHEVAR)
|
|
# do nothing if path of module already known from previous run
|
|
if (DEFINED ${CACHEVAR} AND NOT ${CACHEVAR} MATCHES "NOTFOUND$")
|
|
return ()
|
|
endif ()
|
|
# parse arguments
|
|
CMAKE_PARSE_ARGUMENTS (
|
|
ARGN
|
|
"NO_DEFAULT_PATH;NO_PYTHONPATH"
|
|
"PYTHON_EXECUTABLE;NAME"
|
|
"PATH"
|
|
${ARGN}
|
|
)
|
|
if (NOT ARGN_NAME)
|
|
message ("basis_find_python_module(): Missing NAME argument!")
|
|
endif ()
|
|
if (ARGN_UNPARSED_ARGUMENTS)
|
|
message ("basis_find_python_module(): Invalid arguments: ${ARGN_UNPARSED_ARGUMENTS}")
|
|
endif ()
|
|
if (NOT ARGN_PYTHON_EXECUTABLE)
|
|
set (ARGN_PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}")
|
|
endif ()
|
|
if (ARGN_NO_DEFAULT_PATH)
|
|
set (ARGN_NO_PYTHONPATH TRUE)
|
|
set (ARGN_PYTHON_EXECUTABLE)
|
|
endif ()
|
|
# set initial value of cache entry
|
|
if (${CACHEVAR} MATCHES "^ *$")
|
|
set (${CACHEVAR} "${ARGN_NAME}-NOTFOUND" CACHE PATH "Directory containing ${ARGN_NAME} Python module/package." FORCE)
|
|
else ()
|
|
set (${CACHEVAR} "${ARGN_NAME}-NOTFOUND" CACHE PATH "Directory containing ${ARGN_NAME} Python module/package.")
|
|
endif ()
|
|
# 1. search specified paths
|
|
foreach (P ${ARGN_PATH}) # ignore empty entries
|
|
if (IS_ABSOLUTE "${P}")
|
|
message(DEBUG "Looking for ${ARGN_NAME} in ${P}")
|
|
if (EXISTS "${P}/${ARGN_NAME}.py" OR EXISTS "${P}/${ARGN_NAME}/__init__.py" OR
|
|
EXISTS "${P}/${ARGN_NAME}.pyc" OR EXISTS "${P}/${ARGN_NAME}/__init__.pyc")
|
|
set_property (CACHE ${CACHEVAR} PROPERTY VALUE "${P}")
|
|
return ()
|
|
endif ()
|
|
endif ()
|
|
endforeach ()
|
|
# 2. get __file__ attribute of module loaded in Python
|
|
if (ARGN_PYTHON_EXECUTABLE)
|
|
set (IMPORT_SITE_ERROR FALSE)
|
|
# 2a. try it with -E option -- the preferred way to run Python
|
|
message(DEBUG "Trying to import ${ARGN_NAME} using Python interpreter ${ARGN_PYTHON_EXECUTABLE}")
|
|
execute_process (
|
|
COMMAND "${ARGN_PYTHON_EXECUTABLE}" -E -c "import ${ARGN_NAME}; print(${ARGN_NAME}.__file__)"
|
|
RESULT_VARIABLE STATUS
|
|
OUTPUT_VARIABLE P
|
|
ERROR_VARIABLE ERROR
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if (ERROR MATCHES "'import site' failed|ImportError: No module named site")
|
|
set (IMPORT_SITE_ERROR TRUE)
|
|
endif ()
|
|
# 2b. try it without -E option
|
|
if (NOT STATUS EQUAL 0)
|
|
execute_process (
|
|
COMMAND "${ARGN_PYTHON_EXECUTABLE}" -c "import ${ARGN_NAME}; print(${ARGN_NAME}.__file__)"
|
|
RESULT_VARIABLE STATUS
|
|
OUTPUT_VARIABLE P
|
|
ERROR_VARIABLE ERROR
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if (ERROR MATCHES "'import site' failed|ImportError: No module named site")
|
|
set (IMPORT_SITE_ERROR TRUE)
|
|
endif ()
|
|
if (NOT STATUS EQUAL 0 AND ERROR MATCHES "ImportError: No module named site")
|
|
set (PYTHONHOME "$ENV{PYTHONHOME}")
|
|
unset (ENV{PYTHONHOME})
|
|
execute_process (
|
|
COMMAND "${ARGN_PYTHON_EXECUTABLE}" -c "import ${ARGN_NAME}; print(${ARGN_NAME}.__file__)"
|
|
RESULT_VARIABLE STATUS
|
|
OUTPUT_VARIABLE P
|
|
ERROR_VARIABLE ERROR
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if (ERROR MATCHES "'import site' failed|ImportError: No module named site")
|
|
set (IMPORT_SITE_ERROR TRUE)
|
|
endif ()
|
|
set (ENV{PYTHONHOME} "${PYTHONHOME}")
|
|
endif ()
|
|
endif ()
|
|
if (STATUS EQUAL 0)
|
|
if (P MATCHES "__init__\\.pyc?$")
|
|
get_filename_component (P "${P}" PATH)
|
|
get_filename_component (P "${P}" PATH)
|
|
else ()
|
|
get_filename_component (P "${P}" PATH)
|
|
endif ()
|
|
set_property (CACHE ${CACHEVAR} PROPERTY VALUE "${P}")
|
|
return ()
|
|
else()
|
|
if (NOT STATUS EQUAL 0)
|
|
message(WARNING "${ERROR}")
|
|
endif ()
|
|
|
|
if (IMPORT_SITE_ERROR)
|
|
message (WARNING "Import of site module failed when running Python interpreter ${ARGN_PYTHON_EXECUTABLE}"
|
|
" with and without -E option. Make sure that the Python interpreter is installed properly"
|
|
" and that the PYTHONHOME environment variable is either not set (recommended) or at"
|
|
" least set correctly for this Python installation. Maybe you need to enable this Python"
|
|
" version first somehow if more than one version of Python is installed on your system?"
|
|
" Otherwise, set PYTHON_EXECUTABLE to the right Python interpreter executable (python).")
|
|
endif()
|
|
endif ()
|
|
endif ()
|
|
# 3. search PYTHONPATH
|
|
if (NOT ARGN_NO_PYTHONPATH)
|
|
string (REPLACE ":" ";" PYTHONPATH "$ENV{PYTHONPATH}")
|
|
foreach (P ${PYTHONPATH}) # ignore empty entries
|
|
message(DEBUG "Looking for ${ARGN_NAME} in ${P}")
|
|
if (IS_ABSOLUTE "${P}")
|
|
if (EXISTS "${P}/${ARGN_NAME}.py" OR EXISTS "${P}/${ARGN_NAME}/__init__.py" OR
|
|
EXISTS "${P}/${ARGN_NAME}.pyc" OR EXISTS "${P}/${ARGN_NAME}/__init__.pyc")
|
|
set_property (CACHE ${CACHEVAR} PROPERTY VALUE "${P}")
|
|
return ()
|
|
endif ()
|
|
endif ()
|
|
endforeach ()
|
|
endif ()
|
|
endfunction ()
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# find Python modules
|
|
if (NOT PythonModules_FIND_COMPONENTS AND NOT PythonModules_FIND_OPTIONAL_COMPONENTS)
|
|
message (FATAL_ERROR "PythonModules: No (OPTIONAL_)COMPONENTS (i.e., Python module names) specified!")
|
|
endif ()
|
|
if (NOT DEFINED PythonModules_PYTHONPATH)
|
|
set (PythonModules_PYTHONPATH) # PYTHONPATH of all found modules
|
|
endif ()
|
|
# helper macro
|
|
macro (_PythonModules_find_python_modules ALL_FOUND)
|
|
set (${ALL_FOUND} TRUE)
|
|
foreach (_PythonModules_MODULE ${ARGN})
|
|
set (_PythonModules_VAR "PythonModules_${_PythonModules_MODULE}_PATH")
|
|
set (_PythonModules_TGT "PythonModules_${_PythonModules_MODULE}")
|
|
if (PythonModules_DIR)
|
|
basis_find_python_module (
|
|
${_PythonModules_VAR}
|
|
NAME "${_PythonModules_MODULE}"
|
|
PATH "${PythonModules_DIR}"
|
|
NO_DEFAULT_PATH
|
|
)
|
|
else ()
|
|
basis_find_python_module (
|
|
${_PythonModules_VAR}
|
|
NAME "${_PythonModules_MODULE}"
|
|
PATH "${PythonModules_DIR}"
|
|
)
|
|
endif ()
|
|
mark_as_advanced (${_PythonModules_VAR})
|
|
if (${_PythonModules_VAR} MATCHES "(^ *|NOTFOUND)$")
|
|
set (${ALL_FOUND} FALSE)
|
|
set (PythonModules_${_PythonModules_MODULE}_FOUND FALSE)
|
|
else ()
|
|
if (NOT TARGET ${_PythonModules_TGT})
|
|
add_library (${_PythonModules_TGT} UNKNOWN IMPORTED)
|
|
set_target_properties (
|
|
${_PythonModules_TGT}
|
|
PROPERTIES
|
|
BASIS_TYPE "SCRIPT_LIBRARY"
|
|
IMPORTED_LOCATION "${${_PythonModules_VAR}}"
|
|
)
|
|
endif ()
|
|
set (PythonModules_${_PythonModules_MODULE}_FOUND TRUE)
|
|
list (APPEND PythonModules_PYTHONPATH "${${_PythonModules_VAR}}")
|
|
endif ()
|
|
endforeach ()
|
|
endmacro ()
|
|
# optional first, as PythonModules_FOUND shall be reset to TRUE afterwards
|
|
_PythonModules_find_python_modules (PythonModules_FOUND ${PythonModules_FIND_OPTIONAL_COMPONENTS})
|
|
_PythonModules_find_python_modules (PythonModules_FOUND ${PythonModules_FIND_COMPONENTS})
|
|
# remove duplicate paths in PYTHONPATH
|
|
if (PythonModules_PYTHONPATH)
|
|
list (REMOVE_DUPLICATES PythonModules_PYTHONPATH)
|
|
endif ()
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# handle standard QUIET and REQUIRED arguments
|
|
if (NOT PythonModules_FOUND)
|
|
# list of modules that were not found
|
|
set (_PythonModules_MISSING)
|
|
foreach (_PythonModules_MODULE ${PythonModules_FIND_COMPONENTS})
|
|
if (NOT PythonModules_${_PythonModules_MODULE}_FOUND)
|
|
list (APPEND _PythonModules_MISSING "${_PythonModules_MODULE}")
|
|
endif ()
|
|
endforeach ()
|
|
# hint on how to help finding the Python modules
|
|
set (_PythonModules_HINT)
|
|
if (PYTHON_EXECUTABLE)
|
|
set (_PythonModules_HINT "Check if executing ${PYTHON_EXECUTABLE} -c \"import <module>\" works")
|
|
else ()
|
|
set (_PythonModules_HINT "Set PYTHON_EXECUTABLE, e.g., by searching for Python interpreter first")
|
|
endif ()
|
|
if (_PythonModules_HINT)
|
|
set (_PythonModules_HINT "${_PythonModules_HINT} or set")
|
|
else ()
|
|
set (_PythonModules_HINT "Set")
|
|
endif ()
|
|
set (_PythonModules_HINT "${_PythonModules_HINT} the PythonModules_DIR variable. Alternatively,")
|
|
set (_PythonModules_HINT "${_PythonModules_HINT} set the PythonModules_<module>_PATH variable(s)")
|
|
set (_PythonModules_HINT "${_PythonModules_HINT} instead or the PYTHONPATH environment variable.")
|
|
set (_PythonModules_HINT "${_PythonModules_HINT} Unset PythonModules_DIR if you chose an alternative")
|
|
set (_PythonModules_HINT "${_PythonModules_HINT} option and before rerunning CMake again.")
|
|
# error message
|
|
string (REPLACE ";" ", " ${_PythonModules_MISSING} "${_PythonModules_MISSING}")
|
|
message (FATAL_ERROR "Could NOT find the following Python modules:\n${_PythonModules_MISSING}\n${_PythonModules_HINT}")
|
|
endif ()
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# common <Pkg>_DIR variable
|
|
if (NOT PythonModules_DIR)
|
|
set (
|
|
PythonModules_DIR
|
|
"${PythonModules_PYTHONPATH}"
|
|
CACHE PATH
|
|
"Directory or list of directories separated by ; of installed Python modules."
|
|
FORCE
|
|
)
|
|
endif ()
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# clean up
|
|
unset (_PythonModules_MODULE)
|
|
unset (_PythonModules_VAR)
|
|
unset (_PythonModules_VARS) |