1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmake.cxx,v $
6 Date: $Date: 2008/01/24 19:37:48 $
7 Version: $Revision: 1.355 $
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::FileIsDirectory(args
[2].c_str()) &&
1031 !cmSystemTools::RemoveADirectory(args
[2].c_str()))
1033 std::cerr
<< "Error removing directory \"" << args
[2].c_str()
1041 else if (args
[1] == "remove" && args
.size() > 2)
1044 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1046 if(args
[cc
] == "\\-f" || args
[cc
] == "-f")
1052 // Complain if the file could not be removed, still exists,
1053 // and the -f option was not given.
1054 if(!cmSystemTools::RemoveFile(args
[cc
].c_str()) && !force
&&
1055 cmSystemTools::FileExists(args
[cc
].c_str()))
1064 else if (args
[1] == "touch" && args
.size() > 2)
1066 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1068 // Complain if the file could not be removed, still exists,
1069 // and the -f option was not given.
1070 if(!cmSystemTools::Touch(args
[cc
].c_str(), true))
1078 else if (args
[1] == "touch_nocreate" && args
.size() > 2)
1080 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1082 // Complain if the file could not be removed, still exists,
1083 // and the -f option was not given.
1084 if(!cmSystemTools::Touch(args
[cc
].c_str(), false))
1093 else if (args
[1] == "time" && args
.size() > 2)
1095 std::string command
= args
[2];
1096 for (std::string::size_type cc
= 3; cc
< args
.size(); cc
++)
1099 command
+= args
[cc
];
1102 clock_t clock_start
, clock_finish
;
1103 time_t time_start
, time_finish
;
1106 clock_start
= clock();
1108 cmSystemTools::RunSingleCommand(command
.c_str());
1110 clock_finish
= clock();
1113 double clocks_per_sec
= static_cast<double>(CLOCKS_PER_SEC
);
1114 std::cout
<< "Elapsed time: "
1115 << static_cast<long>(time_finish
- time_start
) << " s. (time)"
1117 << static_cast<double>(clock_finish
- clock_start
) / clocks_per_sec
1123 // Command to calculate the md5sum of a file
1124 else if (args
[1] == "md5sum" && args
.size() >= 3)
1128 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1130 const char *filename
= args
[cc
].c_str();
1131 // Cannot compute md5sum of a directory
1132 if(cmSystemTools::FileIsDirectory(filename
))
1134 std::cerr
<< "Error: " << filename
<< " is a directory" << std::endl
;
1137 else if(!cmSystemTools::ComputeFileMD5(filename
, md5out
))
1139 // To mimic md5sum behavior in a shell:
1140 std::cerr
<< filename
<< ": No such file or directory" << std::endl
;
1145 std::cout
<< std::string(md5out
,32) << " " << filename
<< std::endl
;
1151 // Command to change directory and run a program.
1152 else if (args
[1] == "chdir" && args
.size() >= 4)
1154 std::string directory
= args
[2];
1155 if(!cmSystemTools::FileExists(directory
.c_str()))
1157 cmSystemTools::Error("Directory does not exist for chdir command: ",
1162 std::string command
= "\"";
1165 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1168 command
+= args
[cc
];
1173 if ( cmSystemTools::RunSingleCommand(command
.c_str(), 0, &retval
,
1174 directory
.c_str(), true, timeout
) )
1182 // Command to start progress for a build
1183 else if (args
[1] == "cmake_progress_start" && args
.size() == 4)
1185 // bascially remove the directory
1186 std::string dirName
= args
[2];
1187 dirName
+= "/Progress";
1188 cmSystemTools::RemoveADirectory(dirName
.c_str());
1190 // is the last argument a filename that exists?
1191 FILE *countFile
= fopen(args
[3].c_str(),"r");
1195 fscanf(countFile
,"%i",&count
);
1200 count
= atoi(args
[3].c_str());
1204 cmSystemTools::MakeDirectory(dirName
.c_str());
1205 // write the count into the directory
1206 std::string fName
= dirName
;
1207 fName
+= "/count.txt";
1208 FILE *progFile
= fopen(fName
.c_str(),"w");
1211 fprintf(progFile
,"%i\n",count
);
1218 // Command to report progress for a build
1219 else if (args
[1] == "cmake_progress_report" && args
.size() >= 3)
1221 std::string dirName
= args
[2];
1222 dirName
+= "/Progress";
1228 fName
+= "/count.txt";
1229 progFile
= fopen(fName
.c_str(),"r");
1237 fscanf(progFile
,"%i",&count
);
1241 for (i
= 3; i
< args
.size(); ++i
)
1246 progFile
= fopen(fName
.c_str(),"w");
1249 fprintf(progFile
,"empty");
1253 int fileNum
= static_cast<int>
1254 (cmsys::Directory::GetNumberOfFilesInDirectory(dirName
.c_str()));
1257 // print the progress
1258 fprintf(stdout
,"[%3i%%] ",((fileNum
-3)*100)/count
);
1263 // Command to create a symbolic link. Fails on platforms not
1265 else if (args
[1] == "create_symlink" && args
.size() == 4)
1267 const char* destinationFileName
= args
[3].c_str();
1268 if ( cmSystemTools::FileExists(destinationFileName
) )
1270 if ( cmSystemTools::FileIsSymlink(destinationFileName
) )
1272 if ( !cmSystemTools::RemoveFile(destinationFileName
) ||
1273 cmSystemTools::FileExists(destinationFileName
) )
1283 return cmSystemTools::CreateSymlink(args
[2].c_str(),
1284 args
[3].c_str())? 0:1;
1287 // Internal CMake shared library support.
1288 else if (args
[1] == "cmake_symlink_library" && args
.size() == 5)
1291 std::string realName
= args
[2];
1292 std::string soName
= args
[3];
1293 std::string name
= args
[4];
1294 if(soName
!= realName
)
1296 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1297 if(cmSystemTools::FileExists(soName
.c_str()))
1299 cmSystemTools::RemoveFile(soName
.c_str());
1301 if(!cmSystemTools::CreateSymlink(fname
.c_str(), soName
.c_str()))
1308 std::string fname
= cmSystemTools::GetFilenameName(soName
);
1309 if(cmSystemTools::FileExists(soName
.c_str()))
1311 cmSystemTools::RemoveFile(name
.c_str());
1313 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1320 // Internal CMake versioned executable support.
1321 else if (args
[1] == "cmake_symlink_executable" && args
.size() == 4)
1324 std::string realName
= args
[2];
1325 std::string name
= args
[3];
1326 if(name
!= realName
)
1328 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1329 if(cmSystemTools::FileExists(realName
.c_str()))
1331 cmSystemTools::RemoveFile(name
.c_str());
1333 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1341 #if defined(CMAKE_HAVE_VS_GENERATORS)
1342 // Internal CMake support for calling Visual Studio macros.
1343 else if (args
[1] == "cmake_call_visual_studio_macro" && args
.size() >= 4)
1345 // args[2] = full path to .sln file or "ALL"
1346 // args[3] = name of Visual Studio macro to call
1347 // args[4..args.size()-1] = [optional] args for Visual Studio macro
1349 std::string macroArgs
;
1351 if (args
.size() > 4)
1353 macroArgs
= args
[4];
1355 for (size_t i
= 5; i
< args
.size(); ++i
)
1358 macroArgs
+= args
[i
];
1362 return cmCallVisualStudioMacro::CallMacro(args
[2], args
[3], macroArgs
);
1366 // Internal CMake dependency scanning support.
1367 else if (args
[1] == "cmake_depends" && args
.size() >= 6)
1369 // Use the make system's VERBOSE environment variable to enable
1371 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
1373 // Create a cmake object instance to process dependencies.
1376 std::string homeDir
;
1377 std::string startDir
;
1378 std::string homeOutDir
;
1379 std::string startOutDir
;
1380 std::string depInfo
;
1382 if(args
.size() >= 8)
1386 // -E cmake_depends <generator>
1387 // <home-src-dir> <start-src-dir>
1388 // <home-out-dir> <start-out-dir>
1389 // <dep-info> [--color=$(COLOR)]
1391 // All paths are provided.
1395 homeOutDir
= args
[5];
1396 startOutDir
= args
[6];
1398 if(args
.size() >= 9 &&
1399 args
[8].length() > 8 &&
1400 args
[8].substr(0, 8) == "--color=")
1402 // Enable or disable color based on the switch value.
1403 color
= cmSystemTools::IsOn(args
[8].substr(8).c_str());
1408 // Support older signature for existing makefiles:
1410 // -E cmake_depends <generator>
1411 // <home-out-dir> <start-out-dir>
1414 // Just pretend the source directories are the same as the
1415 // binary directories so at least scanning will work.
1419 homeOutDir
= args
[3];
1420 startOutDir
= args
[3];
1424 // Create a local generator configured for the directory in
1425 // which dependencies will be scanned.
1426 homeDir
= cmSystemTools::CollapseFullPath(homeDir
.c_str());
1427 startDir
= cmSystemTools::CollapseFullPath(startDir
.c_str());
1428 homeOutDir
= cmSystemTools::CollapseFullPath(homeOutDir
.c_str());
1429 startOutDir
= cmSystemTools::CollapseFullPath(startOutDir
.c_str());
1430 cm
.SetHomeDirectory(homeDir
.c_str());
1431 cm
.SetStartDirectory(startDir
.c_str());
1432 cm
.SetHomeOutputDirectory(homeOutDir
.c_str());
1433 cm
.SetStartOutputDirectory(startOutDir
.c_str());
1434 if(cmGlobalGenerator
* ggd
= cm
.CreateGlobalGenerator(gen
.c_str()))
1436 cm
.SetGlobalGenerator(ggd
);
1437 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
1438 lgd
->SetGlobalGenerator(ggd
);
1439 lgd
->GetMakefile()->SetStartDirectory(startDir
.c_str());
1440 lgd
->GetMakefile()->SetStartOutputDirectory(startOutDir
.c_str());
1441 lgd
->GetMakefile()->MakeStartDirectoriesCurrent();
1443 // Actually scan dependencies.
1444 return lgd
->UpdateDependencies(depInfo
.c_str(),
1445 verbose
, color
)? 0 : 2;
1450 // Internal CMake link script support.
1451 else if (args
[1] == "cmake_link_script" && args
.size() >= 3)
1453 return cmake::ExecuteLinkScript(args
);
1456 // Internal CMake unimplemented feature notification.
1457 else if (args
[1] == "cmake_unimplemented_variable")
1459 std::cerr
<< "Feature not implemented for this platform.";
1460 if(args
.size() == 3)
1462 std::cerr
<< " Variable " << args
[2] << " is not set.";
1464 std::cerr
<< std::endl
;
1467 else if (args
[1] == "vs_link_exe")
1469 return cmake::VisualStudioLink(args
, 1);
1471 else if (args
[1] == "vs_link_dll")
1473 return cmake::VisualStudioLink(args
, 2);
1475 #ifdef CMAKE_BUILD_WITH_CMAKE
1476 // Internal CMake color makefile support.
1477 else if (args
[1] == "cmake_echo_color")
1479 return cmake::ExecuteEchoColor(args
);
1484 else if (args
[1] == "tar" && args
.size() > 3)
1486 std::string flags
= args
[2];
1487 std::string outFile
= args
[3];
1488 std::vector
<cmStdString
> files
;
1489 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1491 files
.push_back(args
[cc
]);
1494 bool verbose
= false;
1495 if ( flags
.find_first_of('z') != flags
.npos
)
1499 if ( flags
.find_first_of('v') != flags
.npos
)
1504 if ( flags
.find_first_of('t') != flags
.npos
)
1506 if ( !cmSystemTools::ListTar(outFile
.c_str(), files
, gzip
, verbose
) )
1508 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1512 else if ( flags
.find_first_of('c') != flags
.npos
)
1514 if ( !cmSystemTools::CreateTar(
1515 outFile
.c_str(), files
, gzip
, verbose
) )
1517 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1521 else if ( flags
.find_first_of('x') != flags
.npos
)
1523 if ( !cmSystemTools::ExtractTar(
1524 outFile
.c_str(), files
, gzip
, verbose
) )
1526 cmSystemTools::Error("Problem extracting tar: ", outFile
.c_str());
1533 #if defined(CMAKE_BUILD_WITH_CMAKE)
1534 // Internal CMake Fortran module support.
1535 else if (args
[1] == "cmake_copy_f90_mod" && args
.size() >= 4)
1537 return cmDependsFortran::CopyModule(args
)? 0 : 1;
1541 #if defined(_WIN32) && !defined(__CYGWIN__)
1542 // Write registry value
1543 else if (args
[1] == "write_regv" && args
.size() > 3)
1545 return cmSystemTools::WriteRegistryValue(args
[2].c_str(),
1546 args
[3].c_str()) ? 0 : 1;
1549 // Delete registry value
1550 else if (args
[1] == "delete_regv" && args
.size() > 2)
1552 return cmSystemTools::DeleteRegistryValue(args
[2].c_str()) ? 0 : 1;
1555 else if (args
[1] == "comspec" && args
.size() > 2)
1558 std::string command
= args
[2];
1559 for ( cc
= 3; cc
< args
.size(); cc
++ )
1561 command
+= " " + args
[cc
];
1563 return cmWin32ProcessExecution::Windows9xHack(command
.c_str());
1568 ::CMakeCommandUsage(args
[0].c_str());
1572 void cmake::AddExtraGenerator(const char* name
,
1573 CreateExtraGeneratorFunctionType newFunction
)
1575 cmExternalMakefileProjectGenerator
* extraGenerator
= newFunction();
1576 const std::vector
<std::string
>& supportedGlobalGenerators
=
1577 extraGenerator
->GetSupportedGlobalGenerators();
1579 for(std::vector
<std::string
>::const_iterator
1580 it
= supportedGlobalGenerators
.begin();
1581 it
!= supportedGlobalGenerators
.end();
1584 std::string fullName
= cmExternalMakefileProjectGenerator::
1585 CreateFullGeneratorName(it
->c_str(), name
);
1586 this->ExtraGenerators
[fullName
.c_str()] = newFunction
;
1588 delete extraGenerator
;
1591 void cmake::AddDefaultExtraGenerators()
1593 #if defined(CMAKE_BUILD_WITH_CMAKE)
1594 #if defined(_WIN32) && !defined(__CYGWIN__)
1598 #if !defined(__CYGWIN__)
1599 this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
1600 &cmExtraCodeBlocksGenerator::New
);
1603 #ifdef CMAKE_USE_ECLIPSE
1604 this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
1605 &cmExtraEclipseCDT4Generator::New
);
1608 #ifdef CMAKE_USE_KDEVELOP
1609 this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
1610 &cmGlobalKdevelopGenerator::New
);
1611 // for kdevelop also add the generator with just the name of the
1612 // extra generator, since it was this way since cmake 2.2
1613 this->ExtraGenerators
[cmGlobalKdevelopGenerator::GetActualName()]
1614 = &cmGlobalKdevelopGenerator::New
;
1621 //----------------------------------------------------------------------------
1622 void cmake::GetRegisteredGenerators(std::vector
<std::string
>& names
)
1624 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
1625 i
!= this->Generators
.end(); ++i
)
1627 names
.push_back(i
->first
);
1629 for(RegisteredExtraGeneratorsMap::const_iterator
1630 i
= this->ExtraGenerators
.begin();
1631 i
!= this->ExtraGenerators
.end(); ++i
)
1633 names
.push_back(i
->first
);
1637 cmGlobalGenerator
* cmake::CreateGlobalGenerator(const char* name
)
1639 cmGlobalGenerator
* generator
= 0;
1640 cmExternalMakefileProjectGenerator
* extraGenerator
= 0;
1641 RegisteredGeneratorsMap::const_iterator genIt
= this->Generators
.find(name
);
1642 if(genIt
== this->Generators
.end())
1644 RegisteredExtraGeneratorsMap::const_iterator extraGenIt
=
1645 this->ExtraGenerators
.find(name
);
1646 if (extraGenIt
== this->ExtraGenerators
.end())
1650 extraGenerator
= (extraGenIt
->second
)();
1651 genIt
=this->Generators
.find(extraGenerator
->GetGlobalGeneratorName(name
));
1652 if(genIt
== this->Generators
.end())
1654 delete extraGenerator
;
1659 generator
= (genIt
->second
)();
1660 generator
->SetCMakeInstance(this);
1661 generator
->SetExternalMakefileProjectGenerator(extraGenerator
);
1665 void cmake::SetHomeDirectory(const char* dir
)
1667 this->cmHomeDirectory
= dir
;
1668 cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory
);
1671 void cmake::SetHomeOutputDirectory(const char* lib
)
1673 this->HomeOutputDirectory
= lib
;
1674 cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory
);
1677 void cmake::SetGlobalGenerator(cmGlobalGenerator
*gg
)
1681 cmSystemTools::Error("Error SetGlobalGenerator called with null");
1684 // delete the old generator
1685 if (this->GlobalGenerator
)
1687 delete this->GlobalGenerator
;
1688 // restore the original environment variables CXX and CC
1690 std::string env
= "CC=";
1691 if(this->CCEnvironment
.size())
1693 env
+= this->CCEnvironment
;
1695 cmSystemTools::PutEnv(env
.c_str());
1697 if(this->CXXEnvironment
.size())
1699 env
+= this->CXXEnvironment
;
1701 cmSystemTools::PutEnv(env
.c_str());
1705 this->GlobalGenerator
= gg
;
1707 // set the global flag for unix style paths on cmSystemTools as soon as
1708 // the generator is set. This allows gmake to be used on windows.
1709 cmSystemTools::SetForceUnixPaths
1710 (this->GlobalGenerator
->GetForceUnixPaths());
1712 // Save the environment variables CXX and CC
1713 const char* cxx
= getenv("CXX");
1714 const char* cc
= getenv("CC");
1717 this->CXXEnvironment
= cxx
;
1721 this->CXXEnvironment
= "";
1725 this->CCEnvironment
= cc
;
1729 this->CCEnvironment
= "";
1731 // set the cmake instance just to be sure
1732 gg
->SetCMakeInstance(this);
1735 int cmake::DoPreConfigureChecks()
1737 // Make sure the Start directory contains a CMakeLists.txt file.
1738 std::string srcList
= this->GetHomeDirectory();
1739 srcList
+= "/CMakeLists.txt";
1740 if(!cmSystemTools::FileExists(srcList
.c_str()))
1742 cmOStringStream err
;
1743 if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
1745 err
<< "The source directory \"" << this->GetHomeDirectory()
1746 << "\" does not appear to contain CMakeLists.txt.\n";
1748 else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
1750 err
<< "The source directory \"" << this->GetHomeDirectory()
1751 << "\" is a file, not a directory.\n";
1755 err
<< "The source directory \"" << this->GetHomeDirectory()
1756 << "\" does not exist.\n";
1758 err
<< "Specify --help for usage, or press the help button on the CMake "
1760 cmSystemTools::Error(err
.str().c_str());
1764 // do a sanity check on some values
1765 if(this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY"))
1767 std::string cacheStart
=
1768 this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY");
1769 cacheStart
+= "/CMakeLists.txt";
1770 std::string currentStart
= this->GetHomeDirectory();
1771 currentStart
+= "/CMakeLists.txt";
1772 if(!cmSystemTools::SameFile(cacheStart
.c_str(), currentStart
.c_str()))
1774 std::string message
= "The source \"";
1775 message
+= currentStart
;
1776 message
+= "\" does not match the source \"";
1777 message
+= cacheStart
;
1778 message
+= "\" used to generate cache. ";
1779 message
+= "Re-run cmake with a different source directory.";
1780 cmSystemTools::Error(message
.c_str());
1790 struct SaveCacheEntry
1795 cmCacheManager::CacheEntryType type
;
1798 int cmake::HandleDeleteCacheVariables(const char* var
)
1800 std::vector
<std::string
> argsSplit
;
1801 cmSystemTools::ExpandListArgument(std::string(var
), argsSplit
);
1802 // erase the property to avoid infinite recursion
1803 this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
1805 cmCacheManager::CacheIterator ci
= this->CacheManager
->NewIterator();
1806 std::vector
<SaveCacheEntry
> saved
;
1807 cmOStringStream warning
;
1809 << "You have changed variables that require your cache to be deleted.\n"
1810 << "Configure will be re-run and you may have to reset some variables.\n"
1811 << "The following variables have changed:\n";
1812 for(std::vector
<std::string
>::iterator i
= argsSplit
.begin();
1813 i
!= argsSplit
.end(); ++i
)
1815 SaveCacheEntry save
;
1817 warning
<< *i
<< "= ";
1820 warning
<< *i
<< "\n";
1821 if(ci
.Find(save
.key
.c_str()))
1823 save
.type
= ci
.GetType();
1824 save
.help
= ci
.GetProperty("HELPSTRING");
1826 saved
.push_back(save
);
1830 this->CacheManager
->DeleteCache(this->GetStartOutputDirectory());
1831 // load the empty cache
1833 // restore the changed compilers
1834 for(std::vector
<SaveCacheEntry
>::iterator i
= saved
.begin();
1835 i
!= saved
.end(); ++i
)
1837 this->AddCacheEntry(i
->key
.c_str(), i
->value
.c_str(),
1838 i
->help
.c_str(), i
->type
);
1840 cmSystemTools::Message(warning
.str().c_str());
1841 // avoid reconfigure if there were errors
1842 if(!cmSystemTools::GetErrorOccuredFlag())
1845 return this->Configure();
1850 int cmake::Configure()
1852 int ret
= this->ActualConfigure();
1853 const char* delCacheVars
=
1854 this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
1855 if(delCacheVars
&& delCacheVars
[0] != 0)
1857 return this->HandleDeleteCacheVariables(delCacheVars
);
1863 int cmake::ActualConfigure()
1865 // Construct right now our path conversion table before it's too late:
1866 this->UpdateConversionPathTable();
1867 this->CleanupCommandsAndMacros();
1870 if ( !this->ScriptMode
)
1872 res
= this->DoPreConfigureChecks();
1880 this->CacheManager
->AddCacheEntry
1881 ("CMAKE_HOME_DIRECTORY",
1882 this->GetHomeDirectory(),
1883 "Start directory with the top level CMakeLists.txt file for this "
1885 cmCacheManager::INTERNAL
);
1888 // set the default BACKWARDS compatibility to the current version
1889 if(!this->CacheManager
->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
1892 sprintf(ver
,"%i.%i",cmVersion::GetMajorVersion(),
1893 cmVersion::GetMinorVersion());
1894 this->CacheManager
->AddCacheEntry
1895 ("CMAKE_BACKWARDS_COMPATIBILITY",ver
,
1896 "For backwards compatibility, what version of CMake commands and "
1897 "syntax should this version of CMake allow.",
1898 cmCacheManager::STRING
);
1901 // no generator specified on the command line
1902 if(!this->GlobalGenerator
)
1904 const char* genName
=
1905 this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
1906 const char* extraGenName
=
1907 this->CacheManager
->GetCacheValue("CMAKE_EXTRA_GENERATOR");
1910 std::string fullName
= cmExternalMakefileProjectGenerator::
1911 CreateFullGeneratorName(genName
, extraGenName
);
1912 this->GlobalGenerator
= this->CreateGlobalGenerator(fullName
.c_str());
1914 if(this->GlobalGenerator
)
1916 // set the global flag for unix style paths on cmSystemTools as
1917 // soon as the generator is set. This allows gmake to be used
1919 cmSystemTools::SetForceUnixPaths
1920 (this->GlobalGenerator
->GetForceUnixPaths());
1924 #if defined(__BORLANDC__) && defined(_WIN32)
1925 this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator
);
1926 #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
1927 std::string installedCompiler
;
1928 std::string mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1929 "\\VisualStudio\\8.0\\Setup;Dbghelp_path]";
1930 cmSystemTools::ExpandRegistryValues(mp
);
1931 if (!(mp
== "/registry"))
1933 installedCompiler
= "Visual Studio 8 2005";
1937 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1938 "\\VisualStudio\\7.1;InstallDir]";
1939 cmSystemTools::ExpandRegistryValues(mp
);
1940 if (!(mp
== "/registry"))
1942 installedCompiler
= "Visual Studio 7 .NET 2003";
1946 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1947 "\\VisualStudio\\7.0;InstallDir]";
1948 cmSystemTools::ExpandRegistryValues(mp
);
1949 if (!(mp
== "/registry"))
1951 installedCompiler
= "Visual Studio 7";
1955 installedCompiler
= "Visual Studio 6";
1959 cmGlobalGenerator
* gen
1960 = this->CreateGlobalGenerator(installedCompiler
.c_str());
1963 gen
= new cmGlobalNMakeMakefileGenerator
;
1965 this->SetGlobalGenerator(gen
);
1967 this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3
);
1970 if(!this->GlobalGenerator
)
1972 cmSystemTools::Error("Could not create generator");
1977 const char* genName
= this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
1980 if(strcmp(this->GlobalGenerator
->GetName(), genName
) != 0)
1982 std::string message
= "Error: generator : ";
1983 message
+= this->GlobalGenerator
->GetName();
1984 message
+= "\nDoes not match the generator used previously: ";
1987 "\nEither remove the CMakeCache.txt file or choose a different"
1988 " binary directory.";
1989 cmSystemTools::Error(message
.c_str());
1993 if(!this->CacheManager
->GetCacheValue("CMAKE_GENERATOR"))
1995 this->CacheManager
->AddCacheEntry("CMAKE_GENERATOR",
1996 this->GlobalGenerator
->GetName(),
1997 "Name of generator.",
1998 cmCacheManager::INTERNAL
);
1999 this->CacheManager
->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
2000 this->GlobalGenerator
->GetExtraGeneratorName(),
2001 "Name of external makefile project generator.",
2002 cmCacheManager::INTERNAL
);
2005 // reset any system configuration information, except for when we are
2006 // InTryCompile. With TryCompile the system info is taken from the parent's
2007 // info to save time
2008 if (!this->InTryCompile
)
2010 this->GlobalGenerator
->ClearEnabledLanguages();
2013 this->CleanupWrittenFiles();
2015 // Truncate log files
2016 if (!this->InTryCompile
)
2018 this->TruncateOutputLog("CMakeOutput.log");
2019 this->TruncateOutputLog("CMakeError.log");
2022 // actually do the configure
2023 this->GlobalGenerator
->Configure();
2024 // Before saving the cache
2025 // if the project did not define one of the entries below, add them now
2026 // so users can edit the values in the cache:
2027 // LIBRARY_OUTPUT_PATH
2028 // EXECUTABLE_OUTPUT_PATH
2029 if(!this->CacheManager
->GetCacheValue("LIBRARY_OUTPUT_PATH"))
2031 this->CacheManager
->AddCacheEntry
2032 ("LIBRARY_OUTPUT_PATH", "",
2033 "Single output directory for building all libraries.",
2034 cmCacheManager::PATH
);
2036 if(!this->CacheManager
->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
2038 this->CacheManager
->AddCacheEntry
2039 ("EXECUTABLE_OUTPUT_PATH", "",
2040 "Single output directory for building all executables.",
2041 cmCacheManager::PATH
);
2043 if(!this->CacheManager
->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
2045 this->CacheManager
->AddCacheEntry
2046 ("CMAKE_USE_RELATIVE_PATHS", false,
2047 "If true, cmake will use relative paths in makefiles and projects.");
2048 cmCacheManager::CacheIterator it
=
2049 this->CacheManager
->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
2050 if ( !it
.PropertyExists("ADVANCED") )
2052 it
.SetProperty("ADVANCED", "1");
2056 if(cmSystemTools::GetFatalErrorOccured() &&
2057 (!this->CacheManager
->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
2058 cmSystemTools::IsOff(this->CacheManager
->
2059 GetCacheValue("CMAKE_MAKE_PROGRAM"))))
2061 // We must have a bad generator selection. Wipe the cache entry so the
2062 // user can select another.
2063 this->CacheManager
->RemoveCacheEntry("CMAKE_GENERATOR");
2064 this->CacheManager
->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
2066 // only save the cache if there were no fatal errors
2067 if ( !this->ScriptMode
)
2069 this->CacheManager
->SaveCache(this->GetHomeOutputDirectory());
2071 if ( !this->GraphVizFile
.empty() )
2073 std::cout
<< "Generate graphviz: " << this->GraphVizFile
<< std::endl
;
2074 this->GenerateGraphViz(this->GraphVizFile
.c_str());
2076 if(cmSystemTools::GetErrorOccuredFlag())
2083 bool cmake::CacheVersionMatches()
2086 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION");
2088 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MINOR_VERSION");
2090 this->CacheManager
->GetCacheValue("CMAKE_CACHE_RELEASE_VERSION");
2091 bool cacheSameCMake
= false;
2093 atoi(majv
) == static_cast<int>(cmVersion::GetMajorVersion())
2095 atoi(minv
) == static_cast<int>(cmVersion::GetMinorVersion())
2096 && relv
&& (strcmp(relv
, cmVersion::GetReleaseVersion().c_str()) == 0))
2098 cacheSameCMake
= true;
2100 return cacheSameCMake
;
2103 void cmake::PreLoadCMakeFiles()
2105 std::string pre_load
= this->GetHomeDirectory();
2106 if ( pre_load
.size() > 0 )
2108 pre_load
+= "/PreLoad.cmake";
2109 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2111 this->ReadListFile(pre_load
.c_str());
2114 pre_load
= this->GetHomeOutputDirectory();
2115 if ( pre_load
.size() > 0 )
2117 pre_load
+= "/PreLoad.cmake";
2118 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2120 this->ReadListFile(pre_load
.c_str());
2125 // handle a command line invocation
2126 int cmake::Run(const std::vector
<std::string
>& args
, bool noconfigure
)
2128 // Process the arguments
2129 this->SetArgs(args
);
2130 if(cmSystemTools::GetErrorOccuredFlag())
2135 // If we are given a stamp file check if it is really out of date.
2136 if(!this->CheckStampFile
.empty() &&
2137 cmakeCheckStampFile(this->CheckStampFile
.c_str()))
2142 // set the cmake command
2143 this->CMakeCommand
= args
[0];
2145 if ( !this->ScriptMode
)
2148 if(this->LoadCache() < 0)
2150 cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
2156 this->AddCMakePaths();
2159 // Add any cache args
2160 if ( !this->SetCacheArgs(args
) )
2162 cmSystemTools::Error("Problem processing arguments. Aborting.\n");
2166 // In script mode we terminate after running the script.
2167 if(this->ScriptMode
)
2169 if(cmSystemTools::GetErrorOccuredFlag())
2179 this->PreLoadCMakeFiles();
2181 std::string systemFile
= this->GetHomeOutputDirectory();
2182 systemFile
+= "/CMakeSystem.cmake";
2189 // now run the global generate
2190 // Check the state of the build system to see if we need to regenerate.
2191 if(!this->CheckBuildSystem())
2196 // If we are doing global generate, we better set start and start
2197 // output directory to the root of the project.
2198 std::string oldstartdir
= this->GetStartDirectory();
2199 std::string oldstartoutputdir
= this->GetStartOutputDirectory();
2200 this->SetStartDirectory(this->GetHomeDirectory());
2201 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
2202 int ret
= this->Configure();
2203 if (ret
|| this->ScriptMode
)
2205 #if defined(CMAKE_HAVE_VS_GENERATORS)
2206 if(!this->VSSolutionFile
.empty() && this->GlobalGenerator
)
2208 // CMake is running to regenerate a Visual Studio build tree
2209 // during a build from the VS IDE. The build files cannot be
2210 // regenerated, so we should stop the build.
2211 cmSystemTools::Message(
2212 "CMake Configure step failed. "
2213 "Build files cannot be regenerated correctly. "
2214 "Attempting to stop IDE build.");
2215 cmGlobalVisualStudioGenerator
* gg
=
2216 static_cast<cmGlobalVisualStudioGenerator
*>(this->GlobalGenerator
);
2217 gg
->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop
,
2218 this->VSSolutionFile
.c_str());
2223 ret
= this->Generate();
2224 std::string message
= "Build files have been written to: ";
2225 message
+= this->GetHomeOutputDirectory();
2226 this->UpdateProgress(message
.c_str(), -1);
2231 this->SetStartDirectory(oldstartdir
.c_str());
2232 this->SetStartOutputDirectory(oldstartoutputdir
.c_str());
2237 int cmake::Generate()
2239 if(!this->GlobalGenerator
)
2243 this->GlobalGenerator
->Generate();
2244 if(cmSystemTools::GetErrorOccuredFlag())
2248 if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
2250 this->ReportUndefinedPropertyAccesses
2251 (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
2256 void cmake::AddCacheEntry(const char* key
, const char* value
,
2257 const char* helpString
,
2260 this->CacheManager
->AddCacheEntry(key
, value
,
2262 cmCacheManager::CacheEntryType(type
));
2265 const char* cmake::GetCacheDefinition(const char* name
) const
2267 return this->CacheManager
->GetCacheValue(name
);
2270 int cmake::DumpDocumentationToFile(std::ostream
& f
)
2272 #ifdef CMAKE_BUILD_WITH_CMAKE
2273 // Loop over all registered commands and print out documentation
2278 sprintf(tmp
,"Version %d.%d (%s)", cmVersion::GetMajorVersion(),
2279 cmVersion::GetMinorVersion(),
2280 cmVersion::GetReleaseVersion().c_str());
2282 f
<< "<h1>Documentation for commands of CMake " << tmp
<< "</h1>\n";
2284 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
2285 j
!= this->Commands
.end(); ++j
)
2287 name
= (*j
).second
->GetName();
2288 terse
= (*j
).second
->GetTerseDocumentation();
2289 full
= (*j
).second
->GetFullDocumentation();
2290 f
<< "<li><b>" << name
<< "</b> - " << terse
<< std::endl
2291 << "<br><i>Usage:</i> " << full
<< "</li>" << std::endl
<< std::endl
;
2293 f
<< "</ul></html>\n";
2300 void cmake::AddDefaultCommands()
2302 std::list
<cmCommand
*> commands
;
2303 GetBootstrapCommands(commands
);
2304 GetPredefinedCommands(commands
);
2305 for(std::list
<cmCommand
*>::iterator i
= commands
.begin();
2306 i
!= commands
.end(); ++i
)
2308 this->AddCommand(*i
);
2312 void cmake::AddDefaultGenerators()
2314 #if defined(_WIN32) && !defined(__CYGWIN__)
2315 # if !defined(CMAKE_BOOT_MINGW)
2316 this->Generators
[cmGlobalVisualStudio6Generator::GetActualName()] =
2317 &cmGlobalVisualStudio6Generator::New
;
2318 this->Generators
[cmGlobalVisualStudio7Generator::GetActualName()] =
2319 &cmGlobalVisualStudio7Generator::New
;
2320 this->Generators
[cmGlobalVisualStudio71Generator::GetActualName()] =
2321 &cmGlobalVisualStudio71Generator::New
;
2322 this->Generators
[cmGlobalVisualStudio8Generator::GetActualName()] =
2323 &cmGlobalVisualStudio8Generator::New
;
2324 this->Generators
[cmGlobalVisualStudio9Generator::GetActualName()] =
2325 &cmGlobalVisualStudio9Generator::New
;
2326 this->Generators
[cmGlobalVisualStudio9Win64Generator::GetActualName()] =
2327 &cmGlobalVisualStudio9Win64Generator::New
;
2328 this->Generators
[cmGlobalVisualStudio8Win64Generator::GetActualName()] =
2329 &cmGlobalVisualStudio8Win64Generator::New
;
2330 this->Generators
[cmGlobalBorlandMakefileGenerator::GetActualName()] =
2331 &cmGlobalBorlandMakefileGenerator::New
;
2332 this->Generators
[cmGlobalNMakeMakefileGenerator::GetActualName()] =
2333 &cmGlobalNMakeMakefileGenerator::New
;
2334 this->Generators
[cmGlobalWatcomWMakeGenerator::GetActualName()] =
2335 &cmGlobalWatcomWMakeGenerator::New
;
2337 this->Generators
[cmGlobalMSYSMakefileGenerator::GetActualName()] =
2338 &cmGlobalMSYSMakefileGenerator::New
;
2339 this->Generators
[cmGlobalMinGWMakefileGenerator::GetActualName()] =
2340 &cmGlobalMinGWMakefileGenerator::New
;
2342 this->Generators
[cmGlobalUnixMakefileGenerator3::GetActualName()] =
2343 &cmGlobalUnixMakefileGenerator3::New
;
2344 #ifdef CMAKE_USE_XCODE
2345 this->Generators
[cmGlobalXCodeGenerator::GetActualName()] =
2346 &cmGlobalXCodeGenerator::New
;
2350 int cmake::LoadCache()
2352 // could we not read the cache
2353 if (!this->CacheManager
->LoadCache(this->GetHomeOutputDirectory()))
2355 // if it does exist, but isn;t readable then warn the user
2356 std::string cacheFile
= this->GetHomeOutputDirectory();
2357 cacheFile
+= "/CMakeCache.txt";
2358 if(cmSystemTools::FileExists(cacheFile
.c_str()))
2360 cmSystemTools::Error(
2361 "There is a CMakeCache.txt file for the current binary tree but "
2362 "cmake does not have permission to read it. Please check the "
2363 "permissions of the directory you are trying to run CMake on.");
2368 if (this->CMakeCommand
.size() < 2)
2370 cmSystemTools::Error(
2371 "cmake command was not specified prior to loading the cache in "
2376 // setup CMAKE_ROOT and CMAKE_COMMAND
2377 if(!this->AddCMakePaths())
2382 // set the default BACKWARDS compatibility to the current version
2383 if(!this->CacheManager
->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
2386 sprintf(ver
,"%i.%i",cmVersion::GetMajorVersion(),
2387 cmVersion::GetMinorVersion());
2388 this->CacheManager
->AddCacheEntry
2389 ("CMAKE_BACKWARDS_COMPATIBILITY",ver
,
2390 "For backwards compatibility, what version of CMake commands and "
2391 "syntax should this version of CMake allow.",
2392 cmCacheManager::STRING
);
2398 void cmake::SetProgressCallback(ProgressCallbackType f
, void *cd
)
2400 this->ProgressCallback
= f
;
2401 this->ProgressCallbackClientData
= cd
;
2404 void cmake::UpdateProgress(const char *msg
, float prog
)
2406 if(this->ProgressCallback
&& !this->InTryCompile
)
2408 (*this->ProgressCallback
)(msg
, prog
, this->ProgressCallbackClientData
);
2413 void cmake::GetCommandDocumentation(std::vector
<cmDocumentationEntry
>& v
,
2414 bool withCurrentCommands
,
2415 bool withCompatCommands
) const
2417 for(RegisteredCommandsMap::const_iterator j
= this->Commands
.begin();
2418 j
!= this->Commands
.end(); ++j
)
2420 if ((( withCompatCommands
== false) && ( (*j
).second
->IsDiscouraged()))
2421 || ((withCurrentCommands
== false) && (!(*j
).second
->IsDiscouraged())))
2426 cmDocumentationEntry
e((*j
).second
->GetName(),
2427 (*j
).second
->GetTerseDocumentation(),
2428 (*j
).second
->GetFullDocumentation());
2433 void cmake::GetPropertiesDocumentation(std::map
<std::string
,
2434 cmDocumentationSection
*>& v
)
2436 // loop over the properties and put them into the doc structure
2437 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
2438 i
= this->PropertyDefinitions
.begin();
2439 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
2441 i
->second
.GetPropertiesDocumentation(v
);
2445 void cmake::GetGeneratorDocumentation(std::vector
<cmDocumentationEntry
>& v
)
2447 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
2448 i
!= this->Generators
.end(); ++i
)
2450 cmDocumentationEntry e
;
2451 cmGlobalGenerator
* generator
= (i
->second
)();
2452 generator
->GetDocumentation(e
);
2456 for(RegisteredExtraGeneratorsMap::const_iterator
2457 i
= this->ExtraGenerators
.begin(); i
!= this->ExtraGenerators
.end(); ++i
)
2459 cmDocumentationEntry e
;
2460 cmExternalMakefileProjectGenerator
* generator
= (i
->second
)();
2461 generator
->GetDocumentation(e
, i
->first
.c_str());
2468 void cmake::AddWrittenFile(const char* file
)
2470 this->WrittenFiles
.insert(file
);
2473 bool cmake::HasWrittenFile(const char* file
)
2475 return this->WrittenFiles
.find(file
) != this->WrittenFiles
.end();
2478 void cmake::CleanupWrittenFiles()
2480 this->WrittenFiles
.clear();
2483 void cmake::UpdateConversionPathTable()
2485 // Update the path conversion table with any specified file:
2486 const char* tablepath
=
2487 this->CacheManager
->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
2491 std::ifstream
table( tablepath
);
2494 cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath
,
2495 ". CMake can not open file.");
2496 cmSystemTools::ReportLastSystemError("CMake can not open file.");
2503 // two entries per line
2504 table
>> a
; table
>> b
;
2505 cmSystemTools::AddTranslationPath( a
.c_str(), b
.c_str());
2511 //----------------------------------------------------------------------------
2512 int cmake::CheckBuildSystem()
2514 // We do not need to rerun CMake. Check dependency integrity. Use
2515 // the make system's VERBOSE environment variable to enable verbose
2517 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
2519 // This method will check the integrity of the build system if the
2520 // option was given on the command line. It reads the given file to
2521 // determine whether CMake should rerun.
2523 // If no file is provided for the check, we have to rerun.
2524 if(this->CheckBuildSystemArgument
.size() == 0)
2528 cmOStringStream msg
;
2529 msg
<< "Re-run cmake no build system arguments\n";
2530 cmSystemTools::Stdout(msg
.str().c_str());
2535 // If the file provided does not exist, we have to rerun.
2536 if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument
.c_str()))
2540 cmOStringStream msg
;
2541 msg
<< "Re-run cmake missing file: "
2542 << this->CheckBuildSystemArgument
.c_str() << "\n";
2543 cmSystemTools::Stdout(msg
.str().c_str());
2548 // Read the rerun check file and use it to decide whether to do the
2551 cmGlobalGenerator gg
;
2552 gg
.SetCMakeInstance(&cm
);
2553 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
2554 lg
->SetGlobalGenerator(&gg
);
2555 cmMakefile
* mf
= lg
->GetMakefile();
2556 if(!mf
->ReadListFile(0, this->CheckBuildSystemArgument
.c_str()) ||
2557 cmSystemTools::GetErrorOccuredFlag())
2561 cmOStringStream msg
;
2562 msg
<< "Re-run cmake error reading : "
2563 << this->CheckBuildSystemArgument
.c_str() << "\n";
2564 cmSystemTools::Stdout(msg
.str().c_str());
2566 // There was an error reading the file. Just rerun.
2570 if(this->ClearBuildSystem
)
2572 // Get the generator used for this build system.
2573 const char* genName
= mf
->GetDefinition("CMAKE_DEPENDS_GENERATOR");
2574 if(!genName
|| genName
[0] == '\0')
2576 genName
= "Unix Makefiles";
2579 // Create the generator and use it to clear the dependencies.
2580 std::auto_ptr
<cmGlobalGenerator
>
2581 ggd(this->CreateGlobalGenerator(genName
));
2584 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
2585 lgd
->SetGlobalGenerator(ggd
.get());
2586 lgd
->ClearDependencies(mf
, verbose
);
2590 // Get the set of dependencies and outputs.
2591 std::vector
<std::string
> depends
;
2592 std::vector
<std::string
> outputs
;
2593 const char* dependsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
2594 const char* outputsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
2595 if(dependsStr
&& outputsStr
)
2597 cmSystemTools::ExpandListArgument(dependsStr
, depends
);
2598 cmSystemTools::ExpandListArgument(outputsStr
, outputs
);
2600 if(depends
.empty() || outputs
.empty())
2602 // Not enough information was provided to do the test. Just rerun.
2605 cmOStringStream msg
;
2606 msg
<< "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
2607 "or CMAKE_MAKEFILE_OUTPUTS :\n";
2608 cmSystemTools::Stdout(msg
.str().c_str());
2613 // Find find the newest dependency.
2614 std::vector
<std::string
>::iterator dep
= depends
.begin();
2615 std::string dep_newest
= *dep
++;
2616 for(;dep
!= depends
.end(); ++dep
)
2619 if(this->FileComparison
->FileTimeCompare(dep_newest
.c_str(),
2620 dep
->c_str(), &result
))
2631 cmOStringStream msg
;
2632 msg
<< "Re-run cmake: build system dependency is missing\n";
2633 cmSystemTools::Stdout(msg
.str().c_str());
2639 // Find find the oldest output.
2640 std::vector
<std::string
>::iterator out
= outputs
.begin();
2641 std::string out_oldest
= *out
++;
2642 for(;out
!= outputs
.end(); ++out
)
2645 if(this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2646 out
->c_str(), &result
))
2657 cmOStringStream msg
;
2658 msg
<< "Re-run cmake: build system output is missing\n";
2659 cmSystemTools::Stdout(msg
.str().c_str());
2665 // If any output is older than any dependency then rerun.
2668 if(!this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2675 cmOStringStream msg
;
2676 msg
<< "Re-run cmake file: " << out_oldest
.c_str()
2677 << " older than: " << dep_newest
.c_str() << "\n";
2678 cmSystemTools::Stdout(msg
.str().c_str());
2684 // No need to rerun.
2688 //----------------------------------------------------------------------------
2689 void cmake::TruncateOutputLog(const char* fname
)
2691 std::string fullPath
= this->GetHomeOutputDirectory();
2695 if ( ::stat(fullPath
.c_str(), &st
) )
2699 if ( !this->CacheManager
->GetCacheValue("CMAKE_CACHEFILE_DIR") )
2701 cmSystemTools::RemoveFile(fullPath
.c_str());
2704 off_t fsize
= st
.st_size
;
2705 const off_t maxFileSize
= 50 * 1024;
2706 if ( fsize
< maxFileSize
)
2708 //TODO: truncate file
2713 inline std::string
removeQuotes(const std::string
& s
)
2715 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
2717 return s
.substr(1, s
.size()-2);
2722 std::string
cmake::FindCMakeProgram(const char* name
) const
2725 if ((name
) && (*name
))
2727 const cmMakefile
* mf
2728 = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
2729 #ifdef CMAKE_BUILD_WITH_CMAKE
2730 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2731 path
= removeQuotes(path
);
2732 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2735 path
+= cmSystemTools::GetExecutableExtension();
2736 if(!cmSystemTools::FileExists(path
.c_str()))
2738 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2739 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2742 path
+= cmSystemTools::GetExecutableExtension();
2744 if(!cmSystemTools::FileExists(path
.c_str()))
2746 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2747 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2748 path
+= "/Release/";
2750 path
+= cmSystemTools::GetExecutableExtension();
2753 // Only for bootstrap
2754 path
+= mf
->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
2757 path
+= cmSystemTools::GetExecutableExtension();
2763 const char* cmake::GetCTestCommand()
2765 if ( this->CTestCommand
.empty() )
2767 this->CTestCommand
= this->FindCMakeProgram("ctest");
2769 if ( this->CTestCommand
.empty() )
2771 cmSystemTools::Error("Cannot find the CTest executable");
2772 this->CTestCommand
= "CTEST-COMMAND-NOT-FOUND";
2774 return this->CTestCommand
.c_str();
2777 const char* cmake::GetCPackCommand()
2779 if ( this->CPackCommand
.empty() )
2781 this->CPackCommand
= this->FindCMakeProgram("cpack");
2783 if ( this->CPackCommand
.empty() )
2785 cmSystemTools::Error("Cannot find the CPack executable");
2786 this->CPackCommand
= "CPACK-COMMAND-NOT-FOUND";
2788 return this->CPackCommand
.c_str();
2791 void cmake::GenerateGraphViz(const char* fileName
) const
2793 cmGeneratedFileStream
str(fileName
);
2799 cmGlobalGenerator ggi
;
2800 ggi
.SetCMakeInstance(&cm
);
2801 std::auto_ptr
<cmLocalGenerator
> lg(ggi
.CreateLocalGenerator());
2802 lg
->SetGlobalGenerator(&ggi
);
2803 cmMakefile
*mf
= lg
->GetMakefile();
2805 std::string infile
= this->GetHomeOutputDirectory();
2806 infile
+= "/CMakeGraphVizOptions.cmake";
2807 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2809 infile
= this->GetHomeDirectory();
2810 infile
+= "/CMakeGraphVizOptions.cmake";
2811 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2817 if ( !infile
.empty() )
2819 if ( !mf
->ReadListFile(0, infile
.c_str()) )
2821 cmSystemTools::Error("Problem opening GraphViz options file: ",
2825 std::cout
<< "Read GraphViz options file: " << infile
.c_str()
2829 #define __set_if_not_set(var, value, cmakeDefinition) \
2830 const char* var = mf->GetDefinition(cmakeDefinition); \
2835 __set_if_not_set(graphType
, "digraph", "GRAPHVIZ_GRAPH_TYPE");
2836 __set_if_not_set(graphName
, "GG", "GRAPHVIZ_GRAPH_NAME");
2837 __set_if_not_set(graphHeader
, "node [\n fontsize = \"12\"\n];",
2838 "GRAPHVIZ_GRAPH_HEADER");
2839 __set_if_not_set(graphNodePrefix
, "node", "GRAPHVIZ_NODE_PREFIX");
2840 const char* ignoreTargets
= mf
->GetDefinition("GRAPHVIZ_IGNORE_TARGETS");
2841 std::set
<cmStdString
> ignoreTargetsSet
;
2842 if ( ignoreTargets
)
2844 std::vector
<std::string
> ignoreTargetsVector
;
2845 cmSystemTools::ExpandListArgument(ignoreTargets
,ignoreTargetsVector
);
2846 std::vector
<std::string
>::iterator itvIt
;
2847 for ( itvIt
= ignoreTargetsVector
.begin();
2848 itvIt
!= ignoreTargetsVector
.end();
2851 ignoreTargetsSet
.insert(itvIt
->c_str());
2855 str
<< graphType
<< " " << graphName
<< " {" << std::endl
;
2856 str
<< graphHeader
<< std::endl
;
2858 const cmGlobalGenerator
* gg
= this->GetGlobalGenerator();
2859 const std::vector
<cmLocalGenerator
*>& localGenerators
=
2860 gg
->GetLocalGenerators();
2861 std::vector
<cmLocalGenerator
*>::const_iterator lit
;
2864 // 2 - external target
2866 std::map
<cmStdString
, int> targetDeps
;
2867 std::map
<cmStdString
, const cmTarget
*> targetPtrs
;
2868 std::map
<cmStdString
, cmStdString
> targetNamesNodes
;
2870 // First pass get the list of all cmake targets
2871 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2873 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2874 cmTargets::const_iterator tit
;
2875 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2877 const char* realTargetName
= tit
->first
.c_str();
2878 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2880 // Skip ignored targets
2883 //std::cout << "Found target: " << tit->first.c_str() << std::endl;
2884 cmOStringStream ostr
;
2885 ostr
<< graphNodePrefix
<< cnt
++;
2886 targetNamesNodes
[realTargetName
] = ostr
.str();
2887 targetPtrs
[realTargetName
] = &tit
->second
;
2890 // Ok, now find all the stuff we link to that is not in cmake
2891 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2893 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2894 cmTargets::const_iterator tit
;
2895 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2897 const cmTarget::LinkLibraryVectorType
* ll
2898 = &(tit
->second
.GetOriginalLinkLibraries());
2899 cmTarget::LinkLibraryVectorType::const_iterator llit
;
2900 const char* realTargetName
= tit
->first
.c_str();
2901 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2903 // Skip ignored targets
2906 if ( ll
->size() > 0 )
2908 targetDeps
[realTargetName
] = 1;
2910 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
2912 const char* libName
= llit
->first
.c_str();
2913 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
2914 = targetNamesNodes
.find(libName
);
2915 if ( ignoreTargetsSet
.find(libName
) != ignoreTargetsSet
.end() )
2917 // Skip ignored targets
2920 if ( tarIt
== targetNamesNodes
.end() )
2922 cmOStringStream ostr
;
2923 ostr
<< graphNodePrefix
<< cnt
++;
2924 targetDeps
[libName
] = 2;
2925 targetNamesNodes
[libName
] = ostr
.str();
2926 //str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
2927 //<< "\" shape=\"ellipse\"];" << std::endl;
2931 std::map
<cmStdString
, int>::const_iterator depIt
2932 = targetDeps
.find(libName
);
2933 if ( depIt
== targetDeps
.end() )
2935 targetDeps
[libName
] = 1;
2943 std::map
<cmStdString
, int>::const_iterator depIt
;
2944 for ( depIt
= targetDeps
.begin(); depIt
!= targetDeps
.end(); ++ depIt
)
2946 const char* newTargetName
= depIt
->first
.c_str();
2947 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
2948 = targetNamesNodes
.find(newTargetName
);
2949 if ( tarIt
== targetNamesNodes
.end() )
2951 // We should not be here.
2952 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
2953 << " even though it was added in the previous pass" << std::endl
;
2957 str
<< " \"" << tarIt
->second
.c_str() << "\" [ label=\""
2958 << newTargetName
<< "\" shape=\"";
2959 if ( depIt
->second
== 1 )
2961 std::map
<cmStdString
, const cmTarget
*>::const_iterator tarTypeIt
=
2962 targetPtrs
.find(newTargetName
);
2963 if ( tarTypeIt
== targetPtrs
.end() )
2965 // We should not be here.
2966 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
2967 << " even though it was added in the previous pass" << std::endl
;
2970 const cmTarget
* tg
= tarTypeIt
->second
;
2971 switch ( tg
->GetType() )
2973 case cmTarget::EXECUTABLE
:
2976 case cmTarget::STATIC_LIBRARY
:
2979 case cmTarget::SHARED_LIBRARY
:
2982 case cmTarget::MODULE_LIBRARY
:
2993 str
<< "\"];" << std::endl
;
2996 // Now generate the connectivity
2997 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2999 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
3000 cmTargets::const_iterator tit
;
3001 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
3003 std::map
<cmStdString
, int>::iterator dependIt
3004 = targetDeps
.find(tit
->first
.c_str());
3005 if ( dependIt
== targetDeps
.end() )
3009 std::map
<cmStdString
, cmStdString
>::iterator cmakeTarIt
3010 = targetNamesNodes
.find(tit
->first
.c_str());
3011 const cmTarget::LinkLibraryVectorType
* ll
3012 = &(tit
->second
.GetOriginalLinkLibraries());
3013 cmTarget::LinkLibraryVectorType::const_iterator llit
;
3014 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
3016 const char* libName
= llit
->first
.c_str();
3017 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3018 = targetNamesNodes
.find(libName
);
3019 if ( tarIt
== targetNamesNodes
.end() )
3021 // We should not be here.
3022 std::cout
<< __LINE__
<< " Cannot find library: " << libName
3023 << " even though it was added in the previous pass" << std::endl
;
3026 str
<< " \"" << cmakeTarIt
->second
.c_str() << "\" -> \""
3027 << tarIt
->second
.c_str() << "\"" << std::endl
;
3032 // TODO: Use dotted or something for external libraries
3033 //str << " \"node0\":f4 -> \"node12\"[color=\"#0000ff\" style=dotted]"
3036 str
<< "}" << std::endl
;
3039 //----------------------------------------------------------------------------
3040 #ifdef CMAKE_BUILD_WITH_CMAKE
3041 int cmake::ExecuteEchoColor(std::vector
<std::string
>& args
)
3043 // The arguments are
3044 // argv[0] == <cmake-executable>
3045 // argv[1] == cmake_echo_color
3047 bool enabled
= true;
3048 int color
= cmsysTerminal_Color_Normal
;
3049 bool newline
= true;
3050 for(unsigned int i
=2; i
< args
.size(); ++i
)
3052 if(args
[i
].find("--switch=") == 0)
3054 // Enable or disable color based on the switch value.
3055 std::string value
= args
[i
].substr(9);
3058 if(cmSystemTools::IsOn(value
.c_str()))
3068 else if(args
[i
] == "--normal")
3070 color
= cmsysTerminal_Color_Normal
;
3072 else if(args
[i
] == "--black")
3074 color
= cmsysTerminal_Color_ForegroundBlack
;
3076 else if(args
[i
] == "--red")
3078 color
= cmsysTerminal_Color_ForegroundRed
;
3080 else if(args
[i
] == "--green")
3082 color
= cmsysTerminal_Color_ForegroundGreen
;
3084 else if(args
[i
] == "--yellow")
3086 color
= cmsysTerminal_Color_ForegroundYellow
;
3088 else if(args
[i
] == "--blue")
3090 color
= cmsysTerminal_Color_ForegroundBlue
;
3092 else if(args
[i
] == "--magenta")
3094 color
= cmsysTerminal_Color_ForegroundMagenta
;
3096 else if(args
[i
] == "--cyan")
3098 color
= cmsysTerminal_Color_ForegroundCyan
;
3100 else if(args
[i
] == "--white")
3102 color
= cmsysTerminal_Color_ForegroundWhite
;
3104 else if(args
[i
] == "--bold")
3106 color
|= cmsysTerminal_Color_ForegroundBold
;
3108 else if(args
[i
] == "--no-newline")
3112 else if(args
[i
] == "--newline")
3118 // Color is enabled. Print with the current color.
3119 cmSystemTools::MakefileColorEcho(color
, args
[i
].c_str(),
3127 int cmake::ExecuteEchoColor(std::vector
<std::string
>&)
3133 //----------------------------------------------------------------------------
3134 int cmake::ExecuteLinkScript(std::vector
<std::string
>& args
)
3136 // The arguments are
3137 // argv[0] == <cmake-executable>
3138 // argv[1] == cmake_link_script
3139 // argv[2] == <link-script-name>
3140 // argv[3] == --verbose=?
3141 bool verbose
= false;
3142 if(args
.size() >= 4)
3144 if(args
[3].find("--verbose=") == 0)
3146 if(!cmSystemTools::IsOff(args
[3].substr(10).c_str()))
3153 // Allocate a process instance.
3154 cmsysProcess
* cp
= cmsysProcess_New();
3157 std::cerr
<< "Error allocating process instance in link script."
3162 // Children should share stdout and stderr with this process.
3163 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDOUT
, 1);
3164 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDERR
, 1);
3166 // Run the command lines verbatim.
3167 cmsysProcess_SetOption(cp
, cmsysProcess_Option_Verbatim
, 1);
3169 // Read command lines from the script.
3170 std::ifstream
fin(args
[2].c_str());
3173 std::cerr
<< "Error opening link script \""
3174 << args
[2] << "\"" << std::endl
;
3178 // Run one command at a time.
3179 std::string command
;
3181 while(result
== 0 && cmSystemTools::GetLineFromStream(fin
, command
))
3183 // Setup this command line.
3184 const char* cmd
[2] = {command
.c_str(), 0};
3185 cmsysProcess_SetCommand(cp
, cmd
);
3187 // Report the command if verbose output is enabled.
3190 std::cout
<< command
<< std::endl
;
3193 // Run the command and wait for it to exit.
3194 cmsysProcess_Execute(cp
);
3195 cmsysProcess_WaitForExit(cp
, 0);
3197 // Report failure if any.
3198 switch(cmsysProcess_GetState(cp
))
3200 case cmsysProcess_State_Exited
:
3202 int value
= cmsysProcess_GetExitValue(cp
);
3209 case cmsysProcess_State_Exception
:
3210 std::cerr
<< "Error running link command: "
3211 << cmsysProcess_GetExceptionString(cp
) << std::endl
;
3214 case cmsysProcess_State_Error
:
3215 std::cerr
<< "Error running link command: "
3216 << cmsysProcess_GetErrorString(cp
) << std::endl
;
3224 // Free the process instance.
3225 cmsysProcess_Delete(cp
);
3227 // Return the final resulting return value.
3231 void cmake::DefineProperties(cmake
*cm
)
3234 ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL
,
3235 "If set, report any undefined properties to this file.",
3236 "If this property is set to a filename then when CMake runs "
3237 "it will report any properties or variables that were accessed "
3238 "but not defined into the filename specified in this property."
3242 ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL
,
3243 "Does the target platform support shared libraries.",
3244 "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
3245 "platform supports shared libraries. Basically all current general "
3246 "general purpose OS do so, the exception are usually embedded systems "
3247 "with no or special OSs.");
3249 ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL
,
3250 "Whether FIND_LIBRARY should automatically search lib64 directories.",
3251 "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
3252 "FIND_LIBRARY command should automatically search the lib64 variant of "
3253 "directories called lib in the search path when building 64-bit "
3256 ("ENABLED_FEATURES", cmProperty::GLOBAL
,
3257 "List of features which are enabled during the CMake run.",
3258 "List of features which are enabled during the CMake run. Be default "
3259 "it contains the names of all packages which were found. This is "
3260 "determined using the <NAME>_FOUND variables. Packages which are "
3261 "searched QUIET are not listed. A project can add its own features to "
3262 "this list.This property is used by the macros in FeatureSummary.cmake.");
3264 ("DISABLED_FEATURES", cmProperty::GLOBAL
,
3265 "List of features which are disabled during the CMake run.",
3266 "List of features which are disabled during the CMake run. Be default "
3267 "it contains the names of all packages which were not found. This is "
3268 "determined using the <NAME>_FOUND variables. Packages which are "
3269 "searched QUIET are not listed. A project can add its own features to "
3270 "this list.This property is used by the macros in FeatureSummary.cmake.");
3272 ("PACKAGES_FOUND", cmProperty::GLOBAL
,
3273 "List of packages which were found during the CMake run.",
3274 "List of packages which were found during the CMake run. Whether a "
3275 "package has been found is determined using the <NAME>_FOUND variables.");
3277 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3278 "List of packages which were not found during the CMake run.",
3279 "List of packages which were not found during the CMake run. Whether a "
3280 "package has been found is determined using the <NAME>_FOUND variables.");
3283 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3284 "List of packages which were not found during the CMake run.",
3285 "List of packages which were not found during the CMake run. Whether a "
3286 "package has been found is determined using the <NAME>_FOUND variables.");
3288 "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL
,
3289 "Internal property",
3290 "Used to detect compiler changes, Do not set.");
3292 // ================================================================
3293 // define variables as well
3294 // ================================================================
3295 cmDocumentVariables::DefineVariables(cm
);
3299 void cmake::DefineProperty(const char *name
, cmProperty::ScopeType scope
,
3300 const char *ShortDescription
,
3301 const char *FullDescription
,
3302 bool chained
, const char *docSection
)
3304 this->PropertyDefinitions
[scope
].DefineProperty(name
,scope
,ShortDescription
,
3310 cmPropertyDefinition
*cmake
3311 ::GetPropertyDefinition(const char *name
,
3312 cmProperty::ScopeType scope
)
3314 if (this->IsPropertyDefined(name
,scope
))
3316 return &(this->PropertyDefinitions
[scope
][name
]);
3321 void cmake::RecordPropertyAccess(const char *name
,
3322 cmProperty::ScopeType scope
)
3324 this->AccessedProperties
.insert
3325 (std::pair
<cmStdString
,cmProperty::ScopeType
>(name
,scope
));
3328 void cmake::ReportUndefinedPropertyAccesses(const char *filename
)
3330 FILE *progFile
= fopen(filename
,"w");
3331 if (!progFile
|| !this->GlobalGenerator
)
3336 // what are the enabled languages?
3337 std::vector
<std::string
> enLangs
;
3338 this->GlobalGenerator
->GetEnabledLanguages(enLangs
);
3340 // Common configuration names.
3341 // TODO: Compute current configuration(s).
3342 std::vector
<std::string
> enConfigs
;
3343 enConfigs
.push_back("");
3344 enConfigs
.push_back("DEBUG");
3345 enConfigs
.push_back("RELEASE");
3346 enConfigs
.push_back("MINSIZEREL");
3347 enConfigs
.push_back("RELWITHDEBINFO");
3349 // take all the defined properties and add definitions for all the enabled
3351 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> > aliasedProperties
;
3352 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
3353 i
= this->PropertyDefinitions
.begin();
3354 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
3356 cmPropertyDefinitionMap::iterator j
;
3357 for (j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
3359 // TODO: What if both <LANG> and <CONFIG> appear?
3360 if (j
->first
.find("<CONFIG>") != std::string::npos
)
3362 std::vector
<std::string
>::const_iterator k
;
3363 for (k
= enConfigs
.begin(); k
!= enConfigs
.end(); ++k
)
3365 std::string tmp
= j
->first
;
3366 cmSystemTools::ReplaceString(tmp
, "<CONFIG>", k
->c_str());
3368 aliasedProperties
.insert
3369 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3372 if (j
->first
.find("<LANG>") != std::string::npos
)
3374 std::vector
<std::string
>::const_iterator k
;
3375 for (k
= enLangs
.begin(); k
!= enLangs
.end(); ++k
)
3377 std::string tmp
= j
->first
;
3378 cmSystemTools::ReplaceString(tmp
, "<LANG>", k
->c_str());
3380 aliasedProperties
.insert
3381 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3387 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> >::const_iterator ap
;
3388 ap
= this->AccessedProperties
.begin();
3389 for (;ap
!= this->AccessedProperties
.end(); ++ap
)
3391 if (!this->IsPropertyDefined(ap
->first
.c_str(),ap
->second
) &&
3392 aliasedProperties
.find(std::pair
<cmStdString
,cmProperty::ScopeType
>
3393 (ap
->first
,ap
->second
)) ==
3394 aliasedProperties
.end())
3396 const char *scopeStr
= "";
3399 case cmProperty::TARGET
:
3400 scopeStr
= "TARGET";
3402 case cmProperty::SOURCE_FILE
:
3403 scopeStr
= "SOURCE_FILE";
3405 case cmProperty::DIRECTORY
:
3406 scopeStr
= "DIRECTORY";
3408 case cmProperty::TEST
:
3411 case cmProperty::VARIABLE
:
3412 scopeStr
= "VARIABLE";
3414 case cmProperty::CACHED_VARIABLE
:
3415 scopeStr
= "CACHED_VARIABLE";
3418 scopeStr
= "unknown";
3421 fprintf(progFile
,"%s with scope %s\n",ap
->first
.c_str(),scopeStr
);
3427 bool cmake::IsPropertyDefined(const char *name
, cmProperty::ScopeType scope
)
3429 return this->PropertyDefinitions
[scope
].IsPropertyDefined(name
);
3432 bool cmake::IsPropertyChained(const char *name
, cmProperty::ScopeType scope
)
3434 return this->PropertyDefinitions
[scope
].IsPropertyChained(name
);
3437 void cmake::SetProperty(const char* prop
, const char* value
)
3448 this->Properties
.SetProperty(prop
, value
, cmProperty::GLOBAL
);
3451 void cmake::AppendProperty(const char* prop
, const char* value
)
3457 this->Properties
.AppendProperty(prop
, value
, cmProperty::GLOBAL
);
3460 const char *cmake::GetProperty(const char* prop
)
3462 return this->GetProperty(prop
, cmProperty::GLOBAL
);
3465 const char *cmake::GetProperty(const char* prop
, cmProperty::ScopeType scope
)
3469 // watch for special properties
3470 std::string propname
= prop
;
3471 std::string output
= "";
3472 if ( propname
== "CACHE_VARIABLES" )
3474 cmCacheManager::CacheIterator cit
=
3475 this->GetCacheManager()->GetCacheIterator();
3476 for ( cit
.Begin(); !cit
.IsAtEnd(); cit
.Next() )
3478 if ( output
.size() )
3482 output
+= cit
.GetName();
3484 this->SetProperty("CACHE_VARIABLES", output
.c_str());
3486 else if ( propname
== "COMMANDS" )
3488 cmake::RegisteredCommandsMap::iterator cmds
3489 = this->GetCommands()->begin();
3490 for (unsigned int cc
=0 ; cmds
!= this->GetCommands()->end(); ++ cmds
)
3496 output
+= cmds
->first
.c_str();
3499 this->SetProperty("COMMANDS",output
.c_str());
3502 return this->Properties
.GetPropertyValue(prop
, scope
, chain
);
3505 bool cmake::GetPropertyAsBool(const char* prop
)
3507 return cmSystemTools::IsOn(this->GetProperty(prop
));
3510 int cmake::GetSystemInformation(std::vector
<std::string
>& args
)
3512 // so create the directory
3513 std::string resultFile
;
3514 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
3515 std::string destPath
= cwd
+ "/__cmake_systeminformation";
3516 cmSystemTools::RemoveADirectory(destPath
.c_str());
3517 if (!cmSystemTools::MakeDirectory(destPath
.c_str()))
3519 std::cerr
<< "Error: --system-information must be run from a "
3520 "writable directory!\n";
3524 // process the arguments
3525 bool writeToStdout
= true;
3526 for(unsigned int i
=1; i
< args
.size(); ++i
)
3528 std::string arg
= args
[i
];
3529 if(arg
.find("-V",0) == 0)
3531 this->Verbose
= true;
3533 else if(arg
.find("-G",0) == 0)
3535 std::string value
= arg
.substr(2);
3536 if(value
.size() == 0)
3539 if(i
>= args
.size())
3541 cmSystemTools::Error("No generator specified for -G");
3546 cmGlobalGenerator
* gen
=
3547 this->CreateGlobalGenerator(value
.c_str());
3550 cmSystemTools::Error("Could not create named generator ",
3555 this->SetGlobalGenerator(gen
);
3558 // no option assume it is the output file
3561 if (!cmSystemTools::FileIsFullPath(arg
.c_str()))
3567 writeToStdout
= false;
3572 // we have to find the module directory, so we can copy the files
3573 this->AddCMakePaths();
3574 std::string modulesPath
=
3575 this->CacheManager
->GetCacheValue("CMAKE_ROOT");
3576 modulesPath
+= "/Modules";
3577 std::string inFile
= modulesPath
;
3578 inFile
+= "/SystemInformation.cmake";
3579 std::string outFile
= destPath
;
3580 outFile
+= "/CMakeLists.txt";
3583 if(!cmSystemTools::cmCopyFile(inFile
.c_str(), outFile
.c_str()))
3585 std::cerr
<< "Error copying file \"" << inFile
.c_str()
3586 << "\" to \"" << outFile
.c_str() << "\".\n";
3590 // do we write to a file or to stdout?
3591 if (resultFile
.size() == 0)
3594 resultFile
+= "/__cmake_systeminformation/results.txt";
3597 // now run cmake on the CMakeLists file
3598 cmSystemTools::ChangeDirectory(destPath
.c_str());
3599 std::vector
<std::string
> args2
;
3600 args2
.push_back(args
[0]);
3601 args2
.push_back(destPath
);
3602 std::string resultArg
= "-DRESULT_FILE=";
3603 resultArg
+= resultFile
;
3604 args2
.push_back(resultArg
);
3605 int res
= this->Run(args2
, false);
3609 std::cerr
<< "Error: --system-information failed on internal CMake!\n";
3613 // change back to the original directory
3614 cmSystemTools::ChangeDirectory(cwd
.c_str());
3616 // echo results to stdout if needed
3619 FILE* fin
= fopen(resultFile
.c_str(), "r");
3622 const int bufferSize
= 4096;
3623 char buffer
[bufferSize
];
3625 while((n
= fread(buffer
, 1, bufferSize
, fin
)) > 0)
3627 for(char* c
= buffer
; c
< buffer
+n
; ++c
)
3637 // clean up the directory
3638 cmSystemTools::RemoveADirectory(destPath
.c_str());
3642 //----------------------------------------------------------------------------
3643 static bool cmakeCheckStampFile(const char* stampName
)
3645 // If the stamp file still exists then it must really be out of
3647 if(cmSystemTools::FileExists(stampName
))
3652 // The stamp file does not exist. Use the stamp dependencies to
3653 // determine whether it is really out of date. This works in
3654 // conjunction with cmLocalVisualStudio7Generator to avoid
3655 // repeatedly re-running CMake when the user rebuilds the entire
3657 std::string stampDepends
= stampName
;
3658 stampDepends
+= ".depend";
3659 #if defined(_WIN32) || defined(__CYGWIN__)
3660 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
| std::ios::binary
);
3662 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
);
3666 // The stamp dependencies file cannot be read. Just assume the
3667 // build system is really out of date.
3671 // Compare the stamp dependencies against the dependency file itself.
3672 cmFileTimeComparison ftc
;
3674 while(cmSystemTools::GetLineFromStream(fin
, dep
))
3677 if(dep
.length() >= 1 && dep
[0] != '#' &&
3678 (!ftc
.FileTimeCompare(stampDepends
.c_str(), dep
.c_str(), &result
)
3681 // The stamp depends file is older than this dependency. The
3682 // build system is really out of date.
3687 // The build system is up to date. The stamp file has been removed
3688 // by the VS IDE due to a "rebuild" request. Just restore it.
3689 std::ofstream
stamp(stampName
);
3690 stamp
<< "# CMake generation timestamp file this directory.\n";
3693 // Notify the user why CMake is not re-running. It is safe to
3694 // just print to stdout here because this code is only reachable
3695 // through an undocumented flag used by the VS generator.
3696 std::cout
<< "CMake does not need to re-run because the "
3697 << "generation timestamp is up-to-date.\n";
3702 cmSystemTools::Error("Cannot restore timestamp ", stampName
);
3707 // For visual studio 2005 and newer manifest files need to be embeded into
3708 // exe and dll's. This code does that in such a way that incremental linking
3710 int cmake::VisualStudioLink(std::vector
<std::string
>& args
, int type
)
3716 bool verbose
= false;
3717 if(cmSystemTools::GetEnv("VERBOSE"))
3721 std::vector
<std::string
> expandedArgs
;
3722 for(std::vector
<std::string
>::iterator i
= args
.begin();
3723 i
!= args
.end(); ++i
)
3725 // check for nmake temporary files
3728 std::ifstream
fin(i
->substr(1).c_str());
3730 while(cmSystemTools::GetLineFromStream(fin
,
3733 cmSystemTools::ParseWindowsCommandLine(line
.c_str(), expandedArgs
);
3738 expandedArgs
.push_back(*i
);
3741 // figure out if this is an incremental link or not and run the correct
3743 for(std::vector
<std::string
>::iterator i
= expandedArgs
.begin();
3744 i
!= expandedArgs
.end(); ++i
)
3746 if(cmSystemTools::Strucmp(i
->c_str(), "/INCREMENTAL:YES") == 0)
3750 std::cout
<< "Visual Studio Incremental Link\n";
3752 return cmake::VisualStudioLinkIncremental(expandedArgs
, type
, verbose
);
3757 std::cout
<< "Visual Studio Non-Incremental Link\n";
3759 return cmake::VisualStudioLinkNonIncremental(expandedArgs
, type
, verbose
);
3762 int cmake::ParseVisualStudioLinkCommand(std::vector
<std::string
>& args
,
3763 std::vector
<cmStdString
>& command
,
3764 std::string
& targetName
)
3766 std::vector
<std::string
>::iterator i
= args
.begin();
3768 i
++; // skip vs_link_dll or vs_link_exe
3769 command
.push_back(*i
);
3770 i
++; // move past link command
3771 for(; i
!= args
.end(); ++i
)
3773 command
.push_back(*i
);
3774 if(i
->find("/Fe") == 0)
3776 targetName
= i
->substr(3);
3778 if(i
->find("/out:") == 0)
3780 targetName
= i
->substr(5);
3783 if(targetName
.size() == 0 || command
.size() == 0)
3790 bool cmake::RunCommand(const char* comment
,
3791 std::vector
<cmStdString
>& command
,
3797 std::cout
<< comment
<< ":\n";
3798 for(std::vector
<cmStdString
>::iterator i
= command
.begin();
3799 i
!= command
.end(); ++i
)
3801 std::cout
<< i
->c_str() << " ";
3807 // use rc command to create .res file
3808 cmSystemTools::RunSingleCommand(command
,
3813 std::cout
<< output
<< "\n";
3815 // if retCodeOut is requested then always return true
3816 // and set the retCodeOut to retCode
3819 *retCodeOut
= retCode
;
3824 std::cout
<< comment
<< " failed. with " << retCode
<< "\n";
3826 return retCode
== 0;
3829 int cmake::VisualStudioLinkIncremental(std::vector
<std::string
>& args
,
3830 int type
, bool verbose
)
3832 // This follows the steps listed here:
3833 // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
3835 // 1. Compiler compiles the application and generates the *.obj files.
3836 // 2. An empty manifest file is generated if this is a clean build and if
3837 // not the previous one is reused.
3838 // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
3840 // 4. Linker generates the binary (EXE or DLL) with the /incremental
3841 // switch and embeds the dummy manifest file. The linker also generates
3842 // the real manifest file based on the binaries that your binary depends
3844 // 5. The manifest tool (mt.exe) is then used to generate the final
3847 // If the final manifest is changed, then 6 and 7 are run, if not
3848 // they are skipped, and it is done.
3850 // 6. The resource compiler is invoked one more time.
3851 // 7. Finally, the Linker does another incremental link, but since the
3852 // only thing that has changed is the *.res file that contains the
3853 // manifest it is a short link.
3854 std::vector
<cmStdString
> linkCommand
;
3855 std::string targetName
;
3856 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
3860 std::string manifestArg
= "/MANIFESTFILE:";
3861 std::vector
<cmStdString
> rcCommand
;
3862 rcCommand
.push_back(cmSystemTools::FindProgram("rc.exe"));
3863 std::vector
<cmStdString
> mtCommand
;
3864 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
3865 std::string tempManifest
;
3866 tempManifest
= targetName
;
3867 tempManifest
+= ".intermediate.manifest";
3868 std::string resourceInputFile
= targetName
;
3869 resourceInputFile
+= ".resource.txt";
3872 std::cout
<< "Create " << resourceInputFile
.c_str() << "\n";
3874 // Create input file for rc command
3875 std::ofstream
fout(resourceInputFile
.c_str());
3880 std::string manifestFile
= targetName
;
3881 manifestFile
+= ".embed.manifest";
3882 std::string fullPath
= cmSystemTools::CollapseFullPath(manifestFile
.c_str());
3883 fout
<< type
<< " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
3884 "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath
.c_str() << "\"";
3886 manifestArg
+= tempManifest
;
3887 // add the manifest arg to the linkCommand
3888 linkCommand
.push_back(manifestArg
);
3889 // if manifestFile is not yet created, create an
3891 if(!cmSystemTools::FileExists(manifestFile
.c_str()))
3895 std::cout
<< "Create empty: " << manifestFile
.c_str() << "\n";
3897 std::ofstream
foutTmp(manifestFile
.c_str());
3899 std::string resourceFile
= manifestFile
;
3900 resourceFile
+= ".res";
3901 // add the resource file to the end of the link command
3902 linkCommand
.push_back(resourceFile
);
3903 std::string outputOpt
= "/fo";
3904 outputOpt
+= resourceFile
;
3905 rcCommand
.push_back(outputOpt
);
3906 rcCommand
.push_back(resourceInputFile
);
3907 // Run rc command to create resource
3908 if(!cmake::RunCommand("RC Pass 1", rcCommand
, verbose
))
3912 // Now run the link command to link and create manifest
3913 if(!cmake::RunCommand("LINK Pass 1", linkCommand
, verbose
))
3917 // create mt command
3918 std::string
outArg("/out:");
3919 outArg
+= manifestFile
;
3920 mtCommand
.push_back("/nologo");
3921 mtCommand
.push_back(outArg
);
3922 mtCommand
.push_back("/notify_update");
3923 mtCommand
.push_back("/manifest");
3924 mtCommand
.push_back(tempManifest
);
3925 // now run mt.exe to create the final manifest file
3927 cmake::RunCommand("MT", mtCommand
, verbose
, &mtRet
);
3928 // if mt returns 0, then the manifest was not changed and
3929 // we do not need to do another link step
3934 // check for magic mt return value if mt returns the magic number
3935 // 1090650113 then it means that it updated the manifest file and we need
3936 // to do the final link. If mt has any value other than 0 or 1090650113
3937 // then there was some problem with the command itself and there was an
3938 // error so return the error code back out of cmake so make can report it.
3939 if(mtRet
!= 1090650113)
3943 // update the resource file with the new manifest from the mt command.
3944 if(!cmake::RunCommand("RC Pass 2", rcCommand
, verbose
))
3948 // Run the final incremental link that will put the new manifest resource
3949 // into the file incrementally.
3950 if(!cmake::RunCommand("FINAL LINK", linkCommand
, verbose
))
3957 int cmake::VisualStudioLinkNonIncremental(std::vector
<std::string
>& args
,
3961 std::vector
<cmStdString
> linkCommand
;
3962 std::string targetName
;
3963 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
3967 // Run the link command as given
3968 if(!cmake::RunCommand("LINK", linkCommand
, verbose
))
3972 std::vector
<cmStdString
> mtCommand
;
3973 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
3974 mtCommand
.push_back("/nologo");
3975 mtCommand
.push_back("/manifest");
3976 std::string manifestFile
= targetName
;
3977 manifestFile
+= ".manifest";
3978 mtCommand
.push_back(manifestFile
);
3979 std::string outresource
= "/outputresource:";
3980 outresource
+= targetName
;
3981 outresource
+= ";#";
3990 mtCommand
.push_back(outresource
);
3991 // Now use the mt tool to embed the manifest into the exe or dll
3992 if(!cmake::RunCommand("MT", mtCommand
, verbose
))