1 # Copyright 2016 gRPC authors. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 """Patches the spawn() command for windows compilers. 15 16 Windows has an 8191 character command line limit, but some compilers 17 support an @command_file directive where command_file is a file 18 containing the full command line. 19 """ 20 21 from distutils import ccompiler 22 import os 23 import os.path 24 import shutil 25 import sys 26 import tempfile 27 28 MAX_COMMAND_LENGTH = 8191 29 30 _classic_spawn = ccompiler.CCompiler.spawn 31 32 33 def _commandfile_spawn(self, command): 34 command_length = sum([len(arg) for arg in command]) 35 if os.name == 'nt' and command_length > MAX_COMMAND_LENGTH: 36 # Even if this command doesn't support the @command_file, it will 37 # fail as is so we try blindly 38 print('Command line length exceeded, using command file') 39 print(' '.join(command)) 40 temporary_directory = tempfile.mkdtemp() 41 command_filename = os.path.abspath( 42 os.path.join(temporary_directory, 'command')) 43 with open(command_filename, 'w') as command_file: 44 escaped_args = [ 45 '"' + arg.replace('\\', '\\\\') + '"' for arg in command[1:] 46 ] 47 command_file.write(' '.join(escaped_args)) 48 modified_command = command[:1] + ['@{}'.format(command_filename)] 49 try: 50 _classic_spawn(self, modified_command) 51 finally: 52 shutil.rmtree(temporary_directory) 53 else: 54 _classic_spawn(self, command) 55 56 57 def monkeypatch_spawn(): 58 """Monkeypatching is dumb, but it's either that or we become maintainers of 59 something much, much bigger.""" 60 ccompiler.CCompiler.spawn = _commandfile_spawn 61