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