| /* 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 <functional> | |
| #include <iosfwd> | |
| #include <map> | |
| #include <set> | |
| #include <string> | |
| #include <vector> | |
| #include <cm/optional> | |
| #include <cm/string_view> | |
| #include "cmDiagnostics.h" | |
| #include "cmGeneratorExpression.h" | |
| #include "cmMessageType.h" | |
| class cmExportSet; | |
| class cmGeneratorTarget; | |
| class cmGeneratorFileSet; | |
| class cmLocalGenerator; | |
| /** \class cmExportFileGenerator | |
| * \brief Generate files exporting targets from a build or install tree. | |
| * | |
| * cmExportFileGenerator is the interface class for generating export files. | |
| */ | |
| class cmExportFileGenerator | |
| { | |
| public: | |
| cmExportFileGenerator(); | |
| virtual ~cmExportFileGenerator() = default; | |
| struct ExportInfo | |
| { | |
| std::vector<std::string> Files; | |
| std::set<std::string> Sets; | |
| std::set<std::string> Namespaces; | |
| }; | |
| /** Set the full path to the export file to generate. */ | |
| void SetExportFile(char const* mainFile); | |
| std::string const& GetMainExportFileName() const; | |
| /** Set the namespace in which to place exported target names. */ | |
| void SetNamespace(std::string const& ns) { this->Namespace = ns; } | |
| std::string GetNamespace() const { return this->Namespace; } | |
| /** Add a configuration to be exported. */ | |
| void AddConfiguration(std::string const& config); | |
| /** Create and actually generate the export file. Returns whether there was | |
| an error. */ | |
| bool GenerateImportFile(); | |
| protected: | |
| using ImportPropertyMap = std::map<std::string, std::string>; | |
| using ImportFileSetPropertyMap = std::map<std::string, ImportPropertyMap>; | |
| // Collect properties with detailed information about targets beyond | |
| // their location on disk. | |
| void SetImportDetailProperties(std::string const& config, | |
| std::string const& suffix, | |
| cmGeneratorTarget const* target, | |
| ImportPropertyMap& properties); | |
| enum class ImportLinkPropertyTargetNames | |
| { | |
| Yes, | |
| No, | |
| }; | |
| template <typename T> | |
| void SetImportLinkProperty(std::string const& suffix, | |
| cmGeneratorTarget const* target, | |
| std::string const& propName, | |
| std::vector<T> const& entries, | |
| ImportPropertyMap& properties, | |
| ImportLinkPropertyTargetNames targetNames); | |
| /** Generate the export file to the given output stream. Returns whether | |
| there was an error. */ | |
| virtual bool GenerateImportFile(std::ostream& os) = 0; | |
| /** Each subclass knows how to generate its kind of export file. */ | |
| virtual bool GenerateMainFile(std::ostream& os) = 0; | |
| /** Generate per-configuration target information to the given output | |
| stream. */ | |
| virtual void GenerateImportConfig(std::ostream& os, | |
| std::string const& config); | |
| /** Each subclass knows where the target files are located. */ | |
| virtual void GenerateImportTargetsConfig(std::ostream& os, | |
| std::string const& config, | |
| std::string const& suffix) = 0; | |
| /** Record a target referenced by an exported target. */ | |
| virtual bool NoteLinkedTarget(cmGeneratorTarget const* target, | |
| std::string const& linkedName, | |
| cmGeneratorTarget const* linkedTarget); | |
| /** Each subclass knows how to deal with a target that is missing from an | |
| * export set. */ | |
| virtual void HandleMissingTarget(std::string& link_libs, | |
| cmGeneratorTarget const* depender, | |
| cmGeneratorTarget* dependee) = 0; | |
| /** Complain when a duplicate target is encountered. */ | |
| virtual void ComplainAboutDuplicateTarget( | |
| std::string const& targetName) const = 0; | |
| virtual cm::string_view GetImportPrefixWithSlash() const = 0; | |
| void AddImportPrefix(std::string& exportDirs) const; | |
| void PopulateInterfaceProperty(std::string const& propName, | |
| cmGeneratorTarget const* target, | |
| ImportPropertyMap& properties) const; | |
| void PopulateInterfaceProperty(std::string const& propName, | |
| cmGeneratorTarget const* target, | |
| cmGeneratorExpression::PreprocessContext, | |
| ImportPropertyMap& properties); | |
| void PopulateFileSetInterfaceProperty( | |
| std::string const& propName, cmGeneratorTarget const* target, | |
| cmGeneratorFileSet const* fileSet, | |
| cmGeneratorExpression::PreprocessContext, ImportPropertyMap& properties); | |
| bool PopulateInterfaceLinkLibrariesProperty( | |
| cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext, | |
| ImportPropertyMap& properties); | |
| bool PopulateInterfaceProperties( | |
| cmGeneratorTarget const* target, | |
| std::string const& includesDestinationDirs, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties); | |
| bool PopulateFileSetInterfaceProperties( | |
| cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties); | |
| virtual void IssueMessage(MessageType type, | |
| std::string const& message) const = 0; | |
| virtual void IssueDiagnostic(cmDiagnosticCategory category, | |
| std::string const& message) const = 0; | |
| void ReportError(std::string const& errorMessage) const | |
| { | |
| this->IssueMessage(MessageType::FATAL_ERROR, errorMessage); | |
| } | |
| /** Find the set of export files and the unique namespace (if any) for a | |
| * target. */ | |
| virtual ExportInfo FindExportInfo(cmGeneratorTarget const* target) const = 0; | |
| enum FreeTargetsReplace | |
| { | |
| ReplaceFreeTargets, | |
| NoReplaceFreeTargets | |
| }; | |
| void ResolveTargetsInGeneratorExpressions( | |
| std::string& input, cmGeneratorTarget const* target, | |
| FreeTargetsReplace replace = NoReplaceFreeTargets); | |
| virtual cmExportSet* GetExportSet() const { return nullptr; } | |
| virtual void ReplaceInstallPrefix(std::string& input) const; | |
| virtual std::string InstallNameDir(cmGeneratorTarget const* target, | |
| std::string const& config) = 0; | |
| /** Get the temporary location of the config-agnostic C++ module file. */ | |
| virtual std::string GetCxxModuleFile(std::string const& name) const = 0; | |
| virtual std::string GetCxxModulesDirectory() const = 0; | |
| virtual void GenerateCxxModuleConfigInformation(std::string const&, | |
| std::ostream& os) const = 0; | |
| bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target, | |
| cmLocalGenerator const* lg); | |
| static std::string PropertyConfigSuffix(std::string const& config); | |
| // The namespace in which the exports are placed in the generated file. | |
| std::string Namespace; | |
| // The set of configurations to export. | |
| std::vector<std::string> Configurations; | |
| // The file to generate. | |
| std::string MainImportFile; | |
| std::string FileDir; | |
| std::string FileBase; | |
| std::string FileExt; | |
| bool AppendMode = false; | |
| // The set of targets included in the export. | |
| std::set<cmGeneratorTarget const*> ExportedTargets; | |
| std::vector<std::string> MissingTargets; | |
| std::set<cmGeneratorTarget const*> ExternalTargets; | |
| private: | |
| void PopulateInterfaceProperty(std::string const& propName, | |
| std::string const& outputName, | |
| cmGeneratorTarget const* target, | |
| cmGeneratorExpression::PreprocessContext, | |
| ImportPropertyMap& properties); | |
| void PopulateCompatibleInterfaceProperties( | |
| cmGeneratorTarget const* target, ImportPropertyMap& properties) const; | |
| void PopulateCustomTransitiveInterfaceProperties( | |
| cmGeneratorTarget const* target, | |
| cmGeneratorExpression::PreprocessContext preprocessRule, | |
| ImportPropertyMap& properties); | |
| bool PopulateCxxModuleExportProperties( | |
| cmGeneratorTarget const* gte, ImportPropertyMap& properties, | |
| cmGeneratorExpression::PreprocessContext ctx, | |
| std::string const& includesDestinationDirs, std::string& errorMessage); | |
| bool PopulateExportProperties(cmGeneratorTarget const* gte, | |
| ImportPropertyMap& properties, | |
| std::string& errorMessage) const; | |
| void ResolveTargetsInGeneratorExpression(std::string& input, | |
| cmGeneratorTarget const* target, | |
| cmLocalGenerator const* lg); | |
| }; | |
| extern template void cmExportFileGenerator::SetImportLinkProperty<std::string>( | |
| std::string const&, cmGeneratorTarget const*, std::string const&, | |
| std::vector<std::string> const&, ImportPropertyMap& properties, | |
| ImportLinkPropertyTargetNames); | |
| extern template void cmExportFileGenerator::SetImportLinkProperty<cmLinkItem>( | |
| std::string const&, cmGeneratorTarget const*, std::string const&, | |
| std::vector<cmLinkItem> const&, ImportPropertyMap& properties, | |
| ImportLinkPropertyTargetNames); | |
| /** Walk a generator expression and rewrite the target-name slot of each | |
| `$<TARGET_PROPERTY:>`, `$<TARGET_NAME:>`, `$<LINK_ONLY:>`, and | |
| `$<COMPILE_ONLY:>` construct via the provided callback. The callback | |
| receives the bare target name; if it mutates the name and returns true, | |
| the helper splices the new name back into the genex. Returns the | |
| parse-level error message, if an error was encountered. Callers handle | |
| install-prefix substitution and error reporting themselves. This is used | |
| by the cmExportFileGenerator hierarchy, as well as the cmSbomBuilder | |
| hierarchy. */ | |
| cm::optional<std::string> cmResolveTargetsInGeneratorExpression( | |
| std::string& input, | |
| std::function<bool(std::string& name)> const& addTargetNamespace); |