From 401597bb6262e2f3c26209be3afac235098c55c6 Mon Sep 17 00:00:00 2001 From: Julian Taylor Date: Mon, 1 May 2017 23:07:39 +0200 Subject: BUG: check compiler flags to determine the need for a rebuild Some projects compile an extension multiple times with different flags. As it is not intended to get the extension name from the compiler object, store the last used flags in the dependency file and also check if they match the flags of the current build. --- numpy/distutils/ccompiler.py | 22 +++++++++++++++++----- numpy/distutils/misc_util.py | 12 ++++++++++++ numpy/distutils/unixccompiler.py | 5 +++++ 3 files changed, 34 insertions(+), 5 deletions(-) (limited to 'numpy/distutils') diff --git a/numpy/distutils/ccompiler.py b/numpy/distutils/ccompiler.py index 5f9bd4a84..98c4cc022 100644 --- a/numpy/distutils/ccompiler.py +++ b/numpy/distutils/ccompiler.py @@ -17,10 +17,11 @@ from numpy.distutils import log from numpy.distutils.compat import get_exception from numpy.distutils.exec_command import exec_command from numpy.distutils.misc_util import cyg2win32, is_sequence, mingw32, \ - quote_args, get_num_build_jobs + quote_args, get_num_build_jobs, \ + _commandline_dep_string -def _needs_build(obj): +def _needs_build(obj, cc_args, extra_postargs, pp_opts): """ Check if an objects needs to be rebuild based on its dependencies @@ -40,9 +41,20 @@ def _needs_build(obj): # dep_file is a makefile containing 'object: dependencies' # formated like posix shell (spaces escaped, \ line continuations) + # the last line contains the compiler commandline arguments as some + # projects may compile an extension multiple times with different + # arguments with open(dep_file, "r") as f: - deps = [x for x in shlex.split(f.read(), posix=True) - if x != "\n" and not x.endswith(":")] + lines = f.readlines() + + cmdline =_commandline_dep_string(cc_args, extra_postargs, pp_opts) + last_cmdline = lines[-1] + if last_cmdline != cmdline: + return True + + contents = ''.join(lines[:-1]) + deps = [x for x in shlex.split(contents, posix=True) + if x != "\n" and not x.endswith(":")] try: t_obj = os.stat(obj).st_mtime @@ -230,7 +242,7 @@ def CCompiler_compile(self, sources, output_dir=None, macros=None, def single_compile(args): obj, (src, ext) = args - if _needs_build(obj): + if _needs_build(obj, cc_args, extra_postargs, pp_opts): self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) if isinstance(self, FCompiler): diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py index de0e4a47a..21aaece70 100644 --- a/numpy/distutils/misc_util.py +++ b/numpy/distutils/misc_util.py @@ -541,6 +541,18 @@ def _get_directories(list_of_sources): direcs.append(d[0]) return direcs +def _commandline_dep_string(cc_args, extra_postargs, pp_opts): + """ + Return commandline representation used to determine if a file needs + to be recompiled + """ + cmdline = 'commandline: ' + cmdline += ' '.join(cc_args) + cmdline += ' '.join(extra_postargs) + cmdline += ' '.join(pp_opts) + '\n' + return cmdline + + def get_dependencies(sources): #XXX scan sources for include statements return _get_headers(_get_directories(sources)) diff --git a/numpy/distutils/unixccompiler.py b/numpy/distutils/unixccompiler.py index 307b56ce4..6ed5eec6f 100644 --- a/numpy/distutils/unixccompiler.py +++ b/numpy/distutils/unixccompiler.py @@ -10,6 +10,7 @@ from distutils.errors import DistutilsExecError, CompileError from distutils.unixccompiler import * from numpy.distutils.ccompiler import replace_method from numpy.distutils.compat import get_exception +from numpy.distutils.misc_util import _commandline_dep_string if sys.version_info[0] < 3: from . import log @@ -59,6 +60,10 @@ def UnixCCompiler__compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts msg = str(get_exception()) raise CompileError(msg) + # add commandline flags to dependency file + with open(obj + '.d', 'a') as f: + f.write(_commandline_dep_string(cc_args, extra_postargs, pp_opts)) + replace_method(UnixCCompiler, '_compile', UnixCCompiler__compile) -- cgit v1.2.1