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