ENH: Return utility target after creation
[cmake.git] / Source / cmGlobalGenerator.cxx
blobf60e0b519b0d94a77b6ceb11fa33ea4965ebdd6a
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008-10-01 16:45:49 $
7 Version: $Revision: 1.244 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #if defined(_WIN32) && !defined(__CYGWIN__)
18 #include "windows.h" // this must be first to define GetCurrentDirectory
19 #endif
21 #include "cmGlobalGenerator.h"
22 #include "cmLocalGenerator.h"
23 #include "cmExternalMakefileProjectGenerator.h"
24 #include "cmake.h"
25 #include "cmMakefile.h"
26 #include "cmSourceFile.h"
27 #include "cmVersion.h"
28 #include "cmExportInstallFileGenerator.h"
29 #include "cmComputeTargetDepends.h"
30 #include "cmGeneratedFileStream.h"
32 #include <cmsys/Directory.hxx>
34 #if defined(CMAKE_BUILD_WITH_CMAKE)
35 # include <cmsys/MD5.h>
36 #endif
38 #include <stdlib.h> // required for atof
40 #include <assert.h>
42 cmGlobalGenerator::cmGlobalGenerator()
44 // By default the .SYMBOLIC dependency is not needed on symbolic rules.
45 this->NeedSymbolicMark = false;
47 // by default use the native paths
48 this->ForceUnixPaths = false;
50 // By default do not try to support color.
51 this->ToolSupportsColor = false;
53 // By default do not use link scripts.
54 this->UseLinkScript = false;
56 // Whether an install target is needed.
57 this->InstallTargetEnabled = false;
59 // how long to let try compiles run
60 this->TryCompileTimeout = 0;
62 this->ExtraGenerator = 0;
63 this->CurrentLocalGenerator = 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 this->LocalGenerators.clear();
75 if (this->ExtraGenerator)
77 delete this->ExtraGenerator;
80 this->ClearExportSets();
83 // Find the make program for the generator, required for try compiles
84 void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
86 if(this->FindMakeProgramFile.size() == 0)
88 cmSystemTools::Error(
89 "Generator implementation error, "
90 "all generators must specify this->FindMakeProgramFile");
92 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
93 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
95 std::string setMakeProgram =
96 mf->GetModulesFile(this->FindMakeProgramFile.c_str());
97 if(setMakeProgram.size())
99 mf->ReadListFile(0, setMakeProgram.c_str());
102 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
103 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
105 cmOStringStream err;
106 err << "CMake was unable to find a build program corresponding to \""
107 << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You "
108 << "probably need to select a different build tool.";
109 cmSystemTools::Error(err.str().c_str());
110 cmSystemTools::SetFatalErrorOccured();
111 return;
113 std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
114 // if there are spaces in the make program use short path
115 // but do not short path the actual program name, as
116 // this can cause trouble with VSExpress
117 if(makeProgram.find(' ') != makeProgram.npos)
119 std::string dir;
120 std::string file;
121 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
122 dir, file);
123 std::string saveFile = file;
124 cmSystemTools::GetShortPath(makeProgram.c_str(), makeProgram);
125 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
126 dir, file);
127 makeProgram = dir;
128 makeProgram += "/";
129 makeProgram += saveFile;
130 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
131 "make program",
132 cmCacheManager::FILEPATH);
135 if(makeProgram.find("xcodebuild") != makeProgram.npos)
137 // due to the text file busy /bin/sh problem with xcodebuild
138 // use the cmakexbuild wrapper instead. This program
139 // will run xcodebuild and if it sees the error text file busy
140 // it will stop forwarding output, and let the build finish.
141 // Then it will retry the build. It will continue this
142 // untill no text file busy errors occur.
143 std::string cmakexbuild =
144 this->CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_COMMAND");
145 cmakexbuild = cmakexbuild.substr(0, cmakexbuild.length()-5);
146 cmakexbuild += "cmakexbuild";
148 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM",
149 cmakexbuild.c_str(),
150 "make program",
151 cmCacheManager::FILEPATH);
155 // enable the given language
157 // The following files are loaded in this order:
159 // First figure out what OS we are running on:
161 // CMakeSystem.cmake - configured file created by CMakeDetermineSystem.cmake
162 // CMakeDetermineSystem.cmake - figure out os info and create
163 // CMakeSystem.cmake IF CMAKE_SYSTEM
164 // not set
165 // CMakeSystem.cmake - configured file created by
166 // CMakeDetermineSystem.cmake IF CMAKE_SYSTEM_LOADED
168 // Next try and enable all languages found in the languages vector
170 // FOREACH LANG in languages
171 // CMake(LANG)Compiler.cmake - configured file create by
172 // CMakeDetermine(LANG)Compiler.cmake
173 // CMakeDetermine(LANG)Compiler.cmake - Finds compiler for LANG and
174 // creates CMake(LANG)Compiler.cmake
175 // CMake(LANG)Compiler.cmake - configured file created by
176 // CMakeDetermine(LANG)Compiler.cmake
178 // CMakeSystemSpecificInformation.cmake
179 // - includes Platform/${CMAKE_SYSTEM_NAME}.cmake
180 // may use compiler stuff
182 // FOREACH LANG in languages
183 // CMake(LANG)Information.cmake
184 // - loads Platform/${CMAKE_SYSTEM_NAME}-${COMPILER}.cmake
185 // CMakeTest(LANG)Compiler.cmake
186 // - Make sure the compiler works with a try compile if
187 // CMakeDetermine(LANG) was loaded
189 // Now load a few files that can override values set in any of the above
190 // (PROJECTNAME)Compatibility.cmake
191 // - load any backwards compatibility stuff for current project
192 // ${CMAKE_USER_MAKE_RULES_OVERRIDE}
193 // - allow users a chance to override system variables
197 void
198 cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
199 cmMakefile *mf, bool)
201 if(languages.size() == 0)
203 cmSystemTools::Error("EnableLanguage must have a lang specified!");
204 cmSystemTools::SetFatalErrorOccured();
205 return;
207 mf->AddDefinition("RUN_CONFIGURE", true);
208 std::string rootBin = mf->GetHomeOutputDirectory();
209 rootBin += cmake::GetCMakeFilesDirectory();
211 // If the configuration files path has been set,
212 // then we are in a try compile and need to copy the enable language
213 // files from the parent cmake bin dir, into the try compile bin dir
214 if(this->ConfiguredFilesPath.size())
216 for(std::vector<std::string>::const_iterator l = languages.begin();
217 l != languages.end(); ++l)
219 if(*l == "NONE")
221 this->SetLanguageEnabled("NONE", mf);
222 break;
225 rootBin = this->ConfiguredFilesPath;
228 // set the dir for parent files so they can be used by modules
229 mf->AddDefinition("CMAKE_PLATFORM_ROOT_BIN",rootBin.c_str());
231 // find and make sure CMAKE_MAKE_PROGRAM is defined
232 this->FindMakeProgram(mf);
234 // try and load the CMakeSystem.cmake if it is there
235 std::string fpath = rootBin;
236 if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
238 fpath += "/CMakeSystem.cmake";
239 if(cmSystemTools::FileExists(fpath.c_str()))
241 mf->ReadListFile(0,fpath.c_str());
244 // Load the CMakeDetermineSystem.cmake file and find out
245 // what platform we are running on
246 if (!mf->GetDefinition("CMAKE_SYSTEM"))
248 #if defined(_WIN32) && !defined(__CYGWIN__)
249 /* Windows version number data. */
250 OSVERSIONINFO osvi;
251 ZeroMemory(&osvi, sizeof(osvi));
252 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
253 GetVersionEx (&osvi);
254 cmOStringStream windowsVersionString;
255 windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
256 windowsVersionString.str();
257 mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
258 windowsVersionString.str().c_str());
259 #endif
260 // Read the DetermineSystem file
261 std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
262 mf->ReadListFile(0, systemFile.c_str());
263 // load the CMakeSystem.cmake from the binary directory
264 // this file is configured by the CMakeDetermineSystem.cmake file
265 fpath = rootBin;
266 fpath += "/CMakeSystem.cmake";
267 mf->ReadListFile(0,fpath.c_str());
269 std::map<cmStdString, bool> needTestLanguage;
270 std::map<cmStdString, bool> needSetLanguageEnabledMaps;
271 // foreach language
272 // load the CMakeDetermine(LANG)Compiler.cmake file to find
273 // the compiler
275 for(std::vector<std::string>::const_iterator l = languages.begin();
276 l != languages.end(); ++l)
278 const char* lang = l->c_str();
279 needSetLanguageEnabledMaps[lang] = false;
280 if(*l == "NONE")
282 this->SetLanguageEnabled("NONE", mf);
283 continue;
285 std::string loadedLang = "CMAKE_";
286 loadedLang += lang;
287 loadedLang += "_COMPILER_LOADED";
288 // If the existing build tree was already configured with this
289 // version of CMake then try to load the configured file first
290 // to avoid duplicate compiler tests.
291 unsigned int cacheMajor = mf->GetCacheMajorVersion();
292 unsigned int cacheMinor = mf->GetCacheMinorVersion();
293 unsigned int selfMajor = cmVersion::GetMajorVersion();
294 unsigned int selfMinor = cmVersion::GetMinorVersion();
295 if((this->CMakeInstance->GetIsInTryCompile() ||
296 (selfMajor == cacheMajor && selfMinor == cacheMinor))
297 && !mf->GetDefinition(loadedLang.c_str()))
299 fpath = rootBin;
300 fpath += "/CMake";
301 fpath += lang;
302 fpath += "Compiler.cmake";
303 if(cmSystemTools::FileExists(fpath.c_str()))
305 if(!mf->ReadListFile(0,fpath.c_str()))
307 cmSystemTools::Error("Could not find cmake module file:",
308 fpath.c_str());
310 // if this file was found then the language was already determined
311 // to be working
312 needTestLanguage[lang] = false;
313 this->SetLanguageEnabledFlag(lang, mf);
314 needSetLanguageEnabledMaps[lang] = true;
315 // this can only be called after loading CMake(LANG)Compiler.cmake
319 if(!this->GetLanguageEnabled(lang) )
321 if (this->CMakeInstance->GetIsInTryCompile())
323 cmSystemTools::Error("This should not have happen. "
324 "If you see this message, you are probably "
325 "using a broken CMakeLists.txt file or a "
326 "problematic release of CMake");
328 // if the CMake(LANG)Compiler.cmake file was not found then
329 // load CMakeDetermine(LANG)Compiler.cmake
330 std::string determineCompiler = "CMakeDetermine";
331 determineCompiler += lang;
332 determineCompiler += "Compiler.cmake";
333 std::string determineFile =
334 mf->GetModulesFile(determineCompiler.c_str());
335 if(!mf->ReadListFile(0,determineFile.c_str()))
337 cmSystemTools::Error("Could not find cmake module file:",
338 determineFile.c_str());
340 needTestLanguage[lang] = true;
341 // Some generators like visual studio should not use the env variables
342 // So the global generator can specify that in this variable
343 if(!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV"))
345 // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
346 // into the environment, in case user scripts want to run
347 // configure, or sub cmakes
348 std::string compilerName = "CMAKE_";
349 compilerName += lang;
350 compilerName += "_COMPILER";
351 std::string compilerEnv = "CMAKE_";
352 compilerEnv += lang;
353 compilerEnv += "_COMPILER_ENV_VAR";
354 std::string envVar = mf->GetRequiredDefinition(compilerEnv.c_str());
355 std::string envVarValue =
356 mf->GetRequiredDefinition(compilerName.c_str());
357 std::string env = envVar;
358 env += "=";
359 env += envVarValue;
360 cmSystemTools::PutEnv(env.c_str());
363 // if determineLanguage was called then load the file it
364 // configures CMake(LANG)Compiler.cmake
365 fpath = rootBin;
366 fpath += "/CMake";
367 fpath += lang;
368 fpath += "Compiler.cmake";
369 if(!mf->ReadListFile(0,fpath.c_str()))
371 cmSystemTools::Error("Could not find cmake module file:",
372 fpath.c_str());
374 this->SetLanguageEnabledFlag(lang, mf);
375 needSetLanguageEnabledMaps[lang] = true;
376 // this can only be called after loading CMake(LANG)Compiler.cmake
377 // the language must be enabled for try compile to work, but we do
378 // not know if it is a working compiler yet so set the test language
379 // flag
380 needTestLanguage[lang] = true;
381 } // end if(!this->GetLanguageEnabled(lang) )
382 } // end loop over languages
384 // **** Load the system specific information if not yet loaded
385 if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
387 fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
388 if(!mf->ReadListFile(0,fpath.c_str()))
390 cmSystemTools::Error("Could not find cmake module file:",
391 fpath.c_str());
394 // loop over languages again loading CMake(LANG)Information.cmake
396 for(std::vector<std::string>::const_iterator l = languages.begin();
397 l != languages.end(); ++l)
399 const char* lang = l->c_str();
400 if(*l == "NONE")
402 this->SetLanguageEnabled("NONE", mf);
403 continue;
405 std::string langLoadedVar = "CMAKE_";
406 langLoadedVar += lang;
407 langLoadedVar += "_INFORMATION_LOADED";
408 if (!mf->GetDefinition(langLoadedVar.c_str()))
410 fpath = "CMake";
411 fpath += lang;
412 fpath += "Information.cmake";
413 std::string informationFile = mf->GetModulesFile(fpath.c_str());
414 if (informationFile.empty())
416 cmSystemTools::Error("Could not find cmake module file:",
417 fpath.c_str());
419 else if(!mf->ReadListFile(0, informationFile.c_str()))
421 cmSystemTools::Error("Could not process cmake module file:",
422 informationFile.c_str());
425 if (needSetLanguageEnabledMaps[lang])
427 this->SetLanguageEnabledMaps(lang, mf);
430 std::string compilerName = "CMAKE_";
431 compilerName += lang;
432 compilerName += "_COMPILER";
433 std::string compilerLangFile = rootBin;
434 compilerLangFile += "/CMake";
435 compilerLangFile += lang;
436 compilerLangFile += "Compiler.cmake";
437 // Test the compiler for the language just setup
438 // (but only if a compiler has been actually found)
439 // At this point we should have enough info for a try compile
440 // which is used in the backward stuff
441 // If the language is untested then test it now with a try compile.
442 if (!mf->IsSet(compilerName.c_str()))
444 // if the compiler did not work, then remove the
445 // CMake(LANG)Compiler.cmake file so that it will get tested the
446 // next time cmake is run
447 cmSystemTools::RemoveFile(compilerLangFile.c_str());
449 else if(needTestLanguage[lang])
451 if (!this->CMakeInstance->GetIsInTryCompile())
453 std::string testLang = "CMakeTest";
454 testLang += lang;
455 testLang += "Compiler.cmake";
456 std::string ifpath = mf->GetModulesFile(testLang.c_str());
457 if(!mf->ReadListFile(0,ifpath.c_str()))
459 cmSystemTools::Error("Could not find cmake module file:",
460 ifpath.c_str());
462 std::string compilerWorks = "CMAKE_";
463 compilerWorks += lang;
464 compilerWorks += "_COMPILER_WORKS";
465 // if the compiler did not work, then remove the
466 // CMake(LANG)Compiler.cmake file so that it will get tested the
467 // next time cmake is run
468 if(!mf->IsOn(compilerWorks.c_str()))
470 cmSystemTools::RemoveFile(compilerLangFile.c_str());
472 else
474 // load backwards compatibility stuff for C and CXX
475 // for old versions of CMake ListFiles C and CXX had some
476 // backwards compatibility files they have to load
477 // These files have a bunch of try compiles in them so
478 // should only be done
479 if (mf->NeedBackwardsCompatibility(1,4))
481 if(strcmp(lang, "C") == 0)
483 ifpath =
484 mf->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
485 mf->ReadListFile(0,ifpath.c_str());
487 if(strcmp(lang, "CXX") == 0)
489 ifpath =
490 mf->GetModulesFile("CMakeBackwardCompatibilityCXX.cmake");
491 mf->ReadListFile(0,ifpath.c_str());
495 } // end if in try compile
496 } // end need test language
497 } // end for each language
499 // Now load files that can override any settings on the platform or for
500 // the project First load the project compatibility file if it is in
501 // cmake
502 std::string projectCompatibility = mf->GetDefinition("CMAKE_ROOT");
503 projectCompatibility += "/Modules/";
504 projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
505 projectCompatibility += "Compatibility.cmake";
506 if(cmSystemTools::FileExists(projectCompatibility.c_str()))
508 mf->ReadListFile(0,projectCompatibility.c_str());
512 //----------------------------------------------------------------------------
513 const char*
514 cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source)
516 if(const char* lang = source.GetLanguage())
518 if(this->LanguageToOutputExtension.count(lang) > 0)
520 return this->LanguageToOutputExtension[lang].c_str();
523 else
525 // if no language is found then check to see if it is already an
526 // ouput extension for some language. In that case it should be ignored
527 // and in this map, so it will not be compiled but will just be used.
528 std::string const& ext = source.GetExtension();
529 if(!ext.empty())
531 if(this->OutputExtensions.count(ext))
533 return ext.c_str();
537 return "";
541 const char* cmGlobalGenerator::GetLanguageFromExtension(const char* ext)
543 // if there is an extension and it starts with . then move past the
544 // . because the extensions are not stored with a . in the map
545 if(ext && *ext == '.')
547 ++ext;
549 if(this->ExtensionToLanguage.count(ext) > 0)
551 return this->ExtensionToLanguage[ext].c_str();
553 return 0;
556 /* SetLanguageEnabled() is now split in two parts:
557 at first the enabled-flag is set. This can then be used in EnabledLanguage()
558 for checking whether the language is already enabled. After setting this
559 flag still the values from the cmake variables have to be copied into the
560 internal maps, this is done in SetLanguageEnabledMaps() which is called
561 after the system- and compiler specific files have been loaded.
563 This split was done originally so that compiler-specific configuration
564 files could change the object file extension
565 (CMAKE_<LANG>_OUTPUT_EXTENSION) before the CMake variables were copied
566 to the C++ maps.
568 void cmGlobalGenerator::SetLanguageEnabled(const char* l, cmMakefile* mf)
570 this->SetLanguageEnabledFlag(l, mf);
571 this->SetLanguageEnabledMaps(l, mf);
574 void cmGlobalGenerator::SetLanguageEnabledFlag(const char* l, cmMakefile* mf)
576 this->LanguageEnabled[l] = true;
578 // Fill the language-to-extension map with the current variable
579 // settings to make sure it is available for the try_compile()
580 // command source file signature. In SetLanguageEnabledMaps this
581 // will be done again to account for any compiler- or
582 // platform-specific entries.
583 this->FillExtensionToLanguageMap(l, mf);
586 void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
588 // use LanguageToLinkerPreference to detect whether this functions has
589 // run before
590 if (this->LanguageToLinkerPreference.find(l) !=
591 this->LanguageToLinkerPreference.end())
593 return;
596 std::string linkerPrefVar = std::string("CMAKE_") +
597 std::string(l) + std::string("_LINKER_PREFERENCE");
598 const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
599 int preference = 0;
600 if(linkerPref)
602 if (sscanf(linkerPref, "%d", &preference)!=1)
604 // backward compatibility: before 2.6 LINKER_PREFERENCE
605 // was either "None" or "Prefered", and only the first character was
606 // tested. So if there is a custom language out there and it is
607 // "Prefered", set its preference high
608 if (linkerPref[0]=='P')
610 preference = 100;
612 else
614 preference = 0;
619 if (preference < 0)
621 std::string msg = linkerPrefVar;
622 msg += " is negative, adjusting it to 0";
623 cmSystemTools::Message(msg.c_str(), "Warning");
624 preference = 0;
627 this->LanguageToLinkerPreference[l] = preference;
629 std::string outputExtensionVar = std::string("CMAKE_") +
630 std::string(l) + std::string("_OUTPUT_EXTENSION");
631 const char* outputExtension = mf->GetDefinition(outputExtensionVar.c_str());
632 if(outputExtension)
634 this->LanguageToOutputExtension[l] = outputExtension;
635 this->OutputExtensions[outputExtension] = outputExtension;
636 if(outputExtension[0] == '.')
638 this->OutputExtensions[outputExtension+1] = outputExtension+1;
642 // The map was originally filled by SetLanguageEnabledFlag, but
643 // since then the compiler- and platform-specific files have been
644 // loaded which might have added more entries.
645 this->FillExtensionToLanguageMap(l, mf);
647 std::string ignoreExtensionsVar = std::string("CMAKE_") +
648 std::string(l) + std::string("_IGNORE_EXTENSIONS");
649 std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar.c_str());
650 std::vector<std::string> extensionList;
651 cmSystemTools::ExpandListArgument(ignoreExts, extensionList);
652 for(std::vector<std::string>::iterator i = extensionList.begin();
653 i != extensionList.end(); ++i)
655 this->IgnoreExtensions[*i] = true;
660 void cmGlobalGenerator::FillExtensionToLanguageMap(const char* l,
661 cmMakefile* mf)
663 std::string extensionsVar = std::string("CMAKE_") +
664 std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS");
665 std::string exts = mf->GetSafeDefinition(extensionsVar.c_str());
666 std::vector<std::string> extensionList;
667 cmSystemTools::ExpandListArgument(exts, extensionList);
668 for(std::vector<std::string>::iterator i = extensionList.begin();
669 i != extensionList.end(); ++i)
671 this->ExtensionToLanguage[*i] = l;
675 bool cmGlobalGenerator::IgnoreFile(const char* l)
677 if(this->GetLanguageFromExtension(l))
679 return false;
681 return (this->IgnoreExtensions.count(l) > 0);
684 bool cmGlobalGenerator::GetLanguageEnabled(const char* l) const
686 return (this->LanguageEnabled.find(l)!= this->LanguageEnabled.end());
689 void cmGlobalGenerator::ClearEnabledLanguages()
691 this->LanguageEnabled.clear();
694 bool cmGlobalGenerator::IsDependedOn(const char* project,
695 cmTarget* targetIn)
697 // Get all local gens for this project
698 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
699 // loop over local gens and get the targets for each one
700 for(unsigned int i = 0; i < gens->size(); ++i)
702 cmTargets& targets = (*gens)[i]->GetMakefile()->GetTargets();
703 for (cmTargets::iterator l = targets.begin();
704 l != targets.end(); l++)
706 cmTarget& target = l->second;
707 std::set<cmStdString>::const_iterator pos =
708 target.GetUtilities().find(targetIn->GetName());
709 if(pos != target.GetUtilities().end())
711 return true;
715 return false;
718 void cmGlobalGenerator::Configure()
720 this->FirstTimeProgress = 0.0f;
721 this->ClearExportSets();
722 // Delete any existing cmLocalGenerators
723 unsigned int i;
724 for (i = 0; i < this->LocalGenerators.size(); ++i)
726 delete this->LocalGenerators[i];
728 this->LocalGenerators.clear();
729 this->TargetDependencies.clear();
730 this->TotalTargets.clear();
731 this->LocalGeneratorToTargetMap.clear();
732 this->ProjectMap.clear();
733 this->RuleHashes.clear();
734 this->DirectoryContentMap.clear();
736 // start with this directory
737 cmLocalGenerator *lg = this->CreateLocalGenerator();
738 this->LocalGenerators.push_back(lg);
740 // set the Start directories
741 lg->GetMakefile()->SetStartDirectory
742 (this->CMakeInstance->GetStartDirectory());
743 lg->GetMakefile()->SetStartOutputDirectory
744 (this->CMakeInstance->GetStartOutputDirectory());
745 lg->GetMakefile()->MakeStartDirectoriesCurrent();
747 // now do it
748 lg->Configure();
750 // update the cache entry for the number of local generators, this is used
751 // for progress
752 char num[100];
753 sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size()));
754 this->GetCMakeInstance()->AddCacheEntry
755 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
756 "number of local generators", cmCacheManager::INTERNAL);
758 // check for link libraries and include directories containing "NOTFOUND"
759 // and for infinite loops
760 this->CheckLocalGenerators();
762 // at this point this->LocalGenerators has been filled,
763 // so create the map from project name to vector of local generators
764 this->FillProjectMap();
766 if ( !this->CMakeInstance->GetScriptMode() )
768 const char* msg = "Configuring done";
769 if(cmSystemTools::GetErrorOccuredFlag())
771 msg = "Configuring incomplete, errors occurred!";
773 this->CMakeInstance->UpdateProgress(msg, -1);
777 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
779 // If the property is not enabled then okay.
780 if(!this->CMakeInstance
781 ->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
783 return true;
786 // This generator does not support duplicate custom targets.
787 cmOStringStream e;
788 e << "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
789 << "global property. "
790 << "The \"" << this->GetName() << "\" generator does not support "
791 << "duplicate custom targets. "
792 << "Consider using a Makefiles generator or fix the project to not "
793 << "use duplicat target names.";
794 cmSystemTools::Error(e.str().c_str());
795 return false;
798 void cmGlobalGenerator::Generate()
800 // Some generators track files replaced during the Generate.
801 // Start with an empty vector:
802 this->FilesReplacedDuringGenerate.clear();
804 // Check whether this generator is allowed to run.
805 if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
807 return;
810 // Check that all targets are valid.
811 if(!this->CheckTargets())
813 return;
816 // For each existing cmLocalGenerator
817 unsigned int i;
819 // Consolidate global targets
820 cmTargets globalTargets;
821 this->CreateDefaultGlobalTargets(&globalTargets);
822 for (i = 0; i < this->LocalGenerators.size(); ++i)
824 cmTargets* targets =
825 &(this->LocalGenerators[i]->GetMakefile()->GetTargets());
826 cmTargets::iterator tarIt;
827 for ( tarIt = targets->begin(); tarIt != targets->end(); ++ tarIt )
829 if ( tarIt->second.GetType() == cmTarget::GLOBAL_TARGET )
831 globalTargets[tarIt->first] = tarIt->second;
835 for (i = 0; i < this->LocalGenerators.size(); ++i)
837 cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
838 cmTargets* targets = &(mf->GetTargets());
839 cmTargets::iterator tit;
840 for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit )
842 (*targets)[tit->first] = tit->second;
843 (*targets)[tit->first].SetMakefile(mf);
847 // Add generator specific helper commands
848 for (i = 0; i < this->LocalGenerators.size(); ++i)
850 this->LocalGenerators[i]->AddHelperCommands();
853 // Trace the dependencies, after that no custom commands should be added
854 // because their dependencies might not be handled correctly
855 for (i = 0; i < this->LocalGenerators.size(); ++i)
857 this->LocalGenerators[i]->TraceDependencies();
860 // Compute the manifest of main targets generated.
861 for (i = 0; i < this->LocalGenerators.size(); ++i)
863 this->LocalGenerators[i]->GenerateTargetManifest();
866 // Compute the inter-target dependencies.
868 cmComputeTargetDepends ctd(this);
869 if(!ctd.Compute())
871 return;
873 std::vector<cmTarget*> const& targets = ctd.GetTargets();
874 for(std::vector<cmTarget*>::const_iterator ti = targets.begin();
875 ti != targets.end(); ++ti)
877 ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]);
881 // Create a map from local generator to the complete set of targets
882 // it builds by default.
883 this->FillLocalGeneratorToTargetMap();
885 // Generate project files
886 for (i = 0; i < this->LocalGenerators.size(); ++i)
888 this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
889 this->LocalGenerators[i]->Generate();
890 this->LocalGenerators[i]->GenerateInstallRules();
891 this->LocalGenerators[i]->GenerateTestFiles();
892 this->CMakeInstance->UpdateProgress("Generating",
893 (i+1.0f)/this->LocalGenerators.size());
895 this->SetCurrentLocalGenerator(0);
897 // Update rule hashes.
898 this->CheckRuleHashes();
900 if (this->ExtraGenerator != 0)
902 this->ExtraGenerator->Generate();
905 this->CMakeInstance->UpdateProgress("Generating done", -1);
908 //----------------------------------------------------------------------------
909 bool cmGlobalGenerator::CheckTargets()
911 // Make sure all targets can find their source files.
912 for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
914 cmTargets& targets =
915 this->LocalGenerators[i]->GetMakefile()->GetTargets();
916 for(cmTargets::iterator ti = targets.begin();
917 ti != targets.end(); ++ti)
919 cmTarget& target = ti->second;
920 if(target.GetType() == cmTarget::EXECUTABLE ||
921 target.GetType() == cmTarget::STATIC_LIBRARY ||
922 target.GetType() == cmTarget::SHARED_LIBRARY ||
923 target.GetType() == cmTarget::MODULE_LIBRARY ||
924 target.GetType() == cmTarget::UTILITY)
926 if(!target.FindSourceFiles())
928 return false;
933 return true;
936 void cmGlobalGenerator::CheckLocalGenerators()
938 std::map<cmStdString, cmStdString> notFoundMap;
939 // std::set<cmStdString> notFoundMap;
940 // after it is all done do a ConfigureFinalPass
941 cmCacheManager* manager = 0;
942 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
944 manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
945 this->LocalGenerators[i]->ConfigureFinalPass();
946 const cmTargets & targets =
947 this->LocalGenerators[i]->GetMakefile()->GetTargets();
948 for (cmTargets::const_iterator l = targets.begin();
949 l != targets.end(); l++)
951 const cmTarget::LinkLibraryVectorType& libs =
952 l->second.GetOriginalLinkLibraries();
953 for(cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin();
954 lib != libs.end(); ++lib)
956 if(lib->first.size() > 9 &&
957 cmSystemTools::IsNOTFOUND(lib->first.c_str()))
959 std::string varName = lib->first.substr(0, lib->first.size()-9);
960 cmCacheManager::CacheIterator it =
961 manager->GetCacheIterator(varName.c_str());
962 if(it.GetPropertyAsBool("ADVANCED"))
964 varName += " (ADVANCED)";
966 std::string text = notFoundMap[varName];
967 text += "\n linked by target \"";
968 text += l->second.GetName();
969 text += "\" in directory ";
970 text+=this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
971 notFoundMap[varName] = text;
975 const std::vector<std::string>& incs =
976 this->LocalGenerators[i]->GetMakefile()->GetIncludeDirectories();
978 for( std::vector<std::string>::const_iterator incDir = incs.begin();
979 incDir != incs.end(); ++incDir)
981 if(incDir->size() > 9 &&
982 cmSystemTools::IsNOTFOUND(incDir->c_str()))
984 std::string varName = incDir->substr(0, incDir->size()-9);
985 cmCacheManager::CacheIterator it =
986 manager->GetCacheIterator(varName.c_str());
987 if(it.GetPropertyAsBool("ADVANCED"))
989 varName += " (ADVANCED)";
991 std::string text = notFoundMap[varName];
992 text += "\n used as include directory in directory ";
993 text += this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
994 notFoundMap[varName] = text;
997 this->CMakeInstance->UpdateProgress
998 ("Configuring", 0.9f+0.1f*(i+1.0f)/this->LocalGenerators.size());
1001 if(notFoundMap.size())
1003 std::string notFoundVars;
1004 for(std::map<cmStdString, cmStdString>::const_iterator
1005 ii = notFoundMap.begin();
1006 ii != notFoundMap.end();
1007 ++ii)
1009 notFoundVars += ii->first;
1010 notFoundVars += ii->second;
1011 notFoundVars += "\n";
1013 cmSystemTools::Error("The following variables are used in this project, "
1014 "but they are set to NOTFOUND.\n"
1015 "Please set them or make sure they are set and "
1016 "tested correctly in the CMake files:\n",
1017 notFoundVars.c_str());
1021 int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
1022 const char *projectName,
1023 const char *target,
1024 std::string *output, cmMakefile *mf)
1026 // if this is not set, then this is a first time configure
1027 // and there is a good chance that the try compile stuff will
1028 // take the bulk of the time, so try and guess some progress
1029 // by getting closer and closer to 100 without actually getting there.
1030 if (!this->CMakeInstance->GetCacheManager()->GetCacheValue
1031 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
1033 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1034 // we are in the first time progress and we have no
1035 // idea how long it will be. So, just move 1/10th of the way
1036 // there each time, and don't go over 95%
1037 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1038 if(this->FirstTimeProgress > 0.95f)
1040 this->FirstTimeProgress = 0.95f;
1042 this->CMakeInstance->UpdateProgress("Configuring",
1043 this->FirstTimeProgress);
1046 std::string makeCommand = this->CMakeInstance->
1047 GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
1048 if(makeCommand.size() == 0)
1050 cmSystemTools::Error(
1051 "Generator cannot find the appropriate make command.");
1052 return 1;
1055 std::string newTarget;
1056 if (target && strlen(target))
1058 newTarget += target;
1059 #if 0
1060 #if defined(_WIN32) || defined(__CYGWIN__)
1061 std::string tmp = target;
1062 // if the target does not already end in . something
1063 // then assume .exe
1064 if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
1066 newTarget += ".exe";
1068 #endif // WIN32
1069 #endif
1071 const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
1072 return this->Build(srcdir,bindir,projectName,
1073 newTarget.c_str(),
1074 output,makeCommand.c_str(),config,false,true,
1075 this->TryCompileTimeout);
1078 std::string cmGlobalGenerator
1079 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
1080 const char* additionalOptions, const char *targetName,
1081 const char* config, bool ignoreErrors, bool)
1083 // Project name and config are not used yet.
1084 (void)projectName;
1085 (void)config;
1087 std::string makeCommand =
1088 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
1090 // Since we have full control over the invocation of nmake, let us
1091 // make it quiet.
1092 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
1094 makeCommand += " /NOLOGO ";
1096 if ( ignoreErrors )
1098 makeCommand += " -i";
1100 if ( additionalOptions )
1102 makeCommand += " ";
1103 makeCommand += additionalOptions;
1105 if ( targetName )
1107 makeCommand += " ";
1108 makeCommand += targetName;
1110 return makeCommand;
1113 int cmGlobalGenerator::Build(
1114 const char *, const char *bindir,
1115 const char *projectName, const char *target,
1116 std::string *output,
1117 const char *makeCommandCSTR,
1118 const char *config,
1119 bool clean, bool fast,
1120 double timeout)
1123 * Run an executable command and put the stdout in output.
1125 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1126 cmSystemTools::ChangeDirectory(bindir);
1127 if(output)
1129 *output += "Change Dir: ";
1130 *output += bindir;
1131 *output += "\n";
1134 int retVal;
1135 bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
1136 cmSystemTools::SetRunCommandHideConsole(true);
1137 std::string outputBuffer;
1138 std::string* outputPtr = 0;
1139 if(output)
1141 outputPtr = &outputBuffer;
1144 // should we do a clean first?
1145 if (clean)
1147 std::string cleanCommand =
1148 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1149 0, "clean", config, false, fast);
1150 if(output)
1152 *output += "\nRun Clean Command:";
1153 *output += cleanCommand;
1154 *output += "\n";
1157 if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), outputPtr,
1158 &retVal, 0, false, timeout))
1160 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1161 cmSystemTools::Error("Generator: execution of make clean failed.");
1162 if (output)
1164 *output += *outputPtr;
1165 *output += "\nGenerator: execution of make clean failed.\n";
1168 // return to the original directory
1169 cmSystemTools::ChangeDirectory(cwd.c_str());
1170 return 1;
1172 if (output)
1174 *output += *outputPtr;
1178 // now build
1179 std::string makeCommand =
1180 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1181 0, target, config, false, fast);
1182 if(output)
1184 *output += "\nRun Build Command:";
1185 *output += makeCommand;
1186 *output += "\n";
1189 if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), outputPtr,
1190 &retVal, 0, false, timeout))
1192 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1193 cmSystemTools::Error
1194 ("Generator: execution of make failed. Make command was: ",
1195 makeCommand.c_str());
1196 if (output)
1198 *output += *outputPtr;
1199 *output += "\nGenerator: execution of make failed. Make command was: "
1200 + makeCommand + "\n";
1203 // return to the original directory
1204 cmSystemTools::ChangeDirectory(cwd.c_str());
1205 return 1;
1207 if (output)
1209 *output += *outputPtr;
1211 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1213 // The SGI MipsPro 7.3 compiler does not return an error code when
1214 // the source has a #error in it! This is a work-around for such
1215 // compilers.
1216 if((retVal == 0) && (output->find("#error") != std::string::npos))
1218 retVal = 1;
1221 cmSystemTools::ChangeDirectory(cwd.c_str());
1222 return retVal;
1225 void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
1227 this->LocalGenerators.push_back(lg);
1229 // update progress
1230 // estimate how many lg there will be
1231 const char *numGenC =
1232 this->CMakeInstance->GetCacheManager()->GetCacheValue
1233 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
1235 if (!numGenC)
1237 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1238 // we are in the first time progress and we have no
1239 // idea how long it will be. So, just move half way
1240 // there each time, and don't go over 95%
1241 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1242 if(this->FirstTimeProgress > 0.95f)
1244 this->FirstTimeProgress = 0.95f;
1246 this->CMakeInstance->UpdateProgress("Configuring",
1247 this->FirstTimeProgress);
1248 return;
1251 int numGen = atoi(numGenC);
1252 float prog = 0.9f*this->LocalGenerators.size()/numGen;
1253 if (prog > 0.9f)
1255 prog = 0.9f;
1257 this->CMakeInstance->UpdateProgress("Configuring", prog);
1260 void cmGlobalGenerator::AddInstallComponent(const char* component)
1262 if(component && *component)
1264 this->InstallComponents.insert(component);
1268 void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
1269 cmTarget* target,
1270 cmInstallTargetGenerator* archive,
1271 cmInstallTargetGenerator* runTime,
1272 cmInstallTargetGenerator* library,
1273 cmInstallTargetGenerator* framework,
1274 cmInstallTargetGenerator* bundle,
1275 cmInstallFilesGenerator* headers)
1277 if ((exportSetName) && (*exportSetName) && (target))
1279 cmTargetExport* te = new cmTargetExport(target, archive, runTime, library,
1280 framework, bundle, headers);
1281 this->ExportSets[exportSetName].push_back(te);
1285 //----------------------------------------------------------------------------
1286 void cmGlobalGenerator::ClearExportSets()
1288 for(std::map<cmStdString, std::vector<cmTargetExport*> >::iterator
1289 setIt = this->ExportSets.begin();
1290 setIt != this->ExportSets.end(); ++setIt)
1292 for(unsigned int i = 0; i < setIt->second.size(); ++i)
1294 delete setIt->second[i];
1297 this->ExportSets.clear();
1300 const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet(
1301 const char* name) const
1303 std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator
1304 exportSetIt = this->ExportSets.find(name);
1305 if (exportSetIt != this->ExportSets.end())
1307 return &exportSetIt->second;
1310 return 0;
1314 void cmGlobalGenerator::EnableInstallTarget()
1316 this->InstallTargetEnabled = true;
1319 cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator()
1321 cmLocalGenerator *lg = new cmLocalGenerator;
1322 lg->SetGlobalGenerator(this);
1323 return lg;
1326 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen )
1328 std::string cfp = gen->GetCMakeInstance()->GetHomeOutputDirectory();
1329 cfp += cmake::GetCMakeFilesDirectory();
1330 this->SetConfiguredFilesPath(cfp.c_str());
1331 const char* make =
1332 gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
1333 this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make,
1334 "make program",
1335 cmCacheManager::FILEPATH);
1336 // copy the enabled languages
1337 this->LanguageEnabled = gen->LanguageEnabled;
1338 this->ExtensionToLanguage = gen->ExtensionToLanguage;
1339 this->IgnoreExtensions = gen->IgnoreExtensions;
1340 this->LanguageToOutputExtension = gen->LanguageToOutputExtension;
1341 this->LanguageToLinkerPreference = gen->LanguageToLinkerPreference;
1342 this->OutputExtensions = gen->OutputExtensions;
1345 //----------------------------------------------------------------------------
1346 void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
1348 entry.Name = this->GetName();
1349 entry.Brief = "";
1350 entry.Full = "";
1353 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1354 cmLocalGenerator* gen)
1356 if(!gen || gen == root)
1358 // No directory excludes itself.
1359 return false;
1362 if(gen->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1364 // This directory is excluded from its parent.
1365 return true;
1368 // This directory is included in its parent. Check whether the
1369 // parent is excluded.
1370 return this->IsExcluded(root, gen->GetParent());
1373 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1374 cmTarget& target)
1376 if(target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1378 // This target is excluded from its directory.
1379 return true;
1381 else
1383 // This target is included in its directory. Check whether the
1384 // directory is excluded.
1385 return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator());
1389 void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
1391 for(std::map<cmStdString, bool>::iterator i =
1392 this->LanguageEnabled.begin(); i != this->LanguageEnabled.end(); ++i)
1394 lang.push_back(i->first);
1398 int cmGlobalGenerator::GetLinkerPreference(const char* lang)
1400 std::map<cmStdString, int>::const_iterator it =
1401 this->LanguageToLinkerPreference.find(lang);
1402 if (it != this->LanguageToLinkerPreference.end())
1404 return it->second;
1406 return 0;
1409 void cmGlobalGenerator::FillProjectMap()
1411 this->ProjectMap.clear(); // make sure we start with a clean map
1412 unsigned int i;
1413 for(i = 0; i < this->LocalGenerators.size(); ++i)
1415 // for each local generator add all projects
1416 cmLocalGenerator *lg = this->LocalGenerators[i];
1417 std::string name;
1420 if (name != lg->GetMakefile()->GetProjectName())
1422 name = lg->GetMakefile()->GetProjectName();
1423 this->ProjectMap[name].push_back(this->LocalGenerators[i]);
1425 lg = lg->GetParent();
1427 while (lg);
1432 // Build a map that contains a the set of targets used by each local
1433 // generator directory level.
1434 void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
1436 this->LocalGeneratorToTargetMap.clear();
1437 // Loop over all targets in all local generators.
1438 for(std::vector<cmLocalGenerator*>::const_iterator
1439 lgi = this->LocalGenerators.begin();
1440 lgi != this->LocalGenerators.end(); ++lgi)
1442 cmLocalGenerator* lg = *lgi;
1443 cmMakefile* mf = lg->GetMakefile();
1444 cmTargets& targets = mf->GetTargets();
1445 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1447 cmTarget& target = t->second;
1449 // Consider the directory containing the target and all its
1450 // parents until something excludes the target.
1451 for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target);
1452 clg = clg->GetParent())
1454 // This local generator includes the target.
1455 std::set<cmTarget*>& targetSet =
1456 this->LocalGeneratorToTargetMap[clg];
1457 targetSet.insert(&target);
1459 // Add dependencies of the included target. An excluded
1460 // target may still be included if it is a dependency of a
1461 // non-excluded target.
1462 TargetDependSet & tgtdeps = this->GetTargetDirectDepends(target);
1463 for(TargetDependSet::const_iterator ti = tgtdeps.begin();
1464 ti != tgtdeps.end(); ++ti)
1466 targetSet.insert(*ti);
1474 ///! Find a local generator by its startdirectory
1475 cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
1477 std::vector<cmLocalGenerator*>* gens = &this->LocalGenerators;
1478 for(unsigned int i = 0; i < gens->size(); ++i)
1480 std::string sd = (*gens)[i]->GetMakefile()->GetStartDirectory();
1481 if (sd == start_dir)
1483 return (*gens)[i];
1486 return 0;
1490 //----------------------------------------------------------------------------
1491 cmTarget*
1492 cmGlobalGenerator::FindTarget(const char* project, const char* name)
1494 // if project specific
1495 if(project)
1497 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
1498 for(unsigned int i = 0; i < gens->size(); ++i)
1500 cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
1501 if(ret)
1503 return ret;
1507 // if all projects/directories
1508 else
1510 std::map<cmStdString,cmTarget *>::iterator i =
1511 this->TotalTargets.find ( name );
1512 if ( i != this->TotalTargets.end() )
1514 return i->second;
1517 return 0;
1520 //----------------------------------------------------------------------------
1521 bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
1523 if(cmSystemTools::IsPathToFramework(libname.c_str()))
1525 return true;
1528 if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
1530 if(tgt->IsFrameworkOnApple())
1532 return true;
1536 return false;
1539 //----------------------------------------------------------------------------
1540 inline std::string removeQuotes(const std::string& s)
1542 if(s[0] == '\"' && s[s.size()-1] == '\"')
1544 return s.substr(1, s.size()-2);
1546 return s;
1549 void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
1551 // Store a pointer to the cmake object instance.
1552 this->CMakeInstance = cm;
1555 void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
1557 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
1558 const char* cmakeCfgIntDir = this->GetCMakeCFGInitDirectory();
1559 const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND");
1561 // CPack
1562 std::string workingDir = mf->GetStartOutputDirectory();
1563 cmCustomCommandLines cpackCommandLines;
1564 std::vector<std::string> depends;
1565 cmCustomCommandLine singleLine;
1566 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1567 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1569 singleLine.push_back("-C");
1570 singleLine.push_back(cmakeCfgIntDir);
1572 singleLine.push_back("--config");
1573 std::string configFile = mf->GetStartOutputDirectory();;
1574 configFile += "/CPackConfig.cmake";
1575 std::string relConfigFile = "./CPackConfig.cmake";
1576 singleLine.push_back(relConfigFile);
1577 cpackCommandLines.push_back(singleLine);
1578 if ( this->GetPreinstallTargetName() )
1580 depends.push_back(this->GetPreinstallTargetName());
1582 else
1584 const char* noPackageAll =
1585 mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
1586 if(!noPackageAll || cmSystemTools::IsOff(noPackageAll))
1588 depends.push_back(this->GetAllTargetName());
1591 if(cmSystemTools::FileExists(configFile.c_str()))
1593 (*targets)[this->GetPackageTargetName()]
1594 = this->CreateGlobalTarget(this->GetPackageTargetName(),
1595 "Run CPack packaging tool...",
1596 &cpackCommandLines, depends,
1597 workingDir.c_str());
1599 // CPack source
1600 const char* packageSourceTargetName = this->GetPackageSourceTargetName();
1601 if ( packageSourceTargetName )
1603 cpackCommandLines.erase(cpackCommandLines.begin(),
1604 cpackCommandLines.end());
1605 singleLine.erase(singleLine.begin(), singleLine.end());
1606 depends.erase(depends.begin(), depends.end());
1607 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1608 singleLine.push_back("--config");
1609 configFile = mf->GetStartOutputDirectory();;
1610 configFile += "/CPackSourceCConfig.cmake";
1611 relConfigFile = "./CPackSourceConfig.cmake";
1612 singleLine.push_back(relConfigFile);
1613 if(cmSystemTools::FileExists(configFile.c_str()))
1615 singleLine.push_back(configFile);
1616 cpackCommandLines.push_back(singleLine);
1617 (*targets)[packageSourceTargetName]
1618 = this->CreateGlobalTarget(packageSourceTargetName,
1619 "Run CPack packaging tool for source...",
1620 &cpackCommandLines, depends,
1621 workingDir.c_str()
1626 // Test
1627 if(mf->IsOn("CMAKE_TESTING_ENABLED"))
1629 cpackCommandLines.erase(cpackCommandLines.begin(),
1630 cpackCommandLines.end());
1631 singleLine.erase(singleLine.begin(), singleLine.end());
1632 depends.erase(depends.begin(), depends.end());
1633 singleLine.push_back(this->GetCMakeInstance()->GetCTestCommand());
1634 singleLine.push_back("--force-new-ctest-process");
1635 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1637 singleLine.push_back("-C");
1638 singleLine.push_back(cmakeCfgIntDir);
1640 else // TODO: This is a hack. Should be something to do with the generator
1642 singleLine.push_back("$(ARGS)");
1644 cpackCommandLines.push_back(singleLine);
1645 (*targets)[this->GetTestTargetName()]
1646 = this->CreateGlobalTarget(this->GetTestTargetName(),
1647 "Running tests...", &cpackCommandLines, depends, 0);
1650 //Edit Cache
1651 const char* editCacheTargetName = this->GetEditCacheTargetName();
1652 if ( editCacheTargetName )
1654 cpackCommandLines.erase(cpackCommandLines.begin(),
1655 cpackCommandLines.end());
1656 singleLine.erase(singleLine.begin(), singleLine.end());
1657 depends.erase(depends.begin(), depends.end());
1659 // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
1660 // Otherwise default to the interactive command-line interface.
1661 if(mf->GetDefinition("CMAKE_EDIT_COMMAND"))
1663 singleLine.push_back(mf->GetDefinition("CMAKE_EDIT_COMMAND"));
1664 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1665 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1666 cpackCommandLines.push_back(singleLine);
1667 (*targets)[editCacheTargetName] =
1668 this->CreateGlobalTarget(
1669 editCacheTargetName, "Running CMake cache editor...",
1670 &cpackCommandLines, depends, 0);
1672 else
1674 singleLine.push_back(cmakeCommand);
1675 singleLine.push_back("-i");
1676 singleLine.push_back(".");
1677 cpackCommandLines.push_back(singleLine);
1678 (*targets)[editCacheTargetName] =
1679 this->CreateGlobalTarget(
1680 editCacheTargetName,
1681 "Running interactive CMake command-line interface...",
1682 &cpackCommandLines, depends, 0);
1686 //Rebuild Cache
1687 const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
1688 if ( rebuildCacheTargetName )
1690 cpackCommandLines.erase(cpackCommandLines.begin(),
1691 cpackCommandLines.end());
1692 singleLine.erase(singleLine.begin(), singleLine.end());
1693 depends.erase(depends.begin(), depends.end());
1694 singleLine.push_back(cmakeCommand);
1695 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1696 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1697 cpackCommandLines.push_back(singleLine);
1698 (*targets)[rebuildCacheTargetName] =
1699 this->CreateGlobalTarget(
1700 rebuildCacheTargetName, "Running CMake to regenerate build system...",
1701 &cpackCommandLines, depends, 0);
1704 //Install
1705 if(this->InstallTargetEnabled)
1707 if(!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.')
1709 std::set<cmStdString>* componentsSet = &this->InstallComponents;
1710 cpackCommandLines.erase(cpackCommandLines.begin(),
1711 cpackCommandLines.end());
1712 depends.erase(depends.begin(), depends.end());
1713 cmOStringStream ostr;
1714 if ( componentsSet->size() > 0 )
1716 ostr << "Available install components are:";
1717 std::set<cmStdString>::iterator it;
1718 for (
1719 it = componentsSet->begin();
1720 it != componentsSet->end();
1721 ++ it )
1723 ostr << " \"" << it->c_str() << "\"";
1726 else
1728 ostr << "Only default component available";
1730 singleLine.push_back(ostr.str().c_str());
1731 (*targets)["list_install_components"]
1732 = this->CreateGlobalTarget("list_install_components",
1733 ostr.str().c_str(),
1734 &cpackCommandLines, depends, 0);
1736 std::string cmd;
1737 cpackCommandLines.erase(cpackCommandLines.begin(),
1738 cpackCommandLines.end());
1739 singleLine.erase(singleLine.begin(), singleLine.end());
1740 depends.erase(depends.begin(), depends.end());
1741 if ( this->GetPreinstallTargetName() )
1743 depends.push_back(this->GetPreinstallTargetName());
1745 else
1747 const char* noall =
1748 mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
1749 if(!noall || cmSystemTools::IsOff(noall))
1751 depends.push_back(this->GetAllTargetName());
1754 if(mf->GetDefinition("CMake_BINARY_DIR"))
1756 // We are building CMake itself. We cannot use the original
1757 // executable to install over itself.
1758 cmd = mf->GetDefinition("EXECUTABLE_OUTPUT_PATH");
1759 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1761 cmd += "/";
1762 cmd += cmakeCfgIntDir;
1764 cmd += "/cmake";
1766 else
1768 cmd = cmakeCommand;
1770 singleLine.push_back(cmd.c_str());
1771 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1773 std::string cfgArg = "-DBUILD_TYPE=";
1774 cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR");
1775 singleLine.push_back(cfgArg);
1777 singleLine.push_back("-P");
1778 singleLine.push_back("cmake_install.cmake");
1779 cpackCommandLines.push_back(singleLine);
1780 (*targets)[this->GetInstallTargetName()] =
1781 this->CreateGlobalTarget(
1782 this->GetInstallTargetName(), "Install the project...",
1783 &cpackCommandLines, depends, 0);
1785 // install_local
1786 if(const char* install_local = this->GetInstallLocalTargetName())
1788 cmCustomCommandLine localCmdLine = singleLine;
1790 localCmdLine.insert(localCmdLine.begin()+1,
1791 "-DCMAKE_INSTALL_LOCAL_ONLY=1");
1792 cpackCommandLines.erase(cpackCommandLines.begin(),
1793 cpackCommandLines.end());
1794 cpackCommandLines.push_back(localCmdLine);
1796 (*targets)[install_local] =
1797 this->CreateGlobalTarget(
1798 install_local, "Installing only the local directory...",
1799 &cpackCommandLines, depends, 0);
1802 // install_strip
1803 const char* install_strip = this->GetInstallStripTargetName();
1804 if((install_strip !=0) && (mf->IsSet("CMAKE_STRIP")))
1806 cmCustomCommandLine stripCmdLine = singleLine;
1808 stripCmdLine.insert(stripCmdLine.begin()+1,"-DCMAKE_INSTALL_DO_STRIP=1");
1809 cpackCommandLines.erase(cpackCommandLines.begin(),
1810 cpackCommandLines.end());
1811 cpackCommandLines.push_back(stripCmdLine);
1813 (*targets)[install_strip] =
1814 this->CreateGlobalTarget(
1815 install_strip, "Installing the project stripped...",
1816 &cpackCommandLines, depends, 0);
1821 cmTarget cmGlobalGenerator::CreateGlobalTarget(
1822 const char* name, const char* message,
1823 const cmCustomCommandLines* commandLines,
1824 std::vector<std::string> depends,
1825 const char* workingDirectory,
1826 bool depends_on_all /* = false */)
1828 // Package
1829 cmTarget target;
1830 target.GetProperties().SetCMakeInstance(this->CMakeInstance);
1831 target.SetType(cmTarget::GLOBAL_TARGET, name);
1832 target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
1834 std::vector<std::string> no_outputs;
1835 std::vector<std::string> no_depends;
1836 // Store the custom command in the target.
1837 cmCustomCommand cc(no_outputs, no_depends, *commandLines, 0,
1838 workingDirectory);
1839 target.GetPostBuildCommands().push_back(cc);
1840 target.SetProperty("EchoString", message);
1841 if ( depends_on_all )
1843 target.AddUtility("all");
1845 std::vector<std::string>::iterator dit;
1846 for ( dit = depends.begin(); dit != depends.end(); ++ dit )
1848 target.AddUtility(dit->c_str());
1850 return target;
1853 //----------------------------------------------------------------------------
1854 void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
1855 const char*, std::string&)
1857 // Subclasses that support multiple configurations should implement
1858 // this method to append the subdirectory for the given build
1859 // configuration.
1862 //----------------------------------------------------------------------------
1863 cmGlobalGenerator::TargetDependSet &
1864 cmGlobalGenerator::GetTargetDirectDepends(cmTarget & target)
1866 return this->TargetDependencies[&target];
1869 void cmGlobalGenerator::AddTarget(cmTargets::value_type &v)
1871 assert(!v.second.IsImported());
1872 this->TotalTargets[v.first] = &v.second;
1875 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
1876 cmExternalMakefileProjectGenerator *extraGenerator)
1878 this->ExtraGenerator = extraGenerator;
1879 if (this->ExtraGenerator!=0)
1881 this->ExtraGenerator->SetGlobalGenerator(this);
1885 const char* cmGlobalGenerator::GetExtraGeneratorName() const
1887 return this->ExtraGenerator==0 ? 0 : this->ExtraGenerator->GetName();
1890 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
1892 this->FilesReplacedDuringGenerate.push_back(filename);
1895 void
1896 cmGlobalGenerator
1897 ::GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames)
1899 filenames.clear();
1900 std::copy(
1901 this->FilesReplacedDuringGenerate.begin(),
1902 this->FilesReplacedDuringGenerate.end(),
1903 std::back_inserter(filenames));
1906 void
1907 cmGlobalGenerator
1908 ::GetTargetSets(cmGlobalGenerator::TargetDependSet& projectTargets,
1909 cmGlobalGenerator::TargetDependSet& originalTargets,
1910 cmLocalGenerator* root,
1911 std::vector<cmLocalGenerator*> const& generators)
1913 // loop over all local generators
1914 for(std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
1915 i != generators.end(); ++i)
1917 // check to make sure generator is not excluded
1918 if(this->IsExcluded(root, *i))
1920 continue;
1922 cmMakefile* mf = (*i)->GetMakefile();
1923 // Get the targets in the makefile
1924 cmTargets &tgts = mf->GetTargets();
1925 // loop over all the targets
1926 for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
1928 cmTarget* target = &l->second;
1929 // put the target in the set of original targets
1930 originalTargets.insert(target);
1931 // Get the set of targets that depend on target
1932 this->AddTargetDepends(target,
1933 projectTargets);
1938 void
1939 cmGlobalGenerator::AddTargetDepends(cmTarget* target,
1940 cmGlobalGenerator::TargetDependSet&
1941 projectTargets)
1943 // add the target itself
1944 projectTargets.insert(target);
1945 // get the direct depends of target
1946 cmGlobalGenerator::TargetDependSet const& tset
1947 = this->GetTargetDirectDepends(*target);
1948 if(tset.size())
1950 // if there are targets that depend on target
1951 // add them and their depends as well
1952 for(cmGlobalGenerator::TargetDependSet::const_iterator i =
1953 tset.begin(); i != tset.end(); ++i)
1955 cmTarget* dtarget = *i;
1956 this->AddTargetDepends(dtarget, projectTargets);
1962 //----------------------------------------------------------------------------
1963 void cmGlobalGenerator::AddToManifest(const char* config,
1964 std::string const& f)
1966 // Add to the main manifest for this configuration.
1967 this->TargetManifest[config].insert(f);
1969 // Add to the content listing for the file's directory.
1970 std::string dir = cmSystemTools::GetFilenamePath(f);
1971 std::string file = cmSystemTools::GetFilenameName(f);
1972 this->DirectoryContentMap[dir].insert(file);
1975 //----------------------------------------------------------------------------
1976 std::set<cmStdString> const&
1977 cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
1979 DirectoryContent& dc = this->DirectoryContentMap[dir];
1980 if(needDisk && !dc.LoadedFromDisk)
1982 // Load the directory content from disk.
1983 cmsys::Directory d;
1984 if(d.Load(dir.c_str()))
1986 unsigned long n = d.GetNumberOfFiles();
1987 for(unsigned long i = 0; i < n; ++i)
1989 const char* f = d.GetFile(i);
1990 if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
1992 dc.insert(f);
1996 dc.LoadedFromDisk = true;
1998 return dc;
2001 //----------------------------------------------------------------------------
2002 void
2003 cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
2004 std::vector<std::string>::const_iterator first,
2005 std::vector<std::string>::const_iterator last)
2007 #if defined(CMAKE_BUILD_WITH_CMAKE)
2008 // Ignore if there are no outputs.
2009 if(outputs.empty())
2011 return;
2014 // Compute a hash of the rule.
2015 RuleHash hash;
2017 unsigned char const* data;
2018 int length;
2019 cmsysMD5* sum = cmsysMD5_New();
2020 cmsysMD5_Initialize(sum);
2021 for(std::vector<std::string>::const_iterator i = first; i != last; ++i)
2023 data = reinterpret_cast<unsigned char const*>(i->c_str());
2024 length = static_cast<int>(i->length());
2025 cmsysMD5_Append(sum, data, length);
2027 cmsysMD5_FinalizeHex(sum, hash.Data);
2028 cmsysMD5_Delete(sum);
2031 // Shorten the output name (in expected use case).
2032 cmLocalGenerator* lg = this->GetLocalGenerators()[0];
2033 std::string fname = lg->Convert(outputs[0].c_str(),
2034 cmLocalGenerator::HOME_OUTPUT);
2036 // Associate the hash with this output.
2037 this->RuleHashes[fname] = hash;
2038 #else
2039 (void)outputs;
2040 (void)first;
2041 (void)last;
2042 #endif
2045 //----------------------------------------------------------------------------
2046 void cmGlobalGenerator::CheckRuleHashes()
2048 #if defined(CMAKE_BUILD_WITH_CMAKE)
2049 std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
2050 std::string pfile = home;
2051 pfile += this->GetCMakeInstance()->GetCMakeFilesDirectory();
2052 pfile += "/CMakeRuleHashes.txt";
2054 #if defined(_WIN32) || defined(__CYGWIN__)
2055 std::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
2056 #else
2057 std::ifstream fin(pfile.c_str(), std::ios::in);
2058 #endif
2059 std::string line;
2060 std::string fname;
2061 while(cmSystemTools::GetLineFromStream(fin, line))
2063 // Line format is a 32-byte hex string followed by a space
2064 // followed by a file name (with no escaping).
2066 // Skip blank and comment lines.
2067 if(line.size() < 34 || line[0] == '#')
2069 continue;
2072 // Get the filename.
2073 fname = line.substr(33, line.npos);
2075 // Look for a hash for this file's rule.
2076 std::map<cmStdString, RuleHash>::const_iterator rhi =
2077 this->RuleHashes.find(fname);
2078 if(rhi != this->RuleHashes.end())
2080 // Compare the rule hash in the file to that we were given.
2081 if(strncmp(line.c_str(), rhi->second.Data, 32) != 0)
2083 // The rule has changed. Delete the output so it will be
2084 // built again.
2085 fname = cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
2086 cmSystemTools::RemoveFile(fname.c_str());
2089 else
2091 // We have no hash for a rule previously listed. This may be a
2092 // case where a user has turned off a build option and might
2093 // want to turn it back on later, so do not delete the file.
2094 // Instead, we keep the rule hash as long as the file exists so
2095 // that if the feature is turned back on and the rule has
2096 // changed the file is still rebuilt.
2097 std::string fpath =
2098 cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
2099 if(cmSystemTools::FileExists(fpath.c_str()))
2101 RuleHash hash;
2102 strncpy(hash.Data, line.c_str(), 32);
2103 this->RuleHashes[fname] = hash;
2108 // Now generate a new persistence file with the current hashes.
2109 if(this->RuleHashes.empty())
2111 cmSystemTools::RemoveFile(pfile.c_str());
2113 else
2115 cmGeneratedFileStream fout(pfile.c_str());
2116 fout << "# Hashes of file build rules.\n";
2117 for(std::map<cmStdString, RuleHash>::const_iterator
2118 rhi = this->RuleHashes.begin(); rhi != this->RuleHashes.end(); ++rhi)
2120 fout.write(rhi->second.Data, 32);
2121 fout << " " << rhi->first << "\n";
2124 #endif