/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file LICENSE.rst or https://cmake.org/licensing for details. */ #pragma once #include "cmConfigure.h" // IWYU pragma: keep #include #include #include #include #include #include #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmPropertyMap.h" #include "cmValue.h" class cmMakefile; class cmTarget; class cmFileSet; class cmSourceFile; namespace cm { enum class RuleScope { Local, Global }; template struct enum_hash { typename std::enable_if::value, std::size_t>::type operator()(E const key) const { return static_cast(key); } }; } // // cmRule: base class for various rule types // class cmRule { public: using CustomCommand = std::vector; using CustomCommands = std::vector; virtual ~cmRule() = default; cmRule& operator=(cmRule const&) = delete; cmMakefile& GetMakefile() const { return *this->Makefile; } /** Get the name of the rule */ std::string const& GetName() const { return this->Name; } virtual std::string const& GetParentName() const; /** Get the command lines. */ virtual CustomCommands const& GetCommands() const = 0; /** Get the output files. */ virtual std::vector const& GetOutputs() const = 0; /** Get the extra files produced by the command. */ virtual std::vector const& GetByproducts() const = 0; /** Get the vector that holds the list of dependencies. */ virtual std::vector const& GetDepends() const = 0; /** Get the file that holds the list of dependencies. */ virtual std::string const& GetDepfile() const = 0; enum class ConfiguratorType { FileSet, Source }; enum class ChainConfigurators { No, Yes }; using ConfiguratorSet = std::vector>; void SetConfigurator(ConfiguratorType type, std::string configurator, ChainConfigurators chain = ChainConfigurators::No); ConfiguratorSet const& GetConfigurators(ConfiguratorType type) const; bool HasConfigurators(ConfiguratorType type) const; bool IsGloballyVisible() const { return this->Scope == cm::RuleScope::Global; } cmFileSet* GetOutputFileSet(cmTarget* target, cmFileSet const* fileSet) const; // Special properties cmBTStringRange GetIncludeDirectories() const; cmBTStringRange GetCompileOptions() const; cmBTStringRange GetCompileDefinitions() const; //! Set/Get a property of this rule void SetProperty(std::string const& prop, cmValue value); void SetProperty(std::string const& prop, std::nullptr_t) { this->SetProperty(prop, cmValue{ nullptr }); } void RemoveProperty(std::string const& prop) { this->SetProperty(prop, cmValue{ nullptr }); } void SetProperty(std::string const& prop, std::string const& value) { this->SetProperty(prop, cmValue{ value }); } void AppendProperty(std::string const& prop, std::string const& value, bool asString = false); cmValue GetProperty(std::string const& prop) const; void CheckProperty(std::string const& prop, cmMakefile& context) const; bool InGeneration() const { return this->Generation; } struct Pattern { Pattern(std::string name, std::string value) : Name(std::move(name)) , Value(std::move(value)) { } std::string Name; std::string Value; }; using PatternSet = std::vector; bool Instantiate(cmTarget const* target, cmFileSet const* fileSet, cmFileSet const* outputFileSet, PatternSet& patterns) const; bool Instantiate(cmTarget const* target, cmFileSet const* fileSet, cmFileSet const* outputFileSet, cmSourceFile* source, PatternSet& patterns) const; protected: cmRule(cmMakefile& makefile, std::string name, cm::RuleScope scope); cmRule(cmRule const& parent, cmMakefile& makefile, std::string name, cm::RuleScope scope); private: // switch context cmRule usage void SwitchMode() const { this->Generation = true; } cmMakefile* Makefile; std::string Name; cm::RuleScope Scope = cm::RuleScope::Local; std::unordered_map> Configurators; std::unordered_map> ConfiguratorsChain; cmPropertyMap Properties; std::vector> IncludeDirectories; std::vector> CompileOptions; std::vector> CompileDefinitions; // cmRule properties should not be changed during generation phase // Use mutable field to track current phase independently of state of object // (const or not) mutable bool Generation = false; }; // // cmCustomRule: define a template used to generate custom commands // class cmCustomRule : public cmRule { public: cmCustomRule(cmMakefile& makefile, std::string name, CustomCommands commands, std::vector outputs, cm::RuleScope scope = cm::RuleScope::Local); cmCustomRule& operator=(cmCustomRule const&) = delete; /** Get the command lines. */ CustomCommands const& GetCommands() const override; /** Get the output files. */ std::vector const& GetOutputs() const override; /** Set/Get the extra files produced by the command. */ void SetByproducts(std::vector byproducts); std::vector const& GetByproducts() const override; /** Set/Get the vector that holds the list of dependencies. */ void SetDepends(std::vector depends); std::vector const& GetDepends() const override; /** Set/Get the file that holds the list of dependencies. */ void SetDepfile(std::string depfile); std::string const& GetDepfile() const override; private: CustomCommands Commands; std::vector Outputs; std::vector Byproducts; std::vector Depends; std::string Depfile; }; // // cmSpecializedRule: rule embedding another rule and enabling properties // customization. // class cmSpecializedRule : public cmRule { public: cmSpecializedRule(cmMakefile& makefile, std::string name, cmRule const& parent, cm::RuleScope scope = cm::RuleScope::Local); cmSpecializedRule& operator=(cmSpecializedRule const&) = delete; std::string const& GetParentName() const override; /** Get the command lines. */ CustomCommands const& GetCommands() const override; /** Get the output files. */ std::vector const& GetOutputs() const override; /** Get the extra files produced by the command. */ std::vector const& GetByproducts() const override; /** Get the vector that holds the list of dependencies. */ std::vector const& GetDepends() const override; /** Get the file that holds the list of dependencies. */ std::string const& GetDepfile() const override; private: cmRule const& ParentRule; };