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

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

Issue 1292983004: [GN]: Precompiled header support for GCC. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: switch statement. error handling. some initial docs. Created 5 years, 4 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 | « tools/gn/ninja_binary_target_writer.h ('k') | tools/gn/ninja_binary_target_writer_unittest.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 "tools/gn/ninja_binary_target_writer.h" 5 #include "tools/gn/ninja_binary_target_writer.h"
6 6
7 #include <cstring> 7 #include <cstring>
8 #include <set> 8 #include <set>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 const Tool* tool = target->toolchain()->GetTool(*computed_tool_type); 125 const Tool* tool = target->toolchain()->GetTool(*computed_tool_type);
126 if (!tool) 126 if (!tool)
127 return false; // Tool does not apply for this toolchain.file. 127 return false; // Tool does not apply for this toolchain.file.
128 128
129 // Figure out what output(s) this compiler produces. 129 // Figure out what output(s) this compiler produces.
130 SubstitutionWriter::ApplyListToCompilerAsOutputFile( 130 SubstitutionWriter::ApplyListToCompilerAsOutputFile(
131 target, source, tool->outputs(), outputs); 131 target, source, tool->outputs(), outputs);
132 return !outputs->empty(); 132 return !outputs->empty();
133 } 133 }
134 134
135 // Returns the language-specific prefix/suffix for precomiled header files. 135 // Returns the language-specific suffix for precompiled header files.
136 const char* GetPCHLangForToolType(Toolchain::ToolType type) { 136 const char* GetPCHSuffixForToolType(Toolchain::ToolType type) {
137 switch (type) { 137 switch (type) {
138 case Toolchain::TYPE_CC: 138 case Toolchain::TYPE_CC:
139 return "c"; 139 return "c";
140 case Toolchain::TYPE_CXX: 140 case Toolchain::TYPE_CXX:
141 return "cc"; 141 return "cc";
142 case Toolchain::TYPE_OBJC: 142 case Toolchain::TYPE_OBJC:
143 return "m"; 143 return "m";
144 case Toolchain::TYPE_OBJCXX: 144 case Toolchain::TYPE_OBJCXX:
145 return "mm"; 145 return "mm";
146 default: 146 default:
147 NOTREACHED() << "Not a valid PCH tool type type"; 147 NOTREACHED() << "Not a valid PCH tool type type";
148 return ""; 148 return "";
149 } 149 }
150 } 150 }
151 151
152 // Returns the language-specific lang recognized by gcc’s -x flag for
153 // precompiled header files.
154 const char* GetPCHLangForToolType(Toolchain::ToolType type) {
155 switch (type) {
156 case Toolchain::TYPE_CC:
157 return "c-header";
158 case Toolchain::TYPE_CXX:
159 return "c++-header";
160 case Toolchain::TYPE_OBJC:
161 return "objective-c-header";
162 case Toolchain::TYPE_OBJCXX:
163 return "objective-c++-header";
164 default:
165 NOTREACHED() << "Not a valid PCH tool type type";
166 return "";
167 }
168 }
169
152 // Returns the object files for the precompiled header of the given type (flag 170 // Returns the object files for the precompiled header of the given type (flag
153 // type and tool type must match). 171 // type and tool type must match).
154 void GetWindowsPCHObjectFiles(const Target* target, 172 void GetPCHObjectFiles(const Target* target,
155 Toolchain::ToolType tool_type, 173 Toolchain::ToolType tool_type,
156 std::vector<OutputFile>* outputs) { 174 std::vector<OutputFile>* outputs) {
157 outputs->clear(); 175 outputs->clear();
158 176
159 // Compute the tool. This must use the tool type passed in rather than the 177 // Compute the tool. This must use the tool type passed in rather than the
160 // detected file type of the precompiled source file since the same 178 // detected file type of the precompiled source file since the same
161 // precompiled source file will be used for separate C/C++ compiles. 179 // precompiled source file will be used for separate C/C++ compiles.
162 const Tool* tool = target->toolchain()->GetTool(tool_type); 180 const Tool* tool = target->toolchain()->GetTool(tool_type);
163 if (!tool) 181 if (!tool)
164 return; 182 return;
165 SubstitutionWriter::ApplyListToCompilerAsOutputFile( 183 SubstitutionWriter::ApplyListToCompilerAsOutputFile(
166 target, target->config_values().precompiled_source(), 184 target, target->config_values().precompiled_source(),
167 tool->outputs(), outputs); 185 tool->outputs(), outputs);
168 186
169 if (outputs->empty()) 187 if (outputs->empty())
170 return; 188 return;
171 if (outputs->size() > 1) 189 if (outputs->size() > 1)
172 outputs->resize(1); // Only link the first output from the compiler tool. 190 outputs->resize(1); // Only link the first output from the compiler tool.
173 191
174 // Need to annotate the obj files with the language type. For example: 192 // Need to annotate the obj files with the language type. For example:
175 // obj/foo/target_name.precompile.obj -> 193 // obj/foo/target_name.precompile.obj ->
176 // obj/foo/target_name.precompile.cc.obj 194 // obj/foo/target_name.precompile.cc.obj
177 const char* lang_suffix = GetPCHLangForToolType(tool_type); 195 const char* lang_suffix = GetPCHSuffixForToolType(tool_type);
brettw 2015/08/24 19:36:05 I'm having a hard time trying to compute the inter
Bons 2015/08/24 19:53:57 defines = include_dirs = cflags = cflags_cc = targ
178 std::string& output_value = (*outputs)[0].value(); 196 std::string& output_value = (*outputs)[0].value();
179 size_t extension_offset = FindExtensionOffset(output_value); 197 size_t extension_offset = FindExtensionOffset(output_value);
180 if (extension_offset == std::string::npos) { 198 if (extension_offset == std::string::npos) {
181 NOTREACHED() << "No extension found"; 199 NOTREACHED() << "No extension found";
182 } else { 200 } else {
183 DCHECK(extension_offset >= 1); 201 DCHECK(extension_offset >= 1);
184 DCHECK(output_value[extension_offset - 1] == '.'); 202 DCHECK(output_value[extension_offset - 1] == '.');
185 output_value.insert(extension_offset - 1, "."); 203 output_value.insert(extension_offset - 1, ".");
186 output_value.insert(extension_offset, lang_suffix); 204 output_value.insert(extension_offset, lang_suffix);
187 } 205 }
(...skipping 12 matching lines...) Expand all
200 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; 218 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
201 if (GetOutputFilesForSource(source_set, source, &tool_type, &tool_outputs)) 219 if (GetOutputFilesForSource(source_set, source, &tool_type, &tool_outputs))
202 obj_files->push_back(tool_outputs[0]); 220 obj_files->push_back(tool_outputs[0]);
203 221
204 used_types.Set(GetSourceFileType(source)); 222 used_types.Set(GetSourceFileType(source));
205 } 223 }
206 224
207 // Precompiled header object files. 225 // Precompiled header object files.
208 if (source_set->config_values().has_precompiled_headers()) { 226 if (source_set->config_values().has_precompiled_headers()) {
209 if (used_types.Get(SOURCE_C)) { 227 if (used_types.Get(SOURCE_C)) {
210 GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_CC, &tool_outputs); 228 GetPCHObjectFiles(source_set, Toolchain::TYPE_CC, &tool_outputs);
211 obj_files->Append(tool_outputs.begin(), tool_outputs.end()); 229 obj_files->Append(tool_outputs.begin(), tool_outputs.end());
212 } 230 }
213 if (used_types.Get(SOURCE_CPP)) { 231 if (used_types.Get(SOURCE_CPP)) {
214 GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_CXX, &tool_outputs); 232 GetPCHObjectFiles(source_set, Toolchain::TYPE_CXX, &tool_outputs);
215 obj_files->Append(tool_outputs.begin(), tool_outputs.end()); 233 obj_files->Append(tool_outputs.begin(), tool_outputs.end());
216 } 234 }
217 if (used_types.Get(SOURCE_M)) { 235 if (used_types.Get(SOURCE_M)) {
218 GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_OBJC, &tool_outputs); 236 GetPCHObjectFiles(source_set, Toolchain::TYPE_OBJC, &tool_outputs);
219 obj_files->Append(tool_outputs.begin(), tool_outputs.end()); 237 obj_files->Append(tool_outputs.begin(), tool_outputs.end());
220 } 238 }
221 if (used_types.Get(SOURCE_MM)) { 239 if (used_types.Get(SOURCE_MM)) {
222 GetWindowsPCHObjectFiles(source_set, Toolchain::TYPE_OBJCXX, 240 GetPCHObjectFiles(source_set, Toolchain::TYPE_OBJCXX,
223 &tool_outputs); 241 &tool_outputs);
224 obj_files->Append(tool_outputs.begin(), tool_outputs.end()); 242 obj_files->Append(tool_outputs.begin(), tool_outputs.end());
225 } 243 }
226 } 244 }
227 } 245 }
228 246
229 } // namespace 247 } // namespace
230 248
231 NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target, 249 NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target,
232 std::ostream& out) 250 std::ostream& out)
(...skipping 11 matching lines...) Expand all
244 for (const auto& source : target_->sources()) 262 for (const auto& source : target_->sources())
245 used_types.Set(GetSourceFileType(source)); 263 used_types.Set(GetSourceFileType(source));
246 264
247 WriteCompilerVars(used_types); 265 WriteCompilerVars(used_types);
248 266
249 // The input dependencies will be an order-only dependency. This will cause 267 // The input dependencies will be an order-only dependency. This will cause
250 // Ninja to make sure the inputs are up-to-date before compiling this source, 268 // Ninja to make sure the inputs are up-to-date before compiling this source,
251 // but changes in the inputs deps won't cause the file to be recompiled. 269 // but changes in the inputs deps won't cause the file to be recompiled.
252 // 270 //
253 // This is important to prevent changes in unrelated actions that are 271 // This is important to prevent changes in unrelated actions that are
254 // upstream of this target from causing everything to be recompiled 272 // upstream of this target from causing everything to be recompiled.
255 // 273 //
256 // Why can we get away with this rather than using implicit deps ("|", which 274 // Why can we get away with this rather than using implicit deps ("|", which
257 // will force rebuilds when the inputs change)? For source code, the 275 // will force rebuilds when the inputs change)? For source code, the
258 // computed dependencies of all headers will be computed by the compiler, 276 // computed dependencies of all headers will be computed by the compiler,
259 // which will cause source rebuilds if any "real" upstream dependencies 277 // which will cause source rebuilds if any "real" upstream dependencies
260 // change. 278 // change.
261 // 279 //
262 // If a .cc file is generated by an input dependency, Ninja will see the 280 // If a .cc file is generated by an input dependency, Ninja will see the
263 // input to the build rule doesn't exist, and that it is an output from a 281 // input to the build rule doesn't exist, and that it is an output from a
264 // previous step, and build the previous step first. This is a "real" 282 // previous step, and build the previous step first. This is a "real"
265 // dependency and doesn't need | or || to express. 283 // dependency and doesn't need | or || to express.
266 // 284 //
267 // The only case where this rule matters is for the first build where no .d 285 // The only case where this rule matters is for the first build where no .d
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 IncludeWriter(include_path_output), out_); 357 IncludeWriter(include_path_output), out_);
340 out_ << std::endl; 358 out_ << std::endl;
341 } 359 }
342 360
343 bool has_precompiled_headers = 361 bool has_precompiled_headers =
344 target_->config_values().has_precompiled_headers(); 362 target_->config_values().has_precompiled_headers();
345 363
346 // Some toolchains pass cflags to the assembler since it's the same command, 364 // Some toolchains pass cflags to the assembler since it's the same command,
347 // and cflags_c might also be sent to the objective C compiler. 365 // and cflags_c might also be sent to the objective C compiler.
348 // 366 //
349 // TODO(brettw) remove the SOURCE_M from the CFLAGS_C writing once the Chrome 367 // TODO(brettw): remove the SOURCE_M from the CFLAGS_C writing once the Chrome
350 // Mac build is updated not to pass cflags_c to .m files. 368 // Mac build is updated not to pass cflags_c to .m files.
351 EscapeOptions opts = GetFlagOptions(); 369 EscapeOptions opts = GetFlagOptions();
352 if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_CPP) || 370 if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_CPP) ||
353 used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM) || 371 used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM) ||
354 used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) { 372 used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) {
355 WriteOneFlag(SUBSTITUTION_CFLAGS, false, Toolchain::TYPE_NONE, 373 WriteOneFlag(SUBSTITUTION_CFLAGS, false, Toolchain::TYPE_NONE,
356 &ConfigValues::cflags, opts); 374 &ConfigValues::cflags, opts);
357 } 375 }
358 if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_M) || 376 if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_M) ||
359 used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) { 377 used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 425
408 void NinjaBinaryTargetWriter::WritePrecompiledHeaderCommands( 426 void NinjaBinaryTargetWriter::WritePrecompiledHeaderCommands(
409 const SourceFileTypeSet& used_types, 427 const SourceFileTypeSet& used_types,
410 const OutputFile& order_only_dep, 428 const OutputFile& order_only_dep,
411 std::vector<OutputFile>* object_files) { 429 std::vector<OutputFile>* object_files) {
412 if (!target_->config_values().has_precompiled_headers()) 430 if (!target_->config_values().has_precompiled_headers())
413 return; 431 return;
414 432
415 const Tool* tool_c = target_->toolchain()->GetTool(Toolchain::TYPE_CC); 433 const Tool* tool_c = target_->toolchain()->GetTool(Toolchain::TYPE_CC);
416 if (tool_c && 434 if (tool_c &&
417 tool_c->precompiled_header_type() == Tool::PCH_MSVC && 435 tool_c->precompiled_header_type() != Tool::PCH_NONE &&
418 used_types.Get(SOURCE_C)) { 436 used_types.Get(SOURCE_C)) {
419 WriteWindowsPCHCommand(SUBSTITUTION_CFLAGS_C, 437 WritePCHCommand(SUBSTITUTION_CFLAGS_C,
420 Toolchain::TYPE_CC, 438 Toolchain::TYPE_CC,
421 order_only_dep, object_files); 439 tool_c->precompiled_header_type(),
440 order_only_dep, object_files);
422 } 441 }
423 const Tool* tool_cxx = target_->toolchain()->GetTool(Toolchain::TYPE_CXX); 442 const Tool* tool_cxx = target_->toolchain()->GetTool(Toolchain::TYPE_CXX);
424 if (tool_cxx && 443 if (tool_cxx &&
425 tool_cxx->precompiled_header_type() == Tool::PCH_MSVC && 444 tool_cxx->precompiled_header_type() != Tool::PCH_NONE &&
426 used_types.Get(SOURCE_CPP)) { 445 used_types.Get(SOURCE_CPP)) {
427 WriteWindowsPCHCommand(SUBSTITUTION_CFLAGS_CC, 446 WritePCHCommand(SUBSTITUTION_CFLAGS_CC,
428 Toolchain::TYPE_CXX, 447 Toolchain::TYPE_CXX,
429 order_only_dep, object_files); 448 tool_cxx->precompiled_header_type(),
449 order_only_dep, object_files);
450 }
451
452 const Tool* tool_objc = target_->toolchain()->GetTool(Toolchain::TYPE_OBJC);
453 if (tool_objc &&
454 tool_objc->precompiled_header_type() == Tool::PCH_GCC &&
455 used_types.Get(SOURCE_M)) {
456 WritePCHCommand(SUBSTITUTION_CFLAGS_OBJC,
457 Toolchain::TYPE_OBJC,
458 tool_objc->precompiled_header_type(),
459 order_only_dep, object_files);
460 }
461
462 const Tool* tool_objcxx =
463 target_->toolchain()->GetTool(Toolchain::TYPE_OBJCXX);
464 if (tool_objcxx &&
465 tool_objcxx->precompiled_header_type() == Tool::PCH_GCC &&
466 used_types.Get(SOURCE_MM)) {
467 WritePCHCommand(SUBSTITUTION_CFLAGS_OBJCC,
468 Toolchain::TYPE_OBJCXX,
469 tool_objcxx->precompiled_header_type(),
470 order_only_dep, object_files);
430 } 471 }
431 } 472 }
432 473
433 void NinjaBinaryTargetWriter::WriteWindowsPCHCommand( 474 void NinjaBinaryTargetWriter::WritePCHCommand(
434 SubstitutionType flag_type, 475 SubstitutionType flag_type,
435 Toolchain::ToolType tool_type, 476 Toolchain::ToolType tool_type,
436 const OutputFile& order_only_dep, 477 Tool::PrecompiledHeaderType header_type,
437 std::vector<OutputFile>* object_files) { 478 const OutputFile& order_only_dep,
479 std::vector<OutputFile>* object_files) {
480 // With the GCC toolset, ensure the precompiled source and precompiled header
481 // are the same target.
482 if (header_type == Tool::PCH_GCC) {
483 SourceFile source = target_->config_values().precompiled_source();
484 std::string header_str = target_->config_values().precompiled_header();
485 header_str.insert(0, "//");
486 SourceFile header = SourceFile(SourceFile::SWAP_IN, &header_str);
487 if (source != header) {
488 NOTREACHED() << "PCH source file must equal header for GCC toolchain";
489 }
490 }
491
438 // Compute the object file (it will be language-specific). 492 // Compute the object file (it will be language-specific).
439 std::vector<OutputFile> outputs; 493 std::vector<OutputFile> outputs;
440 GetWindowsPCHObjectFiles(target_, tool_type, &outputs); 494 GetPCHObjectFiles(target_, tool_type, &outputs);
441 if (outputs.empty()) 495 if (outputs.empty())
442 return; 496 return;
443 object_files->insert(object_files->end(), outputs.begin(), outputs.end()); 497 object_files->insert(object_files->end(), outputs.begin(), outputs.end());
444 498
445 // Build line to compile the file. 499 // Build line to compile the file.
446 WriteCompilerBuildLine(target_->config_values().precompiled_source(), 500 WriteCompilerBuildLine(target_->config_values().precompiled_source(),
447 std::vector<OutputFile>(), order_only_dep, tool_type, 501 std::vector<OutputFile>(), order_only_dep, tool_type,
448 outputs); 502 outputs);
449 503
450 // This build line needs a custom language-specific flags value. It needs to 504 // This build line needs a custom language-specific flags value. Rule-specific
451 // include the switch to generate the .pch file in addition to the normal 505 // variables are just indented underneath the rule line, and this defines the
452 // ones. Rule-specific variables are just indented underneath the rule line, 506 // new one in terms of the old value.
453 // and this defines the new one in terms of the old value.
454 out_ << " " << kSubstitutionNinjaNames[flag_type] << " ="; 507 out_ << " " << kSubstitutionNinjaNames[flag_type] << " =";
455 out_ << " ${" << kSubstitutionNinjaNames[flag_type] << "}"; 508 out_ << " ${" << kSubstitutionNinjaNames[flag_type] << "}";
456 509
457 // Append the command to generate the .pch file. 510 switch (header_type) {
458 out_ << " /Yc" << target_->config_values().precompiled_header(); 511 case Tool::PCH_MSVC:
512 // Append the command to generate the .pch file.
513 out_ << " /Yc" << target_->config_values().precompiled_header();
514 break;
515 case Tool::PCH_GCC:
516 // Append the command to specify the language of the .gch file.
517 out_ << " -x " << GetPCHLangForToolType(tool_type);
518 break;
519 case Tool::PCH_NONE:
520 NOTREACHED() << "Cannot write a PCH command with no PCH header type";
521 break;
522 }
459 523
460 // Write two blank lines to help separate the PCH build lines from the 524 // Write two blank lines to help separate the PCH build lines from the
461 // regular source build lines. 525 // regular source build lines.
462 out_ << std::endl << std::endl; 526 out_ << std::endl << std::endl;
463 } 527 }
464 528
465 void NinjaBinaryTargetWriter::WriteSources( 529 void NinjaBinaryTargetWriter::WriteSources(
466 const std::vector<OutputFile>& extra_deps, 530 const std::vector<OutputFile>& extra_deps,
467 const OutputFile& order_only_dep, 531 const OutputFile& order_only_dep,
468 std::vector<OutputFile>* object_files, 532 std::vector<OutputFile>* object_files,
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 for (const auto& non_linkable_dep : non_linkable_deps) { 845 for (const auto& non_linkable_dep : non_linkable_deps) {
782 out_ << " "; 846 out_ << " ";
783 path_output_.WriteFile(out_, non_linkable_dep->dependency_output_file()); 847 path_output_.WriteFile(out_, non_linkable_dep->dependency_output_file());
784 } 848 }
785 } 849 }
786 } 850 }
787 851
788 OutputFile NinjaBinaryTargetWriter::GetWindowsPCHFile( 852 OutputFile NinjaBinaryTargetWriter::GetWindowsPCHFile(
789 Toolchain::ToolType tool_type) const { 853 Toolchain::ToolType tool_type) const {
790 // Use "obj/{dir}/{target_name}_{lang}.pch" which ends up 854 // Use "obj/{dir}/{target_name}_{lang}.pch" which ends up
791 // looking like "obj/chrome/browser/browser.cc.pch" 855 // looking like "obj/chrome/browser/browser_cc.pch"
792 OutputFile ret = GetTargetOutputDirAsOutputFile(target_); 856 OutputFile ret = GetTargetOutputDirAsOutputFile(target_);
793 ret.value().append(target_->label().name()); 857 ret.value().append(target_->label().name());
794 ret.value().push_back('_'); 858 ret.value().push_back('_');
795 ret.value().append(GetPCHLangForToolType(tool_type)); 859 ret.value().append(GetPCHSuffixForToolType(tool_type));
796 ret.value().append(".pch"); 860 ret.value().append(".pch");
797 861
798 return ret; 862 return ret;
799 } 863 }
800 864
801 bool NinjaBinaryTargetWriter::CheckForDuplicateObjectFiles( 865 bool NinjaBinaryTargetWriter::CheckForDuplicateObjectFiles(
802 const std::vector<OutputFile>& files) const { 866 const std::vector<OutputFile>& files) const {
803 base::hash_set<std::string> set; 867 base::hash_set<std::string> set;
804 for (const auto& file : files) { 868 for (const auto& file : files) {
805 if (!set.insert(file.value()).second) { 869 if (!set.insert(file.value()).second) {
(...skipping 11 matching lines...) Expand all
817 "\n" 881 "\n"
818 "In the latter case, either rename one of the files or move one of\n" 882 "In the latter case, either rename one of the files or move one of\n"
819 "the sources to a separate source_set to avoid them both being in\n" 883 "the sources to a separate source_set to avoid them both being in\n"
820 "the same target."); 884 "the same target.");
821 g_scheduler->FailWithError(err); 885 g_scheduler->FailWithError(err);
822 return false; 886 return false;
823 } 887 }
824 } 888 }
825 return true; 889 return true;
826 } 890 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_binary_target_writer.h ('k') | tools/gn/ninja_binary_target_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698