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 #ifndef TOOLS_GN_NINJA_BUILD_WRITER_H_ 6 #define TOOLS_GN_NINJA_BUILD_WRITER_H_ 7 8 #include <iosfwd> 9 #include <map> 10 #include <string_view> 11 #include <unordered_map> 12 #include <vector> 13 14 #include "gn/path_output.h" 15 16 class Builder; 17 class BuildSettings; 18 class Err; 19 class Settings; 20 class Target; 21 class Toolchain; 22 23 namespace base { 24 class CommandLine; 25 } // namespace base 26 27 // Generates the toplevel "build.ninja" file. This references the individual 28 // toolchain files and lists all input .gn files as dependencies of the 29 // build itself. 30 class NinjaBuildWriter { 31 public: 32 NinjaBuildWriter(const BuildSettings* settings, 33 const std::unordered_map<const Settings*, const Toolchain*>& 34 used_toolchains, 35 const std::vector<const Target*>& all_targets, 36 const Toolchain* default_toolchain, 37 const std::vector<const Target*>& default_toolchain_targets, 38 std::ostream& out, 39 std::ostream& dep_out); 40 ~NinjaBuildWriter(); 41 42 // The design of this class is that this static factory function takes the 43 // Builder, extracts the relevant information, and passes it to the class 44 // constructor. The class itself doesn't depend on the Builder at all which 45 // makes testing much easier (tests integrating various functions along with 46 // the Builder get very complicated). 47 static bool RunAndWriteFile(const BuildSettings* settings, 48 const Builder& builder, 49 Err* err); 50 51 // Extracts from an existing build.ninja file's contents the commands 52 // necessary to run GN and regenerate build.ninja. 53 // 54 // The regeneration rules live at the top of the build.ninja file and their 55 // specific contents are an internal detail of NinjaBuildWriter. Used by 56 // commands::PrepareForRegeneration. 57 // 58 // On error, returns an empty string. 59 static std::string ExtractRegenerationCommands(std::istream& build_ninja_in); 60 61 bool Run(Err* err); 62 63 private: 64 // WriteNinjaRules writes the rules that ninja uses to regenerate its own 65 // build files, used whenever a build input file has changed. 66 // 67 // Ninja file regeneration is accomplished by two separate build statements. 68 // This is necessary to work around ninja's behavior of deleting all output 69 // files of a build edge if the edge uses a depfile and is interrupted before 70 // it can complete. Previously, interrupting regeneration would cause ninja to 71 // delete build.ninja, losing any flags/build settings passed to gen 72 // previously and requiring the user to manually 'gen' again. 73 // 74 // The workaround involves misleading ninja about when the build.ninja file is 75 // actually written. The first build statement runs the actual 'gen 76 // --regeneration' command, writing "build.ninja" (and .d and .stamp) and 77 // lists the "build.ninja.d" depfile to automatically trigger regeneration as 78 // needed, but does not list "build.ninja" as an output. The second 79 // statement's stated output is "build.ninja", but it simply uses the phony 80 // rule to refer to the first statement. 81 void WriteNinjaRules(); 82 void WriteAllPools(); 83 bool WriteSubninjas(Err* err); 84 bool WritePhonyAndAllRules(Err* err); 85 86 void WritePhonyRule(const Target* target, std::string_view phony_name); 87 88 const BuildSettings* build_settings_; 89 90 const std::unordered_map<const Settings*, const Toolchain*>& used_toolchains_; 91 const std::vector<const Target*>& all_targets_; 92 const Toolchain* default_toolchain_; 93 const std::vector<const Target*>& default_toolchain_targets_; 94 95 std::ostream& out_; 96 std::ostream& dep_out_; 97 PathOutput path_output_; 98 99 NinjaBuildWriter(const NinjaBuildWriter&) = delete; 100 NinjaBuildWriter& operator=(const NinjaBuildWriter&) = delete; 101 }; 102 103 extern const char kNinjaRules_Help[]; 104 105 // Exposed for testing. 106 base::CommandLine GetSelfInvocationCommandLine( 107 const BuildSettings* build_settings); 108 109 #endif // TOOLS_GN_NINJA_BUILD_WRITER_H_ 110