xref: /petsc/setup.py (revision 6308ffc959976d2703e35cebb0f992ee253a04c2)
1*6308ffc9SLisandro Dalcin#!/usr/bin/env python
2*6308ffc9SLisandro Dalcin
3*6308ffc9SLisandro Dalcin"""
4*6308ffc9SLisandro DalcinPETSc: Portable, Extensible Toolkit for Scientific Computation
5*6308ffc9SLisandro Dalcin==============================================================
6*6308ffc9SLisandro Dalcin
7*6308ffc9SLisandro DalcinThe Portable, Extensible Toolkit for Scientific Computation (PETSc),
8*6308ffc9SLisandro Dalcinis a suite of data structures and routines for the scalable (parallel)
9*6308ffc9SLisandro Dalcinsolution of scientific applications modeled by partial differential
10*6308ffc9SLisandro Dalcinequations. It employs the Message Passing Interface (MPI) standard for
11*6308ffc9SLisandro Dalcinall message-passing communication.
12*6308ffc9SLisandro Dalcin"""
13*6308ffc9SLisandro Dalcin
14*6308ffc9SLisandro Dalcinimport sys, os
15*6308ffc9SLisandro Dalcinfrom distutils.core import setup
16*6308ffc9SLisandro Dalcinfrom distutils.util import get_platform
17*6308ffc9SLisandro Dalcinfrom distutils.spawn import find_executable
18*6308ffc9SLisandro Dalcinfrom distutils.command.build import build as _build
19*6308ffc9SLisandro Dalcinif 'setuptools' in sys.modules:
20*6308ffc9SLisandro Dalcin    from setuptools.command.install import install as _install
21*6308ffc9SLisandro Dalcinelse:
22*6308ffc9SLisandro Dalcin    from distutils.command.install import install as _install
23*6308ffc9SLisandro Dalcinfrom distutils.command.sdist import sdist as _sdist
24*6308ffc9SLisandro Dalcinfrom distutils import log
25*6308ffc9SLisandro Dalcin
26*6308ffc9SLisandro Dalcininit_py = """\
27*6308ffc9SLisandro Dalcin# Author:  PETSc Team
28*6308ffc9SLisandro Dalcin# Contact: petsc-maint@mcs.anl.gov
29*6308ffc9SLisandro Dalcin
30*6308ffc9SLisandro Dalcindef get_petsc_dir():
31*6308ffc9SLisandro Dalcin    import os
32*6308ffc9SLisandro Dalcin    return os.path.dirname(__file__)
33*6308ffc9SLisandro Dalcin
34*6308ffc9SLisandro Dalcindef get_config():
35*6308ffc9SLisandro Dalcin    conf = {}
36*6308ffc9SLisandro Dalcin    conf['PETSC_DIR'] = get_petsc_dir()
37*6308ffc9SLisandro Dalcin    return conf
38*6308ffc9SLisandro Dalcin"""
39*6308ffc9SLisandro Dalcin
40*6308ffc9SLisandro Dalcinmetadata = {
41*6308ffc9SLisandro Dalcin    'provides' : ['petsc'],
42*6308ffc9SLisandro Dalcin    'requires' : [],
43*6308ffc9SLisandro Dalcin}
44*6308ffc9SLisandro Dalcin
45*6308ffc9SLisandro Dalcindef bootstrap():
46*6308ffc9SLisandro Dalcin    # Set PETSC_DIR and PETSC_ARCH,
47*6308ffc9SLisandro Dalcin    PETSC_DIR  = os.path.abspath(os.getcwd())
48*6308ffc9SLisandro Dalcin    PETSC_ARCH = get_platform() + '-python'
49*6308ffc9SLisandro Dalcin    os.environ['PETSC_DIR']  = PETSC_DIR
50*6308ffc9SLisandro Dalcin    os.environ['PETSC_ARCH'] = PETSC_ARCH
51*6308ffc9SLisandro Dalcin    # Generate package __init__.py file
52*6308ffc9SLisandro Dalcin    from distutils.dir_util import mkpath
53*6308ffc9SLisandro Dalcin    pkgdir = os.path.join('config', 'pypi')
54*6308ffc9SLisandro Dalcin    pkgfile = os.path.join(pkgdir, '__init__.py')
55*6308ffc9SLisandro Dalcin    if not os.path.exists(pkgdir):
56*6308ffc9SLisandro Dalcin        mkpath(pkgdir)
57*6308ffc9SLisandro Dalcin    if not os.path.exists(pkgfile):
58*6308ffc9SLisandro Dalcin        open(pkgfile, 'wt').write(init_py)
59*6308ffc9SLisandro Dalcin    # Simple-minded lookup for MPI and mpi4py
60*6308ffc9SLisandro Dalcin    mpi4py = mpicc = None
61*6308ffc9SLisandro Dalcin    try:
62*6308ffc9SLisandro Dalcin        import mpi4py
63*6308ffc9SLisandro Dalcin        conf = mpi4py.get_config()
64*6308ffc9SLisandro Dalcin        mpicc = conf.get('mpicc')
65*6308ffc9SLisandro Dalcin    except ImportError: # mpi4py is not installed
66*6308ffc9SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
67*6308ffc9SLisandro Dalcin    except AttributeError: # mpi4py is too old
68*6308ffc9SLisandro Dalcin        pass
69*6308ffc9SLisandro Dalcin    if not mpi4py and mpicc:
70*6308ffc9SLisandro Dalcin        if (('distribute' in sys.modules) or
71*6308ffc9SLisandro Dalcin            ('setuptools' in sys.modules)):
72*6308ffc9SLisandro Dalcin            metadata['install_requires']= ['mpi4py>=1.2.2']
73*6308ffc9SLisandro Dalcin    if 'setuptools' in sys.modules:
74*6308ffc9SLisandro Dalcin        metadata['zip_safe'] = False
75*6308ffc9SLisandro Dalcin
76*6308ffc9SLisandro Dalcindef config(dry_run=False):
77*6308ffc9SLisandro Dalcin    log.info('PETSc: configure')
78*6308ffc9SLisandro Dalcin    if dry_run: return
79*6308ffc9SLisandro Dalcin    options = [
80*6308ffc9SLisandro Dalcin        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
81*6308ffc9SLisandro Dalcin        '--with-shared',
82*6308ffc9SLisandro Dalcin        '--with-cmake=0', # not needed
83*6308ffc9SLisandro Dalcin        ]
84*6308ffc9SLisandro Dalcin    # MPI
85*6308ffc9SLisandro Dalcin    try:
86*6308ffc9SLisandro Dalcin        import mpi4py
87*6308ffc9SLisandro Dalcin        conf = mpi4py.get_config()
88*6308ffc9SLisandro Dalcin        mpicc = conf.get('mpicc')
89*6308ffc9SLisandro Dalcin    except (ImportError, AttributeError):
90*6308ffc9SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
91*6308ffc9SLisandro Dalcin    if mpicc:
92*6308ffc9SLisandro Dalcin        options.append('--with-cc='+mpicc)
93*6308ffc9SLisandro Dalcin    else:
94*6308ffc9SLisandro Dalcin        options.append('--with-mpi=0')
95*6308ffc9SLisandro Dalcin    options.append('--with-cxx=0') # XXX mpicxx?
96*6308ffc9SLisandro Dalcin    options.append('--with-fc=0')  # XXX mpif90?
97*6308ffc9SLisandro Dalcin    # Run PETSc configure
98*6308ffc9SLisandro Dalcin    status = os.system('%s %s %s' % (
99*6308ffc9SLisandro Dalcin            find_executable('python'),
100*6308ffc9SLisandro Dalcin            os.path.join('config', 'configure.py'),
101*6308ffc9SLisandro Dalcin            ' '.join(options),
102*6308ffc9SLisandro Dalcin            ))
103*6308ffc9SLisandro Dalcin    if status != 0: raise RuntimeError(status)
104*6308ffc9SLisandro Dalcin
105*6308ffc9SLisandro Dalcindef build(dry_run=False):
106*6308ffc9SLisandro Dalcin    log.info('PETSc: build')
107*6308ffc9SLisandro Dalcin    if dry_run: return
108*6308ffc9SLisandro Dalcin    # Run PETSc builder
109*6308ffc9SLisandro Dalcin    status = os.system('make all')
110*6308ffc9SLisandro Dalcin    if status != 0: raise RuntimeError(status)
111*6308ffc9SLisandro Dalcin
112*6308ffc9SLisandro Dalcindef install(dest_dir, prefix=None, dry_run=False):
113*6308ffc9SLisandro Dalcin    log.info('PETSc: install')
114*6308ffc9SLisandro Dalcin    if dry_run: return
115*6308ffc9SLisandro Dalcin    if prefix is None:
116*6308ffc9SLisandro Dalcin        prefix = dest_dir
117*6308ffc9SLisandro Dalcin    options = [
118*6308ffc9SLisandro Dalcin        '--destDir=' + dest_dir,
119*6308ffc9SLisandro Dalcin        '--prefix='  + prefix,
120*6308ffc9SLisandro Dalcin        ]
121*6308ffc9SLisandro Dalcin    # Run PETSc installer
122*6308ffc9SLisandro Dalcin    status = os.system('%s %s %s' % (
123*6308ffc9SLisandro Dalcin            find_executable('python'),
124*6308ffc9SLisandro Dalcin            os.path.join('config', 'install.py'),
125*6308ffc9SLisandro Dalcin            ' '.join(options),
126*6308ffc9SLisandro Dalcin            ))
127*6308ffc9SLisandro Dalcin    if status != 0: raise RuntimeError(status)
128*6308ffc9SLisandro Dalcin
129*6308ffc9SLisandro Dalcinclass context:
130*6308ffc9SLisandro Dalcin    def __init__(self):
131*6308ffc9SLisandro Dalcin        self.sys_argv = sys.argv[:]
132*6308ffc9SLisandro Dalcin        self.wdir = os.getcwd()
133*6308ffc9SLisandro Dalcin    def enter(self):
134*6308ffc9SLisandro Dalcin        del sys.argv[1:]
135*6308ffc9SLisandro Dalcin        pdir = os.environ['PETSC_DIR']
136*6308ffc9SLisandro Dalcin        os.chdir(pdir)
137*6308ffc9SLisandro Dalcin        return self
138*6308ffc9SLisandro Dalcin    def exit(self):
139*6308ffc9SLisandro Dalcin        sys.argv[:] = self.sys_argv
140*6308ffc9SLisandro Dalcin        os.chdir(self.wdir)
141*6308ffc9SLisandro Dalcin
142*6308ffc9SLisandro Dalcinclass cmd_build(_build):
143*6308ffc9SLisandro Dalcin
144*6308ffc9SLisandro Dalcin    def initialize_options(self):
145*6308ffc9SLisandro Dalcin        _build.initialize_options(self)
146*6308ffc9SLisandro Dalcin        PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
147*6308ffc9SLisandro Dalcin        self.build_base = os.path.join(PETSC_ARCH, 'build-python')
148*6308ffc9SLisandro Dalcin
149*6308ffc9SLisandro Dalcin    def run(self):
150*6308ffc9SLisandro Dalcin        _build.run(self)
151*6308ffc9SLisandro Dalcin        ctx = context().enter()
152*6308ffc9SLisandro Dalcin        try:
153*6308ffc9SLisandro Dalcin            config(self.dry_run)
154*6308ffc9SLisandro Dalcin            build(self.dry_run)
155*6308ffc9SLisandro Dalcin        finally:
156*6308ffc9SLisandro Dalcin            ctx.exit()
157*6308ffc9SLisandro Dalcin
158*6308ffc9SLisandro Dalcinclass cmd_install(_install):
159*6308ffc9SLisandro Dalcin
160*6308ffc9SLisandro Dalcin    def initialize_options(self):
161*6308ffc9SLisandro Dalcin        _install.initialize_options(self)
162*6308ffc9SLisandro Dalcin        self.optimize = 1
163*6308ffc9SLisandro Dalcin
164*6308ffc9SLisandro Dalcin    def run(self):
165*6308ffc9SLisandro Dalcin        root_dir = self.install_platlib
166*6308ffc9SLisandro Dalcin        dest_dir = os.path.join(root_dir, 'petsc')
167*6308ffc9SLisandro Dalcin        bdist_base = self.get_finalized_command('bdist').bdist_base
168*6308ffc9SLisandro Dalcin        if dest_dir.startswith(bdist_base):
169*6308ffc9SLisandro Dalcin            prefix = dest_dir[len(bdist_base)+1:]
170*6308ffc9SLisandro Dalcin            prefix = prefix[prefix.index(os.path.sep):]
171*6308ffc9SLisandro Dalcin        else:
172*6308ffc9SLisandro Dalcin            prefix = dest_dir
173*6308ffc9SLisandro Dalcin        dest_dir = os.path.abspath(dest_dir)
174*6308ffc9SLisandro Dalcin        prefix   = os.path.abspath(prefix)
175*6308ffc9SLisandro Dalcin        #
176*6308ffc9SLisandro Dalcin        _install.run(self)
177*6308ffc9SLisandro Dalcin        ctx = context().enter()
178*6308ffc9SLisandro Dalcin        try:
179*6308ffc9SLisandro Dalcin            install(dest_dir, prefix, self.dry_run)
180*6308ffc9SLisandro Dalcin        finally:
181*6308ffc9SLisandro Dalcin            ctx.exit()
182*6308ffc9SLisandro Dalcin
183*6308ffc9SLisandro Dalcinclass cmd_sdist(_sdist):
184*6308ffc9SLisandro Dalcin
185*6308ffc9SLisandro Dalcin    def initialize_options(self):
186*6308ffc9SLisandro Dalcin        _sdist.initialize_options(self)
187*6308ffc9SLisandro Dalcin        self.force_manifest = 1
188*6308ffc9SLisandro Dalcin        self.template = os.path.join('config', 'manifest.in')
189*6308ffc9SLisandro Dalcin
190*6308ffc9SLisandro Dalcindef version():
191*6308ffc9SLisandro Dalcin    import re
192*6308ffc9SLisandro Dalcin    version_re = {
193*6308ffc9SLisandro Dalcin        'major'  : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"),
194*6308ffc9SLisandro Dalcin        'minor'  : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"),
195*6308ffc9SLisandro Dalcin        'micro'  : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"),
196*6308ffc9SLisandro Dalcin        'patch'  : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"),
197*6308ffc9SLisandro Dalcin        'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"),
198*6308ffc9SLisandro Dalcin        }
199*6308ffc9SLisandro Dalcin    petscversion_h = os.path.join('include','petscversion.h')
200*6308ffc9SLisandro Dalcin    data = open(petscversion_h, 'rt').read()
201*6308ffc9SLisandro Dalcin    major = int(version_re['major'].search(data).groups()[0])
202*6308ffc9SLisandro Dalcin    minor = int(version_re['minor'].search(data).groups()[0])
203*6308ffc9SLisandro Dalcin    micro = int(version_re['micro'].search(data).groups()[0])
204*6308ffc9SLisandro Dalcin    patch = int(version_re['patch'].search(data).groups()[0])
205*6308ffc9SLisandro Dalcin    release = int(version_re['release'].search(data).groups()[0])
206*6308ffc9SLisandro Dalcin    if release:
207*6308ffc9SLisandro Dalcin        v = "%d.%d" % (major, minor)
208*6308ffc9SLisandro Dalcin        if micro > 0:
209*6308ffc9SLisandro Dalcin            v += ".%d" % micro
210*6308ffc9SLisandro Dalcin        if patch > 0:
211*6308ffc9SLisandro Dalcin            v += ".post%d" % patch
212*6308ffc9SLisandro Dalcin    else:
213*6308ffc9SLisandro Dalcin        v = "%d.%d.dev%d" % (major, minor+1, 0)
214*6308ffc9SLisandro Dalcin    return v
215*6308ffc9SLisandro Dalcin
216*6308ffc9SLisandro Dalcindef tarball():
217*6308ffc9SLisandro Dalcin    return None # XXX remove this line !!!
218*6308ffc9SLisandro Dalcin    VERSION = version()
219*6308ffc9SLisandro Dalcin    if '.dev' in VERSION:
220*6308ffc9SLisandro Dalcin        return None
221*6308ffc9SLisandro Dalcin    if '.post' not in VERSION:
222*6308ffc9SLisandro Dalcin        VERSION = VERSION + '.post0'
223*6308ffc9SLisandro Dalcin    VERSION = VERSION.replace('.post', '-p')
224*6308ffc9SLisandro Dalcin    return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/'
225*6308ffc9SLisandro Dalcin            'petsc-lite-%s.tar.gz' % VERSION)
226*6308ffc9SLisandro Dalcin
227*6308ffc9SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3]
228*6308ffc9SLisandro Dalcinclassifiers = """
229*6308ffc9SLisandro DalcinLicense :: Public Domain
230*6308ffc9SLisandro DalcinOperating System :: POSIX
231*6308ffc9SLisandro DalcinIntended Audience :: Developers
232*6308ffc9SLisandro DalcinIntended Audience :: Science/Research
233*6308ffc9SLisandro DalcinProgramming Language :: C
234*6308ffc9SLisandro DalcinProgramming Language :: C++
235*6308ffc9SLisandro DalcinProgramming Language :: Fortran
236*6308ffc9SLisandro DalcinProgramming Language :: Python
237*6308ffc9SLisandro DalcinTopic :: Scientific/Engineering
238*6308ffc9SLisandro DalcinTopic :: Software Development :: Libraries
239*6308ffc9SLisandro Dalcin"""
240*6308ffc9SLisandro Dalcin
241*6308ffc9SLisandro Dalcinbootstrap()
242*6308ffc9SLisandro Dalcinsetup(name='petsc',
243*6308ffc9SLisandro Dalcin      version=version(),
244*6308ffc9SLisandro Dalcin      description=description.pop(0),
245*6308ffc9SLisandro Dalcin      long_description='\n'.join(description),
246*6308ffc9SLisandro Dalcin      classifiers= classifiers.split('\n')[1:-1],
247*6308ffc9SLisandro Dalcin      keywords = ['PETSc', 'MPI'],
248*6308ffc9SLisandro Dalcin      platforms=['POSIX'],
249*6308ffc9SLisandro Dalcin      license='PETSc',
250*6308ffc9SLisandro Dalcin
251*6308ffc9SLisandro Dalcin      url='http://www.mcs.anl.gov/petsc/',
252*6308ffc9SLisandro Dalcin      download_url=tarball(),
253*6308ffc9SLisandro Dalcin
254*6308ffc9SLisandro Dalcin      author='PETSc Team',
255*6308ffc9SLisandro Dalcin      author_email='petsc-maint@mcs.anl.gov',
256*6308ffc9SLisandro Dalcin      maintainer='Lisandro Dalcin',
257*6308ffc9SLisandro Dalcin      maintainer_email='dalcinl@gmail.com',
258*6308ffc9SLisandro Dalcin
259*6308ffc9SLisandro Dalcin      packages = ['petsc'],
260*6308ffc9SLisandro Dalcin      package_dir = {'petsc': 'config/pypi'},
261*6308ffc9SLisandro Dalcin      cmdclass={
262*6308ffc9SLisandro Dalcin        'build': cmd_build,
263*6308ffc9SLisandro Dalcin        'install': cmd_install,
264*6308ffc9SLisandro Dalcin        'sdist': cmd_sdist,
265*6308ffc9SLisandro Dalcin        },
266*6308ffc9SLisandro Dalcin      **metadata)
267