Permalink
Browse files

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.
  • Loading branch information...
dstufft authored and sigmavirus24 committed Sep 8, 2017
1 parent 802c4a6 commit 298e07907ae526594069f6fdf31f2f1278cc1ae3
Showing with 7 additions and 55 deletions.
  1. +7 −55 setup.py
View
@@ -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,
)

0 comments on commit 298e079

Please sign in to comment.