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