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