mirror of
https://github.com/reactos/ninja.git
synced 2025-02-21 12:10:28 +00:00
Make deps=msvc experimentally available on non-Windows.
This makes it possible to run most of the clparser tests on non-Windows, and is potentially useful for cross-compiling on non-Windows hosts. Also, the manual didn't document this as Windows-only previously. If you use this on non-Windows, please let me know, else I might undo this change again in the future.
This commit is contained in:
parent
aea5a4d41f
commit
3a88912624
@ -475,6 +475,7 @@ n.comment('Core source files all build into ninja library.')
|
||||
for name in ['build',
|
||||
'build_log',
|
||||
'clean',
|
||||
'clparser',
|
||||
'debug_flags',
|
||||
'depfile_parser',
|
||||
'deps_log',
|
||||
@ -540,6 +541,7 @@ objs = []
|
||||
for name in ['build_log_test',
|
||||
'build_test',
|
||||
'clean_test',
|
||||
'clparser_test',
|
||||
'depfile_parser_test',
|
||||
'deps_log_test',
|
||||
'disk_interface_test',
|
||||
|
@ -25,12 +25,12 @@
|
||||
#endif
|
||||
|
||||
#include "build_log.h"
|
||||
#include "clparser.h"
|
||||
#include "debug_flags.h"
|
||||
#include "depfile_parser.h"
|
||||
#include "deps_log.h"
|
||||
#include "disk_interface.h"
|
||||
#include "graph.h"
|
||||
#include "msvc_helper.h"
|
||||
#include "state.h"
|
||||
#include "subprocess.h"
|
||||
#include "util.h"
|
||||
@ -854,7 +854,6 @@ bool Builder::ExtractDeps(CommandRunner::Result* result,
|
||||
const string& deps_prefix,
|
||||
vector<Node*>* deps_nodes,
|
||||
string* err) {
|
||||
#ifdef _WIN32
|
||||
if (deps_type == "msvc") {
|
||||
CLParser parser;
|
||||
string output;
|
||||
@ -870,7 +869,6 @@ bool Builder::ExtractDeps(CommandRunner::Result* result,
|
||||
deps_nodes->push_back(state_->GetNode(*i, ~0u));
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (deps_type == "gcc") {
|
||||
string depfile = result->edge->GetUnescapedDepfile();
|
||||
if (depfile.empty()) {
|
||||
|
116
src/clparser.cc
Normal file
116
src/clparser.cc
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "clparser.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "includes_normalize.h"
|
||||
#else
|
||||
#include "util.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
/// Return true if \a input ends with \a needle.
|
||||
bool EndsWith(const string& input, const string& needle) {
|
||||
return (input.size() >= needle.size() &&
|
||||
input.substr(input.size() - needle.size()) == needle);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// static
|
||||
string CLParser::FilterShowIncludes(const string& line,
|
||||
const string& deps_prefix) {
|
||||
const string kDepsPrefixEnglish = "Note: including file: ";
|
||||
const char* in = line.c_str();
|
||||
const char* end = in + line.size();
|
||||
const string& prefix = deps_prefix.empty() ? kDepsPrefixEnglish : 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());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// static
|
||||
bool CLParser::IsSystemInclude(string path) {
|
||||
transform(path.begin(), path.end(), path.begin(), ::tolower);
|
||||
// TODO: this is a heuristic, perhaps there's a better way?
|
||||
return (path.find("program files") != string::npos ||
|
||||
path.find("microsoft visual studio") != string::npos);
|
||||
}
|
||||
|
||||
// static
|
||||
bool CLParser::FilterInputFilename(string line) {
|
||||
transform(line.begin(), line.end(), line.begin(), ::tolower);
|
||||
// TODO: other extensions, like .asm?
|
||||
return EndsWith(line, ".c") ||
|
||||
EndsWith(line, ".cc") ||
|
||||
EndsWith(line, ".cxx") ||
|
||||
EndsWith(line, ".cpp");
|
||||
}
|
||||
|
||||
// static
|
||||
bool CLParser::Parse(const string& output, const string& deps_prefix,
|
||||
string* filtered_output, string* err) {
|
||||
// Loop over all lines in the output to process them.
|
||||
assert(&output != filtered_output);
|
||||
size_t start = 0;
|
||||
while (start < output.size()) {
|
||||
size_t end = output.find_first_of("\r\n", start);
|
||||
if (end == string::npos)
|
||||
end = output.size();
|
||||
string line = output.substr(start, end - start);
|
||||
|
||||
string include = FilterShowIncludes(line, deps_prefix);
|
||||
if (!include.empty()) {
|
||||
string normalized;
|
||||
#ifdef _WIN32
|
||||
if (!IncludesNormalize::Normalize(include, NULL, &normalized, err))
|
||||
return false;
|
||||
#else
|
||||
// TODO: should this make the path relative to cwd?
|
||||
normalized = include;
|
||||
unsigned int slash_bits;
|
||||
if (!CanonicalizePath(&normalized, &slash_bits, err))
|
||||
return false;
|
||||
#endif
|
||||
if (!IsSystemInclude(normalized))
|
||||
includes_.insert(normalized);
|
||||
} else if (FilterInputFilename(line)) {
|
||||
// Drop it.
|
||||
// TODO: if we support compiling multiple output files in a single
|
||||
// cl.exe invocation, we should stash the filename.
|
||||
} else {
|
||||
filtered_output->append(line);
|
||||
filtered_output->append("\n");
|
||||
}
|
||||
|
||||
if (end < output.size() && output[end] == '\r')
|
||||
++end;
|
||||
if (end < output.size() && output[end] == '\n')
|
||||
++end;
|
||||
start = end;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
52
src/clparser.h
Normal file
52
src/clparser.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef NINJA_CLPARSER_H_
|
||||
#define NINJA_CLPARSER_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
/// Visual Studio's cl.exe requires some massaging to work with Ninja;
|
||||
/// for example, it emits include information on stderr in a funny
|
||||
/// format when building with /showIncludes. This class parses this
|
||||
/// output.
|
||||
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,
|
||||
const string& deps_prefix);
|
||||
|
||||
/// Return true if a mentioned include file is a system path.
|
||||
/// Filtering these out reduces dependency information considerably.
|
||||
static bool IsSystemInclude(string path);
|
||||
|
||||
/// Parse a line of cl.exe output and return true if it looks like
|
||||
/// it's printing an input filename. This is a heuristic but it appears
|
||||
/// to be the best we can do.
|
||||
/// Exposed for testing.
|
||||
static bool FilterInputFilename(string line);
|
||||
|
||||
/// Parse the full output of cl, filling filtered_output with the text that
|
||||
/// should be printed (if any). Returns true on success, or false with err
|
||||
/// filled. output must not be the same object as filtered_object.
|
||||
bool Parse(const string& output, const string& deps_prefix,
|
||||
string* filtered_output, string* err);
|
||||
|
||||
set<string> includes_;
|
||||
};
|
||||
|
||||
#endif // NINJA_CLPARSER_H_
|
117
src/clparser_test.cc
Normal file
117
src/clparser_test.cc
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright 2011 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "clparser.h"
|
||||
|
||||
#include "test.h"
|
||||
#include "util.h"
|
||||
|
||||
TEST(CLParserTest, ShowIncludes) {
|
||||
ASSERT_EQ("", CLParser::FilterShowIncludes("", ""));
|
||||
|
||||
ASSERT_EQ("", CLParser::FilterShowIncludes("Sample compiler output", ""));
|
||||
ASSERT_EQ("c:\\Some Files\\foobar.h",
|
||||
CLParser::FilterShowIncludes("Note: including file: "
|
||||
"c:\\Some Files\\foobar.h", ""));
|
||||
ASSERT_EQ("c:\\initspaces.h",
|
||||
CLParser::FilterShowIncludes("Note: including file: "
|
||||
"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) {
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("foobar.cc"));
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("foo bar.cc"));
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("baz.c"));
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("FOOBAR.CC"));
|
||||
|
||||
ASSERT_FALSE(CLParser::FilterInputFilename(
|
||||
"src\\cl_helper.cc(166) : fatal error C1075: end "
|
||||
"of file found ..."));
|
||||
}
|
||||
|
||||
TEST(CLParserTest, ParseSimple) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(parser.Parse(
|
||||
"foo\r\n"
|
||||
"Note: inc file prefix: foo.h\r\n"
|
||||
"bar\r\n",
|
||||
"Note: inc file prefix:", &output, &err));
|
||||
|
||||
ASSERT_EQ("foo\nbar\n", output);
|
||||
ASSERT_EQ(1u, parser.includes_.size());
|
||||
ASSERT_EQ("foo.h", *parser.includes_.begin());
|
||||
}
|
||||
|
||||
TEST(CLParserTest, ParseFilenameFilter) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(parser.Parse(
|
||||
"foo.cc\r\n"
|
||||
"cl: warning\r\n",
|
||||
"", &output, &err));
|
||||
ASSERT_EQ("cl: warning\n", output);
|
||||
}
|
||||
|
||||
TEST(CLParserTest, ParseSystemInclude) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(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",
|
||||
"", &output, &err));
|
||||
// We should have dropped the first two includes because they look like
|
||||
// system headers.
|
||||
ASSERT_EQ("", output);
|
||||
ASSERT_EQ(1u, parser.includes_.size());
|
||||
ASSERT_EQ("path.h", *parser.includes_.begin());
|
||||
}
|
||||
|
||||
TEST(CLParserTest, DuplicatedHeader) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(parser.Parse(
|
||||
"Note: including file: foo.h\r\n"
|
||||
"Note: including file: bar.h\r\n"
|
||||
"Note: including file: foo.h\r\n",
|
||||
"", &output, &err));
|
||||
// We should have dropped one copy of foo.h.
|
||||
ASSERT_EQ("", output);
|
||||
ASSERT_EQ(2u, parser.includes_.size());
|
||||
}
|
||||
|
||||
TEST(CLParserTest, DuplicatedHeaderPathConverted) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
|
||||
// This isn't inline in the Parse() call below because the #ifdef in
|
||||
// a macro expansion would confuse MSVC2013's preprocessor.
|
||||
const char kInput[] =
|
||||
"Note: including file: sub/./foo.h\r\n"
|
||||
"Note: including file: bar.h\r\n"
|
||||
#ifdef _WIN32
|
||||
"Note: including file: sub\\foo.h\r\n";
|
||||
#else
|
||||
"Note: including file: sub/foo.h\r\n";
|
||||
#endif
|
||||
ASSERT_TRUE(parser.Parse(kInput, "", &output, &err));
|
||||
// We should have dropped one copy of foo.h.
|
||||
ASSERT_EQ("", output);
|
||||
ASSERT_EQ(2u, parser.includes_.size());
|
||||
}
|
@ -14,23 +14,12 @@
|
||||
|
||||
#include "msvc_helper.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "includes_normalize.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
/// Return true if \a input ends with \a needle.
|
||||
bool EndsWith(const string& input, const string& needle) {
|
||||
return (input.size() >= needle.size() &&
|
||||
input.substr(input.size() - needle.size()) == needle);
|
||||
}
|
||||
|
||||
string Replace(const string& input, const string& find, const string& replace) {
|
||||
string result = input;
|
||||
size_t start_pos = 0;
|
||||
@ -48,78 +37,6 @@ string EscapeForDepfile(const string& path) {
|
||||
return Replace(path, " ", "\\ ");
|
||||
}
|
||||
|
||||
// static
|
||||
string CLParser::FilterShowIncludes(const string& line,
|
||||
const string& deps_prefix) {
|
||||
const string kDepsPrefixEnglish = "Note: including file: ";
|
||||
const char* in = line.c_str();
|
||||
const char* end = in + line.size();
|
||||
const string& prefix = deps_prefix.empty() ? kDepsPrefixEnglish : 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());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// static
|
||||
bool CLParser::IsSystemInclude(string path) {
|
||||
transform(path.begin(), path.end(), path.begin(), ::tolower);
|
||||
// TODO: this is a heuristic, perhaps there's a better way?
|
||||
return (path.find("program files") != string::npos ||
|
||||
path.find("microsoft visual studio") != string::npos);
|
||||
}
|
||||
|
||||
// static
|
||||
bool CLParser::FilterInputFilename(string line) {
|
||||
transform(line.begin(), line.end(), line.begin(), ::tolower);
|
||||
// TODO: other extensions, like .asm?
|
||||
return EndsWith(line, ".c") ||
|
||||
EndsWith(line, ".cc") ||
|
||||
EndsWith(line, ".cxx") ||
|
||||
EndsWith(line, ".cpp");
|
||||
}
|
||||
|
||||
bool CLParser::Parse(const string& output, const string& deps_prefix,
|
||||
string* filtered_output, string* err) {
|
||||
// Loop over all lines in the output to process them.
|
||||
assert(&output != filtered_output);
|
||||
size_t start = 0;
|
||||
while (start < output.size()) {
|
||||
size_t end = output.find_first_of("\r\n", start);
|
||||
if (end == string::npos)
|
||||
end = output.size();
|
||||
string line = output.substr(start, end - start);
|
||||
|
||||
string include = FilterShowIncludes(line, deps_prefix);
|
||||
if (!include.empty()) {
|
||||
string normalized;
|
||||
if (!IncludesNormalize::Normalize(include, NULL, &normalized, err))
|
||||
return false;
|
||||
if (!IsSystemInclude(normalized))
|
||||
includes_.insert(normalized);
|
||||
} else if (FilterInputFilename(line)) {
|
||||
// Drop it.
|
||||
// TODO: if we support compiling multiple output files in a single
|
||||
// cl.exe invocation, we should stash the filename.
|
||||
} else {
|
||||
filtered_output->append(line);
|
||||
filtered_output->append("\n");
|
||||
}
|
||||
|
||||
if (end < output.size() && output[end] == '\r')
|
||||
++end;
|
||||
if (end < output.size() && output[end] == '\n')
|
||||
++end;
|
||||
start = end;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CLWrapper::Run(const string& command, string* output) {
|
||||
SECURITY_ATTRIBUTES security_attributes = {};
|
||||
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
|
@ -13,42 +13,10 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
string EscapeForDepfile(const string& path);
|
||||
|
||||
/// Visual Studio's cl.exe requires some massaging to work with Ninja;
|
||||
/// for example, it emits include information on stderr in a funny
|
||||
/// format when building with /showIncludes. This class parses this
|
||||
/// output.
|
||||
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,
|
||||
const string& deps_prefix);
|
||||
|
||||
/// Return true if a mentioned include file is a system path.
|
||||
/// Filtering these out reduces dependency information considerably.
|
||||
static bool IsSystemInclude(string path);
|
||||
|
||||
/// Parse a line of cl.exe output and return true if it looks like
|
||||
/// it's printing an input filename. This is a heuristic but it appears
|
||||
/// to be the best we can do.
|
||||
/// Exposed for testing.
|
||||
static bool FilterInputFilename(string line);
|
||||
|
||||
/// Parse the full output of cl, filling filtered_output with the text that
|
||||
/// should be printed (if any). Returns true on success, or false with err
|
||||
/// filled. output must not be the same object as filtered_object.
|
||||
bool Parse(const string& output, const string& deps_prefix,
|
||||
string* filtered_output, string* err);
|
||||
|
||||
set<string> includes_;
|
||||
};
|
||||
|
||||
/// Wraps a synchronous execution of a CL subprocess.
|
||||
struct CLWrapper {
|
||||
CLWrapper() : env_block_(NULL) {}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "clparser.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "getopt.h"
|
||||
|
@ -17,99 +17,7 @@
|
||||
#include "test.h"
|
||||
#include "util.h"
|
||||
|
||||
TEST(CLParserTest, ShowIncludes) {
|
||||
ASSERT_EQ("", CLParser::FilterShowIncludes("", ""));
|
||||
|
||||
ASSERT_EQ("", CLParser::FilterShowIncludes("Sample compiler output", ""));
|
||||
ASSERT_EQ("c:\\Some Files\\foobar.h",
|
||||
CLParser::FilterShowIncludes("Note: including file: "
|
||||
"c:\\Some Files\\foobar.h", ""));
|
||||
ASSERT_EQ("c:\\initspaces.h",
|
||||
CLParser::FilterShowIncludes("Note: including file: "
|
||||
"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) {
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("foobar.cc"));
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("foo bar.cc"));
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("baz.c"));
|
||||
ASSERT_TRUE(CLParser::FilterInputFilename("FOOBAR.CC"));
|
||||
|
||||
ASSERT_FALSE(CLParser::FilterInputFilename(
|
||||
"src\\cl_helper.cc(166) : fatal error C1075: end "
|
||||
"of file found ..."));
|
||||
}
|
||||
|
||||
TEST(CLParserTest, ParseSimple) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(parser.Parse(
|
||||
"foo\r\n"
|
||||
"Note: inc file prefix: foo.h\r\n"
|
||||
"bar\r\n",
|
||||
"Note: inc file prefix:", &output, &err));
|
||||
|
||||
ASSERT_EQ("foo\nbar\n", output);
|
||||
ASSERT_EQ(1u, parser.includes_.size());
|
||||
ASSERT_EQ("foo.h", *parser.includes_.begin());
|
||||
}
|
||||
|
||||
TEST(CLParserTest, ParseFilenameFilter) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(parser.Parse(
|
||||
"foo.cc\r\n"
|
||||
"cl: warning\r\n",
|
||||
"", &output, &err));
|
||||
ASSERT_EQ("cl: warning\n", output);
|
||||
}
|
||||
|
||||
TEST(CLParserTest, ParseSystemInclude) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(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",
|
||||
"", &output, &err));
|
||||
// We should have dropped the first two includes because they look like
|
||||
// system headers.
|
||||
ASSERT_EQ("", output);
|
||||
ASSERT_EQ(1u, parser.includes_.size());
|
||||
ASSERT_EQ("path.h", *parser.includes_.begin());
|
||||
}
|
||||
|
||||
TEST(CLParserTest, DuplicatedHeader) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(parser.Parse(
|
||||
"Note: including file: foo.h\r\n"
|
||||
"Note: including file: bar.h\r\n"
|
||||
"Note: including file: foo.h\r\n",
|
||||
"", &output, &err));
|
||||
// We should have dropped one copy of foo.h.
|
||||
ASSERT_EQ("", output);
|
||||
ASSERT_EQ(2u, parser.includes_.size());
|
||||
}
|
||||
|
||||
TEST(CLParserTest, DuplicatedHeaderPathConverted) {
|
||||
CLParser parser;
|
||||
string output, err;
|
||||
ASSERT_TRUE(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",
|
||||
"", &output, &err));
|
||||
// We should have dropped one copy of foo.h.
|
||||
ASSERT_EQ("", output);
|
||||
ASSERT_EQ(2u, parser.includes_.size());
|
||||
}
|
||||
|
||||
TEST(CLParserTest, SpacesInFilename) {
|
||||
TEST(EscapeForDepfileTest, SpacesInFilename) {
|
||||
ASSERT_EQ("sub\\some\\ sdk\\foo.h",
|
||||
EscapeForDepfile("sub\\some sdk\\foo.h"));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user