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

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

Issue 1101323005: GN: Generate phony rules for unique executables. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: reformat Created 5 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
« no previous file with comments | « no previous file | 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"
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 } 184 }
185 185
186 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { 186 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) {
187 std::string all_rules; 187 std::string all_rules;
188 188
189 // Write phony rules for all uniquely-named targets in the default toolchain. 189 // Write phony rules for all uniquely-named targets in the default toolchain.
190 // Don't do other toolchains or we'll get naming conflicts, and if the name 190 // Don't do other toolchains or we'll get naming conflicts, and if the name
191 // isn't unique, also skip it. The exception is for the toplevel targets 191 // isn't unique, also skip it. The exception is for the toplevel targets
192 // which we also find. 192 // which we also find.
193 std::map<std::string, int> small_name_count; 193 std::map<std::string, int> small_name_count;
194 std::map<std::string, int> exe_count;
194 std::vector<const Target*> toplevel_targets; 195 std::vector<const Target*> toplevel_targets;
195 base::hash_set<std::string> target_files; 196 base::hash_set<std::string> target_files;
196 for (const auto& target : default_toolchain_targets_) { 197 for (const auto& target : default_toolchain_targets_) {
197 const Label& label = target->label(); 198 const Label& label = target->label();
198 small_name_count[label.name()]++; 199 small_name_count[label.name()]++;
199 200
200 // Look for targets with a name of the form 201 // Look for targets with a name of the form
201 // dir = "//foo/", name = "foo" 202 // dir = "//foo/", name = "foo"
202 // i.e. where the target name matches the top level directory. We will 203 // i.e. where the target name matches the top level directory. We will
203 // always write phony rules for these even if there is another target with 204 // always write phony rules for these even if there is another target with
204 // the same short name. 205 // the same short name.
205 const std::string& dir_string = label.dir().value(); 206 const std::string& dir_string = label.dir().value();
206 if (dir_string.size() == label.name().size() + 3 && // Size matches. 207 if (dir_string.size() == label.name().size() + 3 && // Size matches.
207 dir_string[0] == '/' && dir_string[1] == '/' && // "//" at beginning. 208 dir_string[0] == '/' && dir_string[1] == '/' && // "//" at beginning.
208 dir_string[dir_string.size() - 1] == '/' && // "/" at end. 209 dir_string[dir_string.size() - 1] == '/' && // "/" at end.
209 dir_string.compare(2, label.name().size(), label.name()) == 0) 210 dir_string.compare(2, label.name().size(), label.name()) == 0)
210 toplevel_targets.push_back(target); 211 toplevel_targets.push_back(target);
212
213 // Look for executables; later we will generate phony rules for them
214 // even if there are non-executable targets with the same name.
215 if (target->output_type() == Target::EXECUTABLE)
216 exe_count[label.name()]++;
211 } 217 }
212 218
213 for (const auto& target : default_toolchain_targets_) { 219 for (const auto& target : default_toolchain_targets_) {
214 const Label& label = target->label(); 220 const Label& label = target->label();
215 OutputFile target_file(target->dependency_output_file()); 221 OutputFile target_file(target->dependency_output_file());
216 // The output files may have leading "./" so normalize those away. 222 // The output files may have leading "./" so normalize those away.
217 NormalizePath(&target_file.value()); 223 NormalizePath(&target_file.value());
218 if (!target_files.insert(target_file.value()).second) { 224 if (!target_files.insert(target_file.value()).second) {
219 *err = Err(Location(), "Duplicate rules for " + target_file.value()); 225 *err = Err(Location(), "Duplicate rules for " + target_file.value());
220 return false; 226 return false;
221 } 227 }
222 228
223 // Write the long name "foo/bar:baz" for the target "//foo/bar:baz". 229 // Write the long name "foo/bar:baz" for the target "//foo/bar:baz".
224 std::string long_name = label.GetUserVisibleName(false); 230 std::string long_name = label.GetUserVisibleName(false);
225 base::TrimString(long_name, "/", &long_name); 231 base::TrimString(long_name, "/", &long_name);
226 WritePhonyRule(target, target_file, long_name); 232 WritePhonyRule(target, target_file, long_name);
227 233
228 // Write the directory name with no target name if they match 234 // Write the directory name with no target name if they match
229 // (e.g. "//foo/bar:bar" -> "foo/bar"). 235 // (e.g. "//foo/bar:bar" -> "foo/bar").
230 if (FindLastDirComponent(label.dir()) == label.name()) { 236 if (FindLastDirComponent(label.dir()) == label.name()) {
231 std::string medium_name = DirectoryWithNoLastSlash(label.dir()); 237 std::string medium_name = DirectoryWithNoLastSlash(label.dir());
232 base::TrimString(medium_name, "/", &medium_name); 238 base::TrimString(medium_name, "/", &medium_name);
233 // That may have generated a name the same as the short name of the 239 // That may have generated a name the same as the short name of the
234 // target which we already wrote. 240 // target which we already wrote.
235 if (medium_name != label.name()) 241 if (medium_name != label.name())
236 WritePhonyRule(target, target_file, medium_name); 242 WritePhonyRule(target, target_file, medium_name);
237 } 243 }
238 244
239 // Write short names for ones which are unique. 245 // Write short names for ones which are either completely unique or there
240 if (small_name_count[label.name()] == 1) 246 // at least only one of them in the default toolchain that is an exe.
247 if (small_name_count[label.name()] == 1 ||
248 (target->output_type() == Target::EXECUTABLE &&
249 exe_count[label.name()] == 1)) {
241 WritePhonyRule(target, target_file, label.name()); 250 WritePhonyRule(target, target_file, label.name());
251 }
242 252
243 if (!all_rules.empty()) 253 if (!all_rules.empty())
244 all_rules.append(" $\n "); 254 all_rules.append(" $\n ");
245 all_rules.append(target_file.value()); 255 all_rules.append(target_file.value());
246 } 256 }
247 257
248 // Pick up phony rules for the toplevel targets with non-unique names (which 258 // Pick up phony rules for the toplevel targets with non-unique names (which
249 // would have been skipped in the above loop). 259 // would have been skipped in the above loop).
250 for (const auto& toplevel_target : toplevel_targets) { 260 for (const auto& toplevel_target : toplevel_targets) {
251 if (small_name_count[toplevel_target->label().name()] > 1) { 261 if (small_name_count[toplevel_target->label().name()] > 1) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 EscapeOptions ninja_escape; 296 EscapeOptions ninja_escape;
287 ninja_escape.mode = ESCAPE_NINJA; 297 ninja_escape.mode = ESCAPE_NINJA;
288 298
289 // Escape for special chars Ninja will handle. 299 // Escape for special chars Ninja will handle.
290 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); 300 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr);
291 301
292 out_ << "build " << escaped << ": phony "; 302 out_ << "build " << escaped << ": phony ";
293 path_output_.WriteFile(out_, target_file); 303 path_output_.WriteFile(out_, target_file);
294 out_ << std::endl; 304 out_ << std::endl;
295 } 305 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698