diff options
author | Yun Peng <pcloudy@google.com> | 2017-04-25 14:21:41 +0200 |
---|---|---|
committer | Vladimir Moskva <vladmos@google.com> | 2017-04-25 14:48:20 +0200 |
commit | 29d5e9c533e74970ca0fa9d1adbe9cc5cbe02cf2 (patch) | |
tree | 2d836096fbf02bbd8b948299705df8f76b63aa63 /tools | |
parent | 3b5f9bd49d4e891aa3ca07e30a28158f1184c3db (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.tpl | 13 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/pydir/msvc_cl.py | 22 | ||||
-rw-r--r-- | tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl | 81 |
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 |