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