cantera/SConstruct
Ray Speth 79b7686e63 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.
2011-12-14 03:53:50 +00:00

395 lines
15 KiB
Python

from buildutils import *
import subst
import platform, sys, os
env = Environment(tools = ['default', 'textfile'])
env.AddMethod(RecursiveInstall)
subst.TOOL_SUBST(env)
# ******************************************************
# *** Set system-dependent defaults for some options ***
# ******************************************************
if os.name == 'posix':
defaultPrefix = '/usr/local'
elif os.name == 'nt':
defaultPrefix = os.environ['ProgramFiles']
# **************************************
# *** Read user-configurable options ***
# **************************************
opts = Variables('cantera.conf')
opts.AddVariables(
PathVariable('prefix', 'Where to install Cantera',
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
BoolVariable('with_lattice_solid', '', True), # ok
BoolVariable('with_metal', '', True), # ok
BoolVariable('with_stoich_substance', '', True), # ok
BoolVariable('with_semiconductor', '', True), # ??
BoolVariable('with_adsorbate', '', True),
BoolVariable('with_spectra', '', True),
BoolVariable('with_pure_fluids', '', True),
BoolVariable('with_ideal_solutions', '', True), # ok
BoolVariable('with_electrolytes', '', True), # ok
BoolVariable('with_prime', '', False), # ok
BoolVariable('with_h298modify_capability', '', False), # ok
BoolVariable('enable_ck', '', True),
BoolVariable('with_kinetics', '', True),
BoolVariable('with_hetero_kinetics', '', True),
BoolVariable('with_reaction_paths', '', True),
BoolVariable('with_vcsnonideal', '', False),
BoolVariable('enable_transport', '', True),
BoolVariable('enable_equil', '', True),
BoolVariable('enable_reactors', '', True),
BoolVariable('enable_flow1d', '', True),
BoolVariable('enable_solvers', '', True),
BoolVariable('enable_rxnpath', '', True),
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')),
BoolVariable('lapack_ftn_trailing_underscore', '', True),
BoolVariable('lapack_ftn_string_len_at_end', '', True),
('bitcompile', '', ''), # '32' or '64'
('CXX', '', env['CXX']),
('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'),
('F90', '', env['F90']),
('F90FLAGS', '', '-O3'),
('install_bin', '', 'config/install-sh'),
('graphvisdir', '' ,''),
('ct_shared_lib', '', 'clib'),
('rpfont', '', 'Helvetica'),
('cantera_version', '', '1.8.x')
# These variables shouldn't be necessary any more...
# ('cxx_ext', '', 'cpp'),
# ('f77_ext', '', 'f'),
# ('f90_ext', '', 'f90'),
# ('exe_ext', '', ''),
# ('lcxx_end_libs', '-lm'),
# ('pic', '', '-fPIC'),
# ('shared', '', '-dynamic'),
# ('lfort_flags', '', '-L/usr/local/lib'),
# ('AR', '', env['AR']),
# ('ARFLAGS', '', env['ARFLAGS']), # ('archive', '', 'ar ruv'),
# ('ranlib', '', 'ranlib'),
)
opts.Update(env)
opts.Save('cantera.conf', env)
# ********************************************
# *** Configure system-specific properties ***
# ********************************************
env['OS'] = platform.system()
if env['F90'] == 'gfortran':
env['FORTRANMODDIRPREFIX'] = '-J'
elif env['F90'] == 'g95':
env['FORTRANMODDIRPREFIX'] = '-fmod='
elif env['F90'] == 'ifort':
env['FORTRANMODDIRPREFIX'] = '-module '
env['FORTRANMODDIR'] = '${TARGET.dir}'
conf = Configure(env)
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 ***
# **************************************
configh = {'CANTERA_VERSION': quoted(env['cantera_version']),
}
# Conditional defines
def cdefine(definevar, configvar, comp=True, value=1):
if env.get(configvar) == comp:
configh[definevar] = value
else:
configh[definevar] = None
cdefine('DEBUG_MODE', 'debug')
cdefine('PURIFY_MODE', 'purify')
# Need to test all of these to see what platform.system() returns
configh['SOLARIS'] = 1 if env['OS'] == 'Solaris' else None
configh['DARWIN'] = 1 if env['OS'] == 'Darwin' else None
configh['CYGWIN'] = 1 if env['OS'] == 'Cygwin' else None
configh['WINMSVC'] = 1 if env['OS'] == 'Windows' else None
cdefine('NEEDS_GENERIC_TEMPL_STATIC_DECL', 'OS', 'Solaris')
cdefine('HAS_NUMPY', 'python_array', 'numpy')
cdefine('HAS_NUMARRAY', 'python_array', 'numarray')
cdefine('HAS_NUMERIC', 'python_array', 'numeric')
cdefine('HAS_NO_PYTHON', 'python_package', 'none')
configh['PYTHON_EXE'] = quoted(env['python_cmd']) if env['python_package'] != 'none' else None
cdefine('HAS_SUNDIALS', 'use_sundials', 'y')
if env['use_sundials']:
cdefine('SUNDIALS_VERSION_22', 'sundials_version', '2.2')
cdefine('SUNDIALS_VERSION_23', 'sundials_version', '2.3')
cdefine('SUNDIALS_VERSION_24', 'sundials_version', '2.4')
cdefine('WITH_ELECTROLYTES', 'with_electrolytes')
cdefine('WITH_IDEAL_SOLUTIONS', 'with_ideal_solutions')
cdefine('WITH_LATTICE_SOLID', 'with_lattice_solid')
cdefine('WITH_METAL', 'with_metal')
cdefine('WITH_STOICH_SUBSTANCE', 'with_stoich_substance')
cdefine('WITH_SEMICONDUCTOR', 'with_semiconductor')
cdefine('WITH_PRIME', 'with_prime')
cdefine('H298MODIFY_CAPABILITY', 'with_n298modify_capability')
cdefine('WITH_PURE_FLUIDS', 'with_pure_fluids')
cdefine('INCL_PURE_FLUIDS', 'with_pure_fluids') # TODO: fix redundancy
cdefine('WITH_HTML_LOGS', 'with_html_log_files')
cdefine('WITH_VCSNONIDEAL', 'with_vcsnonideal')
cdefine('LAPACK_FTN_STRING_LEN_AT_END', 'lapack_ftn_string_len_at_end')
cdefine('LAPACK_FTN_TRAILING_UNDERSCORE', 'lapack_ftn_trailing_underscore')
cdefine('FTN_TRAILING_UNDERSCORE', 'lapack_ftn_trailing_underscore')
cdefine('LAPACK_NAMES_LOWERCASE', 'lapack_names', 'lower')
configh['RXNPATH_FONT'] = quoted(env['rpfont'])
cdefine('THREAD_SAFE_CANTERA', 'build_thread_safe')
cdefine('HAS_SSTREAM', 'HAS_SSTREAM')
configh['CANTERA_DATA'] = quoted(os.path.join(env['prefix'], 'data'))
config_h = env.Command('config.h', 'config.h.in.scons', ConfigBuilder(configh))
env.AlwaysBuild(config_h)
# **********************************************
# *** Set additional configuration variables ***
# **********************************************
if env['blas_lapack_libs'] == '':
# External BLAS/LAPACK were not given, so we need to compile them
env['BUILD_BLAS_LAPACK'] = True
env['blas_lapack_libs'] = ['ctlapack', 'ctblas']
else:
ens['blas_lapack_libs'] = ','.split(env['blas_lapack_libs'])
if env['use_sundials'] == 'y' and env['sundials_include']:
env.Append(CPPPATH=env['sundials_include'])
if env['use_sundials'] == 'y' and env['sundials_libdir']:
env.Append(LIBPATH=env['sundials_libdir'])
env['ct_libdir'] = pjoin(env['prefix'], 'lib')
env['ct_bindir'] = pjoin(env['prefix'], 'bin')
env['ct_incdir'] = pjoin(env['prefix'], 'include', 'cantera')
env['ct_incroot'] = pjoin(env['prefix'], 'include')
env['ct_datadir'] = pjoin(env['prefix'], 'data')
env['ct_demodir'] = pjoin(env['prefix'], 'demos')
env['ct_templdir'] = pjoin(env['prefix'], 'templates')
env['ct_tutdir'] = pjoin(env['prefix'], 'tutorials')
env['ct_docdir'] = pjoin(env['prefix'], 'doc')
env['ct_dir'] = env['prefix']
env['ct_mandir'] = pjoin(env['prefix'], 'man1')
env['ct_matlab_dir'] = pjoin(env['prefix'], 'matlab', 'toolbox')
# *********************
# *** Build Cantera ***
# *********************
buildDir = 'build'
buildTargets = []
installTargets = []
demoTargets = []
env.SConsignFile()
env.Append(CPPPATH=[Dir(os.getcwd()),
Dir('build/include/cantera/kernel'),
Dir('build/include/cantera'),
Dir('build/include')],
LIBPATH=[Dir('build/lib')],
CCFLAGS=['-fPIC'],
FORTRANFLAGS=['-fPIC'],
F90FLAGS=['-fPIC'])
# Put headers in place
for header in mglob(env, 'Cantera/cxx/include', 'h'):
header = env.Command('build/include/cantera/%s' % header.name, header,
Copy('$TARGET', '$SOURCE'))
buildTargets.extend(header)
inst = env.Install('$ct_incdir', header)
installTargets.extend(inst)
for header in mglob(env, 'Cantera/clib/src', 'h'):
hcopy = env.Command('build/include/cantera/clib/%s' % header.name, header,
Copy('$TARGET', '$SOURCE'))
buildTargets.append(header)
inst = env.Install(pjoin('$ct_incdir','clib'), header)
installTargets.extend(inst)
### List of libraries needed to link to Cantera ###
linkLibs = ['clib','oneD','zeroD','equil','kinetics','transport',
'thermo','ctnumerics','ctmath','tpx',
'ctspectra','converters','ctbase']
if env['use_sundials']:
linkLibs.extend(('sundials_cvodes','sundials_nvecserial'))
linkLibs.extend(env['blas_lapack_libs'])
if env['build_with_f2c']:
linkLibs.append('ctf2c')
else:
linkLibs.append('gfortran')
env['cantera_libs'] = linkLibs
configh = env.Command('build/include/cantera/config.h', 'config.h', Copy('$TARGET', '$SOURCE'))
inst = env.Install('$ct_incdir', configh)
installTargets.extend(inst)
# Add targets from the SConscript files in the various subdirectories
Export('env', 'buildDir', 'buildTargets', 'installTargets', 'demoTargets')
VariantDir('build/ext', 'ext', duplicate=0)
SConscript('build/ext/SConscript')
VariantDir('build/kernel', 'Cantera/src', duplicate=0)
SConscript('build/kernel/SConscript')
VariantDir('build/interfaces/clib', 'Cantera/clib', duplicate=0)
SConscript('build/interfaces/clib/SConscript')
VariantDir('build/interfaces/cxx', 'Cantera/cxx', duplicate=0)
SConscript('build/interfaces/cxx/SConscript')
if env['f90_interface']:
VariantDir('build/interfaces/fortran/', 'Cantera/fortran', duplicate=1)
SConscript('build/interfaces/fortran/SConscript')
if env['python_package'] in ('full','minimal'):
SConscript('Cantera/python/SConscript')
if env['matlab_toolbox'] == 'y':
SConscript('Cantera/matlab/SConscript')
VariantDir('build/tools', 'tools', duplicate=0)
SConscript('build/tools/SConscript')
# Data files
inst = env.Install('$ct_datadir', mglob(env, pjoin('data','inputs'), 'cti', 'xml'))
installTargets.extend(inst)
# Install exp3to2.sh (used by some of the tests)
inst = env.Install('$ct_bindir', pjoin('bin', 'exp3to2.sh'))
installTargets.extend(inst)
### Meta-targets ###
build_cantera = Alias('build', buildTargets)
build_demos = Alias('demos', demoTargets)
Default(build_cantera)
def postInstallMessage(target, source, env):
v = sys.version_info
env['python_module_loc'] = pjoin(
env['prefix'], 'lib', 'python%i.%i' % v[:2], 'site-packages')
print """
Cantera has been successfully installed.
File locations:
applications %(ct_bindir)s
library files %(ct_libdir)s
C++ headers %(ct_incdir)s
demos %(ct_demodir)s
data files %(ct_datadir)s""" % env
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 """
Matlab toolbox %(ct_matlab_dir)s
Matlab demos %(ct_demodir)s/matlab
Matlab tutorials %(ct_tutdir)s/matlab
An m-file to set the correct matlab path for Cantera is at:
%(prefix)s/matlab/ctpath.m""" % env
print """
setup script %(ct_bindir)s/setup_cantera
The setup script configures the environment for Cantera. It is
recommended that you run this script by typing:
source %(ct_bindir)s/setup_cantera
before using Cantera, or else include its contents in your shell
login script.
""" % env
finish_install = env.Command('finish_install', [], postInstallMessage)
env.Depends(finish_install, installTargets)
install_cantera = Alias('install', finish_install)