| // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef TOOLS_GN_NINJA_BUILD_WRITER_H_ | |
| #define TOOLS_GN_NINJA_BUILD_WRITER_H_ | |
| #include <iosfwd> | |
| #include <map> | |
| #include <string_view> | |
| #include <unordered_map> | |
| #include <vector> | |
| #include "gn/path_output.h" | |
| class Builder; | |
| class BuildSettings; | |
| class Err; | |
| class Settings; | |
| class Target; | |
| class Toolchain; | |
| namespace base { | |
| class CommandLine; | |
| } // namespace base | |
| // Generates the toplevel "build.ninja" file. This references the individual | |
| // toolchain files and lists all input .gn files as dependencies of the | |
| // build itself. | |
| class NinjaBuildWriter { | |
| public: | |
| NinjaBuildWriter(const BuildSettings* settings, | |
| const std::unordered_map<const Settings*, const Toolchain*>& | |
| used_toolchains, | |
| const std::vector<const Target*>& all_targets, | |
| const Toolchain* default_toolchain, | |
| const std::vector<const Target*>& default_toolchain_targets, | |
| std::ostream& out, | |
| std::ostream& dep_out); | |
| ~NinjaBuildWriter(); | |
| // The design of this class is that this static factory function takes the | |
| // Builder, extracts the relevant information, and passes it to the class | |
| // constructor. The class itself doesn't depend on the Builder at all which | |
| // makes testing much easier (tests integrating various functions along with | |
| // the Builder get very complicated). | |
| static bool RunAndWriteFile(const BuildSettings* settings, | |
| const Builder& builder, | |
| Err* err); | |
| // Extracts from an existing build.ninja file's contents the commands | |
| // necessary to run GN and regenerate build.ninja. | |
| // | |
| // The regeneration rules live at the top of the build.ninja file and their | |
| // specific contents are an internal detail of NinjaBuildWriter. Used by | |
| // commands::PrepareForRegeneration. | |
| // | |
| // On error, returns an empty string. | |
| static std::string ExtractRegenerationCommands(std::istream& build_ninja_in); | |
| bool Run(Err* err); | |
| private: | |
| // WriteNinjaRules writes the rules that ninja uses to regenerate its own | |
| // build files, used whenever a build input file has changed. | |
| // | |
| // Ninja file regeneration is accomplished by two separate build statements. | |
| // This is necessary to work around ninja's behavior of deleting all output | |
| // files of a build edge if the edge uses a depfile and is interrupted before | |
| // it can complete. Previously, interrupting regeneration would cause ninja to | |
| // delete build.ninja, losing any flags/build settings passed to gen | |
| // previously and requiring the user to manually 'gen' again. | |
| // | |
| // The workaround involves misleading ninja about when the build.ninja file is | |
| // actually written. The first build statement runs the actual 'gen | |
| // --regeneration' command, writing "build.ninja" (and .d and .stamp) and | |
| // lists the "build.ninja.d" depfile to automatically trigger regeneration as | |
| // needed, but does not list "build.ninja" as an output. The second | |
| // statement's stated output is "build.ninja", but it simply uses the phony | |
| // rule to refer to the first statement. | |
| void WriteNinjaRules(); | |
| void WriteAllPools(); | |
| bool WriteSubninjas(Err* err); | |
| bool WritePhonyAndAllRules(Err* err); | |
| void WritePhonyRule(const Target* target, std::string_view phony_name); | |
| const BuildSettings* build_settings_; | |
| const std::unordered_map<const Settings*, const Toolchain*>& used_toolchains_; | |
| const std::vector<const Target*>& all_targets_; | |
| const Toolchain* default_toolchain_; | |
| const std::vector<const Target*>& default_toolchain_targets_; | |
| std::ostream& out_; | |
| std::ostream& dep_out_; | |
| PathOutput path_output_; | |
| NinjaBuildWriter(const NinjaBuildWriter&) = delete; | |
| NinjaBuildWriter& operator=(const NinjaBuildWriter&) = delete; | |
| }; | |
| extern const char kNinjaRules_Help[]; | |
| // Exposed for testing. | |
| base::CommandLine GetSelfInvocationCommandLine( | |
| const BuildSettings* build_settings); | |
| #endif // TOOLS_GN_NINJA_BUILD_WRITER_H_ |