diff options
Diffstat (limited to 'Source/cmGlobalNinjaGenerator.h')
-rw-r--r-- | Source/cmGlobalNinjaGenerator.h | 371 |
1 files changed, 232 insertions, 139 deletions
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index e046c7c96..b0008f74a 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -1,27 +1,34 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2011 Peter Collingbourne <peter@pcc.me.uk> - Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com> - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ #ifndef cmGlobalNinjaGenerator_h -# define cmGlobalNinjaGenerator_h +#define cmGlobalNinjaGenerator_h -# include "cmGlobalGenerator.h" -# include "cmGlobalGeneratorFactory.h" -# include "cmNinjaTypes.h" +#include "cmConfigure.h" -//#define NINJA_GEN_VERBOSE_FILES +#include <iosfwd> +#include <map> +#include <set> +#include <string> +#include <utility> +#include <vector> -class cmLocalGenerator; +#include "cmGlobalCommonGenerator.h" +#include "cmGlobalGenerator.h" +#include "cmGlobalGeneratorFactory.h" +#include "cmNinjaTypes.h" +#include "cmPolicies.h" +#include "cm_codecvt.hxx" + +class cmCustomCommand; class cmGeneratedFileStream; class cmGeneratorTarget; +class cmLinkLineComputer; +class cmLocalGenerator; +class cmMakefile; +class cmOutputConverter; +class cmStateDirectory; +class cmake; +struct cmDocumentationEntry; /** * \class cmGlobalNinjaGenerator @@ -42,7 +49,7 @@ class cmGeneratorTarget; * - We extensively use Ninja variable overloading system to minimize the * number of generated rules. */ -class cmGlobalNinjaGenerator : public cmGlobalGenerator +class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator { public: /// The default name of Ninja's build file. Typically: build.ninja. @@ -55,15 +62,23 @@ public: /// The indentation string used when generating Ninja's build file. static const char* INDENT; + /// The shell command used for a no-op. + static std::string const SHELL_NOOP; + /// Write @a count times INDENT level to output stream @a os. static void Indent(std::ostream& os, int count); /// Write a divider in the given output stream @a os. static void WriteDivider(std::ostream& os); - static std::string EncodeIdent(const std::string &ident, std::ostream &vars); - static std::string EncodeLiteral(const std::string &lit); - static std::string EncodePath(const std::string &path); + static std::string EncodeRuleName(std::string const& name); + static std::string EncodeIdent(const std::string& ident, std::ostream& vars); + static std::string EncodeLiteral(const std::string& lit); + std::string EncodePath(const std::string& path); + + cmLinkLineComputer* CreateLinkLineComputer( + cmOutputConverter* outputConverter, + cmStateDirectory const& stateDir) const CM_OVERRIDE; /** * Write the given @a comment to the output stream @a os. It @@ -72,27 +87,39 @@ public: static void WriteComment(std::ostream& os, const std::string& comment); /** + * Utilized by the generator factory to determine if this generator + * supports toolsets. + */ + static bool SupportsToolset() { return false; } + + /** + * Utilized by the generator factory to determine if this generator + * supports platforms. + */ + static bool SupportsPlatform() { return false; } + + bool IsIPOSupported() const CM_OVERRIDE { return true; } + + /** * Write a build statement to @a os with the @a comment using * the @a rule the list of @a outputs files and inputs. * It also writes the variables bound to this build statement. * @warning no escaping of any kind is done here. */ - void WriteBuild(std::ostream& os, - const std::string& comment, - const std::string& rule, - const cmNinjaDeps& outputs, + void WriteBuild(std::ostream& os, const std::string& comment, + const std::string& rule, const cmNinjaDeps& outputs, + const cmNinjaDeps& implicitOuts, const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps, const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables, const std::string& rspfile = std::string(), - int cmdLineLimit = -1); + int cmdLineLimit = 0, bool* usedResponseFile = CM_NULLPTR); /** * Helper to write a build statement with the special 'phony' rule. */ - void WritePhonyBuild(std::ostream& os, - const std::string& comment, + void WritePhonyBuild(std::ostream& os, const std::string& comment, const cmNinjaDeps& outputs, const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps = cmNinjaDeps(), @@ -102,9 +129,10 @@ public: void WriteCustomCommandBuild(const std::string& command, const std::string& description, const std::string& comment, - const cmNinjaDeps& outputs, + const std::string& depfile, bool uses_terminal, + bool restat, const cmNinjaDeps& outputs, const cmNinjaDeps& deps = cmNinjaDeps(), - const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps()); + const cmNinjaDeps& orderOnly = cmNinjaDeps()); void WriteMacOSXContentBuild(const std::string& input, const std::string& output); @@ -114,198 +142,238 @@ public: * It also writes the variables bound to this rule statement. * @warning no escaping of any kind is done here. */ - static void WriteRule(std::ostream& os, - const std::string& name, + static void WriteRule(std::ostream& os, const std::string& name, const std::string& command, const std::string& description, - const std::string& comment, - const std::string& depfile, - const std::string& rspfile, + const std::string& comment, const std::string& depfile, + const std::string& deptype, const std::string& rspfile, const std::string& rspcontent, - bool restat, - bool generator); + const std::string& restat, bool generator); /** * Write a variable named @a name to @a os with value @a value and an * optional @a comment. An @a indent level can be specified. * @warning no escaping of any kind is done here. */ - static void WriteVariable(std::ostream& os, - const std::string& name, + static void WriteVariable(std::ostream& os, const std::string& name, const std::string& value, - const std::string& comment = "", - int indent = 0); + const std::string& comment = "", int indent = 0); /** * Write an include statement including @a filename with an optional * @a comment to the @a os stream. */ - static void WriteInclude(std::ostream& os, - const std::string& filename, + static void WriteInclude(std::ostream& os, const std::string& filename, const std::string& comment = ""); /** * Write a default target statement specifying @a targets as * the default targets. */ - static void WriteDefault(std::ostream& os, - const cmNinjaDeps& targets, + static void WriteDefault(std::ostream& os, const cmNinjaDeps& targets, const std::string& comment = ""); - - static bool IsMinGW() { return UsingMinGW; } - + bool IsGCCOnWindows() const { return UsingGCCOnWindows; } public: - /// Default constructor. - cmGlobalNinjaGenerator(); + cmGlobalNinjaGenerator(cmake* cm); - /// Convenience method for creating an instance of this class. - static cmGlobalGeneratorFactory* NewFactory() { - return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); } + static cmGlobalGeneratorFactory* NewFactory() + { + return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); + } + + ~cmGlobalNinjaGenerator() CM_OVERRIDE {} - /// Destructor. - virtual ~cmGlobalNinjaGenerator() { } + cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) CM_OVERRIDE; - /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator() - virtual cmLocalGenerator* CreateLocalGenerator(); + std::string GetName() const CM_OVERRIDE + { + return cmGlobalNinjaGenerator::GetActualName(); + } - /// Overloaded methods. @see cmGlobalGenerator::GetName(). - virtual const char* GetName() const { - return cmGlobalNinjaGenerator::GetActualName(); } + static std::string GetActualName() { return "Ninja"; } - /// @return the name of this generator. - static const char* GetActualName() { return "Ninja"; } + /** Get encoding used by generator for ninja files */ + codecvt::Encoding GetMakefileEncoding() const CM_OVERRIDE; - /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation() static void GetDocumentation(cmDocumentationEntry& entry); - /// Overloaded methods. @see cmGlobalGenerator::Generate() - virtual void Generate(); - - /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage() - virtual void EnableLanguage(std::vector<std::string>const& languages, - cmMakefile* mf, - bool optional); + void EnableLanguage(std::vector<std::string> const& languages, + cmMakefile* mf, bool optional) CM_OVERRIDE; - /// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand() - virtual std::string GenerateBuildCommand(const char* makeProgram, - const char* projectName, - const char* projectDir, - const char* additionalOptions, - const char* targetName, - const char* config, - bool ignoreErrors, - bool fast); + void GenerateBuildCommand(std::vector<std::string>& makeCommand, + const std::string& makeProgram, + const std::string& projectName, + const std::string& projectDir, + const std::string& targetName, + const std::string& config, bool fast, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) CM_OVERRIDE; // Setup target names - virtual const char* GetAllTargetName() const { return "all"; } - virtual const char* GetInstallTargetName() const { return "install"; } - virtual const char* GetInstallLocalTargetName() const { + const char* GetAllTargetName() const CM_OVERRIDE { return "all"; } + const char* GetInstallTargetName() const CM_OVERRIDE { return "install"; } + const char* GetInstallLocalTargetName() const CM_OVERRIDE + { return "install/local"; } - virtual const char* GetInstallStripTargetName() const { + const char* GetInstallStripTargetName() const CM_OVERRIDE + { return "install/strip"; } - virtual const char* GetTestTargetName() const { return "test"; } - virtual const char* GetPackageTargetName() const { return "package"; } - virtual const char* GetPackageSourceTargetName() const { + const char* GetTestTargetName() const CM_OVERRIDE { return "test"; } + const char* GetPackageTargetName() const CM_OVERRIDE { return "package"; } + const char* GetPackageSourceTargetName() const CM_OVERRIDE + { return "package_source"; } - virtual const char* GetEditCacheTargetName() const { + const char* GetEditCacheTargetName() const CM_OVERRIDE + { return "edit_cache"; } - virtual const char* GetRebuildCacheTargetName() const { + const char* GetRebuildCacheTargetName() const CM_OVERRIDE + { return "rebuild_cache"; } - virtual const char* GetCleanTargetName() const { return "clean"; } + const char* GetCleanTargetName() const CM_OVERRIDE { return "clean"; } + cmGeneratedFileStream* GetBuildFileStream() const + { + return this->BuildFileStream; + } - cmGeneratedFileStream* GetBuildFileStream() const { - return this->BuildFileStream; } - - cmGeneratedFileStream* GetRulesFileStream() const { - return this->RulesFileStream; } + cmGeneratedFileStream* GetRulesFileStream() const + { + return this->RulesFileStream; + } - void AddCXXCompileCommand(const std::string &commandLine, - const std::string &sourceFile); + std::string ConvertToNinjaPath(const std::string& path) const; + + struct MapToNinjaPathImpl + { + cmGlobalNinjaGenerator* GG; + MapToNinjaPathImpl(cmGlobalNinjaGenerator* gg) + : GG(gg) + { + } + std::string operator()(std::string const& path) + { + return this->GG->ConvertToNinjaPath(path); + } + }; + MapToNinjaPathImpl MapToNinjaPath() { return MapToNinjaPathImpl(this); } + + void AddCXXCompileCommand(const std::string& commandLine, + const std::string& sourceFile); /** * Add a rule to the generated build system. * Call WriteRule() behind the scene but perform some check before like: * - Do not add twice the same rule. */ - void AddRule(const std::string& name, - const std::string& command, - const std::string& description, - const std::string& comment, - const std::string& depfile = "", - const std::string& rspfile = "", - const std::string& rspcontent = "", - bool restat = false, - bool generator = false); + void AddRule(const std::string& name, const std::string& command, + const std::string& description, const std::string& comment, + const std::string& depfile, const std::string& deptype, + const std::string& rspfile, const std::string& rspcontent, + const std::string& restat, bool generator); bool HasRule(const std::string& name); void AddCustomCommandRule(); void AddMacOSXContentRule(); - bool HasCustomCommandOutput(const std::string &output) { + bool HasCustomCommandOutput(const std::string& output) + { return this->CustomCommandOutputs.find(output) != - this->CustomCommandOutputs.end(); + this->CustomCommandOutputs.end(); } /// Called when we have seen the given custom command. Returns true /// if we has seen it before. - bool SeenCustomCommand(cmCustomCommand const *cc) { + bool SeenCustomCommand(cmCustomCommand const* cc) + { return !this->CustomCommands.insert(cc).second; } /// Called when we have seen the given custom command output. - void SeenCustomCommandOutput(const std::string &output) { + void SeenCustomCommandOutput(const std::string& output) + { this->CustomCommandOutputs.insert(output); // We don't need the assumed dependencies anymore, because we have // an output. this->AssumedSourceDependencies.erase(output); } - void AddAssumedSourceDependencies(const std::string &source, - const cmNinjaDeps &deps) { - std::set<std::string> &ASD = this->AssumedSourceDependencies[source]; + void AddAssumedSourceDependencies(const std::string& source, + const cmNinjaDeps& deps) + { + std::set<std::string>& ASD = this->AssumedSourceDependencies[source]; // Because we may see the same source file multiple times (same source // specified in multiple targets), compute the union of any assumed // dependencies. ASD.insert(deps.begin(), deps.end()); } - void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs); - void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs); - void AddDependencyToAll(cmTarget* target); + void AppendTargetOutputs( + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + cmNinjaTargetDepends depends = DependOnTargetArtifact); + void AppendTargetDepends( + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + cmNinjaTargetDepends depends = DependOnTargetArtifact); + void AppendTargetDependsClosure(cmGeneratorTarget const* target, + cmNinjaDeps& outputs); + void AddDependencyToAll(cmGeneratorTarget* target); void AddDependencyToAll(const std::string& input); - const std::vector<cmLocalGenerator*>& GetLocalGenerators() const { - return LocalGenerators; } + const std::vector<cmLocalGenerator*>& GetLocalGenerators() const + { + return LocalGenerators; + } - bool IsExcluded(cmLocalGenerator* root, cmTarget& target) { - return cmGlobalGenerator::IsExcluded(root, target); } + bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) + { + return cmGlobalGenerator::IsExcluded(root, target); + } - int GetRuleCmdLength(const std::string& name) { - return RuleCmdLength[name]; } + int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; } - void AddTargetAlias(const std::string& alias, cmTarget* target); + void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target); + void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE; -protected: + // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3 + static std::string RequiredNinjaVersion() { return "1.3"; } + static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; } + static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; } + bool SupportsConsolePool() const; + bool SupportsImplicitOuts() const; - /// Overloaded methods. - /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() - virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; } + std::string NinjaOutputPath(std::string const& path) const; + bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); } + void StripNinjaOutputPathPrefixAsSuffix(std::string& path); + bool WriteDyndepFile(std::string const& dir_top_src, + std::string const& dir_top_bld, + std::string const& dir_cur_src, + std::string const& dir_cur_bld, + std::string const& arg_dd, + std::vector<std::string> const& arg_ddis, + std::string const& module_dir, + std::vector<std::string> const& linked_target_dirs); -private: +protected: + void Generate() CM_OVERRIDE; - /// @see cmGlobalGenerator::ComputeTargetObjects - virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const; + bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const CM_OVERRIDE { return true; } + +private: + std::string GetEditCacheCommand() const CM_OVERRIDE; + bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE; + void CheckNinjaFeatures(); + bool CheckLanguages(std::vector<std::string> const& languages, + cmMakefile* mf) const CM_OVERRIDE; + bool CheckFortran(cmMakefile* mf) const; void OpenBuildFileStream(); void CloseBuildFileStream(); @@ -321,6 +389,7 @@ private: void WriteAssumedSourceDependencies(); void WriteTargetAliases(std::ostream& os); + void WriteFolderTargets(std::ostream& os); void WriteUnknownExplicitDependencies(std::ostream& os); void WriteBuiltinTargets(std::ostream& os); @@ -329,10 +398,13 @@ private: void WriteTargetClean(std::ostream& os); void WriteTargetHelp(std::ostream& os); - std::string ninjaCmd() const; + void ComputeTargetDependsClosure( + cmGeneratorTarget const* target, + std::set<cmGeneratorTarget const*>& depends); + std::string ninjaCmd() const; - /// The file containing the build statement. (the relation ship of the + /// The file containing the build statement. (the relationship of the /// compilation DAG). cmGeneratedFileStream* BuildFileStream; /// The file containing the rule statements. (The action attached to each @@ -353,28 +425,49 @@ private: /// The set of dependencies to add to the "all" target. cmNinjaDeps AllDependencies; + bool UsingGCCOnWindows; + /// The set of custom commands we have seen. std::set<cmCustomCommand const*> CustomCommands; /// The set of custom command outputs we have seen. std::set<std::string> CustomCommandOutputs; - //The combined explicit dependencies of all build commands that the global - //generator has issued. When combined with CombinedBuildOutputs it allows - //us to detect the set of explicit dependencies that have - std::set<std::string> CombinedBuildExplicitDependencies; + /// Whether we are collecting known build outputs and needed + /// dependencies to determine unknown dependencies. + bool ComputingUnknownDependencies; + cmPolicies::PolicyStatus PolicyCMP0058; + + /// The combined explicit dependencies of custom build commands + std::set<std::string> CombinedCustomCommandExplicitDependencies; + + /// When combined with CombinedCustomCommandExplicitDependencies it allows + /// us to detect the set of explicit dependencies that have std::set<std::string> CombinedBuildOutputs; /// The mapping from source file to assumed dependencies. std::map<std::string, std::set<std::string> > AssumedSourceDependencies; - typedef std::map<std::string, cmTarget*> TargetAliasMap; + typedef std::map<std::string, cmGeneratorTarget*> TargetAliasMap; TargetAliasMap TargetAliases; - static cmLocalGenerator* LocalGenerator; + typedef std::map<cmGeneratorTarget const*, + std::set<cmGeneratorTarget const*> > + TargetDependsClosureMap; + TargetDependsClosureMap TargetDependsClosures; - static bool UsingMinGW; + std::string NinjaCommand; + std::string NinjaVersion; + bool NinjaSupportsConsolePool; + bool NinjaSupportsImplicitOuts; + unsigned long NinjaSupportsDyndeps; + +private: + void InitOutputPathPrefix(); + std::string OutputPathPrefix; + std::string TargetAll; + std::string CMakeCacheFile; }; #endif // ! cmGlobalNinjaGenerator_h |