cantera/interfaces/cython/SConscript
Ray Speth 964f88fb0e [Python] Fix to conversion of samples from Python 3 to Python 2
Some calls to the print function weren't being converted to print statements
correctly by 3to2, so now we use the alternative fix, which is to use the
backported print function.

Fixes Issue 216.

Cherry-pick of trunk r2952.
2014-06-20 19:41:37 +00:00

226 lines
9.4 KiB
Python

""" Cython-based Python Module for Python 3 """
from buildutils import *
Import('env', 'build', 'install')
localenv = env.Clone()
def configure_numpy(env, python_command):
script = '\n'.join(("from distutils.sysconfig import *",
"import numpy",
"print(get_config_var('SO'))",
"print(get_python_version())",
"print(numpy.get_include())"))
info = getCommandOutput(python_command, '-c', script)
module_ext, py_version, numpy_include = info.splitlines()[-3:]
incDirs = (".", "../../include", numpy_include,
localenv['sundials_include'], localenv['boost_inc_dir'])
env['py_include_dirs'] = repr([x for x in incDirs if x])
return module_ext, py_version
def add_dependencies(mod, ext):
localenv.Depends(mod, ext)
localenv.Depends(ext, localenv['cantera_staticlib'])
localenv.Depends(mod, dataFiles + testFiles + scripts)
for f in mglob(localenv, 'cantera', 'pyx', 'pxd'):
localenv.Depends(ext, f)
for f in (mglob(localenv, 'cantera', 'py') +
mglob(localenv, 'cantera/test', 'py') +
mglob(localenv, 'cantera/mixmaster', 'py') +
mglob(localenv, 'cantera/mixmaster/Units', 'py') +
mglob(localenv, 'cantera/examples/tutorial', 'py') +
mglob(localenv, 'cantera/examples/equilibrium', 'py') +
mglob(localenv, 'cantera/examples/kinetics', 'py') +
mglob(localenv, 'cantera/examples/transport', 'py') +
mglob(localenv, 'cantera/examples/reactors', 'py') +
mglob(localenv, 'cantera/examples/onedim', 'py') +
mglob(localenv, 'cantera/examples/surface_chemistry', 'py') +
mglob(localenv, 'cantera/examples/misc', 'py')):
localenv.Depends(mod, f)
script_ext = '.py' if os.name == 'nt' else ''
localenv['py_ctml_writer'] = repr('scripts/ctml_writer%s' % script_ext)
localenv['py_ck2cti'] = repr('scripts/ck2cti%s' % script_ext)
localenv['py_mixmaster'] = repr('scripts/mixmaster%s' % script_ext)
# The actual ctml_writer and ck2cti scripts
build(env.Command('cantera/ctml_writer.py',
'#interfaces/python/ctml_writer.py',
Copy('$TARGET', '$SOURCE')))
build(env.Command('cantera/ck2cti.py',
'#interfaces/python/ck2cti.py',
Copy('$TARGET', '$SOURCE')))
# thin wrappers
scripts = []
for script in mglob(env, 'scripts', 'py.in'):
base_name = script.name.split('.')[0]
script = build(env.Command('scripts/%s%s' % (base_name, script_ext), script,
Copy('$TARGET', '$SOURCE')))
scripts.append(script)
def install_module(prefix, python_version):
if prefix == 'USER':
# Install to the OS-dependent user site-packages directory
extra = '--user'
elif prefix:
# A specific location for the Cantera python module has been specified
extra = '--prefix="%s"' % prefix
else:
# Install Python module in the default location
extra = ''
major = python_version[0]
ver = '3' if major == '3' else ''
dummy = 'dummy' + major
if localenv['PYTHON_INSTALLER'] == 'direct':
mod_inst = install(localenv.Command, dummy, mod,
build_cmd + ' install %s' % extra +
' --record ../../build/python%s-installed-files.txt' % major)
global_env = env
def find_module_dir(target, source, env):
check = pjoin('cantera','__init__.py')
for filename in open('build/python%s-installed-files.txt' % major).readlines():
filename = filename.strip()
if filename.endswith(check):
filename = filename.replace(check,'')
global_env['python%s_module_loc' % ver] = os.path.normpath(filename)
break
localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir))
if not ver:
env['install_python2_action'] = mod_inst
elif localenv['PYTHON_INSTALLER'] == 'debian':
install(localenv.Command, dummy, mod,
build_cmd + ' install --install-layout=deb --no-compile %s' % extra)
env['python%s_module_loc' % ver] = '<unspecified>'
elif localenv['PYTHON_INSTALLER'] == 'binary':
install(localenv.Command, dummy, mod,
build_cmd + ' bdist_msi --dist-dir=../..' +
' --target-version=%s' % python_version)
env['python%s_module_loc' % ver] = '<unspecified>'
libDirs = ('../../build/lib', localenv['sundials_libdir'],
localenv['blas_lapack_dir'], localenv['boost_lib_dir'])
localenv['py_cantera_libs'] = repr(localenv['cantera_libs'])
localenv['py_libdirs'] = repr([x for x in libDirs if x])
# Compile the Python module with the same compiler as the rest of Cantera,
# unless otherwise specified
localenv['py_extra_compiler_args'] = repr([])
localenv['py_extra_link_args'] = repr([])
compilerOpt = ''
if localenv['OS'] == 'Windows':
if env['CC'] == 'cl':
flags = ['/EHsc']
if env['debug']:
flags.extend(['/Zi', '/Fd_cantera.pdb'])
localenv['py_extra_link_args'] = repr(['/DEBUG'])
compilerOpt = ' --compiler=msvc'
localenv['py_extra_compiler_args'] = repr(flags)
elif 'gcc' in env['CC']:
compilerOpt = ' --compiler=mingw32'
else:
if '-fprofile-arcs' in localenv['CCFLAGS']:
localenv['py_extra_compiler_args'] = repr(['-fprofile-arcs', '-ftest-coverage'])
localenv['py_extra_link_args'] = repr(['-fprofile-arcs', '-ftest-coverage'])
if env['python_compiler']:
localenv['ENV']['CC'] = env['python_compiler']
localenv['ENV']['CXX'] = env['python_compiler']
if 'LDFLAGS' not in localenv['ENV']:
localenv['ENV']['LDFLAGS'] = ''
for framework in localenv['FRAMEWORKS']:
localenv['ENV']['LDFLAGS'] += ' -framework ' + framework
dataFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/data',
'#build/data')
build(dataFiles)
testFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/test/data',
'#test/data')
build(testFiles)
# Cython module for Python 3.x
if localenv['python3_package'] == 'y':
py3env = localenv.Clone()
module_ext, py3_version = configure_numpy(py3env, py3env['python3_cmd'])
make_setup = py3env.SubstFile('#interfaces/cython/setup3.py',
'#interfaces/cython/setup.py.in')
build(make_setup)
build_base = ('cd interfaces/cython &&'
' $python3_cmd setup3.py %s'
' --build-lib=../../build/python3'
' --build-temp=../../build/temp-py3'
+ compilerOpt)
build_cmd = build_base % 'build'
ext = build(py3env.Command('#build/python3/cantera/_cantera%s' % module_ext,
'setup3.py',
build_base % 'build_ext'))
mod = build(py3env.Command('#build/python3/cantera/__init__.py',
'setup3.py',
build_cmd))
env['python3_module'] = mod
env['python3_extension'] = ext
py3env.AddPreAction(ext, Delete('interfaces/cython/cantera/_cantera.cpp'))
add_dependencies(mod, ext)
install_module(py3env['python3_prefix'], py3_version)
# Cython module for Python 2.x
if localenv['python_package'] == 'new':
py2env = localenv.Clone()
module_ext, py2_version = configure_numpy(py2env, py2env['python_cmd'])
make_setup = py2env.SubstFile('#interfaces/cython/setup2.py',
'#interfaces/cython/setup.py.in')
build(make_setup)
build_base = ('cd interfaces/cython &&'
' $python_cmd setup2.py %s'
' --build-lib=../../build/python2'
' --build-temp=../../build/temp-py2'
+ compilerOpt)
build_cmd = build_base % 'build'
ext = build(py2env.Command('#build/python2/cantera/_cantera%s' % module_ext,
'setup2.py',
build_base % 'build_ext'))
mod = build(py2env.Command('#build/python2/cantera/__init__.py',
'setup2.py',
build_cmd))
env['python2_module'] = mod
env['python2_extension'] = ext
py2env.AddPreAction(ext, Delete('interfaces/cython/cantera/_cantera.cpp'))
# Use 3to2 to convert examples from Python 3 syntax
if env['python_convert_examples']:
def convert_example(target, source, env):
shutil.copyfile(source[0].abspath, target[0].abspath)
subprocess.call(['3to2', '--no-diff', '-n', '-w','-x', 'str',
'-f', 'all', '-f', 'printfunction', '-x', 'print',
'-x', 'open', target[0].abspath])
for subdir in subdirs('cantera/examples'):
dirpath = pjoin('cantera', 'examples', subdir)
for filename in os.listdir(dirpath):
if not filename.endswith('.py'):
continue
targetdir = '../../build/python2/cantera/examples'
a = build(py2env.Command(pjoin(targetdir, subdir, filename),
pjoin(dirpath, filename),
convert_example))
py2env.Depends(a, mod)
add_dependencies(mod, ext)
install_module(py2env['python_prefix'], py2_version)