xref: /petsc/setup.py (revision ac02ff6d880baf1ac0e85eadef24c4550dea2725)
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.
12922ada92SLisandro Dalcin
13922ada92SLisandro Dalcin.. tip::
14922ada92SLisandro Dalcin
15eb1799d5SSatish Balay  You can also install `petsc-master`_ with::
16922ada92SLisandro Dalcin
17eb1799d5SSatish Balay    $ pip install petsc==master
18922ada92SLisandro Dalcin
19eb1799d5SSatish Balay  .. _petsc-master: https://bitbucket.org/petsc/
20eb1799d5SSatish Balay                 petsc/get/master.tar.gz#egg=petsc-master
21e68ebbecSBarry Smith"""
22e68ebbecSBarry Smith
2365a891e7SLisandro Dalcinimport sys, os
2465a891e7SLisandro Dalcinfrom distutils.core import setup
25cb58ab5bSLisandro Dalcinfrom distutils.util import get_platform, split_quoted
26b88f8b63SLisandro Dalcinfrom distutils.spawn import find_executable
2765a891e7SLisandro Dalcinfrom distutils.command.build import build as _build
2865a891e7SLisandro Dalcinif 'setuptools' in sys.modules:
2965a891e7SLisandro Dalcin    from setuptools.command.install import install as _install
3065a891e7SLisandro Dalcinelse:
3165a891e7SLisandro Dalcin    from distutils.command.install import install as _install
32a32381aeSLisandro Dalcinfrom distutils.command.sdist import sdist as _sdist
3365a891e7SLisandro Dalcinfrom distutils import log
3412c1d45bSMatthew G Knepley
3565a891e7SLisandro Dalcininit_py = """\
36a32381aeSLisandro Dalcin# Author:  PETSc Team
37a597b971SLisandro Dalcin# Contact: petsc-maint@mcs.anl.gov
3865a891e7SLisandro Dalcin
3965a891e7SLisandro Dalcindef get_petsc_dir():
4065a891e7SLisandro Dalcin    import os
4165a891e7SLisandro Dalcin    return os.path.dirname(__file__)
4265a891e7SLisandro Dalcin
43a32381aeSLisandro Dalcindef get_config():
44a32381aeSLisandro Dalcin    conf = {}
459fb7a39fSLisandro Dalcin    conf['PETSC_DIR'] = get_petsc_dir()
46a32381aeSLisandro Dalcin    return conf
4765a891e7SLisandro Dalcin"""
4865a891e7SLisandro Dalcin
4959e0f383SLisandro Dalcinmetadata = {
5059e0f383SLisandro Dalcin    'provides' : ['petsc'],
5159e0f383SLisandro Dalcin    'requires' : [],
5259e0f383SLisandro Dalcin}
5359e0f383SLisandro Dalcin
5465a891e7SLisandro Dalcindef bootstrap():
55cb58ab5bSLisandro Dalcin    # Set PETSC_DIR and PETSC_ARCH
5665a891e7SLisandro Dalcin    PETSC_DIR  = os.path.abspath(os.getcwd())
5765a891e7SLisandro Dalcin    PETSC_ARCH = get_platform() + '-python'
5865a891e7SLisandro Dalcin    os.environ['PETSC_DIR']  = PETSC_DIR
5965a891e7SLisandro Dalcin    os.environ['PETSC_ARCH'] = PETSC_ARCH
6065a891e7SLisandro Dalcin    sys.path.insert(0, os.path.join(PETSC_DIR, 'config'))
6105762b81SDavid A Ham    sys.path.insert(0, os.path.join(PETSC_DIR, 'conf'))
6259e0f383SLisandro Dalcin    # Generate package __init__.py file
639fb7a39fSLisandro Dalcin    from distutils.dir_util import mkpath
649fb7a39fSLisandro Dalcin    pkgdir = os.path.join('config', 'pypi')
650ddf2052SLisandro Dalcin    if not os.path.exists(pkgdir): mkpath(pkgdir)
669fb7a39fSLisandro Dalcin    pkgfile = os.path.join(pkgdir, '__init__.py')
67922ada92SLisandro Dalcin    fh = open(pkgfile, 'wt')
68922ada92SLisandro Dalcin    fh.write(init_py)
69922ada92SLisandro Dalcin    fh.close()
7059e0f383SLisandro Dalcin    # Simple-minded lookup for MPI and mpi4py
7159e0f383SLisandro Dalcin    mpi4py = mpicc = None
7259e0f383SLisandro Dalcin    try:
7359e0f383SLisandro Dalcin        import mpi4py
7459e0f383SLisandro Dalcin        conf = mpi4py.get_config()
7559e0f383SLisandro Dalcin        mpicc = conf.get('mpicc')
7659e0f383SLisandro Dalcin    except ImportError: # mpi4py is not installed
77922ada92SLisandro Dalcin        mpi4py = None
7859e0f383SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
791b095333SLisandro Dalcin    except AttributeError: # mpi4py is too old
8059e0f383SLisandro Dalcin        pass
81922ada92SLisandro Dalcin    if ('setuptools' in sys.modules):
82be96eb59SLisandro Dalcin        metadata['zip_safe'] = False
83922ada92SLisandro Dalcin        if not mpi4py and mpicc:
84922ada92SLisandro Dalcin            metadata['install_requires']= ['mpi4py>=1.2.2']
8565a891e7SLisandro Dalcin
8665a891e7SLisandro Dalcindef config(dry_run=False):
8765a891e7SLisandro Dalcin    log.info('PETSc: configure')
8865a891e7SLisandro Dalcin    options = [
8965a891e7SLisandro Dalcin        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
90cb58ab5bSLisandro Dalcin        '--with-shared-libraries=1',
9111035aebSLisandro Dalcin        '--with-debugging=0',
92922ada92SLisandro Dalcin        '--with-c2html=0', # not needed
93*ac02ff6dSBarry Smith        '--with-sowing=0',
94*ac02ff6dSBarry Smith        '--with-fc=0',
95*ac02ff6dSBarry Smith        '--with-cxx=0',
96922ada92SLisandro Dalcin        #'--with-cmake=0',
9765a891e7SLisandro Dalcin        ]
9859e0f383SLisandro Dalcin    # MPI
9959e0f383SLisandro Dalcin    try:
10059e0f383SLisandro Dalcin        import mpi4py
10159e0f383SLisandro Dalcin        conf = mpi4py.get_config()
10259e0f383SLisandro Dalcin        mpicc  = conf.get('mpicc')
103cb58ab5bSLisandro Dalcin        mpicxx = conf.get('mpicxx')
104cb58ab5bSLisandro Dalcin        mpif90 = conf.get('mpif90')
10559e0f383SLisandro Dalcin    except (ImportError, AttributeError):
10659e0f383SLisandro Dalcin        mpicc  = os.environ.get('MPICC')  or find_executable('mpicc')
107cb58ab5bSLisandro Dalcin        mpicxx = os.environ.get('MPICXX') or find_executable('mpicxx')
108cb58ab5bSLisandro Dalcin        mpif90 = os.environ.get('MPIF90') or find_executable('mpif90')
10959e0f383SLisandro Dalcin    if mpicc:
11059e0f383SLisandro Dalcin        options.append('--with-cc='+mpicc)
111cb58ab5bSLisandro Dalcin        if mpicxx:
112cb58ab5bSLisandro Dalcin            options.append('--with-cxx='+mpicxx)
113cb58ab5bSLisandro Dalcin        if mpif90:
114cb58ab5bSLisandro Dalcin            options.append('--with-fc='+mpif90)
11559e0f383SLisandro Dalcin    else:
11659e0f383SLisandro Dalcin        options.append('--with-mpi=0')
117cb58ab5bSLisandro Dalcin    # Extra configure options
118cb58ab5bSLisandro Dalcin    config_opts = os.environ.get('PETSC_CONFIGURE_OPTIONS', '')
119cb58ab5bSLisandro Dalcin    config_opts = split_quoted(config_opts)
120cb58ab5bSLisandro Dalcin    options.extend(config_opts)
121cb58ab5bSLisandro Dalcin    log.info('configure options:')
122cb58ab5bSLisandro Dalcin    for opt in options:
123cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
12459e0f383SLisandro Dalcin    # Run PETSc configure
125cb58ab5bSLisandro Dalcin    if dry_run: return
126e68ebbecSBarry Smith    import configure
12765a891e7SLisandro Dalcin    configure.petsc_configure(options)
128e68ebbecSBarry Smith    import logger
129e68ebbecSBarry Smith    logger.Logger.defaultLog = None
13012c1d45bSMatthew G Knepley
13165a891e7SLisandro Dalcindef build(dry_run=False):
13265a891e7SLisandro Dalcin    log.info('PETSc: build')
133367c215cSLisandro Dalcin    # Run PETSc build
134cb58ab5bSLisandro Dalcin    if dry_run: return
135367c215cSLisandro Dalcin    use_builder_py = False
136367c215cSLisandro Dalcin    if use_builder_py:
137e68ebbecSBarry Smith        import builder
138e68ebbecSBarry Smith        builder.PETScMaker().run()
139105e34d4SBarry Smith        import logger
140105e34d4SBarry Smith        logger.Logger.defaultLog = None
141367c215cSLisandro Dalcin    else:
142367c215cSLisandro Dalcin        make = find_executable('make')
143367c215cSLisandro Dalcin        status = os.system(" ".join(
144367c215cSLisandro Dalcin                [make, 'all']
145367c215cSLisandro Dalcin                ))
146367c215cSLisandro Dalcin        if status != 0: raise RuntimeError(status)
147e68ebbecSBarry Smith
14865a891e7SLisandro Dalcindef install(dest_dir, prefix=None, dry_run=False):
14965a891e7SLisandro Dalcin    log.info('PETSc: install')
15065a891e7SLisandro Dalcin    if prefix is None:
15165a891e7SLisandro Dalcin        prefix = dest_dir
15265a891e7SLisandro Dalcin    options = [
15365a891e7SLisandro Dalcin        '--destDir=' + dest_dir,
1544dee622bSLisandro Dalcin        '--prefix='  + prefix,
15565a891e7SLisandro Dalcin        ]
156cb58ab5bSLisandro Dalcin    log.info('install options:')
157cb58ab5bSLisandro Dalcin    for opt in options:
158cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
15959e0f383SLisandro Dalcin    # Run PETSc installer
160cb58ab5bSLisandro Dalcin    if dry_run: return
161367c215cSLisandro Dalcin    use_install_py = True
162367c215cSLisandro Dalcin    if use_install_py:
163105e34d4SBarry Smith        import install
16465a891e7SLisandro Dalcin        install.Installer(options).run()
16565a891e7SLisandro Dalcin        import logger
16665a891e7SLisandro Dalcin        logger.Logger.defaultLog = None
167367c215cSLisandro Dalcin    else:
168367c215cSLisandro Dalcin        make = find_executable('make')
169367c215cSLisandro Dalcin        status = os.system(" ".join(
170367c215cSLisandro Dalcin                [make, 'install', 'DESTDIR='+dest_dir]
171367c215cSLisandro Dalcin                ))
172367c215cSLisandro Dalcin        if status != 0: raise RuntimeError(status)
17399468c80SLisandro Dalcin
17499468c80SLisandro Dalcinclass context:
17599468c80SLisandro Dalcin    def __init__(self):
17699468c80SLisandro Dalcin        self.sys_argv = sys.argv[:]
17799468c80SLisandro Dalcin        self.wdir = os.getcwd()
17899468c80SLisandro Dalcin    def enter(self):
17999468c80SLisandro Dalcin        del sys.argv[1:]
18099468c80SLisandro Dalcin        pdir = os.environ['PETSC_DIR']
18199468c80SLisandro Dalcin        os.chdir(pdir)
18299468c80SLisandro Dalcin        return self
18399468c80SLisandro Dalcin    def exit(self):
18499468c80SLisandro Dalcin        sys.argv[:] = self.sys_argv
18599468c80SLisandro Dalcin        os.chdir(self.wdir)
186105e34d4SBarry Smith
18765a891e7SLisandro Dalcinclass cmd_build(_build):
18865a891e7SLisandro Dalcin
189a597b971SLisandro Dalcin    def initialize_options(self):
190a597b971SLisandro Dalcin        _build.initialize_options(self)
191a597b971SLisandro Dalcin        PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
192a597b971SLisandro Dalcin        self.build_base = os.path.join(PETSC_ARCH, 'build-python')
193a597b971SLisandro Dalcin
19465a891e7SLisandro Dalcin    def run(self):
19565a891e7SLisandro Dalcin        _build.run(self)
19699468c80SLisandro Dalcin        ctx = context().enter()
19765a891e7SLisandro Dalcin        try:
19865a891e7SLisandro Dalcin            config(self.dry_run)
19965a891e7SLisandro Dalcin            build(self.dry_run)
20065a891e7SLisandro Dalcin        finally:
20199468c80SLisandro Dalcin            ctx.exit()
20265a891e7SLisandro Dalcin
20365a891e7SLisandro Dalcinclass cmd_install(_install):
20465a891e7SLisandro Dalcin
20541716173SLisandro Dalcin    def initialize_options(self):
20641716173SLisandro Dalcin        _install.initialize_options(self)
20741716173SLisandro Dalcin        self.optimize = 1
20841716173SLisandro Dalcin
20965a891e7SLisandro Dalcin    def run(self):
21065a891e7SLisandro Dalcin        root_dir = self.install_platlib
21165a891e7SLisandro Dalcin        dest_dir = os.path.join(root_dir, 'petsc')
21265a891e7SLisandro Dalcin        bdist_base = self.get_finalized_command('bdist').bdist_base
21365a891e7SLisandro Dalcin        if dest_dir.startswith(bdist_base):
21465a891e7SLisandro Dalcin            prefix = dest_dir[len(bdist_base)+1:]
21565a891e7SLisandro Dalcin            prefix = prefix[prefix.index(os.path.sep):]
21665a891e7SLisandro Dalcin        else:
21765a891e7SLisandro Dalcin            prefix = dest_dir
21865a891e7SLisandro Dalcin        dest_dir = os.path.abspath(dest_dir)
21965a891e7SLisandro Dalcin        prefix   = os.path.abspath(prefix)
22099468c80SLisandro Dalcin        #
22199468c80SLisandro Dalcin        _install.run(self)
22299468c80SLisandro Dalcin        ctx = context().enter()
22365a891e7SLisandro Dalcin        try:
22465a891e7SLisandro Dalcin            install(dest_dir, prefix, self.dry_run)
22565a891e7SLisandro Dalcin        finally:
22699468c80SLisandro Dalcin            ctx.exit()
22765a891e7SLisandro Dalcin
228a32381aeSLisandro Dalcinclass cmd_sdist(_sdist):
229a32381aeSLisandro Dalcin
230a32381aeSLisandro Dalcin    def initialize_options(self):
231a32381aeSLisandro Dalcin        _sdist.initialize_options(self)
232a32381aeSLisandro Dalcin        self.force_manifest = 1
23399468c80SLisandro Dalcin        self.template = os.path.join('config', 'manifest.in')
234a32381aeSLisandro Dalcin
23565a891e7SLisandro Dalcindef version():
2367d04d9c9SLisandro Dalcin    import re
2377d04d9c9SLisandro Dalcin    version_re = {
2387d04d9c9SLisandro Dalcin        'major'  : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"),
2397d04d9c9SLisandro Dalcin        'minor'  : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"),
2407d04d9c9SLisandro Dalcin        'micro'  : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"),
2417d04d9c9SLisandro Dalcin        'patch'  : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"),
2427d04d9c9SLisandro Dalcin        'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"),
2437d04d9c9SLisandro Dalcin        }
2447d04d9c9SLisandro Dalcin    petscversion_h = os.path.join('include','petscversion.h')
2457d04d9c9SLisandro Dalcin    data = open(petscversion_h, 'rt').read()
2467d04d9c9SLisandro Dalcin    major = int(version_re['major'].search(data).groups()[0])
2477d04d9c9SLisandro Dalcin    minor = int(version_re['minor'].search(data).groups()[0])
2487d04d9c9SLisandro Dalcin    micro = int(version_re['micro'].search(data).groups()[0])
2497d04d9c9SLisandro Dalcin    patch = int(version_re['patch'].search(data).groups()[0])
2507d04d9c9SLisandro Dalcin    release = int(version_re['release'].search(data).groups()[0])
2517d04d9c9SLisandro Dalcin    if release:
2527d04d9c9SLisandro Dalcin        v = "%d.%d" % (major, minor)
2537d04d9c9SLisandro Dalcin        if micro > 0:
2547d04d9c9SLisandro Dalcin            v += ".%d" % micro
255247a1238SLisandro Dalcin        #if patch > 0:
256247a1238SLisandro Dalcin        #    v += ".post%d" % patch
2577d04d9c9SLisandro Dalcin    else:
25861a717f9SLisandro Dalcin        v = "%d.%d.dev%d" % (major, minor+1, 0)
2597d04d9c9SLisandro Dalcin    return v
26059e0f383SLisandro Dalcin
26165a891e7SLisandro Dalcindef tarball():
26250f36069SLisandro Dalcin    VERSION = version()
26350f36069SLisandro Dalcin    if '.dev' in VERSION:
264a32381aeSLisandro Dalcin        return None
2657d562c6eSLisandro Dalcin    bits = VERSION.split('.')
2667d562c6eSLisandro Dalcin    if len(bits) == 2: bits.append('0')
267247a1238SLisandro Dalcin    PETSC_VERSION = '.'.join(bits[:3])
26850f36069SLisandro Dalcin    return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/'
269a9157d91SLisandro Dalcin            'petsc-lite-%s.tar.gz#egg=petsc-%s' % (PETSC_VERSION, VERSION))
27065a891e7SLisandro Dalcin
27165a891e7SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3]
27265a891e7SLisandro Dalcinclassifiers = """
27365a891e7SLisandro DalcinLicense :: Public Domain
27465a891e7SLisandro DalcinOperating System :: POSIX
27565a891e7SLisandro DalcinIntended Audience :: Developers
27665a891e7SLisandro DalcinIntended Audience :: Science/Research
27765a891e7SLisandro DalcinProgramming Language :: C
27865a891e7SLisandro DalcinProgramming Language :: C++
27965a891e7SLisandro DalcinProgramming Language :: Fortran
28065a891e7SLisandro DalcinProgramming Language :: Python
28165a891e7SLisandro DalcinTopic :: Scientific/Engineering
28265a891e7SLisandro DalcinTopic :: Software Development :: Libraries
28365a891e7SLisandro Dalcin"""
28465a891e7SLisandro Dalcin
28565a891e7SLisandro Dalcinbootstrap()
28665a891e7SLisandro Dalcinsetup(name='petsc',
28765a891e7SLisandro Dalcin      version=version(),
28865a891e7SLisandro Dalcin      description=description.pop(0),
28965a891e7SLisandro Dalcin      long_description='\n'.join(description),
29065a891e7SLisandro Dalcin      classifiers= classifiers.split('\n')[1:-1],
29165a891e7SLisandro Dalcin      keywords = ['PETSc', 'MPI'],
29265a891e7SLisandro Dalcin      platforms=['POSIX'],
29365a891e7SLisandro Dalcin      license='PETSc',
29465a891e7SLisandro Dalcin
29565a891e7SLisandro Dalcin      url='http://www.mcs.anl.gov/petsc/',
29665a891e7SLisandro Dalcin      download_url=tarball(),
29765a891e7SLisandro Dalcin
29865a891e7SLisandro Dalcin      author='PETSc Team',
29999468c80SLisandro Dalcin      author_email='petsc-maint@mcs.anl.gov',
30065a891e7SLisandro Dalcin      maintainer='Lisandro Dalcin',
30165a891e7SLisandro Dalcin      maintainer_email='dalcinl@gmail.com',
30265a891e7SLisandro Dalcin
30365a891e7SLisandro Dalcin      packages = ['petsc'],
3049fb7a39fSLisandro Dalcin      package_dir = {'petsc': 'config/pypi'},
30565a891e7SLisandro Dalcin      cmdclass={
30665a891e7SLisandro Dalcin        'build': cmd_build,
30765a891e7SLisandro Dalcin        'install': cmd_install,
308a32381aeSLisandro Dalcin        'sdist': cmd_sdist,
30965a891e7SLisandro Dalcin        },
31059e0f383SLisandro Dalcin      **metadata)
311