Improve GN clean command.
Previously it would detect a case where the build.ninja file was empty and write a default
one to replace it. This case is rare and the existing code was broken on Windows because
it used printf on a 16-bit file path. It's simpler to just issue an error in this case.
This also adds a small performance improvement by using StringPiece to split the build file
(saves allocating ~16K strings).
Change-Id: I8a4cb31a9e8614d8d14e821ff24434a57da55212
Reviewed-on: https://chromium-review.googlesource.com/602520
Reviewed-by: Bruce Dawson <brucedawson@chromium.org>
Commit-Queue: Brett Wilson <brettw@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#492124}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: f99f80fab8249df24e05e686e7b43e2d4ec574b5
diff --git a/tools/gn/command_clean.cc b/tools/gn/command_clean.cc
index f0348d9..8903986 100644
--- a/tools/gn/command_clean.cc
+++ b/tools/gn/command_clean.cc
@@ -22,21 +22,19 @@
// On error, returns the empty string.
std::string ExtractGNBuildCommands(const base::FilePath& build_ninja_file) {
std::string file_contents;
- if (!base::ReadFileToString(build_ninja_file, &file_contents)) {
+ if (!base::ReadFileToString(build_ninja_file, &file_contents))
return std::string();
- }
- std::vector<std::string> lines = base::SplitString(
+ std::vector<base::StringPiece> lines = base::SplitStringPiece(
file_contents, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
std::string result;
int num_blank_lines = 0;
for (const auto& line : lines) {
- result += line;
- result += "\n";
- if (line.empty()) {
+ line.AppendToString(&result);
+ result.push_back('\n');
+ if (line.empty())
++num_blank_lines;
- }
if (num_blank_lines == 2)
break;
}
@@ -44,15 +42,6 @@
return result;
}
-const char kDefaultNinjaFile[] =
- "rule gn\n"
- " command = gn -q gen //out/%s/\n"
- " description = Regenerating ninja files\n"
- "\n"
- "build build.ninja: gn\n"
- " generator = 1\n"
- " depfile = build.ninja.d\n";
-
} // namespace
namespace commands {
@@ -96,6 +85,13 @@
// will automatically rerun GN the next time Ninja is run.
base::FilePath build_ninja_file = build_dir.AppendASCII("build.ninja");
std::string build_commands = ExtractGNBuildCommands(build_ninja_file);
+ if (build_commands.empty()) {
+ // Couldn't parse the build.ninja file.
+ Err(Location(), "Couldn't read build.ninja in this directory.",
+ "Try running \"gn gen\" on it and then re-running \"gn clean\".")
+ .PrintToStdout();
+ return 1;
+ }
// Read the args.gn file, if any. Not all GN builds have one.
base::FilePath gn_args_file = build_dir.AppendASCII("args.gn");
@@ -115,25 +111,11 @@
}
// Write the build.ninja file sufficiently to regenerate itself.
- if (!build_commands.empty()) {
- if (base::WriteFile(build_ninja_file, build_commands.data(),
- static_cast<int>(build_commands.size())) == -1) {
- Err(Location(), std::string("Failed to write build.ninja."))
- .PrintToStdout();
- return 1;
- }
- } else {
- // Couldn't parse the build.ninja file, write a default thing.
- std::vector<base::FilePath::StringType> components;
- build_ninja_file.GetComponents(&components);
- std::string default_build_file = base::StringPrintf(
- kDefaultNinjaFile, components[components.size() - 2].c_str());
- if (base::WriteFile(build_ninja_file, default_build_file.data(),
- static_cast<int>(default_build_file.size())) == -1) {
- Err(Location(), std::string("Failed to write build.ninja."))
- .PrintToStdout();
- return 1;
- }
+ if (base::WriteFile(build_ninja_file, build_commands.data(),
+ static_cast<int>(build_commands.size())) == -1) {
+ Err(Location(), std::string("Failed to write build.ninja."))
+ .PrintToStdout();
+ return 1;
}
// Write a .d file for the build which references a nonexistant file.