/* 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 "cm_codecvt_Encoding.hxx" #include "cmGlobalGenerator.h" #include "cmTargetDepend.h" #include "cmVSSolution.h" #include "cmVSVersion.h" #include "cmValue.h" class cmCustomCommand; class cmGeneratorTarget; class cmLocalGenerator; class cmMakefile; class cmake; /** \class cmGlobalVisualStudioGenerator * \brief Base class for global Visual Studio generators. * * cmGlobalVisualStudioGenerator provides functionality common to all * global Visual Studio generators. */ class cmGlobalVisualStudioGenerator : public cmGlobalGenerator { public: using VSVersion = cm::VS::Version; ~cmGlobalVisualStudioGenerator() override; VSVersion GetVersion() const; void SetVersion(VSVersion v); /** Is the installed VS an Express edition? */ bool IsExpressEdition() const { return this->ExpressEdition; } void EnableLanguage(std::vector const& languages, cmMakefile*, bool optional) override; bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; /** * Get the name of the target platform (architecture) for which we generate. * The names are as defined by VS, e.g. "Win32", "x64", "Itanium", "ARM". */ std::string const& GetPlatformName() const; /** * Configure CMake's Visual Studio macros file into the user's Visual * Studio macros directory. */ virtual void ConfigureCMakeVisualStudioMacros(); /** * Where does this version of Visual Studio look for macros for the * current user? Returns the empty string if this version of Visual * Studio does not implement support for VB macros. */ virtual std::string GetUserMacrosDirectory(); /** * What is the reg key path to "vsmacros" for this version of Visual * Studio? */ virtual std::string GetUserMacrosRegKeyBase(); cmValue GetDebuggerWorkingDirectory(cmGeneratorTarget* gt) const override; enum MacroName { MacroReload, MacroStop }; /** * Call the ReloadProjects macro if necessary based on * GetFilesReplacedDuringGenerate results. */ void CallVisualStudioMacro(MacroName m, std::string const& vsSolutionFile); // return true if target is fortran only bool TargetIsFortranOnly(cmGeneratorTarget const* gt) const; // return true if target should be included in solution. virtual bool IsInSolution(cmGeneratorTarget const* gt) const; // return true if project dependency should be included in solution. virtual bool IsDepInSolution(std::string const& targetName) const; /** Get the top-level registry key for this VS version. */ std::string GetRegistryBase(); /** Get the top-level registry key for the given VS version. */ static std::string GetRegistryBase(char const* version); /** Return true if the generated build tree may contain multiple builds. i.e. "Can I build Debug and Release in the same tree?" */ bool IsMultiConfig() const override { return true; } /** Return true if building for Windows CE */ virtual bool TargetsWindowsCE() const { return false; } bool IsIncludeExternalMSProjectSupported() const override { return true; } /** Get encoding used by generator for generated source files */ codecvt_Encoding GetMakefileEncoding() const override { return codecvt_Encoding::ANSI; } class TargetSet : public std::set { }; class TargetCompare { std::string First; public: TargetCompare(std::string first) : First(std::move(first)) { } bool operator()(cmGeneratorTarget const* l, cmGeneratorTarget const* r) const; }; class OrderedTargetDependSet; bool FindMakeProgram(cmMakefile*) override; std::string ExpandCFGIntDir(std::string const& str, std::string const& config) const override; void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; std::string GetStartupProjectName(cmLocalGenerator const* root) const; void AddSymbolExportCommand(cmGeneratorTarget*, std::vector& commands, std::string const& configName); bool Open(std::string const& bindir, std::string const& projectName, bool dryRun) override; bool IsVisualStudio() const override { return true; } //! Lookup a stored GUID or compute one deterministically. std::string GetGUID(std::string const& name) const; protected: cmGlobalVisualStudioGenerator(cmake* cm); virtual bool InitializePlatform(cmMakefile* mf); void AddExtraIDETargets() override; // Does this VS version link targets to each other if there are // dependencies in the SLN file? This was done for VS versions // below 8. virtual bool VSLinksDependencies() const { return true; } char const* GetIDEVersion() const; VSVersion Version; bool ExpressEdition; std::string GeneratorPlatform; std::string DefaultPlatformName; /** Return true if the configuration needs to be deployed */ virtual bool NeedsDeploy(cmGeneratorTarget const& target, char const* config) const = 0; /** Returns true if the target system support debugging deployment. */ virtual bool TargetSystemSupportsDeployment() const = 0; static cm::string_view ExternalProjectTypeId(std::string const& path); std::set IsPartOfDefaultBuild( std::vector const& configs, TargetDependSet const& projectTargets, cmGeneratorTarget const* target) const; bool IsDependedOn(TargetDependSet const& projectTargets, cmGeneratorTarget const* target) const; std::map GUIDMap; cm::VS::Solution CreateSolution(cmLocalGenerator const* root, TargetDependSet const& projectTargets) const; cm::VS::Solution::Folder* CreateSolutionFolder( cm::VS::Solution& solution, cm::string_view rawName) const; std::string GetSLNFile(cmLocalGenerator const* root) const; std::string GetSLNFile(std::string const& projectDir, std::string const& projectName) const; void Generate() override; void GenerateSolution(cmLocalGenerator const* root, std::vector const& generators); private: virtual std::string GetVSMakeProgram() = 0; void PrintCompilerAdvice(std::ostream&, std::string const&, cmValue) const override { } }; class cmGlobalVisualStudioGenerator::OrderedTargetDependSet : public std::multiset { using derived = std::multiset; public: using TargetDependSet = cmGlobalGenerator::TargetDependSet; using TargetSet = cmGlobalVisualStudioGenerator::TargetSet; OrderedTargetDependSet(TargetDependSet const&, std::string const& first); OrderedTargetDependSet(TargetSet const&, std::string const& first); };