1f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 2f46a955bSLisandro Dalcin 3f46a955bSLisandro Dalcinimport re 4f46a955bSLisandro Dalcinimport os 5f46a955bSLisandro Dalcinimport sys 6f46a955bSLisandro Dalcinimport glob 7f46a955bSLisandro Dalcinimport copy 8f46a955bSLisandro Dalcinimport warnings 9f46a955bSLisandro Dalcin 10f46a955bSLisandro Dalcintry: 11f46a955bSLisandro Dalcin from cStringIO import StringIO 12f46a955bSLisandro Dalcinexcept ImportError: 13f46a955bSLisandro Dalcin from io import StringIO 14f46a955bSLisandro Dalcin 15f46a955bSLisandro Dalcintry: 16f46a955bSLisandro Dalcin import setuptools 17f46a955bSLisandro Dalcinexcept ImportError: 18f46a955bSLisandro Dalcin setuptools = None 19f46a955bSLisandro Dalcin 20f46a955bSLisandro Dalcinif setuptools: 21f46a955bSLisandro Dalcin from setuptools import setup as _setup 22f46a955bSLisandro Dalcin from setuptools import Extension as _Extension 23f46a955bSLisandro Dalcin from setuptools import Command 24f46a955bSLisandro Dalcinelse: 25f46a955bSLisandro Dalcin from distutils.core import setup as _setup 26f46a955bSLisandro Dalcin from distutils.core import Extension as _Extension 27f46a955bSLisandro Dalcin from distutils.core import Command 28f46a955bSLisandro Dalcin 29f46a955bSLisandro Dalcindef import_command(cmd): 30f46a955bSLisandro Dalcin try: 31f46a955bSLisandro Dalcin from importlib import import_module 32f46a955bSLisandro Dalcin except ImportError: 33f46a955bSLisandro Dalcin def import_module(n): 34f46a955bSLisandro Dalcin return __import__(n, fromlist=[None]) 35f46a955bSLisandro Dalcin try: 36f46a955bSLisandro Dalcin if not setuptools: raise ImportError 37f46a955bSLisandro Dalcin mod = import_module('setuptools.command.' + cmd) 38f46a955bSLisandro Dalcin return getattr(mod, cmd) 39f46a955bSLisandro Dalcin except ImportError: 40f46a955bSLisandro Dalcin mod = import_module('distutils.command.' + cmd) 41f46a955bSLisandro Dalcin return getattr(mod, cmd) 42f46a955bSLisandro Dalcin 43f46a955bSLisandro Dalcin_config = import_command('config') 44f46a955bSLisandro Dalcin_build = import_command('build') 45f46a955bSLisandro Dalcin_build_ext = import_command('build_ext') 46f46a955bSLisandro Dalcin_install = import_command('install') 47f46a955bSLisandro Dalcin 48f46a955bSLisandro Dalcinfrom distutils import log 49f46a955bSLisandro Dalcinfrom distutils import sysconfig 50f46a955bSLisandro Dalcinfrom distutils.util import execute 51f46a955bSLisandro Dalcinfrom distutils.util import split_quoted 52f46a955bSLisandro Dalcinfrom distutils.errors import DistutilsError 53f46a955bSLisandro Dalcin 54f46a955bSLisandro Dalcintry: 55f46a955bSLisandro Dalcin from setuptools import dep_util 56f46a955bSLisandro Dalcinexcept ImportError: 57f46a955bSLisandro Dalcin from distutils import dep_util 58f46a955bSLisandro Dalcin 59f46a955bSLisandro Dalcintry: 60f46a955bSLisandro Dalcin from packaging.version import Version 61f46a955bSLisandro Dalcinexcept ImportError: 62f46a955bSLisandro Dalcin try: 63f46a955bSLisandro Dalcin from setuptools.extern.packaging.version import Version 64f46a955bSLisandro Dalcin except ImportError: 65f46a955bSLisandro Dalcin from distutils.version import StrictVersion as Version 66f46a955bSLisandro Dalcin 67f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 68f46a955bSLisandro Dalcin 69f46a955bSLisandro Dalcin# Cython 70f46a955bSLisandro Dalcin 71b12f50ebSLisandro DalcinCYTHON = '3.0.0' 72f46a955bSLisandro Dalcin 73f46a955bSLisandro Dalcindef cython_req(): 74f46a955bSLisandro Dalcin return CYTHON 75f46a955bSLisandro Dalcin 76f46a955bSLisandro Dalcindef cython_chk(VERSION, verbose=True): 77f46a955bSLisandro Dalcin # 78f46a955bSLisandro Dalcin def warn(message): 79f46a955bSLisandro Dalcin if not verbose: return 80f46a955bSLisandro Dalcin ruler, ws, nl = "*"*80, " " ,"\n" 81f46a955bSLisandro Dalcin pyexe = sys.executable 82f46a955bSLisandro Dalcin advise = "$ %s -m pip install --upgrade cython" % pyexe 83f46a955bSLisandro Dalcin def printer(*s): sys.stderr.write(" ".join(s)+"\n") 84f46a955bSLisandro Dalcin printer(ruler, nl) 85f46a955bSLisandro Dalcin printer(ws, message, nl) 86f46a955bSLisandro Dalcin printer(ws, ws, advise, nl) 87f46a955bSLisandro Dalcin printer(ruler) 88f46a955bSLisandro Dalcin # 89f46a955bSLisandro Dalcin try: 90f46a955bSLisandro Dalcin import Cython 91f46a955bSLisandro Dalcin except ImportError: 92f46a955bSLisandro Dalcin warn("You need Cython to generate C source files.") 93f46a955bSLisandro Dalcin return False 94f46a955bSLisandro Dalcin # 95f46a955bSLisandro Dalcin CYTHON_VERSION = Cython.__version__ 96f46a955bSLisandro Dalcin m = re.match(r"(\d+\.\d+(?:\.\d+)?).*", CYTHON_VERSION) 97f46a955bSLisandro Dalcin if not m: 98f46a955bSLisandro Dalcin warn("Cannot parse Cython version string {0!r}" 99f46a955bSLisandro Dalcin .format(CYTHON_VERSION)) 100f46a955bSLisandro Dalcin return False 101f46a955bSLisandro Dalcin REQUIRED = Version(VERSION) 102f46a955bSLisandro Dalcin PROVIDED = Version(m.groups()[0]) 103b12f50ebSLisandro Dalcin if PROVIDED < REQUIRED: 104b12f50ebSLisandro Dalcin warn("You need Cython >= {0} (you have version {1})" 105f46a955bSLisandro Dalcin .format(VERSION, CYTHON_VERSION)) 106f46a955bSLisandro Dalcin return False 107f46a955bSLisandro Dalcin # 108f46a955bSLisandro Dalcin if verbose: 109f46a955bSLisandro Dalcin log.info("using Cython %s" % CYTHON_VERSION) 110f46a955bSLisandro Dalcin return True 111f46a955bSLisandro Dalcin 112f46a955bSLisandro Dalcindef cython_run( 113f46a955bSLisandro Dalcin source, target=None, 114f46a955bSLisandro Dalcin depends=(), includes=(), 115f46a955bSLisandro Dalcin workdir=None, force=False, 116f46a955bSLisandro Dalcin VERSION="0.0", 117f46a955bSLisandro Dalcin): 118f46a955bSLisandro Dalcin if target is None: 119f46a955bSLisandro Dalcin target = os.path.splitext(source)[0]+'.c' 120f46a955bSLisandro Dalcin cwd = os.getcwd() 121f46a955bSLisandro Dalcin try: 122f46a955bSLisandro Dalcin if workdir: 123f46a955bSLisandro Dalcin os.chdir(workdir) 124f46a955bSLisandro Dalcin alldeps = [source] 125f46a955bSLisandro Dalcin for dep in depends: 126f46a955bSLisandro Dalcin alldeps += glob.glob(dep) 127f46a955bSLisandro Dalcin if not (force or dep_util.newer_group(alldeps, target)): 128f46a955bSLisandro Dalcin log.debug("skipping '%s' -> '%s' (up-to-date)", 129f46a955bSLisandro Dalcin source, target) 130f46a955bSLisandro Dalcin return 131f46a955bSLisandro Dalcin finally: 132f46a955bSLisandro Dalcin os.chdir(cwd) 13380e0d92bSLisandro Dalcin require = 'Cython >= %s' % VERSION 134f46a955bSLisandro Dalcin if setuptools and not cython_chk(VERSION, verbose=False): 135f46a955bSLisandro Dalcin if sys.modules.get('Cython'): 136f46a955bSLisandro Dalcin removed = getattr(sys.modules['Cython'], '__version__', '') 137f46a955bSLisandro Dalcin log.info("removing Cython %s from sys.modules" % removed) 138f46a955bSLisandro Dalcin pkgname = re.compile(r'cython(\.|$)', re.IGNORECASE) 139f46a955bSLisandro Dalcin for modname in list(sys.modules.keys()): 140f46a955bSLisandro Dalcin if pkgname.match(modname): 141f46a955bSLisandro Dalcin del sys.modules[modname] 142f46a955bSLisandro Dalcin try: 143f46a955bSLisandro Dalcin install_setup_requires = setuptools._install_setup_requires 144f46a955bSLisandro Dalcin with warnings.catch_warnings(): 145f46a955bSLisandro Dalcin if hasattr(setuptools, 'SetuptoolsDeprecationWarning'): 146f46a955bSLisandro Dalcin category = setuptools.SetuptoolsDeprecationWarning 147f46a955bSLisandro Dalcin warnings.simplefilter('ignore', category) 148f46a955bSLisandro Dalcin log.info("fetching build requirement '%s'" % require) 149f46a955bSLisandro Dalcin install_setup_requires(dict(setup_requires=[require])) 150f46a955bSLisandro Dalcin except Exception: 151f46a955bSLisandro Dalcin log.info("failed to fetch build requirement '%s'" % require) 152f46a955bSLisandro Dalcin if not cython_chk(VERSION): 153f46a955bSLisandro Dalcin raise DistutilsError("unsatisfied build requirement '%s'" % require) 154f46a955bSLisandro Dalcin # 155f46a955bSLisandro Dalcin log.info("cythonizing '%s' -> '%s'", source, target) 156f46a955bSLisandro Dalcin from cythonize import cythonize 157f46a955bSLisandro Dalcin args = [] 158f46a955bSLisandro Dalcin if workdir: 159f46a955bSLisandro Dalcin args += ['--working', workdir] 160f46a955bSLisandro Dalcin args += [source] 161f46a955bSLisandro Dalcin if target: 162f46a955bSLisandro Dalcin args += ['--output-file', target] 163f46a955bSLisandro Dalcin err = cythonize(args) 164f46a955bSLisandro Dalcin if err: 165f46a955bSLisandro Dalcin raise DistutilsError( 166f46a955bSLisandro Dalcin "Cython failure: '%s' -> '%s'" % (source, target) 167f46a955bSLisandro Dalcin ) 168f46a955bSLisandro Dalcin 169f46a955bSLisandro Dalcin 170f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 171f46a955bSLisandro Dalcin 172f46a955bSLisandro Dalcindef fix_config_vars(names, values): 173f46a955bSLisandro Dalcin values = list(values) 174f46a955bSLisandro Dalcin if 'CONDA_BUILD' in os.environ: 175f46a955bSLisandro Dalcin return values 176f46a955bSLisandro Dalcin if sys.platform == 'darwin': 177f46a955bSLisandro Dalcin if 'ARCHFLAGS' in os.environ: 178f46a955bSLisandro Dalcin ARCHFLAGS = os.environ['ARCHFLAGS'] 179f46a955bSLisandro Dalcin for i, flag in enumerate(list(values)): 180*8acd7bfaSLisandro Dalcin flag, count = re.subn(r'-arch\s+\w+', ' ', str(flag)) 181f46a955bSLisandro Dalcin if count and ARCHFLAGS: 182f46a955bSLisandro Dalcin flag = flag + ' ' + ARCHFLAGS 183f46a955bSLisandro Dalcin values[i] = flag 184f46a955bSLisandro Dalcin if 'SDKROOT' in os.environ: 185f46a955bSLisandro Dalcin SDKROOT = os.environ['SDKROOT'] 186f46a955bSLisandro Dalcin for i, flag in enumerate(list(values)): 187*8acd7bfaSLisandro Dalcin flag, count = re.subn(r'-isysroot [^ \t]*', ' ', str(flag)) 188f46a955bSLisandro Dalcin if count and SDKROOT: 189f46a955bSLisandro Dalcin flag = flag + ' ' + '-isysroot ' + SDKROOT 190f46a955bSLisandro Dalcin values[i] = flag 191f46a955bSLisandro Dalcin return values 192f46a955bSLisandro Dalcin 193f46a955bSLisandro Dalcindef get_config_vars(*names): 194f46a955bSLisandro Dalcin # Core Python configuration 195f46a955bSLisandro Dalcin values = sysconfig.get_config_vars(*names) 196f46a955bSLisandro Dalcin # Do any distutils flags fixup right now 197f46a955bSLisandro Dalcin values = fix_config_vars(names, values) 198f46a955bSLisandro Dalcin return values 199f46a955bSLisandro Dalcin 200f46a955bSLisandro Dalcinfrom distutils.unixccompiler import UnixCCompiler 201f46a955bSLisandro Dalcinrpath_option_orig = UnixCCompiler.runtime_library_dir_option 202f46a955bSLisandro Dalcindef rpath_option(compiler, dir): 203f46a955bSLisandro Dalcin option = rpath_option_orig(compiler, dir) 204f46a955bSLisandro Dalcin if sys.platform[:5] == 'linux': 205f46a955bSLisandro Dalcin if option.startswith('-R'): 206f46a955bSLisandro Dalcin option = option.replace('-R', '-Wl,-rpath,', 1) 207f46a955bSLisandro Dalcin elif option.startswith('-Wl,-R'): 208f46a955bSLisandro Dalcin option = option.replace('-Wl,-R', '-Wl,-rpath,', 1) 209f46a955bSLisandro Dalcin return option 210f46a955bSLisandro DalcinUnixCCompiler.runtime_library_dir_option = rpath_option 211f46a955bSLisandro Dalcin 212f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 213f46a955bSLisandro Dalcin 214f46a955bSLisandro Dalcinclass PetscConfig: 215f46a955bSLisandro Dalcin 216f46a955bSLisandro Dalcin def __init__(self, petsc_dir, petsc_arch, dest_dir=None): 217f46a955bSLisandro Dalcin if dest_dir is None: 218f46a955bSLisandro Dalcin dest_dir = os.environ.get('DESTDIR') 219f46a955bSLisandro Dalcin self.configdict = { } 220f46a955bSLisandro Dalcin if not petsc_dir: 221f46a955bSLisandro Dalcin raise DistutilsError("PETSc not found") 222f46a955bSLisandro Dalcin if not os.path.isdir(petsc_dir): 223f46a955bSLisandro Dalcin raise DistutilsError("invalid PETSC_DIR: %s" % petsc_dir) 224f46a955bSLisandro Dalcin self.version = self._get_petsc_version(petsc_dir) 225f46a955bSLisandro Dalcin self.configdict = self._get_petsc_config(petsc_dir, petsc_arch) 226f46a955bSLisandro Dalcin self.PETSC_DIR = self['PETSC_DIR'] 227f46a955bSLisandro Dalcin self.PETSC_ARCH = self['PETSC_ARCH'] 228f46a955bSLisandro Dalcin self.DESTDIR = dest_dir 229f46a955bSLisandro Dalcin language_map = {'CONLY':'c', 'CXXONLY':'c++'} 230f46a955bSLisandro Dalcin self.language = language_map[self['PETSC_LANGUAGE']] 231f46a955bSLisandro Dalcin 232f46a955bSLisandro Dalcin def __getitem__(self, item): 233f46a955bSLisandro Dalcin return self.configdict[item] 234f46a955bSLisandro Dalcin 235f46a955bSLisandro Dalcin def get(self, item, default=None): 236f46a955bSLisandro Dalcin return self.configdict.get(item, default) 237f46a955bSLisandro Dalcin 238f46a955bSLisandro Dalcin def configure(self, extension, compiler=None): 239f46a955bSLisandro Dalcin self.configure_extension(extension) 240f46a955bSLisandro Dalcin if compiler is not None: 241f46a955bSLisandro Dalcin self.configure_compiler(compiler) 242f46a955bSLisandro Dalcin 243f46a955bSLisandro Dalcin def _get_petsc_version(self, petsc_dir): 244f46a955bSLisandro Dalcin import re 245f46a955bSLisandro Dalcin version_re = { 246f46a955bSLisandro Dalcin 'major' : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"), 247f46a955bSLisandro Dalcin 'minor' : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"), 248f46a955bSLisandro Dalcin 'micro' : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"), 249f46a955bSLisandro Dalcin 'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(-*\d+)"), 250f46a955bSLisandro Dalcin } 251f46a955bSLisandro Dalcin petscversion_h = os.path.join(petsc_dir, 'include', 'petscversion.h') 252f46a955bSLisandro Dalcin with open(petscversion_h, 'rt') as f: data = f.read() 253f46a955bSLisandro Dalcin major = int(version_re['major'].search(data).groups()[0]) 254f46a955bSLisandro Dalcin minor = int(version_re['minor'].search(data).groups()[0]) 255f46a955bSLisandro Dalcin micro = int(version_re['micro'].search(data).groups()[0]) 256f46a955bSLisandro Dalcin release = int(version_re['release'].search(data).groups()[0]) 257f46a955bSLisandro Dalcin return (major, minor, micro), (release == 1) 258f46a955bSLisandro Dalcin 259f46a955bSLisandro Dalcin def _get_petsc_config(self, petsc_dir, petsc_arch): 260f46a955bSLisandro Dalcin from os.path import join, isdir, exists 261f46a955bSLisandro Dalcin PETSC_DIR = petsc_dir 262f46a955bSLisandro Dalcin PETSC_ARCH = petsc_arch 263f46a955bSLisandro Dalcin # 264f46a955bSLisandro Dalcin confdir = join('lib', 'petsc', 'conf') 265f46a955bSLisandro Dalcin if not (PETSC_ARCH and isdir(join(PETSC_DIR, PETSC_ARCH))): 266f46a955bSLisandro Dalcin petscvars = join(PETSC_DIR, confdir, 'petscvariables') 267f46a955bSLisandro Dalcin PETSC_ARCH = makefile(open(petscvars, 'rt')).get('PETSC_ARCH') 268f46a955bSLisandro Dalcin if not (PETSC_ARCH and isdir(join(PETSC_DIR, PETSC_ARCH))): 269f46a955bSLisandro Dalcin PETSC_ARCH = '' 270f46a955bSLisandro Dalcin # 271f46a955bSLisandro Dalcin variables = join(PETSC_DIR, confdir, 'variables') 272f46a955bSLisandro Dalcin if not exists(variables): 273f46a955bSLisandro Dalcin variables = join(PETSC_DIR, PETSC_ARCH, confdir, 'variables') 274f46a955bSLisandro Dalcin petscvariables = join(PETSC_DIR, PETSC_ARCH, confdir, 'petscvariables') 275f46a955bSLisandro Dalcin # 276f46a955bSLisandro Dalcin with open(variables) as f: 277f46a955bSLisandro Dalcin contents = f.read() 278f46a955bSLisandro Dalcin with open(petscvariables) as f: 279f46a955bSLisandro Dalcin contents += f.read() 280f46a955bSLisandro Dalcin # 281f46a955bSLisandro Dalcin confstr = 'PETSC_DIR = %s\n' % PETSC_DIR 282f46a955bSLisandro Dalcin confstr += 'PETSC_ARCH = %s\n' % PETSC_ARCH 283f46a955bSLisandro Dalcin confstr += contents 284f46a955bSLisandro Dalcin confdict = makefile(StringIO(confstr)) 285f46a955bSLisandro Dalcin return confdict 286f46a955bSLisandro Dalcin 287ec81f945SPierre Jolivet def _configure_ext(self, ext, dct, append=False): 288f46a955bSLisandro Dalcin extdict = ext.__dict__ 289f46a955bSLisandro Dalcin for key, values in dct.items(): 290f46a955bSLisandro Dalcin if key in extdict: 291f46a955bSLisandro Dalcin for value in values: 292f46a955bSLisandro Dalcin if value not in extdict[key]: 293ec81f945SPierre Jolivet if not append: 294f46a955bSLisandro Dalcin extdict[key].insert(0, value) 295f46a955bSLisandro Dalcin else: 296f46a955bSLisandro Dalcin extdict[key].append(value) 297f46a955bSLisandro Dalcin 298f46a955bSLisandro Dalcin def configure_extension(self, extension): 299f46a955bSLisandro Dalcin # includes and libraries 300f46a955bSLisandro Dalcin # paths in PETSc config files point to final installation location, but 301f46a955bSLisandro Dalcin # we might be building against PETSc in staging location (DESTDIR) when 302f46a955bSLisandro Dalcin # DESTDIR is set, so append DESTDIR (if nonempty) to those paths 303f46a955bSLisandro Dalcin petsc_inc = flaglist(prepend_to_flags(self.DESTDIR, self['PETSC_CC_INCLUDES'])) 304f46a955bSLisandro Dalcin lib_flags = prepend_to_flags(self.DESTDIR, '-L%s %s' % \ 305f46a955bSLisandro Dalcin (self['PETSC_LIB_DIR'], self['PETSC_LIB_BASIC'])) 306f46a955bSLisandro Dalcin petsc_lib = flaglist(lib_flags) 307f46a955bSLisandro Dalcin # runtime_library_dirs is not supported on Windows 308f46a955bSLisandro Dalcin if sys.platform != 'win32': 309f46a955bSLisandro Dalcin # if DESTDIR is set, then we're building against PETSc in a staging 310f46a955bSLisandro Dalcin # directory, but rpath needs to point to final install directory. 311f46a955bSLisandro Dalcin rpath = strip_prefix(self.DESTDIR, self['PETSC_LIB_DIR']) 312f46a955bSLisandro Dalcin petsc_lib['runtime_library_dirs'].append(rpath) 313f46a955bSLisandro Dalcin 314f46a955bSLisandro Dalcin # Link in extra libraries on static builds 315f46a955bSLisandro Dalcin if self['BUILDSHAREDLIB'] != 'yes': 316f46a955bSLisandro Dalcin petsc_ext_lib = split_quoted(self['PETSC_EXTERNAL_LIB_BASIC']) 317f46a955bSLisandro Dalcin petsc_lib['extra_link_args'].extend(petsc_ext_lib) 318ec81f945SPierre Jolivet self._configure_ext(extension, petsc_inc, append=True) 319f46a955bSLisandro Dalcin self._configure_ext(extension, petsc_lib) 320f46a955bSLisandro Dalcin 321f46a955bSLisandro Dalcin def configure_compiler(self, compiler): 322f46a955bSLisandro Dalcin if compiler.compiler_type != 'unix': return 323f46a955bSLisandro Dalcin getenv = os.environ.get 324f46a955bSLisandro Dalcin # distutils C/C++ compiler 325f46a955bSLisandro Dalcin (cc, cflags, ccshared, cxx) = get_config_vars( 326f46a955bSLisandro Dalcin 'CC', 'CFLAGS', 'CCSHARED', 'CXX') 327f46a955bSLisandro Dalcin ccshared = getenv('CCSHARED', ccshared or '') 328f46a955bSLisandro Dalcin cflags = getenv('CFLAGS', cflags or '') 329f46a955bSLisandro Dalcin cflags = cflags.replace('-Wstrict-prototypes', '') 330f46a955bSLisandro Dalcin # distutils linker 331f46a955bSLisandro Dalcin (ldflags, ldshared, so_ext) = get_config_vars( 332f46a955bSLisandro Dalcin 'LDFLAGS', 'LDSHARED', 'SO') 333f46a955bSLisandro Dalcin ld = cc 334f46a955bSLisandro Dalcin ldshared = getenv('LDSHARED', ldshared) 335f46a955bSLisandro Dalcin ldflags = getenv('LDFLAGS', cflags + ' ' + (ldflags or '')) 336f46a955bSLisandro Dalcin ldcmd = split_quoted(ld) + split_quoted(ldflags) 337e35c6634SSatish Balay ldshared = [flg for flg in split_quoted(ldshared) if flg not in ldcmd and (flg.find('/lib/spack/env')<0)] 338f46a955bSLisandro Dalcin ldshared = str.join(' ', ldshared) 339f46a955bSLisandro Dalcin # 340f46a955bSLisandro Dalcin def get_flags(cmd): 341f46a955bSLisandro Dalcin if not cmd: return '' 342f46a955bSLisandro Dalcin cmd = split_quoted(cmd) 343f46a955bSLisandro Dalcin if os.path.basename(cmd[0]) == 'xcrun': 344f46a955bSLisandro Dalcin del cmd[0] 345f46a955bSLisandro Dalcin while True: 346f46a955bSLisandro Dalcin if cmd[0] == '-sdk': 347f46a955bSLisandro Dalcin del cmd[0:2] 348f46a955bSLisandro Dalcin continue 349f46a955bSLisandro Dalcin if cmd[0] == '-log': 350f46a955bSLisandro Dalcin del cmd[0] 351f46a955bSLisandro Dalcin continue 352f46a955bSLisandro Dalcin break 353f46a955bSLisandro Dalcin return ' '.join(cmd[1:]) 354f46a955bSLisandro Dalcin # PETSc C compiler 355f46a955bSLisandro Dalcin PCC = self['PCC'] 356f46a955bSLisandro Dalcin PCC_FLAGS = get_flags(cc) + ' ' + self['PCC_FLAGS'] 357f46a955bSLisandro Dalcin PCC_FLAGS = PCC_FLAGS.replace('-fvisibility=hidden', '') 358f46a955bSLisandro Dalcin PCC = getenv('PCC', PCC) + ' ' + getenv('PCCFLAGS', PCC_FLAGS) 359f46a955bSLisandro Dalcin PCC_SHARED = str.join(' ', (PCC, ccshared, cflags)) 360f46a955bSLisandro Dalcin # PETSc C++ compiler 361f46a955bSLisandro Dalcin PCXX = PCC if self.language == 'c++' else self.get('CXX', cxx) 362f46a955bSLisandro Dalcin # PETSc linker 363f46a955bSLisandro Dalcin PLD = self['PCC_LINKER'] 364f46a955bSLisandro Dalcin PLD_FLAGS = get_flags(ld) + ' ' + self['PCC_LINKER_FLAGS'] 365f46a955bSLisandro Dalcin PLD_FLAGS = PLD_FLAGS.replace('-fvisibility=hidden', '') 366f46a955bSLisandro Dalcin PLD = getenv('PLD', PLD) + ' ' + getenv('PLDFLAGS', PLD_FLAGS) 367f46a955bSLisandro Dalcin PLD_SHARED = str.join(' ', (PLD, ldshared, ldflags)) 368f46a955bSLisandro Dalcin # 369f46a955bSLisandro Dalcin compiler.set_executables( 370f46a955bSLisandro Dalcin compiler = PCC, 371f46a955bSLisandro Dalcin compiler_cxx = PCXX, 372f46a955bSLisandro Dalcin linker_exe = PLD, 373f46a955bSLisandro Dalcin compiler_so = PCC_SHARED, 374f46a955bSLisandro Dalcin linker_so = PLD_SHARED, 375f46a955bSLisandro Dalcin ) 376f46a955bSLisandro Dalcin compiler.shared_lib_extension = so_ext 377f46a955bSLisandro Dalcin # 378f46a955bSLisandro Dalcin if sys.platform == 'darwin': 379f46a955bSLisandro Dalcin for attr in ('preprocessor', 380f46a955bSLisandro Dalcin 'compiler', 'compiler_cxx', 'compiler_so', 381f46a955bSLisandro Dalcin 'linker_so', 'linker_exe'): 382f46a955bSLisandro Dalcin compiler_cmd = getattr(compiler, attr, []) 383f46a955bSLisandro Dalcin while '-mno-fused-madd' in compiler_cmd: 384f46a955bSLisandro Dalcin compiler_cmd.remove('-mno-fused-madd') 385f46a955bSLisandro Dalcin 386f46a955bSLisandro Dalcin def log_info(self): 387f46a955bSLisandro Dalcin PETSC_DIR = self['PETSC_DIR'] 388f46a955bSLisandro Dalcin PETSC_ARCH = self['PETSC_ARCH'] 389f46a955bSLisandro Dalcin version = ".".join([str(i) for i in self.version[0]]) 390f46a955bSLisandro Dalcin release = ("development", "release")[self.version[1]] 391f46a955bSLisandro Dalcin version_info = version + ' ' + release 392f46a955bSLisandro Dalcin integer_size = '%s-bit' % self['PETSC_INDEX_SIZE'] 393f46a955bSLisandro Dalcin scalar_type = self['PETSC_SCALAR'] 394f46a955bSLisandro Dalcin precision = self['PETSC_PRECISION'] 395f46a955bSLisandro Dalcin language = self['PETSC_LANGUAGE'] 396f46a955bSLisandro Dalcin compiler = self['PCC'] 397f46a955bSLisandro Dalcin linker = self['PCC_LINKER'] 398f46a955bSLisandro Dalcin log.info('PETSC_DIR: %s' % PETSC_DIR ) 399f46a955bSLisandro Dalcin log.info('PETSC_ARCH: %s' % PETSC_ARCH ) 400f46a955bSLisandro Dalcin log.info('version: %s' % version_info) 401f46a955bSLisandro Dalcin log.info('integer-size: %s' % integer_size) 402f46a955bSLisandro Dalcin log.info('scalar-type: %s' % scalar_type) 403f46a955bSLisandro Dalcin log.info('precision: %s' % precision) 404f46a955bSLisandro Dalcin log.info('language: %s' % language) 405f46a955bSLisandro Dalcin log.info('compiler: %s' % compiler) 406f46a955bSLisandro Dalcin log.info('linker: %s' % linker) 407f46a955bSLisandro Dalcin 408f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 409f46a955bSLisandro Dalcin 410f46a955bSLisandro Dalcinclass Extension(_Extension): 411f46a955bSLisandro Dalcin pass 412f46a955bSLisandro Dalcin 413f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 414f46a955bSLisandro Dalcin 415f46a955bSLisandro Dalcincmd_petsc_opts = [ 416f46a955bSLisandro Dalcin ('petsc-dir=', None, 417f46a955bSLisandro Dalcin "define PETSC_DIR, overriding environmental variables"), 418f46a955bSLisandro Dalcin ('petsc-arch=', None, 419f46a955bSLisandro Dalcin "define PETSC_ARCH, overriding environmental variables"), 420f46a955bSLisandro Dalcin ] 421f46a955bSLisandro Dalcin 422f46a955bSLisandro Dalcin 423f46a955bSLisandro Dalcinclass config(_config): 424f46a955bSLisandro Dalcin 425f46a955bSLisandro Dalcin Configure = PetscConfig 426f46a955bSLisandro Dalcin 427f46a955bSLisandro Dalcin user_options = _config.user_options + cmd_petsc_opts 428f46a955bSLisandro Dalcin 429f46a955bSLisandro Dalcin def initialize_options(self): 430f46a955bSLisandro Dalcin _config.initialize_options(self) 431f46a955bSLisandro Dalcin self.petsc_dir = None 432f46a955bSLisandro Dalcin self.petsc_arch = None 433f46a955bSLisandro Dalcin 434f46a955bSLisandro Dalcin def get_config_arch(self, arch): 435f46a955bSLisandro Dalcin return config.Configure(self.petsc_dir, arch) 436f46a955bSLisandro Dalcin 437f46a955bSLisandro Dalcin def run(self): 438f46a955bSLisandro Dalcin _config.run(self) 439f46a955bSLisandro Dalcin self.petsc_dir = config.get_petsc_dir(self.petsc_dir) 440f46a955bSLisandro Dalcin if self.petsc_dir is None: return 441f46a955bSLisandro Dalcin petsc_arch = config.get_petsc_arch(self.petsc_dir, self.petsc_arch) 442f46a955bSLisandro Dalcin log.info('-' * 70) 443f46a955bSLisandro Dalcin log.info('PETSC_DIR: %s' % self.petsc_dir) 444f46a955bSLisandro Dalcin arch_list = petsc_arch 445f46a955bSLisandro Dalcin if not arch_list : 446f46a955bSLisandro Dalcin arch_list = [ None ] 447f46a955bSLisandro Dalcin for arch in arch_list: 448f46a955bSLisandro Dalcin conf = self.get_config_arch(arch) 449f46a955bSLisandro Dalcin archname = conf.PETSC_ARCH or conf['PETSC_ARCH'] 450f46a955bSLisandro Dalcin scalar_type = conf['PETSC_SCALAR'] 451f46a955bSLisandro Dalcin precision = conf['PETSC_PRECISION'] 452f46a955bSLisandro Dalcin language = conf['PETSC_LANGUAGE'] 453f46a955bSLisandro Dalcin compiler = conf['PCC'] 454f46a955bSLisandro Dalcin linker = conf['PCC_LINKER'] 455f46a955bSLisandro Dalcin log.info('-'*70) 456f46a955bSLisandro Dalcin log.info('PETSC_ARCH: %s' % archname) 457f46a955bSLisandro Dalcin log.info(' * scalar-type: %s' % scalar_type) 458f46a955bSLisandro Dalcin log.info(' * precision: %s' % precision) 459f46a955bSLisandro Dalcin log.info(' * language: %s' % language) 460f46a955bSLisandro Dalcin log.info(' * compiler: %s' % compiler) 461f46a955bSLisandro Dalcin log.info(' * linker: %s' % linker) 462f46a955bSLisandro Dalcin log.info('-' * 70) 463f46a955bSLisandro Dalcin 464f46a955bSLisandro Dalcin #@staticmethod 465f46a955bSLisandro Dalcin def get_petsc_dir(petsc_dir): 466f46a955bSLisandro Dalcin if not petsc_dir: return None 467f46a955bSLisandro Dalcin petsc_dir = os.path.expandvars(petsc_dir) 468f46a955bSLisandro Dalcin if not petsc_dir or '$PETSC_DIR' in petsc_dir: 469f46a955bSLisandro Dalcin try: 470f46a955bSLisandro Dalcin import petsc 471f46a955bSLisandro Dalcin petsc_dir = petsc.get_petsc_dir() 472f46a955bSLisandro Dalcin except ImportError: 473f46a955bSLisandro Dalcin log.warn("PETSC_DIR not specified") 474f46a955bSLisandro Dalcin return None 475f46a955bSLisandro Dalcin petsc_dir = os.path.expanduser(petsc_dir) 476f46a955bSLisandro Dalcin petsc_dir = os.path.abspath(petsc_dir) 477f46a955bSLisandro Dalcin return config.chk_petsc_dir(petsc_dir) 478f46a955bSLisandro Dalcin get_petsc_dir = staticmethod(get_petsc_dir) 479f46a955bSLisandro Dalcin 480f46a955bSLisandro Dalcin #@staticmethod 481f46a955bSLisandro Dalcin def chk_petsc_dir(petsc_dir): 482f46a955bSLisandro Dalcin if not os.path.isdir(petsc_dir): 483f46a955bSLisandro Dalcin log.error('invalid PETSC_DIR: %s (ignored)' % petsc_dir) 484f46a955bSLisandro Dalcin return None 485f46a955bSLisandro Dalcin return petsc_dir 486f46a955bSLisandro Dalcin chk_petsc_dir = staticmethod(chk_petsc_dir) 487f46a955bSLisandro Dalcin 488f46a955bSLisandro Dalcin #@staticmethod 489f46a955bSLisandro Dalcin def get_petsc_arch(petsc_dir, petsc_arch): 490f46a955bSLisandro Dalcin if not petsc_dir: return None 491f46a955bSLisandro Dalcin petsc_arch = os.path.expandvars(petsc_arch) 492f46a955bSLisandro Dalcin if (not petsc_arch or '$PETSC_ARCH' in petsc_arch): 493f46a955bSLisandro Dalcin petsc_arch = '' 494f46a955bSLisandro Dalcin petsc_conf = os.path.join(petsc_dir, 'lib', 'petsc', 'conf') 495f46a955bSLisandro Dalcin if os.path.isdir(petsc_conf): 496f46a955bSLisandro Dalcin petscvariables = os.path.join(petsc_conf, 'petscvariables') 497f46a955bSLisandro Dalcin if os.path.exists(petscvariables): 498f46a955bSLisandro Dalcin conf = makefile(open(petscvariables, 'rt')) 499f46a955bSLisandro Dalcin petsc_arch = conf.get('PETSC_ARCH', '') 500f46a955bSLisandro Dalcin petsc_arch = petsc_arch.split(os.pathsep) 501f46a955bSLisandro Dalcin petsc_arch = unique(petsc_arch) 502f46a955bSLisandro Dalcin petsc_arch = [arch for arch in petsc_arch if arch] 503f46a955bSLisandro Dalcin return config.chk_petsc_arch(petsc_dir, petsc_arch) 504f46a955bSLisandro Dalcin get_petsc_arch = staticmethod(get_petsc_arch) 505f46a955bSLisandro Dalcin 506f46a955bSLisandro Dalcin #@staticmethod 507f46a955bSLisandro Dalcin def chk_petsc_arch(petsc_dir, petsc_arch): 508f46a955bSLisandro Dalcin valid_archs = [] 509f46a955bSLisandro Dalcin for arch in petsc_arch: 510f46a955bSLisandro Dalcin arch_path = os.path.join(petsc_dir, arch) 511f46a955bSLisandro Dalcin if os.path.isdir(arch_path): 512f46a955bSLisandro Dalcin valid_archs.append(arch) 513f46a955bSLisandro Dalcin else: 514f46a955bSLisandro Dalcin log.warn("invalid PETSC_ARCH: %s (ignored)" % arch) 515f46a955bSLisandro Dalcin return valid_archs 516f46a955bSLisandro Dalcin chk_petsc_arch = staticmethod(chk_petsc_arch) 517f46a955bSLisandro Dalcin 518f46a955bSLisandro Dalcin 519f46a955bSLisandro Dalcinclass build(_build): 520f46a955bSLisandro Dalcin 52155a74a43SLisandro Dalcin user_options = _build.user_options 52255a74a43SLisandro Dalcin user_options += [( 52355a74a43SLisandro Dalcin 'inplace', 52455a74a43SLisandro Dalcin 'i', 52555a74a43SLisandro Dalcin "ignore build-lib and put compiled extensions into the source " 52655a74a43SLisandro Dalcin "directory alongside your pure Python modules", 52755a74a43SLisandro Dalcin )] 52855a74a43SLisandro Dalcin user_options += cmd_petsc_opts 52955a74a43SLisandro Dalcin 53055a74a43SLisandro Dalcin boolean_options = _build.boolean_options 53155a74a43SLisandro Dalcin boolean_options += ['inplace'] 532f46a955bSLisandro Dalcin 533f46a955bSLisandro Dalcin def initialize_options(self): 534f46a955bSLisandro Dalcin _build.initialize_options(self) 53555a74a43SLisandro Dalcin self.inplace = None 536f46a955bSLisandro Dalcin self.petsc_dir = None 537f46a955bSLisandro Dalcin self.petsc_arch = None 538f46a955bSLisandro Dalcin 539f46a955bSLisandro Dalcin def finalize_options(self): 540f46a955bSLisandro Dalcin _build.finalize_options(self) 54155a74a43SLisandro Dalcin if self.inplace is None: 54255a74a43SLisandro Dalcin self.inplace = False 543f46a955bSLisandro Dalcin self.set_undefined_options('config', 544f46a955bSLisandro Dalcin ('petsc_dir', 'petsc_dir'), 545f46a955bSLisandro Dalcin ('petsc_arch', 'petsc_arch')) 546f46a955bSLisandro Dalcin self.petsc_dir = config.get_petsc_dir(self.petsc_dir) 547f46a955bSLisandro Dalcin self.petsc_arch = config.get_petsc_arch(self.petsc_dir, 548f46a955bSLisandro Dalcin self.petsc_arch) 549f46a955bSLisandro Dalcin 550f46a955bSLisandro Dalcin sub_commands = \ 551f46a955bSLisandro Dalcin [('build_src', lambda *args: True)] + \ 552f46a955bSLisandro Dalcin _build.sub_commands 553f46a955bSLisandro Dalcin 554f46a955bSLisandro Dalcin 555f46a955bSLisandro Dalcinclass build_src(Command): 556f46a955bSLisandro Dalcin description = "build C sources from Cython files" 557f46a955bSLisandro Dalcin 558f46a955bSLisandro Dalcin user_options = [ 559f46a955bSLisandro Dalcin ('force', 'f', 560f46a955bSLisandro Dalcin "forcibly build everything (ignore file timestamps)"), 561f46a955bSLisandro Dalcin ] 562f46a955bSLisandro Dalcin 563f46a955bSLisandro Dalcin boolean_options = ['force'] 564f46a955bSLisandro Dalcin 565f46a955bSLisandro Dalcin def initialize_options(self): 566f46a955bSLisandro Dalcin self.force = False 567f46a955bSLisandro Dalcin 568f46a955bSLisandro Dalcin def finalize_options(self): 569f46a955bSLisandro Dalcin self.set_undefined_options('build', 570f46a955bSLisandro Dalcin ('force', 'force'), 571f46a955bSLisandro Dalcin ) 572f46a955bSLisandro Dalcin 573f46a955bSLisandro Dalcin def run(self): 574f46a955bSLisandro Dalcin sources = getattr(self, 'sources', []) 575f46a955bSLisandro Dalcin for source in sources: 576f46a955bSLisandro Dalcin cython_run( 577f46a955bSLisandro Dalcin force=self.force, 578f46a955bSLisandro Dalcin VERSION=cython_req(), 579f46a955bSLisandro Dalcin **source 580f46a955bSLisandro Dalcin ) 581f46a955bSLisandro Dalcin 582f46a955bSLisandro Dalcin 583f46a955bSLisandro Dalcinclass build_ext(_build_ext): 584f46a955bSLisandro Dalcin 585f46a955bSLisandro Dalcin user_options = _build_ext.user_options + cmd_petsc_opts 586f46a955bSLisandro Dalcin 587f46a955bSLisandro Dalcin def initialize_options(self): 588f46a955bSLisandro Dalcin _build_ext.initialize_options(self) 58955a74a43SLisandro Dalcin self.inplace = None 590f46a955bSLisandro Dalcin self.petsc_dir = None 591f46a955bSLisandro Dalcin self.petsc_arch = None 592f46a955bSLisandro Dalcin self._outputs = [] 593f46a955bSLisandro Dalcin 594f46a955bSLisandro Dalcin def finalize_options(self): 595f46a955bSLisandro Dalcin _build_ext.finalize_options(self) 59655a74a43SLisandro Dalcin self.set_undefined_options('build', ('inplace', 'inplace')) 597f46a955bSLisandro Dalcin self.set_undefined_options('build', 598f46a955bSLisandro Dalcin ('petsc_dir', 'petsc_dir'), 599f46a955bSLisandro Dalcin ('petsc_arch', 'petsc_arch')) 600f46a955bSLisandro Dalcin if ((sys.platform.startswith('linux') or 601f46a955bSLisandro Dalcin sys.platform.startswith('gnu') or 602f46a955bSLisandro Dalcin sys.platform.startswith('sunos')) and 603f46a955bSLisandro Dalcin sysconfig.get_config_var('Py_ENABLE_SHARED')): 604f46a955bSLisandro Dalcin py_version = sysconfig.get_python_version() 605f46a955bSLisandro Dalcin bad_pylib_dir = os.path.join(sys.prefix, "lib", 606f46a955bSLisandro Dalcin "python" + py_version, 607f46a955bSLisandro Dalcin "config") 608f46a955bSLisandro Dalcin try: 609f46a955bSLisandro Dalcin self.library_dirs.remove(bad_pylib_dir) 610f46a955bSLisandro Dalcin except ValueError: 611f46a955bSLisandro Dalcin pass 612f46a955bSLisandro Dalcin pylib_dir = sysconfig.get_config_var("LIBDIR") 613f46a955bSLisandro Dalcin if pylib_dir not in self.library_dirs: 614f46a955bSLisandro Dalcin self.library_dirs.append(pylib_dir) 615f46a955bSLisandro Dalcin if pylib_dir not in self.rpath: 616f46a955bSLisandro Dalcin self.rpath.append(pylib_dir) 617f46a955bSLisandro Dalcin if sys.exec_prefix == '/usr': 618f46a955bSLisandro Dalcin self.library_dirs.remove(pylib_dir) 619f46a955bSLisandro Dalcin self.rpath.remove(pylib_dir) 620f46a955bSLisandro Dalcin 621f46a955bSLisandro Dalcin def _copy_ext(self, ext): 622f46a955bSLisandro Dalcin extclass = ext.__class__ 623f46a955bSLisandro Dalcin fullname = self.get_ext_fullname(ext.name) 624f46a955bSLisandro Dalcin modpath = str.split(fullname, '.') 625f46a955bSLisandro Dalcin pkgpath = os.path.join('', *modpath[0:-1]) 626f46a955bSLisandro Dalcin name = modpath[-1] 627f46a955bSLisandro Dalcin sources = list(ext.sources) 628f46a955bSLisandro Dalcin newext = extclass(name, sources) 629f46a955bSLisandro Dalcin newext.__dict__.update(copy.deepcopy(ext.__dict__)) 630f46a955bSLisandro Dalcin newext.name = name 631f46a955bSLisandro Dalcin return pkgpath, newext 632f46a955bSLisandro Dalcin 633f46a955bSLisandro Dalcin def _build_ext_arch(self, ext, pkgpath, arch): 634f46a955bSLisandro Dalcin build_temp = self.build_temp 635f46a955bSLisandro Dalcin build_lib = self.build_lib 636f46a955bSLisandro Dalcin try: 637f46a955bSLisandro Dalcin self.build_temp = os.path.join(build_temp, arch) 638f46a955bSLisandro Dalcin self.build_lib = os.path.join(build_lib, pkgpath, arch) 639f46a955bSLisandro Dalcin _build_ext.build_extension(self, ext) 640f46a955bSLisandro Dalcin finally: 641f46a955bSLisandro Dalcin self.build_temp = build_temp 642f46a955bSLisandro Dalcin self.build_lib = build_lib 643f46a955bSLisandro Dalcin 644f46a955bSLisandro Dalcin def get_config_arch(self, arch): 645f46a955bSLisandro Dalcin return config.Configure(self.petsc_dir, arch) 646f46a955bSLisandro Dalcin 647f46a955bSLisandro Dalcin def build_extension(self, ext): 648f46a955bSLisandro Dalcin if not isinstance(ext, Extension): 649f46a955bSLisandro Dalcin return _build_ext.build_extension(self, ext) 650f46a955bSLisandro Dalcin petsc_arch = self.petsc_arch 651f46a955bSLisandro Dalcin if not petsc_arch: 652f46a955bSLisandro Dalcin petsc_arch = [ None ] 653f46a955bSLisandro Dalcin for arch in petsc_arch: 654f46a955bSLisandro Dalcin config = self.get_config_arch(arch) 655f46a955bSLisandro Dalcin ARCH = arch or config['PETSC_ARCH'] 656f46a955bSLisandro Dalcin if ARCH not in self.PETSC_ARCH_LIST: 657f46a955bSLisandro Dalcin self.PETSC_ARCH_LIST.append(ARCH) 658f46a955bSLisandro Dalcin self.DESTDIR = config.DESTDIR 659f46a955bSLisandro Dalcin ext.language = config.language 660f46a955bSLisandro Dalcin config.log_info() 661f46a955bSLisandro Dalcin pkgpath, newext = self._copy_ext(ext) 662f46a955bSLisandro Dalcin config.configure(newext, self.compiler) 663f46a955bSLisandro Dalcin self._build_ext_arch(newext, pkgpath, ARCH) 664f46a955bSLisandro Dalcin 665f46a955bSLisandro Dalcin def run(self): 666f46a955bSLisandro Dalcin self.build_sources() 667f46a955bSLisandro Dalcin _build_ext.run(self) 668f46a955bSLisandro Dalcin 669f46a955bSLisandro Dalcin def build_sources(self): 670f46a955bSLisandro Dalcin if 'build_src' in self.distribution.cmdclass: 671f46a955bSLisandro Dalcin self.run_command('build_src') 672f46a955bSLisandro Dalcin 673f46a955bSLisandro Dalcin def build_extensions(self, *args, **kargs): 674f46a955bSLisandro Dalcin self.PETSC_ARCH_LIST = [] 675f46a955bSLisandro Dalcin _build_ext.build_extensions(self, *args,**kargs) 676f46a955bSLisandro Dalcin if not self.PETSC_ARCH_LIST: return 677f46a955bSLisandro Dalcin self.build_configuration(self.PETSC_ARCH_LIST) 678f46a955bSLisandro Dalcin 679f46a955bSLisandro Dalcin def build_configuration(self, arch_list): 680f46a955bSLisandro Dalcin # 681f46a955bSLisandro Dalcin template, variables = self.get_config_data(arch_list) 682f46a955bSLisandro Dalcin config_data = template % variables 683f46a955bSLisandro Dalcin # 684f46a955bSLisandro Dalcin build_lib = self.build_lib 685f46a955bSLisandro Dalcin dist_name = self.distribution.get_name() 686f46a955bSLisandro Dalcin config_file = os.path.join(build_lib, dist_name, 'lib', 687f46a955bSLisandro Dalcin dist_name.replace('4py', '') + '.cfg') 688f46a955bSLisandro Dalcin # 689f46a955bSLisandro Dalcin def write_file(filename, data): 690f46a955bSLisandro Dalcin with open(filename, 'w') as fh: 691f46a955bSLisandro Dalcin fh.write(config_data) 692f46a955bSLisandro Dalcin execute(write_file, (config_file, config_data), 693f46a955bSLisandro Dalcin msg='writing %s' % config_file, 694f46a955bSLisandro Dalcin verbose=self.verbose, dry_run=self.dry_run) 695f46a955bSLisandro Dalcin 696f46a955bSLisandro Dalcin def get_config_data(self, arch_list): 697f46a955bSLisandro Dalcin DESTDIR = self.DESTDIR 698f46a955bSLisandro Dalcin template = "\n".join([ 699f46a955bSLisandro Dalcin "PETSC_DIR = %(PETSC_DIR)s", 700f46a955bSLisandro Dalcin "PETSC_ARCH = %(PETSC_ARCH)s", 701f46a955bSLisandro Dalcin ]) + "\n" 702f46a955bSLisandro Dalcin variables = { 703f46a955bSLisandro Dalcin 'PETSC_DIR' : strip_prefix(DESTDIR, self.petsc_dir), 704f46a955bSLisandro Dalcin 'PETSC_ARCH' : os.path.pathsep.join(arch_list), 705f46a955bSLisandro Dalcin } 706f46a955bSLisandro Dalcin return template, variables 707f46a955bSLisandro Dalcin 708f46a955bSLisandro Dalcin def copy_extensions_to_source(self): 709f46a955bSLisandro Dalcin build_py = self.get_finalized_command('build_py') 710f46a955bSLisandro Dalcin for ext in self.extensions: 711f46a955bSLisandro Dalcin inp_file, reg_file = self._get_inplace_equivalent(build_py, ext) 712f46a955bSLisandro Dalcin 713f46a955bSLisandro Dalcin arch_list = [''] 714f46a955bSLisandro Dalcin if isinstance(ext, Extension) and self.petsc_arch: 715f46a955bSLisandro Dalcin arch_list = self.petsc_arch[:] 716f46a955bSLisandro Dalcin 717f46a955bSLisandro Dalcin file_pairs = [] 718f46a955bSLisandro Dalcin inp_head, inp_tail = os.path.split(inp_file) 719f46a955bSLisandro Dalcin reg_head, reg_tail = os.path.split(reg_file) 720f46a955bSLisandro Dalcin for arch in arch_list: 721f46a955bSLisandro Dalcin inp_file = os.path.join(inp_head, arch, inp_tail) 722f46a955bSLisandro Dalcin reg_file = os.path.join(reg_head, arch, reg_tail) 723f46a955bSLisandro Dalcin file_pairs.append((inp_file, reg_file)) 724f46a955bSLisandro Dalcin 725f46a955bSLisandro Dalcin for inp_file, reg_file in file_pairs: 726f46a955bSLisandro Dalcin if os.path.exists(reg_file) or not ext.optional: 727f46a955bSLisandro Dalcin dest_dir, _ = os.path.split(inp_file) 728f46a955bSLisandro Dalcin self.mkpath(dest_dir) 729f46a955bSLisandro Dalcin self.copy_file(reg_file, inp_file, level=self.verbose) 730f46a955bSLisandro Dalcin 731f46a955bSLisandro Dalcin def get_outputs(self): 732f46a955bSLisandro Dalcin self.check_extensions_list(self.extensions) 733f46a955bSLisandro Dalcin outputs = [] 734f46a955bSLisandro Dalcin for ext in self.extensions: 735f46a955bSLisandro Dalcin fullname = self.get_ext_fullname(ext.name) 736f46a955bSLisandro Dalcin filename = self.get_ext_filename(fullname) 737f46a955bSLisandro Dalcin if isinstance(ext, Extension) and self.petsc_arch: 738f46a955bSLisandro Dalcin head, tail = os.path.split(filename) 739f46a955bSLisandro Dalcin for arch in self.petsc_arch: 740f46a955bSLisandro Dalcin outfile = os.path.join(self.build_lib, head, arch, tail) 741f46a955bSLisandro Dalcin outputs.append(outfile) 742f46a955bSLisandro Dalcin else: 743f46a955bSLisandro Dalcin outfile = os.path.join(self.build_lib, filename) 744f46a955bSLisandro Dalcin outputs.append(outfile) 745f46a955bSLisandro Dalcin outputs = list(set(outputs)) 746f46a955bSLisandro Dalcin return outputs 747f46a955bSLisandro Dalcin 748f46a955bSLisandro Dalcin 749f46a955bSLisandro Dalcinclass install(_install): 750f46a955bSLisandro Dalcin 751f46a955bSLisandro Dalcin def initialize_options(self): 752f46a955bSLisandro Dalcin with warnings.catch_warnings(): 753f46a955bSLisandro Dalcin if setuptools: 754f46a955bSLisandro Dalcin if hasattr(setuptools, 'SetuptoolsDeprecationWarning'): 755f46a955bSLisandro Dalcin category = setuptools.SetuptoolsDeprecationWarning 756f46a955bSLisandro Dalcin warnings.simplefilter('ignore', category) 757f46a955bSLisandro Dalcin _install.initialize_options(self) 758f46a955bSLisandro Dalcin self.old_and_unmanageable = True 759f46a955bSLisandro Dalcin 760f46a955bSLisandro Dalcin 761f46a955bSLisandro Dalcincmdclass_list = [ 762f46a955bSLisandro Dalcin config, 763f46a955bSLisandro Dalcin build, 764f46a955bSLisandro Dalcin build_src, 765f46a955bSLisandro Dalcin build_ext, 766f46a955bSLisandro Dalcin install, 767f46a955bSLisandro Dalcin] 768f46a955bSLisandro Dalcin 769f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 770f46a955bSLisandro Dalcin 771f46a955bSLisandro Dalcindef setup(**attrs): 772f46a955bSLisandro Dalcin cmdclass = attrs.setdefault('cmdclass', {}) 773f46a955bSLisandro Dalcin for cmd in cmdclass_list: 774f46a955bSLisandro Dalcin cmdclass.setdefault(cmd.__name__, cmd) 775f46a955bSLisandro Dalcin build_src.sources = attrs.pop('cython_sources', None) 776f46a955bSLisandro Dalcin use_setup_requires = False # handle Cython requirement ourselves 777f46a955bSLisandro Dalcin if setuptools and build_src.sources and use_setup_requires: 778f46a955bSLisandro Dalcin version = cython_req() 779f46a955bSLisandro Dalcin if not cython_chk(version, verbose=False): 780f46a955bSLisandro Dalcin reqs = attrs.setdefault('setup_requires', []) 781223a8ff9SLisandro Dalcin reqs += ['Cython=='+version] 782f46a955bSLisandro Dalcin return _setup(**attrs) 783f46a955bSLisandro Dalcin 784f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 785f46a955bSLisandro Dalcin 786f46a955bSLisandro Dalcinif setuptools: 787f46a955bSLisandro Dalcin try: 788f46a955bSLisandro Dalcin from setuptools.command import egg_info as mod_egg_info 789f46a955bSLisandro Dalcin _FileList = mod_egg_info.FileList 790f46a955bSLisandro Dalcin class FileList(_FileList): 791f46a955bSLisandro Dalcin def process_template_line(self, line): 792f46a955bSLisandro Dalcin level = log.set_threshold(log.ERROR) 793f46a955bSLisandro Dalcin try: 794f46a955bSLisandro Dalcin _FileList.process_template_line(self, line) 795f46a955bSLisandro Dalcin finally: 796f46a955bSLisandro Dalcin log.set_threshold(level) 797f46a955bSLisandro Dalcin mod_egg_info.FileList = FileList 798f46a955bSLisandro Dalcin except (ImportError, AttributeError): 799f46a955bSLisandro Dalcin pass 800f46a955bSLisandro Dalcin 801f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 802f46a955bSLisandro Dalcin 803f46a955bSLisandro Dalcindef append(seq, item): 804f46a955bSLisandro Dalcin if item not in seq: 805f46a955bSLisandro Dalcin seq.append(item) 806f46a955bSLisandro Dalcin 807f46a955bSLisandro Dalcindef append_dict(conf, dct): 808f46a955bSLisandro Dalcin for key, values in dct.items(): 809f46a955bSLisandro Dalcin if key in conf: 810f46a955bSLisandro Dalcin for value in values: 811f46a955bSLisandro Dalcin if value not in conf[key]: 812f46a955bSLisandro Dalcin conf[key].append(value) 813f46a955bSLisandro Dalcindef unique(seq): 814f46a955bSLisandro Dalcin res = [] 815f46a955bSLisandro Dalcin for item in seq: 816f46a955bSLisandro Dalcin if item not in res: 817f46a955bSLisandro Dalcin res.append(item) 818f46a955bSLisandro Dalcin return res 819f46a955bSLisandro Dalcin 820f46a955bSLisandro Dalcindef flaglist(flags): 821f46a955bSLisandro Dalcin 822f46a955bSLisandro Dalcin conf = { 823f46a955bSLisandro Dalcin 'define_macros' : [], 824f46a955bSLisandro Dalcin 'undef_macros' : [], 825f46a955bSLisandro Dalcin 'include_dirs' : [], 826f46a955bSLisandro Dalcin 827f46a955bSLisandro Dalcin 'libraries' : [], 828f46a955bSLisandro Dalcin 'library_dirs' : [], 829f46a955bSLisandro Dalcin 'runtime_library_dirs': [], 830f46a955bSLisandro Dalcin 831f46a955bSLisandro Dalcin 'extra_compile_args' : [], 832f46a955bSLisandro Dalcin 'extra_link_args' : [], 833f46a955bSLisandro Dalcin } 834f46a955bSLisandro Dalcin 835f46a955bSLisandro Dalcin if type(flags) is str: 836f46a955bSLisandro Dalcin flags = flags.split() 837f46a955bSLisandro Dalcin 838f46a955bSLisandro Dalcin switch = '-Wl,' 839f46a955bSLisandro Dalcin newflags = [] 840f46a955bSLisandro Dalcin linkopts = [] 841f46a955bSLisandro Dalcin for f in flags: 842f46a955bSLisandro Dalcin if f.startswith(switch): 843f46a955bSLisandro Dalcin if len(f) > 4: 844f46a955bSLisandro Dalcin append(linkopts, f[4:]) 845f46a955bSLisandro Dalcin else: 846f46a955bSLisandro Dalcin append(newflags, f) 847f46a955bSLisandro Dalcin if linkopts: 848f46a955bSLisandro Dalcin newflags.append(switch + ','.join(linkopts)) 849f46a955bSLisandro Dalcin flags = newflags 850f46a955bSLisandro Dalcin 851f46a955bSLisandro Dalcin append_next_word = None 852f46a955bSLisandro Dalcin 853f46a955bSLisandro Dalcin for word in flags: 854f46a955bSLisandro Dalcin 855f46a955bSLisandro Dalcin if append_next_word is not None: 856f46a955bSLisandro Dalcin append(append_next_word, word) 857f46a955bSLisandro Dalcin append_next_word = None 858f46a955bSLisandro Dalcin continue 859f46a955bSLisandro Dalcin 860f46a955bSLisandro Dalcin switch, value = word[0:2], word[2:] 861f46a955bSLisandro Dalcin 862f46a955bSLisandro Dalcin if switch == "-I": 863f46a955bSLisandro Dalcin append(conf['include_dirs'], value) 864f46a955bSLisandro Dalcin elif switch == "-D": 865f46a955bSLisandro Dalcin try: 866f46a955bSLisandro Dalcin idx = value.index("=") 867f46a955bSLisandro Dalcin macro = (value[:idx], value[idx+1:]) 868f46a955bSLisandro Dalcin except ValueError: 869f46a955bSLisandro Dalcin macro = (value, None) 870f46a955bSLisandro Dalcin append(conf['define_macros'], macro) 871f46a955bSLisandro Dalcin elif switch == "-U": 872f46a955bSLisandro Dalcin append(conf['undef_macros'], value) 873f46a955bSLisandro Dalcin elif switch == "-l": 874f46a955bSLisandro Dalcin append(conf['libraries'], value) 875f46a955bSLisandro Dalcin elif switch == "-L": 876f46a955bSLisandro Dalcin append(conf['library_dirs'], value) 877f46a955bSLisandro Dalcin elif switch == "-R": 878f46a955bSLisandro Dalcin append(conf['runtime_library_dirs'], value) 879f46a955bSLisandro Dalcin elif word.startswith("-Wl"): 880f46a955bSLisandro Dalcin linkopts = word.split(',') 881f46a955bSLisandro Dalcin append_dict(conf, flaglist(linkopts[1:])) 882f46a955bSLisandro Dalcin elif word == "-rpath": 883f46a955bSLisandro Dalcin append_next_word = conf['runtime_library_dirs'] 884f46a955bSLisandro Dalcin elif word == "-Xlinker": 885f46a955bSLisandro Dalcin append_next_word = conf['extra_link_args'] 886f46a955bSLisandro Dalcin else: 887f46a955bSLisandro Dalcin #log.warn("unrecognized flag '%s'" % word) 888f46a955bSLisandro Dalcin pass 889f46a955bSLisandro Dalcin return conf 890f46a955bSLisandro Dalcin 891f46a955bSLisandro Dalcindef prepend_to_flags(path, flags): 892f46a955bSLisandro Dalcin """Prepend a path to compiler flags with absolute paths""" 893f46a955bSLisandro Dalcin if not path: 894f46a955bSLisandro Dalcin return flags 895f46a955bSLisandro Dalcin def append_path(m): 896f46a955bSLisandro Dalcin switch = m.group(1) 897f46a955bSLisandro Dalcin open_quote = m.group(4) 898f46a955bSLisandro Dalcin old_path = m.group(5) 899f46a955bSLisandro Dalcin close_quote = m.group(6) 900f46a955bSLisandro Dalcin if os.path.isabs(old_path): 901f46a955bSLisandro Dalcin moded_path = os.path.normpath(path + os.path.sep + old_path) 902f46a955bSLisandro Dalcin return switch + open_quote + moded_path + close_quote 903f46a955bSLisandro Dalcin return m.group(0) 904f46a955bSLisandro Dalcin return re.sub(r'((^|\s+)(-I|-L))(\s*["\']?)(\S+)(["\']?)', 905f46a955bSLisandro Dalcin append_path, flags) 906f46a955bSLisandro Dalcin 907f46a955bSLisandro Dalcindef strip_prefix(prefix, string): 908f46a955bSLisandro Dalcin if not prefix: 909f46a955bSLisandro Dalcin return string 910f46a955bSLisandro Dalcin return re.sub(r'^' + prefix, '', string) 911f46a955bSLisandro Dalcin 912f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 913f46a955bSLisandro Dalcin 914f46a955bSLisandro Dalcinfrom distutils.text_file import TextFile 915f46a955bSLisandro Dalcin 916f46a955bSLisandro Dalcin# Regexes needed for parsing Makefile-like syntaxes 917f46a955bSLisandro Dalcinimport re as _re 918*8acd7bfaSLisandro Dalcin_variable_rx = _re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") 919f46a955bSLisandro Dalcin_findvar1_rx = _re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") 920f46a955bSLisandro Dalcin_findvar2_rx = _re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") 921f46a955bSLisandro Dalcin 922f46a955bSLisandro Dalcindef makefile(fileobj, dct=None): 923f46a955bSLisandro Dalcin """Parse a Makefile-style file. 924f46a955bSLisandro Dalcin 925f46a955bSLisandro Dalcin A dictionary containing name/value pairs is returned. If an 926f46a955bSLisandro Dalcin optional dictionary is passed in as the second argument, it is 927f46a955bSLisandro Dalcin used instead of a new dictionary. 928f46a955bSLisandro Dalcin """ 929f46a955bSLisandro Dalcin fp = TextFile(file=fileobj, 930f46a955bSLisandro Dalcin strip_comments=1, 931f46a955bSLisandro Dalcin skip_blanks=1, 932f46a955bSLisandro Dalcin join_lines=1) 933f46a955bSLisandro Dalcin 934f46a955bSLisandro Dalcin if dct is None: 935f46a955bSLisandro Dalcin dct = {} 936f46a955bSLisandro Dalcin done = {} 937f46a955bSLisandro Dalcin notdone = {} 938f46a955bSLisandro Dalcin 939f46a955bSLisandro Dalcin while 1: 940f46a955bSLisandro Dalcin line = fp.readline() 941f46a955bSLisandro Dalcin if line is None: # eof 942f46a955bSLisandro Dalcin break 943f46a955bSLisandro Dalcin m = _variable_rx.match(line) 944f46a955bSLisandro Dalcin if m: 945f46a955bSLisandro Dalcin n, v = m.group(1, 2) 946f46a955bSLisandro Dalcin v = str.strip(v) 947f46a955bSLisandro Dalcin if "$" in v: 948f46a955bSLisandro Dalcin notdone[n] = v 949f46a955bSLisandro Dalcin else: 950f46a955bSLisandro Dalcin try: v = int(v) 951f46a955bSLisandro Dalcin except ValueError: pass 952f46a955bSLisandro Dalcin done[n] = v 953f46a955bSLisandro Dalcin try: del notdone[n] 954f46a955bSLisandro Dalcin except KeyError: pass 955f46a955bSLisandro Dalcin fp.close() 956f46a955bSLisandro Dalcin 957f46a955bSLisandro Dalcin # do variable interpolation here 958f46a955bSLisandro Dalcin while notdone: 959f46a955bSLisandro Dalcin for name in list(notdone.keys()): 960f46a955bSLisandro Dalcin value = notdone[name] 961f46a955bSLisandro Dalcin m = _findvar1_rx.search(value) or _findvar2_rx.search(value) 962f46a955bSLisandro Dalcin if m: 963f46a955bSLisandro Dalcin n = m.group(1) 964f46a955bSLisandro Dalcin found = True 965f46a955bSLisandro Dalcin if n in done: 966f46a955bSLisandro Dalcin item = str(done[n]) 967f46a955bSLisandro Dalcin elif n in notdone: 968f46a955bSLisandro Dalcin # get it on a subsequent round 969f46a955bSLisandro Dalcin found = False 970f46a955bSLisandro Dalcin else: 971f46a955bSLisandro Dalcin done[n] = item = "" 972f46a955bSLisandro Dalcin if found: 973f46a955bSLisandro Dalcin after = value[m.end():] 974f46a955bSLisandro Dalcin value = value[:m.start()] + item + after 975f46a955bSLisandro Dalcin if "$" in after: 976f46a955bSLisandro Dalcin notdone[name] = value 977f46a955bSLisandro Dalcin else: 978f46a955bSLisandro Dalcin try: value = int(value) 979f46a955bSLisandro Dalcin except ValueError: 980f46a955bSLisandro Dalcin done[name] = str.strip(value) 981f46a955bSLisandro Dalcin else: 982f46a955bSLisandro Dalcin done[name] = value 983f46a955bSLisandro Dalcin del notdone[name] 984f46a955bSLisandro Dalcin else: 985f46a955bSLisandro Dalcin # bogus variable reference; 986f46a955bSLisandro Dalcin # just drop it since we can't deal 987f46a955bSLisandro Dalcin del notdone[name] 988f46a955bSLisandro Dalcin # save the results in the global dictionary 989f46a955bSLisandro Dalcin dct.update(done) 990f46a955bSLisandro Dalcin return dct 991f46a955bSLisandro Dalcin 992f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 993