blob: 377cc7a9f37d8c02fa5a47e2266e80ab91925ae5 [file] [log] [blame]
Jan Tattermusch7897ae92017-06-07 22:57:36 +02001# Copyright 2016 gRPC authors.
Ken Payson5998cd72016-08-10 15:39:43 -07002#
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003# 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
Ken Payson5998cd72016-08-10 15:39:43 -07006#
Jan Tattermusch7897ae92017-06-07 22:57:36 +02007# http://www.apache.org/licenses/LICENSE-2.0
Ken Payson5998cd72016-08-10 15:39:43 -07008#
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009# 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.
Ken Payson5998cd72016-08-10 15:39:43 -070014"""Patches the spawn() command for windows compilers.
15
16Windows has an 8191 character command line limit, but some compilers
17support an @command_file directive where command_file is a file
18containing the full command line.
19"""
20
21from distutils import ccompiler
22import os
23import os.path
24import shutil
25import sys
26import tempfile
27
28MAX_COMMAND_LENGTH = 8191
29
30_classic_spawn = ccompiler.CCompiler.spawn
31
Masood Malekghassemicc793702017-01-13 19:20:10 -080032
Ken Payson5998cd72016-08-10 15:39:43 -070033def _commandfile_spawn(self, command):
Masood Malekghassemicc793702017-01-13 19:20:10 -080034 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)
Ken Payson5998cd72016-08-10 15:39:43 -070055
56
57def monkeypatch_spawn():
Masood Malekghassemicc793702017-01-13 19:20:10 -080058 """Monkeypatching is dumb, but it's either that or we become maintainers of
Ken Payson5998cd72016-08-10 15:39:43 -070059 something much, much bigger."""
Masood Malekghassemicc793702017-01-13 19:20:10 -080060 ccompiler.CCompiler.spawn = _commandfile_spawn