From fb90e51d816c2256d7c5165d7262146f391d4365 Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Fri, 8 Sep 2017 11:05:24 -0400 Subject: [PATCH] Fallback to Pure Python if Compilation fails Originally this code attempted to determine if compiling the C ext would succeed, and if it thought it should, it would then require that the C extension succeed in order to install. This fails in cases where the detection code passes, but compiling ultimately fails (one instance this might happen is if the Python headers are not installed). Instead of "asking permission", this code will now just attempt to compile the module, and will fall back to pure Python if that fails, unless the person has explicitly asked for the C module, in which case it will still just fail. --- setup.py | 62 +++++++------------------------------------------------- 1 file changed, 7 insertions(+), 55 deletions(-) diff --git a/setup.py b/setup.py index 9892ab52..479ff04f 100644 --- a/setup.py +++ b/setup.py @@ -204,63 +204,16 @@ def build_extensions(self): self.check_extensions_list(self.extensions) for ext in self.extensions: with_ext = self.distribution.ext_status(ext) - if with_ext is None: - with_ext = self.check_extension_availability(ext) - if not with_ext: + if with_ext is not None and not with_ext: continue if with_cython: ext.sources = self.cython_sources(ext.sources, ext) - self.build_extension(ext) - - def check_extension_availability(self, ext): - cache = os.path.join(self.build_temp, 'check_%s.out' % ext.feature_name) - if not self.force and os.path.isfile(cache): - data = open(cache).read().strip() - if data == '1': - return True - elif data == '0': - return False - mkpath(self.build_temp) - src = os.path.join(self.build_temp, 'check_%s.c' % ext.feature_name) - open(src, 'w').write(ext.feature_check) - log.info("checking if %s is compilable" % ext.feature_name) - try: - [obj] = self.compiler.compile([src], - macros=ext.define_macros+[(undef,) for undef in ext.undef_macros], - include_dirs=ext.include_dirs, - extra_postargs=(ext.extra_compile_args or []), - depends=ext.depends) - except CompileError: - log.warn("") - log.warn("%s is not found or a compiler error: forcing --%s" - % (ext.feature_name, ext.neg_option_name)) - log.warn("(if %s is installed correctly, you may need to" - % ext.feature_name) - log.warn(" specify the option --include-dirs or uncomment and") - log.warn(" modify the parameter include_dirs in setup.cfg)") - open(cache, 'w').write('0\n') - return False - prog = 'check_%s' % ext.feature_name - log.info("checking if %s is linkable" % ext.feature_name) - try: - self.compiler.link_executable([obj], prog, - output_dir=self.build_temp, - libraries=ext.libraries, - library_dirs=ext.library_dirs, - runtime_library_dirs=ext.runtime_library_dirs, - extra_postargs=(ext.extra_link_args or [])) - except LinkError: - log.warn("") - log.warn("%s is not found or a linker error: forcing --%s" - % (ext.feature_name, ext.neg_option_name)) - log.warn("(if %s is installed correctly, you may need to" - % ext.feature_name) - log.warn(" specify the option --library-dirs or uncomment and") - log.warn(" modify the parameter library_dirs in setup.cfg)") - open(cache, 'w').write('0\n') - return False - open(cache, 'w').write('1\n') - return True + try: + self.build_extension(ext) + except (CompileError, LinkError): + if with_ext is not None: + raise + log.warn("Error compiling module, falling back to pure Python") class bdist_rpm(_bdist_rpm): @@ -342,4 +295,3 @@ def run(self): distclass=Distribution, cmdclass=cmdclass, ) -