xref: /petsc/setup.py (revision be96eb59de56b0041bf0b1762ab8a3dff56b132b)
1e68ebbecSBarry Smith#!/usr/bin/env python
2e68ebbecSBarry Smith
3e68ebbecSBarry Smith"""
465a891e7SLisandro DalcinPETSc: Portable, Extensible Toolkit for Scientific Computation
565a891e7SLisandro Dalcin==============================================================
665a891e7SLisandro Dalcin
765a891e7SLisandro DalcinThe Portable, Extensible Toolkit for Scientific Computation (PETSc),
865a891e7SLisandro Dalcinis a suite of data structures and routines for the scalable (parallel)
965a891e7SLisandro Dalcinsolution of scientific applications modeled by partial differential
1065a891e7SLisandro Dalcinequations. It employs the Message Passing Interface (MPI) standard for
1165a891e7SLisandro Dalcinall message-passing communication.
12e68ebbecSBarry Smith"""
13e68ebbecSBarry Smith
1465a891e7SLisandro Dalcinimport sys, os
1565a891e7SLisandro Dalcinfrom distutils.core import setup
1665a891e7SLisandro Dalcinfrom distutils.util import get_platform
17b88f8b63SLisandro Dalcinfrom distutils.spawn import find_executable
1865a891e7SLisandro Dalcinfrom distutils.command.build import build as _build
1965a891e7SLisandro Dalcinif 'setuptools' in sys.modules:
2065a891e7SLisandro Dalcin    from setuptools.command.install import install as _install
2165a891e7SLisandro Dalcinelse:
2265a891e7SLisandro Dalcin    from distutils.command.install import install as _install
23a32381aeSLisandro Dalcinfrom distutils.command.sdist import sdist as _sdist
2465a891e7SLisandro Dalcinfrom distutils import log
2512c1d45bSMatthew G Knepley
2659e0f383SLisandro DalcinPETSC_DIR  = None
2759e0f383SLisandro DalcinPETSC_ARCH = None
2859e0f383SLisandro Dalcin
2965a891e7SLisandro Dalcininit_py = """\
30a32381aeSLisandro Dalcin# Author:  PETSc Team
31a32381aeSLisandro Dalcin# Contact: petsc-users@mcs.anl.gov
3265a891e7SLisandro Dalcin
3365a891e7SLisandro Dalcindef get_petsc_dir():
3465a891e7SLisandro Dalcin    import os
3565a891e7SLisandro Dalcin    return os.path.dirname(__file__)
3665a891e7SLisandro Dalcin
37a32381aeSLisandro Dalcindef get_config():
38a32381aeSLisandro Dalcin    conf = {}
399fb7a39fSLisandro Dalcin    conf['PETSC_DIR'] = get_petsc_dir()
40a32381aeSLisandro Dalcin    return conf
4165a891e7SLisandro Dalcin"""
4265a891e7SLisandro Dalcin
4359e0f383SLisandro Dalcinmetadata = {
4459e0f383SLisandro Dalcin    'provides' : ['petsc'],
4559e0f383SLisandro Dalcin    'requires' : [],
4659e0f383SLisandro Dalcin}
4759e0f383SLisandro Dalcin
4865a891e7SLisandro Dalcindef bootstrap():
4959e0f383SLisandro Dalcin    # Set PETSC_DIR and PETSC_ARCH,
5059e0f383SLisandro Dalcin    global PETSC_DIR, PETSC_ARCH
5165a891e7SLisandro Dalcin    PETSC_DIR  = os.path.abspath(os.getcwd())
5265a891e7SLisandro Dalcin    PETSC_ARCH = get_platform() + '-python'
5365a891e7SLisandro Dalcin    os.environ['PETSC_DIR']  = PETSC_DIR
5465a891e7SLisandro Dalcin    os.environ['PETSC_ARCH'] = PETSC_ARCH
5565a891e7SLisandro Dalcin    sys.path.insert(0, os.path.join(PETSC_DIR, 'config'))
5659e0f383SLisandro Dalcin    # Generate package __init__.py file
579fb7a39fSLisandro Dalcin    from distutils.dir_util import mkpath
589fb7a39fSLisandro Dalcin    pkgdir = os.path.join('config', 'pypi')
599fb7a39fSLisandro Dalcin    pkgfile = os.path.join(pkgdir, '__init__.py')
609fb7a39fSLisandro Dalcin    if not os.path.exists(pkgdir):
619fb7a39fSLisandro Dalcin        mkpath(pkgdir)
629fb7a39fSLisandro Dalcin    if not os.path.exists(pkgfile):
6365a891e7SLisandro Dalcin        open(pkgfile, 'wt').write(init_py)
6459e0f383SLisandro Dalcin    # Simple-minded lookup for MPI and mpi4py
6559e0f383SLisandro Dalcin    mpi4py = mpicc = None
6659e0f383SLisandro Dalcin    try:
6759e0f383SLisandro Dalcin        import mpi4py
6859e0f383SLisandro Dalcin        conf = mpi4py.get_config()
6959e0f383SLisandro Dalcin        mpicc = conf.get('mpicc')
7059e0f383SLisandro Dalcin    except ImportError: # mpi4py is not installed
7159e0f383SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
721b095333SLisandro Dalcin    except AttributeError: # mpi4py is too old
7359e0f383SLisandro Dalcin        pass
7459e0f383SLisandro Dalcin    if not mpi4py and mpicc:
751b095333SLisandro Dalcin        if (('distribute' in sys.modules) or
761b095333SLisandro Dalcin            ('setuptools' in sys.modules)):
771b095333SLisandro Dalcin            metadata['install_requires']= ['mpi4py>=1.2.2']
78*be96eb59SLisandro Dalcin    if 'setuptools' in sys.modules:
79*be96eb59SLisandro Dalcin        metadata['zip_safe'] = False
8065a891e7SLisandro Dalcin
8165a891e7SLisandro Dalcindef config(dry_run=False):
8265a891e7SLisandro Dalcin    log.info('PETSc: configure')
8365a891e7SLisandro Dalcin    if dry_run: return
8465a891e7SLisandro Dalcin    options = [
8565a891e7SLisandro Dalcin        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
8665a891e7SLisandro Dalcin        '--with-shared-libraries',
8759e0f383SLisandro Dalcin        '--with-cmake=0', # not needed
8865a891e7SLisandro Dalcin        ]
8959e0f383SLisandro Dalcin    # MPI
9059e0f383SLisandro Dalcin    try:
9159e0f383SLisandro Dalcin        import mpi4py
9259e0f383SLisandro Dalcin        conf = mpi4py.get_config()
9359e0f383SLisandro Dalcin        mpicc = conf.get('mpicc')
9459e0f383SLisandro Dalcin    except (ImportError, AttributeError):
9559e0f383SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
9659e0f383SLisandro Dalcin    if mpicc:
9759e0f383SLisandro Dalcin        options.append('--with-cc='+mpicc)
9859e0f383SLisandro Dalcin    else:
9959e0f383SLisandro Dalcin        options.append('--with-mpi=0')
10099468c80SLisandro Dalcin    options.append('--with-cxx=0') # XXX mpicxx?
10199468c80SLisandro Dalcin    options.append('--with-fc=0')  # XXX mpif90?
10259e0f383SLisandro Dalcin    # Run PETSc configure
103e68ebbecSBarry Smith    import configure
10465a891e7SLisandro Dalcin    configure.petsc_configure(options)
105e68ebbecSBarry Smith    import logger
106e68ebbecSBarry Smith    logger.Logger.defaultLog = None
10712c1d45bSMatthew G Knepley
10865a891e7SLisandro Dalcindef build(dry_run=False):
10965a891e7SLisandro Dalcin    log.info('PETSc: build')
11065a891e7SLisandro Dalcin    if dry_run: return
11159e0f383SLisandro Dalcin    # Run PETSc builder
112e68ebbecSBarry Smith    import builder
113e68ebbecSBarry Smith    builder.PETScMaker().run()
114105e34d4SBarry Smith    import logger
115105e34d4SBarry Smith    logger.Logger.defaultLog = None
116e68ebbecSBarry Smith
11765a891e7SLisandro Dalcindef install(dest_dir, prefix=None, dry_run=False):
11865a891e7SLisandro Dalcin    log.info('PETSc: install')
11965a891e7SLisandro Dalcin    if dry_run: return
12065a891e7SLisandro Dalcin    if prefix is None:
12165a891e7SLisandro Dalcin        prefix = dest_dir
12265a891e7SLisandro Dalcin    options = [
12365a891e7SLisandro Dalcin        '--destDir=' + dest_dir,
1244dee622bSLisandro Dalcin        '--prefix='  + prefix,
12565a891e7SLisandro Dalcin        ]
12659e0f383SLisandro Dalcin    # Run PETSc installer
127105e34d4SBarry Smith    import install
12865a891e7SLisandro Dalcin    install.Installer(options).run()
12965a891e7SLisandro Dalcin    import logger
13065a891e7SLisandro Dalcin    logger.Logger.defaultLog = None
13199468c80SLisandro Dalcin
13299468c80SLisandro Dalcinclass context:
13399468c80SLisandro Dalcin    def __init__(self):
13499468c80SLisandro Dalcin        self.sys_argv = sys.argv[:]
13599468c80SLisandro Dalcin        self.wdir = os.getcwd()
13699468c80SLisandro Dalcin    def enter(self):
13799468c80SLisandro Dalcin        del sys.argv[1:]
13899468c80SLisandro Dalcin        pdir = os.environ['PETSC_DIR']
13999468c80SLisandro Dalcin        os.chdir(pdir)
14099468c80SLisandro Dalcin        return self
14199468c80SLisandro Dalcin    def exit(self):
14299468c80SLisandro Dalcin        sys.argv[:] = self.sys_argv
14399468c80SLisandro Dalcin        os.chdir(self.wdir)
144105e34d4SBarry Smith
14565a891e7SLisandro Dalcinclass cmd_build(_build):
14665a891e7SLisandro Dalcin
14765a891e7SLisandro Dalcin    def run(self):
14865a891e7SLisandro Dalcin        _build.run(self)
14999468c80SLisandro Dalcin        ctx = context().enter()
15065a891e7SLisandro Dalcin        try:
15165a891e7SLisandro Dalcin            config(self.dry_run)
15265a891e7SLisandro Dalcin            build(self.dry_run)
15365a891e7SLisandro Dalcin        finally:
15499468c80SLisandro Dalcin            ctx.exit()
15565a891e7SLisandro Dalcin
15665a891e7SLisandro Dalcinclass cmd_install(_install):
15765a891e7SLisandro Dalcin
15865a891e7SLisandro Dalcin    def run(self):
15965a891e7SLisandro Dalcin        root_dir = self.install_platlib
16065a891e7SLisandro Dalcin        dest_dir = os.path.join(root_dir, 'petsc')
16165a891e7SLisandro Dalcin        bdist_base = self.get_finalized_command('bdist').bdist_base
16265a891e7SLisandro Dalcin        if dest_dir.startswith(bdist_base):
16365a891e7SLisandro Dalcin            prefix = dest_dir[len(bdist_base)+1:]
16465a891e7SLisandro Dalcin            prefix = prefix[prefix.index(os.path.sep):]
16565a891e7SLisandro Dalcin        else:
16665a891e7SLisandro Dalcin            prefix = dest_dir
16765a891e7SLisandro Dalcin        dest_dir = os.path.abspath(dest_dir)
16865a891e7SLisandro Dalcin        prefix   = os.path.abspath(prefix)
16999468c80SLisandro Dalcin        #
17099468c80SLisandro Dalcin        _install.run(self)
17199468c80SLisandro Dalcin        ctx = context().enter()
17265a891e7SLisandro Dalcin        try:
17365a891e7SLisandro Dalcin            install(dest_dir, prefix, self.dry_run)
17465a891e7SLisandro Dalcin        finally:
17599468c80SLisandro Dalcin            ctx.exit()
17665a891e7SLisandro Dalcin
177a32381aeSLisandro Dalcinclass cmd_sdist(_sdist):
178a32381aeSLisandro Dalcin
179a32381aeSLisandro Dalcin    def initialize_options(self):
180a32381aeSLisandro Dalcin        _sdist.initialize_options(self)
181a32381aeSLisandro Dalcin        self.force_manifest = 1
18299468c80SLisandro Dalcin        self.template = os.path.join('config', 'manifest.in')
183a32381aeSLisandro Dalcin
18465a891e7SLisandro Dalcindef version():
1857d04d9c9SLisandro Dalcin    import re
1867d04d9c9SLisandro Dalcin    version_re = {
1877d04d9c9SLisandro Dalcin        'major'  : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"),
1887d04d9c9SLisandro Dalcin        'minor'  : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"),
1897d04d9c9SLisandro Dalcin        'micro'  : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"),
1907d04d9c9SLisandro Dalcin        'patch'  : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"),
1917d04d9c9SLisandro Dalcin        'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"),
1927d04d9c9SLisandro Dalcin        }
1937d04d9c9SLisandro Dalcin    petscversion_h = os.path.join('include','petscversion.h')
1947d04d9c9SLisandro Dalcin    data = open(petscversion_h, 'rt').read()
1957d04d9c9SLisandro Dalcin    major = int(version_re['major'].search(data).groups()[0])
1967d04d9c9SLisandro Dalcin    minor = int(version_re['minor'].search(data).groups()[0])
1977d04d9c9SLisandro Dalcin    micro = int(version_re['micro'].search(data).groups()[0])
1987d04d9c9SLisandro Dalcin    patch = int(version_re['patch'].search(data).groups()[0])
1997d04d9c9SLisandro Dalcin    release = int(version_re['release'].search(data).groups()[0])
2007d04d9c9SLisandro Dalcin    if release:
2017d04d9c9SLisandro Dalcin        v = "%d.%d" % (major, minor)
2027d04d9c9SLisandro Dalcin        if micro > 0:
2037d04d9c9SLisandro Dalcin            v += ".%d" % micro
2047d04d9c9SLisandro Dalcin        if patch > 0:
20561a717f9SLisandro Dalcin            v += ".post%d" % patch
2067d04d9c9SLisandro Dalcin    else:
20761a717f9SLisandro Dalcin        v = "%d.%d.dev%d" % (major, minor+1, 0)
2087d04d9c9SLisandro Dalcin    return v
20959e0f383SLisandro Dalcin
21065a891e7SLisandro Dalcindef tarball():
21150f36069SLisandro Dalcin    VERSION = version()
21250f36069SLisandro Dalcin    if '.dev' in VERSION:
213a32381aeSLisandro Dalcin        return None
21450f36069SLisandro Dalcin    if '.post' not in VERSION:
21550f36069SLisandro Dalcin        VERSION = VERSION + '.post0'
21650f36069SLisandro Dalcin    VERSION = VERSION.replace('.post', '-p')
21750f36069SLisandro Dalcin    return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/'
21850f36069SLisandro Dalcin            'petsc-lite-%s.tar.gz' % VERSION)
21965a891e7SLisandro Dalcin
22065a891e7SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3]
22165a891e7SLisandro Dalcinclassifiers = """
22265a891e7SLisandro DalcinLicense :: Public Domain
22365a891e7SLisandro DalcinOperating System :: POSIX
22465a891e7SLisandro DalcinIntended Audience :: Developers
22565a891e7SLisandro DalcinIntended Audience :: Science/Research
22665a891e7SLisandro DalcinProgramming Language :: C
22765a891e7SLisandro DalcinProgramming Language :: C++
22865a891e7SLisandro DalcinProgramming Language :: Fortran
22965a891e7SLisandro DalcinProgramming Language :: Python
23065a891e7SLisandro DalcinTopic :: Scientific/Engineering
23165a891e7SLisandro DalcinTopic :: Software Development :: Libraries
23265a891e7SLisandro Dalcin"""
23365a891e7SLisandro Dalcin
23465a891e7SLisandro Dalcinbootstrap()
23565a891e7SLisandro Dalcinsetup(name='petsc',
23665a891e7SLisandro Dalcin      version=version(),
23765a891e7SLisandro Dalcin      description=description.pop(0),
23865a891e7SLisandro Dalcin      long_description='\n'.join(description),
23965a891e7SLisandro Dalcin      classifiers= classifiers.split('\n')[1:-1],
24065a891e7SLisandro Dalcin      keywords = ['PETSc', 'MPI'],
24165a891e7SLisandro Dalcin      platforms=['POSIX'],
24265a891e7SLisandro Dalcin      license='PETSc',
24365a891e7SLisandro Dalcin
24465a891e7SLisandro Dalcin      url='http://www.mcs.anl.gov/petsc/',
24565a891e7SLisandro Dalcin      download_url=tarball(),
24665a891e7SLisandro Dalcin
24765a891e7SLisandro Dalcin      author='PETSc Team',
24899468c80SLisandro Dalcin      author_email='petsc-maint@mcs.anl.gov',
24965a891e7SLisandro Dalcin      maintainer='Lisandro Dalcin',
25065a891e7SLisandro Dalcin      maintainer_email='dalcinl@gmail.com',
25165a891e7SLisandro Dalcin
25265a891e7SLisandro Dalcin      packages = ['petsc'],
2539fb7a39fSLisandro Dalcin      package_dir = {'petsc': 'config/pypi'},
25465a891e7SLisandro Dalcin      cmdclass={
25565a891e7SLisandro Dalcin        'build': cmd_build,
25665a891e7SLisandro Dalcin        'install': cmd_install,
257a32381aeSLisandro Dalcin        'sdist': cmd_sdist,
25865a891e7SLisandro Dalcin        },
25959e0f383SLisandro Dalcin      **metadata)
260