From 4046e48ac10793b9a64289b1b69f48dcf1a0dcab Mon Sep 17 00:00:00 2001 From: James Harris Date: Fri, 15 Feb 2019 10:50:27 -0600 Subject: [PATCH] task: calculate correct cmdline bytes The previous patches to workaround http://support.microsoft.com/kb/830473 drastically over estimated the number of characters in commands by treating the repr() version of the command array as a reasonable estimator of commandline length. This caused commands attempt to write argsfiles before they should have. The new calculation calculates the number characters in the command array and adds the number of spaces that would be added by ' '.join(cmd) this provides a much closer estimate of the commandline length. This also limits the CLI-length on non windows platforms to 200kB. This prevents us hitting the much larger argument limits on Linux/BSD/MacOS platforms. --- waflib/Task.py | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/waflib/Task.py b/waflib/Task.py index f6707610..eeae0288 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -308,23 +308,29 @@ class Task(evil): # workaround for command line length limit: # http://support.microsoft.com/kb/830473 - if not isinstance(cmd, str) and (len(repr(cmd)) >= 8192 if Utils.is_win32 else len(cmd) > 200000): - cmd, args = self.split_argfile(cmd) - try: - (fd, tmp) = tempfile.mkstemp() - os.write(fd, '\r\n'.join(args).encode()) - os.close(fd) - if Logs.verbose: - Logs.debug('argfile: @%r -> %r', tmp, args) - return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw) - finally: + if not isinstance(cmd, str): + # Calculate commandline length: + cmd_bytes = sum([len(arg) for arg in cmd] + len(cmd) -1) + # Shunt arguments to a temporary file if the command is + # going to be too long. + if (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000): + cmd, args = self.split_argfile(cmd) try: - os.remove(tmp) - except OSError: - # anti-virus and indexers can keep files open -_- - pass - else: - return self.generator.bld.exec_command(cmd, **kw) + (fd, tmp) = tempfile.mkstemp() + os.write(fd, '\r\n'.join(args).encode()) + os.close(fd) + if Logs.verbose: + Logs.debug('argfile: @%r -> %r', tmp, args) + return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw) + finally: + try: + os.remove(tmp) + except OSError: + # anti-virus and indexers can keep files open -_- + pass + # If this line is hit then the command can be passed down stream + # directly. + return self.generator.bld.exec_command(cmd, **kw) def process(self): """