1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmake.cxx,v $
6 Date: $Date: 2008-01-20 18:36:13 $
7 Version: $Revision: 1.354 $
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"
32 #if defined(CMAKE_BUILD_WITH_CMAKE)
33 # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
34 # include "cmVariableWatch.h"
35 # include <cmsys/Terminal.h>
38 #include <cmsys/Directory.hxx>
39 #include <cmsys/Process.h>
40 #include <cmsys/Glob.hxx>
41 #include <cmsys/RegularExpression.hxx>
43 // only build kdevelop generator on non-windows platforms
44 // when not bootstrapping cmake
46 # if defined(CMAKE_BUILD_WITH_CMAKE)
47 # define CMAKE_USE_KDEVELOP
51 #if defined(CMAKE_BUILD_WITH_CMAKE)
52 # define CMAKE_USE_ECLIPSE
55 #if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
56 # define CMAKE_BOOT_MINGW
59 // include the generator
60 #if defined(_WIN32) && !defined(__CYGWIN__)
61 # if !defined(CMAKE_BOOT_MINGW)
62 # include "cmGlobalVisualStudio6Generator.h"
63 # include "cmGlobalVisualStudio7Generator.h"
64 # include "cmGlobalVisualStudio71Generator.h"
65 # include "cmGlobalVisualStudio8Generator.h"
66 # include "cmGlobalVisualStudio9Generator.h"
67 # include "cmGlobalVisualStudio9Win64Generator.h"
68 # include "cmGlobalVisualStudio8Win64Generator.h"
69 # include "cmGlobalBorlandMakefileGenerator.h"
70 # include "cmGlobalNMakeMakefileGenerator.h"
71 # include "cmGlobalWatcomWMakeGenerator.h"
72 # define CMAKE_HAVE_VS_GENERATORS
74 # include "cmGlobalMSYSMakefileGenerator.h"
75 # include "cmGlobalMinGWMakefileGenerator.h"
76 # include "cmWin32ProcessExecution.h"
79 #include "cmGlobalUnixMakefileGenerator3.h"
81 #if defined(CMAKE_HAVE_VS_GENERATORS)
82 #include "cmCallVisualStudioMacro.h"
85 #if !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
86 # include "cmExtraCodeBlocksGenerator.h"
89 #ifdef CMAKE_USE_KDEVELOP
90 # include "cmGlobalKdevelopGenerator.h"
93 #ifdef CMAKE_USE_ECLIPSE
94 # include "cmExtraEclipseCDT4Generator.h"
97 #include <stdlib.h> // required for atoi
99 #if defined( __APPLE__ )
100 # if defined(CMAKE_BUILD_WITH_CMAKE)
101 # include "cmGlobalXCodeGenerator.h"
102 # define CMAKE_USE_XCODE 1
104 # include <sys/types.h>
105 # include <sys/time.h>
106 # include <sys/resource.h>
109 #include <sys/stat.h> // struct stat
111 #include <memory> // auto_ptr
113 static bool cmakeCheckStampFile(const char* stampName
);
115 void cmNeedBackwardsCompatibility(const std::string
& variable
,
116 int access_type
, void*, const char*, const cmMakefile
*)
118 #ifdef CMAKE_BUILD_WITH_CMAKE
119 if (access_type
== cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS
)
121 std::string message
= "An attempt was made to access a variable: ";
124 " that has not been defined. Some variables were always defined "
125 "by CMake in versions prior to 1.6. To fix this you might need to set "
126 "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
127 "you are writing a CMakeList file, (or have already set "
128 "CMAKE_BACKWARDS_COMPATABILITY to 1.4 or less) then you probably need "
129 "to include a CMake module to test for the feature this variable "
131 cmSystemTools::Error(message
.c_str());
141 this->DebugOutput
= false;
142 this->DebugTryCompile
= false;
143 this->ClearBuildSystem
= false;
144 this->FileComparison
= new cmFileTimeComparison
;
146 this->Properties
.SetCMakeInstance(this);
148 // initialize properties
149 cmSourceFile::DefineProperties(this);
150 cmTarget::DefineProperties(this);
151 cmMakefile::DefineProperties(this);
152 cmTest::DefineProperties(this);
153 cmake::DefineProperties(this);
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
;
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 if (this->GlobalGenerator
)
208 delete this->GlobalGenerator
;
209 this->GlobalGenerator
= 0;
211 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
212 j
!= this->Commands
.end(); ++j
)
216 #ifdef CMAKE_BUILD_WITH_CMAKE
217 delete this->VariableWatch
;
219 delete this->FileComparison
;
222 void cmake::CleanupCommandsAndMacros()
224 std::vector
<cmCommand
*> commands
;
225 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
226 j
!= this->Commands
.end(); ++j
)
228 if ( !j
->second
->IsA("cmMacroHelperCommand") &&
229 !j
->second
->IsA("cmFunctionHelperCommand"))
231 commands
.push_back(j
->second
);
238 this->Commands
.erase(this->Commands
.begin(), this->Commands
.end());
239 std::vector
<cmCommand
*>::iterator it
;
240 for ( it
= commands
.begin(); it
!= commands
.end();
243 this->Commands
[cmSystemTools::LowerCase((*it
)->GetName())] = *it
;
247 bool cmake::CommandExists(const char* name
) const
249 std::string sName
= cmSystemTools::LowerCase(name
);
250 return (this->Commands
.find(sName
) != this->Commands
.end());
253 cmCommand
*cmake::GetCommand(const char *name
)
256 std::string sName
= cmSystemTools::LowerCase(name
);
257 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
258 if (pos
!= this->Commands
.end())
265 void cmake::RenameCommand(const char*oldName
, const char* newName
)
267 // if the command already exists, free the old one
268 std::string sOldName
= cmSystemTools::LowerCase(oldName
);
269 std::string sNewName
= cmSystemTools::LowerCase(newName
);
270 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sOldName
);
271 if ( pos
== this->Commands
.end() )
275 cmCommand
* cmd
= pos
->second
;
277 pos
= this->Commands
.find(sNewName
);
278 if (pos
!= this->Commands
.end())
281 this->Commands
.erase(pos
);
283 this->Commands
.insert(RegisteredCommandsMap::value_type(sNewName
, cmd
));
284 pos
= this->Commands
.find(sOldName
);
285 this->Commands
.erase(pos
);
288 void cmake::RemoveCommand(const char* name
)
290 std::string sName
= cmSystemTools::LowerCase(name
);
291 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
292 if ( pos
!= this->Commands
.end() )
295 this->Commands
.erase(pos
);
299 void cmake::AddCommand(cmCommand
* wg
)
301 std::string name
= cmSystemTools::LowerCase(wg
->GetName());
302 // if the command already exists, free the old one
303 RegisteredCommandsMap::iterator pos
= this->Commands
.find(name
);
304 if (pos
!= this->Commands
.end())
307 this->Commands
.erase(pos
);
309 this->Commands
.insert( RegisteredCommandsMap::value_type(name
, wg
));
313 void cmake::RemoveUnscriptableCommands()
315 std::vector
<std::string
> unscriptableCommands
;
316 cmake::RegisteredCommandsMap
* commands
= this->GetCommands();
317 for (cmake::RegisteredCommandsMap::const_iterator pos
= commands
->begin();
318 pos
!= commands
->end();
321 if (!pos
->second
->IsScriptable())
323 unscriptableCommands
.push_back(pos
->first
);
327 for(std::vector
<std::string
>::const_iterator it
=unscriptableCommands
.begin();
328 it
!= unscriptableCommands
.end();
331 this->RemoveCommand(it
->c_str());
336 bool cmake::SetCacheArgs(const std::vector
<std::string
>& args
)
338 for(unsigned int i
=1; i
< args
.size(); ++i
)
340 std::string arg
= args
[i
];
341 if(arg
.find("-D",0) == 0)
343 std::string entry
= arg
.substr(2);
344 if(entry
.size() == 0)
353 cmSystemTools::Error("-D must be followed with VAR=VALUE.");
357 std::string var
, value
;
358 cmCacheManager::CacheEntryType type
= cmCacheManager::UNINITIALIZED
;
359 if(cmCacheManager::ParseEntry(entry
.c_str(), var
, value
, type
) ||
360 cmCacheManager::ParseEntry(entry
.c_str(), var
, value
))
362 this->CacheManager
->AddCacheEntry(var
.c_str(), value
.c_str(),
363 "No help, variable specified on the command line.", type
);
367 std::cerr
<< "Parse error in command line argument: " << arg
<< "\n"
368 << "Should be: VAR:type=value\n";
369 cmSystemTools::Error("No cmake scrpt provided.");
373 else if(arg
.find("-U",0) == 0)
375 std::string entryPattern
= arg
.substr(2);
376 if(entryPattern
.size() == 0)
381 entryPattern
= args
[i
];
385 cmSystemTools::Error("-U must be followed with VAR.");
389 cmsys::RegularExpression
regex(
390 cmsys::Glob::PatternToRegex(entryPattern
.c_str(), true).c_str());
391 //go through all cache entries and collect the vars which will be removed
392 std::vector
<std::string
> entriesToDelete
;
393 cmCacheManager::CacheIterator it
=
394 this->CacheManager
->GetCacheIterator();
395 for ( it
.Begin(); !it
.IsAtEnd(); it
.Next() )
397 cmCacheManager::CacheEntryType t
= it
.GetType();
398 if(t
!= cmCacheManager::STATIC
)
400 std::string entryName
= it
.GetName();
401 if (regex
.find(entryName
.c_str()))
403 entriesToDelete
.push_back(entryName
);
408 // now remove them from the cache
409 for(std::vector
<std::string
>::const_iterator currentEntry
=
410 entriesToDelete
.begin();
411 currentEntry
!= entriesToDelete
.end();
414 this->CacheManager
->RemoveCacheEntry(currentEntry
->c_str());
417 else if(arg
.find("-C",0) == 0)
419 std::string path
= arg
.substr(2);
420 if ( path
.size() == 0 )
429 cmSystemTools::Error("-C must be followed by a file name.");
433 std::cerr
<< "loading initial cache file " << path
.c_str() << "\n";
434 this->ReadListFile(path
.c_str());
436 else if(arg
.find("-P",0) == 0)
441 cmSystemTools::Error("-P must be followed by a file name.");
444 std::string path
= args
[i
];
445 if ( path
.size() == 0 )
447 cmSystemTools::Error("No cmake script provided.");
450 this->ReadListFile(path
.c_str());
456 void cmake::ReadListFile(const char *path
)
458 // if a generator was not yet created, temporarily create one
459 cmGlobalGenerator
*gg
= this->GetGlobalGenerator();
460 bool created
= false;
462 // if a generator was not specified use a generic one
465 gg
= new cmGlobalGenerator
;
466 gg
->SetCMakeInstance(this);
470 // read in the list file to fill the cache
473 std::auto_ptr
<cmLocalGenerator
> lg(gg
->CreateLocalGenerator());
474 lg
->SetGlobalGenerator(gg
);
475 lg
->GetMakefile()->SetHomeOutputDirectory
476 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
477 lg
->GetMakefile()->SetStartOutputDirectory
478 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
479 lg
->GetMakefile()->SetHomeDirectory
480 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
481 lg
->GetMakefile()->SetStartDirectory
482 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
483 if (!lg
->GetMakefile()->ReadListFile(0, path
))
485 cmSystemTools::Error("Error processing file:", path
);
489 // free generic one if generated
497 void cmake::SetArgs(const std::vector
<std::string
>& args
)
499 bool directoriesSet
= false;
500 for(unsigned int i
=1; i
< args
.size(); ++i
)
502 std::string arg
= args
[i
];
503 if(arg
.find("-H",0) == 0)
505 directoriesSet
= true;
506 std::string path
= arg
.substr(2);
507 path
= cmSystemTools::CollapseFullPath(path
.c_str());
508 cmSystemTools::ConvertToUnixSlashes(path
);
509 this->SetHomeDirectory(path
.c_str());
511 else if(arg
.find("-S",0) == 0)
513 // There is no local generate anymore. Ignore -S option.
515 else if(arg
.find("-O",0) == 0)
517 // There is no local generate anymore. Ignore -O option.
519 else if(arg
.find("-B",0) == 0)
521 directoriesSet
= true;
522 std::string path
= arg
.substr(2);
523 path
= cmSystemTools::CollapseFullPath(path
.c_str());
524 cmSystemTools::ConvertToUnixSlashes(path
);
525 this->SetHomeOutputDirectory(path
.c_str());
527 else if((i
< args
.size()-1) && (arg
.find("--check-build-system",0) == 0))
529 this->CheckBuildSystemArgument
= args
[++i
];
530 this->ClearBuildSystem
= (atoi(args
[++i
].c_str()) > 0);
532 else if((i
< args
.size()-1) && (arg
.find("--check-stamp-file",0) == 0))
534 this->CheckStampFile
= args
[++i
];
536 #if defined(CMAKE_HAVE_VS_GENERATORS)
537 else if((i
< args
.size()-1) && (arg
.find("--vs-solution-file",0) == 0))
539 this->VSSolutionFile
= args
[++i
];
542 else if(arg
.find("-V",0) == 0)
544 this->Verbose
= true;
546 else if(arg
.find("-D",0) == 0)
550 else if(arg
.find("-U",0) == 0)
554 else if(arg
.find("-C",0) == 0)
558 else if(arg
.find("-P",0) == 0)
563 else if(arg
.find("--graphviz=",0) == 0)
565 std::string path
= arg
.substr(strlen("--graphviz="));
566 path
= cmSystemTools::CollapseFullPath(path
.c_str());
567 cmSystemTools::ConvertToUnixSlashes(path
);
568 this->GraphVizFile
= path
;
569 if ( this->GraphVizFile
.empty() )
571 cmSystemTools::Error("No file specified for --graphviz");
574 else if(arg
.find("--debug-trycompile",0) == 0)
576 std::cout
<< "debug trycompile on\n";
577 this->DebugTryCompileOn();
579 else if(arg
.find("--debug-output",0) == 0)
581 std::cout
<< "Running with debug output on.\n";
582 this->DebugOutputOn();
584 else if(arg
.find("-G",0) == 0)
586 std::string value
= arg
.substr(2);
587 if(value
.size() == 0)
592 cmSystemTools::Error("No generator specified for -G");
597 cmGlobalGenerator
* gen
=
598 this->CreateGlobalGenerator(value
.c_str());
601 cmSystemTools::Error("Could not create named generator ",
606 this->SetGlobalGenerator(gen
);
609 // no option assume it is the path to the source
612 directoriesSet
= true;
613 this->SetDirectoriesFromFile(arg
.c_str());
618 this->SetHomeOutputDirectory
619 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
620 this->SetStartOutputDirectory
621 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
622 this->SetHomeDirectory
623 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
624 this->SetStartDirectory
625 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
628 this->SetStartDirectory(this->GetHomeDirectory());
629 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
632 //----------------------------------------------------------------------------
633 void cmake::SetDirectoriesFromFile(const char* arg
)
635 // Check if the argument refers to a CMakeCache.txt or
636 // CMakeLists.txt file.
637 std::string listPath
;
638 std::string cachePath
;
639 bool argIsFile
= false;
640 if(cmSystemTools::FileIsDirectory(arg
))
642 std::string path
= cmSystemTools::CollapseFullPath(arg
);
643 cmSystemTools::ConvertToUnixSlashes(path
);
644 std::string cacheFile
= path
;
645 cacheFile
+= "/CMakeCache.txt";
646 std::string listFile
= path
;
647 listFile
+= "/CMakeLists.txt";
648 if(cmSystemTools::FileExists(cacheFile
.c_str()))
652 if(cmSystemTools::FileExists(listFile
.c_str()))
657 else if(cmSystemTools::FileExists(arg
))
660 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
661 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
662 name
= cmSystemTools::LowerCase(name
);
663 if(name
== "cmakecache.txt")
665 cachePath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
667 else if(name
== "cmakelists.txt")
669 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
674 // Specified file or directory does not exist. Try to set things
675 // up to produce a meaningful error message.
676 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
677 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
678 name
= cmSystemTools::LowerCase(name
);
679 if(name
== "cmakecache.txt" || name
== "cmakelists.txt")
682 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
690 // If there is a CMakeCache.txt file, use its settings.
691 if(cachePath
.length() > 0)
693 cmCacheManager
* cachem
= this->GetCacheManager();
694 cmCacheManager::CacheIterator it
= cachem
->NewIterator();
695 if(cachem
->LoadCache(cachePath
.c_str()) &&
696 it
.Find("CMAKE_HOME_DIRECTORY"))
698 this->SetHomeOutputDirectory(cachePath
.c_str());
699 this->SetStartOutputDirectory(cachePath
.c_str());
700 this->SetHomeDirectory(it
.GetValue());
701 this->SetStartDirectory(it
.GetValue());
706 // If there is a CMakeLists.txt file, use it as the source tree.
707 if(listPath
.length() > 0)
709 this->SetHomeDirectory(listPath
.c_str());
710 this->SetStartDirectory(listPath
.c_str());
714 // Source CMakeLists.txt file given. It was probably dropped
715 // onto the executable in a GUI. Default to an in-source build.
716 this->SetHomeOutputDirectory(listPath
.c_str());
717 this->SetStartOutputDirectory(listPath
.c_str());
721 // Source directory given on command line. Use current working
722 // directory as build tree.
723 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
724 this->SetHomeOutputDirectory(cwd
.c_str());
725 this->SetStartOutputDirectory(cwd
.c_str());
730 // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
731 // argument. Assume it is the path to the source tree, and use the
732 // current working directory as the build tree.
733 std::string full
= cmSystemTools::CollapseFullPath(arg
);
734 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
735 this->SetHomeDirectory(full
.c_str());
736 this->SetStartDirectory(full
.c_str());
737 this->SetHomeOutputDirectory(cwd
.c_str());
738 this->SetStartOutputDirectory(cwd
.c_str());
741 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
743 int cmake::AddCMakePaths()
745 // Find the cmake executable
746 std::string cMakeSelf
= cmSystemTools::GetExecutableDirectory();
747 cMakeSelf
+= "/cmake";
748 cMakeSelf
+= cmSystemTools::GetExecutableExtension();
749 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
751 cmSystemTools::Error("CMake executable cannot be found at ",
755 // Save the value in the cache
756 this->CacheManager
->AddCacheEntry
757 ("CMAKE_COMMAND",cMakeSelf
.c_str(), "Path to CMake executable.",
758 cmCacheManager::INTERNAL
);
760 // Find and save the command to edit the cache
761 std::string editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
762 "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
763 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
765 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
766 "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
768 if(cmSystemTools::FileExists(editCacheCommand
.c_str()))
770 this->CacheManager
->AddCacheEntry
771 ("CMAKE_EDIT_COMMAND", editCacheCommand
.c_str(),
772 "Path to cache edit program executable.", cmCacheManager::INTERNAL
);
774 std::string ctestCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
775 "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
776 if(cmSystemTools::FileExists(ctestCommand
.c_str()))
778 this->CacheManager
->AddCacheEntry
779 ("CMAKE_CTEST_COMMAND", ctestCommand
.c_str(),
780 "Path to ctest program executable.", cmCacheManager::INTERNAL
);
782 std::string cpackCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
783 "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
784 if(cmSystemTools::FileExists(ctestCommand
.c_str()))
786 this->CacheManager
->AddCacheEntry
787 ("CMAKE_CPACK_COMMAND", cpackCommand
.c_str(),
788 "Path to cpack program executable.", cmCacheManager::INTERNAL
);
791 // do CMAKE_ROOT, look for the environment variable first
792 std::string cMakeRoot
;
794 if (getenv("CMAKE_ROOT"))
796 cMakeRoot
= getenv("CMAKE_ROOT");
797 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
799 if(!cmSystemTools::FileExists(modules
.c_str()))
802 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
803 std::string::size_type slashPos
= cMakeRoot
.rfind("/");
804 if(slashPos
!= std::string::npos
)
806 cMakeRoot
= cMakeRoot
.substr(0, slashPos
);
808 // is there no Modules direcory there?
809 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
812 if (!cmSystemTools::FileExists(modules
.c_str()))
814 // try exe/../share/cmake
815 cMakeRoot
+= CMAKE_DATA_DIR
;
816 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
818 #ifdef CMAKE_ROOT_DIR
819 if (!cmSystemTools::FileExists(modules
.c_str()))
821 // try compiled in root directory
822 cMakeRoot
= CMAKE_ROOT_DIR
;
823 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
827 if (!cmSystemTools::FileExists(modules
.c_str()))
829 // try compiled in install prefix
830 cMakeRoot
= CMAKE_PREFIX CMAKE_DATA_DIR
;
831 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
834 if (!cmSystemTools::FileExists(modules
.c_str()))
837 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
838 cMakeRoot
+= CMAKE_DATA_DIR
;
839 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
841 if(!cmSystemTools::FileExists(modules
.c_str()))
844 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
845 // is there no Modules direcory there?
846 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
848 if (!cmSystemTools::FileExists(modules
.c_str()))
850 // couldn't find modules
851 cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n"
852 "CMake has most likely not been installed correctly.\n"
853 "Modules directory not found in\n",
857 this->CacheManager
->AddCacheEntry
858 ("CMAKE_ROOT", cMakeRoot
.c_str(),
859 "Path to CMake installation.", cmCacheManager::INTERNAL
);
862 std::string comspec
= "cmw9xcom.exe";
863 cmSystemTools::SetWindows9xComspecSubstitute(comspec
.c_str());
870 void CMakeCommandUsage(const char* program
)
872 cmOStringStream errorStream
;
874 #ifdef CMAKE_BUILD_WITH_CMAKE
876 << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
879 << "cmake bootstrap\n";
883 << "Usage: " << program
<< " -E [command] [arguments ...]\n"
884 << "Available commands: \n"
885 << " chdir dir cmd [args]... - run command in a given directory\n"
886 << " copy file destination - copy file to destination (either file "
888 << " copy_if_different in-file out-file - copy file if input has "
890 << " copy_directory source destination - copy directory 'source' "
891 "content to directory 'destination'\n"
892 << " compare_files file1 file2 - check if file1 is same as file2\n"
893 << " echo [string]... - displays arguments as text\n"
894 << " echo_append [string]... - displays arguments as text but no new "
896 << " environment - display the current enviroment\n"
897 << " make_directory dir - create a directory\n"
898 << " md5sum file1 [...] - compute md5sum of files\n"
899 << " remove_directory dir - remove a directory and its contents\n"
900 << " remove [-f] file1 file2 ... - remove the file(s), use -f to force "
902 << " tar [cxt][vfz] file.tar file/dir1 file/dir2 ... - create a tar "
904 << " time command [args] ... - run command and return elapsed time\n"
905 << " touch file - touch a file.\n"
906 << " touch_nocreate file - touch a file but do not create it.\n"
907 #if defined(_WIN32) && !defined(__CYGWIN__)
908 << " write_regv key value - write registry value\n"
909 << " delete_regv key - delete registry value\n"
910 << " comspec - on windows 9x use this for RunCommand\n"
912 << " create_symlink old new - create a symbolic link new -> old\n"
916 cmSystemTools::Error(errorStream
.str().c_str());
919 int cmake::ExecuteCMakeCommand(std::vector
<std::string
>& args
)
924 if (args
[1] == "copy" && args
.size() == 4)
926 if(!cmSystemTools::cmCopyFile(args
[2].c_str(), args
[3].c_str()))
928 std::cerr
<< "Error copying file \"" << args
[2].c_str()
929 << "\" to \"" << args
[3].c_str() << "\".\n";
935 // Copy file if different.
936 if (args
[1] == "copy_if_different" && args
.size() == 4)
938 if(!cmSystemTools::CopyFileIfDifferent(args
[2].c_str(),
941 std::cerr
<< "Error copying file (if different) from \""
942 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
949 // Copy directory content
950 if (args
[1] == "copy_directory" && args
.size() == 4)
952 if(!cmSystemTools::CopyADirectory(args
[2].c_str(), args
[3].c_str()))
954 std::cerr
<< "Error copying directory from \""
955 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
963 if (args
[1] == "compare_files" && args
.size() == 4)
965 if(cmSystemTools::FilesDiffer(args
[2].c_str(), args
[3].c_str()))
967 std::cerr
<< "Files \""
968 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
969 << "\" are different.\n";
976 else if (args
[1] == "echo" )
979 const char* space
= "";
980 for ( cc
= 2; cc
< args
.size(); cc
++ )
982 std::cout
<< space
<< args
[cc
];
985 std::cout
<< std::endl
;
989 // Echo string no new line
990 else if (args
[1] == "echo_append" )
993 const char* space
= "";
994 for ( cc
= 2; cc
< args
.size(); cc
++ )
996 std::cout
<< space
<< args
[cc
];
1002 #if defined(CMAKE_BUILD_WITH_CMAKE)
1003 // Command to create a symbolic link. Fails on platforms not
1005 else if (args
[1] == "environment" )
1007 std::vector
<std::string
> env
= cmSystemTools::GetEnvironmentVariables();
1008 std::vector
<std::string
>::iterator it
;
1009 for ( it
= env
.begin(); it
!= env
.end(); ++ it
)
1011 std::cout
<< it
->c_str() << std::endl
;
1017 else if (args
[1] == "make_directory" && args
.size() == 3)
1019 if(!cmSystemTools::MakeDirectory(args
[2].c_str()))
1021 std::cerr
<< "Error making directory \"" << args
[2].c_str()
1028 else if (args
[1] == "remove_directory" && args
.size() == 3)
1030 if(!cmSystemTools::RemoveADirectory(args
[2].c_str()))
1032 std::cerr
<< "Error removing directory \"" << args
[2].c_str()
1040 else if (args
[1] == "remove" && args
.size() > 2)
1043 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1045 if(args
[cc
] == "\\-f" || args
[cc
] == "-f")
1051 // Complain if the file could not be removed, still exists,
1052 // and the -f option was not given.
1053 if(!cmSystemTools::RemoveFile(args
[cc
].c_str()) && !force
&&
1054 cmSystemTools::FileExists(args
[cc
].c_str()))
1063 else if (args
[1] == "touch" && args
.size() > 2)
1065 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1067 // Complain if the file could not be removed, still exists,
1068 // and the -f option was not given.
1069 if(!cmSystemTools::Touch(args
[cc
].c_str(), true))
1077 else if (args
[1] == "touch_nocreate" && args
.size() > 2)
1079 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1081 // Complain if the file could not be removed, still exists,
1082 // and the -f option was not given.
1083 if(!cmSystemTools::Touch(args
[cc
].c_str(), false))
1092 else if (args
[1] == "time" && args
.size() > 2)
1094 std::string command
= args
[2];
1095 for (std::string::size_type cc
= 3; cc
< args
.size(); cc
++)
1098 command
+= args
[cc
];
1101 clock_t clock_start
, clock_finish
;
1102 time_t time_start
, time_finish
;
1105 clock_start
= clock();
1107 cmSystemTools::RunSingleCommand(command
.c_str());
1109 clock_finish
= clock();
1112 double clocks_per_sec
= static_cast<double>(CLOCKS_PER_SEC
);
1113 std::cout
<< "Elapsed time: "
1114 << static_cast<long>(time_finish
- time_start
) << " s. (time)"
1116 << static_cast<double>(clock_finish
- clock_start
) / clocks_per_sec
1122 // Command to calculate the md5sum of a file
1123 else if (args
[1] == "md5sum" && args
.size() >= 3)
1127 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1129 const char *filename
= args
[cc
].c_str();
1130 // Cannot compute md5sum of a directory
1131 if(cmSystemTools::FileIsDirectory(filename
))
1133 std::cerr
<< "Error: " << filename
<< " is a directory" << std::endl
;
1136 else if(!cmSystemTools::ComputeFileMD5(filename
, md5out
))
1138 // To mimic md5sum behavior in a shell:
1139 std::cerr
<< filename
<< ": No such file or directory" << std::endl
;
1144 std::cout
<< std::string(md5out
,32) << " " << filename
<< std::endl
;
1150 // Command to change directory and run a program.
1151 else if (args
[1] == "chdir" && args
.size() >= 4)
1153 std::string directory
= args
[2];
1154 if(!cmSystemTools::FileExists(directory
.c_str()))
1156 cmSystemTools::Error("Directory does not exist for chdir command: ",
1161 std::string command
= "\"";
1164 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1167 command
+= args
[cc
];
1172 if ( cmSystemTools::RunSingleCommand(command
.c_str(), 0, &retval
,
1173 directory
.c_str(), true, timeout
) )
1181 // Command to start progress for a build
1182 else if (args
[1] == "cmake_progress_start" && args
.size() == 4)
1184 // bascially remove the directory
1185 std::string dirName
= args
[2];
1186 dirName
+= "/Progress";
1187 cmSystemTools::RemoveADirectory(dirName
.c_str());
1189 // is the last argument a filename that exists?
1190 FILE *countFile
= fopen(args
[3].c_str(),"r");
1194 fscanf(countFile
,"%i",&count
);
1199 count
= atoi(args
[3].c_str());
1203 cmSystemTools::MakeDirectory(dirName
.c_str());
1204 // write the count into the directory
1205 std::string fName
= dirName
;
1206 fName
+= "/count.txt";
1207 FILE *progFile
= fopen(fName
.c_str(),"w");
1210 fprintf(progFile
,"%i\n",count
);
1217 // Command to report progress for a build
1218 else if (args
[1] == "cmake_progress_report" && args
.size() >= 3)
1220 std::string dirName
= args
[2];
1221 dirName
+= "/Progress";
1227 fName
+= "/count.txt";
1228 progFile
= fopen(fName
.c_str(),"r");
1236 fscanf(progFile
,"%i",&count
);
1240 for (i
= 3; i
< args
.size(); ++i
)
1245 progFile
= fopen(fName
.c_str(),"w");
1248 fprintf(progFile
,"empty");
1252 int fileNum
= static_cast<int>
1253 (cmsys::Directory::GetNumberOfFilesInDirectory(dirName
.c_str()));
1256 // print the progress
1257 fprintf(stdout
,"[%3i%%] ",((fileNum
-3)*100)/count
);
1262 // Command to create a symbolic link. Fails on platforms not
1264 else if (args
[1] == "create_symlink" && args
.size() == 4)
1266 const char* destinationFileName
= args
[3].c_str();
1267 if ( cmSystemTools::FileExists(destinationFileName
) )
1269 if ( cmSystemTools::FileIsSymlink(destinationFileName
) )
1271 if ( !cmSystemTools::RemoveFile(destinationFileName
) ||
1272 cmSystemTools::FileExists(destinationFileName
) )
1282 return cmSystemTools::CreateSymlink(args
[2].c_str(),
1283 args
[3].c_str())? 0:1;
1286 // Internal CMake shared library support.
1287 else if (args
[1] == "cmake_symlink_library" && args
.size() == 5)
1290 std::string realName
= args
[2];
1291 std::string soName
= args
[3];
1292 std::string name
= args
[4];
1293 if(soName
!= realName
)
1295 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1296 if(cmSystemTools::FileExists(soName
.c_str()))
1298 cmSystemTools::RemoveFile(soName
.c_str());
1300 if(!cmSystemTools::CreateSymlink(fname
.c_str(), soName
.c_str()))
1307 std::string fname
= cmSystemTools::GetFilenameName(soName
);
1308 if(cmSystemTools::FileExists(soName
.c_str()))
1310 cmSystemTools::RemoveFile(name
.c_str());
1312 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1319 // Internal CMake versioned executable support.
1320 else if (args
[1] == "cmake_symlink_executable" && args
.size() == 4)
1323 std::string realName
= args
[2];
1324 std::string name
= args
[3];
1325 if(name
!= realName
)
1327 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1328 if(cmSystemTools::FileExists(realName
.c_str()))
1330 cmSystemTools::RemoveFile(name
.c_str());
1332 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1340 #if defined(CMAKE_HAVE_VS_GENERATORS)
1341 // Internal CMake support for calling Visual Studio macros.
1342 else if (args
[1] == "cmake_call_visual_studio_macro" && args
.size() >= 4)
1344 // args[2] = full path to .sln file or "ALL"
1345 // args[3] = name of Visual Studio macro to call
1346 // args[4..args.size()-1] = [optional] args for Visual Studio macro
1348 std::string macroArgs
;
1350 if (args
.size() > 4)
1352 macroArgs
= args
[4];
1354 for (size_t i
= 5; i
< args
.size(); ++i
)
1357 macroArgs
+= args
[i
];
1361 return cmCallVisualStudioMacro::CallMacro(args
[2], args
[3], macroArgs
);
1365 // Internal CMake dependency scanning support.
1366 else if (args
[1] == "cmake_depends" && args
.size() >= 6)
1368 // Use the make system's VERBOSE environment variable to enable
1370 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
1372 // Create a cmake object instance to process dependencies.
1375 std::string homeDir
;
1376 std::string startDir
;
1377 std::string homeOutDir
;
1378 std::string startOutDir
;
1379 std::string depInfo
;
1381 if(args
.size() >= 8)
1385 // -E cmake_depends <generator>
1386 // <home-src-dir> <start-src-dir>
1387 // <home-out-dir> <start-out-dir>
1388 // <dep-info> [--color=$(COLOR)]
1390 // All paths are provided.
1394 homeOutDir
= args
[5];
1395 startOutDir
= args
[6];
1397 if(args
.size() >= 9 &&
1398 args
[8].length() > 8 &&
1399 args
[8].substr(0, 8) == "--color=")
1401 // Enable or disable color based on the switch value.
1402 color
= cmSystemTools::IsOn(args
[8].substr(8).c_str());
1407 // Support older signature for existing makefiles:
1409 // -E cmake_depends <generator>
1410 // <home-out-dir> <start-out-dir>
1413 // Just pretend the source directories are the same as the
1414 // binary directories so at least scanning will work.
1418 homeOutDir
= args
[3];
1419 startOutDir
= args
[3];
1423 // Create a local generator configured for the directory in
1424 // which dependencies will be scanned.
1425 homeDir
= cmSystemTools::CollapseFullPath(homeDir
.c_str());
1426 startDir
= cmSystemTools::CollapseFullPath(startDir
.c_str());
1427 homeOutDir
= cmSystemTools::CollapseFullPath(homeOutDir
.c_str());
1428 startOutDir
= cmSystemTools::CollapseFullPath(startOutDir
.c_str());
1429 cm
.SetHomeDirectory(homeDir
.c_str());
1430 cm
.SetStartDirectory(startDir
.c_str());
1431 cm
.SetHomeOutputDirectory(homeOutDir
.c_str());
1432 cm
.SetStartOutputDirectory(startOutDir
.c_str());
1433 if(cmGlobalGenerator
* ggd
= cm
.CreateGlobalGenerator(gen
.c_str()))
1435 cm
.SetGlobalGenerator(ggd
);
1436 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
1437 lgd
->SetGlobalGenerator(ggd
);
1438 lgd
->GetMakefile()->SetStartDirectory(startDir
.c_str());
1439 lgd
->GetMakefile()->SetStartOutputDirectory(startOutDir
.c_str());
1440 lgd
->GetMakefile()->MakeStartDirectoriesCurrent();
1442 // Actually scan dependencies.
1443 return lgd
->UpdateDependencies(depInfo
.c_str(),
1444 verbose
, color
)? 0 : 2;
1449 // Internal CMake link script support.
1450 else if (args
[1] == "cmake_link_script" && args
.size() >= 3)
1452 return cmake::ExecuteLinkScript(args
);
1455 // Internal CMake unimplemented feature notification.
1456 else if (args
[1] == "cmake_unimplemented_variable")
1458 std::cerr
<< "Feature not implemented for this platform.";
1459 if(args
.size() == 3)
1461 std::cerr
<< " Variable " << args
[2] << " is not set.";
1463 std::cerr
<< std::endl
;
1466 else if (args
[1] == "vs_link_exe")
1468 return cmake::VisualStudioLink(args
, 1);
1470 else if (args
[1] == "vs_link_dll")
1472 return cmake::VisualStudioLink(args
, 2);
1474 #ifdef CMAKE_BUILD_WITH_CMAKE
1475 // Internal CMake color makefile support.
1476 else if (args
[1] == "cmake_echo_color")
1478 return cmake::ExecuteEchoColor(args
);
1483 else if (args
[1] == "tar" && args
.size() > 3)
1485 std::string flags
= args
[2];
1486 std::string outFile
= args
[3];
1487 std::vector
<cmStdString
> files
;
1488 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1490 files
.push_back(args
[cc
]);
1493 bool verbose
= false;
1494 if ( flags
.find_first_of('z') != flags
.npos
)
1498 if ( flags
.find_first_of('v') != flags
.npos
)
1503 if ( flags
.find_first_of('t') != flags
.npos
)
1505 if ( !cmSystemTools::ListTar(outFile
.c_str(), files
, gzip
, verbose
) )
1507 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1511 else if ( flags
.find_first_of('c') != flags
.npos
)
1513 if ( !cmSystemTools::CreateTar(
1514 outFile
.c_str(), files
, gzip
, verbose
) )
1516 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1520 else if ( flags
.find_first_of('x') != flags
.npos
)
1522 if ( !cmSystemTools::ExtractTar(
1523 outFile
.c_str(), files
, gzip
, verbose
) )
1525 cmSystemTools::Error("Problem extracting tar: ", outFile
.c_str());
1532 #if defined(CMAKE_BUILD_WITH_CMAKE)
1533 // Internal CMake Fortran module support.
1534 else if (args
[1] == "cmake_copy_f90_mod" && args
.size() >= 4)
1536 return cmDependsFortran::CopyModule(args
)? 0 : 1;
1540 #if defined(_WIN32) && !defined(__CYGWIN__)
1541 // Write registry value
1542 else if (args
[1] == "write_regv" && args
.size() > 3)
1544 return cmSystemTools::WriteRegistryValue(args
[2].c_str(),
1545 args
[3].c_str()) ? 0 : 1;
1548 // Delete registry value
1549 else if (args
[1] == "delete_regv" && args
.size() > 2)
1551 return cmSystemTools::DeleteRegistryValue(args
[2].c_str()) ? 0 : 1;
1554 else if (args
[1] == "comspec" && args
.size() > 2)
1557 std::string command
= args
[2];
1558 for ( cc
= 3; cc
< args
.size(); cc
++ )
1560 command
+= " " + args
[cc
];
1562 return cmWin32ProcessExecution::Windows9xHack(command
.c_str());
1567 ::CMakeCommandUsage(args
[0].c_str());
1571 void cmake::AddExtraGenerator(const char* name
,
1572 CreateExtraGeneratorFunctionType newFunction
)
1574 cmExternalMakefileProjectGenerator
* extraGenerator
= newFunction();
1575 const std::vector
<std::string
>& supportedGlobalGenerators
=
1576 extraGenerator
->GetSupportedGlobalGenerators();
1578 for(std::vector
<std::string
>::const_iterator
1579 it
= supportedGlobalGenerators
.begin();
1580 it
!= supportedGlobalGenerators
.end();
1583 std::string fullName
= cmExternalMakefileProjectGenerator::
1584 CreateFullGeneratorName(it
->c_str(), name
);
1585 this->ExtraGenerators
[fullName
.c_str()] = newFunction
;
1587 delete extraGenerator
;
1590 void cmake::AddDefaultExtraGenerators()
1592 #if defined(CMAKE_BUILD_WITH_CMAKE)
1593 #if defined(_WIN32) && !defined(__CYGWIN__)
1597 #if !defined(__CYGWIN__)
1598 this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
1599 &cmExtraCodeBlocksGenerator::New
);
1602 #ifdef CMAKE_USE_ECLIPSE
1603 this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
1604 &cmExtraEclipseCDT4Generator::New
);
1607 #ifdef CMAKE_USE_KDEVELOP
1608 this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
1609 &cmGlobalKdevelopGenerator::New
);
1610 // for kdevelop also add the generator with just the name of the
1611 // extra generator, since it was this way since cmake 2.2
1612 this->ExtraGenerators
[cmGlobalKdevelopGenerator::GetActualName()]
1613 = &cmGlobalKdevelopGenerator::New
;
1620 //----------------------------------------------------------------------------
1621 void cmake::GetRegisteredGenerators(std::vector
<std::string
>& names
)
1623 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
1624 i
!= this->Generators
.end(); ++i
)
1626 names
.push_back(i
->first
);
1628 for(RegisteredExtraGeneratorsMap::const_iterator
1629 i
= this->ExtraGenerators
.begin();
1630 i
!= this->ExtraGenerators
.end(); ++i
)
1632 names
.push_back(i
->first
);
1636 cmGlobalGenerator
* cmake::CreateGlobalGenerator(const char* name
)
1638 cmGlobalGenerator
* generator
= 0;
1639 cmExternalMakefileProjectGenerator
* extraGenerator
= 0;
1640 RegisteredGeneratorsMap::const_iterator genIt
= this->Generators
.find(name
);
1641 if(genIt
== this->Generators
.end())
1643 RegisteredExtraGeneratorsMap::const_iterator extraGenIt
=
1644 this->ExtraGenerators
.find(name
);
1645 if (extraGenIt
== this->ExtraGenerators
.end())
1649 extraGenerator
= (extraGenIt
->second
)();
1650 genIt
=this->Generators
.find(extraGenerator
->GetGlobalGeneratorName(name
));
1651 if(genIt
== this->Generators
.end())
1653 delete extraGenerator
;
1658 generator
= (genIt
->second
)();
1659 generator
->SetCMakeInstance(this);
1660 generator
->SetExternalMakefileProjectGenerator(extraGenerator
);
1664 void cmake::SetHomeDirectory(const char* dir
)
1666 this->cmHomeDirectory
= dir
;
1667 cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory
);
1670 void cmake::SetHomeOutputDirectory(const char* lib
)
1672 this->HomeOutputDirectory
= lib
;
1673 cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory
);
1676 void cmake::SetGlobalGenerator(cmGlobalGenerator
*gg
)
1680 cmSystemTools::Error("Error SetGlobalGenerator called with null");
1683 // delete the old generator
1684 if (this->GlobalGenerator
)
1686 delete this->GlobalGenerator
;
1687 // restore the original environment variables CXX and CC
1689 std::string env
= "CC=";
1690 if(this->CCEnvironment
.size())
1692 env
+= this->CCEnvironment
;
1694 cmSystemTools::PutEnv(env
.c_str());
1696 if(this->CXXEnvironment
.size())
1698 env
+= this->CXXEnvironment
;
1700 cmSystemTools::PutEnv(env
.c_str());
1704 this->GlobalGenerator
= gg
;
1706 // set the global flag for unix style paths on cmSystemTools as soon as
1707 // the generator is set. This allows gmake to be used on windows.
1708 cmSystemTools::SetForceUnixPaths
1709 (this->GlobalGenerator
->GetForceUnixPaths());
1711 // Save the environment variables CXX and CC
1712 const char* cxx
= getenv("CXX");
1713 const char* cc
= getenv("CC");
1716 this->CXXEnvironment
= cxx
;
1720 this->CXXEnvironment
= "";
1724 this->CCEnvironment
= cc
;
1728 this->CCEnvironment
= "";
1730 // set the cmake instance just to be sure
1731 gg
->SetCMakeInstance(this);
1734 int cmake::DoPreConfigureChecks()
1736 // Make sure the Start directory contains a CMakeLists.txt file.
1737 std::string srcList
= this->GetHomeDirectory();
1738 srcList
+= "/CMakeLists.txt";
1739 if(!cmSystemTools::FileExists(srcList
.c_str()))
1741 cmOStringStream err
;
1742 if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
1744 err
<< "The source directory \"" << this->GetHomeDirectory()
1745 << "\" does not appear to contain CMakeLists.txt.\n";
1747 else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
1749 err
<< "The source directory \"" << this->GetHomeDirectory()
1750 << "\" is a file, not a directory.\n";
1754 err
<< "The source directory \"" << this->GetHomeDirectory()
1755 << "\" does not exist.\n";
1757 err
<< "Specify --help for usage, or press the help button on the CMake "
1759 cmSystemTools::Error(err
.str().c_str());
1763 // do a sanity check on some values
1764 if(this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY"))
1766 std::string cacheStart
=
1767 this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY");
1768 cacheStart
+= "/CMakeLists.txt";
1769 std::string currentStart
= this->GetHomeDirectory();
1770 currentStart
+= "/CMakeLists.txt";
1771 if(!cmSystemTools::SameFile(cacheStart
.c_str(), currentStart
.c_str()))
1773 std::string message
= "The source \"";
1774 message
+= currentStart
;
1775 message
+= "\" does not match the source \"";
1776 message
+= cacheStart
;
1777 message
+= "\" used to generate cache. ";
1778 message
+= "Re-run cmake with a different source directory.";
1779 cmSystemTools::Error(message
.c_str());
1789 struct SaveCacheEntry
1794 cmCacheManager::CacheEntryType type
;
1797 int cmake::HandleDeleteCacheVariables(const char* var
)
1799 std::vector
<std::string
> argsSplit
;
1800 cmSystemTools::ExpandListArgument(std::string(var
), argsSplit
);
1801 // erase the property to avoid infinite recursion
1802 this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
1804 cmCacheManager::CacheIterator ci
= this->CacheManager
->NewIterator();
1805 std::vector
<SaveCacheEntry
> saved
;
1806 cmOStringStream warning
;
1808 << "You have changed variables that require your cache to be deleted.\n"
1809 << "Configure will be re-run and you may have to reset some variables.\n"
1810 << "The following variables have changed:\n";
1811 for(std::vector
<std::string
>::iterator i
= argsSplit
.begin();
1812 i
!= argsSplit
.end(); ++i
)
1814 SaveCacheEntry save
;
1816 warning
<< *i
<< "= ";
1819 warning
<< *i
<< "\n";
1820 if(ci
.Find(save
.key
.c_str()))
1822 save
.type
= ci
.GetType();
1823 save
.help
= ci
.GetProperty("HELPSTRING");
1825 saved
.push_back(save
);
1829 this->CacheManager
->DeleteCache(this->GetStartOutputDirectory());
1830 // load the empty cache
1832 // restore the changed compilers
1833 for(std::vector
<SaveCacheEntry
>::iterator i
= saved
.begin();
1834 i
!= saved
.end(); ++i
)
1836 this->AddCacheEntry(i
->key
.c_str(), i
->value
.c_str(),
1837 i
->help
.c_str(), i
->type
);
1839 cmSystemTools::Message(warning
.str().c_str());
1840 // avoid reconfigure if there were errors
1841 if(!cmSystemTools::GetErrorOccuredFlag())
1844 return this->Configure();
1849 int cmake::Configure()
1851 int ret
= this->ActualConfigure();
1852 const char* delCacheVars
=
1853 this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
1854 if(delCacheVars
&& delCacheVars
[0] != 0)
1856 return this->HandleDeleteCacheVariables(delCacheVars
);
1862 int cmake::ActualConfigure()
1864 // Construct right now our path conversion table before it's too late:
1865 this->UpdateConversionPathTable();
1866 this->CleanupCommandsAndMacros();
1869 if ( !this->ScriptMode
)
1871 res
= this->DoPreConfigureChecks();
1879 this->CacheManager
->AddCacheEntry
1880 ("CMAKE_HOME_DIRECTORY",
1881 this->GetHomeDirectory(),
1882 "Start directory with the top level CMakeLists.txt file for this "
1884 cmCacheManager::INTERNAL
);
1887 // set the default BACKWARDS compatibility to the current version
1888 if(!this->CacheManager
->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
1891 sprintf(ver
,"%i.%i",cmVersion::GetMajorVersion(),
1892 cmVersion::GetMinorVersion());
1893 this->CacheManager
->AddCacheEntry
1894 ("CMAKE_BACKWARDS_COMPATIBILITY",ver
,
1895 "For backwards compatibility, what version of CMake commands and "
1896 "syntax should this version of CMake allow.",
1897 cmCacheManager::STRING
);
1900 // no generator specified on the command line
1901 if(!this->GlobalGenerator
)
1903 const char* genName
=
1904 this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
1905 const char* extraGenName
=
1906 this->CacheManager
->GetCacheValue("CMAKE_EXTRA_GENERATOR");
1909 std::string fullName
= cmExternalMakefileProjectGenerator::
1910 CreateFullGeneratorName(genName
, extraGenName
);
1911 this->GlobalGenerator
= this->CreateGlobalGenerator(fullName
.c_str());
1913 if(this->GlobalGenerator
)
1915 // set the global flag for unix style paths on cmSystemTools as
1916 // soon as the generator is set. This allows gmake to be used
1918 cmSystemTools::SetForceUnixPaths
1919 (this->GlobalGenerator
->GetForceUnixPaths());
1923 #if defined(__BORLANDC__) && defined(_WIN32)
1924 this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator
);
1925 #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
1926 std::string installedCompiler
;
1927 std::string mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1928 "\\VisualStudio\\8.0\\Setup;Dbghelp_path]";
1929 cmSystemTools::ExpandRegistryValues(mp
);
1930 if (!(mp
== "/registry"))
1932 installedCompiler
= "Visual Studio 8 2005";
1936 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1937 "\\VisualStudio\\7.1;InstallDir]";
1938 cmSystemTools::ExpandRegistryValues(mp
);
1939 if (!(mp
== "/registry"))
1941 installedCompiler
= "Visual Studio 7 .NET 2003";
1945 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1946 "\\VisualStudio\\7.0;InstallDir]";
1947 cmSystemTools::ExpandRegistryValues(mp
);
1948 if (!(mp
== "/registry"))
1950 installedCompiler
= "Visual Studio 7";
1954 installedCompiler
= "Visual Studio 6";
1958 cmGlobalGenerator
* gen
1959 = this->CreateGlobalGenerator(installedCompiler
.c_str());
1962 gen
= new cmGlobalNMakeMakefileGenerator
;
1964 this->SetGlobalGenerator(gen
);
1966 this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3
);
1969 if(!this->GlobalGenerator
)
1971 cmSystemTools::Error("Could not create generator");
1976 const char* genName
= this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
1979 if(strcmp(this->GlobalGenerator
->GetName(), genName
) != 0)
1981 std::string message
= "Error: generator : ";
1982 message
+= this->GlobalGenerator
->GetName();
1983 message
+= "\nDoes not match the generator used previously: ";
1986 "\nEither remove the CMakeCache.txt file or choose a different"
1987 " binary directory.";
1988 cmSystemTools::Error(message
.c_str());
1992 if(!this->CacheManager
->GetCacheValue("CMAKE_GENERATOR"))
1994 this->CacheManager
->AddCacheEntry("CMAKE_GENERATOR",
1995 this->GlobalGenerator
->GetName(),
1996 "Name of generator.",
1997 cmCacheManager::INTERNAL
);
1998 this->CacheManager
->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
1999 this->GlobalGenerator
->GetExtraGeneratorName(),
2000 "Name of external makefile project generator.",
2001 cmCacheManager::INTERNAL
);
2004 // reset any system configuration information, except for when we are
2005 // InTryCompile. With TryCompile the system info is taken from the parent's
2006 // info to save time
2007 if (!this->InTryCompile
)
2009 this->GlobalGenerator
->ClearEnabledLanguages();
2012 this->CleanupWrittenFiles();
2014 // Truncate log files
2015 if (!this->InTryCompile
)
2017 this->TruncateOutputLog("CMakeOutput.log");
2018 this->TruncateOutputLog("CMakeError.log");
2021 // actually do the configure
2022 this->GlobalGenerator
->Configure();
2023 // Before saving the cache
2024 // if the project did not define one of the entries below, add them now
2025 // so users can edit the values in the cache:
2026 // LIBRARY_OUTPUT_PATH
2027 // EXECUTABLE_OUTPUT_PATH
2028 if(!this->CacheManager
->GetCacheValue("LIBRARY_OUTPUT_PATH"))
2030 this->CacheManager
->AddCacheEntry
2031 ("LIBRARY_OUTPUT_PATH", "",
2032 "Single output directory for building all libraries.",
2033 cmCacheManager::PATH
);
2035 if(!this->CacheManager
->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
2037 this->CacheManager
->AddCacheEntry
2038 ("EXECUTABLE_OUTPUT_PATH", "",
2039 "Single output directory for building all executables.",
2040 cmCacheManager::PATH
);
2042 if(!this->CacheManager
->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
2044 this->CacheManager
->AddCacheEntry
2045 ("CMAKE_USE_RELATIVE_PATHS", false,
2046 "If true, cmake will use relative paths in makefiles and projects.");
2047 cmCacheManager::CacheIterator it
=
2048 this->CacheManager
->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
2049 if ( !it
.PropertyExists("ADVANCED") )
2051 it
.SetProperty("ADVANCED", "1");
2055 if(cmSystemTools::GetFatalErrorOccured() &&
2056 (!this->CacheManager
->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
2057 cmSystemTools::IsOff(this->CacheManager
->
2058 GetCacheValue("CMAKE_MAKE_PROGRAM"))))
2060 // We must have a bad generator selection. Wipe the cache entry so the
2061 // user can select another.
2062 this->CacheManager
->RemoveCacheEntry("CMAKE_GENERATOR");
2063 this->CacheManager
->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
2065 // only save the cache if there were no fatal errors
2066 if ( !this->ScriptMode
)
2068 this->CacheManager
->SaveCache(this->GetHomeOutputDirectory());
2070 if ( !this->GraphVizFile
.empty() )
2072 std::cout
<< "Generate graphviz: " << this->GraphVizFile
<< std::endl
;
2073 this->GenerateGraphViz(this->GraphVizFile
.c_str());
2075 if(cmSystemTools::GetErrorOccuredFlag())
2082 bool cmake::CacheVersionMatches()
2085 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION");
2087 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MINOR_VERSION");
2089 this->CacheManager
->GetCacheValue("CMAKE_CACHE_RELEASE_VERSION");
2090 bool cacheSameCMake
= false;
2092 atoi(majv
) == static_cast<int>(cmVersion::GetMajorVersion())
2094 atoi(minv
) == static_cast<int>(cmVersion::GetMinorVersion())
2095 && relv
&& (strcmp(relv
, cmVersion::GetReleaseVersion().c_str()) == 0))
2097 cacheSameCMake
= true;
2099 return cacheSameCMake
;
2102 void cmake::PreLoadCMakeFiles()
2104 std::string pre_load
= this->GetHomeDirectory();
2105 if ( pre_load
.size() > 0 )
2107 pre_load
+= "/PreLoad.cmake";
2108 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2110 this->ReadListFile(pre_load
.c_str());
2113 pre_load
= this->GetHomeOutputDirectory();
2114 if ( pre_load
.size() > 0 )
2116 pre_load
+= "/PreLoad.cmake";
2117 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2119 this->ReadListFile(pre_load
.c_str());
2124 // handle a command line invocation
2125 int cmake::Run(const std::vector
<std::string
>& args
, bool noconfigure
)
2127 // Process the arguments
2128 this->SetArgs(args
);
2129 if(cmSystemTools::GetErrorOccuredFlag())
2134 // If we are given a stamp file check if it is really out of date.
2135 if(!this->CheckStampFile
.empty() &&
2136 cmakeCheckStampFile(this->CheckStampFile
.c_str()))
2141 // set the cmake command
2142 this->CMakeCommand
= args
[0];
2144 if ( !this->ScriptMode
)
2147 if(this->LoadCache() < 0)
2149 cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
2155 this->AddCMakePaths();
2158 // Add any cache args
2159 if ( !this->SetCacheArgs(args
) )
2161 cmSystemTools::Error("Problem processing arguments. Aborting.\n");
2165 // In script mode we terminate after running the script.
2166 if(this->ScriptMode
)
2168 if(cmSystemTools::GetErrorOccuredFlag())
2178 this->PreLoadCMakeFiles();
2180 std::string systemFile
= this->GetHomeOutputDirectory();
2181 systemFile
+= "/CMakeSystem.cmake";
2188 // now run the global generate
2189 // Check the state of the build system to see if we need to regenerate.
2190 if(!this->CheckBuildSystem())
2195 // If we are doing global generate, we better set start and start
2196 // output directory to the root of the project.
2197 std::string oldstartdir
= this->GetStartDirectory();
2198 std::string oldstartoutputdir
= this->GetStartOutputDirectory();
2199 this->SetStartDirectory(this->GetHomeDirectory());
2200 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
2201 int ret
= this->Configure();
2202 if (ret
|| this->ScriptMode
)
2204 #if defined(CMAKE_HAVE_VS_GENERATORS)
2205 if(!this->VSSolutionFile
.empty() && this->GlobalGenerator
)
2207 // CMake is running to regenerate a Visual Studio build tree
2208 // during a build from the VS IDE. The build files cannot be
2209 // regenerated, so we should stop the build.
2210 cmSystemTools::Message(
2211 "CMake Configure step failed. "
2212 "Build files cannot be regenerated correctly. "
2213 "Attempting to stop IDE build.");
2214 cmGlobalVisualStudioGenerator
* gg
=
2215 static_cast<cmGlobalVisualStudioGenerator
*>(this->GlobalGenerator
);
2216 gg
->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop
,
2217 this->VSSolutionFile
.c_str());
2222 ret
= this->Generate();
2223 std::string message
= "Build files have been written to: ";
2224 message
+= this->GetHomeOutputDirectory();
2225 this->UpdateProgress(message
.c_str(), -1);
2230 this->SetStartDirectory(oldstartdir
.c_str());
2231 this->SetStartOutputDirectory(oldstartoutputdir
.c_str());
2236 int cmake::Generate()
2238 if(!this->GlobalGenerator
)
2242 this->GlobalGenerator
->Generate();
2243 if(cmSystemTools::GetErrorOccuredFlag())
2247 if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
2249 this->ReportUndefinedPropertyAccesses
2250 (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
2255 void cmake::AddCacheEntry(const char* key
, const char* value
,
2256 const char* helpString
,
2259 this->CacheManager
->AddCacheEntry(key
, value
,
2261 cmCacheManager::CacheEntryType(type
));
2264 const char* cmake::GetCacheDefinition(const char* name
) const
2266 return this->CacheManager
->GetCacheValue(name
);
2269 int cmake::DumpDocumentationToFile(std::ostream
& f
)
2271 #ifdef CMAKE_BUILD_WITH_CMAKE
2272 // Loop over all registered commands and print out documentation
2277 sprintf(tmp
,"Version %d.%d (%s)", cmVersion::GetMajorVersion(),
2278 cmVersion::GetMinorVersion(),
2279 cmVersion::GetReleaseVersion().c_str());
2281 f
<< "<h1>Documentation for commands of CMake " << tmp
<< "</h1>\n";
2283 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
2284 j
!= this->Commands
.end(); ++j
)
2286 name
= (*j
).second
->GetName();
2287 terse
= (*j
).second
->GetTerseDocumentation();
2288 full
= (*j
).second
->GetFullDocumentation();
2289 f
<< "<li><b>" << name
<< "</b> - " << terse
<< std::endl
2290 << "<br><i>Usage:</i> " << full
<< "</li>" << std::endl
<< std::endl
;
2292 f
<< "</ul></html>\n";
2299 void cmake::AddDefaultCommands()
2301 std::list
<cmCommand
*> commands
;
2302 GetBootstrapCommands(commands
);
2303 GetPredefinedCommands(commands
);
2304 for(std::list
<cmCommand
*>::iterator i
= commands
.begin();
2305 i
!= commands
.end(); ++i
)
2307 this->AddCommand(*i
);
2311 void cmake::AddDefaultGenerators()
2313 #if defined(_WIN32) && !defined(__CYGWIN__)
2314 # if !defined(CMAKE_BOOT_MINGW)
2315 this->Generators
[cmGlobalVisualStudio6Generator::GetActualName()] =
2316 &cmGlobalVisualStudio6Generator::New
;
2317 this->Generators
[cmGlobalVisualStudio7Generator::GetActualName()] =
2318 &cmGlobalVisualStudio7Generator::New
;
2319 this->Generators
[cmGlobalVisualStudio71Generator::GetActualName()] =
2320 &cmGlobalVisualStudio71Generator::New
;
2321 this->Generators
[cmGlobalVisualStudio8Generator::GetActualName()] =
2322 &cmGlobalVisualStudio8Generator::New
;
2323 this->Generators
[cmGlobalVisualStudio9Generator::GetActualName()] =
2324 &cmGlobalVisualStudio9Generator::New
;
2325 this->Generators
[cmGlobalVisualStudio9Win64Generator::GetActualName()] =
2326 &cmGlobalVisualStudio9Win64Generator::New
;
2327 this->Generators
[cmGlobalVisualStudio8Win64Generator::GetActualName()] =
2328 &cmGlobalVisualStudio8Win64Generator::New
;
2329 this->Generators
[cmGlobalBorlandMakefileGenerator::GetActualName()] =
2330 &cmGlobalBorlandMakefileGenerator::New
;
2331 this->Generators
[cmGlobalNMakeMakefileGenerator::GetActualName()] =
2332 &cmGlobalNMakeMakefileGenerator::New
;
2333 this->Generators
[cmGlobalWatcomWMakeGenerator::GetActualName()] =
2334 &cmGlobalWatcomWMakeGenerator::New
;
2336 this->Generators
[cmGlobalMSYSMakefileGenerator::GetActualName()] =
2337 &cmGlobalMSYSMakefileGenerator::New
;
2338 this->Generators
[cmGlobalMinGWMakefileGenerator::GetActualName()] =
2339 &cmGlobalMinGWMakefileGenerator::New
;
2341 this->Generators
[cmGlobalUnixMakefileGenerator3::GetActualName()] =
2342 &cmGlobalUnixMakefileGenerator3::New
;
2343 #ifdef CMAKE_USE_XCODE
2344 this->Generators
[cmGlobalXCodeGenerator::GetActualName()] =
2345 &cmGlobalXCodeGenerator::New
;
2349 int cmake::LoadCache()
2351 // could we not read the cache
2352 if (!this->CacheManager
->LoadCache(this->GetHomeOutputDirectory()))
2354 // if it does exist, but isn;t readable then warn the user
2355 std::string cacheFile
= this->GetHomeOutputDirectory();
2356 cacheFile
+= "/CMakeCache.txt";
2357 if(cmSystemTools::FileExists(cacheFile
.c_str()))
2359 cmSystemTools::Error(
2360 "There is a CMakeCache.txt file for the current binary tree but "
2361 "cmake does not have permission to read it. Please check the "
2362 "permissions of the directory you are trying to run CMake on.");
2367 if (this->CMakeCommand
.size() < 2)
2369 cmSystemTools::Error(
2370 "cmake command was not specified prior to loading the cache in "
2375 // setup CMAKE_ROOT and CMAKE_COMMAND
2376 if(!this->AddCMakePaths())
2381 // set the default BACKWARDS compatibility to the current version
2382 if(!this->CacheManager
->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
2385 sprintf(ver
,"%i.%i",cmVersion::GetMajorVersion(),
2386 cmVersion::GetMinorVersion());
2387 this->CacheManager
->AddCacheEntry
2388 ("CMAKE_BACKWARDS_COMPATIBILITY",ver
,
2389 "For backwards compatibility, what version of CMake commands and "
2390 "syntax should this version of CMake allow.",
2391 cmCacheManager::STRING
);
2397 void cmake::SetProgressCallback(ProgressCallbackType f
, void *cd
)
2399 this->ProgressCallback
= f
;
2400 this->ProgressCallbackClientData
= cd
;
2403 void cmake::UpdateProgress(const char *msg
, float prog
)
2405 if(this->ProgressCallback
&& !this->InTryCompile
)
2407 (*this->ProgressCallback
)(msg
, prog
, this->ProgressCallbackClientData
);
2412 void cmake::GetCommandDocumentation(std::vector
<cmDocumentationEntry
>& v
,
2413 bool withCurrentCommands
,
2414 bool withCompatCommands
) const
2416 for(RegisteredCommandsMap::const_iterator j
= this->Commands
.begin();
2417 j
!= this->Commands
.end(); ++j
)
2419 if ((( withCompatCommands
== false) && ( (*j
).second
->IsDiscouraged()))
2420 || ((withCurrentCommands
== false) && (!(*j
).second
->IsDiscouraged())))
2425 cmDocumentationEntry
e((*j
).second
->GetName(),
2426 (*j
).second
->GetTerseDocumentation(),
2427 (*j
).second
->GetFullDocumentation());
2432 void cmake::GetPropertiesDocumentation(std::map
<std::string
,
2433 cmDocumentationSection
*>& v
)
2435 // loop over the properties and put them into the doc structure
2436 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
2437 i
= this->PropertyDefinitions
.begin();
2438 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
2440 i
->second
.GetPropertiesDocumentation(v
);
2444 void cmake::GetGeneratorDocumentation(std::vector
<cmDocumentationEntry
>& v
)
2446 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
2447 i
!= this->Generators
.end(); ++i
)
2449 cmDocumentationEntry e
;
2450 cmGlobalGenerator
* generator
= (i
->second
)();
2451 generator
->GetDocumentation(e
);
2455 for(RegisteredExtraGeneratorsMap::const_iterator
2456 i
= this->ExtraGenerators
.begin(); i
!= this->ExtraGenerators
.end(); ++i
)
2458 cmDocumentationEntry e
;
2459 cmExternalMakefileProjectGenerator
* generator
= (i
->second
)();
2460 generator
->GetDocumentation(e
, i
->first
.c_str());
2467 void cmake::AddWrittenFile(const char* file
)
2469 this->WrittenFiles
.insert(file
);
2472 bool cmake::HasWrittenFile(const char* file
)
2474 return this->WrittenFiles
.find(file
) != this->WrittenFiles
.end();
2477 void cmake::CleanupWrittenFiles()
2479 this->WrittenFiles
.clear();
2482 void cmake::UpdateConversionPathTable()
2484 // Update the path conversion table with any specified file:
2485 const char* tablepath
=
2486 this->CacheManager
->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
2490 std::ifstream
table( tablepath
);
2493 cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath
,
2494 ". CMake can not open file.");
2495 cmSystemTools::ReportLastSystemError("CMake can not open file.");
2502 // two entries per line
2503 table
>> a
; table
>> b
;
2504 cmSystemTools::AddTranslationPath( a
.c_str(), b
.c_str());
2510 //----------------------------------------------------------------------------
2511 int cmake::CheckBuildSystem()
2513 // We do not need to rerun CMake. Check dependency integrity. Use
2514 // the make system's VERBOSE environment variable to enable verbose
2516 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
2518 // This method will check the integrity of the build system if the
2519 // option was given on the command line. It reads the given file to
2520 // determine whether CMake should rerun.
2522 // If no file is provided for the check, we have to rerun.
2523 if(this->CheckBuildSystemArgument
.size() == 0)
2527 cmOStringStream msg
;
2528 msg
<< "Re-run cmake no build system arguments\n";
2529 cmSystemTools::Stdout(msg
.str().c_str());
2534 // If the file provided does not exist, we have to rerun.
2535 if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument
.c_str()))
2539 cmOStringStream msg
;
2540 msg
<< "Re-run cmake missing file: "
2541 << this->CheckBuildSystemArgument
.c_str() << "\n";
2542 cmSystemTools::Stdout(msg
.str().c_str());
2547 // Read the rerun check file and use it to decide whether to do the
2550 cmGlobalGenerator gg
;
2551 gg
.SetCMakeInstance(&cm
);
2552 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
2553 lg
->SetGlobalGenerator(&gg
);
2554 cmMakefile
* mf
= lg
->GetMakefile();
2555 if(!mf
->ReadListFile(0, this->CheckBuildSystemArgument
.c_str()) ||
2556 cmSystemTools::GetErrorOccuredFlag())
2560 cmOStringStream msg
;
2561 msg
<< "Re-run cmake error reading : "
2562 << this->CheckBuildSystemArgument
.c_str() << "\n";
2563 cmSystemTools::Stdout(msg
.str().c_str());
2565 // There was an error reading the file. Just rerun.
2569 if(this->ClearBuildSystem
)
2571 // Get the generator used for this build system.
2572 const char* genName
= mf
->GetDefinition("CMAKE_DEPENDS_GENERATOR");
2573 if(!genName
|| genName
[0] == '\0')
2575 genName
= "Unix Makefiles";
2578 // Create the generator and use it to clear the dependencies.
2579 std::auto_ptr
<cmGlobalGenerator
>
2580 ggd(this->CreateGlobalGenerator(genName
));
2583 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
2584 lgd
->SetGlobalGenerator(ggd
.get());
2585 lgd
->ClearDependencies(mf
, verbose
);
2589 // Get the set of dependencies and outputs.
2590 std::vector
<std::string
> depends
;
2591 std::vector
<std::string
> outputs
;
2592 const char* dependsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
2593 const char* outputsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
2594 if(dependsStr
&& outputsStr
)
2596 cmSystemTools::ExpandListArgument(dependsStr
, depends
);
2597 cmSystemTools::ExpandListArgument(outputsStr
, outputs
);
2599 if(depends
.empty() || outputs
.empty())
2601 // Not enough information was provided to do the test. Just rerun.
2604 cmOStringStream msg
;
2605 msg
<< "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
2606 "or CMAKE_MAKEFILE_OUTPUTS :\n";
2607 cmSystemTools::Stdout(msg
.str().c_str());
2612 // Find find the newest dependency.
2613 std::vector
<std::string
>::iterator dep
= depends
.begin();
2614 std::string dep_newest
= *dep
++;
2615 for(;dep
!= depends
.end(); ++dep
)
2618 if(this->FileComparison
->FileTimeCompare(dep_newest
.c_str(),
2619 dep
->c_str(), &result
))
2630 cmOStringStream msg
;
2631 msg
<< "Re-run cmake: build system dependency is missing\n";
2632 cmSystemTools::Stdout(msg
.str().c_str());
2638 // Find find the oldest output.
2639 std::vector
<std::string
>::iterator out
= outputs
.begin();
2640 std::string out_oldest
= *out
++;
2641 for(;out
!= outputs
.end(); ++out
)
2644 if(this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2645 out
->c_str(), &result
))
2656 cmOStringStream msg
;
2657 msg
<< "Re-run cmake: build system output is missing\n";
2658 cmSystemTools::Stdout(msg
.str().c_str());
2664 // If any output is older than any dependency then rerun.
2667 if(!this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2674 cmOStringStream msg
;
2675 msg
<< "Re-run cmake file: " << out_oldest
.c_str()
2676 << " older than: " << dep_newest
.c_str() << "\n";
2677 cmSystemTools::Stdout(msg
.str().c_str());
2683 // No need to rerun.
2687 //----------------------------------------------------------------------------
2688 void cmake::TruncateOutputLog(const char* fname
)
2690 std::string fullPath
= this->GetHomeOutputDirectory();
2694 if ( ::stat(fullPath
.c_str(), &st
) )
2698 if ( !this->CacheManager
->GetCacheValue("CMAKE_CACHEFILE_DIR") )
2700 cmSystemTools::RemoveFile(fullPath
.c_str());
2703 off_t fsize
= st
.st_size
;
2704 const off_t maxFileSize
= 50 * 1024;
2705 if ( fsize
< maxFileSize
)
2707 //TODO: truncate file
2712 inline std::string
removeQuotes(const std::string
& s
)
2714 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
2716 return s
.substr(1, s
.size()-2);
2721 std::string
cmake::FindCMakeProgram(const char* name
) const
2724 if ((name
) && (*name
))
2726 const cmMakefile
* mf
2727 = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
2728 #ifdef CMAKE_BUILD_WITH_CMAKE
2729 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2730 path
= removeQuotes(path
);
2731 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2734 path
+= cmSystemTools::GetExecutableExtension();
2735 if(!cmSystemTools::FileExists(path
.c_str()))
2737 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2738 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2741 path
+= cmSystemTools::GetExecutableExtension();
2743 if(!cmSystemTools::FileExists(path
.c_str()))
2745 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2746 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2747 path
+= "/Release/";
2749 path
+= cmSystemTools::GetExecutableExtension();
2752 // Only for bootstrap
2753 path
+= mf
->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
2756 path
+= cmSystemTools::GetExecutableExtension();
2762 const char* cmake::GetCTestCommand()
2764 if ( this->CTestCommand
.empty() )
2766 this->CTestCommand
= this->FindCMakeProgram("ctest");
2768 if ( this->CTestCommand
.empty() )
2770 cmSystemTools::Error("Cannot find the CTest executable");
2771 this->CTestCommand
= "CTEST-COMMAND-NOT-FOUND";
2773 return this->CTestCommand
.c_str();
2776 const char* cmake::GetCPackCommand()
2778 if ( this->CPackCommand
.empty() )
2780 this->CPackCommand
= this->FindCMakeProgram("cpack");
2782 if ( this->CPackCommand
.empty() )
2784 cmSystemTools::Error("Cannot find the CPack executable");
2785 this->CPackCommand
= "CPACK-COMMAND-NOT-FOUND";
2787 return this->CPackCommand
.c_str();
2790 void cmake::GenerateGraphViz(const char* fileName
) const
2792 cmGeneratedFileStream
str(fileName
);
2798 cmGlobalGenerator ggi
;
2799 ggi
.SetCMakeInstance(&cm
);
2800 std::auto_ptr
<cmLocalGenerator
> lg(ggi
.CreateLocalGenerator());
2801 lg
->SetGlobalGenerator(&ggi
);
2802 cmMakefile
*mf
= lg
->GetMakefile();
2804 std::string infile
= this->GetHomeOutputDirectory();
2805 infile
+= "/CMakeGraphVizOptions.cmake";
2806 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2808 infile
= this->GetHomeDirectory();
2809 infile
+= "/CMakeGraphVizOptions.cmake";
2810 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2816 if ( !infile
.empty() )
2818 if ( !mf
->ReadListFile(0, infile
.c_str()) )
2820 cmSystemTools::Error("Problem opening GraphViz options file: ",
2824 std::cout
<< "Read GraphViz options file: " << infile
.c_str()
2828 #define __set_if_not_set(var, value, cmakeDefinition) \
2829 const char* var = mf->GetDefinition(cmakeDefinition); \
2834 __set_if_not_set(graphType
, "digraph", "GRAPHVIZ_GRAPH_TYPE");
2835 __set_if_not_set(graphName
, "GG", "GRAPHVIZ_GRAPH_NAME");
2836 __set_if_not_set(graphHeader
, "node [\n fontsize = \"12\"\n];",
2837 "GRAPHVIZ_GRAPH_HEADER");
2838 __set_if_not_set(graphNodePrefix
, "node", "GRAPHVIZ_NODE_PREFIX");
2839 const char* ignoreTargets
= mf
->GetDefinition("GRAPHVIZ_IGNORE_TARGETS");
2840 std::set
<cmStdString
> ignoreTargetsSet
;
2841 if ( ignoreTargets
)
2843 std::vector
<std::string
> ignoreTargetsVector
;
2844 cmSystemTools::ExpandListArgument(ignoreTargets
,ignoreTargetsVector
);
2845 std::vector
<std::string
>::iterator itvIt
;
2846 for ( itvIt
= ignoreTargetsVector
.begin();
2847 itvIt
!= ignoreTargetsVector
.end();
2850 ignoreTargetsSet
.insert(itvIt
->c_str());
2854 str
<< graphType
<< " " << graphName
<< " {" << std::endl
;
2855 str
<< graphHeader
<< std::endl
;
2857 const cmGlobalGenerator
* gg
= this->GetGlobalGenerator();
2858 const std::vector
<cmLocalGenerator
*>& localGenerators
=
2859 gg
->GetLocalGenerators();
2860 std::vector
<cmLocalGenerator
*>::const_iterator lit
;
2863 // 2 - external target
2865 std::map
<cmStdString
, int> targetDeps
;
2866 std::map
<cmStdString
, const cmTarget
*> targetPtrs
;
2867 std::map
<cmStdString
, cmStdString
> targetNamesNodes
;
2869 // First pass get the list of all cmake targets
2870 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2872 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2873 cmTargets::const_iterator tit
;
2874 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2876 const char* realTargetName
= tit
->first
.c_str();
2877 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2879 // Skip ignored targets
2882 //std::cout << "Found target: " << tit->first.c_str() << std::endl;
2883 cmOStringStream ostr
;
2884 ostr
<< graphNodePrefix
<< cnt
++;
2885 targetNamesNodes
[realTargetName
] = ostr
.str();
2886 targetPtrs
[realTargetName
] = &tit
->second
;
2889 // Ok, now find all the stuff we link to that is not in cmake
2890 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2892 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2893 cmTargets::const_iterator tit
;
2894 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2896 const cmTarget::LinkLibraryVectorType
* ll
2897 = &(tit
->second
.GetOriginalLinkLibraries());
2898 cmTarget::LinkLibraryVectorType::const_iterator llit
;
2899 const char* realTargetName
= tit
->first
.c_str();
2900 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2902 // Skip ignored targets
2905 if ( ll
->size() > 0 )
2907 targetDeps
[realTargetName
] = 1;
2909 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
2911 const char* libName
= llit
->first
.c_str();
2912 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
2913 = targetNamesNodes
.find(libName
);
2914 if ( ignoreTargetsSet
.find(libName
) != ignoreTargetsSet
.end() )
2916 // Skip ignored targets
2919 if ( tarIt
== targetNamesNodes
.end() )
2921 cmOStringStream ostr
;
2922 ostr
<< graphNodePrefix
<< cnt
++;
2923 targetDeps
[libName
] = 2;
2924 targetNamesNodes
[libName
] = ostr
.str();
2925 //str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
2926 //<< "\" shape=\"ellipse\"];" << std::endl;
2930 std::map
<cmStdString
, int>::const_iterator depIt
2931 = targetDeps
.find(libName
);
2932 if ( depIt
== targetDeps
.end() )
2934 targetDeps
[libName
] = 1;
2942 std::map
<cmStdString
, int>::const_iterator depIt
;
2943 for ( depIt
= targetDeps
.begin(); depIt
!= targetDeps
.end(); ++ depIt
)
2945 const char* newTargetName
= depIt
->first
.c_str();
2946 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
2947 = targetNamesNodes
.find(newTargetName
);
2948 if ( tarIt
== targetNamesNodes
.end() )
2950 // We should not be here.
2951 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
2952 << " even though it was added in the previous pass" << std::endl
;
2956 str
<< " \"" << tarIt
->second
.c_str() << "\" [ label=\""
2957 << newTargetName
<< "\" shape=\"";
2958 if ( depIt
->second
== 1 )
2960 std::map
<cmStdString
, const cmTarget
*>::const_iterator tarTypeIt
=
2961 targetPtrs
.find(newTargetName
);
2962 if ( tarTypeIt
== targetPtrs
.end() )
2964 // We should not be here.
2965 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
2966 << " even though it was added in the previous pass" << std::endl
;
2969 const cmTarget
* tg
= tarTypeIt
->second
;
2970 switch ( tg
->GetType() )
2972 case cmTarget::EXECUTABLE
:
2975 case cmTarget::STATIC_LIBRARY
:
2978 case cmTarget::SHARED_LIBRARY
:
2981 case cmTarget::MODULE_LIBRARY
:
2992 str
<< "\"];" << std::endl
;
2995 // Now generate the connectivity
2996 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2998 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2999 cmTargets::const_iterator tit
;
3000 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
3002 std::map
<cmStdString
, int>::iterator dependIt
3003 = targetDeps
.find(tit
->first
.c_str());
3004 if ( dependIt
== targetDeps
.end() )
3008 std::map
<cmStdString
, cmStdString
>::iterator cmakeTarIt
3009 = targetNamesNodes
.find(tit
->first
.c_str());
3010 const cmTarget::LinkLibraryVectorType
* ll
3011 = &(tit
->second
.GetOriginalLinkLibraries());
3012 cmTarget::LinkLibraryVectorType::const_iterator llit
;
3013 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
3015 const char* libName
= llit
->first
.c_str();
3016 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3017 = targetNamesNodes
.find(libName
);
3018 if ( tarIt
== targetNamesNodes
.end() )
3020 // We should not be here.
3021 std::cout
<< __LINE__
<< " Cannot find library: " << libName
3022 << " even though it was added in the previous pass" << std::endl
;
3025 str
<< " \"" << cmakeTarIt
->second
.c_str() << "\" -> \""
3026 << tarIt
->second
.c_str() << "\"" << std::endl
;
3031 // TODO: Use dotted or something for external libraries
3032 //str << " \"node0\":f4 -> \"node12\"[color=\"#0000ff\" style=dotted]"
3035 str
<< "}" << std::endl
;
3038 //----------------------------------------------------------------------------
3039 #ifdef CMAKE_BUILD_WITH_CMAKE
3040 int cmake::ExecuteEchoColor(std::vector
<std::string
>& args
)
3042 // The arguments are
3043 // argv[0] == <cmake-executable>
3044 // argv[1] == cmake_echo_color
3046 bool enabled
= true;
3047 int color
= cmsysTerminal_Color_Normal
;
3048 bool newline
= true;
3049 for(unsigned int i
=2; i
< args
.size(); ++i
)
3051 if(args
[i
].find("--switch=") == 0)
3053 // Enable or disable color based on the switch value.
3054 std::string value
= args
[i
].substr(9);
3057 if(cmSystemTools::IsOn(value
.c_str()))
3067 else if(args
[i
] == "--normal")
3069 color
= cmsysTerminal_Color_Normal
;
3071 else if(args
[i
] == "--black")
3073 color
= cmsysTerminal_Color_ForegroundBlack
;
3075 else if(args
[i
] == "--red")
3077 color
= cmsysTerminal_Color_ForegroundRed
;
3079 else if(args
[i
] == "--green")
3081 color
= cmsysTerminal_Color_ForegroundGreen
;
3083 else if(args
[i
] == "--yellow")
3085 color
= cmsysTerminal_Color_ForegroundYellow
;
3087 else if(args
[i
] == "--blue")
3089 color
= cmsysTerminal_Color_ForegroundBlue
;
3091 else if(args
[i
] == "--magenta")
3093 color
= cmsysTerminal_Color_ForegroundMagenta
;
3095 else if(args
[i
] == "--cyan")
3097 color
= cmsysTerminal_Color_ForegroundCyan
;
3099 else if(args
[i
] == "--white")
3101 color
= cmsysTerminal_Color_ForegroundWhite
;
3103 else if(args
[i
] == "--bold")
3105 color
|= cmsysTerminal_Color_ForegroundBold
;
3107 else if(args
[i
] == "--no-newline")
3111 else if(args
[i
] == "--newline")
3117 // Color is enabled. Print with the current color.
3118 cmSystemTools::MakefileColorEcho(color
, args
[i
].c_str(),
3126 int cmake::ExecuteEchoColor(std::vector
<std::string
>&)
3132 //----------------------------------------------------------------------------
3133 int cmake::ExecuteLinkScript(std::vector
<std::string
>& args
)
3135 // The arguments are
3136 // argv[0] == <cmake-executable>
3137 // argv[1] == cmake_link_script
3138 // argv[2] == <link-script-name>
3139 // argv[3] == --verbose=?
3140 bool verbose
= false;
3141 if(args
.size() >= 4)
3143 if(args
[3].find("--verbose=") == 0)
3145 if(!cmSystemTools::IsOff(args
[3].substr(10).c_str()))
3152 // Allocate a process instance.
3153 cmsysProcess
* cp
= cmsysProcess_New();
3156 std::cerr
<< "Error allocating process instance in link script."
3161 // Children should share stdout and stderr with this process.
3162 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDOUT
, 1);
3163 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDERR
, 1);
3165 // Run the command lines verbatim.
3166 cmsysProcess_SetOption(cp
, cmsysProcess_Option_Verbatim
, 1);
3168 // Read command lines from the script.
3169 std::ifstream
fin(args
[2].c_str());
3172 std::cerr
<< "Error opening link script \""
3173 << args
[2] << "\"" << std::endl
;
3177 // Run one command at a time.
3178 std::string command
;
3180 while(result
== 0 && cmSystemTools::GetLineFromStream(fin
, command
))
3182 // Setup this command line.
3183 const char* cmd
[2] = {command
.c_str(), 0};
3184 cmsysProcess_SetCommand(cp
, cmd
);
3186 // Report the command if verbose output is enabled.
3189 std::cout
<< command
<< std::endl
;
3192 // Run the command and wait for it to exit.
3193 cmsysProcess_Execute(cp
);
3194 cmsysProcess_WaitForExit(cp
, 0);
3196 // Report failure if any.
3197 switch(cmsysProcess_GetState(cp
))
3199 case cmsysProcess_State_Exited
:
3201 int value
= cmsysProcess_GetExitValue(cp
);
3208 case cmsysProcess_State_Exception
:
3209 std::cerr
<< "Error running link command: "
3210 << cmsysProcess_GetExceptionString(cp
) << std::endl
;
3213 case cmsysProcess_State_Error
:
3214 std::cerr
<< "Error running link command: "
3215 << cmsysProcess_GetErrorString(cp
) << std::endl
;
3223 // Free the process instance.
3224 cmsysProcess_Delete(cp
);
3226 // Return the final resulting return value.
3230 void cmake::DefineProperties(cmake
*cm
)
3233 ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL
,
3234 "If set, report any undefined properties to this file.",
3235 "If this property is set to a filename then when CMake runs "
3236 "it will report any properties or variables that were accessed "
3237 "but not defined into the filename specified in this property."
3241 ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL
,
3242 "Does the target platform support shared libraries.",
3243 "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
3244 "platform supports shared libraries. Basically all current general "
3245 "general purpose OS do so, the exception are usually embedded systems "
3246 "with no or special OSs.");
3248 ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL
,
3249 "Whether FIND_LIBRARY should automatically search lib64 directories.",
3250 "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
3251 "FIND_LIBRARY command should automatically search the lib64 variant of "
3252 "directories called lib in the search path when building 64-bit "
3255 ("ENABLED_FEATURES", cmProperty::GLOBAL
,
3256 "List of features which are enabled during the CMake run.",
3257 "List of features which are enabled during the CMake run. Be default "
3258 "it contains the names of all packages which were found. This is "
3259 "determined using the <NAME>_FOUND variables. Packages which are "
3260 "searched QUIET are not listed. A project can add its own features to "
3261 "this list.This property is used by the macros in FeatureSummary.cmake.");
3263 ("DISABLED_FEATURES", cmProperty::GLOBAL
,
3264 "List of features which are disabled during the CMake run.",
3265 "List of features which are disabled during the CMake run. Be default "
3266 "it contains the names of all packages which were not found. This is "
3267 "determined using the <NAME>_FOUND variables. Packages which are "
3268 "searched QUIET are not listed. A project can add its own features to "
3269 "this list.This property is used by the macros in FeatureSummary.cmake.");
3271 ("PACKAGES_FOUND", cmProperty::GLOBAL
,
3272 "List of packages which were found during the CMake run.",
3273 "List of packages which were found during the CMake run. Whether a "
3274 "package has been found is determined using the <NAME>_FOUND variables.");
3276 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3277 "List of packages which were not found during the CMake run.",
3278 "List of packages which were not found during the CMake run. Whether a "
3279 "package has been found is determined using the <NAME>_FOUND variables.");
3282 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3283 "List of packages which were not found during the CMake run.",
3284 "List of packages which were not found during the CMake run. Whether a "
3285 "package has been found is determined using the <NAME>_FOUND variables.");
3287 "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL
,
3288 "Internal property",
3289 "Used to detect compiler changes, Do not set.");
3291 // ================================================================
3292 // define variables as well
3293 // ================================================================
3294 cmDocumentVariables::DefineVariables(cm
);
3298 void cmake::DefineProperty(const char *name
, cmProperty::ScopeType scope
,
3299 const char *ShortDescription
,
3300 const char *FullDescription
,
3301 bool chained
, const char *docSection
)
3303 this->PropertyDefinitions
[scope
].DefineProperty(name
,scope
,ShortDescription
,
3309 cmPropertyDefinition
*cmake
3310 ::GetPropertyDefinition(const char *name
,
3311 cmProperty::ScopeType scope
)
3313 if (this->IsPropertyDefined(name
,scope
))
3315 return &(this->PropertyDefinitions
[scope
][name
]);
3320 void cmake::RecordPropertyAccess(const char *name
,
3321 cmProperty::ScopeType scope
)
3323 this->AccessedProperties
.insert
3324 (std::pair
<cmStdString
,cmProperty::ScopeType
>(name
,scope
));
3327 void cmake::ReportUndefinedPropertyAccesses(const char *filename
)
3329 FILE *progFile
= fopen(filename
,"w");
3330 if (!progFile
|| !this->GlobalGenerator
)
3335 // what are the enabled languages?
3336 std::vector
<std::string
> enLangs
;
3337 this->GlobalGenerator
->GetEnabledLanguages(enLangs
);
3339 // Common configuration names.
3340 // TODO: Compute current configuration(s).
3341 std::vector
<std::string
> enConfigs
;
3342 enConfigs
.push_back("");
3343 enConfigs
.push_back("DEBUG");
3344 enConfigs
.push_back("RELEASE");
3345 enConfigs
.push_back("MINSIZEREL");
3346 enConfigs
.push_back("RELWITHDEBINFO");
3348 // take all the defined properties and add definitions for all the enabled
3350 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> > aliasedProperties
;
3351 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
3352 i
= this->PropertyDefinitions
.begin();
3353 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
3355 cmPropertyDefinitionMap::iterator j
;
3356 for (j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
3358 // TODO: What if both <LANG> and <CONFIG> appear?
3359 if (j
->first
.find("<CONFIG>") != std::string::npos
)
3361 std::vector
<std::string
>::const_iterator k
;
3362 for (k
= enConfigs
.begin(); k
!= enConfigs
.end(); ++k
)
3364 std::string tmp
= j
->first
;
3365 cmSystemTools::ReplaceString(tmp
, "<CONFIG>", k
->c_str());
3367 aliasedProperties
.insert
3368 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3371 if (j
->first
.find("<LANG>") != std::string::npos
)
3373 std::vector
<std::string
>::const_iterator k
;
3374 for (k
= enLangs
.begin(); k
!= enLangs
.end(); ++k
)
3376 std::string tmp
= j
->first
;
3377 cmSystemTools::ReplaceString(tmp
, "<LANG>", k
->c_str());
3379 aliasedProperties
.insert
3380 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3386 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> >::const_iterator ap
;
3387 ap
= this->AccessedProperties
.begin();
3388 for (;ap
!= this->AccessedProperties
.end(); ++ap
)
3390 if (!this->IsPropertyDefined(ap
->first
.c_str(),ap
->second
) &&
3391 aliasedProperties
.find(std::pair
<cmStdString
,cmProperty::ScopeType
>
3392 (ap
->first
,ap
->second
)) ==
3393 aliasedProperties
.end())
3395 const char *scopeStr
= "";
3398 case cmProperty::TARGET
:
3399 scopeStr
= "TARGET";
3401 case cmProperty::SOURCE_FILE
:
3402 scopeStr
= "SOURCE_FILE";
3404 case cmProperty::DIRECTORY
:
3405 scopeStr
= "DIRECTORY";
3407 case cmProperty::TEST
:
3410 case cmProperty::VARIABLE
:
3411 scopeStr
= "VARIABLE";
3413 case cmProperty::CACHED_VARIABLE
:
3414 scopeStr
= "CACHED_VARIABLE";
3417 scopeStr
= "unknown";
3420 fprintf(progFile
,"%s with scope %s\n",ap
->first
.c_str(),scopeStr
);
3426 bool cmake::IsPropertyDefined(const char *name
, cmProperty::ScopeType scope
)
3428 return this->PropertyDefinitions
[scope
].IsPropertyDefined(name
);
3431 bool cmake::IsPropertyChained(const char *name
, cmProperty::ScopeType scope
)
3433 return this->PropertyDefinitions
[scope
].IsPropertyChained(name
);
3436 void cmake::SetProperty(const char* prop
, const char* value
)
3447 this->Properties
.SetProperty(prop
, value
, cmProperty::GLOBAL
);
3450 void cmake::AppendProperty(const char* prop
, const char* value
)
3456 this->Properties
.AppendProperty(prop
, value
, cmProperty::GLOBAL
);
3459 const char *cmake::GetProperty(const char* prop
)
3461 return this->GetProperty(prop
, cmProperty::GLOBAL
);
3464 const char *cmake::GetProperty(const char* prop
, cmProperty::ScopeType scope
)
3468 // watch for special properties
3469 std::string propname
= prop
;
3470 std::string output
= "";
3471 if ( propname
== "CACHE_VARIABLES" )
3473 cmCacheManager::CacheIterator cit
=
3474 this->GetCacheManager()->GetCacheIterator();
3475 for ( cit
.Begin(); !cit
.IsAtEnd(); cit
.Next() )
3477 if ( output
.size() )
3481 output
+= cit
.GetName();
3483 this->SetProperty("CACHE_VARIABLES", output
.c_str());
3485 else if ( propname
== "COMMANDS" )
3487 cmake::RegisteredCommandsMap::iterator cmds
3488 = this->GetCommands()->begin();
3489 for (unsigned int cc
=0 ; cmds
!= this->GetCommands()->end(); ++ cmds
)
3495 output
+= cmds
->first
.c_str();
3498 this->SetProperty("COMMANDS",output
.c_str());
3501 return this->Properties
.GetPropertyValue(prop
, scope
, chain
);
3504 bool cmake::GetPropertyAsBool(const char* prop
)
3506 return cmSystemTools::IsOn(this->GetProperty(prop
));
3509 int cmake::GetSystemInformation(std::vector
<std::string
>& args
)
3511 // so create the directory
3512 std::string resultFile
;
3513 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
3514 std::string destPath
= cwd
+ "/__cmake_systeminformation";
3515 cmSystemTools::RemoveADirectory(destPath
.c_str());
3516 if (!cmSystemTools::MakeDirectory(destPath
.c_str()))
3518 std::cerr
<< "Error: --system-information must be run from a "
3519 "writable directory!\n";
3523 // process the arguments
3524 bool writeToStdout
= true;
3525 for(unsigned int i
=1; i
< args
.size(); ++i
)
3527 std::string arg
= args
[i
];
3528 if(arg
.find("-V",0) == 0)
3530 this->Verbose
= true;
3532 else if(arg
.find("-G",0) == 0)
3534 std::string value
= arg
.substr(2);
3535 if(value
.size() == 0)
3538 if(i
>= args
.size())
3540 cmSystemTools::Error("No generator specified for -G");
3545 cmGlobalGenerator
* gen
=
3546 this->CreateGlobalGenerator(value
.c_str());
3549 cmSystemTools::Error("Could not create named generator ",
3554 this->SetGlobalGenerator(gen
);
3557 // no option assume it is the output file
3560 if (!cmSystemTools::FileIsFullPath(arg
.c_str()))
3566 writeToStdout
= false;
3571 // we have to find the module directory, so we can copy the files
3572 this->AddCMakePaths();
3573 std::string modulesPath
=
3574 this->CacheManager
->GetCacheValue("CMAKE_ROOT");
3575 modulesPath
+= "/Modules";
3576 std::string inFile
= modulesPath
;
3577 inFile
+= "/SystemInformation.cmake";
3578 std::string outFile
= destPath
;
3579 outFile
+= "/CMakeLists.txt";
3582 if(!cmSystemTools::cmCopyFile(inFile
.c_str(), outFile
.c_str()))
3584 std::cerr
<< "Error copying file \"" << inFile
.c_str()
3585 << "\" to \"" << outFile
.c_str() << "\".\n";
3589 // do we write to a file or to stdout?
3590 if (resultFile
.size() == 0)
3593 resultFile
+= "/__cmake_systeminformation/results.txt";
3596 // now run cmake on the CMakeLists file
3597 cmSystemTools::ChangeDirectory(destPath
.c_str());
3598 std::vector
<std::string
> args2
;
3599 args2
.push_back(args
[0]);
3600 args2
.push_back(destPath
);
3601 std::string resultArg
= "-DRESULT_FILE=";
3602 resultArg
+= resultFile
;
3603 args2
.push_back(resultArg
);
3604 int res
= this->Run(args2
, false);
3608 std::cerr
<< "Error: --system-information failed on internal CMake!\n";
3612 // change back to the original directory
3613 cmSystemTools::ChangeDirectory(cwd
.c_str());
3615 // echo results to stdout if needed
3618 FILE* fin
= fopen(resultFile
.c_str(), "r");
3621 const int bufferSize
= 4096;
3622 char buffer
[bufferSize
];
3624 while((n
= fread(buffer
, 1, bufferSize
, fin
)) > 0)
3626 for(char* c
= buffer
; c
< buffer
+n
; ++c
)
3636 // clean up the directory
3637 cmSystemTools::RemoveADirectory(destPath
.c_str());
3641 //----------------------------------------------------------------------------
3642 static bool cmakeCheckStampFile(const char* stampName
)
3644 // If the stamp file still exists then it must really be out of
3646 if(cmSystemTools::FileExists(stampName
))
3651 // The stamp file does not exist. Use the stamp dependencies to
3652 // determine whether it is really out of date. This works in
3653 // conjunction with cmLocalVisualStudio7Generator to avoid
3654 // repeatedly re-running CMake when the user rebuilds the entire
3656 std::string stampDepends
= stampName
;
3657 stampDepends
+= ".depend";
3658 #if defined(_WIN32) || defined(__CYGWIN__)
3659 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
| std::ios::binary
);
3661 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
);
3665 // The stamp dependencies file cannot be read. Just assume the
3666 // build system is really out of date.
3670 // Compare the stamp dependencies against the dependency file itself.
3671 cmFileTimeComparison ftc
;
3673 while(cmSystemTools::GetLineFromStream(fin
, dep
))
3676 if(dep
.length() >= 1 && dep
[0] != '#' &&
3677 (!ftc
.FileTimeCompare(stampDepends
.c_str(), dep
.c_str(), &result
)
3680 // The stamp depends file is older than this dependency. The
3681 // build system is really out of date.
3686 // The build system is up to date. The stamp file has been removed
3687 // by the VS IDE due to a "rebuild" request. Just restore it.
3688 std::ofstream
stamp(stampName
);
3689 stamp
<< "# CMake generation timestamp file this directory.\n";
3692 // Notify the user why CMake is not re-running. It is safe to
3693 // just print to stdout here because this code is only reachable
3694 // through an undocumented flag used by the VS generator.
3695 std::cout
<< "CMake does not need to re-run because the "
3696 << "generation timestamp is up-to-date.\n";
3701 cmSystemTools::Error("Cannot restore timestamp ", stampName
);
3706 // For visual studio 2005 and newer manifest files need to be embeded into
3707 // exe and dll's. This code does that in such a way that incremental linking
3709 int cmake::VisualStudioLink(std::vector
<std::string
>& args
, int type
)
3715 bool verbose
= false;
3716 if(cmSystemTools::GetEnv("VERBOSE"))
3720 std::vector
<std::string
> expandedArgs
;
3721 for(std::vector
<std::string
>::iterator i
= args
.begin();
3722 i
!= args
.end(); ++i
)
3724 // check for nmake temporary files
3727 std::ifstream
fin(i
->substr(1).c_str());
3729 while(cmSystemTools::GetLineFromStream(fin
,
3732 cmSystemTools::ParseWindowsCommandLine(line
.c_str(), expandedArgs
);
3737 expandedArgs
.push_back(*i
);
3740 // figure out if this is an incremental link or not and run the correct
3742 for(std::vector
<std::string
>::iterator i
= expandedArgs
.begin();
3743 i
!= expandedArgs
.end(); ++i
)
3745 if(cmSystemTools::Strucmp(i
->c_str(), "/INCREMENTAL:YES") == 0)
3749 std::cout
<< "Visual Studio Incremental Link\n";
3751 return cmake::VisualStudioLinkIncremental(expandedArgs
, type
, verbose
);
3756 std::cout
<< "Visual Studio Non-Incremental Link\n";
3758 return cmake::VisualStudioLinkNonIncremental(expandedArgs
, type
, verbose
);
3761 int cmake::ParseVisualStudioLinkCommand(std::vector
<std::string
>& args
,
3762 std::vector
<cmStdString
>& command
,
3763 std::string
& targetName
)
3765 std::vector
<std::string
>::iterator i
= args
.begin();
3767 i
++; // skip vs_link_dll or vs_link_exe
3768 command
.push_back(*i
);
3769 i
++; // move past link command
3770 for(; i
!= args
.end(); ++i
)
3772 command
.push_back(*i
);
3773 if(i
->find("/Fe") == 0)
3775 targetName
= i
->substr(3);
3777 if(i
->find("/out:") == 0)
3779 targetName
= i
->substr(5);
3782 if(targetName
.size() == 0 || command
.size() == 0)
3789 bool cmake::RunCommand(const char* comment
,
3790 std::vector
<cmStdString
>& command
,
3796 std::cout
<< comment
<< ":\n";
3797 for(std::vector
<cmStdString
>::iterator i
= command
.begin();
3798 i
!= command
.end(); ++i
)
3800 std::cout
<< i
->c_str() << " ";
3806 // use rc command to create .res file
3807 cmSystemTools::RunSingleCommand(command
,
3812 std::cout
<< output
<< "\n";
3814 // if retCodeOut is requested then always return true
3815 // and set the retCodeOut to retCode
3818 *retCodeOut
= retCode
;
3823 std::cout
<< comment
<< " failed. with " << retCode
<< "\n";
3825 return retCode
== 0;
3828 int cmake::VisualStudioLinkIncremental(std::vector
<std::string
>& args
,
3829 int type
, bool verbose
)
3831 // This follows the steps listed here:
3832 // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
3834 // 1. Compiler compiles the application and generates the *.obj files.
3835 // 2. An empty manifest file is generated if this is a clean build and if
3836 // not the previous one is reused.
3837 // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
3839 // 4. Linker generates the binary (EXE or DLL) with the /incremental
3840 // switch and embeds the dummy manifest file. The linker also generates
3841 // the real manifest file based on the binaries that your binary depends
3843 // 5. The manifest tool (mt.exe) is then used to generate the final
3846 // If the final manifest is changed, then 6 and 7 are run, if not
3847 // they are skipped, and it is done.
3849 // 6. The resource compiler is invoked one more time.
3850 // 7. Finally, the Linker does another incremental link, but since the
3851 // only thing that has changed is the *.res file that contains the
3852 // manifest it is a short link.
3853 std::vector
<cmStdString
> linkCommand
;
3854 std::string targetName
;
3855 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
3859 std::string manifestArg
= "/MANIFESTFILE:";
3860 std::vector
<cmStdString
> rcCommand
;
3861 rcCommand
.push_back(cmSystemTools::FindProgram("rc.exe"));
3862 std::vector
<cmStdString
> mtCommand
;
3863 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
3864 std::string tempManifest
;
3865 tempManifest
= targetName
;
3866 tempManifest
+= ".intermediate.manifest";
3867 std::string resourceInputFile
= targetName
;
3868 resourceInputFile
+= ".resource.txt";
3871 std::cout
<< "Create " << resourceInputFile
.c_str() << "\n";
3873 // Create input file for rc command
3874 std::ofstream
fout(resourceInputFile
.c_str());
3879 std::string manifestFile
= targetName
;
3880 manifestFile
+= ".embed.manifest";
3881 std::string fullPath
= cmSystemTools::CollapseFullPath(manifestFile
.c_str());
3882 fout
<< type
<< " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
3883 "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath
.c_str() << "\"";
3885 manifestArg
+= tempManifest
;
3886 // add the manifest arg to the linkCommand
3887 linkCommand
.push_back(manifestArg
);
3888 // if manifestFile is not yet created, create an
3890 if(!cmSystemTools::FileExists(manifestFile
.c_str()))
3894 std::cout
<< "Create empty: " << manifestFile
.c_str() << "\n";
3896 std::ofstream
foutTmp(manifestFile
.c_str());
3898 std::string resourceFile
= manifestFile
;
3899 resourceFile
+= ".res";
3900 // add the resource file to the end of the link command
3901 linkCommand
.push_back(resourceFile
);
3902 std::string outputOpt
= "/fo";
3903 outputOpt
+= resourceFile
;
3904 rcCommand
.push_back(outputOpt
);
3905 rcCommand
.push_back(resourceInputFile
);
3906 // Run rc command to create resource
3907 if(!cmake::RunCommand("RC Pass 1", rcCommand
, verbose
))
3911 // Now run the link command to link and create manifest
3912 if(!cmake::RunCommand("LINK Pass 1", linkCommand
, verbose
))
3916 // create mt command
3917 std::string
outArg("/out:");
3918 outArg
+= manifestFile
;
3919 mtCommand
.push_back("/nologo");
3920 mtCommand
.push_back(outArg
);
3921 mtCommand
.push_back("/notify_update");
3922 mtCommand
.push_back("/manifest");
3923 mtCommand
.push_back(tempManifest
);
3924 // now run mt.exe to create the final manifest file
3926 cmake::RunCommand("MT", mtCommand
, verbose
, &mtRet
);
3927 // if mt returns 0, then the manifest was not changed and
3928 // we do not need to do another link step
3933 // check for magic mt return value if mt returns the magic number
3934 // 1090650113 then it means that it updated the manifest file and we need
3935 // to do the final link. If mt has any value other than 0 or 1090650113
3936 // then there was some problem with the command itself and there was an
3937 // error so return the error code back out of cmake so make can report it.
3938 if(mtRet
!= 1090650113)
3942 // update the resource file with the new manifest from the mt command.
3943 if(!cmake::RunCommand("RC Pass 2", rcCommand
, verbose
))
3947 // Run the final incremental link that will put the new manifest resource
3948 // into the file incrementally.
3949 if(!cmake::RunCommand("FINAL LINK", linkCommand
, verbose
))
3956 int cmake::VisualStudioLinkNonIncremental(std::vector
<std::string
>& args
,
3960 std::vector
<cmStdString
> linkCommand
;
3961 std::string targetName
;
3962 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
3966 // Run the link command as given
3967 if(!cmake::RunCommand("LINK", linkCommand
, verbose
))
3971 std::vector
<cmStdString
> mtCommand
;
3972 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
3973 mtCommand
.push_back("/nologo");
3974 mtCommand
.push_back("/manifest");
3975 std::string manifestFile
= targetName
;
3976 manifestFile
+= ".manifest";
3977 mtCommand
.push_back(manifestFile
);
3978 std::string outresource
= "/outputresource:";
3979 outresource
+= targetName
;
3980 outresource
+= ";#";
3989 mtCommand
.push_back(outresource
);
3990 // Now use the mt tool to embed the manifest into the exe or dll
3991 if(!cmake::RunCommand("MT", mtCommand
, verbose
))