Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmake.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmake.h"
13 #include "cmDocumentVariables.h"
14 #include "time.h"
15 #include "cmCacheManager.h"
16 #include "cmMakefile.h"
17 #include "cmLocalGenerator.h"
18 #include "cmExternalMakefileProjectGenerator.h"
19 #include "cmCommands.h"
20 #include "cmCommand.h"
21 #include "cmFileTimeComparison.h"
22 #include "cmGeneratedFileStream.h"
23 #include "cmQtAutomoc.h"
24 #include "cmSourceFile.h"
25 #include "cmVersion.h"
26 #include "cmTest.h"
27 #include "cmDocumentationFormatterText.h"
28
29 #if defined(CMAKE_BUILD_WITH_CMAKE)
30 # include "cmGraphVizWriter.h"
31 # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
32 # include "cmVariableWatch.h"
33 # include <cmsys/Terminal.h>
34 # include <cmsys/CommandLineArguments.hxx>
35 #endif
36
37 #include <cmsys/Directory.hxx>
38 #include <cmsys/Process.h>
39 #include <cmsys/Glob.hxx>
40 #include <cmsys/RegularExpression.hxx>
41
42 // only build kdevelop generator on non-windows platforms
43 // when not bootstrapping cmake
44 #if !defined(_WIN32)
45 # if defined(CMAKE_BUILD_WITH_CMAKE)
46 #   define CMAKE_USE_KDEVELOP
47 # endif
48 #endif
49
50 #if defined(CMAKE_BUILD_WITH_CMAKE)
51 #  define CMAKE_USE_ECLIPSE
52 #endif
53
54 #if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
55 # define CMAKE_BOOT_MINGW
56 #endif
57
58 // include the generator
59 #if defined(_WIN32) && !defined(__CYGWIN__)
60 #  if !defined(CMAKE_BOOT_MINGW)
61 #    include "cmGlobalVisualStudio6Generator.h"
62 #    include "cmGlobalVisualStudio7Generator.h"
63 #    include "cmGlobalVisualStudio71Generator.h"
64 #    include "cmGlobalVisualStudio8Generator.h"
65 #    include "cmGlobalVisualStudio9Generator.h"
66 #    include "cmGlobalVisualStudio10Generator.h"
67 #    include "cmGlobalVisualStudio11Generator.h"
68 #    include "cmGlobalVisualStudio12Generator.h"
69 #    include "cmGlobalBorlandMakefileGenerator.h"
70 #    include "cmGlobalNMakeMakefileGenerator.h"
71 #    include "cmGlobalJOMMakefileGenerator.h"
72 #    include "cmGlobalWatcomWMakeGenerator.h"
73 #    define CMAKE_HAVE_VS_GENERATORS
74 #  endif
75 #  include "cmGlobalMSYSMakefileGenerator.h"
76 #  include "cmGlobalMinGWMakefileGenerator.h"
77 #  include "cmWin32ProcessExecution.h"
78 #else
79 #endif
80 #include "cmGlobalUnixMakefileGenerator3.h"
81 #include "cmGlobalNinjaGenerator.h"
82
83
84 #if defined(CMAKE_HAVE_VS_GENERATORS)
85 #include "cmCallVisualStudioMacro.h"
86 #include "cmVisualStudioWCEPlatformParser.h"
87 #endif
88
89 #if !defined(CMAKE_BOOT_MINGW)
90 # include "cmExtraCodeBlocksGenerator.h"
91 #endif
92 #include "cmExtraSublimeTextGenerator.h"
93
94 #ifdef CMAKE_USE_KDEVELOP
95 # include "cmGlobalKdevelopGenerator.h"
96 #endif
97
98 #ifdef CMAKE_USE_ECLIPSE
99 # include "cmExtraEclipseCDT4Generator.h"
100 #endif
101
102 #include <stdlib.h> // required for atoi
103
104 #if defined( __APPLE__ )
105 #  if defined(CMAKE_BUILD_WITH_CMAKE)
106 #    include "cmGlobalXCodeGenerator.h"
107 #    define CMAKE_USE_XCODE 1
108 #  endif
109 #  include <sys/types.h>
110 #  include <sys/time.h>
111 #  include <sys/resource.h>
112 #endif
113
114 #include <sys/stat.h> // struct stat
115
116 static bool cmakeCheckStampFile(const char* stampName);
117 static bool cmakeCheckStampList(const char* stampName);
118
119 void cmNeedBackwardsCompatibility(const std::string& variable,
120   int access_type, void*, const char*, const cmMakefile*)
121 {
122 #ifdef CMAKE_BUILD_WITH_CMAKE
123   if (access_type == cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS)
124     {
125     std::string message = "An attempt was made to access a variable: ";
126     message += variable;
127     message +=
128       " that has not been defined. Some variables were always defined "
129       "by CMake in versions prior to 1.6. To fix this you might need to set "
130       "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
131       "you are writing a CMakeLists file, (or have already set "
132       "CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less) then you probably need "
133       "to include a CMake module to test for the feature this variable "
134       "defines.";
135     cmSystemTools::Error(message.c_str());
136     }
137 #else
138   (void)variable;
139   (void)access_type;
140 #endif
141 }
142
143 void cmWarnUnusedCliWarning(const std::string& variable,
144   int, void* ctx, const char*, const cmMakefile*)
145 {
146   cmake* cm = reinterpret_cast<cmake*>(ctx);
147   cm->MarkCliAsUsed(variable);
148 }
149
150 cmake::cmake()
151 {
152   this->Trace = false;
153   this->WarnUninitialized = false;
154   this->WarnUnused = false;
155   this->WarnUnusedCli = true;
156   this->CheckSystemVars = false;
157   this->SuppressDevWarnings = false;
158   this->DoSuppressDevWarnings = false;
159   this->DebugOutput = false;
160   this->DebugTryCompile = false;
161   this->ClearBuildSystem = false;
162   this->FileComparison = new cmFileTimeComparison;
163
164   this->Policies = new cmPolicies();
165   this->InitializeProperties();
166
167 #ifdef __APPLE__
168   struct rlimit rlp;
169   if(!getrlimit(RLIMIT_STACK, &rlp))
170     {
171     if(rlp.rlim_cur != rlp.rlim_max)
172       {
173         rlp.rlim_cur = rlp.rlim_max;
174          setrlimit(RLIMIT_STACK, &rlp);
175       }
176     }
177 #endif
178
179   this->Verbose = false;
180   this->InTryCompile = false;
181   this->CacheManager = new cmCacheManager(this);
182   this->GlobalGenerator = 0;
183   this->ProgressCallback = 0;
184   this->ProgressCallbackClientData = 0;
185   this->CurrentWorkingMode = NORMAL_MODE;
186
187 #ifdef CMAKE_BUILD_WITH_CMAKE
188   this->VariableWatch = new cmVariableWatch;
189   this->VariableWatch->AddWatch("CMAKE_WORDS_BIGENDIAN",
190                             cmNeedBackwardsCompatibility);
191   this->VariableWatch->AddWatch("CMAKE_SIZEOF_INT",
192                             cmNeedBackwardsCompatibility);
193   this->VariableWatch->AddWatch("CMAKE_X_LIBS",
194                             cmNeedBackwardsCompatibility);
195 #endif
196
197   this->AddDefaultGenerators();
198   this->AddDefaultExtraGenerators();
199   this->AddDefaultCommands();
200
201   // Make sure we can capture the build tool output.
202   cmSystemTools::EnableVSConsoleOutput();
203 }
204
205 cmake::~cmake()
206 {
207   delete this->CacheManager;
208   delete this->Policies;
209   if (this->GlobalGenerator)
210     {
211     delete this->GlobalGenerator;
212     this->GlobalGenerator = 0;
213     }
214   for(RegisteredCommandsMap::iterator j = this->Commands.begin();
215       j != this->Commands.end(); ++j)
216     {
217     delete (*j).second;
218     }
219   for(RegisteredGeneratorsVector::iterator j = this->Generators.begin();
220       j != this->Generators.end(); ++j)
221     {
222     delete *j;
223     }
224 #ifdef CMAKE_BUILD_WITH_CMAKE
225   delete this->VariableWatch;
226 #endif
227   delete this->FileComparison;
228 }
229
230 void cmake::InitializeProperties()
231 {
232   this->Properties.clear();
233   this->Properties.SetCMakeInstance(this);
234   this->AccessedProperties.clear();
235   this->PropertyDefinitions.clear();
236
237   // initialize properties
238   cmCacheManager::DefineProperties(this);
239   cmSourceFile::DefineProperties(this);
240   cmTarget::DefineProperties(this);
241   cmMakefile::DefineProperties(this);
242   cmTest::DefineProperties(this);
243   cmake::DefineProperties(this);
244 }
245
246 void cmake::CleanupCommandsAndMacros()
247 {
248   this->InitializeProperties();
249   std::vector<cmCommand*> commands;
250   for(RegisteredCommandsMap::iterator j = this->Commands.begin();
251       j != this->Commands.end(); ++j)
252     {
253     if ( !j->second->IsA("cmMacroHelperCommand") &&
254          !j->second->IsA("cmFunctionHelperCommand"))
255       {
256       commands.push_back(j->second);
257       }
258     else
259       {
260       delete j->second;
261       }
262     }
263   this->Commands.erase(this->Commands.begin(), this->Commands.end());
264   std::vector<cmCommand*>::iterator it;
265   for ( it = commands.begin(); it != commands.end();
266     ++ it )
267     {
268     this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
269     }
270 }
271
272 bool cmake::CommandExists(const char* name) const
273 {
274   std::string sName = cmSystemTools::LowerCase(name);
275   return (this->Commands.find(sName) != this->Commands.end());
276 }
277
278 cmCommand *cmake::GetCommand(const char *name)
279 {
280   cmCommand* rm = 0;
281   std::string sName = cmSystemTools::LowerCase(name);
282   RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
283   if (pos != this->Commands.end())
284     {
285     rm = (*pos).second;
286     }
287   return rm;
288 }
289
290 void cmake::RenameCommand(const char*oldName, const char* newName)
291 {
292   // if the command already exists, free the old one
293   std::string sOldName = cmSystemTools::LowerCase(oldName);
294   std::string sNewName = cmSystemTools::LowerCase(newName);
295   RegisteredCommandsMap::iterator pos = this->Commands.find(sOldName);
296   if ( pos == this->Commands.end() )
297     {
298     return;
299     }
300   cmCommand* cmd = pos->second;
301
302   pos = this->Commands.find(sNewName);
303   if (pos != this->Commands.end())
304     {
305     delete pos->second;
306     this->Commands.erase(pos);
307     }
308   this->Commands.insert(RegisteredCommandsMap::value_type(sNewName, cmd));
309   pos = this->Commands.find(sOldName);
310   this->Commands.erase(pos);
311 }
312
313 void cmake::RemoveCommand(const char* name)
314 {
315   std::string sName = cmSystemTools::LowerCase(name);
316   RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
317   if ( pos != this->Commands.end() )
318     {
319     delete pos->second;
320     this->Commands.erase(pos);
321     }
322 }
323
324 void cmake::AddCommand(cmCommand* wg)
325 {
326   std::string name = cmSystemTools::LowerCase(wg->GetName());
327   // if the command already exists, free the old one
328   RegisteredCommandsMap::iterator pos = this->Commands.find(name);
329   if (pos != this->Commands.end())
330     {
331     delete pos->second;
332     this->Commands.erase(pos);
333     }
334   this->Commands.insert( RegisteredCommandsMap::value_type(name, wg));
335 }
336
337
338 void cmake::RemoveUnscriptableCommands()
339 {
340   std::vector<std::string> unscriptableCommands;
341   cmake::RegisteredCommandsMap* commands = this->GetCommands();
342   for (cmake::RegisteredCommandsMap::const_iterator pos = commands->begin();
343        pos != commands->end();
344        ++pos)
345     {
346     if (!pos->second->IsScriptable())
347       {
348       unscriptableCommands.push_back(pos->first);
349       }
350     }
351
352   for(std::vector<std::string>::const_iterator it=unscriptableCommands.begin();
353       it != unscriptableCommands.end();
354       ++it)
355     {
356     this->RemoveCommand(it->c_str());
357     }
358 }
359
360 // Parse the args
361 bool cmake::SetCacheArgs(const std::vector<std::string>& args)
362 {
363   bool findPackageMode = false;
364   for(unsigned int i=1; i < args.size(); ++i)
365     {
366     std::string arg = args[i];
367     if(arg.find("-D",0) == 0)
368       {
369       std::string entry = arg.substr(2);
370       if(entry.size() == 0)
371         {
372         ++i;
373         if(i < args.size())
374           {
375           entry = args[i];
376           }
377         else
378           {
379           cmSystemTools::Error("-D must be followed with VAR=VALUE.");
380           return false;
381           }
382         }
383       std::string var, value;
384       cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
385       if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
386         {
387         // The value is transformed if it is a filepath for example, so
388         // we can't compare whether the value is already in the cache until
389         // after we call AddCacheEntry.
390         const char *cachedValue =
391                               this->CacheManager->GetCacheValue(var.c_str());
392
393         this->CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
394           "No help, variable specified on the command line.", type);
395         if(this->WarnUnusedCli)
396           {
397           if (!cachedValue
398               || strcmp(this->CacheManager->GetCacheValue(var.c_str()),
399                         cachedValue) != 0)
400             {
401             this->WatchUnusedCli(var.c_str());
402             }
403           }
404         }
405       else
406         {
407         std::cerr << "Parse error in command line argument: " << arg << "\n"
408                   << "Should be: VAR:type=value\n";
409         cmSystemTools::Error("No cmake script provided.");
410         return false;
411         }
412       }
413     else if(arg.find("-Wno-dev",0) == 0)
414       {
415       this->SuppressDevWarnings = true;
416       this->DoSuppressDevWarnings = true;
417       }
418     else if(arg.find("-Wdev",0) == 0)
419       {
420       this->SuppressDevWarnings = false;
421       this->DoSuppressDevWarnings = true;
422       }
423     else if(arg.find("-U",0) == 0)
424       {
425       std::string entryPattern = arg.substr(2);
426       if(entryPattern.size() == 0)
427         {
428         ++i;
429         if(i < args.size())
430           {
431           entryPattern = args[i];
432           }
433         else
434           {
435           cmSystemTools::Error("-U must be followed with VAR.");
436           return false;
437           }
438         }
439       cmsys::RegularExpression regex(
440         cmsys::Glob::PatternToRegex(entryPattern.c_str(), true, true).c_str());
441       //go through all cache entries and collect the vars which will be removed
442       std::vector<std::string> entriesToDelete;
443       cmCacheManager::CacheIterator it =
444                                     this->CacheManager->GetCacheIterator();
445       for ( it.Begin(); !it.IsAtEnd(); it.Next() )
446         {
447         cmCacheManager::CacheEntryType t = it.GetType();
448         if(t != cmCacheManager::STATIC)
449           {
450           std::string entryName = it.GetName();
451           if (regex.find(entryName.c_str()))
452             {
453             entriesToDelete.push_back(entryName);
454             }
455           }
456         }
457
458       // now remove them from the cache
459       for(std::vector<std::string>::const_iterator currentEntry =
460           entriesToDelete.begin();
461           currentEntry != entriesToDelete.end();
462           ++currentEntry)
463         {
464         this->CacheManager->RemoveCacheEntry(currentEntry->c_str());
465         }
466       }
467     else if(arg.find("-C",0) == 0)
468       {
469       std::string path = arg.substr(2);
470       if ( path.size() == 0 )
471         {
472         ++i;
473         if(i < args.size())
474           {
475           path = args[i];
476           }
477         else
478           {
479           cmSystemTools::Error("-C must be followed by a file name.");
480           return false;
481           }
482         }
483       std::cerr << "loading initial cache file " << path.c_str() << "\n";
484       this->ReadListFile(args, path.c_str());
485       }
486     else if(arg.find("-P",0) == 0)
487       {
488       i++;
489       if(i >= args.size())
490         {
491         cmSystemTools::Error("-P must be followed by a file name.");
492         return false;
493         }
494       std::string path = args[i];
495       if ( path.size() == 0 )
496         {
497         cmSystemTools::Error("No cmake script provided.");
498         return false;
499         }
500       this->ReadListFile(args, path.c_str());
501       }
502     else if (arg.find("--find-package",0) == 0)
503       {
504       findPackageMode = true;
505       }
506     }
507
508   if (findPackageMode)
509     {
510     return this->FindPackage(args);
511     }
512
513   return true;
514 }
515
516 void cmake::ReadListFile(const std::vector<std::string>& args,
517                          const char *path)
518 {
519   // if a generator was not yet created, temporarily create one
520   cmGlobalGenerator *gg = this->GetGlobalGenerator();
521   bool created = false;
522
523   // if a generator was not specified use a generic one
524   if (!gg)
525     {
526     gg = new cmGlobalGenerator;
527     gg->SetCMakeInstance(this);
528     created = true;
529     }
530
531   // read in the list file to fill the cache
532   if(path)
533     {
534     cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
535     lg->GetMakefile()->SetHomeOutputDirectory
536       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
537     lg->GetMakefile()->SetStartOutputDirectory
538       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
539     lg->GetMakefile()->SetHomeDirectory
540       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
541     lg->GetMakefile()->SetStartDirectory
542       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
543     if (this->GetWorkingMode() != NORMAL_MODE)
544       {
545       std::string file(cmSystemTools::CollapseFullPath(path));
546       cmSystemTools::ConvertToUnixSlashes(file);
547       lg->GetMakefile()->SetScriptModeFile(file.c_str());
548
549       lg->GetMakefile()->SetArgcArgv(args);
550       }
551     if (!lg->GetMakefile()->ReadListFile(0, path))
552       {
553       cmSystemTools::Error("Error processing file: ", path);
554       }
555     }
556
557   // free generic one if generated
558   if (created)
559     {
560     delete gg;
561     }
562 }
563
564
565 bool cmake::FindPackage(const std::vector<std::string>& args)
566 {
567   // if a generator was not yet created, temporarily create one
568   cmGlobalGenerator *gg = new cmGlobalGenerator;
569   gg->SetCMakeInstance(this);
570   this->SetGlobalGenerator(gg);
571
572   // read in the list file to fill the cache
573   cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
574   cmMakefile* mf = lg->GetMakefile();
575   mf->SetHomeOutputDirectory
576     (cmSystemTools::GetCurrentWorkingDirectory().c_str());
577   mf->SetStartOutputDirectory
578     (cmSystemTools::GetCurrentWorkingDirectory().c_str());
579   mf->SetHomeDirectory
580     (cmSystemTools::GetCurrentWorkingDirectory().c_str());
581   mf->SetStartDirectory
582     (cmSystemTools::GetCurrentWorkingDirectory().c_str());
583
584   mf->SetArgcArgv(args);
585
586   std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake");
587   mf->ReadListFile(0, systemFile.c_str());
588
589   std::string language = mf->GetSafeDefinition("LANGUAGE");
590   std::string mode = mf->GetSafeDefinition("MODE");
591   std::string packageName = mf->GetSafeDefinition("NAME");
592   bool packageFound = mf->IsOn("PACKAGE_FOUND");
593   bool quiet = mf->IsOn("PACKAGE_QUIET");
594
595   if (!packageFound)
596     {
597     if (!quiet)
598       {
599       printf("%s not found.\n", packageName.c_str());
600       }
601     }
602   else if (mode == "EXIST")
603     {
604     if (!quiet)
605       {
606       printf("%s found.\n", packageName.c_str());
607       }
608     }
609   else if (mode == "COMPILE")
610     {
611     std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS");
612     std::vector<std::string> includeDirs;
613     cmSystemTools::ExpandListArgument(includes, includeDirs);
614
615     std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0,
616                                                    language.c_str(), false);
617
618     std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
619     printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
620     }
621   else if (mode == "LINK")
622     {
623     const char* targetName = "dummy";
624     std::vector<std::string> srcs;
625     cmTarget* tgt = mf->AddExecutable(targetName, srcs, true);
626     tgt->SetProperty("LINKER_LANGUAGE", language.c_str());
627
628     std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES");
629     std::vector<std::string> libList;
630     cmSystemTools::ExpandListArgument(libs, libList);
631     for(std::vector<std::string>::const_iterator libIt=libList.begin();
632             libIt != libList.end();
633             ++libIt)
634       {
635       mf->AddLinkLibraryForTarget(targetName, libIt->c_str(),
636                                   cmTarget::GENERAL);
637       }
638
639
640     std::string linkLibs;
641     std::string frameworkPath;
642     std::string linkPath;
643     std::string flags;
644     std::string linkFlags;
645     cmGeneratorTarget gtgt(tgt);
646     lg->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags,
647                        &gtgt);
648     linkLibs = frameworkPath + linkPath + linkLibs;
649
650     printf("%s\n", linkLibs.c_str() );
651
652 /*    if ( use_win32 )
653       {
654       tgt->SetProperty("WIN32_EXECUTABLE", "ON");
655       }
656     if ( use_macbundle)
657       {
658       tgt->SetProperty("MACOSX_BUNDLE", "ON");
659       }*/
660     }
661
662   // free generic one if generated
663 //  this->SetGlobalGenerator(0); // setting 0-pointer is not possible
664 //  delete gg; // this crashes inside the cmake instance
665
666   return packageFound;
667 }
668
669
670 // Parse the args
671 void cmake::SetArgs(const std::vector<std::string>& args,
672                     bool directoriesSetBefore)
673 {
674   bool directoriesSet = directoriesSetBefore;
675   bool haveToolset = false;
676   for(unsigned int i=1; i < args.size(); ++i)
677     {
678     std::string arg = args[i];
679     if(arg.find("-H",0) == 0)
680       {
681       directoriesSet = true;
682       std::string path = arg.substr(2);
683       path = cmSystemTools::CollapseFullPath(path.c_str());
684       cmSystemTools::ConvertToUnixSlashes(path);
685       this->SetHomeDirectory(path.c_str());
686       }
687     else if(arg.find("-S",0) == 0)
688       {
689       // There is no local generate anymore.  Ignore -S option.
690       }
691     else if(arg.find("-O",0) == 0)
692       {
693       // There is no local generate anymore.  Ignore -O option.
694       }
695     else if(arg.find("-B",0) == 0)
696       {
697       directoriesSet = true;
698       std::string path = arg.substr(2);
699       path = cmSystemTools::CollapseFullPath(path.c_str());
700       cmSystemTools::ConvertToUnixSlashes(path);
701       this->SetHomeOutputDirectory(path.c_str());
702       }
703     else if((i < args.size()-1) && (arg.find("--check-build-system",0) == 0))
704       {
705       this->CheckBuildSystemArgument = args[++i];
706       this->ClearBuildSystem = (atoi(args[++i].c_str()) > 0);
707       }
708     else if((i < args.size()-1) && (arg.find("--check-stamp-file",0) == 0))
709       {
710       this->CheckStampFile = args[++i];
711       }
712     else if((i < args.size()-1) && (arg.find("--check-stamp-list",0) == 0))
713       {
714       this->CheckStampList = args[++i];
715       }
716 #if defined(CMAKE_HAVE_VS_GENERATORS)
717     else if((i < args.size()-1) && (arg.find("--vs-solution-file",0) == 0))
718       {
719       this->VSSolutionFile = args[++i];
720       }
721 #endif
722     else if(arg.find("-V",0) == 0)
723       {
724         this->Verbose = true;
725       }
726     else if(arg.find("-D",0) == 0)
727       {
728       // skip for now
729       }
730     else if(arg.find("-U",0) == 0)
731       {
732       // skip for now
733       }
734     else if(arg.find("-C",0) == 0)
735       {
736       // skip for now
737       }
738     else if(arg.find("-P",0) == 0)
739       {
740       // skip for now
741       i++;
742       }
743     else if(arg.find("--find-package",0) == 0)
744       {
745       // skip for now
746       i++;
747       }
748     else if(arg.find("-Wno-dev",0) == 0)
749       {
750       // skip for now
751       }
752     else if(arg.find("-Wdev",0) == 0)
753       {
754       // skip for now
755       }
756     else if(arg.find("--graphviz=",0) == 0)
757       {
758       std::string path = arg.substr(strlen("--graphviz="));
759       path = cmSystemTools::CollapseFullPath(path.c_str());
760       cmSystemTools::ConvertToUnixSlashes(path);
761       this->GraphVizFile = path;
762       if ( this->GraphVizFile.empty() )
763         {
764         cmSystemTools::Error("No file specified for --graphviz");
765         }
766       }
767     else if(arg.find("--debug-trycompile",0) == 0)
768       {
769       std::cout << "debug trycompile on\n";
770       this->DebugTryCompileOn();
771       }
772     else if(arg.find("--debug-output",0) == 0)
773       {
774       std::cout << "Running with debug output on.\n";
775       this->SetDebugOutputOn(true);
776       }
777     else if(arg.find("--trace",0) == 0)
778       {
779       std::cout << "Running with trace output on.\n";
780       this->SetTrace(true);
781       }
782     else if(arg.find("--warn-uninitialized",0) == 0)
783       {
784       std::cout << "Warn about uninitialized values.\n";
785       this->SetWarnUninitialized(true);
786       }
787     else if(arg.find("--warn-unused-vars",0) == 0)
788       {
789       std::cout << "Finding unused variables.\n";
790       this->SetWarnUnused(true);
791       }
792     else if(arg.find("--no-warn-unused-cli",0) == 0)
793       {
794       std::cout << "Not searching for unused variables given on the " <<
795                    "command line.\n";
796       this->SetWarnUnusedCli(false);
797       }
798     else if(arg.find("--check-system-vars",0) == 0)
799       {
800       std::cout << "Also check system files when warning about unused and " <<
801                    "uninitialized variables.\n";
802       this->SetCheckSystemVars(true);
803       }
804     else if(arg.find("-T",0) == 0)
805       {
806       std::string value = arg.substr(2);
807       if(value.size() == 0)
808         {
809         ++i;
810         if(i >= args.size())
811           {
812           cmSystemTools::Error("No toolset specified for -T");
813           return;
814           }
815         value = args[i];
816         }
817       if(haveToolset)
818         {
819         cmSystemTools::Error("Multiple -T options not allowed");
820         return;
821         }
822       this->GeneratorToolset = value;
823       haveToolset = true;
824       }
825     else if(arg.find("-G",0) == 0)
826       {
827       std::string value = arg.substr(2);
828       if(value.size() == 0)
829         {
830         ++i;
831         if(i >= args.size())
832           {
833           cmSystemTools::Error("No generator specified for -G");
834           return;
835           }
836         value = args[i];
837         }
838       cmGlobalGenerator* gen =
839         this->CreateGlobalGenerator(value.c_str());
840       if(!gen)
841         {
842         cmSystemTools::Error("Could not create named generator ",
843                              value.c_str());
844         }
845       else
846         {
847         this->SetGlobalGenerator(gen);
848         }
849       }
850     // no option assume it is the path to the source
851     else
852       {
853       directoriesSet = true;
854       this->SetDirectoriesFromFile(arg.c_str());
855       }
856     }
857   if(!directoriesSet)
858     {
859     this->SetHomeOutputDirectory
860       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
861     this->SetStartOutputDirectory
862       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
863     this->SetHomeDirectory
864       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
865     this->SetStartDirectory
866       (cmSystemTools::GetCurrentWorkingDirectory().c_str());
867     }
868
869   this->SetStartDirectory(this->GetHomeDirectory());
870   this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
871 }
872
873 //----------------------------------------------------------------------------
874 void cmake::SetDirectoriesFromFile(const char* arg)
875 {
876   // Check if the argument refers to a CMakeCache.txt or
877   // CMakeLists.txt file.
878   std::string listPath;
879   std::string cachePath;
880   bool argIsFile = false;
881   if(cmSystemTools::FileIsDirectory(arg))
882     {
883     std::string path = cmSystemTools::CollapseFullPath(arg);
884     cmSystemTools::ConvertToUnixSlashes(path);
885     std::string cacheFile = path;
886     cacheFile += "/CMakeCache.txt";
887     std::string listFile = path;
888     listFile += "/CMakeLists.txt";
889     if(cmSystemTools::FileExists(cacheFile.c_str()))
890       {
891       cachePath = path;
892       }
893     if(cmSystemTools::FileExists(listFile.c_str()))
894       {
895       listPath = path;
896       }
897     }
898   else if(cmSystemTools::FileExists(arg))
899     {
900     argIsFile = true;
901     std::string fullPath = cmSystemTools::CollapseFullPath(arg);
902     std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
903     name = cmSystemTools::LowerCase(name);
904     if(name == "cmakecache.txt")
905       {
906       cachePath = cmSystemTools::GetFilenamePath(fullPath.c_str());
907       }
908     else if(name == "cmakelists.txt")
909       {
910       listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
911       }
912     }
913   else
914     {
915     // Specified file or directory does not exist.  Try to set things
916     // up to produce a meaningful error message.
917     std::string fullPath = cmSystemTools::CollapseFullPath(arg);
918     std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
919     name = cmSystemTools::LowerCase(name);
920     if(name == "cmakecache.txt" || name == "cmakelists.txt")
921       {
922       argIsFile = true;
923       listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
924       }
925     else
926       {
927       listPath = fullPath;
928       }
929     }
930
931   // If there is a CMakeCache.txt file, use its settings.
932   if(cachePath.length() > 0)
933     {
934     cmCacheManager* cachem = this->GetCacheManager();
935     cmCacheManager::CacheIterator it = cachem->NewIterator();
936     if(cachem->LoadCache(cachePath.c_str()) &&
937       it.Find("CMAKE_HOME_DIRECTORY"))
938       {
939       this->SetHomeOutputDirectory(cachePath.c_str());
940       this->SetStartOutputDirectory(cachePath.c_str());
941       this->SetHomeDirectory(it.GetValue());
942       this->SetStartDirectory(it.GetValue());
943       return;
944       }
945     }
946
947   // If there is a CMakeLists.txt file, use it as the source tree.
948   if(listPath.length() > 0)
949     {
950     this->SetHomeDirectory(listPath.c_str());
951     this->SetStartDirectory(listPath.c_str());
952
953     if(argIsFile)
954       {
955       // Source CMakeLists.txt file given.  It was probably dropped
956       // onto the executable in a GUI.  Default to an in-source build.
957       this->SetHomeOutputDirectory(listPath.c_str());
958       this->SetStartOutputDirectory(listPath.c_str());
959       }
960     else
961       {
962       // Source directory given on command line.  Use current working
963       // directory as build tree.
964       std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
965       this->SetHomeOutputDirectory(cwd.c_str());
966       this->SetStartOutputDirectory(cwd.c_str());
967       }
968     return;
969     }
970
971   // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
972   // argument.  Assume it is the path to the source tree, and use the
973   // current working directory as the build tree.
974   std::string full = cmSystemTools::CollapseFullPath(arg);
975   std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
976   this->SetHomeDirectory(full.c_str());
977   this->SetStartDirectory(full.c_str());
978   this->SetHomeOutputDirectory(cwd.c_str());
979   this->SetStartOutputDirectory(cwd.c_str());
980 }
981
982 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
983 // cache
984 int cmake::AddCMakePaths()
985 {
986   // Find the cmake executable
987   std::string cMakeSelf = cmSystemTools::GetExecutableDirectory();
988   cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
989   cMakeSelf += "/cmake";
990   cMakeSelf += cmSystemTools::GetExecutableExtension();
991 #ifdef __APPLE__
992   // on the apple this might be the gui bundle
993   if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
994     {
995     cMakeSelf = cmSystemTools::GetExecutableDirectory();
996     cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
997     cMakeSelf += "../../../..";
998     cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
999     cMakeSelf = cmSystemTools::CollapseFullPath(cMakeSelf.c_str());
1000     cMakeSelf += "/cmake";
1001     std::cerr << cMakeSelf.c_str() << "\n";
1002     }
1003 #endif
1004   if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
1005     {
1006     cmSystemTools::Error("CMake executable cannot be found at ",
1007                          cMakeSelf.c_str());
1008     return 0;
1009     }
1010   // Save the value in the cache
1011   this->CacheManager->AddCacheEntry
1012     ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
1013      cmCacheManager::INTERNAL);
1014   // if the edit command is not yet in the cache,
1015   // or if CMakeEditCommand has been set on this object,
1016   // then set the CMAKE_EDIT_COMMAND in the cache
1017   // This will mean that the last gui to edit the cache
1018   // will be the one that make edit_cache uses.
1019   if(!this->GetCacheDefinition("CMAKE_EDIT_COMMAND")
1020     || !this->CMakeEditCommand.empty())
1021     {
1022     // Find and save the command to edit the cache
1023     std::string editCacheCommand;
1024     if(!this->CMakeEditCommand.empty())
1025       {
1026       editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf)
1027         + std::string("/")
1028         + this->CMakeEditCommand
1029         + cmSystemTools::GetFilenameExtension(cMakeSelf);
1030       }
1031     if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
1032       {
1033       editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1034         "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1035       }
1036     if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
1037       {
1038       editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1039         "/cmake-gui" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1040       }
1041     if(cmSystemTools::FileExists(editCacheCommand.c_str()))
1042       {
1043       this->CacheManager->AddCacheEntry
1044         ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
1045          "Path to cache edit program executable.", cmCacheManager::INTERNAL);
1046       }
1047     }
1048   std::string ctestCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1049     "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1050   if(cmSystemTools::FileExists(ctestCommand.c_str()))
1051     {
1052     this->CacheManager->AddCacheEntry
1053       ("CMAKE_CTEST_COMMAND", ctestCommand.c_str(),
1054        "Path to ctest program executable.", cmCacheManager::INTERNAL);
1055     }
1056   std::string cpackCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1057     "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1058   if(cmSystemTools::FileExists(cpackCommand.c_str()))
1059     {
1060     this->CacheManager->AddCacheEntry
1061       ("CMAKE_CPACK_COMMAND", cpackCommand.c_str(),
1062        "Path to cpack program executable.", cmCacheManager::INTERNAL);
1063     }
1064
1065   // do CMAKE_ROOT, look for the environment variable first
1066   std::string cMakeRoot;
1067   std::string modules;
1068   if (getenv("CMAKE_ROOT"))
1069     {
1070     cMakeRoot = getenv("CMAKE_ROOT");
1071     modules = cMakeRoot + "/Modules/CMake.cmake";
1072     }
1073   if(!cmSystemTools::FileExists(modules.c_str()))
1074     {
1075     // next try exe/..
1076     cMakeRoot = cmSystemTools::GetRealPath(cMakeSelf.c_str());
1077     cMakeRoot = cmSystemTools::GetProgramPath(cMakeRoot.c_str());
1078     std::string::size_type slashPos = cMakeRoot.rfind("/");
1079     if(slashPos != std::string::npos)
1080       {
1081       cMakeRoot = cMakeRoot.substr(0, slashPos);
1082       }
1083     // is there no Modules directory there?
1084     modules = cMakeRoot + "/Modules/CMake.cmake";
1085     }
1086
1087   if (!cmSystemTools::FileExists(modules.c_str()))
1088     {
1089     // try exe/../share/cmake
1090     cMakeRoot += CMAKE_DATA_DIR;
1091     modules = cMakeRoot + "/Modules/CMake.cmake";
1092     }
1093 #ifdef CMAKE_ROOT_DIR
1094   if (!cmSystemTools::FileExists(modules.c_str()))
1095     {
1096     // try compiled in root directory
1097     cMakeRoot = CMAKE_ROOT_DIR;
1098     modules = cMakeRoot + "/Modules/CMake.cmake";
1099     }
1100 #endif
1101   if (!cmSystemTools::FileExists(modules.c_str()))
1102     {
1103     // try
1104     cMakeRoot  = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
1105     cMakeRoot += CMAKE_DATA_DIR;
1106     modules = cMakeRoot +  "/Modules/CMake.cmake";
1107     }
1108   if(!cmSystemTools::FileExists(modules.c_str()))
1109     {
1110     // next try exe
1111     cMakeRoot  = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
1112     // is there no Modules directory there?
1113     modules = cMakeRoot + "/Modules/CMake.cmake";
1114     }
1115   if (!cmSystemTools::FileExists(modules.c_str()))
1116     {
1117     // couldn't find modules
1118     cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n"
1119       "CMake has most likely not been installed correctly.\n"
1120       "Modules directory not found in\n",
1121       cMakeRoot.c_str());
1122     return 0;
1123     }
1124   this->CacheManager->AddCacheEntry
1125     ("CMAKE_ROOT", cMakeRoot.c_str(),
1126      "Path to CMake installation.", cmCacheManager::INTERNAL);
1127
1128 #ifdef _WIN32
1129   std::string comspec = "cmw9xcom.exe";
1130   cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
1131 #endif
1132   return 1;
1133 }
1134
1135
1136
1137 void CMakeCommandUsage(const char* program)
1138 {
1139   cmOStringStream errorStream;
1140
1141 #ifdef CMAKE_BUILD_WITH_CMAKE
1142   errorStream
1143     << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
1144 #else
1145   errorStream
1146     << "cmake bootstrap\n";
1147 #endif
1148   // If you add new commands, change here,
1149   // and in cmakemain.cxx in the options table
1150   errorStream
1151     << "Usage: " << program << " -E [command] [arguments ...]\n"
1152     << "Available commands: \n"
1153     << "  chdir dir cmd [args]...   - run command in a given directory\n"
1154     << "  compare_files file1 file2 - check if file1 is same as file2\n"
1155     << "  copy file destination     - copy file to destination (either file "
1156        "or directory)\n"
1157     << "  copy_directory source destination   - copy directory 'source' "
1158        "content to directory 'destination'\n"
1159     << "  copy_if_different in-file out-file  - copy file if input has "
1160        "changed\n"
1161     << "  echo [string]...          - displays arguments as text\n"
1162     << "  echo_append [string]...   - displays arguments as text but no new "
1163        "line\n"
1164     << "  environment               - display the current environment\n"
1165     << "  make_directory dir        - create a directory\n"
1166     << "  md5sum file1 [...]        - compute md5sum of files\n"
1167     << "  remove [-f] file1 file2 ... - remove the file(s), use -f to force "
1168        "it\n"
1169     << "  remove_directory dir      - remove a directory and its contents\n"
1170     << "  rename oldname newname    - rename a file or directory "
1171        "(on one volume)\n"
1172     << "  tar [cxt][vfz][cvfj] file.tar [file/dir1 file/dir2 ...]\n"
1173     << "                            - create or extract a tar or zip archive\n"
1174     << "  time command [args] ...   - run command and return elapsed time\n"
1175     << "  touch file                - touch a file.\n"
1176     << "  touch_nocreate file       - touch a file but do not create it.\n"
1177 #if defined(_WIN32) && !defined(__CYGWIN__)
1178     << "Available on Windows only:\n"
1179     << "  comspec                   - on windows 9x use this for RunCommand\n"
1180     << "  delete_regv key           - delete registry value\n"
1181     << "  env_vs8_wince sdkname     - displays a batch file which sets the "
1182        "environment for the provided Windows CE SDK installed in VS2005\n"
1183     << "  env_vs9_wince sdkname     - displays a batch file which sets the "
1184        "environment for the provided Windows CE SDK installed in VS2008\n"
1185     << "  write_regv key value      - write registry value\n"
1186 #else
1187     << "Available on UNIX only:\n"
1188     << "  create_symlink old new    - create a symbolic link new -> old\n"
1189 #endif
1190     ;
1191
1192   cmSystemTools::Error(errorStream.str().c_str());
1193 }
1194
1195 int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
1196 {
1197   // IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
1198   if (args.size() > 1)
1199     {
1200     // Copy file
1201     if (args[1] == "copy" && args.size() == 4)
1202       {
1203       if(!cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str()))
1204         {
1205         std::cerr << "Error copying file \"" << args[2].c_str()
1206                   << "\" to \"" << args[3].c_str() << "\".\n";
1207         return 1;
1208         }
1209       return 0;
1210       }
1211
1212     // Copy file if different.
1213     if (args[1] == "copy_if_different" && args.size() == 4)
1214       {
1215       if(!cmSystemTools::CopyFileIfDifferent(args[2].c_str(),
1216           args[3].c_str()))
1217         {
1218         std::cerr << "Error copying file (if different) from \""
1219                   << args[2].c_str() << "\" to \"" << args[3].c_str()
1220                   << "\".\n";
1221         return 1;
1222         }
1223       return 0;
1224       }
1225
1226     // Copy directory content
1227     if (args[1] == "copy_directory" && args.size() == 4)
1228       {
1229       if(!cmSystemTools::CopyADirectory(args[2].c_str(), args[3].c_str()))
1230         {
1231         std::cerr << "Error copying directory from \""
1232                   << args[2].c_str() << "\" to \"" << args[3].c_str()
1233                   << "\".\n";
1234         return 1;
1235         }
1236       return 0;
1237       }
1238
1239     // Rename a file or directory
1240     if (args[1] == "rename" && args.size() == 4)
1241       {
1242       if(!cmSystemTools::RenameFile(args[2].c_str(), args[3].c_str()))
1243         {
1244         std::string e = cmSystemTools::GetLastSystemError();
1245         std::cerr << "Error renaming from \""
1246                   << args[2].c_str() << "\" to \"" << args[3].c_str()
1247                   << "\": " << e << "\n";
1248         return 1;
1249         }
1250       return 0;
1251       }
1252
1253     // Compare files
1254     if (args[1] == "compare_files" && args.size() == 4)
1255       {
1256       if(cmSystemTools::FilesDiffer(args[2].c_str(), args[3].c_str()))
1257         {
1258         std::cerr << "Files \""
1259                   << args[2].c_str() << "\" to \"" << args[3].c_str()
1260                   << "\" are different.\n";
1261         return 1;
1262         }
1263       return 0;
1264       }
1265
1266     // Echo string
1267     else if (args[1] == "echo" )
1268       {
1269       unsigned int cc;
1270       const char* space = "";
1271       for ( cc = 2; cc < args.size(); cc ++ )
1272         {
1273         std::cout << space << args[cc];
1274         space = " ";
1275         }
1276       std::cout << std::endl;
1277       return 0;
1278       }
1279
1280     // Echo string no new line
1281     else if (args[1] == "echo_append" )
1282       {
1283       unsigned int cc;
1284       const char* space = "";
1285       for ( cc = 2; cc < args.size(); cc ++ )
1286         {
1287         std::cout << space << args[cc];
1288         space = " ";
1289         }
1290       return 0;
1291       }
1292
1293 #if defined(CMAKE_BUILD_WITH_CMAKE)
1294     // Command to create a symbolic link.  Fails on platforms not
1295     // supporting them.
1296     else if (args[1] == "environment" )
1297       {
1298       std::vector<std::string> env = cmSystemTools::GetEnvironmentVariables();
1299       std::vector<std::string>::iterator it;
1300       for ( it = env.begin(); it != env.end(); ++ it )
1301         {
1302         std::cout << it->c_str() << std::endl;
1303         }
1304       return 0;
1305       }
1306 #endif
1307
1308     else if (args[1] == "make_directory" && args.size() == 3)
1309       {
1310       if(!cmSystemTools::MakeDirectory(args[2].c_str()))
1311         {
1312         std::cerr << "Error making directory \"" << args[2].c_str()
1313                   << "\".\n";
1314         return 1;
1315         }
1316       return 0;
1317       }
1318
1319     else if (args[1] == "remove_directory" && args.size() == 3)
1320       {
1321       if(cmSystemTools::FileIsDirectory(args[2].c_str()) &&
1322          !cmSystemTools::RemoveADirectory(args[2].c_str()))
1323         {
1324         std::cerr << "Error removing directory \"" << args[2].c_str()
1325                   << "\".\n";
1326         return 1;
1327         }
1328       return 0;
1329       }
1330
1331     // Remove file
1332     else if (args[1] == "remove" && args.size() > 2)
1333       {
1334       bool force = false;
1335       for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1336         {
1337         if(args[cc] == "\\-f" || args[cc] == "-f")
1338           {
1339           force = true;
1340           }
1341         else
1342           {
1343           // Complain if the file could not be removed, still exists,
1344           // and the -f option was not given.
1345           if(!cmSystemTools::RemoveFile(args[cc].c_str()) && !force &&
1346              cmSystemTools::FileExists(args[cc].c_str()))
1347             {
1348             return 1;
1349             }
1350           }
1351         }
1352       return 0;
1353       }
1354     // Touch file
1355     else if (args[1] == "touch" && args.size() > 2)
1356       {
1357       for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1358         {
1359         // Complain if the file could not be removed, still exists,
1360         // and the -f option was not given.
1361         if(!cmSystemTools::Touch(args[cc].c_str(), true))
1362           {
1363           return 1;
1364           }
1365         }
1366       return 0;
1367       }
1368     // Touch file
1369     else if (args[1] == "touch_nocreate" && args.size() > 2)
1370       {
1371       for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1372         {
1373         // Complain if the file could not be removed, still exists,
1374         // and the -f option was not given.
1375         if(!cmSystemTools::Touch(args[cc].c_str(), false))
1376           {
1377           return 1;
1378           }
1379         }
1380       return 0;
1381       }
1382
1383     // Clock command
1384     else if (args[1] == "time" && args.size() > 2)
1385       {
1386       std::string command = args[2];
1387       for (std::string::size_type cc = 3; cc < args.size(); cc ++)
1388         {
1389         command += " ";
1390         command += args[cc];
1391         }
1392
1393       clock_t clock_start, clock_finish;
1394       time_t time_start, time_finish;
1395
1396       time(&time_start);
1397       clock_start = clock();
1398       int ret =0;
1399       cmSystemTools::RunSingleCommand(command.c_str(), 0, &ret);
1400
1401       clock_finish = clock();
1402       time(&time_finish);
1403
1404       double clocks_per_sec = static_cast<double>(CLOCKS_PER_SEC);
1405       std::cout << "Elapsed time: "
1406         << static_cast<long>(time_finish - time_start) << " s. (time)"
1407         << ", "
1408         << static_cast<double>(clock_finish - clock_start) / clocks_per_sec
1409         << " s. (clock)"
1410         << "\n";
1411       return ret;
1412       }
1413     // Command to calculate the md5sum of a file
1414     else if (args[1] == "md5sum" && args.size() >= 3)
1415       {
1416       char md5out[32];
1417       int retval = 0;
1418       for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1419         {
1420         const char *filename = args[cc].c_str();
1421         // Cannot compute md5sum of a directory
1422         if(cmSystemTools::FileIsDirectory(filename))
1423           {
1424           std::cerr << "Error: " << filename << " is a directory" << std::endl;
1425           retval++;
1426           }
1427         else if(!cmSystemTools::ComputeFileMD5(filename, md5out))
1428           {
1429           // To mimic md5sum behavior in a shell:
1430           std::cerr << filename << ": No such file or directory" << std::endl;
1431           retval++;
1432           }
1433         else
1434           {
1435           std::cout << std::string(md5out,32) << "  " << filename << std::endl;
1436           }
1437         }
1438       return retval;
1439       }
1440
1441     // Command to change directory and run a program.
1442     else if (args[1] == "chdir" && args.size() >= 4)
1443       {
1444       std::string directory = args[2];
1445       if(!cmSystemTools::FileExists(directory.c_str()))
1446         {
1447         cmSystemTools::Error("Directory does not exist for chdir command: ",
1448                              args[2].c_str());
1449         return 1;
1450         }
1451
1452       std::string command = "\"";
1453       command += args[3];
1454       command += "\"";
1455       for (std::string::size_type cc = 4; cc < args.size(); cc ++)
1456         {
1457         command += " \"";
1458         command += args[cc];
1459         command += "\"";
1460         }
1461       int retval = 0;
1462       int timeout = 0;
1463       if ( cmSystemTools::RunSingleCommand(command.c_str(), 0, &retval,
1464              directory.c_str(), cmSystemTools::OUTPUT_NORMAL, timeout) )
1465         {
1466         return retval;
1467         }
1468
1469       return 1;
1470       }
1471
1472     // Command to start progress for a build
1473     else if (args[1] == "cmake_progress_start" && args.size() == 4)
1474       {
1475       // basically remove the directory
1476       std::string dirName = args[2];
1477       dirName += "/Progress";
1478       cmSystemTools::RemoveADirectory(dirName.c_str());
1479
1480       // is the last argument a filename that exists?
1481       FILE *countFile = fopen(args[3].c_str(),"r");
1482       int count;
1483       if (countFile)
1484         {
1485         if (1!=fscanf(countFile,"%i",&count))
1486           {
1487           cmSystemTools::Message("Could not read from count file.");
1488           }
1489         fclose(countFile);
1490         }
1491       else
1492         {
1493         count = atoi(args[3].c_str());
1494         }
1495       if (count)
1496         {
1497         cmSystemTools::MakeDirectory(dirName.c_str());
1498         // write the count into the directory
1499         std::string fName = dirName;
1500         fName += "/count.txt";
1501         FILE *progFile = fopen(fName.c_str(),"w");
1502         if (progFile)
1503           {
1504           fprintf(progFile,"%i\n",count);
1505           fclose(progFile);
1506           }
1507         }
1508       return 0;
1509       }
1510
1511     // Command to report progress for a build
1512     else if (args[1] == "cmake_progress_report" && args.size() >= 3)
1513       {
1514       std::string dirName = args[2];
1515       dirName += "/Progress";
1516       std::string fName;
1517       FILE *progFile;
1518
1519       // read the count
1520       fName = dirName;
1521       fName += "/count.txt";
1522       progFile = fopen(fName.c_str(),"r");
1523       int count = 0;
1524       if (!progFile)
1525         {
1526         return 0;
1527         }
1528       else
1529         {
1530         if (1!=fscanf(progFile,"%i",&count))
1531           {
1532           cmSystemTools::Message("Could not read from progress file.");
1533           }
1534         fclose(progFile);
1535         }
1536       unsigned int i;
1537       for (i = 3; i < args.size(); ++i)
1538         {
1539         fName = dirName;
1540         fName += "/";
1541         fName += args[i];
1542         progFile = fopen(fName.c_str(),"w");
1543         if (progFile)
1544           {
1545           fprintf(progFile,"empty");
1546           fclose(progFile);
1547           }
1548         }
1549       int fileNum = static_cast<int>
1550         (cmsys::Directory::GetNumberOfFilesInDirectory(dirName.c_str()));
1551       if (count > 0)
1552         {
1553         // print the progress
1554         fprintf(stdout,"[%3i%%] ",((fileNum-3)*100)/count);
1555         }
1556       return 0;
1557       }
1558
1559     // Command to create a symbolic link.  Fails on platforms not
1560     // supporting them.
1561     else if (args[1] == "create_symlink" && args.size() == 4)
1562       {
1563       const char* destinationFileName = args[3].c_str();
1564       if ( cmSystemTools::FileExists(destinationFileName) )
1565         {
1566         if ( cmSystemTools::FileIsSymlink(destinationFileName) )
1567           {
1568           if ( !cmSystemTools::RemoveFile(destinationFileName) ||
1569             cmSystemTools::FileExists(destinationFileName) )
1570             {
1571             return 0;
1572             }
1573           }
1574         else
1575           {
1576           return 0;
1577           }
1578         }
1579       return cmSystemTools::CreateSymlink(args[2].c_str(),
1580                                           args[3].c_str())? 0:1;
1581       }
1582
1583     // Internal CMake shared library support.
1584     else if (args[1] == "cmake_symlink_library" && args.size() == 5)
1585       {
1586       return cmake::SymlinkLibrary(args);
1587       }
1588     // Internal CMake versioned executable support.
1589     else if (args[1] == "cmake_symlink_executable" && args.size() == 4)
1590       {
1591       return cmake::SymlinkExecutable(args);
1592       }
1593
1594 #if defined(CMAKE_HAVE_VS_GENERATORS)
1595     // Internal CMake support for calling Visual Studio macros.
1596     else if (args[1] == "cmake_call_visual_studio_macro" && args.size() >= 4)
1597       {
1598       // args[2] = full path to .sln file or "ALL"
1599       // args[3] = name of Visual Studio macro to call
1600       // args[4..args.size()-1] = [optional] args for Visual Studio macro
1601
1602       std::string macroArgs;
1603
1604       if (args.size() > 4)
1605         {
1606         macroArgs = args[4];
1607
1608         for (size_t i = 5; i < args.size(); ++i)
1609           {
1610           macroArgs += " ";
1611           macroArgs += args[i];
1612           }
1613         }
1614
1615       return cmCallVisualStudioMacro::CallMacro(args[2], args[3],
1616         macroArgs, true);
1617       }
1618 #endif
1619
1620     // Internal CMake dependency scanning support.
1621     else if (args[1] == "cmake_depends" && args.size() >= 6)
1622       {
1623       // Use the make system's VERBOSE environment variable to enable
1624       // verbose output. This can be skipped by also setting CMAKE_NO_VERBOSE
1625       // (which is set by the Eclipse and KDevelop generators).
1626       bool verbose = ((cmSystemTools::GetEnv("VERBOSE") != 0)
1627                        && (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == 0));
1628
1629       // Create a cmake object instance to process dependencies.
1630       cmake cm;
1631       std::string gen;
1632       std::string homeDir;
1633       std::string startDir;
1634       std::string homeOutDir;
1635       std::string startOutDir;
1636       std::string depInfo;
1637       bool color = false;
1638       if(args.size() >= 8)
1639         {
1640         // Full signature:
1641         //
1642         //   -E cmake_depends <generator>
1643         //                    <home-src-dir> <start-src-dir>
1644         //                    <home-out-dir> <start-out-dir>
1645         //                    <dep-info> [--color=$(COLOR)]
1646         //
1647         // All paths are provided.
1648         gen = args[2];
1649         homeDir = args[3];
1650         startDir = args[4];
1651         homeOutDir = args[5];
1652         startOutDir = args[6];
1653         depInfo = args[7];
1654         if(args.size() >= 9 &&
1655            args[8].length() >= 8 &&
1656            args[8].substr(0, 8) == "--color=")
1657           {
1658           // Enable or disable color based on the switch value.
1659           color = (args[8].size() == 8 ||
1660                    cmSystemTools::IsOn(args[8].substr(8).c_str()));
1661           }
1662         }
1663       else
1664         {
1665         // Support older signature for existing makefiles:
1666         //
1667         //   -E cmake_depends <generator>
1668         //                    <home-out-dir> <start-out-dir>
1669         //                    <dep-info>
1670         //
1671         // Just pretend the source directories are the same as the
1672         // binary directories so at least scanning will work.
1673         gen = args[2];
1674         homeDir = args[3];
1675         startDir = args[4];
1676         homeOutDir = args[3];
1677         startOutDir = args[3];
1678         depInfo = args[5];
1679         }
1680
1681       // Create a local generator configured for the directory in
1682       // which dependencies will be scanned.
1683       homeDir = cmSystemTools::CollapseFullPath(homeDir.c_str());
1684       startDir = cmSystemTools::CollapseFullPath(startDir.c_str());
1685       homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir.c_str());
1686       startOutDir = cmSystemTools::CollapseFullPath(startOutDir.c_str());
1687       cm.SetHomeDirectory(homeDir.c_str());
1688       cm.SetStartDirectory(startDir.c_str());
1689       cm.SetHomeOutputDirectory(homeOutDir.c_str());
1690       cm.SetStartOutputDirectory(startOutDir.c_str());
1691       if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str()))
1692         {
1693         cm.SetGlobalGenerator(ggd);
1694         cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
1695         lgd->GetMakefile()->SetStartDirectory(startDir.c_str());
1696         lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
1697         lgd->GetMakefile()->MakeStartDirectoriesCurrent();
1698
1699         // Actually scan dependencies.
1700         return lgd->UpdateDependencies(depInfo.c_str(),
1701                                        verbose, color)? 0 : 2;
1702         }
1703       return 1;
1704       }
1705
1706     // Internal CMake link script support.
1707     else if (args[1] == "cmake_link_script" && args.size() >= 3)
1708       {
1709       return cmake::ExecuteLinkScript(args);
1710       }
1711
1712     // Internal CMake unimplemented feature notification.
1713     else if (args[1] == "cmake_unimplemented_variable")
1714       {
1715       std::cerr << "Feature not implemented for this platform.";
1716       if(args.size() == 3)
1717         {
1718         std::cerr << "  Variable " << args[2] << " is not set.";
1719         }
1720       std::cerr << std::endl;
1721       return 1;
1722       }
1723     else if (args[1] == "vs_link_exe")
1724       {
1725       return cmake::VisualStudioLink(args, 1);
1726       }
1727     else if (args[1] == "vs_link_dll")
1728       {
1729       return cmake::VisualStudioLink(args, 2);
1730       }
1731 #ifdef CMAKE_BUILD_WITH_CMAKE
1732     // Internal CMake color makefile support.
1733     else if (args[1] == "cmake_echo_color")
1734       {
1735       return cmake::ExecuteEchoColor(args);
1736       }
1737     else if (args[1] == "cmake_automoc" && args.size() >= 4)
1738       {
1739         cmQtAutomoc automoc;
1740         const char *config = args[3].empty() ? 0 : args[3].c_str();
1741         bool automocSuccess = automoc.Run(args[2].c_str(), config);
1742         return automocSuccess ? 0 : 1;
1743       }
1744 #endif
1745
1746     // Tar files
1747     else if (args[1] == "tar" && args.size() > 3)
1748       {
1749       std::string flags = args[2];
1750       std::string outFile = args[3];
1751       std::vector<cmStdString> files;
1752       for (std::string::size_type cc = 4; cc < args.size(); cc ++)
1753         {
1754         files.push_back(args[cc]);
1755         }
1756       bool gzip = false;
1757       bool bzip2 = false;
1758       bool verbose = false;
1759       if ( flags.find_first_of('j') != flags.npos )
1760         {
1761         bzip2 = true;
1762         }
1763       if ( flags.find_first_of('z') != flags.npos )
1764         {
1765         gzip = true;
1766         }
1767       if ( flags.find_first_of('v') != flags.npos )
1768         {
1769         verbose = true;
1770         }
1771
1772       if ( flags.find_first_of('t') != flags.npos )
1773         {
1774         if ( !cmSystemTools::ListTar(outFile.c_str(), gzip, verbose) )
1775           {
1776           cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
1777           return 1;
1778           }
1779         }
1780       else if ( flags.find_first_of('c') != flags.npos )
1781         {
1782         if ( !cmSystemTools::CreateTar(
1783                outFile.c_str(), files, gzip, bzip2, verbose) )
1784           {
1785           cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
1786           return 1;
1787           }
1788         }
1789       else if ( flags.find_first_of('x') != flags.npos )
1790         {
1791         if ( !cmSystemTools::ExtractTar(
1792             outFile.c_str(), gzip, verbose) )
1793           {
1794           cmSystemTools::Error("Problem extracting tar: ", outFile.c_str());
1795           return 1;
1796           }
1797 #ifdef WIN32
1798         // OK, on windows 7 after we untar some files,
1799         // sometimes we can not rename the directory after
1800         // the untar is done. This breaks the external project
1801         // untar and rename code.  So, by default we will wait
1802         // 1/10th of a second after the untar.  If CMAKE_UNTAR_DELAY
1803         // is set in the env, its value will be used instead of 100.
1804         int delay = 100;
1805         const char* delayVar = cmSystemTools::GetEnv("CMAKE_UNTAR_DELAY");
1806         if(delayVar)
1807           {
1808           delay = atoi(delayVar);
1809           }
1810         if(delay)
1811           {
1812           cmSystemTools::Delay(delay);
1813           }
1814 #endif
1815         }
1816       return 0;
1817       }
1818
1819 #if defined(CMAKE_BUILD_WITH_CMAKE)
1820     // Internal CMake Fortran module support.
1821     else if (args[1] == "cmake_copy_f90_mod" && args.size() >= 4)
1822       {
1823       return cmDependsFortran::CopyModule(args)? 0 : 1;
1824       }
1825 #endif
1826
1827 #if defined(_WIN32) && !defined(__CYGWIN__)
1828     // Write registry value
1829     else if (args[1] == "write_regv" && args.size() > 3)
1830       {
1831       return cmSystemTools::WriteRegistryValue(args[2].c_str(),
1832                                                args[3].c_str()) ? 0 : 1;
1833       }
1834
1835     // Delete registry value
1836     else if (args[1] == "delete_regv" && args.size() > 2)
1837       {
1838       return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
1839       }
1840     // Remove file
1841     else if (args[1] == "comspec" && args.size() > 2)
1842       {
1843       unsigned int cc;
1844       std::string command = args[2];
1845       for ( cc = 3; cc < args.size(); cc ++ )
1846         {
1847         command += " " + args[cc];
1848         }
1849       return cmWin32ProcessExecution::Windows9xHack(command.c_str());
1850       }
1851     else if (args[1] == "env_vs8_wince" && args.size() == 3)
1852       {
1853       return cmake::WindowsCEEnvironment("8.0", args[2]);
1854       }
1855     else if (args[1] == "env_vs9_wince" && args.size() == 3)
1856       {
1857       return cmake::WindowsCEEnvironment("9.0", args[2]);
1858       }
1859 #endif
1860     }
1861
1862   ::CMakeCommandUsage(args[0].c_str());
1863   return 1;
1864 }
1865
1866 void cmake::AddExtraGenerator(const char* name,
1867                               CreateExtraGeneratorFunctionType newFunction)
1868 {
1869   cmExternalMakefileProjectGenerator* extraGenerator = newFunction();
1870   const std::vector<std::string>& supportedGlobalGenerators =
1871                                 extraGenerator->GetSupportedGlobalGenerators();
1872
1873   for(std::vector<std::string>::const_iterator
1874       it = supportedGlobalGenerators.begin();
1875       it != supportedGlobalGenerators.end();
1876       ++it )
1877     {
1878     std::string fullName = cmExternalMakefileProjectGenerator::
1879                                     CreateFullGeneratorName(it->c_str(), name);
1880     this->ExtraGenerators[fullName.c_str()] = newFunction;
1881     }
1882   delete extraGenerator;
1883 }
1884
1885 void cmake::AddDefaultExtraGenerators()
1886 {
1887 #if defined(CMAKE_BUILD_WITH_CMAKE)
1888 #if defined(_WIN32) && !defined(__CYGWIN__)
1889   // e.g. kdevelop4 ?
1890 #endif
1891
1892   this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
1893                           &cmExtraCodeBlocksGenerator::New);
1894   this->AddExtraGenerator(cmExtraSublimeTextGenerator::GetActualName(),
1895                           &cmExtraSublimeTextGenerator::New);
1896
1897 #ifdef CMAKE_USE_ECLIPSE
1898   this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
1899                           &cmExtraEclipseCDT4Generator::New);
1900 #endif
1901
1902 #ifdef CMAKE_USE_KDEVELOP
1903   this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
1904                           &cmGlobalKdevelopGenerator::New);
1905   // for kdevelop also add the generator with just the name of the
1906   // extra generator, since it was this way since cmake 2.2
1907   this->ExtraGenerators[cmGlobalKdevelopGenerator::GetActualName()]
1908                                              = &cmGlobalKdevelopGenerator::New;
1909 #endif
1910
1911 #endif
1912 }
1913
1914
1915 //----------------------------------------------------------------------------
1916 void cmake::GetRegisteredGenerators(std::vector<std::string>& names)
1917 {
1918   for(RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
1919       i != this->Generators.end(); ++i)
1920     {
1921     (*i)->GetGenerators(names);
1922     }
1923   for(RegisteredExtraGeneratorsMap::const_iterator
1924       i = this->ExtraGenerators.begin();
1925       i != this->ExtraGenerators.end(); ++i)
1926     {
1927     names.push_back(i->first);
1928     }
1929 }
1930
1931 cmGlobalGenerator* cmake::CreateGlobalGenerator(const char* name)
1932 {
1933   cmExternalMakefileProjectGenerator* extraGenerator = 0;
1934   RegisteredExtraGeneratorsMap::const_iterator extraGenIt =
1935                                             this->ExtraGenerators.find(name);
1936   if (extraGenIt != this->ExtraGenerators.end())
1937     {
1938     extraGenerator = (extraGenIt->second)();
1939     name = extraGenerator->GetGlobalGeneratorName(name);
1940     }
1941
1942   cmGlobalGenerator* generator = 0;
1943   for (RegisteredGeneratorsVector::const_iterator i =
1944     this->Generators.begin(); i != this->Generators.end(); ++i)
1945     {
1946     generator = (*i)->CreateGlobalGenerator(name);
1947     if (generator)
1948       {
1949       break;
1950       }
1951     }
1952
1953   if (generator)
1954     {
1955     generator->SetCMakeInstance(this);
1956     generator->SetExternalMakefileProjectGenerator(extraGenerator);
1957     }
1958   else
1959     {
1960     delete extraGenerator;
1961     }
1962
1963   return generator;
1964 }
1965
1966 void cmake::SetHomeDirectory(const char* dir)
1967 {
1968   this->cmHomeDirectory = dir;
1969   cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory);
1970 }
1971
1972 void cmake::SetHomeOutputDirectory(const char* lib)
1973 {
1974   this->HomeOutputDirectory = lib;
1975   cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory);
1976 }
1977
1978 void cmake::SetGlobalGenerator(cmGlobalGenerator *gg)
1979 {
1980   if(!gg)
1981     {
1982     cmSystemTools::Error("Error SetGlobalGenerator called with null");
1983     return;
1984     }
1985   // delete the old generator
1986   if (this->GlobalGenerator)
1987     {
1988     delete this->GlobalGenerator;
1989     // restore the original environment variables CXX and CC
1990     // Restore CC
1991     std::string env = "CC=";
1992     if(this->CCEnvironment.size())
1993       {
1994       env += this->CCEnvironment;
1995       }
1996     cmSystemTools::PutEnv(env.c_str());
1997     env = "CXX=";
1998     if(this->CXXEnvironment.size())
1999       {
2000       env += this->CXXEnvironment;
2001       }
2002     cmSystemTools::PutEnv(env.c_str());
2003     }
2004
2005   // set the new
2006   this->GlobalGenerator = gg;
2007
2008   // set the global flag for unix style paths on cmSystemTools as soon as
2009   // the generator is set.  This allows gmake to be used on windows.
2010   cmSystemTools::SetForceUnixPaths
2011     (this->GlobalGenerator->GetForceUnixPaths());
2012
2013   // Save the environment variables CXX and CC
2014   const char* cxx = getenv("CXX");
2015   const char* cc = getenv("CC");
2016   if(cxx)
2017     {
2018     this->CXXEnvironment = cxx;
2019     }
2020   else
2021     {
2022     this->CXXEnvironment = "";
2023     }
2024   if(cc)
2025     {
2026     this->CCEnvironment = cc;
2027     }
2028   else
2029     {
2030     this->CCEnvironment = "";
2031     }
2032   // set the cmake instance just to be sure
2033   gg->SetCMakeInstance(this);
2034 }
2035
2036 int cmake::DoPreConfigureChecks()
2037 {
2038   // Make sure the Start directory contains a CMakeLists.txt file.
2039   std::string srcList = this->GetHomeDirectory();
2040   srcList += "/CMakeLists.txt";
2041   if(!cmSystemTools::FileExists(srcList.c_str()))
2042     {
2043     cmOStringStream err;
2044     if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
2045       {
2046       err << "The source directory \"" << this->GetHomeDirectory()
2047           << "\" does not appear to contain CMakeLists.txt.\n";
2048       }
2049     else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
2050       {
2051       err << "The source directory \"" << this->GetHomeDirectory()
2052           << "\" is a file, not a directory.\n";
2053       }
2054     else
2055       {
2056       err << "The source directory \"" << this->GetHomeDirectory()
2057           << "\" does not exist.\n";
2058       }
2059     err << "Specify --help for usage, or press the help button on the CMake "
2060       "GUI.";
2061     cmSystemTools::Error(err.str().c_str());
2062     return -2;
2063     }
2064
2065   // do a sanity check on some values
2066   if(this->CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY"))
2067     {
2068     std::string cacheStart =
2069       this->CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY");
2070     cacheStart += "/CMakeLists.txt";
2071     std::string currentStart = this->GetHomeDirectory();
2072     currentStart += "/CMakeLists.txt";
2073     if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
2074       {
2075       std::string message = "The source \"";
2076       message += currentStart;
2077       message += "\" does not match the source \"";
2078       message += cacheStart;
2079       message += "\" used to generate cache.  ";
2080       message += "Re-run cmake with a different source directory.";
2081       cmSystemTools::Error(message.c_str());
2082       return -2;
2083       }
2084     }
2085   else
2086     {
2087     return 0;
2088     }
2089   return 1;
2090 }
2091 struct SaveCacheEntry
2092 {
2093   std::string key;
2094   std::string value;
2095   std::string help;
2096   cmCacheManager::CacheEntryType type;
2097 };
2098
2099 int cmake::HandleDeleteCacheVariables(const char* var)
2100 {
2101   std::vector<std::string> argsSplit;
2102   cmSystemTools::ExpandListArgument(std::string(var), argsSplit, true);
2103   // erase the property to avoid infinite recursion
2104   this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
2105   if(this->GetIsInTryCompile())
2106     {
2107     return 0;
2108     }
2109   cmCacheManager::CacheIterator ci = this->CacheManager->NewIterator();
2110   std::vector<SaveCacheEntry> saved;
2111   cmOStringStream warning;
2112   warning
2113     << "You have changed variables that require your cache to be deleted.\n"
2114     << "Configure will be re-run and you may have to reset some variables.\n"
2115     << "The following variables have changed:\n";
2116   for(std::vector<std::string>::iterator i = argsSplit.begin();
2117       i != argsSplit.end(); ++i)
2118     {
2119     SaveCacheEntry save;
2120     save.key = *i;
2121     warning << *i << "= ";
2122     i++;
2123     save.value = *i;
2124     warning << *i << "\n";
2125     if(ci.Find(save.key.c_str()))
2126       {
2127       save.type = ci.GetType();
2128       save.help = ci.GetProperty("HELPSTRING");
2129       }
2130     saved.push_back(save);
2131     }
2132
2133   // remove the cache
2134   this->CacheManager->DeleteCache(this->GetStartOutputDirectory());
2135   // load the empty cache
2136   this->LoadCache();
2137   // restore the changed compilers
2138   for(std::vector<SaveCacheEntry>::iterator i = saved.begin();
2139       i != saved.end(); ++i)
2140     {
2141     this->AddCacheEntry(i->key.c_str(), i->value.c_str(),
2142                         i->help.c_str(), i->type);
2143     }
2144   cmSystemTools::Message(warning.str().c_str());
2145   // avoid reconfigure if there were errors
2146   if(!cmSystemTools::GetErrorOccuredFlag())
2147     {
2148     // re-run configure
2149     return this->Configure();
2150     }
2151   return 0;
2152 }
2153
2154 int cmake::Configure()
2155 {
2156   if(this->DoSuppressDevWarnings)
2157     {
2158     if(this->SuppressDevWarnings)
2159       {
2160       this->CacheManager->
2161         AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE",
2162                       "Suppress Warnings that are meant for"
2163                       " the author of the CMakeLists.txt files.",
2164                       cmCacheManager::INTERNAL);
2165       }
2166     else
2167       {
2168       this->CacheManager->
2169         AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE",
2170                       "Suppress Warnings that are meant for"
2171                       " the author of the CMakeLists.txt files.",
2172                       cmCacheManager::INTERNAL);
2173       }
2174     }
2175   int ret = this->ActualConfigure();
2176   const char* delCacheVars =
2177     this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
2178   if(delCacheVars && delCacheVars[0] != 0)
2179     {
2180     return this->HandleDeleteCacheVariables(delCacheVars);
2181     }
2182   return ret;
2183
2184 }
2185
2186 int cmake::ActualConfigure()
2187 {
2188   // Construct right now our path conversion table before it's too late:
2189   this->UpdateConversionPathTable();
2190   this->CleanupCommandsAndMacros();
2191
2192   int res = 0;
2193   if ( this->GetWorkingMode() == NORMAL_MODE )
2194     {
2195     res = this->DoPreConfigureChecks();
2196     }
2197   if ( res < 0 )
2198     {
2199     return -2;
2200     }
2201   if ( !res )
2202     {
2203     this->CacheManager->AddCacheEntry
2204       ("CMAKE_HOME_DIRECTORY",
2205        this->GetHomeDirectory(),
2206        "Start directory with the top level CMakeLists.txt file for this "
2207        "project",
2208        cmCacheManager::INTERNAL);
2209     }
2210
2211   // no generator specified on the command line
2212   if(!this->GlobalGenerator)
2213     {
2214     const char* genName =
2215       this->CacheManager->GetCacheValue("CMAKE_GENERATOR");
2216     const char* extraGenName =
2217       this->CacheManager->GetCacheValue("CMAKE_EXTRA_GENERATOR");
2218     if(genName)
2219       {
2220       std::string fullName = cmExternalMakefileProjectGenerator::
2221                                 CreateFullGeneratorName(genName, extraGenName);
2222       this->GlobalGenerator = this->CreateGlobalGenerator(fullName.c_str());
2223       }
2224     if(this->GlobalGenerator)
2225       {
2226       // set the global flag for unix style paths on cmSystemTools as
2227       // soon as the generator is set.  This allows gmake to be used
2228       // on windows.
2229       cmSystemTools::SetForceUnixPaths
2230         (this->GlobalGenerator->GetForceUnixPaths());
2231       }
2232     else
2233       {
2234 #if defined(__BORLANDC__) && defined(_WIN32)
2235       this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator);
2236 #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
2237       std::string installedCompiler;
2238       // Try to find the newest VS installed on the computer and
2239       // use that as a default if -G is not specified
2240       const std::string vsregBase =
2241         "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\";
2242       std::vector<std::string> vsVerions;
2243       vsVerions.push_back("VisualStudio\\");
2244       vsVerions.push_back("VCExpress\\");
2245       vsVerions.push_back("WDExpress\\");
2246       struct VSRegistryEntryName
2247       {
2248         const char* MSVersion;
2249         const char* GeneratorName;
2250       };
2251       VSRegistryEntryName version[] = {
2252         {"6.0", "Visual Studio 6"},
2253         {"7.0", "Visual Studio 7"},
2254         {"7.1", "Visual Studio 7 .NET 2003"},
2255         {"8.0", "Visual Studio 8 2005"},
2256         {"9.0", "Visual Studio 9 2008"},
2257         {"10.0", "Visual Studio 10"},
2258         {"11.0", "Visual Studio 11"},
2259         {"12.0", "Visual Studio 12"},
2260         {0, 0}};
2261       for(int i=0; version[i].MSVersion != 0; i++)
2262         {
2263         for(size_t b=0; b < vsVerions.size(); b++)
2264           {
2265           std::string reg = vsregBase + vsVerions[b] + version[i].MSVersion;
2266           reg += ";InstallDir]";
2267           cmSystemTools::ExpandRegistryValues(reg,
2268                                               cmSystemTools::KeyWOW64_32);
2269           if (!(reg == "/registry"))
2270             {
2271             installedCompiler = version[i].GeneratorName;
2272             break;
2273             }
2274           }
2275         }
2276       cmGlobalGenerator* gen
2277         = this->CreateGlobalGenerator(installedCompiler.c_str());
2278       if(!gen)
2279         {
2280         gen = new cmGlobalNMakeMakefileGenerator;
2281         }
2282       this->SetGlobalGenerator(gen);
2283       std::cout << "-- Building for: " << gen->GetName() << "\n";
2284 #else
2285       this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3);
2286 #endif
2287       }
2288     if(!this->GlobalGenerator)
2289       {
2290       cmSystemTools::Error("Could not create generator");
2291       return -1;
2292       }
2293     }
2294
2295   const char* genName = this->CacheManager->GetCacheValue("CMAKE_GENERATOR");
2296   if(genName)
2297     {
2298     if(strcmp(this->GlobalGenerator->GetName(), genName) != 0)
2299       {
2300       std::string message = "Error: generator : ";
2301       message += this->GlobalGenerator->GetName();
2302       message += "\nDoes not match the generator used previously: ";
2303       message += genName;
2304       message +=
2305         "\nEither remove the CMakeCache.txt file or choose a different"
2306         " binary directory.";
2307       cmSystemTools::Error(message.c_str());
2308       return -2;
2309       }
2310     }
2311   if(!this->CacheManager->GetCacheValue("CMAKE_GENERATOR"))
2312     {
2313     this->CacheManager->AddCacheEntry("CMAKE_GENERATOR",
2314                                       this->GlobalGenerator->GetName(),
2315                                       "Name of generator.",
2316                                       cmCacheManager::INTERNAL);
2317     this->CacheManager->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
2318                                 this->GlobalGenerator->GetExtraGeneratorName(),
2319                                 "Name of external makefile project generator.",
2320                                 cmCacheManager::INTERNAL);
2321     }
2322
2323   if(const char* tsName =
2324      this->CacheManager->GetCacheValue("CMAKE_GENERATOR_TOOLSET"))
2325     {
2326     if(this->GeneratorToolset.empty())
2327       {
2328       this->GeneratorToolset = tsName;
2329       }
2330     else if(this->GeneratorToolset != tsName)
2331       {
2332       std::string message = "Error: generator toolset: ";
2333       message += this->GeneratorToolset;
2334       message += "\nDoes not match the toolset used previously: ";
2335       message += tsName;
2336       message +=
2337         "\nEither remove the CMakeCache.txt file or choose a different"
2338         " binary directory.";
2339       cmSystemTools::Error(message.c_str());
2340       return -2;
2341       }
2342     }
2343   else
2344     {
2345     this->CacheManager->AddCacheEntry("CMAKE_GENERATOR_TOOLSET",
2346                                       this->GeneratorToolset.c_str(),
2347                                       "Name of generator toolset.",
2348                                       cmCacheManager::INTERNAL);
2349     }
2350   if(!this->GeneratorToolset.empty() &&
2351      !this->GlobalGenerator->SetGeneratorToolset(this->GeneratorToolset))
2352     {
2353     return -2;
2354     }
2355
2356   // reset any system configuration information, except for when we are
2357   // InTryCompile. With TryCompile the system info is taken from the parent's
2358   // info to save time
2359   if (!this->InTryCompile)
2360     {
2361     this->GlobalGenerator->ClearEnabledLanguages();
2362     }
2363
2364   // Truncate log files
2365   if (!this->InTryCompile)
2366     {
2367     this->TruncateOutputLog("CMakeOutput.log");
2368     this->TruncateOutputLog("CMakeError.log");
2369     }
2370
2371   // actually do the configure
2372   this->GlobalGenerator->Configure();
2373   // Before saving the cache
2374   // if the project did not define one of the entries below, add them now
2375   // so users can edit the values in the cache:
2376
2377   // We used to always present LIBRARY_OUTPUT_PATH and
2378   // EXECUTABLE_OUTPUT_PATH.  They are now documented as old-style and
2379   // should no longer be used.  Therefore we present them only if the
2380   // project requires compatibility with CMake 2.4.  We detect this
2381   // here by looking for the old CMAKE_BACKWARDS_COMPATIBILITY
2382   // variable created when CMP0001 is not set to NEW.
2383   if(this->GetCacheManager()->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
2384     {
2385     if(!this->CacheManager->GetCacheValue("LIBRARY_OUTPUT_PATH"))
2386       {
2387       this->CacheManager->AddCacheEntry
2388         ("LIBRARY_OUTPUT_PATH", "",
2389          "Single output directory for building all libraries.",
2390          cmCacheManager::PATH);
2391       }
2392     if(!this->CacheManager->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
2393       {
2394       this->CacheManager->AddCacheEntry
2395         ("EXECUTABLE_OUTPUT_PATH", "",
2396          "Single output directory for building all executables.",
2397          cmCacheManager::PATH);
2398       }
2399     }
2400   if(!this->CacheManager->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
2401     {
2402     this->CacheManager->AddCacheEntry
2403       ("CMAKE_USE_RELATIVE_PATHS", "OFF",
2404        "If true, cmake will use relative paths in makefiles and projects.",
2405        cmCacheManager::BOOL);
2406     cmCacheManager::CacheIterator it =
2407       this->CacheManager->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
2408     if ( !it.PropertyExists("ADVANCED") )
2409       {
2410       it.SetProperty("ADVANCED", "1");
2411       }
2412     }
2413
2414   if(cmSystemTools::GetFatalErrorOccured() &&
2415      (!this->CacheManager->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
2416       cmSystemTools::IsOff(this->CacheManager->
2417                            GetCacheValue("CMAKE_MAKE_PROGRAM"))))
2418     {
2419     // We must have a bad generator selection.  Wipe the cache entry so the
2420     // user can select another.
2421     this->CacheManager->RemoveCacheEntry("CMAKE_GENERATOR");
2422     this->CacheManager->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
2423     }
2424
2425   cmMakefile* mf=this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
2426   if (mf->IsOn("CTEST_USE_LAUNCHERS")
2427               && !this->GetProperty("RULE_LAUNCH_COMPILE", cmProperty::GLOBAL))
2428     {
2429     cmSystemTools::Error("CTEST_USE_LAUNCHERS is enabled, but the "
2430                         "RULE_LAUNCH_COMPILE global property is not defined.\n"
2431                         "Did you forget to include(CTest) in the toplevel "
2432                          "CMakeLists.txt ?");
2433     }
2434
2435   // only save the cache if there were no fatal errors
2436   if ( this->GetWorkingMode() == NORMAL_MODE )
2437     {
2438     this->CacheManager->SaveCache(this->GetHomeOutputDirectory());
2439     }
2440   if ( !this->GraphVizFile.empty() )
2441     {
2442     std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl;
2443     this->GenerateGraphViz(this->GraphVizFile.c_str());
2444     }
2445   if(cmSystemTools::GetErrorOccuredFlag())
2446     {
2447     return -1;
2448     }
2449   return 0;
2450 }
2451
2452 void cmake::PreLoadCMakeFiles()
2453 {
2454   std::vector<std::string> args;
2455   std::string pre_load = this->GetHomeDirectory();
2456   if ( pre_load.size() > 0 )
2457     {
2458     pre_load += "/PreLoad.cmake";
2459     if ( cmSystemTools::FileExists(pre_load.c_str()) )
2460       {
2461       this->ReadListFile(args, pre_load.c_str());
2462       }
2463     }
2464   pre_load = this->GetHomeOutputDirectory();
2465   if ( pre_load.size() > 0 )
2466     {
2467     pre_load += "/PreLoad.cmake";
2468     if ( cmSystemTools::FileExists(pre_load.c_str()) )
2469       {
2470       this->ReadListFile(args, pre_load.c_str());
2471       }
2472     }
2473 }
2474
2475 // handle a command line invocation
2476 int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
2477 {
2478   // Process the arguments
2479   this->SetArgs(args);
2480   if(cmSystemTools::GetErrorOccuredFlag())
2481     {
2482     return -1;
2483     }
2484
2485   // If we are given a stamp list file check if it is really out of date.
2486   if(!this->CheckStampList.empty() &&
2487      cmakeCheckStampList(this->CheckStampList.c_str()))
2488     {
2489     return 0;
2490     }
2491
2492   // If we are given a stamp file check if it is really out of date.
2493   if(!this->CheckStampFile.empty() &&
2494      cmakeCheckStampFile(this->CheckStampFile.c_str()))
2495     {
2496     return 0;
2497     }
2498
2499   // set the cmake command
2500   this->CMakeCommand = args[0];
2501
2502   if ( this->GetWorkingMode() == NORMAL_MODE )
2503     {
2504     // load the cache
2505     if(this->LoadCache() < 0)
2506       {
2507       cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
2508       return -1;
2509       }
2510     }
2511   else
2512     {
2513     this->AddCMakePaths();
2514     }
2515   // Add any cache args
2516   if ( !this->SetCacheArgs(args) )
2517     {
2518     cmSystemTools::Error("Problem processing arguments. Aborting.\n");
2519     return -1;
2520     }
2521
2522   // In script mode we terminate after running the script.
2523   if(this->GetWorkingMode() != NORMAL_MODE)
2524     {
2525     if(cmSystemTools::GetErrorOccuredFlag())
2526       {
2527       return -1;
2528       }
2529     else
2530       {
2531       return 0;
2532       }
2533     }
2534
2535   // If MAKEFLAGS are given in the environment, remove the environment
2536   // variable.  This will prevent try-compile from succeeding when it
2537   // should fail (if "-i" is an option).  We cannot simply test
2538   // whether "-i" is given and remove it because some make programs
2539   // encode the MAKEFLAGS variable in a strange way.
2540   if(getenv("MAKEFLAGS"))
2541     {
2542     cmSystemTools::PutEnv("MAKEFLAGS=");
2543     }
2544
2545   this->PreLoadCMakeFiles();
2546
2547   if ( noconfigure )
2548     {
2549     return 0;
2550     }
2551
2552   // now run the global generate
2553   // Check the state of the build system to see if we need to regenerate.
2554   if(!this->CheckBuildSystem())
2555     {
2556     return 0;
2557     }
2558
2559   // If we are doing global generate, we better set start and start
2560   // output directory to the root of the project.
2561   std::string oldstartdir = this->GetStartDirectory();
2562   std::string oldstartoutputdir = this->GetStartOutputDirectory();
2563   this->SetStartDirectory(this->GetHomeDirectory());
2564   this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
2565   int ret = this->Configure();
2566   if (ret || this->GetWorkingMode() != NORMAL_MODE)
2567     {
2568 #if defined(CMAKE_HAVE_VS_GENERATORS)
2569     if(!this->VSSolutionFile.empty() && this->GlobalGenerator)
2570       {
2571       // CMake is running to regenerate a Visual Studio build tree
2572       // during a build from the VS IDE.  The build files cannot be
2573       // regenerated, so we should stop the build.
2574       cmSystemTools::Message(
2575         "CMake Configure step failed.  "
2576         "Build files cannot be regenerated correctly.  "
2577         "Attempting to stop IDE build.");
2578       cmGlobalVisualStudioGenerator* gg =
2579         static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
2580       gg->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop,
2581                                 this->VSSolutionFile.c_str());
2582       }
2583 #endif
2584     return ret;
2585     }
2586   ret = this->Generate();
2587   std::string message = "Build files have been written to: ";
2588   message += this->GetHomeOutputDirectory();
2589   this->UpdateProgress(message.c_str(), -1);
2590   if(ret)
2591     {
2592     return ret;
2593     }
2594   this->SetStartDirectory(oldstartdir.c_str());
2595   this->SetStartOutputDirectory(oldstartoutputdir.c_str());
2596
2597   return ret;
2598 }
2599
2600 int cmake::Generate()
2601 {
2602   if(!this->GlobalGenerator)
2603     {
2604     return -1;
2605     }
2606   this->GlobalGenerator->Generate();
2607   if(this->WarnUnusedCli)
2608     {
2609     this->RunCheckForUnusedVariables();
2610     }
2611   if(cmSystemTools::GetErrorOccuredFlag())
2612     {
2613     return -1;
2614     }
2615   if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
2616     {
2617     this->ReportUndefinedPropertyAccesses
2618       (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
2619     }
2620   // Save the cache again after a successful Generate so that any internal
2621   // variables created during Generate are saved. (Specifically target GUIDs
2622   // for the Visual Studio and Xcode generators.)
2623   if ( this->GetWorkingMode() == NORMAL_MODE )
2624     {
2625     this->CacheManager->SaveCache(this->GetHomeOutputDirectory());
2626     }
2627   return 0;
2628 }
2629
2630 void cmake::AddCacheEntry(const char* key, const char* value,
2631                           const char* helpString,
2632                           int type)
2633 {
2634   this->CacheManager->AddCacheEntry(key, value,
2635                                     helpString,
2636                                     cmCacheManager::CacheEntryType(type));
2637 }
2638
2639 const char* cmake::GetCacheDefinition(const char* name) const
2640 {
2641   return this->CacheManager->GetCacheValue(name);
2642 }
2643
2644 void cmake::AddDefaultCommands()
2645 {
2646   std::list<cmCommand*> commands;
2647   GetBootstrapCommands1(commands);
2648   GetBootstrapCommands2(commands);
2649   GetPredefinedCommands(commands);
2650   for(std::list<cmCommand*>::iterator i = commands.begin();
2651       i != commands.end(); ++i)
2652     {
2653     this->AddCommand(*i);
2654     }
2655 }
2656
2657 void cmake::AddDefaultGenerators()
2658 {
2659 #if defined(_WIN32) && !defined(__CYGWIN__)
2660 # if !defined(CMAKE_BOOT_MINGW)
2661   this->Generators.push_back(
2662     cmGlobalVisualStudio6Generator::NewFactory());
2663   this->Generators.push_back(
2664     cmGlobalVisualStudio7Generator::NewFactory());
2665   this->Generators.push_back(
2666     cmGlobalVisualStudio10Generator::NewFactory());
2667   this->Generators.push_back(
2668     cmGlobalVisualStudio11Generator::NewFactory());
2669   this->Generators.push_back(
2670     cmGlobalVisualStudio12Generator::NewFactory());
2671   this->Generators.push_back(
2672     cmGlobalVisualStudio71Generator::NewFactory());
2673   this->Generators.push_back(
2674     cmGlobalVisualStudio8Generator::NewFactory());
2675   this->Generators.push_back(
2676     cmGlobalVisualStudio9Generator::NewFactory());
2677   this->Generators.push_back(
2678     cmGlobalBorlandMakefileGenerator::NewFactory());
2679   this->Generators.push_back(
2680     cmGlobalNMakeMakefileGenerator::NewFactory());
2681   this->Generators.push_back(
2682     cmGlobalJOMMakefileGenerator::NewFactory());
2683   this->Generators.push_back(
2684     cmGlobalWatcomWMakeGenerator::NewFactory());
2685 # endif
2686   this->Generators.push_back(
2687     cmGlobalMSYSMakefileGenerator::NewFactory());
2688   this->Generators.push_back(
2689     cmGlobalMinGWMakefileGenerator::NewFactory());
2690 #endif
2691   this->Generators.push_back(
2692     cmGlobalUnixMakefileGenerator3::NewFactory());
2693   this->Generators.push_back(
2694     cmGlobalNinjaGenerator::NewFactory());
2695 #ifdef CMAKE_USE_XCODE
2696   this->Generators.push_back(
2697     cmGlobalXCodeGenerator::NewFactory());
2698 #endif
2699 }
2700
2701 int cmake::LoadCache()
2702 {
2703   // could we not read the cache
2704   if (!this->CacheManager->LoadCache(this->GetHomeOutputDirectory()))
2705     {
2706     // if it does exist, but isn't readable then warn the user
2707     std::string cacheFile = this->GetHomeOutputDirectory();
2708     cacheFile += "/CMakeCache.txt";
2709     if(cmSystemTools::FileExists(cacheFile.c_str()))
2710       {
2711       cmSystemTools::Error(
2712         "There is a CMakeCache.txt file for the current binary tree but "
2713         "cmake does not have permission to read it. Please check the "
2714         "permissions of the directory you are trying to run CMake on.");
2715       return -1;
2716       }
2717     }
2718
2719   if (this->CMakeCommand.size() < 2)
2720     {
2721     cmSystemTools::Error(
2722       "cmake command was not specified prior to loading the cache in "
2723       "cmake.cxx");
2724     return -1;
2725     }
2726
2727   // setup CMAKE_ROOT and CMAKE_COMMAND
2728   if(!this->AddCMakePaths())
2729     {
2730     return -3;
2731     }
2732   return 0;
2733 }
2734
2735 void cmake::SetProgressCallback(ProgressCallbackType f, void *cd)
2736 {
2737   this->ProgressCallback = f;
2738   this->ProgressCallbackClientData = cd;
2739 }
2740
2741 void cmake::UpdateProgress(const char *msg, float prog)
2742 {
2743   if(this->ProgressCallback && !this->InTryCompile)
2744     {
2745     (*this->ProgressCallback)(msg, prog, this->ProgressCallbackClientData);
2746     return;
2747     }
2748 }
2749
2750 void cmake::GetCommandDocumentation(std::vector<cmDocumentationEntry>& v,
2751                                     bool withCurrentCommands,
2752                                     bool withCompatCommands) const
2753 {
2754   for(RegisteredCommandsMap::const_iterator j = this->Commands.begin();
2755       j != this->Commands.end(); ++j)
2756     {
2757     if (((  withCompatCommands == false) && ( (*j).second->IsDiscouraged()))
2758         || ((withCurrentCommands == false) && (!(*j).second->IsDiscouraged()))
2759         || (!((*j).second->ShouldAppearInDocumentation()))
2760         )
2761       {
2762       continue;
2763       }
2764
2765     cmDocumentationEntry e((*j).second->GetName(),
2766                            (*j).second->GetTerseDocumentation(),
2767                            (*j).second->GetFullDocumentation());
2768     v.push_back(e);
2769     }
2770 }
2771
2772 void cmake::GetPolicyDocumentation(std::vector<cmDocumentationEntry>& v)
2773 {
2774   this->Policies->GetDocumentation(v);
2775 }
2776
2777 void cmake::GetPropertiesDocumentation(std::map<std::string,
2778                                        cmDocumentationSection *>& v)
2779 {
2780   // loop over the properties and put them into the doc structure
2781   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::iterator i;
2782   i = this->PropertyDefinitions.begin();
2783   for (;i != this->PropertyDefinitions.end(); ++i)
2784     {
2785     i->second.GetPropertiesDocumentation(v);
2786     }
2787 }
2788
2789 void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
2790 {
2791   for(RegisteredGeneratorsVector::const_iterator i =
2792       this->Generators.begin(); i != this->Generators.end(); ++i)
2793     {
2794     cmDocumentationEntry e;
2795     (*i)->GetDocumentation(e);
2796     v.push_back(e);
2797     }
2798   for(RegisteredExtraGeneratorsMap::const_iterator i =
2799       this->ExtraGenerators.begin(); i != this->ExtraGenerators.end(); ++i)
2800     {
2801     cmDocumentationEntry e;
2802     cmExternalMakefileProjectGenerator* generator = (i->second)();
2803     generator->GetDocumentation(e, i->first.c_str());
2804     e.Name = i->first;
2805     delete generator;
2806     v.push_back(e);
2807     }
2808 }
2809
2810 void cmake::UpdateConversionPathTable()
2811 {
2812   // Update the path conversion table with any specified file:
2813   const char* tablepath =
2814     this->CacheManager->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
2815
2816   if(tablepath)
2817     {
2818     std::ifstream table( tablepath );
2819     if(!table)
2820       {
2821       cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath,
2822         ". CMake can not open file.");
2823       cmSystemTools::ReportLastSystemError("CMake can not open file.");
2824       }
2825     else
2826       {
2827       std::string a, b;
2828       while(!table.eof())
2829         {
2830         // two entries per line
2831         table >> a; table >> b;
2832         cmSystemTools::AddTranslationPath( a.c_str(), b.c_str());
2833         }
2834       }
2835     }
2836 }
2837
2838 //----------------------------------------------------------------------------
2839 int cmake::CheckBuildSystem()
2840 {
2841   // We do not need to rerun CMake.  Check dependency integrity.  Use
2842   // the make system's VERBOSE environment variable to enable verbose
2843   // output. This can be skipped by setting CMAKE_NO_VERBOSE (which is set
2844   // by the Eclipse and KDevelop generators).
2845   bool verbose = ((cmSystemTools::GetEnv("VERBOSE") != 0)
2846                    && (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == 0));
2847
2848   // This method will check the integrity of the build system if the
2849   // option was given on the command line.  It reads the given file to
2850   // determine whether CMake should rerun.
2851
2852   // If no file is provided for the check, we have to rerun.
2853   if(this->CheckBuildSystemArgument.size() == 0)
2854     {
2855     if(verbose)
2856       {
2857       cmOStringStream msg;
2858       msg << "Re-run cmake no build system arguments\n";
2859       cmSystemTools::Stdout(msg.str().c_str());
2860       }
2861     return 1;
2862     }
2863
2864   // If the file provided does not exist, we have to rerun.
2865   if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument.c_str()))
2866     {
2867     if(verbose)
2868       {
2869       cmOStringStream msg;
2870       msg << "Re-run cmake missing file: "
2871           << this->CheckBuildSystemArgument.c_str() << "\n";
2872       cmSystemTools::Stdout(msg.str().c_str());
2873       }
2874     return 1;
2875     }
2876
2877   // Read the rerun check file and use it to decide whether to do the
2878   // global generate.
2879   cmake cm;
2880   cmGlobalGenerator gg;
2881   gg.SetCMakeInstance(&cm);
2882   cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
2883   cmMakefile* mf = lg->GetMakefile();
2884   if(!mf->ReadListFile(0, this->CheckBuildSystemArgument.c_str()) ||
2885      cmSystemTools::GetErrorOccuredFlag())
2886     {
2887     if(verbose)
2888       {
2889       cmOStringStream msg;
2890       msg << "Re-run cmake error reading : "
2891           << this->CheckBuildSystemArgument.c_str() << "\n";
2892       cmSystemTools::Stdout(msg.str().c_str());
2893       }
2894     // There was an error reading the file.  Just rerun.
2895     return 1;
2896     }
2897
2898   if(this->ClearBuildSystem)
2899     {
2900     // Get the generator used for this build system.
2901     const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
2902     if(!genName || genName[0] == '\0')
2903       {
2904       genName = "Unix Makefiles";
2905       }
2906
2907     // Create the generator and use it to clear the dependencies.
2908     cmsys::auto_ptr<cmGlobalGenerator>
2909       ggd(this->CreateGlobalGenerator(genName));
2910     if(ggd.get())
2911       {
2912       cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
2913       lgd->ClearDependencies(mf, verbose);
2914       }
2915     }
2916
2917   // If any byproduct of makefile generation is missing we must re-run.
2918   std::vector<std::string> products;
2919   if(const char* productStr = mf->GetDefinition("CMAKE_MAKEFILE_PRODUCTS"))
2920     {
2921     cmSystemTools::ExpandListArgument(productStr, products);
2922     }
2923   for(std::vector<std::string>::const_iterator pi = products.begin();
2924       pi != products.end(); ++pi)
2925     {
2926     if(!(cmSystemTools::FileExists(pi->c_str()) ||
2927          cmSystemTools::FileIsSymlink(pi->c_str())))
2928       {
2929       if(verbose)
2930         {
2931         cmOStringStream msg;
2932         msg << "Re-run cmake, missing byproduct: " << *pi << "\n";
2933         cmSystemTools::Stdout(msg.str().c_str());
2934         }
2935       return 1;
2936       }
2937     }
2938
2939   // Get the set of dependencies and outputs.
2940   std::vector<std::string> depends;
2941   std::vector<std::string> outputs;
2942   const char* dependsStr = mf->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
2943   const char* outputsStr = mf->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
2944   if(dependsStr && outputsStr)
2945     {
2946     cmSystemTools::ExpandListArgument(dependsStr, depends);
2947     cmSystemTools::ExpandListArgument(outputsStr, outputs);
2948     }
2949   if(depends.empty() || outputs.empty())
2950     {
2951     // Not enough information was provided to do the test.  Just rerun.
2952     if(verbose)
2953       {
2954       cmOStringStream msg;
2955       msg << "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
2956         "or CMAKE_MAKEFILE_OUTPUTS :\n";
2957       cmSystemTools::Stdout(msg.str().c_str());
2958       }
2959     return 1;
2960     }
2961
2962   // Find the newest dependency.
2963   std::vector<std::string>::iterator dep = depends.begin();
2964   std::string dep_newest = *dep++;
2965   for(;dep != depends.end(); ++dep)
2966     {
2967     int result = 0;
2968     if(this->FileComparison->FileTimeCompare(dep_newest.c_str(),
2969                                              dep->c_str(), &result))
2970       {
2971       if(result < 0)
2972         {
2973         dep_newest = *dep;
2974         }
2975       }
2976     else
2977       {
2978       if(verbose)
2979         {
2980         cmOStringStream msg;
2981         msg << "Re-run cmake: build system dependency is missing\n";
2982         cmSystemTools::Stdout(msg.str().c_str());
2983         }
2984       return 1;
2985       }
2986     }
2987
2988   // Find the oldest output.
2989   std::vector<std::string>::iterator out = outputs.begin();
2990   std::string out_oldest = *out++;
2991   for(;out != outputs.end(); ++out)
2992     {
2993     int result = 0;
2994     if(this->FileComparison->FileTimeCompare(out_oldest.c_str(),
2995                                              out->c_str(), &result))
2996       {
2997       if(result > 0)
2998         {
2999         out_oldest = *out;
3000         }
3001       }
3002     else
3003       {
3004       if(verbose)
3005         {
3006         cmOStringStream msg;
3007         msg << "Re-run cmake: build system output is missing\n";
3008         cmSystemTools::Stdout(msg.str().c_str());
3009         }
3010       return 1;
3011       }
3012     }
3013
3014   // If any output is older than any dependency then rerun.
3015   {
3016   int result = 0;
3017   if(!this->FileComparison->FileTimeCompare(out_oldest.c_str(),
3018                                             dep_newest.c_str(),
3019                                             &result) ||
3020      result < 0)
3021     {
3022     if(verbose)
3023       {
3024       cmOStringStream msg;
3025       msg << "Re-run cmake file: " << out_oldest.c_str()
3026           << " older than: " << dep_newest.c_str() << "\n";
3027       cmSystemTools::Stdout(msg.str().c_str());
3028       }
3029     return 1;
3030     }
3031   }
3032
3033   // No need to rerun.
3034   return 0;
3035 }
3036
3037 //----------------------------------------------------------------------------
3038 void cmake::TruncateOutputLog(const char* fname)
3039 {
3040   std::string fullPath = this->GetHomeOutputDirectory();
3041   fullPath += "/";
3042   fullPath += fname;
3043   struct stat st;
3044   if ( ::stat(fullPath.c_str(), &st) )
3045     {
3046     return;
3047     }
3048   if ( !this->CacheManager->GetCacheValue("CMAKE_CACHEFILE_DIR") )
3049     {
3050     cmSystemTools::RemoveFile(fullPath.c_str());
3051     return;
3052     }
3053   off_t fsize = st.st_size;
3054   const off_t maxFileSize = 50 * 1024;
3055   if ( fsize < maxFileSize )
3056     {
3057     //TODO: truncate file
3058     return;
3059     }
3060 }
3061
3062 inline std::string removeQuotes(const std::string& s)
3063 {
3064   if(s[0] == '\"' && s[s.size()-1] == '\"')
3065     {
3066     return s.substr(1, s.size()-2);
3067     }
3068   return s;
3069 }
3070
3071 std::string cmake::FindCMakeProgram(const char* name) const
3072 {
3073   std::string path;
3074   if ((name) && (*name))
3075     {
3076     const cmMakefile* mf
3077         = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
3078 #ifdef CMAKE_BUILD_WITH_CMAKE
3079     path = mf->GetRequiredDefinition("CMAKE_COMMAND");
3080     path = removeQuotes(path);
3081     path = cmSystemTools::GetFilenamePath(path.c_str());
3082     path += "/";
3083     path += name;
3084     path += cmSystemTools::GetExecutableExtension();
3085     if(!cmSystemTools::FileExists(path.c_str()))
3086     {
3087       path = mf->GetRequiredDefinition("CMAKE_COMMAND");
3088       path = cmSystemTools::GetFilenamePath(path.c_str());
3089       path += "/Debug/";
3090       path += name;
3091       path += cmSystemTools::GetExecutableExtension();
3092     }
3093     if(!cmSystemTools::FileExists(path.c_str()))
3094     {
3095       path = mf->GetRequiredDefinition("CMAKE_COMMAND");
3096       path = cmSystemTools::GetFilenamePath(path.c_str());
3097       path += "/Release/";
3098       path += name;
3099       path += cmSystemTools::GetExecutableExtension();
3100     }
3101 #else
3102     // Only for bootstrap
3103     path += mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
3104     path += "/";
3105     path += name;
3106     path += cmSystemTools::GetExecutableExtension();
3107 #endif
3108     }
3109   return path;
3110 }
3111
3112 const char* cmake::GetCTestCommand()
3113 {
3114   if ( this->CTestCommand.empty() )
3115     {
3116     this->CTestCommand = this->FindCMakeProgram("ctest");
3117     }
3118   if ( this->CTestCommand.empty() )
3119     {
3120     cmSystemTools::Error("Cannot find the CTest executable");
3121     this->CTestCommand = "CTEST-COMMAND-NOT-FOUND";
3122     }
3123   return this->CTestCommand.c_str();
3124 }
3125
3126 const char* cmake::GetCPackCommand()
3127 {
3128   if ( this->CPackCommand.empty() )
3129     {
3130     this->CPackCommand = this->FindCMakeProgram("cpack");
3131     }
3132   if ( this->CPackCommand.empty() )
3133     {
3134     cmSystemTools::Error("Cannot find the CPack executable");
3135     this->CPackCommand = "CPACK-COMMAND-NOT-FOUND";
3136     }
3137     return this->CPackCommand.c_str();
3138 }
3139
3140
3141 const char* cmake::GetCMakeCommand()
3142 {
3143   return this->CMakeCommand.c_str();
3144 }
3145
3146
3147 void cmake::MarkCliAsUsed(const std::string& variable)
3148 {
3149   this->UsedCliVariables[variable] = true;
3150 }
3151
3152 void cmake::GenerateGraphViz(const char* fileName) const
3153 {
3154 #ifdef CMAKE_BUILD_WITH_CMAKE
3155   cmsys::auto_ptr<cmGraphVizWriter> gvWriter(
3156        new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
3157
3158   std::string settingsFile = this->GetHomeOutputDirectory();
3159   settingsFile += "/CMakeGraphVizOptions.cmake";
3160   std::string fallbackSettingsFile = this->GetHomeDirectory();
3161   fallbackSettingsFile += "/CMakeGraphVizOptions.cmake";
3162
3163   gvWriter->ReadSettings(settingsFile.c_str(), fallbackSettingsFile.c_str());
3164
3165   gvWriter->WritePerTargetFiles(fileName);
3166   gvWriter->WriteTargetDependersFiles(fileName);
3167   gvWriter->WriteGlobalFile(fileName);
3168
3169 #endif
3170 }
3171
3172
3173 //----------------------------------------------------------------------------
3174 int cmake::SymlinkLibrary(std::vector<std::string>& args)
3175 {
3176   int result = 0;
3177   std::string realName = args[2];
3178   std::string soName = args[3];
3179   std::string name = args[4];
3180   if(soName != realName)
3181     {
3182     if(!cmake::SymlinkInternal(realName, soName))
3183       {
3184       cmSystemTools::ReportLastSystemError("cmake_symlink_library");
3185       result = 1;
3186       }
3187     }
3188   if(name != soName)
3189     {
3190     if(!cmake::SymlinkInternal(soName, name))
3191       {
3192       cmSystemTools::ReportLastSystemError("cmake_symlink_library");
3193       result = 1;
3194       }
3195     }
3196   return result;
3197 }
3198
3199 //----------------------------------------------------------------------------
3200 int cmake::SymlinkExecutable(std::vector<std::string>& args)
3201 {
3202   int result = 0;
3203   std::string realName = args[2];
3204   std::string name = args[3];
3205   if(name != realName)
3206     {
3207     if(!cmake::SymlinkInternal(realName, name))
3208       {
3209       cmSystemTools::ReportLastSystemError("cmake_symlink_executable");
3210       result = 1;
3211       }
3212     }
3213   return result;
3214 }
3215
3216 //----------------------------------------------------------------------------
3217 bool cmake::SymlinkInternal(std::string const& file, std::string const& link)
3218 {
3219   if(cmSystemTools::FileExists(link.c_str()) ||
3220      cmSystemTools::FileIsSymlink(link.c_str()))
3221     {
3222     cmSystemTools::RemoveFile(link.c_str());
3223     }
3224 #if defined(_WIN32) && !defined(__CYGWIN__)
3225   return cmSystemTools::CopyFileAlways(file.c_str(), link.c_str());
3226 #else
3227   std::string linktext = cmSystemTools::GetFilenameName(file);
3228   return cmSystemTools::CreateSymlink(linktext.c_str(), link.c_str());
3229 #endif
3230 }
3231
3232 //----------------------------------------------------------------------------
3233 #ifdef CMAKE_BUILD_WITH_CMAKE
3234 int cmake::ExecuteEchoColor(std::vector<std::string>& args)
3235 {
3236   // The arguments are
3237   //   argv[0] == <cmake-executable>
3238   //   argv[1] == cmake_echo_color
3239
3240   bool enabled = true;
3241   int color = cmsysTerminal_Color_Normal;
3242   bool newline = true;
3243   for(unsigned int i=2; i < args.size(); ++i)
3244     {
3245     if(args[i].find("--switch=") == 0)
3246       {
3247       // Enable or disable color based on the switch value.
3248       std::string value = args[i].substr(9);
3249       if(!value.empty())
3250         {
3251         if(cmSystemTools::IsOn(value.c_str()))
3252           {
3253           enabled = true;
3254           }
3255         else
3256           {
3257           enabled = false;
3258           }
3259         }
3260       }
3261     else if(args[i] == "--normal")
3262       {
3263       color = cmsysTerminal_Color_Normal;
3264       }
3265     else if(args[i] == "--black")
3266       {
3267       color = cmsysTerminal_Color_ForegroundBlack;
3268       }
3269     else if(args[i] == "--red")
3270       {
3271       color = cmsysTerminal_Color_ForegroundRed;
3272       }
3273     else if(args[i] == "--green")
3274       {
3275       color = cmsysTerminal_Color_ForegroundGreen;
3276       }
3277     else if(args[i] == "--yellow")
3278       {
3279       color = cmsysTerminal_Color_ForegroundYellow;
3280       }
3281     else if(args[i] == "--blue")
3282       {
3283       color = cmsysTerminal_Color_ForegroundBlue;
3284       }
3285     else if(args[i] == "--magenta")
3286       {
3287       color = cmsysTerminal_Color_ForegroundMagenta;
3288       }
3289     else if(args[i] == "--cyan")
3290       {
3291       color = cmsysTerminal_Color_ForegroundCyan;
3292       }
3293     else if(args[i] == "--white")
3294       {
3295       color = cmsysTerminal_Color_ForegroundWhite;
3296       }
3297     else if(args[i] == "--bold")
3298       {
3299       color |= cmsysTerminal_Color_ForegroundBold;
3300       }
3301     else if(args[i] == "--no-newline")
3302       {
3303       newline = false;
3304       }
3305     else if(args[i] == "--newline")
3306       {
3307       newline = true;
3308       }
3309     else
3310       {
3311       // Color is enabled.  Print with the current color.
3312       cmSystemTools::MakefileColorEcho(color, args[i].c_str(),
3313                                        newline, enabled);
3314       }
3315     }
3316
3317   return 0;
3318 }
3319 #else
3320 int cmake::ExecuteEchoColor(std::vector<std::string>&)
3321 {
3322   return 1;
3323 }
3324 #endif
3325
3326 //----------------------------------------------------------------------------
3327 int cmake::ExecuteLinkScript(std::vector<std::string>& args)
3328 {
3329   // The arguments are
3330   //   argv[0] == <cmake-executable>
3331   //   argv[1] == cmake_link_script
3332   //   argv[2] == <link-script-name>
3333   //   argv[3] == --verbose=?
3334   bool verbose = false;
3335   if(args.size() >= 4)
3336     {
3337     if(args[3].find("--verbose=") == 0)
3338       {
3339       if(!cmSystemTools::IsOff(args[3].substr(10).c_str()))
3340         {
3341         verbose = true;
3342         }
3343       }
3344     }
3345
3346   // Allocate a process instance.
3347   cmsysProcess* cp = cmsysProcess_New();
3348   if(!cp)
3349     {
3350     std::cerr << "Error allocating process instance in link script."
3351               << std::endl;
3352     return 1;
3353     }
3354
3355   // Children should share stdout and stderr with this process.
3356   cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
3357   cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
3358
3359   // Run the command lines verbatim.
3360   cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
3361
3362   // Read command lines from the script.
3363   std::ifstream fin(args[2].c_str());
3364   if(!fin)
3365     {
3366     std::cerr << "Error opening link script \""
3367               << args[2] << "\"" << std::endl;
3368     return 1;
3369     }
3370
3371   // Run one command at a time.
3372   std::string command;
3373   int result = 0;
3374   while(result == 0 && cmSystemTools::GetLineFromStream(fin, command))
3375     {
3376     // Skip empty command lines.
3377     if(command.find_first_not_of(" \t") == command.npos)
3378       {
3379       continue;
3380       }
3381
3382     // Setup this command line.
3383     const char* cmd[2] = {command.c_str(), 0};
3384     cmsysProcess_SetCommand(cp, cmd);
3385
3386     // Report the command if verbose output is enabled.
3387     if(verbose)
3388       {
3389       std::cout << command << std::endl;
3390       }
3391
3392     // Run the command and wait for it to exit.
3393     cmsysProcess_Execute(cp);
3394     cmsysProcess_WaitForExit(cp, 0);
3395
3396     // Report failure if any.
3397     switch(cmsysProcess_GetState(cp))
3398       {
3399       case cmsysProcess_State_Exited:
3400         {
3401         int value = cmsysProcess_GetExitValue(cp);
3402         if(value != 0)
3403           {
3404           result = value;
3405           }
3406         }
3407         break;
3408       case cmsysProcess_State_Exception:
3409         std::cerr << "Error running link command: "
3410                   << cmsysProcess_GetExceptionString(cp) << std::endl;
3411         result = 1;
3412         break;
3413       case cmsysProcess_State_Error:
3414         std::cerr << "Error running link command: "
3415                   << cmsysProcess_GetErrorString(cp) << std::endl;
3416         result = 2;
3417         break;
3418       default:
3419         break;
3420       };
3421     }
3422
3423   // Free the process instance.
3424   cmsysProcess_Delete(cp);
3425
3426   // Return the final resulting return value.
3427   return result;
3428 }
3429
3430 void cmake::DefineProperties(cmake *cm)
3431 {
3432   cm->DefineProperty
3433     ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL,
3434      "If set, report any undefined properties to this file.",
3435      "If this property is set to a filename then when CMake runs "
3436      "it will report any properties or variables that were accessed "
3437      "but not defined into the filename specified in this property."
3438      );
3439
3440   cm->DefineProperty
3441     ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL,
3442      "Does the target platform support shared libraries.",
3443      "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
3444      "platform supports shared libraries. Basically all current general "
3445      "general purpose OS do so, the exception are usually embedded systems "
3446      "with no or special OSs.");
3447
3448   cm->DefineProperty
3449     ("TARGET_ARCHIVES_MAY_BE_SHARED_LIBS", cmProperty::GLOBAL,
3450      "Set if shared libraries may be named like archives.",
3451      "On AIX shared libraries may be named \"lib<name>.a\".  "
3452      "This property is set to true on such platforms.");
3453
3454   cm->DefineProperty
3455     ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL,
3456      "Whether FIND_LIBRARY should automatically search lib64 directories.",
3457      "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
3458      "FIND_LIBRARY command should automatically search the lib64 variant of "
3459      "directories called lib in the search path when building 64-bit "
3460      "binaries.");
3461   cm->DefineProperty
3462     ("FIND_LIBRARY_USE_OPENBSD_VERSIONING", cmProperty::GLOBAL,
3463      "Whether FIND_LIBRARY should find OpenBSD-style shared libraries.",
3464      "This property is a boolean specifying whether the FIND_LIBRARY "
3465      "command should find shared libraries with OpenBSD-style versioned "
3466      "extension: \".so.<major>.<minor>\".  "
3467      "The property is set to true on OpenBSD and false on other platforms.");
3468   cm->DefineProperty
3469     ("ENABLED_FEATURES", cmProperty::GLOBAL,
3470      "List of features which are enabled during the CMake run.",
3471      "List of features which are enabled during the CMake run. By default "
3472      "it contains the names of all packages which were found. This is "
3473      "determined using the <NAME>_FOUND variables. Packages which are "
3474      "searched QUIET are not listed. A project can add its own features to "
3475      "this list. "
3476      "This property is used by the macros in FeatureSummary.cmake.");
3477   cm->DefineProperty
3478     ("DISABLED_FEATURES", cmProperty::GLOBAL,
3479      "List of features which are disabled during the CMake run.",
3480      "List of features which are disabled during the CMake run. By default "
3481      "it contains the names of all packages which were not found. This is "
3482      "determined using the <NAME>_FOUND variables. Packages which are "
3483      "searched QUIET are not listed. A project can add its own features to "
3484      "this list. "
3485      "This property is used by the macros in FeatureSummary.cmake.");
3486   cm->DefineProperty
3487     ("PACKAGES_FOUND", cmProperty::GLOBAL,
3488      "List of packages which were found during the CMake run.",
3489      "List of packages which were found during the CMake run. Whether a "
3490      "package has been found is determined using the <NAME>_FOUND variables.");
3491   cm->DefineProperty
3492     ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL,
3493      "List of packages which were not found during the CMake run.",
3494      "List of packages which were not found during the CMake run. Whether a "
3495      "package has been found is determined using the <NAME>_FOUND variables.");
3496
3497   cm->DefineProperty(
3498     "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL,
3499     "Internal property",
3500     "Used to detect compiler changes, Do not set.");
3501
3502   cm->DefineProperty(
3503     "DEBUG_CONFIGURATIONS", cmProperty::GLOBAL,
3504     "Specify which configurations are for debugging.",
3505     "The value must be a semi-colon separated list of configuration names.  "
3506     "Currently this property is used only by the target_link_libraries "
3507     "command (see its documentation for details).  "
3508     "Additional uses may be defined in the future.  "
3509     "\n"
3510     "This property must be set at the top level of the project and before "
3511     "the first target_link_libraries command invocation.  "
3512     "If any entry in the list does not match a valid configuration for "
3513     "the project the behavior is undefined.");
3514
3515   cm->DefineProperty(
3516     "GLOBAL_DEPENDS_DEBUG_MODE", cmProperty::GLOBAL,
3517     "Enable global target dependency graph debug mode.",
3518     "CMake automatically analyzes the global inter-target dependency graph "
3519     "at the beginning of native build system generation.  "
3520     "This property causes it to display details of its analysis to stderr.");
3521
3522   cm->DefineProperty(
3523     "GLOBAL_DEPENDS_NO_CYCLES", cmProperty::GLOBAL,
3524     "Disallow global target dependency graph cycles.",
3525     "CMake automatically analyzes the global inter-target dependency graph "
3526     "at the beginning of native build system generation.  "
3527     "It reports an error if the dependency graph contains a cycle that "
3528     "does not consist of all STATIC library targets.  "
3529     "This property tells CMake to disallow all cycles completely, even "
3530     "among static libraries.");
3531
3532   cm->DefineProperty(
3533     "ALLOW_DUPLICATE_CUSTOM_TARGETS", cmProperty::GLOBAL,
3534     "Allow duplicate custom targets to be created.",
3535     "Normally CMake requires that all targets built in a project have "
3536     "globally unique logical names (see policy CMP0002).  "
3537     "This is necessary to generate meaningful project file names in "
3538     "Xcode and VS IDE generators.  "
3539     "It also allows the target names to be referenced unambiguously.\n"
3540     "Makefile generators are capable of supporting duplicate custom target "
3541     "names.  "
3542     "For projects that care only about Makefile generators and do "
3543     "not wish to support Xcode or VS IDE generators, one may set this "
3544     "property to true to allow duplicate custom targets.  "
3545     "The property allows multiple add_custom_target command calls in "
3546     "different directories to specify the same target name.  "
3547     "However, setting this property will cause non-Makefile generators "
3548     "to produce an error and refuse to generate the project."
3549     );
3550
3551   cm->DefineProperty
3552     ("IN_TRY_COMPILE", cmProperty::GLOBAL,
3553      "Read-only property that is true during a try-compile configuration.",
3554      "True when building a project inside a TRY_COMPILE or TRY_RUN command.");
3555   cm->DefineProperty
3556     ("ENABLED_LANGUAGES", cmProperty::GLOBAL,
3557      "Read-only property that contains the list of currently "
3558      "enabled languages",
3559      "Set to list of currently enabled languages.");
3560
3561   cm->DefineProperty
3562     ("RULE_LAUNCH_COMPILE", cmProperty::GLOBAL,
3563      "Specify a launcher for compile rules.",
3564      "Makefile generators prefix compiler commands with the given "
3565      "launcher command line.  "
3566      "This is intended to allow launchers to intercept build problems "
3567      "with high granularity.  "
3568      "Non-Makefile generators currently ignore this property.");
3569   cm->DefineProperty
3570     ("RULE_LAUNCH_LINK", cmProperty::GLOBAL,
3571      "Specify a launcher for link rules.",
3572      "Makefile generators prefix link and archive commands with the given "
3573      "launcher command line.  "
3574      "This is intended to allow launchers to intercept build problems "
3575      "with high granularity.  "
3576      "Non-Makefile generators currently ignore this property.");
3577   cm->DefineProperty
3578     ("RULE_LAUNCH_CUSTOM", cmProperty::GLOBAL,
3579      "Specify a launcher for custom rules.",
3580      "Makefile generators prefix custom commands with the given "
3581      "launcher command line.  "
3582      "This is intended to allow launchers to intercept build problems "
3583      "with high granularity.  "
3584      "Non-Makefile generators currently ignore this property.");
3585
3586   cm->DefineProperty
3587     ("RULE_MESSAGES", cmProperty::GLOBAL,
3588      "Specify whether to report a message for each make rule.",
3589      "This property specifies whether Makefile generators should add a "
3590      "progress message describing what each build rule does.  "
3591      "If the property is not set the default is ON.  "
3592      "Set the property to OFF to disable granular messages and report only "
3593      "as each target completes.  "
3594      "This is intended to allow scripted builds to avoid the build time "
3595      "cost of detailed reports.  "
3596      "If a CMAKE_RULE_MESSAGES cache entry exists its value initializes "
3597      "the value of this property.  "
3598      "Non-Makefile generators currently ignore this property.");
3599
3600   cm->DefineProperty
3601     ("USE_FOLDERS", cmProperty::GLOBAL,
3602      "Use the FOLDER target property to organize targets into folders.",
3603      "If not set, CMake treats this property as OFF by default. "
3604      "CMake generators that are capable of organizing into a "
3605      "hierarchy of folders use the values of the FOLDER target "
3606      "property to name those folders. See also the documentation "
3607      "for the FOLDER target property.");
3608
3609   cm->DefineProperty
3610     ("AUTOMOC_TARGETS_FOLDER", cmProperty::GLOBAL,
3611      "Name of FOLDER for *_automoc targets that are added automatically by "
3612      "CMake for targets for which AUTOMOC is enabled.",
3613      "If not set, CMake uses the FOLDER property of the parent target as a "
3614      "default value for this property. See also the documentation for the "
3615      "FOLDER target property and the AUTOMOC target property.");
3616
3617   cm->DefineProperty
3618     ("PREDEFINED_TARGETS_FOLDER", cmProperty::GLOBAL,
3619      "Name of FOLDER for targets that are added automatically by CMake.",
3620      "If not set, CMake uses \"CMakePredefinedTargets\" as a default "
3621      "value for this property. Targets such as INSTALL, PACKAGE and "
3622      "RUN_TESTS will be organized into this FOLDER. See also the "
3623      "documentation for the FOLDER target property.");
3624
3625   // ================================================================
3626   // define variables as well
3627   // ================================================================
3628   cmDocumentVariables::DefineVariables(cm);
3629 }
3630
3631
3632 void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope,
3633                            const char *ShortDescription,
3634                            const char *FullDescription,
3635                            bool chained, const char *docSection)
3636 {
3637   this->PropertyDefinitions[scope].DefineProperty(name,scope,ShortDescription,
3638                                                   FullDescription,
3639                                                   docSection,
3640                                                   chained);
3641 }
3642
3643 bool cmake::GetIsPropertyDefined(const char *name,
3644                                  cmProperty::ScopeType scope)
3645 {
3646   return this->PropertyDefinitions[scope].find(name) !=
3647                                       this->PropertyDefinitions[scope].end();
3648 }
3649
3650 cmPropertyDefinition *cmake
3651 ::GetPropertyDefinition(const char *name,
3652                         cmProperty::ScopeType scope)
3653 {
3654   if (this->IsPropertyDefined(name,scope))
3655     {
3656     return &(this->PropertyDefinitions[scope][name]);
3657     }
3658   return 0;
3659 }
3660
3661 void cmake::RecordPropertyAccess(const char *name,
3662                                  cmProperty::ScopeType scope)
3663 {
3664   this->AccessedProperties.insert
3665     (std::pair<cmStdString,cmProperty::ScopeType>(name,scope));
3666 }
3667
3668 void cmake::ReportUndefinedPropertyAccesses(const char *filename)
3669 {
3670   if(!this->GlobalGenerator)
3671     { return; }
3672   FILE *progFile = fopen(filename,"w");
3673   if(!progFile)
3674     { return; }
3675
3676   // what are the enabled languages?
3677   std::vector<std::string> enLangs;
3678   this->GlobalGenerator->GetEnabledLanguages(enLangs);
3679
3680   // Common configuration names.
3681   // TODO: Compute current configuration(s).
3682   std::vector<std::string> enConfigs;
3683   enConfigs.push_back("");
3684   enConfigs.push_back("DEBUG");
3685   enConfigs.push_back("RELEASE");
3686   enConfigs.push_back("MINSIZEREL");
3687   enConfigs.push_back("RELWITHDEBINFO");
3688
3689   // take all the defined properties and add definitions for all the enabled
3690   // languages
3691   std::set<std::pair<cmStdString,cmProperty::ScopeType> > aliasedProperties;
3692   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::iterator i;
3693   i = this->PropertyDefinitions.begin();
3694   for (;i != this->PropertyDefinitions.end(); ++i)
3695     {
3696     cmPropertyDefinitionMap::iterator j;
3697     for (j = i->second.begin(); j != i->second.end(); ++j)
3698       {
3699       // TODO: What if both <LANG> and <CONFIG> appear?
3700       if (j->first.find("<CONFIG>") != std::string::npos)
3701         {
3702         std::vector<std::string>::const_iterator k;
3703         for (k = enConfigs.begin(); k != enConfigs.end(); ++k)
3704           {
3705           std::string tmp = j->first;
3706           cmSystemTools::ReplaceString(tmp, "<CONFIG>", k->c_str());
3707           // add alias
3708           aliasedProperties.insert
3709             (std::pair<cmStdString,cmProperty::ScopeType>(tmp,i->first));
3710           }
3711         }
3712       if (j->first.find("<LANG>") != std::string::npos)
3713         {
3714         std::vector<std::string>::const_iterator k;
3715         for (k = enLangs.begin(); k != enLangs.end(); ++k)
3716           {
3717           std::string tmp = j->first;
3718           cmSystemTools::ReplaceString(tmp, "<LANG>", k->c_str());
3719           // add alias
3720           aliasedProperties.insert
3721             (std::pair<cmStdString,cmProperty::ScopeType>(tmp,i->first));
3722           }
3723         }
3724       }
3725     }
3726
3727   std::set<std::pair<cmStdString,cmProperty::ScopeType> >::const_iterator ap;
3728   ap = this->AccessedProperties.begin();
3729   for (;ap != this->AccessedProperties.end(); ++ap)
3730     {
3731     if (!this->IsPropertyDefined(ap->first.c_str(),ap->second) &&
3732         aliasedProperties.find(std::pair<cmStdString,cmProperty::ScopeType>
3733                                (ap->first,ap->second)) ==
3734         aliasedProperties.end())
3735       {
3736       const char *scopeStr = "";
3737       switch (ap->second)
3738         {
3739         case cmProperty::TARGET:
3740           scopeStr = "TARGET";
3741           break;
3742         case cmProperty::SOURCE_FILE:
3743           scopeStr = "SOURCE_FILE";
3744         break;
3745         case cmProperty::DIRECTORY:
3746           scopeStr = "DIRECTORY";
3747           break;
3748         case cmProperty::TEST:
3749           scopeStr = "TEST";
3750           break;
3751         case cmProperty::VARIABLE:
3752           scopeStr = "VARIABLE";
3753           break;
3754         case cmProperty::CACHED_VARIABLE:
3755           scopeStr = "CACHED_VARIABLE";
3756           break;
3757         default:
3758           scopeStr = "unknown";
3759         break;
3760         }
3761       fprintf(progFile, "%s with scope %s\n", ap->first.c_str(), scopeStr);
3762       }
3763     }
3764   fclose(progFile);
3765 }
3766
3767 bool cmake::IsPropertyDefined(const char *name, cmProperty::ScopeType scope)
3768 {
3769   return this->PropertyDefinitions[scope].IsPropertyDefined(name);
3770 }
3771
3772 bool cmake::IsPropertyChained(const char *name, cmProperty::ScopeType scope)
3773 {
3774   return this->PropertyDefinitions[scope].IsPropertyChained(name);
3775 }
3776
3777 void cmake::SetProperty(const char* prop, const char* value)
3778 {
3779   if (!prop)
3780     {
3781     return;
3782     }
3783
3784   // Special hook to invalidate cached value.
3785   if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0)
3786     {
3787     this->DebugConfigs.clear();
3788     }
3789
3790   this->Properties.SetProperty(prop, value, cmProperty::GLOBAL);
3791 }
3792
3793 void cmake::AppendProperty(const char* prop, const char* value, bool asString)
3794 {
3795   if (!prop)
3796     {
3797     return;
3798     }
3799
3800   // Special hook to invalidate cached value.
3801   if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0)
3802     {
3803     this->DebugConfigs.clear();
3804     }
3805
3806   this->Properties.AppendProperty(prop, value, cmProperty::GLOBAL, asString);
3807 }
3808
3809 const char *cmake::GetProperty(const char* prop)
3810 {
3811   return this->GetProperty(prop, cmProperty::GLOBAL);
3812 }
3813
3814 const char *cmake::GetProperty(const char* prop, cmProperty::ScopeType scope)
3815 {
3816   if(!prop)
3817     {
3818     return 0;
3819     }
3820   bool chain = false;
3821
3822   // watch for special properties
3823   std::string propname = prop;
3824   std::string output = "";
3825   if ( propname == "CACHE_VARIABLES" )
3826     {
3827     cmCacheManager::CacheIterator cit =
3828       this->GetCacheManager()->GetCacheIterator();
3829     for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
3830       {
3831       if ( output.size() )
3832         {
3833         output += ";";
3834         }
3835       output += cit.GetName();
3836       }
3837     this->SetProperty("CACHE_VARIABLES", output.c_str());
3838     }
3839   else if ( propname == "COMMANDS" )
3840     {
3841     cmake::RegisteredCommandsMap::iterator cmds
3842         = this->GetCommands()->begin();
3843     for (unsigned int cc=0 ; cmds != this->GetCommands()->end(); ++ cmds )
3844       {
3845       if ( cc > 0 )
3846         {
3847         output += ";";
3848         }
3849       output += cmds->first.c_str();
3850       cc++;
3851       }
3852     this->SetProperty("COMMANDS",output.c_str());
3853     }
3854   else if ( propname == "IN_TRY_COMPILE" )
3855     {
3856     this->SetProperty("IN_TRY_COMPILE",
3857                       this->GetIsInTryCompile()? "1":"0");
3858     }
3859   else if ( propname == "ENABLED_LANGUAGES" )
3860     {
3861     std::string lang;
3862     if(this->GlobalGenerator)
3863       {
3864       std::vector<std::string> enLangs;
3865       this->GlobalGenerator->GetEnabledLanguages(enLangs);
3866       const char* sep = "";
3867       for(std::vector<std::string>::iterator i = enLangs.begin();
3868           i != enLangs.end(); ++i)
3869         {
3870         lang += sep;
3871         sep = ";";
3872         lang += *i;
3873         }
3874       }
3875     this->SetProperty("ENABLED_LANGUAGES", lang.c_str());
3876     }
3877   return this->Properties.GetPropertyValue(prop, scope, chain);
3878 }
3879
3880 bool cmake::GetPropertyAsBool(const char* prop)
3881 {
3882   return cmSystemTools::IsOn(this->GetProperty(prop));
3883 }
3884
3885 int cmake::GetSystemInformation(std::vector<std::string>& args)
3886 {
3887   // so create the directory
3888   std::string resultFile;
3889   std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
3890   std::string destPath = cwd + "/__cmake_systeminformation";
3891   cmSystemTools::RemoveADirectory(destPath.c_str());
3892   if (!cmSystemTools::MakeDirectory(destPath.c_str()))
3893     {
3894     std::cerr << "Error: --system-information must be run from a "
3895       "writable directory!\n";
3896     return 1;
3897     }
3898
3899   // process the arguments
3900   bool writeToStdout = true;
3901   for(unsigned int i=1; i < args.size(); ++i)
3902     {
3903     std::string arg = args[i];
3904     if(arg.find("-V",0) == 0)
3905       {
3906       this->Verbose = true;
3907       }
3908     else if(arg.find("-G",0) == 0)
3909       {
3910       std::string value = arg.substr(2);
3911       if(value.size() == 0)
3912         {
3913         ++i;
3914         if(i >= args.size())
3915           {
3916           cmSystemTools::Error("No generator specified for -G");
3917           return -1;
3918           }
3919         value = args[i];
3920         }
3921       cmGlobalGenerator* gen =
3922         this->CreateGlobalGenerator(value.c_str());
3923       if(!gen)
3924         {
3925         cmSystemTools::Error("Could not create named generator ",
3926                              value.c_str());
3927         }
3928       else
3929         {
3930         this->SetGlobalGenerator(gen);
3931         }
3932       }
3933     // no option assume it is the output file
3934     else
3935       {
3936       if (!cmSystemTools::FileIsFullPath(arg.c_str()))
3937         {
3938         resultFile = cwd;
3939         resultFile += "/";
3940         }
3941       resultFile += arg;
3942       writeToStdout = false;
3943       }
3944     }
3945
3946
3947   // we have to find the module directory, so we can copy the files
3948   this->AddCMakePaths();
3949   std::string modulesPath =
3950     this->CacheManager->GetCacheValue("CMAKE_ROOT");
3951   modulesPath += "/Modules";
3952   std::string inFile = modulesPath;
3953   inFile += "/SystemInformation.cmake";
3954   std::string outFile = destPath;
3955   outFile += "/CMakeLists.txt";
3956
3957   // Copy file
3958   if(!cmSystemTools::cmCopyFile(inFile.c_str(), outFile.c_str()))
3959     {
3960     std::cerr << "Error copying file \"" << inFile.c_str()
3961               << "\" to \"" << outFile.c_str() << "\".\n";
3962     return 1;
3963     }
3964
3965   // do we write to a file or to stdout?
3966   if (resultFile.size() == 0)
3967     {
3968     resultFile = cwd;
3969     resultFile += "/__cmake_systeminformation/results.txt";
3970     }
3971
3972   // now run cmake on the CMakeLists file
3973   cmSystemTools::ChangeDirectory(destPath.c_str());
3974   std::vector<std::string> args2;
3975   args2.push_back(args[0]);
3976   args2.push_back(destPath);
3977   std::string resultArg = "-DRESULT_FILE=";
3978   resultArg += resultFile;
3979   args2.push_back(resultArg);
3980   int res = this->Run(args2, false);
3981
3982   if (res != 0)
3983     {
3984     std::cerr << "Error: --system-information failed on internal CMake!\n";
3985     return res;
3986     }
3987
3988   // change back to the original directory
3989   cmSystemTools::ChangeDirectory(cwd.c_str());
3990
3991   // echo results to stdout if needed
3992   if (writeToStdout)
3993     {
3994     FILE* fin = fopen(resultFile.c_str(), "r");
3995     if(fin)
3996       {
3997       const int bufferSize = 4096;
3998       char buffer[bufferSize];
3999       size_t n;
4000       while((n = fread(buffer, 1, bufferSize, fin)) > 0)
4001         {
4002         for(char* c = buffer; c < buffer+n; ++c)
4003           {
4004           putc(*c, stdout);
4005           }
4006         fflush(stdout);
4007         }
4008       fclose(fin);
4009       }
4010     }
4011
4012   // clean up the directory
4013   cmSystemTools::RemoveADirectory(destPath.c_str());
4014   return 0;
4015 }
4016
4017 //----------------------------------------------------------------------------
4018 static bool cmakeCheckStampFile(const char* stampName)
4019 {
4020   // The stamp file does not exist.  Use the stamp dependencies to
4021   // determine whether it is really out of date.  This works in
4022   // conjunction with cmLocalVisualStudio7Generator to avoid
4023   // repeatedly re-running CMake when the user rebuilds the entire
4024   // solution.
4025   std::string stampDepends = stampName;
4026   stampDepends += ".depend";
4027 #if defined(_WIN32) || defined(__CYGWIN__)
4028   std::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
4029 #else
4030   std::ifstream fin(stampDepends.c_str(), std::ios::in);
4031 #endif
4032   if(!fin)
4033     {
4034     // The stamp dependencies file cannot be read.  Just assume the
4035     // build system is really out of date.
4036     std::cout << "CMake is re-running because " << stampName
4037               << " dependency file is missing.\n";
4038     return false;
4039     }
4040
4041   // Compare the stamp dependencies against the dependency file itself.
4042   cmFileTimeComparison ftc;
4043   std::string dep;
4044   while(cmSystemTools::GetLineFromStream(fin, dep))
4045     {
4046     int result;
4047     if(dep.length() >= 1 && dep[0] != '#' &&
4048        (!ftc.FileTimeCompare(stampDepends.c_str(), dep.c_str(), &result)
4049         || result < 0))
4050       {
4051       // The stamp depends file is older than this dependency.  The
4052       // build system is really out of date.
4053       std::cout << "CMake is re-running because " << stampName
4054                 << " is out-of-date.\n";
4055       std::cout << "  the file '" << dep << "'\n";
4056       std::cout << "  is newer than '" << stampDepends << "'\n";
4057       std::cout << "  result='" << result << "'\n";
4058       return false;
4059       }
4060     }
4061
4062   // The build system is up to date.  The stamp file has been removed
4063   // by the VS IDE due to a "rebuild" request.  Restore it atomically.
4064   cmOStringStream stampTempStream;
4065   stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
4066   std::string stampTempString = stampTempStream.str();
4067   const char* stampTemp = stampTempString.c_str();
4068   {
4069   // TODO: Teach cmGeneratedFileStream to use a random temp file (with
4070   // multiple tries in unlikely case of conflict) and use that here.
4071   std::ofstream stamp(stampTemp);
4072   stamp << "# CMake generation timestamp file for this directory.\n";
4073   }
4074   if(cmSystemTools::RenameFile(stampTemp, stampName))
4075     {
4076     // Notify the user why CMake is not re-running.  It is safe to
4077     // just print to stdout here because this code is only reachable
4078     // through an undocumented flag used by the VS generator.
4079     std::cout << "CMake does not need to re-run because "
4080               << stampName << " is up-to-date.\n";
4081     return true;
4082     }
4083   else
4084     {
4085     cmSystemTools::RemoveFile(stampTemp);
4086     cmSystemTools::Error("Cannot restore timestamp ", stampName);
4087     return false;
4088     }
4089 }
4090
4091 //----------------------------------------------------------------------------
4092 static bool cmakeCheckStampList(const char* stampList)
4093 {
4094   // If the stamp list does not exist CMake must rerun to generate it.
4095   if(!cmSystemTools::FileExists(stampList))
4096     {
4097     std::cout << "CMake is re-running because generate.stamp.list "
4098               << "is missing.\n";
4099     return false;
4100     }
4101   std::ifstream fin(stampList);
4102   if(!fin)
4103     {
4104     std::cout << "CMake is re-running because generate.stamp.list "
4105               << "could not be read.\n";
4106     return false;
4107     }
4108
4109   // Check each stamp.
4110   std::string stampName;
4111   while(cmSystemTools::GetLineFromStream(fin, stampName))
4112     {
4113     if(!cmakeCheckStampFile(stampName.c_str()))
4114       {
4115       return false;
4116       }
4117     }
4118   return true;
4119 }
4120
4121 //----------------------------------------------------------------------------
4122 int cmake::WindowsCEEnvironment(const char* version, const std::string& name)
4123 {
4124 #if defined(CMAKE_HAVE_VS_GENERATORS)
4125   cmVisualStudioWCEPlatformParser parser(name.c_str());
4126   parser.ParseVersion(version);
4127   if (parser.Found())
4128     {
4129     std::cout << "@echo off" << std::endl;
4130     std::cout << "echo Environment Selection: " << name << std::endl;
4131     std::cout << "set PATH=" << parser.GetPathDirectories() << std::endl;
4132     std::cout << "set INCLUDE=" << parser.GetIncludeDirectories() <<std::endl;
4133     std::cout << "set LIB=" << parser.GetLibraryDirectories() <<std::endl;
4134     return 0;
4135     }
4136 #else
4137   (void)version;
4138 #endif
4139
4140   std::cerr << "Could not find " << name;
4141   return -1;
4142 }
4143
4144 // For visual studio 2005 and newer manifest files need to be embedded into
4145 // exe and dll's.  This code does that in such a way that incremental linking
4146 // still works.
4147 int cmake::VisualStudioLink(std::vector<std::string>& args, int type)
4148 {
4149   if(args.size() < 2)
4150     {
4151     return -1;
4152     }
4153   bool verbose = false;
4154   if(cmSystemTools::GetEnv("VERBOSE"))
4155     {
4156     verbose = true;
4157     }
4158   std::vector<std::string> expandedArgs;
4159   for(std::vector<std::string>::iterator i = args.begin();
4160       i != args.end(); ++i)
4161     {
4162     // check for nmake temporary files
4163     if((*i)[0] == '@' && i->find("@CMakeFiles") != 0 )
4164       {
4165       std::ifstream fin(i->substr(1).c_str());
4166       std::string line;
4167       while(cmSystemTools::GetLineFromStream(fin,
4168                                              line))
4169         {
4170         cmSystemTools::ParseWindowsCommandLine(line.c_str(), expandedArgs);
4171         }
4172       }
4173     else
4174       {
4175       expandedArgs.push_back(*i);
4176       }
4177     }
4178   bool hasIncremental = false;
4179   bool hasManifest = true;
4180   for(std::vector<std::string>::iterator i = expandedArgs.begin();
4181       i != expandedArgs.end(); ++i)
4182     {
4183     if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL:YES") == 0)
4184       {
4185       hasIncremental = true;
4186       }
4187     if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL") == 0)
4188       {
4189       hasIncremental = true;
4190       }
4191     if(cmSystemTools::Strucmp(i->c_str(), "/MANIFEST:NO") == 0)
4192       {
4193       hasManifest = false;
4194       }
4195     }
4196   if(hasIncremental && hasManifest)
4197     {
4198     if(verbose)
4199       {
4200       std::cout << "Visual Studio Incremental Link with embedded manifests\n";
4201       }
4202     return cmake::VisualStudioLinkIncremental(expandedArgs, type, verbose);
4203     }
4204   if(verbose)
4205     {
4206     if(!hasIncremental)
4207       {
4208       std::cout << "Visual Studio Non-Incremental Link\n";
4209       }
4210     else
4211       {
4212       std::cout << "Visual Studio Incremental Link without manifests\n";
4213       }
4214     }
4215   return cmake::VisualStudioLinkNonIncremental(expandedArgs,
4216                                                type, hasManifest, verbose);
4217 }
4218
4219 int cmake::ParseVisualStudioLinkCommand(std::vector<std::string>& args,
4220                                         std::vector<cmStdString>& command,
4221                                         std::string& targetName)
4222 {
4223   std::vector<std::string>::iterator i = args.begin();
4224   i++; // skip -E
4225   i++; // skip vs_link_dll or vs_link_exe
4226   command.push_back(*i);
4227   i++; // move past link command
4228   for(; i != args.end(); ++i)
4229     {
4230     command.push_back(*i);
4231     if(i->find("/Fe") == 0)
4232       {
4233       targetName = i->substr(3);
4234       }
4235     if(i->find("/out:") == 0)
4236       {
4237       targetName = i->substr(5);
4238       }
4239     }
4240   if(targetName.size() == 0 || command.size() == 0)
4241     {
4242     return -1;
4243     }
4244   return 0;
4245 }
4246
4247 bool cmake::RunCommand(const char* comment,
4248                        std::vector<cmStdString>& command,
4249                        bool verbose,
4250                        int* retCodeOut)
4251 {
4252   if(verbose)
4253     {
4254     std::cout << comment << ":\n";
4255     for(std::vector<cmStdString>::iterator i = command.begin();
4256         i != command.end(); ++i)
4257       {
4258       std::cout << i->c_str() << " ";
4259       }
4260     std::cout << "\n";
4261     }
4262   std::string output;
4263   int retCode =0;
4264   // use rc command to create .res file
4265   cmSystemTools::RunSingleCommand(command,
4266                                   &output,
4267                                   &retCode, 0, cmSystemTools::OUTPUT_NONE);
4268   // always print the output of the command, unless
4269   // it is the dumb rc command banner, but if the command
4270   // returned an error code then print the output anyway as
4271   // the banner may be mixed with some other important information.
4272   if(output.find("Resource Compiler Version") == output.npos
4273      || retCode !=0)
4274     {
4275     std::cout << output;
4276     }
4277   // if retCodeOut is requested then always return true
4278   // and set the retCodeOut to retCode
4279   if(retCodeOut)
4280     {
4281     *retCodeOut = retCode;
4282     return true;
4283     }
4284   if(retCode != 0)
4285     {
4286     std::cout << comment << " failed. with " << retCode << "\n";
4287     }
4288   return retCode == 0;
4289 }
4290
4291 int cmake::VisualStudioLinkIncremental(std::vector<std::string>& args,
4292                                        int type, bool verbose)
4293 {
4294   // This follows the steps listed here:
4295   // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
4296
4297   //    1.  Compiler compiles the application and generates the *.obj files.
4298   //    2.  An empty manifest file is generated if this is a clean build and if
4299   //    not the previous one is reused.
4300   //    3.  The resource compiler (rc.exe) compiles the *.manifest file to a
4301   //    *.res file.
4302   //    4.  Linker generates the binary (EXE or DLL) with the /incremental
4303   //    switch and embeds the dummy manifest file. The linker also generates
4304   //    the real manifest file based on the binaries that your binary depends
4305   //    on.
4306   //    5.  The manifest tool (mt.exe) is then used to generate the final
4307   //    manifest.
4308
4309   // If the final manifest is changed, then 6 and 7 are run, if not
4310   // they are skipped, and it is done.
4311
4312   //    6.  The resource compiler is invoked one more time.
4313   //    7.  Finally, the Linker does another incremental link, but since the
4314   //    only thing that has changed is the *.res file that contains the
4315   //    manifest it is a short link.
4316   std::vector<cmStdString> linkCommand;
4317   std::string targetName;
4318   if(cmake::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
4319     {
4320     return -1;
4321     }
4322   std::string manifestArg = "/MANIFESTFILE:";
4323   std::vector<cmStdString> rcCommand;
4324   rcCommand.push_back(cmSystemTools::FindProgram("rc.exe"));
4325   std::vector<cmStdString> mtCommand;
4326   mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
4327   std::string tempManifest;
4328   tempManifest = targetName;
4329   tempManifest += ".intermediate.manifest";
4330   std::string resourceInputFile = targetName;
4331   resourceInputFile += ".resource.txt";
4332   if(verbose)
4333     {
4334     std::cout << "Create " << resourceInputFile.c_str() << "\n";
4335     }
4336   // Create input file for rc command
4337   std::ofstream fout(resourceInputFile.c_str());
4338   if(!fout)
4339     {
4340     return -1;
4341     }
4342   std::string manifestFile = targetName;
4343   manifestFile += ".embed.manifest";
4344   std::string fullPath= cmSystemTools::CollapseFullPath(manifestFile.c_str());
4345   fout << type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
4346     "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath.c_str() << "\"";
4347   fout.close();
4348   manifestArg += tempManifest;
4349   // add the manifest arg to the linkCommand
4350   linkCommand.push_back("/MANIFEST");
4351   linkCommand.push_back(manifestArg);
4352   // if manifestFile is not yet created, create an
4353   // empty one
4354   if(!cmSystemTools::FileExists(manifestFile.c_str()))
4355     {
4356     if(verbose)
4357       {
4358       std::cout << "Create empty: " << manifestFile.c_str() << "\n";
4359       }
4360     std::ofstream foutTmp(manifestFile.c_str());
4361     }
4362   std::string resourceFile = manifestFile;
4363   resourceFile += ".res";
4364   // add the resource file to the end of the link command
4365   linkCommand.push_back(resourceFile);
4366   std::string outputOpt = "/fo";
4367   outputOpt += resourceFile;
4368   rcCommand.push_back(outputOpt);
4369   rcCommand.push_back(resourceInputFile);
4370   // Run rc command to create resource
4371   if(!cmake::RunCommand("RC Pass 1", rcCommand, verbose))
4372     {
4373     return -1;
4374     }
4375   // Now run the link command to link and create manifest
4376   if(!cmake::RunCommand("LINK Pass 1", linkCommand, verbose))
4377     {
4378     return -1;
4379     }
4380   // create mt command
4381   std::string outArg("/out:");
4382   outArg+= manifestFile;
4383   mtCommand.push_back("/nologo");
4384   mtCommand.push_back(outArg);
4385   mtCommand.push_back("/notify_update");
4386   mtCommand.push_back("/manifest");
4387   mtCommand.push_back(tempManifest);
4388   //  now run mt.exe to create the final manifest file
4389   int mtRet =0;
4390   cmake::RunCommand("MT", mtCommand, verbose, &mtRet);
4391   // if mt returns 0, then the manifest was not changed and
4392   // we do not need to do another link step
4393   if(mtRet == 0)
4394     {
4395     return 0;
4396     }
4397   // check for magic mt return value if mt returns the magic number
4398   // 1090650113 then it means that it updated the manifest file and we need
4399   // to do the final link.  If mt has any value other than 0 or 1090650113
4400   // then there was some problem with the command itself and there was an
4401   // error so return the error code back out of cmake so make can report it.
4402   if(mtRet != 1090650113)
4403     {
4404     return mtRet;
4405     }
4406   // update the resource file with the new manifest from the mt command.
4407   if(!cmake::RunCommand("RC Pass 2", rcCommand, verbose))
4408     {
4409     return -1;
4410     }
4411   // Run the final incremental link that will put the new manifest resource
4412   // into the file incrementally.
4413   if(!cmake::RunCommand("FINAL LINK", linkCommand, verbose))
4414     {
4415     return -1;
4416     }
4417   return 0;
4418 }
4419
4420 int cmake::VisualStudioLinkNonIncremental(std::vector<std::string>& args,
4421                                           int type,
4422                                           bool hasManifest,
4423                                           bool verbose)
4424 {
4425   std::vector<cmStdString> linkCommand;
4426   std::string targetName;
4427   if(cmake::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
4428     {
4429     return -1;
4430     }
4431   // Run the link command as given
4432   if (hasManifest)
4433     {
4434     linkCommand.push_back("/MANIFEST");
4435     }
4436   if(!cmake::RunCommand("LINK", linkCommand, verbose))
4437     {
4438     return -1;
4439     }
4440   if(!hasManifest)
4441     {
4442     return 0;
4443     }
4444   std::vector<cmStdString> mtCommand;
4445   mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
4446   mtCommand.push_back("/nologo");
4447   mtCommand.push_back("/manifest");
4448   std::string manifestFile = targetName;
4449   manifestFile += ".manifest";
4450   mtCommand.push_back(manifestFile);
4451   std::string outresource = "/outputresource:";
4452   outresource += targetName;
4453   outresource += ";#";
4454   if(type == 1)
4455     {
4456     outresource += "1";
4457     }
4458   else if(type == 2)
4459     {
4460     outresource += "2";
4461     }
4462   mtCommand.push_back(outresource);
4463   // Now use the mt tool to embed the manifest into the exe or dll
4464   if(!cmake::RunCommand("MT", mtCommand, verbose))
4465     {
4466     return -1;
4467     }
4468   return 0;
4469 }
4470
4471 //----------------------------------------------------------------------------
4472 void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
4473                          cmListFileBacktrace const& backtrace)
4474 {
4475   cmOStringStream msg;
4476   bool isError = false;
4477   // Construct the message header.
4478   if(t == cmake::FATAL_ERROR)
4479     {
4480     isError = true;
4481     msg << "CMake Error";
4482     }
4483   else if(t == cmake::INTERNAL_ERROR)
4484     {
4485     isError = true;
4486     msg << "CMake Internal Error (please report a bug)";
4487     }
4488   else if(t == cmake::LOG)
4489     {
4490     msg << "CMake Debug Log";
4491     }
4492   else
4493     {
4494     msg << "CMake Warning";
4495     if(t == cmake::AUTHOR_WARNING)
4496       {
4497       // Allow suppression of these warnings.
4498       cmCacheManager::CacheIterator it = this->CacheManager
4499         ->GetCacheIterator("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
4500       if(!it.IsAtEnd() && it.GetValueAsBool())
4501         {
4502         return;
4503         }
4504       msg << " (dev)";
4505       }
4506     }
4507
4508   // Add the immediate context.
4509   cmListFileBacktrace::const_iterator i = backtrace.begin();
4510   if(i != backtrace.end())
4511     {
4512     cmListFileContext const& lfc = *i;
4513     msg << (lfc.Line? " at ": " in ") << lfc;
4514     ++i;
4515     }
4516
4517   // Add the message text.
4518   {
4519   msg << ":\n";
4520   cmDocumentationFormatterText formatter;
4521   formatter.SetIndent("  ");
4522   formatter.PrintFormatted(msg, text.c_str());
4523   }
4524
4525   // Add the rest of the context.
4526   if(i != backtrace.end())
4527     {
4528     msg << "Call Stack (most recent call first):\n";
4529     while(i != backtrace.end())
4530       {
4531       cmListFileContext const& lfc = *i;
4532       msg << "  " << lfc << "\n";
4533       ++i;
4534       }
4535     }
4536
4537   // Add a note about warning suppression.
4538   if(t == cmake::AUTHOR_WARNING)
4539     {
4540     msg <<
4541       "This warning is for project developers.  Use -Wno-dev to suppress it.";
4542     }
4543
4544   // Add a terminating blank line.
4545   msg << "\n";
4546
4547   // Output the message.
4548   if(isError)
4549     {
4550     cmSystemTools::SetErrorOccured();
4551     cmSystemTools::Message(msg.str().c_str(), "Error");
4552     }
4553   else
4554     {
4555     cmSystemTools::Message(msg.str().c_str(), "Warning");
4556     }
4557 }
4558
4559 //----------------------------------------------------------------------------
4560 std::vector<std::string> const& cmake::GetDebugConfigs()
4561 {
4562   // Compute on-demand.
4563   if(this->DebugConfigs.empty())
4564     {
4565     if(const char* config_list = this->GetProperty("DEBUG_CONFIGURATIONS"))
4566       {
4567       // Expand the specified list and convert to upper-case.
4568       cmSystemTools::ExpandListArgument(config_list, this->DebugConfigs);
4569       for(std::vector<std::string>::iterator i = this->DebugConfigs.begin();
4570           i != this->DebugConfigs.end(); ++i)
4571         {
4572         *i = cmSystemTools::UpperCase(*i);
4573         }
4574       }
4575     // If no configurations were specified, use a default list.
4576     if(this->DebugConfigs.empty())
4577       {
4578       this->DebugConfigs.push_back("DEBUG");
4579       }
4580     }
4581   return this->DebugConfigs;
4582 }
4583
4584
4585 int cmake::Build(const std::string& dir,
4586                  const std::string& target,
4587                  const std::string& config,
4588                  const std::vector<std::string>& nativeOptions,
4589                  bool clean,
4590                  cmSystemTools::OutputOption outputflag)
4591 {
4592   if(!cmSystemTools::FileIsDirectory(dir.c_str()))
4593     {
4594     std::cerr << "Error: " << dir << " is not a directory\n";
4595     return 1;
4596     }
4597   std::string cachePath = dir;
4598   cmSystemTools::ConvertToUnixSlashes(cachePath);
4599   cmCacheManager* cachem = this->GetCacheManager();
4600   cmCacheManager::CacheIterator it = cachem->NewIterator();
4601   if(!cachem->LoadCache(cachePath.c_str()))
4602     {
4603     std::cerr << "Error: could not load cache\n";
4604     return 1;
4605     }
4606   if(!it.Find("CMAKE_GENERATOR"))
4607     {
4608     std::cerr << "Error: could find generator in Cache\n";
4609     return 1;
4610     }
4611   cmsys::auto_ptr<cmGlobalGenerator> gen(
4612     this->CreateGlobalGenerator(it.GetValue()));
4613   std::string output;
4614   std::string projName;
4615   std::string makeProgram;
4616   if(!it.Find("CMAKE_PROJECT_NAME"))
4617     {
4618     std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
4619     return 1;
4620     }
4621   projName = it.GetValue();
4622   if(!it.Find("CMAKE_MAKE_PROGRAM"))
4623     {
4624     std::cerr << "Error: could not find CMAKE_MAKE_PROGRAM in Cache\n";
4625     return 1;
4626     }
4627   makeProgram = it.GetValue();
4628   return gen->Build(0, dir.c_str(),
4629                     projName.c_str(), target.c_str(),
4630                     &output,
4631                     makeProgram.c_str(),
4632                     config.c_str(), clean, false, 0, outputflag,
4633                     0, nativeOptions);
4634 }
4635
4636 void cmake::WatchUnusedCli(const char* var)
4637 {
4638 #ifdef CMAKE_BUILD_WITH_CMAKE
4639   this->VariableWatch->AddWatch(var, cmWarnUnusedCliWarning, this);
4640   if(this->UsedCliVariables.find(var) == this->UsedCliVariables.end())
4641     {
4642     this->UsedCliVariables[var] = false;
4643     }
4644 #endif
4645 }
4646
4647 void cmake::UnwatchUnusedCli(const char* var)
4648 {
4649 #ifdef CMAKE_BUILD_WITH_CMAKE
4650   this->VariableWatch->RemoveWatch(var, cmWarnUnusedCliWarning);
4651   this->UsedCliVariables.erase(var);
4652 #endif
4653 }
4654
4655 void cmake::RunCheckForUnusedVariables()
4656 {
4657 #ifdef CMAKE_BUILD_WITH_CMAKE
4658   bool haveUnused = false;
4659   cmOStringStream msg;
4660   msg << "Manually-specified variables were not used by the project:";
4661   for(std::map<cmStdString, bool>::const_iterator
4662         it = this->UsedCliVariables.begin();
4663       it != this->UsedCliVariables.end(); ++it)
4664     {
4665     if(!it->second)
4666       {
4667       haveUnused = true;
4668       msg << "\n  " << it->first;
4669       }
4670     }
4671   if(haveUnused)
4672     {
4673     this->IssueMessage(cmake::WARNING, msg.str(), cmListFileBacktrace());
4674     }
4675 #endif
4676 }