ninja_target_writer.cc revision d3868032626d59662ff73b372b5d584c1d144c53
1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file. 4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/ninja_target_writer.h" 6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <fstream> 8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <sstream> 9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/file_util.h" 11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/logging.h" 12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/string_util.h" 13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config_values_extractors.h" 14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h" 15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/escape.h" 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/file_template.h" 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/location.h" 18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/path_output.h" 19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h" 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/string_utils.h" 21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target.h" 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace { 24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstatic const char kCustomTargetSourceKey[] = "{{source}}"; 26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstatic const char kCustomTargetSourceNamePartKey[] = "{{source_name_part}}"; 27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstruct DefineWriter { 29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch void operator()(const std::string& s, std::ostream& out) const { 30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out << " -D" << s; 31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstruct IncludeWriter { 35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch IncludeWriter(PathOutput& path_output, 36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const NinjaHelper& h) 37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch : helper(h), 38d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_(path_output), 39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch old_inhibit_quoting_(path_output.inhibit_quoting()) { 40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Inhibit quoting since we'll put quotes around the whole thing ourselves. 41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Since we're writing in NINJA escaping mode, this won't actually do 42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // anything, but I think we may need to change to shell-and-then-ninja 43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // escaping for this in the future. 44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.set_inhibit_quoting(true); 45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ~IncludeWriter() { 47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.set_inhibit_quoting(old_inhibit_quoting_); 48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch void operator()(const SourceDir& d, std::ostream& out) const { 51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out << " \"-I"; 52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // It's important not to include the trailing slash on directories or on 53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Windows it will be a backslash and the compiler might think we're 54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // escaping the quote! 55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteDir(out, d, PathOutput::DIR_NO_LAST_SLASH); 56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out << "\""; 57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const NinjaHelper& helper; 60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch PathOutput& path_output_; 61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bool old_inhibit_quoting_; // So we can put the PathOutput back. 62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} // namespace 65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 66d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::NinjaTargetWriter(const Target* target, std::ostream& out) 67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch : settings_(target->settings()), 68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch target_(target), 69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_(out), 70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_(settings_->build_settings()->build_dir(), 71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ESCAPE_NINJA, true), 72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch helper_(settings_->build_settings()) { 73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 75d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::~NinjaTargetWriter() { 76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::Run() { 79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "arch = environment.x86\n"; 80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target_->output_type() == Target::COPY_FILES) { 82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteCopyRules(); 83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else if (target_->output_type() == Target::CUSTOM) { 84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteCustomRules(); 85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteCompilerVars(); 87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 88d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::vector<OutputFile> obj_files; 89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteSources(&obj_files); 90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteLinkerStuff(obj_files); 92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static 96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::RunAndWriteFile(const Target* target) { 97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target->output_type() == Target::NONE) 98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return; 99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Settings* settings = target->settings(); 101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NinjaHelper helper(settings->build_settings()); 102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::FilePath ninja_file(settings->build_settings()->GetFullPath( 104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch helper.GetNinjaFileForTarget(target).GetSourceFile( 105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch settings->build_settings()))); 106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch file_util::CreateDirectory(ninja_file.DirName()); 108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // It's rediculously faster to write to a string and then write that to 110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // disk in one operation than to use an fstream here. 111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::stringstream file; 112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (file.fail()) { 113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch g_scheduler->FailWithError( 114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err(Location(), "Error writing ninja file.", 115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "Unable to open \"" + FilePathToUTF8(ninja_file) + "\"\n" 116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "for writing.")); 117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return; 118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 120d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NinjaTargetWriter gen(target, file); 121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch gen.Run(); 122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string contents = file.str(); 124d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch file_util::WriteFile(ninja_file, contents.c_str(), contents.size()); 125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::WriteCopyRules() { 128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The dest dir should be inside the output dir so we can just remove the 129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // prefix and get ninja-relative paths. 130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& output_dir = 131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch settings_->build_settings()->build_dir().value(); 132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& dest_dir = target_->destdir().value(); 133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(StartsWithASCII(dest_dir, output_dir, true)); 134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string relative_dest_dir(&dest_dir[output_dir.size()], 135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_dir.size() - output_dir.size()); 136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Target::FileList& sources = target_->sources(); 138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::vector<OutputFile> dest_files; 139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_files.reserve(sources.size()); 140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Write out rules for each file copied. 142d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < sources.size(); i++) { 143d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const SourceFile& input_file = sources[i]; 144d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The files should have the same name but in the dest dir. 146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::StringPiece name_part = FindFilename(&input_file.value()); 147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch OutputFile dest_file(relative_dest_dir); 148d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch AppendStringPiece(&dest_file.value(), name_part); 149d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_files.push_back(dest_file); 151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "build "; 153d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, dest_file); 154d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << ": copy "; 155d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, input_file); 156d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 159d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Write out the rule for the target to copy all of them. 160d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl << "build "; 161d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); 162d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << ": stamp"; 163d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < dest_files.size(); i++) { 164d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, dest_files[i]); 166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) need some kind of stamp file for depending on this, as well 170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // as order_only=prebuild. 171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::WriteCustomRules() { 174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Make a unique name for this rule. 175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string target_label = target_->label().GetUserVisibleName(true); 176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string custom_rule_name(target_label); 177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name); 178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch custom_rule_name.append("_rule"); 179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Run the script from the dir of the BUILD file. This has no trailing 181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // slash. 182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const SourceDir& script_cd = target_->label().dir(); 183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string script_cd_to_root = InvertDir(script_cd); 184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (script_cd_to_root.empty()) { 185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch script_cd_to_root = "."; 186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Remove trailing slash 188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(script_cd_to_root[script_cd_to_root.size() - 1] == '/'); 189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch script_cd_to_root.resize(script_cd_to_root.size() - 1); 190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string script_relative_to_cd = 193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch script_cd_to_root + target_->script().value(); 194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bool no_sources = target_->sources().empty(); 196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Use a unique name for the response file when there are multiple build 198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // steps so that they don't stomp on each other. 199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string rspfile = custom_rule_name; 200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!no_sources) 201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch rspfile += ".$unique_name"; 202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch rspfile += ".rsp"; 203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // First write the custom rule. 205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "rule " << custom_rule_name << std::endl; 206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " command = $pythonpath gyp-win-tool action-wrapper $arch " 207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch << rspfile << " "; 208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteDir(out_, script_cd, PathOutput::DIR_NO_LAST_SLASH); 209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " description = CUSTOM " << target_label << std::endl; 211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " restat = 1" << std::endl; 212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " rspfile = " << rspfile << std::endl; 213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The build command goes in the rsp file. 215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " rspfile_content = $pythonpath " << script_relative_to_cd; 216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < target_->script_args().size(); i++) { 217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& arg = target_->script_args()[i]; 218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteCustomArg(arg); 220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl << std::endl; 222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Precompute the common dependencies for each step. This includes the 224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // script itself (changing the script should force a rebuild) and any data 225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // files. 226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::ostringstream common_deps_stream; 227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(common_deps_stream, target_->script()); 228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Target::FileList& datas = target_->data(); 229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < datas.size(); i++) { 230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch common_deps_stream << " "; 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(common_deps_stream, datas[i]); 232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& common_deps = common_deps_stream.str(); 234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Collects all output files for writing below. 236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::vector<OutputFile> output_files; 237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 238d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (no_sources) { 239d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // No sources, write a rule that invokes the script once with the 240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // outputs as outputs, and the data as inputs. 241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "build"; 242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Target::FileList& outputs = target_->outputs(); 243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < outputs.size(); i++) { 244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch OutputFile output_path( 245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RemovePrefix(outputs[i].value(), 246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch settings_->build_settings()->build_dir().value())); 247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch output_files.push_back(output_path); 248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, output_path); 250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << ": " << custom_rule_name << " " << common_deps << std::endl; 252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Write separate rules for each input source file. 254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteCustomSourceRules(custom_rule_name, common_deps, script_cd, 255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch script_cd_to_root, &output_files); 256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Last write a stamp rule to collect all outputs. 260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "build "; 261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); 262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << ": stamp"; 263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < output_files.size(); i++) { 264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, output_files[i]); 266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::WriteCustomArg(const std::string& arg) { 271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This can be optimized if it's called a lot. 272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch EscapeOptions options; 273d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch options.mode = ESCAPE_NINJA; 274d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string output_str = EscapeString(arg, options); 275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Do this substitution after escaping our our $ will be escaped (which we 277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // don't want). 278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSource, 279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "${source}"); 280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSourceNamePart, 281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "${source_name_part}"); 282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << output_str; 283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 284d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::WriteCustomSourceRules( 286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& custom_rule_name, 287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& common_deps, 288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const SourceDir& script_cd, 289d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& script_cd_to_root, 290d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::vector<OutputFile>* output_files) { 291d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Construct the template for generating the output files from each source. 292d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Target::FileList& outputs = target_->outputs(); 293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::vector<std::string> output_template_args; 294d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < outputs.size(); i++) { 295d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // All outputs should be in the output dir. 296d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch output_template_args.push_back( 297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RemovePrefix(outputs[i].value(), 298d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch settings_->build_settings()->build_dir().value())); 299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 300d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch FileTemplate output_template(output_template_args); 301d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 302d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Prevent re-allocating each time by initializing outside the loop. 303d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::vector<std::string> output_template_result; 304d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 305d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Path output formatter for wrigin source paths passed to the script. 306d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch PathOutput script_source_path_output(script_cd, ESCAPE_SHELL, true); 307d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 308d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Target::FileList& sources = target_->sources(); 309d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < sources.size(); i++) { 310d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Write outputs for this source file computed by the template. 311d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "build"; 312d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch output_template.ApplyString(sources[i].value(), &output_template_result); 313d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t out_i = 0; out_i < output_template_result.size(); out_i++) { 314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch OutputFile output_path(output_template_result[out_i]); 315d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch output_files->push_back(output_path); 316d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 317d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, output_path); 318d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 319d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 320d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << ": " << custom_rule_name 321d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch << " " << common_deps 322d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch << " "; 323d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, sources[i]); 324d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 325d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 326d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " unique_name = " << i << std::endl; 327d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 328d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The source file here should be relative to the script directory since 329d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // this is the variable passed to the script. Here we slightly abuse the 330d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // OutputFile object by putting a non-output-relative path in it to signal 331d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // that the PathWriter should not prepend directories. 332d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " source = "; 333d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch script_source_path_output.WriteFile(out_, sources[i]); 334d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 335d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " source_name_part = " 337d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch << FindFilenameNoExtension(&sources[i].value()).as_string() 338d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch << std::endl; 339d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 340d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 341d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 342d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::WriteCompilerVars() { 343d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Defines. 344d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "defines ="; 345d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RecursiveTargetConfigToStream(target_, &ConfigValues::defines, 346d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DefineWriter(), out_); 347d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 348d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 349d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Includes. 350d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "includes ="; 351d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RecursiveTargetConfigToStream(target_, &ConfigValues::includes, 352d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch IncludeWriter(path_output_, helper_), out_); 353d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 354d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 355d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 356d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // C flags and friends. 357d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "cflags ="; 358d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RecursiveTargetConfigStringsToStream(target_, &ConfigValues::cflags, out_); 359d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 360d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "cflags_c ="; 361d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RecursiveTargetConfigStringsToStream(target_, &ConfigValues::cflags_c, out_); 362d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 363d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "cflags_cc ="; 364d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RecursiveTargetConfigStringsToStream(target_, &ConfigValues::cflags_cc, out_); 365d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 366d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 367d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 368d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 369d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 370d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::WriteSources( 371d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::vector<OutputFile>* object_files) { 372d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Target::FileList& sources = target_->sources(); 373d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch object_files->reserve(sources.size()); 374d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 375d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < sources.size(); i++) { 376d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const SourceFile& input_file = sources[i]; 377d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 378d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch SourceFileType input_file_type = GetSourceFileType(input_file, 379d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch settings_->target_os()); 380d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (input_file_type == SOURCE_UNKNOWN) 381d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch continue; // Skip unknown file types. 382d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const char* command = GetCommandForSourceType(input_file_type); 383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!command) 384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch continue; // Skip files not needing compilation. 385d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 386d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch OutputFile output_file = helper_.GetOutputFileForSource( 387d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch target_, input_file, input_file_type); 388d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch object_files->push_back(output_file); 389d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 390d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "build "; 391d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, output_file); 392d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << ": " << command << " "; 393d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, input_file); 394d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 395d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 396d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 397d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 398d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 399d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::WriteLinkerStuff( 400d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::vector<OutputFile>& object_files) { 401d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Manifest file on Windows. 402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) this seems not to be necessary for static libs, skip in 403d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // that case? 404d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch OutputFile windows_manifest; 405d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (settings_->IsWin()) { 406d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch windows_manifest.value().assign(helper_.GetTargetOutputDir(target_)); 407d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch windows_manifest.value().append(target_->label().name()); 408d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch windows_manifest.value().append(".intermediate.manifest"); 409d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "manifests = "; 410d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, windows_manifest); 411d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 412d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 413d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 414d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Linker flags, append manifest flag on Windows to reference our file. 415d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "ldflags ="; 416d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags, out_); 417d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (settings_->IsWin()) 418d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " /MANIFEST /ManifestFile:"; 419d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, windows_manifest); 420d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch { // HACK ERASEME BRETTW FIXME 421d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " /DEBUG /MACHINE:X86 /LIBPATH:\"C:\\Program Files (x86)\\Windows Kits\\8.0\\Lib\\win8\\um\\x86\" /DELAYLOAD:dbghelp.dll /DELAYLOAD:dwmapi.dll /DELAYLOAD:shell32.dll /DELAYLOAD:uxtheme.dll /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat /SUBSYSTEM:CONSOLE /INCREMENTAL /FIXED:NO /DYNAMICBASE:NO wininet.lib dnsapi.lib version.lib msimg32.lib ws2_32.lib usp10.lib psapi.lib dbghelp.lib winmm.lib shlwapi.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib user32.lib uuid.lib odbc32.lib odbccp32.lib delayimp.lib /NXCOMPAT"; 422d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 423d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 424d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 425d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Libraries to link. 426d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "libs =" << std::endl; 427d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 428d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The external output file is the one that other libs depend on. 429d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch OutputFile external_output_file = helper_.GetTargetOutputFile(target_); 430d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 431d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The internal output file is the "main thing" we think we're making. In 432d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // the case of shared libraries, this is the shared library and the external 433d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // output file is the import library. In other cases, the internal one and 434d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // the external one are the same. 435d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch OutputFile internal_output_file; 436d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target_->output_type() == Target::SHARED_LIBRARY) { 437d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (settings_->IsWin()) { 438d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch internal_output_file = OutputFile(target_->label().name() + ".dll"); 439d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 440d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); // TODO(brettw) write this. 441d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 442d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 443d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch internal_output_file = external_output_file; 444d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 445d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 446d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) should we append data files to this? 447d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 448d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // In Python see "self.ninja.build(output, command, input," 449d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "build "; 450d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, internal_output_file); 451d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (external_output_file != internal_output_file) { 452d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 453d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, external_output_file); 454d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 455d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << ": " << GetCommandForTargetType(); 456d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < object_files.size(); i++) { 457d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 458d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, object_files[i]); 459d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 460d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 461d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target_->output_type() == Target::EXECUTABLE || 462d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch target_->output_type() == Target::SHARED_LIBRARY || 463d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch target_->output_type() == Target::LOADABLE_MODULE) { 464d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::vector<const Target*>& deps = target_->deps(); 465d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::set<const Target*>& inherited = target_->inherited_libraries(); 466d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 467d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Now append linkable libraries to the linker command. 468d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < deps.size(); i++) { 469d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (deps[i]->IsLinkable() && 470d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch inherited.find(deps[i]) == inherited.end()) { 471d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 472d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, 473d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch helper_.GetTargetOutputFile(target_->deps()[i])); 474d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 475d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 476d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (std::set<const Target*>::const_iterator i = inherited.begin(); 477d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch i != inherited.end(); ++i) { 478d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " "; 479d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i)); 480d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 481d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 482d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 483d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 484d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target_->output_type() == Target::SHARED_LIBRARY) { 485d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " soname = "; 486d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, internal_output_file); 487d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 488d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 489d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " lib = "; 490d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, internal_output_file); 491d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 492d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 493d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " dll = "; 494d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, internal_output_file); 495d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 496d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 497d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (settings_->IsWin()) { 498d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " implibflag = /IMPLIB:"; 499d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_.WriteFile(out_, external_output_file); 500d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 501d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 502d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 503d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 504d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) postbuild steps here. 505d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 506d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 507d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 508d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 509d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* NinjaTargetWriter::GetCommandForSourceType( 510d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch SourceFileType type) const { 511d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (type == SOURCE_C) 512d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "cc"; 513d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (type == SOURCE_CC) 514d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "cxx"; 515d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 516d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) asm files. 517d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 518d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (settings_->IsMac()) { 519d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (type == SOURCE_M) 520d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "objc"; 521d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (type == SOURCE_MM) 522d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "objcxx"; 523d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 524d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 525d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (settings_->IsWin()) { 526d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (type == SOURCE_RC) 527d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "rc"; 528d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 529d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 530d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) stuff about "S" files on non-Windows. 531d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return NULL; 532d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 533d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 534d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* NinjaTargetWriter::GetCommandForTargetType() const { 535d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target_->output_type() == Target::NONE) { 536d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 537d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ""; 538d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 539d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 540d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target_->output_type() == Target::STATIC_LIBRARY) { 541d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) stuff about standalong static libraryes on Unix in 542d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // WriteTarget in the Python one, and lots of postbuild steps. 543d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "alink"; 544d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 545d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 546d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (target_->output_type() == Target::SHARED_LIBRARY) 547d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "solink"; 548d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 549d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "link"; 550d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 551