OLD | NEW |
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/setup.h" | 5 #include "tools/gn/setup.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <sstream> | 10 #include <sstream> |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 "\n" | 61 "\n" |
62 " check_targets [optional]\n" | 62 " check_targets [optional]\n" |
63 " A list of labels and label patterns that should be checked when\n" | 63 " A list of labels and label patterns that should be checked when\n" |
64 " running \"gn check\" or \"gn gen --check\". If unspecified, all\n" | 64 " running \"gn check\" or \"gn gen --check\". If unspecified, all\n" |
65 " targets will be checked. If it is the empty list, no targets will\n" | 65 " targets will be checked. If it is the empty list, no targets will\n" |
66 " be checked.\n" | 66 " be checked.\n" |
67 "\n" | 67 "\n" |
68 " The format of this list is identical to that of \"visibility\"\n" | 68 " The format of this list is identical to that of \"visibility\"\n" |
69 " so see \"gn help visibility\" for examples.\n" | 69 " so see \"gn help visibility\" for examples.\n" |
70 "\n" | 70 "\n" |
| 71 " exec_script_whitelist [optional]\n" |
| 72 " A list of .gn/.gni files (not labels) that have permission to call\n" |
| 73 " the exec_script function. If this list is defined, calls to\n" |
| 74 " exec_script will be checked against this list and GN will fail if\n" |
| 75 " the current file isn't in the list.\n" |
| 76 "\n" |
| 77 " This is to allow the use of exec_script to be restricted since\n" |
| 78 " is easy to use inappropriately. Wildcards are not supported.\n" |
| 79 " Files in the secondary_source tree (if defined) should be\n" |
| 80 " referenced by ignoring the secondary tree and naming them as if\n" |
| 81 " they are in the main tree.\n" |
| 82 "\n" |
| 83 " If unspecified, the ability to call exec_script is unrestricted.\n" |
| 84 "\n" |
| 85 " Example:\n" |
| 86 " exec_script_whitelist = [\n" |
| 87 " \"//base/BUILD.gn\",\n" |
| 88 " \"//build/my_config.gni\",\n" |
| 89 " ]\n" |
| 90 "\n" |
71 " root [optional]\n" | 91 " root [optional]\n" |
72 " Label of the root build target. The GN build will start by loading\n" | 92 " Label of the root build target. The GN build will start by loading\n" |
73 " the build file containing this target name. This defaults to\n" | 93 " the build file containing this target name. This defaults to\n" |
74 " \"//:\" which will cause the file //BUILD.gn to be loaded.\n" | 94 " \"//:\" which will cause the file //BUILD.gn to be loaded.\n" |
75 "\n" | 95 "\n" |
76 " secondary_source [optional]\n" | 96 " secondary_source [optional]\n" |
77 " Label of an alternate directory tree to find input files. When\n" | 97 " Label of an alternate directory tree to find input files. When\n" |
78 " searching for a BUILD.gn file (or the build config file discussed\n" | 98 " searching for a BUILD.gn file (or the build config file discussed\n" |
79 " above), the file will first be looked for in the source root.\n" | 99 " above), the file will first be looked for in the source root.\n" |
80 " If it's not found, the secondary source root will be checked\n" | 100 " If it's not found, the secondary source root will be checked\n" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 main_loop->PostTask(FROM_HERE, base::Bind(&Builder::ItemDefined, builder, | 143 main_loop->PostTask(FROM_HERE, base::Bind(&Builder::ItemDefined, builder, |
124 base::Passed(&item))); | 144 base::Passed(&item))); |
125 } | 145 } |
126 | 146 |
127 void DecrementWorkCount() { | 147 void DecrementWorkCount() { |
128 g_scheduler->DecrementWorkCount(); | 148 g_scheduler->DecrementWorkCount(); |
129 } | 149 } |
130 | 150 |
131 } // namespace | 151 } // namespace |
132 | 152 |
133 // CommonSetup ----------------------------------------------------------------- | 153 const char Setup::kBuildArgFileName[] = "args.gn"; |
134 | 154 |
135 const char CommonSetup::kBuildArgFileName[] = "args.gn"; | 155 Setup::Setup() |
136 | |
137 CommonSetup::CommonSetup() | |
138 : build_settings_(), | 156 : build_settings_(), |
139 loader_(new LoaderImpl(&build_settings_)), | 157 loader_(new LoaderImpl(&build_settings_)), |
140 builder_(new Builder(loader_.get())), | 158 builder_(new Builder(loader_.get())), |
141 root_build_file_("//BUILD.gn"), | 159 root_build_file_("//BUILD.gn"), |
142 check_for_bad_items_(true), | 160 check_for_bad_items_(true), |
143 check_for_unused_overrides_(true), | 161 check_for_unused_overrides_(true), |
144 check_public_headers_(false) { | 162 check_public_headers_(false), |
145 loader_->set_complete_callback(base::Bind(&DecrementWorkCount)); | |
146 } | |
147 | |
148 CommonSetup::CommonSetup(const CommonSetup& other) | |
149 : build_settings_(other.build_settings_), | |
150 loader_(new LoaderImpl(&build_settings_)), | |
151 builder_(new Builder(loader_.get())), | |
152 root_build_file_(other.root_build_file_), | |
153 check_for_bad_items_(other.check_for_bad_items_), | |
154 check_for_unused_overrides_(other.check_for_unused_overrides_), | |
155 check_public_headers_(other.check_public_headers_) { | |
156 loader_->set_complete_callback(base::Bind(&DecrementWorkCount)); | |
157 } | |
158 | |
159 CommonSetup::~CommonSetup() { | |
160 } | |
161 | |
162 void CommonSetup::RunPreMessageLoop() { | |
163 // Load the root build file. | |
164 loader_->Load(root_build_file_, LocationRange(), Label()); | |
165 | |
166 // Will be decremented with the loader is drained. | |
167 g_scheduler->IncrementWorkCount(); | |
168 } | |
169 | |
170 bool CommonSetup::RunPostMessageLoop() { | |
171 Err err; | |
172 if (check_for_bad_items_) { | |
173 if (!builder_->CheckForBadItems(&err)) { | |
174 err.PrintToStdout(); | |
175 return false; | |
176 } | |
177 } | |
178 | |
179 if (check_for_unused_overrides_) { | |
180 if (!build_settings_.build_args().VerifyAllOverridesUsed(&err)) { | |
181 // TODO(brettw) implement a system of warnings. Until we have a better | |
182 // system, print the error but don't return failure. | |
183 err.PrintToStdout(); | |
184 return true; | |
185 } | |
186 } | |
187 | |
188 if (check_public_headers_) { | |
189 std::vector<const Target*> all_targets = builder_->GetAllResolvedTargets(); | |
190 std::vector<const Target*> to_check; | |
191 if (check_patterns()) { | |
192 commands::FilterTargetsByPatterns(all_targets, *check_patterns(), | |
193 &to_check); | |
194 } else { | |
195 to_check = all_targets; | |
196 } | |
197 | |
198 if (!commands::CheckPublicHeaders(&build_settings_, all_targets, | |
199 to_check, false)) { | |
200 return false; | |
201 } | |
202 } | |
203 | |
204 // Write out tracing and timing if requested. | |
205 const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); | |
206 if (cmdline->HasSwitch(switches::kTime)) | |
207 PrintLongHelp(SummarizeTraces()); | |
208 if (cmdline->HasSwitch(switches::kTracelog)) | |
209 SaveTraces(cmdline->GetSwitchValuePath(switches::kTracelog)); | |
210 | |
211 return true; | |
212 } | |
213 | |
214 // Setup ----------------------------------------------------------------------- | |
215 | |
216 Setup::Setup() | |
217 : CommonSetup(), | |
218 empty_settings_(&empty_build_settings_, std::string()), | 163 empty_settings_(&empty_build_settings_, std::string()), |
219 dotfile_scope_(&empty_settings_), | 164 dotfile_scope_(&empty_settings_), |
220 fill_arguments_(true) { | 165 fill_arguments_(true) { |
221 empty_settings_.set_toolchain_label(Label()); | 166 empty_settings_.set_toolchain_label(Label()); |
222 build_settings_.set_item_defined_callback( | 167 build_settings_.set_item_defined_callback( |
223 base::Bind(&ItemDefinedCallback, scheduler_.main_loop(), builder_)); | 168 base::Bind(&ItemDefinedCallback, scheduler_.main_loop(), builder_)); |
224 | 169 |
| 170 loader_->set_complete_callback(base::Bind(&DecrementWorkCount)); |
225 // The scheduler's main loop wasn't created when the Loader was created, so | 171 // The scheduler's main loop wasn't created when the Loader was created, so |
226 // we need to set it now. | 172 // we need to set it now. |
227 loader_->set_main_loop(scheduler_.main_loop()); | 173 loader_->set_main_loop(scheduler_.main_loop()); |
228 } | 174 } |
229 | 175 |
230 Setup::~Setup() { | 176 Setup::~Setup() { |
231 } | 177 } |
232 | 178 |
233 bool Setup::DoSetup(const std::string& build_dir, bool force_create) { | 179 bool Setup::DoSetup(const std::string& build_dir, bool force_create) { |
234 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); | 180 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 return true; | 213 return true; |
268 } | 214 } |
269 | 215 |
270 bool Setup::Run() { | 216 bool Setup::Run() { |
271 RunPreMessageLoop(); | 217 RunPreMessageLoop(); |
272 if (!scheduler_.Run()) | 218 if (!scheduler_.Run()) |
273 return false; | 219 return false; |
274 return RunPostMessageLoop(); | 220 return RunPostMessageLoop(); |
275 } | 221 } |
276 | 222 |
277 Scheduler* Setup::GetScheduler() { | |
278 return &scheduler_; | |
279 } | |
280 | |
281 SourceFile Setup::GetBuildArgFile() const { | 223 SourceFile Setup::GetBuildArgFile() const { |
282 return SourceFile(build_settings_.build_dir().value() + kBuildArgFileName); | 224 return SourceFile(build_settings_.build_dir().value() + kBuildArgFileName); |
283 } | 225 } |
284 | 226 |
| 227 void Setup::RunPreMessageLoop() { |
| 228 // Load the root build file. |
| 229 loader_->Load(root_build_file_, LocationRange(), Label()); |
| 230 |
| 231 // Will be decremented with the loader is drained. |
| 232 g_scheduler->IncrementWorkCount(); |
| 233 } |
| 234 |
| 235 bool Setup::RunPostMessageLoop() { |
| 236 Err err; |
| 237 if (check_for_bad_items_) { |
| 238 if (!builder_->CheckForBadItems(&err)) { |
| 239 err.PrintToStdout(); |
| 240 return false; |
| 241 } |
| 242 } |
| 243 |
| 244 if (check_for_unused_overrides_) { |
| 245 if (!build_settings_.build_args().VerifyAllOverridesUsed(&err)) { |
| 246 // TODO(brettw) implement a system of warnings. Until we have a better |
| 247 // system, print the error but don't return failure. |
| 248 err.PrintToStdout(); |
| 249 return true; |
| 250 } |
| 251 } |
| 252 |
| 253 if (check_public_headers_) { |
| 254 std::vector<const Target*> all_targets = builder_->GetAllResolvedTargets(); |
| 255 std::vector<const Target*> to_check; |
| 256 if (check_patterns()) { |
| 257 commands::FilterTargetsByPatterns(all_targets, *check_patterns(), |
| 258 &to_check); |
| 259 } else { |
| 260 to_check = all_targets; |
| 261 } |
| 262 |
| 263 if (!commands::CheckPublicHeaders(&build_settings_, all_targets, |
| 264 to_check, false)) { |
| 265 return false; |
| 266 } |
| 267 } |
| 268 |
| 269 // Write out tracing and timing if requested. |
| 270 const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); |
| 271 if (cmdline->HasSwitch(switches::kTime)) |
| 272 PrintLongHelp(SummarizeTraces()); |
| 273 if (cmdline->HasSwitch(switches::kTracelog)) |
| 274 SaveTraces(cmdline->GetSwitchValuePath(switches::kTracelog)); |
| 275 |
| 276 return true; |
| 277 } |
| 278 |
285 bool Setup::FillArguments(const base::CommandLine& cmdline) { | 279 bool Setup::FillArguments(const base::CommandLine& cmdline) { |
286 // Use the args on the command line if specified, and save them. Do this even | 280 // Use the args on the command line if specified, and save them. Do this even |
287 // if the list is empty (this means clear any defaults). | 281 // if the list is empty (this means clear any defaults). |
288 if (cmdline.HasSwitch(switches::kArgs)) { | 282 if (cmdline.HasSwitch(switches::kArgs)) { |
289 if (!FillArgsFromCommandLine(cmdline.GetSwitchValueASCII(switches::kArgs))) | 283 if (!FillArgsFromCommandLine(cmdline.GetSwitchValueASCII(switches::kArgs))) |
290 return false; | 284 return false; |
291 SaveArgsToFile(); | 285 SaveArgsToFile(); |
292 return true; | 286 return true; |
293 } | 287 } |
294 | 288 |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 if (err.has_error()) { | 531 if (err.has_error()) { |
538 err.PrintToStdout(); | 532 err.PrintToStdout(); |
539 return false; | 533 return false; |
540 } | 534 } |
541 | 535 |
542 return true; | 536 return true; |
543 } | 537 } |
544 | 538 |
545 bool Setup::FillOtherConfig(const base::CommandLine& cmdline) { | 539 bool Setup::FillOtherConfig(const base::CommandLine& cmdline) { |
546 Err err; | 540 Err err; |
| 541 SourceDir current_dir("//"); |
547 | 542 |
548 // Secondary source path, read from the config file if present. | 543 // Secondary source path, read from the config file if present. |
549 // Read from the config file if present. | 544 // Read from the config file if present. |
550 const Value* secondary_value = | 545 const Value* secondary_value = |
551 dotfile_scope_.GetValue("secondary_source", true); | 546 dotfile_scope_.GetValue("secondary_source", true); |
552 if (secondary_value) { | 547 if (secondary_value) { |
553 if (!secondary_value->VerifyTypeIs(Value::STRING, &err)) { | 548 if (!secondary_value->VerifyTypeIs(Value::STRING, &err)) { |
554 err.PrintToStdout(); | 549 err.PrintToStdout(); |
555 return false; | 550 return false; |
556 } | 551 } |
557 build_settings_.SetSecondarySourcePath( | 552 build_settings_.SetSecondarySourcePath( |
558 SourceDir(secondary_value->string_value())); | 553 SourceDir(secondary_value->string_value())); |
559 } | 554 } |
560 | 555 |
561 // Root build file. | 556 // Root build file. |
562 const Value* root_value = dotfile_scope_.GetValue("root", true); | 557 const Value* root_value = dotfile_scope_.GetValue("root", true); |
563 if (root_value) { | 558 if (root_value) { |
564 if (!root_value->VerifyTypeIs(Value::STRING, &err)) { | 559 if (!root_value->VerifyTypeIs(Value::STRING, &err)) { |
565 err.PrintToStdout(); | 560 err.PrintToStdout(); |
566 return false; | 561 return false; |
567 } | 562 } |
568 | 563 |
569 Label root_target_label = | 564 Label root_target_label = |
570 Label::Resolve(SourceDir("//"), Label(), *root_value, &err); | 565 Label::Resolve(current_dir, Label(), *root_value, &err); |
571 if (err.has_error()) { | 566 if (err.has_error()) { |
572 err.PrintToStdout(); | 567 err.PrintToStdout(); |
573 return false; | 568 return false; |
574 } | 569 } |
575 | 570 |
576 root_build_file_ = Loader::BuildFileForLabel(root_target_label); | 571 root_build_file_ = Loader::BuildFileForLabel(root_target_label); |
577 } | 572 } |
578 | 573 |
579 // Build config file. | 574 // Build config file. |
580 const Value* build_config_value = | 575 const Value* build_config_value = |
581 dotfile_scope_.GetValue("buildconfig", true); | 576 dotfile_scope_.GetValue("buildconfig", true); |
582 if (!build_config_value) { | 577 if (!build_config_value) { |
583 Err(Location(), "No build config file.", | 578 Err(Location(), "No build config file.", |
584 "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) + "\")\n" | 579 "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) + "\")\n" |
585 "didn't specify a \"buildconfig\" value.").PrintToStdout(); | 580 "didn't specify a \"buildconfig\" value.").PrintToStdout(); |
586 return false; | 581 return false; |
587 } else if (!build_config_value->VerifyTypeIs(Value::STRING, &err)) { | 582 } else if (!build_config_value->VerifyTypeIs(Value::STRING, &err)) { |
588 err.PrintToStdout(); | 583 err.PrintToStdout(); |
589 return false; | 584 return false; |
590 } | 585 } |
591 build_settings_.set_build_config_file( | 586 build_settings_.set_build_config_file( |
592 SourceFile(build_config_value->string_value())); | 587 SourceFile(build_config_value->string_value())); |
593 | 588 |
594 // Targets to check. | 589 // Targets to check. |
595 const Value* check_targets_value = | 590 const Value* check_targets_value = |
596 dotfile_scope_.GetValue("check_targets", true); | 591 dotfile_scope_.GetValue("check_targets", true); |
597 if (check_targets_value) { | 592 if (check_targets_value) { |
598 check_patterns_.reset(new std::vector<LabelPattern>); | |
599 | |
600 // Fill the list of targets to check. | 593 // Fill the list of targets to check. |
601 if (!check_targets_value->VerifyTypeIs(Value::LIST, &err)) { | 594 if (!check_targets_value->VerifyTypeIs(Value::LIST, &err)) { |
602 err.PrintToStdout(); | 595 err.PrintToStdout(); |
603 return false; | 596 return false; |
604 } | 597 } |
605 SourceDir current_dir("//"); | 598 |
| 599 check_patterns_.reset(new std::vector<LabelPattern>); |
606 for (const auto& item : check_targets_value->list_value()) { | 600 for (const auto& item : check_targets_value->list_value()) { |
607 check_patterns_->push_back( | 601 check_patterns_->push_back( |
608 LabelPattern::GetPattern(current_dir, item, &err)); | 602 LabelPattern::GetPattern(current_dir, item, &err)); |
609 if (err.has_error()) { | 603 if (err.has_error()) { |
610 err.PrintToStdout(); | 604 err.PrintToStdout(); |
611 return false; | 605 return false; |
612 } | 606 } |
613 } | 607 } |
614 } | 608 } |
615 | 609 |
| 610 // Fill exec_script_whitelist. |
| 611 const Value* exec_script_whitelist_value = |
| 612 dotfile_scope_.GetValue("exec_script_whitelist", true); |
| 613 if (exec_script_whitelist_value) { |
| 614 // Fill the list of targets to check. |
| 615 if (!exec_script_whitelist_value->VerifyTypeIs(Value::LIST, &err)) { |
| 616 err.PrintToStdout(); |
| 617 return false; |
| 618 } |
| 619 scoped_ptr<std::set<SourceFile>> whitelist(new std::set<SourceFile>); |
| 620 for (const auto& item : exec_script_whitelist_value->list_value()) { |
| 621 if (!item.VerifyTypeIs(Value::STRING, &err)) { |
| 622 err.PrintToStdout(); |
| 623 return false; |
| 624 } |
| 625 whitelist->insert(current_dir.ResolveRelativeFile(item.string_value())); |
| 626 } |
| 627 build_settings_.set_exec_script_whitelist(whitelist.Pass()); |
| 628 } |
| 629 |
616 return true; | 630 return true; |
617 } | 631 } |
618 | |
619 // DependentSetup -------------------------------------------------------------- | |
620 | |
621 DependentSetup::DependentSetup(Setup* derive_from) | |
622 : CommonSetup(*derive_from), | |
623 scheduler_(derive_from->GetScheduler()) { | |
624 build_settings_.set_item_defined_callback( | |
625 base::Bind(&ItemDefinedCallback, scheduler_->main_loop(), builder_)); | |
626 } | |
627 | |
628 DependentSetup::DependentSetup(DependentSetup* derive_from) | |
629 : CommonSetup(*derive_from), | |
630 scheduler_(derive_from->GetScheduler()) { | |
631 build_settings_.set_item_defined_callback( | |
632 base::Bind(&ItemDefinedCallback, scheduler_->main_loop(), builder_)); | |
633 } | |
634 | |
635 DependentSetup::~DependentSetup() { | |
636 } | |
637 | |
638 Scheduler* DependentSetup::GetScheduler() { | |
639 return scheduler_; | |
640 } | |
641 | |
642 void DependentSetup::RunPreMessageLoop() { | |
643 CommonSetup::RunPreMessageLoop(); | |
644 } | |
645 | |
646 bool DependentSetup::RunPostMessageLoop() { | |
647 return CommonSetup::RunPostMessageLoop(); | |
648 } | |
649 | |
OLD | NEW |