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