0fe55f048df771ada786f40bf15b90eaff580d9c
[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<std::pair<std::string, std::string>>
2558 cmGlobalGenerator::SplitFrameworkPath(const std::string& path,
2559                                       bool extendedFormat) 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 (!libname.empty() && !cmHasPrefix(libname, name)) {
2575       return cm::nullopt;
2576     }
2577     return std::pair<std::string, std::string>{ frameworkPath.match(2), name };
2578   }
2579
2580   if (extendedFormat) {
2581     // path format can be more flexible: (/path/to/)?fwName(.framework)?
2582     auto fwDir = cmSystemTools::GetParentDirectory(path);
2583     auto name = cmSystemTools::GetFilenameLastExtension(path) == ".framework"
2584       ? cmSystemTools::GetFilenameWithoutExtension(path)
2585       : cmSystemTools::GetFilenameName(path);
2586
2587     return std::pair<std::string, std::string>{ fwDir, name };
2588   }
2589
2590   return cm::nullopt;
2591 }
2592
2593 bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName,
2594                                      std::string const& reason) const
2595 {
2596   cmTarget* tgt = this->FindTarget(targetName);
2597   if (!tgt) {
2598     return true;
2599   }
2600   MessageType messageType = MessageType::AUTHOR_WARNING;
2601   std::ostringstream e;
2602   bool issueMessage = false;
2603   switch (tgt->GetPolicyStatusCMP0037()) {
2604     case cmPolicies::WARN:
2605       e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
2606       issueMessage = true;
2607       CM_FALLTHROUGH;
2608     case cmPolicies::OLD:
2609       break;
2610     case cmPolicies::NEW:
2611     case cmPolicies::REQUIRED_IF_USED:
2612     case cmPolicies::REQUIRED_ALWAYS:
2613       issueMessage = true;
2614       messageType = MessageType::FATAL_ERROR;
2615       break;
2616   }
2617   if (issueMessage) {
2618     e << "The target name \"" << targetName << "\" is reserved " << reason
2619       << ".";
2620     if (messageType == MessageType::AUTHOR_WARNING) {
2621       e << "  It may result in undefined behavior.";
2622     }
2623     this->GetCMakeInstance()->IssueMessage(messageType, e.str(),
2624                                            tgt->GetBacktrace());
2625     if (messageType == MessageType::FATAL_ERROR) {
2626       return false;
2627     }
2628   }
2629   return true;
2630 }
2631
2632 void cmGlobalGenerator::CreateDefaultGlobalTargets(
2633   std::vector<GlobalTargetInfo>& targets)
2634 {
2635   this->AddGlobalTarget_Package(targets);
2636   this->AddGlobalTarget_PackageSource(targets);
2637   this->AddGlobalTarget_Test(targets);
2638   this->AddGlobalTarget_EditCache(targets);
2639   this->AddGlobalTarget_RebuildCache(targets);
2640   this->AddGlobalTarget_Install(targets);
2641 }
2642
2643 void cmGlobalGenerator::AddGlobalTarget_Package(
2644   std::vector<GlobalTargetInfo>& targets)
2645 {
2646   auto& mf = this->Makefiles[0];
2647   std::string configFile =
2648     cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake");
2649   if (!cmSystemTools::FileExists(configFile)) {
2650     return;
2651   }
2652
2653   static const auto reservedTargets = { "package", "PACKAGE" };
2654   for (auto const& target : reservedTargets) {
2655     if (!this->CheckCMP0037(target, "when CPack packaging is enabled")) {
2656       return;
2657     }
2658   }
2659
2660   const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
2661   GlobalTargetInfo gti;
2662   gti.Name = this->GetPackageTargetName();
2663   gti.Message = "Run CPack packaging tool...";
2664   gti.UsesTerminal = true;
2665   gti.WorkingDir = mf->GetCurrentBinaryDirectory();
2666   cmCustomCommandLine singleLine;
2667   singleLine.push_back(cmSystemTools::GetCPackCommand());
2668   if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
2669     singleLine.push_back("-C");
2670     singleLine.push_back(cmakeCfgIntDir);
2671   }
2672   singleLine.push_back("--config");
2673   singleLine.push_back("./CPackConfig.cmake");
2674   gti.CommandLines.push_back(std::move(singleLine));
2675   if (this->GetPreinstallTargetName()) {
2676     gti.Depends.emplace_back(this->GetPreinstallTargetName());
2677   } else {
2678     cmValue noPackageAll =
2679       mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
2680     if (cmIsOff(noPackageAll)) {
2681       gti.Depends.emplace_back(this->GetAllTargetName());
2682     }
2683   }
2684   targets.push_back(std::move(gti));
2685 }
2686
2687 void cmGlobalGenerator::AddGlobalTarget_PackageSource(
2688   std::vector<GlobalTargetInfo>& targets)
2689 {
2690   const char* packageSourceTargetName = this->GetPackageSourceTargetName();
2691   if (!packageSourceTargetName) {
2692     return;
2693   }
2694
2695   auto& mf = this->Makefiles[0];
2696   std::string configFile =
2697     cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake");
2698   if (!cmSystemTools::FileExists(configFile)) {
2699     return;
2700   }
2701
2702   static const auto reservedTargets = { "package_source" };
2703   for (auto const& target : reservedTargets) {
2704     if (!this->CheckCMP0037(target,
2705                             "when CPack source packaging is enabled")) {
2706       return;
2707     }
2708   }
2709
2710   GlobalTargetInfo gti;
2711   gti.Name = packageSourceTargetName;
2712   gti.Message = "Run CPack packaging tool for source...";
2713   gti.WorkingDir = mf->GetCurrentBinaryDirectory();
2714   gti.UsesTerminal = true;
2715   cmCustomCommandLine singleLine;
2716   singleLine.push_back(cmSystemTools::GetCPackCommand());
2717   singleLine.push_back("--config");
2718   singleLine.push_back("./CPackSourceConfig.cmake");
2719   singleLine.push_back(std::move(configFile));
2720   gti.CommandLines.push_back(std::move(singleLine));
2721   targets.push_back(std::move(gti));
2722 }
2723
2724 void cmGlobalGenerator::AddGlobalTarget_Test(
2725   std::vector<GlobalTargetInfo>& targets)
2726 {
2727   auto& mf = this->Makefiles[0];
2728   if (!mf->IsOn("CMAKE_TESTING_ENABLED")) {
2729     return;
2730   }
2731
2732   static const auto reservedTargets = { "test", "RUN_TESTS" };
2733   for (auto const& target : reservedTargets) {
2734     if (!this->CheckCMP0037(target, "when CTest testing is enabled")) {
2735       return;
2736     }
2737   }
2738
2739   const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
2740   GlobalTargetInfo gti;
2741   gti.Name = this->GetTestTargetName();
2742   gti.Message = "Running tests...";
2743   gti.UsesTerminal = true;
2744   cmCustomCommandLine singleLine;
2745   singleLine.push_back(cmSystemTools::GetCTestCommand());
2746   singleLine.push_back("--force-new-ctest-process");
2747   std::vector<std::string> args;
2748   if (mf->GetDefExpandList("CMAKE_CTEST_ARGUMENTS", args)) {
2749     for (auto const& arg : args) {
2750       singleLine.push_back(arg);
2751     }
2752   }
2753   if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
2754     singleLine.push_back("-C");
2755     singleLine.push_back(cmakeCfgIntDir);
2756   } else // TODO: This is a hack. Should be something to do with the
2757          // generator
2758   {
2759     singleLine.push_back("$(ARGS)");
2760   }
2761   gti.CommandLines.push_back(std::move(singleLine));
2762   targets.push_back(std::move(gti));
2763 }
2764
2765 void cmGlobalGenerator::AddGlobalTarget_EditCache(
2766   std::vector<GlobalTargetInfo>& targets) const
2767 {
2768   const char* editCacheTargetName = this->GetEditCacheTargetName();
2769   if (!editCacheTargetName) {
2770     return;
2771   }
2772   GlobalTargetInfo gti;
2773   gti.Name = editCacheTargetName;
2774   gti.PerConfig = cmTarget::PerConfig::No;
2775   cmCustomCommandLine singleLine;
2776
2777   // Use generator preference for the edit_cache rule if it is defined.
2778   std::string edit_cmd = this->GetEditCacheCommand();
2779   if (!edit_cmd.empty()) {
2780     singleLine.push_back(std::move(edit_cmd));
2781     singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
2782     singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
2783     gti.Message = "Running CMake cache editor...";
2784     gti.UsesTerminal = true;
2785   } else {
2786     singleLine.push_back(cmSystemTools::GetCMakeCommand());
2787     singleLine.push_back("-E");
2788     singleLine.push_back("echo");
2789     singleLine.push_back("No interactive CMake dialog available.");
2790     gti.Message = "No interactive CMake dialog available...";
2791     gti.UsesTerminal = false;
2792     gti.StdPipesUTF8 = true;
2793   }
2794   gti.CommandLines.push_back(std::move(singleLine));
2795
2796   targets.push_back(std::move(gti));
2797 }
2798
2799 void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
2800   std::vector<GlobalTargetInfo>& targets) const
2801 {
2802   const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
2803   if (!rebuildCacheTargetName) {
2804     return;
2805   }
2806   GlobalTargetInfo gti;
2807   gti.Name = rebuildCacheTargetName;
2808   gti.Message = "Running CMake to regenerate build system...";
2809   gti.UsesTerminal = true;
2810   gti.PerConfig = cmTarget::PerConfig::No;
2811   cmCustomCommandLine singleLine;
2812   singleLine.push_back(cmSystemTools::GetCMakeCommand());
2813   singleLine.push_back("--regenerate-during-build");
2814   singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
2815   singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
2816   gti.CommandLines.push_back(std::move(singleLine));
2817   gti.StdPipesUTF8 = true;
2818   targets.push_back(std::move(gti));
2819 }
2820
2821 void cmGlobalGenerator::AddGlobalTarget_Install(
2822   std::vector<GlobalTargetInfo>& targets)
2823 {
2824   auto& mf = this->Makefiles[0];
2825   const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
2826   bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES");
2827   if (this->InstallTargetEnabled && skipInstallRules) {
2828     this->CMakeInstance->IssueMessage(
2829       MessageType::WARNING,
2830       "CMAKE_SKIP_INSTALL_RULES was enabled even though "
2831       "installation rules have been specified",
2832       mf->GetBacktrace());
2833   } else if (this->InstallTargetEnabled && !skipInstallRules) {
2834     if (!(cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.')) {
2835       std::set<std::string>* componentsSet = &this->InstallComponents;
2836       std::ostringstream ostr;
2837       if (!componentsSet->empty()) {
2838         ostr << "Available install components are: ";
2839         ostr << cmWrap('"', *componentsSet, '"', " ");
2840       } else {
2841         ostr << "Only default component available";
2842       }
2843       GlobalTargetInfo gti;
2844       gti.Name = "list_install_components";
2845       gti.Message = ostr.str();
2846       gti.UsesTerminal = false;
2847       targets.push_back(std::move(gti));
2848     }
2849     std::string cmd = cmSystemTools::GetCMakeCommand();
2850     GlobalTargetInfo gti;
2851     gti.Name = this->GetInstallTargetName();
2852     gti.Message = "Install the project...";
2853     gti.UsesTerminal = true;
2854     gti.StdPipesUTF8 = true;
2855     cmCustomCommandLine singleLine;
2856     if (this->GetPreinstallTargetName()) {
2857       gti.Depends.emplace_back(this->GetPreinstallTargetName());
2858     } else {
2859       cmValue noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
2860       if (cmIsOff(noall)) {
2861         gti.Depends.emplace_back(this->GetAllTargetName());
2862       }
2863     }
2864     if (mf->GetDefinition("CMake_BINARY_DIR") &&
2865         !mf->IsOn("CMAKE_CROSSCOMPILING")) {
2866       // We are building CMake itself.  We cannot use the original
2867       // executable to install over itself.  The generator will
2868       // automatically convert this name to the build-time location.
2869       cmd = "cmake";
2870     }
2871     singleLine.push_back(cmd);
2872     if (cmNonempty(cmakeCfgIntDir) && cmakeCfgIntDir[0] != '.') {
2873       std::string cfgArg = "-DBUILD_TYPE=";
2874       bool useEPN = this->UseEffectivePlatformName(mf.get());
2875       if (useEPN) {
2876         cfgArg += "$(CONFIGURATION)";
2877         singleLine.push_back(cfgArg);
2878         cfgArg = "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)";
2879       } else {
2880         cfgArg += *mf->GetDefinition("CMAKE_CFG_INTDIR");
2881       }
2882       singleLine.push_back(cfgArg);
2883     }
2884     singleLine.push_back("-P");
2885     singleLine.push_back("cmake_install.cmake");
2886     gti.CommandLines.push_back(singleLine);
2887     targets.push_back(gti);
2888
2889     // install_local
2890     if (const char* install_local = this->GetInstallLocalTargetName()) {
2891       gti.Name = install_local;
2892       gti.Message = "Installing only the local directory...";
2893       gti.UsesTerminal = true;
2894       gti.CommandLines.clear();
2895
2896       cmCustomCommandLine localCmdLine = singleLine;
2897
2898       localCmdLine.insert(localCmdLine.begin() + 1,
2899                           "-DCMAKE_INSTALL_LOCAL_ONLY=1");
2900
2901       gti.CommandLines.push_back(std::move(localCmdLine));
2902       targets.push_back(gti);
2903     }
2904
2905     // install_strip
2906     const char* install_strip = this->GetInstallStripTargetName();
2907     if ((install_strip != nullptr) && (mf->IsSet("CMAKE_STRIP"))) {
2908       gti.Name = install_strip;
2909       gti.Message = "Installing the project stripped...";
2910       gti.UsesTerminal = true;
2911       gti.CommandLines.clear();
2912
2913       cmCustomCommandLine stripCmdLine = singleLine;
2914
2915       stripCmdLine.insert(stripCmdLine.begin() + 1,
2916                           "-DCMAKE_INSTALL_DO_STRIP=1");
2917       gti.CommandLines.push_back(std::move(stripCmdLine));
2918       targets.push_back(gti);
2919     }
2920   }
2921 }
2922
2923 std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const
2924 {
2925   cmValue prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
2926     "PREDEFINED_TARGETS_FOLDER");
2927
2928   if (prop) {
2929     return *prop;
2930   }
2931
2932   return "CMakePredefinedTargets";
2933 }
2934
2935 bool cmGlobalGenerator::UseFolderProperty() const
2936 {
2937   cmValue prop =
2938     this->GetCMakeInstance()->GetState()->GetGlobalProperty("USE_FOLDERS");
2939
2940   // If this property is defined, let the setter turn this on or off...
2941   //
2942   if (prop) {
2943     return cmIsOn(*prop);
2944   }
2945
2946   // By default, this feature is OFF, since it is not supported in the
2947   // Visual Studio Express editions until VS11:
2948   //
2949   return false;
2950 }
2951
2952 void cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
2953                                            cmMakefile* mf)
2954 {
2955   // Package
2956   auto tb =
2957     mf->CreateNewTarget(gti.Name, cmStateEnums::GLOBAL_TARGET, gti.PerConfig);
2958
2959   // Do nothing if gti.Name is already used
2960   if (!tb.second) {
2961     return;
2962   }
2963
2964   cmTarget& target = tb.first;
2965   target.SetProperty("EXCLUDE_FROM_ALL", "TRUE");
2966
2967   // Store the custom command in the target.
2968   cmCustomCommand cc;
2969   cc.SetCommandLines(gti.CommandLines);
2970   cc.SetWorkingDirectory(gti.WorkingDir.c_str());
2971   cc.SetStdPipesUTF8(gti.StdPipesUTF8);
2972   cc.SetUsesTerminal(gti.UsesTerminal);
2973   target.AddPostBuildCommand(std::move(cc));
2974   if (!gti.Message.empty()) {
2975     target.SetProperty("EchoString", gti.Message);
2976   }
2977   for (std::string const& d : gti.Depends) {
2978     target.AddUtility(d, false);
2979   }
2980
2981   // Organize in the "predefined targets" folder:
2982   //
2983   if (this->UseFolderProperty()) {
2984     target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
2985   }
2986 }
2987
2988 std::string cmGlobalGenerator::GenerateRuleFile(
2989   std::string const& output) const
2990 {
2991   std::string ruleFile = cmStrCat(output, ".rule");
2992   const char* dir = this->GetCMakeCFGIntDir();
2993   if (dir && dir[0] == '$') {
2994     cmSystemTools::ReplaceString(ruleFile, dir, "/CMakeFiles");
2995   }
2996   return ruleFile;
2997 }
2998
2999 bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
3000 {
3001   return mf->PlatformIsAppleEmbedded();
3002 }
3003
3004 std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
3005   std::string const& l) const
3006 {
3007   auto const it = this->LanguageToOriginalSharedLibFlags.find(l);
3008   if (it != this->LanguageToOriginalSharedLibFlags.end()) {
3009     return it->second;
3010   }
3011   return "";
3012 }
3013
3014 void cmGlobalGenerator::AppendDirectoryForConfig(const std::string& /*unused*/,
3015                                                  const std::string& /*unused*/,
3016                                                  const std::string& /*unused*/,
3017                                                  std::string& /*unused*/)
3018 {
3019   // Subclasses that support multiple configurations should implement
3020   // this method to append the subdirectory for the given build
3021   // configuration.
3022 }
3023
3024 cmGlobalGenerator::TargetDependSet const&
3025 cmGlobalGenerator::GetTargetDirectDepends(cmGeneratorTarget const* target)
3026 {
3027   return this->TargetDependencies[target];
3028 }
3029
3030 bool cmGlobalGenerator::IsReservedTarget(std::string const& name)
3031 {
3032   // The following is a list of targets reserved
3033   // by one or more of the cmake generators.
3034
3035   // Adding additional targets to this list will require a policy!
3036   const char* reservedTargets[] = { "all",       "ALL_BUILD",  "help",
3037                                     "install",   "INSTALL",    "preinstall",
3038                                     "clean",     "edit_cache", "rebuild_cache",
3039                                     "ZERO_CHECK" };
3040
3041   return cm::contains(reservedTargets, name);
3042 }
3043
3044 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
3045   std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator)
3046 {
3047   this->ExtraGenerator = std::move(extraGenerator);
3048   if (this->ExtraGenerator) {
3049     this->ExtraGenerator->SetGlobalGenerator(this);
3050   }
3051 }
3052
3053 std::string cmGlobalGenerator::GetExtraGeneratorName() const
3054 {
3055   return this->ExtraGenerator ? this->ExtraGenerator->GetName()
3056                               : std::string();
3057 }
3058
3059 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
3060 {
3061   this->FilesReplacedDuringGenerate.push_back(filename);
3062 }
3063
3064 void cmGlobalGenerator::GetFilesReplacedDuringGenerate(
3065   std::vector<std::string>& filenames)
3066 {
3067   filenames.clear();
3068   std::copy(this->FilesReplacedDuringGenerate.begin(),
3069             this->FilesReplacedDuringGenerate.end(),
3070             std::back_inserter(filenames));
3071 }
3072
3073 void cmGlobalGenerator::GetTargetSets(
3074   TargetDependSet& projectTargets, TargetDependSet& originalTargets,
3075   cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
3076 {
3077   // loop over all local generators
3078   for (auto* generator : generators) {
3079     // check to make sure generator is not excluded
3080     if (this->IsExcluded(root, generator)) {
3081       continue;
3082     }
3083     // loop over all the generator targets in the makefile
3084     for (const auto& target : generator->GetGeneratorTargets()) {
3085       if (this->IsRootOnlyTarget(target.get()) &&
3086           target->GetLocalGenerator() != root) {
3087         continue;
3088       }
3089       // put the target in the set of original targets
3090       originalTargets.insert(target.get());
3091       // Get the set of targets that depend on target
3092       this->AddTargetDepends(target.get(), projectTargets);
3093     }
3094   }
3095 }
3096
3097 bool cmGlobalGenerator::IsRootOnlyTarget(cmGeneratorTarget* target) const
3098 {
3099   return (target->GetType() == cmStateEnums::GLOBAL_TARGET ||
3100           target->GetName() == this->GetAllTargetName());
3101 }
3102
3103 void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target,
3104                                          TargetDependSet& projectTargets)
3105 {
3106   // add the target itself
3107   if (projectTargets.insert(target).second) {
3108     // This is the first time we have encountered the target.
3109     // Recursively follow its dependencies.
3110     for (auto const& t : this->GetTargetDirectDepends(target)) {
3111       this->AddTargetDepends(t, projectTargets);
3112     }
3113   }
3114 }
3115
3116 void cmGlobalGenerator::AddToManifest(std::string const& f)
3117 {
3118   // Add to the content listing for the file's directory.
3119   std::string dir = cmSystemTools::GetFilenamePath(f);
3120   std::string file = cmSystemTools::GetFilenameName(f);
3121   DirectoryContent& dc = this->DirectoryContentMap[dir];
3122   dc.Generated.insert(file);
3123   dc.All.insert(file);
3124 }
3125
3126 std::set<std::string> const& cmGlobalGenerator::GetDirectoryContent(
3127   std::string const& dir, bool needDisk)
3128 {
3129   DirectoryContent& dc = this->DirectoryContentMap[dir];
3130   if (needDisk) {
3131     long mt = cmSystemTools::ModifiedTime(dir);
3132     if (mt != dc.LastDiskTime) {
3133       // Reset to non-loaded directory content.
3134       dc.All = dc.Generated;
3135
3136       // Load the directory content from disk.
3137       cmsys::Directory d;
3138       if (d.Load(dir)) {
3139         unsigned long n = d.GetNumberOfFiles();
3140         for (unsigned long i = 0; i < n; ++i) {
3141           const char* f = d.GetFile(i);
3142           if (strcmp(f, ".") != 0 && strcmp(f, "..") != 0) {
3143             dc.All.insert(f);
3144           }
3145         }
3146       }
3147       dc.LastDiskTime = mt;
3148     }
3149   }
3150   return dc.All;
3151 }
3152
3153 void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
3154                                     std::string const& content)
3155 {
3156 #if !defined(CMAKE_BOOTSTRAP)
3157   // Ignore if there are no outputs.
3158   if (outputs.empty()) {
3159     return;
3160   }
3161
3162   // Compute a hash of the rule.
3163   RuleHash hash;
3164   {
3165     cmCryptoHash md5(cmCryptoHash::AlgoMD5);
3166     std::string const md5_hex = md5.HashString(content);
3167     memcpy(hash.Data, md5_hex.c_str(), 32);
3168   }
3169
3170   // Shorten the output name (in expected use case).
3171   std::string fname =
3172     this->LocalGenerators[0]->MaybeRelativeToTopBinDir(outputs[0]);
3173
3174   // Associate the hash with this output.
3175   this->RuleHashes[fname] = hash;
3176 #else
3177   (void)outputs;
3178   (void)content;
3179 #endif
3180 }
3181
3182 void cmGlobalGenerator::CheckRuleHashes()
3183 {
3184 #if !defined(CMAKE_BOOTSTRAP)
3185   std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
3186   std::string pfile = cmStrCat(home, "/CMakeFiles/CMakeRuleHashes.txt");
3187   this->CheckRuleHashes(pfile, home);
3188   this->WriteRuleHashes(pfile);
3189 #endif
3190 }
3191
3192 void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
3193                                         std::string const& home)
3194 {
3195 #if defined(_WIN32) || defined(__CYGWIN__)
3196   cmsys::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
3197 #else
3198   cmsys::ifstream fin(pfile.c_str());
3199 #endif
3200   if (!fin) {
3201     return;
3202   }
3203   std::string line;
3204   std::string fname;
3205   while (cmSystemTools::GetLineFromStream(fin, line)) {
3206     // Line format is a 32-byte hex string followed by a space
3207     // followed by a file name (with no escaping).
3208
3209     // Skip blank and comment lines.
3210     if (line.size() < 34 || line[0] == '#') {
3211       continue;
3212     }
3213
3214     // Get the filename.
3215     fname = line.substr(33);
3216
3217     // Look for a hash for this file's rule.
3218     auto const rhi = this->RuleHashes.find(fname);
3219     if (rhi != this->RuleHashes.end()) {
3220       // Compare the rule hash in the file to that we were given.
3221       if (strncmp(line.c_str(), rhi->second.Data, 32) != 0) {
3222         // The rule has changed.  Delete the output so it will be
3223         // built again.
3224         fname = cmSystemTools::CollapseFullPath(fname, home);
3225         cmSystemTools::RemoveFile(fname);
3226       }
3227     } else {
3228       // We have no hash for a rule previously listed.  This may be a
3229       // case where a user has turned off a build option and might
3230       // want to turn it back on later, so do not delete the file.
3231       // Instead, we keep the rule hash as long as the file exists so
3232       // that if the feature is turned back on and the rule has
3233       // changed the file is still rebuilt.
3234       std::string fpath = cmSystemTools::CollapseFullPath(fname, home);
3235       if (cmSystemTools::FileExists(fpath)) {
3236         RuleHash hash;
3237         memcpy(hash.Data, line.c_str(), 32);
3238         this->RuleHashes[fname] = hash;
3239       }
3240     }
3241   }
3242 }
3243
3244 void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
3245 {
3246   // Now generate a new persistence file with the current hashes.
3247   if (this->RuleHashes.empty()) {
3248     cmSystemTools::RemoveFile(pfile);
3249   } else {
3250     cmGeneratedFileStream fout(pfile);
3251     fout << "# Hashes of file build rules.\n";
3252     for (auto const& rh : this->RuleHashes) {
3253       fout.write(rh.second.Data, 32);
3254       fout << " " << rh.first << "\n";
3255     }
3256   }
3257 }
3258
3259 void cmGlobalGenerator::WriteSummary()
3260 {
3261   // Record all target directories in a central location.
3262   std::string fname = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
3263                                "/CMakeFiles/TargetDirectories.txt");
3264   cmGeneratedFileStream fout(fname);
3265
3266   for (const auto& lg : this->LocalGenerators) {
3267     for (const auto& tgt : lg->GetGeneratorTargets()) {
3268       if (!tgt->IsInBuildSystem()) {
3269         continue;
3270       }
3271       this->WriteSummary(tgt.get());
3272       fout << tgt->GetSupportDirectory() << "\n";
3273     }
3274   }
3275 }
3276
3277 void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
3278 {
3279   // Place the labels file in a per-target support directory.
3280   std::string dir = target->GetSupportDirectory();
3281   std::string file = cmStrCat(dir, "/Labels.txt");
3282   std::string json_file = dir + "/Labels.json";
3283
3284 #ifndef CMAKE_BOOTSTRAP
3285   // Check whether labels are enabled for this target.
3286   cmValue targetLabels = target->GetProperty("LABELS");
3287   cmValue directoryLabels =
3288     target->Target->GetMakefile()->GetProperty("LABELS");
3289   cmValue cmakeDirectoryLabels =
3290     target->Target->GetMakefile()->GetDefinition("CMAKE_DIRECTORY_LABELS");
3291   if (targetLabels || directoryLabels || cmakeDirectoryLabels) {
3292     Json::Value lj_root(Json::objectValue);
3293     Json::Value& lj_target = lj_root["target"] = Json::objectValue;
3294     lj_target["name"] = target->GetName();
3295     Json::Value& lj_target_labels = lj_target["labels"] = Json::arrayValue;
3296     Json::Value& lj_sources = lj_root["sources"] = Json::arrayValue;
3297
3298     cmSystemTools::MakeDirectory(dir);
3299     cmGeneratedFileStream fout(file);
3300
3301     std::vector<std::string> labels;
3302
3303     // List the target-wide labels.  All sources in the target get
3304     // these labels.
3305     if (targetLabels) {
3306       cmExpandList(*targetLabels, labels);
3307       if (!labels.empty()) {
3308         fout << "# Target labels\n";
3309         for (std::string const& l : labels) {
3310           fout << " " << l << "\n";
3311           lj_target_labels.append(l);
3312         }
3313       }
3314     }
3315
3316     // List directory labels
3317     std::vector<std::string> directoryLabelsList;
3318     std::vector<std::string> cmakeDirectoryLabelsList;
3319
3320     if (directoryLabels) {
3321       cmExpandList(*directoryLabels, directoryLabelsList);
3322     }
3323
3324     if (cmakeDirectoryLabels) {
3325       cmExpandList(*cmakeDirectoryLabels, cmakeDirectoryLabelsList);
3326     }
3327
3328     if (!directoryLabelsList.empty() || !cmakeDirectoryLabelsList.empty()) {
3329       fout << "# Directory labels\n";
3330     }
3331
3332     for (std::string const& li : directoryLabelsList) {
3333       fout << " " << li << "\n";
3334       lj_target_labels.append(li);
3335     }
3336
3337     for (std::string const& li : cmakeDirectoryLabelsList) {
3338       fout << " " << li << "\n";
3339       lj_target_labels.append(li);
3340     }
3341
3342     // List the source files with any per-source labels.
3343     fout << "# Source files and their labels\n";
3344     std::vector<cmSourceFile*> sources;
3345     std::vector<std::string> const& configs =
3346       target->Target->GetMakefile()->GetGeneratorConfigs(
3347         cmMakefile::IncludeEmptyConfig);
3348     for (std::string const& c : configs) {
3349       target->GetSourceFiles(sources, c);
3350     }
3351     auto const sourcesEnd = cmRemoveDuplicates(sources);
3352     for (cmSourceFile* sf : cmMakeRange(sources.cbegin(), sourcesEnd)) {
3353       Json::Value& lj_source = lj_sources.append(Json::objectValue);
3354       std::string const& sfp = sf->ResolveFullPath();
3355       fout << sfp << "\n";
3356       lj_source["file"] = sfp;
3357       if (cmValue svalue = sf->GetProperty("LABELS")) {
3358         labels.clear();
3359         Json::Value& lj_source_labels = lj_source["labels"] = Json::arrayValue;
3360         cmExpandList(*svalue, labels);
3361         for (std::string const& label : labels) {
3362           fout << " " << label << "\n";
3363           lj_source_labels.append(label);
3364         }
3365       }
3366     }
3367     cmGeneratedFileStream json_fout(json_file);
3368     json_fout << lj_root;
3369   } else
3370 #endif
3371   {
3372     cmSystemTools::RemoveFile(file);
3373     cmSystemTools::RemoveFile(json_file);
3374   }
3375 }
3376
3377 // static
3378 std::string cmGlobalGenerator::EscapeJSON(const std::string& s)
3379 {
3380   std::string result;
3381   result.reserve(s.size());
3382   for (char i : s) {
3383     switch (i) {
3384       case '"':
3385       case '\\':
3386         result += '\\';
3387         result += i;
3388         break;
3389       case '\n':
3390         result += "\\n";
3391         break;
3392       case '\t':
3393         result += "\\t";
3394         break;
3395       default:
3396         result += i;
3397     }
3398   }
3399   return result;
3400 }
3401
3402 void cmGlobalGenerator::SetFilenameTargetDepends(
3403   cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts)
3404 {
3405   this->FilenameTargetDepends[sf] = tgts;
3406 }
3407
3408 std::set<cmGeneratorTarget const*> const&
3409 cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const
3410 {
3411   return this->FilenameTargetDepends[sf];
3412 }
3413
3414 const std::string& cmGlobalGenerator::GetRealPath(const std::string& dir)
3415 {
3416   auto i = this->RealPaths.lower_bound(dir);
3417   if (i == this->RealPaths.end() ||
3418       this->RealPaths.key_comp()(dir, i->first)) {
3419     i = this->RealPaths.emplace_hint(i, dir, cmSystemTools::GetRealPath(dir));
3420   }
3421   return i->second;
3422 }
3423
3424 std::string cmGlobalGenerator::NewDeferId()
3425 {
3426   return cmStrCat("__"_s, std::to_string(this->NextDeferId++));
3427 }
3428
3429 void cmGlobalGenerator::ProcessEvaluationFiles()
3430 {
3431   std::vector<std::string> generatedFiles;
3432   for (auto& localGen : this->LocalGenerators) {
3433     localGen->ProcessEvaluationFiles(generatedFiles);
3434   }
3435 }
3436
3437 std::string cmGlobalGenerator::ExpandCFGIntDir(
3438   const std::string& str, const std::string& /*config*/) const
3439 {
3440   return str;
3441 }
3442
3443 bool cmGlobalGenerator::GenerateCPackPropertiesFile()
3444 {
3445   cmake::InstalledFilesMap const& installedFiles =
3446     this->CMakeInstance->GetInstalledFiles();
3447
3448   const auto& lg = this->LocalGenerators[0];
3449   cmMakefile* mf = lg->GetMakefile();
3450
3451   std::vector<std::string> configs =
3452     mf->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig);
3453   std::string config = mf->GetDefaultConfiguration();
3454
3455   std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
3456                               "/CPackProperties.cmake");
3457
3458   if (!cmSystemTools::FileExists(path) && installedFiles.empty()) {
3459     return true;
3460   }
3461
3462   cmGeneratedFileStream file(path);
3463   file << "# CPack properties\n";
3464
3465   for (auto const& i : installedFiles) {
3466     cmInstalledFile const& installedFile = i.second;
3467
3468     cmCPackPropertiesGenerator cpackPropertiesGenerator(
3469       lg.get(), installedFile, configs);
3470
3471     cpackPropertiesGenerator.Generate(file, config, configs);
3472   }
3473
3474   return true;
3475 }
3476
3477 cmInstallRuntimeDependencySet*
3478 cmGlobalGenerator::CreateAnonymousRuntimeDependencySet()
3479 {
3480   auto set = cm::make_unique<cmInstallRuntimeDependencySet>();
3481   auto* retval = set.get();
3482   this->RuntimeDependencySets.push_back(std::move(set));
3483   return retval;
3484 }
3485
3486 cmInstallRuntimeDependencySet* cmGlobalGenerator::GetNamedRuntimeDependencySet(
3487   const std::string& name)
3488 {
3489   auto it = this->RuntimeDependencySetsByName.find(name);
3490   if (it == this->RuntimeDependencySetsByName.end()) {
3491     auto set = cm::make_unique<cmInstallRuntimeDependencySet>(name);
3492     it =
3493       this->RuntimeDependencySetsByName.insert(std::make_pair(name, set.get()))
3494         .first;
3495     this->RuntimeDependencySets.push_back(std::move(set));
3496   }
3497   return it->second;
3498 }