#!/usr/bin/env python3 # setup script # Copyright (C) 2019, 2020 Nguyễn Gia Phong # Copyright (C) 2020 Francesco Caliumi # # This file is part of palace. # # palace is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, # or (at your option) any later version. # # palace is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with palace. If not, see . import re from distutils import log from distutils.command.clean import clean from distutils.dir_util import mkpath from distutils.errors import DistutilsExecError, DistutilsFileError from distutils.file_util import copy_file from operator import methodcaller from os import environ, unlink from os.path import dirname, join from platform import system from subprocess import DEVNULL, PIPE, run, CalledProcessError from Cython.Build import cythonize from setuptools import setup, Extension from setuptools.command.build_ext import build_ext CPPSTD = '/std:c++14' if system() == 'Windows' else '-std=c++14' try: TRACE = int(environ['CYTHON_TRACE']) except KeyError: TRACE = 0 except ValueError: TRACE = 0 def src(file: str) -> str: """Return path to the given file in src.""" return join(dirname(__file__), 'src', file) class BuildAlure2Ext(build_ext): """Builder of extensions linked to alure2.""" def finalize_options(self) -> None: """Add alure2's and its dependencies' include directories and objects to Extension attributes. """ super().finalize_options() mkpath(self.build_temp) copy_file(join(dirname(__file__), 'CMakeLists.txt'), self.build_temp) try: cmake = run( ['cmake', '.'], check=True, stdout=DEVNULL, stderr=PIPE, cwd=self.build_temp, universal_newlines=True) except CalledProcessError as e: log.error(e.stderr.strip()) raise DistutilsExecError(str(e)) for key, value in map(methodcaller('groups'), re.finditer(r'^alure2_(\w*)=(.*)$', cmake.stderr, re.MULTILINE)): for ext in self.extensions: getattr(ext, key).extend(value.split(';')) class CleanCppToo(clean): """Clean command that remove Cython C++ outputs.""" def run(self) -> None: """Remove Cython C++ outputs on clean command.""" for cpp in [src('palace.cpp')]: log.info(f'removing {cpp!r}') try: unlink(cpp) except OSError as e: raise DistutilsFileError( f'could not delete {cpp!r}: {e.strerror}') super().run() setup(cmdclass=dict(build_ext=BuildAlure2Ext, clean=CleanCppToo), ext_modules=cythonize( Extension(name='palace', sources=[src('palace.pyx')], define_macros=[('CYTHON_TRACE', TRACE)], extra_compile_args=[CPPSTD], language='c++'), compiler_directives=dict( binding=True, linetrace=TRACE, language_level='3str', c_string_type='str', c_string_encoding='utf8')))