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 3 // found in the LICENSE file. 4 5 #include "tools/gn/ninja_target_writer.h" 6 7 #include <fstream> 8 #include <sstream> 9 10 #include "base/file_util.h" 11 #include "tools/gn/err.h" 12 #include "tools/gn/file_template.h" 13 #include "tools/gn/ninja_binary_target_writer.h" 14 #include "tools/gn/ninja_copy_target_writer.h" 15 #include "tools/gn/ninja_group_target_writer.h" 16 #include "tools/gn/ninja_script_target_writer.h" 17 #include "tools/gn/scheduler.h" 18 #include "tools/gn/string_utils.h" 19 #include "tools/gn/target.h" 20 #include "tools/gn/trace.h" 21 22 NinjaTargetWriter::NinjaTargetWriter(const Target* target, 23 const Toolchain* toolchain, 24 std::ostream& out) 25 : settings_(target->settings()), 26 target_(target), 27 toolchain_(toolchain), 28 out_(out), 29 path_output_(settings_->build_settings()->build_dir(), 30 ESCAPE_NINJA, true), 31 helper_(settings_->build_settings()) { 32 } 33 34 NinjaTargetWriter::~NinjaTargetWriter() { 35 } 36 37 // static 38 void NinjaTargetWriter::RunAndWriteFile(const Target* target, 39 const Toolchain* toolchain) { 40 const Settings* settings = target->settings(); 41 NinjaHelper helper(settings->build_settings()); 42 43 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, 44 target->label().GetUserVisibleName(false)); 45 trace.SetToolchain(settings->toolchain_label()); 46 47 base::FilePath ninja_file(settings->build_settings()->GetFullPath( 48 helper.GetNinjaFileForTarget(target).GetSourceFile( 49 settings->build_settings()))); 50 51 if (g_scheduler->verbose_logging()) 52 g_scheduler->Log("Writing", FilePathToUTF8(ninja_file)); 53 54 base::CreateDirectory(ninja_file.DirName()); 55 56 // It's rediculously faster to write to a string and then write that to 57 // disk in one operation than to use an fstream here. 58 std::stringstream file; 59 60 // Call out to the correct sub-type of writer. 61 if (target->output_type() == Target::COPY_FILES) { 62 NinjaCopyTargetWriter writer(target, toolchain, file); 63 writer.Run(); 64 } else if (target->output_type() == Target::CUSTOM) { 65 NinjaScriptTargetWriter writer(target, toolchain, file); 66 writer.Run(); 67 } else if (target->output_type() == Target::GROUP) { 68 NinjaGroupTargetWriter writer(target, toolchain, file); 69 writer.Run(); 70 } else if (target->output_type() == Target::EXECUTABLE || 71 target->output_type() == Target::STATIC_LIBRARY || 72 target->output_type() == Target::SHARED_LIBRARY || 73 target->output_type() == Target::SOURCE_SET) { 74 NinjaBinaryTargetWriter writer(target, toolchain, file); 75 writer.Run(); 76 } else { 77 CHECK(0); 78 } 79 80 std::string contents = file.str(); 81 file_util::WriteFile(ninja_file, contents.c_str(), 82 static_cast<int>(contents.size())); 83 } 84 85 std::string NinjaTargetWriter::GetSourcesImplicitDeps() const { 86 std::ostringstream ret; 87 ret << " |"; 88 89 // Input files are order-only deps. 90 const Target::FileList& prereqs = target_->source_prereqs(); 91 bool has_files = !prereqs.empty(); 92 for (size_t i = 0; i < prereqs.size(); i++) { 93 ret << " "; 94 path_output_.WriteFile(ret, prereqs[i]); 95 } 96 97 // Add on any direct deps marked as "hard". 98 const LabelTargetVector& deps = target_->deps(); 99 for (size_t i = 0; i < deps.size(); i++) { 100 if (deps[i].ptr->hard_dep()) { 101 has_files = true; 102 ret << " "; 103 path_output_.WriteFile(ret, helper_.GetTargetOutputFile(deps[i].ptr)); 104 } 105 } 106 107 if (has_files) 108 return ret.str(); 109 return std::string(); // No files added. 110 } 111 112 FileTemplate NinjaTargetWriter::GetOutputTemplate() const { 113 const Target::FileList& outputs = target_->script_values().outputs(); 114 std::vector<std::string> output_template_args; 115 for (size_t i = 0; i < outputs.size(); i++) { 116 // All outputs should be in the output dir. 117 output_template_args.push_back( 118 RemovePrefix(outputs[i].value(), 119 settings_->build_settings()->build_dir().value())); 120 } 121 return FileTemplate(output_template_args); 122 } 123