xref: /petsc/setup.py (revision 1b0953335cf15d88cf752e3df40240fa6bfd0d76)
1#!/usr/bin/env python
2
3"""
4PETSc: Portable, Extensible Toolkit for Scientific Computation
5==============================================================
6
7The Portable, Extensible Toolkit for Scientific Computation (PETSc),
8is a suite of data structures and routines for the scalable (parallel)
9solution of scientific applications modeled by partial differential
10equations. It employs the Message Passing Interface (MPI) standard for
11all message-passing communication.
12"""
13
14import sys, os
15from distutils.core import setup
16from distutils.util import get_platform
17from distutils.spawn import find_executable
18from distutils.command.build import build as _build
19if 'setuptools' in sys.modules:
20    from setuptools.command.install import install as _install
21else:
22    from distutils.command.install import install as _install
23from distutils.command.sdist import sdist as _sdist
24from distutils import log
25
26PETSC_DIR  = None
27PETSC_ARCH = None
28
29init_py = """\
30# Author:  PETSc Team
31# Contact: petsc-users@mcs.anl.gov
32
33def get_petsc_dir():
34    import os
35    return os.path.dirname(__file__)
36
37def get_petsc_arch():
38    return ''
39
40def get_config():
41    conf = {}
42    conf['petsc_dir'] = get_petsc_dir()
43    return conf
44"""
45
46metadata = {
47    'provides' : ['petsc'],
48    'requires' : [],
49}
50
51def bootstrap():
52    # Set PETSC_DIR and PETSC_ARCH,
53    global PETSC_DIR, PETSC_ARCH
54    PETSC_DIR  = os.path.abspath(os.getcwd())
55    PETSC_ARCH = get_platform() + '-python'
56    os.environ['PETSC_DIR']  = PETSC_DIR
57    os.environ['PETSC_ARCH'] = PETSC_ARCH
58    sys.path.insert(0, os.path.join(PETSC_DIR, 'config'))
59    # Generate package __init__.py file
60    try:
61        if not os.path.exists(PETSC_ARCH):
62            os.mkdir(PETSC_ARCH)
63        pkgfile = os.path.join(PETSC_ARCH, '__init__.py')
64        if not os.path.exists(pkgfile):
65            open(pkgfile, 'wt').write(init_py)
66    except:
67        pass
68    # Simple-minded lookup for MPI and mpi4py
69    mpi4py = mpicc = None
70    try:
71        import mpi4py
72        conf = mpi4py.get_config()
73        mpicc = conf.get('mpicc')
74    except ImportError: # mpi4py is not installed
75        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
76    except AttributeError: # mpi4py is too old
77        pass
78    if not mpi4py and mpicc:
79        if (('distribute' in sys.modules) or
80            ('setuptools' in sys.modules)):
81            metadata['install_requires']= ['mpi4py>=1.2.2']
82
83def config(dry_run=False):
84    log.info('PETSc: configure')
85    if dry_run: return
86    options = [
87        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
88        '--with-shared-libraries',
89        '--with-cmake=0', # not needed
90        ]
91    # MPI
92    try:
93        import mpi4py
94        conf = mpi4py.get_config()
95        mpicc = conf.get('mpicc')
96    except (ImportError, AttributeError):
97        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
98    if mpicc:
99        options.append('--with-cc='+mpicc)
100    else:
101        options.append('--with-mpi=0')
102    options.extend([
103        '--with-fc=0',    # XXX mpif90?
104        '--with-cxx=0',   # XXX mpicxx?
105        ])
106    # Run PETSc configure
107    import configure
108    configure.petsc_configure(options)
109    import logger
110    logger.Logger.defaultLog = None
111
112def build(dry_run=False):
113    log.info('PETSc: build')
114    if dry_run: return
115    # Run PETSc builder
116    import builder
117    builder.PETScMaker().run()
118    import logger
119    logger.Logger.defaultLog = None
120
121def install(dest_dir, prefix=None, dry_run=False):
122    log.info('PETSc: install')
123    if dry_run: return
124    if prefix is None:
125        prefix = dest_dir
126    options = [
127        '--destDir=' + dest_dir,
128        '--prefix='  + prefix
129        ]
130    # Run PETSc installer
131    import install
132    install.Installer(options).run()
133    import logger
134    logger.Logger.defaultLog = None
135    # temporary hack - delete log files created by BuildSystem
136    delfiles=['RDict.db','RDict.log',
137              'build.log','default.log',
138              'build.log.bkp','default.log.bkp']
139    for delfile in delfiles:
140        try:
141            if (os.path.exists(delfile) and
142                os.stat(delfile).st_uid==0):
143                os.remove(delfile)
144        except:
145            pass
146
147class cmd_build(_build):
148
149    def finalize_options(self):
150        if self.build_base is None:
151            self.build_base= 'build'
152        self.build_base = os.path.join(
153            os.environ['PETSC_ARCH'], self.build_base)
154        _build.finalize_options(self)
155
156    def run(self):
157        _build.run(self)
158        wdir = os.getcwd()
159        pdir = os.environ['PETSC_DIR']
160        try:
161            os.chdir(pdir)
162            config(self.dry_run)
163            build(self.dry_run)
164        finally:
165            os.chdir(wdir)
166
167class cmd_install(_install):
168
169    def run(self):
170        _install.run(self)
171        root_dir = self.install_platlib
172        dest_dir = os.path.join(root_dir, 'petsc')
173        bdist_base = self.get_finalized_command('bdist').bdist_base
174        if dest_dir.startswith(bdist_base):
175            prefix = dest_dir[len(bdist_base)+1:]
176            prefix = prefix[prefix.index(os.path.sep):]
177        else:
178            prefix = dest_dir
179        dest_dir = os.path.abspath(dest_dir)
180        prefix = os.path.abspath(prefix)
181        wdir = os.getcwd()
182        pdir = os.environ['PETSC_DIR']
183        try:
184            os.chdir(pdir)
185            install(dest_dir, prefix, self.dry_run)
186        finally:
187            os.chdir(wdir)
188
189class cmd_sdist(_sdist):
190
191    def initialize_options(self):
192        _sdist.initialize_options(self)
193        self.force_manifest = 1
194        self.template = os.path.join('config', 'MANIFEST.in')
195
196    def run(self):
197        _sdist.run(self)
198        try:
199            os.remove(self.manifest)
200        except Exception:
201            pass
202
203def version():
204    return '3.2.dev1' # XXX should parse include/petscversion.h
205
206def tarball():
207    return None
208    return ('http://ftp.mcs.anl.gov/pub/petsc/<XXX>/' # XXX fix this line
209            'petsc-lite-%s.tar.gz' % version() )
210
211description = __doc__.split('\n')[1:-1]; del description[1:3]
212classifiers = """
213License :: Public Domain
214Operating System :: POSIX
215Intended Audience :: Developers
216Intended Audience :: Science/Research
217Programming Language :: C
218Programming Language :: C++
219Programming Language :: Fortran
220Programming Language :: Python
221Topic :: Scientific/Engineering
222Topic :: Software Development :: Libraries
223"""
224
225bootstrap()
226setup(name='petsc',
227      version=version(),
228      description=description.pop(0),
229      long_description='\n'.join(description),
230      classifiers= classifiers.split('\n')[1:-1],
231      keywords = ['PETSc', 'MPI'],
232      platforms=['POSIX'],
233      license='PETSc',
234
235      url='http://www.mcs.anl.gov/petsc/',
236      download_url=tarball(),
237
238      author='PETSc Team',
239      author_email='petsc-users@mcs.anl.gov',
240      maintainer='Lisandro Dalcin',
241      maintainer_email='dalcinl@gmail.com',
242
243      packages = ['petsc'],
244      package_dir = {'petsc': os.environ['PETSC_ARCH']},
245      cmdclass={
246        'build': cmd_build,
247        'install': cmd_install,
248        'sdist': cmd_sdist,
249        },
250      **metadata)
251