From 79b7686e638ba34d6c67613b04ca9ae3420d09ed Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Wed, 14 Dec 2011 03:53:50 +0000 Subject: [PATCH] More robust installation of the Python package with SCons SCons now checks for an array package (numpy by default) and builds the full Python module if it finds it, otherwise it builds the minimal package. --- Cantera/python/SConscript | 47 ++++++------ Cantera/python/setup.py | 36 --------- Cantera/python/setup.py.in | 148 ++++++------------------------------- SConstruct | 112 +++++++++++++--------------- tools/SConscript | 2 +- 5 files changed, 96 insertions(+), 249 deletions(-) delete mode 100644 Cantera/python/setup.py diff --git a/Cantera/python/SConscript b/Cantera/python/SConscript index cb45d5b9a..2b22625a8 100644 --- a/Cantera/python/SConscript +++ b/Cantera/python/SConscript @@ -5,29 +5,25 @@ Import('env', 'buildTargets', 'installTargets') localenv = env.Clone() -def make_ctconf(target, source, env): - text = """ -buildPython = %(BUILD_PYTHON)s -ctversion = %(cantera_version)r -""" % env - - with open(str(target[0]), 'w') as f: - f.write(text) - gcv = distutils.sysconfig.get_config_var localenv.Append(CPPPATH=[gcv('INCLUDEPY')], SHLINKFLAGS=gcv('LDFLAGS'), CPPFLAGS=[gcv('BASECFLAGS'), gcv('OPT')]) -pymodule = localenv.SharedLibrary('Cantera/_cantera', ['src/pycantera.cpp'], - LIBS=localenv['cantera_libs'], - SHLIBPREFIX='', - SHLIBSUFFIX=gcv('SO')) -buildTargets.extend(pymodule) +make_setup = localenv.SubstFile('setup.py', 'setup.py.in') -localenv.AddPreAction(pymodule, make_ctconf) -localenv.AddPostAction(pymodule, 'cd Cantera/python; $python_cmd setup.py build') +if env['python_package'] == 'full': + pymodule = localenv.SharedLibrary('Cantera/_cantera', ['src/pycantera.cpp'], + LIBS=localenv['cantera_libs'], + SHLIBPREFIX='', + SHLIBSUFFIX=gcv('SO')) + buildTargets.extend(pymodule) + localenv.Depends(pymodule, make_setup) +elif env['python_package'] == 'minimal': + pymodule = make_setup + +localenv.AddPostAction(make_setup, 'cd Cantera/python; $python_cmd setup.py build') # Install the Python module if env['cantera_python_home'] is None: @@ -44,13 +40,14 @@ inst = localenv.Command('dummy', pymodule, 'cd Cantera/python; $python_cmd setup.py install %s' % extra) installTargets.extend(inst) -# Copy tutorials -inst = localenv.Install('$ct_tutdir', mglob(localenv, 'tutorial', 'py')) -installTargets.extend(inst) +if env['python_package'] == 'full': + # Copy tutorials + inst = localenv.Install('$ct_tutdir', mglob(localenv, 'tutorial', 'py')) + installTargets.extend(inst) -# Copy examples -exampleFiles = sum([localenv.Glob(pjoin('examples', '*', '*', name)) - for name in ['runtest', 'cleanup', '*.txt', '*.py', '*.csv']], []) -for f in exampleFiles: - subdir1, subdir2 = psplit(f.path)[3:5] - installTargets.extend(localenv.Install(pjoin('$ct_demodir','python',subdir1,subdir2), f)) + # Copy examples + exampleFiles = sum([localenv.Glob(pjoin('examples', '*', '*', name)) + for name in ['runtest', 'cleanup', '*.txt', '*.py', '*.csv']], []) + for f in exampleFiles: + subdir1, subdir2 = psplit(f.path)[3:5] + installTargets.extend(localenv.Install(pjoin('$ct_demodir','python',subdir1,subdir2), f)) diff --git a/Cantera/python/setup.py b/Cantera/python/setup.py deleted file mode 100644 index ec58c6842..000000000 --- a/Cantera/python/setup.py +++ /dev/null @@ -1,36 +0,0 @@ -import sys -import string -from distutils.core import setup, Extension - -import ctconf - -platform = sys.platform - -# values: -# 0 do nothing -# 1 install only ctml_writer.py -# 2 install full package - -if ctconf.buildPython >= 2: - setup(name="Cantera", - version=ctconf.ctversion, - description="The Cantera Python Interface", - long_description=""" - """, - author="Prof. D. G. Goodwin, Caltech", - author_email="dgoodwin@caltech.edu", - url="http://code.google.com/p/cantera", - package_dir = {'MixMaster':'../../apps/MixMaster'}, - packages = ["","Cantera","Cantera.OneD", - "MixMaster","MixMaster.Units"], - package_data = {'Cantera': ['_cantera.so']}) -elif ctconf.buildPython == 1: - setup(name="Cantera CTI File Processor", - version=ctconf.ctversion, - description="Converts .cti files to CTML", - long_description=""" - """, - author="Prof. D. G. Goodwin, Caltech", - author_email="dgoodwin@caltech.edu", - url="http://www.cantera.org", - py_modules = ["ctml_writer"]) diff --git a/Cantera/python/setup.py.in b/Cantera/python/setup.py.in index 957fa1e62..f6fc6884d 100644 --- a/Cantera/python/setup.py.in +++ b/Cantera/python/setup.py.in @@ -2,139 +2,33 @@ import sys import string from distutils.core import setup, Extension -# -# HKM -# note having a % in a string may cause the distutils module to error exit -# This occurs on solaris, as some CC parameters have % in their names. - -libs = [] platform = sys.platform -flibs = [] -if @build_with_f2c@ <> 1: - flibstr = '@FLIBS@' - f1 = flibstr.replace('-l', ' ') - flibs = f1.split() - -linkargs = '@LCXX_FLAGS@' - -numarray_incl = "@NUMARRAY_INC_DIR@" -numpy_incl = "@NUMPY_INC_DIR@" - -num_collect = [] -if (type(numarray_incl).__name__=='str') : - if numarray_incl <> '': - numarray_list = numarray_incl.split(":") - num_collect = num_collect + numarray_list - -if (type(numpy_incl).__name__=='str') : - if numpy_incl <> '': - numpy_list = numpy_incl.split(":") - num_collect = num_collect + numpy_list - -incdirs=["../../build/include", "src", "../clib/src"] - -if num_collect <> '': - for x in num_collect : - if x <> '' : - incdirs.append(x) - -bllibstr = "@BLAS_LAPACK_LIBS@" -bllibs = bllibstr.replace('-l',' ') -bllist = bllibs.split() - -cvlibstr = "@CVODE_LIBS@" -cvlibs = cvlibstr.replace('-l',' ') -cvlist = cvlibs.split() - -thermolib = [] -need_cathermo = @NEED_CATHERMO@ -if need_cathermo == 1: - thermolib = ["thermo"] - -extra_link = linkargs + " " + "@EXTRA_LINK@" -linkargs = extra_link.split() - -bldirstr = "@LOCAL_LIB_DIRS@" -bldirs = bldirstr.replace('-L',' ') -dirlist = bldirs.split() -libdir = ['@buildlib@'] -for d in dirlist: - libdir.append(d) - -endlibstr1 = "@LCXX_END_LIBS@" -endlib1 = endlibstr1.replace('-l', ' ') -endlib = endlib1.split() - -locallibstr = "@LOCAL_LIBS@" -local1 = locallibstr.replace('-l', ' ') -locallibs = local1.split() - -if platform == "win32": - libs = ["clib", "zeroD","oneD","kinetics", "transport", - "cantera"] + bllist + cvlist + ["ctbase", "ctmath", "tpx"] -else: - libs = ["clib"] + locallibs - #if flibs: - # libs = libs - #libs = ["clib", "zeroD","oneD", "kinetics", "transport", - # "equil", "ctnumerics", "converters"] + thermolib + bllist + cvlist + ["ctbase", "ctmath", "tpx", "boost_thread-mt-1_34"] - - if @build_with_f2c@ == 1: - libs.append("ctf2c") - else: - libs = libs + flibs - - for d in endlib: - libs.append(d) - - # values: # 0 do nothing # 1 install only ctml_writer.py # 2 install full package -buildPython = @BUILD_PYTHON@ -if buildPython >= 2: -# try: - setup(name="Cantera", - version="@ctversion@", - description="The Cantera Python Interface", - long_description=""" +if '@python_package@' == 'full': + setup(name="Cantera", + version="@cantera_version@", + description="The Cantera Python Interface", + long_description=""" """, - author="Prof. D. G. Goodwin, Caltech", - author_email="dgoodwin@caltech.edu", - url="http://code.google.com/p/cantera", - package_dir = {'MixMaster':'../../apps/MixMaster'}, - packages = ["","Cantera","Cantera.OneD", - "MixMaster","MixMaster.Units"], - ext_modules=[ Extension("Cantera._cantera", - ["src/pycantera.cpp"], - include_dirs=incdirs, - library_dirs = libdir, - libraries = libs, - extra_link_args = linkargs - ) - ], - ) -# except: -# if buildPython == 3: -# buildPython = 1 -# else: -# raise 'Error encountered while building or installing the Cantera python modules!' - - -if buildPython == 1: -# try: - setup(name="Cantera CTI File Processor", - version="@ctversion@", - description="Converts .cti files to CTML", - long_description=""" + author="Prof. D. G. Goodwin, Caltech", + author_email="dgoodwin@caltech.edu", + url="http://code.google.com/p/cantera", + package_dir = {'MixMaster':'../../apps/MixMaster'}, + packages = ["","Cantera","Cantera.OneD", + "MixMaster","MixMaster.Units"], + package_data = {'Cantera': ['_cantera.so']}) +elif '@python_package@' == 'minimal': + setup(name="Cantera CTI File Processor", + version="@cantera_version@", + description="Converts .cti files to CTML", + long_description=""" """, - author="Prof. D. G. Goodwin, Caltech", - author_email="dgoodwin@caltech.edu", - url="http://www.cantera.org", - py_modules = ["ctml_writer"], - ) -# except: -# raise 'Error encountered while building or installing the Cantera CTI file preprocessor!' + author="Prof. D. G. Goodwin, Caltech", + author_email="dgoodwin@caltech.edu", + url="http://www.cantera.org", + py_modules = ["ctml_writer"]) diff --git a/SConstruct b/SConstruct index e7827a214..b9c3aa23b 100644 --- a/SConstruct +++ b/SConstruct @@ -11,9 +11,9 @@ subst.TOOL_SUBST(env) # ****************************************************** if os.name == 'posix': - env['default_prefix'] = '/usr/local' + defaultPrefix = '/usr/local' elif os.name == 'nt': - env['default_prefix'] = os.environ['ProgramFiles'] + defaultPrefix = os.environ['ProgramFiles'] # ************************************** # *** Read user-configurable options *** @@ -22,12 +22,24 @@ elif os.name == 'nt': opts = Variables('cantera.conf') opts.AddVariables( PathVariable('prefix', 'Where to install Cantera', - env['default_prefix'], PathVariable.PathIsDirCreate), - EnumVariable('python_package', 'build python package?', 'full', - ('full', 'minimal', 'none')), + defaultPrefix, PathVariable.PathIsDirCreate), + EnumVariable('python_package', 'build python package?', 'default', + ('full', 'minimal', 'none','default')), PathVariable('python_cmd', 'Path to the python interpreter', sys.executable), + EnumVariable('python_array', 'Which Python array package to use', + 'numpy', ('numpy', 'numarray', 'numeric')), + PathVariable('python_array_home', + 'Location for array package (e.g. if installed with --home)', + '', PathVariable.PathAccept), + PathVariable('cantera_python_home', 'where to install the python package', + '', PathVariable.PathAccept), EnumVariable('matlab_toolbox', '', 'n', ('y', 'n', 'default')), + PathVariable('matlab_cmd', 'Path to the matlab executable', + 'matlab', PathVariable.PathAccept), BoolVariable('f90_interface', 'Build Fortran90 interface?', False), + PathVariable('f90', 'Fortran compiler', + 'gfortran', PathVariable.PathAccept), + ('f90flags', '', '-O3'), ('purify', '', ''), ('user_src_dir', '', 'Cantera/user'), BoolVariable('debug', '', False), # ok @@ -56,6 +68,9 @@ opts.AddVariables( BoolVariable('enable_tpx', '', True), BoolVariable('with_html_log_files', '', True), EnumVariable('use_sundials', '', 'default', ('default', 'y', 'n')), + EnumVariable('sundials_version' ,'', '2.4', ('2.2','2.3','2.4')), + PathVariable('sundials_include' ,'', ''), + PathVariable('sundials_libdir', '', ''), ('blas_lapack_libs', '', ''), # 'lapack,blas' or 'lapack,f77blas,cblas,atlas' etc. ('blas_lapack_dir', '', ''), # '/usr/lib/lapack' etc EnumVariable('lapack_names', '', 'lower', ('lower','upper')), @@ -66,6 +81,9 @@ opts.AddVariables( ('CC', '', env['CC']), ('CXXFLAGS', '', '-O3 -Wall'), BoolVariable('build_thread_safe', '', False), + PathVariable('boost_inc_dir', '', '/usr/include/'), + PathVariable('boost_lib_dir', '', '/usr/lib/'), + ('boost_thread_lib', '', 'boost_thread'), BoolVariable('build_with_f2c', '', True), ('F77', '', env['F77']), ('F77FLAGS', '', '-O3'), @@ -90,60 +108,6 @@ opts.AddVariables( # ('ranlib', '', 'ranlib'), ) -opts.Update(env) - -# Additional options that apply only if building the full python package -if env['prefix'] == env['default_prefix']: - pyprefix = None -else: - pyprefix = env['prefix'] - -if env['python_package'] in ('full', 'default'): - opts.AddVariables( - EnumVariable('python_array', 'Which Python array package to use', - 'numpy', ('numpy', 'numarray', 'numeric')), - PathVariable('python_array_home', - 'Location for array package (e.g. if installed with --home)', - '', PathVariable.PathAccept), - PathVariable('cantera_python_home', 'where to install the python package', - pyprefix, PathVariable.PathAccept) - ) - - env['BUILD_PYTHON'] = 3 -elif env['python_package'] == 'minimal': - env['BUILD_PYTHON'] = 1 -else: - env['BUILD_PYTHON'] = 0 - -# Options that apply only if building the Matlab interface -if env['matlab_toolbox'] != 'n': - opts.AddVariables( - PathVariable('matlab_cmd', 'Path to the matlab executable', - 'matlab', PathVariable.PathAccept) - ) - -# Options that apply only if building the Fortran interface -if env['f90_interface']: - opts.AddVariables( - PathVariable('f90', 'Fortran compiler', - 'gfortran', PathVariable.PathAccept), - ('f90flags', '', '-O3') - ) - -# Extra options for Sundials -if env['use_sundials'] != 'n': - opts.AddVariables( - EnumVariable('sundials_version' ,'', '2.4', ('2.2','2.3','2.4')), - PathVariable('sundials_include' ,'', ''), - PathVariable('sundials_libdir', '', '')) - -# Extra options for Boost.Thread -if env['build_thread_safe']: - opts.AddVariables( - PathVariable('boost_inc_dir', '', '/usr/include/'), - PathVariable('boost_lib_dir', '', '/usr/lib/'), - ('boost_thread_lib', '', 'boost_thread')) - opts.Update(env) opts.Save('cantera.conf', env) @@ -167,6 +131,28 @@ env['HAS_SSTREAM'] = conf.CheckCXXHeader('sstream', '<>') env = conf.Finish() +if env['cantera_python_home'] == '' and env['prefix'] != defaultPrefix: + env['cantera_python_home'] = env['prefix'] + +if env['python_package'] in ('full','default'): + # Test to see if we can import the specified array module + warnNoPython = False + if env['python_array_home']: + sys.path.append(env['python_array_home']) + try: + __import__(env['python_array']) + print """INFO: Building the full Python package using %s.""" % env['python_array'] + env['python_package'] = 'full' + except ImportError: + if env['python_package'] == 'full': + print ("""ERROR: Unable to find the array package """ + """'%s' required by the full Python package.""" % env['python_array']) + sys.exit(1) + else: + print ("""WARNING: Not building the full Python package """ + """ because the array package '%s' could not be found.""" % env['python_array']) + warnNoPython = True + env['python_package'] = 'minimal' # ************************************** # *** Set options needed in config.h *** @@ -333,7 +319,7 @@ if env['f90_interface']: VariantDir('build/interfaces/fortran/', 'Cantera/fortran', duplicate=1) SConscript('build/interfaces/fortran/SConscript') -if env['BUILD_PYTHON']: +if env['python_package'] in ('full','minimal'): SConscript('Cantera/python/SConscript') if env['matlab_toolbox'] == 'y': @@ -375,6 +361,12 @@ File locations: if env['python_package'] == 'full': print """ Python package %(python_module_loc)s""" % env + elif warnNoPython: + print """ + ################################################################# + WARNING: the Cantera Python package was not installed because a + suitable array package (e.g. numpy) could not be found. + #################################################################""" if env['matlab_toolbox'] == 'y': print """ diff --git a/tools/SConscript b/tools/SConscript index 27fc4bdce..da40ef106 100644 --- a/tools/SConscript +++ b/tools/SConscript @@ -40,7 +40,7 @@ inst = localenv.Install('$ct_bindir','setup_cantera') installTargets.append(inst) # 'mixmaster' -if env['BUILD_PYTHON'] >= 2: +if env['python_package'] == 'full': target = localenv.SubstFile('mixmaster', 'mixmaster.in') buildTargets.extend(target) inst = localenv.Install('$ct_bindir', 'mixmaster')