ninja_target_writer.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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 "tools/gn/err.h" 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_binary_target_writer.h" 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_copy_target_writer.h" 143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_group_target_writer.h" 153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_script_target_writer.h" 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h" 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target.h" 18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 19d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::NinjaTargetWriter(const Target* target, std::ostream& out) 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch : settings_(target->settings()), 21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch target_(target), 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_(out), 23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path_output_(settings_->build_settings()->build_dir(), 24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ESCAPE_NINJA, true), 25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch helper_(settings_->build_settings()) { 26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 28d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::~NinjaTargetWriter() { 29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static 32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::RunAndWriteFile(const Target* target) { 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // External targets don't get written to disk, we assume they're managed by 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // an external program. If we're not using an external generator, this is 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // ignored. 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (target->settings()->build_settings()->using_external_generator() && 37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) target->external()) 38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Settings* settings = target->settings(); 41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NinjaHelper helper(settings->build_settings()); 42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::FilePath ninja_file(settings->build_settings()->GetFullPath( 44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch helper.GetNinjaFileForTarget(target).GetSourceFile( 45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch settings->build_settings()))); 46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (g_scheduler->verbose_logging()) 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) g_scheduler->Log("Writing", FilePathToUTF8(ninja_file)); 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch file_util::CreateDirectory(ninja_file.DirName()); 51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // It's rediculously faster to write to a string and then write that to 53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // disk in one operation than to use an fstream here. 54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::stringstream file; 55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (file.fail()) { 56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch g_scheduler->FailWithError( 57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err(Location(), "Error writing ninja file.", 58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "Unable to open \"" + FilePathToUTF8(ninja_file) + "\"\n" 59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "for writing.")); 60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return; 61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Call out to the correct sub-type of writer. 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (target->output_type() == Target::COPY_FILES) { 653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NinjaCopyTargetWriter writer(target, file); 663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) writer.Run(); 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (target->output_type() == Target::CUSTOM) { 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NinjaScriptTargetWriter writer(target, file); 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) writer.Run(); 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (target->output_type() == Target::GROUP) { 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NinjaGroupTargetWriter writer(target, file); 723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) writer.Run(); 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (target->output_type() == Target::EXECUTABLE || 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) target->output_type() == Target::STATIC_LIBRARY || 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) target->output_type() == Target::SHARED_LIBRARY) { 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NinjaBinaryTargetWriter writer(target, file); 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) writer.Run(); 78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CHECK(0); 80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string contents = file.str(); 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) file_util::WriteFile(ninja_file, contents.c_str(), contents.size()); 84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void NinjaTargetWriter::WriteEnvironment() { 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(brettw) have a better way to do the environment setup on Windows. 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (target_->settings()->IsWin()) 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) out_ << "arch = environment.x86\n"; 90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const Toolchain* NinjaTargetWriter::GetToolchain() const { 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return target_->settings()->toolchain(); 94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string NinjaTargetWriter::GetSourcesImplicitDeps() const { 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::ostringstream ret; 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ret << " |"; 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Input files are order-only deps. 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const Target::FileList& prereqs = target_->source_prereqs(); 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool has_files = !prereqs.empty(); 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (size_t i = 0; i < prereqs.size(); i++) { 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ret << " "; 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) path_output_.WriteFile(ret, prereqs[i]); 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Add on any direct deps marked as "hard". 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<const Target*>& deps = target_->deps(); 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (size_t i = 0; i < deps.size(); i++) { 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (deps[i]->hard_dep()) { 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) has_files = true; 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ret << " "; 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) path_output_.WriteFile(ret, helper_.GetTargetOutputFile(deps[i])); 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (has_files) 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return ret.str(); 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return std::string(); // No files added. 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 122