| // 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_TARGET_WRITER_H_ | |
| #define TOOLS_GN_NINJA_TARGET_WRITER_H_ | |
| #include <iosfwd> | |
| #include "gn/path_output.h" | |
| #include "gn/resolved_target_data.h" | |
| #include "gn/substitution_type.h" | |
| class OutputFile; | |
| class Settings; | |
| class Target; | |
| struct SubstitutionBits; | |
| // Generates one target's ".ninja" file. The toplevel "build.ninja" file is | |
| // generated by the NinjaBuildWriter. | |
| class NinjaTargetWriter { | |
| public: | |
| NinjaTargetWriter(const Target* target, std::ostream& out); | |
| virtual ~NinjaTargetWriter(); | |
| // Returns a ResolvedTargetData that can be used to retrieve information | |
| // from targets. The instance can be set through SetResolvedTargetData() | |
| // or may be created on demand otherwise (which is useful to keep unit-tests | |
| // simple). | |
| const ResolvedTargetData& resolved() const; | |
| // Sets the ResolvedTargetData instance to return for future resolved() | |
| // calls. Does not transfer ownership, and allows several NinjaTargetWriter | |
| // instances to share the same cached information. | |
| void SetResolvedTargetData(ResolvedTargetData* resolved); | |
| // Set the vector that will receive the Ninja output file paths generated | |
| // by this writer. A nullptr value means no output files needs to be | |
| // collected. | |
| void SetNinjaOutputs(std::vector<OutputFile>* ninja_outputs); | |
| // Returns the build line to be written to the toolchain build file. | |
| // | |
| // Some targets have their rules written to separate files, and some can have | |
| // their rules coalesced in the main build file. For the coalesced case, this | |
| // function will return the rules as a string. For the separate file case, | |
| // the separate ninja file will be written and the return string will be the | |
| // subninja command to load that file. | |
| // | |
| // If |ninja_outputs| is not nullptr, it will be set with the list of | |
| // Ninja output paths generated by the corresponding writer. | |
| static std::string RunAndWriteFile( | |
| const Target* target, | |
| ResolvedTargetData* resolved = nullptr, | |
| std::vector<OutputFile>* ninja_outputs = nullptr); | |
| // Writes a stamp or phony rule for the target's public inputs if it exports | |
| // any. This does nothing if resolved->ExportsPublicInputs(target) returns | |
| // false. | |
| static void WritePublicInputsStampOrPhony(const Target* target, | |
| ResolvedTargetData* resolved, | |
| std::ostream& out); | |
| // Targets need to depend on all their recursive hard deps. Listing all of | |
| // them on each target makes the generated ninja files very large, since | |
| // targets near the top of the dependency graph tend to have thousands of | |
| // recursive hard deps. Instead, every target with at least two hard deps | |
| // gets a stamp or phony rule for its hard deps which depends on the target's | |
| // direct hard deps, and on the hard deps rules of the direct deps that hard | |
| // deps are inherited from. BUNDLE_DATA targets are never included (see | |
| // WriteInputDepsStampOrPhonyAndGetDep()). | |
| static void WriteHardDepsStampOrPhony(const Target* target, | |
| ResolvedTargetData* resolved, | |
| std::ostream& out); | |
| // Appends what a build statement needs to depend on to depend on all hard | |
| // deps of |target|: Nothing if it has no hard deps, the hard dep itself if | |
| // it has just one, else the rule written by WriteHardDepsStampOrPhony(). | |
| static void AppendHardDepsOutputs(const Target* target, | |
| const ResolvedTargetData& resolved, | |
| std::vector<OutputFile>* outputs); | |
| virtual void Run() = 0; | |
| protected: | |
| // Returns a writable pointer to resolved(). Only used internally. | |
| ResolvedTargetData* GetResolvedTargetData(); | |
| // Writes out the substitution values that are shared between the different | |
| // types of tools (target gen dir, target label, etc.). Only the substitutions | |
| // identified by the given bits will be written. | |
| void WriteSharedVars(const SubstitutionBits& bits); | |
| // Writes out the substitution values that are shared between C compiler tools | |
| // and action tools. Only the substitutions identified by the given bits will | |
| // be written. | |
| // If respect_source_used is set, the generated substitution values will | |
| // respect the types of source code used; otherwise they will respect the bits | |
| // passed in. | |
| void WriteCCompilerVars(const SubstitutionBits& bits, | |
| bool indent, | |
| bool respect_source_used); | |
| // Writes out the substitution values that are shared between Rust tools | |
| // and action tools. Only the substitutions identified by the given bits will | |
| // be written, unless 'always_write' is specified. | |
| void WriteRustCompilerVars(const SubstitutionBits& bits, | |
| bool indent, | |
| bool always_write); | |
| struct InputDeps { | |
| std::vector<OutputFile> implicit; | |
| std::vector<OutputFile> order_only; | |
| }; | |
| // Writes to the output stream a phony rule for input dependencies, and | |
| // returns the file to be appended to source rules that encodes the | |
| // dependencies for the current target. | |
| // If num_output_uses is small, this might return all input dependencies | |
| // directly, without writing a phony rule. | |
| // If there are no implicit dependencies and no additional target dependencies | |
| // are passed in, this returns an empty struct. | |
| InputDeps WriteInputDepsStampOrPhonyAndGetDep( | |
| const std::vector<const Target*>& additional_hard_deps, | |
| size_t num_output_uses) const; | |
| // Writes to the output file a final phony rule for the target that aliases | |
| // the given list of files. | |
| void WriteStampOrPhonyForTarget( | |
| const std::vector<OutputFile>& deps, | |
| const std::vector<OutputFile>& order_only_deps); | |
| // Writes the validation dependencies to the output stream. | |
| void WriteValidations(); | |
| const Settings* settings_; // Non-owning. | |
| const Target* target_; // Non-owning. | |
| std::ostream& out_; | |
| PathOutput path_output_; | |
| // Write a Ninja output file to out_, and also add it to |*ninja_outputs_| | |
| // if needed. | |
| void WriteOutput(const OutputFile& output) const; | |
| void WriteOutput(OutputFile&& output) const; | |
| // Same as WriteOutput() for a list of Ninja output file paths. | |
| void WriteOutputs(const std::vector<OutputFile>& outputs) const; | |
| void WriteOutputs(std::vector<OutputFile>&& outputs) const; | |
| // The list of all Ninja output file paths generated by this writer for | |
| // this target. Used to implement the --ide=ninja_outputs `gn gen` flag. | |
| // Needs to be mutable because WriteOutput() and WriteOutputs() need to | |
| // be const. | |
| mutable std::vector<OutputFile>* ninja_outputs_ = nullptr; | |
| // The ResolvedTargetData instance can be set through SetResolvedTargetData() | |
| // or it will be created lazily when resolved() is called, hence the need | |
| // for 'mutable' here. | |
| mutable ResolvedTargetData* resolved_ptr_ = nullptr; | |
| mutable std::unique_ptr<ResolvedTargetData> resolved_owned_; | |
| private: | |
| void WriteCopyRules(); | |
| void WriteEscapedSubstitution(const Substitution* type); | |
| NinjaTargetWriter(const NinjaTargetWriter&) = delete; | |
| NinjaTargetWriter& operator=(const NinjaTargetWriter&) = delete; | |
| }; | |
| #endif // TOOLS_GN_NINJA_TARGET_WRITER_H_ |