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_build_writer.h" 6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <fstream> 8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <map> 9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/command_line.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/path_service.h" 13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/process/process_handle.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/string_util.h" 15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/utf_string_conversions.h" 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "build/build_config.h" 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/build_settings.h" 183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "tools/gn/escape.h" 19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/filesystem_utils.h" 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/input_file_manager.h" 2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "tools/gn/ninja_utils.h" 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h" 23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target.h" 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/trace.h" 25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <windows.h> 28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace { 31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string GetSelfInvocationCommand(const BuildSettings* build_settings) { 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath executable; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PathService::Get(base::FILE_EXE, &executable); 35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CommandLine cmdline(executable.NormalizePathSeparatorsTo('/')); 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cmdline.AppendArg("gen"); 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cmdline.AppendArg(build_settings->build_dir().value()); 39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch cmdline.AppendSwitchPath("--root", build_settings->root_path()); 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cmdline.AppendSwitch("-q"); // Don't write output. 41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) EscapeOptions escape_shell; 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) escape_shell.mode = ESCAPE_NINJA_COMMAND; 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#if defined(OS_WIN) 451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The command line code quoting varies by platform. We have one string, 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // possibly with spaces, that we want to quote. The Windows command line 471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // quotes again, so we don't want quoting. The Posix one doesn't. 481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) escape_shell.inhibit_quoting = true; 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const CommandLine& our_cmdline = *CommandLine::ForCurrentProcess(); 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const CommandLine::SwitchMap& switches = our_cmdline.GetSwitches(); 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (CommandLine::SwitchMap::const_iterator i = switches.begin(); 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) i != switches.end(); ++i) { 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Only write arguments we haven't already written. Always skip "args" 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // since those will have been written to the file and will be used 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // implicitly in the future. Keeping --args would mean changes to the file 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // would be ignored. 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (i->first != "q" && i->first != "root" && i->first != "args") { 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string escaped_value = 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) EscapeString(FilePathToUTF8(i->second), escape_shell, NULL); 628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) cmdline.AppendSwitchASCII(i->first, escaped_value); 638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::WideToUTF8(cmdline.GetCommandLineString()); 68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#else 69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return cmdline.GetCommandLineString(); 70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} // namespace 74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 75d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaBuildWriter::NinjaBuildWriter( 76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const BuildSettings* build_settings, 77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::vector<const Settings*>& all_settings, 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Toolchain* default_toolchain, 79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::vector<const Target*>& default_toolchain_targets, 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::ostream& out, 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::ostream& dep_out) 82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch : build_settings_(build_settings), 83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch all_settings_(all_settings), 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default_toolchain_(default_toolchain), 85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default_toolchain_targets_(default_toolchain_targets), 86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_(out), 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dep_out_(dep_out), 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) path_output_(build_settings->build_dir(), ESCAPE_NINJA) { 89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 91d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaBuildWriter::~NinjaBuildWriter() { 92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaBuildWriter::Run() { 95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteNinjaRules(); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WriteLinkPool(); 97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WriteSubninjas(); 98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch WritePhonyAndAllRules(); 99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static 102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool NinjaBuildWriter::RunAndWriteFile( 103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const BuildSettings* build_settings, 104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::vector<const Settings*>& all_settings, 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Toolchain* default_toolchain, 106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::vector<const Target*>& default_toolchain_targets) { 10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, "build.ninja"); 10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::FilePath ninja_file(build_settings->GetFullPath( 110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch SourceFile(build_settings->build_dir().value() + "build.ninja"))); 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CreateDirectory(ninja_file.DirName()); 112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::ofstream file; 114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch file.open(FilePathToUTF8(ninja_file).c_str(), 115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::ios_base::out | std::ios_base::binary); 116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (file.fail()) 117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return false; 118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::ofstream depfile; 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) depfile.open((FilePathToUTF8(ninja_file) + ".d").c_str(), 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::ios_base::out | std::ios_base::binary); 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (depfile.fail()) 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NinjaBuildWriter gen(build_settings, all_settings, default_toolchain, 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) default_toolchain_targets, file, depfile); 127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch gen.Run(); 128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return true; 129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaBuildWriter::WriteNinjaRules() { 132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "rule gn\n"; 133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << " command = " << GetSelfInvocationCommand(build_settings_) << "\n"; 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) out_ << " description = Regenerating ninja files\n\n"; 135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // This rule will regenerate the ninja files when any input file has changed. 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) out_ << "build build.ninja: gn\n" 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " generator = 1\n" 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << " depfile = build.ninja.d\n"; 140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Input build files. These go in the ".d" file. If we write them as 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // dependencies in the .ninja file itself, ninja will expect the files to 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // exist and will error if they don't. When files are listed in a depfile, 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // missing files are ignored. 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dep_out_ << "build.ninja:"; 1463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::vector<base::FilePath> input_files; 1473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch g_scheduler->input_file_manager()->GetAllPhysicalInputFileNames(&input_files); 1483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch for (size_t i = 0; i < input_files.size(); i++) 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dep_out_ << " " << FilePathToUTF8(input_files[i]); 150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Other files read by the build. 1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<base::FilePath> other_files = g_scheduler->GetGenDependencies(); 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0; i < other_files.size(); i++) 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dep_out_ << " " << FilePathToUTF8(other_files[i]); 155d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) out_ << std::endl; 157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid NinjaBuildWriter::WriteLinkPool() { 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci out_ << "pool link_pool\n" 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << " depth = " << default_toolchain_->concurrent_links() << std::endl 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << std::endl; 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaBuildWriter::WriteSubninjas() { 166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < all_settings_.size(); i++) { 167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "subninja "; 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) path_output_.WriteFile(out_, GetNinjaFileForToolchain(all_settings_[i])); 169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << std::endl; 172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaBuildWriter::WritePhonyAndAllRules() { 175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string all_rules; 176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Write phony rules for all uniquely-named targets in the default toolchain. 178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Don't do other toolchains or we'll get naming conflicts, and if the name 1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // isn't unique, also skip it. The exception is for the toplevel targets 1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // which we also find. 181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch std::map<std::string, int> small_name_count; 1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<const Target*> toplevel_targets; 183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { 184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Target* target = default_toolchain_targets_[i]; 1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Label& label = target->label(); 1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu small_name_count[label.name()]++; 1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Look for targets with a name of the form 1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // dir = "//foo/", name = "foo" 1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // i.e. where the target name matches the top level directory. We will 1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // always write phony rules for these even if there is another target with 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // the same short name. 1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const std::string& dir_string = label.dir().value(); 1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (dir_string.size() == label.name().size() + 3 && // Size matches. 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir_string[0] == '/' && dir_string[1] == '/' && // "//" at beginning. 1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir_string[dir_string.size() - 1] == '/' && // "/" at end. 1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu dir_string.compare(2, label.name().size(), label.name()) == 0) 1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu toplevel_targets.push_back(target); 1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { 2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Target* target = default_toolchain_targets_[i]; 2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Label& label = target->label(); 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OutputFile target_file(target->dependency_output_file()); 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The output files may have leading "./" so normalize those away. 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NormalizePath(&target_file.value()); 2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Write the long name "foo/bar:baz" for the target "//foo/bar:baz". 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string long_name = label.GetUserVisibleName(false); 2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TrimString(long_name, "/", &long_name); 2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WritePhonyRule(target, target_file, long_name); 2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Write the directory name with no target name if they match 2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // (e.g. "//foo/bar:bar" -> "foo/bar"). 2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (FindLastDirComponent(label.dir()) == label.name()) { 2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string medium_name = DirectoryWithNoLastSlash(label.dir()); 2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TrimString(medium_name, "/", &medium_name); 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // That may have generated a name the same as the short name of the 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // target which we already wrote. 2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (medium_name != label.name()) 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WritePhonyRule(target, target_file, medium_name); 222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Write short names for ones which are unique. 2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (small_name_count[label.name()] == 1) 2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WritePhonyRule(target, target_file, label.name()); 2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!all_rules.empty()) 229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch all_rules.append(" $\n "); 230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch all_rules.append(target_file.value()); 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Pick up phony rules for the toplevel targets with non-unique names (which 2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // would have been skipped in the above loop). 2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (size_t i = 0; i < toplevel_targets.size(); i++) { 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (small_name_count[toplevel_targets[i]->label().name()] > 1) { 2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Target* target = toplevel_targets[i]; 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) WritePhonyRule(target, target->dependency_output_file(), 2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu target->label().name()); 2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!all_rules.empty()) { 244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "\nbuild all: phony " << all_rules << std::endl; 245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch out_ << "default all" << std::endl; 246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid NinjaBuildWriter::WritePhonyRule(const Target* target, 2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const OutputFile& target_file, 2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const std::string& phony_name) { 2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (target_file.value() == phony_name) 2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; // No need for a phony rule. 2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EscapeOptions ninja_escape; 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ninja_escape.mode = ESCAPE_NINJA; 2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Escape for special chars Ninja will handle. 2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::string escaped = EscapeString(phony_name, ninja_escape, NULL); 2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu out_ << "build " << escaped << ": phony "; 2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu path_output_.WriteFile(out_, target_file); 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu out_ << std::endl; 2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 265