1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmake.cxx,v $
6 Date: $Date: 2009-04-15 13:58:33 $
7 Version: $Revision: 1.415 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmDocumentVariables.h"
20 #include "cmCacheManager.h"
21 #include "cmMakefile.h"
22 #include "cmLocalGenerator.h"
23 #include "cmExternalMakefileProjectGenerator.h"
24 #include "cmCommands.h"
25 #include "cmCommand.h"
26 #include "cmFileTimeComparison.h"
27 #include "cmGeneratedFileStream.h"
28 #include "cmSourceFile.h"
29 #include "cmVersion.h"
31 #include "cmDocumentationFormatterText.h"
33 #if defined(CMAKE_BUILD_WITH_CMAKE)
34 # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
35 # include "cmVariableWatch.h"
36 # include <cmsys/Terminal.h>
37 # include <cmsys/CommandLineArguments.hxx>
40 #include <cmsys/Directory.hxx>
41 #include <cmsys/Process.h>
42 #include <cmsys/Glob.hxx>
43 #include <cmsys/RegularExpression.hxx>
45 // only build kdevelop generator on non-windows platforms
46 // when not bootstrapping cmake
48 # if defined(CMAKE_BUILD_WITH_CMAKE)
49 # define CMAKE_USE_KDEVELOP
53 #if defined(CMAKE_BUILD_WITH_CMAKE)
54 # define CMAKE_USE_ECLIPSE
57 #if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
58 # define CMAKE_BOOT_MINGW
61 // include the generator
62 #if defined(_WIN32) && !defined(__CYGWIN__)
63 # if !defined(CMAKE_BOOT_MINGW)
64 # include "cmGlobalVisualStudio6Generator.h"
65 # include "cmGlobalVisualStudio7Generator.h"
66 # include "cmGlobalVisualStudio71Generator.h"
67 # include "cmGlobalVisualStudio8Generator.h"
68 # include "cmGlobalVisualStudio9Generator.h"
69 # include "cmGlobalVisualStudio9Win64Generator.h"
70 # include "cmGlobalVisualStudio8Win64Generator.h"
71 # include "cmGlobalBorlandMakefileGenerator.h"
72 # include "cmGlobalNMakeMakefileGenerator.h"
73 # include "cmGlobalWatcomWMakeGenerator.h"
74 # define CMAKE_HAVE_VS_GENERATORS
76 # include "cmGlobalMSYSMakefileGenerator.h"
77 # include "cmGlobalMinGWMakefileGenerator.h"
78 # include "cmWin32ProcessExecution.h"
81 #include "cmGlobalUnixMakefileGenerator3.h"
83 #if defined(CMAKE_HAVE_VS_GENERATORS)
84 #include "cmCallVisualStudioMacro.h"
87 #if !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
88 # include "cmExtraCodeBlocksGenerator.h"
91 #ifdef CMAKE_USE_KDEVELOP
92 # include "cmGlobalKdevelopGenerator.h"
95 #ifdef CMAKE_USE_ECLIPSE
96 # include "cmExtraEclipseCDT4Generator.h"
99 #include <stdlib.h> // required for atoi
101 #if defined( __APPLE__ )
102 # if defined(CMAKE_BUILD_WITH_CMAKE)
103 # include "cmGlobalXCodeGenerator.h"
104 # define CMAKE_USE_XCODE 1
106 # include <sys/types.h>
107 # include <sys/time.h>
108 # include <sys/resource.h>
111 #include <sys/stat.h> // struct stat
113 #include <memory> // auto_ptr
115 static bool cmakeCheckStampFile(const char* stampName
);
116 static bool cmakeCheckStampList(const char* stampName
);
118 void cmNeedBackwardsCompatibility(const std::string
& variable
,
119 int access_type
, void*, const char*, const cmMakefile
*)
121 #ifdef CMAKE_BUILD_WITH_CMAKE
122 if (access_type
== cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS
)
124 std::string message
= "An attempt was made to access a variable: ";
127 " that has not been defined. Some variables were always defined "
128 "by CMake in versions prior to 1.6. To fix this you might need to set "
129 "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
130 "you are writing a CMakeList file, (or have already set "
131 "CMAKE_BACKWARDS_COMPATABILITY to 1.4 or less) then you probably need "
132 "to include a CMake module to test for the feature this variable "
134 cmSystemTools::Error(message
.c_str());
145 this->SuppressDevWarnings
= false;
146 this->DoSuppressDevWarnings
= false;
147 this->DebugOutput
= false;
148 this->DebugTryCompile
= false;
149 this->ClearBuildSystem
= false;
150 this->FileComparison
= new cmFileTimeComparison
;
152 this->Policies
= new cmPolicies();
153 this->InitializeProperties();
157 if(!getrlimit(RLIMIT_STACK
, &rlp
))
159 if(rlp
.rlim_cur
!= rlp
.rlim_max
)
161 rlp
.rlim_cur
= rlp
.rlim_max
;
162 setrlimit(RLIMIT_STACK
, &rlp
);
167 // If MAKEFLAGS are given in the environment, remove the environment
168 // variable. This will prevent try-compile from succeeding when it
169 // should fail (if "-i" is an option). We cannot simply test
170 // whether "-i" is given and remove it because some make programs
171 // encode the MAKEFLAGS variable in a strange way.
172 if(getenv("MAKEFLAGS"))
174 cmSystemTools::PutEnv("MAKEFLAGS=");
177 this->Verbose
= false;
178 this->InTryCompile
= false;
179 this->CacheManager
= new cmCacheManager(this);
180 this->GlobalGenerator
= 0;
181 this->ProgressCallback
= 0;
182 this->ProgressCallbackClientData
= 0;
183 this->ScriptMode
= false;
185 #ifdef CMAKE_BUILD_WITH_CMAKE
186 this->VariableWatch
= new cmVariableWatch
;
187 this->VariableWatch
->AddWatch("CMAKE_WORDS_BIGENDIAN",
188 cmNeedBackwardsCompatibility
);
189 this->VariableWatch
->AddWatch("CMAKE_SIZEOF_INT",
190 cmNeedBackwardsCompatibility
);
191 this->VariableWatch
->AddWatch("CMAKE_X_LIBS",
192 cmNeedBackwardsCompatibility
);
195 this->AddDefaultGenerators();
196 this->AddDefaultExtraGenerators();
197 this->AddDefaultCommands();
199 // Make sure we can capture the build tool output.
200 cmSystemTools::EnableVSConsoleOutput();
205 delete this->CacheManager
;
206 delete this->Policies
;
207 if (this->GlobalGenerator
)
209 delete this->GlobalGenerator
;
210 this->GlobalGenerator
= 0;
212 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
213 j
!= this->Commands
.end(); ++j
)
217 #ifdef CMAKE_BUILD_WITH_CMAKE
218 delete this->VariableWatch
;
220 delete this->FileComparison
;
223 void cmake::InitializeProperties()
225 this->Properties
.clear();
226 this->Properties
.SetCMakeInstance(this);
227 this->AccessedProperties
.clear();
228 this->PropertyDefinitions
.clear();
230 // initialize properties
231 cmCacheManager::DefineProperties(this);
232 cmSourceFile::DefineProperties(this);
233 cmTarget::DefineProperties(this);
234 cmMakefile::DefineProperties(this);
235 cmTest::DefineProperties(this);
236 cmake::DefineProperties(this);
239 void cmake::CleanupCommandsAndMacros()
241 this->InitializeProperties();
242 std::vector
<cmCommand
*> commands
;
243 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
244 j
!= this->Commands
.end(); ++j
)
246 if ( !j
->second
->IsA("cmMacroHelperCommand") &&
247 !j
->second
->IsA("cmFunctionHelperCommand"))
249 commands
.push_back(j
->second
);
256 this->Commands
.erase(this->Commands
.begin(), this->Commands
.end());
257 std::vector
<cmCommand
*>::iterator it
;
258 for ( it
= commands
.begin(); it
!= commands
.end();
261 this->Commands
[cmSystemTools::LowerCase((*it
)->GetName())] = *it
;
265 bool cmake::CommandExists(const char* name
) const
267 std::string sName
= cmSystemTools::LowerCase(name
);
268 return (this->Commands
.find(sName
) != this->Commands
.end());
271 cmCommand
*cmake::GetCommand(const char *name
)
274 std::string sName
= cmSystemTools::LowerCase(name
);
275 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
276 if (pos
!= this->Commands
.end())
283 void cmake::RenameCommand(const char*oldName
, const char* newName
)
285 // if the command already exists, free the old one
286 std::string sOldName
= cmSystemTools::LowerCase(oldName
);
287 std::string sNewName
= cmSystemTools::LowerCase(newName
);
288 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sOldName
);
289 if ( pos
== this->Commands
.end() )
293 cmCommand
* cmd
= pos
->second
;
295 pos
= this->Commands
.find(sNewName
);
296 if (pos
!= this->Commands
.end())
299 this->Commands
.erase(pos
);
301 this->Commands
.insert(RegisteredCommandsMap::value_type(sNewName
, cmd
));
302 pos
= this->Commands
.find(sOldName
);
303 this->Commands
.erase(pos
);
306 void cmake::RemoveCommand(const char* name
)
308 std::string sName
= cmSystemTools::LowerCase(name
);
309 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
310 if ( pos
!= this->Commands
.end() )
313 this->Commands
.erase(pos
);
317 void cmake::AddCommand(cmCommand
* wg
)
319 std::string name
= cmSystemTools::LowerCase(wg
->GetName());
320 // if the command already exists, free the old one
321 RegisteredCommandsMap::iterator pos
= this->Commands
.find(name
);
322 if (pos
!= this->Commands
.end())
325 this->Commands
.erase(pos
);
327 this->Commands
.insert( RegisteredCommandsMap::value_type(name
, wg
));
331 void cmake::RemoveUnscriptableCommands()
333 std::vector
<std::string
> unscriptableCommands
;
334 cmake::RegisteredCommandsMap
* commands
= this->GetCommands();
335 for (cmake::RegisteredCommandsMap::const_iterator pos
= commands
->begin();
336 pos
!= commands
->end();
339 if (!pos
->second
->IsScriptable())
341 unscriptableCommands
.push_back(pos
->first
);
345 for(std::vector
<std::string
>::const_iterator it
=unscriptableCommands
.begin();
346 it
!= unscriptableCommands
.end();
349 this->RemoveCommand(it
->c_str());
354 bool cmake::SetCacheArgs(const std::vector
<std::string
>& args
)
356 for(unsigned int i
=1; i
< args
.size(); ++i
)
358 std::string arg
= args
[i
];
359 if(arg
.find("-D",0) == 0)
361 std::string entry
= arg
.substr(2);
362 if(entry
.size() == 0)
371 cmSystemTools::Error("-D must be followed with VAR=VALUE.");
375 std::string var
, value
;
376 cmCacheManager::CacheEntryType type
= cmCacheManager::UNINITIALIZED
;
377 if(cmCacheManager::ParseEntry(entry
.c_str(), var
, value
, type
) ||
378 cmCacheManager::ParseEntry(entry
.c_str(), var
, value
))
380 this->CacheManager
->AddCacheEntry(var
.c_str(), value
.c_str(),
381 "No help, variable specified on the command line.", type
);
385 std::cerr
<< "Parse error in command line argument: " << arg
<< "\n"
386 << "Should be: VAR:type=value\n";
387 cmSystemTools::Error("No cmake scrpt provided.");
391 else if(arg
.find("-Wno-dev",0) == 0)
393 this->SuppressDevWarnings
= true;
394 this->DoSuppressDevWarnings
= true;
396 else if(arg
.find("-Wdev",0) == 0)
398 this->SuppressDevWarnings
= false;
399 this->DoSuppressDevWarnings
= true;
401 else if(arg
.find("-U",0) == 0)
403 std::string entryPattern
= arg
.substr(2);
404 if(entryPattern
.size() == 0)
409 entryPattern
= args
[i
];
413 cmSystemTools::Error("-U must be followed with VAR.");
417 cmsys::RegularExpression
regex(
418 cmsys::Glob::PatternToRegex(entryPattern
.c_str(), true).c_str());
419 //go through all cache entries and collect the vars which will be removed
420 std::vector
<std::string
> entriesToDelete
;
421 cmCacheManager::CacheIterator it
=
422 this->CacheManager
->GetCacheIterator();
423 for ( it
.Begin(); !it
.IsAtEnd(); it
.Next() )
425 cmCacheManager::CacheEntryType t
= it
.GetType();
426 if(t
!= cmCacheManager::STATIC
)
428 std::string entryName
= it
.GetName();
429 if (regex
.find(entryName
.c_str()))
431 entriesToDelete
.push_back(entryName
);
436 // now remove them from the cache
437 for(std::vector
<std::string
>::const_iterator currentEntry
=
438 entriesToDelete
.begin();
439 currentEntry
!= entriesToDelete
.end();
442 this->CacheManager
->RemoveCacheEntry(currentEntry
->c_str());
445 else if(arg
.find("-C",0) == 0)
447 std::string path
= arg
.substr(2);
448 if ( path
.size() == 0 )
457 cmSystemTools::Error("-C must be followed by a file name.");
461 std::cerr
<< "loading initial cache file " << path
.c_str() << "\n";
462 this->ReadListFile(path
.c_str());
464 else if(arg
.find("-P",0) == 0)
469 cmSystemTools::Error("-P must be followed by a file name.");
472 std::string path
= args
[i
];
473 if ( path
.size() == 0 )
475 cmSystemTools::Error("No cmake script provided.");
478 this->ReadListFile(path
.c_str());
484 void cmake::ReadListFile(const char *path
)
486 // if a generator was not yet created, temporarily create one
487 cmGlobalGenerator
*gg
= this->GetGlobalGenerator();
488 bool created
= false;
490 // if a generator was not specified use a generic one
493 gg
= new cmGlobalGenerator
;
494 gg
->SetCMakeInstance(this);
498 // read in the list file to fill the cache
501 std::auto_ptr
<cmLocalGenerator
> lg(gg
->CreateLocalGenerator());
502 lg
->SetGlobalGenerator(gg
);
503 lg
->GetMakefile()->SetHomeOutputDirectory
504 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
505 lg
->GetMakefile()->SetStartOutputDirectory
506 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
507 lg
->GetMakefile()->SetHomeDirectory
508 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
509 lg
->GetMakefile()->SetStartDirectory
510 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
511 if (!lg
->GetMakefile()->ReadListFile(0, path
))
513 cmSystemTools::Error("Error processing file:", path
);
517 // free generic one if generated
525 void cmake::SetArgs(const std::vector
<std::string
>& args
)
527 bool directoriesSet
= false;
528 for(unsigned int i
=1; i
< args
.size(); ++i
)
530 std::string arg
= args
[i
];
531 if(arg
.find("-H",0) == 0)
533 directoriesSet
= true;
534 std::string path
= arg
.substr(2);
535 path
= cmSystemTools::CollapseFullPath(path
.c_str());
536 cmSystemTools::ConvertToUnixSlashes(path
);
537 this->SetHomeDirectory(path
.c_str());
539 else if(arg
.find("-S",0) == 0)
541 // There is no local generate anymore. Ignore -S option.
543 else if(arg
.find("-O",0) == 0)
545 // There is no local generate anymore. Ignore -O option.
547 else if(arg
.find("-B",0) == 0)
549 directoriesSet
= true;
550 std::string path
= arg
.substr(2);
551 path
= cmSystemTools::CollapseFullPath(path
.c_str());
552 cmSystemTools::ConvertToUnixSlashes(path
);
553 this->SetHomeOutputDirectory(path
.c_str());
555 else if((i
< args
.size()-1) && (arg
.find("--check-build-system",0) == 0))
557 this->CheckBuildSystemArgument
= args
[++i
];
558 this->ClearBuildSystem
= (atoi(args
[++i
].c_str()) > 0);
560 else if((i
< args
.size()-1) && (arg
.find("--check-stamp-file",0) == 0))
562 this->CheckStampFile
= args
[++i
];
564 else if((i
< args
.size()-1) && (arg
.find("--check-stamp-list",0) == 0))
566 this->CheckStampList
= args
[++i
];
568 #if defined(CMAKE_HAVE_VS_GENERATORS)
569 else if((i
< args
.size()-1) && (arg
.find("--vs-solution-file",0) == 0))
571 this->VSSolutionFile
= args
[++i
];
574 else if(arg
.find("-V",0) == 0)
576 this->Verbose
= true;
578 else if(arg
.find("-D",0) == 0)
582 else if(arg
.find("-U",0) == 0)
586 else if(arg
.find("-C",0) == 0)
590 else if(arg
.find("-P",0) == 0)
595 else if(arg
.find("-Wno-dev",0) == 0)
599 else if(arg
.find("-Wdev",0) == 0)
603 else if(arg
.find("--graphviz=",0) == 0)
605 std::string path
= arg
.substr(strlen("--graphviz="));
606 path
= cmSystemTools::CollapseFullPath(path
.c_str());
607 cmSystemTools::ConvertToUnixSlashes(path
);
608 this->GraphVizFile
= path
;
609 if ( this->GraphVizFile
.empty() )
611 cmSystemTools::Error("No file specified for --graphviz");
614 else if(arg
.find("--debug-trycompile",0) == 0)
616 std::cout
<< "debug trycompile on\n";
617 this->DebugTryCompileOn();
619 else if(arg
.find("--debug-output",0) == 0)
621 std::cout
<< "Running with debug output on.\n";
622 this->SetDebugOutputOn(true);
624 else if(arg
.find("--trace",0) == 0)
626 std::cout
<< "Running with trace output on.\n";
627 this->SetTrace(true);
629 else if(arg
.find("-G",0) == 0)
631 std::string value
= arg
.substr(2);
632 if(value
.size() == 0)
637 cmSystemTools::Error("No generator specified for -G");
642 cmGlobalGenerator
* gen
=
643 this->CreateGlobalGenerator(value
.c_str());
646 cmSystemTools::Error("Could not create named generator ",
651 this->SetGlobalGenerator(gen
);
654 // no option assume it is the path to the source
657 directoriesSet
= true;
658 this->SetDirectoriesFromFile(arg
.c_str());
663 this->SetHomeOutputDirectory
664 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
665 this->SetStartOutputDirectory
666 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
667 this->SetHomeDirectory
668 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
669 this->SetStartDirectory
670 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
673 this->SetStartDirectory(this->GetHomeDirectory());
674 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
677 //----------------------------------------------------------------------------
678 void cmake::SetDirectoriesFromFile(const char* arg
)
680 // Check if the argument refers to a CMakeCache.txt or
681 // CMakeLists.txt file.
682 std::string listPath
;
683 std::string cachePath
;
684 bool argIsFile
= false;
685 if(cmSystemTools::FileIsDirectory(arg
))
687 std::string path
= cmSystemTools::CollapseFullPath(arg
);
688 cmSystemTools::ConvertToUnixSlashes(path
);
689 std::string cacheFile
= path
;
690 cacheFile
+= "/CMakeCache.txt";
691 std::string listFile
= path
;
692 listFile
+= "/CMakeLists.txt";
693 if(cmSystemTools::FileExists(cacheFile
.c_str()))
697 if(cmSystemTools::FileExists(listFile
.c_str()))
702 else if(cmSystemTools::FileExists(arg
))
705 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
706 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
707 name
= cmSystemTools::LowerCase(name
);
708 if(name
== "cmakecache.txt")
710 cachePath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
712 else if(name
== "cmakelists.txt")
714 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
719 // Specified file or directory does not exist. Try to set things
720 // up to produce a meaningful error message.
721 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
722 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
723 name
= cmSystemTools::LowerCase(name
);
724 if(name
== "cmakecache.txt" || name
== "cmakelists.txt")
727 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
735 // If there is a CMakeCache.txt file, use its settings.
736 if(cachePath
.length() > 0)
738 cmCacheManager
* cachem
= this->GetCacheManager();
739 cmCacheManager::CacheIterator it
= cachem
->NewIterator();
740 if(cachem
->LoadCache(cachePath
.c_str()) &&
741 it
.Find("CMAKE_HOME_DIRECTORY"))
743 this->SetHomeOutputDirectory(cachePath
.c_str());
744 this->SetStartOutputDirectory(cachePath
.c_str());
745 this->SetHomeDirectory(it
.GetValue());
746 this->SetStartDirectory(it
.GetValue());
751 // If there is a CMakeLists.txt file, use it as the source tree.
752 if(listPath
.length() > 0)
754 this->SetHomeDirectory(listPath
.c_str());
755 this->SetStartDirectory(listPath
.c_str());
759 // Source CMakeLists.txt file given. It was probably dropped
760 // onto the executable in a GUI. Default to an in-source build.
761 this->SetHomeOutputDirectory(listPath
.c_str());
762 this->SetStartOutputDirectory(listPath
.c_str());
766 // Source directory given on command line. Use current working
767 // directory as build tree.
768 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
769 this->SetHomeOutputDirectory(cwd
.c_str());
770 this->SetStartOutputDirectory(cwd
.c_str());
775 // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
776 // argument. Assume it is the path to the source tree, and use the
777 // current working directory as the build tree.
778 std::string full
= cmSystemTools::CollapseFullPath(arg
);
779 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
780 this->SetHomeDirectory(full
.c_str());
781 this->SetStartDirectory(full
.c_str());
782 this->SetHomeOutputDirectory(cwd
.c_str());
783 this->SetStartOutputDirectory(cwd
.c_str());
786 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
788 int cmake::AddCMakePaths()
790 // Find the cmake executable
791 std::string cMakeSelf
= cmSystemTools::GetExecutableDirectory();
792 cMakeSelf
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
793 cMakeSelf
+= "/cmake";
794 cMakeSelf
+= cmSystemTools::GetExecutableExtension();
796 // on the apple this might be the gui bundle
797 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
799 cMakeSelf
= cmSystemTools::GetExecutableDirectory();
800 cMakeSelf
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
801 cMakeSelf
+= "../../../..";
802 cMakeSelf
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
803 cMakeSelf
= cmSystemTools::CollapseFullPath(cMakeSelf
.c_str());
804 cMakeSelf
+= "/cmake";
805 std::cerr
<< cMakeSelf
.c_str() << "\n";
808 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
810 cmSystemTools::Error("CMake executable cannot be found at ",
814 // Save the value in the cache
815 this->CacheManager
->AddCacheEntry
816 ("CMAKE_COMMAND",cMakeSelf
.c_str(), "Path to CMake executable.",
817 cmCacheManager::INTERNAL
);
818 // if the edit command is not yet in the cache,
819 // or if CMakeEditCommand has been set on this object,
820 // then set the CMAKE_EDIT_COMMAND in the cache
821 // This will mean that the last gui to edit the cache
822 // will be the one that make edit_cache uses.
823 if(!this->GetCacheDefinition("CMAKE_EDIT_COMMAND")
824 || !this->CMakeEditCommand
.empty())
826 // Find and save the command to edit the cache
827 std::string editCacheCommand
;
828 if(!this->CMakeEditCommand
.empty())
830 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
)
832 + this->CMakeEditCommand
833 + cmSystemTools::GetFilenameExtension(cMakeSelf
);
835 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
837 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
838 "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
840 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
842 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
843 "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
845 if(cmSystemTools::FileExists(editCacheCommand
.c_str()))
847 this->CacheManager
->AddCacheEntry
848 ("CMAKE_EDIT_COMMAND", editCacheCommand
.c_str(),
849 "Path to cache edit program executable.", cmCacheManager::INTERNAL
);
852 std::string ctestCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
853 "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
854 if(cmSystemTools::FileExists(ctestCommand
.c_str()))
856 this->CacheManager
->AddCacheEntry
857 ("CMAKE_CTEST_COMMAND", ctestCommand
.c_str(),
858 "Path to ctest program executable.", cmCacheManager::INTERNAL
);
860 std::string cpackCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
861 "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
862 if(cmSystemTools::FileExists(cpackCommand
.c_str()))
864 this->CacheManager
->AddCacheEntry
865 ("CMAKE_CPACK_COMMAND", cpackCommand
.c_str(),
866 "Path to cpack program executable.", cmCacheManager::INTERNAL
);
869 // do CMAKE_ROOT, look for the environment variable first
870 std::string cMakeRoot
;
872 if (getenv("CMAKE_ROOT"))
874 cMakeRoot
= getenv("CMAKE_ROOT");
875 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
877 if(!cmSystemTools::FileExists(modules
.c_str()))
880 cMakeRoot
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
881 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeRoot
.c_str());
882 std::string::size_type slashPos
= cMakeRoot
.rfind("/");
883 if(slashPos
!= std::string::npos
)
885 cMakeRoot
= cMakeRoot
.substr(0, slashPos
);
887 // is there no Modules direcory there?
888 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
891 if (!cmSystemTools::FileExists(modules
.c_str()))
893 // try exe/../share/cmake
894 cMakeRoot
+= CMAKE_DATA_DIR
;
895 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
897 #ifdef CMAKE_ROOT_DIR
898 if (!cmSystemTools::FileExists(modules
.c_str()))
900 // try compiled in root directory
901 cMakeRoot
= CMAKE_ROOT_DIR
;
902 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
905 if (!cmSystemTools::FileExists(modules
.c_str()))
908 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
909 cMakeRoot
+= CMAKE_DATA_DIR
;
910 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
912 if(!cmSystemTools::FileExists(modules
.c_str()))
915 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
916 // is there no Modules direcory there?
917 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
919 if (!cmSystemTools::FileExists(modules
.c_str()))
921 // couldn't find modules
922 cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n"
923 "CMake has most likely not been installed correctly.\n"
924 "Modules directory not found in\n",
928 this->CacheManager
->AddCacheEntry
929 ("CMAKE_ROOT", cMakeRoot
.c_str(),
930 "Path to CMake installation.", cmCacheManager::INTERNAL
);
933 std::string comspec
= "cmw9xcom.exe";
934 cmSystemTools::SetWindows9xComspecSubstitute(comspec
.c_str());
941 void CMakeCommandUsage(const char* program
)
943 cmOStringStream errorStream
;
945 #ifdef CMAKE_BUILD_WITH_CMAKE
947 << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
950 << "cmake bootstrap\n";
952 // If you add new commands, change here,
953 // and in cmakemain.cxx in the options table
955 << "Usage: " << program
<< " -E [command] [arguments ...]\n"
956 << "Available commands: \n"
957 << " chdir dir cmd [args]... - run command in a given directory\n"
958 << " rename oldname newname - rename a file or directory "
960 << " copy file destination - copy file to destination (either file "
962 << " copy_if_different in-file out-file - copy file if input has "
964 << " copy_directory source destination - copy directory 'source' "
965 "content to directory 'destination'\n"
966 << " compare_files file1 file2 - check if file1 is same as file2\n"
967 << " echo [string]... - displays arguments as text\n"
968 << " echo_append [string]... - displays arguments as text but no new "
970 << " environment - display the current enviroment\n"
971 << " make_directory dir - create a directory\n"
972 << " md5sum file1 [...] - compute md5sum of files\n"
973 << " remove_directory dir - remove a directory and its contents\n"
974 << " remove [-f] file1 file2 ... - remove the file(s), use -f to force "
976 << " tar [cxt][vfz] file.tar file/dir1 file/dir2 ... - create a tar "
978 << " time command [args] ... - run command and return elapsed time\n"
979 << " touch file - touch a file.\n"
980 << " touch_nocreate file - touch a file but do not create it.\n"
981 << " build build_dir - build the project in build_dir.\n"
982 #if defined(_WIN32) && !defined(__CYGWIN__)
983 << " write_regv key value - write registry value\n"
984 << " delete_regv key - delete registry value\n"
985 << " comspec - on windows 9x use this for RunCommand\n"
987 << " create_symlink old new - create a symbolic link new -> old\n"
991 cmSystemTools::Error(errorStream
.str().c_str());
994 int cmake::ExecuteCMakeCommand(std::vector
<std::string
>& args
)
996 // IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
1000 if (args
[1] == "copy" && args
.size() == 4)
1002 if(!cmSystemTools::cmCopyFile(args
[2].c_str(), args
[3].c_str()))
1004 std::cerr
<< "Error copying file \"" << args
[2].c_str()
1005 << "\" to \"" << args
[3].c_str() << "\".\n";
1011 // Copy file if different.
1012 if (args
[1] == "copy_if_different" && args
.size() == 4)
1014 if(!cmSystemTools::CopyFileIfDifferent(args
[2].c_str(),
1017 std::cerr
<< "Error copying file (if different) from \""
1018 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
1025 // Copy directory content
1026 if (args
[1] == "copy_directory" && args
.size() == 4)
1028 if(!cmSystemTools::CopyADirectory(args
[2].c_str(), args
[3].c_str()))
1030 std::cerr
<< "Error copying directory from \""
1031 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
1038 // Rename a file or directory
1039 if (args
[1] == "rename" && args
.size() == 4)
1041 if(!cmSystemTools::RenameFile(args
[2].c_str(), args
[3].c_str()))
1043 std::string e
= cmSystemTools::GetLastSystemError();
1044 std::cerr
<< "Error renaming from \""
1045 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
1046 << "\": " << e
<< "\n";
1053 if (args
[1] == "compare_files" && args
.size() == 4)
1055 if(cmSystemTools::FilesDiffer(args
[2].c_str(), args
[3].c_str()))
1057 std::cerr
<< "Files \""
1058 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
1059 << "\" are different.\n";
1066 else if (args
[1] == "echo" )
1069 const char* space
= "";
1070 for ( cc
= 2; cc
< args
.size(); cc
++ )
1072 std::cout
<< space
<< args
[cc
];
1075 std::cout
<< std::endl
;
1079 // Echo string no new line
1080 else if (args
[1] == "echo_append" )
1083 const char* space
= "";
1084 for ( cc
= 2; cc
< args
.size(); cc
++ )
1086 std::cout
<< space
<< args
[cc
];
1092 #if defined(CMAKE_BUILD_WITH_CMAKE)
1093 // Command to create a symbolic link. Fails on platforms not
1095 else if (args
[1] == "environment" )
1097 std::vector
<std::string
> env
= cmSystemTools::GetEnvironmentVariables();
1098 std::vector
<std::string
>::iterator it
;
1099 for ( it
= env
.begin(); it
!= env
.end(); ++ it
)
1101 std::cout
<< it
->c_str() << std::endl
;
1107 else if (args
[1] == "make_directory" && args
.size() == 3)
1109 if(!cmSystemTools::MakeDirectory(args
[2].c_str()))
1111 std::cerr
<< "Error making directory \"" << args
[2].c_str()
1118 else if (args
[1] == "remove_directory" && args
.size() == 3)
1120 if(cmSystemTools::FileIsDirectory(args
[2].c_str()) &&
1121 !cmSystemTools::RemoveADirectory(args
[2].c_str()))
1123 std::cerr
<< "Error removing directory \"" << args
[2].c_str()
1131 else if (args
[1] == "remove" && args
.size() > 2)
1134 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1136 if(args
[cc
] == "\\-f" || args
[cc
] == "-f")
1142 // Complain if the file could not be removed, still exists,
1143 // and the -f option was not given.
1144 if(!cmSystemTools::RemoveFile(args
[cc
].c_str()) && !force
&&
1145 cmSystemTools::FileExists(args
[cc
].c_str()))
1154 else if (args
[1] == "touch" && args
.size() > 2)
1156 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1158 // Complain if the file could not be removed, still exists,
1159 // and the -f option was not given.
1160 if(!cmSystemTools::Touch(args
[cc
].c_str(), true))
1168 else if (args
[1] == "touch_nocreate" && args
.size() > 2)
1170 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1172 // Complain if the file could not be removed, still exists,
1173 // and the -f option was not given.
1174 if(!cmSystemTools::Touch(args
[cc
].c_str(), false))
1183 else if (args
[1] == "time" && args
.size() > 2)
1185 std::string command
= args
[2];
1186 for (std::string::size_type cc
= 3; cc
< args
.size(); cc
++)
1189 command
+= args
[cc
];
1192 clock_t clock_start
, clock_finish
;
1193 time_t time_start
, time_finish
;
1196 clock_start
= clock();
1198 cmSystemTools::RunSingleCommand(command
.c_str(), 0, &ret
);
1200 clock_finish
= clock();
1203 double clocks_per_sec
= static_cast<double>(CLOCKS_PER_SEC
);
1204 std::cout
<< "Elapsed time: "
1205 << static_cast<long>(time_finish
- time_start
) << " s. (time)"
1207 << static_cast<double>(clock_finish
- clock_start
) / clocks_per_sec
1212 // Command to calculate the md5sum of a file
1213 else if (args
[1] == "md5sum" && args
.size() >= 3)
1217 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1219 const char *filename
= args
[cc
].c_str();
1220 // Cannot compute md5sum of a directory
1221 if(cmSystemTools::FileIsDirectory(filename
))
1223 std::cerr
<< "Error: " << filename
<< " is a directory" << std::endl
;
1226 else if(!cmSystemTools::ComputeFileMD5(filename
, md5out
))
1228 // To mimic md5sum behavior in a shell:
1229 std::cerr
<< filename
<< ": No such file or directory" << std::endl
;
1234 std::cout
<< std::string(md5out
,32) << " " << filename
<< std::endl
;
1240 // Command to change directory and run a program.
1241 else if (args
[1] == "chdir" && args
.size() >= 4)
1243 std::string directory
= args
[2];
1244 if(!cmSystemTools::FileExists(directory
.c_str()))
1246 cmSystemTools::Error("Directory does not exist for chdir command: ",
1251 std::string command
= "\"";
1254 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1257 command
+= args
[cc
];
1262 if ( cmSystemTools::RunSingleCommand(command
.c_str(), 0, &retval
,
1263 directory
.c_str(), true, timeout
) )
1271 // Command to start progress for a build
1272 else if (args
[1] == "cmake_progress_start" && args
.size() == 4)
1274 // bascially remove the directory
1275 std::string dirName
= args
[2];
1276 dirName
+= "/Progress";
1277 cmSystemTools::RemoveADirectory(dirName
.c_str());
1279 // is the last argument a filename that exists?
1280 FILE *countFile
= fopen(args
[3].c_str(),"r");
1284 fscanf(countFile
,"%i",&count
);
1289 count
= atoi(args
[3].c_str());
1293 cmSystemTools::MakeDirectory(dirName
.c_str());
1294 // write the count into the directory
1295 std::string fName
= dirName
;
1296 fName
+= "/count.txt";
1297 FILE *progFile
= fopen(fName
.c_str(),"w");
1300 fprintf(progFile
,"%i\n",count
);
1307 // Command to report progress for a build
1308 else if (args
[1] == "cmake_progress_report" && args
.size() >= 3)
1310 std::string dirName
= args
[2];
1311 dirName
+= "/Progress";
1317 fName
+= "/count.txt";
1318 progFile
= fopen(fName
.c_str(),"r");
1326 fscanf(progFile
,"%i",&count
);
1330 for (i
= 3; i
< args
.size(); ++i
)
1335 progFile
= fopen(fName
.c_str(),"w");
1338 fprintf(progFile
,"empty");
1342 int fileNum
= static_cast<int>
1343 (cmsys::Directory::GetNumberOfFilesInDirectory(dirName
.c_str()));
1346 // print the progress
1347 fprintf(stdout
,"[%3i%%] ",((fileNum
-3)*100)/count
);
1352 // Command to create a symbolic link. Fails on platforms not
1354 else if (args
[1] == "create_symlink" && args
.size() == 4)
1356 const char* destinationFileName
= args
[3].c_str();
1357 if ( cmSystemTools::FileExists(destinationFileName
) )
1359 if ( cmSystemTools::FileIsSymlink(destinationFileName
) )
1361 if ( !cmSystemTools::RemoveFile(destinationFileName
) ||
1362 cmSystemTools::FileExists(destinationFileName
) )
1372 return cmSystemTools::CreateSymlink(args
[2].c_str(),
1373 args
[3].c_str())? 0:1;
1376 // Internal CMake shared library support.
1377 else if (args
[1] == "cmake_symlink_library" && args
.size() == 5)
1380 std::string realName
= args
[2];
1381 std::string soName
= args
[3];
1382 std::string name
= args
[4];
1383 if(soName
!= realName
)
1385 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1386 if(cmSystemTools::FileExists(soName
.c_str()) ||
1387 cmSystemTools::FileIsSymlink(soName
.c_str()))
1389 cmSystemTools::RemoveFile(soName
.c_str());
1391 if(!cmSystemTools::CreateSymlink(fname
.c_str(), soName
.c_str()))
1393 cmSystemTools::ReportLastSystemError("cmake_symlink_library");
1399 std::string fname
= cmSystemTools::GetFilenameName(soName
);
1400 if(cmSystemTools::FileExists(name
.c_str()) ||
1401 cmSystemTools::FileIsSymlink(name
.c_str()))
1403 cmSystemTools::RemoveFile(name
.c_str());
1405 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1407 cmSystemTools::ReportLastSystemError("cmake_symlink_library");
1413 // Internal CMake versioned executable support.
1414 else if (args
[1] == "cmake_symlink_executable" && args
.size() == 4)
1417 std::string realName
= args
[2];
1418 std::string name
= args
[3];
1419 if(name
!= realName
)
1421 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1422 if(cmSystemTools::FileExists(name
.c_str()) ||
1423 cmSystemTools::FileIsSymlink(name
.c_str()))
1425 cmSystemTools::RemoveFile(name
.c_str());
1427 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1429 cmSystemTools::ReportLastSystemError("cmake_symlink_executable");
1436 #if defined(CMAKE_HAVE_VS_GENERATORS)
1437 // Internal CMake support for calling Visual Studio macros.
1438 else if (args
[1] == "cmake_call_visual_studio_macro" && args
.size() >= 4)
1440 // args[2] = full path to .sln file or "ALL"
1441 // args[3] = name of Visual Studio macro to call
1442 // args[4..args.size()-1] = [optional] args for Visual Studio macro
1444 std::string macroArgs
;
1446 if (args
.size() > 4)
1448 macroArgs
= args
[4];
1450 for (size_t i
= 5; i
< args
.size(); ++i
)
1453 macroArgs
+= args
[i
];
1457 return cmCallVisualStudioMacro::CallMacro(args
[2], args
[3],
1462 // Internal CMake dependency scanning support.
1463 else if (args
[1] == "cmake_depends" && args
.size() >= 6)
1465 // Use the make system's VERBOSE environment variable to enable
1467 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
1469 // Create a cmake object instance to process dependencies.
1472 std::string homeDir
;
1473 std::string startDir
;
1474 std::string homeOutDir
;
1475 std::string startOutDir
;
1476 std::string depInfo
;
1478 if(args
.size() >= 8)
1482 // -E cmake_depends <generator>
1483 // <home-src-dir> <start-src-dir>
1484 // <home-out-dir> <start-out-dir>
1485 // <dep-info> [--color=$(COLOR)]
1487 // All paths are provided.
1491 homeOutDir
= args
[5];
1492 startOutDir
= args
[6];
1494 if(args
.size() >= 9 &&
1495 args
[8].length() > 8 &&
1496 args
[8].substr(0, 8) == "--color=")
1498 // Enable or disable color based on the switch value.
1499 color
= cmSystemTools::IsOn(args
[8].substr(8).c_str());
1504 // Support older signature for existing makefiles:
1506 // -E cmake_depends <generator>
1507 // <home-out-dir> <start-out-dir>
1510 // Just pretend the source directories are the same as the
1511 // binary directories so at least scanning will work.
1515 homeOutDir
= args
[3];
1516 startOutDir
= args
[3];
1520 // Create a local generator configured for the directory in
1521 // which dependencies will be scanned.
1522 homeDir
= cmSystemTools::CollapseFullPath(homeDir
.c_str());
1523 startDir
= cmSystemTools::CollapseFullPath(startDir
.c_str());
1524 homeOutDir
= cmSystemTools::CollapseFullPath(homeOutDir
.c_str());
1525 startOutDir
= cmSystemTools::CollapseFullPath(startOutDir
.c_str());
1526 cm
.SetHomeDirectory(homeDir
.c_str());
1527 cm
.SetStartDirectory(startDir
.c_str());
1528 cm
.SetHomeOutputDirectory(homeOutDir
.c_str());
1529 cm
.SetStartOutputDirectory(startOutDir
.c_str());
1530 if(cmGlobalGenerator
* ggd
= cm
.CreateGlobalGenerator(gen
.c_str()))
1532 cm
.SetGlobalGenerator(ggd
);
1533 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
1534 lgd
->SetGlobalGenerator(ggd
);
1535 lgd
->GetMakefile()->SetStartDirectory(startDir
.c_str());
1536 lgd
->GetMakefile()->SetStartOutputDirectory(startOutDir
.c_str());
1537 lgd
->GetMakefile()->MakeStartDirectoriesCurrent();
1539 // Actually scan dependencies.
1540 return lgd
->UpdateDependencies(depInfo
.c_str(),
1541 verbose
, color
)? 0 : 2;
1546 // Internal CMake link script support.
1547 else if (args
[1] == "cmake_link_script" && args
.size() >= 3)
1549 return cmake::ExecuteLinkScript(args
);
1552 // Internal CMake unimplemented feature notification.
1553 else if (args
[1] == "cmake_unimplemented_variable")
1555 std::cerr
<< "Feature not implemented for this platform.";
1556 if(args
.size() == 3)
1558 std::cerr
<< " Variable " << args
[2] << " is not set.";
1560 std::cerr
<< std::endl
;
1563 else if (args
[1] == "vs_link_exe")
1565 return cmake::VisualStudioLink(args
, 1);
1567 else if (args
[1] == "vs_link_dll")
1569 return cmake::VisualStudioLink(args
, 2);
1571 #ifdef CMAKE_BUILD_WITH_CMAKE
1572 // Internal CMake color makefile support.
1573 else if (args
[1] == "cmake_echo_color")
1575 return cmake::ExecuteEchoColor(args
);
1580 else if (args
[1] == "tar" && args
.size() > 3)
1582 std::string flags
= args
[2];
1583 std::string outFile
= args
[3];
1584 std::vector
<cmStdString
> files
;
1585 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1587 files
.push_back(args
[cc
]);
1590 bool verbose
= false;
1591 if ( flags
.find_first_of('z') != flags
.npos
)
1595 if ( flags
.find_first_of('v') != flags
.npos
)
1600 if ( flags
.find_first_of('t') != flags
.npos
)
1602 if ( !cmSystemTools::ListTar(outFile
.c_str(), files
, gzip
, verbose
) )
1604 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1608 else if ( flags
.find_first_of('c') != flags
.npos
)
1610 if ( !cmSystemTools::CreateTar(
1611 outFile
.c_str(), files
, gzip
, verbose
) )
1613 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1617 else if ( flags
.find_first_of('x') != flags
.npos
)
1619 if ( !cmSystemTools::ExtractTar(
1620 outFile
.c_str(), files
, gzip
, verbose
) )
1622 cmSystemTools::Error("Problem extracting tar: ", outFile
.c_str());
1629 #if defined(CMAKE_BUILD_WITH_CMAKE)
1630 // Internal CMake Fortran module support.
1631 else if (args
[1] == "cmake_copy_f90_mod" && args
.size() >= 4)
1633 return cmDependsFortran::CopyModule(args
)? 0 : 1;
1637 #if defined(_WIN32) && !defined(__CYGWIN__)
1638 // Write registry value
1639 else if (args
[1] == "write_regv" && args
.size() > 3)
1641 return cmSystemTools::WriteRegistryValue(args
[2].c_str(),
1642 args
[3].c_str()) ? 0 : 1;
1645 // Delete registry value
1646 else if (args
[1] == "delete_regv" && args
.size() > 2)
1648 return cmSystemTools::DeleteRegistryValue(args
[2].c_str()) ? 0 : 1;
1651 else if (args
[1] == "comspec" && args
.size() > 2)
1654 std::string command
= args
[2];
1655 for ( cc
= 3; cc
< args
.size(); cc
++ )
1657 command
+= " " + args
[cc
];
1659 return cmWin32ProcessExecution::Windows9xHack(command
.c_str());
1664 ::CMakeCommandUsage(args
[0].c_str());
1668 void cmake::AddExtraGenerator(const char* name
,
1669 CreateExtraGeneratorFunctionType newFunction
)
1671 cmExternalMakefileProjectGenerator
* extraGenerator
= newFunction();
1672 const std::vector
<std::string
>& supportedGlobalGenerators
=
1673 extraGenerator
->GetSupportedGlobalGenerators();
1675 for(std::vector
<std::string
>::const_iterator
1676 it
= supportedGlobalGenerators
.begin();
1677 it
!= supportedGlobalGenerators
.end();
1680 std::string fullName
= cmExternalMakefileProjectGenerator::
1681 CreateFullGeneratorName(it
->c_str(), name
);
1682 this->ExtraGenerators
[fullName
.c_str()] = newFunction
;
1684 delete extraGenerator
;
1687 void cmake::AddDefaultExtraGenerators()
1689 #if defined(CMAKE_BUILD_WITH_CMAKE)
1690 #if defined(_WIN32) && !defined(__CYGWIN__)
1694 #if !defined(__CYGWIN__)
1695 this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
1696 &cmExtraCodeBlocksGenerator::New
);
1699 #ifdef CMAKE_USE_ECLIPSE
1700 this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
1701 &cmExtraEclipseCDT4Generator::New
);
1704 #ifdef CMAKE_USE_KDEVELOP
1705 this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
1706 &cmGlobalKdevelopGenerator::New
);
1707 // for kdevelop also add the generator with just the name of the
1708 // extra generator, since it was this way since cmake 2.2
1709 this->ExtraGenerators
[cmGlobalKdevelopGenerator::GetActualName()]
1710 = &cmGlobalKdevelopGenerator::New
;
1717 //----------------------------------------------------------------------------
1718 void cmake::GetRegisteredGenerators(std::vector
<std::string
>& names
)
1720 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
1721 i
!= this->Generators
.end(); ++i
)
1723 names
.push_back(i
->first
);
1725 for(RegisteredExtraGeneratorsMap::const_iterator
1726 i
= this->ExtraGenerators
.begin();
1727 i
!= this->ExtraGenerators
.end(); ++i
)
1729 names
.push_back(i
->first
);
1733 cmGlobalGenerator
* cmake::CreateGlobalGenerator(const char* name
)
1735 cmGlobalGenerator
* generator
= 0;
1736 cmExternalMakefileProjectGenerator
* extraGenerator
= 0;
1737 RegisteredGeneratorsMap::const_iterator genIt
= this->Generators
.find(name
);
1738 if(genIt
== this->Generators
.end())
1740 RegisteredExtraGeneratorsMap::const_iterator extraGenIt
=
1741 this->ExtraGenerators
.find(name
);
1742 if (extraGenIt
== this->ExtraGenerators
.end())
1746 extraGenerator
= (extraGenIt
->second
)();
1747 genIt
=this->Generators
.find(extraGenerator
->GetGlobalGeneratorName(name
));
1748 if(genIt
== this->Generators
.end())
1750 delete extraGenerator
;
1755 generator
= (genIt
->second
)();
1756 generator
->SetCMakeInstance(this);
1757 generator
->SetExternalMakefileProjectGenerator(extraGenerator
);
1761 void cmake::SetHomeDirectory(const char* dir
)
1763 this->cmHomeDirectory
= dir
;
1764 cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory
);
1767 void cmake::SetHomeOutputDirectory(const char* lib
)
1769 this->HomeOutputDirectory
= lib
;
1770 cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory
);
1773 void cmake::SetGlobalGenerator(cmGlobalGenerator
*gg
)
1777 cmSystemTools::Error("Error SetGlobalGenerator called with null");
1780 // delete the old generator
1781 if (this->GlobalGenerator
)
1783 delete this->GlobalGenerator
;
1784 // restore the original environment variables CXX and CC
1786 std::string env
= "CC=";
1787 if(this->CCEnvironment
.size())
1789 env
+= this->CCEnvironment
;
1791 cmSystemTools::PutEnv(env
.c_str());
1793 if(this->CXXEnvironment
.size())
1795 env
+= this->CXXEnvironment
;
1797 cmSystemTools::PutEnv(env
.c_str());
1801 this->GlobalGenerator
= gg
;
1803 // set the global flag for unix style paths on cmSystemTools as soon as
1804 // the generator is set. This allows gmake to be used on windows.
1805 cmSystemTools::SetForceUnixPaths
1806 (this->GlobalGenerator
->GetForceUnixPaths());
1808 // Save the environment variables CXX and CC
1809 const char* cxx
= getenv("CXX");
1810 const char* cc
= getenv("CC");
1813 this->CXXEnvironment
= cxx
;
1817 this->CXXEnvironment
= "";
1821 this->CCEnvironment
= cc
;
1825 this->CCEnvironment
= "";
1827 // set the cmake instance just to be sure
1828 gg
->SetCMakeInstance(this);
1831 int cmake::DoPreConfigureChecks()
1833 // Make sure the Start directory contains a CMakeLists.txt file.
1834 std::string srcList
= this->GetHomeDirectory();
1835 srcList
+= "/CMakeLists.txt";
1836 if(!cmSystemTools::FileExists(srcList
.c_str()))
1838 cmOStringStream err
;
1839 if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
1841 err
<< "The source directory \"" << this->GetHomeDirectory()
1842 << "\" does not appear to contain CMakeLists.txt.\n";
1844 else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
1846 err
<< "The source directory \"" << this->GetHomeDirectory()
1847 << "\" is a file, not a directory.\n";
1851 err
<< "The source directory \"" << this->GetHomeDirectory()
1852 << "\" does not exist.\n";
1854 err
<< "Specify --help for usage, or press the help button on the CMake "
1856 cmSystemTools::Error(err
.str().c_str());
1860 // do a sanity check on some values
1861 if(this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY"))
1863 std::string cacheStart
=
1864 this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY");
1865 cacheStart
+= "/CMakeLists.txt";
1866 std::string currentStart
= this->GetHomeDirectory();
1867 currentStart
+= "/CMakeLists.txt";
1868 if(!cmSystemTools::SameFile(cacheStart
.c_str(), currentStart
.c_str()))
1870 std::string message
= "The source \"";
1871 message
+= currentStart
;
1872 message
+= "\" does not match the source \"";
1873 message
+= cacheStart
;
1874 message
+= "\" used to generate cache. ";
1875 message
+= "Re-run cmake with a different source directory.";
1876 cmSystemTools::Error(message
.c_str());
1886 struct SaveCacheEntry
1891 cmCacheManager::CacheEntryType type
;
1894 int cmake::HandleDeleteCacheVariables(const char* var
)
1896 std::vector
<std::string
> argsSplit
;
1897 cmSystemTools::ExpandListArgument(std::string(var
), argsSplit
);
1898 // erase the property to avoid infinite recursion
1899 this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
1900 if(this->GetIsInTryCompile())
1904 cmCacheManager::CacheIterator ci
= this->CacheManager
->NewIterator();
1905 std::vector
<SaveCacheEntry
> saved
;
1906 cmOStringStream warning
;
1908 << "You have changed variables that require your cache to be deleted.\n"
1909 << "Configure will be re-run and you may have to reset some variables.\n"
1910 << "The following variables have changed:\n";
1911 for(std::vector
<std::string
>::iterator i
= argsSplit
.begin();
1912 i
!= argsSplit
.end(); ++i
)
1914 SaveCacheEntry save
;
1916 warning
<< *i
<< "= ";
1919 warning
<< *i
<< "\n";
1920 if(ci
.Find(save
.key
.c_str()))
1922 save
.type
= ci
.GetType();
1923 save
.help
= ci
.GetProperty("HELPSTRING");
1925 saved
.push_back(save
);
1929 this->CacheManager
->DeleteCache(this->GetStartOutputDirectory());
1930 // load the empty cache
1932 // restore the changed compilers
1933 for(std::vector
<SaveCacheEntry
>::iterator i
= saved
.begin();
1934 i
!= saved
.end(); ++i
)
1936 this->AddCacheEntry(i
->key
.c_str(), i
->value
.c_str(),
1937 i
->help
.c_str(), i
->type
);
1939 cmSystemTools::Message(warning
.str().c_str());
1940 // avoid reconfigure if there were errors
1941 if(!cmSystemTools::GetErrorOccuredFlag())
1944 return this->Configure();
1949 int cmake::Configure()
1951 if(this->DoSuppressDevWarnings
)
1953 if(this->SuppressDevWarnings
)
1955 this->CacheManager
->
1956 AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE",
1957 "Suppress Warnings that are meant for"
1958 " the author of the CMakeLists.txt files.",
1959 cmCacheManager::INTERNAL
);
1963 this->CacheManager
->
1964 AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE",
1965 "Suppress Warnings that are meant for"
1966 " the author of the CMakeLists.txt files.",
1967 cmCacheManager::INTERNAL
);
1970 int ret
= this->ActualConfigure();
1971 const char* delCacheVars
=
1972 this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
1973 if(delCacheVars
&& delCacheVars
[0] != 0)
1975 return this->HandleDeleteCacheVariables(delCacheVars
);
1981 int cmake::ActualConfigure()
1983 // Construct right now our path conversion table before it's too late:
1984 this->UpdateConversionPathTable();
1985 this->CleanupCommandsAndMacros();
1988 if ( !this->ScriptMode
)
1990 res
= this->DoPreConfigureChecks();
1998 this->CacheManager
->AddCacheEntry
1999 ("CMAKE_HOME_DIRECTORY",
2000 this->GetHomeDirectory(),
2001 "Start directory with the top level CMakeLists.txt file for this "
2003 cmCacheManager::INTERNAL
);
2006 // no generator specified on the command line
2007 if(!this->GlobalGenerator
)
2009 const char* genName
=
2010 this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
2011 const char* extraGenName
=
2012 this->CacheManager
->GetCacheValue("CMAKE_EXTRA_GENERATOR");
2015 std::string fullName
= cmExternalMakefileProjectGenerator::
2016 CreateFullGeneratorName(genName
, extraGenName
);
2017 this->GlobalGenerator
= this->CreateGlobalGenerator(fullName
.c_str());
2019 if(this->GlobalGenerator
)
2021 // set the global flag for unix style paths on cmSystemTools as
2022 // soon as the generator is set. This allows gmake to be used
2024 cmSystemTools::SetForceUnixPaths
2025 (this->GlobalGenerator
->GetForceUnixPaths());
2029 #if defined(__BORLANDC__) && defined(_WIN32)
2030 this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator
);
2031 #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
2032 std::string installedCompiler
;
2033 std::string mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
2034 "\\VisualStudio\\8.0\\Setup;Dbghelp_path]";
2035 cmSystemTools::ExpandRegistryValues(mp
);
2036 if (!(mp
== "/registry"))
2038 installedCompiler
= "Visual Studio 8 2005";
2042 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
2043 "\\VisualStudio\\7.1;InstallDir]";
2044 cmSystemTools::ExpandRegistryValues(mp
);
2045 if (!(mp
== "/registry"))
2047 installedCompiler
= "Visual Studio 7 .NET 2003";
2051 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
2052 "\\VisualStudio\\7.0;InstallDir]";
2053 cmSystemTools::ExpandRegistryValues(mp
);
2054 if (!(mp
== "/registry"))
2056 installedCompiler
= "Visual Studio 7";
2060 installedCompiler
= "Visual Studio 6";
2064 cmGlobalGenerator
* gen
2065 = this->CreateGlobalGenerator(installedCompiler
.c_str());
2068 gen
= new cmGlobalNMakeMakefileGenerator
;
2070 this->SetGlobalGenerator(gen
);
2072 this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3
);
2075 if(!this->GlobalGenerator
)
2077 cmSystemTools::Error("Could not create generator");
2082 const char* genName
= this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
2085 if(strcmp(this->GlobalGenerator
->GetName(), genName
) != 0)
2087 std::string message
= "Error: generator : ";
2088 message
+= this->GlobalGenerator
->GetName();
2089 message
+= "\nDoes not match the generator used previously: ";
2092 "\nEither remove the CMakeCache.txt file or choose a different"
2093 " binary directory.";
2094 cmSystemTools::Error(message
.c_str());
2098 if(!this->CacheManager
->GetCacheValue("CMAKE_GENERATOR"))
2100 this->CacheManager
->AddCacheEntry("CMAKE_GENERATOR",
2101 this->GlobalGenerator
->GetName(),
2102 "Name of generator.",
2103 cmCacheManager::INTERNAL
);
2104 this->CacheManager
->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
2105 this->GlobalGenerator
->GetExtraGeneratorName(),
2106 "Name of external makefile project generator.",
2107 cmCacheManager::INTERNAL
);
2110 // reset any system configuration information, except for when we are
2111 // InTryCompile. With TryCompile the system info is taken from the parent's
2112 // info to save time
2113 if (!this->InTryCompile
)
2115 this->GlobalGenerator
->ClearEnabledLanguages();
2118 // Truncate log files
2119 if (!this->InTryCompile
)
2121 this->TruncateOutputLog("CMakeOutput.log");
2122 this->TruncateOutputLog("CMakeError.log");
2125 // actually do the configure
2126 this->GlobalGenerator
->Configure();
2127 // Before saving the cache
2128 // if the project did not define one of the entries below, add them now
2129 // so users can edit the values in the cache:
2131 // We used to always present LIBRARY_OUTPUT_PATH and
2132 // EXECUTABLE_OUTPUT_PATH. They are now documented as old-style and
2133 // should no longer be used. Therefore we present them only if the
2134 // project requires compatibility with CMake 2.4. We detect this
2135 // here by looking for the old CMAKE_BACKWARDS_COMPATABILITY
2136 // variable created when CMP0001 is not set to NEW.
2137 if(this->GetCacheManager()->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
2139 if(!this->CacheManager
->GetCacheValue("LIBRARY_OUTPUT_PATH"))
2141 this->CacheManager
->AddCacheEntry
2142 ("LIBRARY_OUTPUT_PATH", "",
2143 "Single output directory for building all libraries.",
2144 cmCacheManager::PATH
);
2146 if(!this->CacheManager
->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
2148 this->CacheManager
->AddCacheEntry
2149 ("EXECUTABLE_OUTPUT_PATH", "",
2150 "Single output directory for building all executables.",
2151 cmCacheManager::PATH
);
2154 if(!this->CacheManager
->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
2156 this->CacheManager
->AddCacheEntry
2157 ("CMAKE_USE_RELATIVE_PATHS", false,
2158 "If true, cmake will use relative paths in makefiles and projects.");
2159 cmCacheManager::CacheIterator it
=
2160 this->CacheManager
->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
2161 if ( !it
.PropertyExists("ADVANCED") )
2163 it
.SetProperty("ADVANCED", "1");
2167 if(cmSystemTools::GetFatalErrorOccured() &&
2168 (!this->CacheManager
->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
2169 cmSystemTools::IsOff(this->CacheManager
->
2170 GetCacheValue("CMAKE_MAKE_PROGRAM"))))
2172 // We must have a bad generator selection. Wipe the cache entry so the
2173 // user can select another.
2174 this->CacheManager
->RemoveCacheEntry("CMAKE_GENERATOR");
2175 this->CacheManager
->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
2177 // only save the cache if there were no fatal errors
2178 if ( !this->ScriptMode
)
2180 this->CacheManager
->SaveCache(this->GetHomeOutputDirectory());
2182 if ( !this->GraphVizFile
.empty() )
2184 std::cout
<< "Generate graphviz: " << this->GraphVizFile
<< std::endl
;
2185 this->GenerateGraphViz(this->GraphVizFile
.c_str());
2187 if(cmSystemTools::GetErrorOccuredFlag())
2194 void cmake::PreLoadCMakeFiles()
2196 std::string pre_load
= this->GetHomeDirectory();
2197 if ( pre_load
.size() > 0 )
2199 pre_load
+= "/PreLoad.cmake";
2200 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2202 this->ReadListFile(pre_load
.c_str());
2205 pre_load
= this->GetHomeOutputDirectory();
2206 if ( pre_load
.size() > 0 )
2208 pre_load
+= "/PreLoad.cmake";
2209 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2211 this->ReadListFile(pre_load
.c_str());
2216 // handle a command line invocation
2217 int cmake::Run(const std::vector
<std::string
>& args
, bool noconfigure
)
2219 // Process the arguments
2220 this->SetArgs(args
);
2221 if(cmSystemTools::GetErrorOccuredFlag())
2226 // If we are given a stamp list file check if it is really out of date.
2227 if(!this->CheckStampList
.empty() &&
2228 cmakeCheckStampList(this->CheckStampList
.c_str()))
2233 // If we are given a stamp file check if it is really out of date.
2234 if(!this->CheckStampFile
.empty() &&
2235 cmakeCheckStampFile(this->CheckStampFile
.c_str()))
2240 // set the cmake command
2241 this->CMakeCommand
= args
[0];
2243 if ( !this->ScriptMode
)
2246 if(this->LoadCache() < 0)
2248 cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
2254 this->AddCMakePaths();
2256 // Add any cache args
2257 if ( !this->SetCacheArgs(args
) )
2259 cmSystemTools::Error("Problem processing arguments. Aborting.\n");
2263 // In script mode we terminate after running the script.
2264 if(this->ScriptMode
)
2266 if(cmSystemTools::GetErrorOccuredFlag())
2276 this->PreLoadCMakeFiles();
2278 std::string systemFile
= this->GetHomeOutputDirectory();
2279 systemFile
+= "/CMakeSystem.cmake";
2286 // now run the global generate
2287 // Check the state of the build system to see if we need to regenerate.
2288 if(!this->CheckBuildSystem())
2293 // If we are doing global generate, we better set start and start
2294 // output directory to the root of the project.
2295 std::string oldstartdir
= this->GetStartDirectory();
2296 std::string oldstartoutputdir
= this->GetStartOutputDirectory();
2297 this->SetStartDirectory(this->GetHomeDirectory());
2298 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
2299 int ret
= this->Configure();
2300 if (ret
|| this->ScriptMode
)
2302 #if defined(CMAKE_HAVE_VS_GENERATORS)
2303 if(!this->VSSolutionFile
.empty() && this->GlobalGenerator
)
2305 // CMake is running to regenerate a Visual Studio build tree
2306 // during a build from the VS IDE. The build files cannot be
2307 // regenerated, so we should stop the build.
2308 cmSystemTools::Message(
2309 "CMake Configure step failed. "
2310 "Build files cannot be regenerated correctly. "
2311 "Attempting to stop IDE build.");
2312 cmGlobalVisualStudioGenerator
* gg
=
2313 static_cast<cmGlobalVisualStudioGenerator
*>(this->GlobalGenerator
);
2314 gg
->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop
,
2315 this->VSSolutionFile
.c_str());
2320 ret
= this->Generate();
2321 std::string message
= "Build files have been written to: ";
2322 message
+= this->GetHomeOutputDirectory();
2323 this->UpdateProgress(message
.c_str(), -1);
2328 this->SetStartDirectory(oldstartdir
.c_str());
2329 this->SetStartOutputDirectory(oldstartoutputdir
.c_str());
2334 int cmake::Generate()
2336 if(!this->GlobalGenerator
)
2340 this->GlobalGenerator
->Generate();
2341 if(cmSystemTools::GetErrorOccuredFlag())
2345 if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
2347 this->ReportUndefinedPropertyAccesses
2348 (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
2353 void cmake::AddCacheEntry(const char* key
, const char* value
,
2354 const char* helpString
,
2357 this->CacheManager
->AddCacheEntry(key
, value
,
2359 cmCacheManager::CacheEntryType(type
));
2362 const char* cmake::GetCacheDefinition(const char* name
) const
2364 return this->CacheManager
->GetCacheValue(name
);
2367 int cmake::DumpDocumentationToFile(std::ostream
& f
)
2369 #ifdef CMAKE_BUILD_WITH_CMAKE
2370 // Loop over all registered commands and print out documentation
2375 sprintf(tmp
,"Version %s", cmVersion::GetCMakeVersion());
2377 f
<< "<h1>Documentation for commands of CMake " << tmp
<< "</h1>\n";
2379 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
2380 j
!= this->Commands
.end(); ++j
)
2382 name
= (*j
).second
->GetName();
2383 terse
= (*j
).second
->GetTerseDocumentation();
2384 full
= (*j
).second
->GetFullDocumentation();
2385 f
<< "<li><b>" << name
<< "</b> - " << terse
<< std::endl
2386 << "<br><i>Usage:</i> " << full
<< "</li>" << std::endl
<< std::endl
;
2388 f
<< "</ul></html>\n";
2395 void cmake::AddDefaultCommands()
2397 std::list
<cmCommand
*> commands
;
2398 GetBootstrapCommands(commands
);
2399 GetPredefinedCommands(commands
);
2400 for(std::list
<cmCommand
*>::iterator i
= commands
.begin();
2401 i
!= commands
.end(); ++i
)
2403 this->AddCommand(*i
);
2407 void cmake::AddDefaultGenerators()
2409 #if defined(_WIN32) && !defined(__CYGWIN__)
2410 # if !defined(CMAKE_BOOT_MINGW)
2411 this->Generators
[cmGlobalVisualStudio6Generator::GetActualName()] =
2412 &cmGlobalVisualStudio6Generator::New
;
2413 this->Generators
[cmGlobalVisualStudio7Generator::GetActualName()] =
2414 &cmGlobalVisualStudio7Generator::New
;
2415 this->Generators
[cmGlobalVisualStudio71Generator::GetActualName()] =
2416 &cmGlobalVisualStudio71Generator::New
;
2417 this->Generators
[cmGlobalVisualStudio8Generator::GetActualName()] =
2418 &cmGlobalVisualStudio8Generator::New
;
2419 this->Generators
[cmGlobalVisualStudio9Generator::GetActualName()] =
2420 &cmGlobalVisualStudio9Generator::New
;
2421 this->Generators
[cmGlobalVisualStudio9Win64Generator::GetActualName()] =
2422 &cmGlobalVisualStudio9Win64Generator::New
;
2423 this->Generators
[cmGlobalVisualStudio8Win64Generator::GetActualName()] =
2424 &cmGlobalVisualStudio8Win64Generator::New
;
2425 this->Generators
[cmGlobalBorlandMakefileGenerator::GetActualName()] =
2426 &cmGlobalBorlandMakefileGenerator::New
;
2427 this->Generators
[cmGlobalNMakeMakefileGenerator::GetActualName()] =
2428 &cmGlobalNMakeMakefileGenerator::New
;
2429 this->Generators
[cmGlobalWatcomWMakeGenerator::GetActualName()] =
2430 &cmGlobalWatcomWMakeGenerator::New
;
2432 this->Generators
[cmGlobalMSYSMakefileGenerator::GetActualName()] =
2433 &cmGlobalMSYSMakefileGenerator::New
;
2434 this->Generators
[cmGlobalMinGWMakefileGenerator::GetActualName()] =
2435 &cmGlobalMinGWMakefileGenerator::New
;
2437 this->Generators
[cmGlobalUnixMakefileGenerator3::GetActualName()] =
2438 &cmGlobalUnixMakefileGenerator3::New
;
2439 #ifdef CMAKE_USE_XCODE
2440 this->Generators
[cmGlobalXCodeGenerator::GetActualName()] =
2441 &cmGlobalXCodeGenerator::New
;
2445 int cmake::LoadCache()
2447 // could we not read the cache
2448 if (!this->CacheManager
->LoadCache(this->GetHomeOutputDirectory()))
2450 // if it does exist, but isn;t readable then warn the user
2451 std::string cacheFile
= this->GetHomeOutputDirectory();
2452 cacheFile
+= "/CMakeCache.txt";
2453 if(cmSystemTools::FileExists(cacheFile
.c_str()))
2455 cmSystemTools::Error(
2456 "There is a CMakeCache.txt file for the current binary tree but "
2457 "cmake does not have permission to read it. Please check the "
2458 "permissions of the directory you are trying to run CMake on.");
2463 if (this->CMakeCommand
.size() < 2)
2465 cmSystemTools::Error(
2466 "cmake command was not specified prior to loading the cache in "
2471 // setup CMAKE_ROOT and CMAKE_COMMAND
2472 if(!this->AddCMakePaths())
2479 void cmake::SetProgressCallback(ProgressCallbackType f
, void *cd
)
2481 this->ProgressCallback
= f
;
2482 this->ProgressCallbackClientData
= cd
;
2485 void cmake::UpdateProgress(const char *msg
, float prog
)
2487 if(this->ProgressCallback
&& !this->InTryCompile
)
2489 (*this->ProgressCallback
)(msg
, prog
, this->ProgressCallbackClientData
);
2494 void cmake::GetCommandDocumentation(std::vector
<cmDocumentationEntry
>& v
,
2495 bool withCurrentCommands
,
2496 bool withCompatCommands
) const
2498 for(RegisteredCommandsMap::const_iterator j
= this->Commands
.begin();
2499 j
!= this->Commands
.end(); ++j
)
2501 if ((( withCompatCommands
== false) && ( (*j
).second
->IsDiscouraged()))
2502 || ((withCurrentCommands
== false) && (!(*j
).second
->IsDiscouraged())))
2507 cmDocumentationEntry
e((*j
).second
->GetName(),
2508 (*j
).second
->GetTerseDocumentation(),
2509 (*j
).second
->GetFullDocumentation());
2514 void cmake::GetPolicyDocumentation(std::vector
<cmDocumentationEntry
>& v
)
2516 this->Policies
->GetDocumentation(v
);
2519 void cmake::GetPropertiesDocumentation(std::map
<std::string
,
2520 cmDocumentationSection
*>& v
)
2522 // loop over the properties and put them into the doc structure
2523 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
2524 i
= this->PropertyDefinitions
.begin();
2525 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
2527 i
->second
.GetPropertiesDocumentation(v
);
2531 void cmake::GetGeneratorDocumentation(std::vector
<cmDocumentationEntry
>& v
)
2533 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
2534 i
!= this->Generators
.end(); ++i
)
2536 cmDocumentationEntry e
;
2537 cmGlobalGenerator
* generator
= (i
->second
)();
2538 generator
->GetDocumentation(e
);
2542 for(RegisteredExtraGeneratorsMap::const_iterator
2543 i
= this->ExtraGenerators
.begin(); i
!= this->ExtraGenerators
.end(); ++i
)
2545 cmDocumentationEntry e
;
2546 cmExternalMakefileProjectGenerator
* generator
= (i
->second
)();
2547 generator
->GetDocumentation(e
, i
->first
.c_str());
2554 void cmake::UpdateConversionPathTable()
2556 // Update the path conversion table with any specified file:
2557 const char* tablepath
=
2558 this->CacheManager
->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
2562 std::ifstream
table( tablepath
);
2565 cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath
,
2566 ". CMake can not open file.");
2567 cmSystemTools::ReportLastSystemError("CMake can not open file.");
2574 // two entries per line
2575 table
>> a
; table
>> b
;
2576 cmSystemTools::AddTranslationPath( a
.c_str(), b
.c_str());
2582 //----------------------------------------------------------------------------
2583 int cmake::CheckBuildSystem()
2585 // We do not need to rerun CMake. Check dependency integrity. Use
2586 // the make system's VERBOSE environment variable to enable verbose
2588 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
2590 // This method will check the integrity of the build system if the
2591 // option was given on the command line. It reads the given file to
2592 // determine whether CMake should rerun.
2594 // If no file is provided for the check, we have to rerun.
2595 if(this->CheckBuildSystemArgument
.size() == 0)
2599 cmOStringStream msg
;
2600 msg
<< "Re-run cmake no build system arguments\n";
2601 cmSystemTools::Stdout(msg
.str().c_str());
2606 // If the file provided does not exist, we have to rerun.
2607 if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument
.c_str()))
2611 cmOStringStream msg
;
2612 msg
<< "Re-run cmake missing file: "
2613 << this->CheckBuildSystemArgument
.c_str() << "\n";
2614 cmSystemTools::Stdout(msg
.str().c_str());
2619 // Read the rerun check file and use it to decide whether to do the
2622 cmGlobalGenerator gg
;
2623 gg
.SetCMakeInstance(&cm
);
2624 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
2625 lg
->SetGlobalGenerator(&gg
);
2626 cmMakefile
* mf
= lg
->GetMakefile();
2627 if(!mf
->ReadListFile(0, this->CheckBuildSystemArgument
.c_str()) ||
2628 cmSystemTools::GetErrorOccuredFlag())
2632 cmOStringStream msg
;
2633 msg
<< "Re-run cmake error reading : "
2634 << this->CheckBuildSystemArgument
.c_str() << "\n";
2635 cmSystemTools::Stdout(msg
.str().c_str());
2637 // There was an error reading the file. Just rerun.
2641 if(this->ClearBuildSystem
)
2643 // Get the generator used for this build system.
2644 const char* genName
= mf
->GetDefinition("CMAKE_DEPENDS_GENERATOR");
2645 if(!genName
|| genName
[0] == '\0')
2647 genName
= "Unix Makefiles";
2650 // Create the generator and use it to clear the dependencies.
2651 std::auto_ptr
<cmGlobalGenerator
>
2652 ggd(this->CreateGlobalGenerator(genName
));
2655 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
2656 lgd
->SetGlobalGenerator(ggd
.get());
2657 lgd
->ClearDependencies(mf
, verbose
);
2661 // If any byproduct of makefile generation is missing we must re-run.
2662 std::vector
<std::string
> products
;
2663 if(const char* productStr
= mf
->GetDefinition("CMAKE_MAKEFILE_PRODUCTS"))
2665 cmSystemTools::ExpandListArgument(productStr
, products
);
2667 for(std::vector
<std::string
>::const_iterator pi
= products
.begin();
2668 pi
!= products
.end(); ++pi
)
2670 if(!(cmSystemTools::FileExists(pi
->c_str()) ||
2671 cmSystemTools::FileIsSymlink(pi
->c_str())))
2675 cmOStringStream msg
;
2676 msg
<< "Re-run cmake, missing byproduct: " << *pi
<< "\n";
2677 cmSystemTools::Stdout(msg
.str().c_str());
2683 // Get the set of dependencies and outputs.
2684 std::vector
<std::string
> depends
;
2685 std::vector
<std::string
> outputs
;
2686 const char* dependsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
2687 const char* outputsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
2688 if(dependsStr
&& outputsStr
)
2690 cmSystemTools::ExpandListArgument(dependsStr
, depends
);
2691 cmSystemTools::ExpandListArgument(outputsStr
, outputs
);
2693 if(depends
.empty() || outputs
.empty())
2695 // Not enough information was provided to do the test. Just rerun.
2698 cmOStringStream msg
;
2699 msg
<< "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
2700 "or CMAKE_MAKEFILE_OUTPUTS :\n";
2701 cmSystemTools::Stdout(msg
.str().c_str());
2706 // Find find the newest dependency.
2707 std::vector
<std::string
>::iterator dep
= depends
.begin();
2708 std::string dep_newest
= *dep
++;
2709 for(;dep
!= depends
.end(); ++dep
)
2712 if(this->FileComparison
->FileTimeCompare(dep_newest
.c_str(),
2713 dep
->c_str(), &result
))
2724 cmOStringStream msg
;
2725 msg
<< "Re-run cmake: build system dependency is missing\n";
2726 cmSystemTools::Stdout(msg
.str().c_str());
2732 // Find find the oldest output.
2733 std::vector
<std::string
>::iterator out
= outputs
.begin();
2734 std::string out_oldest
= *out
++;
2735 for(;out
!= outputs
.end(); ++out
)
2738 if(this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2739 out
->c_str(), &result
))
2750 cmOStringStream msg
;
2751 msg
<< "Re-run cmake: build system output is missing\n";
2752 cmSystemTools::Stdout(msg
.str().c_str());
2758 // If any output is older than any dependency then rerun.
2761 if(!this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2768 cmOStringStream msg
;
2769 msg
<< "Re-run cmake file: " << out_oldest
.c_str()
2770 << " older than: " << dep_newest
.c_str() << "\n";
2771 cmSystemTools::Stdout(msg
.str().c_str());
2777 // No need to rerun.
2781 //----------------------------------------------------------------------------
2782 void cmake::TruncateOutputLog(const char* fname
)
2784 std::string fullPath
= this->GetHomeOutputDirectory();
2788 if ( ::stat(fullPath
.c_str(), &st
) )
2792 if ( !this->CacheManager
->GetCacheValue("CMAKE_CACHEFILE_DIR") )
2794 cmSystemTools::RemoveFile(fullPath
.c_str());
2797 off_t fsize
= st
.st_size
;
2798 const off_t maxFileSize
= 50 * 1024;
2799 if ( fsize
< maxFileSize
)
2801 //TODO: truncate file
2806 inline std::string
removeQuotes(const std::string
& s
)
2808 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
2810 return s
.substr(1, s
.size()-2);
2815 std::string
cmake::FindCMakeProgram(const char* name
) const
2818 if ((name
) && (*name
))
2820 const cmMakefile
* mf
2821 = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
2822 #ifdef CMAKE_BUILD_WITH_CMAKE
2823 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2824 path
= removeQuotes(path
);
2825 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2828 path
+= cmSystemTools::GetExecutableExtension();
2829 if(!cmSystemTools::FileExists(path
.c_str()))
2831 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2832 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2835 path
+= cmSystemTools::GetExecutableExtension();
2837 if(!cmSystemTools::FileExists(path
.c_str()))
2839 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2840 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2841 path
+= "/Release/";
2843 path
+= cmSystemTools::GetExecutableExtension();
2846 // Only for bootstrap
2847 path
+= mf
->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
2850 path
+= cmSystemTools::GetExecutableExtension();
2856 const char* cmake::GetCTestCommand()
2858 if ( this->CTestCommand
.empty() )
2860 this->CTestCommand
= this->FindCMakeProgram("ctest");
2862 if ( this->CTestCommand
.empty() )
2864 cmSystemTools::Error("Cannot find the CTest executable");
2865 this->CTestCommand
= "CTEST-COMMAND-NOT-FOUND";
2867 return this->CTestCommand
.c_str();
2870 const char* cmake::GetCPackCommand()
2872 if ( this->CPackCommand
.empty() )
2874 this->CPackCommand
= this->FindCMakeProgram("cpack");
2876 if ( this->CPackCommand
.empty() )
2878 cmSystemTools::Error("Cannot find the CPack executable");
2879 this->CPackCommand
= "CPACK-COMMAND-NOT-FOUND";
2881 return this->CPackCommand
.c_str();
2884 void cmake::GenerateGraphViz(const char* fileName
) const
2886 cmGeneratedFileStream
str(fileName
);
2892 cmGlobalGenerator ggi
;
2893 ggi
.SetCMakeInstance(&cm
);
2894 std::auto_ptr
<cmLocalGenerator
> lg(ggi
.CreateLocalGenerator());
2895 lg
->SetGlobalGenerator(&ggi
);
2896 cmMakefile
*mf
= lg
->GetMakefile();
2898 std::string infile
= this->GetHomeOutputDirectory();
2899 infile
+= "/CMakeGraphVizOptions.cmake";
2900 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2902 infile
= this->GetHomeDirectory();
2903 infile
+= "/CMakeGraphVizOptions.cmake";
2904 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2910 if ( !infile
.empty() )
2912 if ( !mf
->ReadListFile(0, infile
.c_str()) )
2914 cmSystemTools::Error("Problem opening GraphViz options file: ",
2918 std::cout
<< "Read GraphViz options file: " << infile
.c_str()
2922 #define __set_if_not_set(var, value, cmakeDefinition) \
2923 const char* var = mf->GetDefinition(cmakeDefinition); \
2928 __set_if_not_set(graphType
, "digraph", "GRAPHVIZ_GRAPH_TYPE");
2929 __set_if_not_set(graphName
, "GG", "GRAPHVIZ_GRAPH_NAME");
2930 __set_if_not_set(graphHeader
, "node [\n fontsize = \"12\"\n];",
2931 "GRAPHVIZ_GRAPH_HEADER");
2932 __set_if_not_set(graphNodePrefix
, "node", "GRAPHVIZ_NODE_PREFIX");
2933 const char* ignoreTargets
= mf
->GetDefinition("GRAPHVIZ_IGNORE_TARGETS");
2934 std::set
<cmStdString
> ignoreTargetsSet
;
2935 if ( ignoreTargets
)
2937 std::vector
<std::string
> ignoreTargetsVector
;
2938 cmSystemTools::ExpandListArgument(ignoreTargets
,ignoreTargetsVector
);
2939 std::vector
<std::string
>::iterator itvIt
;
2940 for ( itvIt
= ignoreTargetsVector
.begin();
2941 itvIt
!= ignoreTargetsVector
.end();
2944 ignoreTargetsSet
.insert(itvIt
->c_str());
2948 str
<< graphType
<< " " << graphName
<< " {" << std::endl
;
2949 str
<< graphHeader
<< std::endl
;
2951 const cmGlobalGenerator
* gg
= this->GetGlobalGenerator();
2952 const std::vector
<cmLocalGenerator
*>& localGenerators
=
2953 gg
->GetLocalGenerators();
2954 std::vector
<cmLocalGenerator
*>::const_iterator lit
;
2957 // 2 - external target
2959 std::map
<cmStdString
, int> targetDeps
;
2960 std::map
<cmStdString
, const cmTarget
*> targetPtrs
;
2961 std::map
<cmStdString
, cmStdString
> targetNamesNodes
;
2963 // First pass get the list of all cmake targets
2964 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2966 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2967 cmTargets::const_iterator tit
;
2968 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2970 const char* realTargetName
= tit
->first
.c_str();
2971 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2973 // Skip ignored targets
2976 //std::cout << "Found target: " << tit->first.c_str() << std::endl;
2977 cmOStringStream ostr
;
2978 ostr
<< graphNodePrefix
<< cnt
++;
2979 targetNamesNodes
[realTargetName
] = ostr
.str();
2980 targetPtrs
[realTargetName
] = &tit
->second
;
2983 // Ok, now find all the stuff we link to that is not in cmake
2984 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2986 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2987 cmTargets::const_iterator tit
;
2988 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2990 const cmTarget::LinkLibraryVectorType
* ll
2991 = &(tit
->second
.GetOriginalLinkLibraries());
2992 cmTarget::LinkLibraryVectorType::const_iterator llit
;
2993 const char* realTargetName
= tit
->first
.c_str();
2994 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2996 // Skip ignored targets
2999 if ( ll
->size() > 0 )
3001 targetDeps
[realTargetName
] = 1;
3003 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
3005 const char* libName
= llit
->first
.c_str();
3006 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3007 = targetNamesNodes
.find(libName
);
3008 if ( ignoreTargetsSet
.find(libName
) != ignoreTargetsSet
.end() )
3010 // Skip ignored targets
3013 if ( tarIt
== targetNamesNodes
.end() )
3015 cmOStringStream ostr
;
3016 ostr
<< graphNodePrefix
<< cnt
++;
3017 targetDeps
[libName
] = 2;
3018 targetNamesNodes
[libName
] = ostr
.str();
3019 //str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
3020 //<< "\" shape=\"ellipse\"];" << std::endl;
3024 std::map
<cmStdString
, int>::const_iterator depIt
3025 = targetDeps
.find(libName
);
3026 if ( depIt
== targetDeps
.end() )
3028 targetDeps
[libName
] = 1;
3036 std::map
<cmStdString
, int>::const_iterator depIt
;
3037 for ( depIt
= targetDeps
.begin(); depIt
!= targetDeps
.end(); ++ depIt
)
3039 const char* newTargetName
= depIt
->first
.c_str();
3040 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3041 = targetNamesNodes
.find(newTargetName
);
3042 if ( tarIt
== targetNamesNodes
.end() )
3044 // We should not be here.
3045 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
3046 << " even though it was added in the previous pass" << std::endl
;
3050 str
<< " \"" << tarIt
->second
.c_str() << "\" [ label=\""
3051 << newTargetName
<< "\" shape=\"";
3052 if ( depIt
->second
== 1 )
3054 std::map
<cmStdString
, const cmTarget
*>::const_iterator tarTypeIt
=
3055 targetPtrs
.find(newTargetName
);
3056 if ( tarTypeIt
== targetPtrs
.end() )
3058 // We should not be here.
3059 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
3060 << " even though it was added in the previous pass" << std::endl
;
3063 const cmTarget
* tg
= tarTypeIt
->second
;
3064 switch ( tg
->GetType() )
3066 case cmTarget::EXECUTABLE
:
3069 case cmTarget::STATIC_LIBRARY
:
3072 case cmTarget::SHARED_LIBRARY
:
3075 case cmTarget::MODULE_LIBRARY
:
3086 str
<< "\"];" << std::endl
;
3089 // Now generate the connectivity
3090 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
3092 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
3093 cmTargets::const_iterator tit
;
3094 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
3096 std::map
<cmStdString
, int>::iterator dependIt
3097 = targetDeps
.find(tit
->first
.c_str());
3098 if ( dependIt
== targetDeps
.end() )
3102 std::map
<cmStdString
, cmStdString
>::iterator cmakeTarIt
3103 = targetNamesNodes
.find(tit
->first
.c_str());
3104 const cmTarget::LinkLibraryVectorType
* ll
3105 = &(tit
->second
.GetOriginalLinkLibraries());
3106 cmTarget::LinkLibraryVectorType::const_iterator llit
;
3107 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
3109 const char* libName
= llit
->first
.c_str();
3110 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3111 = targetNamesNodes
.find(libName
);
3112 if ( tarIt
== targetNamesNodes
.end() )
3114 // We should not be here.
3115 std::cout
<< __LINE__
<< " Cannot find library: " << libName
3116 << " even though it was added in the previous pass" << std::endl
;
3119 str
<< " \"" << cmakeTarIt
->second
.c_str() << "\" -> \""
3120 << tarIt
->second
.c_str() << "\"" << std::endl
;
3125 // TODO: Use dotted or something for external libraries
3126 //str << " \"node0\":f4 -> \"node12\"[color=\"#0000ff\" style=dotted]"
3129 str
<< "}" << std::endl
;
3132 //----------------------------------------------------------------------------
3133 #ifdef CMAKE_BUILD_WITH_CMAKE
3134 int cmake::ExecuteEchoColor(std::vector
<std::string
>& args
)
3136 // The arguments are
3137 // argv[0] == <cmake-executable>
3138 // argv[1] == cmake_echo_color
3140 bool enabled
= true;
3141 int color
= cmsysTerminal_Color_Normal
;
3142 bool newline
= true;
3143 for(unsigned int i
=2; i
< args
.size(); ++i
)
3145 if(args
[i
].find("--switch=") == 0)
3147 // Enable or disable color based on the switch value.
3148 std::string value
= args
[i
].substr(9);
3151 if(cmSystemTools::IsOn(value
.c_str()))
3161 else if(args
[i
] == "--normal")
3163 color
= cmsysTerminal_Color_Normal
;
3165 else if(args
[i
] == "--black")
3167 color
= cmsysTerminal_Color_ForegroundBlack
;
3169 else if(args
[i
] == "--red")
3171 color
= cmsysTerminal_Color_ForegroundRed
;
3173 else if(args
[i
] == "--green")
3175 color
= cmsysTerminal_Color_ForegroundGreen
;
3177 else if(args
[i
] == "--yellow")
3179 color
= cmsysTerminal_Color_ForegroundYellow
;
3181 else if(args
[i
] == "--blue")
3183 color
= cmsysTerminal_Color_ForegroundBlue
;
3185 else if(args
[i
] == "--magenta")
3187 color
= cmsysTerminal_Color_ForegroundMagenta
;
3189 else if(args
[i
] == "--cyan")
3191 color
= cmsysTerminal_Color_ForegroundCyan
;
3193 else if(args
[i
] == "--white")
3195 color
= cmsysTerminal_Color_ForegroundWhite
;
3197 else if(args
[i
] == "--bold")
3199 color
|= cmsysTerminal_Color_ForegroundBold
;
3201 else if(args
[i
] == "--no-newline")
3205 else if(args
[i
] == "--newline")
3211 // Color is enabled. Print with the current color.
3212 cmSystemTools::MakefileColorEcho(color
, args
[i
].c_str(),
3220 int cmake::ExecuteEchoColor(std::vector
<std::string
>&)
3226 //----------------------------------------------------------------------------
3227 int cmake::ExecuteLinkScript(std::vector
<std::string
>& args
)
3229 // The arguments are
3230 // argv[0] == <cmake-executable>
3231 // argv[1] == cmake_link_script
3232 // argv[2] == <link-script-name>
3233 // argv[3] == --verbose=?
3234 bool verbose
= false;
3235 if(args
.size() >= 4)
3237 if(args
[3].find("--verbose=") == 0)
3239 if(!cmSystemTools::IsOff(args
[3].substr(10).c_str()))
3246 // Allocate a process instance.
3247 cmsysProcess
* cp
= cmsysProcess_New();
3250 std::cerr
<< "Error allocating process instance in link script."
3255 // Children should share stdout and stderr with this process.
3256 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDOUT
, 1);
3257 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDERR
, 1);
3259 // Run the command lines verbatim.
3260 cmsysProcess_SetOption(cp
, cmsysProcess_Option_Verbatim
, 1);
3262 // Read command lines from the script.
3263 std::ifstream
fin(args
[2].c_str());
3266 std::cerr
<< "Error opening link script \""
3267 << args
[2] << "\"" << std::endl
;
3271 // Run one command at a time.
3272 std::string command
;
3274 while(result
== 0 && cmSystemTools::GetLineFromStream(fin
, command
))
3276 // Setup this command line.
3277 const char* cmd
[2] = {command
.c_str(), 0};
3278 cmsysProcess_SetCommand(cp
, cmd
);
3280 // Report the command if verbose output is enabled.
3283 std::cout
<< command
<< std::endl
;
3286 // Run the command and wait for it to exit.
3287 cmsysProcess_Execute(cp
);
3288 cmsysProcess_WaitForExit(cp
, 0);
3290 // Report failure if any.
3291 switch(cmsysProcess_GetState(cp
))
3293 case cmsysProcess_State_Exited
:
3295 int value
= cmsysProcess_GetExitValue(cp
);
3302 case cmsysProcess_State_Exception
:
3303 std::cerr
<< "Error running link command: "
3304 << cmsysProcess_GetExceptionString(cp
) << std::endl
;
3307 case cmsysProcess_State_Error
:
3308 std::cerr
<< "Error running link command: "
3309 << cmsysProcess_GetErrorString(cp
) << std::endl
;
3317 // Free the process instance.
3318 cmsysProcess_Delete(cp
);
3320 // Return the final resulting return value.
3324 void cmake::DefineProperties(cmake
*cm
)
3327 ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL
,
3328 "If set, report any undefined properties to this file.",
3329 "If this property is set to a filename then when CMake runs "
3330 "it will report any properties or variables that were accessed "
3331 "but not defined into the filename specified in this property."
3335 ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL
,
3336 "Does the target platform support shared libraries.",
3337 "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
3338 "platform supports shared libraries. Basically all current general "
3339 "general purpose OS do so, the exception are usually embedded systems "
3340 "with no or special OSs.");
3343 ("TARGET_ARCHIVES_MAY_BE_SHARED_LIBS", cmProperty::GLOBAL
,
3344 "Set if shared libraries may be named like archives.",
3345 "On AIX shared libraries may be named \"lib<name>.a\". "
3346 "This property is set to true on such platforms.");
3349 ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL
,
3350 "Whether FIND_LIBRARY should automatically search lib64 directories.",
3351 "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
3352 "FIND_LIBRARY command should automatically search the lib64 variant of "
3353 "directories called lib in the search path when building 64-bit "
3356 ("FIND_LIBRARY_USE_OPENBSD_VERSIONING", cmProperty::GLOBAL
,
3357 "Whether FIND_LIBRARY should find OpenBSD-style shared libraries.",
3358 "This property is a boolean specifying whether the FIND_LIBRARY "
3359 "command should find shared libraries with OpenBSD-style versioned "
3360 "extension: \".so.<major>.<minor>\". "
3361 "The property is set to true on OpenBSD and false on other platforms.");
3363 ("ENABLED_FEATURES", cmProperty::GLOBAL
,
3364 "List of features which are enabled during the CMake run.",
3365 "List of features which are enabled during the CMake run. Be default "
3366 "it contains the names of all packages which were found. This is "
3367 "determined using the <NAME>_FOUND variables. Packages which are "
3368 "searched QUIET are not listed. A project can add its own features to "
3369 "this list.This property is used by the macros in FeatureSummary.cmake.");
3371 ("DISABLED_FEATURES", cmProperty::GLOBAL
,
3372 "List of features which are disabled during the CMake run.",
3373 "List of features which are disabled during the CMake run. Be default "
3374 "it contains the names of all packages which were not found. This is "
3375 "determined using the <NAME>_FOUND variables. Packages which are "
3376 "searched QUIET are not listed. A project can add its own features to "
3377 "this list.This property is used by the macros in FeatureSummary.cmake.");
3379 ("PACKAGES_FOUND", cmProperty::GLOBAL
,
3380 "List of packages which were found during the CMake run.",
3381 "List of packages which were found during the CMake run. Whether a "
3382 "package has been found is determined using the <NAME>_FOUND variables.");
3384 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3385 "List of packages which were not found during the CMake run.",
3386 "List of packages which were not found during the CMake run. Whether a "
3387 "package has been found is determined using the <NAME>_FOUND variables.");
3390 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3391 "List of packages which were not found during the CMake run.",
3392 "List of packages which were not found during the CMake run. Whether a "
3393 "package has been found is determined using the <NAME>_FOUND variables.");
3395 "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL
,
3396 "Internal property",
3397 "Used to detect compiler changes, Do not set.");
3400 "DEBUG_CONFIGURATIONS", cmProperty::GLOBAL
,
3401 "Specify which configurations are for debugging.",
3402 "The value must be a semi-colon separated list of configuration names. "
3403 "Currently this property is used only by the target_link_libraries "
3404 "command (see its documentation for details). "
3405 "Additional uses may be defined in the future. "
3407 "This property must be set at the top level of the project and before "
3408 "the first target_link_libraries command invocation. "
3409 "If any entry in the list does not match a valid configuration for "
3410 "the project the behavior is undefined.");
3413 "GLOBAL_DEPENDS_DEBUG_MODE", cmProperty::GLOBAL
,
3414 "Enable global target dependency graph debug mode.",
3415 "CMake automatically analyzes the global inter-target dependency graph "
3416 "at the beginning of native build system generation. "
3417 "This property causes it to display details of its analysis to stderr.");
3420 "ALLOW_DUPLICATE_CUSTOM_TARGETS", cmProperty::GLOBAL
,
3421 "Allow duplicate custom targets to be created.",
3422 "Normally CMake requires that all targets built in a project have "
3423 "globally unique logical names (see policy CMP0002). "
3424 "This is necessary to generate meaningful project file names in "
3425 "Xcode and VS IDE generators. "
3426 "It also allows the target names to be referenced unambiguously.\n"
3427 "Makefile generators are capable of supporting duplicate custom target "
3429 "For projects that care only about Makefile generators and do "
3430 "not wish to support Xcode or VS IDE generators, one may set this "
3431 "property to true to allow duplicate custom targets. "
3432 "The property allows multiple add_custom_target command calls in "
3433 "different directories to specify the same target name. "
3434 "However, setting this property will cause non-Makefile generators "
3435 "to produce an error and refuse to generate the project."
3439 ("IN_TRY_COMPILE", cmProperty::GLOBAL
,
3440 "Read-only property that is true during a try-compile configuration.",
3441 "True when building a project inside a TRY_COMPILE or TRY_RUN command.");
3443 ("ENABLED_LANGUAGES", cmProperty::GLOBAL
,
3444 "Read-only property that contains the list of currently "
3445 "enabled languages",
3446 "Set to list of currently enabled lanauges.");
3449 ("RULE_LAUNCH_COMPILE", cmProperty::GLOBAL
,
3450 "Specify a launcher for compile rules.",
3451 "Makefile generators prefix compiler commands with the given "
3452 "launcher command line. "
3453 "This is intended to allow launchers to intercept build problems "
3454 "with high granularity. "
3455 "Non-Makefile generators currently ignore this property.");
3457 ("RULE_LAUNCH_LINK", cmProperty::GLOBAL
,
3458 "Specify a launcher for link rules.",
3459 "Makefile generators prefix link and archive commands with the given "
3460 "launcher command line. "
3461 "This is intended to allow launchers to intercept build problems "
3462 "with high granularity. "
3463 "Non-Makefile generators currently ignore this property.");
3465 ("RULE_LAUNCH_CUSTOM", cmProperty::GLOBAL
,
3466 "Specify a launcher for custom rules.",
3467 "Makefile generators prefix custom commands with the given "
3468 "launcher command line. "
3469 "This is intended to allow launchers to intercept build problems "
3470 "with high granularity. "
3471 "Non-Makefile generators currently ignore this property.");
3474 ("RULE_MESSAGES", cmProperty::GLOBAL
,
3475 "Specify whether to report a message for each make rule.",
3476 "This property specifies whether Makefile generators should add a "
3477 "progress message describing what each build rule does. "
3478 "If the property is not set the default is ON. "
3479 "Set the property to OFF to disable granular messages and report only "
3480 "as each target completes. "
3481 "This is intended to allow scripted builds to avoid the build time "
3482 "cost of detailed reports. "
3483 "If a CMAKE_RULE_MESSAGES cache entry exists its value initializes "
3484 "the value of this property. "
3485 "Non-Makefile generators currently ignore this property.");
3487 // ================================================================
3488 // define variables as well
3489 // ================================================================
3490 cmDocumentVariables::DefineVariables(cm
);
3494 void cmake::DefineProperty(const char *name
, cmProperty::ScopeType scope
,
3495 const char *ShortDescription
,
3496 const char *FullDescription
,
3497 bool chained
, const char *docSection
)
3499 this->PropertyDefinitions
[scope
].DefineProperty(name
,scope
,ShortDescription
,
3505 cmPropertyDefinition
*cmake
3506 ::GetPropertyDefinition(const char *name
,
3507 cmProperty::ScopeType scope
)
3509 if (this->IsPropertyDefined(name
,scope
))
3511 return &(this->PropertyDefinitions
[scope
][name
]);
3516 void cmake::RecordPropertyAccess(const char *name
,
3517 cmProperty::ScopeType scope
)
3519 this->AccessedProperties
.insert
3520 (std::pair
<cmStdString
,cmProperty::ScopeType
>(name
,scope
));
3523 void cmake::ReportUndefinedPropertyAccesses(const char *filename
)
3525 FILE *progFile
= fopen(filename
,"w");
3526 if (!progFile
|| !this->GlobalGenerator
)
3531 // what are the enabled languages?
3532 std::vector
<std::string
> enLangs
;
3533 this->GlobalGenerator
->GetEnabledLanguages(enLangs
);
3535 // Common configuration names.
3536 // TODO: Compute current configuration(s).
3537 std::vector
<std::string
> enConfigs
;
3538 enConfigs
.push_back("");
3539 enConfigs
.push_back("DEBUG");
3540 enConfigs
.push_back("RELEASE");
3541 enConfigs
.push_back("MINSIZEREL");
3542 enConfigs
.push_back("RELWITHDEBINFO");
3544 // take all the defined properties and add definitions for all the enabled
3546 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> > aliasedProperties
;
3547 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
3548 i
= this->PropertyDefinitions
.begin();
3549 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
3551 cmPropertyDefinitionMap::iterator j
;
3552 for (j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
3554 // TODO: What if both <LANG> and <CONFIG> appear?
3555 if (j
->first
.find("<CONFIG>") != std::string::npos
)
3557 std::vector
<std::string
>::const_iterator k
;
3558 for (k
= enConfigs
.begin(); k
!= enConfigs
.end(); ++k
)
3560 std::string tmp
= j
->first
;
3561 cmSystemTools::ReplaceString(tmp
, "<CONFIG>", k
->c_str());
3563 aliasedProperties
.insert
3564 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3567 if (j
->first
.find("<LANG>") != std::string::npos
)
3569 std::vector
<std::string
>::const_iterator k
;
3570 for (k
= enLangs
.begin(); k
!= enLangs
.end(); ++k
)
3572 std::string tmp
= j
->first
;
3573 cmSystemTools::ReplaceString(tmp
, "<LANG>", k
->c_str());
3575 aliasedProperties
.insert
3576 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3582 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> >::const_iterator ap
;
3583 ap
= this->AccessedProperties
.begin();
3584 for (;ap
!= this->AccessedProperties
.end(); ++ap
)
3586 if (!this->IsPropertyDefined(ap
->first
.c_str(),ap
->second
) &&
3587 aliasedProperties
.find(std::pair
<cmStdString
,cmProperty::ScopeType
>
3588 (ap
->first
,ap
->second
)) ==
3589 aliasedProperties
.end())
3591 const char *scopeStr
= "";
3594 case cmProperty::TARGET
:
3595 scopeStr
= "TARGET";
3597 case cmProperty::SOURCE_FILE
:
3598 scopeStr
= "SOURCE_FILE";
3600 case cmProperty::DIRECTORY
:
3601 scopeStr
= "DIRECTORY";
3603 case cmProperty::TEST
:
3606 case cmProperty::VARIABLE
:
3607 scopeStr
= "VARIABLE";
3609 case cmProperty::CACHED_VARIABLE
:
3610 scopeStr
= "CACHED_VARIABLE";
3613 scopeStr
= "unknown";
3616 fprintf(progFile
, "%s with scope %s\n", ap
->first
.c_str(), scopeStr
);
3622 bool cmake::IsPropertyDefined(const char *name
, cmProperty::ScopeType scope
)
3624 return this->PropertyDefinitions
[scope
].IsPropertyDefined(name
);
3627 bool cmake::IsPropertyChained(const char *name
, cmProperty::ScopeType scope
)
3629 return this->PropertyDefinitions
[scope
].IsPropertyChained(name
);
3632 void cmake::SetProperty(const char* prop
, const char* value
)
3639 // Special hook to invalidate cached value.
3640 if(strcmp(prop
, "DEBUG_CONFIGURATIONS") == 0)
3642 this->DebugConfigs
.clear();
3645 this->Properties
.SetProperty(prop
, value
, cmProperty::GLOBAL
);
3648 void cmake::AppendProperty(const char* prop
, const char* value
)
3655 // Special hook to invalidate cached value.
3656 if(strcmp(prop
, "DEBUG_CONFIGURATIONS") == 0)
3658 this->DebugConfigs
.clear();
3661 this->Properties
.AppendProperty(prop
, value
, cmProperty::GLOBAL
);
3664 const char *cmake::GetProperty(const char* prop
)
3666 return this->GetProperty(prop
, cmProperty::GLOBAL
);
3669 const char *cmake::GetProperty(const char* prop
, cmProperty::ScopeType scope
)
3677 // watch for special properties
3678 std::string propname
= prop
;
3679 std::string output
= "";
3680 if ( propname
== "CACHE_VARIABLES" )
3682 cmCacheManager::CacheIterator cit
=
3683 this->GetCacheManager()->GetCacheIterator();
3684 for ( cit
.Begin(); !cit
.IsAtEnd(); cit
.Next() )
3686 if ( output
.size() )
3690 output
+= cit
.GetName();
3692 this->SetProperty("CACHE_VARIABLES", output
.c_str());
3694 else if ( propname
== "COMMANDS" )
3696 cmake::RegisteredCommandsMap::iterator cmds
3697 = this->GetCommands()->begin();
3698 for (unsigned int cc
=0 ; cmds
!= this->GetCommands()->end(); ++ cmds
)
3704 output
+= cmds
->first
.c_str();
3707 this->SetProperty("COMMANDS",output
.c_str());
3709 else if ( propname
== "IN_TRY_COMPILE" )
3711 this->SetProperty("IN_TRY_COMPILE",
3712 this->GetIsInTryCompile()? "1":"0");
3714 else if ( propname
== "ENABLED_LANGUAGES" )
3717 if(this->GlobalGenerator
)
3719 std::vector
<std::string
> enLangs
;
3720 this->GlobalGenerator
->GetEnabledLanguages(enLangs
);
3721 const char* sep
= "";
3722 for(std::vector
<std::string
>::iterator i
= enLangs
.begin();
3723 i
!= enLangs
.end(); ++i
)
3730 this->SetProperty("ENABLED_LANGUAGES", lang
.c_str());
3732 return this->Properties
.GetPropertyValue(prop
, scope
, chain
);
3735 bool cmake::GetPropertyAsBool(const char* prop
)
3737 return cmSystemTools::IsOn(this->GetProperty(prop
));
3740 int cmake::GetSystemInformation(std::vector
<std::string
>& args
)
3742 // so create the directory
3743 std::string resultFile
;
3744 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
3745 std::string destPath
= cwd
+ "/__cmake_systeminformation";
3746 cmSystemTools::RemoveADirectory(destPath
.c_str());
3747 if (!cmSystemTools::MakeDirectory(destPath
.c_str()))
3749 std::cerr
<< "Error: --system-information must be run from a "
3750 "writable directory!\n";
3754 // process the arguments
3755 bool writeToStdout
= true;
3756 for(unsigned int i
=1; i
< args
.size(); ++i
)
3758 std::string arg
= args
[i
];
3759 if(arg
.find("-V",0) == 0)
3761 this->Verbose
= true;
3763 else if(arg
.find("-G",0) == 0)
3765 std::string value
= arg
.substr(2);
3766 if(value
.size() == 0)
3769 if(i
>= args
.size())
3771 cmSystemTools::Error("No generator specified for -G");
3776 cmGlobalGenerator
* gen
=
3777 this->CreateGlobalGenerator(value
.c_str());
3780 cmSystemTools::Error("Could not create named generator ",
3785 this->SetGlobalGenerator(gen
);
3788 // no option assume it is the output file
3791 if (!cmSystemTools::FileIsFullPath(arg
.c_str()))
3797 writeToStdout
= false;
3802 // we have to find the module directory, so we can copy the files
3803 this->AddCMakePaths();
3804 std::string modulesPath
=
3805 this->CacheManager
->GetCacheValue("CMAKE_ROOT");
3806 modulesPath
+= "/Modules";
3807 std::string inFile
= modulesPath
;
3808 inFile
+= "/SystemInformation.cmake";
3809 std::string outFile
= destPath
;
3810 outFile
+= "/CMakeLists.txt";
3813 if(!cmSystemTools::cmCopyFile(inFile
.c_str(), outFile
.c_str()))
3815 std::cerr
<< "Error copying file \"" << inFile
.c_str()
3816 << "\" to \"" << outFile
.c_str() << "\".\n";
3820 // do we write to a file or to stdout?
3821 if (resultFile
.size() == 0)
3824 resultFile
+= "/__cmake_systeminformation/results.txt";
3827 // now run cmake on the CMakeLists file
3828 cmSystemTools::ChangeDirectory(destPath
.c_str());
3829 std::vector
<std::string
> args2
;
3830 args2
.push_back(args
[0]);
3831 args2
.push_back(destPath
);
3832 std::string resultArg
= "-DRESULT_FILE=";
3833 resultArg
+= resultFile
;
3834 args2
.push_back(resultArg
);
3835 int res
= this->Run(args2
, false);
3839 std::cerr
<< "Error: --system-information failed on internal CMake!\n";
3843 // change back to the original directory
3844 cmSystemTools::ChangeDirectory(cwd
.c_str());
3846 // echo results to stdout if needed
3849 FILE* fin
= fopen(resultFile
.c_str(), "r");
3852 const int bufferSize
= 4096;
3853 char buffer
[bufferSize
];
3855 while((n
= fread(buffer
, 1, bufferSize
, fin
)) > 0)
3857 for(char* c
= buffer
; c
< buffer
+n
; ++c
)
3867 // clean up the directory
3868 cmSystemTools::RemoveADirectory(destPath
.c_str());
3872 //----------------------------------------------------------------------------
3873 static bool cmakeCheckStampFile(const char* stampName
)
3875 // If the stamp file still exists then it must really be out of
3877 if(cmSystemTools::FileExists(stampName
))
3879 // Notify the user why CMake is re-running. It is safe to
3880 // just print to stdout here because this code is only reachable
3881 // through an undocumented flag used by the VS generator.
3882 std::cout
<< "CMake is re-running because build system is out-of-date.\n";
3886 // The stamp file does not exist. Use the stamp dependencies to
3887 // determine whether it is really out of date. This works in
3888 // conjunction with cmLocalVisualStudio7Generator to avoid
3889 // repeatedly re-running CMake when the user rebuilds the entire
3891 std::string stampDepends
= stampName
;
3892 stampDepends
+= ".depend";
3893 #if defined(_WIN32) || defined(__CYGWIN__)
3894 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
| std::ios::binary
);
3896 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
);
3900 // The stamp dependencies file cannot be read. Just assume the
3901 // build system is really out of date.
3902 std::cout
<< "CMake is re-running because " << stampName
3903 << " dependency file is missing.\n";
3907 // Compare the stamp dependencies against the dependency file itself.
3908 cmFileTimeComparison ftc
;
3910 while(cmSystemTools::GetLineFromStream(fin
, dep
))
3913 if(dep
.length() >= 1 && dep
[0] != '#' &&
3914 (!ftc
.FileTimeCompare(stampDepends
.c_str(), dep
.c_str(), &result
)
3917 // The stamp depends file is older than this dependency. The
3918 // build system is really out of date.
3919 std::cout
<< "CMake is re-running because " << stampName
3920 << " is out-of-date.\n";
3925 // The build system is up to date. The stamp file has been removed
3926 // by the VS IDE due to a "rebuild" request. Just restore it.
3927 std::ofstream
stamp(stampName
);
3928 stamp
<< "# CMake generation timestamp file this directory.\n";
3931 // Notify the user why CMake is not re-running. It is safe to
3932 // just print to stdout here because this code is only reachable
3933 // through an undocumented flag used by the VS generator.
3934 std::cout
<< "CMake does not need to re-run because "
3935 << stampName
<< " is up-to-date.\n";
3940 cmSystemTools::Error("Cannot restore timestamp ", stampName
);
3945 //----------------------------------------------------------------------------
3946 static bool cmakeCheckStampList(const char* stampList
)
3948 // If the stamp list does not exist CMake must rerun to generate it.
3949 if(!cmSystemTools::FileExists(stampList
))
3951 std::cout
<< "CMake is re-running because generate.stamp.list "
3955 std::ifstream
fin(stampList
);
3958 std::cout
<< "CMake is re-running because generate.stamp.list "
3959 << "could not be read.\n";
3963 // Check each stamp.
3964 std::string stampName
;
3965 while(cmSystemTools::GetLineFromStream(fin
, stampName
))
3967 if(!cmakeCheckStampFile(stampName
.c_str()))
3975 // For visual studio 2005 and newer manifest files need to be embeded into
3976 // exe and dll's. This code does that in such a way that incremental linking
3978 int cmake::VisualStudioLink(std::vector
<std::string
>& args
, int type
)
3984 bool verbose
= false;
3985 if(cmSystemTools::GetEnv("VERBOSE"))
3989 std::vector
<std::string
> expandedArgs
;
3990 for(std::vector
<std::string
>::iterator i
= args
.begin();
3991 i
!= args
.end(); ++i
)
3993 // check for nmake temporary files
3994 if((*i
)[0] == '@' && i
->find("@CMakeFiles") != 0 )
3996 std::ifstream
fin(i
->substr(1).c_str());
3998 while(cmSystemTools::GetLineFromStream(fin
,
4001 cmSystemTools::ParseWindowsCommandLine(line
.c_str(), expandedArgs
);
4006 expandedArgs
.push_back(*i
);
4009 bool hasIncremental
= false;
4010 bool hasManifest
= true;
4011 for(std::vector
<std::string
>::iterator i
= expandedArgs
.begin();
4012 i
!= expandedArgs
.end(); ++i
)
4014 if(cmSystemTools::Strucmp(i
->c_str(), "/INCREMENTAL:YES") == 0)
4016 hasIncremental
= true;
4018 if(cmSystemTools::Strucmp(i
->c_str(), "/MANIFEST:NO") == 0)
4020 hasManifest
= false;
4023 if(hasIncremental
&& hasManifest
)
4027 std::cout
<< "Visual Studio Incremental Link with embeded manifests\n";
4029 return cmake::VisualStudioLinkIncremental(expandedArgs
, type
, verbose
);
4035 std::cout
<< "Visual Studio Non-Incremental Link\n";
4039 std::cout
<< "Visual Studio Incremental Link without manifests\n";
4042 return cmake::VisualStudioLinkNonIncremental(expandedArgs
,
4043 type
, hasManifest
, verbose
);
4046 int cmake::ParseVisualStudioLinkCommand(std::vector
<std::string
>& args
,
4047 std::vector
<cmStdString
>& command
,
4048 std::string
& targetName
)
4050 std::vector
<std::string
>::iterator i
= args
.begin();
4052 i
++; // skip vs_link_dll or vs_link_exe
4053 command
.push_back(*i
);
4054 i
++; // move past link command
4055 for(; i
!= args
.end(); ++i
)
4057 command
.push_back(*i
);
4058 if(i
->find("/Fe") == 0)
4060 targetName
= i
->substr(3);
4062 if(i
->find("/out:") == 0)
4064 targetName
= i
->substr(5);
4067 if(targetName
.size() == 0 || command
.size() == 0)
4074 bool cmake::RunCommand(const char* comment
,
4075 std::vector
<cmStdString
>& command
,
4081 std::cout
<< comment
<< ":\n";
4082 for(std::vector
<cmStdString
>::iterator i
= command
.begin();
4083 i
!= command
.end(); ++i
)
4085 std::cout
<< i
->c_str() << " ";
4091 // use rc command to create .res file
4092 cmSystemTools::RunSingleCommand(command
,
4094 &retCode
, 0, false);
4095 // always print the output of the command, unless
4096 // it is the dumb rc command banner, but if the command
4097 // returned an error code then print the output anyway as
4098 // the banner may be mixed with some other important information.
4099 if(output
.find("Resource Compiler Version") == output
.npos
4102 std::cout
<< output
;
4104 // if retCodeOut is requested then always return true
4105 // and set the retCodeOut to retCode
4108 *retCodeOut
= retCode
;
4113 std::cout
<< comment
<< " failed. with " << retCode
<< "\n";
4115 return retCode
== 0;
4118 int cmake::VisualStudioLinkIncremental(std::vector
<std::string
>& args
,
4119 int type
, bool verbose
)
4121 // This follows the steps listed here:
4122 // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
4124 // 1. Compiler compiles the application and generates the *.obj files.
4125 // 2. An empty manifest file is generated if this is a clean build and if
4126 // not the previous one is reused.
4127 // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
4129 // 4. Linker generates the binary (EXE or DLL) with the /incremental
4130 // switch and embeds the dummy manifest file. The linker also generates
4131 // the real manifest file based on the binaries that your binary depends
4133 // 5. The manifest tool (mt.exe) is then used to generate the final
4136 // If the final manifest is changed, then 6 and 7 are run, if not
4137 // they are skipped, and it is done.
4139 // 6. The resource compiler is invoked one more time.
4140 // 7. Finally, the Linker does another incremental link, but since the
4141 // only thing that has changed is the *.res file that contains the
4142 // manifest it is a short link.
4143 std::vector
<cmStdString
> linkCommand
;
4144 std::string targetName
;
4145 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
4149 std::string manifestArg
= "/MANIFESTFILE:";
4150 std::vector
<cmStdString
> rcCommand
;
4151 rcCommand
.push_back(cmSystemTools::FindProgram("rc.exe"));
4152 std::vector
<cmStdString
> mtCommand
;
4153 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
4154 std::string tempManifest
;
4155 tempManifest
= targetName
;
4156 tempManifest
+= ".intermediate.manifest";
4157 std::string resourceInputFile
= targetName
;
4158 resourceInputFile
+= ".resource.txt";
4161 std::cout
<< "Create " << resourceInputFile
.c_str() << "\n";
4163 // Create input file for rc command
4164 std::ofstream
fout(resourceInputFile
.c_str());
4169 std::string manifestFile
= targetName
;
4170 manifestFile
+= ".embed.manifest";
4171 std::string fullPath
= cmSystemTools::CollapseFullPath(manifestFile
.c_str());
4172 fout
<< type
<< " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
4173 "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath
.c_str() << "\"";
4175 manifestArg
+= tempManifest
;
4176 // add the manifest arg to the linkCommand
4177 linkCommand
.push_back(manifestArg
);
4178 // if manifestFile is not yet created, create an
4180 if(!cmSystemTools::FileExists(manifestFile
.c_str()))
4184 std::cout
<< "Create empty: " << manifestFile
.c_str() << "\n";
4186 std::ofstream
foutTmp(manifestFile
.c_str());
4188 std::string resourceFile
= manifestFile
;
4189 resourceFile
+= ".res";
4190 // add the resource file to the end of the link command
4191 linkCommand
.push_back(resourceFile
);
4192 std::string outputOpt
= "/fo";
4193 outputOpt
+= resourceFile
;
4194 rcCommand
.push_back(outputOpt
);
4195 rcCommand
.push_back(resourceInputFile
);
4196 // Run rc command to create resource
4197 if(!cmake::RunCommand("RC Pass 1", rcCommand
, verbose
))
4201 // Now run the link command to link and create manifest
4202 if(!cmake::RunCommand("LINK Pass 1", linkCommand
, verbose
))
4206 // create mt command
4207 std::string
outArg("/out:");
4208 outArg
+= manifestFile
;
4209 mtCommand
.push_back("/nologo");
4210 mtCommand
.push_back(outArg
);
4211 mtCommand
.push_back("/notify_update");
4212 mtCommand
.push_back("/manifest");
4213 mtCommand
.push_back(tempManifest
);
4214 // now run mt.exe to create the final manifest file
4216 cmake::RunCommand("MT", mtCommand
, verbose
, &mtRet
);
4217 // if mt returns 0, then the manifest was not changed and
4218 // we do not need to do another link step
4223 // check for magic mt return value if mt returns the magic number
4224 // 1090650113 then it means that it updated the manifest file and we need
4225 // to do the final link. If mt has any value other than 0 or 1090650113
4226 // then there was some problem with the command itself and there was an
4227 // error so return the error code back out of cmake so make can report it.
4228 if(mtRet
!= 1090650113)
4232 // update the resource file with the new manifest from the mt command.
4233 if(!cmake::RunCommand("RC Pass 2", rcCommand
, verbose
))
4237 // Run the final incremental link that will put the new manifest resource
4238 // into the file incrementally.
4239 if(!cmake::RunCommand("FINAL LINK", linkCommand
, verbose
))
4246 int cmake::VisualStudioLinkNonIncremental(std::vector
<std::string
>& args
,
4251 std::vector
<cmStdString
> linkCommand
;
4252 std::string targetName
;
4253 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
4257 // Run the link command as given
4258 if(!cmake::RunCommand("LINK", linkCommand
, verbose
))
4266 std::vector
<cmStdString
> mtCommand
;
4267 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
4268 mtCommand
.push_back("/nologo");
4269 mtCommand
.push_back("/manifest");
4270 std::string manifestFile
= targetName
;
4271 manifestFile
+= ".manifest";
4272 mtCommand
.push_back(manifestFile
);
4273 std::string outresource
= "/outputresource:";
4274 outresource
+= targetName
;
4275 outresource
+= ";#";
4284 mtCommand
.push_back(outresource
);
4285 // Now use the mt tool to embed the manifest into the exe or dll
4286 if(!cmake::RunCommand("MT", mtCommand
, verbose
))
4293 //----------------------------------------------------------------------------
4294 void cmake::IssueMessage(cmake::MessageType t
, std::string
const& text
,
4295 cmListFileBacktrace
const& backtrace
)
4297 cmOStringStream msg
;
4298 bool isError
= false;
4299 // Construct the message header.
4300 if(t
== cmake::FATAL_ERROR
)
4303 msg
<< "CMake Error";
4305 else if(t
== cmake::INTERNAL_ERROR
)
4308 msg
<< "CMake Internal Error (please report a bug)";
4312 msg
<< "CMake Warning";
4313 if(t
== cmake::AUTHOR_WARNING
)
4315 // Allow suppression of these warnings.
4316 cmCacheManager::CacheIterator it
= this->CacheManager
4317 ->GetCacheIterator("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
4318 if(!it
.IsAtEnd() && it
.GetValueAsBool())
4326 // Add the immediate context.
4327 cmListFileBacktrace::const_iterator i
= backtrace
.begin();
4328 if(i
!= backtrace
.end())
4330 cmListFileContext
const& lfc
= *i
;
4331 msg
<< (lfc
.Line
? " at ": " in ") << lfc
;
4335 // Add the message text.
4338 cmDocumentationFormatterText formatter
;
4339 formatter
.SetIndent(" ");
4340 formatter
.PrintFormatted(msg
, text
.c_str());
4343 // Add the rest of the context.
4344 if(i
!= backtrace
.end())
4346 msg
<< "Call Stack (most recent call first):\n";
4347 while(i
!= backtrace
.end())
4349 cmListFileContext
const& lfc
= *i
;
4350 msg
<< " " << lfc
<< "\n";
4355 // Add a note about warning suppression.
4356 if(t
== cmake::AUTHOR_WARNING
)
4359 "This warning is for project developers. Use -Wno-dev to suppress it.";
4362 // Add a terminating blank line.
4365 // Output the message.
4368 cmSystemTools::SetErrorOccured();
4369 cmSystemTools::Message(msg
.str().c_str(), "Error");
4373 cmSystemTools::Message(msg
.str().c_str(), "Warning");
4377 //----------------------------------------------------------------------------
4378 std::vector
<std::string
> const& cmake::GetDebugConfigs()
4380 // Compute on-demand.
4381 if(this->DebugConfigs
.empty())
4383 if(const char* config_list
= this->GetProperty("DEBUG_CONFIGURATIONS"))
4385 // Expand the specified list and convert to upper-case.
4386 cmSystemTools::ExpandListArgument(config_list
, this->DebugConfigs
);
4387 for(std::vector
<std::string
>::iterator i
= this->DebugConfigs
.begin();
4388 i
!= this->DebugConfigs
.end(); ++i
)
4390 *i
= cmSystemTools::UpperCase(*i
);
4393 // If no configurations were specified, use a default list.
4394 if(this->DebugConfigs
.empty())
4396 this->DebugConfigs
.push_back("DEBUG");
4399 return this->DebugConfigs
;
4403 int cmake::Build(const std::string
& dir
,
4404 const std::string
& target
,
4405 const std::string
& config
,
4406 const std::vector
<std::string
>& nativeOptions
,
4409 if(!cmSystemTools::FileIsDirectory(dir
.c_str()))
4411 std::cerr
<< "Error: " << dir
<< " is not a directory\n";
4414 std::string cachePath
= dir
;
4415 cmSystemTools::ConvertToUnixSlashes(cachePath
);
4416 cmCacheManager
* cachem
= this->GetCacheManager();
4417 cmCacheManager::CacheIterator it
= cachem
->NewIterator();
4418 if(!cachem
->LoadCache(cachePath
.c_str()))
4420 std::cerr
<< "Error: could not load cache\n";
4423 if(!it
.Find("CMAKE_GENERATOR"))
4425 std::cerr
<< "Error: could find generator in Cache\n";
4428 cmGlobalGenerator
* gen
=
4429 this->CreateGlobalGenerator(it
.GetValue());
4431 std::string projName
;
4432 std::string makeProgram
;
4433 if(!it
.Find("CMAKE_PROJECT_NAME"))
4435 std::cerr
<< "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
4438 projName
= it
.GetValue();
4439 if(!it
.Find("CMAKE_MAKE_PROGRAM"))
4441 std::cerr
<< "Error: could not find CMAKE_MAKE_PROGRAM in Cache\n";
4444 makeProgram
= it
.GetValue();
4445 return gen
->Build(0, dir
.c_str(),
4446 projName
.c_str(), target
.c_str(),
4448 makeProgram
.c_str(),
4449 config
.c_str(), clean
, false, 0, true,