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