OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-cogutil / cmake / OpenCogFindPython.cmake

137 lines · cmake ref:
# ----------------------------------------------------------
# Python and Cython
#
# NOTE: Python interpreter is needed for running python unit tests,
# and for running the FindCython module.
#
# Search for Python3
FIND_PACKAGE(Python3 COMPONENTS Interpreter Development)
IF (Python3_Interpreter_FOUND)
	SET (HAVE_PY_INTERP 1)
	MESSAGE(STATUS "Python ${Python3_VERSION} interpreter found.")
ENDIF()

IF (Python3_Development_FOUND)
	SET (HAVE_PY_LIBS 1)
ELSE()
	MESSAGE(STATUS "Python libraries NOT found.")
ENDIF()

# Cython is used to generate python bindings.
IF(HAVE_PY_INTERP)
	# Version 0.24 or later needed for @property markup for python2
	FIND_PACKAGE(Cython 0.24.0)

	IF (CYTHON_FOUND AND HAVE_PY_LIBS)
		ADD_DEFINITIONS(-DHAVE_CYTHON)
		SET(HAVE_CYTHON 1)

		# The CMake interfaces are completely different between
		# Cmake 3 and CMake 4. Try to be backwards compat, if possible.
		IF (NOT DEFINED PYTHON_INSTALL_PREFIX)
			IF (DEFINED Python3_SITEARCH)
				SET(PYTHON_INSTALL_PREFIX ${Python3_SITEARCH})
			ENDIF()
		ENDIF()

		IF (NOT DEFINED PYTHON_INSTALL_PREFIX)
			FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/scripts)
			# Unpack Python install destination detection script into project
			# binary dir.
			#
			# This is a hack due to the distutils in debian/ubuntu's
			# python3 being misconfigured.
			# See discussion https://github.com/opencog/atomspace/issues/1782
			#
			# If the bug is fixed, most of this script could be replaced by:
			#
			# from distutils.sysconfig import get_python_lib;
			# print(get_python_lib(plat_specific=True, prefix=prefix))
			#
			# However, using this would not respect python virtual
			# environments, so the below is still better!
			FILE(WRITE ${PROJECT_BINARY_DIR}/scripts/get_python_lib.py
				"import sys\n"
				"import sysconfig\n"
				"import site\n"
				"\n"
				"if __name__ == '__main__':\n"
				"    prefix = sys.argv[1]\n"
				"\n"
				"    # Use sites if the prefix is recognized and the sites module is available\n"
				"    # (virtualenv is missing getsitepackages())\n"
				"    if hasattr(site, 'getsitepackages'):\n"
				"        paths = [p for p in site.getsitepackages() if p.startswith(prefix)]\n"
				"        if len(paths) == 1:\n"
				"            print(paths[0])\n"
				"            exit(0)\n"
				"    \n"
				"    # Use sysconfig platlib as the fall back\n"
				"    print(sysconfig.get_paths()['platlib'])\n"
				)

			# Find python destination dir for python bindings
			# because it may differ on each operating system.
			EXECUTE_PROCESS(
				COMMAND ${Python3_EXECUTABLE}
				"${PROJECT_BINARY_DIR}/scripts/get_python_lib.py"
				"${CMAKE_INSTALL_PREFIX}"
				OUTPUT_VARIABLE PYTHON_DEST
				)

			# Replace new line at end
			STRING(REPLACE "\n" "" PYTHON_DEST "${PYTHON_DEST}")
			IF ("${PYTHON_DEST}" STREQUAL "")
				MESSAGE(FATAL_ERROR "Python destination dir not found")
			ELSE ("${PYTHON_DEST}" STREQUAL "")
				MESSAGE(STATUS "Python destination dir found: ${PYTHON_DEST}" )
			ENDIF ("${PYTHON_DEST}" STREQUAL "")

			# thunk
			SET(PYTHON_ROOT "${PYTHON_DEST}")
			SET(PYTHON_DEST "${PYTHON_DEST}/opencog")
		ELSE()
			SET(PYTHON_ROOT "${PYTHON_INSTALL_PREFIX}")
			SET(PYTHON_DEST "${PYTHON_INSTALL_PREFIX}/opencog")
		ENDIF()

		MESSAGE(STATUS
			"Python install dir: ${PYTHON_DEST}" )

	ELSE (CYTHON_FOUND AND HAVE_PY_LIBS)
		IF(NOT CYTHON_FOUND)
			MESSAGE(STATUS "Cython executable not found.")
		ENDIF(NOT CYTHON_FOUND)
	ENDIF (CYTHON_FOUND AND HAVE_PY_LIBS)

	# Nosetests will find and automatically run python tests.
	IF (Python3_Interpreter_FOUND)
		FIND_PROGRAM(NOSETESTS_EXECUTABLE nosetests3)
	ENDIF ()
	IF (NOT NOSETESTS_EXECUTABLE)
		FIND_PROGRAM(NOSETESTS_EXECUTABLE nose2-3)
	ENDIF ()
	IF (NOT NOSETESTS_EXECUTABLE)
		MESSAGE(STATUS "nosetests not found")
	ENDIF ()
	IF (NOSETESTS_EXECUTABLE AND CYTHON_FOUND AND HAVE_PY_LIBS)
		SET(HAVE_NOSETESTS 1)
		MESSAGE(STATUS "Using nosetests executable " ${NOSETESTS_EXECUTABLE})
	ENDIF (NOSETESTS_EXECUTABLE AND CYTHON_FOUND AND HAVE_PY_LIBS)

	# Pytest will find and automatically run python tests.
	IF (Python3_Interpreter_FOUND)
		FIND_PROGRAM(PYTEST_EXECUTABLE pytest-3)
	ENDIF ()
	IF (NOT PYTEST_EXECUTABLE)
		FIND_PROGRAM(PYTEST_EXECUTABLE pytest)
	ENDIF ()
	IF (NOT PYTEST_EXECUTABLE)
		MESSAGE(STATUS "pytest not found")
	ENDIF ()
	IF (PYTEST_EXECUTABLE AND CYTHON_FOUND AND HAVE_PY_LIBS)
		SET(HAVE_PYTEST 1)
		MESSAGE(STATUS "Using pytest executable " ${PYTEST_EXECUTABLE})
	ENDIF (PYTEST_EXECUTABLE AND CYTHON_FOUND AND HAVE_PY_LIBS)
ENDIF(HAVE_PY_INTERP)