ninja_target_writer.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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/ninja_binary_target_writer.h" 13#include "tools/gn/ninja_copy_target_writer.h" 14#include "tools/gn/ninja_group_target_writer.h" 15#include "tools/gn/ninja_script_target_writer.h" 16#include "tools/gn/scheduler.h" 17#include "tools/gn/target.h" 18 19NinjaTargetWriter::NinjaTargetWriter(const Target* target, std::ostream& out) 20 : settings_(target->settings()), 21 target_(target), 22 out_(out), 23 path_output_(settings_->build_settings()->build_dir(), 24 ESCAPE_NINJA, true), 25 helper_(settings_->build_settings()) { 26} 27 28NinjaTargetWriter::~NinjaTargetWriter() { 29} 30 31// static 32void NinjaTargetWriter::RunAndWriteFile(const Target* target) { 33 // External targets don't get written to disk, we assume they're managed by 34 // an external program. If we're not using an external generator, this is 35 // ignored. 36 if (target->settings()->build_settings()->using_external_generator() && 37 target->external()) 38 return; 39 40 const Settings* settings = target->settings(); 41 NinjaHelper helper(settings->build_settings()); 42 43 base::FilePath ninja_file(settings->build_settings()->GetFullPath( 44 helper.GetNinjaFileForTarget(target).GetSourceFile( 45 settings->build_settings()))); 46 47 if (g_scheduler->verbose_logging()) 48 g_scheduler->Log("Writing", FilePathToUTF8(ninja_file)); 49 50 file_util::CreateDirectory(ninja_file.DirName()); 51 52 // It's rediculously faster to write to a string and then write that to 53 // disk in one operation than to use an fstream here. 54 std::stringstream file; 55 if (file.fail()) { 56 g_scheduler->FailWithError( 57 Err(Location(), "Error writing ninja file.", 58 "Unable to open \"" + FilePathToUTF8(ninja_file) + "\"\n" 59 "for writing.")); 60 return; 61 } 62 63 // Call out to the correct sub-type of writer. 64 if (target->output_type() == Target::COPY_FILES) { 65 NinjaCopyTargetWriter writer(target, file); 66 writer.Run(); 67 } else if (target->output_type() == Target::CUSTOM) { 68 NinjaScriptTargetWriter writer(target, file); 69 writer.Run(); 70 } else if (target->output_type() == Target::GROUP) { 71 NinjaGroupTargetWriter writer(target, file); 72 writer.Run(); 73 } else if (target->output_type() == Target::EXECUTABLE || 74 target->output_type() == Target::STATIC_LIBRARY || 75 target->output_type() == Target::SHARED_LIBRARY) { 76 NinjaBinaryTargetWriter writer(target, file); 77 writer.Run(); 78 } else { 79 CHECK(0); 80 } 81 82 std::string contents = file.str(); 83 file_util::WriteFile(ninja_file, contents.c_str(), contents.size()); 84} 85 86void NinjaTargetWriter::WriteEnvironment() { 87 // TODO(brettw) have a better way to do the environment setup on Windows. 88 if (target_->settings()->IsWin()) 89 out_ << "arch = environment.x86\n"; 90} 91 92const Toolchain* NinjaTargetWriter::GetToolchain() const { 93 return target_->settings()->toolchain(); 94} 95 96std::string NinjaTargetWriter::GetSourcesImplicitDeps() const { 97 std::ostringstream ret; 98 ret << " |"; 99 100 // Input files are order-only deps. 101 const Target::FileList& prereqs = target_->source_prereqs(); 102 bool has_files = !prereqs.empty(); 103 for (size_t i = 0; i < prereqs.size(); i++) { 104 ret << " "; 105 path_output_.WriteFile(ret, prereqs[i]); 106 } 107 108 // Add on any direct deps marked as "hard". 109 const std::vector<const Target*>& deps = target_->deps(); 110 for (size_t i = 0; i < deps.size(); i++) { 111 if (deps[i]->hard_dep()) { 112 has_files = true; 113 ret << " "; 114 path_output_.WriteFile(ret, helper_.GetTargetOutputFile(deps[i])); 115 } 116 } 117 118 if (has_files) 119 return ret.str(); 120 return std::string(); // No files added. 121} 122