root/simulator/trunk/vendor/cmake/Source/cmake.cxx

Revision 1463, 134.1 kB (checked in by sehenley, 7 months ago)

Update to cmake-2.8.1-rc3

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