xref: /petsc/setup.py (revision cb58ab5b9cb3ca1780c133041329b01997f78e6d)
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
16*cb58ab5bSLisandro Dalcinfrom distutils.util import get_platform, split_quoted
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
2665a891e7SLisandro Dalcininit_py = """\
27a32381aeSLisandro Dalcin# Author:  PETSc Team
28a597b971SLisandro Dalcin# Contact: petsc-maint@mcs.anl.gov
2965a891e7SLisandro Dalcin
3065a891e7SLisandro Dalcindef get_petsc_dir():
3165a891e7SLisandro Dalcin    import os
3265a891e7SLisandro Dalcin    return os.path.dirname(__file__)
3365a891e7SLisandro Dalcin
34a32381aeSLisandro Dalcindef get_config():
35a32381aeSLisandro Dalcin    conf = {}
369fb7a39fSLisandro Dalcin    conf['PETSC_DIR'] = get_petsc_dir()
37a32381aeSLisandro Dalcin    return conf
3865a891e7SLisandro Dalcin"""
3965a891e7SLisandro Dalcin
4059e0f383SLisandro Dalcinmetadata = {
4159e0f383SLisandro Dalcin    'provides' : ['petsc'],
4259e0f383SLisandro Dalcin    'requires' : [],
4359e0f383SLisandro Dalcin}
4459e0f383SLisandro Dalcin
4565a891e7SLisandro Dalcindef bootstrap():
46*cb58ab5bSLisandro Dalcin    # Set PETSC_DIR and PETSC_ARCH
4765a891e7SLisandro Dalcin    PETSC_DIR  = os.path.abspath(os.getcwd())
4865a891e7SLisandro Dalcin    PETSC_ARCH = get_platform() + '-python'
4965a891e7SLisandro Dalcin    os.environ['PETSC_DIR']  = PETSC_DIR
5065a891e7SLisandro Dalcin    os.environ['PETSC_ARCH'] = PETSC_ARCH
5165a891e7SLisandro Dalcin    sys.path.insert(0, os.path.join(PETSC_DIR, 'config'))
5259e0f383SLisandro Dalcin    # Generate package __init__.py file
539fb7a39fSLisandro Dalcin    from distutils.dir_util import mkpath
549fb7a39fSLisandro Dalcin    pkgdir = os.path.join('config', 'pypi')
559fb7a39fSLisandro Dalcin    pkgfile = os.path.join(pkgdir, '__init__.py')
569fb7a39fSLisandro Dalcin    if not os.path.exists(pkgdir):
579fb7a39fSLisandro Dalcin        mkpath(pkgdir)
589fb7a39fSLisandro Dalcin    if not os.path.exists(pkgfile):
5965a891e7SLisandro Dalcin        open(pkgfile, 'wt').write(init_py)
6059e0f383SLisandro Dalcin    # Simple-minded lookup for MPI and mpi4py
6159e0f383SLisandro Dalcin    mpi4py = mpicc = None
6259e0f383SLisandro Dalcin    try:
6359e0f383SLisandro Dalcin        import mpi4py
6459e0f383SLisandro Dalcin        conf = mpi4py.get_config()
6559e0f383SLisandro Dalcin        mpicc = conf.get('mpicc')
6659e0f383SLisandro Dalcin    except ImportError: # mpi4py is not installed
6759e0f383SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
681b095333SLisandro Dalcin    except AttributeError: # mpi4py is too old
6959e0f383SLisandro Dalcin        pass
7059e0f383SLisandro Dalcin    if not mpi4py and mpicc:
711b095333SLisandro Dalcin        if (('distribute' in sys.modules) or
721b095333SLisandro Dalcin            ('setuptools' in sys.modules)):
731b095333SLisandro Dalcin            metadata['install_requires']= ['mpi4py>=1.2.2']
74be96eb59SLisandro Dalcin    if 'setuptools' in sys.modules:
75be96eb59SLisandro Dalcin        metadata['zip_safe'] = False
7665a891e7SLisandro Dalcin
7765a891e7SLisandro Dalcindef config(dry_run=False):
7865a891e7SLisandro Dalcin    log.info('PETSc: configure')
7965a891e7SLisandro Dalcin    options = [
8065a891e7SLisandro Dalcin        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
81*cb58ab5bSLisandro Dalcin        '--with-shared-libraries=1',
8211035aebSLisandro Dalcin        '--with-debugging=0',
8359e0f383SLisandro Dalcin        '--with-cmake=0', # not needed
8465a891e7SLisandro Dalcin        ]
8559e0f383SLisandro Dalcin    # MPI
8659e0f383SLisandro Dalcin    try:
8759e0f383SLisandro Dalcin        import mpi4py
8859e0f383SLisandro Dalcin        conf = mpi4py.get_config()
8959e0f383SLisandro Dalcin        mpicc  = conf.get('mpicc')
90*cb58ab5bSLisandro Dalcin        mpicxx = conf.get('mpicxx')
91*cb58ab5bSLisandro Dalcin        mpif90 = conf.get('mpif90')
9259e0f383SLisandro Dalcin    except (ImportError, AttributeError):
9359e0f383SLisandro Dalcin        mpicc  = os.environ.get('MPICC')  or find_executable('mpicc')
94*cb58ab5bSLisandro Dalcin        mpicxx = os.environ.get('MPICXX') or find_executable('mpicxx')
95*cb58ab5bSLisandro Dalcin        mpif90 = os.environ.get('MPIF90') or find_executable('mpif90')
9659e0f383SLisandro Dalcin    if mpicc:
9759e0f383SLisandro Dalcin        options.append('--with-cc='+mpicc)
98*cb58ab5bSLisandro Dalcin        if mpicxx:
99*cb58ab5bSLisandro Dalcin            options.append('--with-cxx='+mpicxx)
100*cb58ab5bSLisandro Dalcin        if mpif90:
101*cb58ab5bSLisandro Dalcin            options.append('--with-fc='+mpif90)
10259e0f383SLisandro Dalcin    else:
10359e0f383SLisandro Dalcin        options.append('--with-mpi=0')
104*cb58ab5bSLisandro Dalcin    # Extra configure options
105*cb58ab5bSLisandro Dalcin    config_opts = os.environ.get('PETSC_CONFIGURE_OPTIONS', '')
106*cb58ab5bSLisandro Dalcin    config_opts = split_quoted(config_opts)
107*cb58ab5bSLisandro Dalcin    options.extend(config_opts)
108*cb58ab5bSLisandro Dalcin    log.info('configure options:')
109*cb58ab5bSLisandro Dalcin    for opt in options:
110*cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
11159e0f383SLisandro Dalcin    # Run PETSc configure
112*cb58ab5bSLisandro Dalcin    if dry_run: return
113e68ebbecSBarry Smith    import configure
11465a891e7SLisandro Dalcin    configure.petsc_configure(options)
115e68ebbecSBarry Smith    import logger
116e68ebbecSBarry Smith    logger.Logger.defaultLog = None
11712c1d45bSMatthew G Knepley
11865a891e7SLisandro Dalcindef build(dry_run=False):
11965a891e7SLisandro Dalcin    log.info('PETSc: build')
12059e0f383SLisandro Dalcin    # Run PETSc builder
121*cb58ab5bSLisandro Dalcin    if dry_run: return
122e68ebbecSBarry Smith    import builder
123e68ebbecSBarry Smith    builder.PETScMaker().run()
124105e34d4SBarry Smith    import logger
125105e34d4SBarry Smith    logger.Logger.defaultLog = None
126e68ebbecSBarry Smith
12765a891e7SLisandro Dalcindef install(dest_dir, prefix=None, dry_run=False):
12865a891e7SLisandro Dalcin    log.info('PETSc: install')
12965a891e7SLisandro Dalcin    if prefix is None:
13065a891e7SLisandro Dalcin        prefix = dest_dir
13165a891e7SLisandro Dalcin    options = [
13265a891e7SLisandro Dalcin        '--destDir=' + dest_dir,
1334dee622bSLisandro Dalcin        '--prefix='  + prefix,
13465a891e7SLisandro Dalcin        ]
135*cb58ab5bSLisandro Dalcin    log.info('install options:')
136*cb58ab5bSLisandro Dalcin    for opt in options:
137*cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
13859e0f383SLisandro Dalcin    # Run PETSc installer
139*cb58ab5bSLisandro Dalcin    if dry_run: return
140105e34d4SBarry Smith    import install
14165a891e7SLisandro Dalcin    install.Installer(options).run()
14265a891e7SLisandro Dalcin    import logger
14365a891e7SLisandro Dalcin    logger.Logger.defaultLog = None
14499468c80SLisandro Dalcin
14599468c80SLisandro Dalcinclass context:
14699468c80SLisandro Dalcin    def __init__(self):
14799468c80SLisandro Dalcin        self.sys_argv = sys.argv[:]
14899468c80SLisandro Dalcin        self.wdir = os.getcwd()
14999468c80SLisandro Dalcin    def enter(self):
15099468c80SLisandro Dalcin        del sys.argv[1:]
15199468c80SLisandro Dalcin        pdir = os.environ['PETSC_DIR']
15299468c80SLisandro Dalcin        os.chdir(pdir)
15399468c80SLisandro Dalcin        return self
15499468c80SLisandro Dalcin    def exit(self):
15599468c80SLisandro Dalcin        sys.argv[:] = self.sys_argv
15699468c80SLisandro Dalcin        os.chdir(self.wdir)
157105e34d4SBarry Smith
15865a891e7SLisandro Dalcinclass cmd_build(_build):
15965a891e7SLisandro Dalcin
160a597b971SLisandro Dalcin    def initialize_options(self):
161a597b971SLisandro Dalcin        _build.initialize_options(self)
162a597b971SLisandro Dalcin        PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
163a597b971SLisandro Dalcin        self.build_base = os.path.join(PETSC_ARCH, 'build-python')
164a597b971SLisandro Dalcin
16565a891e7SLisandro Dalcin    def run(self):
16665a891e7SLisandro Dalcin        _build.run(self)
16799468c80SLisandro Dalcin        ctx = context().enter()
16865a891e7SLisandro Dalcin        try:
16965a891e7SLisandro Dalcin            config(self.dry_run)
17065a891e7SLisandro Dalcin            build(self.dry_run)
17165a891e7SLisandro Dalcin        finally:
17299468c80SLisandro Dalcin            ctx.exit()
17365a891e7SLisandro Dalcin
17465a891e7SLisandro Dalcinclass cmd_install(_install):
17565a891e7SLisandro Dalcin
17641716173SLisandro Dalcin    def initialize_options(self):
17741716173SLisandro Dalcin        _install.initialize_options(self)
17841716173SLisandro Dalcin        self.optimize = 1
17941716173SLisandro Dalcin
18065a891e7SLisandro Dalcin    def run(self):
18165a891e7SLisandro Dalcin        root_dir = self.install_platlib
18265a891e7SLisandro Dalcin        dest_dir = os.path.join(root_dir, 'petsc')
18365a891e7SLisandro Dalcin        bdist_base = self.get_finalized_command('bdist').bdist_base
18465a891e7SLisandro Dalcin        if dest_dir.startswith(bdist_base):
18565a891e7SLisandro Dalcin            prefix = dest_dir[len(bdist_base)+1:]
18665a891e7SLisandro Dalcin            prefix = prefix[prefix.index(os.path.sep):]
18765a891e7SLisandro Dalcin        else:
18865a891e7SLisandro Dalcin            prefix = dest_dir
18965a891e7SLisandro Dalcin        dest_dir = os.path.abspath(dest_dir)
19065a891e7SLisandro Dalcin        prefix   = os.path.abspath(prefix)
19199468c80SLisandro Dalcin        #
19299468c80SLisandro Dalcin        _install.run(self)
19399468c80SLisandro Dalcin        ctx = context().enter()
19465a891e7SLisandro Dalcin        try:
19565a891e7SLisandro Dalcin            install(dest_dir, prefix, self.dry_run)
19665a891e7SLisandro Dalcin        finally:
19799468c80SLisandro Dalcin            ctx.exit()
19865a891e7SLisandro Dalcin
199a32381aeSLisandro Dalcinclass cmd_sdist(_sdist):
200a32381aeSLisandro Dalcin
201a32381aeSLisandro Dalcin    def initialize_options(self):
202a32381aeSLisandro Dalcin        _sdist.initialize_options(self)
203a32381aeSLisandro Dalcin        self.force_manifest = 1
20499468c80SLisandro Dalcin        self.template = os.path.join('config', 'manifest.in')
205a32381aeSLisandro Dalcin
20665a891e7SLisandro Dalcindef version():
2077d04d9c9SLisandro Dalcin    import re
2087d04d9c9SLisandro Dalcin    version_re = {
2097d04d9c9SLisandro Dalcin        'major'  : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"),
2107d04d9c9SLisandro Dalcin        'minor'  : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"),
2117d04d9c9SLisandro Dalcin        'micro'  : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"),
2127d04d9c9SLisandro Dalcin        'patch'  : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"),
2137d04d9c9SLisandro Dalcin        'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"),
2147d04d9c9SLisandro Dalcin        }
2157d04d9c9SLisandro Dalcin    petscversion_h = os.path.join('include','petscversion.h')
2167d04d9c9SLisandro Dalcin    data = open(petscversion_h, 'rt').read()
2177d04d9c9SLisandro Dalcin    major = int(version_re['major'].search(data).groups()[0])
2187d04d9c9SLisandro Dalcin    minor = int(version_re['minor'].search(data).groups()[0])
2197d04d9c9SLisandro Dalcin    micro = int(version_re['micro'].search(data).groups()[0])
2207d04d9c9SLisandro Dalcin    patch = int(version_re['patch'].search(data).groups()[0])
2217d04d9c9SLisandro Dalcin    release = int(version_re['release'].search(data).groups()[0])
2227d04d9c9SLisandro Dalcin    if release:
2237d04d9c9SLisandro Dalcin        v = "%d.%d" % (major, minor)
2247d04d9c9SLisandro Dalcin        if micro > 0:
2257d04d9c9SLisandro Dalcin            v += ".%d" % micro
2267d04d9c9SLisandro Dalcin        if patch > 0:
22761a717f9SLisandro Dalcin            v += ".post%d" % patch
2287d04d9c9SLisandro Dalcin    else:
22961a717f9SLisandro Dalcin        v = "%d.%d.dev%d" % (major, minor+1, 0)
2307d04d9c9SLisandro Dalcin    return v
23159e0f383SLisandro Dalcin
23265a891e7SLisandro Dalcindef tarball():
23350f36069SLisandro Dalcin    VERSION = version()
23450f36069SLisandro Dalcin    if '.dev' in VERSION:
235a32381aeSLisandro Dalcin        return None
23650f36069SLisandro Dalcin    if '.post' not in VERSION:
23750f36069SLisandro Dalcin        VERSION = VERSION + '.post0'
23850f36069SLisandro Dalcin    VERSION = VERSION.replace('.post', '-p')
23950f36069SLisandro Dalcin    return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/'
24050f36069SLisandro Dalcin            'petsc-lite-%s.tar.gz' % VERSION)
24165a891e7SLisandro Dalcin
24265a891e7SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3]
24365a891e7SLisandro Dalcinclassifiers = """
24465a891e7SLisandro DalcinLicense :: Public Domain
24565a891e7SLisandro DalcinOperating System :: POSIX
24665a891e7SLisandro DalcinIntended Audience :: Developers
24765a891e7SLisandro DalcinIntended Audience :: Science/Research
24865a891e7SLisandro DalcinProgramming Language :: C
24965a891e7SLisandro DalcinProgramming Language :: C++
25065a891e7SLisandro DalcinProgramming Language :: Fortran
25165a891e7SLisandro DalcinProgramming Language :: Python
25265a891e7SLisandro DalcinTopic :: Scientific/Engineering
25365a891e7SLisandro DalcinTopic :: Software Development :: Libraries
25465a891e7SLisandro Dalcin"""
25565a891e7SLisandro Dalcin
25665a891e7SLisandro Dalcinbootstrap()
25765a891e7SLisandro Dalcinsetup(name='petsc',
25865a891e7SLisandro Dalcin      version=version(),
25965a891e7SLisandro Dalcin      description=description.pop(0),
26065a891e7SLisandro Dalcin      long_description='\n'.join(description),
26165a891e7SLisandro Dalcin      classifiers= classifiers.split('\n')[1:-1],
26265a891e7SLisandro Dalcin      keywords = ['PETSc', 'MPI'],
26365a891e7SLisandro Dalcin      platforms=['POSIX'],
26465a891e7SLisandro Dalcin      license='PETSc',
26565a891e7SLisandro Dalcin
26665a891e7SLisandro Dalcin      url='http://www.mcs.anl.gov/petsc/',
26765a891e7SLisandro Dalcin      download_url=tarball(),
26865a891e7SLisandro Dalcin
26965a891e7SLisandro Dalcin      author='PETSc Team',
27099468c80SLisandro Dalcin      author_email='petsc-maint@mcs.anl.gov',
27165a891e7SLisandro Dalcin      maintainer='Lisandro Dalcin',
27265a891e7SLisandro Dalcin      maintainer_email='dalcinl@gmail.com',
27365a891e7SLisandro Dalcin
27465a891e7SLisandro Dalcin      packages = ['petsc'],
2759fb7a39fSLisandro Dalcin      package_dir = {'petsc': 'config/pypi'},
27665a891e7SLisandro Dalcin      cmdclass={
27765a891e7SLisandro Dalcin        'build': cmd_build,
27865a891e7SLisandro Dalcin        'install': cmd_install,
279a32381aeSLisandro Dalcin        'sdist': cmd_sdist,
28065a891e7SLisandro Dalcin        },
28159e0f383SLisandro Dalcin      **metadata)
282