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