xref: /petsc/setup.py (revision 11035aebcfed94f9dcb5dc3ce725ed4c007d68c9)
16308ffc9SLisandro Dalcin#!/usr/bin/env python
26308ffc9SLisandro Dalcin
36308ffc9SLisandro Dalcin"""
46308ffc9SLisandro DalcinPETSc: Portable, Extensible Toolkit for Scientific Computation
56308ffc9SLisandro Dalcin==============================================================
66308ffc9SLisandro Dalcin
76308ffc9SLisandro DalcinThe Portable, Extensible Toolkit for Scientific Computation (PETSc),
86308ffc9SLisandro Dalcinis a suite of data structures and routines for the scalable (parallel)
96308ffc9SLisandro Dalcinsolution of scientific applications modeled by partial differential
106308ffc9SLisandro Dalcinequations. It employs the Message Passing Interface (MPI) standard for
116308ffc9SLisandro Dalcinall message-passing communication.
126308ffc9SLisandro Dalcin"""
136308ffc9SLisandro Dalcin
146308ffc9SLisandro Dalcinimport sys, os
156308ffc9SLisandro Dalcinfrom distutils.core import setup
166308ffc9SLisandro Dalcinfrom distutils.util import get_platform
176308ffc9SLisandro Dalcinfrom distutils.spawn import find_executable
186308ffc9SLisandro Dalcinfrom distutils.command.build import build as _build
196308ffc9SLisandro Dalcinif 'setuptools' in sys.modules:
206308ffc9SLisandro Dalcin    from setuptools.command.install import install as _install
216308ffc9SLisandro Dalcinelse:
226308ffc9SLisandro Dalcin    from distutils.command.install import install as _install
236308ffc9SLisandro Dalcinfrom distutils.command.sdist import sdist as _sdist
246308ffc9SLisandro Dalcinfrom distutils import log
256308ffc9SLisandro Dalcin
266308ffc9SLisandro Dalcininit_py = """\
276308ffc9SLisandro Dalcin# Author:  PETSc Team
286308ffc9SLisandro Dalcin# Contact: petsc-maint@mcs.anl.gov
296308ffc9SLisandro Dalcin
306308ffc9SLisandro Dalcindef get_petsc_dir():
316308ffc9SLisandro Dalcin    import os
326308ffc9SLisandro Dalcin    return os.path.dirname(__file__)
336308ffc9SLisandro Dalcin
346308ffc9SLisandro Dalcindef get_config():
356308ffc9SLisandro Dalcin    conf = {}
366308ffc9SLisandro Dalcin    conf['PETSC_DIR'] = get_petsc_dir()
376308ffc9SLisandro Dalcin    return conf
386308ffc9SLisandro Dalcin"""
396308ffc9SLisandro Dalcin
406308ffc9SLisandro Dalcinmetadata = {
416308ffc9SLisandro Dalcin    'provides' : ['petsc'],
426308ffc9SLisandro Dalcin    'requires' : [],
436308ffc9SLisandro Dalcin}
446308ffc9SLisandro Dalcin
456308ffc9SLisandro Dalcindef bootstrap():
466308ffc9SLisandro Dalcin    # Set PETSC_DIR and PETSC_ARCH,
476308ffc9SLisandro Dalcin    PETSC_DIR  = os.path.abspath(os.getcwd())
486308ffc9SLisandro Dalcin    PETSC_ARCH = get_platform() + '-python'
496308ffc9SLisandro Dalcin    os.environ['PETSC_DIR']  = PETSC_DIR
506308ffc9SLisandro Dalcin    os.environ['PETSC_ARCH'] = PETSC_ARCH
516308ffc9SLisandro Dalcin    # Generate package __init__.py file
526308ffc9SLisandro Dalcin    from distutils.dir_util import mkpath
536308ffc9SLisandro Dalcin    pkgdir = os.path.join('config', 'pypi')
546308ffc9SLisandro Dalcin    pkgfile = os.path.join(pkgdir, '__init__.py')
556308ffc9SLisandro Dalcin    if not os.path.exists(pkgdir):
566308ffc9SLisandro Dalcin        mkpath(pkgdir)
576308ffc9SLisandro Dalcin    if not os.path.exists(pkgfile):
586308ffc9SLisandro Dalcin        open(pkgfile, 'wt').write(init_py)
596308ffc9SLisandro Dalcin    # Simple-minded lookup for MPI and mpi4py
606308ffc9SLisandro Dalcin    mpi4py = mpicc = None
616308ffc9SLisandro Dalcin    try:
626308ffc9SLisandro Dalcin        import mpi4py
636308ffc9SLisandro Dalcin        conf = mpi4py.get_config()
646308ffc9SLisandro Dalcin        mpicc = conf.get('mpicc')
656308ffc9SLisandro Dalcin    except ImportError: # mpi4py is not installed
666308ffc9SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
676308ffc9SLisandro Dalcin    except AttributeError: # mpi4py is too old
686308ffc9SLisandro Dalcin        pass
696308ffc9SLisandro Dalcin    if not mpi4py and mpicc:
706308ffc9SLisandro Dalcin        if (('distribute' in sys.modules) or
716308ffc9SLisandro Dalcin            ('setuptools' in sys.modules)):
726308ffc9SLisandro Dalcin            metadata['install_requires']= ['mpi4py>=1.2.2']
736308ffc9SLisandro Dalcin    if 'setuptools' in sys.modules:
746308ffc9SLisandro Dalcin        metadata['zip_safe'] = False
756308ffc9SLisandro Dalcin
766308ffc9SLisandro Dalcindef config(dry_run=False):
776308ffc9SLisandro Dalcin    log.info('PETSc: configure')
786308ffc9SLisandro Dalcin    if dry_run: return
796308ffc9SLisandro Dalcin    options = [
806308ffc9SLisandro Dalcin        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
81*11035aebSLisandro Dalcin        '--with-debugging=0',
826308ffc9SLisandro Dalcin        '--with-shared',
836308ffc9SLisandro Dalcin        '--with-cmake=0', # not needed
846308ffc9SLisandro Dalcin        ]
856308ffc9SLisandro Dalcin    # MPI
866308ffc9SLisandro Dalcin    try:
876308ffc9SLisandro Dalcin        import mpi4py
886308ffc9SLisandro Dalcin        conf = mpi4py.get_config()
896308ffc9SLisandro Dalcin        mpicc = conf.get('mpicc')
906308ffc9SLisandro Dalcin    except (ImportError, AttributeError):
916308ffc9SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
926308ffc9SLisandro Dalcin    if mpicc:
936308ffc9SLisandro Dalcin        options.append('--with-cc='+mpicc)
946308ffc9SLisandro Dalcin    else:
956308ffc9SLisandro Dalcin        options.append('--with-mpi=0')
966308ffc9SLisandro Dalcin    options.append('--with-cxx=0') # XXX mpicxx?
976308ffc9SLisandro Dalcin    options.append('--with-fc=0')  # XXX mpif90?
986308ffc9SLisandro Dalcin    # Run PETSc configure
996308ffc9SLisandro Dalcin    status = os.system('%s %s %s' % (
1006308ffc9SLisandro Dalcin            find_executable('python'),
1016308ffc9SLisandro Dalcin            os.path.join('config', 'configure.py'),
1026308ffc9SLisandro Dalcin            ' '.join(options),
1036308ffc9SLisandro Dalcin            ))
1046308ffc9SLisandro Dalcin    if status != 0: raise RuntimeError(status)
1056308ffc9SLisandro Dalcin
1066308ffc9SLisandro Dalcindef build(dry_run=False):
1076308ffc9SLisandro Dalcin    log.info('PETSc: build')
1086308ffc9SLisandro Dalcin    if dry_run: return
1096308ffc9SLisandro Dalcin    # Run PETSc builder
1106308ffc9SLisandro Dalcin    status = os.system('make all')
1116308ffc9SLisandro Dalcin    if status != 0: raise RuntimeError(status)
1126308ffc9SLisandro Dalcin
1136308ffc9SLisandro Dalcindef install(dest_dir, prefix=None, dry_run=False):
1146308ffc9SLisandro Dalcin    log.info('PETSc: install')
1156308ffc9SLisandro Dalcin    if dry_run: return
1166308ffc9SLisandro Dalcin    if prefix is None:
1176308ffc9SLisandro Dalcin        prefix = dest_dir
1186308ffc9SLisandro Dalcin    options = [
1196308ffc9SLisandro Dalcin        '--destDir=' + dest_dir,
1206308ffc9SLisandro Dalcin        '--prefix='  + prefix,
1216308ffc9SLisandro Dalcin        ]
1226308ffc9SLisandro Dalcin    # Run PETSc installer
1236308ffc9SLisandro Dalcin    status = os.system('%s %s %s' % (
1246308ffc9SLisandro Dalcin            find_executable('python'),
1256308ffc9SLisandro Dalcin            os.path.join('config', 'install.py'),
1266308ffc9SLisandro Dalcin            ' '.join(options),
1276308ffc9SLisandro Dalcin            ))
1286308ffc9SLisandro Dalcin    if status != 0: raise RuntimeError(status)
1296308ffc9SLisandro Dalcin
1306308ffc9SLisandro Dalcinclass context:
1316308ffc9SLisandro Dalcin    def __init__(self):
1326308ffc9SLisandro Dalcin        self.sys_argv = sys.argv[:]
1336308ffc9SLisandro Dalcin        self.wdir = os.getcwd()
1346308ffc9SLisandro Dalcin    def enter(self):
1356308ffc9SLisandro Dalcin        del sys.argv[1:]
1366308ffc9SLisandro Dalcin        pdir = os.environ['PETSC_DIR']
1376308ffc9SLisandro Dalcin        os.chdir(pdir)
1386308ffc9SLisandro Dalcin        return self
1396308ffc9SLisandro Dalcin    def exit(self):
1406308ffc9SLisandro Dalcin        sys.argv[:] = self.sys_argv
1416308ffc9SLisandro Dalcin        os.chdir(self.wdir)
1426308ffc9SLisandro Dalcin
1436308ffc9SLisandro Dalcinclass cmd_build(_build):
1446308ffc9SLisandro Dalcin
1456308ffc9SLisandro Dalcin    def initialize_options(self):
1466308ffc9SLisandro Dalcin        _build.initialize_options(self)
1476308ffc9SLisandro Dalcin        PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
1486308ffc9SLisandro Dalcin        self.build_base = os.path.join(PETSC_ARCH, 'build-python')
1496308ffc9SLisandro Dalcin
1506308ffc9SLisandro Dalcin    def run(self):
1516308ffc9SLisandro Dalcin        _build.run(self)
1526308ffc9SLisandro Dalcin        ctx = context().enter()
1536308ffc9SLisandro Dalcin        try:
1546308ffc9SLisandro Dalcin            config(self.dry_run)
1556308ffc9SLisandro Dalcin            build(self.dry_run)
1566308ffc9SLisandro Dalcin        finally:
1576308ffc9SLisandro Dalcin            ctx.exit()
1586308ffc9SLisandro Dalcin
1596308ffc9SLisandro Dalcinclass cmd_install(_install):
1606308ffc9SLisandro Dalcin
1616308ffc9SLisandro Dalcin    def initialize_options(self):
1626308ffc9SLisandro Dalcin        _install.initialize_options(self)
1636308ffc9SLisandro Dalcin        self.optimize = 1
1646308ffc9SLisandro Dalcin
1656308ffc9SLisandro Dalcin    def run(self):
1666308ffc9SLisandro Dalcin        root_dir = self.install_platlib
1676308ffc9SLisandro Dalcin        dest_dir = os.path.join(root_dir, 'petsc')
1686308ffc9SLisandro Dalcin        bdist_base = self.get_finalized_command('bdist').bdist_base
1696308ffc9SLisandro Dalcin        if dest_dir.startswith(bdist_base):
1706308ffc9SLisandro Dalcin            prefix = dest_dir[len(bdist_base)+1:]
1716308ffc9SLisandro Dalcin            prefix = prefix[prefix.index(os.path.sep):]
1726308ffc9SLisandro Dalcin        else:
1736308ffc9SLisandro Dalcin            prefix = dest_dir
1746308ffc9SLisandro Dalcin        dest_dir = os.path.abspath(dest_dir)
1756308ffc9SLisandro Dalcin        prefix   = os.path.abspath(prefix)
1766308ffc9SLisandro Dalcin        #
1776308ffc9SLisandro Dalcin        _install.run(self)
1786308ffc9SLisandro Dalcin        ctx = context().enter()
1796308ffc9SLisandro Dalcin        try:
1806308ffc9SLisandro Dalcin            install(dest_dir, prefix, self.dry_run)
1816308ffc9SLisandro Dalcin        finally:
1826308ffc9SLisandro Dalcin            ctx.exit()
1836308ffc9SLisandro Dalcin
1846308ffc9SLisandro Dalcinclass cmd_sdist(_sdist):
1856308ffc9SLisandro Dalcin
1866308ffc9SLisandro Dalcin    def initialize_options(self):
1876308ffc9SLisandro Dalcin        _sdist.initialize_options(self)
1886308ffc9SLisandro Dalcin        self.force_manifest = 1
1896308ffc9SLisandro Dalcin        self.template = os.path.join('config', 'manifest.in')
1906308ffc9SLisandro Dalcin
1916308ffc9SLisandro Dalcindef version():
1926308ffc9SLisandro Dalcin    import re
1936308ffc9SLisandro Dalcin    version_re = {
1946308ffc9SLisandro Dalcin        'major'  : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"),
1956308ffc9SLisandro Dalcin        'minor'  : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"),
1966308ffc9SLisandro Dalcin        'micro'  : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"),
1976308ffc9SLisandro Dalcin        'patch'  : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"),
1986308ffc9SLisandro Dalcin        'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"),
1996308ffc9SLisandro Dalcin        }
2006308ffc9SLisandro Dalcin    petscversion_h = os.path.join('include','petscversion.h')
2016308ffc9SLisandro Dalcin    data = open(petscversion_h, 'rt').read()
2026308ffc9SLisandro Dalcin    major = int(version_re['major'].search(data).groups()[0])
2036308ffc9SLisandro Dalcin    minor = int(version_re['minor'].search(data).groups()[0])
2046308ffc9SLisandro Dalcin    micro = int(version_re['micro'].search(data).groups()[0])
2056308ffc9SLisandro Dalcin    patch = int(version_re['patch'].search(data).groups()[0])
2066308ffc9SLisandro Dalcin    release = int(version_re['release'].search(data).groups()[0])
2076308ffc9SLisandro Dalcin    if release:
2086308ffc9SLisandro Dalcin        v = "%d.%d" % (major, minor)
2096308ffc9SLisandro Dalcin        if micro > 0:
2106308ffc9SLisandro Dalcin            v += ".%d" % micro
2116308ffc9SLisandro Dalcin        if patch > 0:
2126308ffc9SLisandro Dalcin            v += ".post%d" % patch
2136308ffc9SLisandro Dalcin    else:
2146308ffc9SLisandro Dalcin        v = "%d.%d.dev%d" % (major, minor+1, 0)
2156308ffc9SLisandro Dalcin    return v
2166308ffc9SLisandro Dalcin
2176308ffc9SLisandro Dalcindef tarball():
2186308ffc9SLisandro Dalcin    VERSION = version()
2196308ffc9SLisandro Dalcin    if '.dev' in VERSION:
2206308ffc9SLisandro Dalcin        return None
2216308ffc9SLisandro Dalcin    if '.post' not in VERSION:
2226308ffc9SLisandro Dalcin        VERSION = VERSION + '.post0'
2236308ffc9SLisandro Dalcin    VERSION = VERSION.replace('.post', '-p')
2246308ffc9SLisandro Dalcin    return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/'
2256308ffc9SLisandro Dalcin            'petsc-lite-%s.tar.gz' % VERSION)
2266308ffc9SLisandro Dalcin
2276308ffc9SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3]
2286308ffc9SLisandro Dalcinclassifiers = """
2296308ffc9SLisandro DalcinLicense :: Public Domain
2306308ffc9SLisandro DalcinOperating System :: POSIX
2316308ffc9SLisandro DalcinIntended Audience :: Developers
2326308ffc9SLisandro DalcinIntended Audience :: Science/Research
2336308ffc9SLisandro DalcinProgramming Language :: C
2346308ffc9SLisandro DalcinProgramming Language :: C++
2356308ffc9SLisandro DalcinProgramming Language :: Fortran
2366308ffc9SLisandro DalcinProgramming Language :: Python
2376308ffc9SLisandro DalcinTopic :: Scientific/Engineering
2386308ffc9SLisandro DalcinTopic :: Software Development :: Libraries
2396308ffc9SLisandro Dalcin"""
2406308ffc9SLisandro Dalcin
2416308ffc9SLisandro Dalcinbootstrap()
2426308ffc9SLisandro Dalcinsetup(name='petsc',
2436308ffc9SLisandro Dalcin      version=version(),
2446308ffc9SLisandro Dalcin      description=description.pop(0),
2456308ffc9SLisandro Dalcin      long_description='\n'.join(description),
2466308ffc9SLisandro Dalcin      classifiers= classifiers.split('\n')[1:-1],
2476308ffc9SLisandro Dalcin      keywords = ['PETSc', 'MPI'],
2486308ffc9SLisandro Dalcin      platforms=['POSIX'],
2496308ffc9SLisandro Dalcin      license='PETSc',
2506308ffc9SLisandro Dalcin
2516308ffc9SLisandro Dalcin      url='http://www.mcs.anl.gov/petsc/',
2526308ffc9SLisandro Dalcin      download_url=tarball(),
2536308ffc9SLisandro Dalcin
2546308ffc9SLisandro Dalcin      author='PETSc Team',
2556308ffc9SLisandro Dalcin      author_email='petsc-maint@mcs.anl.gov',
2566308ffc9SLisandro Dalcin      maintainer='Lisandro Dalcin',
2576308ffc9SLisandro Dalcin      maintainer_email='dalcinl@gmail.com',
2586308ffc9SLisandro Dalcin
2596308ffc9SLisandro Dalcin      packages = ['petsc'],
2606308ffc9SLisandro Dalcin      package_dir = {'petsc': 'config/pypi'},
2616308ffc9SLisandro Dalcin      cmdclass={
2626308ffc9SLisandro Dalcin        'build': cmd_build,
2636308ffc9SLisandro Dalcin        'install': cmd_install,
2646308ffc9SLisandro Dalcin        'sdist': cmd_sdist,
2656308ffc9SLisandro Dalcin        },
2666308ffc9SLisandro Dalcin      **metadata)
267