Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmGlobalGenerator.cxx
blob7c40ca65f2a735f4a18f3cf1e02d9be29a3816be
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-09 16:19:27 $
7 Version: $Revision: 1.253 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #if defined(_WIN32) && !defined(__CYGWIN__)
18 #include "windows.h" // this must be first to define GetCurrentDirectory
19 #endif
21 #include "cmGlobalGenerator.h"
22 #include "cmLocalGenerator.h"
23 #include "cmExternalMakefileProjectGenerator.h"
24 #include "cmake.h"
25 #include "cmMakefile.h"
26 #include "cmSourceFile.h"
27 #include "cmVersion.h"
28 #include "cmExportInstallFileGenerator.h"
29 #include "cmComputeTargetDepends.h"
30 #include "cmGeneratedFileStream.h"
32 #include <cmsys/Directory.hxx>
34 #if defined(CMAKE_BUILD_WITH_CMAKE)
35 # include <cmsys/MD5.h>
36 #endif
38 #include <stdlib.h> // required for atof
40 #include <assert.h>
42 cmGlobalGenerator::cmGlobalGenerator()
44 // By default the .SYMBOLIC dependency is not needed on symbolic rules.
45 this->NeedSymbolicMark = false;
47 // by default use the native paths
48 this->ForceUnixPaths = false;
50 // By default do not try to support color.
51 this->ToolSupportsColor = false;
53 // By default do not use link scripts.
54 this->UseLinkScript = false;
56 // Whether an install target is needed.
57 this->InstallTargetEnabled = false;
59 // how long to let try compiles run
60 this->TryCompileTimeout = 0;
62 this->ExtraGenerator = 0;
63 this->CurrentLocalGenerator = 0;
66 cmGlobalGenerator::~cmGlobalGenerator()
68 // Delete any existing cmLocalGenerators
69 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
71 delete this->LocalGenerators[i];
73 this->LocalGenerators.clear();
75 if (this->ExtraGenerator)
77 delete this->ExtraGenerator;
80 this->ClearExportSets();
83 // Find the make program for the generator, required for try compiles
84 void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
86 if(this->FindMakeProgramFile.size() == 0)
88 cmSystemTools::Error(
89 "Generator implementation error, "
90 "all generators must specify this->FindMakeProgramFile");
92 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
93 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
95 std::string setMakeProgram =
96 mf->GetModulesFile(this->FindMakeProgramFile.c_str());
97 if(setMakeProgram.size())
99 mf->ReadListFile(0, setMakeProgram.c_str());
102 if(!mf->GetDefinition("CMAKE_MAKE_PROGRAM")
103 || cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
105 cmOStringStream err;
106 err << "CMake was unable to find a build program corresponding to \""
107 << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You "
108 << "probably need to select a different build tool.";
109 cmSystemTools::Error(err.str().c_str());
110 cmSystemTools::SetFatalErrorOccured();
111 return;
113 std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
114 // if there are spaces in the make program use short path
115 // but do not short path the actual program name, as
116 // this can cause trouble with VSExpress
117 if(makeProgram.find(' ') != makeProgram.npos)
119 std::string dir;
120 std::string file;
121 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
122 dir, file);
123 std::string saveFile = file;
124 cmSystemTools::GetShortPath(makeProgram.c_str(), makeProgram);
125 cmSystemTools::SplitProgramPath(makeProgram.c_str(),
126 dir, file);
127 makeProgram = dir;
128 makeProgram += "/";
129 makeProgram += saveFile;
130 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
131 "make program",
132 cmCacheManager::FILEPATH);
135 if(makeProgram.find("xcodebuild") != makeProgram.npos)
137 // due to the text file busy /bin/sh problem with xcodebuild
138 // use the cmakexbuild wrapper instead. This program
139 // will run xcodebuild and if it sees the error text file busy
140 // it will stop forwarding output, and let the build finish.
141 // Then it will retry the build. It will continue this
142 // untill no text file busy errors occur.
143 std::string cmakexbuild =
144 this->CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_COMMAND");
145 cmakexbuild = cmakexbuild.substr(0, cmakexbuild.length()-5);
146 cmakexbuild += "cmakexbuild";
148 mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM",
149 cmakexbuild.c_str(),
150 "make program",
151 cmCacheManager::FILEPATH);
155 // enable the given language
157 // The following files are loaded in this order:
159 // First figure out what OS we are running on:
161 // CMakeSystem.cmake - configured file created by CMakeDetermineSystem.cmake
162 // CMakeDetermineSystem.cmake - figure out os info and create
163 // CMakeSystem.cmake IF CMAKE_SYSTEM
164 // not set
165 // CMakeSystem.cmake - configured file created by
166 // CMakeDetermineSystem.cmake IF CMAKE_SYSTEM_LOADED
168 // Next try and enable all languages found in the languages vector
170 // FOREACH LANG in languages
171 // CMake(LANG)Compiler.cmake - configured file create by
172 // CMakeDetermine(LANG)Compiler.cmake
173 // CMakeDetermine(LANG)Compiler.cmake - Finds compiler for LANG and
174 // creates CMake(LANG)Compiler.cmake
175 // CMake(LANG)Compiler.cmake - configured file created by
176 // CMakeDetermine(LANG)Compiler.cmake
178 // CMakeSystemSpecificInformation.cmake
179 // - includes Platform/${CMAKE_SYSTEM_NAME}.cmake
180 // may use compiler stuff
182 // FOREACH LANG in languages
183 // CMake(LANG)Information.cmake
184 // - loads Platform/${CMAKE_SYSTEM_NAME}-${COMPILER}.cmake
185 // CMakeTest(LANG)Compiler.cmake
186 // - Make sure the compiler works with a try compile if
187 // CMakeDetermine(LANG) was loaded
189 // Now load a few files that can override values set in any of the above
190 // (PROJECTNAME)Compatibility.cmake
191 // - load any backwards compatibility stuff for current project
192 // ${CMAKE_USER_MAKE_RULES_OVERRIDE}
193 // - allow users a chance to override system variables
197 void
198 cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
199 cmMakefile *mf, bool)
201 if(languages.size() == 0)
203 cmSystemTools::Error("EnableLanguage must have a lang specified!");
204 cmSystemTools::SetFatalErrorOccured();
205 return;
207 mf->AddDefinition("RUN_CONFIGURE", true);
208 std::string rootBin = mf->GetHomeOutputDirectory();
209 rootBin += cmake::GetCMakeFilesDirectory();
211 // If the configuration files path has been set,
212 // then we are in a try compile and need to copy the enable language
213 // files from the parent cmake bin dir, into the try compile bin dir
214 if(this->ConfiguredFilesPath.size())
216 for(std::vector<std::string>::const_iterator l = languages.begin();
217 l != languages.end(); ++l)
219 if(*l == "NONE")
221 this->SetLanguageEnabled("NONE", mf);
222 break;
225 rootBin = this->ConfiguredFilesPath;
228 // set the dir for parent files so they can be used by modules
229 mf->AddDefinition("CMAKE_PLATFORM_ROOT_BIN",rootBin.c_str());
231 // find and make sure CMAKE_MAKE_PROGRAM is defined
232 this->FindMakeProgram(mf);
234 // try and load the CMakeSystem.cmake if it is there
235 std::string fpath = rootBin;
236 if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
238 fpath += "/CMakeSystem.cmake";
239 if(cmSystemTools::FileExists(fpath.c_str()))
241 mf->ReadListFile(0,fpath.c_str());
244 // Load the CMakeDetermineSystem.cmake file and find out
245 // what platform we are running on
246 if (!mf->GetDefinition("CMAKE_SYSTEM"))
248 #if defined(_WIN32) && !defined(__CYGWIN__)
249 /* Windows version number data. */
250 OSVERSIONINFO osvi;
251 ZeroMemory(&osvi, sizeof(osvi));
252 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
253 GetVersionEx (&osvi);
254 cmOStringStream windowsVersionString;
255 windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
256 windowsVersionString.str();
257 mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
258 windowsVersionString.str().c_str());
259 #endif
260 // Read the DetermineSystem file
261 std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
262 mf->ReadListFile(0, systemFile.c_str());
263 // load the CMakeSystem.cmake from the binary directory
264 // this file is configured by the CMakeDetermineSystem.cmake file
265 fpath = rootBin;
266 fpath += "/CMakeSystem.cmake";
267 mf->ReadListFile(0,fpath.c_str());
269 std::map<cmStdString, bool> needTestLanguage;
270 std::map<cmStdString, bool> needSetLanguageEnabledMaps;
271 // foreach language
272 // load the CMakeDetermine(LANG)Compiler.cmake file to find
273 // the compiler
275 for(std::vector<std::string>::const_iterator l = languages.begin();
276 l != languages.end(); ++l)
278 const char* lang = l->c_str();
279 needSetLanguageEnabledMaps[lang] = false;
280 if(*l == "NONE")
282 this->SetLanguageEnabled("NONE", mf);
283 continue;
285 std::string loadedLang = "CMAKE_";
286 loadedLang += lang;
287 loadedLang += "_COMPILER_LOADED";
288 // If the existing build tree was already configured with this
289 // version of CMake then try to load the configured file first
290 // to avoid duplicate compiler tests.
291 unsigned int cacheMajor = mf->GetCacheMajorVersion();
292 unsigned int cacheMinor = mf->GetCacheMinorVersion();
293 unsigned int selfMajor = cmVersion::GetMajorVersion();
294 unsigned int selfMinor = cmVersion::GetMinorVersion();
295 if((this->CMakeInstance->GetIsInTryCompile() ||
296 (selfMajor == cacheMajor && selfMinor == cacheMinor))
297 && !mf->GetDefinition(loadedLang.c_str()))
299 fpath = rootBin;
300 fpath += "/CMake";
301 fpath += lang;
302 fpath += "Compiler.cmake";
303 if(cmSystemTools::FileExists(fpath.c_str()))
305 if(!mf->ReadListFile(0,fpath.c_str()))
307 cmSystemTools::Error("Could not find cmake module file:",
308 fpath.c_str());
310 // if this file was found then the language was already determined
311 // to be working
312 needTestLanguage[lang] = false;
313 this->SetLanguageEnabledFlag(lang, mf);
314 needSetLanguageEnabledMaps[lang] = true;
315 // this can only be called after loading CMake(LANG)Compiler.cmake
319 if(!this->GetLanguageEnabled(lang) )
321 if (this->CMakeInstance->GetIsInTryCompile())
323 cmSystemTools::Error("This should not have happen. "
324 "If you see this message, you are probably "
325 "using a broken CMakeLists.txt file or a "
326 "problematic release of CMake");
328 // if the CMake(LANG)Compiler.cmake file was not found then
329 // load CMakeDetermine(LANG)Compiler.cmake
330 std::string determineCompiler = "CMakeDetermine";
331 determineCompiler += lang;
332 determineCompiler += "Compiler.cmake";
333 std::string determineFile =
334 mf->GetModulesFile(determineCompiler.c_str());
335 if(!mf->ReadListFile(0,determineFile.c_str()))
337 cmSystemTools::Error("Could not find cmake module file:",
338 determineFile.c_str());
340 needTestLanguage[lang] = true;
341 // Some generators like visual studio should not use the env variables
342 // So the global generator can specify that in this variable
343 if(!mf->GetDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV"))
345 // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
346 // into the environment, in case user scripts want to run
347 // configure, or sub cmakes
348 std::string compilerName = "CMAKE_";
349 compilerName += lang;
350 compilerName += "_COMPILER";
351 std::string compilerEnv = "CMAKE_";
352 compilerEnv += lang;
353 compilerEnv += "_COMPILER_ENV_VAR";
354 std::string envVar = mf->GetRequiredDefinition(compilerEnv.c_str());
355 std::string envVarValue =
356 mf->GetRequiredDefinition(compilerName.c_str());
357 std::string env = envVar;
358 env += "=";
359 env += envVarValue;
360 cmSystemTools::PutEnv(env.c_str());
363 // if determineLanguage was called then load the file it
364 // configures CMake(LANG)Compiler.cmake
365 fpath = rootBin;
366 fpath += "/CMake";
367 fpath += lang;
368 fpath += "Compiler.cmake";
369 if(!mf->ReadListFile(0,fpath.c_str()))
371 cmSystemTools::Error("Could not find cmake module file:",
372 fpath.c_str());
374 this->SetLanguageEnabledFlag(lang, mf);
375 needSetLanguageEnabledMaps[lang] = true;
376 // this can only be called after loading CMake(LANG)Compiler.cmake
377 // the language must be enabled for try compile to work, but we do
378 // not know if it is a working compiler yet so set the test language
379 // flag
380 needTestLanguage[lang] = true;
381 } // end if(!this->GetLanguageEnabled(lang) )
382 } // end loop over languages
384 // **** Load the system specific information if not yet loaded
385 if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
387 fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
388 if(!mf->ReadListFile(0,fpath.c_str()))
390 cmSystemTools::Error("Could not find cmake module file:",
391 fpath.c_str());
394 // loop over languages again loading CMake(LANG)Information.cmake
396 for(std::vector<std::string>::const_iterator l = languages.begin();
397 l != languages.end(); ++l)
399 const char* lang = l->c_str();
400 if(*l == "NONE")
402 this->SetLanguageEnabled("NONE", mf);
403 continue;
405 std::string langLoadedVar = "CMAKE_";
406 langLoadedVar += lang;
407 langLoadedVar += "_INFORMATION_LOADED";
408 if (!mf->GetDefinition(langLoadedVar.c_str()))
410 fpath = "CMake";
411 fpath += lang;
412 fpath += "Information.cmake";
413 std::string informationFile = mf->GetModulesFile(fpath.c_str());
414 if (informationFile.empty())
416 cmSystemTools::Error("Could not find cmake module file:",
417 fpath.c_str());
419 else if(!mf->ReadListFile(0, informationFile.c_str()))
421 cmSystemTools::Error("Could not process cmake module file:",
422 informationFile.c_str());
425 if (needSetLanguageEnabledMaps[lang])
427 this->SetLanguageEnabledMaps(lang, mf);
430 std::string compilerName = "CMAKE_";
431 compilerName += lang;
432 compilerName += "_COMPILER";
433 std::string compilerLangFile = rootBin;
434 compilerLangFile += "/CMake";
435 compilerLangFile += lang;
436 compilerLangFile += "Compiler.cmake";
437 // Test the compiler for the language just setup
438 // (but only if a compiler has been actually found)
439 // At this point we should have enough info for a try compile
440 // which is used in the backward stuff
441 // If the language is untested then test it now with a try compile.
442 if (!mf->IsSet(compilerName.c_str()))
444 // if the compiler did not work, then remove the
445 // CMake(LANG)Compiler.cmake file so that it will get tested the
446 // next time cmake is run
447 cmSystemTools::RemoveFile(compilerLangFile.c_str());
449 else if(needTestLanguage[lang])
451 if (!this->CMakeInstance->GetIsInTryCompile())
453 std::string testLang = "CMakeTest";
454 testLang += lang;
455 testLang += "Compiler.cmake";
456 std::string ifpath = mf->GetModulesFile(testLang.c_str());
457 if(!mf->ReadListFile(0,ifpath.c_str()))
459 cmSystemTools::Error("Could not find cmake module file:",
460 ifpath.c_str());
462 std::string compilerWorks = "CMAKE_";
463 compilerWorks += lang;
464 compilerWorks += "_COMPILER_WORKS";
465 // if the compiler did not work, then remove the
466 // CMake(LANG)Compiler.cmake file so that it will get tested the
467 // next time cmake is run
468 if(!mf->IsOn(compilerWorks.c_str()))
470 cmSystemTools::RemoveFile(compilerLangFile.c_str());
472 else
474 // load backwards compatibility stuff for C and CXX
475 // for old versions of CMake ListFiles C and CXX had some
476 // backwards compatibility files they have to load
477 // These files have a bunch of try compiles in them so
478 // should only be done
479 if (mf->NeedBackwardsCompatibility(1,4))
481 if(strcmp(lang, "C") == 0)
483 ifpath =
484 mf->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
485 mf->ReadListFile(0,ifpath.c_str());
487 if(strcmp(lang, "CXX") == 0)
489 ifpath =
490 mf->GetModulesFile("CMakeBackwardCompatibilityCXX.cmake");
491 mf->ReadListFile(0,ifpath.c_str());
495 } // end if in try compile
496 } // end need test language
497 } // end for each language
499 // Now load files that can override any settings on the platform or for
500 // the project First load the project compatibility file if it is in
501 // cmake
502 std::string projectCompatibility = mf->GetDefinition("CMAKE_ROOT");
503 projectCompatibility += "/Modules/";
504 projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
505 projectCompatibility += "Compatibility.cmake";
506 if(cmSystemTools::FileExists(projectCompatibility.c_str()))
508 mf->ReadListFile(0,projectCompatibility.c_str());
512 //----------------------------------------------------------------------------
513 const char*
514 cmGlobalGenerator::GetLanguageOutputExtension(cmSourceFile const& source)
516 if(const char* lang = source.GetLanguage())
518 if(this->LanguageToOutputExtension.count(lang) > 0)
520 return this->LanguageToOutputExtension[lang].c_str();
523 else
525 // if no language is found then check to see if it is already an
526 // ouput extension for some language. In that case it should be ignored
527 // and in this map, so it will not be compiled but will just be used.
528 std::string const& ext = source.GetExtension();
529 if(!ext.empty())
531 if(this->OutputExtensions.count(ext))
533 return ext.c_str();
537 return "";
541 const char* cmGlobalGenerator::GetLanguageFromExtension(const char* ext)
543 // if there is an extension and it starts with . then move past the
544 // . because the extensions are not stored with a . in the map
545 if(ext && *ext == '.')
547 ++ext;
549 if(this->ExtensionToLanguage.count(ext) > 0)
551 return this->ExtensionToLanguage[ext].c_str();
553 return 0;
556 /* SetLanguageEnabled() is now split in two parts:
557 at first the enabled-flag is set. This can then be used in EnabledLanguage()
558 for checking whether the language is already enabled. After setting this
559 flag still the values from the cmake variables have to be copied into the
560 internal maps, this is done in SetLanguageEnabledMaps() which is called
561 after the system- and compiler specific files have been loaded.
563 This split was done originally so that compiler-specific configuration
564 files could change the object file extension
565 (CMAKE_<LANG>_OUTPUT_EXTENSION) before the CMake variables were copied
566 to the C++ maps.
568 void cmGlobalGenerator::SetLanguageEnabled(const char* l, cmMakefile* mf)
570 this->SetLanguageEnabledFlag(l, mf);
571 this->SetLanguageEnabledMaps(l, mf);
574 void cmGlobalGenerator::SetLanguageEnabledFlag(const char* l, cmMakefile* mf)
576 this->LanguageEnabled[l] = true;
578 // Fill the language-to-extension map with the current variable
579 // settings to make sure it is available for the try_compile()
580 // command source file signature. In SetLanguageEnabledMaps this
581 // will be done again to account for any compiler- or
582 // platform-specific entries.
583 this->FillExtensionToLanguageMap(l, mf);
586 void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
588 // use LanguageToLinkerPreference to detect whether this functions has
589 // run before
590 if (this->LanguageToLinkerPreference.find(l) !=
591 this->LanguageToLinkerPreference.end())
593 return;
596 std::string linkerPrefVar = std::string("CMAKE_") +
597 std::string(l) + std::string("_LINKER_PREFERENCE");
598 const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
599 int preference = 0;
600 if(linkerPref)
602 if (sscanf(linkerPref, "%d", &preference)!=1)
604 // backward compatibility: before 2.6 LINKER_PREFERENCE
605 // was either "None" or "Prefered", and only the first character was
606 // tested. So if there is a custom language out there and it is
607 // "Prefered", set its preference high
608 if (linkerPref[0]=='P')
610 preference = 100;
612 else
614 preference = 0;
619 if (preference < 0)
621 std::string msg = linkerPrefVar;
622 msg += " is negative, adjusting it to 0";
623 cmSystemTools::Message(msg.c_str(), "Warning");
624 preference = 0;
627 this->LanguageToLinkerPreference[l] = preference;
629 std::string outputExtensionVar = std::string("CMAKE_") +
630 std::string(l) + std::string("_OUTPUT_EXTENSION");
631 const char* outputExtension = mf->GetDefinition(outputExtensionVar.c_str());
632 if(outputExtension)
634 this->LanguageToOutputExtension[l] = outputExtension;
635 this->OutputExtensions[outputExtension] = outputExtension;
636 if(outputExtension[0] == '.')
638 this->OutputExtensions[outputExtension+1] = outputExtension+1;
642 // The map was originally filled by SetLanguageEnabledFlag, but
643 // since then the compiler- and platform-specific files have been
644 // loaded which might have added more entries.
645 this->FillExtensionToLanguageMap(l, mf);
647 std::string ignoreExtensionsVar = std::string("CMAKE_") +
648 std::string(l) + std::string("_IGNORE_EXTENSIONS");
649 std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar.c_str());
650 std::vector<std::string> extensionList;
651 cmSystemTools::ExpandListArgument(ignoreExts, extensionList);
652 for(std::vector<std::string>::iterator i = extensionList.begin();
653 i != extensionList.end(); ++i)
655 this->IgnoreExtensions[*i] = true;
660 void cmGlobalGenerator::FillExtensionToLanguageMap(const char* l,
661 cmMakefile* mf)
663 std::string extensionsVar = std::string("CMAKE_") +
664 std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS");
665 std::string exts = mf->GetSafeDefinition(extensionsVar.c_str());
666 std::vector<std::string> extensionList;
667 cmSystemTools::ExpandListArgument(exts, extensionList);
668 for(std::vector<std::string>::iterator i = extensionList.begin();
669 i != extensionList.end(); ++i)
671 this->ExtensionToLanguage[*i] = l;
675 bool cmGlobalGenerator::IgnoreFile(const char* l)
677 if(this->GetLanguageFromExtension(l))
679 return false;
681 return (this->IgnoreExtensions.count(l) > 0);
684 bool cmGlobalGenerator::GetLanguageEnabled(const char* l) const
686 return (this->LanguageEnabled.find(l)!= this->LanguageEnabled.end());
689 void cmGlobalGenerator::ClearEnabledLanguages()
691 this->LanguageEnabled.clear();
694 bool cmGlobalGenerator::IsDependedOn(const char* project,
695 cmTarget* targetIn)
697 // Get all local gens for this project
698 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
699 // loop over local gens and get the targets for each one
700 for(unsigned int i = 0; i < gens->size(); ++i)
702 cmTargets& targets = (*gens)[i]->GetMakefile()->GetTargets();
703 for (cmTargets::iterator l = targets.begin();
704 l != targets.end(); l++)
706 cmTarget& target = l->second;
707 std::set<cmStdString>::const_iterator pos =
708 target.GetUtilities().find(targetIn->GetName());
709 if(pos != target.GetUtilities().end())
711 return true;
715 return false;
718 void cmGlobalGenerator::Configure()
720 this->FirstTimeProgress = 0.0f;
721 this->ClearExportSets();
722 // Delete any existing cmLocalGenerators
723 unsigned int i;
724 for (i = 0; i < this->LocalGenerators.size(); ++i)
726 delete this->LocalGenerators[i];
728 this->LocalGenerators.clear();
729 this->TargetDependencies.clear();
730 this->TotalTargets.clear();
731 this->LocalGeneratorToTargetMap.clear();
732 this->ProjectMap.clear();
733 this->RuleHashes.clear();
734 this->DirectoryContentMap.clear();
735 this->BinaryDirectories.clear();
737 // start with this directory
738 cmLocalGenerator *lg = this->CreateLocalGenerator();
739 this->LocalGenerators.push_back(lg);
741 // set the Start directories
742 cmMakefile* mf = lg->GetMakefile();
743 lg->GetMakefile()->SetStartDirectory
744 (this->CMakeInstance->GetStartDirectory());
745 lg->GetMakefile()->SetStartOutputDirectory
746 (this->CMakeInstance->GetStartOutputDirectory());
747 lg->GetMakefile()->MakeStartDirectoriesCurrent();
749 this->BinaryDirectories.insert(mf->GetStartOutputDirectory());
751 // now do it
752 lg->Configure();
754 // update the cache entry for the number of local generators, this is used
755 // for progress
756 char num[100];
757 sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size()));
758 this->GetCMakeInstance()->AddCacheEntry
759 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
760 "number of local generators", cmCacheManager::INTERNAL);
762 // check for link libraries and include directories containing "NOTFOUND"
763 // and for infinite loops
764 this->CheckLocalGenerators();
766 // at this point this->LocalGenerators has been filled,
767 // so create the map from project name to vector of local generators
768 this->FillProjectMap();
770 if ( !this->CMakeInstance->GetScriptMode() )
772 const char* msg = "Configuring done";
773 if(cmSystemTools::GetErrorOccuredFlag())
775 msg = "Configuring incomplete, errors occurred!";
777 this->CMakeInstance->UpdateProgress(msg, -1);
781 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
783 // If the property is not enabled then okay.
784 if(!this->CMakeInstance
785 ->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
787 return true;
790 // This generator does not support duplicate custom targets.
791 cmOStringStream e;
792 e << "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
793 << "global property. "
794 << "The \"" << this->GetName() << "\" generator does not support "
795 << "duplicate custom targets. "
796 << "Consider using a Makefiles generator or fix the project to not "
797 << "use duplicat target names.";
798 cmSystemTools::Error(e.str().c_str());
799 return false;
802 void cmGlobalGenerator::Generate()
804 // Some generators track files replaced during the Generate.
805 // Start with an empty vector:
806 this->FilesReplacedDuringGenerate.clear();
808 // Check whether this generator is allowed to run.
809 if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
811 return;
814 // Check that all targets are valid.
815 if(!this->CheckTargets())
817 return;
820 // For each existing cmLocalGenerator
821 unsigned int i;
823 // Consolidate global targets
824 cmTargets globalTargets;
825 this->CreateDefaultGlobalTargets(&globalTargets);
826 for (i = 0; i < this->LocalGenerators.size(); ++i)
828 cmTargets* targets =
829 &(this->LocalGenerators[i]->GetMakefile()->GetTargets());
830 cmTargets::iterator tarIt;
831 for ( tarIt = targets->begin(); tarIt != targets->end(); ++ tarIt )
833 if ( tarIt->second.GetType() == cmTarget::GLOBAL_TARGET )
835 globalTargets[tarIt->first] = tarIt->second;
839 for (i = 0; i < this->LocalGenerators.size(); ++i)
841 cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
842 cmTargets* targets = &(mf->GetTargets());
843 cmTargets::iterator tit;
844 for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit )
846 (*targets)[tit->first] = tit->second;
847 (*targets)[tit->first].SetMakefile(mf);
851 // Add generator specific helper commands
852 for (i = 0; i < this->LocalGenerators.size(); ++i)
854 this->LocalGenerators[i]->AddHelperCommands();
857 // Trace the dependencies, after that no custom commands should be added
858 // because their dependencies might not be handled correctly
859 for (i = 0; i < this->LocalGenerators.size(); ++i)
861 this->LocalGenerators[i]->TraceDependencies();
864 // Compute the manifest of main targets generated.
865 for (i = 0; i < this->LocalGenerators.size(); ++i)
867 this->LocalGenerators[i]->GenerateTargetManifest();
870 // Compute the inter-target dependencies.
872 cmComputeTargetDepends ctd(this);
873 if(!ctd.Compute())
875 return;
877 std::vector<cmTarget*> const& targets = ctd.GetTargets();
878 for(std::vector<cmTarget*>::const_iterator ti = targets.begin();
879 ti != targets.end(); ++ti)
881 ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]);
885 // Create a map from local generator to the complete set of targets
886 // it builds by default.
887 this->FillLocalGeneratorToTargetMap();
889 // Generate project files
890 for (i = 0; i < this->LocalGenerators.size(); ++i)
892 this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
893 this->LocalGenerators[i]->Generate();
894 this->LocalGenerators[i]->GenerateInstallRules();
895 this->LocalGenerators[i]->GenerateTestFiles();
896 this->CMakeInstance->UpdateProgress("Generating",
897 (i+1.0f)/this->LocalGenerators.size());
899 this->SetCurrentLocalGenerator(0);
901 // Update rule hashes.
902 this->CheckRuleHashes();
904 this->WriteSummary();
906 if (this->ExtraGenerator != 0)
908 this->ExtraGenerator->Generate();
911 this->CMakeInstance->UpdateProgress("Generating done", -1);
914 //----------------------------------------------------------------------------
915 bool cmGlobalGenerator::CheckTargets()
917 // Make sure all targets can find their source files.
918 for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
920 cmTargets& targets =
921 this->LocalGenerators[i]->GetMakefile()->GetTargets();
922 for(cmTargets::iterator ti = targets.begin();
923 ti != targets.end(); ++ti)
925 cmTarget& target = ti->second;
926 if(target.GetType() == cmTarget::EXECUTABLE ||
927 target.GetType() == cmTarget::STATIC_LIBRARY ||
928 target.GetType() == cmTarget::SHARED_LIBRARY ||
929 target.GetType() == cmTarget::MODULE_LIBRARY ||
930 target.GetType() == cmTarget::UTILITY)
932 if(!target.FindSourceFiles())
934 return false;
939 return true;
942 void cmGlobalGenerator::CheckLocalGenerators()
944 std::map<cmStdString, cmStdString> notFoundMap;
945 // std::set<cmStdString> notFoundMap;
946 // after it is all done do a ConfigureFinalPass
947 cmCacheManager* manager = 0;
948 for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
950 manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
951 this->LocalGenerators[i]->ConfigureFinalPass();
952 const cmTargets & targets =
953 this->LocalGenerators[i]->GetMakefile()->GetTargets();
954 for (cmTargets::const_iterator l = targets.begin();
955 l != targets.end(); l++)
957 const cmTarget::LinkLibraryVectorType& libs =
958 l->second.GetOriginalLinkLibraries();
959 for(cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin();
960 lib != libs.end(); ++lib)
962 if(lib->first.size() > 9 &&
963 cmSystemTools::IsNOTFOUND(lib->first.c_str()))
965 std::string varName = lib->first.substr(0, lib->first.size()-9);
966 cmCacheManager::CacheIterator it =
967 manager->GetCacheIterator(varName.c_str());
968 if(it.GetPropertyAsBool("ADVANCED"))
970 varName += " (ADVANCED)";
972 std::string text = notFoundMap[varName];
973 text += "\n linked by target \"";
974 text += l->second.GetName();
975 text += "\" in directory ";
976 text+=this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
977 notFoundMap[varName] = text;
981 const std::vector<std::string>& incs =
982 this->LocalGenerators[i]->GetMakefile()->GetIncludeDirectories();
984 for( std::vector<std::string>::const_iterator incDir = incs.begin();
985 incDir != incs.end(); ++incDir)
987 if(incDir->size() > 9 &&
988 cmSystemTools::IsNOTFOUND(incDir->c_str()))
990 std::string varName = incDir->substr(0, incDir->size()-9);
991 cmCacheManager::CacheIterator it =
992 manager->GetCacheIterator(varName.c_str());
993 if(it.GetPropertyAsBool("ADVANCED"))
995 varName += " (ADVANCED)";
997 std::string text = notFoundMap[varName];
998 text += "\n used as include directory in directory ";
999 text += this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
1000 notFoundMap[varName] = text;
1003 this->CMakeInstance->UpdateProgress
1004 ("Configuring", 0.9f+0.1f*(i+1.0f)/this->LocalGenerators.size());
1007 if(notFoundMap.size())
1009 std::string notFoundVars;
1010 for(std::map<cmStdString, cmStdString>::const_iterator
1011 ii = notFoundMap.begin();
1012 ii != notFoundMap.end();
1013 ++ii)
1015 notFoundVars += ii->first;
1016 notFoundVars += ii->second;
1017 notFoundVars += "\n";
1019 cmSystemTools::Error("The following variables are used in this project, "
1020 "but they are set to NOTFOUND.\n"
1021 "Please set them or make sure they are set and "
1022 "tested correctly in the CMake files:\n",
1023 notFoundVars.c_str());
1027 int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
1028 const char *projectName,
1029 const char *target,
1030 std::string *output, cmMakefile *mf)
1032 // if this is not set, then this is a first time configure
1033 // and there is a good chance that the try compile stuff will
1034 // take the bulk of the time, so try and guess some progress
1035 // by getting closer and closer to 100 without actually getting there.
1036 if (!this->CMakeInstance->GetCacheManager()->GetCacheValue
1037 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
1039 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1040 // we are in the first time progress and we have no
1041 // idea how long it will be. So, just move 1/10th of the way
1042 // there each time, and don't go over 95%
1043 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1044 if(this->FirstTimeProgress > 0.95f)
1046 this->FirstTimeProgress = 0.95f;
1048 this->CMakeInstance->UpdateProgress("Configuring",
1049 this->FirstTimeProgress);
1052 std::string makeCommand = this->CMakeInstance->
1053 GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
1054 if(makeCommand.size() == 0)
1056 cmSystemTools::Error(
1057 "Generator cannot find the appropriate make command.");
1058 return 1;
1061 std::string newTarget;
1062 if (target && strlen(target))
1064 newTarget += target;
1065 #if 0
1066 #if defined(_WIN32) || defined(__CYGWIN__)
1067 std::string tmp = target;
1068 // if the target does not already end in . something
1069 // then assume .exe
1070 if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
1072 newTarget += ".exe";
1074 #endif // WIN32
1075 #endif
1077 const char* config = mf->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
1078 return this->Build(srcdir,bindir,projectName,
1079 newTarget.c_str(),
1080 output,makeCommand.c_str(),config,false,true,
1081 this->TryCompileTimeout);
1084 std::string cmGlobalGenerator
1085 ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
1086 const char* additionalOptions, const char *targetName,
1087 const char* config, bool ignoreErrors, bool)
1089 // Project name and config are not used yet.
1090 (void)projectName;
1091 (void)config;
1093 std::string makeCommand =
1094 cmSystemTools::ConvertToUnixOutputPath(makeProgram);
1096 // Since we have full control over the invocation of nmake, let us
1097 // make it quiet.
1098 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
1100 makeCommand += " /NOLOGO ";
1102 if ( ignoreErrors )
1104 makeCommand += " -i";
1106 if ( additionalOptions )
1108 makeCommand += " ";
1109 makeCommand += additionalOptions;
1111 if ( targetName )
1113 makeCommand += " ";
1114 makeCommand += targetName;
1116 return makeCommand;
1119 int cmGlobalGenerator::Build(
1120 const char *, const char *bindir,
1121 const char *projectName, const char *target,
1122 std::string *output,
1123 const char *makeCommandCSTR,
1124 const char *config,
1125 bool clean, bool fast,
1126 double timeout,
1127 bool verbose,
1128 const char* extraOptions,
1129 std::vector<std::string> const& nativeOptions)
1132 * Run an executable command and put the stdout in output.
1134 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1135 cmSystemTools::ChangeDirectory(bindir);
1136 if(output)
1138 *output += "Change Dir: ";
1139 *output += bindir;
1140 *output += "\n";
1143 int retVal;
1144 bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
1145 cmSystemTools::SetRunCommandHideConsole(true);
1146 std::string outputBuffer;
1147 std::string* outputPtr = 0;
1148 if(output)
1150 outputPtr = &outputBuffer;
1153 // should we do a clean first?
1154 if (clean)
1156 std::string cleanCommand =
1157 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1158 0, "clean", config, false, fast);
1159 if(output)
1161 *output += "\nRun Clean Command:";
1162 *output += cleanCommand;
1163 *output += "\n";
1166 if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), outputPtr,
1167 &retVal, 0, verbose, timeout))
1169 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1170 cmSystemTools::Error("Generator: execution of make clean failed.");
1171 if (output)
1173 *output += *outputPtr;
1174 *output += "\nGenerator: execution of make clean failed.\n";
1177 // return to the original directory
1178 cmSystemTools::ChangeDirectory(cwd.c_str());
1179 return 1;
1181 if (output)
1183 *output += *outputPtr;
1187 // now build
1188 std::string makeCommand =
1189 this->GenerateBuildCommand(makeCommandCSTR, projectName,
1190 extraOptions, target,
1191 config, false, fast);
1192 if(output)
1194 *output += "\nRun Build Command:";
1195 *output += makeCommand;
1196 *output += "\n";
1199 std::vector<cmStdString> command =
1200 cmSystemTools::ParseArguments(makeCommand.c_str());
1201 for(std::vector<std::string>::const_iterator ni = nativeOptions.begin();
1202 ni != nativeOptions.end(); ++ni)
1204 command.push_back(*ni);
1207 if (!cmSystemTools::RunSingleCommand(command, outputPtr,
1208 &retVal, 0, verbose, timeout))
1210 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1211 cmSystemTools::Error
1212 ("Generator: execution of make failed. Make command was: ",
1213 makeCommand.c_str());
1214 if (output)
1216 *output += *outputPtr;
1217 *output += "\nGenerator: execution of make failed. Make command was: "
1218 + makeCommand + "\n";
1221 // return to the original directory
1222 cmSystemTools::ChangeDirectory(cwd.c_str());
1223 return 1;
1225 if (output)
1227 *output += *outputPtr;
1229 cmSystemTools::SetRunCommandHideConsole(hideconsole);
1231 // The SGI MipsPro 7.3 compiler does not return an error code when
1232 // the source has a #error in it! This is a work-around for such
1233 // compilers.
1234 if((retVal == 0) && (output->find("#error") != std::string::npos))
1236 retVal = 1;
1239 cmSystemTools::ChangeDirectory(cwd.c_str());
1240 return retVal;
1243 void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
1245 this->LocalGenerators.push_back(lg);
1247 // update progress
1248 // estimate how many lg there will be
1249 const char *numGenC =
1250 this->CMakeInstance->GetCacheManager()->GetCacheValue
1251 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
1253 if (!numGenC)
1255 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1256 // we are in the first time progress and we have no
1257 // idea how long it will be. So, just move half way
1258 // there each time, and don't go over 95%
1259 this->FirstTimeProgress += ((1.0f - this->FirstTimeProgress) /30.0f);
1260 if(this->FirstTimeProgress > 0.95f)
1262 this->FirstTimeProgress = 0.95f;
1264 this->CMakeInstance->UpdateProgress("Configuring",
1265 this->FirstTimeProgress);
1266 return;
1269 int numGen = atoi(numGenC);
1270 float prog = 0.9f*this->LocalGenerators.size()/numGen;
1271 if (prog > 0.9f)
1273 prog = 0.9f;
1275 this->CMakeInstance->UpdateProgress("Configuring", prog);
1278 void cmGlobalGenerator::AddInstallComponent(const char* component)
1280 if(component && *component)
1282 this->InstallComponents.insert(component);
1286 void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
1287 cmTarget* target,
1288 cmInstallTargetGenerator* archive,
1289 cmInstallTargetGenerator* runTime,
1290 cmInstallTargetGenerator* library,
1291 cmInstallTargetGenerator* framework,
1292 cmInstallTargetGenerator* bundle,
1293 cmInstallFilesGenerator* headers)
1295 if ((exportSetName) && (*exportSetName) && (target))
1297 cmTargetExport* te = new cmTargetExport(target, archive, runTime, library,
1298 framework, bundle, headers);
1299 this->ExportSets[exportSetName].push_back(te);
1303 //----------------------------------------------------------------------------
1304 void cmGlobalGenerator::ClearExportSets()
1306 for(std::map<cmStdString, std::vector<cmTargetExport*> >::iterator
1307 setIt = this->ExportSets.begin();
1308 setIt != this->ExportSets.end(); ++setIt)
1310 for(unsigned int i = 0; i < setIt->second.size(); ++i)
1312 delete setIt->second[i];
1315 this->ExportSets.clear();
1318 const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet(
1319 const char* name) const
1321 std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator
1322 exportSetIt = this->ExportSets.find(name);
1323 if (exportSetIt != this->ExportSets.end())
1325 return &exportSetIt->second;
1328 return 0;
1332 void cmGlobalGenerator::EnableInstallTarget()
1334 this->InstallTargetEnabled = true;
1337 cmLocalGenerator *cmGlobalGenerator::CreateLocalGenerator()
1339 cmLocalGenerator *lg = new cmLocalGenerator;
1340 lg->SetGlobalGenerator(this);
1341 return lg;
1344 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen )
1346 std::string cfp = gen->GetCMakeInstance()->GetHomeOutputDirectory();
1347 cfp += cmake::GetCMakeFilesDirectory();
1348 this->SetConfiguredFilesPath(cfp.c_str());
1349 const char* make =
1350 gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
1351 this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make,
1352 "make program",
1353 cmCacheManager::FILEPATH);
1354 // copy the enabled languages
1355 this->LanguageEnabled = gen->LanguageEnabled;
1356 this->ExtensionToLanguage = gen->ExtensionToLanguage;
1357 this->IgnoreExtensions = gen->IgnoreExtensions;
1358 this->LanguageToOutputExtension = gen->LanguageToOutputExtension;
1359 this->LanguageToLinkerPreference = gen->LanguageToLinkerPreference;
1360 this->OutputExtensions = gen->OutputExtensions;
1363 //----------------------------------------------------------------------------
1364 void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
1366 entry.Name = this->GetName();
1367 entry.Brief = "";
1368 entry.Full = "";
1371 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1372 cmLocalGenerator* gen)
1374 if(!gen || gen == root)
1376 // No directory excludes itself.
1377 return false;
1380 if(gen->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1382 // This directory is excluded from its parent.
1383 return true;
1386 // This directory is included in its parent. Check whether the
1387 // parent is excluded.
1388 return this->IsExcluded(root, gen->GetParent());
1391 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
1392 cmTarget& target)
1394 if(target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1396 // This target is excluded from its directory.
1397 return true;
1399 else
1401 // This target is included in its directory. Check whether the
1402 // directory is excluded.
1403 return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator());
1407 void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
1409 for(std::map<cmStdString, bool>::iterator i =
1410 this->LanguageEnabled.begin(); i != this->LanguageEnabled.end(); ++i)
1412 lang.push_back(i->first);
1416 int cmGlobalGenerator::GetLinkerPreference(const char* lang)
1418 std::map<cmStdString, int>::const_iterator it =
1419 this->LanguageToLinkerPreference.find(lang);
1420 if (it != this->LanguageToLinkerPreference.end())
1422 return it->second;
1424 return 0;
1427 void cmGlobalGenerator::FillProjectMap()
1429 this->ProjectMap.clear(); // make sure we start with a clean map
1430 unsigned int i;
1431 for(i = 0; i < this->LocalGenerators.size(); ++i)
1433 // for each local generator add all projects
1434 cmLocalGenerator *lg = this->LocalGenerators[i];
1435 std::string name;
1438 if (name != lg->GetMakefile()->GetProjectName())
1440 name = lg->GetMakefile()->GetProjectName();
1441 this->ProjectMap[name].push_back(this->LocalGenerators[i]);
1443 lg = lg->GetParent();
1445 while (lg);
1450 // Build a map that contains a the set of targets used by each local
1451 // generator directory level.
1452 void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
1454 this->LocalGeneratorToTargetMap.clear();
1455 // Loop over all targets in all local generators.
1456 for(std::vector<cmLocalGenerator*>::const_iterator
1457 lgi = this->LocalGenerators.begin();
1458 lgi != this->LocalGenerators.end(); ++lgi)
1460 cmLocalGenerator* lg = *lgi;
1461 cmMakefile* mf = lg->GetMakefile();
1462 cmTargets& targets = mf->GetTargets();
1463 for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1465 cmTarget& target = t->second;
1467 // Consider the directory containing the target and all its
1468 // parents until something excludes the target.
1469 for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target);
1470 clg = clg->GetParent())
1472 // This local generator includes the target.
1473 std::set<cmTarget*>& targetSet =
1474 this->LocalGeneratorToTargetMap[clg];
1475 targetSet.insert(&target);
1477 // Add dependencies of the included target. An excluded
1478 // target may still be included if it is a dependency of a
1479 // non-excluded target.
1480 TargetDependSet & tgtdeps = this->GetTargetDirectDepends(target);
1481 for(TargetDependSet::const_iterator ti = tgtdeps.begin();
1482 ti != tgtdeps.end(); ++ti)
1484 targetSet.insert(*ti);
1492 ///! Find a local generator by its startdirectory
1493 cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
1495 std::vector<cmLocalGenerator*>* gens = &this->LocalGenerators;
1496 for(unsigned int i = 0; i < gens->size(); ++i)
1498 std::string sd = (*gens)[i]->GetMakefile()->GetStartDirectory();
1499 if (sd == start_dir)
1501 return (*gens)[i];
1504 return 0;
1508 //----------------------------------------------------------------------------
1509 cmTarget*
1510 cmGlobalGenerator::FindTarget(const char* project, const char* name)
1512 // if project specific
1513 if(project)
1515 std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
1516 for(unsigned int i = 0; i < gens->size(); ++i)
1518 cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
1519 if(ret)
1521 return ret;
1525 // if all projects/directories
1526 else
1528 std::map<cmStdString,cmTarget *>::iterator i =
1529 this->TotalTargets.find ( name );
1530 if ( i != this->TotalTargets.end() )
1532 return i->second;
1535 return 0;
1538 //----------------------------------------------------------------------------
1539 bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
1541 if(cmSystemTools::IsPathToFramework(libname.c_str()))
1543 return true;
1546 if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
1548 if(tgt->IsFrameworkOnApple())
1550 return true;
1554 return false;
1557 //----------------------------------------------------------------------------
1558 inline std::string removeQuotes(const std::string& s)
1560 if(s[0] == '\"' && s[s.size()-1] == '\"')
1562 return s.substr(1, s.size()-2);
1564 return s;
1567 void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
1569 // Store a pointer to the cmake object instance.
1570 this->CMakeInstance = cm;
1573 void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
1575 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
1576 const char* cmakeCfgIntDir = this->GetCMakeCFGInitDirectory();
1577 const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND");
1579 // CPack
1580 std::string workingDir = mf->GetStartOutputDirectory();
1581 cmCustomCommandLines cpackCommandLines;
1582 std::vector<std::string> depends;
1583 cmCustomCommandLine singleLine;
1584 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1585 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1587 singleLine.push_back("-C");
1588 singleLine.push_back(cmakeCfgIntDir);
1590 singleLine.push_back("--config");
1591 std::string configFile = mf->GetStartOutputDirectory();;
1592 configFile += "/CPackConfig.cmake";
1593 std::string relConfigFile = "./CPackConfig.cmake";
1594 singleLine.push_back(relConfigFile);
1595 cpackCommandLines.push_back(singleLine);
1596 if ( this->GetPreinstallTargetName() )
1598 depends.push_back(this->GetPreinstallTargetName());
1600 else
1602 const char* noPackageAll =
1603 mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
1604 if(!noPackageAll || cmSystemTools::IsOff(noPackageAll))
1606 depends.push_back(this->GetAllTargetName());
1609 if(cmSystemTools::FileExists(configFile.c_str()))
1611 (*targets)[this->GetPackageTargetName()]
1612 = this->CreateGlobalTarget(this->GetPackageTargetName(),
1613 "Run CPack packaging tool...",
1614 &cpackCommandLines, depends,
1615 workingDir.c_str());
1617 // CPack source
1618 const char* packageSourceTargetName = this->GetPackageSourceTargetName();
1619 if ( packageSourceTargetName )
1621 cpackCommandLines.erase(cpackCommandLines.begin(),
1622 cpackCommandLines.end());
1623 singleLine.erase(singleLine.begin(), singleLine.end());
1624 depends.erase(depends.begin(), depends.end());
1625 singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand());
1626 singleLine.push_back("--config");
1627 configFile = mf->GetStartOutputDirectory();;
1628 configFile += "/CPackSourceConfig.cmake";
1629 relConfigFile = "./CPackSourceConfig.cmake";
1630 singleLine.push_back(relConfigFile);
1631 if(cmSystemTools::FileExists(configFile.c_str()))
1633 singleLine.push_back(configFile);
1634 cpackCommandLines.push_back(singleLine);
1635 (*targets)[packageSourceTargetName]
1636 = this->CreateGlobalTarget(packageSourceTargetName,
1637 "Run CPack packaging tool for source...",
1638 &cpackCommandLines, depends,
1639 workingDir.c_str()
1644 // Test
1645 if(mf->IsOn("CMAKE_TESTING_ENABLED"))
1647 cpackCommandLines.erase(cpackCommandLines.begin(),
1648 cpackCommandLines.end());
1649 singleLine.erase(singleLine.begin(), singleLine.end());
1650 depends.erase(depends.begin(), depends.end());
1651 singleLine.push_back(this->GetCMakeInstance()->GetCTestCommand());
1652 singleLine.push_back("--force-new-ctest-process");
1653 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1655 singleLine.push_back("-C");
1656 singleLine.push_back(cmakeCfgIntDir);
1658 else // TODO: This is a hack. Should be something to do with the generator
1660 singleLine.push_back("$(ARGS)");
1662 cpackCommandLines.push_back(singleLine);
1663 (*targets)[this->GetTestTargetName()]
1664 = this->CreateGlobalTarget(this->GetTestTargetName(),
1665 "Running tests...", &cpackCommandLines, depends, 0);
1668 //Edit Cache
1669 const char* editCacheTargetName = this->GetEditCacheTargetName();
1670 if ( editCacheTargetName )
1672 cpackCommandLines.erase(cpackCommandLines.begin(),
1673 cpackCommandLines.end());
1674 singleLine.erase(singleLine.begin(), singleLine.end());
1675 depends.erase(depends.begin(), depends.end());
1677 // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
1678 // Otherwise default to the interactive command-line interface.
1679 if(mf->GetDefinition("CMAKE_EDIT_COMMAND"))
1681 singleLine.push_back(mf->GetDefinition("CMAKE_EDIT_COMMAND"));
1682 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1683 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1684 cpackCommandLines.push_back(singleLine);
1685 (*targets)[editCacheTargetName] =
1686 this->CreateGlobalTarget(
1687 editCacheTargetName, "Running CMake cache editor...",
1688 &cpackCommandLines, depends, 0);
1690 else
1692 singleLine.push_back(cmakeCommand);
1693 singleLine.push_back("-i");
1694 singleLine.push_back(".");
1695 cpackCommandLines.push_back(singleLine);
1696 (*targets)[editCacheTargetName] =
1697 this->CreateGlobalTarget(
1698 editCacheTargetName,
1699 "Running interactive CMake command-line interface...",
1700 &cpackCommandLines, depends, 0);
1704 //Rebuild Cache
1705 const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
1706 if ( rebuildCacheTargetName )
1708 cpackCommandLines.erase(cpackCommandLines.begin(),
1709 cpackCommandLines.end());
1710 singleLine.erase(singleLine.begin(), singleLine.end());
1711 depends.erase(depends.begin(), depends.end());
1712 singleLine.push_back(cmakeCommand);
1713 singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
1714 singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
1715 cpackCommandLines.push_back(singleLine);
1716 (*targets)[rebuildCacheTargetName] =
1717 this->CreateGlobalTarget(
1718 rebuildCacheTargetName, "Running CMake to regenerate build system...",
1719 &cpackCommandLines, depends, 0);
1722 //Install
1723 if(this->InstallTargetEnabled)
1725 if(!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.')
1727 std::set<cmStdString>* componentsSet = &this->InstallComponents;
1728 cpackCommandLines.erase(cpackCommandLines.begin(),
1729 cpackCommandLines.end());
1730 depends.erase(depends.begin(), depends.end());
1731 cmOStringStream ostr;
1732 if ( componentsSet->size() > 0 )
1734 ostr << "Available install components are:";
1735 std::set<cmStdString>::iterator it;
1736 for (
1737 it = componentsSet->begin();
1738 it != componentsSet->end();
1739 ++ it )
1741 ostr << " \"" << it->c_str() << "\"";
1744 else
1746 ostr << "Only default component available";
1748 singleLine.push_back(ostr.str().c_str());
1749 (*targets)["list_install_components"]
1750 = this->CreateGlobalTarget("list_install_components",
1751 ostr.str().c_str(),
1752 &cpackCommandLines, depends, 0);
1754 std::string cmd;
1755 cpackCommandLines.erase(cpackCommandLines.begin(),
1756 cpackCommandLines.end());
1757 singleLine.erase(singleLine.begin(), singleLine.end());
1758 depends.erase(depends.begin(), depends.end());
1759 if ( this->GetPreinstallTargetName() )
1761 depends.push_back(this->GetPreinstallTargetName());
1763 else
1765 const char* noall =
1766 mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
1767 if(!noall || cmSystemTools::IsOff(noall))
1769 depends.push_back(this->GetAllTargetName());
1772 if(mf->GetDefinition("CMake_BINARY_DIR"))
1774 // We are building CMake itself. We cannot use the original
1775 // executable to install over itself.
1776 cmd = mf->GetDefinition("EXECUTABLE_OUTPUT_PATH");
1777 if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.')
1779 cmd += "/";
1780 cmd += cmakeCfgIntDir;
1782 cmd += "/cmake";
1784 else
1786 cmd = cmakeCommand;
1788 singleLine.push_back(cmd.c_str());
1789 if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' )
1791 std::string cfgArg = "-DBUILD_TYPE=";
1792 cfgArg += mf->GetDefinition("CMAKE_CFG_INTDIR");
1793 singleLine.push_back(cfgArg);
1795 singleLine.push_back("-P");
1796 singleLine.push_back("cmake_install.cmake");
1797 cpackCommandLines.push_back(singleLine);
1798 (*targets)[this->GetInstallTargetName()] =
1799 this->CreateGlobalTarget(
1800 this->GetInstallTargetName(), "Install the project...",
1801 &cpackCommandLines, depends, 0);
1803 // install_local
1804 if(const char* install_local = this->GetInstallLocalTargetName())
1806 cmCustomCommandLine localCmdLine = singleLine;
1808 localCmdLine.insert(localCmdLine.begin()+1,
1809 "-DCMAKE_INSTALL_LOCAL_ONLY=1");
1810 cpackCommandLines.erase(cpackCommandLines.begin(),
1811 cpackCommandLines.end());
1812 cpackCommandLines.push_back(localCmdLine);
1814 (*targets)[install_local] =
1815 this->CreateGlobalTarget(
1816 install_local, "Installing only the local directory...",
1817 &cpackCommandLines, depends, 0);
1820 // install_strip
1821 const char* install_strip = this->GetInstallStripTargetName();
1822 if((install_strip !=0) && (mf->IsSet("CMAKE_STRIP")))
1824 cmCustomCommandLine stripCmdLine = singleLine;
1826 stripCmdLine.insert(stripCmdLine.begin()+1,"-DCMAKE_INSTALL_DO_STRIP=1");
1827 cpackCommandLines.erase(cpackCommandLines.begin(),
1828 cpackCommandLines.end());
1829 cpackCommandLines.push_back(stripCmdLine);
1831 (*targets)[install_strip] =
1832 this->CreateGlobalTarget(
1833 install_strip, "Installing the project stripped...",
1834 &cpackCommandLines, depends, 0);
1839 cmTarget cmGlobalGenerator::CreateGlobalTarget(
1840 const char* name, const char* message,
1841 const cmCustomCommandLines* commandLines,
1842 std::vector<std::string> depends,
1843 const char* workingDirectory,
1844 bool depends_on_all /* = false */)
1846 // Package
1847 cmTarget target;
1848 target.GetProperties().SetCMakeInstance(this->CMakeInstance);
1849 target.SetType(cmTarget::GLOBAL_TARGET, name);
1850 target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
1852 std::vector<std::string> no_outputs;
1853 std::vector<std::string> no_depends;
1854 // Store the custom command in the target.
1855 cmCustomCommand cc(no_outputs, no_depends, *commandLines, 0,
1856 workingDirectory);
1857 target.GetPostBuildCommands().push_back(cc);
1858 target.SetProperty("EchoString", message);
1859 if ( depends_on_all )
1861 target.AddUtility("all");
1863 std::vector<std::string>::iterator dit;
1864 for ( dit = depends.begin(); dit != depends.end(); ++ dit )
1866 target.AddUtility(dit->c_str());
1868 return target;
1871 //----------------------------------------------------------------------------
1872 void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
1873 const char*, std::string&)
1875 // Subclasses that support multiple configurations should implement
1876 // this method to append the subdirectory for the given build
1877 // configuration.
1880 //----------------------------------------------------------------------------
1881 cmGlobalGenerator::TargetDependSet &
1882 cmGlobalGenerator::GetTargetDirectDepends(cmTarget & target)
1884 return this->TargetDependencies[&target];
1887 void cmGlobalGenerator::AddTarget(cmTargets::value_type &v)
1889 assert(!v.second.IsImported());
1890 this->TotalTargets[v.first] = &v.second;
1893 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
1894 cmExternalMakefileProjectGenerator *extraGenerator)
1896 this->ExtraGenerator = extraGenerator;
1897 if (this->ExtraGenerator!=0)
1899 this->ExtraGenerator->SetGlobalGenerator(this);
1903 const char* cmGlobalGenerator::GetExtraGeneratorName() const
1905 return this->ExtraGenerator==0 ? 0 : this->ExtraGenerator->GetName();
1908 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string& filename)
1910 this->FilesReplacedDuringGenerate.push_back(filename);
1913 void
1914 cmGlobalGenerator
1915 ::GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames)
1917 filenames.clear();
1918 std::copy(
1919 this->FilesReplacedDuringGenerate.begin(),
1920 this->FilesReplacedDuringGenerate.end(),
1921 std::back_inserter(filenames));
1924 void
1925 cmGlobalGenerator
1926 ::GetTargetSets(cmGlobalGenerator::TargetDependSet& projectTargets,
1927 cmGlobalGenerator::TargetDependSet& originalTargets,
1928 cmLocalGenerator* root,
1929 std::vector<cmLocalGenerator*> const& generators)
1931 // loop over all local generators
1932 for(std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
1933 i != generators.end(); ++i)
1935 // check to make sure generator is not excluded
1936 if(this->IsExcluded(root, *i))
1938 continue;
1940 cmMakefile* mf = (*i)->GetMakefile();
1941 // Get the targets in the makefile
1942 cmTargets &tgts = mf->GetTargets();
1943 // loop over all the targets
1944 for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
1946 cmTarget* target = &l->second;
1947 // put the target in the set of original targets
1948 originalTargets.insert(target);
1949 // Get the set of targets that depend on target
1950 this->AddTargetDepends(target,
1951 projectTargets);
1956 void
1957 cmGlobalGenerator::AddTargetDepends(cmTarget* target,
1958 cmGlobalGenerator::TargetDependSet&
1959 projectTargets)
1961 // add the target itself
1962 projectTargets.insert(target);
1963 // get the direct depends of target
1964 cmGlobalGenerator::TargetDependSet const& tset
1965 = this->GetTargetDirectDepends(*target);
1966 if(tset.size())
1968 // if there are targets that depend on target
1969 // add them and their depends as well
1970 for(cmGlobalGenerator::TargetDependSet::const_iterator i =
1971 tset.begin(); i != tset.end(); ++i)
1973 cmTarget* dtarget = *i;
1974 this->AddTargetDepends(dtarget, projectTargets);
1980 //----------------------------------------------------------------------------
1981 void cmGlobalGenerator::AddToManifest(const char* config,
1982 std::string const& f)
1984 // Add to the main manifest for this configuration.
1985 this->TargetManifest[config].insert(f);
1987 // Add to the content listing for the file's directory.
1988 std::string dir = cmSystemTools::GetFilenamePath(f);
1989 std::string file = cmSystemTools::GetFilenameName(f);
1990 this->DirectoryContentMap[dir].insert(file);
1993 //----------------------------------------------------------------------------
1994 std::set<cmStdString> const&
1995 cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
1997 DirectoryContent& dc = this->DirectoryContentMap[dir];
1998 if(needDisk && !dc.LoadedFromDisk)
2000 // Load the directory content from disk.
2001 cmsys::Directory d;
2002 if(d.Load(dir.c_str()))
2004 unsigned long n = d.GetNumberOfFiles();
2005 for(unsigned long i = 0; i < n; ++i)
2007 const char* f = d.GetFile(i);
2008 if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
2010 dc.insert(f);
2014 dc.LoadedFromDisk = true;
2016 return dc;
2019 //----------------------------------------------------------------------------
2020 void
2021 cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
2022 std::string const& content)
2024 #if defined(CMAKE_BUILD_WITH_CMAKE)
2025 // Ignore if there are no outputs.
2026 if(outputs.empty())
2028 return;
2031 // Compute a hash of the rule.
2032 RuleHash hash;
2034 unsigned char const* data =
2035 reinterpret_cast<unsigned char const*>(content.c_str());
2036 int length = static_cast<int>(content.length());
2037 cmsysMD5* sum = cmsysMD5_New();
2038 cmsysMD5_Initialize(sum);
2039 cmsysMD5_Append(sum, data, length);
2040 cmsysMD5_FinalizeHex(sum, hash.Data);
2041 cmsysMD5_Delete(sum);
2044 // Shorten the output name (in expected use case).
2045 cmLocalGenerator* lg = this->GetLocalGenerators()[0];
2046 std::string fname = lg->Convert(outputs[0].c_str(),
2047 cmLocalGenerator::HOME_OUTPUT);
2049 // Associate the hash with this output.
2050 this->RuleHashes[fname] = hash;
2051 #else
2052 (void)outputs;
2053 (void)content;
2054 #endif
2057 //----------------------------------------------------------------------------
2058 void cmGlobalGenerator::CheckRuleHashes()
2060 #if defined(CMAKE_BUILD_WITH_CMAKE)
2061 std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
2062 std::string pfile = home;
2063 pfile += this->GetCMakeInstance()->GetCMakeFilesDirectory();
2064 pfile += "/CMakeRuleHashes.txt";
2066 #if defined(_WIN32) || defined(__CYGWIN__)
2067 std::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
2068 #else
2069 std::ifstream fin(pfile.c_str(), std::ios::in);
2070 #endif
2071 std::string line;
2072 std::string fname;
2073 while(cmSystemTools::GetLineFromStream(fin, line))
2075 // Line format is a 32-byte hex string followed by a space
2076 // followed by a file name (with no escaping).
2078 // Skip blank and comment lines.
2079 if(line.size() < 34 || line[0] == '#')
2081 continue;
2084 // Get the filename.
2085 fname = line.substr(33, line.npos);
2087 // Look for a hash for this file's rule.
2088 std::map<cmStdString, RuleHash>::const_iterator rhi =
2089 this->RuleHashes.find(fname);
2090 if(rhi != this->RuleHashes.end())
2092 // Compare the rule hash in the file to that we were given.
2093 if(strncmp(line.c_str(), rhi->second.Data, 32) != 0)
2095 // The rule has changed. Delete the output so it will be
2096 // built again.
2097 fname = cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
2098 cmSystemTools::RemoveFile(fname.c_str());
2101 else
2103 // We have no hash for a rule previously listed. This may be a
2104 // case where a user has turned off a build option and might
2105 // want to turn it back on later, so do not delete the file.
2106 // Instead, we keep the rule hash as long as the file exists so
2107 // that if the feature is turned back on and the rule has
2108 // changed the file is still rebuilt.
2109 std::string fpath =
2110 cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
2111 if(cmSystemTools::FileExists(fpath.c_str()))
2113 RuleHash hash;
2114 strncpy(hash.Data, line.c_str(), 32);
2115 this->RuleHashes[fname] = hash;
2120 // Now generate a new persistence file with the current hashes.
2121 if(this->RuleHashes.empty())
2123 cmSystemTools::RemoveFile(pfile.c_str());
2125 else
2127 cmGeneratedFileStream fout(pfile.c_str());
2128 fout << "# Hashes of file build rules.\n";
2129 for(std::map<cmStdString, RuleHash>::const_iterator
2130 rhi = this->RuleHashes.begin(); rhi != this->RuleHashes.end(); ++rhi)
2132 fout.write(rhi->second.Data, 32);
2133 fout << " " << rhi->first << "\n";
2136 #endif
2139 //----------------------------------------------------------------------------
2140 void cmGlobalGenerator::WriteSummary()
2142 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
2144 // Record all target directories in a central location.
2145 std::string fname = mf->GetHomeOutputDirectory();
2146 fname += cmake::GetCMakeFilesDirectory();
2147 fname += "/TargetDirectories.txt";
2148 cmGeneratedFileStream fout(fname.c_str());
2150 // Generate summary information files for each target.
2151 std::string dir;
2152 for(std::map<cmStdString,cmTarget *>::const_iterator ti =
2153 this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti)
2155 this->WriteSummary(ti->second);
2156 fout << ti->second->GetSupportDirectory() << "\n";
2160 //----------------------------------------------------------------------------
2161 void cmGlobalGenerator::WriteSummary(cmTarget* target)
2163 // Place the labels file in a per-target support directory.
2164 std::string dir = target->GetSupportDirectory();
2165 std::string file = dir;
2166 file += "/Labels.txt";
2168 // Check whether labels are enabled for this target.
2169 if(const char* value = target->GetProperty("LABELS"))
2171 cmSystemTools::MakeDirectory(dir.c_str());
2172 cmGeneratedFileStream fout(file.c_str());
2174 // List the target-wide labels. All sources in the target get
2175 // these labels.
2176 std::vector<std::string> labels;
2177 cmSystemTools::ExpandListArgument(value, labels);
2178 if(!labels.empty())
2180 fout << "# Target labels\n";
2181 for(std::vector<std::string>::const_iterator li = labels.begin();
2182 li != labels.end(); ++li)
2184 fout << " " << *li << "\n";
2188 // List the source files with any per-source labels.
2189 fout << "# Source files and their labels\n";
2190 std::vector<cmSourceFile*> const& sources = target->GetSourceFiles();
2191 for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
2192 si != sources.end(); ++si)
2194 cmSourceFile* sf = *si;
2195 fout << sf->GetFullPath() << "\n";
2196 if(const char* svalue = sf->GetProperty("LABELS"))
2198 labels.clear();
2199 cmSystemTools::ExpandListArgument(svalue, labels);
2200 for(std::vector<std::string>::const_iterator li = labels.begin();
2201 li != labels.end(); ++li)
2203 fout << " " << *li << "\n";
2208 else
2210 cmSystemTools::RemoveFile(file.c_str());