From 50013b77422245d4fcf2b877ba1c977c47fd45ba Mon Sep 17 00:00:00 2001 From: Radomir Stevanovic Date: Wed, 19 May 2021 05:03:01 -0700 Subject: [PATCH] Use pyproject.toml for build requirements Simplifies `setup.py`. Cythonizes always when installed from source. Required `pip>=10.0` to install from source. Older pips will still be able to install from wheels. --- MANIFEST.in | 1 + greedy/descent.pyx | 1 - pyproject.toml | 8 +++++ requirements.txt | 4 +++ setup.py | 79 ++++++++++++++++------------------------------ 5 files changed, 41 insertions(+), 52 deletions(-) create mode 100644 pyproject.toml diff --git a/MANIFEST.in b/MANIFEST.in index 2354ca0..f73ec3c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,2 @@ +include pyproject.toml recursive-include greedy *.h *.cpp *.pxd *.pyx diff --git a/greedy/descent.pyx b/greedy/descent.pyx index b7fa437..968d722 100644 --- a/greedy/descent.pyx +++ b/greedy/descent.pyx @@ -1,7 +1,6 @@ # distutils: language = c++ # distutils: include_dirs = greedy/src/ # distutils: sources = greedy/src/descent.cpp -# distutils: language_level = 3 # Copyright 2019 D-Wave Systems Inc. # diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8d3a555 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,8 @@ +[build-system] +requires = [ + "setuptools>=42.0.0", # PEP-420 support, PEP-517/518 support + "wheel>=0.30.0", # limited python api support + "cython>=0.29.23,<3.0", + "numpy==1.19.4", +] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt index c362a60..9a791ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,7 @@ numpy==1.19.4 dimod==0.9.14 cython==0.29.21 + +# build +wheel>=0.30.0 +setuptools>=56.2.0 \ No newline at end of file diff --git a/setup.py b/setup.py index 8c9e519..3d1a710 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,28 @@ +# Copyright 2021 D-Wave Systems Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os -from io import open -from setuptools import setup, find_packages, Extension + +from setuptools import setup, Extension from setuptools.command.build_ext import build_ext +from Cython.Build import cythonize +import numpy -class cythonizing_build_ext(build_ext): - """Cython extensions adaptive build: cythonize if possible, include numpy - headers, add custom compile/link flags.""" +class build_ext_with_args(build_ext): + """Add compiler-specific compile/link flags.""" - # Custom extension compile/link flags extra_compile_args = { 'msvc': ['/std:c++14'], 'unix': ['-std=c++11'], @@ -16,48 +30,22 @@ class cythonizing_build_ext(build_ext): extra_link_args = { 'msvc': [], - 'unix': [], + 'unix': ['-std=c++11'], } def build_extensions(self): - # try using cython if available, fallback to using pre-cythonized - # files (if they exist; if not, ultimately fail) - try: - from Cython.Build import cythonize - - # cythonization step will remove this flag needed by setuptools - _needs_stub = [ext._needs_stub for ext in self.extensions] - - self.extensions = cythonize(self.extensions) - - # restore _needs_stub flags for setuptools - for ext, ns in zip(self.extensions, _needs_stub): - ext._needs_stub = ns - - except ImportError: - # cython not available, assume cythonized cpp files exist - for ext in self.extensions: - ext.sources = [source.replace(".pyx", ".cpp") for source in ext.sources] - - # add compiler/linker flags compiler = self.compiler.compiler_type compile_args = self.extra_compile_args[compiler] for ext in self.extensions: ext.extra_compile_args = compile_args + print(dir(ext)) - link_args = self.extra_compile_args[compiler] + link_args = self.extra_link_args[compiler] for ext in self.extensions: ext.extra_compile_args = link_args - build_ext.build_extensions(self) - - def finalize_options(self): - build_ext.finalize_options(self) - - # add numpy include files - import numpy - self.include_dirs.append(numpy.get_include()) + super().build_extensions() # Load package info, without importing the package @@ -77,20 +65,10 @@ def finalize_options(self): 'test': ['coverage', 'mock', 'parameterized', 'dwave-system>=1.0.0'], } -# Setup (extension build) requirements -setup_requires = ['numpy>=1.16.0,<2.0.0'] - -# We distribute cythonized source, so cython is not required -# for install (build) from package, but allow manual override via env var -USE_CYTHON = os.getenv('USE_CYTHON', False) - -if USE_CYTHON: - setup_requires.append('cython>=0.29.12') - extensions = [Extension( name='greedy.descent', - sources=['./greedy/descent.pyx'], - include_dirs=['./greedy/src/'] + sources=['greedy/descent.pyx'], + include_dirs=[numpy.get_include()] )] classifiers = [ @@ -118,10 +96,9 @@ def finalize_options(self): packages=packages, python_requires=python_requires, install_requires=install_requires, - setup_requires=setup_requires, extras_require=extras_require, - ext_modules=extensions, - cmdclass={'build_ext': cythonizing_build_ext}, + ext_modules=cythonize(extensions), + cmdclass={'build_ext': build_ext_with_args}, classifiers=classifiers, zip_safe=False, )