Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: tools/gn/ninja_build_writer.cc

Issue 247663006: Add more phony rules to GN build (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tests Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/gn/ninja_build_writer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/ninja_build_writer.h" 5 #include "tools/gn/ninja_build_writer.h"
6 6
7 #include <fstream> 7 #include <fstream>
8 #include <map> 8 #include <map>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/path_service.h" 12 #include "base/path_service.h"
13 #include "base/process/process_handle.h" 13 #include "base/process/process_handle.h"
14 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
15 #include "build/build_config.h" 16 #include "build/build_config.h"
16 #include "tools/gn/build_settings.h" 17 #include "tools/gn/build_settings.h"
17 #include "tools/gn/escape.h" 18 #include "tools/gn/escape.h"
18 #include "tools/gn/filesystem_utils.h" 19 #include "tools/gn/filesystem_utils.h"
19 #include "tools/gn/input_file_manager.h" 20 #include "tools/gn/input_file_manager.h"
20 #include "tools/gn/scheduler.h" 21 #include "tools/gn/scheduler.h"
21 #include "tools/gn/target.h" 22 #include "tools/gn/target.h"
22 #include "tools/gn/trace.h" 23 #include "tools/gn/trace.h"
23 24
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 out_ << std::endl; 173 out_ << std::endl;
173 } 174 }
174 out_ << std::endl; 175 out_ << std::endl;
175 } 176 }
176 177
177 void NinjaBuildWriter::WritePhonyAndAllRules() { 178 void NinjaBuildWriter::WritePhonyAndAllRules() {
178 std::string all_rules; 179 std::string all_rules;
179 180
180 // Write phony rules for all uniquely-named targets in the default toolchain. 181 // Write phony rules for all uniquely-named targets in the default toolchain.
181 // Don't do other toolchains or we'll get naming conflicts, and if the name 182 // Don't do other toolchains or we'll get naming conflicts, and if the name
182 // isn't unique, also skip it. 183 // isn't unique, also skip it. The exception is for the toplevel targets
184 // which we also find.
183 std::map<std::string, int> small_name_count; 185 std::map<std::string, int> small_name_count;
184 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) 186 std::vector<const Target*> toplevel_targets;
185 small_name_count[default_toolchain_targets_[i]->label().name()]++; 187 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) {
188 const Target* target = default_toolchain_targets_[i];
189 const Label& label = target->label();
190 small_name_count[label.name()]++;
191
192 // Look for targets with a name of the form
193 // dir = "//foo/", name = "foo"
194 // i.e. where the target name matches the top level directory. We will
195 // always write phony rules for these even if there is another target with
196 // the same short name.
197 const std::string& dir_string = label.dir().value();
198 if (dir_string.size() == label.name().size() + 3 && // Size matches.
199 dir_string[0] == '/' && dir_string[1] == '/' && // "//" at beginning.
200 dir_string[dir_string.size() - 1] == '/' && // "/" at end.
201 dir_string.compare(2, label.name().size(), label.name()) == 0)
202 toplevel_targets.push_back(target);
203 }
186 204
187 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { 205 for (size_t i = 0; i < default_toolchain_targets_.size(); i++) {
188 const Target* target = default_toolchain_targets_[i]; 206 const Target* target = default_toolchain_targets_[i];
207 const Label& label = target->label();
208 OutputFile target_file = helper_.GetTargetOutputFile(target);
189 209
190 OutputFile target_file = helper_.GetTargetOutputFile(target); 210 // Write the long name "foo/bar:baz" for the target "//foo/bar:baz".
191 if (target_file.value() != target->label().name() && 211 std::string long_name = label.GetUserVisibleName(false);
192 small_name_count[default_toolchain_targets_[i]->label().name()] == 1) { 212 base::TrimString(long_name, "/", &long_name);
193 out_ << "build " << target->label().name() << ": phony "; 213 WritePhonyRule(target, target_file, long_name);
194 path_output_.WriteFile(out_, target_file); 214
195 out_ << std::endl; 215 // Write the directory name with no target name if they match
216 // (e.g. "//foo/bar:bar" -> "foo/bar").
217 if (FindLastDirComponent(label.dir()) == label.name()) {
218 std::string medium_name = DirectoryWithNoLastSlash(label.dir());
219 base::TrimString(medium_name, "/", &medium_name);
220 // That may have generated a name the same as the short name of the
221 // target which we already wrote.
222 if (medium_name != label.name())
223 WritePhonyRule(target, target_file, medium_name);
196 } 224 }
197 225
226 // Write short names for ones which are unique.
227 if (small_name_count[label.name()] == 1)
228 WritePhonyRule(target, target_file, label.name());
229
198 if (!all_rules.empty()) 230 if (!all_rules.empty())
199 all_rules.append(" $\n "); 231 all_rules.append(" $\n ");
200 all_rules.append(target_file.value()); 232 all_rules.append(target_file.value());
201 } 233 }
202 234
235 // Pick up phony rules for the toplevel targets with non-unique names (which
236 // would have been skipped in the above loop).
237 for (size_t i = 0; i < toplevel_targets.size(); i++) {
238 if (small_name_count[toplevel_targets[i]->label().name()] > 1) {
239 const Target* target = toplevel_targets[i];
240 WritePhonyRule(target, helper_.GetTargetOutputFile(target),
241 target->label().name());
242 }
243 }
244
203 if (!all_rules.empty()) { 245 if (!all_rules.empty()) {
204 out_ << "\nbuild all: phony " << all_rules << std::endl; 246 out_ << "\nbuild all: phony " << all_rules << std::endl;
205 out_ << "default all" << std::endl; 247 out_ << "default all" << std::endl;
206 } 248 }
207 } 249 }
208 250
251 void NinjaBuildWriter::WritePhonyRule(const Target* target,
252 const OutputFile& target_file,
253 const std::string& phony_name) {
254 if (target_file.value() == phony_name)
255 return; // No need for a phony rule.
256
257 EscapeOptions ninja_escape;
258 ninja_escape.mode = ESCAPE_NINJA;
259
260 // Escape for special chars Ninja will handle.
261 std::string escaped = EscapeString(phony_name, ninja_escape, NULL);
262
263 out_ << "build " << escaped << ": phony ";
264 path_output_.WriteFile(out_, target_file);
265 out_ << std::endl;
266 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_build_writer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698