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 from distutils.dir_util import mkpath 58 pkgdir = os.path.join('config', 'pypi') 59 pkgfile = os.path.join(pkgdir, '__init__.py') 60 if not os.path.exists(pkgdir): 61 mkpath(pkgdir) 62 if not os.path.exists(pkgfile): 63 open(pkgfile, 'wt').write(init_py) 64 # Simple-minded lookup for MPI and mpi4py 65 mpi4py = mpicc = None 66 try: 67 import mpi4py 68 conf = mpi4py.get_config() 69 mpicc = conf.get('mpicc') 70 except ImportError: # mpi4py is not installed 71 mpicc = os.environ.get('MPICC') or find_executable('mpicc') 72 except AttributeError: # mpi4py is too old 73 pass 74 if not mpi4py and mpicc: 75 if (('distribute' in sys.modules) or 76 ('setuptools' in sys.modules)): 77 metadata['install_requires']= ['mpi4py>=1.2.2'] 78 if 'setuptools' in sys.modules: 79 metadata['zip_safe'] = False 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.append('--with-cxx=0') # XXX mpicxx? 101 options.append('--with-fc=0') # XXX mpif90? 102 # Run PETSc configure 103 import configure 104 configure.petsc_configure(options) 105 import logger 106 logger.Logger.defaultLog = None 107 108def build(dry_run=False): 109 log.info('PETSc: build') 110 if dry_run: return 111 # Run PETSc builder 112 import builder 113 builder.PETScMaker().run() 114 import logger 115 logger.Logger.defaultLog = None 116 117def install(dest_dir, prefix=None, dry_run=False): 118 log.info('PETSc: install') 119 if dry_run: return 120 if prefix is None: 121 prefix = dest_dir 122 options = [ 123 '--destDir=' + dest_dir, 124 '--prefix=' + prefix, 125 ] 126 # Run PETSc installer 127 import install 128 install.Installer(options).run() 129 import logger 130 logger.Logger.defaultLog = None 131 132class context: 133 def __init__(self): 134 self.sys_argv = sys.argv[:] 135 self.wdir = os.getcwd() 136 def enter(self): 137 del sys.argv[1:] 138 pdir = os.environ['PETSC_DIR'] 139 os.chdir(pdir) 140 return self 141 def exit(self): 142 sys.argv[:] = self.sys_argv 143 os.chdir(self.wdir) 144 145class cmd_build(_build): 146 147 def run(self): 148 _build.run(self) 149 ctx = context().enter() 150 try: 151 config(self.dry_run) 152 build(self.dry_run) 153 finally: 154 ctx.exit() 155 156class cmd_install(_install): 157 158 def run(self): 159 root_dir = self.install_platlib 160 dest_dir = os.path.join(root_dir, 'petsc') 161 bdist_base = self.get_finalized_command('bdist').bdist_base 162 if dest_dir.startswith(bdist_base): 163 prefix = dest_dir[len(bdist_base)+1:] 164 prefix = prefix[prefix.index(os.path.sep):] 165 else: 166 prefix = dest_dir 167 dest_dir = os.path.abspath(dest_dir) 168 prefix = os.path.abspath(prefix) 169 # 170 _install.run(self) 171 ctx = context().enter() 172 try: 173 install(dest_dir, prefix, self.dry_run) 174 finally: 175 ctx.exit() 176 177class cmd_sdist(_sdist): 178 179 def initialize_options(self): 180 _sdist.initialize_options(self) 181 self.force_manifest = 1 182 self.template = os.path.join('config', 'manifest.in') 183 184def version(): 185 import re 186 version_re = { 187 'major' : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"), 188 'minor' : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"), 189 'micro' : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"), 190 'patch' : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"), 191 'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"), 192 } 193 petscversion_h = os.path.join('include','petscversion.h') 194 data = open(petscversion_h, 'rt').read() 195 major = int(version_re['major'].search(data).groups()[0]) 196 minor = int(version_re['minor'].search(data).groups()[0]) 197 micro = int(version_re['micro'].search(data).groups()[0]) 198 patch = int(version_re['patch'].search(data).groups()[0]) 199 release = int(version_re['release'].search(data).groups()[0]) 200 if release: 201 v = "%d.%d" % (major, minor) 202 if micro > 0: 203 v += ".%d" % micro 204 if patch > 0: 205 v += ".post%d" % patch 206 else: 207 v = "%d.%d.dev%d" % (major, minor+1, 0) 208 return v 209 210def tarball(): 211 VERSION = version() 212 if '.dev' in VERSION: 213 return None 214 if '.post' not in VERSION: 215 VERSION = VERSION + '.post0' 216 VERSION = VERSION.replace('.post', '-p') 217 return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/' 218 'petsc-lite-%s.tar.gz' % VERSION) 219 220description = __doc__.split('\n')[1:-1]; del description[1:3] 221classifiers = """ 222License :: Public Domain 223Operating System :: POSIX 224Intended Audience :: Developers 225Intended Audience :: Science/Research 226Programming Language :: C 227Programming Language :: C++ 228Programming Language :: Fortran 229Programming Language :: Python 230Topic :: Scientific/Engineering 231Topic :: Software Development :: Libraries 232""" 233 234bootstrap() 235setup(name='petsc', 236 version=version(), 237 description=description.pop(0), 238 long_description='\n'.join(description), 239 classifiers= classifiers.split('\n')[1:-1], 240 keywords = ['PETSc', 'MPI'], 241 platforms=['POSIX'], 242 license='PETSc', 243 244 url='http://www.mcs.anl.gov/petsc/', 245 download_url=tarball(), 246 247 author='PETSc Team', 248 author_email='petsc-maint@mcs.anl.gov', 249 maintainer='Lisandro Dalcin', 250 maintainer_email='dalcinl@gmail.com', 251 252 packages = ['petsc'], 253 package_dir = {'petsc': 'config/pypi'}, 254 cmdclass={ 255 'build': cmd_build, 256 'install': cmd_install, 257 'sdist': cmd_sdist, 258 }, 259 **metadata) 260