aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar Yun Peng <pcloudy@google.com>2017-04-25 14:21:41 +0200
committerGravatar Vladimir Moskva <vladmos@google.com>2017-04-25 14:48:20 +0200
commit29d5e9c533e74970ca0fa9d1adbe9cc5cbe02cf2 (patch)
tree2d836096fbf02bbd8b948299705df8f76b63aa63 /tools
parent3b5f9bd49d4e891aa3ca07e30a28158f1184c3db (diff)
Parse /showIncludes output for MSVC compiler
Instead of parsing .d file generated by wrapper script, we directly parse the output of /showIncludes option. Change-Id: Id94e20a5cb05a494a793fd6a43756d44d27cea8a PiperOrigin-RevId: 154161939
Diffstat (limited to 'tools')
-rw-r--r--tools/cpp/CROSSTOOL.tpl13
-rw-r--r--tools/cpp/wrapper/bin/pydir/msvc_cl.py22
-rw-r--r--tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl81
3 files changed, 37 insertions, 79 deletions
diff --git a/tools/cpp/CROSSTOOL.tpl b/tools/cpp/CROSSTOOL.tpl
index 2d394c62f1..353e86fa82 100644
--- a/tools/cpp/CROSSTOOL.tpl
+++ b/tools/cpp/CROSSTOOL.tpl
@@ -300,8 +300,15 @@ toolchain {
}
}
+ # Stop adding any flag for dotD file, Bazel knows how to parse the output of /showIncludes option
+ # TODO(bazel-team): Remove this empty feature. https://github.com/bazelbuild/bazel/issues/2868
feature {
name: 'dependency_file'
+ }
+
+ # Tell Bazel to parse the output of /showIncludes
+ feature {
+ name: 'parse_showincludes'
flag_set {
action: 'assemble'
action: 'preprocess-assemble'
@@ -310,10 +317,8 @@ toolchain {
action: 'c++-module-compile'
action: 'c++-header-preprocessing'
action: 'c++-header-parsing'
- expand_if_all_available: 'dependency_file'
flag_group {
- flag: '/DEPENDENCY_FILE'
- flag: '%{dependency_file}'
+ flag: "/showIncludes"
}
}
}
@@ -361,6 +366,7 @@ toolchain {
}
implies: 'nologo'
implies: 'msvc_env'
+ implies: 'parse_showincludes'
}
action_config {
@@ -396,6 +402,7 @@ toolchain {
}
implies: 'nologo'
implies: 'msvc_env'
+ implies: 'parse_showincludes'
}
action_config {
diff --git a/tools/cpp/wrapper/bin/pydir/msvc_cl.py b/tools/cpp/wrapper/bin/pydir/msvc_cl.py
index 89766a6fb7..4f4b685fc8 100644
--- a/tools/cpp/wrapper/bin/pydir/msvc_cl.py
+++ b/tools/cpp/wrapper/bin/pydir/msvc_cl.py
@@ -43,7 +43,6 @@ GCCPATTERNS = [
# This is unneeded for Windows.
(('-include', '(.+)'), ['/FI$PATH0']),
- (('/DEPENDENCY_FILE', '(.+)'), ['$GENERATE_DEPS0']),
('-w', ['/w']),
('-Wall', ['/Wall']),
('-Wsign-compare', ['/we4018']),
@@ -107,6 +106,27 @@ class MsvcCompiler(msvc_tools.WindowsRunner):
"""
parser = msvc_tools.ArgParser(self, argv, GCCPATTERNS)
+ # Select runtime option
+ # Find the last runtime option passed
+ rt = None
+ rt_idx = -1
+ for i, opt in enumerate(reversed(parser.options)):
+ if opt in ['/MT', '/MTd', '/MD', '/MDd']:
+ if opt[-1] == 'd':
+ parser.enforce_debug_rt = True
+ rt = opt[:3]
+ rt_idx = len(parser.options) - i - 1
+ break
+ rt = rt or '/MT' # Default to static runtime
+ # Add debug if necessary
+ if parser.enforce_debug_rt:
+ rt += 'd'
+ # Include runtime option
+ if rt_idx >= 0:
+ parser.options[rt_idx] = rt
+ else:
+ parser.options.append(rt)
+
compiler = 'cl'
if parser.is_cuda_compilation:
compiler = 'nvcc'
diff --git a/tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl b/tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl
index 76a5aa57a5..b8f86abc3b 100644
--- a/tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl
+++ b/tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl
@@ -20,6 +20,7 @@ import ntpath
import os
import re
import subprocess
+import sys
MAX_PATH = 260 # The maximum number of characters in a Windows path.
MAX_OPTION_LENGTH = 10 # The maximum length of a compiler/linker option.
@@ -58,6 +59,7 @@ class ArgParser(object):
self.global_whole_archive = None
self.is_cuda_compilation = None
self.cuda_log = False
+ self.enforce_debug_rt = False
self._ParseArgs(argv)
def ReplaceLibrary(self, arg):
@@ -256,7 +258,6 @@ class ArgParser(object):
matched = []
unmatched = []
files = []
- enforce_debug_rt = False
while i < len(argv):
num_matched, action, groups = self._MatchOneArg(argv[i:])
arg = argv[i]
@@ -308,7 +309,7 @@ class ArgParser(object):
continue
if entry == '$DEBUG_RT':
- enforce_debug_rt = True
+ self.enforce_debug_rt = True
continue
if not groups:
@@ -338,11 +339,6 @@ class ArgParser(object):
exit(-1)
continue
- if entry == ('$GENERATE_DEPS%d' % g):
- self.options.append('/showIncludes')
- self.deps_file = value
- continue
-
# Regular substitution.
patterns = {
'$%d' % g: value,
@@ -356,27 +352,6 @@ class ArgParser(object):
i += num_matched
self.leftover = unmatched
- # Select runtime option
- # Find the last runtime option passed
- rt = None
- rt_idx = -1
- for i, opt in enumerate(reversed(self.options)):
- if opt in ['/MT', '/MTd', '/MD', '/MDd']:
- if opt[-1] == 'd':
- enforce_debug_rt = True
- rt = opt[:3]
- rt_idx = len(self.options) - i - 1
- break
- rt = rt or '/MT' # Default to static runtime
- # Add debug if necessary
- if enforce_debug_rt:
- rt += 'd'
- # Include runtime option
- if rt_idx >= 0:
- self.options[rt_idx] = rt
- else:
- self.options.append(rt)
-
# Add in any parsed files
self.options += files
@@ -452,28 +427,7 @@ class WindowsRunner(object):
Returns:
The return code from executing binary.
"""
- # Filter out some not-so-useful cl windows messages.
- filters = [
- '.*warning LNK4006: __NULL_IMPORT_DESCRIPTOR already defined.*\n',
- '.*warning LNK4044: unrecognized option \'/MT\'; ignored.*\n',
- '.*warning LNK4044: unrecognized option \'/link\'; ignored.*\n',
- '.*warning LNK4221: This object file does not define any '
- 'previously.*\n',
- '\r\n',
- '\n\r',
- ]
-
- # Check again the arguments are within MAX_PATH.
- for arg in args:
- if os.path.splitext(arg)[1].lower() in ['.c', '.cc', '.cpp', '.s']:
- # cl.exe prints out the file name it is compiling; add that to the
- # filter.
- name = arg.rpartition(ntpath.sep)[2]
- filters.append(name)
-
- # Construct a large regular expression for all filters.
- output_filter = re.compile('(' + ')|('.join(filters) + ')')
- includes_filter = re.compile(r'Note: including file:\s+(.*)')
+
# Run the command.
if parser.params_file:
try:
@@ -493,32 +447,9 @@ class WindowsRunner(object):
# Unconmment the following line to see what exact command is executed.
# print("Running: " + " ".join(cmd))
proc = subprocess.Popen(cmd,
+ stdout=sys.stdout,
+ stderr=sys.stderr,
env=os.environ.copy(),
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
shell=True)
- deps = []
- for line in proc.stdout:
- line = line.decode('utf-8')
- if not output_filter.match(line):
- includes = includes_filter.match(line)
- if includes:
- filename = includes.group(1).rstrip()
- deps += [filename]
- else:
- print(line.rstrip())
proc.wait()
-
- # Generate deps file if requested.
- if parser.deps_file:
- with open(parser.deps_file, 'w') as deps_file:
- # Start with the name of the output file.
- deps_file.write(parser.output_file + ': \\\n')
- for i, dep in enumerate(deps):
- dep = dep.replace('\\', '/').replace(' ', '\\ ')
- deps_file.write(' ' + dep)
- if i < len(deps) - 1:
- deps_file.write(' \\')
- deps_file.write('\n')
-
return proc.returncode