xref: /petsc/setup.py (revision ca62002a6d0de4345da451d0c81de3890471e29a)
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
17*ca62002aSBarry Smith    $ pip install https://bitbucket.org/petsc/petsc/get/master.tar.gz#egg=petsc-master
18922ada92SLisandro Dalcin
19*ca62002aSBarry Smith  Then install petsc4py with
20*ca62002aSBarry Smith
21*ca62002aSBarry Smith    $ pip install https://bitbucket.org/petsc/petsc4py/get/master.tar.gz#egg=petsc4py-master
22*ca62002aSBarry Smith
23e68ebbecSBarry Smith"""
24e68ebbecSBarry Smith
2565a891e7SLisandro Dalcinimport sys, os
2665a891e7SLisandro Dalcinfrom distutils.core import setup
27cb58ab5bSLisandro Dalcinfrom distutils.util import get_platform, split_quoted
28b88f8b63SLisandro Dalcinfrom distutils.spawn import find_executable
2965a891e7SLisandro Dalcinfrom distutils.command.build import build as _build
3065a891e7SLisandro Dalcinif 'setuptools' in sys.modules:
3165a891e7SLisandro Dalcin    from setuptools.command.install import install as _install
3265a891e7SLisandro Dalcinelse:
3365a891e7SLisandro Dalcin    from distutils.command.install import install as _install
34a32381aeSLisandro Dalcinfrom distutils.command.sdist import sdist as _sdist
3565a891e7SLisandro Dalcinfrom distutils import log
3612c1d45bSMatthew G Knepley
3765a891e7SLisandro Dalcininit_py = """\
38a32381aeSLisandro Dalcin# Author:  PETSc Team
39a597b971SLisandro Dalcin# Contact: petsc-maint@mcs.anl.gov
4065a891e7SLisandro Dalcin
4165a891e7SLisandro Dalcindef get_petsc_dir():
4265a891e7SLisandro Dalcin    import os
4365a891e7SLisandro Dalcin    return os.path.dirname(__file__)
4465a891e7SLisandro Dalcin
45a32381aeSLisandro Dalcindef get_config():
46a32381aeSLisandro Dalcin    conf = {}
479fb7a39fSLisandro Dalcin    conf['PETSC_DIR'] = get_petsc_dir()
48a32381aeSLisandro Dalcin    return conf
4965a891e7SLisandro Dalcin"""
5065a891e7SLisandro Dalcin
5159e0f383SLisandro Dalcinmetadata = {
5259e0f383SLisandro Dalcin    'provides' : ['petsc'],
5359e0f383SLisandro Dalcin    'requires' : [],
5459e0f383SLisandro Dalcin}
5559e0f383SLisandro Dalcin
5665a891e7SLisandro Dalcindef bootstrap():
57cb58ab5bSLisandro Dalcin    # Set PETSC_DIR and PETSC_ARCH
5865a891e7SLisandro Dalcin    PETSC_DIR  = os.path.abspath(os.getcwd())
5965a891e7SLisandro Dalcin    PETSC_ARCH = get_platform() + '-python'
6065a891e7SLisandro Dalcin    os.environ['PETSC_DIR']  = PETSC_DIR
6165a891e7SLisandro Dalcin    os.environ['PETSC_ARCH'] = PETSC_ARCH
6265a891e7SLisandro Dalcin    sys.path.insert(0, os.path.join(PETSC_DIR, 'config'))
6305762b81SDavid A Ham    sys.path.insert(0, os.path.join(PETSC_DIR, 'conf'))
6459e0f383SLisandro Dalcin    # Generate package __init__.py file
659fb7a39fSLisandro Dalcin    from distutils.dir_util import mkpath
669fb7a39fSLisandro Dalcin    pkgdir = os.path.join('config', 'pypi')
670ddf2052SLisandro Dalcin    if not os.path.exists(pkgdir): mkpath(pkgdir)
689fb7a39fSLisandro Dalcin    pkgfile = os.path.join(pkgdir, '__init__.py')
69922ada92SLisandro Dalcin    fh = open(pkgfile, 'wt')
70922ada92SLisandro Dalcin    fh.write(init_py)
71922ada92SLisandro Dalcin    fh.close()
7259e0f383SLisandro Dalcin    # Simple-minded lookup for MPI and mpi4py
7359e0f383SLisandro Dalcin    mpi4py = mpicc = None
7459e0f383SLisandro Dalcin    try:
7559e0f383SLisandro Dalcin        import mpi4py
7659e0f383SLisandro Dalcin        conf = mpi4py.get_config()
7759e0f383SLisandro Dalcin        mpicc = conf.get('mpicc')
7859e0f383SLisandro Dalcin    except ImportError: # mpi4py is not installed
79922ada92SLisandro Dalcin        mpi4py = None
8059e0f383SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
811b095333SLisandro Dalcin    except AttributeError: # mpi4py is too old
8259e0f383SLisandro Dalcin        pass
83922ada92SLisandro Dalcin    if ('setuptools' in sys.modules):
84be96eb59SLisandro Dalcin        metadata['zip_safe'] = False
85922ada92SLisandro Dalcin        if not mpi4py and mpicc:
86922ada92SLisandro Dalcin            metadata['install_requires']= ['mpi4py>=1.2.2']
8765a891e7SLisandro Dalcin
8865a891e7SLisandro Dalcindef config(dry_run=False):
8965a891e7SLisandro Dalcin    log.info('PETSc: configure')
9065a891e7SLisandro Dalcin    options = [
9165a891e7SLisandro Dalcin        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
92cb58ab5bSLisandro Dalcin        '--with-shared-libraries=1',
9311035aebSLisandro Dalcin        '--with-debugging=0',
94922ada92SLisandro Dalcin        '--with-c2html=0', # not needed
95ac02ff6dSBarry Smith        '--with-sowing=0',
96ac02ff6dSBarry Smith        '--with-fc=0',
97ac02ff6dSBarry Smith        '--with-cxx=0',
98922ada92SLisandro Dalcin        #'--with-cmake=0',
9965a891e7SLisandro Dalcin        ]
10059e0f383SLisandro Dalcin    # MPI
10159e0f383SLisandro Dalcin    try:
10259e0f383SLisandro Dalcin        import mpi4py
10359e0f383SLisandro Dalcin        conf = mpi4py.get_config()
10459e0f383SLisandro Dalcin        mpicc  = conf.get('mpicc')
105cb58ab5bSLisandro Dalcin        mpicxx = conf.get('mpicxx')
106cb58ab5bSLisandro Dalcin        mpif90 = conf.get('mpif90')
10759e0f383SLisandro Dalcin    except (ImportError, AttributeError):
10859e0f383SLisandro Dalcin        mpicc  = os.environ.get('MPICC')  or find_executable('mpicc')
109cb58ab5bSLisandro Dalcin        mpicxx = os.environ.get('MPICXX') or find_executable('mpicxx')
110cb58ab5bSLisandro Dalcin        mpif90 = os.environ.get('MPIF90') or find_executable('mpif90')
11159e0f383SLisandro Dalcin    if mpicc:
11259e0f383SLisandro Dalcin        options.append('--with-cc='+mpicc)
113cb58ab5bSLisandro Dalcin        if mpicxx:
114cb58ab5bSLisandro Dalcin            options.append('--with-cxx='+mpicxx)
115cb58ab5bSLisandro Dalcin        if mpif90:
116cb58ab5bSLisandro Dalcin            options.append('--with-fc='+mpif90)
11759e0f383SLisandro Dalcin    else:
11859e0f383SLisandro Dalcin        options.append('--with-mpi=0')
119cb58ab5bSLisandro Dalcin    # Extra configure options
120cb58ab5bSLisandro Dalcin    config_opts = os.environ.get('PETSC_CONFIGURE_OPTIONS', '')
121cb58ab5bSLisandro Dalcin    config_opts = split_quoted(config_opts)
122cb58ab5bSLisandro Dalcin    options.extend(config_opts)
123cb58ab5bSLisandro Dalcin    log.info('configure options:')
124cb58ab5bSLisandro Dalcin    for opt in options:
125cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
12659e0f383SLisandro Dalcin    # Run PETSc configure
127cb58ab5bSLisandro Dalcin    if dry_run: return
128e68ebbecSBarry Smith    import configure
12965a891e7SLisandro Dalcin    configure.petsc_configure(options)
130e68ebbecSBarry Smith    import logger
131e68ebbecSBarry Smith    logger.Logger.defaultLog = None
13212c1d45bSMatthew G Knepley
13365a891e7SLisandro Dalcindef build(dry_run=False):
13465a891e7SLisandro Dalcin    log.info('PETSc: build')
135367c215cSLisandro Dalcin    # Run PETSc build
136cb58ab5bSLisandro Dalcin    if dry_run: return
137367c215cSLisandro Dalcin    use_builder_py = False
138367c215cSLisandro Dalcin    if use_builder_py:
139e68ebbecSBarry Smith        import builder
140e68ebbecSBarry Smith        builder.PETScMaker().run()
141105e34d4SBarry Smith        import logger
142105e34d4SBarry Smith        logger.Logger.defaultLog = None
143367c215cSLisandro Dalcin    else:
144367c215cSLisandro Dalcin        make = find_executable('make')
145367c215cSLisandro Dalcin        status = os.system(" ".join(
146367c215cSLisandro Dalcin                [make, 'all']
147367c215cSLisandro Dalcin                ))
148367c215cSLisandro Dalcin        if status != 0: raise RuntimeError(status)
149e68ebbecSBarry Smith
15065a891e7SLisandro Dalcindef install(dest_dir, prefix=None, dry_run=False):
15165a891e7SLisandro Dalcin    log.info('PETSc: install')
15265a891e7SLisandro Dalcin    if prefix is None:
15365a891e7SLisandro Dalcin        prefix = dest_dir
15465a891e7SLisandro Dalcin    options = [
15565a891e7SLisandro Dalcin        '--destDir=' + dest_dir,
1564dee622bSLisandro Dalcin        '--prefix='  + prefix,
15765a891e7SLisandro Dalcin        ]
158cb58ab5bSLisandro Dalcin    log.info('install options:')
159cb58ab5bSLisandro Dalcin    for opt in options:
160cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
16159e0f383SLisandro Dalcin    # Run PETSc installer
162cb58ab5bSLisandro Dalcin    if dry_run: return
163367c215cSLisandro Dalcin    use_install_py = True
164367c215cSLisandro Dalcin    if use_install_py:
165105e34d4SBarry Smith        import install
16665a891e7SLisandro Dalcin        install.Installer(options).run()
16765a891e7SLisandro Dalcin        import logger
16865a891e7SLisandro Dalcin        logger.Logger.defaultLog = None
169367c215cSLisandro Dalcin    else:
170367c215cSLisandro Dalcin        make = find_executable('make')
171367c215cSLisandro Dalcin        status = os.system(" ".join(
172367c215cSLisandro Dalcin                [make, 'install', 'DESTDIR='+dest_dir]
173367c215cSLisandro Dalcin                ))
174367c215cSLisandro Dalcin        if status != 0: raise RuntimeError(status)
17599468c80SLisandro Dalcin
17699468c80SLisandro Dalcinclass context:
17799468c80SLisandro Dalcin    def __init__(self):
17899468c80SLisandro Dalcin        self.sys_argv = sys.argv[:]
17999468c80SLisandro Dalcin        self.wdir = os.getcwd()
18099468c80SLisandro Dalcin    def enter(self):
18199468c80SLisandro Dalcin        del sys.argv[1:]
18299468c80SLisandro Dalcin        pdir = os.environ['PETSC_DIR']
18399468c80SLisandro Dalcin        os.chdir(pdir)
18499468c80SLisandro Dalcin        return self
18599468c80SLisandro Dalcin    def exit(self):
18699468c80SLisandro Dalcin        sys.argv[:] = self.sys_argv
18799468c80SLisandro Dalcin        os.chdir(self.wdir)
188105e34d4SBarry Smith
18965a891e7SLisandro Dalcinclass cmd_build(_build):
19065a891e7SLisandro Dalcin
191a597b971SLisandro Dalcin    def initialize_options(self):
192a597b971SLisandro Dalcin        _build.initialize_options(self)
193a597b971SLisandro Dalcin        PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
194a597b971SLisandro Dalcin        self.build_base = os.path.join(PETSC_ARCH, 'build-python')
195a597b971SLisandro Dalcin
19665a891e7SLisandro Dalcin    def run(self):
19765a891e7SLisandro Dalcin        _build.run(self)
19899468c80SLisandro Dalcin        ctx = context().enter()
19965a891e7SLisandro Dalcin        try:
20065a891e7SLisandro Dalcin            config(self.dry_run)
20165a891e7SLisandro Dalcin            build(self.dry_run)
20265a891e7SLisandro Dalcin        finally:
20399468c80SLisandro Dalcin            ctx.exit()
20465a891e7SLisandro Dalcin
20565a891e7SLisandro Dalcinclass cmd_install(_install):
20665a891e7SLisandro Dalcin
20741716173SLisandro Dalcin    def initialize_options(self):
20841716173SLisandro Dalcin        _install.initialize_options(self)
20941716173SLisandro Dalcin        self.optimize = 1
21041716173SLisandro Dalcin
21165a891e7SLisandro Dalcin    def run(self):
21265a891e7SLisandro Dalcin        root_dir = self.install_platlib
21365a891e7SLisandro Dalcin        dest_dir = os.path.join(root_dir, 'petsc')
21465a891e7SLisandro Dalcin        bdist_base = self.get_finalized_command('bdist').bdist_base
21565a891e7SLisandro Dalcin        if dest_dir.startswith(bdist_base):
21665a891e7SLisandro Dalcin            prefix = dest_dir[len(bdist_base)+1:]
21765a891e7SLisandro Dalcin            prefix = prefix[prefix.index(os.path.sep):]
21865a891e7SLisandro Dalcin        else:
21965a891e7SLisandro Dalcin            prefix = dest_dir
22065a891e7SLisandro Dalcin        dest_dir = os.path.abspath(dest_dir)
22165a891e7SLisandro Dalcin        prefix   = os.path.abspath(prefix)
22299468c80SLisandro Dalcin        #
22399468c80SLisandro Dalcin        _install.run(self)
22499468c80SLisandro Dalcin        ctx = context().enter()
22565a891e7SLisandro Dalcin        try:
22665a891e7SLisandro Dalcin            install(dest_dir, prefix, self.dry_run)
22765a891e7SLisandro Dalcin        finally:
22899468c80SLisandro Dalcin            ctx.exit()
22965a891e7SLisandro Dalcin
230a32381aeSLisandro Dalcinclass cmd_sdist(_sdist):
231a32381aeSLisandro Dalcin
232a32381aeSLisandro Dalcin    def initialize_options(self):
233a32381aeSLisandro Dalcin        _sdist.initialize_options(self)
234a32381aeSLisandro Dalcin        self.force_manifest = 1
23599468c80SLisandro Dalcin        self.template = os.path.join('config', 'manifest.in')
236a32381aeSLisandro Dalcin
23765a891e7SLisandro Dalcindef version():
2387d04d9c9SLisandro Dalcin    import re
2397d04d9c9SLisandro Dalcin    version_re = {
2407d04d9c9SLisandro Dalcin        'major'  : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"),
2417d04d9c9SLisandro Dalcin        'minor'  : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"),
2427d04d9c9SLisandro Dalcin        'micro'  : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"),
2437d04d9c9SLisandro Dalcin        'patch'  : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"),
2447d04d9c9SLisandro Dalcin        'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"),
2457d04d9c9SLisandro Dalcin        }
2467d04d9c9SLisandro Dalcin    petscversion_h = os.path.join('include','petscversion.h')
2477d04d9c9SLisandro Dalcin    data = open(petscversion_h, 'rt').read()
2487d04d9c9SLisandro Dalcin    major = int(version_re['major'].search(data).groups()[0])
2497d04d9c9SLisandro Dalcin    minor = int(version_re['minor'].search(data).groups()[0])
2507d04d9c9SLisandro Dalcin    micro = int(version_re['micro'].search(data).groups()[0])
2517d04d9c9SLisandro Dalcin    patch = int(version_re['patch'].search(data).groups()[0])
2527d04d9c9SLisandro Dalcin    release = int(version_re['release'].search(data).groups()[0])
2537d04d9c9SLisandro Dalcin    if release:
2547d04d9c9SLisandro Dalcin        v = "%d.%d" % (major, minor)
2557d04d9c9SLisandro Dalcin        if micro > 0:
2567d04d9c9SLisandro Dalcin            v += ".%d" % micro
257247a1238SLisandro Dalcin        #if patch > 0:
258247a1238SLisandro Dalcin        #    v += ".post%d" % patch
2597d04d9c9SLisandro Dalcin    else:
26061a717f9SLisandro Dalcin        v = "%d.%d.dev%d" % (major, minor+1, 0)
2617d04d9c9SLisandro Dalcin    return v
26259e0f383SLisandro Dalcin
26365a891e7SLisandro Dalcindef tarball():
26450f36069SLisandro Dalcin    VERSION = version()
26550f36069SLisandro Dalcin    if '.dev' in VERSION:
266a32381aeSLisandro Dalcin        return None
2677d562c6eSLisandro Dalcin    bits = VERSION.split('.')
2687d562c6eSLisandro Dalcin    if len(bits) == 2: bits.append('0')
269247a1238SLisandro Dalcin    PETSC_VERSION = '.'.join(bits[:3])
27050f36069SLisandro Dalcin    return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/'
271a9157d91SLisandro Dalcin            'petsc-lite-%s.tar.gz#egg=petsc-%s' % (PETSC_VERSION, VERSION))
27265a891e7SLisandro Dalcin
27365a891e7SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3]
27465a891e7SLisandro Dalcinclassifiers = """
27565a891e7SLisandro DalcinLicense :: Public Domain
27665a891e7SLisandro DalcinOperating System :: POSIX
27765a891e7SLisandro DalcinIntended Audience :: Developers
27865a891e7SLisandro DalcinIntended Audience :: Science/Research
27965a891e7SLisandro DalcinProgramming Language :: C
28065a891e7SLisandro DalcinProgramming Language :: C++
28165a891e7SLisandro DalcinProgramming Language :: Fortran
28265a891e7SLisandro DalcinProgramming Language :: Python
28365a891e7SLisandro DalcinTopic :: Scientific/Engineering
28465a891e7SLisandro DalcinTopic :: Software Development :: Libraries
28565a891e7SLisandro Dalcin"""
28665a891e7SLisandro Dalcin
28765a891e7SLisandro Dalcinbootstrap()
28865a891e7SLisandro Dalcinsetup(name='petsc',
28965a891e7SLisandro Dalcin      version=version(),
29065a891e7SLisandro Dalcin      description=description.pop(0),
29165a891e7SLisandro Dalcin      long_description='\n'.join(description),
29265a891e7SLisandro Dalcin      classifiers= classifiers.split('\n')[1:-1],
29365a891e7SLisandro Dalcin      keywords = ['PETSc', 'MPI'],
29465a891e7SLisandro Dalcin      platforms=['POSIX'],
29565a891e7SLisandro Dalcin      license='PETSc',
29665a891e7SLisandro Dalcin
29765a891e7SLisandro Dalcin      url='http://www.mcs.anl.gov/petsc/',
29865a891e7SLisandro Dalcin      download_url=tarball(),
29965a891e7SLisandro Dalcin
30065a891e7SLisandro Dalcin      author='PETSc Team',
30199468c80SLisandro Dalcin      author_email='petsc-maint@mcs.anl.gov',
30265a891e7SLisandro Dalcin      maintainer='Lisandro Dalcin',
30365a891e7SLisandro Dalcin      maintainer_email='dalcinl@gmail.com',
30465a891e7SLisandro Dalcin
30565a891e7SLisandro Dalcin      packages = ['petsc'],
3069fb7a39fSLisandro Dalcin      package_dir = {'petsc': 'config/pypi'},
30765a891e7SLisandro Dalcin      cmdclass={
30865a891e7SLisandro Dalcin        'build': cmd_build,
30965a891e7SLisandro Dalcin        'install': cmd_install,
310a32381aeSLisandro Dalcin        'sdist': cmd_sdist,
31165a891e7SLisandro Dalcin        },
31259e0f383SLisandro Dalcin      **metadata)
313