Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Source / cmGlobalGenerator.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmGlobalGenerator.h"
4
5 #include <algorithm>
6 #include <cassert>
7 #include <cstdio>
8 #include <cstdlib>
9 #include <cstring>
10 #include <functional>
11 #include <initializer_list>
12 #include <iterator>
13 #include <sstream>
14 #include <utility>
15
16 #include <cm/memory>
17 #include <cm/optional>
18 #include <cmext/algorithm>
19 #include <cmext/string_view>
20
21 #include "cmsys/Directory.hxx"
22 #include "cmsys/FStream.hxx"
23 #include "cmsys/RegularExpression.hxx"
24
25 #if defined(_WIN32) && !defined(__CYGWIN__)
26 #  include <windows.h>
27 #endif
28
29 #include "cmAlgorithms.h"
30 #include "cmCPackPropertiesGenerator.h"
31 #include "cmComputeTargetDepends.h"
32 #include "cmCustomCommand.h"
33 #include "cmCustomCommandLines.h"
34 #include "cmDuration.h"
35 #include "cmExportBuildFileGenerator.h"
36 #include "cmExternalMakefileProjectGenerator.h"
37 #include "cmGeneratedFileStream.h"
38 #include "cmGeneratorExpression.h"
39 #include "cmGeneratorTarget.h"
40 #include "cmInstallGenerator.h"
41 #include "cmInstallRuntimeDependencySet.h"
42 #include "cmLinkLineComputer.h"
43 #include "cmLocalGenerator.h"
44 #include "cmMSVC60LinkLineComputer.h"
45 #include "cmMakefile.h"
46 #include "cmMessageType.h"
47 #include "cmPolicies.h"
48 #include "cmRange.h"
49 #include "cmSourceFile.h"
50 #include "cmState.h"
51 #include "cmStateDirectory.h"
52 #include "cmStateTypes.h"
53 #include "cmStringAlgorithms.h"
54 #include "cmSystemTools.h"
55 #include "cmValue.h"
56 #include "cmVersion.h"
57 #include "cmWorkingDirectory.h"
58 #include "cmake.h"
59
60 #if !defined(CMAKE_BOOTSTRAP)
61 #  include <cm3p/json/value.h>
62 #  include <cm3p/json/writer.h>
63
64 #  include "cmCryptoHash.h"
65 #  include "cmQtAutoGenGlobalInitializer.h"
66 #endif
67
68 const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =
69   "CMAKE_PLATFORM_INFO_INITIALIZED";
70
71 class cmInstalledFile;
72
73 bool cmTarget::StrictTargetComparison::operator()(cmTarget const* t1,
74                                                   cmTarget const* t2) const
75 {
76   int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
77   if (nameResult == 0) {
78     return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory().c_str(),
79                   t2->GetMakefile()->GetCurrentBinaryDirectory().c_str()) < 0;
80   }
81   return nameResult < 0;
82 }
83
84 cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
85   : CMakeInstance(cm)
86 {
87   // By default the .SYMBOLIC dependency is not needed on symbolic rules.
88   this->NeedSymbolicMark = false;
89
90   // by default use the native paths
91   this->ForceUnixPaths = false;
92
93   // By default do not try to support color.
94   this->ToolSupportsColor = false;
95
96   // By default do not use link scripts.
97   this->UseLinkScript = false;
98
99   // Whether an install target is needed.
100   this->InstallTargetEnabled = false;
101
102   // how long to let try compiles run
103   this->TryCompileTimeout = cmDuration::zero();
104
105   this->CurrentConfigureMakefile = nullptr;
106   this->TryCompileOuterMakefile = nullptr;
107
108   this->ConfigureDoneCMP0026AndCMP0024 = false;
109   this->FirstTimeProgress = 0.0f;
110
111   this->RecursionDepth = 0;
112
113   cm->GetState()->SetIsGeneratorMultiConfig(false);
114   cm->GetState()->SetMinGWMake(false);
115   cm->GetState()->SetMSYSShell(false);
116   cm->GetState()->SetNMake(false);
117   cm->GetState()->SetWatcomWMake(false);
118   cm->GetState()->SetWindowsShell(false);
119   cm->GetState()->SetWindowsVSIDE(false);
120 }
121
122 cmGlobalGenerator::~cmGlobalGenerator()
123 {
124   this->ClearGeneratorMembers();
125 }
126
127 #if !defined(CMAKE_BOOTSTRAP)
128 Json::Value cmGlobalGenerator::GetJson() const
129 {
130   Json::Value generator = Json::objectValue;
131   generator["name"] = this->GetName();
132   generator["multiConfig"] = this->IsMultiConfig();
133   return generator;
134 }
135 #endif
136
137 bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i,
138                                              cmMakefile* mf)
139 {
140   if (i.empty()) {
141     return true;
142   }
143
144   std::ostringstream e;
145   /* clang-format off */
146   e <<
147     "Generator\n"
148     "  " << this->GetName() << "\n"
149     "does not support instance specification, but instance\n"
150     "  " << i << "\n"
151     "was specified.";
152   /* clang-format on */
153   mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
154   return false;
155 }
156
157 bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
158                                              cmMakefile* mf)
159 {
160   if (p.empty()) {
161     return true;
162   }
163
164   std::ostringstream e;
165   /* clang-format off */
166   e <<
167     "Generator\n"
168     "  " << this->GetName() << "\n"
169     "does not support platform specification, but platform\n"
170     "  " << p << "\n"
171     "was specified.";
172   /* clang-format on */
173   mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
174   return false;
175 }
176
177 bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, bool,
178                                             cmMakefile* mf)
179 {
180   if (ts.empty()) {
181     return true;
182   }
183   std::ostringstream e;
184   /* clang-format off */
185   e <<
186     "Generator\n"
187     "  " << this->GetName() << "\n"
188     "does not support toolset specification, but toolset\n"
189     "  " << ts << "\n"
190     "was specified.";
191   /* clang-format on */
192   mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
193   return false;
194 }
195
196 std::string cmGlobalGenerator::SelectMakeProgram(
197   const std::string& inMakeProgram, const std::string& makeDefault) const
198 {
199   std::string makeProgram = inMakeProgram;
200   if (cmIsOff(makeProgram)) {
201     cmValue makeProgramCSTR =
202       this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
203     if (cmIsOff(makeProgramCSTR)) {
204       makeProgram = makeDefault;
205     } else {
206       makeProgram = *makeProgramCSTR;
207     }
208     if (cmIsOff(makeProgram) && !makeProgram.empty()) {
209       makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND";
210     }
211   }
212   return makeProgram;
213 }
214
215 void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
216                                                 cmMakefile* mf,
217                                                 bool optional) const
218 {
219   std::string langComp = cmStrCat("CMAKE_", lang, "_COMPILER");
220
221   if (!mf->GetDefinition(langComp)) {
222     if (!optional) {
223       cmSystemTools::Error(langComp + " not set, after EnableLanguage");
224     }
225     return;
226   }
227   std::string const& name = mf->GetRequiredDefinition(langComp);
228   std::string path;
229   if (!cmSystemTools::FileIsFullPath(name)) {
230     path = cmSystemTools::FindProgram(name);
231   } else {
232     path = name;
233   }
234   if (!optional && (path.empty() || !cmSystemTools::FileExists(path))) {
235     return;
236   }
237   cmValue cname =
238     this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp);
239
240   // Split compiler from arguments
241   std::vector<std::string> cnameArgVec;
242   if (cname && !cname->empty()) {
243     cmExpandList(*cname, cnameArgVec);
244     cname = cmValue(cnameArgVec.front());
245   }
246
247   std::string changeVars;
248   if (cname && !optional) {
249     std::string cnameString;
250     if (!cmSystemTools::FileIsFullPath(*cname)) {
251       cnameString = cmSystemTools::FindProgram(*cname);
252     } else {
253       cnameString = *cname;
254     }
255     std::string pathString = path;
256     // get rid of potentially multiple slashes:
257     cmSystemTools::ConvertToUnixSlashes(cnameString);
258     cmSystemTools::ConvertToUnixSlashes(pathString);
259     if (cnameString != pathString) {
260       cmValue cvars = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
261         "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
262       if (cvars) {
263         changeVars += *cvars;
264         changeVars += ";";
265       }
266       changeVars += langComp;
267       changeVars += ";";
268       changeVars += *cname;
269       this->GetCMakeInstance()->GetState()->SetGlobalProperty(
270         "__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars.c_str());
271     }
272   }
273 }
274
275 void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen)
276 {
277   this->BuildExportSets[gen->GetMainExportFileName()] = gen;
278 }
279
280 void cmGlobalGenerator::AddBuildExportExportSet(
281   cmExportBuildFileGenerator* gen)
282 {
283   this->BuildExportExportSets[gen->GetMainExportFileName()] = gen;
284   this->AddBuildExportSet(gen);
285 }
286
287 bool cmGlobalGenerator::GenerateImportFile(const std::string& file)
288 {
289   auto const it = this->BuildExportSets.find(file);
290   if (it != this->BuildExportSets.end()) {
291     bool result = it->second->GenerateImportFile();
292
293     if (!this->ConfigureDoneCMP0026AndCMP0024) {
294       for (const auto& m : this->Makefiles) {
295         m->RemoveExportBuildFileGeneratorCMP0024(it->second);
296       }
297     }
298
299     this->BuildExportSets.erase(it);
300     return result;
301   }
302   return false;
303 }
304
305 void cmGlobalGenerator::ForceLinkerLanguages()
306 {
307 }
308
309 bool cmGlobalGenerator::CheckTargetsForMissingSources() const
310 {
311   bool failed = false;
312   for (const auto& localGen : this->LocalGenerators) {
313     for (const auto& target : localGen->GetGeneratorTargets()) {
314       if (!target->CanCompileSources() ||
315           cmIsOn(target->GetProperty("ghs_integrity_app"))) {
316         continue;
317       }
318
319       if (target->GetAllConfigSources().empty()) {
320         std::ostringstream e;
321         e << "No SOURCES given to target: " << target->GetName();
322         this->GetCMakeInstance()->IssueMessage(
323           MessageType::FATAL_ERROR, e.str(), target->GetBacktrace());
324         failed = true;
325       }
326     }
327   }
328   return failed;
329 }
330
331 void cmGlobalGenerator::CheckTargetLinkLibraries() const
332 {
333   for (const auto& generator : this->LocalGenerators) {
334     for (const auto& gt : generator->GetGeneratorTargets()) {
335       gt->CheckLinkLibraries();
336     }
337     for (const auto& gt : generator->GetOwnedImportedGeneratorTargets()) {
338       gt->CheckLinkLibraries();
339     }
340   }
341 }
342
343 bool cmGlobalGenerator::CheckTargetsForType() const
344 {
345   if (!this->GetLanguageEnabled("Swift")) {
346     return false;
347   }
348   bool failed = false;
349   for (const auto& generator : this->LocalGenerators) {
350     for (const auto& target : generator->GetGeneratorTargets()) {
351       std::string systemName =
352         target->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
353       if (systemName.find("Windows") == std::string::npos) {
354         continue;
355       }
356
357       if (target->GetType() == cmStateEnums::EXECUTABLE) {
358         std::vector<std::string> const& configs =
359           target->Makefile->GetGeneratorConfigs(
360             cmMakefile::IncludeEmptyConfig);
361         for (std::string const& config : configs) {
362           if (target->IsWin32Executable(config) &&
363               target->GetLinkerLanguage(config) == "Swift") {
364             this->GetCMakeInstance()->IssueMessage(
365               MessageType::FATAL_ERROR,
366               "WIN32_EXECUTABLE property is not supported on Swift "
367               "executables",
368               target->GetBacktrace());
369             failed = true;
370           }
371         }
372       }
373     }
374   }
375   return failed;
376 }
377
378 bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const
379 {
380   if (!this->GetLanguageEnabled("C") && !this->GetLanguageEnabled("CXX")) {
381     return false;
382   }
383   bool failed = false;
384   for (const auto& generator : this->LocalGenerators) {
385     for (const auto& target : generator->GetGeneratorTargets()) {
386       if (!target->CanCompileSources() ||
387           cmIsOn(target->GetProperty("ghs_integrity_app"))) {
388         continue;
389       }
390
391       std::string const& reuseFrom =
392         target->GetSafeProperty("PRECOMPILE_HEADERS_REUSE_FROM");
393       std::string const& compilePdb =
394         target->GetSafeProperty("COMPILE_PDB_NAME");
395
396       if (!reuseFrom.empty() && reuseFrom != compilePdb) {
397         const std::string e = cmStrCat(
398           "PRECOMPILE_HEADERS_REUSE_FROM property is set on target (\"",
399           target->GetName(),
400           "\"). Reusable precompile headers requires the COMPILE_PDB_NAME"
401           " property to have the value \"",
402           reuseFrom, "\"\n");
403         this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
404                                                target->GetBacktrace());
405         failed = true;
406       }
407     }
408   }
409   return failed;
410 }
411
412 bool cmGlobalGenerator::IsExportedTargetsFile(
413   const std::string& filename) const
414 {
415   auto const it = this->BuildExportSets.find(filename);
416   if (it == this->BuildExportSets.end()) {
417     return false;
418   }
419   return !cm::contains(this->BuildExportExportSets, filename);
420 }
421
422 // Find the make program for the generator, required for try compiles
423 bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
424 {
425   if (this->FindMakeProgramFile.empty()) {
426     cmSystemTools::Error(
427       "Generator implementation error, "
428       "all generators must specify this->FindMakeProgramFile");
429     return false;
430   }
431   if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
432     std::string setMakeProgram = mf->GetModulesFile(this->FindMakeProgramFile);
433     if (!setMakeProgram.empty()) {
434       mf->ReadListFile(setMakeProgram);
435     }
436   }
437   if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
438     std::ostringstream err;
439     err << "CMake was unable to find a build program corresponding to \""
440         << this->GetName() << "\".  CMAKE_MAKE_PROGRAM is not set.  You "
441         << "probably need to select a different build tool.";
442     cmSystemTools::Error(err.str());
443     cmSystemTools::SetFatalErrorOccurred();
444     return false;
445   }
446   std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
447   // if there are spaces in the make program use short path
448   // but do not short path the actual program name, as
449   // this can cause trouble with VSExpress
450   if (makeProgram.find(' ') != std::string::npos) {
451     std::string dir;
452     std::string file;
453     cmSystemTools::SplitProgramPath(makeProgram, dir, file);
454     std::string saveFile = file;
455     cmSystemTools::GetShortPath(makeProgram, makeProgram);
456     cmSystemTools::SplitProgramPath(makeProgram, dir, file);
457     makeProgram = cmStrCat(dir, '/', saveFile);
458     mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram, "make program",
459                            cmStateEnums::FILEPATH);
460   }
461   return true;
462 }
463
464 bool cmGlobalGenerator::CheckLanguages(
465   std::vector<std::string> const& /* languages */, cmMakefile* /* mf */) const
466 {
467   return true;
468 }
469
470 // enable the given language
471 //
472 // The following files are loaded in this order:
473 //
474 // First figure out what OS we are running on:
475 //
476 // CMakeSystem.cmake - configured file created by CMakeDetermineSystem.cmake
477 //   CMakeDetermineSystem.cmake - figure out os info and create
478 //                                CMakeSystem.cmake IF CMAKE_SYSTEM
479 //                                not set
480 //   CMakeSystem.cmake - configured file created by
481 //                       CMakeDetermineSystem.cmake IF CMAKE_SYSTEM_LOADED
482
483 // CMakeSystemSpecificInitialize.cmake
484 //   - includes Platform/${CMAKE_SYSTEM_NAME}-Initialize.cmake
485
486 // Next try and enable all languages found in the languages vector
487 //
488 // FOREACH LANG in languages
489 //   CMake(LANG)Compiler.cmake - configured file create by
490 //                               CMakeDetermine(LANG)Compiler.cmake
491 //     CMakeDetermine(LANG)Compiler.cmake - Finds compiler for LANG and
492 //                                          creates CMake(LANG)Compiler.cmake
493 //     CMake(LANG)Compiler.cmake - configured file created by
494 //                                 CMakeDetermine(LANG)Compiler.cmake
495 //
496 // CMakeSystemSpecificInformation.cmake
497 //   - includes Platform/${CMAKE_SYSTEM_NAME}.cmake
498 //     may use compiler stuff
499
500 // FOREACH LANG in languages
501 //   CMake(LANG)Information.cmake
502 //     - loads Platform/${CMAKE_SYSTEM_NAME}-${COMPILER}.cmake
503 //   CMakeTest(LANG)Compiler.cmake
504 //     - Make sure the compiler works with a try compile if
505 //       CMakeDetermine(LANG) was loaded
506 //
507 // Now load a few files that can override values set in any of the above
508 // (PROJECTNAME)Compatibility.cmake
509 //   - load any backwards compatibility stuff for current project
510 // ${CMAKE_USER_MAKE_RULES_OVERRIDE}
511 //   - allow users a chance to override system variables
512 //
513 //
514
515 void cmGlobalGenerator::EnableLanguage(
516   std::vector<std::string> const& languages, cmMakefile* mf, bool optional)
517 {
518   if (!this->IsMultiConfig() &&
519       !this->GetCMakeInstance()->GetIsInTryCompile()) {
520     std::string envBuildType;
521     if (!mf->GetDefinition("CMAKE_BUILD_TYPE") &&
522         cmSystemTools::GetEnv("CMAKE_BUILD_TYPE", envBuildType)) {
523       mf->AddCacheDefinition(
524         "CMAKE_BUILD_TYPE", envBuildType,
525         "Choose the type of build.  Options include: empty, "
526         "Debug, Release, RelWithDebInfo, MinSizeRel.",
527         cmStateEnums::STRING);
528     }
529   }
530
531   if (languages.empty()) {
532     cmSystemTools::Error("EnableLanguage must have a lang specified!");
533     cmSystemTools::SetFatalErrorOccurred();
534     return;
535   }
536
537   std::set<std::string> cur_languages(languages.begin(), languages.end());
538   for (std::string const& li : cur_languages) {
539     if (!this->LanguagesInProgress.insert(li).second) {
540       std::ostringstream e;
541       e << "Language '" << li
542         << "' is currently being enabled.  "
543            "Recursive call not allowed.";
544       mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
545       cmSystemTools::SetFatalErrorOccurred();
546       return;
547     }
548   }
549
550   if (this->TryCompileOuterMakefile) {
551     // In a try-compile we can only enable languages provided by caller.
552     for (std::string const& lang : languages) {
553       if (lang == "NONE") {
554         this->SetLanguageEnabled("NONE", mf);
555       } else {
556         if (!cm::contains(this->LanguagesReady, lang)) {
557           std::ostringstream e;
558           e << "The test project needs language " << lang
559             << " which is not enabled.";
560           this->TryCompileOuterMakefile->IssueMessage(MessageType::FATAL_ERROR,
561                                                       e.str());
562           cmSystemTools::SetFatalErrorOccurred();
563           return;
564         }
565       }
566     }
567   }
568
569   bool fatalError = false;
570
571   mf->AddDefinitionBool("RUN_CONFIGURE", true);
572   std::string rootBin =
573     cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
574
575   // If the configuration files path has been set,
576   // then we are in a try compile and need to copy the enable language
577   // files from the parent cmake bin dir, into the try compile bin dir
578   if (!this->ConfiguredFilesPath.empty()) {
579     rootBin = this->ConfiguredFilesPath;
580   }
581   rootBin += '/';
582   rootBin += cmVersion::GetCMakeVersion();
583
584   // set the dir for parent files so they can be used by modules
585   mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR", rootBin);
586
587   if (!this->CMakeInstance->GetIsInTryCompile()) {
588     // Keep a mark in the cache to indicate that we've initialized the
589     // platform information directory.  If the platform information
590     // directory exists but the mark is missing then CMakeCache.txt
591     // has been removed or replaced without also removing the CMakeFiles/
592     // directory.  In this case remove the platform information directory
593     // so that it will be re-initialized and the relevant information
594     // restored in the cache.
595     if (cmSystemTools::FileIsDirectory(rootBin) &&
596         !mf->IsOn(kCMAKE_PLATFORM_INFO_INITIALIZED)) {
597       cmSystemTools::RemoveADirectory(rootBin);
598     }
599     this->GetCMakeInstance()->AddCacheEntry(
600       kCMAKE_PLATFORM_INFO_INITIALIZED, "1",
601       "Platform information initialized", cmStateEnums::INTERNAL);
602   }
603
604   // try and load the CMakeSystem.cmake if it is there
605   std::string fpath = rootBin;
606   bool const readCMakeSystem = !mf->GetDefinition("CMAKE_SYSTEM_LOADED");
607   if (readCMakeSystem) {
608     fpath += "/CMakeSystem.cmake";
609     if (cmSystemTools::FileExists(fpath)) {
610       mf->ReadListFile(fpath);
611     }
612   }
613
614   //  Load the CMakeDetermineSystem.cmake file and find out
615   // what platform we are running on
616   if (!mf->GetDefinition("CMAKE_SYSTEM")) {
617 #if defined(_WIN32) && !defined(__CYGWIN__)
618     cmSystemTools::WindowsVersion windowsVersion =
619       cmSystemTools::GetWindowsVersion();
620     std::ostringstream windowsVersionString;
621     windowsVersionString << windowsVersion.dwMajorVersion << "."
622                          << windowsVersion.dwMinorVersion << "."
623                          << windowsVersion.dwBuildNumber;
624     mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", windowsVersionString.str());
625 #endif
626     // Read the DetermineSystem file
627     std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
628     mf->ReadListFile(systemFile);
629     // load the CMakeSystem.cmake from the binary directory
630     // this file is configured by the CMakeDetermineSystem.cmake file
631     fpath = cmStrCat(rootBin, "/CMakeSystem.cmake");
632     mf->ReadListFile(fpath);
633   }
634
635   if (readCMakeSystem) {
636     // Tell the generator about the instance, if any.
637     std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
638     if (!this->SetGeneratorInstance(instance, mf)) {
639       cmSystemTools::SetFatalErrorOccurred();
640       return;
641     }
642
643     // Tell the generator about the target system.
644     std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
645     if (!this->SetSystemName(system, mf)) {
646       cmSystemTools::SetFatalErrorOccurred();
647       return;
648     }
649
650     // Tell the generator about the platform, if any.
651     std::string platform = mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM");
652     if (!this->SetGeneratorPlatform(platform, mf)) {
653       cmSystemTools::SetFatalErrorOccurred();
654       return;
655     }
656
657     // Tell the generator about the toolset, if any.
658     std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET");
659     if (!this->SetGeneratorToolset(toolset, false, mf)) {
660       cmSystemTools::SetFatalErrorOccurred();
661       return;
662     }
663
664     // Find the native build tool for this generator.
665     if (!this->FindMakeProgram(mf)) {
666       return;
667     }
668
669     // One-time includes of user-provided project setup files
670     mf->GetState()->SetInTopLevelIncludes(true);
671     std::string includes =
672       mf->GetSafeDefinition("CMAKE_PROJECT_TOP_LEVEL_INCLUDES");
673     std::vector<std::string> includesList = cmExpandedList(includes);
674     for (std::string const& setupFile : includesList) {
675       std::string absSetupFile = cmSystemTools::CollapseFullPath(
676         setupFile, mf->GetCurrentSourceDirectory());
677       if (!cmSystemTools::FileExists(absSetupFile)) {
678         cmSystemTools::Error(
679           "CMAKE_PROJECT_TOP_LEVEL_INCLUDES file does not exist: " +
680           setupFile);
681         mf->GetState()->SetInTopLevelIncludes(false);
682         return;
683       }
684       if (cmSystemTools::FileIsDirectory(absSetupFile)) {
685         cmSystemTools::Error(
686           "CMAKE_PROJECT_TOP_LEVEL_INCLUDES file is a directory: " +
687           setupFile);
688         mf->GetState()->SetInTopLevelIncludes(false);
689         return;
690       }
691       if (!mf->ReadListFile(absSetupFile)) {
692         cmSystemTools::Error(
693           "Failed reading CMAKE_PROJECT_TOP_LEVEL_INCLUDES file: " +
694           setupFile);
695         mf->GetState()->SetInTopLevelIncludes(false);
696         return;
697       }
698     }
699   }
700   mf->GetState()->SetInTopLevelIncludes(false);
701
702   // Check that the languages are supported by the generator and its
703   // native build tool found above.
704   if (!this->CheckLanguages(languages, mf)) {
705     return;
706   }
707
708   // **** Load the system specific initialization if not yet loaded
709   if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED")) {
710     fpath = mf->GetModulesFile("CMakeSystemSpecificInitialize.cmake");
711     if (!mf->ReadListFile(fpath)) {
712       cmSystemTools::Error("Could not find cmake module file: "
713                            "CMakeSystemSpecificInitialize.cmake");
714     }
715   }
716
717   std::map<std::string, bool> needTestLanguage;
718   std::map<std::string, bool> needSetLanguageEnabledMaps;
719   // foreach language
720   // load the CMakeDetermine(LANG)Compiler.cmake file to find
721   // the compiler
722
723   for (std::string const& lang : languages) {
724     needSetLanguageEnabledMaps[lang] = false;
725     if (lang == "NONE") {
726       this->SetLanguageEnabled("NONE", mf);
727       continue;
728     }
729     std::string loadedLang = cmStrCat("CMAKE_", lang, "_COMPILER_LOADED");
730     if (!mf->GetDefinition(loadedLang)) {
731       fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
732
733       // If the existing build tree was already configured with this
734       // version of CMake then try to load the configured file first
735       // to avoid duplicate compiler tests.
736       if (cmSystemTools::FileExists(fpath)) {
737         if (!mf->ReadListFile(fpath)) {
738           cmSystemTools::Error("Could not find cmake module file: " + fpath);
739         }
740         // if this file was found then the language was already determined
741         // to be working
742         needTestLanguage[lang] = false;
743         this->SetLanguageEnabledFlag(lang, mf);
744         needSetLanguageEnabledMaps[lang] = true;
745         // this can only be called after loading CMake(LANG)Compiler.cmake
746       }
747     }
748
749     if (!this->GetLanguageEnabled(lang)) {
750       if (this->CMakeInstance->GetIsInTryCompile()) {
751         cmSystemTools::Error("This should not have happened. "
752                              "If you see this message, you are probably "
753                              "using a broken CMakeLists.txt file or a "
754                              "problematic release of CMake");
755       }
756       // if the CMake(LANG)Compiler.cmake file was not found then
757       // load CMakeDetermine(LANG)Compiler.cmake
758       std::string determineCompiler =
759         cmStrCat("CMakeDetermine", lang, "Compiler.cmake");
760       std::string determineFile = mf->GetModulesFile(determineCompiler);
761       if (!mf->ReadListFile(determineFile)) {
762         cmSystemTools::Error("Could not find cmake module file: " +
763                              determineCompiler);
764       }
765       if (cmSystemTools::GetFatalErrorOccurred()) {
766         return;
767       }
768       needTestLanguage[lang] = true;
769       // Some generators like visual studio should not use the env variables
770       // So the global generator can specify that in this variable
771       if ((mf->GetPolicyStatus(cmPolicies::CMP0132) == cmPolicies::OLD ||
772            mf->GetPolicyStatus(cmPolicies::CMP0132) == cmPolicies::WARN) &&
773           !mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV")) {
774         // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
775         // into the environment, in case user scripts want to run
776         // configure, or sub cmakes
777         std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
778         std::string compilerEnv =
779           cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
780         const std::string& envVar = mf->GetRequiredDefinition(compilerEnv);
781         const std::string& envVarValue =
782           mf->GetRequiredDefinition(compilerName);
783         std::string env = cmStrCat(envVar, '=', envVarValue);
784         cmSystemTools::PutEnv(env);
785       }
786
787       // if determineLanguage was called then load the file it
788       // configures CMake(LANG)Compiler.cmake
789       fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
790       if (!mf->ReadListFile(fpath)) {
791         cmSystemTools::Error("Could not find cmake module file: " + fpath);
792       }
793       this->SetLanguageEnabledFlag(lang, mf);
794       needSetLanguageEnabledMaps[lang] = true;
795       // this can only be called after loading CMake(LANG)Compiler.cmake
796       // the language must be enabled for try compile to work, but we do
797       // not know if it is a working compiler yet so set the test language
798       // flag
799       needTestLanguage[lang] = true;
800     } // end if(!this->GetLanguageEnabled(lang) )
801   }   // end loop over languages
802
803   // **** Load the system specific information if not yet loaded
804   if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED")) {
805     fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
806     if (!mf->ReadListFile(fpath)) {
807       cmSystemTools::Error("Could not find cmake module file: "
808                            "CMakeSystemSpecificInformation.cmake");
809     }
810   }
811   // loop over languages again loading CMake(LANG)Information.cmake
812   //
813   for (std::string const& lang : languages) {
814     if (lang == "NONE") {
815       this->SetLanguageEnabled("NONE", mf);
816       continue;
817     }
818
819     // Check that the compiler was found.
820     std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
821     std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
822     std::ostringstream noCompiler;
823     cmValue compilerFile = mf->GetDefinition(compilerName);
824     if (!cmNonempty(compilerFile) || cmIsNOTFOUND(*compilerFile)) {
825       /* clang-format off */
826       noCompiler <<
827         "No " << compilerName << " could be found.\n"
828         ;
829       /* clang-format on */
830     } else if ((lang != "RC") && (lang != "ASM_MASM")) {
831       if (!cmSystemTools::FileIsFullPath(*compilerFile)) {
832         /* clang-format off */
833         noCompiler <<
834           "The " << compilerName << ":\n"
835           "  " << *compilerFile << "\n"
836           "is not a full path and was not found in the PATH.\n"
837           ;
838         /* clang-format on */
839       } else if (!cmSystemTools::FileExists(*compilerFile)) {
840         /* clang-format off */
841         noCompiler <<
842           "The " << compilerName << ":\n"
843           "  " << *compilerFile << "\n"
844           "is not a full path to an existing compiler tool.\n"
845           ;
846         /* clang-format on */
847       }
848     }
849     if (!noCompiler.str().empty()) {
850       // Skip testing this language since the compiler is not found.
851       needTestLanguage[lang] = false;
852       if (!optional) {
853         // The compiler was not found and it is not optional.  Remove
854         // CMake(LANG)Compiler.cmake so we try again next time CMake runs.
855         std::string compilerLangFile =
856           cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
857         cmSystemTools::RemoveFile(compilerLangFile);
858         if (!this->CMakeInstance->GetIsInTryCompile()) {
859           this->PrintCompilerAdvice(noCompiler, lang,
860                                     mf->GetDefinition(compilerEnv));
861           mf->IssueMessage(MessageType::FATAL_ERROR, noCompiler.str());
862           fatalError = true;
863         }
864       }
865     }
866
867     std::string langLoadedVar =
868       cmStrCat("CMAKE_", lang, "_INFORMATION_LOADED");
869     if (!mf->GetDefinition(langLoadedVar)) {
870       fpath = cmStrCat("CMake", lang, "Information.cmake");
871       std::string informationFile = mf->GetModulesFile(fpath);
872       if (informationFile.empty()) {
873         cmSystemTools::Error("Could not find cmake module file: " + fpath);
874       } else if (!mf->ReadListFile(informationFile)) {
875         cmSystemTools::Error("Could not process cmake module file: " +
876                              informationFile);
877       }
878     }
879     if (needSetLanguageEnabledMaps[lang]) {
880       this->SetLanguageEnabledMaps(lang, mf);
881     }
882     this->LanguagesReady.insert(lang);
883
884     // Test the compiler for the language just setup
885     // (but only if a compiler has been actually found)
886     // At this point we should have enough info for a try compile
887     // which is used in the backward stuff
888     // If the language is untested then test it now with a try compile.
889     if (needTestLanguage[lang]) {
890       if (!this->CMakeInstance->GetIsInTryCompile()) {
891         std::string testLang = cmStrCat("CMakeTest", lang, "Compiler.cmake");
892         std::string ifpath = mf->GetModulesFile(testLang);
893         if (!mf->ReadListFile(ifpath)) {
894           cmSystemTools::Error("Could not find cmake module file: " +
895                                testLang);
896         }
897         std::string compilerWorks =
898           cmStrCat("CMAKE_", lang, "_COMPILER_WORKS");
899         // if the compiler did not work, then remove the
900         // CMake(LANG)Compiler.cmake file so that it will get tested the
901         // next time cmake is run
902         if (!mf->IsOn(compilerWorks)) {
903           std::string compilerLangFile =
904             cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
905           cmSystemTools::RemoveFile(compilerLangFile);
906         }
907       } // end if in try compile
908     }   // end need test language
909     // Store the shared library flags so that we can satisfy CMP0018
910     std::string sharedLibFlagsVar =
911       cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS");
912     this->LanguageToOriginalSharedLibFlags[lang] =
913       mf->GetSafeDefinition(sharedLibFlagsVar);
914
915     // Translate compiler ids for compatibility.
916     this->CheckCompilerIdCompatibility(mf, lang);
917   } // end for each language
918
919   // Now load files that can override any settings on the platform or for
920   // the project First load the project compatibility file if it is in
921   // cmake
922   std::string projectCompatibility =
923     cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/",
924              mf->GetSafeDefinition("PROJECT_NAME"), "Compatibility.cmake");
925   if (cmSystemTools::FileExists(projectCompatibility)) {
926     mf->ReadListFile(projectCompatibility);
927   }
928   // Inform any extra generator of the new language.
929   if (this->ExtraGenerator) {
930     this->ExtraGenerator->EnableLanguage(languages, mf, false);
931   }
932
933   if (fatalError) {
934     cmSystemTools::SetFatalErrorOccurred();
935   }
936
937   for (std::string const& lang : cur_languages) {
938     this->LanguagesInProgress.erase(lang);
939   }
940 }
941
942 void cmGlobalGenerator::PrintCompilerAdvice(std::ostream& os,
943                                             std::string const& lang,
944                                             cmValue envVar) const
945 {
946   // Subclasses override this method if they do not support this advice.
947   os << "Tell CMake where to find the compiler by setting ";
948   if (envVar) {
949     os << "either the environment variable \"" << envVar << "\" or ";
950   }
951   os << "the CMake cache entry CMAKE_" << lang
952      << "_COMPILER "
953         "to the full path to the compiler, or to the compiler name "
954         "if it is in the PATH.";
955 }
956
957 void cmGlobalGenerator::CheckCompilerIdCompatibility(
958   cmMakefile* mf, std::string const& lang) const
959 {
960   std::string compilerIdVar = "CMAKE_" + lang + "_COMPILER_ID";
961   std::string const compilerId = mf->GetSafeDefinition(compilerIdVar);
962
963   if (compilerId == "AppleClang") {
964     switch (mf->GetPolicyStatus(cmPolicies::CMP0025)) {
965       case cmPolicies::WARN:
966         if (!this->CMakeInstance->GetIsInTryCompile() &&
967             mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0025")) {
968           std::ostringstream w;
969           /* clang-format off */
970           w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0025) << "\n"
971             "Converting " << lang <<
972             R"( compiler id "AppleClang" to "Clang" for compatibility.)"
973             ;
974           /* clang-format on */
975           mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
976         }
977         CM_FALLTHROUGH;
978       case cmPolicies::OLD:
979         // OLD behavior is to convert AppleClang to Clang.
980         mf->AddDefinition(compilerIdVar, "Clang");
981         break;
982       case cmPolicies::REQUIRED_IF_USED:
983       case cmPolicies::REQUIRED_ALWAYS:
984         mf->IssueMessage(
985           MessageType::FATAL_ERROR,
986           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025));
987         break;
988       case cmPolicies::NEW:
989         // NEW behavior is to keep AppleClang.
990         break;
991     }
992   }
993
994   if (compilerId == "QCC") {
995     switch (mf->GetPolicyStatus(cmPolicies::CMP0047)) {
996       case cmPolicies::WARN:
997         if (!this->CMakeInstance->GetIsInTryCompile() &&
998             mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0047")) {
999           std::ostringstream w;
1000           /* clang-format off */
1001           w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0047) << "\n"
1002             "Converting " << lang <<
1003             R"( compiler id "QCC" to "GNU" for compatibility.)"
1004             ;
1005           /* clang-format on */
1006           mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
1007         }
1008         CM_FALLTHROUGH;
1009       case cmPolicies::OLD:
1010         // OLD behavior is to convert QCC to GNU.
1011         mf->AddDefinition(compilerIdVar, "GNU");
1012         if (lang == "C") {
1013           mf->AddDefinition("CMAKE_COMPILER_IS_GNUCC", "1");
1014         } else if (lang == "CXX") {
1015           mf->AddDefinition("CMAKE_COMPILER_IS_GNUCXX", "1");
1016         }
1017         break;
1018       case cmPolicies::REQUIRED_IF_USED:
1019       case cmPolicies::REQUIRED_ALWAYS:
1020         mf->IssueMessage(
1021           MessageType::FATAL_ERROR,
1022           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047));
1023         CM_FALLTHROUGH;
1024       case cmPolicies::NEW:
1025         // NEW behavior is to keep QCC.
1026         break;
1027     }
1028   }
1029
1030   if (compilerId == "XLClang") {
1031     switch (mf->GetPolicyStatus(cmPolicies::CMP0089)) {
1032       case cmPolicies::WARN:
1033         if (!this->CMakeInstance->GetIsInTryCompile() &&
1034             mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0089")) {
1035           std::ostringstream w;
1036           /* clang-format off */
1037           w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0089) << "\n"
1038             "Converting " << lang <<
1039             R"( compiler id "XLClang" to "XL" for compatibility.)"
1040             ;
1041           /* clang-format on */
1042           mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
1043         }
1044         CM_FALLTHROUGH;
1045       case cmPolicies::OLD:
1046         // OLD behavior is to convert XLClang to XL.
1047         mf->AddDefinition(compilerIdVar, "XL");
1048         break;
1049       case cmPolicies::REQUIRED_IF_USED:
1050       case cmPolicies::REQUIRED_ALWAYS:
1051         mf->IssueMessage(
1052           MessageType::FATAL_ERROR,
1053           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0089));
1054         break;
1055       case cmPolicies::NEW:
1056         // NEW behavior is to keep AppleClang.
1057         break;
1058     }
1059   }
1060
1061   if (compilerId == "LCC") {
1062     switch (mf->GetPolicyStatus(cmPolicies::CMP0129)) {
1063       case cmPolicies::WARN:
1064         if (!this->CMakeInstance->GetIsInTryCompile() &&
1065             mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0129")) {
1066           std::ostringstream w;
1067           /* clang-format off */
1068           w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0129) << "\n"
1069             "Converting " << lang <<
1070             R"( compiler id "LCC" to "GNU" for compatibility.)"
1071             ;
1072           /* clang-format on */
1073           mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
1074         }
1075         CM_FALLTHROUGH;
1076       case cmPolicies::OLD:
1077         // OLD behavior is to convert LCC to GNU.
1078         mf->AddDefinition(compilerIdVar, "GNU");
1079         if (lang == "C") {
1080           mf->AddDefinition("CMAKE_COMPILER_IS_GNUCC", "1");
1081         } else if (lang == "CXX") {
1082           mf->AddDefinition("CMAKE_COMPILER_IS_GNUCXX", "1");
1083         } else if (lang == "Fortran") {
1084           mf->AddDefinition("CMAKE_COMPILER_IS_GNUG77", "1");
1085         }
1086         {
1087           // Fix compiler versions.
1088           std::string version = "CMAKE_" + lang + "_COMPILER_VERSION";
1089           std::string emulated = "CMAKE_" + lang + "_SIMULATE_VERSION";
1090           std::string emulatedId = "CMAKE_" + lang + "_SIMULATE_ID";
1091           std::string const& actual = mf->GetRequiredDefinition(emulated);
1092           mf->AddDefinition(version, actual);
1093           mf->RemoveDefinition(emulatedId);
1094           mf->RemoveDefinition(emulated);
1095         }
1096         break;
1097       case cmPolicies::REQUIRED_IF_USED:
1098       case cmPolicies::REQUIRED_ALWAYS:
1099         mf->IssueMessage(
1100           MessageType::FATAL_ERROR,
1101           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0129));
1102         CM_FALLTHROUGH;
1103       case cmPolicies::NEW:
1104         // NEW behavior is to keep LCC.
1105         break;
1106     }
1107   }
1108 }
1109
1110 std::string cmGlobalGenerator::GetLanguageOutputExtension(
1111   cmSourceFile const& source) const
1112 {
1113   const std::string& lang = source.GetLanguage();
1114   if (!lang.empty()) {
1115     auto const it = this->LanguageToOutputExtension.find(lang);
1116     if (it != this->LanguageToOutputExtension.end()) {
1117       return it->second;
1118     }
1119   } else {
1120     // if no language is found then check to see if it is already an
1121     // output extension for some language.  In that case it should be ignored
1122     // and in this map, so it will not be compiled but will just be used.
1123     std::string const& ext = source.GetExtension();
1124     if (!ext.empty()) {
1125       if (this->OutputExtensions.count(ext)) {
1126         return ext;
1127       }
1128     }
1129   }
1130   return "";
1131 }
1132
1133 std::string cmGlobalGenerator::GetLanguageFromExtension(const char* ext) const
1134 {
1135   // if there is an extension and it starts with . then move past the
1136   // . because the extensions are not stored with a .  in the map
1137   if (!ext) {
1138     return "";
1139   }
1140   if (*ext == '.') {
1141     ++ext;
1142   }
1143   auto const it = this->ExtensionToLanguage.find(ext);
1144   if (it != this->ExtensionToLanguage.end()) {
1145     return it->second;
1146   }
1147   return "";
1148 }
1149
1150 /* SetLanguageEnabled() is now split in two parts:
1151 at first the enabled-flag is set. This can then be used in EnabledLanguage()
1152 for checking whether the language is already enabled. After setting this
1153 flag still the values from the cmake variables have to be copied into the
1154 internal maps, this is done in SetLanguageEnabledMaps() which is called
1155 after the system- and compiler specific files have been loaded.
1156
1157 This split was done originally so that compiler-specific configuration
1158 files could change the object file extension
1159 (CMAKE_<LANG>_OUTPUT_EXTENSION) before the CMake variables were copied
1160 to the C++ maps.
1161 */
1162 void cmGlobalGenerator::SetLanguageEnabled(const std::string& l,
1163                                            cmMakefile* mf)
1164 {
1165   this->SetLanguageEnabledFlag(l, mf);
1166   this->SetLanguageEnabledMaps(l, mf);
1167 }
1168
1169 void cmGlobalGenerator::SetLanguageEnabledFlag(const std::string& l,
1170                                                cmMakefile* mf)
1171 {
1172   this->CMakeInstance->GetState()->SetLanguageEnabled(l);
1173
1174   // Fill the language-to-extension map with the current variable
1175   // settings to make sure it is available for the try_compile()
1176   // command source file signature.  In SetLanguageEnabledMaps this
1177   // will be done again to account for any compiler- or
1178   // platform-specific entries.
1179   this->FillExtensionToLanguageMap(l, mf);
1180 }
1181
1182 void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
1183                                                cmMakefile* mf)
1184 {
1185   // use LanguageToLinkerPreference to detect whether this functions has
1186   // run before
1187   if (cm::contains(this->LanguageToLinkerPreference, l)) {
1188     return;
1189   }
1190
1191   std::string linkerPrefVar = "CMAKE_" + l + "_LINKER_PREFERENCE";
1192   cmValue linkerPref = mf->GetDefinition(linkerPrefVar);
1193   int preference = 0;
1194   if (cmNonempty(linkerPref)) {
1195     if (sscanf(linkerPref->c_str(), "%d", &preference) != 1) {
1196       // backward compatibility: before 2.6 LINKER_PREFERENCE
1197       // was either "None" or "Preferred", and only the first character was
1198       // tested. So if there is a custom language out there and it is
1199       // "Preferred", set its preference high
1200       if ((*linkerPref)[0] == 'P') {
1201         preference = 100;
1202       } else {
1203         preference = 0;
1204       }
1205     }
1206   }
1207
1208   if (preference < 0) {
1209     std::string msg =
1210       cmStrCat(linkerPrefVar, " is negative, adjusting it to 0");
1211     cmSystemTools::Message(msg, "Warning");
1212     preference = 0;
1213   }
1214
1215   this->LanguageToLinkerPreference[l] = preference;
1216
1217   std::string outputExtensionVar = "CMAKE_" + l + "_OUTPUT_EXTENSION";
1218   if (cmValue p = mf->GetDefinition(outputExtensionVar)) {
1219     std::string outputExtension = *p;
1220     this->LanguageToOutputExtension[l] = outputExtension;
1221     this->OutputExtensions[outputExtension] = outputExtension;
1222     if (cmHasPrefix(outputExtension, ".")) {
1223       outputExtension = outputExtension.substr(1);
1224       this->OutputExtensions[outputExtension] = outputExtension;
1225     }
1226   }
1227
1228   // The map was originally filled by SetLanguageEnabledFlag, but
1229   // since then the compiler- and platform-specific files have been
1230   // loaded which might have added more entries.
1231   this->FillExtensionToLanguageMap(l, mf);
1232
1233   std::string ignoreExtensionsVar =
1234     std::string("CMAKE_") + std::string(l) + std::string("_IGNORE_EXTENSIONS");
1235   std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar);
1236   std::vector<std::string> extensionList = cmExpandedList(ignoreExts);
1237   for (std::string const& i : extensionList) {
1238     this->IgnoreExtensions[i] = true;
1239   }
1240 }
1241
1242 void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l,
1243                                                    cmMakefile* mf)
1244 {
1245   std::string extensionsVar = std::string("CMAKE_") + std::string(l) +
1246     std::string("_SOURCE_FILE_EXTENSIONS");
1247   const std::string& exts = mf->GetSafeDefinition(extensionsVar);
1248   std::vector<std::string> extensionList = cmExpandedList(exts);
1249   for (std::string const& i : extensionList) {
1250     this->ExtensionToLanguage[i] = l;
1251   }
1252 }
1253
1254 cmValue cmGlobalGenerator::GetGlobalSetting(std::string const& name) const
1255 {
1256   assert(!this->Makefiles.empty());
1257   return this->Makefiles[0]->GetDefinition(name);
1258 }
1259
1260 bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const
1261 {
1262   assert(!this->Makefiles.empty());
1263   return this->Makefiles[0]->IsOn(name);
1264 }
1265
1266 std::string cmGlobalGenerator::GetSafeGlobalSetting(
1267   std::string const& name) const
1268 {
1269   assert(!this->Makefiles.empty());
1270   return this->Makefiles[0]->GetDefinition(name);
1271 }
1272
1273 bool cmGlobalGenerator::IgnoreFile(const char* ext) const
1274 {
1275   if (!this->GetLanguageFromExtension(ext).empty()) {
1276     return false;
1277   }
1278   return (this->IgnoreExtensions.count(ext) > 0);
1279 }
1280
1281 bool cmGlobalGenerator::GetLanguageEnabled(const std::string& l) const
1282 {
1283   return this->CMakeInstance->GetState()->GetLanguageEnabled(l);
1284 }
1285
1286 void cmGlobalGenerator::ClearEnabledLanguages()
1287 {
1288   this->CMakeInstance->GetState()->ClearEnabledLanguages();
1289 }
1290
1291 void cmGlobalGenerator::CreateLocalGenerators()
1292 {
1293   this->LocalGeneratorSearchIndex.clear();
1294   this->LocalGenerators.clear();
1295   this->LocalGenerators.reserve(this->Makefiles.size());
1296   for (const auto& m : this->Makefiles) {
1297     auto lg = this->CreateLocalGenerator(m.get());
1298     this->IndexLocalGenerator(lg.get());
1299     this->LocalGenerators.push_back(std::move(lg));
1300   }
1301 }
1302
1303 void cmGlobalGenerator::Configure()
1304 {
1305   this->FirstTimeProgress = 0.0f;
1306   this->ClearGeneratorMembers();
1307   this->NextDeferId = 0;
1308
1309   cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
1310
1311   snapshot.GetDirectory().SetCurrentSource(
1312     this->CMakeInstance->GetHomeDirectory());
1313   snapshot.GetDirectory().SetCurrentBinary(
1314     this->CMakeInstance->GetHomeOutputDirectory());
1315
1316   auto dirMfu = cm::make_unique<cmMakefile>(this, snapshot);
1317   auto* dirMf = dirMfu.get();
1318   this->Makefiles.push_back(std::move(dirMfu));
1319   dirMf->SetRecursionDepth(this->RecursionDepth);
1320   this->IndexMakefile(dirMf);
1321
1322   this->BinaryDirectories.insert(
1323     this->CMakeInstance->GetHomeOutputDirectory());
1324
1325   // now do it
1326   this->ConfigureDoneCMP0026AndCMP0024 = false;
1327   dirMf->Configure();
1328   dirMf->EnforceDirectoryLevelRules();
1329
1330   this->ConfigureDoneCMP0026AndCMP0024 = true;
1331
1332   // Put a copy of each global target in every directory.
1333   {
1334     std::vector<GlobalTargetInfo> globalTargets;
1335     this->CreateDefaultGlobalTargets(globalTargets);
1336
1337     for (const auto& mf : this->Makefiles) {
1338       for (GlobalTargetInfo const& globalTarget : globalTargets) {
1339         this->CreateGlobalTarget(globalTarget, mf.get());
1340       }
1341     }
1342   }
1343
1344   // update the cache entry for the number of local generators, this is used
1345   // for progress
1346   char num[100];
1347   snprintf(num, sizeof(num), "%d", static_cast<int>(this->Makefiles.size()));
1348   this->GetCMakeInstance()->AddCacheEntry("CMAKE_NUMBER_OF_MAKEFILES", num,
1349                                           "number of local generators",
1350                                           cmStateEnums::INTERNAL);
1351
1352   if (this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) {
1353     std::ostringstream msg;
1354     if (cmSystemTools::GetErrorOccurredFlag()) {
1355       msg << "Configuring incomplete, errors occurred!";
1356       const char* logs[] = { "CMakeOutput.log", "CMakeError.log", nullptr };
1357       for (const char** log = logs; *log; ++log) {
1358         std::string f = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
1359                                  "/CMakeFiles/", *log);
1360         if (cmSystemTools::FileExists(f)) {
1361           msg << "\nSee also \"" << f << "\".";
1362         }
1363       }
1364     } else {
1365       msg << "Configuring done";
1366     }
1367     this->CMakeInstance->UpdateProgress(msg.str(), -1);
1368   }
1369 }
1370
1371 void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes)
1372 {
1373   this->CreateLocalGenerators();
1374   // Commit side effects only if we are actually generating
1375   if (this->GetConfigureDoneCMP0026()) {
1376     this->CheckTargetProperties();
1377   }
1378   this->CreateGeneratorTargets(targetTypes);
1379   if (targetTypes == TargetTypes::AllTargets) {
1380     this->ComputeBuildFileGenerators();
1381   }
1382 }
1383
1384 void cmGlobalGenerator::CreateImportedGenerationObjects(
1385   cmMakefile* mf, const std::vector<std::string>& targets,
1386   std::vector<const cmGeneratorTarget*>& exports)
1387 {
1388   this->CreateGenerationObjects(ImportedOnly);
1389   auto const mfit =
1390     std::find_if(this->Makefiles.begin(), this->Makefiles.end(),
1391                  [mf](const std::unique_ptr<cmMakefile>& item) {
1392                    return item.get() == mf;
1393                  });
1394   auto& lg =
1395     this->LocalGenerators[std::distance(this->Makefiles.begin(), mfit)];
1396   for (std::string const& t : targets) {
1397     cmGeneratorTarget* gt = lg->FindGeneratorTargetToUse(t);
1398     if (gt) {
1399       exports.push_back(gt);
1400     }
1401   }
1402 }
1403
1404 cmExportBuildFileGenerator* cmGlobalGenerator::GetExportedTargetsFile(
1405   const std::string& filename) const
1406 {
1407   auto const it = this->BuildExportSets.find(filename);
1408   return it == this->BuildExportSets.end() ? nullptr : it->second;
1409 }
1410
1411 void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target)
1412 {
1413   this->CMP0042WarnTargets.insert(target);
1414 }
1415
1416 void cmGlobalGenerator::AddCMP0068WarnTarget(const std::string& target)
1417 {
1418   this->CMP0068WarnTargets.insert(target);
1419 }
1420
1421 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const
1422 {
1423   // If the property is not enabled then okay.
1424   if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(
1425         "ALLOW_DUPLICATE_CUSTOM_TARGETS")) {
1426     return true;
1427   }
1428
1429   // This generator does not support duplicate custom targets.
1430   std::ostringstream e;
1431   e << "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
1432     << "global property.  "
1433     << "The \"" << this->GetName() << "\" generator does not support "
1434     << "duplicate custom targets.  "
1435     << "Consider using a Makefiles generator or fix the project to not "
1436     << "use duplicate target names.";
1437   cmSystemTools::Error(e.str());
1438   return false;
1439 }
1440
1441 void cmGlobalGenerator::ComputeBuildFileGenerators()
1442 {
1443   for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
1444     std::vector<std::unique_ptr<cmExportBuildFileGenerator>> const& gens =
1445       this->Makefiles[i]->GetExportBuildFileGenerators();
1446     for (std::unique_ptr<cmExportBuildFileGenerator> const& g : gens) {
1447       g->Compute(this->LocalGenerators[i].get());
1448     }
1449   }
1450 }
1451
1452 bool cmGlobalGenerator::UnsupportedVariableIsDefined(const std::string& name,
1453                                                      bool supported) const
1454 {
1455   if (!supported && this->Makefiles.front()->GetDefinition(name)) {
1456     std::ostringstream e;
1457     /* clang-format off */
1458     e <<
1459       "Generator\n"
1460       "  " << this->GetName() << "\n"
1461       "does not support variable\n"
1462       "  " << name << "\n"
1463       "but it has been specified."
1464       ;
1465     /* clang-format on */
1466     this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str());
1467     return true;
1468   }
1469
1470   return false;
1471 }
1472
1473 bool cmGlobalGenerator::Compute()
1474 {
1475   // Make sure unsupported variables are not used.
1476   if (this->UnsupportedVariableIsDefined("CMAKE_DEFAULT_BUILD_TYPE",
1477                                          this->SupportsDefaultBuildType())) {
1478     return false;
1479   }
1480   if (this->UnsupportedVariableIsDefined("CMAKE_CROSS_CONFIGS",
1481                                          this->SupportsCrossConfigs())) {
1482     return false;
1483   }
1484   if (this->UnsupportedVariableIsDefined("CMAKE_DEFAULT_CONFIGS",
1485                                          this->SupportsDefaultConfigs())) {
1486     return false;
1487   }
1488   if (!this->InspectConfigTypeVariables()) {
1489     return false;
1490   }
1491
1492   // Some generators track files replaced during the Generate.
1493   // Start with an empty vector:
1494   this->FilesReplacedDuringGenerate.clear();
1495
1496   // clear targets to issue warning CMP0042 for
1497   this->CMP0042WarnTargets.clear();
1498   // clear targets to issue warning CMP0068 for
1499   this->CMP0068WarnTargets.clear();
1500
1501   // Check whether this generator is allowed to run.
1502   if (!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) {
1503     return false;
1504   }
1505   this->FinalizeTargetConfiguration();
1506
1507   this->CreateGenerationObjects();
1508
1509   // at this point this->LocalGenerators has been filled,
1510   // so create the map from project name to vector of local generators
1511   this->FillProjectMap();
1512
1513   // Add automatically generated sources (e.g. unity build).
1514   if (!this->AddAutomaticSources()) {
1515     return false;
1516   }
1517
1518   // Iterate through all targets and add verification targets for header sets
1519   if (!this->AddHeaderSetVerification()) {
1520     return false;
1521   }
1522
1523   // Iterate through all targets and set up AUTOMOC, AUTOUIC and AUTORCC
1524   if (!this->QtAutoGen()) {
1525     return false;
1526   }
1527
1528   // Add generator specific helper commands
1529   for (const auto& localGen : this->LocalGenerators) {
1530     localGen->AddHelperCommands();
1531   }
1532
1533   // Perform up-front computation in order to handle errors (such as unknown
1534   // features) at this point. While processing the compile features we also
1535   // calculate and cache the language standard required by the compile
1536   // features.
1537   for (const auto& localGen : this->LocalGenerators) {
1538     if (!localGen->ComputeTargetCompileFeatures()) {
1539       return false;
1540     }
1541   }
1542
1543   for (const auto& localGen : this->LocalGenerators) {
1544     cmMakefile* mf = localGen->GetMakefile();
1545     for (const auto& g : mf->GetInstallGenerators()) {
1546       if (!g->Compute(localGen.get())) {
1547         return false;
1548       }
1549     }
1550   }
1551
1552   this->AddExtraIDETargets();
1553
1554   // Trace the dependencies, after that no custom commands should be added
1555   // because their dependencies might not be handled correctly
1556   for (const auto& localGen : this->LocalGenerators) {
1557     localGen->TraceDependencies();
1558   }
1559
1560   // Make sure that all (non-imported) targets have source files added!
1561   if (this->CheckTargetsForMissingSources()) {
1562     return false;
1563   }
1564
1565   this->ForceLinkerLanguages();
1566
1567   // Compute the manifest of main targets generated.
1568   for (const auto& localGen : this->LocalGenerators) {
1569     localGen->ComputeTargetManifest();
1570   }
1571
1572   // Compute the inter-target dependencies.
1573   if (!this->ComputeTargetDepends()) {
1574     return false;
1575   }
1576   this->ComputeTargetOrder();
1577
1578   if (this->CheckTargetsForType()) {
1579     return false;
1580   }
1581
1582   if (this->CheckTargetsForPchCompilePdb()) {
1583     return false;
1584   }
1585
1586   for (const auto& localGen : this->LocalGenerators) {
1587     localGen->ComputeHomeRelativeOutputPath();
1588   }
1589
1590   return true;
1591 }
1592
1593 void cmGlobalGenerator::Generate()
1594 {
1595   // Create a map from local generator to the complete set of targets
1596   // it builds by default.
1597   this->InitializeProgressMarks();
1598
1599   this->ProcessEvaluationFiles();
1600
1601   this->CMakeInstance->UpdateProgress("Generating", 0.1f);
1602
1603   // Generate project files
1604   for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
1605     this->SetCurrentMakefile(this->LocalGenerators[i]->GetMakefile());
1606     this->LocalGenerators[i]->Generate();
1607     if (!this->LocalGenerators[i]->GetMakefile()->IsOn(
1608           "CMAKE_SKIP_INSTALL_RULES")) {
1609       this->LocalGenerators[i]->GenerateInstallRules();
1610     }
1611     this->LocalGenerators[i]->GenerateTestFiles();
1612     this->CMakeInstance->UpdateProgress(
1613       "Generating",
1614       0.1f +
1615         0.9f * (static_cast<float>(i) + 1.0f) /
1616           static_cast<float>(this->LocalGenerators.size()));
1617   }
1618   this->SetCurrentMakefile(nullptr);
1619
1620   if (!this->GenerateCPackPropertiesFile()) {
1621     this->GetCMakeInstance()->IssueMessage(
1622       MessageType::FATAL_ERROR, "Could not write CPack properties file.");
1623   }
1624
1625   for (auto& buildExpSet : this->BuildExportSets) {
1626     if (!buildExpSet.second->GenerateImportFile()) {
1627       if (!cmSystemTools::GetErrorOccurredFlag()) {
1628         this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
1629                                                "Could not write export file.");
1630       }
1631       return;
1632     }
1633   }
1634   // Update rule hashes.
1635   this->CheckRuleHashes();
1636
1637   this->WriteSummary();
1638
1639   if (this->ExtraGenerator) {
1640     this->ExtraGenerator->Generate();
1641   }
1642
1643   // Perform validation checks on memoized link structures.
1644   this->CheckTargetLinkLibraries();
1645
1646   if (!this->CMP0042WarnTargets.empty()) {
1647     std::ostringstream w;
1648     w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0042) << "\n";
1649     w << "MACOSX_RPATH is not specified for"
1650          " the following targets:\n";
1651     for (std::string const& t : this->CMP0042WarnTargets) {
1652       w << " " << t << "\n";
1653     }
1654     this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
1655                                            w.str());
1656   }
1657
1658   if (!this->CMP0068WarnTargets.empty()) {
1659     std::ostringstream w;
1660     /* clang-format off */
1661     w <<
1662       cmPolicies::GetPolicyWarning(cmPolicies::CMP0068) << "\n"
1663       "For compatibility with older versions of CMake, the install_name "
1664       "fields for the following targets are still affected by RPATH "
1665       "settings:\n"
1666       ;
1667     /* clang-format on */
1668     for (std::string const& t : this->CMP0068WarnTargets) {
1669       w << " " << t << "\n";
1670     }
1671     this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
1672                                            w.str());
1673   }
1674
1675   this->CMakeInstance->UpdateProgress("Generating done", -1);
1676 }
1677
1678 bool cmGlobalGenerator::ComputeTargetDepends()
1679 {
1680   cmComputeTargetDepends ctd(this);
1681   if (!ctd.Compute()) {
1682     return false;
1683   }
1684   for (cmGeneratorTarget const* target : ctd.GetTargets()) {
1685     ctd.GetTargetDirectDepends(target, this->TargetDependencies[target]);
1686   }
1687   return true;
1688 }
1689
1690 std::vector<cmGeneratorTarget*>
1691 cmGlobalGenerator::GetLocalGeneratorTargetsInOrder(cmLocalGenerator* lg) const
1692 {
1693   std::vector<cmGeneratorTarget*> gts;
1694   cm::append(gts, lg->GetGeneratorTargets());
1695   std::sort(gts.begin(), gts.end(),
1696             [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) {
1697               return this->TargetOrderIndex.at(l) <
1698                 this->TargetOrderIndex.at(r);
1699             });
1700   return gts;
1701 }
1702
1703 void cmGlobalGenerator::ComputeTargetOrder()
1704 {
1705   size_t index = 0;
1706   auto const& lgens = this->GetLocalGenerators();
1707   for (auto const& lgen : lgens) {
1708     const auto& targets = lgen->GetGeneratorTargets();
1709     for (const auto& gt : targets) {
1710       this->ComputeTargetOrder(gt.get(), index);
1711     }
1712   }
1713   assert(index == this->TargetOrderIndex.size());
1714 }
1715
1716 void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
1717                                            size_t& index)
1718 {
1719   std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0);
1720   auto insertion = this->TargetOrderIndex.insert(value);
1721   if (!insertion.second) {
1722     return;
1723   }
1724   auto entry = insertion.first;
1725
1726   const auto& deps = this->GetTargetDirectDepends(gt);
1727   for (const auto& d : deps) {
1728     this->ComputeTargetOrder(d, index);
1729   }
1730
1731   entry->second = index++;
1732 }
1733
1734 bool cmGlobalGenerator::QtAutoGen()
1735 {
1736 #ifndef CMAKE_BOOTSTRAP
1737   cmQtAutoGenGlobalInitializer initializer(this->LocalGenerators);
1738   return initializer.generate();
1739 #else
1740   return true;
1741 #endif
1742 }
1743
1744 bool cmGlobalGenerator::AddHeaderSetVerification()
1745 {
1746   for (auto const& gen : this->LocalGenerators) {
1747     // Because AddHeaderSetVerification() adds generator targets, we need to
1748     // cache the existing list of generator targets before starting.
1749     std::vector<cmGeneratorTarget*> genTargets;
1750     genTargets.reserve(gen->GetGeneratorTargets().size());
1751     for (auto const& tgt : gen->GetGeneratorTargets()) {
1752       genTargets.push_back(tgt.get());
1753     }
1754
1755     for (auto* tgt : genTargets) {
1756       if (!tgt->AddHeaderSetVerification()) {
1757         return false;
1758       }
1759     }
1760   }
1761
1762   cmTarget* allVerifyTarget = this->Makefiles.front()->FindTargetToUse(
1763     "all_verify_interface_header_sets", true);
1764   if (allVerifyTarget) {
1765     this->LocalGenerators.front()->AddGeneratorTarget(
1766       cm::make_unique<cmGeneratorTarget>(allVerifyTarget,
1767                                          this->LocalGenerators.front().get()));
1768   }
1769
1770   return true;
1771 }
1772
1773 bool cmGlobalGenerator::AddAutomaticSources()
1774 {
1775   for (const auto& lg : this->LocalGenerators) {
1776     lg->CreateEvaluationFileOutputs();
1777   }
1778   for (const auto& lg : this->LocalGenerators) {
1779     for (const auto& gt : lg->GetGeneratorTargets()) {
1780       if (!gt->CanCompileSources()) {
1781         continue;
1782       }
1783       lg->AddUnityBuild(gt.get());
1784       lg->AddISPCDependencies(gt.get());
1785       // Targets that re-use a PCH are handled below.
1786       if (!gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
1787         lg->AddPchDependencies(gt.get());
1788       }
1789       lg->AddXCConfigSources(gt.get());
1790     }
1791   }
1792   for (const auto& lg : this->LocalGenerators) {
1793     for (const auto& gt : lg->GetGeneratorTargets()) {
1794       if (!gt->CanCompileSources()) {
1795         continue;
1796       }
1797       // Handle targets that re-use a PCH from an above-handled target.
1798       if (gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
1799         lg->AddPchDependencies(gt.get());
1800       }
1801     }
1802   }
1803   // The above transformations may have changed the classification of sources.
1804   // Clear the source list and classification cache (KindedSources) of all
1805   // targets so that it will be recomputed correctly by the generators later
1806   // now that the above transformations are done for all targets.
1807   for (const auto& lg : this->LocalGenerators) {
1808     for (const auto& gt : lg->GetGeneratorTargets()) {
1809       gt->ClearSourcesCache();
1810     }
1811   }
1812   return true;
1813 }
1814
1815 std::unique_ptr<cmLinkLineComputer> cmGlobalGenerator::CreateLinkLineComputer(
1816   cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const
1817 {
1818   return cm::make_unique<cmLinkLineComputer>(outputConverter, stateDir);
1819 }
1820
1821 std::unique_ptr<cmLinkLineComputer>
1822 cmGlobalGenerator::CreateMSVC60LinkLineComputer(
1823   cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const
1824 {
1825   return std::unique_ptr<cmLinkLineComputer>(
1826     cm::make_unique<cmMSVC60LinkLineComputer>(outputConverter, stateDir));
1827 }
1828
1829 void cmGlobalGenerator::FinalizeTargetConfiguration()
1830 {
1831   std::vector<std::string> const langs =
1832     this->CMakeInstance->GetState()->GetEnabledLanguages();
1833
1834   // Construct per-target generator information.
1835   for (const auto& mf : this->Makefiles) {
1836     const cmBTStringRange noConfigCompileDefinitions =
1837       mf->GetCompileDefinitionsEntries();
1838     cm::optional<std::map<std::string, cmValue>> perConfigCompileDefinitions;
1839
1840     for (auto& target : mf->GetTargets()) {
1841       cmTarget* t = &target.second;
1842       t->FinalizeTargetConfiguration(noConfigCompileDefinitions,
1843                                      perConfigCompileDefinitions);
1844     }
1845
1846     // The standard include directories for each language
1847     // should be treated as system include directories.
1848     std::set<std::string> standardIncludesSet;
1849     for (std::string const& li : langs) {
1850       std::string const standardIncludesVar =
1851         "CMAKE_" + li + "_STANDARD_INCLUDE_DIRECTORIES";
1852       std::string const& standardIncludesStr =
1853         mf->GetSafeDefinition(standardIncludesVar);
1854       std::vector<std::string> standardIncludesVec =
1855         cmExpandedList(standardIncludesStr);
1856       standardIncludesSet.insert(standardIncludesVec.begin(),
1857                                  standardIncludesVec.end());
1858     }
1859     mf->AddSystemIncludeDirectories(standardIncludesSet);
1860   }
1861 }
1862
1863 void cmGlobalGenerator::CreateGeneratorTargets(
1864   TargetTypes targetTypes, cmMakefile* mf, cmLocalGenerator* lg,
1865   std::map<cmTarget*, cmGeneratorTarget*> const& importedMap)
1866 {
1867   if (targetTypes == AllTargets) {
1868     for (cmTarget* target : mf->GetOrderedTargets()) {
1869       lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(target, lg));
1870     }
1871   }
1872
1873   for (cmTarget* t : mf->GetImportedTargets()) {
1874     lg->AddImportedGeneratorTarget(importedMap.find(t)->second);
1875   }
1876 }
1877
1878 void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes)
1879 {
1880   std::map<cmTarget*, cmGeneratorTarget*> importedMap;
1881   for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
1882     auto& mf = this->Makefiles[i];
1883     for (const auto& ownedImpTgt : mf->GetOwnedImportedTargets()) {
1884       cmLocalGenerator* lg = this->LocalGenerators[i].get();
1885       auto gt = cm::make_unique<cmGeneratorTarget>(ownedImpTgt.get(), lg);
1886       importedMap[ownedImpTgt.get()] = gt.get();
1887       lg->AddOwnedImportedGeneratorTarget(std::move(gt));
1888     }
1889   }
1890
1891   // Construct per-target generator information.
1892   for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
1893     this->CreateGeneratorTargets(targetTypes, this->Makefiles[i].get(),
1894                                  this->LocalGenerators[i].get(), importedMap);
1895   }
1896 }
1897
1898 void cmGlobalGenerator::ClearGeneratorMembers()
1899 {
1900   this->BuildExportSets.clear();
1901
1902   this->Makefiles.clear();
1903
1904   this->LocalGenerators.clear();
1905
1906   this->AliasTargets.clear();
1907   this->ExportSets.clear();
1908   this->InstallComponents.clear();
1909   this->TargetDependencies.clear();
1910   this->TargetSearchIndex.clear();
1911   this->GeneratorTargetSearchIndex.clear();
1912   this->MakefileSearchIndex.clear();
1913   this->LocalGeneratorSearchIndex.clear();
1914   this->TargetOrderIndex.clear();
1915   this->ProjectMap.clear();
1916   this->RuleHashes.clear();
1917   this->DirectoryContentMap.clear();
1918   this->BinaryDirectories.clear();
1919   this->GeneratedFiles.clear();
1920 }
1921
1922 void cmGlobalGenerator::ComputeTargetObjectDirectory(
1923   cmGeneratorTarget* /*unused*/) const
1924 {
1925 }
1926
1927 void cmGlobalGenerator::CheckTargetProperties()
1928 {
1929   // check for link libraries and include directories containing "NOTFOUND"
1930   // and for infinite loops
1931   std::map<std::string, std::string> notFoundMap;
1932   cmState* state = this->GetCMakeInstance()->GetState();
1933   for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
1934     this->Makefiles[i]->Generate(*this->LocalGenerators[i]);
1935     for (auto const& target : this->Makefiles[i]->GetTargets()) {
1936       if (target.second.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
1937         continue;
1938       }
1939       for (auto const& lib : target.second.GetOriginalLinkLibraries()) {
1940         if (lib.first.size() > 9 && cmIsNOTFOUND(lib.first)) {
1941           std::string varName = lib.first.substr(0, lib.first.size() - 9);
1942           if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
1943             varName += " (ADVANCED)";
1944           }
1945           std::string text =
1946             cmStrCat(notFoundMap[varName], "\n    linked by target \"",
1947                      target.second.GetName(), "\" in directory ",
1948                      this->Makefiles[i]->GetCurrentSourceDirectory());
1949           notFoundMap[varName] = text;
1950         }
1951       }
1952       std::vector<std::string> incs;
1953       cmValue incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES");
1954       if (!incDirProp) {
1955         continue;
1956       }
1957
1958       std::string incDirs = cmGeneratorExpression::Preprocess(
1959         *incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
1960
1961       cmExpandList(incDirs, incs);
1962
1963       for (std::string const& incDir : incs) {
1964         if (incDir.size() > 9 && cmIsNOTFOUND(incDir)) {
1965           std::string varName = incDir.substr(0, incDir.size() - 9);
1966           if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
1967             varName += " (ADVANCED)";
1968           }
1969           std::string text =
1970             cmStrCat(notFoundMap[varName],
1971                      "\n   used as include directory in directory ",
1972                      this->Makefiles[i]->GetCurrentSourceDirectory());
1973           notFoundMap[varName] = text;
1974         }
1975       }
1976     }
1977   }
1978
1979   if (!notFoundMap.empty()) {
1980     std::string notFoundVars;
1981     for (auto const& notFound : notFoundMap) {
1982       notFoundVars += notFound.first;
1983       notFoundVars += notFound.second;
1984       notFoundVars += "\n";
1985     }
1986     cmSystemTools::Error("The following variables are used in this project, "
1987                          "but they are set to NOTFOUND.\n"
1988                          "Please set them or make sure they are set and "
1989                          "tested correctly in the CMake files:\n" +
1990                          notFoundVars);
1991   }
1992 }
1993
1994 int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
1995                                   const std::string& bindir,
1996                                   const std::string& projectName,
1997                                   const std::string& target, bool fast,
1998                                   std::string& output, cmMakefile* mf)
1999 {
2000   // if this is not set, then this is a first time configure
2001   // and there is a good chance that the try compile stuff will
2002   // take the bulk of the time, so try and guess some progress
2003   // by getting closer and closer to 100 without actually getting there.
2004   if (!this->CMakeInstance->GetState()->GetInitializedCacheValue(
2005         "CMAKE_NUMBER_OF_MAKEFILES")) {
2006     // If CMAKE_NUMBER_OF_MAKEFILES is not set
2007     // we are in the first time progress and we have no
2008     // idea how long it will be.  So, just move 1/10th of the way
2009     // there each time, and don't go over 95%
2010     this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) / 30.0f);
2011     if (this->FirstTimeProgress > 0.95f) {
2012       this->FirstTimeProgress = 0.95f;
2013     }
2014     this->CMakeInstance->UpdateProgress("Configuring",
2015                                         this->FirstTimeProgress);
2016   }
2017
2018   std::vector<std::string> newTarget = {};
2019   if (!target.empty()) {
2020     newTarget = { target };
2021   }
2022   std::string config =
2023     mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
2024   cmBuildOptions defaultBuildOptions(false, fast, PackageResolveMode::Disable);
2025
2026   return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "",
2027                      config, defaultBuildOptions, false,
2028                      this->TryCompileTimeout);
2029 }
2030
2031 std::vector<cmGlobalGenerator::GeneratedMakeCommand>
2032 cmGlobalGenerator::GenerateBuildCommand(
2033   const std::string& /*unused*/, const std::string& /*unused*/,
2034   const std::string& /*unused*/, std::vector<std::string> const& /*unused*/,
2035   const std::string& /*unused*/, int /*unused*/, bool /*unused*/,
2036   const cmBuildOptions& /*unused*/, std::vector<std::string> const& /*unused*/)
2037 {
2038   GeneratedMakeCommand makeCommand;
2039   makeCommand.Add("cmGlobalGenerator::GenerateBuildCommand not implemented");
2040   return { std::move(makeCommand) };
2041 }
2042
2043 void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
2044                                                 int /*jobs*/) const
2045 {
2046   // Subclasses override this method if they e.g want to give a warning that
2047   // they do not support certain build command line options
2048 }
2049
2050 int cmGlobalGenerator::Build(
2051   int jobs, const std::string& /*unused*/, const std::string& bindir,
2052   const std::string& projectName, const std::vector<std::string>& targets,
2053   std::string& output, const std::string& makeCommandCSTR,
2054   const std::string& config, const cmBuildOptions& buildOptions, bool verbose,
2055   cmDuration timeout, cmSystemTools::OutputOption outputflag,
2056   std::vector<std::string> const& nativeOptions)
2057 {
2058   bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
2059
2060   /**
2061    * Run an executable command and put the stdout in output.
2062    */
2063   cmWorkingDirectory workdir(bindir);
2064   output += "Change Dir: ";
2065   output += bindir;
2066   output += "\n";
2067   if (workdir.Failed()) {
2068     cmSystemTools::SetRunCommandHideConsole(hideconsole);
2069     std::string err = cmStrCat("Failed to change directory: ",
2070                                std::strerror(workdir.GetLastResult()));
2071     cmSystemTools::Error(err);
2072     output += err;
2073     output += "\n";
2074     return 1;
2075   }
2076   std::string realConfig = config;
2077   if (realConfig.empty()) {
2078     realConfig = this->GetDefaultBuildConfig();
2079   }
2080
2081   int retVal = 0;
2082   cmSystemTools::SetRunCommandHideConsole(true);
2083   std::string outputBuffer;
2084   std::string* outputPtr = &outputBuffer;
2085
2086   std::vector<GeneratedMakeCommand> makeCommand = this->GenerateBuildCommand(
2087     makeCommandCSTR, projectName, bindir, targets, realConfig, jobs, verbose,
2088     buildOptions, nativeOptions);
2089
2090   // Workaround to convince some commands to produce output.
2091   if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
2092       makeCommand.back().RequiresOutputForward) {
2093     outputflag = cmSystemTools::OUTPUT_FORWARD;
2094   }
2095
2096   // should we do a clean first?
2097   if (buildOptions.Clean) {
2098     std::vector<GeneratedMakeCommand> cleanCommand =
2099       this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
2100                                  { "clean" }, realConfig, jobs, verbose,
2101                                  buildOptions);
2102     output += "\nRun Clean Command:";
2103     output += cleanCommand.front().Printable();
2104     output += "\n";
2105     if (cleanCommand.size() != 1) {
2106       this->GetCMakeInstance()->IssueMessage(MessageType::INTERNAL_ERROR,
2107                                              "The generator did not produce "
2108                                              "exactly one command for the "
2109                                              "'clean' target");
2110       return 1;
2111     }
2112     if (!cmSystemTools::RunSingleCommand(cleanCommand.front().PrimaryCommand,
2113                                          outputPtr, outputPtr, &retVal,
2114                                          nullptr, outputflag, timeout)) {
2115       cmSystemTools::SetRunCommandHideConsole(hideconsole);
2116       cmSystemTools::Error("Generator: execution of make clean failed.");
2117       output += *outputPtr;
2118       output += "\nGenerator: execution of make clean failed.\n";
2119
2120       return 1;
2121     }
2122     output += *outputPtr;
2123   }
2124
2125   // now build
2126   std::string makeCommandStr;
2127   output += "\nRun Build Command(s):";
2128
2129   retVal = 0;
2130   for (auto command = makeCommand.begin();
2131        command != makeCommand.end() && retVal == 0; ++command) {
2132     makeCommandStr = command->Printable();
2133     if (command != makeCommand.end()) {
2134       makeCommandStr += " && ";
2135     }
2136
2137     output += makeCommandStr;
2138     if (!cmSystemTools::RunSingleCommand(command->PrimaryCommand, outputPtr,
2139                                          outputPtr, &retVal, nullptr,
2140                                          outputflag, timeout)) {
2141       cmSystemTools::SetRunCommandHideConsole(hideconsole);
2142       cmSystemTools::Error(
2143         "Generator: execution of make failed. Make command was: " +
2144         makeCommandStr);
2145       output += *outputPtr;
2146       output += "\nGenerator: execution of make failed. Make command was: " +
2147         makeCommandStr + "\n";
2148
2149       return 1;
2150     }
2151     output += *outputPtr;
2152   }
2153   output += "\n";
2154   cmSystemTools::SetRunCommandHideConsole(hideconsole);
2155
2156   // The OpenWatcom tools do not return an error code when a link
2157   // library is not found!
2158   if (this->CMakeInstance->GetState()->UseWatcomWMake() && retVal == 0 &&
2159       output.find("W1008: cannot open") != std::string::npos) {
2160     retVal = 1;
2161   }
2162
2163   return retVal;
2164 }
2165
2166 bool cmGlobalGenerator::Open(const std::string& bindir,
2167                              const std::string& projectName, bool dryRun)
2168 {
2169   if (this->ExtraGenerator) {
2170     return this->ExtraGenerator->Open(bindir, projectName, dryRun);
2171   }
2172
2173   return false;
2174 }
2175
2176 std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
2177   const std::string& target, const std::string& config,
2178   const std::string& parallel, const std::string& native, bool ignoreErrors)
2179 {
2180   std::string makeCommand = cmSystemTools::GetCMakeCommand();
2181   makeCommand =
2182     cmStrCat(cmSystemTools::ConvertToOutputPath(makeCommand), " --build .");
2183   if (!config.empty()) {
2184     makeCommand += " --config \"";
2185     makeCommand += config;
2186     makeCommand += "\"";
2187   }
2188   if (!parallel.empty()) {
2189     makeCommand += " --parallel \"";
2190     makeCommand += parallel;
2191     makeCommand += "\"";
2192   }
2193   if (!target.empty()) {
2194     makeCommand += " --target \"";
2195     makeCommand += target;
2196     makeCommand += "\"";
2197   }
2198   const char* sep = " -- ";
2199   if (ignoreErrors) {
2200     const char* iflag = this->GetBuildIgnoreErrorsFlag();
2201     if (iflag && *iflag) {
2202       makeCommand += sep;
2203       makeCommand += iflag;
2204       sep = " ";
2205     }
2206   }
2207   if (!native.empty()) {
2208     makeCommand += sep;
2209     makeCommand += native;
2210   }
2211   return makeCommand;
2212 }
2213
2214 void cmGlobalGenerator::AddMakefile(std::unique_ptr<cmMakefile> mf)
2215 {
2216   this->IndexMakefile(mf.get());
2217   this->Makefiles.push_back(std::move(mf));
2218
2219   // update progress
2220   // estimate how many lg there will be
2221   cmValue numGenC = this->CMakeInstance->GetState()->GetInitializedCacheValue(
2222     "CMAKE_NUMBER_OF_MAKEFILES");
2223
2224   if (!numGenC) {
2225     // If CMAKE_NUMBER_OF_MAKEFILES is not set
2226     // we are in the first time progress and we have no
2227     // idea how long it will be.  So, just move half way
2228     // there each time, and don't go over 95%
2229     this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) / 30.0f);
2230     if (this->FirstTimeProgress > 0.95f) {
2231       this->FirstTimeProgress = 0.95f;
2232     }
2233     this->CMakeInstance->UpdateProgress("Configuring",
2234                                         this->FirstTimeProgress);
2235     return;
2236   }
2237
2238   int numGen = atoi(numGenC->c_str());
2239   float prog =
2240     static_cast<float>(this->Makefiles.size()) / static_cast<float>(numGen);
2241   if (prog > 1.0f) {
2242     prog = 1.0f;
2243   }
2244   this->CMakeInstance->UpdateProgress("Configuring", prog);
2245 }
2246
2247 void cmGlobalGenerator::AddInstallComponent(const std::string& component)
2248 {
2249   if (!component.empty()) {
2250     this->InstallComponents.insert(component);
2251   }
2252 }
2253
2254 void cmGlobalGenerator::MarkAsGeneratedFile(const std::string& filepath)
2255 {
2256   this->GeneratedFiles.insert(filepath);
2257 }
2258
2259 bool cmGlobalGenerator::IsGeneratedFile(const std::string& filepath)
2260 {
2261   return this->GeneratedFiles.find(filepath) != this->GeneratedFiles.end();
2262 }
2263
2264 void cmGlobalGenerator::EnableInstallTarget()
2265 {
2266   this->InstallTargetEnabled = true;
2267 }
2268
2269 std::unique_ptr<cmLocalGenerator> cmGlobalGenerator::CreateLocalGenerator(
2270   cmMakefile* mf)
2271 {
2272   return cm::make_unique<cmLocalGenerator>(this, mf);
2273 }
2274
2275 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen,
2276                                                      cmMakefile* mf)
2277 {
2278   this->SetConfiguredFilesPath(gen);
2279   this->TryCompileOuterMakefile = mf;
2280   cmValue make =
2281     gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
2282   this->GetCMakeInstance()->AddCacheEntry(
2283     "CMAKE_MAKE_PROGRAM", make, "make program", cmStateEnums::FILEPATH);
2284   // copy the enabled languages
2285   this->GetCMakeInstance()->GetState()->SetEnabledLanguages(
2286     gen->GetCMakeInstance()->GetState()->GetEnabledLanguages());
2287   this->LanguagesReady = gen->LanguagesReady;
2288   this->ExtensionToLanguage = gen->ExtensionToLanguage;
2289   this->IgnoreExtensions = gen->IgnoreExtensions;
2290   this->LanguageToOutputExtension = gen->LanguageToOutputExtension;
2291   this->LanguageToLinkerPreference = gen->LanguageToLinkerPreference;
2292   this->OutputExtensions = gen->OutputExtensions;
2293 }
2294
2295 void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
2296 {
2297   if (!gen->ConfiguredFilesPath.empty()) {
2298     this->ConfiguredFilesPath = gen->ConfiguredFilesPath;
2299   } else {
2300     this->ConfiguredFilesPath =
2301       cmStrCat(gen->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
2302   }
2303 }
2304
2305 bool cmGlobalGenerator::IsExcluded(cmStateSnapshot const& rootSnp,
2306                                    cmStateSnapshot const& snp_) const
2307 {
2308   cmStateSnapshot snp = snp_;
2309   while (snp.IsValid()) {
2310     if (snp == rootSnp) {
2311       // No directory excludes itself.
2312       return false;
2313     }
2314
2315     if (snp.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
2316       // This directory is excluded from its parent.
2317       return true;
2318     }
2319     snp = snp.GetBuildsystemDirectoryParent();
2320   }
2321   return false;
2322 }
2323
2324 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
2325                                    cmLocalGenerator* gen) const
2326 {
2327   assert(gen);
2328
2329   cmStateSnapshot rootSnp = root->GetStateSnapshot();
2330   cmStateSnapshot snp = gen->GetStateSnapshot();
2331
2332   return this->IsExcluded(rootSnp, snp);
2333 }
2334
2335 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
2336                                    const cmGeneratorTarget* target) const
2337 {
2338   if (!target->IsInBuildSystem()) {
2339     return true;
2340   }
2341   cmMakefile* mf = root->GetMakefile();
2342   const std::string EXCLUDE_FROM_ALL = "EXCLUDE_FROM_ALL";
2343   if (cmValue exclude = target->GetProperty(EXCLUDE_FROM_ALL)) {
2344     // Expand the property value per configuration.
2345     unsigned int trueCount = 0;
2346     unsigned int falseCount = 0;
2347     const std::vector<std::string>& configs =
2348       mf->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
2349     for (const std::string& config : configs) {
2350       cmGeneratorExpressionInterpreter genexInterpreter(root, config, target);
2351       if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) {
2352         ++trueCount;
2353       } else {
2354         ++falseCount;
2355       }
2356     }
2357
2358     // Check whether the genex expansion of the property agrees in all
2359     // configurations.
2360     if (trueCount > 0 && falseCount > 0) {
2361       std::ostringstream e;
2362       e << "The EXCLUDE_FROM_ALL property of target \"" << target->GetName()
2363         << "\" varies by configuration. This is not supported by the \""
2364         << root->GetGlobalGenerator()->GetName() << "\" generator.";
2365       mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
2366     }
2367     return trueCount;
2368   }
2369   // This target is included in its directory.  Check whether the
2370   // directory is excluded.
2371   return this->IsExcluded(root, target->GetLocalGenerator());
2372 }
2373
2374 void cmGlobalGenerator::GetEnabledLanguages(
2375   std::vector<std::string>& lang) const
2376 {
2377   lang = this->CMakeInstance->GetState()->GetEnabledLanguages();
2378 }
2379
2380 int cmGlobalGenerator::GetLinkerPreference(const std::string& lang) const
2381 {
2382   auto const it = this->LanguageToLinkerPreference.find(lang);
2383   if (it != this->LanguageToLinkerPreference.end()) {
2384     return it->second;
2385   }
2386   return 0;
2387 }
2388
2389 void cmGlobalGenerator::FillProjectMap()
2390 {
2391   this->ProjectMap.clear(); // make sure we start with a clean map
2392   for (const auto& localGen : this->LocalGenerators) {
2393     // for each local generator add all projects
2394     cmStateSnapshot snp = localGen->GetStateSnapshot();
2395     std::string name;
2396     do {
2397       std::string snpProjName = snp.GetProjectName();
2398       if (name != snpProjName) {
2399         name = snpProjName;
2400         this->ProjectMap[name].push_back(localGen.get());
2401       }
2402       snp = snp.GetBuildsystemDirectoryParent();
2403     } while (snp.IsValid());
2404   }
2405 }
2406
2407 cmMakefile* cmGlobalGenerator::FindMakefile(const std::string& start_dir) const
2408 {
2409   auto const it = this->MakefileSearchIndex.find(start_dir);
2410   if (it != this->MakefileSearchIndex.end()) {
2411     return it->second;
2412   }
2413   return nullptr;
2414 }
2415
2416 cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(
2417   cmDirectoryId const& id) const
2418 {
2419   auto const it = this->LocalGeneratorSearchIndex.find(id.String);
2420   if (it != this->LocalGeneratorSearchIndex.end()) {
2421     return it->second;
2422   }
2423   return nullptr;
2424 }
2425
2426 void cmGlobalGenerator::AddAlias(const std::string& name,
2427                                  std::string const& tgtName)
2428 {
2429   this->AliasTargets[name] = tgtName;
2430 }
2431
2432 bool cmGlobalGenerator::IsAlias(const std::string& name) const
2433 {
2434   return cm::contains(this->AliasTargets, name);
2435 }
2436
2437 void cmGlobalGenerator::IndexTarget(cmTarget* t)
2438 {
2439   if (!t->IsImported() || t->IsImportedGloballyVisible()) {
2440     this->TargetSearchIndex[t->GetName()] = t;
2441   }
2442 }
2443
2444 void cmGlobalGenerator::IndexGeneratorTarget(cmGeneratorTarget* gt)
2445 {
2446   if (!gt->IsImported() || gt->IsImportedGloballyVisible()) {
2447     this->GeneratorTargetSearchIndex[gt->GetName()] = gt;
2448   }
2449 }
2450
2451 static char const hexDigits[] = "0123456789abcdef";
2452
2453 std::string cmGlobalGenerator::IndexGeneratorTargetUniquely(
2454   cmGeneratorTarget const* gt)
2455 {
2456   // Use the pointer value to uniquely identify the target instance.
2457   // Use a ":" prefix to avoid conflict with project-defined targets.
2458   // We must satisfy cmGeneratorExpression::IsValidTargetName so use no
2459   // other special characters.
2460   constexpr size_t sizeof_ptr =
2461     sizeof(gt); // NOLINT(bugprone-sizeof-expression)
2462   char buf[1 + sizeof_ptr * 2];
2463   char* b = buf;
2464   *b++ = ':';
2465   for (size_t i = 0; i < sizeof_ptr; ++i) {
2466     unsigned char const c = reinterpret_cast<unsigned char const*>(&gt)[i];
2467     *b++ = hexDigits[(c & 0xf0) >> 4];
2468     *b++ = hexDigits[(c & 0x0f)];
2469   }
2470   std::string id(buf, sizeof(buf));
2471   // We internally index pointers to non-const generator targets
2472   // but our callers only have pointers to const generator targets.
2473   // They will give up non-const privileges when looking up anyway.
2474   this->GeneratorTargetSearchIndex[id] = const_cast<cmGeneratorTarget*>(gt);
2475   return id;
2476 }
2477
2478 void cmGlobalGenerator::IndexMakefile(cmMakefile* mf)
2479 {
2480   // We index by both source and binary directory.  add_subdirectory
2481   // supports multiple build directories sharing the same source directory.
2482   // The source directory index will reference only the first time it is used.
2483   this->MakefileSearchIndex.insert(
2484     MakefileMap::value_type(mf->GetCurrentSourceDirectory(), mf));
2485   this->MakefileSearchIndex.insert(
2486     MakefileMap::value_type(mf->GetCurrentBinaryDirectory(), mf));
2487 }
2488
2489 void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg)
2490 {
2491   cmDirectoryId id = lg->GetMakefile()->GetDirectoryId();
2492   this->LocalGeneratorSearchIndex[id.String] = lg;
2493 }
2494
2495 cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const
2496 {
2497   auto const it = this->TargetSearchIndex.find(name);
2498   if (it != this->TargetSearchIndex.end()) {
2499     return it->second;
2500   }
2501   return nullptr;
2502 }
2503
2504 cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTargetImpl(
2505   std::string const& name) const
2506 {
2507   auto const it = this->GeneratorTargetSearchIndex.find(name);
2508   if (it != this->GeneratorTargetSearchIndex.end()) {
2509     return it->second;
2510   }
2511   return nullptr;
2512 }
2513
2514 cmTarget* cmGlobalGenerator::FindTarget(const std::string& name,
2515                                         bool excludeAliases) const
2516 {
2517   if (!excludeAliases) {
2518     auto const ai = this->AliasTargets.find(name);
2519     if (ai != this->AliasTargets.end()) {
2520       return this->FindTargetImpl(ai->second);
2521     }
2522   }
2523   return this->FindTargetImpl(name);
2524 }
2525
2526 cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTarget(
2527   const std::string& name) const
2528 {
2529   auto const ai = this->AliasTargets.find(name);
2530   if (ai != this->AliasTargets.end()) {
2531     return this->FindGeneratorTargetImpl(ai->second);
2532   }
2533   return this->FindGeneratorTargetImpl(name);
2534 }
2535
2536 bool cmGlobalGenerator::NameResolvesToFramework(
2537   const std::string& libname) const
2538 {
2539   if (cmSystemTools::IsPathToFramework(libname)) {
2540     return true;
2541   }
2542
2543   if (cmTarget* tgt = this->FindTarget(libname)) {
2544     if (tgt->IsFrameworkOnApple()) {
2545       return true;
2546     }
2547   }
2548
2549   return false;
2550 }
2551
2552 // If the file has no extension it's either a raw executable or might
2553 // be a direct reference to a binary within a framework (bad practice!).
2554 // This is where we change the path to point to the framework directory.
2555 // .tbd files also can be located in SDK frameworks (they are
2556 // placeholders for actual libraries shipped with the OS)
2557 cm::optional<cmGlobalGenerator::FrameworkDescriptor>
2558 cmGlobalGenerator::SplitFrameworkPath(const std::string& path,
2559                                       FrameworkFormat format) const
2560 {
2561   // Check for framework structure:
2562   //    (/path/to/)?FwName.framework
2563   // or (/path/to/)?FwName.framework/FwName(.tbd)?
2564   // or (/path/to/)?FwName.framework/Versions/*/FwName(.tbd)?
2565   static cmsys::RegularExpression frameworkPath(
2566     "((.+)/)?(.+)\\.framework(/Versions/[^/]+)?(/(.+))?$");
2567
2568   auto ext = cmSystemTools::GetFilenameLastExtension(path);
2569   if ((ext.empty() || ext == ".tbd" || ext == ".framework") &&
2570       frameworkPath.find(path)) {
2571     auto name = frameworkPath.match(3);
2572     auto libname =
2573       cmSystemTools::GetFilenameWithoutExtension(frameworkPath.match(6));
2574     if (format == FrameworkFormat::Strict && libname.empty()) {
2575       return cm::nullopt;
2576     }
2577     if (!libname.empty() && !cmHasPrefix(libname, name)) {
2578       return cm::nullopt;
2579     }
2580
2581     if (libname.empty() || name.size() == libname.size()) {
2582       return FrameworkDescriptor{ frameworkPath.match(2), name };
2583     }
2584
2585     return FrameworkDescriptor{ frameworkPath.match(2), name,
2586                                 libname.substr(name.size()) };
2587   }
2588
2589   if (format == FrameworkFormat::Extended) {
2590     // path format can be more flexible: (/path/to/)?fwName(.framework)?
2591     auto fwDir = cmSystemTools::GetParentDirectory(path);
2592     auto name = cmSystemTools::GetFilenameLastExtension(path) == ".framework"
2593       ? cmSystemTools::GetFilenameWithoutExtension(path)
2594       : cmSystemTools::GetFilenameName(path);
2595
2596     return FrameworkDescriptor{ fwDir, name };
2597   }
2598
2599   return cm::nullopt;
2600 }
2601
2602 bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName,
2603                                      std::string const& reason) const
2604 {
2605   cmTarget* tgt = this->FindTarget(targetName);
2606   if (!tgt) {
2607     return true;
2608   }
2609   MessageType messageType = MessageType::AUTHOR_WARNING;
2610   std::ostringstream e;
2611   bool issueMessage = false;
2612   switch (tgt->GetPolicyStatusCMP0037()) {
2613     case cmPolicies::WARN:
2614       e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
2615       issueMessage = true;
2616       CM_FALLTHROUGH;
2617     case cmPolicies::OLD:
2618       break;
2619     case cmPolicies::NEW:
2620     case cmPolicies::REQUIRED_IF_USED:
2621     case cmPolicies::REQUIRED_ALWAYS:
2622       issueMessage = true;
2623       messageType = MessageType::FATAL_ERROR;
2624       break;
2625   }
2626   if (issueMessage) {
2627     e << "The target name \"" << targetName << "\" is reserved " << reason
2628       << ".";
2629     if (messageType == MessageType::AUTHOR_WARNING) {
2630       e << "  It may result in undefined behavior.";
2631     }
2632     this->GetCMakeInstance()->IssueMessage(messageType, e.str(),
2633                                            tgt->GetBacktrace());
2634     if (messageType == MessageType::FATAL_ERROR) {
2635       return false;
2636     }
2637   }
2638   return true;
2639 }
2640
2641 void cmGlobalGenerator::CreateDefaultGlobalTargets(
2642   std::vector<GlobalTargetInfo>& targets)
2643 {
2644   this->AddGlobalTarget_Package(targets);
2645   this->AddGlobalTarget_PackageSource(targets);
2646   this->AddGlobalTarget_Test(targets);
2647   this->AddGlobalTarget_EditCache(targets);
2648   this->AddGlobalTarget_RebuildCache(targets);
2649   this->AddGlobalTarget_Install(targets);
2650 }
2651
2652 void cmGlobalGenerator::AddGlobalTarget_Package(
2653   std::vector<GlobalTargetInfo>& targets)
2654 {
2655   auto& mf = this->Makefiles[0];
2656   std::string configFile =
2657     cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake");
2658   if (!cmSystemTools::FileExists(configFile)) {
2659     return;
2660   }
2661
2662   static const auto reservedTargets = { "package", "PACKAGE" };
2663   for (auto const& target : reservedTargets) {
2664     if (!this->CheckCMP0037(target, "when CPack packaging is enabled")) {
2665       return;
2666     }
2667   }
2668
2669   const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
2670   GlobalTargetInfo gti;
2671   gti.Name = this->GetPackageTargetName();
2672   gti.Message = "Run CPack packaging tool...";
2673   gti.UsesTerminal = true;
2674   gti.WorkingDir = mf->GetCurrentBinaryDirectory();
2675   cmCustomCommandLine singleLine;
2676   singleLine.push_back(cmSystemTools::GetCPackCommand());
2677   if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
2678     singleLine.push_back("-C");
2679     singleLine.push_back(cmakeCfgIntDir);
2680   }
2681   singleLine.push_back("--config");
2682   singleLine.push_back("./CPackConfig.cmake");
2683   gti.CommandLines.push_back(std::move(singleLine));
2684   if (this->GetPreinstallTargetName()) {
2685     gti.Depends.emplace_back(this->GetPreinstallTargetName());
2686   } else {
2687     cmValue noPackageAll =
2688       mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
2689     if (cmIsOff(noPackageAll)) {
2690       gti.Depends.emplace_back(this->GetAllTargetName());
2691     }
2692   }
2693   targets.push_back(std::move(gti));
2694 }
2695
2696 void cmGlobalGenerator::AddGlobalTarget_PackageSource(
2697   std::vector<GlobalTargetInfo>& targets)
2698 {
2699   const char* packageSourceTargetName = this->GetPackageSourceTargetName();
2700   if (!packageSourceTargetName) {
2701     return;
2702   }
2703
2704   auto& mf = this->Makefiles[0];
2705   std::string configFile =
2706     cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake");
2707   if (!cmSystemTools::FileExists(configFile)) {
2708     return;
2709   }
2710
2711   static const auto reservedTargets = { "package_source" };
2712   for (auto const& target : reservedTargets) {
2713     if (!this->CheckCMP0037(target,
2714                             "when CPack source packaging is enabled")) {
2715       return;
2716     }
2717   }
2718
2719   GlobalTargetInfo gti;
2720   gti.Name = packageSourceTargetName;
2721   gti.Message = "Run CPack packaging tool for source...";
2722   gti.WorkingDir = mf->GetCurrentBinaryDirectory();
2723   gti.UsesTerminal = true;
2724   cmCustomCommandLine singleLine;
2725   singleLine.push_back(cmSystemTools::GetCPackCommand());
2726   singleLine.push_back("--config");
2727   singleLine.push_back("./CPackSourceConfig.cmake");
2728   singleLine.push_back(std::move(configFile));
2729   gti.CommandLines.push_back(std::move(singleLine));
2730   targets.push_back(std::move(gti));
2731 }
2732
2733 void cmGlobalGenerator::AddGlobalTarget_Test(
2734   std::vector<GlobalTargetInfo>& targets)
2735 {
2736   auto& mf = this->Makefiles[0];
2737   if (!mf->IsOn("CMAKE_TESTING_ENABLED")) {
2738     return;
2739   }
2740
2741   static const auto reservedTargets = { "test", "RUN_TESTS" };
2742   for (auto const& target : reservedTargets) {
2743     if (!this->CheckCMP0037(target, "when CTest testing is enabled")) {
2744       return;
2745     }
2746   }
2747
2748   const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
2749   GlobalTargetInfo gti;
2750   gti.Name = this->GetTestTargetName();
2751   gti.Message = "Running tests...";
2752   gti.UsesTerminal = true;
2753   cmCustomCommandLine singleLine;
2754   singleLine.push_back(cmSystemTools::GetCTestCommand());
2755   singleLine.push_back("--force-new-ctest-process");
2756   std::vector<std::string> args;
2757   if (mf->GetDefExpandList("CMAKE_CTEST_ARGUMENTS", args)) {
2758     for (auto const& arg : args) {
2759       singleLine.push_back(arg);
2760     }
2761   }
2762   if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
2763     singleLine.push_back("-C");
2764     singleLine.push_back(cmakeCfgIntDir);
2765   } else // TODO: This is a hack. Should be something to do with the
2766          // generator
2767   {
2768     singleLine.push_back("$(ARGS)");
2769   }
2770   gti.CommandLines.push_back(std::move(singleLine));
2771   targets.push_back(std::move(gti));
2772 }
2773
2774 void cmGlobalGenerator::AddGlobalTarget_EditCache(
2775   std::vector<GlobalTargetInfo>& targets) const
2776 {
2777   const char* editCacheTargetName = this->GetEditCacheTargetName();
2778   if (!editCacheTargetName) {
2779     return;
2780   }
2781   GlobalTargetInfo gti;
2782   gti.Name = editCacheTargetName;
2783   gti.PerConfig = cmTarget::PerConfig::No;
2784   cmCustomCommandLine singleLine;
2785
2786   // Use generator preference for the edit_cache rule if it is defined.
2787   std::string edit_cmd = this->GetEditCacheCommand();
2788   if (!edit_cmd.empty()) {
2789     singleLine.push_back(std::move(edit_cmd));
2790     singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
2791     singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
2792     gti.Message = "Running CMake cache editor...";
2793     gti.UsesTerminal = true;
2794   } else {
2795     singleLine.push_back(cmSystemTools::GetCMakeCommand());
2796     singleLine.push_back("-E");
2797     singleLine.push_back("echo");
2798     singleLine.push_back("No interactive CMake dialog available.");
2799     gti.Message = "No interactive CMake dialog available...";
2800     gti.UsesTerminal = false;
2801     gti.StdPipesUTF8 = true;
2802   }
2803   gti.CommandLines.push_back(std::move(singleLine));
2804
2805   targets.push_back(std::move(gti));
2806 }
2807
2808 void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
2809   std::vector<GlobalTargetInfo>& targets) const
2810 {
2811   const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
2812   if (!rebuildCacheTargetName) {
2813     return;
2814   }
2815   GlobalTargetInfo gti;
2816   gti.Name = rebuildCacheTargetName;
2817   gti.Message = "Running CMake to regenerate build system...";
2818   gti.UsesTerminal = true;
2819   gti.PerConfig = cmTarget::PerConfig::No;
2820   cmCustomCommandLine singleLine;
2821   singleLine.push_back(cmSystemTools::GetCMakeCommand());
2822   singleLine.push_back("--regenerate-during-build");
2823   singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
2824   singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
2825   gti.CommandLines.push_back(std::move(singleLine));
2826   gti.StdPipesUTF8 = true;
2827   targets.push_back(std::move(gti));
2828 }
2829
2830 void cmGlobalGenerator::AddGlobalTarget_Install(
2831   std::vector<GlobalTargetInfo>& targets)
2832 {
2833   auto& mf = this->Makefiles[0];
2834   const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
2835   bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES");
2836   if (this->InstallTargetEnabled && skipInstallRules) {
2837     this->CMakeInstance->IssueMessage(
2838       MessageType::WARNING,
2839       "CMAKE_SKIP_INSTALL_RULES was enabled even though "
2840       "installation rules have been specified",
2841       mf->GetBacktrace());
2842   } else if (this->InstallTargetEnabled && !skipInstallRules) {
2843     if (!(cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.')) {
2844       std::set<std::string>* componentsSet = &this->InstallComponents;
2845       std::ostringstream ostr;
2846       if (!componentsSet->empty()) {
2847         ostr << "Available install components are: ";
2848         ostr << cmWrap('"', *componentsSet, '"', " ");
2849       } else {
2850         ostr << "Only default component available";
2851       }
2852       GlobalTargetInfo gti;
2853       gti.Name = "list_install_components";
2854       gti.Message = ostr.str();
2855       gti.UsesTerminal = false;
2856       targets.push_back(std::move(gti));
2857     }
2858     std::string cmd = cmSystemTools::GetCMakeCommand();
2859     GlobalTargetInfo gti;
2860     gti.Name = this->GetInstallTargetName();
2861     gti.Message = "Install the project...";
2862     gti.UsesTerminal = true;
2863     gti.StdPipesUTF8 = true;
2864     cmCustomCommandLine singleLine;
2865     if (this->GetPreinstallTargetName()) {
2866       gti.Depends.emplace_back(this->GetPreinstallTargetName());
2867     } else {
2868       cmValue noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
2869       if (cmIsOff(noall)) {
2870         gti.Depends.emplace_back(this->GetAllTargetName());
2871       }
2872     }
2873     if (mf->GetDefinition("CMake_BINARY_DIR") &&
2874         !mf->IsOn("CMAKE_CROSSCOMPILING")) {
2875       // We are building CMake itself.  We cannot use the original
2876       // executable to install over itself.  The generator will
2877       // automatically convert this name to the build-time location.
2878       cmd = "cmake";
2879     }
2880     singleLine.push_back(cmd);
2881     if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
2882       std::string cfgArg = "-DBUILD_TYPE=";
2883       bool useEPN = this->UseEffectivePlatformName(mf.get());
2884       if (useEPN) {
2885         cfgArg += "$(CONFIGURATION)";
2886         singleLine.push_back(cfgArg);
2887         cfgArg = "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)";
2888       } else {
2889         cfgArg += *mf->GetDefinition("CMAKE_CFG_INTDIR");
2890       }
2891       singleLine.push_back(cfgArg);
2892     }
2893     singleLine.push_back("-P");
2894     singleLine.push_back("cmake_install.cmake");
2895     gti.CommandLines.push_back(singleLine);
2896     targets.push_back(gti);
2897
2898     // install_local
2899     if (const char* install_local = this->GetInstallLocalTargetName()) {
2900       gti.Name = install_local;
2901       gti.Message = "Installing only the local directory...";
2902       gti.UsesTerminal = true;
2903       gti.CommandLines.clear();
2904
2905       cmCustomCommandLine localCmdLine = singleLine;
2906
2907       localCmdLine.insert(localCmdLine.begin() + 1,
2908                           "-DCMAKE_INSTALL_LOCAL_ONLY=1");
2909
2910       gti.CommandLines.push_back(std::move(localCmdLine));
2911       targets.push_back(gti);
2912     }
2913
2914     // install_strip
2915     const char* install_strip = this->GetInstallStripTargetName();
2916     if ((install_strip != nullptr) && (mf->IsSet("CMAKE_STRIP"))) {
2917       gti.Name = install_strip;
2918       gti.Message = "Installing the project stripped...";
2919       gti.UsesTerminal = true;
2920       gti.CommandLines.clear();
2921
2922       cmCustomCommandLine stripCmdLine = singleLine;
2923
2924       stripCmdLine.insert(stripCmdLine.begin() + 1,
2925                           "-DCMAKE_INSTALL_DO_STRIP=1");
2926       gti.CommandLines.push_back(std::move(stripCmdLine));
2927       targets.push_back(gti);
2928     }
2929   }
2930 }
2931
2932 std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const
2933 {
2934   cmValue prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
2935     "PREDEFINED_TARGETS_FOLDER");
2936
2937   if (prop) {
2938     return *prop;
2939   }
2940
2941   return "CMakePredefinedTargets";
2942 }
2943
2944 bool cmGlobalGenerator::UseFolderProperty() const
2945 {
2946   cmValue prop =
2947     this->GetCMakeInstance()->GetState()->GetGlobalProperty("USE_FOLDERS");
2948
2949   // If this property is defined, let the setter turn this on or off...
2950   //
2951   if (prop) {
2952     return cmIsOn(*prop);
2953   }
2954
2955   // By default, this feature is OFF, since it is not supported in the
2956   // Visual Studio Express editions until VS11:
2957   //
2958   return false;
2959 }
2960
2961 void cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
2962                                            cmMakefile* mf)
2963 {
2964   // Package
2965   auto tb =
2966     mf->CreateNewTarget(gti.Name, cmStateEnums::GLOBAL_TARGET, gti.PerConfig);
2967
2968   // Do nothing if gti.Name is already used
2969   if (!tb.second) {
2970     return;
2971   }
2972
2973   cmTarget& target = tb.first;
2974   target.SetProperty("EXCLUDE_FROM_ALL", "TRUE");
2975
2976   // Store the custom command in the target.
2977   cmCustomCommand cc;
2978   cc.SetCommandLines(gti.CommandLines);
2979   cc.SetWorkingDirectory(gti.WorkingDir.c_str());
2980   cc.SetStdPipesUTF8(gti.StdPipesUTF8);
2981   cc.SetUsesTerminal(gti.UsesTerminal);
2982   target.AddPostBuildCommand(std::move(cc));
2983   if (!gti.Message.empty()) {
2984     target.SetProperty("EchoString", gti.Message);
2985   }
2986   for (std::string const& d : gti.Depends) {
2987     target.AddUtility(d, false);
2988   }
2989
2990   // Organize in the "predefined targets" folder:
2991   //
2992   if (this->UseFolderProperty()) {
2993     target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
2994   }
2995 }
2996
2997 std::string cmGlobalGenerator::GenerateRuleFile(
2998   std::string const& output) const
2999 {
3000   std::string ruleFile = cmStrCat(output, ".rule");
3001   const char* dir = this->GetCMakeCFGIntDir();
3002   if (dir && dir[0] == '$') {
3003     cmSystemTools::ReplaceString(ruleFile, dir, "/CMakeFiles");
3004   }
3005   return ruleFile;
3006 }
3007
3008 bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
3009 {
3010   return mf->PlatformIsAppleEmbedded();
3011 }
3012
3013 std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
3014   std::string const& l) const
3015 {
3016   auto const it = this->LanguageToOriginalSharedLibFlags.find(l);
3017   if (it != this->LanguageToOriginalSharedLibFlags.end()) {
3018     return it->second;
3019   }
3020   return "";
3021 }
3022
3023 void cmGlobalGenerator::AppendDirectoryForConfig(const std::string& /*unused*/,
3024                                                  const std::string& /*unused*/,
3025                                                  const std::string& /*unused*/,
3026                                                  std::string& /*unused*/)
3027 {
3028   // Subclasses that support multiple configurations should implement
3029   // this method to append the subdirectory for the given build
3030   // configuration.
3031 }
3032
3033 cmGlobalGenerator::TargetDependSet const&
3034 cmGlobalGenerator::GetTargetDirectDepends(cmGeneratorTarget const* target)
3035 {
3036   return this->TargetDependencies[target];
3037 }
3038
3039 bool cmGlobalGenerator::IsReservedTarget(std::string const& name)
3040 {
3041   // The following is a list of targets reserved
3042   // by one or more of the cmake generators.
3043
3044   // Adding additional targets to this list will require a policy!
3045   const char* reservedTargets[] = { "all",       "ALL_BUILD",  "help",
3046                                     "install",   "INSTALL",    "preinstall",
3047                                     "clean",     "edit_cache", "rebuild_cache",
3048                                     "ZERO_CHECK" };
3049
3050   return cm::contains(reservedTargets, name);
3051 }
3052
3053 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
3054   std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator)
3055 {
3056   this->ExtraGenerator = std::move(extraGenerator);
3057   if (this->ExtraGenerator) {
3058     this->ExtraGenerator->SetGlobalGenerator(this);
3059   }
3060 }
3061
3062 std::string cmGlobalGenerator::GetExtraGeneratorName() const
3063 {
3064   return this->ExtraGenerator ? this->ExtraGenerator->GetName()
3065                               : std::string();
3066 }
3067
3068 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
3069 {
3070   this->FilesReplacedDuringGenerate.push_back(filename);
3071 }
3072
3073 void cmGlobalGenerator::GetFilesReplacedDuringGenerate(
3074   std::vector<std::string>& filenames)
3075 {
3076   filenames.clear();
3077   std::copy(this->FilesReplacedDuringGenerate.begin(),
3078             this->FilesReplacedDuringGenerate.end(),
3079             std::back_inserter(filenames));
3080 }
3081
3082 void cmGlobalGenerator::GetTargetSets(
3083   TargetDependSet& projectTargets, TargetDependSet& originalTargets,
3084   cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
3085 {
3086   // loop over all local generators
3087   for (auto* generator : generators) {
3088     // check to make sure generator is not excluded
3089     if (this->IsExcluded(root, generator)) {
3090       continue;
3091     }
3092     // loop over all the generator targets in the makefile
3093     for (const auto& target : generator->GetGeneratorTargets()) {
3094       if (this->IsRootOnlyTarget(target.get()) &&
3095           target->GetLocalGenerator() != root) {
3096         continue;
3097       }
3098       // put the target in the set of original targets
3099       originalTargets.insert(target.get());
3100       // Get the set of targets that depend on target
3101       this->AddTargetDepends(target.get(), projectTargets);
3102     }
3103   }
3104 }
3105
3106 bool cmGlobalGenerator::IsRootOnlyTarget(cmGeneratorTarget* target) const
3107 {
3108   return (target->GetType() == cmStateEnums::GLOBAL_TARGET ||
3109           target->GetName() == this->GetAllTargetName());
3110 }
3111
3112 void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target,
3113                                          TargetDependSet& projectTargets)
3114 {
3115   // add the target itself
3116   if (projectTargets.insert(target).second) {
3117     // This is the first time we have encountered the target.
3118     // Recursively follow its dependencies.
3119     for (auto const& t : this->GetTargetDirectDepends(target)) {
3120       this->AddTargetDepends(t, projectTargets);
3121     }
3122   }
3123 }
3124
3125 void cmGlobalGenerator::AddToManifest(std::string const& f)
3126 {
3127   // Add to the content listing for the file's directory.
3128   std::string dir = cmSystemTools::GetFilenamePath(f);
3129   std::string file = cmSystemTools::GetFilenameName(f);
3130   DirectoryContent& dc = this->DirectoryContentMap[dir];
3131   dc.Generated.insert(file);
3132   dc.All.insert(file);
3133 }
3134
3135 std::set<std::string> const& cmGlobalGenerator::GetDirectoryContent(
3136   std::string const& dir, bool needDisk)
3137 {
3138   DirectoryContent& dc = this->DirectoryContentMap[dir];
3139   if (needDisk) {
3140     long mt = cmSystemTools::ModifiedTime(dir);
3141     if (mt != dc.LastDiskTime) {
3142       // Reset to non-loaded directory content.
3143       dc.All = dc.Generated;
3144
3145       // Load the directory content from disk.
3146       cmsys::Directory d;
3147       if (d.Load(dir)) {
3148         unsigned long n = d.GetNumberOfFiles();
3149         for (unsigned long i = 0; i < n; ++i) {
3150           const char* f = d.GetFile(i);
3151           if (strcmp(f, ".") != 0 && strcmp(f, "..") != 0) {
3152             dc.All.insert(f);
3153           }
3154         }
3155       }
3156       dc.LastDiskTime = mt;
3157     }
3158   }
3159   return dc.All;
3160 }
3161
3162 void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
3163                                     std::string const& content)
3164 {
3165 #if !defined(CMAKE_BOOTSTRAP)
3166   // Ignore if there are no outputs.
3167   if (outputs.empty()) {
3168     return;
3169   }
3170
3171   // Compute a hash of the rule.
3172   RuleHash hash;
3173   {
3174     cmCryptoHash md5(cmCryptoHash::AlgoMD5);
3175     std::string const md5_hex = md5.HashString(content);
3176     memcpy(hash.Data, md5_hex.c_str(), 32);
3177   }
3178
3179   // Shorten the output name (in expected use case).
3180   std::string fname =
3181     this->LocalGenerators[0]->MaybeRelativeToTopBinDir(outputs[0]);
3182
3183   // Associate the hash with this output.
3184   this->RuleHashes[fname] = hash;
3185 #else
3186   (void)outputs;
3187   (void)content;
3188 #endif
3189 }
3190
3191 void cmGlobalGenerator::CheckRuleHashes()
3192 {
3193 #if !defined(CMAKE_BOOTSTRAP)
3194   std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
3195   std::string pfile = cmStrCat(home, "/CMakeFiles/CMakeRuleHashes.txt");
3196   this->CheckRuleHashes(pfile, home);
3197   this->WriteRuleHashes(pfile);
3198 #endif
3199 }
3200
3201 void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
3202                                         std::string const& home)
3203 {
3204 #if defined(_WIN32) || defined(__CYGWIN__)
3205   cmsys::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
3206 #else
3207   cmsys::ifstream fin(pfile.c_str());
3208 #endif
3209   if (!fin) {
3210     return;
3211   }
3212   std::string line;
3213   std::string fname;
3214   while (cmSystemTools::GetLineFromStream(fin, line)) {
3215     // Line format is a 32-byte hex string followed by a space
3216     // followed by a file name (with no escaping).
3217
3218     // Skip blank and comment lines.
3219     if (line.size() < 34 || line[0] == '#') {
3220       continue;
3221     }
3222
3223     // Get the filename.
3224     fname = line.substr(33);
3225
3226     // Look for a hash for this file's rule.
3227     auto const rhi = this->RuleHashes.find(fname);
3228     if (rhi != this->RuleHashes.end()) {
3229       // Compare the rule hash in the file to that we were given.
3230       if (strncmp(line.c_str(), rhi->second.Data, 32) != 0) {
3231         // The rule has changed.  Delete the output so it will be
3232         // built again.
3233         fname = cmSystemTools::CollapseFullPath(fname, home);
3234         cmSystemTools::RemoveFile(fname);
3235       }
3236     } else {
3237       // We have no hash for a rule previously listed.  This may be a
3238       // case where a user has turned off a build option and might
3239       // want to turn it back on later, so do not delete the file.
3240       // Instead, we keep the rule hash as long as the file exists so
3241       // that if the feature is turned back on and the rule has
3242       // changed the file is still rebuilt.
3243       std::string fpath = cmSystemTools::CollapseFullPath(fname, home);
3244       if (cmSystemTools::FileExists(fpath)) {
3245         RuleHash hash;
3246         memcpy(hash.Data, line.c_str(), 32);
3247         this->RuleHashes[fname] = hash;
3248       }
3249     }
3250   }
3251 }
3252
3253 void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
3254 {
3255   // Now generate a new persistence file with the current hashes.
3256   if (this->RuleHashes.empty()) {
3257     cmSystemTools::RemoveFile(pfile);
3258   } else {
3259     cmGeneratedFileStream fout(pfile);
3260     fout << "# Hashes of file build rules.\n";
3261     for (auto const& rh : this->RuleHashes) {
3262       fout.write(rh.second.Data, 32);
3263       fout << " " << rh.first << "\n";
3264     }
3265   }
3266 }
3267
3268 void cmGlobalGenerator::WriteSummary()
3269 {
3270   // Record all target directories in a central location.
3271   std::string fname = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
3272                                "/CMakeFiles/TargetDirectories.txt");
3273   cmGeneratedFileStream fout(fname);
3274
3275   for (const auto& lg : this->LocalGenerators) {
3276     for (const auto& tgt : lg->GetGeneratorTargets()) {
3277       if (!tgt->IsInBuildSystem()) {
3278         continue;
3279       }
3280       this->WriteSummary(tgt.get());
3281       fout << tgt->GetSupportDirectory() << "\n";
3282     }
3283   }
3284 }
3285
3286 void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
3287 {
3288   // Place the labels file in a per-target support directory.
3289   std::string dir = target->GetSupportDirectory();
3290   std::string file = cmStrCat(dir, "/Labels.txt");
3291   std::string json_file = dir + "/Labels.json";
3292
3293 #ifndef CMAKE_BOOTSTRAP
3294   // Check whether labels are enabled for this target.
3295   cmValue targetLabels = target->GetProperty("LABELS");
3296   cmValue directoryLabels =
3297     target->Target->GetMakefile()->GetProperty("LABELS");
3298   cmValue cmakeDirectoryLabels =
3299     target->Target->GetMakefile()->GetDefinition("CMAKE_DIRECTORY_LABELS");
3300   if (targetLabels || directoryLabels || cmakeDirectoryLabels) {
3301     Json::Value lj_root(Json::objectValue);
3302     Json::Value& lj_target = lj_root["target"] = Json::objectValue;
3303     lj_target["name"] = target->GetName();
3304     Json::Value& lj_target_labels = lj_target["labels"] = Json::arrayValue;
3305     Json::Value& lj_sources = lj_root["sources"] = Json::arrayValue;
3306
3307     cmSystemTools::MakeDirectory(dir);
3308     cmGeneratedFileStream fout(file);
3309
3310     std::vector<std::string> labels;
3311
3312     // List the target-wide labels.  All sources in the target get
3313     // these labels.
3314     if (targetLabels) {
3315       cmExpandList(*targetLabels, labels);
3316       if (!labels.empty()) {
3317         fout << "# Target labels\n";
3318         for (std::string const& l : labels) {
3319           fout << " " << l << "\n";
3320           lj_target_labels.append(l);
3321         }
3322       }
3323     }
3324
3325     // List directory labels
3326     std::vector<std::string> directoryLabelsList;
3327     std::vector<std::string> cmakeDirectoryLabelsList;
3328
3329     if (directoryLabels) {
3330       cmExpandList(*directoryLabels, directoryLabelsList);
3331     }
3332
3333     if (cmakeDirectoryLabels) {
3334       cmExpandList(*cmakeDirectoryLabels, cmakeDirectoryLabelsList);
3335     }
3336
3337     if (!directoryLabelsList.empty() || !cmakeDirectoryLabelsList.empty()) {
3338       fout << "# Directory labels\n";
3339     }
3340
3341     for (std::string const& li : directoryLabelsList) {
3342       fout << " " << li << "\n";
3343       lj_target_labels.append(li);
3344     }
3345
3346     for (std::string const& li : cmakeDirectoryLabelsList) {
3347       fout << " " << li << "\n";
3348       lj_target_labels.append(li);
3349     }
3350
3351     // List the source files with any per-source labels.
3352     fout << "# Source files and their labels\n";
3353     std::vector<cmSourceFile*> sources;
3354     std::vector<std::string> const& configs =
3355       target->Target->GetMakefile()->GetGeneratorConfigs(
3356         cmMakefile::IncludeEmptyConfig);
3357     for (std::string const& c : configs) {
3358       target->GetSourceFiles(sources, c);
3359     }
3360     auto const sourcesEnd = cmRemoveDuplicates(sources);
3361     for (cmSourceFile* sf : cmMakeRange(sources.cbegin(), sourcesEnd)) {
3362       Json::Value& lj_source = lj_sources.append(Json::objectValue);
3363       std::string const& sfp = sf->ResolveFullPath();
3364       fout << sfp << "\n";
3365       lj_source["file"] = sfp;
3366       if (cmValue svalue = sf->GetProperty("LABELS")) {
3367         labels.clear();
3368         Json::Value& lj_source_labels = lj_source["labels"] = Json::arrayValue;
3369         cmExpandList(*svalue, labels);
3370         for (std::string const& label : labels) {
3371           fout << " " << label << "\n";
3372           lj_source_labels.append(label);
3373         }
3374       }
3375     }
3376     cmGeneratedFileStream json_fout(json_file);
3377     json_fout << lj_root;
3378   } else
3379 #endif
3380   {
3381     cmSystemTools::RemoveFile(file);
3382     cmSystemTools::RemoveFile(json_file);
3383   }
3384 }
3385
3386 // static
3387 std::string cmGlobalGenerator::EscapeJSON(const std::string& s)
3388 {
3389   std::string result;
3390   result.reserve(s.size());
3391   for (char i : s) {
3392     switch (i) {
3393       case '"':
3394       case '\\':
3395         result += '\\';
3396         result += i;
3397         break;
3398       case '\n':
3399         result += "\\n";
3400         break;
3401       case '\t':
3402         result += "\\t";
3403         break;
3404       default:
3405         result += i;
3406     }
3407   }
3408   return result;
3409 }
3410
3411 void cmGlobalGenerator::SetFilenameTargetDepends(
3412   cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts)
3413 {
3414   this->FilenameTargetDepends[sf] = tgts;
3415 }
3416
3417 std::set<cmGeneratorTarget const*> const&
3418 cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const
3419 {
3420   return this->FilenameTargetDepends[sf];
3421 }
3422
3423 const std::string& cmGlobalGenerator::GetRealPath(const std::string& dir)
3424 {
3425   auto i = this->RealPaths.lower_bound(dir);
3426   if (i == this->RealPaths.end() ||
3427       this->RealPaths.key_comp()(dir, i->first)) {
3428     i = this->RealPaths.emplace_hint(i, dir, cmSystemTools::GetRealPath(dir));
3429   }
3430   return i->second;
3431 }
3432
3433 std::string cmGlobalGenerator::NewDeferId()
3434 {
3435   return cmStrCat("__"_s, std::to_string(this->NextDeferId++));
3436 }
3437
3438 void cmGlobalGenerator::ProcessEvaluationFiles()
3439 {
3440   std::vector<std::string> generatedFiles;
3441   for (auto& localGen : this->LocalGenerators) {
3442     localGen->ProcessEvaluationFiles(generatedFiles);
3443   }
3444 }
3445
3446 std::string cmGlobalGenerator::ExpandCFGIntDir(
3447   const std::string& str, const std::string& /*config*/) const
3448 {
3449   return str;
3450 }
3451
3452 bool cmGlobalGenerator::GenerateCPackPropertiesFile()
3453 {
3454   cmake::InstalledFilesMap const& installedFiles =
3455     this->CMakeInstance->GetInstalledFiles();
3456
3457   const auto& lg = this->LocalGenerators[0];
3458   cmMakefile* mf = lg->GetMakefile();
3459
3460   std::vector<std::string> configs =
3461     mf->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig);
3462   std::string config = mf->GetDefaultConfiguration();
3463
3464   std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
3465                               "/CPackProperties.cmake");
3466
3467   if (!cmSystemTools::FileExists(path) && installedFiles.empty()) {
3468     return true;
3469   }
3470
3471   cmGeneratedFileStream file(path);
3472   file << "# CPack properties\n";
3473
3474   for (auto const& i : installedFiles) {
3475     cmInstalledFile const& installedFile = i.second;
3476
3477     cmCPackPropertiesGenerator cpackPropertiesGenerator(
3478       lg.get(), installedFile, configs);
3479
3480     cpackPropertiesGenerator.Generate(file, config, configs);
3481   }
3482
3483   return true;
3484 }
3485
3486 cmInstallRuntimeDependencySet*
3487 cmGlobalGenerator::CreateAnonymousRuntimeDependencySet()
3488 {
3489   auto set = cm::make_unique<cmInstallRuntimeDependencySet>();
3490   auto* retval = set.get();
3491   this->RuntimeDependencySets.push_back(std::move(set));
3492   return retval;
3493 }
3494
3495 cmInstallRuntimeDependencySet* cmGlobalGenerator::GetNamedRuntimeDependencySet(
3496   const std::string& name)
3497 {
3498   auto it = this->RuntimeDependencySetsByName.find(name);
3499   if (it == this->RuntimeDependencySetsByName.end()) {
3500     auto set = cm::make_unique<cmInstallRuntimeDependencySet>(name);
3501     it =
3502       this->RuntimeDependencySetsByName.insert(std::make_pair(name, set.get()))
3503         .first;
3504     this->RuntimeDependencySets.push_back(std::move(set));
3505   }
3506   return it->second;
3507 }