BUG: fix some bad changes in progress calc
[cmake.git] / Source / cmGlobalGenerator.cxx
blob79547b664513ba70703b5435930ae63762c1bf82
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008-03-04 23:41:52 $
7 Version: $Revision: 1.227 $
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"
31 #include <cmsys/Directory.hxx>
33 #include <stdlib.h> // required for atof
35 #include <assert.h>
37 cmGlobalGenerator::cmGlobalGenerator()
39 // By default the .SYMBOLIC dependency is not needed on symbolic rules.
40 this->NeedSymbolicMark = false;
42 // by default use the native paths
43 this->ForceUnixPaths = false;
45 // By default do not try to support color.
46 this->ToolSupportsColor = false;
48 // By default do not use link scripts.
49 this->UseLinkScript = false;
51 // Whether an install target is needed.
52 this->InstallTargetEnabled = false;
54 // how long to let try compiles run
55 this->TryCompileTimeout = 0;
57 this->ExtraGenerator = 0;
58 this->CurrentLocalGenerator = 0;
61 cmGlobalGenerator::~cmGlobalGenerator()
63 // Delete any existing cmLocalGenerators
64 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
66 delete this->LocalGenerators[i];
68 this->LocalGenerators.clear();
70 if (this->ExtraGenerator)
72 delete this->ExtraGenerator;
75 for (std::map<cmStdString, std::vector<cmTargetExport*> >::iterator
76 setIt = this->ExportSets.begin();
77 setIt != this->ExportSets.end();
78 ++setIt)
80 for (unsigned int i = 0; i < setIt->second.size(); ++i)
82 delete setIt->second[i];
87 // Find the make program for the generator, required for try compiles
88 void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
90 if(this->FindMakeProgramFile.size() == 0)
92 cmSystemTools::Error(
93 "Generator implementation error, "
94 "all generators must specify this->FindMakeProgramFile");
96 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
97 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
99 std::string setMakeProgram =
100 mf->GetModulesFile(this->FindMakeProgramFile.c_str());
101 if(setMakeProgram.size())
103 mf->ReadListFile(0, setMakeProgram.c_str());
106 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
107 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
109 cmOStringStream err;
110 err << "CMake was unable to find a build program corresponding to \""
111 << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You "
112 << "probably need to select a different build tool.";
113 cmSystemTools::Error(err.str().c_str());
114 cmSystemTools::SetFatalErrorOccured();
115 return;
117 std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
118 // if there are spaces in the make program use short path
119 // but do not short path the actual program name, as
120 // this can cause trouble with VSExpress
121 if(makeProgram.find(' ') != makeProgram.npos)
123 std::string dir;
124 std::string file;
125 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
126 dir, file);
127 std::string saveFile = file;
128 cmSystemTools::GetShortPath(makeProgram.c_str(), makeProgram);
129 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
130 dir, file);
131 makeProgram = dir;
132 makeProgram += "/";
133 makeProgram += saveFile;
134 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
135 "make program",
136 cmCacheManager::FILEPATH);
139 if(makeProgram.find("xcodebuild") != makeProgram.npos)
141 // due to the text file busy /bin/sh problem with xcodebuild
142 // use the cmakexbuild wrapper instead. This program
143 // will run xcodebuild and if it sees the error text file busy
144 // it will stop forwarding output, and let the build finish.
145 // Then it will retry the build. It will continue this
146 // untill no text file busy errors occur.
147 std::string cmakexbuild =
148 this->CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_COMMAND");
149 cmakexbuild = cmakexbuild.substr(0, cmakexbuild.length()-5);
150 cmakexbuild += "cmakexbuild";
152 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM",
153 cmakexbuild.c_str(),
154 "make program",
155 cmCacheManager::FILEPATH);
159 // enable the given language
161 // The following files are loaded in this order:
163 // First figure out what OS we are running on:
165 // CMakeSystem.cmake - configured file created by CMakeDetermineSystem.cmake
166 // CMakeDetermineSystem.cmake - figure out os info and create
167 // CMakeSystem.cmake IF CMAKE_SYSTEM
168 // not set
169 // CMakeSystem.cmake - configured file created by
170 // CMakeDetermineSystem.cmake IF CMAKE_SYSTEM_LOADED
172 // Next try and enable all languages found in the languages vector
174 // FOREACH LANG in languages
175 // CMake(LANG)Compiler.cmake - configured file create by
176 // CMakeDetermine(LANG)Compiler.cmake
177 // CMakeDetermine(LANG)Compiler.cmake - Finds compiler for LANG and
178 // creates CMake(LANG)Compiler.cmake
179 // CMake(LANG)Compiler.cmake - configured file created by
180 // CMakeDetermine(LANG)Compiler.cmake
182 // CMakeSystemSpecificInformation.cmake
183 // - includes Platform/${CMAKE_SYSTEM_NAME}.cmake
184 // may use compiler stuff
186 // FOREACH LANG in languages
187 // CMake(LANG)Information.cmake
188 // - loads Platform/${CMAKE_SYSTEM_NAME}-${COMPILER}.cmake
189 // CMakeTest(LANG)Compiler.cmake
190 // - Make sure the compiler works with a try compile if
191 // CMakeDetermine(LANG) was loaded
193 // Now load a few files that can override values set in any of the above
194 // (PROJECTNAME)Compatibility.cmake
195 // - load any backwards compatibility stuff for current project
196 // ${CMAKE_USER_MAKE_RULES_OVERRIDE}
197 // - allow users a chance to override system variables
201 void
202 cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
203 cmMakefile *mf, bool)
205 if(languages.size() == 0)
207 cmSystemTools::Error("EnableLanguage must have a lang specified!");
208 cmSystemTools::SetFatalErrorOccured();
209 return;
211 mf->AddDefinition("RUN_CONFIGURE", true);
212 std::string rootBin = mf->GetHomeOutputDirectory();
213 rootBin += cmake::GetCMakeFilesDirectory();
215 // If the configuration files path has been set,
216 // then we are in a try compile and need to copy the enable language
217 // files from the parent cmake bin dir, into the try compile bin dir
218 if(this->ConfiguredFilesPath.size())
220 for(std::vector<std::string>::const_iterator l = languages.begin();
221 l != languages.end(); ++l)
223 if(*l == "NONE")
225 this->SetLanguageEnabled("NONE", mf);
226 break;
229 rootBin = this->ConfiguredFilesPath;
232 // set the dir for parent files so they can be used by modules
233 mf->AddDefinition("CMAKE_PLATFORM_ROOT_BIN",rootBin.c_str());
235 // find and make sure CMAKE_MAKE_PROGRAM is defined
236 this->FindMakeProgram(mf);
238 // try and load the CMakeSystem.cmake if it is there
239 std::string fpath = rootBin;
240 if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
242 fpath += "/CMakeSystem.cmake";
243 if(cmSystemTools::FileExists(fpath.c_str()))
245 mf->ReadListFile(0,fpath.c_str());
248 // Load the CMakeDetermineSystem.cmake file and find out
249 // what platform we are running on
250 if (!mf->GetDefinition("CMAKE_SYSTEM"))
252 #if defined(_WIN32) && !defined(__CYGWIN__)
253 /* Windows version number data. */
254 OSVERSIONINFO osvi;
255 ZeroMemory(&osvi, sizeof(osvi));
256 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
257 GetVersionEx (&osvi);
258 cmOStringStream windowsVersionString;
259 windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
260 windowsVersionString.str();
261 mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
262 windowsVersionString.str().c_str());
263 #endif
264 // Read the DetermineSystem file
265 std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
266 mf->ReadListFile(0, systemFile.c_str());
267 // load the CMakeSystem.cmake from the binary directory
268 // this file is configured by the CMakeDetermineSystem.cmake file
269 fpath = rootBin;
270 fpath += "/CMakeSystem.cmake";
271 mf->ReadListFile(0,fpath.c_str());
273 std::map<cmStdString, bool> needTestLanguage;
274 std::map<cmStdString, bool> needSetLanguageEnabledMaps;
275 // foreach language
276 // load the CMakeDetermine(LANG)Compiler.cmake file to find
277 // the compiler
279 for(std::vector<std::string>::const_iterator l = languages.begin();
280 l != languages.end(); ++l)
282 const char* lang = l->c_str();
283 needSetLanguageEnabledMaps[lang] = false;
284 if(*l == "NONE")
286 this->SetLanguageEnabled("NONE", mf);
287 continue;
289 std::string loadedLang = "CMAKE_";
290 loadedLang += lang;
291 loadedLang += "_COMPILER_LOADED";
292 // If the existing build tree was already configured with this
293 // version of CMake then try to load the configured file first
294 // to avoid duplicate compiler tests.
295 unsigned int cacheMajor = mf->GetCacheMajorVersion();
296 unsigned int cacheMinor = mf->GetCacheMinorVersion();
297 unsigned int selfMajor = cmVersion::GetMajorVersion();
298 unsigned int selfMinor = cmVersion::GetMinorVersion();
299 if((this->CMakeInstance->GetIsInTryCompile() ||
300 (selfMajor == cacheMajor && selfMinor == cacheMinor))
301 && !mf->GetDefinition(loadedLang.c_str()))
303 fpath = rootBin;
304 fpath += "/CMake";
305 fpath += lang;
306 fpath += "Compiler.cmake";
307 if(cmSystemTools::FileExists(fpath.c_str()))
309 if(!mf->ReadListFile(0,fpath.c_str()))
311 cmSystemTools::Error("Could not find cmake module file:",
312 fpath.c_str());
314 // if this file was found then the language was already determined
315 // to be working
316 needTestLanguage[lang] = false;
317 this->SetLanguageEnabledFlag(lang, mf);
318 needSetLanguageEnabledMaps[lang] = true;
319 // this can only be called after loading CMake(LANG)Compiler.cmake
323 if(!this->GetLanguageEnabled(lang) )
325 if (this->CMakeInstance->GetIsInTryCompile())
327 cmSystemTools::Error("This should not have happen. "
328 "If you see this message, you are probably "
329 "using a broken CMakeLists.txt file or a "
330 "problematic release of CMake");
332 // if the CMake(LANG)Compiler.cmake file was not found then
333 // load CMakeDetermine(LANG)Compiler.cmake
334 std::string determineCompiler = "CMakeDetermine";
335 determineCompiler += lang;
336 determineCompiler += "Compiler.cmake";
337 std::string determineFile =
338 mf->GetModulesFile(determineCompiler.c_str());
339 if(!mf->ReadListFile(0,determineFile.c_str()))
341 cmSystemTools::Error("Could not find cmake module file:",
342 determineFile.c_str());
344 needTestLanguage[lang] = true;
345 // Some generators like visual studio should not use the env variables
346 // So the global generator can specify that in this variable
347 if(!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV"))
349 // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
350 // into the environment, in case user scripts want to run
351 // configure, or sub cmakes
352 std::string compilerName = "CMAKE_";
353 compilerName += lang;
354 compilerName += "_COMPILER";
355 std::string compilerEnv = "CMAKE_";
356 compilerEnv += lang;
357 compilerEnv += "_COMPILER_ENV_VAR";
358 std::string envVar = mf->GetRequiredDefinition(compilerEnv.c_str());
359 std::string envVarValue =
360 mf->GetRequiredDefinition(compilerName.c_str());
361 std::string env = envVar;
362 env += "=";
363 env += envVarValue;
364 cmSystemTools::PutEnv(env.c_str());
367 // if determineLanguage was called then load the file it
368 // configures CMake(LANG)Compiler.cmake
369 fpath = rootBin;
370 fpath += "/CMake";
371 fpath += lang;
372 fpath += "Compiler.cmake";
373 if(!mf->ReadListFile(0,fpath.c_str()))
375 cmSystemTools::Error("Could not find cmake module file:",
376 fpath.c_str());
378 this->SetLanguageEnabledFlag(lang, mf);
379 needSetLanguageEnabledMaps[lang] = true;
380 // this can only be called after loading CMake(LANG)Compiler.cmake
381 // the language must be enabled for try compile to work, but we do
382 // not know if it is a working compiler yet so set the test language
383 // flag
384 needTestLanguage[lang] = true;
385 } // end if(!this->GetLanguageEnabled(lang) )
386 } // end loop over languages
388 // **** Load the system specific information if not yet loaded
389 if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
391 fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
392 if(!mf->ReadListFile(0,fpath.c_str()))
394 cmSystemTools::Error("Could not find cmake module file:",
395 fpath.c_str());
398 // loop over languages again loading CMake(LANG)Information.cmake
400 for(std::vector<std::string>::const_iterator l = languages.begin();
401 l != languages.end(); ++l)
403 const char* lang = l->c_str();
404 if(*l == "NONE")
406 this->SetLanguageEnabled("NONE", mf);
407 continue;
409 std::string langLoadedVar = "CMAKE_";
410 langLoadedVar += lang;
411 langLoadedVar += "_INFORMATION_LOADED";
412 if (!mf->GetDefinition(langLoadedVar.c_str()))
414 fpath = "CMake";
415 fpath += lang;
416 fpath += "Information.cmake";
417 fpath = mf->GetModulesFile(fpath.c_str());
418 if(!mf->ReadListFile(0,fpath.c_str()))
420 cmSystemTools::Error("Could not find cmake module file:",
421 fpath.c_str());
424 if (needSetLanguageEnabledMaps[lang])
426 this->SetLanguageEnabledMaps(lang, mf);
429 // Test the compiler for the language just setup
430 // At this point we should have enough info for a try compile
431 // which is used in the backward stuff
432 // If the language is untested then test it now with a try compile.
433 if(needTestLanguage[lang])
435 if (!this->CMakeInstance->GetIsInTryCompile())
437 std::string testLang = "CMakeTest";
438 testLang += lang;
439 testLang += "Compiler.cmake";
440 std::string ifpath = mf->GetModulesFile(testLang.c_str());
441 if(!mf->ReadListFile(0,ifpath.c_str()))
443 cmSystemTools::Error("Could not find cmake module file:",
444 ifpath.c_str());
446 std::string compilerWorks = "CMAKE_";
447 compilerWorks += lang;
448 compilerWorks += "_COMPILER_WORKS";
449 // if the compiler did not work, then remove the
450 // CMake(LANG)Compiler.cmake file so that it will get tested the
451 // next time cmake is run
452 if(!mf->IsOn(compilerWorks.c_str()))
454 fpath = rootBin;
455 fpath += "/CMake";
456 fpath += lang;
457 fpath += "Compiler.cmake";
458 cmSystemTools::RemoveFile(fpath.c_str());
460 else
462 // load backwards compatibility stuff for C and CXX
463 // for old versions of CMake ListFiles C and CXX had some
464 // backwards compatibility files they have to load
465 // These files have a bunch of try compiles in them so
466 // should only be done
467 if (mf->NeedBackwardsCompatibility(1,4))
469 if(strcmp(lang, "C") == 0)
471 ifpath =
472 mf->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
473 mf->ReadListFile(0,ifpath.c_str());
475 if(strcmp(lang, "CXX") == 0)
477 ifpath =
478 mf->GetModulesFile("CMakeBackwardCompatibilityCXX.cmake");
479 mf->ReadListFile(0,ifpath.c_str());
483 } // end if in try compile
484 } // end need test language
485 } // end for each language
487 // Now load files that can override any settings on the platform or for
488 // the project First load the project compatibility file if it is in
489 // cmake
490 std::string projectCompatibility = mf->GetDefinition("CMAKE_ROOT");
491 projectCompatibility += "/Modules/";
492 projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
493 projectCompatibility += "Compatibility.cmake";
494 if(cmSystemTools::FileExists(projectCompatibility.c_str()))
496 mf->ReadListFile(0,projectCompatibility.c_str());
500 //----------------------------------------------------------------------------
501 const char*
502 cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source)
504 if(const char* lang = source.GetLanguage())
506 if(this->LanguageToOutputExtension.count(lang) > 0)
508 return this->LanguageToOutputExtension[lang].c_str();
511 else
513 // if no language is found then check to see if it is already an
514 // ouput extension for some language. In that case it should be ignored
515 // and in this map, so it will not be compiled but will just be used.
516 std::string const& ext = source.GetExtension();
517 if(!ext.empty())
519 if(this->OutputExtensions.count(ext))
521 return ext.c_str();
525 return "";
529 const char* cmGlobalGenerator::GetLanguageFromExtension(const char* ext)
531 // if there is an extension and it starts with . then move past the
532 // . because the extensions are not stored with a . in the map
533 if(ext && *ext == '.')
535 ++ext;
537 if(this->ExtensionToLanguage.count(ext) > 0)
539 return this->ExtensionToLanguage[ext].c_str();
541 return 0;
544 /* SetLanguageEnabled() is now split in two parts:
545 at first the enabled-flag is set. This can then be used in EnabledLanguage()
546 for checking whether the language is already enabled. After setting this
547 flag still the values from the cmake variables have to be copied into the
548 internal maps, this is done in SetLanguageEnabledMaps() which is called
549 after the system- and compiler specific files have been loaded.
551 void cmGlobalGenerator::SetLanguageEnabled(const char* l, cmMakefile* mf)
553 this->SetLanguageEnabledFlag(l, mf);
554 this->SetLanguageEnabledMaps(l, mf);
557 void cmGlobalGenerator::SetLanguageEnabledFlag(const char* l, cmMakefile*)
559 this->LanguageEnabled[l] = true;
562 void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
564 // use LanguageToLinkerPreference to detect whether this functions has
565 // run before
566 if (this->LanguageToLinkerPreference.find(l) !=
567 this->LanguageToLinkerPreference.end())
569 return;
572 std::string linkerPrefVar = std::string("CMAKE_") +
573 std::string(l) + std::string("_LINKER_PREFERENCE");
574 const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
575 int preference = 0;
576 if(linkerPref)
578 if (sscanf(linkerPref, "%d", &preference)!=1)
580 // backward compatibility: before 2.6 LINKER_PREFERENCE
581 // was either "None" or "Prefered", and only the first character was
582 // tested. So if there is a custom language out there and it is
583 // "Prefered", set its preference high
584 if (linkerPref[0]=='P')
586 preference = 100;
588 else
590 preference = 0;
595 if (preference < 0)
597 std::string msg = linkerPrefVar;
598 msg += " is negative, adjusting it to 0";
599 cmSystemTools::Message(msg.c_str(), "Warning");
600 preference = 0;
603 this->LanguageToLinkerPreference[l] = preference;
605 std::string outputExtensionVar = std::string("CMAKE_") +
606 std::string(l) + std::string("_OUTPUT_EXTENSION");
607 const char* outputExtension = mf->GetDefinition(outputExtensionVar.c_str());
608 if(outputExtension)
610 this->LanguageToOutputExtension[l] = outputExtension;
611 this->OutputExtensions[outputExtension] = outputExtension;
612 if(outputExtension[0] == '.')
614 this->OutputExtensions[outputExtension+1] = outputExtension+1;
618 std::string extensionsVar = std::string("CMAKE_") +
619 std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS");
620 std::string ignoreExtensionsVar = std::string("CMAKE_") +
621 std::string(l) + std::string("_IGNORE_EXTENSIONS");
622 std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar.c_str());
623 std::string exts = mf->GetSafeDefinition(extensionsVar.c_str());
624 std::vector<std::string> extensionList;
625 cmSystemTools::ExpandListArgument(exts, extensionList);
626 for(std::vector<std::string>::iterator i = extensionList.begin();
627 i != extensionList.end(); ++i)
629 this->ExtensionToLanguage[*i] = l;
631 cmSystemTools::ExpandListArgument(ignoreExts, extensionList);
632 for(std::vector<std::string>::iterator i = extensionList.begin();
633 i != extensionList.end(); ++i)
635 this->IgnoreExtensions[*i] = true;
640 bool cmGlobalGenerator::IgnoreFile(const char* l)
642 if(this->GetLanguageFromExtension(l))
644 return false;
646 return (this->IgnoreExtensions.count(l) > 0);
649 bool cmGlobalGenerator::GetLanguageEnabled(const char* l) const
651 return (this->LanguageEnabled.find(l)!= this->LanguageEnabled.end());
654 void cmGlobalGenerator::ClearEnabledLanguages()
656 this->LanguageEnabled.clear();
659 bool cmGlobalGenerator::IsDependedOn(const char* project,
660 cmTarget* targetIn)
662 // Get all local gens for this project
663 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
664 // loop over local gens and get the targets for each one
665 for(unsigned int i = 0; i < gens->size(); ++i)
667 cmTargets& targets = (*gens)[i]->GetMakefile()->GetTargets();
668 for (cmTargets::iterator l = targets.begin();
669 l != targets.end(); l++)
671 cmTarget& target = l->second;
672 std::set<cmStdString>::const_iterator pos =
673 target.GetUtilities().find(targetIn->GetName());
674 if(pos != target.GetUtilities().end())
676 return true;
680 return false;
683 void cmGlobalGenerator::Configure()
685 this->FirstTimeProgress = 0.0f;
686 // Delete any existing cmLocalGenerators
687 unsigned int i;
688 for (i = 0; i < this->LocalGenerators.size(); ++i)
690 delete this->LocalGenerators[i];
692 this->LocalGenerators.clear();
693 this->TargetDependencies.clear();
694 this->TotalTargets.clear();
695 this->LocalGeneratorToTargetMap.clear();
696 this->ProjectMap.clear();
698 // start with this directory
699 cmLocalGenerator *lg = this->CreateLocalGenerator();
700 this->LocalGenerators.push_back(lg);
702 // set the Start directories
703 lg->GetMakefile()->SetStartDirectory
704 (this->CMakeInstance->GetStartDirectory());
705 lg->GetMakefile()->SetStartOutputDirectory
706 (this->CMakeInstance->GetStartOutputDirectory());
707 lg->GetMakefile()->MakeStartDirectoriesCurrent();
709 // now do it
710 lg->Configure();
712 // update the cache entry for the number of local generators, this is used
713 // for progress
714 char num[100];
715 sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size()));
716 this->GetCMakeInstance()->AddCacheEntry
717 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
718 "number of local generators", cmCacheManager::INTERNAL);
720 // check for link libraries and include directories containing "NOTFOUND"
721 // and for infinite loops
722 this->CheckLocalGenerators();
724 // at this point this->LocalGenerators has been filled,
725 // so create the map from project name to vector of local generators
726 this->FillProjectMap();
728 if ( !this->CMakeInstance->GetScriptMode() )
730 this->CMakeInstance->UpdateProgress("Configuring done", -1);
734 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
736 // If the property is not enabled then okay.
737 if(!this->CMakeInstance
738 ->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
740 return true;
743 // This generator does not support duplicate custom targets.
744 cmOStringStream e;
745 e << "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
746 << "global property. "
747 << "The \"" << this->GetName() << "\" generator does not support "
748 << "duplicate custom targets. "
749 << "Consider using a Makefiles generator or fix the project to not "
750 << "use duplicat target names.";
751 cmSystemTools::Error(e.str().c_str());
752 return false;
755 void cmGlobalGenerator::Generate()
757 // Some generators track files replaced during the Generate.
758 // Start with an empty vector:
759 this->FilesReplacedDuringGenerate.clear();
761 // Check whether this generator is allowed to run.
762 if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
764 return;
767 // For each existing cmLocalGenerator
768 unsigned int i;
770 // Consolidate global targets
771 cmTargets globalTargets;
772 this->CreateDefaultGlobalTargets(&globalTargets);
773 for (i = 0; i < this->LocalGenerators.size(); ++i)
775 cmTargets* targets =
776 &(this->LocalGenerators[i]->GetMakefile()->GetTargets());
777 cmTargets::iterator tarIt;
778 for ( tarIt = targets->begin(); tarIt != targets->end(); ++ tarIt )
780 if ( tarIt->second.GetType() == cmTarget::GLOBAL_TARGET )
782 globalTargets[tarIt->first] = tarIt->second;
786 for (i = 0; i < this->LocalGenerators.size(); ++i)
788 cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
789 cmTargets* targets = &(mf->GetTargets());
790 cmTargets::iterator tit;
791 for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit )
793 (*targets)[tit->first] = tit->second;
794 (*targets)[tit->first].SetMakefile(mf);
798 // Add generator specific helper commands
799 for (i = 0; i < this->LocalGenerators.size(); ++i)
801 this->LocalGenerators[i]->AddHelperCommands();
804 // Trace the dependencies, after that no custom commands should be added
805 // because their dependencies might not be handled correctly
806 for (i = 0; i < this->LocalGenerators.size(); ++i)
808 this->LocalGenerators[i]->TraceDependencies();
811 // Compute the manifest of main targets generated.
812 for (i = 0; i < this->LocalGenerators.size(); ++i)
814 this->LocalGenerators[i]->GenerateTargetManifest();
817 // Compute the inter-target dependencies.
819 cmComputeTargetDepends ctd(this);
820 ctd.Compute();
821 std::vector<cmTarget*> const& targets = ctd.GetTargets();
822 for(std::vector<cmTarget*>::const_iterator ti = targets.begin();
823 ti != targets.end(); ++ti)
825 ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]);
829 // Create a map from local generator to the complete set of targets
830 // it builds by default.
831 this->FillLocalGeneratorToTargetMap();
833 // Generate project files
834 for (i = 0; i < this->LocalGenerators.size(); ++i)
836 this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
837 this->LocalGenerators[i]->Generate();
838 this->LocalGenerators[i]->GenerateInstallRules();
839 this->LocalGenerators[i]->GenerateTestFiles();
840 this->CMakeInstance->UpdateProgress("Generating",
841 (i+1.0f)/this->LocalGenerators.size());
843 this->SetCurrentLocalGenerator(0);
845 if (this->ExtraGenerator != 0)
847 this->ExtraGenerator->Generate();
850 this->CMakeInstance->UpdateProgress("Generating done", -1);
853 void cmGlobalGenerator::CheckLocalGenerators()
855 std::map<cmStdString, cmStdString> notFoundMap;
856 // std::set<cmStdString> notFoundMap;
857 // after it is all done do a ConfigureFinalPass
858 cmCacheManager* manager = 0;
859 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
861 manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
862 this->LocalGenerators[i]->ConfigureFinalPass();
863 const cmTargets & targets =
864 this->LocalGenerators[i]->GetMakefile()->GetTargets();
865 for (cmTargets::const_iterator l = targets.begin();
866 l != targets.end(); l++)
868 const cmTarget::LinkLibraryVectorType& libs=l->second.GetLinkLibraries();
869 for(cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin();
870 lib != libs.end(); ++lib)
872 if(lib->first.size() > 9 &&
873 cmSystemTools::IsNOTFOUND(lib->first.c_str()))
875 std::string varName = lib->first.substr(0, lib->first.size()-9);
876 cmCacheManager::CacheIterator it =
877 manager->GetCacheIterator(varName.c_str());
878 if(it.GetPropertyAsBool("ADVANCED"))
880 varName += " (ADVANCED)";
882 std::string text = notFoundMap[varName];
883 text += "\n linked by target \"";
884 text += l->second.GetName();
885 text += "\" in directory ";
886 text+=this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
887 notFoundMap[varName] = text;
891 const std::vector<std::string>& incs =
892 this->LocalGenerators[i]->GetMakefile()->GetIncludeDirectories();
894 for( std::vector<std::string>::const_iterator incDir = incs.begin();
895 incDir != incs.end(); ++incDir)
897 if(incDir->size() > 9 &&
898 cmSystemTools::IsNOTFOUND(incDir->c_str()))
900 std::string varName = incDir->substr(0, incDir->size()-9);
901 cmCacheManager::CacheIterator it =
902 manager->GetCacheIterator(varName.c_str());
903 if(it.GetPropertyAsBool("ADVANCED"))
905 varName += " (ADVANCED)";
907 std::string text = notFoundMap[varName];
908 text += "\n used as include directory in directory ";
909 text += this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
910 notFoundMap[varName] = text;
913 this->CMakeInstance->UpdateProgress
914 ("Configuring", 0.9f+0.1f*(i+1.0f)/this->LocalGenerators.size());
915 this->LocalGenerators[i]->GetMakefile()->CheckInfiniteLoops();
918 if(notFoundMap.size())
920 std::string notFoundVars;
921 for(std::map<cmStdString, cmStdString>::const_iterator
922 ii = notFoundMap.begin();
923 ii != notFoundMap.end();
924 ++ii)
926 notFoundVars += ii->first;
927 notFoundVars += ii->second;
928 notFoundVars += "\n";
930 cmSystemTools::Error("The following variables are used in this project, "
931 "but they are set to NOTFOUND.\n"
932 "Please set them or make sure they are set and "
933 "tested correctly in the CMake files:\n",
934 notFoundVars.c_str());
938 int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
939 const char *projectName,
940 const char *target,
941 std::string *output, cmMakefile *mf)
943 // if this is not set, then this is a first time configure
944 // and there is a good chance that the try compile stuff will
945 // take the bulk of the time, so try and guess some progress
946 // by getting closer and closer to 100 without actually getting there.
947 if (!this->CMakeInstance->GetCacheManager()->GetCacheValue
948 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
950 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
951 // we are in the first time progress and we have no
952 // idea how long it will be. So, just move 1/10th of the way
953 // there each time, and don't go over 95%
954 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
955 if(this->FirstTimeProgress > 0.95f)
957 this->FirstTimeProgress = 0.95f;
959 this->CMakeInstance->UpdateProgress("Configuring",
960 this->FirstTimeProgress);
963 std::string makeCommand = this->CMakeInstance->
964 GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
965 if(makeCommand.size() == 0)
967 cmSystemTools::Error(
968 "Generator cannot find the appropriate make command.");
969 return 1;
972 std::string newTarget;
973 if (target && strlen(target))
975 newTarget += target;
976 #if 0
977 #if defined(_WIN32) || defined(__CYGWIN__)
978 std::string tmp = target;
979 // if the target does not already end in . something
980 // then assume .exe
981 if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
983 newTarget += ".exe";
985 #endif // WIN32
986 #endif
988 const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
989 return this->Build(srcdir,bindir,projectName,
990 newTarget.c_str(),
991 output,makeCommand.c_str(),config,false,true,
992 this->TryCompileTimeout);
995 std::string cmGlobalGenerator
996 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
997 const char* additionalOptions, const char *targetName,
998 const char* config, bool ignoreErrors, bool)
1000 // Project name and config are not used yet.
1001 (void)projectName;
1002 (void)config;
1004 std::string makeCommand =
1005 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
1007 // Since we have full control over the invocation of nmake, let us
1008 // make it quiet.
1009 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
1011 makeCommand += " /NOLOGO ";
1013 if ( ignoreErrors )
1015 makeCommand += " -i";
1017 if ( additionalOptions )
1019 makeCommand += " ";
1020 makeCommand += additionalOptions;
1022 if ( targetName )
1024 makeCommand += " ";
1025 makeCommand += targetName;
1027 return makeCommand;
1030 int cmGlobalGenerator::Build(
1031 const char *, const char *bindir,
1032 const char *projectName, const char *target,
1033 std::string *output,
1034 const char *makeCommandCSTR,
1035 const char *config,
1036 bool clean, bool fast,
1037 double timeout)
1040 * Run an executable command and put the stdout in output.
1042 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1043 cmSystemTools::ChangeDirectory(bindir);
1044 if(output)
1046 *output += "Change Dir: ";
1047 *output += bindir;
1048 *output += "\n";
1051 int retVal;
1052 bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
1053 cmSystemTools::SetRunCommandHideConsole(true);
1054 std::string outputBuffer;
1055 std::string* outputPtr = 0;
1056 if(output)
1058 outputPtr = &outputBuffer;
1061 // should we do a clean first?
1062 if (clean)
1064 std::string cleanCommand =
1065 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1066 0, "clean", config, false, fast);
1067 if(output)
1069 *output += "\nRun Clean Command:";
1070 *output += cleanCommand;
1071 *output += "\n";
1074 if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), outputPtr,
1075 &retVal, 0, false, timeout))
1077 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1078 cmSystemTools::Error("Generator: execution of make clean failed.");
1079 if (output)
1081 *output += *outputPtr;
1082 *output += "\nGenerator: execution of make clean failed.\n";
1085 // return to the original directory
1086 cmSystemTools::ChangeDirectory(cwd.c_str());
1087 return 1;
1089 if (output)
1091 *output += *outputPtr;
1095 // now build
1096 std::string makeCommand =
1097 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1098 0, target, config, false, fast);
1099 if(output)
1101 *output += "\nRun Build Command:";
1102 *output += makeCommand;
1103 *output += "\n";
1106 if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), outputPtr,
1107 &retVal, 0, false, timeout))
1109 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1110 cmSystemTools::Error
1111 ("Generator: execution of make failed. Make command was: ",
1112 makeCommand.c_str());
1113 if (output)
1115 *output += *outputPtr;
1116 *output += "\nGenerator: execution of make failed. Make command was: "
1117 + makeCommand + "\n";
1120 // return to the original directory
1121 cmSystemTools::ChangeDirectory(cwd.c_str());
1122 return 1;
1124 if (output)
1126 *output += *outputPtr;
1128 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1130 // The SGI MipsPro 7.3 compiler does not return an error code when
1131 // the source has a #error in it! This is a work-around for such
1132 // compilers.
1133 if((retVal == 0) && (output->find("#error") != std::string::npos))
1135 retVal = 1;
1138 cmSystemTools::ChangeDirectory(cwd.c_str());
1139 return retVal;
1142 void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
1144 this->LocalGenerators.push_back(lg);
1146 // update progress
1147 // estimate how many lg there will be
1148 const char *numGenC =
1149 this->CMakeInstance->GetCacheManager()->GetCacheValue
1150 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
1152 if (!numGenC)
1154 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1155 // we are in the first time progress and we have no
1156 // idea how long it will be. So, just move half way
1157 // there each time, and don't go over 95%
1158 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1159 if(this->FirstTimeProgress > 0.95f)
1161 this->FirstTimeProgress = 0.95f;
1163 this->CMakeInstance->UpdateProgress("Configuring",
1164 this->FirstTimeProgress);
1165 return;
1168 int numGen = atoi(numGenC);
1169 float prog = 0.9f*this->LocalGenerators.size()/numGen;
1170 if (prog > 0.9f)
1172 prog = 0.9f;
1174 this->CMakeInstance->UpdateProgress("Configuring", prog);
1177 void cmGlobalGenerator::AddInstallComponent(const char* component)
1179 if(component && *component)
1181 this->InstallComponents.insert(component);
1185 void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
1186 cmTarget* target,
1187 cmInstallTargetGenerator* archive,
1188 cmInstallTargetGenerator* runTime,
1189 cmInstallTargetGenerator* library,
1190 cmInstallTargetGenerator* framework,
1191 cmInstallTargetGenerator* bundle,
1192 cmInstallFilesGenerator* headers)
1194 if ((exportSetName) && (*exportSetName) && (target))
1196 cmTargetExport* te = new cmTargetExport(target, archive, runTime, library,
1197 framework, bundle, headers);
1198 this->ExportSets[exportSetName].push_back(te);
1202 const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet(
1203 const char* name) const
1205 std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator
1206 exportSetIt = this->ExportSets.find(name);
1207 if (exportSetIt != this->ExportSets.end())
1209 return &exportSetIt->second;
1212 return 0;
1216 void cmGlobalGenerator::EnableInstallTarget()
1218 this->InstallTargetEnabled = true;
1221 cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator()
1223 cmLocalGenerator *lg = new cmLocalGenerator;
1224 lg->SetGlobalGenerator(this);
1225 return lg;
1228 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen )
1230 std::string cfp = gen->GetCMakeInstance()->GetHomeOutputDirectory();
1231 cfp += cmake::GetCMakeFilesDirectory();
1232 this->SetConfiguredFilesPath(cfp.c_str());
1233 const char* make =
1234 gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
1235 this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make,
1236 "make program",
1237 cmCacheManager::FILEPATH);
1238 // copy the enabled languages
1239 this->LanguageEnabled = gen->LanguageEnabled;
1240 this->ExtensionToLanguage = gen->ExtensionToLanguage;
1241 this->IgnoreExtensions = gen->IgnoreExtensions;
1242 this->LanguageToOutputExtension = gen->LanguageToOutputExtension;
1243 this->LanguageToLinkerPreference = gen->LanguageToLinkerPreference;
1244 this->OutputExtensions = gen->OutputExtensions;
1247 //----------------------------------------------------------------------------
1248 void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
1250 entry.Name = this->GetName();
1251 entry.Brief = "";
1252 entry.Full = "";
1255 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1256 cmLocalGenerator* gen)
1258 if(!gen || gen == root)
1260 // No directory excludes itself.
1261 return false;
1264 if(gen->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1266 // This directory is excluded from its parent.
1267 return true;
1270 // This directory is included in its parent. Check whether the
1271 // parent is excluded.
1272 return this->IsExcluded(root, gen->GetParent());
1275 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1276 cmTarget& target)
1278 if(target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1280 // This target is excluded from its directory.
1281 return true;
1283 else
1285 // This target is included in its directory. Check whether the
1286 // directory is excluded.
1287 return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator());
1291 void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
1293 for(std::map<cmStdString, bool>::iterator i =
1294 this->LanguageEnabled.begin(); i != this->LanguageEnabled.end(); ++i)
1296 lang.push_back(i->first);
1300 int cmGlobalGenerator::GetLinkerPreference(const char* lang)
1302 std::map<cmStdString, int>::const_iterator it =
1303 this->LanguageToLinkerPreference.find(lang);
1304 if (it != this->LanguageToLinkerPreference.end())
1306 return it->second;
1308 return 0;
1311 void cmGlobalGenerator::FillProjectMap()
1313 this->ProjectMap.clear(); // make sure we start with a clean map
1314 unsigned int i;
1315 for(i = 0; i < this->LocalGenerators.size(); ++i)
1317 // for each local generator add all projects
1318 cmLocalGenerator *lg = this->LocalGenerators[i];
1319 std::string name;
1322 if (name != lg->GetMakefile()->GetProjectName())
1324 name = lg->GetMakefile()->GetProjectName();
1325 this->ProjectMap[name].push_back(this->LocalGenerators[i]);
1327 lg = lg->GetParent();
1329 while (lg);
1334 // Build a map that contains a the set of targets used by each local
1335 // generator directory level.
1336 void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
1338 this->LocalGeneratorToTargetMap.clear();
1339 // Loop over all targets in all local generators.
1340 for(std::vector<cmLocalGenerator*>::const_iterator
1341 lgi = this->LocalGenerators.begin();
1342 lgi != this->LocalGenerators.end(); ++lgi)
1344 cmLocalGenerator* lg = *lgi;
1345 cmMakefile* mf = lg->GetMakefile();
1346 cmTargets& targets = mf->GetTargets();
1347 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1349 cmTarget& target = t->second;
1351 // Consider the directory containing the target and all its
1352 // parents until something excludes the target.
1353 for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target);
1354 clg = clg->GetParent())
1356 // This local generator includes the target.
1357 std::set<cmTarget*>& targetSet =
1358 this->LocalGeneratorToTargetMap[clg];
1359 targetSet.insert(&target);
1361 // Add dependencies of the included target. An excluded
1362 // target may still be included if it is a dependency of a
1363 // non-excluded target.
1364 TargetDependSet & tgtdeps = this->GetTargetDirectDepends(target);
1365 for(TargetDependSet::const_iterator ti = tgtdeps.begin();
1366 ti != tgtdeps.end(); ++ti)
1368 targetSet.insert(*ti);
1376 ///! Find a local generator by its startdirectory
1377 cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
1379 std::vector<cmLocalGenerator*>* gens = &this->LocalGenerators;
1380 for(unsigned int i = 0; i < gens->size(); ++i)
1382 std::string sd = (*gens)[i]->GetMakefile()->GetStartDirectory();
1383 if (sd == start_dir)
1385 return (*gens)[i];
1388 return 0;
1392 //----------------------------------------------------------------------------
1393 cmTarget*
1394 cmGlobalGenerator::FindTarget(const char* project, const char* name)
1396 // if project specific
1397 if(project)
1399 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
1400 for(unsigned int i = 0; i < gens->size(); ++i)
1402 cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
1403 if(ret)
1405 return ret;
1409 // if all projects/directories
1410 else
1412 std::map<cmStdString,cmTarget *>::iterator i =
1413 this->TotalTargets.find ( name );
1414 if ( i != this->TotalTargets.end() )
1416 return i->second;
1419 return 0;
1422 //----------------------------------------------------------------------------
1423 bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
1425 if(cmSystemTools::IsPathToFramework(libname.c_str()))
1427 return true;
1430 if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
1432 if(tgt->IsFrameworkOnApple())
1434 return true;
1438 return false;
1441 //----------------------------------------------------------------------------
1442 inline std::string removeQuotes(const std::string& s)
1444 if(s[0] == '\"' && s[s.size()-1] == '\"')
1446 return s.substr(1, s.size()-2);
1448 return s;
1451 void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
1453 // Store a pointer to the cmake object instance.
1454 this->CMakeInstance = cm;
1457 void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
1459 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
1460 const char* cmakeCfgIntDir = this->GetCMakeCFGInitDirectory();
1461 const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND");
1463 // CPack
1464 cmCustomCommandLines cpackCommandLines;
1465 std::vector<std::string> depends;
1466 cmCustomCommandLine singleLine;
1467 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1468 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1470 singleLine.push_back("-C");
1471 singleLine.push_back(cmakeCfgIntDir);
1473 singleLine.push_back("--config");
1474 std::string configFile = mf->GetStartOutputDirectory();;
1475 configFile += "/CPackConfig.cmake";
1476 singleLine.push_back(configFile);
1477 cpackCommandLines.push_back(singleLine);
1478 if ( this->GetPreinstallTargetName() )
1480 depends.push_back("preinstall");
1482 else
1484 const char* noPackageAll =
1485 mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
1486 if(!noPackageAll || cmSystemTools::IsOff(noPackageAll))
1488 depends.push_back(this->GetAllTargetName());
1491 if(cmSystemTools::FileExists(configFile.c_str()))
1493 (*targets)[this->GetPackageTargetName()]
1494 = this->CreateGlobalTarget(this->GetPackageTargetName(),
1495 "Run CPack packaging tool...",
1496 &cpackCommandLines, depends);
1498 // CPack source
1499 const char* packageSourceTargetName = this->GetPackageSourceTargetName();
1500 if ( packageSourceTargetName )
1502 cpackCommandLines.erase(cpackCommandLines.begin(),
1503 cpackCommandLines.end());
1504 singleLine.erase(singleLine.begin(), singleLine.end());
1505 depends.erase(depends.begin(), depends.end());
1506 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1507 singleLine.push_back("--config");
1508 configFile = mf->GetStartOutputDirectory();;
1509 configFile += "/CPackSourceConfig.cmake";
1510 if(cmSystemTools::FileExists(configFile.c_str()))
1512 singleLine.push_back(configFile);
1513 cpackCommandLines.push_back(singleLine);
1514 (*targets)[packageSourceTargetName]
1515 = this->CreateGlobalTarget(packageSourceTargetName,
1516 "Run CPack packaging tool for source...",
1517 &cpackCommandLines, depends);
1521 // Test
1522 if(mf->IsOn("CMAKE_TESTING_ENABLED"))
1524 cpackCommandLines.erase(cpackCommandLines.begin(),
1525 cpackCommandLines.end());
1526 singleLine.erase(singleLine.begin(), singleLine.end());
1527 depends.erase(depends.begin(), depends.end());
1528 singleLine.push_back(this->GetCMakeInstance()->GetCTestCommand());
1529 singleLine.push_back("--force-new-ctest-process");
1530 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1532 singleLine.push_back("-C");
1533 singleLine.push_back(cmakeCfgIntDir);
1535 else // TODO: This is a hack. Should be something to do with the generator
1537 singleLine.push_back("$(ARGS)");
1539 cpackCommandLines.push_back(singleLine);
1540 (*targets)[this->GetTestTargetName()]
1541 = this->CreateGlobalTarget(this->GetTestTargetName(),
1542 "Running tests...", &cpackCommandLines, depends);
1545 //Edit Cache
1546 const char* editCacheTargetName = this->GetEditCacheTargetName();
1547 if ( editCacheTargetName )
1549 cpackCommandLines.erase(cpackCommandLines.begin(),
1550 cpackCommandLines.end());
1551 singleLine.erase(singleLine.begin(), singleLine.end());
1552 depends.erase(depends.begin(), depends.end());
1554 // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
1555 // Otherwise default to the interactive command-line interface.
1556 if(mf->GetDefinition("CMAKE_EDIT_COMMAND"))
1558 singleLine.push_back(mf->GetDefinition("CMAKE_EDIT_COMMAND"));
1559 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1560 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1561 cpackCommandLines.push_back(singleLine);
1562 (*targets)[editCacheTargetName] =
1563 this->CreateGlobalTarget(
1564 editCacheTargetName, "Running CMake cache editor...",
1565 &cpackCommandLines, depends);
1567 else
1569 singleLine.push_back(cmakeCommand);
1570 singleLine.push_back("-i");
1571 singleLine.push_back(".");
1572 cpackCommandLines.push_back(singleLine);
1573 (*targets)[editCacheTargetName] =
1574 this->CreateGlobalTarget(
1575 editCacheTargetName,
1576 "Running interactive CMake command-line interface...",
1577 &cpackCommandLines, depends);
1581 //Rebuild Cache
1582 const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
1583 if ( rebuildCacheTargetName )
1585 cpackCommandLines.erase(cpackCommandLines.begin(),
1586 cpackCommandLines.end());
1587 singleLine.erase(singleLine.begin(), singleLine.end());
1588 depends.erase(depends.begin(), depends.end());
1589 singleLine.push_back(cmakeCommand);
1590 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1591 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1592 cpackCommandLines.push_back(singleLine);
1593 (*targets)[rebuildCacheTargetName] =
1594 this->CreateGlobalTarget(
1595 rebuildCacheTargetName, "Running CMake to regenerate build system...",
1596 &cpackCommandLines, depends);
1599 //Install
1600 if(this->InstallTargetEnabled)
1602 if(!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.')
1604 std::set<cmStdString>* componentsSet = &this->InstallComponents;
1605 cpackCommandLines.erase(cpackCommandLines.begin(),
1606 cpackCommandLines.end());
1607 depends.erase(depends.begin(), depends.end());
1608 cmOStringStream ostr;
1609 if ( componentsSet->size() > 0 )
1611 ostr << "Available install components are:";
1612 std::set<cmStdString>::iterator it;
1613 for (
1614 it = componentsSet->begin();
1615 it != componentsSet->end();
1616 ++ it )
1618 ostr << " \"" << it->c_str() << "\"";
1621 else
1623 ostr << "Only default component available";
1625 singleLine.push_back(ostr.str().c_str());
1626 (*targets)["list_install_components"]
1627 = this->CreateGlobalTarget("list_install_components",
1628 ostr.str().c_str(),
1629 &cpackCommandLines, depends);
1631 std::string cmd;
1632 cpackCommandLines.erase(cpackCommandLines.begin(),
1633 cpackCommandLines.end());
1634 singleLine.erase(singleLine.begin(), singleLine.end());
1635 depends.erase(depends.begin(), depends.end());
1636 if ( this->GetPreinstallTargetName() )
1638 depends.push_back(this->GetPreinstallTargetName());
1640 else
1642 const char* noall =
1643 mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
1644 if(!noall || cmSystemTools::IsOff(noall))
1646 depends.push_back(this->GetAllTargetName());
1649 if(mf->GetDefinition("CMake_BINARY_DIR"))
1651 // We are building CMake itself. We cannot use the original
1652 // executable to install over itself.
1653 cmd = mf->GetDefinition("EXECUTABLE_OUTPUT_PATH");
1654 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1656 cmd += "/";
1657 cmd += cmakeCfgIntDir;
1659 cmd += "/cmake";
1661 else
1663 cmd = cmakeCommand;
1665 singleLine.push_back(cmd.c_str());
1666 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1668 std::string cfgArg = "-DBUILD_TYPE=";
1669 cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR");
1670 singleLine.push_back(cfgArg);
1672 singleLine.push_back("-P");
1673 singleLine.push_back("cmake_install.cmake");
1674 cpackCommandLines.push_back(singleLine);
1675 (*targets)[this->GetInstallTargetName()] =
1676 this->CreateGlobalTarget(
1677 this->GetInstallTargetName(), "Install the project...",
1678 &cpackCommandLines, depends);
1680 // install_local
1681 if(const char* install_local = this->GetInstallLocalTargetName())
1683 cmCustomCommandLine localCmdLine = singleLine;
1685 localCmdLine.insert(localCmdLine.begin()+1,
1686 "-DCMAKE_INSTALL_LOCAL_ONLY=1");
1687 cpackCommandLines.erase(cpackCommandLines.begin(),
1688 cpackCommandLines.end());
1689 cpackCommandLines.push_back(localCmdLine);
1691 (*targets)[install_local] =
1692 this->CreateGlobalTarget(
1693 install_local, "Installing only the local directory...",
1694 &cpackCommandLines, depends);
1697 // install_strip
1698 const char* install_strip = this->GetInstallStripTargetName();
1699 if((install_strip !=0) && (mf->IsSet("CMAKE_STRIP")))
1701 cmCustomCommandLine stripCmdLine = singleLine;
1703 stripCmdLine.insert(stripCmdLine.begin()+1,"-DCMAKE_INSTALL_DO_STRIP=1");
1704 cpackCommandLines.erase(cpackCommandLines.begin(),
1705 cpackCommandLines.end());
1706 cpackCommandLines.push_back(stripCmdLine);
1708 (*targets)[install_strip] =
1709 this->CreateGlobalTarget(
1710 install_strip, "Installing the project stripped...",
1711 &cpackCommandLines, depends);
1716 cmTarget cmGlobalGenerator::CreateGlobalTarget(
1717 const char* name, const char* message,
1718 const cmCustomCommandLines* commandLines,
1719 std::vector<std::string> depends,
1720 bool depends_on_all /* = false */)
1722 // Package
1723 cmTarget target;
1724 target.GetProperties().SetCMakeInstance(this->CMakeInstance);
1725 target.SetType(cmTarget::GLOBAL_TARGET, name);
1726 target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
1728 std::vector<std::string> no_outputs;
1729 std::vector<std::string> no_depends;
1730 // Store the custom command in the target.
1731 cmCustomCommand cc(no_outputs, no_depends, *commandLines, 0, 0);
1732 target.GetPostBuildCommands().push_back(cc);
1733 target.SetProperty("EchoString", message);
1734 if ( depends_on_all )
1736 target.AddUtility("all");
1738 std::vector<std::string>::iterator dit;
1739 for ( dit = depends.begin(); dit != depends.end(); ++ dit )
1741 target.AddUtility(dit->c_str());
1743 return target;
1746 //----------------------------------------------------------------------------
1747 void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
1748 const char*, std::string&)
1750 // Subclasses that support multiple configurations should implement
1751 // this method to append the subdirectory for the given build
1752 // configuration.
1755 //----------------------------------------------------------------------------
1756 cmGlobalGenerator::TargetDependSet &
1757 cmGlobalGenerator::GetTargetDirectDepends(cmTarget & target)
1759 return this->TargetDependencies[&target];
1762 void cmGlobalGenerator::AddTarget(cmTargets::value_type &v)
1764 assert(!v.second.IsImported());
1765 this->TotalTargets[v.first] = &v.second;
1768 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
1769 cmExternalMakefileProjectGenerator *extraGenerator)
1771 this->ExtraGenerator = extraGenerator;
1772 if (this->ExtraGenerator!=0)
1774 this->ExtraGenerator->SetGlobalGenerator(this);
1778 const char* cmGlobalGenerator::GetExtraGeneratorName() const
1780 return this->ExtraGenerator==0 ? 0 : this->ExtraGenerator->GetName();
1783 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
1785 this->FilesReplacedDuringGenerate.push_back(filename);
1788 void
1789 cmGlobalGenerator
1790 ::GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames)
1792 filenames.clear();
1793 std::copy(
1794 this->FilesReplacedDuringGenerate.begin(),
1795 this->FilesReplacedDuringGenerate.end(),
1796 std::back_inserter(filenames));
1799 void
1800 cmGlobalGenerator
1801 ::GetTargetSets(cmGlobalGenerator::TargetDependSet& projectTargets,
1802 cmGlobalGenerator::TargetDependSet& originalTargets,
1803 cmLocalGenerator* root,
1804 std::vector<cmLocalGenerator*> const& generators)
1806 // loop over all local generators
1807 for(std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
1808 i != generators.end(); ++i)
1810 // check to make sure generator is not excluded
1811 if(this->IsExcluded(root, *i))
1813 continue;
1815 cmMakefile* mf = (*i)->GetMakefile();
1816 // Get the targets in the makefile
1817 cmTargets &tgts = mf->GetTargets();
1818 // loop over all the targets
1819 for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
1821 cmTarget* target = &l->second;
1822 // put the target in the set of original targets
1823 originalTargets.insert(target);
1824 // Get the set of targets that depend on target
1825 this->AddTargetDepends(target,
1826 projectTargets);
1831 void
1832 cmGlobalGenerator::AddTargetDepends(cmTarget* target,
1833 cmGlobalGenerator::TargetDependSet&
1834 projectTargets)
1836 // add the target itself
1837 projectTargets.insert(target);
1838 // get the direct depends of target
1839 cmGlobalGenerator::TargetDependSet const& tset
1840 = this->GetTargetDirectDepends(*target);
1841 if(tset.size())
1843 // if there are targets that depend on target
1844 // add them and their depends as well
1845 for(cmGlobalGenerator::TargetDependSet::const_iterator i =
1846 tset.begin(); i != tset.end(); ++i)
1848 cmTarget* dtarget = *i;
1849 this->AddTargetDepends(dtarget, projectTargets);
1855 //----------------------------------------------------------------------------
1856 void cmGlobalGenerator::AddToManifest(const char* config,
1857 std::string const& f)
1859 // Add to the main manifest for this configuration.
1860 this->TargetManifest[config].insert(f);
1862 // Add to the content listing for the file's directory.
1863 std::string dir = cmSystemTools::GetFilenamePath(f);
1864 std::string file = cmSystemTools::GetFilenameName(f);
1865 this->DirectoryContentMap[dir].insert(file);
1868 //----------------------------------------------------------------------------
1869 std::set<cmStdString> const&
1870 cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
1872 DirectoryContent& dc = this->DirectoryContentMap[dir];
1873 if(needDisk && !dc.LoadedFromDisk)
1875 // Load the directory content from disk.
1876 cmsys::Directory d;
1877 if(d.Load(dir.c_str()))
1879 unsigned long n = d.GetNumberOfFiles();
1880 for(unsigned long i = 0; i < n; ++i)
1882 const char* f = d.GetFile(i);
1883 if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
1885 dc.insert(f);
1889 dc.LoadedFromDisk = true;
1891 return dc;