summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Kümmel <kuemmel@coffeelogic.de>2013-10-13 10:20:17 (GMT)
committerPeter Kümmel <syntheticpp@gmx.net>2013-10-18 23:25:47 (GMT)
commit037b0934f929ba17434906fb781aeb1acb583385 (patch)
treef426231b651860a2ddc382d2c1ff842cdeab95d0
parent6f7ea464bb9161ce2e15deb97977886de152c12d (diff)
downloadNinja-037b0934f929ba17434906fb781aeb1acb583385.zip
Ninja-037b0934f929ba17434906fb781aeb1acb583385.tar.gz
Ninja-037b0934f929ba17434906fb781aeb1acb583385.tar.bz2
add deps_prefix for localized /showIncludes' output parsing
-rw-r--r--doc/manual.asciidoc10
-rw-r--r--src/build.cc6
-rw-r--r--src/build.h2
-rw-r--r--src/includes_normalize_test.cc2
-rw-r--r--src/msvc_helper-win32.cc15
-rw-r--r--src/msvc_helper.h4
-rw-r--r--src/msvc_helper_main-win32.cc9
-rw-r--r--src/msvc_helper_test.cc29
8 files changed, 50 insertions, 27 deletions
diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc
index a735257..67fcbfd 100644
--- a/doc/manual.asciidoc
+++ b/doc/manual.asciidoc
@@ -580,9 +580,13 @@ Ninja supports this processing in two forms.
http://msdn.microsoft.com/en-us/library/hdkef6tk(v=vs.90).aspx[`/showIncludes`
flag]. Briefly, this means the tool outputs specially-formatted lines
to its stdout. Ninja then filters these lines from the displayed
- output. No `depfile` attribute is necessary.
+ output. No `depfile` attribute is necessary, but the localized string
+ in front of the the header file path. For instance
+ `msvc_deps_prefix = Note: including file: `
+ for a English Visual Studio (the default). Should be globally defined.
+
----
+msvc_deps_prefix = Note: including file:
rule cc
deps = msvc
command = cl /showIncludes -c $in /Fo$out
@@ -772,6 +776,10 @@ keys.
stored as `.ninja_deps` in the `builddir`, see <<ref_toplevel,the
discussion of `builddir`>>.
+`msvc_deps_prefix`:: _(Available since Ninja 1.5.)_ defines the string
+ which should be stripped from msvc's /showIncludes output. Only
+ needed when `deps = msvc` and no English Visual Studio version is used.
+
`description`:: a short description of the command, used to pretty-print
the command as it's running. The `-v` flag controls whether to print
the full command or its description; if a command fails, the full command
diff --git a/src/build.cc b/src/build.cc
index 9718f85..33aa85b 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -714,9 +714,10 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
// build perspective.
vector<Node*> deps_nodes;
string deps_type = edge->GetBinding("deps");
+ const string deps_prefix = edge->GetBinding("msvc_deps_prefix");
if (!deps_type.empty()) {
string extract_err;
- if (!ExtractDeps(result, deps_type, &deps_nodes, &extract_err) &&
+ if (!ExtractDeps(result, deps_type, deps_prefix, &deps_nodes, &extract_err) &&
result->success()) {
if (!result->output.empty())
result->output.append("\n");
@@ -802,12 +803,13 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
bool Builder::ExtractDeps(CommandRunner::Result* result,
const string& deps_type,
+ const string& deps_prefix,
vector<Node*>* deps_nodes,
string* err) {
#ifdef _WIN32
if (deps_type == "msvc") {
CLParser parser;
- result->output = parser.Parse(result->output);
+ result->output = parser.Parse(result->output, deps_prefix);
for (set<string>::iterator i = parser.includes_.begin();
i != parser.includes_.end(); ++i) {
deps_nodes->push_back(state_->GetNode(*i));
diff --git a/src/build.h b/src/build.h
index 5b6c83c..1122d84 100644
--- a/src/build.h
+++ b/src/build.h
@@ -180,7 +180,7 @@ struct Builder {
BuildStatus* status_;
private:
- bool ExtractDeps(CommandRunner::Result* result, const string& deps_type,
+ bool ExtractDeps(CommandRunner::Result* result, const string& deps_type, const string& deps_prefix,
vector<Node*>* deps_nodes, string* err);
DiskInterface* disk_interface_;
diff --git a/src/includes_normalize_test.cc b/src/includes_normalize_test.cc
index 1713d5d..419996f 100644
--- a/src/includes_normalize_test.cc
+++ b/src/includes_normalize_test.cc
@@ -38,7 +38,7 @@ string GetCurDir() {
} // namespace
TEST(IncludesNormalize, WithRelative) {
- string currentdir = IncludesNormalize::ToLower(GetCurDir());
+ string currentdir = GetCurDir();
EXPECT_EQ("c", IncludesNormalize::Normalize("a/b/c", "a/b"));
EXPECT_EQ("a", IncludesNormalize::Normalize(IncludesNormalize::AbsPath("a"),
NULL));
diff --git a/src/msvc_helper-win32.cc b/src/msvc_helper-win32.cc
index 7c45029..3065ab0 100644
--- a/src/msvc_helper-win32.cc
+++ b/src/msvc_helper-win32.cc
@@ -48,14 +48,13 @@ string EscapeForDepfile(const string& path) {
}
// static
-string CLParser::FilterShowIncludes(const string& line) {
- static const char kMagicPrefix[] = "Note: including file: ";
+string CLParser::FilterShowIncludes(const string& line, const string& deps_prefix) {
+ static const string deps_prefix_english = "Note: including file: ";
const char* in = line.c_str();
const char* end = in + line.size();
-
- if (end - in > (int)sizeof(kMagicPrefix) - 1 &&
- memcmp(in, kMagicPrefix, sizeof(kMagicPrefix) - 1) == 0) {
- in += sizeof(kMagicPrefix) - 1;
+ const string& prefix = deps_prefix.empty() ? deps_prefix_english : deps_prefix;
+ if (end - in > (int)prefix.size() && memcmp(in, prefix.c_str(), (int)prefix.size()) == 0) {
+ in += prefix.size();
while (*in == ' ')
++in;
return line.substr(in - line.c_str());
@@ -81,7 +80,7 @@ bool CLParser::FilterInputFilename(string line) {
EndsWith(line, ".cpp");
}
-string CLParser::Parse(const string& output) {
+string CLParser::Parse(const string& output, const string& deps_prefix) {
string filtered_output;
// Loop over all lines in the output to process them.
@@ -92,7 +91,7 @@ string CLParser::Parse(const string& output) {
end = output.size();
string line = output.substr(start, end - start);
- string include = FilterShowIncludes(line);
+ string include = FilterShowIncludes(line, deps_prefix);
if (!include.empty()) {
include = IncludesNormalize::Normalize(include, NULL);
if (!IsSystemInclude(include))
diff --git a/src/msvc_helper.h b/src/msvc_helper.h
index e207485..0433769 100644
--- a/src/msvc_helper.h
+++ b/src/msvc_helper.h
@@ -27,7 +27,7 @@ struct CLParser {
/// Parse a line of cl.exe output and extract /showIncludes info.
/// If a dependency is extracted, returns a nonempty string.
/// Exposed for testing.
- static string FilterShowIncludes(const string& line);
+ static string FilterShowIncludes(const string& line, const string& deps_prefix);
/// Return true if a mentioned include file is a system path.
/// Filtering these out reduces dependency information considerably.
@@ -41,7 +41,7 @@ struct CLParser {
/// Parse the full output of cl, returning the output (if any) that
/// should printed.
- string Parse(const string& output);
+ string Parse(const string& output, const string& deps_prefix);
set<string> includes_;
};
diff --git a/src/msvc_helper_main-win32.cc b/src/msvc_helper_main-win32.cc
index e3a7846..58bc797 100644
--- a/src/msvc_helper_main-win32.cc
+++ b/src/msvc_helper_main-win32.cc
@@ -31,6 +31,7 @@ void Usage() {
"options:\n"
" -e ENVFILE load environment block from ENVFILE as environment\n"
" -o FILE write output dependency information to FILE.d\n"
+" -p STRING localized prefix of msvc's /showIncludes output\n"
);
}
@@ -84,7 +85,8 @@ int MSVCHelperMain(int argc, char** argv) {
{ NULL, 0, NULL, 0 }
};
int opt;
- while ((opt = getopt_long(argc, argv, "e:o:h", kLongOptions, NULL)) != -1) {
+ string deps_prefix;
+ while ((opt = getopt_long(argc, argv, "e:o:p:h", kLongOptions, NULL)) != -1) {
switch (opt) {
case 'e':
envfile = optarg;
@@ -92,6 +94,9 @@ int MSVCHelperMain(int argc, char** argv) {
case 'o':
output_filename = optarg;
break;
+ case 'p':
+ deps_prefix = optarg;
+ break;
case 'h':
default:
Usage();
@@ -122,7 +127,7 @@ int MSVCHelperMain(int argc, char** argv) {
if (output_filename) {
CLParser parser;
- output = parser.Parse(output);
+ output = parser.Parse(output, deps_prefix);
WriteDepFileOrDie(output_filename, parser);
}
diff --git a/src/msvc_helper_test.cc b/src/msvc_helper_test.cc
index 02f2863..48fbe21 100644
--- a/src/msvc_helper_test.cc
+++ b/src/msvc_helper_test.cc
@@ -20,15 +20,19 @@
#include "util.h"
TEST(CLParserTest, ShowIncludes) {
- ASSERT_EQ("", CLParser::FilterShowIncludes(""));
+ ASSERT_EQ("", CLParser::FilterShowIncludes("", ""));
- ASSERT_EQ("", CLParser::FilterShowIncludes("Sample compiler output"));
+ ASSERT_EQ("", CLParser::FilterShowIncludes("Sample compiler output", ""));
ASSERT_EQ("c:\\Some Files\\foobar.h",
CLParser::FilterShowIncludes("Note: including file: "
- "c:\\Some Files\\foobar.h"));
+ "c:\\Some Files\\foobar.h", ""));
ASSERT_EQ("c:\\initspaces.h",
CLParser::FilterShowIncludes("Note: including file: "
- "c:\\initspaces.h"));
+ "c:\\initspaces.h", ""));
+ ASSERT_EQ("c:\\initspaces.h",
+ CLParser::FilterShowIncludes("Non-default prefix: inc file: "
+ "c:\\initspaces.h",
+ "Non-default prefix: inc file:"));
}
TEST(CLParserTest, FilterInputFilename) {
@@ -46,8 +50,9 @@ TEST(CLParserTest, ParseSimple) {
CLParser parser;
string output = parser.Parse(
"foo\r\n"
- "Note: including file: foo.h\r\n"
- "bar\r\n");
+ "Note: inc file prefix: foo.h\r\n"
+ "bar\r\n",
+ "Note: inc file prefix:");
ASSERT_EQ("foo\nbar\n", output);
ASSERT_EQ(1u, parser.includes_.size());
@@ -58,7 +63,8 @@ TEST(CLParserTest, ParseFilenameFilter) {
CLParser parser;
string output = parser.Parse(
"foo.cc\r\n"
- "cl: warning\r\n");
+ "cl: warning\r\n",
+ "");
ASSERT_EQ("cl: warning\n", output);
}
@@ -67,7 +73,8 @@ TEST(CLParserTest, ParseSystemInclude) {
string output = parser.Parse(
"Note: including file: c:\\Program Files\\foo.h\r\n"
"Note: including file: d:\\Microsoft Visual Studio\\bar.h\r\n"
- "Note: including file: path.h\r\n");
+ "Note: including file: path.h\r\n",
+ "");
// We should have dropped the first two includes because they look like
// system headers.
ASSERT_EQ("", output);
@@ -80,7 +87,8 @@ TEST(CLParserTest, DuplicatedHeader) {
string output = parser.Parse(
"Note: including file: foo.h\r\n"
"Note: including file: bar.h\r\n"
- "Note: including file: foo.h\r\n");
+ "Note: including file: foo.h\r\n",
+ "");
// We should have dropped one copy of foo.h.
ASSERT_EQ("", output);
ASSERT_EQ(2u, parser.includes_.size());
@@ -91,7 +99,8 @@ TEST(CLParserTest, DuplicatedHeaderPathConverted) {
string output = parser.Parse(
"Note: including file: sub/foo.h\r\n"
"Note: including file: bar.h\r\n"
- "Note: including file: sub\\foo.h\r\n");
+ "Note: including file: sub\\foo.h\r\n",
+ "");
// We should have dropped one copy of foo.h.
ASSERT_EQ("", output);
ASSERT_EQ(2u, parser.includes_.size());