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

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

Issue 56433003: GN threading refactor (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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/command_gen.cc ('k') | tools/gn/command_refs.cc » ('j') | 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 <iostream> 5 #include <iostream>
6 #include <map> 6 #include <map>
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/environment.h" 11 #include "base/environment.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/time/time.h" 13 #include "base/time/time.h"
14 #include "tools/gn/build_settings.h" 14 #include "tools/gn/build_settings.h"
15 #include "tools/gn/commands.h" 15 #include "tools/gn/commands.h"
16 #include "tools/gn/err.h" 16 #include "tools/gn/err.h"
17 #include "tools/gn/gyp_helper.h" 17 #include "tools/gn/gyp_helper.h"
18 #include "tools/gn/gyp_target_writer.h" 18 #include "tools/gn/gyp_target_writer.h"
19 #include "tools/gn/item_node.h"
20 #include "tools/gn/location.h" 19 #include "tools/gn/location.h"
21 #include "tools/gn/setup.h" 20 #include "tools/gn/setup.h"
22 #include "tools/gn/source_file.h" 21 #include "tools/gn/source_file.h"
23 #include "tools/gn/standard_out.h" 22 #include "tools/gn/standard_out.h"
24 #include "tools/gn/target.h" 23 #include "tools/gn/target.h"
25 24
26 namespace commands { 25 namespace commands {
27 26
28 namespace { 27 namespace {
29 28
30 typedef GypTargetWriter::TargetGroup TargetGroup; 29 typedef GypTargetWriter::TargetGroup TargetGroup;
31 typedef std::map<Label, TargetGroup> CorrelatedTargetsMap; 30 typedef std::map<Label, TargetGroup> CorrelatedTargetsMap;
32 typedef std::map<SourceFile, std::vector<TargetGroup> > GroupedTargetsMap; 31 typedef std::map<SourceFile, std::vector<TargetGroup> > GroupedTargetsMap;
33 typedef std::map<std::string, std::string> StringStringMap; 32 typedef std::map<std::string, std::string> StringStringMap;
34 33
34 std::vector<const BuilderRecord*> GetAllResolvedTargetRecords(
35 const Builder* builder) {
36 std::vector<const BuilderRecord*> all = builder->GetAllRecords();
37 std::vector<const BuilderRecord*> result;
38 result.reserve(all.size());
39 for (size_t i = 0; i < all.size(); i++) {
40 if (all[i]->type() == BuilderRecord::ITEM_TARGET &&
41 all[i]->should_generate() &&
42 all[i]->item())
43 result.push_back(all[i]);
44 }
45 return result;
46 }
47
35 // Groups targets sharing the same label between debug and release. 48 // Groups targets sharing the same label between debug and release.
36 void CorrelateTargets(const std::vector<const Target*>& debug_targets, 49 void CorrelateTargets(const std::vector<const BuilderRecord*>& debug_targets,
37 const std::vector<const Target*>& release_targets, 50 const std::vector<const BuilderRecord*>& release_targets,
38 CorrelatedTargetsMap* correlated) { 51 CorrelatedTargetsMap* correlated) {
39 for (size_t i = 0; i < debug_targets.size(); i++) { 52 for (size_t i = 0; i < debug_targets.size(); i++) {
40 const Target* target = debug_targets[i]; 53 const BuilderRecord* record = debug_targets[i];
41 (*correlated)[target->label()].debug = target; 54 (*correlated)[record->label()].debug = record;
42 } 55 }
43 for (size_t i = 0; i < release_targets.size(); i++) { 56 for (size_t i = 0; i < release_targets.size(); i++) {
44 const Target* target = release_targets[i]; 57 const BuilderRecord* record = release_targets[i];
45 (*correlated)[target->label()].release = target; 58 (*correlated)[record->label()].release = record;
46 } 59 }
47 } 60 }
48 61
49 // Verifies that both debug and release variants match. They can differ only 62 // Verifies that both debug and release variants match. They can differ only
50 // by flags. 63 // by flags.
51 bool EnsureTargetsMatch(const TargetGroup& group, Err* err) { 64 bool EnsureTargetsMatch(const TargetGroup& group, Err* err) {
52 // Check that both debug and release made this target. 65 // Check that both debug and release made this target.
53 if (!group.debug || !group.release) { 66 if (!group.debug || !group.release) {
54 const Target* non_null_one = group.debug ? group.debug : group.release; 67 const BuilderRecord* non_null_one =
68 group.debug ? group.debug : group.release;
55 *err = Err(Location(), "The debug and release builds did not both generate " 69 *err = Err(Location(), "The debug and release builds did not both generate "
56 "a target with the name\n" + 70 "a target with the name\n" +
57 non_null_one->label().GetUserVisibleName(true)); 71 non_null_one->label().GetUserVisibleName(true));
58 return false; 72 return false;
59 } 73 }
60 74
75 const Target* debug_target = group.debug->item()->AsTarget();
76 const Target* release_target = group.release->item()->AsTarget();
77
61 // Check the flags that determine if and where we write the GYP file. 78 // Check the flags that determine if and where we write the GYP file.
62 if (group.debug->item_node()->should_generate() != 79 if (group.debug->should_generate() != group.release->should_generate() ||
63 group.release->item_node()->should_generate() || 80 debug_target->external() != release_target->external() ||
64 group.debug->external() != group.release->external() || 81 debug_target->gyp_file() != release_target->gyp_file()) {
65 group.debug->gyp_file() != group.release->gyp_file()) {
66 *err = Err(Location(), "The metadata for the target\n" + 82 *err = Err(Location(), "The metadata for the target\n" +
67 group.debug->label().GetUserVisibleName(true) + 83 group.debug->label().GetUserVisibleName(true) +
68 "\ndoesn't match between the debug and release builds."); 84 "\ndoesn't match between the debug and release builds.");
69 return false; 85 return false;
70 } 86 }
71 87
72 // Check that the sources match. 88 // Check that the sources match.
73 if (group.debug->sources().size() != group.release->sources().size()) { 89 if (debug_target->sources().size() != release_target->sources().size()) {
74 *err = Err(Location(), "The source file count for the target\n" + 90 *err = Err(Location(), "The source file count for the target\n" +
75 group.debug->label().GetUserVisibleName(true) + 91 group.debug->label().GetUserVisibleName(true) +
76 "\ndoesn't have the same number of files between the debug and " 92 "\ndoesn't have the same number of files between the debug and "
77 "release builds."); 93 "release builds.");
78 return false; 94 return false;
79 } 95 }
80 for (size_t i = 0; i < group.debug->sources().size(); i++) { 96 for (size_t i = 0; i < debug_target->sources().size(); i++) {
81 if (group.debug->sources()[i] != group.release->sources()[i]) { 97 if (debug_target->sources()[i] != release_target->sources()[i]) {
82 *err = Err(Location(), "The debug and release version of the target \n" + 98 *err = Err(Location(), "The debug and release version of the target \n" +
83 group.debug->label().GetUserVisibleName(true) + 99 group.debug->label().GetUserVisibleName(true) +
84 "\ndon't agree on the file\n" + 100 "\ndon't agree on the file\n" +
85 group.debug->sources()[i].value()); 101 debug_target->sources()[i].value());
86 return false; 102 return false;
87 } 103 }
88 } 104 }
89 105
90 // Check that the deps match. 106 // Check that the deps match.
91 if (group.debug->deps().size() != group.release->deps().size()) { 107 if (debug_target->deps().size() != release_target->deps().size()) {
92 *err = Err(Location(), "The source file count for the target\n" + 108 *err = Err(Location(), "The source file count for the target\n" +
93 group.debug->label().GetUserVisibleName(true) + 109 group.debug->label().GetUserVisibleName(true) +
94 "\ndoesn't have the same number of deps between the debug and " 110 "\ndoesn't have the same number of deps between the debug and "
95 "release builds."); 111 "release builds.");
96 return false; 112 return false;
97 } 113 }
98 for (size_t i = 0; i < group.debug->deps().size(); i++) { 114 for (size_t i = 0; i < debug_target->deps().size(); i++) {
99 if (group.debug->deps()[i].label != group.release->deps()[i].label) { 115 if (debug_target->deps()[i].label != release_target->deps()[i].label) {
100 *err = Err(Location(), "The debug and release version of the target \n" + 116 *err = Err(Location(), "The debug and release version of the target \n" +
101 group.debug->label().GetUserVisibleName(true) + 117 group.debug->label().GetUserVisibleName(true) +
102 "\ndon't agree on the dep\n" + 118 "\ndon't agree on the dep\n" +
103 group.debug->deps()[i].label.GetUserVisibleName(true)); 119 debug_target->deps()[i].label.GetUserVisibleName(true));
104 return false; 120 return false;
105 } 121 }
106 } 122 }
107
108 return true; 123 return true;
109 } 124 }
110 125
111 // Python uses shlex.split, which we partially emulate here. 126 // Python uses shlex.split, which we partially emulate here.
112 // 127 //
113 // Advances to the next "word" in a GYP_DEFINES entry. This is something 128 // Advances to the next "word" in a GYP_DEFINES entry. This is something
114 // separated by whitespace or '='. We allow backslash escaping and quoting. 129 // separated by whitespace or '='. We allow backslash escaping and quoting.
115 // The return value will be the index into the array immediately following the 130 // The return value will be the index into the array immediately following the
116 // word, and the contents of the word will be placed into |*word|. 131 // word, and the contents of the word will be placed into |*word|.
117 size_t GetNextGypDefinesWord(const std::string& defines, 132 size_t GetNextGypDefinesWord(const std::string& defines,
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 } 220 }
206 221
207 // Windows SDK path. GYP and the GN build use the same name. 222 // Windows SDK path. GYP and the GN build use the same name.
208 static const char kWinSdkPath[] = "windows_sdk_path"; 223 static const char kWinSdkPath[] = "windows_sdk_path";
209 if (!gyp_defines[kWinSdkPath].empty()) 224 if (!gyp_defines[kWinSdkPath].empty())
210 result[kWinSdkPath] = Value(NULL, gyp_defines[kWinSdkPath]); 225 result[kWinSdkPath] = Value(NULL, gyp_defines[kWinSdkPath]);
211 226
212 return result; 227 return result;
213 } 228 }
214 229
215 // Returns the number of targets, number of GYP files. 230 // Returns the (number of targets, number of GYP files).
216 std::pair<int, int> WriteGypFiles( 231 std::pair<int, int> WriteGypFiles(CommonSetup* debug_setup,
217 const BuildSettings& debug_settings, 232 CommonSetup* release_setup,
218 const BuildSettings& release_settings, 233 Err* err) {
219 Err* err) {
220 // Group all targets by output GYP file name. 234 // Group all targets by output GYP file name.
221 std::vector<const Target*> debug_targets; 235 std::vector<const BuilderRecord*> debug_targets =
222 std::vector<const Target*> release_targets; 236 GetAllResolvedTargetRecords(debug_setup->builder());
223 debug_settings.target_manager().GetAllTargets(&debug_targets); 237 std::vector<const BuilderRecord*> release_targets =
224 release_settings.target_manager().GetAllTargets(&release_targets); 238 GetAllResolvedTargetRecords(release_setup->builder());
225 239
226 // Match up the debug and release version of each target by label. 240 // Match up the debug and release version of each target by label.
227 CorrelatedTargetsMap correlated; 241 CorrelatedTargetsMap correlated;
228 CorrelateTargets(debug_targets, release_targets, &correlated); 242 CorrelateTargets(debug_targets, release_targets, &correlated);
229 243
230 GypHelper helper; 244 GypHelper helper;
231 GroupedTargetsMap grouped_targets; 245 GroupedTargetsMap grouped_targets;
232 int target_count = 0; 246 int target_count = 0;
233 for (CorrelatedTargetsMap::iterator i = correlated.begin(); 247 for (CorrelatedTargetsMap::iterator i = correlated.begin();
234 i != correlated.end(); ++i) { 248 i != correlated.end(); ++i) {
235 const TargetGroup& group = i->second; 249 const TargetGroup& group = i->second;
236 if (!group.debug->item_node()->should_generate()) 250 if (!group.debug->should_generate())
237 continue; // Skip non-generated ones. 251 continue; // Skip non-generated ones.
238 if (group.debug->external()) 252 if (group.debug->item()->AsTarget()->external())
239 continue; // Skip external ones. 253 continue; // Skip external ones.
240 if (group.debug->gyp_file().is_null()) 254 if (group.debug->item()->AsTarget()->gyp_file().is_null())
241 continue; // Skip ones without GYP files. 255 continue; // Skip ones without GYP files.
242 256
243 if (!EnsureTargetsMatch(group, err)) 257 if (!EnsureTargetsMatch(group, err))
244 return std::make_pair(0, 0); 258 return std::make_pair(0, 0);
245 259
246 target_count++; 260 target_count++;
247 grouped_targets[helper.GetGypFileForTarget(group.debug, err)].push_back( 261 grouped_targets[
248 group); 262 helper.GetGypFileForTarget(group.debug->item()->AsTarget(), err)]
263 .push_back(group);
249 if (err->has_error()) 264 if (err->has_error())
250 return std::make_pair(0, 0); 265 return std::make_pair(0, 0);
251 } 266 }
252 267
253 // Write each GYP file. 268 // Write each GYP file.
254 for (GroupedTargetsMap::iterator i = grouped_targets.begin(); 269 for (GroupedTargetsMap::iterator i = grouped_targets.begin();
255 i != grouped_targets.end(); ++i) { 270 i != grouped_targets.end(); ++i) {
256 GypTargetWriter::WriteFile(i->first, i->second, err); 271 GypTargetWriter::WriteFile(i->first, i->second, err);
257 if (err->has_error()) 272 if (err->has_error())
258 return std::make_pair(0, 0); 273 return std::make_pair(0, 0);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 "gn_release.tmp/")); 366 "gn_release.tmp/"));
352 367
353 // Run both debug and release builds in parallel. 368 // Run both debug and release builds in parallel.
354 setup_release->RunPreMessageLoop(); 369 setup_release->RunPreMessageLoop();
355 if (!setup_debug->Run()) 370 if (!setup_debug->Run())
356 return 1; 371 return 1;
357 if (!setup_release->RunPostMessageLoop()) 372 if (!setup_release->RunPostMessageLoop())
358 return 1; 373 return 1;
359 374
360 Err err; 375 Err err;
361 std::pair<int, int> counts = WriteGypFiles(setup_debug->build_settings(), 376 std::pair<int, int> counts = WriteGypFiles(setup_debug, setup_release, &err);
362 setup_release->build_settings(),
363 &err);
364 if (err.has_error()) { 377 if (err.has_error()) {
365 err.PrintToStdout(); 378 err.PrintToStdout();
366 return 1; 379 return 1;
367 } 380 }
368 381
369 // Timing info. 382 // Timing info.
370 base::TimeTicks end_time = base::TimeTicks::Now(); 383 base::TimeTicks end_time = base::TimeTicks::Now();
371 if (!cmdline->HasSwitch(kSwitchQuiet)) { 384 if (!cmdline->HasSwitch(kSwitchQuiet)) {
372 OutputString("Done. ", DECORATION_GREEN); 385 OutputString("Done. ", DECORATION_GREEN);
373 386
374 std::string stats = "Wrote " + 387 std::string stats = "Wrote " +
375 base::IntToString(counts.first) + " targets to " + 388 base::IntToString(counts.first) + " targets to " +
376 base::IntToString(counts.second) + " GYP files read from " + 389 base::IntToString(counts.second) + " GYP files read from " +
377 base::IntToString( 390 base::IntToString(
378 setup_debug->scheduler().input_file_manager()->GetInputFileCount()) 391 setup_debug->scheduler().input_file_manager()->GetInputFileCount())
379 + " GN files in " + 392 + " GN files in " +
380 base::IntToString((end_time - begin_time).InMilliseconds()) + "ms\n"; 393 base::IntToString((end_time - begin_time).InMilliseconds()) + "ms\n";
381 394
382 OutputString(stats); 395 OutputString(stats);
383 } 396 }
384 397
385 return 0; 398 return 0;
386 } 399 }
387 400
388 } // namespace commands 401 } // namespace commands
OLDNEW
« no previous file with comments | « tools/gn/command_gen.cc ('k') | tools/gn/command_refs.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698