forked from kiwibrowser/android
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommand_clean.cc
More file actions
129 lines (110 loc) · 4.33 KB
/
Copy pathcommand_clean.cc
File metadata and controls
129 lines (110 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "tools/gn/commands.h"
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/setup.h"
namespace {
// Extracts from a build.ninja the commands to run GN.
//
// The commands to run GN are the gn rule and build.ninja build step at the top
// of the build.ninja file. We want to keep these when deleting GN builds since
// we want to preserve the command-line flags to GN.
//
// 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))
return std::string();
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) {
line.AppendToString(&result);
result.push_back('\n');
if (line.empty())
++num_blank_lines;
if (num_blank_lines == 3)
break;
}
return result;
}
} // namespace
namespace commands {
const char kClean[] = "clean";
const char kClean_HelpShort[] =
"clean: Cleans the output directory.";
const char kClean_Help[] =
"gn clean <out_dir>\n"
"\n"
" Deletes the contents of the output directory except for args.gn and\n"
" creates a Ninja build environment sufficient to regenerate the build.\n";
int RunClean(const std::vector<std::string>& args) {
if (args.size() != 1) {
Err(Location(), "You're holding it wrong.",
"Usage: \"gn clean <out_dir>\"").PrintToStdout();
return 1;
}
Setup* setup = new Setup;
if (!setup->DoSetup(args[0], false))
return 1;
base::FilePath build_dir(setup->build_settings().GetFullPath(
SourceDir(setup->build_settings().build_dir().value())));
// NOTE: Not all GN builds have args.gn file hence we check here
// if a build.ninja.d files exists instead.
base::FilePath build_ninja_d_file = build_dir.AppendASCII("build.ninja.d");
if (!base::PathExists(build_ninja_d_file)) {
Err(Location(),
base::StringPrintf(
"%s does not look like a build directory.\n",
FilePathToUTF8(build_ninja_d_file.DirName().value()).c_str()))
.PrintToStdout();
return 1;
}
// Erase everything but the args file, and write a dummy build.ninja file that
// 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;
}
base::FileEnumerator traversal(
build_dir, false,
base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
for (base::FilePath current = traversal.Next(); !current.empty();
current = traversal.Next()) {
if (!base::FilePath::CompareEqualIgnoreCase(current.BaseName().value(),
FILE_PATH_LITERAL("args.gn"))) {
base::DeleteFile(current, true);
}
}
// Write the build.ninja file sufficiently to regenerate itself.
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.
// This will make Ninja always mark the build as dirty.
std::string dummy_content("build.ninja: nonexistant_file.gn\n");
if (base::WriteFile(build_ninja_d_file, dummy_content.data(),
static_cast<int>(dummy_content.size())) == -1) {
Err(Location(), std::string("Failed to write build.ninja.d."))
.PrintToStdout();
return 1;
}
return 0;
}
} // namespace commands