1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 file Copyright.txt or https://cmake.org/licensing for details. */ 3 #pragma once 4 5 #include "cmConfigure.h" // IWYU pragma: keep 6 7 #include <iosfwd> 8 #include <map> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "cmGlobalGenerator.h" 14 #include "cmTargetDepend.h" 15 16 class cmCustomCommand; 17 class cmGeneratorTarget; 18 class cmLocalGenerator; 19 class cmMakefile; 20 class cmake; 21 22 /** \class cmGlobalVisualStudioGenerator 23 * \brief Base class for global Visual Studio generators. 24 * 25 * cmGlobalVisualStudioGenerator provides functionality common to all 26 * global Visual Studio generators. 27 */ 28 class cmGlobalVisualStudioGenerator : public cmGlobalGenerator 29 { 30 public: 31 /** Known versions of Visual Studio. */ 32 enum VSVersion 33 { 34 VS9 = 90, 35 VS10 = 100, 36 VS11 = 110, 37 VS12 = 120, 38 /* VS13 = 130 was skipped */ 39 VS14 = 140, 40 VS15 = 150, 41 VS16 = 160, 42 VS17 = 170 43 }; 44 45 virtual ~cmGlobalVisualStudioGenerator(); 46 47 VSVersion GetVersion() const; 48 void SetVersion(VSVersion v); 49 50 /** Is the installed VS an Express edition? */ IsExpressEdition()51 bool IsExpressEdition() const { return this->ExpressEdition; } 52 53 void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, 54 bool optional) override; 55 56 bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; 57 58 /** 59 * Get the name of the target platform (architecture) for which we generate. 60 * The names are as defined by VS, e.g. "Win32", "x64", "Itanium", "ARM". 61 */ 62 std::string const& GetPlatformName() const; 63 64 /** 65 * Configure CMake's Visual Studio macros file into the user's Visual 66 * Studio macros directory. 67 */ 68 virtual void ConfigureCMakeVisualStudioMacros(); 69 70 /** 71 * Where does this version of Visual Studio look for macros for the 72 * current user? Returns the empty string if this version of Visual 73 * Studio does not implement support for VB macros. 74 */ 75 virtual std::string GetUserMacrosDirectory(); 76 77 /** 78 * What is the reg key path to "vsmacros" for this version of Visual 79 * Studio? 80 */ 81 virtual std::string GetUserMacrosRegKeyBase(); 82 83 enum MacroName 84 { 85 MacroReload, 86 MacroStop 87 }; 88 89 /** 90 * Call the ReloadProjects macro if necessary based on 91 * GetFilesReplacedDuringGenerate results. 92 */ 93 void CallVisualStudioMacro(MacroName m, const std::string& vsSolutionFile); 94 95 // return true if target is fortran only 96 bool TargetIsFortranOnly(const cmGeneratorTarget* gt); 97 98 /** Get the top-level registry key for this VS version. */ 99 std::string GetRegistryBase(); 100 101 /** Get the top-level registry key for the given VS version. */ 102 static std::string GetRegistryBase(const char* version); 103 104 /** Return true if the generated build tree may contain multiple builds. 105 i.e. "Can I build Debug and Release in the same tree?" */ IsMultiConfig()106 bool IsMultiConfig() const override { return true; } 107 108 /** Return true if building for Windows CE */ TargetsWindowsCE()109 virtual bool TargetsWindowsCE() const { return false; } 110 IsIncludeExternalMSProjectSupported()111 bool IsIncludeExternalMSProjectSupported() const override { return true; } 112 113 /** Get encoding used by generator for generated source files 114 */ GetMakefileEncoding()115 codecvt::Encoding GetMakefileEncoding() const override 116 { 117 return codecvt::ANSI; 118 } 119 120 class TargetSet : public std::set<cmGeneratorTarget const*> 121 { 122 }; 123 class TargetCompare 124 { 125 std::string First; 126 127 public: TargetCompare(std::string const & first)128 TargetCompare(std::string const& first) 129 : First(first) 130 { 131 } 132 bool operator()(cmGeneratorTarget const* l, 133 cmGeneratorTarget const* r) const; 134 }; 135 class OrderedTargetDependSet; 136 137 bool FindMakeProgram(cmMakefile*) override; 138 139 std::string ExpandCFGIntDir(const std::string& str, 140 const std::string& config) const override; 141 142 void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; 143 144 std::string GetStartupProjectName(cmLocalGenerator const* root) const; 145 146 void AddSymbolExportCommand(cmGeneratorTarget*, 147 std::vector<cmCustomCommand>& commands, 148 std::string const& configName); 149 150 bool Open(const std::string& bindir, const std::string& projectName, 151 bool dryRun) override; 152 IsVisualStudio()153 bool IsVisualStudio() const override { return true; } 154 155 protected: 156 cmGlobalVisualStudioGenerator(cmake* cm, 157 std::string const& platformInGeneratorName); 158 159 void AddExtraIDETargets() override; 160 161 // Does this VS version link targets to each other if there are 162 // dependencies in the SLN file? This was done for VS versions 163 // below 8. VSLinksDependencies()164 virtual bool VSLinksDependencies() const { return true; } 165 166 const char* GetIDEVersion() const; 167 168 void WriteSLNHeader(std::ostream& fout); 169 170 bool ComputeTargetDepends() override; 171 class VSDependSet : public std::set<std::string> 172 { 173 }; 174 class VSDependMap : public std::map<cmGeneratorTarget const*, VSDependSet> 175 { 176 }; 177 VSDependMap VSTargetDepends; 178 void ComputeVSTargetDepends(cmGeneratorTarget*); 179 180 bool CheckTargetLinks(cmGeneratorTarget& target, const std::string& name); 181 std::string GetUtilityForTarget(cmGeneratorTarget& target, 182 const std::string&); 183 virtual std::string WriteUtilityDepend(cmGeneratorTarget const*) = 0; 184 std::string GetUtilityDepend(const cmGeneratorTarget* target); 185 using UtilityDependsMap = std::map<cmGeneratorTarget const*, std::string>; 186 UtilityDependsMap UtilityDepends; 187 188 protected: 189 VSVersion Version; 190 bool ExpressEdition; 191 192 std::string GeneratorPlatform; 193 std::string DefaultPlatformName; 194 bool PlatformInGeneratorName = false; 195 196 private: 197 virtual std::string GetVSMakeProgram() = 0; PrintCompilerAdvice(std::ostream &,std::string const &,cmValue)198 void PrintCompilerAdvice(std::ostream&, std::string const&, 199 cmValue) const override 200 { 201 } 202 203 void FollowLinkDepends(cmGeneratorTarget const* target, 204 std::set<cmGeneratorTarget const*>& linked); 205 206 class TargetSetMap : public std::map<cmGeneratorTarget*, TargetSet> 207 { 208 }; 209 TargetSetMap TargetLinkClosure; 210 void FillLinkClosure(const cmGeneratorTarget* target, TargetSet& linked); 211 TargetSet const& GetTargetLinkClosure(cmGeneratorTarget* target); 212 }; 213 214 class cmGlobalVisualStudioGenerator::OrderedTargetDependSet 215 : public std::multiset<cmTargetDepend, 216 cmGlobalVisualStudioGenerator::TargetCompare> 217 { 218 using derived = std::multiset<cmTargetDepend, 219 cmGlobalVisualStudioGenerator::TargetCompare>; 220 221 public: 222 using TargetDependSet = cmGlobalGenerator::TargetDependSet; 223 using TargetSet = cmGlobalVisualStudioGenerator::TargetSet; 224 OrderedTargetDependSet(TargetDependSet const&, std::string const& first); 225 OrderedTargetDependSet(TargetSet const&, std::string const& first); 226 }; 227