1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #if defined(_WIN32) && !defined(__CYGWIN__)
13 #include "windows.h" // this must be first to define GetCurrentDirectory
16 #include "cmGlobalGenerator.h"
17 #include "cmLocalGenerator.h"
18 #include "cmExternalMakefileProjectGenerator.h"
20 #include "cmMakefile.h"
21 #include "cmQtAutomoc.h"
22 #include "cmSourceFile.h"
23 #include "cmVersion.h"
24 #include "cmTargetExport.h"
25 #include "cmComputeTargetDepends.h"
26 #include "cmGeneratedFileStream.h"
27 #include "cmGeneratorTarget.h"
28 #include "cmGeneratorExpression.h"
29 #include "cmGeneratorExpressionEvaluationFile.h"
31 #include <cmsys/Directory.hxx>
33 #if defined(CMAKE_BUILD_WITH_CMAKE)
34 # include <cmsys/MD5.h>
37 #include <stdlib.h> // required for atof
41 cmGlobalGenerator::cmGlobalGenerator()
43 // By default the .SYMBOLIC dependency is not needed on symbolic rules.
44 this->NeedSymbolicMark = false;
46 // by default use the native paths
47 this->ForceUnixPaths = false;
49 // By default do not try to support color.
50 this->ToolSupportsColor = false;
52 // By default do not use link scripts.
53 this->UseLinkScript = false;
55 // Whether an install target is needed.
56 this->InstallTargetEnabled = false;
58 // how long to let try compiles run
59 this->TryCompileTimeout = 0;
61 this->ExtraGenerator = 0;
62 this->CurrentLocalGenerator = 0;
63 this->TryCompileOuterMakefile = 0;
66 cmGlobalGenerator::~cmGlobalGenerator()
68 // Delete any existing cmLocalGenerators
69 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
71 delete this->LocalGenerators[i];
73 for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
74 li = this->EvaluationFiles.begin();
75 li != this->EvaluationFiles.end();
80 this->LocalGenerators.clear();
82 if (this->ExtraGenerator)
84 delete this->ExtraGenerator;
87 this->ClearGeneratorTargets();
90 bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts)
95 " " << this->GetName() << "\n"
96 "does not support toolset specification, but toolset\n"
99 this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
100 cmListFileBacktrace());
104 void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
108 std::string langComp = "CMAKE_";
110 langComp += "_COMPILER";
112 if(!mf->GetDefinition(langComp.c_str()))
116 cmSystemTools::Error(langComp.c_str(),
117 " not set, after EnableLanguage");
121 const char* name = mf->GetRequiredDefinition(langComp.c_str());
123 if(!cmSystemTools::FileIsFullPath(name))
125 path = cmSystemTools::FindProgram(name);
131 if((path.size() == 0 || !cmSystemTools::FileExists(path.c_str()))
132 && (optional==false))
134 std::string message = "your ";
136 message += " compiler: \"";
138 message += "\" was not found. Please set ";
140 message += " to a valid compiler path or name.";
141 cmSystemTools::Error(message.c_str());
144 std::string doc = lang;
146 const char* cname = this->GetCMakeInstance()->
147 GetCacheManager()->GetCacheValue(langComp.c_str());
148 std::string changeVars;
149 if(cname && (path != cname) && (optional==false))
151 std::string cnameString = cname;
152 std::string pathString = path;
153 // get rid of potentially multiple slashes:
154 cmSystemTools::ConvertToUnixSlashes(cnameString);
155 cmSystemTools::ConvertToUnixSlashes(pathString);
156 if (cnameString != pathString)
159 this->GetCMakeInstance()->GetProperty(
160 "__CMAKE_DELETE_CACHE_CHANGE_VARS_");
166 changeVars += langComp;
169 this->GetCMakeInstance()->SetProperty(
170 "__CMAKE_DELETE_CACHE_CHANGE_VARS_",
174 mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
175 doc.c_str(), cmCacheManager::FILEPATH);
178 // Find the make program for the generator, required for try compiles
179 void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
181 if(this->FindMakeProgramFile.size() == 0)
183 cmSystemTools::Error(
184 "Generator implementation error, "
185 "all generators must specify this->FindMakeProgramFile");
187 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
188 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
190 std::string setMakeProgram =
191 mf->GetModulesFile(this->FindMakeProgramFile.c_str());
192 if(setMakeProgram.size())
194 mf->ReadListFile(0, setMakeProgram.c_str());
197 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
198 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
201 err << "CMake was unable to find a build program corresponding to \""
202 << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You "
203 << "probably need to select a different build tool.";
204 cmSystemTools::Error(err.str().c_str());
205 cmSystemTools::SetFatalErrorOccured();
208 std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
209 // if there are spaces in the make program use short path
210 // but do not short path the actual program name, as
211 // this can cause trouble with VSExpress
212 if(makeProgram.find(' ') != makeProgram.npos)
216 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
218 std::string saveFile = file;
219 cmSystemTools::GetShortPath(makeProgram.c_str(), makeProgram);
220 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
224 makeProgram += saveFile;
225 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
227 cmCacheManager::FILEPATH);
230 if(makeProgram.find("xcodebuild") != makeProgram.npos)
232 // due to the text file busy /bin/sh problem with xcodebuild
233 // use the cmakexbuild wrapper instead. This program
234 // will run xcodebuild and if it sees the error text file busy
235 // it will stop forwarding output, and let the build finish.
236 // Then it will retry the build. It will continue this
237 // untill no text file busy errors occur.
238 std::string cmakexbuild =
239 this->CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_COMMAND");
240 cmakexbuild = cmakexbuild.substr(0, cmakexbuild.length()-5);
241 cmakexbuild += "cmakexbuild";
243 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM",
246 cmCacheManager::FILEPATH);
250 // enable the given language
252 // The following files are loaded in this order:
254 // First figure out what OS we are running on:
256 // CMakeSystem.cmake - configured file created by CMakeDetermineSystem.cmake
257 // CMakeDetermineSystem.cmake - figure out os info and create
258 // CMakeSystem.cmake IF CMAKE_SYSTEM
260 // CMakeSystem.cmake - configured file created by
261 // CMakeDetermineSystem.cmake IF CMAKE_SYSTEM_LOADED
263 // Next try and enable all languages found in the languages vector
265 // FOREACH LANG in languages
266 // CMake(LANG)Compiler.cmake - configured file create by
267 // CMakeDetermine(LANG)Compiler.cmake
268 // CMakeDetermine(LANG)Compiler.cmake - Finds compiler for LANG and
269 // creates CMake(LANG)Compiler.cmake
270 // CMake(LANG)Compiler.cmake - configured file created by
271 // CMakeDetermine(LANG)Compiler.cmake
273 // CMakeSystemSpecificInformation.cmake
274 // - includes Platform/${CMAKE_SYSTEM_NAME}.cmake
275 // may use compiler stuff
277 // FOREACH LANG in languages
278 // CMake(LANG)Information.cmake
279 // - loads Platform/${CMAKE_SYSTEM_NAME}-${COMPILER}.cmake
280 // CMakeTest(LANG)Compiler.cmake
281 // - Make sure the compiler works with a try compile if
282 // CMakeDetermine(LANG) was loaded
284 // Now load a few files that can override values set in any of the above
285 // (PROJECTNAME)Compatibility.cmake
286 // - load any backwards compatibility stuff for current project
287 // ${CMAKE_USER_MAKE_RULES_OVERRIDE}
288 // - allow users a chance to override system variables
293 cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
294 cmMakefile *mf, bool)
296 if(languages.size() == 0)
298 cmSystemTools::Error("EnableLanguage must have a lang specified!");
299 cmSystemTools::SetFatalErrorOccured();
303 if(this->TryCompileOuterMakefile)
305 // In a try-compile we can only enable languages provided by caller.
306 for(std::vector<std::string>::const_iterator li = languages.begin();
307 li != languages.end(); ++li)
311 this->SetLanguageEnabled("NONE", mf);
315 const char* lang = li->c_str();
316 if(this->LanguagesReady.find(lang) == this->LanguagesReady.end())
319 e << "The test project needs language "
320 << lang << " which is not enabled.";
321 this->TryCompileOuterMakefile
322 ->IssueMessage(cmake::FATAL_ERROR, e.str());
323 cmSystemTools::SetFatalErrorOccured();
330 mf->AddDefinition("RUN_CONFIGURE", true);
331 std::string rootBin = mf->GetHomeOutputDirectory();
332 rootBin += cmake::GetCMakeFilesDirectory();
334 // If the configuration files path has been set,
335 // then we are in a try compile and need to copy the enable language
336 // files from the parent cmake bin dir, into the try compile bin dir
337 if(this->ConfiguredFilesPath.size())
339 rootBin = this->ConfiguredFilesPath;
342 rootBin += cmVersion::GetCMakeVersion();
344 // set the dir for parent files so they can be used by modules
345 mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR",rootBin.c_str());
347 // find and make sure CMAKE_MAKE_PROGRAM is defined
348 this->FindMakeProgram(mf);
350 // try and load the CMakeSystem.cmake if it is there
351 std::string fpath = rootBin;
352 if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
354 fpath += "/CMakeSystem.cmake";
355 if(cmSystemTools::FileExists(fpath.c_str()))
357 mf->ReadListFile(0,fpath.c_str());
360 // Load the CMakeDetermineSystem.cmake file and find out
361 // what platform we are running on
362 if (!mf->GetDefinition("CMAKE_SYSTEM"))
364 #if defined(_WIN32) && !defined(__CYGWIN__)
365 /* Windows version number data. */
367 ZeroMemory(&osvi, sizeof(osvi));
368 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
369 GetVersionEx (&osvi);
370 cmOStringStream windowsVersionString;
371 windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
372 windowsVersionString.str();
373 mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
374 windowsVersionString.str().c_str());
376 // Read the DetermineSystem file
377 std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
378 mf->ReadListFile(0, systemFile.c_str());
379 // load the CMakeSystem.cmake from the binary directory
380 // this file is configured by the CMakeDetermineSystem.cmake file
382 fpath += "/CMakeSystem.cmake";
383 mf->ReadListFile(0,fpath.c_str());
385 std::map<cmStdString, bool> needTestLanguage;
386 std::map<cmStdString, bool> needSetLanguageEnabledMaps;
388 // load the CMakeDetermine(LANG)Compiler.cmake file to find
391 for(std::vector<std::string>::const_iterator l = languages.begin();
392 l != languages.end(); ++l)
394 const char* lang = l->c_str();
395 needSetLanguageEnabledMaps[lang] = false;
398 this->SetLanguageEnabled("NONE", mf);
401 std::string loadedLang = "CMAKE_";
403 loadedLang += "_COMPILER_LOADED";
404 if(!mf->GetDefinition(loadedLang.c_str()))
409 fpath += "Compiler.cmake";
411 // If the existing build tree was already configured with this
412 // version of CMake then try to load the configured file first
413 // to avoid duplicate compiler tests.
414 if(cmSystemTools::FileExists(fpath.c_str()))
416 if(!mf->ReadListFile(0,fpath.c_str()))
418 cmSystemTools::Error("Could not find cmake module file: ",
421 // if this file was found then the language was already determined
423 needTestLanguage[lang] = false;
424 this->SetLanguageEnabledFlag(lang, mf);
425 needSetLanguageEnabledMaps[lang] = true;
426 // this can only be called after loading CMake(LANG)Compiler.cmake
430 if(!this->GetLanguageEnabled(lang) )
432 if (this->CMakeInstance->GetIsInTryCompile())
434 cmSystemTools::Error("This should not have happened. "
435 "If you see this message, you are probably "
436 "using a broken CMakeLists.txt file or a "
437 "problematic release of CMake");
439 // if the CMake(LANG)Compiler.cmake file was not found then
440 // load CMakeDetermine(LANG)Compiler.cmake
441 std::string determineCompiler = "CMakeDetermine";
442 determineCompiler += lang;
443 determineCompiler += "Compiler.cmake";
444 std::string determineFile =
445 mf->GetModulesFile(determineCompiler.c_str());
446 if(!mf->ReadListFile(0,determineFile.c_str()))
448 cmSystemTools::Error("Could not find cmake module file: ",
449 determineFile.c_str());
451 needTestLanguage[lang] = true;
452 // Some generators like visual studio should not use the env variables
453 // So the global generator can specify that in this variable
454 if(!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV"))
456 // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
457 // into the environment, in case user scripts want to run
458 // configure, or sub cmakes
459 std::string compilerName = "CMAKE_";
460 compilerName += lang;
461 compilerName += "_COMPILER";
462 std::string compilerEnv = "CMAKE_";
464 compilerEnv += "_COMPILER_ENV_VAR";
465 std::string envVar = mf->GetRequiredDefinition(compilerEnv.c_str());
466 std::string envVarValue =
467 mf->GetRequiredDefinition(compilerName.c_str());
468 std::string env = envVar;
471 cmSystemTools::PutEnv(env.c_str());
474 // if determineLanguage was called then load the file it
475 // configures CMake(LANG)Compiler.cmake
479 fpath += "Compiler.cmake";
480 if(!mf->ReadListFile(0,fpath.c_str()))
482 cmSystemTools::Error("Could not find cmake module file: ",
485 this->SetLanguageEnabledFlag(lang, mf);
486 needSetLanguageEnabledMaps[lang] = true;
487 // this can only be called after loading CMake(LANG)Compiler.cmake
488 // the language must be enabled for try compile to work, but we do
489 // not know if it is a working compiler yet so set the test language
491 needTestLanguage[lang] = true;
492 } // end if(!this->GetLanguageEnabled(lang) )
493 } // end loop over languages
495 // **** Load the system specific information if not yet loaded
496 if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
498 fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
499 if(!mf->ReadListFile(0,fpath.c_str()))
501 cmSystemTools::Error("Could not find cmake module file: ",
505 // loop over languages again loading CMake(LANG)Information.cmake
507 for(std::vector<std::string>::const_iterator l = languages.begin();
508 l != languages.end(); ++l)
510 const char* lang = l->c_str();
513 this->SetLanguageEnabled("NONE", mf);
516 std::string langLoadedVar = "CMAKE_";
517 langLoadedVar += lang;
518 langLoadedVar += "_INFORMATION_LOADED";
519 if (!mf->GetDefinition(langLoadedVar.c_str()))
523 fpath += "Information.cmake";
524 std::string informationFile = mf->GetModulesFile(fpath.c_str());
525 if (informationFile.empty())
527 cmSystemTools::Error("Could not find cmake module file: ",
530 else if(!mf->ReadListFile(0, informationFile.c_str()))
532 cmSystemTools::Error("Could not process cmake module file: ",
533 informationFile.c_str());
536 if (needSetLanguageEnabledMaps[lang])
538 this->SetLanguageEnabledMaps(lang, mf);
540 this->LanguagesReady.insert(lang);
542 std::string compilerName = "CMAKE_";
543 compilerName += lang;
544 compilerName += "_COMPILER";
545 std::string compilerLangFile = rootBin;
546 compilerLangFile += "/CMake";
547 compilerLangFile += lang;
548 compilerLangFile += "Compiler.cmake";
549 // Test the compiler for the language just setup
550 // (but only if a compiler has been actually found)
551 // At this point we should have enough info for a try compile
552 // which is used in the backward stuff
553 // If the language is untested then test it now with a try compile.
554 if (!mf->IsSet(compilerName.c_str()))
556 // if the compiler did not work, then remove the
557 // CMake(LANG)Compiler.cmake file so that it will get tested the
558 // next time cmake is run
559 cmSystemTools::RemoveFile(compilerLangFile.c_str());
561 else if(needTestLanguage[lang])
563 if (!this->CMakeInstance->GetIsInTryCompile())
565 std::string testLang = "CMakeTest";
567 testLang += "Compiler.cmake";
568 std::string ifpath = mf->GetModulesFile(testLang.c_str());
569 if(!mf->ReadListFile(0,ifpath.c_str()))
571 cmSystemTools::Error("Could not find cmake module file: ",
574 std::string compilerWorks = "CMAKE_";
575 compilerWorks += lang;
576 compilerWorks += "_COMPILER_WORKS";
577 // if the compiler did not work, then remove the
578 // CMake(LANG)Compiler.cmake file so that it will get tested the
579 // next time cmake is run
580 if(!mf->IsOn(compilerWorks.c_str()))
582 cmSystemTools::RemoveFile(compilerLangFile.c_str());
586 // load backwards compatibility stuff for C and CXX
587 // for old versions of CMake ListFiles C and CXX had some
588 // backwards compatibility files they have to load
589 // These files have a bunch of try compiles in them so
590 // should only be done
591 if (mf->NeedBackwardsCompatibility(1,4))
593 if(strcmp(lang, "C") == 0)
596 mf->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
597 mf->ReadListFile(0,ifpath.c_str());
599 if(strcmp(lang, "CXX") == 0)
602 mf->GetModulesFile("CMakeBackwardCompatibilityCXX.cmake");
603 mf->ReadListFile(0,ifpath.c_str());
607 } // end if in try compile
608 } // end need test language
609 // Store the shared library flags so that we can satisfy CMP0018
610 std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_";
611 sharedLibFlagsVar += lang;
612 sharedLibFlagsVar += "_FLAGS";
613 const char* sharedLibFlags =
614 mf->GetSafeDefinition(sharedLibFlagsVar.c_str());
617 this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags;
619 } // end for each language
621 // Now load files that can override any settings on the platform or for
622 // the project First load the project compatibility file if it is in
624 std::string projectCompatibility = mf->GetDefinition("CMAKE_ROOT");
625 projectCompatibility += "/Modules/";
626 projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
627 projectCompatibility += "Compatibility.cmake";
628 if(cmSystemTools::FileExists(projectCompatibility.c_str()))
630 mf->ReadListFile(0,projectCompatibility.c_str());
634 //----------------------------------------------------------------------------
636 cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source)
638 if(const char* lang = source.GetLanguage())
640 if(this->LanguageToOutputExtension.count(lang) > 0)
642 return this->LanguageToOutputExtension[lang].c_str();
647 // if no language is found then check to see if it is already an
648 // ouput extension for some language. In that case it should be ignored
649 // and in this map, so it will not be compiled but will just be used.
650 std::string const& ext = source.GetExtension();
653 if(this->OutputExtensions.count(ext))
663 const char* cmGlobalGenerator::GetLanguageFromExtension(const char* ext)
665 // if there is an extension and it starts with . then move past the
666 // . because the extensions are not stored with a . in the map
667 if(ext && *ext == '.')
671 if(this->ExtensionToLanguage.count(ext) > 0)
673 return this->ExtensionToLanguage[ext].c_str();
678 /* SetLanguageEnabled() is now split in two parts:
679 at first the enabled-flag is set. This can then be used in EnabledLanguage()
680 for checking whether the language is already enabled. After setting this
681 flag still the values from the cmake variables have to be copied into the
682 internal maps, this is done in SetLanguageEnabledMaps() which is called
683 after the system- and compiler specific files have been loaded.
685 This split was done originally so that compiler-specific configuration
686 files could change the object file extension
687 (CMAKE_<LANG>_OUTPUT_EXTENSION) before the CMake variables were copied
690 void cmGlobalGenerator::SetLanguageEnabled(const char* l, cmMakefile* mf)
692 this->SetLanguageEnabledFlag(l, mf);
693 this->SetLanguageEnabledMaps(l, mf);
696 void cmGlobalGenerator::SetLanguageEnabledFlag(const char* l, cmMakefile* mf)
698 this->LanguageEnabled[l] = true;
700 // Fill the language-to-extension map with the current variable
701 // settings to make sure it is available for the try_compile()
702 // command source file signature. In SetLanguageEnabledMaps this
703 // will be done again to account for any compiler- or
704 // platform-specific entries.
705 this->FillExtensionToLanguageMap(l, mf);
708 void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
710 // use LanguageToLinkerPreference to detect whether this functions has
712 if (this->LanguageToLinkerPreference.find(l) !=
713 this->LanguageToLinkerPreference.end())
718 std::string linkerPrefVar = std::string("CMAKE_") +
719 std::string(l) + std::string("_LINKER_PREFERENCE");
720 const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
724 if (sscanf(linkerPref, "%d", &preference)!=1)
726 // backward compatibility: before 2.6 LINKER_PREFERENCE
727 // was either "None" or "Prefered", and only the first character was
728 // tested. So if there is a custom language out there and it is
729 // "Prefered", set its preference high
730 if (linkerPref[0]=='P')
743 std::string msg = linkerPrefVar;
744 msg += " is negative, adjusting it to 0";
745 cmSystemTools::Message(msg.c_str(), "Warning");
749 this->LanguageToLinkerPreference[l] = preference;
751 std::string outputExtensionVar = std::string("CMAKE_") +
752 std::string(l) + std::string("_OUTPUT_EXTENSION");
753 const char* outputExtension = mf->GetDefinition(outputExtensionVar.c_str());
756 this->LanguageToOutputExtension[l] = outputExtension;
757 this->OutputExtensions[outputExtension] = outputExtension;
758 if(outputExtension[0] == '.')
760 this->OutputExtensions[outputExtension+1] = outputExtension+1;
764 // The map was originally filled by SetLanguageEnabledFlag, but
765 // since then the compiler- and platform-specific files have been
766 // loaded which might have added more entries.
767 this->FillExtensionToLanguageMap(l, mf);
769 std::string ignoreExtensionsVar = std::string("CMAKE_") +
770 std::string(l) + std::string("_IGNORE_EXTENSIONS");
771 std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar.c_str());
772 std::vector<std::string> extensionList;
773 cmSystemTools::ExpandListArgument(ignoreExts, extensionList);
774 for(std::vector<std::string>::iterator i = extensionList.begin();
775 i != extensionList.end(); ++i)
777 this->IgnoreExtensions[*i] = true;
782 void cmGlobalGenerator::FillExtensionToLanguageMap(const char* l,
785 std::string extensionsVar = std::string("CMAKE_") +
786 std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS");
787 std::string exts = mf->GetSafeDefinition(extensionsVar.c_str());
788 std::vector<std::string> extensionList;
789 cmSystemTools::ExpandListArgument(exts, extensionList);
790 for(std::vector<std::string>::iterator i = extensionList.begin();
791 i != extensionList.end(); ++i)
793 this->ExtensionToLanguage[*i] = l;
797 bool cmGlobalGenerator::IgnoreFile(const char* l)
799 if(this->GetLanguageFromExtension(l))
803 return (this->IgnoreExtensions.count(l) > 0);
806 bool cmGlobalGenerator::GetLanguageEnabled(const char* l) const
808 return (this->LanguageEnabled.find(l)!= this->LanguageEnabled.end());
811 void cmGlobalGenerator::ClearEnabledLanguages()
813 this->LanguageEnabled.clear();
816 bool cmGlobalGenerator::IsDependedOn(const char* project,
819 // Get all local gens for this project
820 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
821 // loop over local gens and get the targets for each one
822 for(unsigned int i = 0; i < gens->size(); ++i)
824 cmTargets& targets = (*gens)[i]->GetMakefile()->GetTargets();
825 for (cmTargets::iterator l = targets.begin();
826 l != targets.end(); l++)
828 cmTarget& target = l->second;
829 TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target);
830 if(tgtdeps.count(targetIn))
839 void cmGlobalGenerator::Configure()
841 this->FirstTimeProgress = 0.0f;
842 this->ClearGeneratorTargets();
843 this->ExportSets.clear();
844 // Delete any existing cmLocalGenerators
846 for (i = 0; i < this->LocalGenerators.size(); ++i)
848 delete this->LocalGenerators[i];
850 this->LocalGenerators.clear();
851 for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
852 li = this->EvaluationFiles.begin();
853 li != this->EvaluationFiles.end();
858 this->EvaluationFiles.clear();
859 this->TargetDependencies.clear();
860 this->TotalTargets.clear();
861 this->ImportedTargets.clear();
862 this->LocalGeneratorToTargetMap.clear();
863 this->ProjectMap.clear();
864 this->RuleHashes.clear();
865 this->DirectoryContentMap.clear();
866 this->BinaryDirectories.clear();
868 // start with this directory
869 cmLocalGenerator *lg = this->CreateLocalGenerator();
870 this->LocalGenerators.push_back(lg);
872 // set the Start directories
873 cmMakefile* mf = lg->GetMakefile();
874 lg->GetMakefile()->SetStartDirectory
875 (this->CMakeInstance->GetStartDirectory());
876 lg->GetMakefile()->SetStartOutputDirectory
877 (this->CMakeInstance->GetStartOutputDirectory());
878 lg->GetMakefile()->MakeStartDirectoriesCurrent();
880 this->BinaryDirectories.insert(mf->GetStartOutputDirectory());
885 // update the cache entry for the number of local generators, this is used
888 sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size()));
889 this->GetCMakeInstance()->AddCacheEntry
890 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
891 "number of local generators", cmCacheManager::INTERNAL);
893 // check for link libraries and include directories containing "NOTFOUND"
894 // and for infinite loops
895 this->CheckLocalGenerators();
897 // at this point this->LocalGenerators has been filled,
898 // so create the map from project name to vector of local generators
899 this->FillProjectMap();
901 if ( this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE)
904 if(cmSystemTools::GetErrorOccuredFlag())
906 msg << "Configuring incomplete, errors occurred!";
907 const char* logs[] = {"CMakeOutput.log", "CMakeError.log", 0};
908 for(const char** log = logs; *log; ++log)
910 std::string f = this->CMakeInstance->GetHomeOutputDirectory();
911 f += this->CMakeInstance->GetCMakeFilesDirectory();
914 if(cmSystemTools::FileExists(f.c_str()))
916 msg << "\nSee also \"" << f << "\".";
922 msg << "Configuring done";
924 this->CMakeInstance->UpdateProgress(msg.str().c_str(), -1);
928 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
930 // If the property is not enabled then okay.
931 if(!this->CMakeInstance
932 ->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
937 // This generator does not support duplicate custom targets.
939 e << "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
940 << "global property. "
941 << "The \"" << this->GetName() << "\" generator does not support "
942 << "duplicate custom targets. "
943 << "Consider using a Makefiles generator or fix the project to not "
944 << "use duplicate target names.";
945 cmSystemTools::Error(e.str().c_str());
949 void cmGlobalGenerator::Generate()
951 // Some generators track files replaced during the Generate.
952 // Start with an empty vector:
953 this->FilesReplacedDuringGenerate.clear();
955 // Check whether this generator is allowed to run.
956 if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
961 // Check that all targets are valid.
962 if(!this->CheckTargets())
967 this->FinalizeTargetCompileDefinitions();
969 // Iterate through all targets and set up automoc for those which have
970 // the AUTOMOC property set
971 this->CreateAutomocTargets();
973 // For each existing cmLocalGenerator
976 // Put a copy of each global target in every directory.
977 cmTargets globalTargets;
978 this->CreateDefaultGlobalTargets(&globalTargets);
979 for (i = 0; i < this->LocalGenerators.size(); ++i)
981 cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
982 cmTargets* targets = &(mf->GetTargets());
983 cmTargets::iterator tit;
984 for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit )
986 (*targets)[tit->first] = tit->second;
987 (*targets)[tit->first].SetMakefile(mf);
990 for ( tit = targets->begin(); tit != targets->end(); ++ tit )
992 tit->second.AppendBuildInterfaceIncludes();
996 // Add generator specific helper commands
997 for (i = 0; i < this->LocalGenerators.size(); ++i)
999 this->LocalGenerators[i]->AddHelperCommands();
1002 // Trace the dependencies, after that no custom commands should be added
1003 // because their dependencies might not be handled correctly
1004 for (i = 0; i < this->LocalGenerators.size(); ++i)
1006 this->LocalGenerators[i]->TraceDependencies();
1009 // Compute the manifest of main targets generated.
1010 for (i = 0; i < this->LocalGenerators.size(); ++i)
1012 this->LocalGenerators[i]->GenerateTargetManifest();
1015 // Create per-target generator information.
1016 this->CreateGeneratorTargets();
1018 this->ProcessEvaluationFiles();
1020 // Compute the inter-target dependencies.
1021 if(!this->ComputeTargetDepends())
1026 // Create a map from local generator to the complete set of targets
1027 // it builds by default.
1028 this->FillLocalGeneratorToTargetMap();
1030 for (i = 0; i < this->LocalGenerators.size(); ++i)
1032 cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
1033 cmTargets* targets = &(mf->GetTargets());
1034 for ( cmTargets::iterator it = targets->begin();
1035 it != targets->end(); ++ it )
1037 it->second.FinalizeSystemIncludeDirectories();
1041 // Generate project files
1042 for (i = 0; i < this->LocalGenerators.size(); ++i)
1044 this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem();
1045 this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
1046 this->LocalGenerators[i]->Generate();
1047 this->LocalGenerators[i]->GenerateInstallRules();
1048 this->LocalGenerators[i]->GenerateTestFiles();
1049 this->CMakeInstance->UpdateProgress("Generating",
1050 (static_cast<float>(i)+1.0f)/
1051 static_cast<float>(this->LocalGenerators.size()));
1053 this->SetCurrentLocalGenerator(0);
1055 // Update rule hashes.
1056 this->CheckRuleHashes();
1058 this->WriteSummary();
1060 if (this->ExtraGenerator != 0)
1062 this->ExtraGenerator->Generate();
1065 this->CMakeInstance->UpdateProgress("Generating done", -1);
1068 //----------------------------------------------------------------------------
1069 bool cmGlobalGenerator::ComputeTargetDepends()
1071 cmComputeTargetDepends ctd(this);
1076 std::vector<cmTarget*> const& targets = ctd.GetTargets();
1077 for(std::vector<cmTarget*>::const_iterator ti = targets.begin();
1078 ti != targets.end(); ++ti)
1080 ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]);
1085 //----------------------------------------------------------------------------
1086 bool cmGlobalGenerator::CheckTargets()
1088 // Make sure all targets can find their source files.
1089 for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
1091 cmTargets& targets =
1092 this->LocalGenerators[i]->GetMakefile()->GetTargets();
1093 for(cmTargets::iterator ti = targets.begin();
1094 ti != targets.end(); ++ti)
1096 cmTarget& target = ti->second;
1097 if(target.GetType() == cmTarget::EXECUTABLE ||
1098 target.GetType() == cmTarget::STATIC_LIBRARY ||
1099 target.GetType() == cmTarget::SHARED_LIBRARY ||
1100 target.GetType() == cmTarget::MODULE_LIBRARY ||
1101 target.GetType() == cmTarget::OBJECT_LIBRARY ||
1102 target.GetType() == cmTarget::UTILITY)
1104 if(!target.FindSourceFiles())
1114 //----------------------------------------------------------------------------
1115 void cmGlobalGenerator::CreateAutomocTargets()
1117 #ifdef CMAKE_BUILD_WITH_CMAKE
1118 typedef std::vector<std::pair<cmQtAutomoc, cmTarget*> > Automocs;
1120 for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
1122 cmTargets& targets =
1123 this->LocalGenerators[i]->GetMakefile()->GetTargets();
1124 for(cmTargets::iterator ti = targets.begin();
1125 ti != targets.end(); ++ti)
1127 cmTarget& target = ti->second;
1128 if(target.GetType() == cmTarget::EXECUTABLE ||
1129 target.GetType() == cmTarget::STATIC_LIBRARY ||
1130 target.GetType() == cmTarget::SHARED_LIBRARY ||
1131 target.GetType() == cmTarget::MODULE_LIBRARY ||
1132 target.GetType() == cmTarget::OBJECT_LIBRARY)
1134 if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported())
1136 cmQtAutomoc automoc;
1137 if(automoc.InitializeMocSourceFile(&target))
1139 automocs.push_back(std::make_pair(automoc, &target));
1145 for (Automocs::iterator it = automocs.begin(); it != automocs.end();
1148 it->first.SetupAutomocTarget(it->second);
1153 //----------------------------------------------------------------------------
1154 void cmGlobalGenerator::FinalizeTargetCompileDefinitions()
1156 // Construct per-target generator information.
1157 for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
1159 cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
1161 const std::vector<cmValueWithOrigin> noconfig_compile_definitions =
1162 mf->GetCompileDefinitionsEntries();
1164 std::vector<std::string> configs;
1165 mf->GetConfigurations(configs);
1167 cmTargets& targets = mf->GetTargets();
1168 for(cmTargets::iterator ti = targets.begin();
1169 ti != targets.end(); ++ti)
1171 cmTarget* t = &ti->second;
1173 for (std::vector<cmValueWithOrigin>::const_iterator it
1174 = noconfig_compile_definitions.begin();
1175 it != noconfig_compile_definitions.end(); ++it)
1177 t->InsertCompileDefinition(*it);
1180 for(std::vector<std::string>::const_iterator ci = configs.begin();
1181 ci != configs.end(); ++ci)
1183 std::string defPropName = "COMPILE_DEFINITIONS_";
1184 defPropName += cmSystemTools::UpperCase(*ci);
1185 t->AppendProperty(defPropName.c_str(),
1186 mf->GetProperty(defPropName.c_str()));
1192 //----------------------------------------------------------------------------
1193 void cmGlobalGenerator::CreateGeneratorTargets()
1195 // Construct per-target generator information.
1196 for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
1198 cmGeneratorTargetsType generatorTargets;
1200 cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
1202 cmTargets& targets = mf->GetTargets();
1203 for(cmTargets::iterator ti = targets.begin();
1204 ti != targets.end(); ++ti)
1206 cmTarget* t = &ti->second;
1207 cmGeneratorTarget* gt = new cmGeneratorTarget(t);
1208 this->GeneratorTargets[t] = gt;
1209 this->ComputeTargetObjects(gt);
1210 generatorTargets[t] = gt;
1213 for(std::vector<cmTarget*>::const_iterator
1214 j = mf->GetOwnedImportedTargets().begin();
1215 j != mf->GetOwnedImportedTargets().end(); ++j)
1217 cmGeneratorTarget* gt = new cmGeneratorTarget(*j);
1218 this->GeneratorTargets[*j] = gt;
1219 generatorTargets[*j] = gt;
1222 mf->SetGeneratorTargets(generatorTargets);
1226 //----------------------------------------------------------------------------
1227 void cmGlobalGenerator::ClearGeneratorTargets()
1229 for(cmGeneratorTargetsType::iterator i = this->GeneratorTargets.begin();
1230 i != this->GeneratorTargets.end(); ++i)
1234 this->GeneratorTargets.clear();
1237 //----------------------------------------------------------------------------
1238 cmGeneratorTarget* cmGlobalGenerator::GetGeneratorTarget(cmTarget* t) const
1240 cmGeneratorTargetsType::const_iterator ti = this->GeneratorTargets.find(t);
1241 if(ti == this->GeneratorTargets.end())
1243 this->CMakeInstance->IssueMessage(
1244 cmake::INTERNAL_ERROR, "Missing cmGeneratorTarget instance!",
1245 cmListFileBacktrace());
1251 //----------------------------------------------------------------------------
1252 void cmGlobalGenerator::ComputeTargetObjects(cmGeneratorTarget*) const
1254 // Implemented in generator subclasses that need this.
1257 void cmGlobalGenerator::CheckLocalGenerators()
1259 std::map<cmStdString, cmStdString> notFoundMap;
1260 // std::set<cmStdString> notFoundMap;
1261 // after it is all done do a ConfigureFinalPass
1262 cmCacheManager* manager = 0;
1263 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
1265 manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
1266 this->LocalGenerators[i]->ConfigureFinalPass();
1267 cmTargets &targets =
1268 this->LocalGenerators[i]->GetMakefile()->GetTargets();
1269 for (cmTargets::iterator l = targets.begin();
1270 l != targets.end(); l++)
1272 const cmTarget::LinkLibraryVectorType& libs =
1273 l->second.GetOriginalLinkLibraries();
1274 for(cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin();
1275 lib != libs.end(); ++lib)
1277 if(lib->first.size() > 9 &&
1278 cmSystemTools::IsNOTFOUND(lib->first.c_str()))
1280 std::string varName = lib->first.substr(0, lib->first.size()-9);
1281 cmCacheManager::CacheIterator it =
1282 manager->GetCacheIterator(varName.c_str());
1283 if(it.GetPropertyAsBool("ADVANCED"))
1285 varName += " (ADVANCED)";
1287 std::string text = notFoundMap[varName];
1288 text += "\n linked by target \"";
1289 text += l->second.GetName();
1290 text += "\" in directory ";
1291 text+=this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
1292 notFoundMap[varName] = text;
1295 std::vector<std::string> incs;
1296 const char *incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
1302 std::string incDirs = cmGeneratorExpression::Preprocess(incDirProp,
1303 cmGeneratorExpression::StripAllGeneratorExpressions);
1305 cmSystemTools::ExpandListArgument(incDirs.c_str(), incs);
1307 for( std::vector<std::string>::const_iterator incDir = incs.begin();
1308 incDir != incs.end(); ++incDir)
1310 if(incDir->size() > 9 &&
1311 cmSystemTools::IsNOTFOUND(incDir->c_str()))
1313 std::string varName = incDir->substr(0, incDir->size()-9);
1314 cmCacheManager::CacheIterator it =
1315 manager->GetCacheIterator(varName.c_str());
1316 if(it.GetPropertyAsBool("ADVANCED"))
1318 varName += " (ADVANCED)";
1320 std::string text = notFoundMap[varName];
1321 text += "\n used as include directory in directory ";
1322 text += this->LocalGenerators[i]
1323 ->GetMakefile()->GetCurrentDirectory();
1324 notFoundMap[varName] = text;
1328 this->CMakeInstance->UpdateProgress
1329 ("Configuring", 0.9f+0.1f*(static_cast<float>(i)+1.0f)/
1330 static_cast<float>(this->LocalGenerators.size()));
1333 if(notFoundMap.size())
1335 std::string notFoundVars;
1336 for(std::map<cmStdString, cmStdString>::const_iterator
1337 ii = notFoundMap.begin();
1338 ii != notFoundMap.end();
1341 notFoundVars += ii->first;
1342 notFoundVars += ii->second;
1343 notFoundVars += "\n";
1345 cmSystemTools::Error("The following variables are used in this project, "
1346 "but they are set to NOTFOUND.\n"
1347 "Please set them or make sure they are set and "
1348 "tested correctly in the CMake files:\n",
1349 notFoundVars.c_str());
1353 int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
1354 const char *projectName,
1355 const char *target, bool fast,
1356 std::string *output, cmMakefile *mf)
1358 // if this is not set, then this is a first time configure
1359 // and there is a good chance that the try compile stuff will
1360 // take the bulk of the time, so try and guess some progress
1361 // by getting closer and closer to 100 without actually getting there.
1362 if (!this->CMakeInstance->GetCacheManager()->GetCacheValue
1363 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
1365 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1366 // we are in the first time progress and we have no
1367 // idea how long it will be. So, just move 1/10th of the way
1368 // there each time, and don't go over 95%
1369 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1370 if(this->FirstTimeProgress > 0.95f)
1372 this->FirstTimeProgress = 0.95f;
1374 this->CMakeInstance->UpdateProgress("Configuring",
1375 this->FirstTimeProgress);
1378 std::string makeCommand = this->CMakeInstance->
1379 GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
1380 if(makeCommand.size() == 0)
1382 cmSystemTools::Error(
1383 "Generator cannot find the appropriate make command.");
1387 std::string newTarget;
1388 if (target && strlen(target))
1390 newTarget += target;
1392 #if defined(_WIN32) || defined(__CYGWIN__)
1393 std::string tmp = target;
1394 // if the target does not already end in . something
1396 if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
1398 newTarget += ".exe";
1403 const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
1404 return this->Build(srcdir,bindir,projectName,
1406 output,makeCommand.c_str(),config,false,fast,
1407 this->TryCompileTimeout);
1410 std::string cmGlobalGenerator
1411 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
1412 const char *projectDir, const char* additionalOptions,
1413 const char *targetName, const char* config,
1414 bool ignoreErrors, bool)
1416 // Project name & dir and config are not used yet.
1421 std::string makeCommand =
1422 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
1424 // Since we have full control over the invocation of nmake, let us
1426 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
1428 makeCommand += " /NOLOGO ";
1432 makeCommand += " -i";
1434 if ( additionalOptions )
1437 makeCommand += additionalOptions;
1442 makeCommand += targetName;
1447 int cmGlobalGenerator::Build(
1448 const char *, const char *bindir,
1449 const char *projectName, const char *target,
1450 std::string *output,
1451 const char *makeCommandCSTR,
1453 bool clean, bool fast,
1455 cmSystemTools::OutputOption outputflag,
1456 const char* extraOptions,
1457 std::vector<std::string> const& nativeOptions)
1460 * Run an executable command and put the stdout in output.
1462 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1463 cmSystemTools::ChangeDirectory(bindir);
1466 *output += "Change Dir: ";
1472 bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
1473 cmSystemTools::SetRunCommandHideConsole(true);
1474 std::string outputBuffer;
1475 std::string* outputPtr = 0;
1478 outputPtr = &outputBuffer;
1481 // should we do a clean first?
1484 std::string cleanCommand =
1485 this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
1486 0, "clean", config, false, fast);
1489 *output += "\nRun Clean Command:";
1490 *output += cleanCommand;
1494 if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), outputPtr,
1495 &retVal, 0, outputflag, timeout))
1497 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1498 cmSystemTools::Error("Generator: execution of make clean failed.");
1501 *output += *outputPtr;
1502 *output += "\nGenerator: execution of make clean failed.\n";
1505 // return to the original directory
1506 cmSystemTools::ChangeDirectory(cwd.c_str());
1511 *output += *outputPtr;
1516 std::string makeCommand =
1517 this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
1518 extraOptions, target,
1519 config, false, fast);
1522 *output += "\nRun Build Command:";
1523 *output += makeCommand;
1527 std::vector<cmStdString> command =
1528 cmSystemTools::ParseArguments(makeCommand.c_str());
1529 for(std::vector<std::string>::const_iterator ni = nativeOptions.begin();
1530 ni != nativeOptions.end(); ++ni)
1532 command.push_back(*ni);
1535 if (!cmSystemTools::RunSingleCommand(command, outputPtr,
1536 &retVal, 0, outputflag, timeout))
1538 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1539 cmSystemTools::Error
1540 ("Generator: execution of make failed. Make command was: ",
1541 makeCommand.c_str());
1544 *output += *outputPtr;
1545 *output += "\nGenerator: execution of make failed. Make command was: "
1546 + makeCommand + "\n";
1549 // return to the original directory
1550 cmSystemTools::ChangeDirectory(cwd.c_str());
1555 *output += *outputPtr;
1557 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1559 // The SGI MipsPro 7.3 compiler does not return an error code when
1560 // the source has a #error in it! This is a work-around for such
1562 if((retVal == 0) && (output->find("#error") != std::string::npos))
1567 cmSystemTools::ChangeDirectory(cwd.c_str());
1571 void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
1573 this->LocalGenerators.push_back(lg);
1576 // estimate how many lg there will be
1577 const char *numGenC =
1578 this->CMakeInstance->GetCacheManager()->GetCacheValue
1579 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
1583 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1584 // we are in the first time progress and we have no
1585 // idea how long it will be. So, just move half way
1586 // there each time, and don't go over 95%
1587 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1588 if(this->FirstTimeProgress > 0.95f)
1590 this->FirstTimeProgress = 0.95f;
1592 this->CMakeInstance->UpdateProgress("Configuring",
1593 this->FirstTimeProgress);
1597 int numGen = atoi(numGenC);
1598 float prog = 0.9f*static_cast<float>(this->LocalGenerators.size())/
1599 static_cast<float>(numGen);
1604 this->CMakeInstance->UpdateProgress("Configuring", prog);
1607 void cmGlobalGenerator::AddInstallComponent(const char* component)
1609 if(component && *component)
1611 this->InstallComponents.insert(component);
1615 void cmGlobalGenerator::EnableInstallTarget()
1617 this->InstallTargetEnabled = true;
1620 cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator()
1622 cmLocalGenerator *lg = new cmLocalGenerator;
1623 lg->SetGlobalGenerator(this);
1627 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen,
1630 this->SetConfiguredFilesPath(gen);
1631 this->TryCompileOuterMakefile = mf;
1633 gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
1634 this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make,
1636 cmCacheManager::FILEPATH);
1637 // copy the enabled languages
1638 this->LanguageEnabled = gen->LanguageEnabled;
1639 this->LanguagesReady = gen->LanguagesReady;
1640 this->ExtensionToLanguage = gen->ExtensionToLanguage;
1641 this->IgnoreExtensions = gen->IgnoreExtensions;
1642 this->LanguageToOutputExtension = gen->LanguageToOutputExtension;
1643 this->LanguageToLinkerPreference = gen->LanguageToLinkerPreference;
1644 this->OutputExtensions = gen->OutputExtensions;
1647 //----------------------------------------------------------------------------
1648 void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
1650 if(!gen->ConfiguredFilesPath.empty())
1652 this->ConfiguredFilesPath = gen->ConfiguredFilesPath;
1656 this->ConfiguredFilesPath = gen->CMakeInstance->GetHomeOutputDirectory();
1657 this->ConfiguredFilesPath += cmake::GetCMakeFilesDirectory();
1661 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1662 cmLocalGenerator* gen)
1664 if(!gen || gen == root)
1666 // No directory excludes itself.
1670 if(gen->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1672 // This directory is excluded from its parent.
1676 // This directory is included in its parent. Check whether the
1677 // parent is excluded.
1678 return this->IsExcluded(root, gen->GetParent());
1681 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1684 if(target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1686 // This target is excluded from its directory.
1691 // This target is included in its directory. Check whether the
1692 // directory is excluded.
1693 return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator());
1697 void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
1699 for(std::map<cmStdString, bool>::iterator i =
1700 this->LanguageEnabled.begin(); i != this->LanguageEnabled.end(); ++i)
1702 lang.push_back(i->first);
1706 int cmGlobalGenerator::GetLinkerPreference(const char* lang)
1708 std::map<cmStdString, int>::const_iterator it =
1709 this->LanguageToLinkerPreference.find(lang);
1710 if (it != this->LanguageToLinkerPreference.end())
1717 void cmGlobalGenerator::FillProjectMap()
1719 this->ProjectMap.clear(); // make sure we start with a clean map
1721 for(i = 0; i < this->LocalGenerators.size(); ++i)
1723 // for each local generator add all projects
1724 cmLocalGenerator *lg = this->LocalGenerators[i];
1728 if (name != lg->GetMakefile()->GetProjectName())
1730 name = lg->GetMakefile()->GetProjectName();
1731 this->ProjectMap[name].push_back(this->LocalGenerators[i]);
1733 lg = lg->GetParent();
1740 // Build a map that contains a the set of targets used by each local
1741 // generator directory level.
1742 void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
1744 this->LocalGeneratorToTargetMap.clear();
1745 // Loop over all targets in all local generators.
1746 for(std::vector<cmLocalGenerator*>::const_iterator
1747 lgi = this->LocalGenerators.begin();
1748 lgi != this->LocalGenerators.end(); ++lgi)
1750 cmLocalGenerator* lg = *lgi;
1751 cmMakefile* mf = lg->GetMakefile();
1752 cmTargets& targets = mf->GetTargets();
1753 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1755 cmTarget& target = t->second;
1757 // Consider the directory containing the target and all its
1758 // parents until something excludes the target.
1759 for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target);
1760 clg = clg->GetParent())
1762 // This local generator includes the target.
1763 std::set<cmTarget*>& targetSet =
1764 this->LocalGeneratorToTargetMap[clg];
1765 targetSet.insert(&target);
1767 // Add dependencies of the included target. An excluded
1768 // target may still be included if it is a dependency of a
1769 // non-excluded target.
1770 TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target);
1771 for(TargetDependSet::const_iterator ti = tgtdeps.begin();
1772 ti != tgtdeps.end(); ++ti)
1774 targetSet.insert(*ti);
1782 ///! Find a local generator by its startdirectory
1783 cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
1785 std::vector<cmLocalGenerator*>* gens = &this->LocalGenerators;
1786 for(unsigned int i = 0; i < gens->size(); ++i)
1788 std::string sd = (*gens)[i]->GetMakefile()->GetStartDirectory();
1789 if (sd == start_dir)
1797 //----------------------------------------------------------------------------
1798 void cmGlobalGenerator::AddAlias(const char *name, cmTarget *tgt)
1800 this->AliasTargets[name] = tgt;
1803 //----------------------------------------------------------------------------
1804 bool cmGlobalGenerator::IsAlias(const char *name)
1806 return this->AliasTargets.find(name) != this->AliasTargets.end();
1809 //----------------------------------------------------------------------------
1811 cmGlobalGenerator::FindTarget(const char* project, const char* name,
1812 bool excludeAliases)
1814 // if project specific
1817 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
1818 for(unsigned int i = 0; i < gens->size(); ++i)
1820 cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name,
1828 // if all projects/directories
1831 if (!excludeAliases)
1833 std::map<cmStdString, cmTarget*>::iterator ai
1834 = this->AliasTargets.find(name);
1835 if (ai != this->AliasTargets.end())
1840 std::map<cmStdString,cmTarget *>::iterator i =
1841 this->TotalTargets.find ( name );
1842 if ( i != this->TotalTargets.end() )
1846 i = this->ImportedTargets.find(name);
1847 if ( i != this->ImportedTargets.end() )
1855 //----------------------------------------------------------------------------
1856 bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
1858 if(cmSystemTools::IsPathToFramework(libname.c_str()))
1863 if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
1865 if(tgt->IsFrameworkOnApple())
1874 //----------------------------------------------------------------------------
1875 inline std::string removeQuotes(const std::string& s)
1877 if(s[0] == '\"' && s[s.size()-1] == '\"')
1879 return s.substr(1, s.size()-2);
1884 void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
1886 // Store a pointer to the cmake object instance.
1887 this->CMakeInstance = cm;
1890 void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
1892 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
1893 const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
1894 const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND");
1897 std::string workingDir = mf->GetStartOutputDirectory();
1898 cmCustomCommandLines cpackCommandLines;
1899 std::vector<std::string> depends;
1900 cmCustomCommandLine singleLine;
1901 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1902 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1904 singleLine.push_back("-C");
1905 singleLine.push_back(cmakeCfgIntDir);
1907 singleLine.push_back("--config");
1908 std::string configFile = mf->GetStartOutputDirectory();;
1909 configFile += "/CPackConfig.cmake";
1910 std::string relConfigFile = "./CPackConfig.cmake";
1911 singleLine.push_back(relConfigFile);
1912 cpackCommandLines.push_back(singleLine);
1913 if ( this->GetPreinstallTargetName() )
1915 depends.push_back(this->GetPreinstallTargetName());
1919 const char* noPackageAll =
1920 mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
1921 if(!noPackageAll || cmSystemTools::IsOff(noPackageAll))
1923 depends.push_back(this->GetAllTargetName());
1926 if(cmSystemTools::FileExists(configFile.c_str()))
1928 (*targets)[this->GetPackageTargetName()]
1929 = this->CreateGlobalTarget(this->GetPackageTargetName(),
1930 "Run CPack packaging tool...",
1931 &cpackCommandLines, depends,
1932 workingDir.c_str());
1935 const char* packageSourceTargetName = this->GetPackageSourceTargetName();
1936 if ( packageSourceTargetName )
1938 cpackCommandLines.erase(cpackCommandLines.begin(),
1939 cpackCommandLines.end());
1940 singleLine.erase(singleLine.begin(), singleLine.end());
1941 depends.erase(depends.begin(), depends.end());
1942 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1943 singleLine.push_back("--config");
1944 configFile = mf->GetStartOutputDirectory();;
1945 configFile += "/CPackSourceConfig.cmake";
1946 relConfigFile = "./CPackSourceConfig.cmake";
1947 singleLine.push_back(relConfigFile);
1948 if(cmSystemTools::FileExists(configFile.c_str()))
1950 singleLine.push_back(configFile);
1951 cpackCommandLines.push_back(singleLine);
1952 (*targets)[packageSourceTargetName]
1953 = this->CreateGlobalTarget(packageSourceTargetName,
1954 "Run CPack packaging tool for source...",
1955 &cpackCommandLines, depends,
1962 if(mf->IsOn("CMAKE_TESTING_ENABLED"))
1964 cpackCommandLines.erase(cpackCommandLines.begin(),
1965 cpackCommandLines.end());
1966 singleLine.erase(singleLine.begin(), singleLine.end());
1967 depends.erase(depends.begin(), depends.end());
1968 singleLine.push_back(this->GetCMakeInstance()->GetCTestCommand());
1969 singleLine.push_back("--force-new-ctest-process");
1970 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1972 singleLine.push_back("-C");
1973 singleLine.push_back(cmakeCfgIntDir);
1975 else // TODO: This is a hack. Should be something to do with the generator
1977 singleLine.push_back("$(ARGS)");
1979 cpackCommandLines.push_back(singleLine);
1980 (*targets)[this->GetTestTargetName()]
1981 = this->CreateGlobalTarget(this->GetTestTargetName(),
1982 "Running tests...", &cpackCommandLines, depends, 0);
1986 const char* editCacheTargetName = this->GetEditCacheTargetName();
1987 if ( editCacheTargetName )
1989 cpackCommandLines.erase(cpackCommandLines.begin(),
1990 cpackCommandLines.end());
1991 singleLine.erase(singleLine.begin(), singleLine.end());
1992 depends.erase(depends.begin(), depends.end());
1994 // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
1995 // Otherwise default to the interactive command-line interface.
1996 if(mf->GetDefinition("CMAKE_EDIT_COMMAND"))
1998 singleLine.push_back(mf->GetDefinition("CMAKE_EDIT_COMMAND"));
1999 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
2000 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
2001 cpackCommandLines.push_back(singleLine);
2002 (*targets)[editCacheTargetName] =
2003 this->CreateGlobalTarget(
2004 editCacheTargetName, "Running CMake cache editor...",
2005 &cpackCommandLines, depends, 0);
2009 singleLine.push_back(cmakeCommand);
2010 singleLine.push_back("-i");
2011 singleLine.push_back(".");
2012 cpackCommandLines.push_back(singleLine);
2013 (*targets)[editCacheTargetName] =
2014 this->CreateGlobalTarget(
2015 editCacheTargetName,
2016 "Running interactive CMake command-line interface...",
2017 &cpackCommandLines, depends, 0);
2022 const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
2023 if ( rebuildCacheTargetName )
2025 cpackCommandLines.erase(cpackCommandLines.begin(),
2026 cpackCommandLines.end());
2027 singleLine.erase(singleLine.begin(), singleLine.end());
2028 depends.erase(depends.begin(), depends.end());
2029 singleLine.push_back(cmakeCommand);
2030 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
2031 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
2032 cpackCommandLines.push_back(singleLine);
2033 (*targets)[rebuildCacheTargetName] =
2034 this->CreateGlobalTarget(
2035 rebuildCacheTargetName, "Running CMake to regenerate build system...",
2036 &cpackCommandLines, depends, 0);
2040 if(this->InstallTargetEnabled)
2042 if(!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.')
2044 std::set<cmStdString>* componentsSet = &this->InstallComponents;
2045 cpackCommandLines.erase(cpackCommandLines.begin(),
2046 cpackCommandLines.end());
2047 depends.erase(depends.begin(), depends.end());
2048 cmOStringStream ostr;
2049 if ( componentsSet->size() > 0 )
2051 ostr << "Available install components are:";
2052 std::set<cmStdString>::iterator it;
2054 it = componentsSet->begin();
2055 it != componentsSet->end();
2058 ostr << " \"" << it->c_str() << "\"";
2063 ostr << "Only default component available";
2065 singleLine.push_back(ostr.str().c_str());
2066 (*targets)["list_install_components"]
2067 = this->CreateGlobalTarget("list_install_components",
2069 &cpackCommandLines, depends, 0);
2071 std::string cmd = cmakeCommand;
2072 cpackCommandLines.erase(cpackCommandLines.begin(),
2073 cpackCommandLines.end());
2074 singleLine.erase(singleLine.begin(), singleLine.end());
2075 depends.erase(depends.begin(), depends.end());
2076 if ( this->GetPreinstallTargetName() )
2078 depends.push_back(this->GetPreinstallTargetName());
2083 mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
2084 if(!noall || cmSystemTools::IsOff(noall))
2086 depends.push_back(this->GetAllTargetName());
2089 if(mf->GetDefinition("CMake_BINARY_DIR"))
2091 // We are building CMake itself. We cannot use the original
2092 // executable to install over itself. The generator will
2093 // automatically convert this name to the build-time location.
2096 singleLine.push_back(cmd.c_str());
2097 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
2099 std::string cfgArg = "-DBUILD_TYPE=";
2100 cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR");
2101 singleLine.push_back(cfgArg);
2103 singleLine.push_back("-P");
2104 singleLine.push_back("cmake_install.cmake");
2105 cpackCommandLines.push_back(singleLine);
2106 (*targets)[this->GetInstallTargetName()] =
2107 this->CreateGlobalTarget(
2108 this->GetInstallTargetName(), "Install the project...",
2109 &cpackCommandLines, depends, 0);
2112 if(const char* install_local = this->GetInstallLocalTargetName())
2114 cmCustomCommandLine localCmdLine = singleLine;
2116 localCmdLine.insert(localCmdLine.begin()+1,
2117 "-DCMAKE_INSTALL_LOCAL_ONLY=1");
2118 cpackCommandLines.erase(cpackCommandLines.begin(),
2119 cpackCommandLines.end());
2120 cpackCommandLines.push_back(localCmdLine);
2122 (*targets)[install_local] =
2123 this->CreateGlobalTarget(
2124 install_local, "Installing only the local directory...",
2125 &cpackCommandLines, depends, 0);
2129 const char* install_strip = this->GetInstallStripTargetName();
2130 if((install_strip !=0) && (mf->IsSet("CMAKE_STRIP")))
2132 cmCustomCommandLine stripCmdLine = singleLine;
2134 stripCmdLine.insert(stripCmdLine.begin()+1,"-DCMAKE_INSTALL_DO_STRIP=1");
2135 cpackCommandLines.erase(cpackCommandLines.begin(),
2136 cpackCommandLines.end());
2137 cpackCommandLines.push_back(stripCmdLine);
2139 (*targets)[install_strip] =
2140 this->CreateGlobalTarget(
2141 install_strip, "Installing the project stripped...",
2142 &cpackCommandLines, depends, 0);
2147 //----------------------------------------------------------------------------
2148 const char* cmGlobalGenerator::GetPredefinedTargetsFolder()
2151 this->GetCMakeInstance()->GetProperty("PREDEFINED_TARGETS_FOLDER");
2158 return "CMakePredefinedTargets";
2161 //----------------------------------------------------------------------------
2162 bool cmGlobalGenerator::UseFolderProperty()
2164 const char* prop = this->GetCMakeInstance()->GetProperty("USE_FOLDERS");
2166 // If this property is defined, let the setter turn this on or off...
2170 return cmSystemTools::IsOn(prop);
2173 // By default, this feature is OFF, since it is not supported in the
2174 // Visual Studio Express editions until VS11:
2179 //----------------------------------------------------------------------------
2180 void cmGlobalGenerator::EnableMinGWLanguage(cmMakefile *mf)
2182 this->FindMakeProgram(mf);
2183 std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
2184 std::vector<std::string> locations;
2185 locations.push_back(cmSystemTools::GetProgramPath(makeProgram.c_str()));
2186 locations.push_back("/mingw/bin");
2187 locations.push_back("c:/mingw/bin");
2188 std::string tgcc = cmSystemTools::FindProgram("gcc", locations);
2189 std::string gcc = "gcc.exe";
2194 std::string tgxx = cmSystemTools::FindProgram("g++", locations);
2195 std::string gxx = "g++.exe";
2200 std::string trc = cmSystemTools::FindProgram("windres", locations);
2201 std::string rc = "windres.exe";
2206 mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str());
2207 mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str());
2208 mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str());
2211 //----------------------------------------------------------------------------
2212 cmTarget cmGlobalGenerator::CreateGlobalTarget(
2213 const char* name, const char* message,
2214 const cmCustomCommandLines* commandLines,
2215 std::vector<std::string> depends,
2216 const char* workingDirectory)
2220 target.GetProperties().SetCMakeInstance(this->CMakeInstance);
2221 target.SetType(cmTarget::GLOBAL_TARGET, name);
2222 target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
2224 std::vector<std::string> no_outputs;
2225 std::vector<std::string> no_depends;
2226 // Store the custom command in the target.
2227 cmCustomCommand cc(0, no_outputs, no_depends, *commandLines, 0,
2229 target.GetPostBuildCommands().push_back(cc);
2230 target.SetProperty("EchoString", message);
2231 std::vector<std::string>::iterator dit;
2232 for ( dit = depends.begin(); dit != depends.end(); ++ dit )
2234 target.AddUtility(dit->c_str());
2237 // Organize in the "predefined targets" folder:
2239 if (this->UseFolderProperty())
2241 target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
2247 //----------------------------------------------------------------------------
2249 cmGlobalGenerator::GenerateRuleFile(std::string const& output) const
2251 std::string ruleFile = output;
2252 ruleFile += ".rule";
2253 const char* dir = this->GetCMakeCFGIntDir();
2254 if(dir && dir[0] == '$')
2256 cmSystemTools::ReplaceString(ruleFile, dir,
2257 cmake::GetCMakeFilesDirectory());
2262 //----------------------------------------------------------------------------
2263 std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
2264 std::string const& l)
2266 if(this->LanguageToOriginalSharedLibFlags.count(l) > 0)
2268 return this->LanguageToOriginalSharedLibFlags[l];
2273 //----------------------------------------------------------------------------
2274 void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
2275 const char*, std::string&)
2277 // Subclasses that support multiple configurations should implement
2278 // this method to append the subdirectory for the given build
2282 //----------------------------------------------------------------------------
2283 cmGlobalGenerator::TargetDependSet const&
2284 cmGlobalGenerator::GetTargetDirectDepends(cmTarget & target)
2286 return this->TargetDependencies[&target];
2289 void cmGlobalGenerator::AddTarget(cmTarget* t)
2293 this->ImportedTargets[t->GetName()] = t;
2297 this->TotalTargets[t->GetName()] = t;
2301 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
2302 cmExternalMakefileProjectGenerator *extraGenerator)
2304 this->ExtraGenerator = extraGenerator;
2305 if (this->ExtraGenerator!=0)
2307 this->ExtraGenerator->SetGlobalGenerator(this);
2311 const char* cmGlobalGenerator::GetExtraGeneratorName() const
2313 return this->ExtraGenerator==0 ? 0 : this->ExtraGenerator->GetName();
2316 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
2318 this->FilesReplacedDuringGenerate.push_back(filename);
2323 ::GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames)
2327 this->FilesReplacedDuringGenerate.begin(),
2328 this->FilesReplacedDuringGenerate.end(),
2329 std::back_inserter(filenames));
2332 //----------------------------------------------------------------------------
2333 void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets,
2334 TargetDependSet& originalTargets,
2335 cmLocalGenerator* root,
2336 GeneratorVector const& generators)
2338 // loop over all local generators
2339 for(std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
2340 i != generators.end(); ++i)
2342 // check to make sure generator is not excluded
2343 if(this->IsExcluded(root, *i))
2347 cmMakefile* mf = (*i)->GetMakefile();
2348 // Get the targets in the makefile
2349 cmTargets &tgts = mf->GetTargets();
2350 // loop over all the targets
2351 for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
2353 cmTarget* target = &l->second;
2354 if(this->IsRootOnlyTarget(target) &&
2355 target->GetMakefile() != root->GetMakefile())
2359 // put the target in the set of original targets
2360 originalTargets.insert(target);
2361 // Get the set of targets that depend on target
2362 this->AddTargetDepends(target, projectTargets);
2367 //----------------------------------------------------------------------------
2368 bool cmGlobalGenerator::IsRootOnlyTarget(cmTarget* target)
2370 return (target->GetType() == cmTarget::GLOBAL_TARGET ||
2371 strcmp(target->GetName(), this->GetAllTargetName()) == 0);
2374 //----------------------------------------------------------------------------
2375 void cmGlobalGenerator::AddTargetDepends(cmTarget* target,
2376 TargetDependSet& projectTargets)
2378 // add the target itself
2379 if(projectTargets.insert(target).second)
2381 // This is the first time we have encountered the target.
2382 // Recursively follow its dependencies.
2383 TargetDependSet const& ts = this->GetTargetDirectDepends(*target);
2384 for(TargetDependSet::const_iterator i = ts.begin(); i != ts.end(); ++i)
2386 cmTarget* dtarget = *i;
2387 this->AddTargetDepends(dtarget, projectTargets);
2393 //----------------------------------------------------------------------------
2394 void cmGlobalGenerator::AddToManifest(const char* config,
2395 std::string const& f)
2397 // Add to the main manifest for this configuration.
2398 this->TargetManifest[config].insert(f);
2400 // Add to the content listing for the file's directory.
2401 std::string dir = cmSystemTools::GetFilenamePath(f);
2402 std::string file = cmSystemTools::GetFilenameName(f);
2403 this->DirectoryContentMap[dir].insert(file);
2406 //----------------------------------------------------------------------------
2407 std::set<cmStdString> const&
2408 cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
2410 DirectoryContent& dc = this->DirectoryContentMap[dir];
2411 if(needDisk && !dc.LoadedFromDisk)
2413 // Load the directory content from disk.
2415 if(d.Load(dir.c_str()))
2417 unsigned long n = d.GetNumberOfFiles();
2418 for(unsigned long i = 0; i < n; ++i)
2420 const char* f = d.GetFile(i);
2421 if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
2427 dc.LoadedFromDisk = true;
2432 //----------------------------------------------------------------------------
2434 cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
2435 std::string const& content)
2437 #if defined(CMAKE_BUILD_WITH_CMAKE)
2438 // Ignore if there are no outputs.
2444 // Compute a hash of the rule.
2447 unsigned char const* data =
2448 reinterpret_cast<unsigned char const*>(content.c_str());
2449 int length = static_cast<int>(content.length());
2450 cmsysMD5* sum = cmsysMD5_New();
2451 cmsysMD5_Initialize(sum);
2452 cmsysMD5_Append(sum, data, length);
2453 cmsysMD5_FinalizeHex(sum, hash.Data);
2454 cmsysMD5_Delete(sum);
2457 // Shorten the output name (in expected use case).
2458 cmLocalGenerator* lg = this->GetLocalGenerators()[0];
2459 std::string fname = lg->Convert(outputs[0].c_str(),
2460 cmLocalGenerator::HOME_OUTPUT);
2462 // Associate the hash with this output.
2463 this->RuleHashes[fname] = hash;
2470 //----------------------------------------------------------------------------
2471 void cmGlobalGenerator::CheckRuleHashes()
2473 #if defined(CMAKE_BUILD_WITH_CMAKE)
2474 std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
2475 std::string pfile = home;
2476 pfile += this->GetCMakeInstance()->GetCMakeFilesDirectory();
2477 pfile += "/CMakeRuleHashes.txt";
2478 this->CheckRuleHashes(pfile, home);
2479 this->WriteRuleHashes(pfile);
2483 //----------------------------------------------------------------------------
2484 void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
2485 std::string const& home)
2487 #if defined(_WIN32) || defined(__CYGWIN__)
2488 std::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
2490 std::ifstream fin(pfile.c_str(), std::ios::in);
2498 while(cmSystemTools::GetLineFromStream(fin, line))
2500 // Line format is a 32-byte hex string followed by a space
2501 // followed by a file name (with no escaping).
2503 // Skip blank and comment lines.
2504 if(line.size() < 34 || line[0] == '#')
2509 // Get the filename.
2510 fname = line.substr(33, line.npos);
2512 // Look for a hash for this file's rule.
2513 std::map<cmStdString, RuleHash>::const_iterator rhi =
2514 this->RuleHashes.find(fname);
2515 if(rhi != this->RuleHashes.end())
2517 // Compare the rule hash in the file to that we were given.
2518 if(strncmp(line.c_str(), rhi->second.Data, 32) != 0)
2520 // The rule has changed. Delete the output so it will be
2522 fname = cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
2523 cmSystemTools::RemoveFile(fname.c_str());
2528 // We have no hash for a rule previously listed. This may be a
2529 // case where a user has turned off a build option and might
2530 // want to turn it back on later, so do not delete the file.
2531 // Instead, we keep the rule hash as long as the file exists so
2532 // that if the feature is turned back on and the rule has
2533 // changed the file is still rebuilt.
2535 cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
2536 if(cmSystemTools::FileExists(fpath.c_str()))
2539 strncpy(hash.Data, line.c_str(), 32);
2540 this->RuleHashes[fname] = hash;
2546 //----------------------------------------------------------------------------
2547 void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
2549 // Now generate a new persistence file with the current hashes.
2550 if(this->RuleHashes.empty())
2552 cmSystemTools::RemoveFile(pfile.c_str());
2556 cmGeneratedFileStream fout(pfile.c_str());
2557 fout << "# Hashes of file build rules.\n";
2558 for(std::map<cmStdString, RuleHash>::const_iterator
2559 rhi = this->RuleHashes.begin(); rhi != this->RuleHashes.end(); ++rhi)
2561 fout.write(rhi->second.Data, 32);
2562 fout << " " << rhi->first << "\n";
2567 //----------------------------------------------------------------------------
2568 void cmGlobalGenerator::WriteSummary()
2570 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
2572 // Record all target directories in a central location.
2573 std::string fname = mf->GetHomeOutputDirectory();
2574 fname += cmake::GetCMakeFilesDirectory();
2575 fname += "/TargetDirectories.txt";
2576 cmGeneratedFileStream fout(fname.c_str());
2578 // Generate summary information files for each target.
2580 for(std::map<cmStdString,cmTarget *>::const_iterator ti =
2581 this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti)
2583 this->WriteSummary(ti->second);
2584 fout << ti->second->GetSupportDirectory() << "\n";
2588 //----------------------------------------------------------------------------
2589 void cmGlobalGenerator::WriteSummary(cmTarget* target)
2591 // Place the labels file in a per-target support directory.
2592 std::string dir = target->GetSupportDirectory();
2593 std::string file = dir;
2594 file += "/Labels.txt";
2596 // Check whether labels are enabled for this target.
2597 if(const char* value = target->GetProperty("LABELS"))
2599 cmSystemTools::MakeDirectory(dir.c_str());
2600 cmGeneratedFileStream fout(file.c_str());
2602 // List the target-wide labels. All sources in the target get
2604 std::vector<std::string> labels;
2605 cmSystemTools::ExpandListArgument(value, labels);
2608 fout << "# Target labels\n";
2609 for(std::vector<std::string>::const_iterator li = labels.begin();
2610 li != labels.end(); ++li)
2612 fout << " " << *li << "\n";
2616 // List the source files with any per-source labels.
2617 fout << "# Source files and their labels\n";
2618 std::vector<cmSourceFile*> const& sources = target->GetSourceFiles();
2619 for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
2620 si != sources.end(); ++si)
2622 cmSourceFile* sf = *si;
2623 fout << sf->GetFullPath() << "\n";
2624 if(const char* svalue = sf->GetProperty("LABELS"))
2627 cmSystemTools::ExpandListArgument(svalue, labels);
2628 for(std::vector<std::string>::const_iterator li = labels.begin();
2629 li != labels.end(); ++li)
2631 fout << " " << *li << "\n";
2638 cmSystemTools::RemoveFile(file.c_str());
2642 //----------------------------------------------------------------------------
2644 std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
2646 for (std::string::size_type i = 0; i < s.size(); ++i) {
2647 if (s[i] == '"' || s[i] == '\\') {
2655 //----------------------------------------------------------------------------
2656 void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile,
2657 cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr,
2658 cmMakefile *makefile,
2659 cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
2660 bool inputIsContent)
2662 this->EvaluationFiles.push_back(
2663 new cmGeneratorExpressionEvaluationFile(inputFile, outputExpr,
2664 makefile, condition,
2668 //----------------------------------------------------------------------------
2669 void cmGlobalGenerator::ProcessEvaluationFiles()
2671 std::set<std::string> generatedFiles;
2672 for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
2673 li = this->EvaluationFiles.begin();
2674 li != this->EvaluationFiles.end();
2678 if (cmSystemTools::GetFatalErrorOccured())
2682 std::vector<std::string> files = (*li)->GetFiles();
2683 for(std::vector<std::string>::const_iterator fi = files.begin();
2684 fi != files.end(); ++fi)
2686 if (!generatedFiles.insert(*fi).second)
2688 cmSystemTools::Error("File to be generated by multiple different "
2689 "commands: ", fi->c_str());