1f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 2f46a955bSLisandro Dalcin 3f46a955bSLisandro Dalcinimport re 4f46a955bSLisandro Dalcinimport os 5f46a955bSLisandro Dalcinimport sys 6f46a955bSLisandro Dalcinimport glob 7f46a955bSLisandro Dalcinimport copy 8f46a955bSLisandro Dalcinimport warnings 96f336411SStefano Zampinifrom distutils import log 106f336411SStefano Zampinifrom distutils import sysconfig 116f336411SStefano Zampinifrom distutils.util import execute 126f336411SStefano Zampinifrom distutils.util import split_quoted 136f336411SStefano Zampinifrom distutils.errors import DistutilsError 146f336411SStefano Zampinifrom distutils.text_file import TextFile 156f336411SStefano Zampini 16f46a955bSLisandro Dalcin 17f46a955bSLisandro Dalcintry: 18f46a955bSLisandro Dalcin from cStringIO import StringIO 19f46a955bSLisandro Dalcinexcept ImportError: 20f46a955bSLisandro Dalcin from io import StringIO 21f46a955bSLisandro Dalcin 22f46a955bSLisandro Dalcintry: 23f46a955bSLisandro Dalcin import setuptools 24f46a955bSLisandro Dalcinexcept ImportError: 25f46a955bSLisandro Dalcin setuptools = None 26f46a955bSLisandro Dalcin 27f46a955bSLisandro Dalcinif setuptools: 28f46a955bSLisandro Dalcin from setuptools import setup as _setup 29f46a955bSLisandro Dalcin from setuptools import Extension as _Extension 30f46a955bSLisandro Dalcin from setuptools import Command 31f46a955bSLisandro Dalcinelse: 32f46a955bSLisandro Dalcin from distutils.core import setup as _setup 33f46a955bSLisandro Dalcin from distutils.core import Extension as _Extension 34f46a955bSLisandro Dalcin from distutils.core import Command 35f46a955bSLisandro Dalcin 366f336411SStefano Zampini 37f46a955bSLisandro Dalcindef import_command(cmd): 38f46a955bSLisandro Dalcin try: 39f46a955bSLisandro Dalcin from importlib import import_module 40f46a955bSLisandro Dalcin except ImportError: 416f336411SStefano Zampini 42f46a955bSLisandro Dalcin def import_module(n): 43f46a955bSLisandro Dalcin return __import__(n, fromlist=[None]) 446f336411SStefano Zampini 45f46a955bSLisandro Dalcin try: 466f336411SStefano Zampini if not setuptools: 476f336411SStefano Zampini raise ImportError 48f46a955bSLisandro Dalcin mod = import_module('setuptools.command.' + cmd) 49f46a955bSLisandro Dalcin return getattr(mod, cmd) 50f46a955bSLisandro Dalcin except ImportError: 51f46a955bSLisandro Dalcin mod = import_module('distutils.command.' + cmd) 52f46a955bSLisandro Dalcin return getattr(mod, cmd) 53f46a955bSLisandro Dalcin 546f336411SStefano Zampini 55f46a955bSLisandro Dalcin_config = import_command('config') 56f46a955bSLisandro Dalcin_build = import_command('build') 57f46a955bSLisandro Dalcin_build_ext = import_command('build_ext') 58f46a955bSLisandro Dalcin_install = import_command('install') 59f46a955bSLisandro Dalcin 60f46a955bSLisandro Dalcintry: 6156478d30SPierre Jolivet from setuptools import modified 62f46a955bSLisandro Dalcinexcept ImportError: 6356478d30SPierre Jolivet try: 6456478d30SPierre Jolivet from setuptools import dep_util as modified 6556478d30SPierre Jolivet except ImportError: 6656478d30SPierre Jolivet from distutils import dep_util as modified 67f46a955bSLisandro Dalcin 68f46a955bSLisandro Dalcintry: 69f46a955bSLisandro Dalcin from packaging.version import Version 70f46a955bSLisandro Dalcinexcept ImportError: 71f46a955bSLisandro Dalcin try: 72f46a955bSLisandro Dalcin from setuptools.extern.packaging.version import Version 73f46a955bSLisandro Dalcin except ImportError: 74f46a955bSLisandro Dalcin from distutils.version import StrictVersion as Version 75f46a955bSLisandro Dalcin 76f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 77f46a955bSLisandro Dalcin 78f46a955bSLisandro Dalcin# Cython 79f46a955bSLisandro Dalcin 80b12f50ebSLisandro DalcinCYTHON = '3.0.0' 81f46a955bSLisandro Dalcin 826f336411SStefano Zampini 83f46a955bSLisandro Dalcindef cython_req(): 84f46a955bSLisandro Dalcin return CYTHON 85f46a955bSLisandro Dalcin 866f336411SStefano Zampini 87f46a955bSLisandro Dalcindef cython_chk(VERSION, verbose=True): 88f46a955bSLisandro Dalcin # 89f46a955bSLisandro Dalcin def warn(message): 906f336411SStefano Zampini if not verbose: 916f336411SStefano Zampini return 926f336411SStefano Zampini ruler, ws, nl = '*' * 80, ' ', '\n' 93f46a955bSLisandro Dalcin pyexe = sys.executable 946f336411SStefano Zampini advise = '$ %s -m pip install --upgrade cython' % pyexe 956f336411SStefano Zampini 966f336411SStefano Zampini def printer(*s): 976f336411SStefano Zampini sys.stderr.write(' '.join(s) + '\n') 986f336411SStefano Zampini 99f46a955bSLisandro Dalcin printer(ruler, nl) 100f46a955bSLisandro Dalcin printer(ws, message, nl) 101f46a955bSLisandro Dalcin printer(ws, ws, advise, nl) 102f46a955bSLisandro Dalcin printer(ruler) 1036f336411SStefano Zampini 104f46a955bSLisandro Dalcin # 105f46a955bSLisandro Dalcin try: 106f46a955bSLisandro Dalcin import Cython 107f46a955bSLisandro Dalcin except ImportError: 1086f336411SStefano Zampini warn('You need Cython to generate C source files.') 109f46a955bSLisandro Dalcin return False 110f46a955bSLisandro Dalcin # 111f46a955bSLisandro Dalcin CYTHON_VERSION = Cython.__version__ 1126f336411SStefano Zampini m = re.match(r'(\d+\.\d+(?:\.\d+)?).*', CYTHON_VERSION) 113f46a955bSLisandro Dalcin if not m: 1146f336411SStefano Zampini warn(f'Cannot parse Cython version string {CYTHON_VERSION!r}') 115f46a955bSLisandro Dalcin return False 116f46a955bSLisandro Dalcin REQUIRED = Version(VERSION) 117f46a955bSLisandro Dalcin PROVIDED = Version(m.groups()[0]) 118b12f50ebSLisandro Dalcin if PROVIDED < REQUIRED: 1196f336411SStefano Zampini warn(f'You need Cython >= {VERSION} (you have version {CYTHON_VERSION})') 120f46a955bSLisandro Dalcin return False 121f46a955bSLisandro Dalcin # 122f46a955bSLisandro Dalcin if verbose: 1236f336411SStefano Zampini log.info('using Cython %s' % CYTHON_VERSION) 124f46a955bSLisandro Dalcin return True 125f46a955bSLisandro Dalcin 1266f336411SStefano Zampini 127f46a955bSLisandro Dalcindef cython_run( 1286f336411SStefano Zampini source, 1296f336411SStefano Zampini target=None, 1306f336411SStefano Zampini depends=(), 1316f336411SStefano Zampini includes=(), 1326f336411SStefano Zampini workdir=None, 1336f336411SStefano Zampini force=False, 1346f336411SStefano Zampini VERSION='0.0', 135f46a955bSLisandro Dalcin): 136f46a955bSLisandro Dalcin if target is None: 137f46a955bSLisandro Dalcin target = os.path.splitext(source)[0] + '.c' 138f46a955bSLisandro Dalcin cwd = os.getcwd() 139f46a955bSLisandro Dalcin try: 140f46a955bSLisandro Dalcin if workdir: 141f46a955bSLisandro Dalcin os.chdir(workdir) 142f46a955bSLisandro Dalcin alldeps = [source] 143f46a955bSLisandro Dalcin for dep in depends: 144f46a955bSLisandro Dalcin alldeps += glob.glob(dep) 14556478d30SPierre Jolivet if not (force or modified.newer_group(alldeps, target)): 1466f336411SStefano Zampini log.debug("skipping '%s' -> '%s' (up-to-date)", source, target) 147f46a955bSLisandro Dalcin return 148f46a955bSLisandro Dalcin finally: 149f46a955bSLisandro Dalcin os.chdir(cwd) 15080e0d92bSLisandro Dalcin require = 'Cython >= %s' % VERSION 151f46a955bSLisandro Dalcin if setuptools and not cython_chk(VERSION, verbose=False): 152f46a955bSLisandro Dalcin if sys.modules.get('Cython'): 153f46a955bSLisandro Dalcin removed = getattr(sys.modules['Cython'], '__version__', '') 1546f336411SStefano Zampini log.info('removing Cython %s from sys.modules' % removed) 155f46a955bSLisandro Dalcin pkgname = re.compile(r'cython(\.|$)', re.IGNORECASE) 156f46a955bSLisandro Dalcin for modname in list(sys.modules.keys()): 157f46a955bSLisandro Dalcin if pkgname.match(modname): 158f46a955bSLisandro Dalcin del sys.modules[modname] 159f46a955bSLisandro Dalcin try: 160f46a955bSLisandro Dalcin install_setup_requires = setuptools._install_setup_requires 161f46a955bSLisandro Dalcin with warnings.catch_warnings(): 162f46a955bSLisandro Dalcin if hasattr(setuptools, 'SetuptoolsDeprecationWarning'): 163f46a955bSLisandro Dalcin category = setuptools.SetuptoolsDeprecationWarning 164f46a955bSLisandro Dalcin warnings.simplefilter('ignore', category) 165f46a955bSLisandro Dalcin log.info("fetching build requirement '%s'" % require) 1666f336411SStefano Zampini install_setup_requires({'setup_requires': [require]}) 167f46a955bSLisandro Dalcin except Exception: 168f46a955bSLisandro Dalcin log.info("failed to fetch build requirement '%s'" % require) 169f46a955bSLisandro Dalcin if not cython_chk(VERSION): 170f46a955bSLisandro Dalcin raise DistutilsError("unsatisfied build requirement '%s'" % require) 171f46a955bSLisandro Dalcin # 172f46a955bSLisandro Dalcin log.info("cythonizing '%s' -> '%s'", source, target) 173f46a955bSLisandro Dalcin from cythonize import cythonize 1746f336411SStefano Zampini 175f46a955bSLisandro Dalcin args = [] 176f46a955bSLisandro Dalcin if workdir: 177f46a955bSLisandro Dalcin args += ['--working', workdir] 178f46a955bSLisandro Dalcin args += [source] 179f46a955bSLisandro Dalcin if target: 180f46a955bSLisandro Dalcin args += ['--output-file', target] 181f46a955bSLisandro Dalcin err = cythonize(args) 182f46a955bSLisandro Dalcin if err: 1836f336411SStefano Zampini raise DistutilsError(f"Cython failure: '{source}' -> '{target}'") 184f46a955bSLisandro Dalcin 185f46a955bSLisandro Dalcin 186f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 187f46a955bSLisandro Dalcin 1886f336411SStefano Zampini 189f46a955bSLisandro Dalcindef fix_config_vars(names, values): 190f46a955bSLisandro Dalcin values = list(values) 191f46a955bSLisandro Dalcin if 'CONDA_BUILD' in os.environ: 192f46a955bSLisandro Dalcin return values 193f46a955bSLisandro Dalcin if sys.platform == 'darwin': 194f46a955bSLisandro Dalcin if 'ARCHFLAGS' in os.environ: 195f46a955bSLisandro Dalcin ARCHFLAGS = os.environ['ARCHFLAGS'] 196f46a955bSLisandro Dalcin for i, flag in enumerate(list(values)): 1978acd7bfaSLisandro Dalcin flag, count = re.subn(r'-arch\s+\w+', ' ', str(flag)) 198f46a955bSLisandro Dalcin if count and ARCHFLAGS: 199f46a955bSLisandro Dalcin flag = flag + ' ' + ARCHFLAGS 200f46a955bSLisandro Dalcin values[i] = flag 201f46a955bSLisandro Dalcin if 'SDKROOT' in os.environ: 202f46a955bSLisandro Dalcin SDKROOT = os.environ['SDKROOT'] 203f46a955bSLisandro Dalcin for i, flag in enumerate(list(values)): 2048acd7bfaSLisandro Dalcin flag, count = re.subn(r'-isysroot [^ \t]*', ' ', str(flag)) 205f46a955bSLisandro Dalcin if count and SDKROOT: 206f46a955bSLisandro Dalcin flag = flag + ' ' + '-isysroot ' + SDKROOT 207f46a955bSLisandro Dalcin values[i] = flag 208f46a955bSLisandro Dalcin return values 209f46a955bSLisandro Dalcin 2106f336411SStefano Zampini 211f46a955bSLisandro Dalcindef get_config_vars(*names): 212f46a955bSLisandro Dalcin # Core Python configuration 213f46a955bSLisandro Dalcin values = sysconfig.get_config_vars(*names) 214f46a955bSLisandro Dalcin # Do any distutils flags fixup right now 2156f336411SStefano Zampini return fix_config_vars(names, values) 2166f336411SStefano Zampini 217f46a955bSLisandro Dalcin 218f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 219f46a955bSLisandro Dalcin 220f46a955bSLisandro Dalcin 2216f336411SStefano Zampiniclass PetscConfig: 222f46a955bSLisandro Dalcin def __init__(self, petsc_dir, petsc_arch, dest_dir=None): 223f46a955bSLisandro Dalcin if dest_dir is None: 224f46a955bSLisandro Dalcin dest_dir = os.environ.get('DESTDIR') 225f46a955bSLisandro Dalcin self.configdict = {} 226f46a955bSLisandro Dalcin if not petsc_dir: 2276f336411SStefano Zampini raise DistutilsError('PETSc not found') 228f46a955bSLisandro Dalcin if not os.path.isdir(petsc_dir): 2296f336411SStefano Zampini raise DistutilsError('invalid PETSC_DIR: %s' % petsc_dir) 230f46a955bSLisandro Dalcin self.version = self._get_petsc_version(petsc_dir) 231f46a955bSLisandro Dalcin self.configdict = self._get_petsc_config(petsc_dir, petsc_arch) 232f46a955bSLisandro Dalcin self.PETSC_DIR = self['PETSC_DIR'] 233f46a955bSLisandro Dalcin self.PETSC_ARCH = self['PETSC_ARCH'] 234f46a955bSLisandro Dalcin self.DESTDIR = dest_dir 235f46a955bSLisandro Dalcin language_map = {'CONLY': 'c', 'CXXONLY': 'c++'} 236f46a955bSLisandro Dalcin self.language = language_map[self['PETSC_LANGUAGE']] 237f46a955bSLisandro Dalcin 238f46a955bSLisandro Dalcin def __getitem__(self, item): 239f46a955bSLisandro Dalcin return self.configdict[item] 240f46a955bSLisandro Dalcin 241f46a955bSLisandro Dalcin def get(self, item, default=None): 242f46a955bSLisandro Dalcin return self.configdict.get(item, default) 243f46a955bSLisandro Dalcin 244f46a955bSLisandro Dalcin def configure(self, extension, compiler=None): 245f46a955bSLisandro Dalcin self.configure_extension(extension) 246f46a955bSLisandro Dalcin if compiler is not None: 247f46a955bSLisandro Dalcin self.configure_compiler(compiler) 248f46a955bSLisandro Dalcin 249f46a955bSLisandro Dalcin def _get_petsc_version(self, petsc_dir): 250f46a955bSLisandro Dalcin import re 2516f336411SStefano Zampini 252f46a955bSLisandro Dalcin version_re = { 2536f336411SStefano Zampini 'major': re.compile(r'#define\s+PETSC_VERSION_MAJOR\s+(\d+)'), 2546f336411SStefano Zampini 'minor': re.compile(r'#define\s+PETSC_VERSION_MINOR\s+(\d+)'), 2556f336411SStefano Zampini 'micro': re.compile(r'#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)'), 2566f336411SStefano Zampini 'release': re.compile(r'#define\s+PETSC_VERSION_RELEASE\s+(-*\d+)'), 257f46a955bSLisandro Dalcin } 258f46a955bSLisandro Dalcin petscversion_h = os.path.join(petsc_dir, 'include', 'petscversion.h') 2596f336411SStefano Zampini with open(petscversion_h, 'rt') as f: 2606f336411SStefano Zampini data = f.read() 261f46a955bSLisandro Dalcin major = int(version_re['major'].search(data).groups()[0]) 262f46a955bSLisandro Dalcin minor = int(version_re['minor'].search(data).groups()[0]) 263f46a955bSLisandro Dalcin micro = int(version_re['micro'].search(data).groups()[0]) 264f46a955bSLisandro Dalcin release = int(version_re['release'].search(data).groups()[0]) 265f46a955bSLisandro Dalcin return (major, minor, micro), (release == 1) 266f46a955bSLisandro Dalcin 267f46a955bSLisandro Dalcin def _get_petsc_config(self, petsc_dir, petsc_arch): 268f46a955bSLisandro Dalcin from os.path import join, isdir, exists 2696f336411SStefano Zampini 270f46a955bSLisandro Dalcin PETSC_DIR = petsc_dir 271f46a955bSLisandro Dalcin PETSC_ARCH = petsc_arch 272f46a955bSLisandro Dalcin # 273f46a955bSLisandro Dalcin confdir = join('lib', 'petsc', 'conf') 274f46a955bSLisandro Dalcin if not (PETSC_ARCH and isdir(join(PETSC_DIR, PETSC_ARCH))): 275f46a955bSLisandro Dalcin petscvars = join(PETSC_DIR, confdir, 'petscvariables') 276f46a955bSLisandro Dalcin PETSC_ARCH = makefile(open(petscvars, 'rt')).get('PETSC_ARCH') 277f46a955bSLisandro Dalcin if not (PETSC_ARCH and isdir(join(PETSC_DIR, PETSC_ARCH))): 278f46a955bSLisandro Dalcin PETSC_ARCH = '' 279f46a955bSLisandro Dalcin # 280f46a955bSLisandro Dalcin variables = join(PETSC_DIR, confdir, 'variables') 281f46a955bSLisandro Dalcin if not exists(variables): 282f46a955bSLisandro Dalcin variables = join(PETSC_DIR, PETSC_ARCH, confdir, 'variables') 283f46a955bSLisandro Dalcin petscvariables = join(PETSC_DIR, PETSC_ARCH, confdir, 'petscvariables') 284f46a955bSLisandro Dalcin # 285f46a955bSLisandro Dalcin with open(variables) as f: 286f46a955bSLisandro Dalcin contents = f.read() 287f46a955bSLisandro Dalcin with open(petscvariables) as f: 288f46a955bSLisandro Dalcin contents += f.read() 289f46a955bSLisandro Dalcin # 290f46a955bSLisandro Dalcin confstr = 'PETSC_DIR = %s\n' % PETSC_DIR 291f46a955bSLisandro Dalcin confstr += 'PETSC_ARCH = %s\n' % PETSC_ARCH 292f46a955bSLisandro Dalcin confstr += contents 2936f336411SStefano Zampini return makefile(StringIO(confstr)) 294f46a955bSLisandro Dalcin 295ec81f945SPierre Jolivet def _configure_ext(self, ext, dct, append=False): 296f46a955bSLisandro Dalcin extdict = ext.__dict__ 297f46a955bSLisandro Dalcin for key, values in dct.items(): 298f46a955bSLisandro Dalcin if key in extdict: 299f46a955bSLisandro Dalcin for value in values: 300f46a955bSLisandro Dalcin if value not in extdict[key]: 301ec81f945SPierre Jolivet if not append: 302f46a955bSLisandro Dalcin extdict[key].insert(0, value) 303f46a955bSLisandro Dalcin else: 304f46a955bSLisandro Dalcin extdict[key].append(value) 305f46a955bSLisandro Dalcin 306f46a955bSLisandro Dalcin def configure_extension(self, extension): 307f46a955bSLisandro Dalcin # includes and libraries 308f46a955bSLisandro Dalcin # paths in PETSc config files point to final installation location, but 309f46a955bSLisandro Dalcin # we might be building against PETSc in staging location (DESTDIR) when 310f46a955bSLisandro Dalcin # DESTDIR is set, so append DESTDIR (if nonempty) to those paths 311f46a955bSLisandro Dalcin petsc_inc = flaglist(prepend_to_flags(self.DESTDIR, self['PETSC_CC_INCLUDES'])) 3126f336411SStefano Zampini lib_flags = prepend_to_flags( 3136f336411SStefano Zampini self.DESTDIR, 3146f336411SStefano Zampini '-L{} {}'.format(self['PETSC_LIB_DIR'], self['PETSC_LIB_BASIC']), 3156f336411SStefano Zampini ) 316f46a955bSLisandro Dalcin petsc_lib = flaglist(lib_flags) 317f46a955bSLisandro Dalcin # runtime_library_dirs is not supported on Windows 318f46a955bSLisandro Dalcin if sys.platform != 'win32': 319f46a955bSLisandro Dalcin # if DESTDIR is set, then we're building against PETSc in a staging 320f46a955bSLisandro Dalcin # directory, but rpath needs to point to final install directory. 321693647e8SLisandro Dalcin rpath = [strip_prefix(self.DESTDIR, self['PETSC_LIB_DIR'])] 322693647e8SLisandro Dalcin if sys.modules.get('petsc') is not None: 323693647e8SLisandro Dalcin if sys.platform == 'darwin': 324693647e8SLisandro Dalcin rpath = ['@loader_path/../../petsc/lib'] 325693647e8SLisandro Dalcin else: 326693647e8SLisandro Dalcin rpath = ['$ORIGIN/../../petsc/lib'] 327693647e8SLisandro Dalcin petsc_lib['runtime_library_dirs'].extend(rpath) 328f46a955bSLisandro Dalcin # Link in extra libraries on static builds 329f46a955bSLisandro Dalcin if self['BUILDSHAREDLIB'] != 'yes': 330f46a955bSLisandro Dalcin petsc_ext_lib = split_quoted(self['PETSC_EXTERNAL_LIB_BASIC']) 331f46a955bSLisandro Dalcin petsc_lib['extra_link_args'].extend(petsc_ext_lib) 332ec81f945SPierre Jolivet self._configure_ext(extension, petsc_inc, append=True) 333f46a955bSLisandro Dalcin self._configure_ext(extension, petsc_lib) 334f46a955bSLisandro Dalcin 335f46a955bSLisandro Dalcin def configure_compiler(self, compiler): 3366f336411SStefano Zampini if compiler.compiler_type != 'unix': 3376f336411SStefano Zampini return 338f46a955bSLisandro Dalcin getenv = os.environ.get 339f46a955bSLisandro Dalcin # distutils C/C++ compiler 3406f336411SStefano Zampini (cc, cflags, ccshared, cxx) = get_config_vars('CC', 'CFLAGS', 'CCSHARED', 'CXX') 341f46a955bSLisandro Dalcin ccshared = getenv('CCSHARED', ccshared or '') 342f46a955bSLisandro Dalcin cflags = getenv('CFLAGS', cflags or '') 343f46a955bSLisandro Dalcin cflags = cflags.replace('-Wstrict-prototypes', '') 344f46a955bSLisandro Dalcin # distutils linker 3456f336411SStefano Zampini (ldflags, ldshared, so_ext) = get_config_vars('LDFLAGS', 'LDSHARED', 'SO') 346f46a955bSLisandro Dalcin ld = cc 347f46a955bSLisandro Dalcin ldshared = getenv('LDSHARED', ldshared) 348f46a955bSLisandro Dalcin ldflags = getenv('LDFLAGS', cflags + ' ' + (ldflags or '')) 349f46a955bSLisandro Dalcin ldcmd = split_quoted(ld) + split_quoted(ldflags) 3506f336411SStefano Zampini ldshared = [ 3516f336411SStefano Zampini flg 3526f336411SStefano Zampini for flg in split_quoted(ldshared) 3536f336411SStefano Zampini if flg not in ldcmd and (flg.find('/lib/spack/env') < 0) 3546f336411SStefano Zampini ] 355f46a955bSLisandro Dalcin ldshared = str.join(' ', ldshared) 3566f336411SStefano Zampini 357f46a955bSLisandro Dalcin # 358f46a955bSLisandro Dalcin def get_flags(cmd): 3596f336411SStefano Zampini if not cmd: 3606f336411SStefano Zampini return '' 361f46a955bSLisandro Dalcin cmd = split_quoted(cmd) 362f46a955bSLisandro Dalcin if os.path.basename(cmd[0]) == 'xcrun': 363f46a955bSLisandro Dalcin del cmd[0] 364f46a955bSLisandro Dalcin while True: 365f46a955bSLisandro Dalcin if cmd[0] == '-sdk': 366f46a955bSLisandro Dalcin del cmd[0:2] 367f46a955bSLisandro Dalcin continue 368f46a955bSLisandro Dalcin if cmd[0] == '-log': 369f46a955bSLisandro Dalcin del cmd[0] 370f46a955bSLisandro Dalcin continue 371f46a955bSLisandro Dalcin break 372f46a955bSLisandro Dalcin return ' '.join(cmd[1:]) 3736f336411SStefano Zampini 374f46a955bSLisandro Dalcin # PETSc C compiler 375f46a955bSLisandro Dalcin PCC = self['PCC'] 376f46a955bSLisandro Dalcin PCC_FLAGS = get_flags(cc) + ' ' + self['PCC_FLAGS'] 377f46a955bSLisandro Dalcin PCC_FLAGS = PCC_FLAGS.replace('-fvisibility=hidden', '') 378*52c29a0dSSatish Balay PCC_FLAGS = PCC_FLAGS.replace('-Wpedantic', '-Wno-pedantic') 379*52c29a0dSSatish Balay PCC_FLAGS = PCC_FLAGS.replace('-Wextra-semi-stmt', '-Wno-extra-semi-stmt') 380f46a955bSLisandro Dalcin PCC = getenv('PCC', PCC) + ' ' + getenv('PCCFLAGS', PCC_FLAGS) 381f46a955bSLisandro Dalcin PCC_SHARED = str.join(' ', (PCC, ccshared, cflags)) 382f46a955bSLisandro Dalcin # PETSc C++ compiler 383f46a955bSLisandro Dalcin PCXX = PCC if self.language == 'c++' else self.get('CXX', cxx) 384f46a955bSLisandro Dalcin # PETSc linker 385f46a955bSLisandro Dalcin PLD = self['PCC_LINKER'] 386f46a955bSLisandro Dalcin PLD_FLAGS = get_flags(ld) + ' ' + self['PCC_LINKER_FLAGS'] 387f46a955bSLisandro Dalcin PLD_FLAGS = PLD_FLAGS.replace('-fvisibility=hidden', '') 388f46a955bSLisandro Dalcin PLD = getenv('PLD', PLD) + ' ' + getenv('PLDFLAGS', PLD_FLAGS) 389f46a955bSLisandro Dalcin PLD_SHARED = str.join(' ', (PLD, ldshared, ldflags)) 390f46a955bSLisandro Dalcin # 391f46a955bSLisandro Dalcin compiler.set_executables( 392f46a955bSLisandro Dalcin compiler=PCC, 393f46a955bSLisandro Dalcin compiler_cxx=PCXX, 394f46a955bSLisandro Dalcin linker_exe=PLD, 395f46a955bSLisandro Dalcin compiler_so=PCC_SHARED, 396f46a955bSLisandro Dalcin linker_so=PLD_SHARED, 397f46a955bSLisandro Dalcin ) 398f46a955bSLisandro Dalcin compiler.shared_lib_extension = so_ext 399f46a955bSLisandro Dalcin 400f46a955bSLisandro Dalcin def log_info(self): 401f46a955bSLisandro Dalcin PETSC_DIR = self['PETSC_DIR'] 402f46a955bSLisandro Dalcin PETSC_ARCH = self['PETSC_ARCH'] 4036f336411SStefano Zampini version = '.'.join([str(i) for i in self.version[0]]) 4046f336411SStefano Zampini release = ('development', 'release')[self.version[1]] 405f46a955bSLisandro Dalcin version_info = version + ' ' + release 406f46a955bSLisandro Dalcin integer_size = '%s-bit' % self['PETSC_INDEX_SIZE'] 407f46a955bSLisandro Dalcin scalar_type = self['PETSC_SCALAR'] 408f46a955bSLisandro Dalcin precision = self['PETSC_PRECISION'] 409f46a955bSLisandro Dalcin language = self['PETSC_LANGUAGE'] 410f46a955bSLisandro Dalcin compiler = self['PCC'] 411f46a955bSLisandro Dalcin linker = self['PCC_LINKER'] 412f46a955bSLisandro Dalcin log.info('PETSC_DIR: %s' % PETSC_DIR) 413f46a955bSLisandro Dalcin log.info('PETSC_ARCH: %s' % PETSC_ARCH) 414f46a955bSLisandro Dalcin log.info('version: %s' % version_info) 415f46a955bSLisandro Dalcin log.info('integer-size: %s' % integer_size) 416f46a955bSLisandro Dalcin log.info('scalar-type: %s' % scalar_type) 417f46a955bSLisandro Dalcin log.info('precision: %s' % precision) 418f46a955bSLisandro Dalcin log.info('language: %s' % language) 419f46a955bSLisandro Dalcin log.info('compiler: %s' % compiler) 420f46a955bSLisandro Dalcin log.info('linker: %s' % linker) 421f46a955bSLisandro Dalcin 4226f336411SStefano Zampini 423f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 424f46a955bSLisandro Dalcin 4256f336411SStefano Zampini 426f46a955bSLisandro Dalcinclass Extension(_Extension): 427f46a955bSLisandro Dalcin pass 428f46a955bSLisandro Dalcin 4296f336411SStefano Zampini 430f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 431f46a955bSLisandro Dalcin 432f46a955bSLisandro Dalcincmd_petsc_opts = [ 4336f336411SStefano Zampini ('petsc-dir=', None, 'define PETSC_DIR, overriding environmental variables'), 4346f336411SStefano Zampini ('petsc-arch=', None, 'define PETSC_ARCH, overriding environmental variables'), 435f46a955bSLisandro Dalcin] 436f46a955bSLisandro Dalcin 437f46a955bSLisandro Dalcin 438f46a955bSLisandro Dalcinclass config(_config): 439f46a955bSLisandro Dalcin Configure = PetscConfig 440f46a955bSLisandro Dalcin 441f46a955bSLisandro Dalcin user_options = _config.user_options + cmd_petsc_opts 442f46a955bSLisandro Dalcin 443f46a955bSLisandro Dalcin def initialize_options(self): 444f46a955bSLisandro Dalcin _config.initialize_options(self) 445f46a955bSLisandro Dalcin self.petsc_dir = None 446f46a955bSLisandro Dalcin self.petsc_arch = None 447f46a955bSLisandro Dalcin 448f46a955bSLisandro Dalcin def get_config_arch(self, arch): 449f46a955bSLisandro Dalcin return config.Configure(self.petsc_dir, arch) 450f46a955bSLisandro Dalcin 451f46a955bSLisandro Dalcin def run(self): 452f46a955bSLisandro Dalcin _config.run(self) 453f46a955bSLisandro Dalcin self.petsc_dir = config.get_petsc_dir(self.petsc_dir) 4546f336411SStefano Zampini if self.petsc_dir is None: 4556f336411SStefano Zampini return 456f46a955bSLisandro Dalcin petsc_arch = config.get_petsc_arch(self.petsc_dir, self.petsc_arch) 457f46a955bSLisandro Dalcin log.info('-' * 70) 458f46a955bSLisandro Dalcin log.info('PETSC_DIR: %s' % self.petsc_dir) 459f46a955bSLisandro Dalcin arch_list = petsc_arch 460f46a955bSLisandro Dalcin if not arch_list: 461f46a955bSLisandro Dalcin arch_list = [None] 462f46a955bSLisandro Dalcin for arch in arch_list: 463f46a955bSLisandro Dalcin conf = self.get_config_arch(arch) 464f46a955bSLisandro Dalcin archname = conf.PETSC_ARCH or conf['PETSC_ARCH'] 465f46a955bSLisandro Dalcin scalar_type = conf['PETSC_SCALAR'] 466f46a955bSLisandro Dalcin precision = conf['PETSC_PRECISION'] 467f46a955bSLisandro Dalcin language = conf['PETSC_LANGUAGE'] 468f46a955bSLisandro Dalcin compiler = conf['PCC'] 469f46a955bSLisandro Dalcin linker = conf['PCC_LINKER'] 470f46a955bSLisandro Dalcin log.info('-' * 70) 471f46a955bSLisandro Dalcin log.info('PETSC_ARCH: %s' % archname) 472f46a955bSLisandro Dalcin log.info(' * scalar-type: %s' % scalar_type) 473f46a955bSLisandro Dalcin log.info(' * precision: %s' % precision) 474f46a955bSLisandro Dalcin log.info(' * language: %s' % language) 475f46a955bSLisandro Dalcin log.info(' * compiler: %s' % compiler) 476f46a955bSLisandro Dalcin log.info(' * linker: %s' % linker) 477f46a955bSLisandro Dalcin log.info('-' * 70) 478f46a955bSLisandro Dalcin 479f46a955bSLisandro Dalcin # @staticmethod 480f46a955bSLisandro Dalcin def get_petsc_dir(petsc_dir): 4816f336411SStefano Zampini if not petsc_dir: 4826f336411SStefano Zampini return None 483f46a955bSLisandro Dalcin petsc_dir = os.path.expandvars(petsc_dir) 484f46a955bSLisandro Dalcin if not petsc_dir or '$PETSC_DIR' in petsc_dir: 485f46a955bSLisandro Dalcin try: 486f46a955bSLisandro Dalcin import petsc 4876f336411SStefano Zampini 488f46a955bSLisandro Dalcin petsc_dir = petsc.get_petsc_dir() 489f46a955bSLisandro Dalcin except ImportError: 4906f336411SStefano Zampini log.warn('PETSC_DIR not specified') 491f46a955bSLisandro Dalcin return None 492f46a955bSLisandro Dalcin petsc_dir = os.path.expanduser(petsc_dir) 493f46a955bSLisandro Dalcin petsc_dir = os.path.abspath(petsc_dir) 494f46a955bSLisandro Dalcin return config.chk_petsc_dir(petsc_dir) 4956f336411SStefano Zampini 496f46a955bSLisandro Dalcin get_petsc_dir = staticmethod(get_petsc_dir) 497f46a955bSLisandro Dalcin 498f46a955bSLisandro Dalcin # @staticmethod 499f46a955bSLisandro Dalcin def chk_petsc_dir(petsc_dir): 500f46a955bSLisandro Dalcin if not os.path.isdir(petsc_dir): 501f46a955bSLisandro Dalcin log.error('invalid PETSC_DIR: %s (ignored)' % petsc_dir) 502f46a955bSLisandro Dalcin return None 503f46a955bSLisandro Dalcin return petsc_dir 5046f336411SStefano Zampini 505f46a955bSLisandro Dalcin chk_petsc_dir = staticmethod(chk_petsc_dir) 506f46a955bSLisandro Dalcin 507f46a955bSLisandro Dalcin # @staticmethod 508f46a955bSLisandro Dalcin def get_petsc_arch(petsc_dir, petsc_arch): 5096f336411SStefano Zampini if not petsc_dir: 5106f336411SStefano Zampini return None 511f46a955bSLisandro Dalcin petsc_arch = os.path.expandvars(petsc_arch) 5126f336411SStefano Zampini if not petsc_arch or '$PETSC_ARCH' in petsc_arch: 513f46a955bSLisandro Dalcin petsc_arch = '' 514f46a955bSLisandro Dalcin petsc_conf = os.path.join(petsc_dir, 'lib', 'petsc', 'conf') 515f46a955bSLisandro Dalcin if os.path.isdir(petsc_conf): 516f46a955bSLisandro Dalcin petscvariables = os.path.join(petsc_conf, 'petscvariables') 517f46a955bSLisandro Dalcin if os.path.exists(petscvariables): 518f46a955bSLisandro Dalcin conf = makefile(open(petscvariables, 'rt')) 519f46a955bSLisandro Dalcin petsc_arch = conf.get('PETSC_ARCH', '') 520f46a955bSLisandro Dalcin petsc_arch = petsc_arch.split(os.pathsep) 521f46a955bSLisandro Dalcin petsc_arch = unique(petsc_arch) 522f46a955bSLisandro Dalcin petsc_arch = [arch for arch in petsc_arch if arch] 523f46a955bSLisandro Dalcin return config.chk_petsc_arch(petsc_dir, petsc_arch) 5246f336411SStefano Zampini 525f46a955bSLisandro Dalcin get_petsc_arch = staticmethod(get_petsc_arch) 526f46a955bSLisandro Dalcin 527f46a955bSLisandro Dalcin # @staticmethod 528f46a955bSLisandro Dalcin def chk_petsc_arch(petsc_dir, petsc_arch): 529f46a955bSLisandro Dalcin valid_archs = [] 530f46a955bSLisandro Dalcin for arch in petsc_arch: 531f46a955bSLisandro Dalcin arch_path = os.path.join(petsc_dir, arch) 532f46a955bSLisandro Dalcin if os.path.isdir(arch_path): 533f46a955bSLisandro Dalcin valid_archs.append(arch) 534f46a955bSLisandro Dalcin else: 5356f336411SStefano Zampini log.warn('invalid PETSC_ARCH: %s (ignored)' % arch) 536f46a955bSLisandro Dalcin return valid_archs 5376f336411SStefano Zampini 538f46a955bSLisandro Dalcin chk_petsc_arch = staticmethod(chk_petsc_arch) 539f46a955bSLisandro Dalcin 540f46a955bSLisandro Dalcin 541f46a955bSLisandro Dalcinclass build(_build): 54255a74a43SLisandro Dalcin user_options = _build.user_options 5436f336411SStefano Zampini user_options += [ 5446f336411SStefano Zampini ( 54555a74a43SLisandro Dalcin 'inplace', 54655a74a43SLisandro Dalcin 'i', 5476f336411SStefano Zampini 'ignore build-lib and put compiled extensions into the source ' 5486f336411SStefano Zampini 'directory alongside your pure Python modules', 5496f336411SStefano Zampini ) 5506f336411SStefano Zampini ] 55155a74a43SLisandro Dalcin user_options += cmd_petsc_opts 55255a74a43SLisandro Dalcin 55355a74a43SLisandro Dalcin boolean_options = _build.boolean_options 55455a74a43SLisandro Dalcin boolean_options += ['inplace'] 555f46a955bSLisandro Dalcin 556f46a955bSLisandro Dalcin def initialize_options(self): 557f46a955bSLisandro Dalcin _build.initialize_options(self) 55855a74a43SLisandro Dalcin self.inplace = None 559f46a955bSLisandro Dalcin self.petsc_dir = None 560f46a955bSLisandro Dalcin self.petsc_arch = None 561f46a955bSLisandro Dalcin 562f46a955bSLisandro Dalcin def finalize_options(self): 563f46a955bSLisandro Dalcin _build.finalize_options(self) 56455a74a43SLisandro Dalcin if self.inplace is None: 56555a74a43SLisandro Dalcin self.inplace = False 5666f336411SStefano Zampini self.set_undefined_options( 5676f336411SStefano Zampini 'config', ('petsc_dir', 'petsc_dir'), ('petsc_arch', 'petsc_arch') 5686f336411SStefano Zampini ) 569f46a955bSLisandro Dalcin self.petsc_dir = config.get_petsc_dir(self.petsc_dir) 5706f336411SStefano Zampini self.petsc_arch = config.get_petsc_arch(self.petsc_dir, self.petsc_arch) 571f46a955bSLisandro Dalcin 5726f336411SStefano Zampini sub_commands = [('build_src', lambda *args: True)] + _build.sub_commands 573f46a955bSLisandro Dalcin 574f46a955bSLisandro Dalcin 575f46a955bSLisandro Dalcinclass build_src(Command): 5766f336411SStefano Zampini description = 'build C sources from Cython files' 577f46a955bSLisandro Dalcin 578f46a955bSLisandro Dalcin user_options = [ 5796f336411SStefano Zampini ('force', 'f', 'forcibly build everything (ignore file timestamps)'), 580f46a955bSLisandro Dalcin ] 581f46a955bSLisandro Dalcin 582f46a955bSLisandro Dalcin boolean_options = ['force'] 583f46a955bSLisandro Dalcin 584f46a955bSLisandro Dalcin def initialize_options(self): 585f46a955bSLisandro Dalcin self.force = False 586f46a955bSLisandro Dalcin 587f46a955bSLisandro Dalcin def finalize_options(self): 5886f336411SStefano Zampini self.set_undefined_options( 5896f336411SStefano Zampini 'build', 590f46a955bSLisandro Dalcin ('force', 'force'), 591f46a955bSLisandro Dalcin ) 592f46a955bSLisandro Dalcin 593f46a955bSLisandro Dalcin def run(self): 594f46a955bSLisandro Dalcin sources = getattr(self, 'sources', []) 595f46a955bSLisandro Dalcin for source in sources: 5966f336411SStefano Zampini cython_run(force=self.force, VERSION=cython_req(), **source) 597f46a955bSLisandro Dalcin 598f46a955bSLisandro Dalcin 599f46a955bSLisandro Dalcinclass build_ext(_build_ext): 600f46a955bSLisandro Dalcin user_options = _build_ext.user_options + cmd_petsc_opts 601f46a955bSLisandro Dalcin 602f46a955bSLisandro Dalcin def initialize_options(self): 603f46a955bSLisandro Dalcin _build_ext.initialize_options(self) 60455a74a43SLisandro Dalcin self.inplace = None 605f46a955bSLisandro Dalcin self.petsc_dir = None 606f46a955bSLisandro Dalcin self.petsc_arch = None 607f46a955bSLisandro Dalcin self._outputs = [] 608f46a955bSLisandro Dalcin 609f46a955bSLisandro Dalcin def finalize_options(self): 610f46a955bSLisandro Dalcin _build_ext.finalize_options(self) 61155a74a43SLisandro Dalcin self.set_undefined_options('build', ('inplace', 'inplace')) 6126f336411SStefano Zampini self.set_undefined_options( 6136f336411SStefano Zampini 'build', ('petsc_dir', 'petsc_dir'), ('petsc_arch', 'petsc_arch') 6146f336411SStefano Zampini ) 615f46a955bSLisandro Dalcin 616f46a955bSLisandro Dalcin def _copy_ext(self, ext): 617f46a955bSLisandro Dalcin extclass = ext.__class__ 618f46a955bSLisandro Dalcin fullname = self.get_ext_fullname(ext.name) 619f46a955bSLisandro Dalcin modpath = str.split(fullname, '.') 620f46a955bSLisandro Dalcin pkgpath = os.path.join('', *modpath[0:-1]) 621f46a955bSLisandro Dalcin name = modpath[-1] 622f46a955bSLisandro Dalcin sources = list(ext.sources) 623f46a955bSLisandro Dalcin newext = extclass(name, sources) 624f46a955bSLisandro Dalcin newext.__dict__.update(copy.deepcopy(ext.__dict__)) 625f46a955bSLisandro Dalcin newext.name = name 626f46a955bSLisandro Dalcin return pkgpath, newext 627f46a955bSLisandro Dalcin 628f46a955bSLisandro Dalcin def _build_ext_arch(self, ext, pkgpath, arch): 629f46a955bSLisandro Dalcin build_temp = self.build_temp 630f46a955bSLisandro Dalcin build_lib = self.build_lib 631f46a955bSLisandro Dalcin try: 632f46a955bSLisandro Dalcin self.build_temp = os.path.join(build_temp, arch) 633f46a955bSLisandro Dalcin self.build_lib = os.path.join(build_lib, pkgpath, arch) 634f46a955bSLisandro Dalcin _build_ext.build_extension(self, ext) 635f46a955bSLisandro Dalcin finally: 636f46a955bSLisandro Dalcin self.build_temp = build_temp 637f46a955bSLisandro Dalcin self.build_lib = build_lib 638f46a955bSLisandro Dalcin 639f46a955bSLisandro Dalcin def get_config_arch(self, arch): 640f46a955bSLisandro Dalcin return config.Configure(self.petsc_dir, arch) 641f46a955bSLisandro Dalcin 642f46a955bSLisandro Dalcin def build_extension(self, ext): 643f46a955bSLisandro Dalcin if not isinstance(ext, Extension): 644f46a955bSLisandro Dalcin return _build_ext.build_extension(self, ext) 645f46a955bSLisandro Dalcin petsc_arch = self.petsc_arch 646f46a955bSLisandro Dalcin if not petsc_arch: 647f46a955bSLisandro Dalcin petsc_arch = [None] 648f46a955bSLisandro Dalcin for arch in petsc_arch: 649f46a955bSLisandro Dalcin config = self.get_config_arch(arch) 650f46a955bSLisandro Dalcin ARCH = arch or config['PETSC_ARCH'] 651f46a955bSLisandro Dalcin if ARCH not in self.PETSC_ARCH_LIST: 652f46a955bSLisandro Dalcin self.PETSC_ARCH_LIST.append(ARCH) 653f46a955bSLisandro Dalcin self.DESTDIR = config.DESTDIR 654f46a955bSLisandro Dalcin ext.language = config.language 655f46a955bSLisandro Dalcin config.log_info() 656f46a955bSLisandro Dalcin pkgpath, newext = self._copy_ext(ext) 657f46a955bSLisandro Dalcin config.configure(newext, self.compiler) 658f46a955bSLisandro Dalcin self._build_ext_arch(newext, pkgpath, ARCH) 6596f336411SStefano Zampini return None 660f46a955bSLisandro Dalcin 661f46a955bSLisandro Dalcin def run(self): 662f46a955bSLisandro Dalcin self.build_sources() 663f46a955bSLisandro Dalcin _build_ext.run(self) 664f46a955bSLisandro Dalcin 665f46a955bSLisandro Dalcin def build_sources(self): 666f46a955bSLisandro Dalcin if 'build_src' in self.distribution.cmdclass: 667f46a955bSLisandro Dalcin self.run_command('build_src') 668f46a955bSLisandro Dalcin 669f46a955bSLisandro Dalcin def build_extensions(self, *args, **kargs): 670f46a955bSLisandro Dalcin self.PETSC_ARCH_LIST = [] 671f46a955bSLisandro Dalcin _build_ext.build_extensions(self, *args, **kargs) 6726f336411SStefano Zampini if not self.PETSC_ARCH_LIST: 6736f336411SStefano Zampini return 674f46a955bSLisandro Dalcin self.build_configuration(self.PETSC_ARCH_LIST) 675f46a955bSLisandro Dalcin 676f46a955bSLisandro Dalcin def build_configuration(self, arch_list): 677f46a955bSLisandro Dalcin # 678f46a955bSLisandro Dalcin template, variables = self.get_config_data(arch_list) 679f46a955bSLisandro Dalcin config_data = template % variables 680f46a955bSLisandro Dalcin # 681f46a955bSLisandro Dalcin build_lib = self.build_lib 682f46a955bSLisandro Dalcin dist_name = self.distribution.get_name() 6836f336411SStefano Zampini config_file = os.path.join( 6846f336411SStefano Zampini build_lib, dist_name, 'lib', dist_name.replace('4py', '') + '.cfg' 6856f336411SStefano Zampini ) 6866f336411SStefano Zampini 687f46a955bSLisandro Dalcin # 688f46a955bSLisandro Dalcin def write_file(filename, data): 689f46a955bSLisandro Dalcin with open(filename, 'w') as fh: 690f46a955bSLisandro Dalcin fh.write(config_data) 6916f336411SStefano Zampini 6926f336411SStefano Zampini execute( 6936f336411SStefano Zampini write_file, 6946f336411SStefano Zampini (config_file, config_data), 695f46a955bSLisandro Dalcin msg='writing %s' % config_file, 6966f336411SStefano Zampini verbose=self.verbose, 6976f336411SStefano Zampini dry_run=self.dry_run, 6986f336411SStefano Zampini ) 699f46a955bSLisandro Dalcin 700f46a955bSLisandro Dalcin def get_config_data(self, arch_list): 701f46a955bSLisandro Dalcin DESTDIR = self.DESTDIR 7026f336411SStefano Zampini template = ( 7036f336411SStefano Zampini '\n'.join( 7046f336411SStefano Zampini [ 7056f336411SStefano Zampini 'PETSC_DIR = %(PETSC_DIR)s', 7066f336411SStefano Zampini 'PETSC_ARCH = %(PETSC_ARCH)s', 7076f336411SStefano Zampini ] 7086f336411SStefano Zampini ) 7096f336411SStefano Zampini + '\n' 7106f336411SStefano Zampini ) 711f46a955bSLisandro Dalcin variables = { 712f46a955bSLisandro Dalcin 'PETSC_DIR': strip_prefix(DESTDIR, self.petsc_dir), 713f46a955bSLisandro Dalcin 'PETSC_ARCH': os.path.pathsep.join(arch_list), 714f46a955bSLisandro Dalcin } 715f46a955bSLisandro Dalcin return template, variables 716f46a955bSLisandro Dalcin 717f46a955bSLisandro Dalcin def copy_extensions_to_source(self): 718f46a955bSLisandro Dalcin build_py = self.get_finalized_command('build_py') 719f46a955bSLisandro Dalcin for ext in self.extensions: 720f46a955bSLisandro Dalcin inp_file, reg_file = self._get_inplace_equivalent(build_py, ext) 721f46a955bSLisandro Dalcin 722f46a955bSLisandro Dalcin arch_list = [''] 723f46a955bSLisandro Dalcin if isinstance(ext, Extension) and self.petsc_arch: 724f46a955bSLisandro Dalcin arch_list = self.petsc_arch[:] 725f46a955bSLisandro Dalcin 726f46a955bSLisandro Dalcin file_pairs = [] 727f46a955bSLisandro Dalcin inp_head, inp_tail = os.path.split(inp_file) 728f46a955bSLisandro Dalcin reg_head, reg_tail = os.path.split(reg_file) 729f46a955bSLisandro Dalcin for arch in arch_list: 730f46a955bSLisandro Dalcin inp_file = os.path.join(inp_head, arch, inp_tail) 731f46a955bSLisandro Dalcin reg_file = os.path.join(reg_head, arch, reg_tail) 732f46a955bSLisandro Dalcin file_pairs.append((inp_file, reg_file)) 733f46a955bSLisandro Dalcin 734f46a955bSLisandro Dalcin for inp_file, reg_file in file_pairs: 735f46a955bSLisandro Dalcin if os.path.exists(reg_file) or not ext.optional: 736f46a955bSLisandro Dalcin dest_dir, _ = os.path.split(inp_file) 737f46a955bSLisandro Dalcin self.mkpath(dest_dir) 738f46a955bSLisandro Dalcin self.copy_file(reg_file, inp_file, level=self.verbose) 739f46a955bSLisandro Dalcin 740f46a955bSLisandro Dalcin def get_outputs(self): 741f46a955bSLisandro Dalcin self.check_extensions_list(self.extensions) 742f46a955bSLisandro Dalcin outputs = [] 743f46a955bSLisandro Dalcin for ext in self.extensions: 744f46a955bSLisandro Dalcin fullname = self.get_ext_fullname(ext.name) 745f46a955bSLisandro Dalcin filename = self.get_ext_filename(fullname) 746f46a955bSLisandro Dalcin if isinstance(ext, Extension) and self.petsc_arch: 747f46a955bSLisandro Dalcin head, tail = os.path.split(filename) 748f46a955bSLisandro Dalcin for arch in self.petsc_arch: 749f46a955bSLisandro Dalcin outfile = os.path.join(self.build_lib, head, arch, tail) 750f46a955bSLisandro Dalcin outputs.append(outfile) 751f46a955bSLisandro Dalcin else: 752f46a955bSLisandro Dalcin outfile = os.path.join(self.build_lib, filename) 753f46a955bSLisandro Dalcin outputs.append(outfile) 7546f336411SStefano Zampini return list(set(outputs)) 755f46a955bSLisandro Dalcin 756f46a955bSLisandro Dalcin 757f46a955bSLisandro Dalcinclass install(_install): 758f46a955bSLisandro Dalcin def initialize_options(self): 759f46a955bSLisandro Dalcin with warnings.catch_warnings(): 760f46a955bSLisandro Dalcin if setuptools: 761f46a955bSLisandro Dalcin if hasattr(setuptools, 'SetuptoolsDeprecationWarning'): 762f46a955bSLisandro Dalcin category = setuptools.SetuptoolsDeprecationWarning 763f46a955bSLisandro Dalcin warnings.simplefilter('ignore', category) 764f46a955bSLisandro Dalcin _install.initialize_options(self) 765f46a955bSLisandro Dalcin self.old_and_unmanageable = True 766f46a955bSLisandro Dalcin 767f46a955bSLisandro Dalcin 768f46a955bSLisandro Dalcincmdclass_list = [ 769f46a955bSLisandro Dalcin config, 770f46a955bSLisandro Dalcin build, 771f46a955bSLisandro Dalcin build_src, 772f46a955bSLisandro Dalcin build_ext, 773f46a955bSLisandro Dalcin install, 774f46a955bSLisandro Dalcin] 775f46a955bSLisandro Dalcin 776f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 777f46a955bSLisandro Dalcin 7786f336411SStefano Zampini 779f46a955bSLisandro Dalcindef setup(**attrs): 780f46a955bSLisandro Dalcin cmdclass = attrs.setdefault('cmdclass', {}) 781f46a955bSLisandro Dalcin for cmd in cmdclass_list: 782f46a955bSLisandro Dalcin cmdclass.setdefault(cmd.__name__, cmd) 783f46a955bSLisandro Dalcin build_src.sources = attrs.pop('cython_sources', None) 784f46a955bSLisandro Dalcin use_setup_requires = False # handle Cython requirement ourselves 785f46a955bSLisandro Dalcin if setuptools and build_src.sources and use_setup_requires: 786f46a955bSLisandro Dalcin version = cython_req() 787f46a955bSLisandro Dalcin if not cython_chk(version, verbose=False): 788f46a955bSLisandro Dalcin reqs = attrs.setdefault('setup_requires', []) 789693647e8SLisandro Dalcin reqs += ['Cython>=' + version] 790f46a955bSLisandro Dalcin return _setup(**attrs) 791f46a955bSLisandro Dalcin 7926f336411SStefano Zampini 793f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 794f46a955bSLisandro Dalcin 795f46a955bSLisandro Dalcinif setuptools: 796f46a955bSLisandro Dalcin try: 797f46a955bSLisandro Dalcin from setuptools.command import egg_info as mod_egg_info 7986f336411SStefano Zampini 799f46a955bSLisandro Dalcin _FileList = mod_egg_info.FileList 8006f336411SStefano Zampini 801f46a955bSLisandro Dalcin class FileList(_FileList): 802f46a955bSLisandro Dalcin def process_template_line(self, line): 803f46a955bSLisandro Dalcin level = log.set_threshold(log.ERROR) 804f46a955bSLisandro Dalcin try: 805f46a955bSLisandro Dalcin _FileList.process_template_line(self, line) 806f46a955bSLisandro Dalcin finally: 807f46a955bSLisandro Dalcin log.set_threshold(level) 8086f336411SStefano Zampini 809f46a955bSLisandro Dalcin mod_egg_info.FileList = FileList 810f46a955bSLisandro Dalcin except (ImportError, AttributeError): 811f46a955bSLisandro Dalcin pass 812f46a955bSLisandro Dalcin 813f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 814f46a955bSLisandro Dalcin 8156f336411SStefano Zampini 816f46a955bSLisandro Dalcindef append(seq, item): 817f46a955bSLisandro Dalcin if item not in seq: 818f46a955bSLisandro Dalcin seq.append(item) 819f46a955bSLisandro Dalcin 8206f336411SStefano Zampini 821f46a955bSLisandro Dalcindef append_dict(conf, dct): 822f46a955bSLisandro Dalcin for key, values in dct.items(): 823f46a955bSLisandro Dalcin if key in conf: 824f46a955bSLisandro Dalcin for value in values: 825f46a955bSLisandro Dalcin if value not in conf[key]: 826f46a955bSLisandro Dalcin conf[key].append(value) 8276f336411SStefano Zampini 8286f336411SStefano Zampini 829f46a955bSLisandro Dalcindef unique(seq): 830f46a955bSLisandro Dalcin res = [] 831f46a955bSLisandro Dalcin for item in seq: 832f46a955bSLisandro Dalcin if item not in res: 833f46a955bSLisandro Dalcin res.append(item) 834f46a955bSLisandro Dalcin return res 835f46a955bSLisandro Dalcin 836f46a955bSLisandro Dalcin 8376f336411SStefano Zampinidef flaglist(flags): 838f46a955bSLisandro Dalcin conf = { 839f46a955bSLisandro Dalcin 'define_macros': [], 840f46a955bSLisandro Dalcin 'undef_macros': [], 841f46a955bSLisandro Dalcin 'include_dirs': [], 842f46a955bSLisandro Dalcin 'libraries': [], 843f46a955bSLisandro Dalcin 'library_dirs': [], 844f46a955bSLisandro Dalcin 'runtime_library_dirs': [], 845f46a955bSLisandro Dalcin 'extra_compile_args': [], 846f46a955bSLisandro Dalcin 'extra_link_args': [], 847f46a955bSLisandro Dalcin } 848f46a955bSLisandro Dalcin 8496f336411SStefano Zampini if isinstance(flags, str): 850f46a955bSLisandro Dalcin flags = flags.split() 851f46a955bSLisandro Dalcin 852f46a955bSLisandro Dalcin switch = '-Wl,' 853f46a955bSLisandro Dalcin newflags = [] 854f46a955bSLisandro Dalcin linkopts = [] 855f46a955bSLisandro Dalcin for f in flags: 856f46a955bSLisandro Dalcin if f.startswith(switch): 857f46a955bSLisandro Dalcin if len(f) > 4: 858f46a955bSLisandro Dalcin append(linkopts, f[4:]) 859f46a955bSLisandro Dalcin else: 860f46a955bSLisandro Dalcin append(newflags, f) 861f46a955bSLisandro Dalcin if linkopts: 862f46a955bSLisandro Dalcin newflags.append(switch + ','.join(linkopts)) 863f46a955bSLisandro Dalcin flags = newflags 864f46a955bSLisandro Dalcin 865f46a955bSLisandro Dalcin append_next_word = None 866f46a955bSLisandro Dalcin 867f46a955bSLisandro Dalcin for word in flags: 868f46a955bSLisandro Dalcin if append_next_word is not None: 869f46a955bSLisandro Dalcin append(append_next_word, word) 870f46a955bSLisandro Dalcin append_next_word = None 871f46a955bSLisandro Dalcin continue 872f46a955bSLisandro Dalcin 873f46a955bSLisandro Dalcin switch, value = word[0:2], word[2:] 874f46a955bSLisandro Dalcin 8756f336411SStefano Zampini if switch == '-I': 876f46a955bSLisandro Dalcin append(conf['include_dirs'], value) 8776f336411SStefano Zampini elif switch == '-D': 878f46a955bSLisandro Dalcin try: 8796f336411SStefano Zampini idx = value.index('=') 880f46a955bSLisandro Dalcin macro = (value[:idx], value[idx + 1 :]) 881f46a955bSLisandro Dalcin except ValueError: 882f46a955bSLisandro Dalcin macro = (value, None) 883f46a955bSLisandro Dalcin append(conf['define_macros'], macro) 8846f336411SStefano Zampini elif switch == '-U': 885f46a955bSLisandro Dalcin append(conf['undef_macros'], value) 8866f336411SStefano Zampini elif switch == '-l': 887f46a955bSLisandro Dalcin append(conf['libraries'], value) 8886f336411SStefano Zampini elif switch == '-L': 889f46a955bSLisandro Dalcin append(conf['library_dirs'], value) 8906f336411SStefano Zampini elif switch == '-R': 891f46a955bSLisandro Dalcin append(conf['runtime_library_dirs'], value) 8926f336411SStefano Zampini elif word.startswith('-Wl'): 893f46a955bSLisandro Dalcin linkopts = word.split(',') 894f46a955bSLisandro Dalcin append_dict(conf, flaglist(linkopts[1:])) 8956f336411SStefano Zampini elif word == '-rpath': 896f46a955bSLisandro Dalcin append_next_word = conf['runtime_library_dirs'] 8976f336411SStefano Zampini elif word == '-Xlinker': 898f46a955bSLisandro Dalcin append_next_word = conf['extra_link_args'] 899f46a955bSLisandro Dalcin else: 900f46a955bSLisandro Dalcin # log.warn("unrecognized flag '%s'" % word) 901f46a955bSLisandro Dalcin pass 902f46a955bSLisandro Dalcin return conf 903f46a955bSLisandro Dalcin 9046f336411SStefano Zampini 905f46a955bSLisandro Dalcindef prepend_to_flags(path, flags): 906f46a955bSLisandro Dalcin """Prepend a path to compiler flags with absolute paths""" 907f46a955bSLisandro Dalcin if not path: 908f46a955bSLisandro Dalcin return flags 9096f336411SStefano Zampini 910f46a955bSLisandro Dalcin def append_path(m): 911f46a955bSLisandro Dalcin switch = m.group(1) 912f46a955bSLisandro Dalcin open_quote = m.group(4) 913f46a955bSLisandro Dalcin old_path = m.group(5) 914f46a955bSLisandro Dalcin close_quote = m.group(6) 915f46a955bSLisandro Dalcin if os.path.isabs(old_path): 916f46a955bSLisandro Dalcin moded_path = os.path.normpath(path + os.path.sep + old_path) 917f46a955bSLisandro Dalcin return switch + open_quote + moded_path + close_quote 918f46a955bSLisandro Dalcin return m.group(0) 9196f336411SStefano Zampini 9206f336411SStefano Zampini return re.sub(r'((^|\s+)(-I|-L))(\s*["\']?)(\S+)(["\']?)', append_path, flags) 9216f336411SStefano Zampini 922f46a955bSLisandro Dalcin 923f46a955bSLisandro Dalcindef strip_prefix(prefix, string): 924f46a955bSLisandro Dalcin if not prefix: 925f46a955bSLisandro Dalcin return string 926f46a955bSLisandro Dalcin return re.sub(r'^' + prefix, '', string) 927f46a955bSLisandro Dalcin 9286f336411SStefano Zampini 929f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 930f46a955bSLisandro Dalcin 931f46a955bSLisandro Dalcin# Regexes needed for parsing Makefile-like syntaxes 9326f336411SStefano Zampini_variable_rx = re.compile(r'([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)') 9336f336411SStefano Zampini_findvar1_rx = re.compile(r'\$\(([A-Za-z][A-Za-z0-9_]*)\)') 9346f336411SStefano Zampini_findvar2_rx = re.compile(r'\${([A-Za-z][A-Za-z0-9_]*)}') 9356f336411SStefano Zampini 936f46a955bSLisandro Dalcin 937f46a955bSLisandro Dalcindef makefile(fileobj, dct=None): 938f46a955bSLisandro Dalcin """Parse a Makefile-style file. 939f46a955bSLisandro Dalcin 940f46a955bSLisandro Dalcin A dictionary containing name/value pairs is returned. If an 941f46a955bSLisandro Dalcin optional dictionary is passed in as the second argument, it is 942f46a955bSLisandro Dalcin used instead of a new dictionary. 943f46a955bSLisandro Dalcin """ 9446f336411SStefano Zampini fp = TextFile(file=fileobj, strip_comments=1, skip_blanks=1, join_lines=1) 945f46a955bSLisandro Dalcin 946f46a955bSLisandro Dalcin if dct is None: 947f46a955bSLisandro Dalcin dct = {} 948f46a955bSLisandro Dalcin done = {} 949f46a955bSLisandro Dalcin notdone = {} 950f46a955bSLisandro Dalcin 951f46a955bSLisandro Dalcin while 1: 952f46a955bSLisandro Dalcin line = fp.readline() 953f46a955bSLisandro Dalcin if line is None: # eof 954f46a955bSLisandro Dalcin break 955f46a955bSLisandro Dalcin m = _variable_rx.match(line) 956f46a955bSLisandro Dalcin if m: 957f46a955bSLisandro Dalcin n, v = m.group(1, 2) 958f46a955bSLisandro Dalcin v = str.strip(v) 9596f336411SStefano Zampini if '$' in v: 960f46a955bSLisandro Dalcin notdone[n] = v 961f46a955bSLisandro Dalcin else: 9626f336411SStefano Zampini try: 9636f336411SStefano Zampini v = int(v) 9646f336411SStefano Zampini except ValueError: 9656f336411SStefano Zampini pass 966f46a955bSLisandro Dalcin done[n] = v 9676f336411SStefano Zampini try: 9686f336411SStefano Zampini del notdone[n] 9696f336411SStefano Zampini except KeyError: 9706f336411SStefano Zampini pass 971f46a955bSLisandro Dalcin fp.close() 972f46a955bSLisandro Dalcin 973f46a955bSLisandro Dalcin # do variable interpolation here 974f46a955bSLisandro Dalcin while notdone: 975f46a955bSLisandro Dalcin for name in list(notdone.keys()): 976f46a955bSLisandro Dalcin value = notdone[name] 977f46a955bSLisandro Dalcin m = _findvar1_rx.search(value) or _findvar2_rx.search(value) 978f46a955bSLisandro Dalcin if m: 979f46a955bSLisandro Dalcin n = m.group(1) 980f46a955bSLisandro Dalcin found = True 981f46a955bSLisandro Dalcin if n in done: 982f46a955bSLisandro Dalcin item = str(done[n]) 983f46a955bSLisandro Dalcin elif n in notdone: 984f46a955bSLisandro Dalcin # get it on a subsequent round 985f46a955bSLisandro Dalcin found = False 986f46a955bSLisandro Dalcin else: 9876f336411SStefano Zampini done[n] = item = '' 988f46a955bSLisandro Dalcin if found: 989f46a955bSLisandro Dalcin after = value[m.end() :] 990f46a955bSLisandro Dalcin value = value[: m.start()] + item + after 9916f336411SStefano Zampini if '$' in after: 992f46a955bSLisandro Dalcin notdone[name] = value 993f46a955bSLisandro Dalcin else: 9946f336411SStefano Zampini try: 9956f336411SStefano Zampini value = int(value) 996f46a955bSLisandro Dalcin except ValueError: 997f46a955bSLisandro Dalcin done[name] = str.strip(value) 998f46a955bSLisandro Dalcin else: 999f46a955bSLisandro Dalcin done[name] = value 1000f46a955bSLisandro Dalcin del notdone[name] 1001f46a955bSLisandro Dalcin else: 1002f46a955bSLisandro Dalcin # bogus variable reference; 1003f46a955bSLisandro Dalcin # just drop it since we can't deal 1004f46a955bSLisandro Dalcin del notdone[name] 1005f46a955bSLisandro Dalcin # save the results in the global dictionary 1006f46a955bSLisandro Dalcin dct.update(done) 1007f46a955bSLisandro Dalcin return dct 1008f46a955bSLisandro Dalcin 10096f336411SStefano Zampini 1010f46a955bSLisandro Dalcin# -------------------------------------------------------------------- 1011