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