Files
ResInsight/ThirdParty/Ert/python/cmake/Modules/init_python.cmake
2018-04-09 08:48:36 +02:00

197 lines
5.9 KiB
CMake

# This macro will initialize the current cmake session for Python. The
# macro starts by looking for the Python interpreter of correct
# version. When a Python interepreter of the correct version has been
# located the macro will continue to set variables, load other cmake
# modules and generate scripts to be used in the remaining part of the
# cmake process.
#
# Variables which will be set:
# ----------------------------
#
# PYTHON_INSTALL_PREFIX: All python packages will be located in
# ${GLOBAL_PREFIX}/${PYTHON_INSTALL_PREFIX} - this applies both
# when searching for dependencies and when installing.
#
# CTEST_PYTHONPATH: Normal ':' separated path variables which is
# passed to the test runner. Should contain the PYTHONPATH to
# all third party packages which are not in the default search
# path. The CTEST_PYTHONPATH variable will be updated by the
# python_package( ) function when searching for third party
# packages.
#
#
# New functions/macros which will be available:
# ---------------------------------------------
#
# add_python_package( ): This function will copy python source files
# to the build directory, 'compile' them and set up installation.
#
#
# add_python_test( ): Set up a test based on invoking a Python test
# class with a small python executable front end.
#
# find_python_package( ): Will search for a python package.
#
#
# New scripts generated:
# ----------------------
#
#
# cmake_pyc: Small script which will run in-place Python compilation
# of a directory tree recursively.
#
# cmake_pyc_file: Small script which will compile one python file.
#
# ctest_run_python: Small script which will invoke one Python test class.
#
# All the generated scripts will be located in ${PROJECT_BINARY_DIR}/bin.
#
#
# Downstream projects should use this as:
#
# include( init_python )
# init_python( 2.7 )
# ...
macro(init_python target_version)
FIND_PACKAGE(PythonInterp)
if (NOT DEFINED PYTHON_EXECUTABLE)
message(WARNING "Python interpreter not found - Python wrappers not enabled")
set( BUILD_PYTHON OFF PARENT_SCOPE )
return()
endif()
if (PYTHON_VERSION_MAJOR EQUAL 3)
message(WARNING "libecl is not PYTHON 3 compatible. Python wrappers are enabled, but will fail horribly.")
elseif (NOT "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" STREQUAL "${target_version}")
message(WARNING "Need Python version ${target_version}, found version: ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} - Python wrappers not enabled")
set( BUILD_PYTHON OFF PARENT_SCOPE )
return()
endif()
if (EXISTS "/etc/debian_version")
set( PYTHON_PACKAGE_PATH "dist-packages")
else()
set( PYTHON_PACKAGE_PATH "site-packages")
endif()
set(PYTHON_INSTALL_PREFIX "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/${PYTHON_PACKAGE_PATH}" CACHE STRING "Subdirectory to install Python modules in")
set(CTEST_PYTHONPATH ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX})
configure_python_env( )
include(add_python_test)
include(find_python_package)
include(add_python_package)
endmacro()
# The function configure_python_env( ) will generate three small
# Python scripts which will be located in ${PROJECT_BINARY_DIR}/bin
# and will be used when 'compiling' and testing Python code. The
# function will be called from the init_python() macro.
function( configure_python_env )
FILE(WRITE "${PROJECT_BINARY_DIR}/bin/ctest_run_python"
"import sys
import os
from unittest import TextTestRunner
def runTestCase(tests, verbosity=0):
test_result = TextTestRunner(verbosity=verbosity).run(tests)
if len(test_result.errors) or len(test_result.failures):
test_result.printErrors()
sys.exit(1)
# This will update both the internal sys.path load order and the
# environment variable PYTHONPATH with the following list:
#
# cwd:CTEST_PYTHONPATH:PYTHONPATH
def update_path():
path_list = [os.getcwd()]
if 'CTEST_PYTHONPATH' in os.environ:
ctest_pythonpath = os.environ['CTEST_PYTHONPATH']
for path in ctest_pythonpath.split(':'):
path_list.append( path )
for path in reversed(path_list):
sys.path.insert(0 , path)
if 'PYTHONPATH' in os.environ:
pythonpath = os.environ['PYTHONPATH']
for path in pythonpath.split(':'):
path_list.append( path )
os.environ['PYTHONPATH'] = ':'.join( path_list )
if __name__ == '__main__':
update_path( )
from ecl.util.test import ErtTestRunner
for test_class in sys.argv[1:]:
tests = ErtTestRunner.getTestsFromTestClass(test_class)
# Set verbosity to 2 to see which test method in a class that fails.
runTestCase(tests, verbosity=0)
")
#-----------------------------------------------------------------
FILE(WRITE "${PROJECT_BINARY_DIR}/bin/cmake_pyc"
"
import py_compile
import os
import os.path
import sys
import shutil
src_file = sys.argv[1]
target_file = sys.argv[2]
(target_path , tail) = os.path.split( target_file )
if not os.path.exists( target_path ):
try:
os.makedirs( target_path )
except:
# When running make with multiple processes there might be a
# race to create this directory.
pass
shutil.copyfile( src_file , target_file )
shutil.copystat( src_file , target_file )
try:
py_compile.compile( target_file , doraise = True)
except Exception as error:
sys.exit('py_compile(%s) failed:%s' % (target_file , error))
")
#-----------------------------------------------------------------
FILE(WRITE "${PROJECT_BINARY_DIR}/bin/cmake_pyc_file"
"
import py_compile
import os
import sys
import os.path
# Small 'python compiler' used in the build system for ert.
for file in sys.argv[1:]:
try:
py_compile.compile( file , doraise = True )
except Exception as error:
sys.exit('py_compile(%s) failed:%s' % (file , error))
")
endfunction()