1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalGenerator.cxx,v $
6 Date: $Date: 2008-10-01 16:45:49 $
7 Version: $Revision: 1.244 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #if defined(_WIN32) && !defined(__CYGWIN__)
18 #include "windows.h" // this must be first to define GetCurrentDirectory
21 #include "cmGlobalGenerator.h"
22 #include "cmLocalGenerator.h"
23 #include "cmExternalMakefileProjectGenerator.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>
38 #include <stdlib.h> // required for atof
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)
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")))
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();
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
)
121 cmSystemTools::SplitProgramPath(makeProgram
.c_str(),
123 std::string saveFile
= file
;
124 cmSystemTools::GetShortPath(makeProgram
.c_str(), makeProgram
);
125 cmSystemTools::SplitProgramPath(makeProgram
.c_str(),
129 makeProgram
+= saveFile
;
130 mf
->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram
.c_str(),
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",
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
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
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();
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
)
221 this->SetLanguageEnabled("NONE", mf
);
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. */
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());
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
266 fpath
+= "/CMakeSystem.cmake";
267 mf
->ReadListFile(0,fpath
.c_str());
269 std::map
<cmStdString
, bool> needTestLanguage
;
270 std::map
<cmStdString
, bool> needSetLanguageEnabledMaps
;
272 // load the CMakeDetermine(LANG)Compiler.cmake file to find
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;
282 this->SetLanguageEnabled("NONE", mf
);
285 std::string loadedLang
= "CMAKE_";
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()))
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:",
310 // if this file was found then the language was already determined
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_";
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
;
360 cmSystemTools::PutEnv(env
.c_str());
363 // if determineLanguage was called then load the file it
364 // configures CMake(LANG)Compiler.cmake
368 fpath
+= "Compiler.cmake";
369 if(!mf
->ReadListFile(0,fpath
.c_str()))
371 cmSystemTools::Error("Could not find cmake module file:",
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
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:",
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();
402 this->SetLanguageEnabled("NONE", mf
);
405 std::string langLoadedVar
= "CMAKE_";
406 langLoadedVar
+= lang
;
407 langLoadedVar
+= "_INFORMATION_LOADED";
408 if (!mf
->GetDefinition(langLoadedVar
.c_str()))
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:",
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";
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:",
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());
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)
484 mf
->GetModulesFile("CMakeBackwardCompatibilityC.cmake");
485 mf
->ReadListFile(0,ifpath
.c_str());
487 if(strcmp(lang
, "CXX") == 0)
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
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 //----------------------------------------------------------------------------
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();
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();
531 if(this->OutputExtensions
.count(ext
))
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
== '.')
549 if(this->ExtensionToLanguage
.count(ext
) > 0)
551 return this->ExtensionToLanguage
[ext
].c_str();
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
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
590 if (this->LanguageToLinkerPreference
.find(l
) !=
591 this->LanguageToLinkerPreference
.end())
596 std::string linkerPrefVar
= std::string("CMAKE_") +
597 std::string(l
) + std::string("_LINKER_PREFERENCE");
598 const char* linkerPref
= mf
->GetDefinition(linkerPrefVar
.c_str());
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')
621 std::string msg
= linkerPrefVar
;
622 msg
+= " is negative, adjusting it to 0";
623 cmSystemTools::Message(msg
.c_str(), "Warning");
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());
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
,
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
))
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
,
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())
718 void cmGlobalGenerator::Configure()
720 this->FirstTimeProgress
= 0.0f
;
721 this->ClearExportSets();
722 // Delete any existing cmLocalGenerators
724 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
726 delete this->LocalGenerators
[i
];
728 this->LocalGenerators
.clear();
729 this->TargetDependencies
.clear();
730 this->TotalTargets
.clear();
731 this->LocalGeneratorToTargetMap
.clear();
732 this->ProjectMap
.clear();
733 this->RuleHashes
.clear();
734 this->DirectoryContentMap
.clear();
736 // start with this directory
737 cmLocalGenerator
*lg
= this->CreateLocalGenerator();
738 this->LocalGenerators
.push_back(lg
);
740 // set the Start directories
741 lg
->GetMakefile()->SetStartDirectory
742 (this->CMakeInstance
->GetStartDirectory());
743 lg
->GetMakefile()->SetStartOutputDirectory
744 (this->CMakeInstance
->GetStartOutputDirectory());
745 lg
->GetMakefile()->MakeStartDirectoriesCurrent();
750 // update the cache entry for the number of local generators, this is used
753 sprintf(num
,"%d",static_cast<int>(this->LocalGenerators
.size()));
754 this->GetCMakeInstance()->AddCacheEntry
755 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num
,
756 "number of local generators", cmCacheManager::INTERNAL
);
758 // check for link libraries and include directories containing "NOTFOUND"
759 // and for infinite loops
760 this->CheckLocalGenerators();
762 // at this point this->LocalGenerators has been filled,
763 // so create the map from project name to vector of local generators
764 this->FillProjectMap();
766 if ( !this->CMakeInstance
->GetScriptMode() )
768 const char* msg
= "Configuring done";
769 if(cmSystemTools::GetErrorOccuredFlag())
771 msg
= "Configuring incomplete, errors occurred!";
773 this->CMakeInstance
->UpdateProgress(msg
, -1);
777 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
779 // If the property is not enabled then okay.
780 if(!this->CMakeInstance
781 ->GetPropertyAsBool("ALLOW_DUPLICATE_CUSTOM_TARGETS"))
786 // This generator does not support duplicate custom targets.
788 e
<< "This project has enabled the ALLOW_DUPLICATE_CUSTOM_TARGETS "
789 << "global property. "
790 << "The \"" << this->GetName() << "\" generator does not support "
791 << "duplicate custom targets. "
792 << "Consider using a Makefiles generator or fix the project to not "
793 << "use duplicat target names.";
794 cmSystemTools::Error(e
.str().c_str());
798 void cmGlobalGenerator::Generate()
800 // Some generators track files replaced during the Generate.
801 // Start with an empty vector:
802 this->FilesReplacedDuringGenerate
.clear();
804 // Check whether this generator is allowed to run.
805 if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
810 // Check that all targets are valid.
811 if(!this->CheckTargets())
816 // For each existing cmLocalGenerator
819 // Consolidate global targets
820 cmTargets globalTargets
;
821 this->CreateDefaultGlobalTargets(&globalTargets
);
822 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
825 &(this->LocalGenerators
[i
]->GetMakefile()->GetTargets());
826 cmTargets::iterator tarIt
;
827 for ( tarIt
= targets
->begin(); tarIt
!= targets
->end(); ++ tarIt
)
829 if ( tarIt
->second
.GetType() == cmTarget::GLOBAL_TARGET
)
831 globalTargets
[tarIt
->first
] = tarIt
->second
;
835 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
837 cmMakefile
* mf
= this->LocalGenerators
[i
]->GetMakefile();
838 cmTargets
* targets
= &(mf
->GetTargets());
839 cmTargets::iterator tit
;
840 for ( tit
= globalTargets
.begin(); tit
!= globalTargets
.end(); ++ tit
)
842 (*targets
)[tit
->first
] = tit
->second
;
843 (*targets
)[tit
->first
].SetMakefile(mf
);
847 // Add generator specific helper commands
848 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
850 this->LocalGenerators
[i
]->AddHelperCommands();
853 // Trace the dependencies, after that no custom commands should be added
854 // because their dependencies might not be handled correctly
855 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
857 this->LocalGenerators
[i
]->TraceDependencies();
860 // Compute the manifest of main targets generated.
861 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
863 this->LocalGenerators
[i
]->GenerateTargetManifest();
866 // Compute the inter-target dependencies.
868 cmComputeTargetDepends
ctd(this);
873 std::vector
<cmTarget
*> const& targets
= ctd
.GetTargets();
874 for(std::vector
<cmTarget
*>::const_iterator ti
= targets
.begin();
875 ti
!= targets
.end(); ++ti
)
877 ctd
.GetTargetDirectDepends(*ti
, this->TargetDependencies
[*ti
]);
881 // Create a map from local generator to the complete set of targets
882 // it builds by default.
883 this->FillLocalGeneratorToTargetMap();
885 // Generate project files
886 for (i
= 0; i
< this->LocalGenerators
.size(); ++i
)
888 this->SetCurrentLocalGenerator(this->LocalGenerators
[i
]);
889 this->LocalGenerators
[i
]->Generate();
890 this->LocalGenerators
[i
]->GenerateInstallRules();
891 this->LocalGenerators
[i
]->GenerateTestFiles();
892 this->CMakeInstance
->UpdateProgress("Generating",
893 (i
+1.0f
)/this->LocalGenerators
.size());
895 this->SetCurrentLocalGenerator(0);
897 // Update rule hashes.
898 this->CheckRuleHashes();
900 if (this->ExtraGenerator
!= 0)
902 this->ExtraGenerator
->Generate();
905 this->CMakeInstance
->UpdateProgress("Generating done", -1);
908 //----------------------------------------------------------------------------
909 bool cmGlobalGenerator::CheckTargets()
911 // Make sure all targets can find their source files.
912 for(unsigned int i
=0; i
< this->LocalGenerators
.size(); ++i
)
915 this->LocalGenerators
[i
]->GetMakefile()->GetTargets();
916 for(cmTargets::iterator ti
= targets
.begin();
917 ti
!= targets
.end(); ++ti
)
919 cmTarget
& target
= ti
->second
;
920 if(target
.GetType() == cmTarget::EXECUTABLE
||
921 target
.GetType() == cmTarget::STATIC_LIBRARY
||
922 target
.GetType() == cmTarget::SHARED_LIBRARY
||
923 target
.GetType() == cmTarget::MODULE_LIBRARY
||
924 target
.GetType() == cmTarget::UTILITY
)
926 if(!target
.FindSourceFiles())
936 void cmGlobalGenerator::CheckLocalGenerators()
938 std::map
<cmStdString
, cmStdString
> notFoundMap
;
939 // std::set<cmStdString> notFoundMap;
940 // after it is all done do a ConfigureFinalPass
941 cmCacheManager
* manager
= 0;
942 for (unsigned int i
= 0; i
< this->LocalGenerators
.size(); ++i
)
944 manager
= this->LocalGenerators
[i
]->GetMakefile()->GetCacheManager();
945 this->LocalGenerators
[i
]->ConfigureFinalPass();
946 const cmTargets
& targets
=
947 this->LocalGenerators
[i
]->GetMakefile()->GetTargets();
948 for (cmTargets::const_iterator l
= targets
.begin();
949 l
!= targets
.end(); l
++)
951 const cmTarget::LinkLibraryVectorType
& libs
=
952 l
->second
.GetOriginalLinkLibraries();
953 for(cmTarget::LinkLibraryVectorType::const_iterator lib
= libs
.begin();
954 lib
!= libs
.end(); ++lib
)
956 if(lib
->first
.size() > 9 &&
957 cmSystemTools::IsNOTFOUND(lib
->first
.c_str()))
959 std::string varName
= lib
->first
.substr(0, lib
->first
.size()-9);
960 cmCacheManager::CacheIterator it
=
961 manager
->GetCacheIterator(varName
.c_str());
962 if(it
.GetPropertyAsBool("ADVANCED"))
964 varName
+= " (ADVANCED)";
966 std::string text
= notFoundMap
[varName
];
967 text
+= "\n linked by target \"";
968 text
+= l
->second
.GetName();
969 text
+= "\" in directory ";
970 text
+=this->LocalGenerators
[i
]->GetMakefile()->GetCurrentDirectory();
971 notFoundMap
[varName
] = text
;
975 const std::vector
<std::string
>& incs
=
976 this->LocalGenerators
[i
]->GetMakefile()->GetIncludeDirectories();
978 for( std::vector
<std::string
>::const_iterator incDir
= incs
.begin();
979 incDir
!= incs
.end(); ++incDir
)
981 if(incDir
->size() > 9 &&
982 cmSystemTools::IsNOTFOUND(incDir
->c_str()))
984 std::string varName
= incDir
->substr(0, incDir
->size()-9);
985 cmCacheManager::CacheIterator it
=
986 manager
->GetCacheIterator(varName
.c_str());
987 if(it
.GetPropertyAsBool("ADVANCED"))
989 varName
+= " (ADVANCED)";
991 std::string text
= notFoundMap
[varName
];
992 text
+= "\n used as include directory in directory ";
993 text
+= this->LocalGenerators
[i
]->GetMakefile()->GetCurrentDirectory();
994 notFoundMap
[varName
] = text
;
997 this->CMakeInstance
->UpdateProgress
998 ("Configuring", 0.9f
+0.1f
*(i
+1.0f
)/this->LocalGenerators
.size());
1001 if(notFoundMap
.size())
1003 std::string notFoundVars
;
1004 for(std::map
<cmStdString
, cmStdString
>::const_iterator
1005 ii
= notFoundMap
.begin();
1006 ii
!= notFoundMap
.end();
1009 notFoundVars
+= ii
->first
;
1010 notFoundVars
+= ii
->second
;
1011 notFoundVars
+= "\n";
1013 cmSystemTools::Error("The following variables are used in this project, "
1014 "but they are set to NOTFOUND.\n"
1015 "Please set them or make sure they are set and "
1016 "tested correctly in the CMake files:\n",
1017 notFoundVars
.c_str());
1021 int cmGlobalGenerator::TryCompile(const char *srcdir
, const char *bindir
,
1022 const char *projectName
,
1024 std::string
*output
, cmMakefile
*mf
)
1026 // if this is not set, then this is a first time configure
1027 // and there is a good chance that the try compile stuff will
1028 // take the bulk of the time, so try and guess some progress
1029 // by getting closer and closer to 100 without actually getting there.
1030 if (!this->CMakeInstance
->GetCacheManager()->GetCacheValue
1031 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
1033 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1034 // we are in the first time progress and we have no
1035 // idea how long it will be. So, just move 1/10th of the way
1036 // there each time, and don't go over 95%
1037 this->FirstTimeProgress
+= ((1.0f
- this->FirstTimeProgress
) /30.0f
);
1038 if(this->FirstTimeProgress
> 0.95f
)
1040 this->FirstTimeProgress
= 0.95f
;
1042 this->CMakeInstance
->UpdateProgress("Configuring",
1043 this->FirstTimeProgress
);
1046 std::string makeCommand
= this->CMakeInstance
->
1047 GetCacheManager()->GetCacheValue("CMAKE_MAKE_PROGRAM");
1048 if(makeCommand
.size() == 0)
1050 cmSystemTools::Error(
1051 "Generator cannot find the appropriate make command.");
1055 std::string newTarget
;
1056 if (target
&& strlen(target
))
1058 newTarget
+= target
;
1060 #if defined(_WIN32) || defined(__CYGWIN__)
1061 std::string tmp
= target
;
1062 // if the target does not already end in . something
1064 if(tmp
.size() < 4 || tmp
[tmp
.size()-4] != '.')
1066 newTarget
+= ".exe";
1071 const char* config
= mf
->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
1072 return this->Build(srcdir
,bindir
,projectName
,
1074 output
,makeCommand
.c_str(),config
,false,true,
1075 this->TryCompileTimeout
);
1078 std::string cmGlobalGenerator
1079 ::GenerateBuildCommand(const char* makeProgram
, const char *projectName
,
1080 const char* additionalOptions
, const char *targetName
,
1081 const char* config
, bool ignoreErrors
, bool)
1083 // Project name and config are not used yet.
1087 std::string makeCommand
=
1088 cmSystemTools::ConvertToUnixOutputPath(makeProgram
);
1090 // Since we have full control over the invocation of nmake, let us
1092 if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
1094 makeCommand
+= " /NOLOGO ";
1098 makeCommand
+= " -i";
1100 if ( additionalOptions
)
1103 makeCommand
+= additionalOptions
;
1108 makeCommand
+= targetName
;
1113 int cmGlobalGenerator::Build(
1114 const char *, const char *bindir
,
1115 const char *projectName
, const char *target
,
1116 std::string
*output
,
1117 const char *makeCommandCSTR
,
1119 bool clean
, bool fast
,
1123 * Run an executable command and put the stdout in output.
1125 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
1126 cmSystemTools::ChangeDirectory(bindir
);
1129 *output
+= "Change Dir: ";
1135 bool hideconsole
= cmSystemTools::GetRunCommandHideConsole();
1136 cmSystemTools::SetRunCommandHideConsole(true);
1137 std::string outputBuffer
;
1138 std::string
* outputPtr
= 0;
1141 outputPtr
= &outputBuffer
;
1144 // should we do a clean first?
1147 std::string cleanCommand
=
1148 this->GenerateBuildCommand(makeCommandCSTR
, projectName
,
1149 0, "clean", config
, false, fast
);
1152 *output
+= "\nRun Clean Command:";
1153 *output
+= cleanCommand
;
1157 if (!cmSystemTools::RunSingleCommand(cleanCommand
.c_str(), outputPtr
,
1158 &retVal
, 0, false, timeout
))
1160 cmSystemTools::SetRunCommandHideConsole(hideconsole
);
1161 cmSystemTools::Error("Generator: execution of make clean failed.");
1164 *output
+= *outputPtr
;
1165 *output
+= "\nGenerator: execution of make clean failed.\n";
1168 // return to the original directory
1169 cmSystemTools::ChangeDirectory(cwd
.c_str());
1174 *output
+= *outputPtr
;
1179 std::string makeCommand
=
1180 this->GenerateBuildCommand(makeCommandCSTR
, projectName
,
1181 0, target
, config
, false, fast
);
1184 *output
+= "\nRun Build Command:";
1185 *output
+= makeCommand
;
1189 if (!cmSystemTools::RunSingleCommand(makeCommand
.c_str(), outputPtr
,
1190 &retVal
, 0, false, timeout
))
1192 cmSystemTools::SetRunCommandHideConsole(hideconsole
);
1193 cmSystemTools::Error
1194 ("Generator: execution of make failed. Make command was: ",
1195 makeCommand
.c_str());
1198 *output
+= *outputPtr
;
1199 *output
+= "\nGenerator: execution of make failed. Make command was: "
1200 + makeCommand
+ "\n";
1203 // return to the original directory
1204 cmSystemTools::ChangeDirectory(cwd
.c_str());
1209 *output
+= *outputPtr
;
1211 cmSystemTools::SetRunCommandHideConsole(hideconsole
);
1213 // The SGI MipsPro 7.3 compiler does not return an error code when
1214 // the source has a #error in it! This is a work-around for such
1216 if((retVal
== 0) && (output
->find("#error") != std::string::npos
))
1221 cmSystemTools::ChangeDirectory(cwd
.c_str());
1225 void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator
*lg
)
1227 this->LocalGenerators
.push_back(lg
);
1230 // estimate how many lg there will be
1231 const char *numGenC
=
1232 this->CMakeInstance
->GetCacheManager()->GetCacheValue
1233 ("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
1237 // If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
1238 // we are in the first time progress and we have no
1239 // idea how long it will be. So, just move half way
1240 // there each time, and don't go over 95%
1241 this->FirstTimeProgress
+= ((1.0f
- this->FirstTimeProgress
) /30.0f
);
1242 if(this->FirstTimeProgress
> 0.95f
)
1244 this->FirstTimeProgress
= 0.95f
;
1246 this->CMakeInstance
->UpdateProgress("Configuring",
1247 this->FirstTimeProgress
);
1251 int numGen
= atoi(numGenC
);
1252 float prog
= 0.9f
*this->LocalGenerators
.size()/numGen
;
1257 this->CMakeInstance
->UpdateProgress("Configuring", prog
);
1260 void cmGlobalGenerator::AddInstallComponent(const char* component
)
1262 if(component
&& *component
)
1264 this->InstallComponents
.insert(component
);
1268 void cmGlobalGenerator::AddTargetToExports(const char* exportSetName
,
1270 cmInstallTargetGenerator
* archive
,
1271 cmInstallTargetGenerator
* runTime
,
1272 cmInstallTargetGenerator
* library
,
1273 cmInstallTargetGenerator
* framework
,
1274 cmInstallTargetGenerator
* bundle
,
1275 cmInstallFilesGenerator
* headers
)
1277 if ((exportSetName
) && (*exportSetName
) && (target
))
1279 cmTargetExport
* te
= new cmTargetExport(target
, archive
, runTime
, library
,
1280 framework
, bundle
, headers
);
1281 this->ExportSets
[exportSetName
].push_back(te
);
1285 //----------------------------------------------------------------------------
1286 void cmGlobalGenerator::ClearExportSets()
1288 for(std::map
<cmStdString
, std::vector
<cmTargetExport
*> >::iterator
1289 setIt
= this->ExportSets
.begin();
1290 setIt
!= this->ExportSets
.end(); ++setIt
)
1292 for(unsigned int i
= 0; i
< setIt
->second
.size(); ++i
)
1294 delete setIt
->second
[i
];
1297 this->ExportSets
.clear();
1300 const std::vector
<cmTargetExport
*>* cmGlobalGenerator::GetExportSet(
1301 const char* name
) const
1303 std::map
<cmStdString
, std::vector
<cmTargetExport
*> >::const_iterator
1304 exportSetIt
= this->ExportSets
.find(name
);
1305 if (exportSetIt
!= this->ExportSets
.end())
1307 return &exportSetIt
->second
;
1314 void cmGlobalGenerator::EnableInstallTarget()
1316 this->InstallTargetEnabled
= true;
1319 cmLocalGenerator
*cmGlobalGenerator::CreateLocalGenerator()
1321 cmLocalGenerator
*lg
= new cmLocalGenerator
;
1322 lg
->SetGlobalGenerator(this);
1326 void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator
*gen
)
1328 std::string cfp
= gen
->GetCMakeInstance()->GetHomeOutputDirectory();
1329 cfp
+= cmake::GetCMakeFilesDirectory();
1330 this->SetConfiguredFilesPath(cfp
.c_str());
1332 gen
->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
1333 this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", make
,
1335 cmCacheManager::FILEPATH
);
1336 // copy the enabled languages
1337 this->LanguageEnabled
= gen
->LanguageEnabled
;
1338 this->ExtensionToLanguage
= gen
->ExtensionToLanguage
;
1339 this->IgnoreExtensions
= gen
->IgnoreExtensions
;
1340 this->LanguageToOutputExtension
= gen
->LanguageToOutputExtension
;
1341 this->LanguageToLinkerPreference
= gen
->LanguageToLinkerPreference
;
1342 this->OutputExtensions
= gen
->OutputExtensions
;
1345 //----------------------------------------------------------------------------
1346 void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry
& entry
) const
1348 entry
.Name
= this->GetName();
1353 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator
* root
,
1354 cmLocalGenerator
* gen
)
1356 if(!gen
|| gen
== root
)
1358 // No directory excludes itself.
1362 if(gen
->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1364 // This directory is excluded from its parent.
1368 // This directory is included in its parent. Check whether the
1369 // parent is excluded.
1370 return this->IsExcluded(root
, gen
->GetParent());
1373 bool cmGlobalGenerator::IsExcluded(cmLocalGenerator
* root
,
1376 if(target
.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
1378 // This target is excluded from its directory.
1383 // This target is included in its directory. Check whether the
1384 // directory is excluded.
1385 return this->IsExcluded(root
, target
.GetMakefile()->GetLocalGenerator());
1389 void cmGlobalGenerator::GetEnabledLanguages(std::vector
<std::string
>& lang
)
1391 for(std::map
<cmStdString
, bool>::iterator i
=
1392 this->LanguageEnabled
.begin(); i
!= this->LanguageEnabled
.end(); ++i
)
1394 lang
.push_back(i
->first
);
1398 int cmGlobalGenerator::GetLinkerPreference(const char* lang
)
1400 std::map
<cmStdString
, int>::const_iterator it
=
1401 this->LanguageToLinkerPreference
.find(lang
);
1402 if (it
!= this->LanguageToLinkerPreference
.end())
1409 void cmGlobalGenerator::FillProjectMap()
1411 this->ProjectMap
.clear(); // make sure we start with a clean map
1413 for(i
= 0; i
< this->LocalGenerators
.size(); ++i
)
1415 // for each local generator add all projects
1416 cmLocalGenerator
*lg
= this->LocalGenerators
[i
];
1420 if (name
!= lg
->GetMakefile()->GetProjectName())
1422 name
= lg
->GetMakefile()->GetProjectName();
1423 this->ProjectMap
[name
].push_back(this->LocalGenerators
[i
]);
1425 lg
= lg
->GetParent();
1432 // Build a map that contains a the set of targets used by each local
1433 // generator directory level.
1434 void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
1436 this->LocalGeneratorToTargetMap
.clear();
1437 // Loop over all targets in all local generators.
1438 for(std::vector
<cmLocalGenerator
*>::const_iterator
1439 lgi
= this->LocalGenerators
.begin();
1440 lgi
!= this->LocalGenerators
.end(); ++lgi
)
1442 cmLocalGenerator
* lg
= *lgi
;
1443 cmMakefile
* mf
= lg
->GetMakefile();
1444 cmTargets
& targets
= mf
->GetTargets();
1445 for(cmTargets::iterator t
= targets
.begin(); t
!= targets
.end(); ++t
)
1447 cmTarget
& target
= t
->second
;
1449 // Consider the directory containing the target and all its
1450 // parents until something excludes the target.
1451 for(cmLocalGenerator
* clg
= lg
; clg
&& !this->IsExcluded(clg
, target
);
1452 clg
= clg
->GetParent())
1454 // This local generator includes the target.
1455 std::set
<cmTarget
*>& targetSet
=
1456 this->LocalGeneratorToTargetMap
[clg
];
1457 targetSet
.insert(&target
);
1459 // Add dependencies of the included target. An excluded
1460 // target may still be included if it is a dependency of a
1461 // non-excluded target.
1462 TargetDependSet
& tgtdeps
= this->GetTargetDirectDepends(target
);
1463 for(TargetDependSet::const_iterator ti
= tgtdeps
.begin();
1464 ti
!= tgtdeps
.end(); ++ti
)
1466 targetSet
.insert(*ti
);
1474 ///! Find a local generator by its startdirectory
1475 cmLocalGenerator
* cmGlobalGenerator::FindLocalGenerator(const char* start_dir
)
1477 std::vector
<cmLocalGenerator
*>* gens
= &this->LocalGenerators
;
1478 for(unsigned int i
= 0; i
< gens
->size(); ++i
)
1480 std::string sd
= (*gens
)[i
]->GetMakefile()->GetStartDirectory();
1481 if (sd
== start_dir
)
1490 //----------------------------------------------------------------------------
1492 cmGlobalGenerator::FindTarget(const char* project
, const char* name
)
1494 // if project specific
1497 std::vector
<cmLocalGenerator
*>* gens
= &this->ProjectMap
[project
];
1498 for(unsigned int i
= 0; i
< gens
->size(); ++i
)
1500 cmTarget
* ret
= (*gens
)[i
]->GetMakefile()->FindTarget(name
);
1507 // if all projects/directories
1510 std::map
<cmStdString
,cmTarget
*>::iterator i
=
1511 this->TotalTargets
.find ( name
);
1512 if ( i
!= this->TotalTargets
.end() )
1520 //----------------------------------------------------------------------------
1521 bool cmGlobalGenerator::NameResolvesToFramework(const std::string
& libname
)
1523 if(cmSystemTools::IsPathToFramework(libname
.c_str()))
1528 if(cmTarget
* tgt
= this->FindTarget(0, libname
.c_str()))
1530 if(tgt
->IsFrameworkOnApple())
1539 //----------------------------------------------------------------------------
1540 inline std::string
removeQuotes(const std::string
& s
)
1542 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
1544 return s
.substr(1, s
.size()-2);
1549 void cmGlobalGenerator::SetCMakeInstance(cmake
* cm
)
1551 // Store a pointer to the cmake object instance.
1552 this->CMakeInstance
= cm
;
1555 void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets
* targets
)
1557 cmMakefile
* mf
= this->LocalGenerators
[0]->GetMakefile();
1558 const char* cmakeCfgIntDir
= this->GetCMakeCFGInitDirectory();
1559 const char* cmakeCommand
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
1562 std::string workingDir
= mf
->GetStartOutputDirectory();
1563 cmCustomCommandLines cpackCommandLines
;
1564 std::vector
<std::string
> depends
;
1565 cmCustomCommandLine singleLine
;
1566 singleLine
.push_back(this->GetCMakeInstance()->GetCPackCommand());
1567 if ( cmakeCfgIntDir
&& *cmakeCfgIntDir
&& cmakeCfgIntDir
[0] != '.' )
1569 singleLine
.push_back("-C");
1570 singleLine
.push_back(cmakeCfgIntDir
);
1572 singleLine
.push_back("--config");
1573 std::string configFile
= mf
->GetStartOutputDirectory();;
1574 configFile
+= "/CPackConfig.cmake";
1575 std::string relConfigFile
= "./CPackConfig.cmake";
1576 singleLine
.push_back(relConfigFile
);
1577 cpackCommandLines
.push_back(singleLine
);
1578 if ( this->GetPreinstallTargetName() )
1580 depends
.push_back(this->GetPreinstallTargetName());
1584 const char* noPackageAll
=
1585 mf
->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
1586 if(!noPackageAll
|| cmSystemTools::IsOff(noPackageAll
))
1588 depends
.push_back(this->GetAllTargetName());
1591 if(cmSystemTools::FileExists(configFile
.c_str()))
1593 (*targets
)[this->GetPackageTargetName()]
1594 = this->CreateGlobalTarget(this->GetPackageTargetName(),
1595 "Run CPack packaging tool...",
1596 &cpackCommandLines
, depends
,
1597 workingDir
.c_str());
1600 const char* packageSourceTargetName
= this->GetPackageSourceTargetName();
1601 if ( packageSourceTargetName
)
1603 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1604 cpackCommandLines
.end());
1605 singleLine
.erase(singleLine
.begin(), singleLine
.end());
1606 depends
.erase(depends
.begin(), depends
.end());
1607 singleLine
.push_back(this->GetCMakeInstance()->GetCPackCommand());
1608 singleLine
.push_back("--config");
1609 configFile
= mf
->GetStartOutputDirectory();;
1610 configFile
+= "/CPackSourceCConfig.cmake";
1611 relConfigFile
= "./CPackSourceConfig.cmake";
1612 singleLine
.push_back(relConfigFile
);
1613 if(cmSystemTools::FileExists(configFile
.c_str()))
1615 singleLine
.push_back(configFile
);
1616 cpackCommandLines
.push_back(singleLine
);
1617 (*targets
)[packageSourceTargetName
]
1618 = this->CreateGlobalTarget(packageSourceTargetName
,
1619 "Run CPack packaging tool for source...",
1620 &cpackCommandLines
, depends
,
1627 if(mf
->IsOn("CMAKE_TESTING_ENABLED"))
1629 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1630 cpackCommandLines
.end());
1631 singleLine
.erase(singleLine
.begin(), singleLine
.end());
1632 depends
.erase(depends
.begin(), depends
.end());
1633 singleLine
.push_back(this->GetCMakeInstance()->GetCTestCommand());
1634 singleLine
.push_back("--force-new-ctest-process");
1635 if(cmakeCfgIntDir
&& *cmakeCfgIntDir
&& cmakeCfgIntDir
[0] != '.')
1637 singleLine
.push_back("-C");
1638 singleLine
.push_back(cmakeCfgIntDir
);
1640 else // TODO: This is a hack. Should be something to do with the generator
1642 singleLine
.push_back("$(ARGS)");
1644 cpackCommandLines
.push_back(singleLine
);
1645 (*targets
)[this->GetTestTargetName()]
1646 = this->CreateGlobalTarget(this->GetTestTargetName(),
1647 "Running tests...", &cpackCommandLines
, depends
, 0);
1651 const char* editCacheTargetName
= this->GetEditCacheTargetName();
1652 if ( editCacheTargetName
)
1654 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1655 cpackCommandLines
.end());
1656 singleLine
.erase(singleLine
.begin(), singleLine
.end());
1657 depends
.erase(depends
.begin(), depends
.end());
1659 // Use CMAKE_EDIT_COMMAND for the edit_cache rule if it is defined.
1660 // Otherwise default to the interactive command-line interface.
1661 if(mf
->GetDefinition("CMAKE_EDIT_COMMAND"))
1663 singleLine
.push_back(mf
->GetDefinition("CMAKE_EDIT_COMMAND"));
1664 singleLine
.push_back("-H$(CMAKE_SOURCE_DIR)");
1665 singleLine
.push_back("-B$(CMAKE_BINARY_DIR)");
1666 cpackCommandLines
.push_back(singleLine
);
1667 (*targets
)[editCacheTargetName
] =
1668 this->CreateGlobalTarget(
1669 editCacheTargetName
, "Running CMake cache editor...",
1670 &cpackCommandLines
, depends
, 0);
1674 singleLine
.push_back(cmakeCommand
);
1675 singleLine
.push_back("-i");
1676 singleLine
.push_back(".");
1677 cpackCommandLines
.push_back(singleLine
);
1678 (*targets
)[editCacheTargetName
] =
1679 this->CreateGlobalTarget(
1680 editCacheTargetName
,
1681 "Running interactive CMake command-line interface...",
1682 &cpackCommandLines
, depends
, 0);
1687 const char* rebuildCacheTargetName
= this->GetRebuildCacheTargetName();
1688 if ( rebuildCacheTargetName
)
1690 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1691 cpackCommandLines
.end());
1692 singleLine
.erase(singleLine
.begin(), singleLine
.end());
1693 depends
.erase(depends
.begin(), depends
.end());
1694 singleLine
.push_back(cmakeCommand
);
1695 singleLine
.push_back("-H$(CMAKE_SOURCE_DIR)");
1696 singleLine
.push_back("-B$(CMAKE_BINARY_DIR)");
1697 cpackCommandLines
.push_back(singleLine
);
1698 (*targets
)[rebuildCacheTargetName
] =
1699 this->CreateGlobalTarget(
1700 rebuildCacheTargetName
, "Running CMake to regenerate build system...",
1701 &cpackCommandLines
, depends
, 0);
1705 if(this->InstallTargetEnabled
)
1707 if(!cmakeCfgIntDir
|| !*cmakeCfgIntDir
|| cmakeCfgIntDir
[0] == '.')
1709 std::set
<cmStdString
>* componentsSet
= &this->InstallComponents
;
1710 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1711 cpackCommandLines
.end());
1712 depends
.erase(depends
.begin(), depends
.end());
1713 cmOStringStream ostr
;
1714 if ( componentsSet
->size() > 0 )
1716 ostr
<< "Available install components are:";
1717 std::set
<cmStdString
>::iterator it
;
1719 it
= componentsSet
->begin();
1720 it
!= componentsSet
->end();
1723 ostr
<< " \"" << it
->c_str() << "\"";
1728 ostr
<< "Only default component available";
1730 singleLine
.push_back(ostr
.str().c_str());
1731 (*targets
)["list_install_components"]
1732 = this->CreateGlobalTarget("list_install_components",
1734 &cpackCommandLines
, depends
, 0);
1737 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1738 cpackCommandLines
.end());
1739 singleLine
.erase(singleLine
.begin(), singleLine
.end());
1740 depends
.erase(depends
.begin(), depends
.end());
1741 if ( this->GetPreinstallTargetName() )
1743 depends
.push_back(this->GetPreinstallTargetName());
1748 mf
->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
1749 if(!noall
|| cmSystemTools::IsOff(noall
))
1751 depends
.push_back(this->GetAllTargetName());
1754 if(mf
->GetDefinition("CMake_BINARY_DIR"))
1756 // We are building CMake itself. We cannot use the original
1757 // executable to install over itself.
1758 cmd
= mf
->GetDefinition("EXECUTABLE_OUTPUT_PATH");
1759 if(cmakeCfgIntDir
&& *cmakeCfgIntDir
&& cmakeCfgIntDir
[0] != '.')
1762 cmd
+= cmakeCfgIntDir
;
1770 singleLine
.push_back(cmd
.c_str());
1771 if ( cmakeCfgIntDir
&& *cmakeCfgIntDir
&& cmakeCfgIntDir
[0] != '.' )
1773 std::string cfgArg
= "-DBUILD_TYPE=";
1774 cfgArg
+= mf
->GetDefinition("CMAKE_CFG_INTDIR");
1775 singleLine
.push_back(cfgArg
);
1777 singleLine
.push_back("-P");
1778 singleLine
.push_back("cmake_install.cmake");
1779 cpackCommandLines
.push_back(singleLine
);
1780 (*targets
)[this->GetInstallTargetName()] =
1781 this->CreateGlobalTarget(
1782 this->GetInstallTargetName(), "Install the project...",
1783 &cpackCommandLines
, depends
, 0);
1786 if(const char* install_local
= this->GetInstallLocalTargetName())
1788 cmCustomCommandLine localCmdLine
= singleLine
;
1790 localCmdLine
.insert(localCmdLine
.begin()+1,
1791 "-DCMAKE_INSTALL_LOCAL_ONLY=1");
1792 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1793 cpackCommandLines
.end());
1794 cpackCommandLines
.push_back(localCmdLine
);
1796 (*targets
)[install_local
] =
1797 this->CreateGlobalTarget(
1798 install_local
, "Installing only the local directory...",
1799 &cpackCommandLines
, depends
, 0);
1803 const char* install_strip
= this->GetInstallStripTargetName();
1804 if((install_strip
!=0) && (mf
->IsSet("CMAKE_STRIP")))
1806 cmCustomCommandLine stripCmdLine
= singleLine
;
1808 stripCmdLine
.insert(stripCmdLine
.begin()+1,"-DCMAKE_INSTALL_DO_STRIP=1");
1809 cpackCommandLines
.erase(cpackCommandLines
.begin(),
1810 cpackCommandLines
.end());
1811 cpackCommandLines
.push_back(stripCmdLine
);
1813 (*targets
)[install_strip
] =
1814 this->CreateGlobalTarget(
1815 install_strip
, "Installing the project stripped...",
1816 &cpackCommandLines
, depends
, 0);
1821 cmTarget
cmGlobalGenerator::CreateGlobalTarget(
1822 const char* name
, const char* message
,
1823 const cmCustomCommandLines
* commandLines
,
1824 std::vector
<std::string
> depends
,
1825 const char* workingDirectory
,
1826 bool depends_on_all
/* = false */)
1830 target
.GetProperties().SetCMakeInstance(this->CMakeInstance
);
1831 target
.SetType(cmTarget::GLOBAL_TARGET
, name
);
1832 target
.SetProperty("EXCLUDE_FROM_ALL","TRUE");
1834 std::vector
<std::string
> no_outputs
;
1835 std::vector
<std::string
> no_depends
;
1836 // Store the custom command in the target.
1837 cmCustomCommand
cc(no_outputs
, no_depends
, *commandLines
, 0,
1839 target
.GetPostBuildCommands().push_back(cc
);
1840 target
.SetProperty("EchoString", message
);
1841 if ( depends_on_all
)
1843 target
.AddUtility("all");
1845 std::vector
<std::string
>::iterator dit
;
1846 for ( dit
= depends
.begin(); dit
!= depends
.end(); ++ dit
)
1848 target
.AddUtility(dit
->c_str());
1853 //----------------------------------------------------------------------------
1854 void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
1855 const char*, std::string
&)
1857 // Subclasses that support multiple configurations should implement
1858 // this method to append the subdirectory for the given build
1862 //----------------------------------------------------------------------------
1863 cmGlobalGenerator::TargetDependSet
&
1864 cmGlobalGenerator::GetTargetDirectDepends(cmTarget
& target
)
1866 return this->TargetDependencies
[&target
];
1869 void cmGlobalGenerator::AddTarget(cmTargets::value_type
&v
)
1871 assert(!v
.second
.IsImported());
1872 this->TotalTargets
[v
.first
] = &v
.second
;
1875 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
1876 cmExternalMakefileProjectGenerator
*extraGenerator
)
1878 this->ExtraGenerator
= extraGenerator
;
1879 if (this->ExtraGenerator
!=0)
1881 this->ExtraGenerator
->SetGlobalGenerator(this);
1885 const char* cmGlobalGenerator::GetExtraGeneratorName() const
1887 return this->ExtraGenerator
==0 ? 0 : this->ExtraGenerator
->GetName();
1890 void cmGlobalGenerator::FileReplacedDuringGenerate(const std::string
& filename
)
1892 this->FilesReplacedDuringGenerate
.push_back(filename
);
1897 ::GetFilesReplacedDuringGenerate(std::vector
<std::string
>& filenames
)
1901 this->FilesReplacedDuringGenerate
.begin(),
1902 this->FilesReplacedDuringGenerate
.end(),
1903 std::back_inserter(filenames
));
1908 ::GetTargetSets(cmGlobalGenerator::TargetDependSet
& projectTargets
,
1909 cmGlobalGenerator::TargetDependSet
& originalTargets
,
1910 cmLocalGenerator
* root
,
1911 std::vector
<cmLocalGenerator
*> const& generators
)
1913 // loop over all local generators
1914 for(std::vector
<cmLocalGenerator
*>::const_iterator i
= generators
.begin();
1915 i
!= generators
.end(); ++i
)
1917 // check to make sure generator is not excluded
1918 if(this->IsExcluded(root
, *i
))
1922 cmMakefile
* mf
= (*i
)->GetMakefile();
1923 // Get the targets in the makefile
1924 cmTargets
&tgts
= mf
->GetTargets();
1925 // loop over all the targets
1926 for (cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); ++l
)
1928 cmTarget
* target
= &l
->second
;
1929 // put the target in the set of original targets
1930 originalTargets
.insert(target
);
1931 // Get the set of targets that depend on target
1932 this->AddTargetDepends(target
,
1939 cmGlobalGenerator::AddTargetDepends(cmTarget
* target
,
1940 cmGlobalGenerator::TargetDependSet
&
1943 // add the target itself
1944 projectTargets
.insert(target
);
1945 // get the direct depends of target
1946 cmGlobalGenerator::TargetDependSet
const& tset
1947 = this->GetTargetDirectDepends(*target
);
1950 // if there are targets that depend on target
1951 // add them and their depends as well
1952 for(cmGlobalGenerator::TargetDependSet::const_iterator i
=
1953 tset
.begin(); i
!= tset
.end(); ++i
)
1955 cmTarget
* dtarget
= *i
;
1956 this->AddTargetDepends(dtarget
, projectTargets
);
1962 //----------------------------------------------------------------------------
1963 void cmGlobalGenerator::AddToManifest(const char* config
,
1964 std::string
const& f
)
1966 // Add to the main manifest for this configuration.
1967 this->TargetManifest
[config
].insert(f
);
1969 // Add to the content listing for the file's directory.
1970 std::string dir
= cmSystemTools::GetFilenamePath(f
);
1971 std::string file
= cmSystemTools::GetFilenameName(f
);
1972 this->DirectoryContentMap
[dir
].insert(file
);
1975 //----------------------------------------------------------------------------
1976 std::set
<cmStdString
> const&
1977 cmGlobalGenerator::GetDirectoryContent(std::string
const& dir
, bool needDisk
)
1979 DirectoryContent
& dc
= this->DirectoryContentMap
[dir
];
1980 if(needDisk
&& !dc
.LoadedFromDisk
)
1982 // Load the directory content from disk.
1984 if(d
.Load(dir
.c_str()))
1986 unsigned long n
= d
.GetNumberOfFiles();
1987 for(unsigned long i
= 0; i
< n
; ++i
)
1989 const char* f
= d
.GetFile(i
);
1990 if(strcmp(f
, ".") != 0 && strcmp(f
, "..") != 0)
1996 dc
.LoadedFromDisk
= true;
2001 //----------------------------------------------------------------------------
2003 cmGlobalGenerator::AddRuleHash(const std::vector
<std::string
>& outputs
,
2004 std::vector
<std::string
>::const_iterator first
,
2005 std::vector
<std::string
>::const_iterator last
)
2007 #if defined(CMAKE_BUILD_WITH_CMAKE)
2008 // Ignore if there are no outputs.
2014 // Compute a hash of the rule.
2017 unsigned char const* data
;
2019 cmsysMD5
* sum
= cmsysMD5_New();
2020 cmsysMD5_Initialize(sum
);
2021 for(std::vector
<std::string
>::const_iterator i
= first
; i
!= last
; ++i
)
2023 data
= reinterpret_cast<unsigned char const*>(i
->c_str());
2024 length
= static_cast<int>(i
->length());
2025 cmsysMD5_Append(sum
, data
, length
);
2027 cmsysMD5_FinalizeHex(sum
, hash
.Data
);
2028 cmsysMD5_Delete(sum
);
2031 // Shorten the output name (in expected use case).
2032 cmLocalGenerator
* lg
= this->GetLocalGenerators()[0];
2033 std::string fname
= lg
->Convert(outputs
[0].c_str(),
2034 cmLocalGenerator::HOME_OUTPUT
);
2036 // Associate the hash with this output.
2037 this->RuleHashes
[fname
] = hash
;
2045 //----------------------------------------------------------------------------
2046 void cmGlobalGenerator::CheckRuleHashes()
2048 #if defined(CMAKE_BUILD_WITH_CMAKE)
2049 std::string home
= this->GetCMakeInstance()->GetHomeOutputDirectory();
2050 std::string pfile
= home
;
2051 pfile
+= this->GetCMakeInstance()->GetCMakeFilesDirectory();
2052 pfile
+= "/CMakeRuleHashes.txt";
2054 #if defined(_WIN32) || defined(__CYGWIN__)
2055 std::ifstream
fin(pfile
.c_str(), std::ios::in
| std::ios::binary
);
2057 std::ifstream
fin(pfile
.c_str(), std::ios::in
);
2061 while(cmSystemTools::GetLineFromStream(fin
, line
))
2063 // Line format is a 32-byte hex string followed by a space
2064 // followed by a file name (with no escaping).
2066 // Skip blank and comment lines.
2067 if(line
.size() < 34 || line
[0] == '#')
2072 // Get the filename.
2073 fname
= line
.substr(33, line
.npos
);
2075 // Look for a hash for this file's rule.
2076 std::map
<cmStdString
, RuleHash
>::const_iterator rhi
=
2077 this->RuleHashes
.find(fname
);
2078 if(rhi
!= this->RuleHashes
.end())
2080 // Compare the rule hash in the file to that we were given.
2081 if(strncmp(line
.c_str(), rhi
->second
.Data
, 32) != 0)
2083 // The rule has changed. Delete the output so it will be
2085 fname
= cmSystemTools::CollapseFullPath(fname
.c_str(), home
.c_str());
2086 cmSystemTools::RemoveFile(fname
.c_str());
2091 // We have no hash for a rule previously listed. This may be a
2092 // case where a user has turned off a build option and might
2093 // want to turn it back on later, so do not delete the file.
2094 // Instead, we keep the rule hash as long as the file exists so
2095 // that if the feature is turned back on and the rule has
2096 // changed the file is still rebuilt.
2098 cmSystemTools::CollapseFullPath(fname
.c_str(), home
.c_str());
2099 if(cmSystemTools::FileExists(fpath
.c_str()))
2102 strncpy(hash
.Data
, line
.c_str(), 32);
2103 this->RuleHashes
[fname
] = hash
;
2108 // Now generate a new persistence file with the current hashes.
2109 if(this->RuleHashes
.empty())
2111 cmSystemTools::RemoveFile(pfile
.c_str());
2115 cmGeneratedFileStream
fout(pfile
.c_str());
2116 fout
<< "# Hashes of file build rules.\n";
2117 for(std::map
<cmStdString
, RuleHash
>::const_iterator
2118 rhi
= this->RuleHashes
.begin(); rhi
!= this->RuleHashes
.end(); ++rhi
)
2120 fout
.write(rhi
->second
.Data
, 32);
2121 fout
<< " " << rhi
->first
<< "\n";