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 <cstddef>
8 #include <iosfwd>
9 #include <map>
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <utility>
16 #include <vector>
17 
18 #include <cm/optional>
19 #include <cmext/algorithm>
20 
21 #include "cm_codecvt.hxx"
22 
23 #include "cmCustomCommandLines.h"
24 #include "cmDuration.h"
25 #include "cmExportSet.h"
26 #include "cmStateSnapshot.h"
27 #include "cmStringAlgorithms.h"
28 #include "cmSystemTools.h"
29 #include "cmTarget.h"
30 #include "cmTargetDepend.h"
31 #include "cmTransformDepfile.h"
32 #include "cmValue.h"
33 
34 #if !defined(CMAKE_BOOTSTRAP)
35 #  include <cm3p/json/value.h>
36 
37 #  include "cmFileLockPool.h"
38 #endif
39 
40 #define CMAKE_DIRECTORY_ID_SEP "::@"
41 
42 class cmDirectoryId;
43 class cmExportBuildFileGenerator;
44 class cmExternalMakefileProjectGenerator;
45 class cmGeneratorTarget;
46 class cmInstallRuntimeDependencySet;
47 class cmLinkLineComputer;
48 class cmLocalGenerator;
49 class cmMakefile;
50 class cmOutputConverter;
51 class cmSourceFile;
52 class cmState;
53 class cmStateDirectory;
54 class cmake;
55 
56 namespace detail {
AppendStrs(std::vector<std::string> &)57 inline void AppendStrs(std::vector<std::string>&)
58 {
59 }
60 template <typename T, typename... Ts>
AppendStrs(std::vector<std::string> & command,T && s,Ts &&...ts)61 inline void AppendStrs(std::vector<std::string>& command, T&& s, Ts&&... ts)
62 {
63   command.emplace_back(std::forward<T>(s));
64   AppendStrs(command, std::forward<Ts>(ts)...);
65 }
66 
67 struct GeneratedMakeCommand
68 {
69   // Add each argument as a separate element to the vector
70   template <typename... T>
AddGeneratedMakeCommand71   void Add(T&&... args)
72   {
73     // iterate the args and append each one
74     AppendStrs(this->PrimaryCommand, std::forward<T>(args)...);
75   }
76 
77   // Add each value in the iterators as a separate element to the vector
AddGeneratedMakeCommand78   void Add(std::vector<std::string>::const_iterator start,
79            std::vector<std::string>::const_iterator end)
80   {
81     cm::append(this->PrimaryCommand, start, end);
82   }
83 
PrintableGeneratedMakeCommand84   std::string Printable() const { return cmJoin(this->PrimaryCommand, " "); }
85 
86   std::vector<std::string> PrimaryCommand;
87   bool RequiresOutputForward = false;
88 };
89 }
90 
91 /** \class cmGlobalGenerator
92  * \brief Responsible for overseeing the generation process for the entire tree
93  *
94  * Subclasses of this class generate makefiles for various
95  * platforms.
96  */
97 class cmGlobalGenerator
98 {
99 public:
100   using LocalGeneratorVector = std::vector<std::unique_ptr<cmLocalGenerator>>;
101 
102   //! Free any memory allocated with the GlobalGenerator
103   cmGlobalGenerator(cmake* cm);
104   virtual ~cmGlobalGenerator();
105 
106   virtual std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
107     cmMakefile* mf);
108 
109   //! Get the name for this generator
GetName()110   virtual std::string GetName() const { return "Generic"; }
111 
112   /** Check whether the given name matches the current generator.  */
MatchesGeneratorName(const std::string & name)113   virtual bool MatchesGeneratorName(const std::string& name) const
114   {
115     return this->GetName() == name;
116   }
117 
118   /** Get encoding used by generator for makefile files */
GetMakefileEncoding()119   virtual codecvt::Encoding GetMakefileEncoding() const
120   {
121     return codecvt::None;
122   }
123 
124 #if !defined(CMAKE_BOOTSTRAP)
125   /** Get a JSON object describing the generator.  */
126   virtual Json::Value GetJson() const;
127 #endif
128 
129   /** Tell the generator about the target system.  */
SetSystemName(std::string const &,cmMakefile *)130   virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; }
131 
132   /** Set the generator-specific instance.  Returns true if supported.  */
133   virtual bool SetGeneratorInstance(std::string const& i, cmMakefile* mf);
134 
135   /** Set the generator-specific platform name.  Returns true if platform
136       is supported and false otherwise.  */
137   virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
138 
139   /** Set the generator-specific toolset name.  Returns true if toolset
140       is supported and false otherwise.  */
141   virtual bool SetGeneratorToolset(std::string const& ts, bool build,
142                                    cmMakefile* mf);
143 
144   /** Read any other cache entries needed for cmake --build. */
ReadCacheEntriesForBuild(const cmState &)145   virtual bool ReadCacheEntriesForBuild(const cmState& /*state*/)
146   {
147     return true;
148   }
149 
150   /**
151    * Create LocalGenerators and process the CMakeLists files. This does not
152    * actually produce any makefiles, DSPs, etc.
153    */
154   virtual void Configure();
155 
InspectConfigTypeVariables()156   virtual bool InspectConfigTypeVariables() { return true; }
157 
158   bool Compute();
AddExtraIDETargets()159   virtual void AddExtraIDETargets() {}
160 
161   enum TargetTypes
162   {
163     AllTargets,
164     ImportedOnly
165   };
166 
167   void CreateImportedGenerationObjects(
168     cmMakefile* mf, std::vector<std::string> const& targets,
169     std::vector<cmGeneratorTarget const*>& exports);
170   void CreateGenerationObjects(TargetTypes targetTypes = AllTargets);
171 
172   /**
173    * Generate the all required files for building this project/tree. This
174    * basically creates a series of LocalGenerators for each directory and
175    * requests that they Generate.
176    */
177   virtual void Generate();
178 
179   virtual std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer(
180     cmOutputConverter* outputConverter,
181     cmStateDirectory const& stateDir) const;
182 
183   std::unique_ptr<cmLinkLineComputer> CreateMSVC60LinkLineComputer(
184     cmOutputConverter* outputConverter,
185     cmStateDirectory const& stateDir) const;
186 
187   /**
188    * Set/Get and Clear the enabled languages.
189    */
190   void SetLanguageEnabled(const std::string&, cmMakefile* mf);
191   bool GetLanguageEnabled(const std::string&) const;
192   void ClearEnabledLanguages();
193   void GetEnabledLanguages(std::vector<std::string>& lang) const;
194   /**
195    * Try to determine system information such as shared library
196    * extension, pthreads, byte order etc.
197    */
198   virtual void EnableLanguage(std::vector<std::string> const& languages,
199                               cmMakefile*, bool optional);
200 
201   /**
202    * Resolve the CMAKE_<lang>_COMPILER setting for the given language.
203    * Intended to be called from EnableLanguage.
204    */
205   void ResolveLanguageCompiler(const std::string& lang, cmMakefile* mf,
206                                bool optional) const;
207 
208   /**
209    * Try to determine system information, get it from another generator
210    */
211   void EnableLanguagesFromGenerator(cmGlobalGenerator* gen, cmMakefile* mf);
212 
213   /**
214    * Try running cmake and building a file. This is used for dynamically
215    * loaded commands, not as part of the usual build process.
216    */
217   int TryCompile(int jobs, const std::string& srcdir,
218                  const std::string& bindir, const std::string& projectName,
219                  const std::string& targetName, bool fast, std::string& output,
220                  cmMakefile* mf);
221 
222   /**
223    * Build a file given the following information. This is a more direct call
224    * that is used by both CTest and TryCompile. If target name is NULL or
225    * empty then all is assumed. clean indicates if a "make clean" should be
226    * done first.
227    */
228   int Build(
229     int jobs, const std::string& srcdir, const std::string& bindir,
230     const std::string& projectName,
231     std::vector<std::string> const& targetNames, std::string& output,
232     const std::string& makeProgram, const std::string& config, bool clean,
233     bool fast, bool verbose, cmDuration timeout,
234     cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_NONE,
235     std::vector<std::string> const& nativeOptions =
236       std::vector<std::string>());
237 
238   /**
239    * Open a generated IDE project given the following information.
240    */
241   virtual bool Open(const std::string& bindir, const std::string& projectName,
242                     bool dryRun);
243 
244   struct GeneratedMakeCommand final : public detail::GeneratedMakeCommand
245   {
246   };
247 
248   virtual std::vector<GeneratedMakeCommand> GenerateBuildCommand(
249     const std::string& makeProgram, const std::string& projectName,
250     const std::string& projectDir, std::vector<std::string> const& targetNames,
251     const std::string& config, bool fast, int jobs, bool verbose,
252     std::vector<std::string> const& makeOptions = std::vector<std::string>());
253 
254   virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
255 
256   /**
257    * Generate a "cmake --build" call for a given target, config and parallel
258    * level.
259    */
260   std::string GenerateCMakeBuildCommand(const std::string& target,
261                                         const std::string& config,
262                                         const std::string& parallel,
263                                         const std::string& native,
264                                         bool ignoreErrors);
265 
266   //! Get the CMake instance
GetCMakeInstance()267   cmake* GetCMakeInstance() const { return this->CMakeInstance; }
268 
269   void SetConfiguredFilesPath(cmGlobalGenerator* gen);
GetMakefiles()270   const std::vector<std::unique_ptr<cmMakefile>>& GetMakefiles() const
271   {
272     return this->Makefiles;
273   }
GetLocalGenerators()274   const LocalGeneratorVector& GetLocalGenerators() const
275   {
276     return this->LocalGenerators;
277   }
278 
279   std::vector<cmGeneratorTarget*> GetLocalGeneratorTargetsInOrder(
280     cmLocalGenerator* lg) const;
281 
GetCurrentMakefile()282   cmMakefile* GetCurrentMakefile() const
283   {
284     return this->CurrentConfigureMakefile;
285   }
286 
SetCurrentMakefile(cmMakefile * mf)287   void SetCurrentMakefile(cmMakefile* mf)
288   {
289     this->CurrentConfigureMakefile = mf;
290   }
291 
292   void AddMakefile(std::unique_ptr<cmMakefile> mf);
293 
294   //! Set an generator for an "external makefile based project"
295   void SetExternalMakefileProjectGenerator(
296     std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator);
297 
298   std::string GetExtraGeneratorName() const;
299 
300   void AddInstallComponent(const std::string& component);
301 
302   /** Mark the (absolute path to a) file as generated.  */
303   void MarkAsGeneratedFile(const std::string& filepath);
304   /** Determine if the absolute filepath belongs to a generated file.  */
305   bool IsGeneratedFile(const std::string& filepath);
306 
GetInstallComponents()307   const std::set<std::string>* GetInstallComponents() const
308   {
309     return &this->InstallComponents;
310   }
311 
GetExportSets()312   cmExportSetMap& GetExportSets() { return this->ExportSets; }
313 
314   cmValue GetGlobalSetting(std::string const& name) const;
315   bool GlobalSettingIsOn(std::string const& name) const;
316   std::string GetSafeGlobalSetting(std::string const& name) const;
317 
318   /** Add a file to the manifest of generated targets for a configuration.  */
319   void AddToManifest(std::string const& f);
320 
321   void EnableInstallTarget();
322 
323   cmDuration TryCompileTimeout;
324 
GetForceUnixPaths()325   bool GetForceUnixPaths() const { return this->ForceUnixPaths; }
GetToolSupportsColor()326   bool GetToolSupportsColor() const { return this->ToolSupportsColor; }
327 
328   //! return the language for the given extension
329   std::string GetLanguageFromExtension(const char* ext) const;
330   //! is an extension to be ignored
331   bool IgnoreFile(const char* ext) const;
332   //! What is the preference for linkers and this language (None or Preferred)
333   int GetLinkerPreference(const std::string& lang) const;
334   //! What is the object file extension for a given source file?
335   std::string GetLanguageOutputExtension(cmSourceFile const&) const;
336 
337   //! What is the configurations directory variable called?
GetCMakeCFGIntDir()338   virtual const char* GetCMakeCFGIntDir() const { return "."; }
339 
340   //! expand CFGIntDir for a configuration
341   virtual std::string ExpandCFGIntDir(const std::string& str,
342                                       const std::string& config) const;
343 
344   /** Get whether the generator should use a script for link commands.  */
GetUseLinkScript()345   bool GetUseLinkScript() const { return this->UseLinkScript; }
346 
347   /** Get whether the generator should produce special marks on rules
348       producing symbolic (non-file) outputs.  */
GetNeedSymbolicMark()349   bool GetNeedSymbolicMark() const { return this->NeedSymbolicMark; }
350 
351   /*
352    * Determine what program to use for building the project.
353    */
354   virtual bool FindMakeProgram(cmMakefile*);
355 
356   //! Find a target by name by searching the local generators.
357   cmTarget* FindTarget(const std::string& name,
358                        bool excludeAliases = false) const;
359 
360   cmGeneratorTarget* FindGeneratorTarget(const std::string& name) const;
361 
362   void AddAlias(const std::string& name, const std::string& tgtName);
363   bool IsAlias(const std::string& name) const;
364 
365   /** Determine if a name resolves to a framework on disk or a built target
366       that is a framework. */
367   bool NameResolvesToFramework(const std::string& libname) const;
368 
369   cmMakefile* FindMakefile(const std::string& start_dir) const;
370   cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
371 
372   /** Append the subdirectory for the given configuration.  If anything is
373       appended the given prefix and suffix will be appended around it, which
374       is useful for leading or trailing slashes.  */
375   virtual void AppendDirectoryForConfig(const std::string& prefix,
376                                         const std::string& config,
377                                         const std::string& suffix,
378                                         std::string& dir);
379 
380   /** Get the content of a directory.  Directory listings are cached
381       and re-loaded from disk only when modified.  During the generation
382       step the content will include the target files to be built even if
383       they do not yet exist.  */
384   std::set<std::string> const& GetDirectoryContent(std::string const& dir,
385                                                    bool needDisk = true);
386 
387   void IndexTarget(cmTarget* t);
388   void IndexGeneratorTarget(cmGeneratorTarget* gt);
389 
390   // Index the target using a name that is unique to that target
391   // even if other targets have the same name.
392   std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt);
393 
394   static bool IsReservedTarget(std::string const& name);
395 
GetAllTargetName()396   virtual const char* GetAllTargetName() const { return "ALL_BUILD"; }
GetInstallTargetName()397   virtual const char* GetInstallTargetName() const { return "INSTALL"; }
GetInstallLocalTargetName()398   virtual const char* GetInstallLocalTargetName() const { return nullptr; }
GetInstallStripTargetName()399   virtual const char* GetInstallStripTargetName() const { return nullptr; }
GetPreinstallTargetName()400   virtual const char* GetPreinstallTargetName() const { return nullptr; }
GetTestTargetName()401   virtual const char* GetTestTargetName() const { return "RUN_TESTS"; }
GetPackageTargetName()402   virtual const char* GetPackageTargetName() const { return "PACKAGE"; }
GetPackageSourceTargetName()403   virtual const char* GetPackageSourceTargetName() const { return nullptr; }
GetEditCacheTargetName()404   virtual const char* GetEditCacheTargetName() const { return nullptr; }
GetRebuildCacheTargetName()405   virtual const char* GetRebuildCacheTargetName() const { return nullptr; }
GetCleanTargetName()406   virtual const char* GetCleanTargetName() const { return nullptr; }
407 
408   // Lookup edit_cache target command preferred by this generator.
GetEditCacheCommand()409   virtual std::string GetEditCacheCommand() const { return ""; }
410 
411   // Default config to use for cmake --build
GetDefaultBuildConfig()412   virtual std::string GetDefaultBuildConfig() const { return "Debug"; }
413 
414   // Class to track a set of dependencies.
415   using TargetDependSet = cmTargetDependSet;
416 
417   // what targets does the specified target depend on directly
418   // via a target_link_libraries or add_dependencies
419   TargetDependSet const& GetTargetDirectDepends(
420     const cmGeneratorTarget* target);
421 
GetProjectMap()422   const std::map<std::string, std::vector<cmLocalGenerator*>>& GetProjectMap()
423     const
424   {
425     return this->ProjectMap;
426   }
427 
428   // track files replaced during a Generate
429   void FileReplacedDuringGenerate(const std::string& filename);
430   void GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames);
431 
432   void AddRuleHash(const std::vector<std::string>& outputs,
433                    std::string const& content);
434 
435   /** Return whether the given binary directory is unused.  */
BinaryDirectoryIsNew(const std::string & dir)436   bool BinaryDirectoryIsNew(const std::string& dir)
437   {
438     return this->BinaryDirectories.insert(dir).second;
439   }
440 
441   /** Return true if the generated build tree may contain multiple builds.
442       i.e. "Can I build Debug and Release in the same tree?" */
IsMultiConfig()443   virtual bool IsMultiConfig() const { return false; }
444 
IsXcode()445   virtual bool IsXcode() const { return false; }
446 
IsVisualStudio()447   virtual bool IsVisualStudio() const { return false; }
448 
IsVisualStudioAtLeast10()449   virtual bool IsVisualStudioAtLeast10() const { return false; }
450 
IsNinja()451   virtual bool IsNinja() const { return false; }
452 
453   /** Return true if we know the exact location of object files.
454       If false, store the reason in the given string.
455       This is meaningful only after EnableLanguage has been called.  */
HasKnownObjectFileLocation(std::string *)456   virtual bool HasKnownObjectFileLocation(std::string*) const { return true; }
457 
458   virtual bool UseFolderProperty() const;
459 
IsIPOSupported()460   virtual bool IsIPOSupported() const { return false; }
461 
462   /** Return whether the generator can import external visual studio project
463       using INCLUDE_EXTERNAL_MSPROJECT */
IsIncludeExternalMSProjectSupported()464   virtual bool IsIncludeExternalMSProjectSupported() const { return false; }
465 
466   /** Return whether the generator should use EFFECTIVE_PLATFORM_NAME. This is
467       relevant for mixed macOS and iOS builds. */
UseEffectivePlatformName(cmMakefile *)468   virtual bool UseEffectivePlatformName(cmMakefile*) const { return false; }
469 
470   /** Return whether the "Resources" folder prefix should be stripped from
471       MacFolder. */
472   virtual bool ShouldStripResourcePath(cmMakefile*) const;
473 
SupportsCustomCommandDepfile()474   virtual bool SupportsCustomCommandDepfile() const { return false; }
DepfileFormat()475   virtual cm::optional<cmDepfileFormat> DepfileFormat() const
476   {
477     return cm::nullopt;
478   }
479 
480   std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
481 
482   /** Generate an <output>.rule file path for a given command output.  */
483   virtual std::string GenerateRuleFile(std::string const& output) const;
484 
SupportsDefaultBuildType()485   virtual bool SupportsDefaultBuildType() const { return false; }
SupportsCrossConfigs()486   virtual bool SupportsCrossConfigs() const { return false; }
SupportsDefaultConfigs()487   virtual bool SupportsDefaultConfigs() const { return false; }
488 
489   static std::string EscapeJSON(const std::string& s);
490 
491   void ProcessEvaluationFiles();
492 
GetBuildExportSets()493   std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets()
494   {
495     return this->BuildExportSets;
496   }
497   void AddBuildExportSet(cmExportBuildFileGenerator* gen);
498   void AddBuildExportExportSet(cmExportBuildFileGenerator* gen);
499   bool IsExportedTargetsFile(const std::string& filename) const;
500   bool GenerateImportFile(const std::string& file);
501   cmExportBuildFileGenerator* GetExportedTargetsFile(
502     const std::string& filename) const;
503   void AddCMP0042WarnTarget(const std::string& target);
504   void AddCMP0068WarnTarget(const std::string& target);
505 
506   virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
507 
508   bool GenerateCPackPropertiesFile();
509 
510   void SetFilenameTargetDepends(
511     cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts);
512   const std::set<const cmGeneratorTarget*>& GetFilenameTargetDepends(
513     cmSourceFile* sf) const;
514 
515 #if !defined(CMAKE_BOOTSTRAP)
GetFileLockPool()516   cmFileLockPool& GetFileLockPool() { return this->FileLockPool; }
517 #endif
518 
GetConfigureDoneCMP0026()519   bool GetConfigureDoneCMP0026() const
520   {
521     return this->ConfigureDoneCMP0026AndCMP0024;
522   }
523 
524   std::string MakeSilentFlag;
525 
526   int RecursionDepth;
527 
GetQtAutoGenConfigs(std::vector<std::string> & configs)528   virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const
529   {
530     configs.emplace_back("$<CONFIG>");
531   }
532 
533   std::string const& GetRealPath(std::string const& dir);
534 
535   std::string NewDeferId();
536 
537   cmInstallRuntimeDependencySet* CreateAnonymousRuntimeDependencySet();
538 
539   cmInstallRuntimeDependencySet* GetNamedRuntimeDependencySet(
540     const std::string& name);
541 
542 protected:
543   // for a project collect all its targets by following depend
544   // information, and also collect all the targets
545   void GetTargetSets(TargetDependSet& projectTargets,
546                      TargetDependSet& originalTargets, cmLocalGenerator* root,
547                      std::vector<cmLocalGenerator*>& generators);
548   bool IsRootOnlyTarget(cmGeneratorTarget* target) const;
549   void AddTargetDepends(const cmGeneratorTarget* target,
550                         TargetDependSet& projectTargets);
551   void SetLanguageEnabledFlag(const std::string& l, cmMakefile* mf);
552   void SetLanguageEnabledMaps(const std::string& l, cmMakefile* mf);
553   void FillExtensionToLanguageMap(const std::string& l, cmMakefile* mf);
554   virtual bool CheckLanguages(std::vector<std::string> const& languages,
555                               cmMakefile* mf) const;
556   virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
557                                    cmValue envVar) const;
558 
559   virtual bool ComputeTargetDepends();
560 
561   virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
562 
563   /// @brief Qt AUTOMOC/UIC/RCC target generation
564   /// @return true on success
565   bool QtAutoGen();
566 
567   bool AddAutomaticSources();
568 
569   std::string SelectMakeProgram(const std::string& makeProgram,
570                                 const std::string& makeDefault = "") const;
571 
572   // Fill the ProjectMap, this must be called after LocalGenerators
573   // has been populated.
574   void FillProjectMap();
575   void CheckTargetProperties();
576   bool IsExcluded(cmStateSnapshot const& root,
577                   cmStateSnapshot const& snp) const;
578   bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
579   bool IsExcluded(cmLocalGenerator* root,
580                   const cmGeneratorTarget* target) const;
InitializeProgressMarks()581   virtual void InitializeProgressMarks() {}
582 
583   struct GlobalTargetInfo
584   {
585     std::string Name;
586     std::string Message;
587     cmCustomCommandLines CommandLines;
588     std::vector<std::string> Depends;
589     std::string WorkingDir;
590     bool UsesTerminal = false;
591     cmTarget::PerConfig PerConfig = cmTarget::PerConfig::Yes;
592     bool StdPipesUTF8 = false;
593   };
594 
595   void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);
596 
597   void AddGlobalTarget_Package(std::vector<GlobalTargetInfo>& targets);
598   void AddGlobalTarget_PackageSource(std::vector<GlobalTargetInfo>& targets);
599   void AddGlobalTarget_Test(std::vector<GlobalTargetInfo>& targets);
600   void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets) const;
601   void AddGlobalTarget_RebuildCache(
602     std::vector<GlobalTargetInfo>& targets) const;
603   void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
604   void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
605 
606   std::string FindMakeProgramFile;
607   std::string ConfiguredFilesPath;
608   cmake* CMakeInstance;
609   std::vector<std::unique_ptr<cmMakefile>> Makefiles;
610   LocalGeneratorVector LocalGenerators;
611   cmMakefile* CurrentConfigureMakefile;
612   // map from project name to vector of local generators in that project
613   std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap;
614 
615   // Set of named installation components requested by the project.
616   std::set<std::string> InstallComponents;
617   // Sets of named target exports
618   cmExportSetMap ExportSets;
619   std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
620   std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
621 
622   std::map<std::string, std::string> AliasTargets;
623 
624   cmTarget* FindTargetImpl(std::string const& name) const;
625 
626   cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;
627 
628   std::string GetPredefinedTargetsFolder() const;
629 
630 private:
631   using TargetMap = std::unordered_map<std::string, cmTarget*>;
632   using GeneratorTargetMap =
633     std::unordered_map<std::string, cmGeneratorTarget*>;
634   using MakefileMap = std::unordered_map<std::string, cmMakefile*>;
635   using LocalGeneratorMap = std::unordered_map<std::string, cmLocalGenerator*>;
636   // Map efficiently from target name to cmTarget instance.
637   // Do not use this structure for looping over all targets.
638   // It contains both normal and globally visible imported targets.
639   TargetMap TargetSearchIndex;
640   GeneratorTargetMap GeneratorTargetSearchIndex;
641 
642   // Map efficiently from source directory path to cmMakefile instance.
643   // Do not use this structure for looping over all directories.
644   // It may not contain all of them (see note in IndexMakefile method).
645   MakefileMap MakefileSearchIndex;
646 
647   // Map efficiently from source directory path to cmLocalGenerator instance.
648   // Do not use this structure for looping over all directories.
649   // Its order is not deterministic.
650   LocalGeneratorMap LocalGeneratorSearchIndex;
651 
652   void ComputeTargetOrder();
653   void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index);
654   std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;
655 
656   cmMakefile* TryCompileOuterMakefile;
657   // If you add a new map here, make sure it is copied
658   // in EnableLanguagesFromGenerator
659   std::map<std::string, bool> IgnoreExtensions;
660   std::set<std::string> LanguagesReady; // Ready for try_compile
661   std::set<std::string> LanguagesInProgress;
662   std::map<std::string, std::string> OutputExtensions;
663   std::map<std::string, std::string> LanguageToOutputExtension;
664   std::map<std::string, std::string> ExtensionToLanguage;
665   std::map<std::string, int> LanguageToLinkerPreference;
666   std::map<std::string, std::string> LanguageToOriginalSharedLibFlags;
667 
668   // Deferral id generation.
669   size_t NextDeferId = 0;
670 
671   // Record hashes for rules and outputs.
672   struct RuleHash
673   {
674     char Data[32];
675   };
676   std::map<std::string, RuleHash> RuleHashes;
677   void CheckRuleHashes();
678   void CheckRuleHashes(std::string const& pfile, std::string const& home);
679   void WriteRuleHashes(std::string const& pfile);
680 
681   void WriteSummary();
682   void WriteSummary(cmGeneratorTarget* target);
683   void FinalizeTargetCompileInfo();
684 
685   virtual void ForceLinkerLanguages();
686 
687   bool CheckTargetsForMissingSources() const;
688   bool CheckTargetsForType() const;
689   bool CheckTargetsForPchCompilePdb() const;
690 
691   void CreateLocalGenerators();
692 
693   void CheckCompilerIdCompatibility(cmMakefile* mf,
694                                     std::string const& lang) const;
695 
696   void ComputeBuildFileGenerators();
697 
698   std::unique_ptr<cmExternalMakefileProjectGenerator> ExtraGenerator;
699 
700   // track files replaced during a Generate
701   std::vector<std::string> FilesReplacedDuringGenerate;
702 
703   // Store computed inter-target dependencies.
704   using TargetDependMap = std::map<cmGeneratorTarget const*, TargetDependSet>;
705   TargetDependMap TargetDependencies;
706 
707   friend class cmake;
708   void CreateGeneratorTargets(
709     TargetTypes targetTypes, cmMakefile* mf, cmLocalGenerator* lg,
710     std::map<cmTarget*, cmGeneratorTarget*> const& importedMap);
711   void CreateGeneratorTargets(TargetTypes targetTypes);
712 
713   void ClearGeneratorMembers();
714 
715   bool CheckCMP0037(std::string const& targetName,
716                     std::string const& reason) const;
717 
718   void IndexMakefile(cmMakefile* mf);
719   void IndexLocalGenerator(cmLocalGenerator* lg);
720 
GetBuildIgnoreErrorsFlag()721   virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; }
722 
723   bool UnsupportedVariableIsDefined(const std::string& name,
724                                     bool supported) const;
725 
726   // Cache directory content and target files to be built.
727   struct DirectoryContent
728   {
729     long LastDiskTime = -1;
730     std::set<std::string> All;
731     std::set<std::string> Generated;
732   };
733   std::map<std::string, DirectoryContent> DirectoryContentMap;
734 
735   // Set of binary directories on disk.
736   std::set<std::string> BinaryDirectories;
737 
738   // track targets to issue CMP0042 warning for.
739   std::set<std::string> CMP0042WarnTargets;
740   // track targets to issue CMP0068 warning for.
741   std::set<std::string> CMP0068WarnTargets;
742 
743   mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*>>
744     FilenameTargetDepends;
745 
746   std::map<std::string, std::string> RealPaths;
747 
748   std::unordered_set<std::string> GeneratedFiles;
749 
750   std::vector<std::unique_ptr<cmInstallRuntimeDependencySet>>
751     RuntimeDependencySets;
752   std::map<std::string, cmInstallRuntimeDependencySet*>
753     RuntimeDependencySetsByName;
754 
755 #if !defined(CMAKE_BOOTSTRAP)
756   // Pool of file locks
757   cmFileLockPool FileLockPool;
758 #endif
759 
760 protected:
761   float FirstTimeProgress;
762   bool NeedSymbolicMark;
763   bool UseLinkScript;
764   bool ForceUnixPaths;
765   bool ToolSupportsColor;
766   bool InstallTargetEnabled;
767   bool ConfigureDoneCMP0026AndCMP0024;
768 };
769