Skip to content

Commit

Permalink
Add show_includes dep file processor for MSVC
Browse files Browse the repository at this point in the history
Summary:
This diff adds basic support to create dep files with MSVC.

[**Context**](https://learn.microsoft.com/en-us/cpp/build/reference/showincludes-list-include-files?view=msvc-170)
When the compiler comes to an include file during compilation, a message is output, as in this example:

```
Note: including file: d:\temp\1.h
Note: including file:  d:\temp\2.h
```
In this case, ```2.h``` was included from within ```1.h```, causing the indentation.

As in buck2 we don't care (yet) about which file includes which we strip out the prefix, normalize the paths and print to dep file.

Reviewed By: krallin

Differential Revision: D43244023

fbshipit-source-id: e9312672c55e64dd2b83545cf6f9b9acc61bf2cb
  • Loading branch information
lmvasquezg authored and facebook-github-bot committed Apr 11, 2023
1 parent 5166ec7 commit c4053da
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 1 deletion.
1 change: 1 addition & 0 deletions prelude/cxx/tools/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ prelude.python_bootstrap_library(
srcs = [
"makefile_to_dep_file.py",
"show_headers_to_dep_file.py",
"show_includes_to_dep_file.py",
"dep_file_utils.py",
],
visibility = ["PUBLIC"],
Expand Down
4 changes: 3 additions & 1 deletion prelude/cxx/tools/dep_file_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import sys

from makefile_to_dep_file import process_dep_file

from show_headers_to_dep_file import process_show_headers_dep_file
from show_includes_to_dep_file import process_show_includes_dep_file


def main():
Expand All @@ -36,6 +36,8 @@ def main():
dep_tracking_mode = sys.argv[1]
if dep_tracking_mode == "show_headers":
process_show_headers_dep_file(sys.argv[3], sys.argv[4:], sys.argv[2])
elif dep_tracking_mode == "show_includes":
process_show_includes_dep_file(sys.argv[3], sys.argv[4:], sys.argv[2])
else:
process_dep_file(sys.argv[2:])

Expand Down
70 changes: 70 additions & 0 deletions prelude/cxx/tools/show_includes_to_dep_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under both the MIT license found in the
# LICENSE-MIT file in the root directory of this source tree and the Apache
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.

import os
import subprocess
import sys

import dep_file_utils

DEP_PREFIX = "Note: including file:"
# output_path -> path to write the dep field to
# cmd_args -> command to be run to get dependencies from compiler
# source_file -> Path to the file we're generating the dep file for. We need this since
# when generating dependencies for a file using show_headers, the output does not include
# the file itself, so we need the path to add it manually
def process_show_includes_dep_file(output_path, cmd_args, input_file):
out = subprocess.run(cmd_args, stdout=subprocess.PIPE, encoding="utf-8")
if out.returncode == 0:
rewrite_dep_file_for_msvc(out.stdout, output_path, input_file)
else:
parse_stdout_error_output(out.stdout)
sys.exit(out.returncode)


def rewrite_dep_file_for_msvc(output, dst_path, input_file):
"""
Convert stdout generated by MSVC to dep file. This will be a mix of output like:
file.cpp
Note: including file: path/to/dep1.h
Note: including file: path/to/dep2.h
Note: including file: path/to/dep3.h
error: this is an error!
and we want to get:
path/to/dep1.h
path/to/dep2.h
path/to/dep3.h
"""
here = os.getcwd() + os.sep
deps = []
# First line is the name of the file we're generating deps for.
# We manually include it later so let's ignore it.
lines = output.splitlines()[1:]
for line in lines:
if DEP_PREFIX in line:
line = line.replace(DEP_PREFIX, "").strip()
deps.append(line)
else:
print(line, file=sys.stderr)
deps.append(input_file)
normalized_deps = dep_file_utils.normalize_deps(deps, here)

with open(dst_path, "w") as f:
for dep in normalized_deps:
f.write(dep)
f.write("\n")


def parse_stdout_error_output(output):
lines = output.splitlines()[1:]
for line in lines:
if DEP_PREFIX not in line:
print(line, file=sys.stderr)

0 comments on commit c4053da

Please sign in to comment.