Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmGlobalGenerator.cxx
blob50abaef9adcff1aa9417e08bc262bdd53aaa3295
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008/02/14 21:42:29 $
7 Version: $Revision: 1.226 $
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 const char* versionValue
468 = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
469 if (atof(versionValue) <= 1.4)
471 if(strcmp(lang, "C") == 0)
473 ifpath =
474 mf->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
475 mf->ReadListFile(0,ifpath.c_str());
477 if(strcmp(lang, "CXX") == 0)
479 ifpath =
480 mf->GetModulesFile("CMakeBackwardCompatibilityCXX.cmake");
481 mf->ReadListFile(0,ifpath.c_str());
485 } // end if in try compile
486 } // end need test language
487 } // end for each language
489 // Now load files that can override any settings on the platform or for
490 // the project First load the project compatibility file if it is in
491 // cmake
492 std::string projectCompatibility = mf->GetDefinition("CMAKE_ROOT");
493 projectCompatibility += "/Modules/";
494 projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
495 projectCompatibility += "Compatibility.cmake";
496 if(cmSystemTools::FileExists(projectCompatibility.c_str()))
498 mf->ReadListFile(0,projectCompatibility.c_str());
502 //----------------------------------------------------------------------------
503 const char*
504 cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source)
506 if(const char* lang = source.GetLanguage())
508 if(this->LanguageToOutputExtension.count(lang) > 0)
510 return this->LanguageToOutputExtension[lang].c_str();
513 else
515 // if no language is found then check to see if it is already an
516 // ouput extension for some language. In that case it should be ignored
517 // and in this map, so it will not be compiled but will just be used.
518 std::string const& ext = source.GetExtension();
519 if(!ext.empty())
521 if(this->OutputExtensions.count(ext))
523 return ext.c_str();
527 return "";
531 const char* cmGlobalGenerator::GetLanguageFromExtension(const char* ext)
533 // if there is an extension and it starts with . then move past the
534 // . because the extensions are not stored with a . in the map
535 if(ext && *ext == '.')
537 ++ext;
539 if(this->ExtensionToLanguage.count(ext) > 0)
541 return this->ExtensionToLanguage[ext].c_str();
543 return 0;
546 /* SetLanguageEnabled() is now split in two parts:
547 at first the enabled-flag is set. This can then be used in EnabledLanguage()
548 for checking whether the language is already enabled. After setting this
549 flag still the values from the cmake variables have to be copied into the
550 internal maps, this is done in SetLanguageEnabledMaps() which is called
551 after the system- and compiler specific files have been loaded.
553 void cmGlobalGenerator::SetLanguageEnabled(const char* l, cmMakefile* mf)
555 this->SetLanguageEnabledFlag(l, mf);
556 this->SetLanguageEnabledMaps(l, mf);
559 void cmGlobalGenerator::SetLanguageEnabledFlag(const char* l, cmMakefile*)
561 this->LanguageEnabled[l] = true;
564 void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
566 // use LanguageToLinkerPreference to detect whether this functions has
567 // run before
568 if (this->LanguageToLinkerPreference.find(l) !=
569 this->LanguageToLinkerPreference.end())
571 return;
574 std::string linkerPrefVar = std::string("CMAKE_") +
575 std::string(l) + std::string("_LINKER_PREFERENCE");
576 const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
577 int preference = 0;
578 if(linkerPref)
580 if (sscanf(linkerPref, "%d", &preference)!=1)
582 // backward compatibility: before 2.6 LINKER_PREFERENCE
583 // was either "None" or "Prefered", and only the first character was
584 // tested. So if there is a custom language out there and it is
585 // "Prefered", set its preference high
586 if (linkerPref[0]=='P')
588 preference = 100;
590 else
592 preference = 0;
597 if (preference < 0)
599 std::string msg = linkerPrefVar;
600 msg += " is negative, adjusting it to 0";
601 cmSystemTools::Message(msg.c_str(), "Warning");
602 preference = 0;
605 this->LanguageToLinkerPreference[l] = preference;
607 std::string outputExtensionVar = std::string("CMAKE_") +
608 std::string(l) + std::string("_OUTPUT_EXTENSION");
609 const char* outputExtension = mf->GetDefinition(outputExtensionVar.c_str());
610 if(outputExtension)
612 this->LanguageToOutputExtension[l] = outputExtension;
613 this->OutputExtensions[outputExtension] = outputExtension;
614 if(outputExtension[0] == '.')
616 this->OutputExtensions[outputExtension+1] = outputExtension+1;
620 std::string extensionsVar = std::string("CMAKE_") +
621 std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS");
622 std::string ignoreExtensionsVar = std::string("CMAKE_") +
623 std::string(l) + std::string("_IGNORE_EXTENSIONS");
624 std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar.c_str());
625 std::string exts = mf->GetSafeDefinition(extensionsVar.c_str());
626 std::vector<std::string> extensionList;
627 cmSystemTools::ExpandListArgument(exts, extensionList);
628 for(std::vector<std::string>::iterator i = extensionList.begin();
629 i != extensionList.end(); ++i)
631 this->ExtensionToLanguage[*i] = l;
633 cmSystemTools::ExpandListArgument(ignoreExts, extensionList);
634 for(std::vector<std::string>::iterator i = extensionList.begin();
635 i != extensionList.end(); ++i)
637 this->IgnoreExtensions[*i] = true;
642 bool cmGlobalGenerator::IgnoreFile(const char* l)
644 if(this->GetLanguageFromExtension(l))
646 return false;
648 return (this->IgnoreExtensions.count(l) > 0);
651 bool cmGlobalGenerator::GetLanguageEnabled(const char* l) const
653 return (this->LanguageEnabled.find(l)!= this->LanguageEnabled.end());
656 void cmGlobalGenerator::ClearEnabledLanguages()
658 this->LanguageEnabled.clear();
661 bool cmGlobalGenerator::IsDependedOn(const char* project,
662 cmTarget* targetIn)
664 // Get all local gens for this project
665 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
666 // loop over local gens and get the targets for each one
667 for(unsigned int i = 0; i < gens->size(); ++i)
669 cmTargets& targets = (*gens)[i]->GetMakefile()->GetTargets();
670 for (cmTargets::iterator l = targets.begin();
671 l != targets.end(); l++)
673 cmTarget& target = l->second;
674 std::set<cmStdString>::const_iterator pos =
675 target.GetUtilities().find(targetIn->GetName());
676 if(pos != target.GetUtilities().end())
678 return true;
682 return false;
685 void cmGlobalGenerator::Configure()
687 this->FirstTimeProgress = 0.0f;
688 // Delete any existing cmLocalGenerators
689 unsigned int i;
690 for (i = 0; i < this->LocalGenerators.size(); ++i)
692 delete this->LocalGenerators[i];
694 this->LocalGenerators.clear();
695 this->TargetDependencies.clear();
696 this->TotalTargets.clear();
697 this->LocalGeneratorToTargetMap.clear();
698 this->ProjectMap.clear();
700 // start with this directory
701 cmLocalGenerator *lg = this->CreateLocalGenerator();
702 this->LocalGenerators.push_back(lg);
704 // set the Start directories
705 lg->GetMakefile()->SetStartDirectory
706 (this->CMakeInstance->GetStartDirectory());
707 lg->GetMakefile()->SetStartOutputDirectory
708 (this->CMakeInstance->GetStartOutputDirectory());
709 lg->GetMakefile()->MakeStartDirectoriesCurrent();
711 // now do it
712 lg->Configure();
714 // update the cache entry for the number of local generators, this is used
715 // for progress
716 char num[100];
717 sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size()));
718 this->GetCMakeInstance()->AddCacheEntry
719 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
720 "number of local generators", cmCacheManager::INTERNAL);
722 // check for link libraries and include directories containing "NOTFOUND"
723 // and for infinite loops
724 this->CheckLocalGenerators();
726 // at this point this->LocalGenerators has been filled,
727 // so create the map from project name to vector of local generators
728 this->FillProjectMap();
730 if ( !this->CMakeInstance->GetScriptMode() )
732 this->CMakeInstance->UpdateProgress("Configuring done", -1);
736 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
738 // If the property is not enabled then okay.
739 if(!this->CMakeInstance
740 ->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
742 return true;
745 // This generator does not support duplicate custom targets.
746 cmOStringStream e;
747 e << "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
748 << "global property. "
749 << "The \"" << this->GetName() << "\" generator does not support "
750 << "duplicate custom targets. "
751 << "Consider using a Makefiles generator or fix the project to not "
752 << "use duplicat target names.";
753 cmSystemTools::Error(e.str().c_str());
754 return false;
757 void cmGlobalGenerator::Generate()
759 // Some generators track files replaced during the Generate.
760 // Start with an empty vector:
761 this->FilesReplacedDuringGenerate.clear();
763 // Check whether this generator is allowed to run.
764 if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
766 return;
769 // For each existing cmLocalGenerator
770 unsigned int i;
772 // Consolidate global targets
773 cmTargets globalTargets;
774 this->CreateDefaultGlobalTargets(&globalTargets);
775 for (i = 0; i < this->LocalGenerators.size(); ++i)
777 cmTargets* targets =
778 &(this->LocalGenerators[i]->GetMakefile()->GetTargets());
779 cmTargets::iterator tarIt;
780 for ( tarIt = targets->begin(); tarIt != targets->end(); ++ tarIt )
782 if ( tarIt->second.GetType() == cmTarget::GLOBAL_TARGET )
784 globalTargets[tarIt->first] = tarIt->second;
788 for (i = 0; i < this->LocalGenerators.size(); ++i)
790 cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
791 cmTargets* targets = &(mf->GetTargets());
792 cmTargets::iterator tit;
793 for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit )
795 (*targets)[tit->first] = tit->second;
796 (*targets)[tit->first].SetMakefile(mf);
800 // Add generator specific helper commands
801 for (i = 0; i < this->LocalGenerators.size(); ++i)
803 this->LocalGenerators[i]->AddHelperCommands();
806 // Trace the dependencies, after that no custom commands should be added
807 // because their dependencies might not be handled correctly
808 for (i = 0; i < this->LocalGenerators.size(); ++i)
810 this->LocalGenerators[i]->TraceDependencies();
813 // Compute the manifest of main targets generated.
814 for (i = 0; i < this->LocalGenerators.size(); ++i)
816 this->LocalGenerators[i]->GenerateTargetManifest();
819 // Compute the inter-target dependencies.
821 cmComputeTargetDepends ctd(this);
822 ctd.Compute();
823 std::vector<cmTarget*> const& targets = ctd.GetTargets();
824 for(std::vector<cmTarget*>::const_iterator ti = targets.begin();
825 ti != targets.end(); ++ti)
827 ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]);
831 // Create a map from local generator to the complete set of targets
832 // it builds by default.
833 this->FillLocalGeneratorToTargetMap();
835 // Generate project files
836 for (i = 0; i < this->LocalGenerators.size(); ++i)
838 this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
839 this->LocalGenerators[i]->Generate();
840 this->LocalGenerators[i]->GenerateInstallRules();
841 this->LocalGenerators[i]->GenerateTestFiles();
842 this->CMakeInstance->UpdateProgress("Generating",
843 (i+1.0f)/this->LocalGenerators.size());
845 this->SetCurrentLocalGenerator(0);
847 if (this->ExtraGenerator != 0)
849 this->ExtraGenerator->Generate();
852 this->CMakeInstance->UpdateProgress("Generating done", -1);
855 void cmGlobalGenerator::CheckLocalGenerators()
857 std::map<cmStdString, cmStdString> notFoundMap;
858 // std::set<cmStdString> notFoundMap;
859 // after it is all done do a ConfigureFinalPass
860 cmCacheManager* manager = 0;
861 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
863 manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
864 this->LocalGenerators[i]->ConfigureFinalPass();
865 const cmTargets & targets =
866 this->LocalGenerators[i]->GetMakefile()->GetTargets();
867 for (cmTargets::const_iterator l = targets.begin();
868 l != targets.end(); l++)
870 const cmTarget::LinkLibraryVectorType& libs=l->second.GetLinkLibraries();
871 for(cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin();
872 lib != libs.end(); ++lib)
874 if(lib->first.size() > 9 &&
875 cmSystemTools::IsNOTFOUND(lib->first.c_str()))
877 std::string varName = lib->first.substr(0, lib->first.size()-9);
878 cmCacheManager::CacheIterator it =
879 manager->GetCacheIterator(varName.c_str());
880 if(it.GetPropertyAsBool("ADVANCED"))
882 varName += " (ADVANCED)";
884 std::string text = notFoundMap[varName];
885 text += "\n linked by target \"";
886 text += l->second.GetName();
887 text += "\" in directory ";
888 text+=this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
889 notFoundMap[varName] = text;
893 const std::vector<std::string>& incs =
894 this->LocalGenerators[i]->GetMakefile()->GetIncludeDirectories();
896 for( std::vector<std::string>::const_iterator incDir = incs.begin();
897 incDir != incs.end(); ++incDir)
899 if(incDir->size() > 9 &&
900 cmSystemTools::IsNOTFOUND(incDir->c_str()))
902 std::string varName = incDir->substr(0, incDir->size()-9);
903 cmCacheManager::CacheIterator it =
904 manager->GetCacheIterator(varName.c_str());
905 if(it.GetPropertyAsBool("ADVANCED"))
907 varName += " (ADVANCED)";
909 std::string text = notFoundMap[varName];
910 text += "\n used as include directory in directory ";
911 text += this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
912 notFoundMap[varName] = text;
915 this->CMakeInstance->UpdateProgress
916 ("Configuring", 0.9f+0.1f*(i+1.0f)/this->LocalGenerators.size());
917 this->LocalGenerators[i]->GetMakefile()->CheckInfiniteLoops();
920 if(notFoundMap.size())
922 std::string notFoundVars;
923 for(std::map<cmStdString, cmStdString>::const_iterator
924 ii = notFoundMap.begin();
925 ii != notFoundMap.end();
926 ++ii)
928 notFoundVars += ii->first;
929 notFoundVars += ii->second;
930 notFoundVars += "\n";
932 cmSystemTools::Error("The following variables are used in this project, "
933 "but they are set to NOTFOUND.\n"
934 "Please set them or make sure they are set and "
935 "tested correctly in the CMake files:\n",
936 notFoundVars.c_str());
940 int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
941 const char *projectName,
942 const char *target,
943 std::string *output, cmMakefile *mf)
945 // if this is not set, then this is a first time configure
946 // and there is a good chance that the try compile stuff will
947 // take the bulk of the time, so try and guess some progress
948 // by getting closer and closer to 100 without actually getting there.
949 if (!this->CMakeInstance->GetCacheManager()->GetCacheValue
950 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
952 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
953 // we are in the first time progress and we have no
954 // idea how long it will be. So, just move 1/10th of the way
955 // there each time, and don't go over 95%
956 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
957 if(this->FirstTimeProgress > 0.95f)
959 this->FirstTimeProgress = 0.95f;
961 this->CMakeInstance->UpdateProgress("Configuring",
962 this->FirstTimeProgress);
965 std::string makeCommand = this->CMakeInstance->
966 GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
967 if(makeCommand.size() == 0)
969 cmSystemTools::Error(
970 "Generator cannot find the appropriate make command.");
971 return 1;
974 std::string newTarget;
975 if (target && strlen(target))
977 newTarget += target;
978 #if 0
979 #if defined(_WIN32) || defined(__CYGWIN__)
980 std::string tmp = target;
981 // if the target does not already end in . something
982 // then assume .exe
983 if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
985 newTarget += ".exe";
987 #endif // WIN32
988 #endif
990 const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
991 return this->Build(srcdir,bindir,projectName,
992 newTarget.c_str(),
993 output,makeCommand.c_str(),config,false,true,
994 this->TryCompileTimeout);
997 std::string cmGlobalGenerator
998 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
999 const char* additionalOptions, const char *targetName,
1000 const char* config, bool ignoreErrors, bool)
1002 // Project name and config are not used yet.
1003 (void)projectName;
1004 (void)config;
1006 std::string makeCommand =
1007 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
1009 // Since we have full control over the invocation of nmake, let us
1010 // make it quiet.
1011 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
1013 makeCommand += " /NOLOGO ";
1015 if ( ignoreErrors )
1017 makeCommand += " -i";
1019 if ( additionalOptions )
1021 makeCommand += " ";
1022 makeCommand += additionalOptions;
1024 if ( targetName )
1026 makeCommand += " ";
1027 makeCommand += targetName;
1029 return makeCommand;
1032 int cmGlobalGenerator::Build(
1033 const char *, const char *bindir,
1034 const char *projectName, const char *target,
1035 std::string *output,
1036 const char *makeCommandCSTR,
1037 const char *config,
1038 bool clean, bool fast,
1039 double timeout)
1042 * Run an executable command and put the stdout in output.
1044 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1045 cmSystemTools::ChangeDirectory(bindir);
1046 if(output)
1048 *output += "Change Dir: ";
1049 *output += bindir;
1050 *output += "\n";
1053 int retVal;
1054 bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
1055 cmSystemTools::SetRunCommandHideConsole(true);
1056 std::string outputBuffer;
1057 std::string* outputPtr = 0;
1058 if(output)
1060 outputPtr = &outputBuffer;
1063 // should we do a clean first?
1064 if (clean)
1066 std::string cleanCommand =
1067 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1068 0, "clean", config, false, fast);
1069 if(output)
1071 *output += "\nRun Clean Command:";
1072 *output += cleanCommand;
1073 *output += "\n";
1076 if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), outputPtr,
1077 &retVal, 0, false, timeout))
1079 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1080 cmSystemTools::Error("Generator: execution of make clean failed.");
1081 if (output)
1083 *output += *outputPtr;
1084 *output += "\nGenerator: execution of make clean failed.\n";
1087 // return to the original directory
1088 cmSystemTools::ChangeDirectory(cwd.c_str());
1089 return 1;
1091 if (output)
1093 *output += *outputPtr;
1097 // now build
1098 std::string makeCommand =
1099 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1100 0, target, config, false, fast);
1101 if(output)
1103 *output += "\nRun Build Command:";
1104 *output += makeCommand;
1105 *output += "\n";
1108 if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), outputPtr,
1109 &retVal, 0, false, timeout))
1111 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1112 cmSystemTools::Error
1113 ("Generator: execution of make failed. Make command was: ",
1114 makeCommand.c_str());
1115 if (output)
1117 *output += *outputPtr;
1118 *output += "\nGenerator: execution of make failed. Make command was: "
1119 + makeCommand + "\n";
1122 // return to the original directory
1123 cmSystemTools::ChangeDirectory(cwd.c_str());
1124 return 1;
1126 if (output)
1128 *output += *outputPtr;
1130 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1132 // The SGI MipsPro 7.3 compiler does not return an error code when
1133 // the source has a #error in it! This is a work-around for such
1134 // compilers.
1135 if((retVal == 0) && (output->find("#error") != std::string::npos))
1137 retVal = 1;
1140 cmSystemTools::ChangeDirectory(cwd.c_str());
1141 return retVal;
1144 void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
1146 this->LocalGenerators.push_back(lg);
1148 // update progress
1149 // estimate how many lg there will be
1150 const char *numGenC =
1151 this->CMakeInstance->GetCacheManager()->GetCacheValue
1152 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
1154 if (!numGenC)
1156 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1157 // we are in the first time progress and we have no
1158 // idea how long it will be. So, just move half way
1159 // there each time, and don't go over 95%
1160 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1161 if(this->FirstTimeProgress > 0.95f)
1163 this->FirstTimeProgress = 0.95f;
1165 this->CMakeInstance->UpdateProgress("Configuring",
1166 this->FirstTimeProgress);
1167 return;
1170 int numGen = atoi(numGenC);
1171 float prog = 0.9f*this->LocalGenerators.size()/numGen;
1172 if (prog > 0.9f)
1174 prog = 0.9f;
1176 this->CMakeInstance->UpdateProgress("Configuring", prog);
1179 void cmGlobalGenerator::AddInstallComponent(const char* component)
1181 if(component && *component)
1183 this->InstallComponents.insert(component);
1187 void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
1188 cmTarget* target,
1189 cmInstallTargetGenerator* archive,
1190 cmInstallTargetGenerator* runTime,
1191 cmInstallTargetGenerator* library,
1192 cmInstallTargetGenerator* framework,
1193 cmInstallTargetGenerator* bundle,
1194 cmInstallFilesGenerator* headers)
1196 if ((exportSetName) && (*exportSetName) && (target))
1198 cmTargetExport* te = new cmTargetExport(target, archive, runTime, library,
1199 framework, bundle, headers);
1200 this->ExportSets[exportSetName].push_back(te);
1204 const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet(
1205 const char* name) const
1207 std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator
1208 exportSetIt = this->ExportSets.find(name);
1209 if (exportSetIt != this->ExportSets.end())
1211 return &exportSetIt->second;
1214 return 0;
1218 void cmGlobalGenerator::EnableInstallTarget()
1220 this->InstallTargetEnabled = true;
1223 cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator()
1225 cmLocalGenerator *lg = new cmLocalGenerator;
1226 lg->SetGlobalGenerator(this);
1227 return lg;
1230 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen )
1232 std::string cfp = gen->GetCMakeInstance()->GetHomeOutputDirectory();
1233 cfp += cmake::GetCMakeFilesDirectory();
1234 this->SetConfiguredFilesPath(cfp.c_str());
1235 const char* make =
1236 gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
1237 this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make,
1238 "make program",
1239 cmCacheManager::FILEPATH);
1240 // copy the enabled languages
1241 this->LanguageEnabled = gen->LanguageEnabled;
1242 this->ExtensionToLanguage = gen->ExtensionToLanguage;
1243 this->IgnoreExtensions = gen->IgnoreExtensions;
1244 this->LanguageToOutputExtension = gen->LanguageToOutputExtension;
1245 this->LanguageToLinkerPreference = gen->LanguageToLinkerPreference;
1246 this->OutputExtensions = gen->OutputExtensions;
1249 //----------------------------------------------------------------------------
1250 void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
1252 entry.Name = this->GetName();
1253 entry.Brief = "";
1254 entry.Full = "";
1257 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1258 cmLocalGenerator* gen)
1260 if(!gen || gen == root)
1262 // No directory excludes itself.
1263 return false;
1266 if(gen->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1268 // This directory is excluded from its parent.
1269 return true;
1272 // This directory is included in its parent. Check whether the
1273 // parent is excluded.
1274 return this->IsExcluded(root, gen->GetParent());
1277 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1278 cmTarget& target)
1280 if(target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1282 // This target is excluded from its directory.
1283 return true;
1285 else
1287 // This target is included in its directory. Check whether the
1288 // directory is excluded.
1289 return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator());
1293 void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
1295 for(std::map<cmStdString, bool>::iterator i =
1296 this->LanguageEnabled.begin(); i != this->LanguageEnabled.end(); ++i)
1298 lang.push_back(i->first);
1302 int cmGlobalGenerator::GetLinkerPreference(const char* lang)
1304 std::map<cmStdString, int>::const_iterator it =
1305 this->LanguageToLinkerPreference.find(lang);
1306 if (it != this->LanguageToLinkerPreference.end())
1308 return it->second;
1310 return 0;
1313 void cmGlobalGenerator::FillProjectMap()
1315 this->ProjectMap.clear(); // make sure we start with a clean map
1316 unsigned int i;
1317 for(i = 0; i < this->LocalGenerators.size(); ++i)
1319 // for each local generator add all projects
1320 cmLocalGenerator *lg = this->LocalGenerators[i];
1321 std::string name;
1324 if (name != lg->GetMakefile()->GetProjectName())
1326 name = lg->GetMakefile()->GetProjectName();
1327 this->ProjectMap[name].push_back(this->LocalGenerators[i]);
1329 lg = lg->GetParent();
1331 while (lg);
1336 // Build a map that contains a the set of targets used by each local
1337 // generator directory level.
1338 void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
1340 this->LocalGeneratorToTargetMap.clear();
1341 // Loop over all targets in all local generators.
1342 for(std::vector<cmLocalGenerator*>::const_iterator
1343 lgi = this->LocalGenerators.begin();
1344 lgi != this->LocalGenerators.end(); ++lgi)
1346 cmLocalGenerator* lg = *lgi;
1347 cmMakefile* mf = lg->GetMakefile();
1348 cmTargets& targets = mf->GetTargets();
1349 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1351 cmTarget& target = t->second;
1353 // Consider the directory containing the target and all its
1354 // parents until something excludes the target.
1355 for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target);
1356 clg = clg->GetParent())
1358 // This local generator includes the target.
1359 std::set<cmTarget*>& targetSet =
1360 this->LocalGeneratorToTargetMap[clg];
1361 targetSet.insert(&target);
1363 // Add dependencies of the included target. An excluded
1364 // target may still be included if it is a dependency of a
1365 // non-excluded target.
1366 TargetDependSet & tgtdeps = this->GetTargetDirectDepends(target);
1367 for(TargetDependSet::const_iterator ti = tgtdeps.begin();
1368 ti != tgtdeps.end(); ++ti)
1370 targetSet.insert(*ti);
1378 ///! Find a local generator by its startdirectory
1379 cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
1381 std::vector<cmLocalGenerator*>* gens = &this->LocalGenerators;
1382 for(unsigned int i = 0; i < gens->size(); ++i)
1384 std::string sd = (*gens)[i]->GetMakefile()->GetStartDirectory();
1385 if (sd == start_dir)
1387 return (*gens)[i];
1390 return 0;
1394 //----------------------------------------------------------------------------
1395 cmTarget*
1396 cmGlobalGenerator::FindTarget(const char* project, const char* name)
1398 // if project specific
1399 if(project)
1401 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
1402 for(unsigned int i = 0; i < gens->size(); ++i)
1404 cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
1405 if(ret)
1407 return ret;
1411 // if all projects/directories
1412 else
1414 std::map<cmStdString,cmTarget *>::iterator i =
1415 this->TotalTargets.find ( name );
1416 if ( i != this->TotalTargets.end() )
1418 return i->second;
1421 return 0;
1424 //----------------------------------------------------------------------------
1425 bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
1427 if(cmSystemTools::IsPathToFramework(libname.c_str()))
1429 return true;
1432 if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
1434 if(tgt->IsFrameworkOnApple())
1436 return true;
1440 return false;
1443 //----------------------------------------------------------------------------
1444 inline std::string removeQuotes(const std::string& s)
1446 if(s[0] == '\"' && s[s.size()-1] == '\"')
1448 return s.substr(1, s.size()-2);
1450 return s;
1453 void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
1455 // Store a pointer to the cmake object instance.
1456 this->CMakeInstance = cm;
1459 void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
1461 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
1462 const char* cmakeCfgIntDir = this->GetCMakeCFGInitDirectory();
1463 const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND");
1465 // CPack
1466 cmCustomCommandLines cpackCommandLines;
1467 std::vector<std::string> depends;
1468 cmCustomCommandLine singleLine;
1469 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1470 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1472 singleLine.push_back("-C");
1473 singleLine.push_back(cmakeCfgIntDir);
1475 singleLine.push_back("--config");
1476 std::string configFile = mf->GetStartOutputDirectory();;
1477 configFile += "/CPackConfig.cmake";
1478 singleLine.push_back(configFile);
1479 cpackCommandLines.push_back(singleLine);
1480 if ( this->GetPreinstallTargetName() )
1482 depends.push_back("preinstall");
1484 else
1486 const char* noPackageAll =
1487 mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
1488 if(!noPackageAll || cmSystemTools::IsOff(noPackageAll))
1490 depends.push_back(this->GetAllTargetName());
1493 if(cmSystemTools::FileExists(configFile.c_str()))
1495 (*targets)[this->GetPackageTargetName()]
1496 = this->CreateGlobalTarget(this->GetPackageTargetName(),
1497 "Run CPack packaging tool...",
1498 &cpackCommandLines, depends);
1500 // CPack source
1501 const char* packageSourceTargetName = this->GetPackageSourceTargetName();
1502 if ( packageSourceTargetName )
1504 cpackCommandLines.erase(cpackCommandLines.begin(),
1505 cpackCommandLines.end());
1506 singleLine.erase(singleLine.begin(), singleLine.end());
1507 depends.erase(depends.begin(), depends.end());
1508 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1509 singleLine.push_back("--config");
1510 configFile = mf->GetStartOutputDirectory();;
1511 configFile += "/CPackSourceConfig.cmake";
1512 if(cmSystemTools::FileExists(configFile.c_str()))
1514 singleLine.push_back(configFile);
1515 cpackCommandLines.push_back(singleLine);
1516 (*targets)[packageSourceTargetName]
1517 = this->CreateGlobalTarget(packageSourceTargetName,
1518 "Run CPack packaging tool for source...",
1519 &cpackCommandLines, depends);
1523 // Test
1524 if(mf->IsOn("CMAKE_TESTING_ENABLED"))
1526 cpackCommandLines.erase(cpackCommandLines.begin(),
1527 cpackCommandLines.end());
1528 singleLine.erase(singleLine.begin(), singleLine.end());
1529 depends.erase(depends.begin(), depends.end());
1530 singleLine.push_back(this->GetCMakeInstance()->GetCTestCommand());
1531 singleLine.push_back("--force-new-ctest-process");
1532 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1534 singleLine.push_back("-C");
1535 singleLine.push_back(cmakeCfgIntDir);
1537 else // TODO: This is a hack. Should be something to do with the generator
1539 singleLine.push_back("$(ARGS)");
1541 cpackCommandLines.push_back(singleLine);
1542 (*targets)[this->GetTestTargetName()]
1543 = this->CreateGlobalTarget(this->GetTestTargetName(),
1544 "Running tests...", &cpackCommandLines, depends);
1547 //Edit Cache
1548 const char* editCacheTargetName = this->GetEditCacheTargetName();
1549 if ( editCacheTargetName )
1551 cpackCommandLines.erase(cpackCommandLines.begin(),
1552 cpackCommandLines.end());
1553 singleLine.erase(singleLine.begin(), singleLine.end());
1554 depends.erase(depends.begin(), depends.end());
1556 // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
1557 // Otherwise default to the interactive command-line interface.
1558 if(mf->GetDefinition("CMAKE_EDIT_COMMAND"))
1560 singleLine.push_back(mf->GetDefinition("CMAKE_EDIT_COMMAND"));
1561 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1562 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1563 cpackCommandLines.push_back(singleLine);
1564 (*targets)[editCacheTargetName] =
1565 this->CreateGlobalTarget(
1566 editCacheTargetName, "Running CMake cache editor...",
1567 &cpackCommandLines, depends);
1569 else
1571 singleLine.push_back(cmakeCommand);
1572 singleLine.push_back("-i");
1573 singleLine.push_back(".");
1574 cpackCommandLines.push_back(singleLine);
1575 (*targets)[editCacheTargetName] =
1576 this->CreateGlobalTarget(
1577 editCacheTargetName,
1578 "Running interactive CMake command-line interface...",
1579 &cpackCommandLines, depends);
1583 //Rebuild Cache
1584 const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
1585 if ( rebuildCacheTargetName )
1587 cpackCommandLines.erase(cpackCommandLines.begin(),
1588 cpackCommandLines.end());
1589 singleLine.erase(singleLine.begin(), singleLine.end());
1590 depends.erase(depends.begin(), depends.end());
1591 singleLine.push_back(cmakeCommand);
1592 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1593 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1594 cpackCommandLines.push_back(singleLine);
1595 (*targets)[rebuildCacheTargetName] =
1596 this->CreateGlobalTarget(
1597 rebuildCacheTargetName, "Running CMake to regenerate build system...",
1598 &cpackCommandLines, depends);
1601 //Install
1602 if(this->InstallTargetEnabled)
1604 if(!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.')
1606 std::set<cmStdString>* componentsSet = &this->InstallComponents;
1607 cpackCommandLines.erase(cpackCommandLines.begin(),
1608 cpackCommandLines.end());
1609 depends.erase(depends.begin(), depends.end());
1610 cmOStringStream ostr;
1611 if ( componentsSet->size() > 0 )
1613 ostr << "Available install components are:";
1614 std::set<cmStdString>::iterator it;
1615 for (
1616 it = componentsSet->begin();
1617 it != componentsSet->end();
1618 ++ it )
1620 ostr << " \"" << it->c_str() << "\"";
1623 else
1625 ostr << "Only default component available";
1627 singleLine.push_back(ostr.str().c_str());
1628 (*targets)["list_install_components"]
1629 = this->CreateGlobalTarget("list_install_components",
1630 ostr.str().c_str(),
1631 &cpackCommandLines, depends);
1633 std::string cmd;
1634 cpackCommandLines.erase(cpackCommandLines.begin(),
1635 cpackCommandLines.end());
1636 singleLine.erase(singleLine.begin(), singleLine.end());
1637 depends.erase(depends.begin(), depends.end());
1638 if ( this->GetPreinstallTargetName() )
1640 depends.push_back(this->GetPreinstallTargetName());
1642 else
1644 const char* noall =
1645 mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
1646 if(!noall || cmSystemTools::IsOff(noall))
1648 depends.push_back(this->GetAllTargetName());
1651 if(mf->GetDefinition("CMake_BINARY_DIR"))
1653 // We are building CMake itself. We cannot use the original
1654 // executable to install over itself.
1655 cmd = mf->GetDefinition("EXECUTABLE_OUTPUT_PATH");
1656 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1658 cmd += "/";
1659 cmd += cmakeCfgIntDir;
1661 cmd += "/cmake";
1663 else
1665 cmd = cmakeCommand;
1667 singleLine.push_back(cmd.c_str());
1668 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1670 std::string cfgArg = "-DBUILD_TYPE=";
1671 cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR");
1672 singleLine.push_back(cfgArg);
1674 singleLine.push_back("-P");
1675 singleLine.push_back("cmake_install.cmake");
1676 cpackCommandLines.push_back(singleLine);
1677 (*targets)[this->GetInstallTargetName()] =
1678 this->CreateGlobalTarget(
1679 this->GetInstallTargetName(), "Install the project...",
1680 &cpackCommandLines, depends);
1682 // install_local
1683 if(const char* install_local = this->GetInstallLocalTargetName())
1685 cmCustomCommandLine localCmdLine = singleLine;
1687 localCmdLine.insert(localCmdLine.begin()+1,
1688 "-DCMAKE_INSTALL_LOCAL_ONLY=1");
1689 cpackCommandLines.erase(cpackCommandLines.begin(),
1690 cpackCommandLines.end());
1691 cpackCommandLines.push_back(localCmdLine);
1693 (*targets)[install_local] =
1694 this->CreateGlobalTarget(
1695 install_local, "Installing only the local directory...",
1696 &cpackCommandLines, depends);
1699 // install_strip
1700 const char* install_strip = this->GetInstallStripTargetName();
1701 if((install_strip !=0) && (mf->IsSet("CMAKE_STRIP")))
1703 cmCustomCommandLine stripCmdLine = singleLine;
1705 stripCmdLine.insert(stripCmdLine.begin()+1,"-DCMAKE_INSTALL_DO_STRIP=1");
1706 cpackCommandLines.erase(cpackCommandLines.begin(),
1707 cpackCommandLines.end());
1708 cpackCommandLines.push_back(stripCmdLine);
1710 (*targets)[install_strip] =
1711 this->CreateGlobalTarget(
1712 install_strip, "Installing the project stripped...",
1713 &cpackCommandLines, depends);
1718 cmTarget cmGlobalGenerator::CreateGlobalTarget(
1719 const char* name, const char* message,
1720 const cmCustomCommandLines* commandLines,
1721 std::vector<std::string> depends,
1722 bool depends_on_all /* = false */)
1724 // Package
1725 cmTarget target;
1726 target.GetProperties().SetCMakeInstance(this->CMakeInstance);
1727 target.SetType(cmTarget::GLOBAL_TARGET, name);
1728 target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
1730 std::vector<std::string> no_outputs;
1731 std::vector<std::string> no_depends;
1732 // Store the custom command in the target.
1733 cmCustomCommand cc(no_outputs, no_depends, *commandLines, 0, 0);
1734 target.GetPostBuildCommands().push_back(cc);
1735 target.SetProperty("EchoString", message);
1736 if ( depends_on_all )
1738 target.AddUtility("all");
1740 std::vector<std::string>::iterator dit;
1741 for ( dit = depends.begin(); dit != depends.end(); ++ dit )
1743 target.AddUtility(dit->c_str());
1745 return target;
1748 //----------------------------------------------------------------------------
1749 void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
1750 const char*, std::string&)
1752 // Subclasses that support multiple configurations should implement
1753 // this method to append the subdirectory for the given build
1754 // configuration.
1757 //----------------------------------------------------------------------------
1758 cmGlobalGenerator::TargetDependSet &
1759 cmGlobalGenerator::GetTargetDirectDepends(cmTarget & target)
1761 return this->TargetDependencies[&target];
1764 void cmGlobalGenerator::AddTarget(cmTargets::value_type &v)
1766 assert(!v.second.IsImported());
1767 this->TotalTargets[v.first] = &v.second;
1770 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
1771 cmExternalMakefileProjectGenerator *extraGenerator)
1773 this->ExtraGenerator = extraGenerator;
1774 if (this->ExtraGenerator!=0)
1776 this->ExtraGenerator->SetGlobalGenerator(this);
1780 const char* cmGlobalGenerator::GetExtraGeneratorName() const
1782 return this->ExtraGenerator==0 ? 0 : this->ExtraGenerator->GetName();
1785 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
1787 this->FilesReplacedDuringGenerate.push_back(filename);
1790 void
1791 cmGlobalGenerator
1792 ::GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames)
1794 filenames.clear();
1795 std::copy(
1796 this->FilesReplacedDuringGenerate.begin(),
1797 this->FilesReplacedDuringGenerate.end(),
1798 std::back_inserter(filenames));
1801 void
1802 cmGlobalGenerator
1803 ::GetTargetSets(cmGlobalGenerator::TargetDependSet& projectTargets,
1804 cmGlobalGenerator::TargetDependSet& originalTargets,
1805 cmLocalGenerator* root,
1806 std::vector<cmLocalGenerator*> const& generators)
1808 // loop over all local generators
1809 for(std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
1810 i != generators.end(); ++i)
1812 // check to make sure generator is not excluded
1813 if(this->IsExcluded(root, *i))
1815 continue;
1817 cmMakefile* mf = (*i)->GetMakefile();
1818 // Get the targets in the makefile
1819 cmTargets &tgts = mf->GetTargets();
1820 // loop over all the targets
1821 for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
1823 cmTarget* target = &l->second;
1824 // put the target in the set of original targets
1825 originalTargets.insert(target);
1826 // Get the set of targets that depend on target
1827 this->AddTargetDepends(target,
1828 projectTargets);
1833 void
1834 cmGlobalGenerator::AddTargetDepends(cmTarget* target,
1835 cmGlobalGenerator::TargetDependSet&
1836 projectTargets)
1838 // add the target itself
1839 projectTargets.insert(target);
1840 // get the direct depends of target
1841 cmGlobalGenerator::TargetDependSet const& tset
1842 = this->GetTargetDirectDepends(*target);
1843 if(tset.size())
1845 // if there are targets that depend on target
1846 // add them and their depends as well
1847 for(cmGlobalGenerator::TargetDependSet::const_iterator i =
1848 tset.begin(); i != tset.end(); ++i)
1850 cmTarget* dtarget = *i;
1851 this->AddTargetDepends(dtarget, projectTargets);
1857 //----------------------------------------------------------------------------
1858 void cmGlobalGenerator::AddToManifest(const char* config,
1859 std::string const& f)
1861 // Add to the main manifest for this configuration.
1862 this->TargetManifest[config].insert(f);
1864 // Add to the content listing for the file's directory.
1865 std::string dir = cmSystemTools::GetFilenamePath(f);
1866 std::string file = cmSystemTools::GetFilenameName(f);
1867 this->DirectoryContentMap[dir].insert(file);
1870 //----------------------------------------------------------------------------
1871 std::set<cmStdString> const&
1872 cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
1874 DirectoryContent& dc = this->DirectoryContentMap[dir];
1875 if(needDisk && !dc.LoadedFromDisk)
1877 // Load the directory content from disk.
1878 cmsys::Directory d;
1879 if(d.Load(dir.c_str()))
1881 unsigned long n = d.GetNumberOfFiles();
1882 for(unsigned long i = 0; i < n; ++i)
1884 const char* f = d.GetFile(i);
1885 if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
1887 dc.insert(f);
1891 dc.LoadedFromDisk = true;
1893 return dc;