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