1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmake.cxx,v $
6 Date: $Date: 2008/03/01 20:20:35 $
7 Version: $Revision: 1.362 $
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->Policies
= new cmPolicies();
148 this->Properties
.SetCMakeInstance(this);
150 // initialize properties
151 cmSourceFile::DefineProperties(this);
152 cmTarget::DefineProperties(this);
153 cmMakefile::DefineProperties(this);
154 cmTest::DefineProperties(this);
155 cmake::DefineProperties(this);
159 if(!getrlimit(RLIMIT_STACK
, &rlp
))
161 if(rlp
.rlim_cur
!= rlp
.rlim_max
)
163 rlp
.rlim_cur
= rlp
.rlim_max
;
164 setrlimit(RLIMIT_STACK
, &rlp
);
169 // If MAKEFLAGS are given in the environment, remove the environment
170 // variable. This will prevent try-compile from succeeding when it
171 // should fail (if "-i" is an option). We cannot simply test
172 // whether "-i" is given and remove it because some make programs
173 // encode the MAKEFLAGS variable in a strange way.
174 if(getenv("MAKEFLAGS"))
176 cmSystemTools::PutEnv("MAKEFLAGS=");
179 this->Verbose
= false;
180 this->InTryCompile
= false;
181 this->CacheManager
= new cmCacheManager
;
182 this->GlobalGenerator
= 0;
183 this->ProgressCallback
= 0;
184 this->ProgressCallbackClientData
= 0;
185 this->ScriptMode
= false;
187 #ifdef CMAKE_BUILD_WITH_CMAKE
188 this->VariableWatch
= new cmVariableWatch
;
189 this->VariableWatch
->AddWatch("CMAKE_WORDS_BIGENDIAN",
190 cmNeedBackwardsCompatibility
);
191 this->VariableWatch
->AddWatch("CMAKE_SIZEOF_INT",
192 cmNeedBackwardsCompatibility
);
193 this->VariableWatch
->AddWatch("CMAKE_X_LIBS",
194 cmNeedBackwardsCompatibility
);
197 this->AddDefaultGenerators();
198 this->AddDefaultExtraGenerators();
199 this->AddDefaultCommands();
201 // Make sure we can capture the build tool output.
202 cmSystemTools::EnableVSConsoleOutput();
207 delete this->CacheManager
;
208 delete this->Policies
;
209 if (this->GlobalGenerator
)
211 delete this->GlobalGenerator
;
212 this->GlobalGenerator
= 0;
214 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
215 j
!= this->Commands
.end(); ++j
)
219 #ifdef CMAKE_BUILD_WITH_CMAKE
220 delete this->VariableWatch
;
222 delete this->FileComparison
;
225 void cmake::CleanupCommandsAndMacros()
227 std::vector
<cmCommand
*> commands
;
228 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
229 j
!= this->Commands
.end(); ++j
)
231 if ( !j
->second
->IsA("cmMacroHelperCommand") &&
232 !j
->second
->IsA("cmFunctionHelperCommand"))
234 commands
.push_back(j
->second
);
241 this->Commands
.erase(this->Commands
.begin(), this->Commands
.end());
242 std::vector
<cmCommand
*>::iterator it
;
243 for ( it
= commands
.begin(); it
!= commands
.end();
246 this->Commands
[cmSystemTools::LowerCase((*it
)->GetName())] = *it
;
250 bool cmake::CommandExists(const char* name
) const
252 std::string sName
= cmSystemTools::LowerCase(name
);
253 return (this->Commands
.find(sName
) != this->Commands
.end());
256 cmCommand
*cmake::GetCommand(const char *name
)
259 std::string sName
= cmSystemTools::LowerCase(name
);
260 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
261 if (pos
!= this->Commands
.end())
268 void cmake::RenameCommand(const char*oldName
, const char* newName
)
270 // if the command already exists, free the old one
271 std::string sOldName
= cmSystemTools::LowerCase(oldName
);
272 std::string sNewName
= cmSystemTools::LowerCase(newName
);
273 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sOldName
);
274 if ( pos
== this->Commands
.end() )
278 cmCommand
* cmd
= pos
->second
;
280 pos
= this->Commands
.find(sNewName
);
281 if (pos
!= this->Commands
.end())
284 this->Commands
.erase(pos
);
286 this->Commands
.insert(RegisteredCommandsMap::value_type(sNewName
, cmd
));
287 pos
= this->Commands
.find(sOldName
);
288 this->Commands
.erase(pos
);
291 void cmake::RemoveCommand(const char* name
)
293 std::string sName
= cmSystemTools::LowerCase(name
);
294 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
295 if ( pos
!= this->Commands
.end() )
298 this->Commands
.erase(pos
);
302 void cmake::AddCommand(cmCommand
* wg
)
304 std::string name
= cmSystemTools::LowerCase(wg
->GetName());
305 // if the command already exists, free the old one
306 RegisteredCommandsMap::iterator pos
= this->Commands
.find(name
);
307 if (pos
!= this->Commands
.end())
310 this->Commands
.erase(pos
);
312 this->Commands
.insert( RegisteredCommandsMap::value_type(name
, wg
));
316 void cmake::RemoveUnscriptableCommands()
318 std::vector
<std::string
> unscriptableCommands
;
319 cmake::RegisteredCommandsMap
* commands
= this->GetCommands();
320 for (cmake::RegisteredCommandsMap::const_iterator pos
= commands
->begin();
321 pos
!= commands
->end();
324 if (!pos
->second
->IsScriptable())
326 unscriptableCommands
.push_back(pos
->first
);
330 for(std::vector
<std::string
>::const_iterator it
=unscriptableCommands
.begin();
331 it
!= unscriptableCommands
.end();
334 this->RemoveCommand(it
->c_str());
339 bool cmake::SetCacheArgs(const std::vector
<std::string
>& args
)
341 for(unsigned int i
=1; i
< args
.size(); ++i
)
343 std::string arg
= args
[i
];
344 if(arg
.find("-D",0) == 0)
346 std::string entry
= arg
.substr(2);
347 if(entry
.size() == 0)
356 cmSystemTools::Error("-D must be followed with VAR=VALUE.");
360 std::string var
, value
;
361 cmCacheManager::CacheEntryType type
= cmCacheManager::UNINITIALIZED
;
362 if(cmCacheManager::ParseEntry(entry
.c_str(), var
, value
, type
) ||
363 cmCacheManager::ParseEntry(entry
.c_str(), var
, value
))
365 this->CacheManager
->AddCacheEntry(var
.c_str(), value
.c_str(),
366 "No help, variable specified on the command line.", type
);
370 std::cerr
<< "Parse error in command line argument: " << arg
<< "\n"
371 << "Should be: VAR:type=value\n";
372 cmSystemTools::Error("No cmake scrpt provided.");
376 else if(arg
.find("-U",0) == 0)
378 std::string entryPattern
= arg
.substr(2);
379 if(entryPattern
.size() == 0)
384 entryPattern
= args
[i
];
388 cmSystemTools::Error("-U must be followed with VAR.");
392 cmsys::RegularExpression
regex(
393 cmsys::Glob::PatternToRegex(entryPattern
.c_str(), true).c_str());
394 //go through all cache entries and collect the vars which will be removed
395 std::vector
<std::string
> entriesToDelete
;
396 cmCacheManager::CacheIterator it
=
397 this->CacheManager
->GetCacheIterator();
398 for ( it
.Begin(); !it
.IsAtEnd(); it
.Next() )
400 cmCacheManager::CacheEntryType t
= it
.GetType();
401 if(t
!= cmCacheManager::STATIC
)
403 std::string entryName
= it
.GetName();
404 if (regex
.find(entryName
.c_str()))
406 entriesToDelete
.push_back(entryName
);
411 // now remove them from the cache
412 for(std::vector
<std::string
>::const_iterator currentEntry
=
413 entriesToDelete
.begin();
414 currentEntry
!= entriesToDelete
.end();
417 this->CacheManager
->RemoveCacheEntry(currentEntry
->c_str());
420 else if(arg
.find("-C",0) == 0)
422 std::string path
= arg
.substr(2);
423 if ( path
.size() == 0 )
432 cmSystemTools::Error("-C must be followed by a file name.");
436 std::cerr
<< "loading initial cache file " << path
.c_str() << "\n";
437 this->ReadListFile(path
.c_str());
439 else if(arg
.find("-P",0) == 0)
444 cmSystemTools::Error("-P must be followed by a file name.");
447 std::string path
= args
[i
];
448 if ( path
.size() == 0 )
450 cmSystemTools::Error("No cmake script provided.");
453 this->ReadListFile(path
.c_str());
459 void cmake::ReadListFile(const char *path
)
461 // if a generator was not yet created, temporarily create one
462 cmGlobalGenerator
*gg
= this->GetGlobalGenerator();
463 bool created
= false;
465 // if a generator was not specified use a generic one
468 gg
= new cmGlobalGenerator
;
469 gg
->SetCMakeInstance(this);
473 // read in the list file to fill the cache
476 std::auto_ptr
<cmLocalGenerator
> lg(gg
->CreateLocalGenerator());
477 lg
->SetGlobalGenerator(gg
);
478 lg
->GetMakefile()->SetHomeOutputDirectory
479 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
480 lg
->GetMakefile()->SetStartOutputDirectory
481 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
482 lg
->GetMakefile()->SetHomeDirectory
483 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
484 lg
->GetMakefile()->SetStartDirectory
485 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
486 if (!lg
->GetMakefile()->ReadListFile(0, path
))
488 cmSystemTools::Error("Error processing file:", path
);
492 // free generic one if generated
500 void cmake::SetArgs(const std::vector
<std::string
>& args
)
502 bool directoriesSet
= false;
503 for(unsigned int i
=1; i
< args
.size(); ++i
)
505 std::string arg
= args
[i
];
506 if(arg
.find("-H",0) == 0)
508 directoriesSet
= true;
509 std::string path
= arg
.substr(2);
510 path
= cmSystemTools::CollapseFullPath(path
.c_str());
511 cmSystemTools::ConvertToUnixSlashes(path
);
512 this->SetHomeDirectory(path
.c_str());
514 else if(arg
.find("-S",0) == 0)
516 // There is no local generate anymore. Ignore -S option.
518 else if(arg
.find("-O",0) == 0)
520 // There is no local generate anymore. Ignore -O option.
522 else if(arg
.find("-B",0) == 0)
524 directoriesSet
= true;
525 std::string path
= arg
.substr(2);
526 path
= cmSystemTools::CollapseFullPath(path
.c_str());
527 cmSystemTools::ConvertToUnixSlashes(path
);
528 this->SetHomeOutputDirectory(path
.c_str());
530 else if((i
< args
.size()-1) && (arg
.find("--check-build-system",0) == 0))
532 this->CheckBuildSystemArgument
= args
[++i
];
533 this->ClearBuildSystem
= (atoi(args
[++i
].c_str()) > 0);
535 else if((i
< args
.size()-1) && (arg
.find("--check-stamp-file",0) == 0))
537 this->CheckStampFile
= args
[++i
];
539 #if defined(CMAKE_HAVE_VS_GENERATORS)
540 else if((i
< args
.size()-1) && (arg
.find("--vs-solution-file",0) == 0))
542 this->VSSolutionFile
= args
[++i
];
545 else if(arg
.find("-V",0) == 0)
547 this->Verbose
= true;
549 else if(arg
.find("-D",0) == 0)
553 else if(arg
.find("-U",0) == 0)
557 else if(arg
.find("-C",0) == 0)
561 else if(arg
.find("-P",0) == 0)
566 else if(arg
.find("--graphviz=",0) == 0)
568 std::string path
= arg
.substr(strlen("--graphviz="));
569 path
= cmSystemTools::CollapseFullPath(path
.c_str());
570 cmSystemTools::ConvertToUnixSlashes(path
);
571 this->GraphVizFile
= path
;
572 if ( this->GraphVizFile
.empty() )
574 cmSystemTools::Error("No file specified for --graphviz");
577 else if(arg
.find("--debug-trycompile",0) == 0)
579 std::cout
<< "debug trycompile on\n";
580 this->DebugTryCompileOn();
582 else if(arg
.find("--debug-output",0) == 0)
584 std::cout
<< "Running with debug output on.\n";
585 this->DebugOutputOn();
587 else if(arg
.find("-G",0) == 0)
589 std::string value
= arg
.substr(2);
590 if(value
.size() == 0)
595 cmSystemTools::Error("No generator specified for -G");
600 cmGlobalGenerator
* gen
=
601 this->CreateGlobalGenerator(value
.c_str());
604 cmSystemTools::Error("Could not create named generator ",
609 this->SetGlobalGenerator(gen
);
612 // no option assume it is the path to the source
615 directoriesSet
= true;
616 this->SetDirectoriesFromFile(arg
.c_str());
621 this->SetHomeOutputDirectory
622 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
623 this->SetStartOutputDirectory
624 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
625 this->SetHomeDirectory
626 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
627 this->SetStartDirectory
628 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
631 this->SetStartDirectory(this->GetHomeDirectory());
632 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
635 //----------------------------------------------------------------------------
636 void cmake::SetDirectoriesFromFile(const char* arg
)
638 // Check if the argument refers to a CMakeCache.txt or
639 // CMakeLists.txt file.
640 std::string listPath
;
641 std::string cachePath
;
642 bool argIsFile
= false;
643 if(cmSystemTools::FileIsDirectory(arg
))
645 std::string path
= cmSystemTools::CollapseFullPath(arg
);
646 cmSystemTools::ConvertToUnixSlashes(path
);
647 std::string cacheFile
= path
;
648 cacheFile
+= "/CMakeCache.txt";
649 std::string listFile
= path
;
650 listFile
+= "/CMakeLists.txt";
651 if(cmSystemTools::FileExists(cacheFile
.c_str()))
655 if(cmSystemTools::FileExists(listFile
.c_str()))
660 else if(cmSystemTools::FileExists(arg
))
663 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
664 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
665 name
= cmSystemTools::LowerCase(name
);
666 if(name
== "cmakecache.txt")
668 cachePath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
670 else if(name
== "cmakelists.txt")
672 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
677 // Specified file or directory does not exist. Try to set things
678 // up to produce a meaningful error message.
679 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
680 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
681 name
= cmSystemTools::LowerCase(name
);
682 if(name
== "cmakecache.txt" || name
== "cmakelists.txt")
685 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
693 // If there is a CMakeCache.txt file, use its settings.
694 if(cachePath
.length() > 0)
696 cmCacheManager
* cachem
= this->GetCacheManager();
697 cmCacheManager::CacheIterator it
= cachem
->NewIterator();
698 if(cachem
->LoadCache(cachePath
.c_str()) &&
699 it
.Find("CMAKE_HOME_DIRECTORY"))
701 this->SetHomeOutputDirectory(cachePath
.c_str());
702 this->SetStartOutputDirectory(cachePath
.c_str());
703 this->SetHomeDirectory(it
.GetValue());
704 this->SetStartDirectory(it
.GetValue());
709 // If there is a CMakeLists.txt file, use it as the source tree.
710 if(listPath
.length() > 0)
712 this->SetHomeDirectory(listPath
.c_str());
713 this->SetStartDirectory(listPath
.c_str());
717 // Source CMakeLists.txt file given. It was probably dropped
718 // onto the executable in a GUI. Default to an in-source build.
719 this->SetHomeOutputDirectory(listPath
.c_str());
720 this->SetStartOutputDirectory(listPath
.c_str());
724 // Source directory given on command line. Use current working
725 // directory as build tree.
726 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
727 this->SetHomeOutputDirectory(cwd
.c_str());
728 this->SetStartOutputDirectory(cwd
.c_str());
733 // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
734 // argument. Assume it is the path to the source tree, and use the
735 // current working directory as the build tree.
736 std::string full
= cmSystemTools::CollapseFullPath(arg
);
737 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
738 this->SetHomeDirectory(full
.c_str());
739 this->SetStartDirectory(full
.c_str());
740 this->SetHomeOutputDirectory(cwd
.c_str());
741 this->SetStartOutputDirectory(cwd
.c_str());
744 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
746 int cmake::AddCMakePaths()
748 // Find the cmake executable
749 std::string cMakeSelf
= cmSystemTools::GetExecutableDirectory();
750 cMakeSelf
+= "/cmake";
751 cMakeSelf
+= cmSystemTools::GetExecutableExtension();
752 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
754 cmSystemTools::Error("CMake executable cannot be found at ",
758 // Save the value in the cache
759 this->CacheManager
->AddCacheEntry
760 ("CMAKE_COMMAND",cMakeSelf
.c_str(), "Path to CMake executable.",
761 cmCacheManager::INTERNAL
);
762 // if the edit command is not yet in the cache,
763 // or if CMakeEditCommand has been set on this object,
764 // then set the CMAKE_EDIT_COMMAND in the cache
765 // This will mean that the last gui to edit the cache
766 // will be the one that make edit_cache uses.
767 if(!this->GetCacheDefinition("CMAKE_EDIT_COMMAND")
768 || !this->CMakeEditCommand
.empty())
770 // Find and save the command to edit the cache
771 std::string editCacheCommand
;
772 if(!this->CMakeEditCommand
.empty())
774 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
)
776 + this->CMakeEditCommand
777 + cmSystemTools::GetFilenameExtension(cMakeSelf
);
779 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
781 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
782 "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
784 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
786 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
787 "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
789 if(cmSystemTools::FileExists(editCacheCommand
.c_str()))
791 this->CacheManager
->AddCacheEntry
792 ("CMAKE_EDIT_COMMAND", editCacheCommand
.c_str(),
793 "Path to cache edit program executable.", cmCacheManager::INTERNAL
);
796 std::string ctestCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
797 "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
798 if(cmSystemTools::FileExists(ctestCommand
.c_str()))
800 this->CacheManager
->AddCacheEntry
801 ("CMAKE_CTEST_COMMAND", ctestCommand
.c_str(),
802 "Path to ctest program executable.", cmCacheManager::INTERNAL
);
804 std::string cpackCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
805 "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
806 if(cmSystemTools::FileExists(ctestCommand
.c_str()))
808 this->CacheManager
->AddCacheEntry
809 ("CMAKE_CPACK_COMMAND", cpackCommand
.c_str(),
810 "Path to cpack program executable.", cmCacheManager::INTERNAL
);
813 // do CMAKE_ROOT, look for the environment variable first
814 std::string cMakeRoot
;
816 if (getenv("CMAKE_ROOT"))
818 cMakeRoot
= getenv("CMAKE_ROOT");
819 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
821 if(!cmSystemTools::FileExists(modules
.c_str()))
824 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
825 std::string::size_type slashPos
= cMakeRoot
.rfind("/");
826 if(slashPos
!= std::string::npos
)
828 cMakeRoot
= cMakeRoot
.substr(0, slashPos
);
830 // is there no Modules direcory there?
831 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
834 if (!cmSystemTools::FileExists(modules
.c_str()))
836 // try exe/../share/cmake
837 cMakeRoot
+= CMAKE_DATA_DIR
;
838 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
840 #ifdef CMAKE_ROOT_DIR
841 if (!cmSystemTools::FileExists(modules
.c_str()))
843 // try compiled in root directory
844 cMakeRoot
= CMAKE_ROOT_DIR
;
845 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
848 if (!cmSystemTools::FileExists(modules
.c_str()))
851 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
852 cMakeRoot
+= CMAKE_DATA_DIR
;
853 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
855 if(!cmSystemTools::FileExists(modules
.c_str()))
858 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
859 // is there no Modules direcory there?
860 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
862 if (!cmSystemTools::FileExists(modules
.c_str()))
864 // couldn't find modules
865 cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n"
866 "CMake has most likely not been installed correctly.\n"
867 "Modules directory not found in\n",
871 this->CacheManager
->AddCacheEntry
872 ("CMAKE_ROOT", cMakeRoot
.c_str(),
873 "Path to CMake installation.", cmCacheManager::INTERNAL
);
876 std::string comspec
= "cmw9xcom.exe";
877 cmSystemTools::SetWindows9xComspecSubstitute(comspec
.c_str());
884 void CMakeCommandUsage(const char* program
)
886 cmOStringStream errorStream
;
888 #ifdef CMAKE_BUILD_WITH_CMAKE
890 << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
893 << "cmake bootstrap\n";
897 << "Usage: " << program
<< " -E [command] [arguments ...]\n"
898 << "Available commands: \n"
899 << " chdir dir cmd [args]... - run command in a given directory\n"
900 << " copy file destination - copy file to destination (either file "
902 << " copy_if_different in-file out-file - copy file if input has "
904 << " copy_directory source destination - copy directory 'source' "
905 "content to directory 'destination'\n"
906 << " compare_files file1 file2 - check if file1 is same as file2\n"
907 << " echo [string]... - displays arguments as text\n"
908 << " echo_append [string]... - displays arguments as text but no new "
910 << " environment - display the current enviroment\n"
911 << " make_directory dir - create a directory\n"
912 << " md5sum file1 [...] - compute md5sum of files\n"
913 << " remove_directory dir - remove a directory and its contents\n"
914 << " remove [-f] file1 file2 ... - remove the file(s), use -f to force "
916 << " tar [cxt][vfz] file.tar file/dir1 file/dir2 ... - create a tar "
918 << " time command [args] ... - run command and return elapsed time\n"
919 << " touch file - touch a file.\n"
920 << " touch_nocreate file - touch a file but do not create it.\n"
921 #if defined(_WIN32) && !defined(__CYGWIN__)
922 << " write_regv key value - write registry value\n"
923 << " delete_regv key - delete registry value\n"
924 << " comspec - on windows 9x use this for RunCommand\n"
926 << " create_symlink old new - create a symbolic link new -> old\n"
930 cmSystemTools::Error(errorStream
.str().c_str());
933 int cmake::ExecuteCMakeCommand(std::vector
<std::string
>& args
)
938 if (args
[1] == "copy" && args
.size() == 4)
940 if(!cmSystemTools::cmCopyFile(args
[2].c_str(), args
[3].c_str()))
942 std::cerr
<< "Error copying file \"" << args
[2].c_str()
943 << "\" to \"" << args
[3].c_str() << "\".\n";
949 // Copy file if different.
950 if (args
[1] == "copy_if_different" && args
.size() == 4)
952 if(!cmSystemTools::CopyFileIfDifferent(args
[2].c_str(),
955 std::cerr
<< "Error copying file (if different) from \""
956 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
963 // Copy directory content
964 if (args
[1] == "copy_directory" && args
.size() == 4)
966 if(!cmSystemTools::CopyADirectory(args
[2].c_str(), args
[3].c_str()))
968 std::cerr
<< "Error copying directory from \""
969 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
977 if (args
[1] == "compare_files" && args
.size() == 4)
979 if(cmSystemTools::FilesDiffer(args
[2].c_str(), args
[3].c_str()))
981 std::cerr
<< "Files \""
982 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
983 << "\" are different.\n";
990 else if (args
[1] == "echo" )
993 const char* space
= "";
994 for ( cc
= 2; cc
< args
.size(); cc
++ )
996 std::cout
<< space
<< args
[cc
];
999 std::cout
<< std::endl
;
1003 // Echo string no new line
1004 else if (args
[1] == "echo_append" )
1007 const char* space
= "";
1008 for ( cc
= 2; cc
< args
.size(); cc
++ )
1010 std::cout
<< space
<< args
[cc
];
1016 #if defined(CMAKE_BUILD_WITH_CMAKE)
1017 // Command to create a symbolic link. Fails on platforms not
1019 else if (args
[1] == "environment" )
1021 std::vector
<std::string
> env
= cmSystemTools::GetEnvironmentVariables();
1022 std::vector
<std::string
>::iterator it
;
1023 for ( it
= env
.begin(); it
!= env
.end(); ++ it
)
1025 std::cout
<< it
->c_str() << std::endl
;
1031 else if (args
[1] == "make_directory" && args
.size() == 3)
1033 if(!cmSystemTools::MakeDirectory(args
[2].c_str()))
1035 std::cerr
<< "Error making directory \"" << args
[2].c_str()
1042 else if (args
[1] == "remove_directory" && args
.size() == 3)
1044 if(cmSystemTools::FileIsDirectory(args
[2].c_str()) &&
1045 !cmSystemTools::RemoveADirectory(args
[2].c_str()))
1047 std::cerr
<< "Error removing directory \"" << args
[2].c_str()
1055 else if (args
[1] == "remove" && args
.size() > 2)
1058 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1060 if(args
[cc
] == "\\-f" || args
[cc
] == "-f")
1066 // Complain if the file could not be removed, still exists,
1067 // and the -f option was not given.
1068 if(!cmSystemTools::RemoveFile(args
[cc
].c_str()) && !force
&&
1069 cmSystemTools::FileExists(args
[cc
].c_str()))
1078 else if (args
[1] == "touch" && 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(), true))
1092 else if (args
[1] == "touch_nocreate" && args
.size() > 2)
1094 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1096 // Complain if the file could not be removed, still exists,
1097 // and the -f option was not given.
1098 if(!cmSystemTools::Touch(args
[cc
].c_str(), false))
1107 else if (args
[1] == "time" && args
.size() > 2)
1109 std::string command
= args
[2];
1110 for (std::string::size_type cc
= 3; cc
< args
.size(); cc
++)
1113 command
+= args
[cc
];
1116 clock_t clock_start
, clock_finish
;
1117 time_t time_start
, time_finish
;
1120 clock_start
= clock();
1122 cmSystemTools::RunSingleCommand(command
.c_str());
1124 clock_finish
= clock();
1127 double clocks_per_sec
= static_cast<double>(CLOCKS_PER_SEC
);
1128 std::cout
<< "Elapsed time: "
1129 << static_cast<long>(time_finish
- time_start
) << " s. (time)"
1131 << static_cast<double>(clock_finish
- clock_start
) / clocks_per_sec
1137 // Command to calculate the md5sum of a file
1138 else if (args
[1] == "md5sum" && args
.size() >= 3)
1142 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1144 const char *filename
= args
[cc
].c_str();
1145 // Cannot compute md5sum of a directory
1146 if(cmSystemTools::FileIsDirectory(filename
))
1148 std::cerr
<< "Error: " << filename
<< " is a directory" << std::endl
;
1151 else if(!cmSystemTools::ComputeFileMD5(filename
, md5out
))
1153 // To mimic md5sum behavior in a shell:
1154 std::cerr
<< filename
<< ": No such file or directory" << std::endl
;
1159 std::cout
<< std::string(md5out
,32) << " " << filename
<< std::endl
;
1165 // Command to change directory and run a program.
1166 else if (args
[1] == "chdir" && args
.size() >= 4)
1168 std::string directory
= args
[2];
1169 if(!cmSystemTools::FileExists(directory
.c_str()))
1171 cmSystemTools::Error("Directory does not exist for chdir command: ",
1176 std::string command
= "\"";
1179 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1182 command
+= args
[cc
];
1187 if ( cmSystemTools::RunSingleCommand(command
.c_str(), 0, &retval
,
1188 directory
.c_str(), true, timeout
) )
1196 // Command to start progress for a build
1197 else if (args
[1] == "cmake_progress_start" && args
.size() == 4)
1199 // bascially remove the directory
1200 std::string dirName
= args
[2];
1201 dirName
+= "/Progress";
1202 cmSystemTools::RemoveADirectory(dirName
.c_str());
1204 // is the last argument a filename that exists?
1205 FILE *countFile
= fopen(args
[3].c_str(),"r");
1209 fscanf(countFile
,"%i",&count
);
1214 count
= atoi(args
[3].c_str());
1218 cmSystemTools::MakeDirectory(dirName
.c_str());
1219 // write the count into the directory
1220 std::string fName
= dirName
;
1221 fName
+= "/count.txt";
1222 FILE *progFile
= fopen(fName
.c_str(),"w");
1225 fprintf(progFile
,"%i\n",count
);
1232 // Command to report progress for a build
1233 else if (args
[1] == "cmake_progress_report" && args
.size() >= 3)
1235 std::string dirName
= args
[2];
1236 dirName
+= "/Progress";
1242 fName
+= "/count.txt";
1243 progFile
= fopen(fName
.c_str(),"r");
1251 fscanf(progFile
,"%i",&count
);
1255 for (i
= 3; i
< args
.size(); ++i
)
1260 progFile
= fopen(fName
.c_str(),"w");
1263 fprintf(progFile
,"empty");
1267 int fileNum
= static_cast<int>
1268 (cmsys::Directory::GetNumberOfFilesInDirectory(dirName
.c_str()));
1271 // print the progress
1272 fprintf(stdout
,"[%3i%%] ",((fileNum
-3)*100)/count
);
1277 // Command to create a symbolic link. Fails on platforms not
1279 else if (args
[1] == "create_symlink" && args
.size() == 4)
1281 const char* destinationFileName
= args
[3].c_str();
1282 if ( cmSystemTools::FileExists(destinationFileName
) )
1284 if ( cmSystemTools::FileIsSymlink(destinationFileName
) )
1286 if ( !cmSystemTools::RemoveFile(destinationFileName
) ||
1287 cmSystemTools::FileExists(destinationFileName
) )
1297 return cmSystemTools::CreateSymlink(args
[2].c_str(),
1298 args
[3].c_str())? 0:1;
1301 // Internal CMake shared library support.
1302 else if (args
[1] == "cmake_symlink_library" && args
.size() == 5)
1305 std::string realName
= args
[2];
1306 std::string soName
= args
[3];
1307 std::string name
= args
[4];
1308 if(soName
!= realName
)
1310 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1311 if(cmSystemTools::FileExists(soName
.c_str()))
1313 cmSystemTools::RemoveFile(soName
.c_str());
1315 if(!cmSystemTools::CreateSymlink(fname
.c_str(), soName
.c_str()))
1322 std::string fname
= cmSystemTools::GetFilenameName(soName
);
1323 if(cmSystemTools::FileExists(soName
.c_str()))
1325 cmSystemTools::RemoveFile(name
.c_str());
1327 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1334 // Internal CMake versioned executable support.
1335 else if (args
[1] == "cmake_symlink_executable" && args
.size() == 4)
1338 std::string realName
= args
[2];
1339 std::string name
= args
[3];
1340 if(name
!= realName
)
1342 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1343 if(cmSystemTools::FileExists(realName
.c_str()))
1345 cmSystemTools::RemoveFile(name
.c_str());
1347 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1355 #if defined(CMAKE_HAVE_VS_GENERATORS)
1356 // Internal CMake support for calling Visual Studio macros.
1357 else if (args
[1] == "cmake_call_visual_studio_macro" && args
.size() >= 4)
1359 // args[2] = full path to .sln file or "ALL"
1360 // args[3] = name of Visual Studio macro to call
1361 // args[4..args.size()-1] = [optional] args for Visual Studio macro
1363 std::string macroArgs
;
1365 if (args
.size() > 4)
1367 macroArgs
= args
[4];
1369 for (size_t i
= 5; i
< args
.size(); ++i
)
1372 macroArgs
+= args
[i
];
1376 return cmCallVisualStudioMacro::CallMacro(args
[2], args
[3], macroArgs
);
1380 // Internal CMake dependency scanning support.
1381 else if (args
[1] == "cmake_depends" && args
.size() >= 6)
1383 // Use the make system's VERBOSE environment variable to enable
1385 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
1387 // Create a cmake object instance to process dependencies.
1390 std::string homeDir
;
1391 std::string startDir
;
1392 std::string homeOutDir
;
1393 std::string startOutDir
;
1394 std::string depInfo
;
1396 if(args
.size() >= 8)
1400 // -E cmake_depends <generator>
1401 // <home-src-dir> <start-src-dir>
1402 // <home-out-dir> <start-out-dir>
1403 // <dep-info> [--color=$(COLOR)]
1405 // All paths are provided.
1409 homeOutDir
= args
[5];
1410 startOutDir
= args
[6];
1412 if(args
.size() >= 9 &&
1413 args
[8].length() > 8 &&
1414 args
[8].substr(0, 8) == "--color=")
1416 // Enable or disable color based on the switch value.
1417 color
= cmSystemTools::IsOn(args
[8].substr(8).c_str());
1422 // Support older signature for existing makefiles:
1424 // -E cmake_depends <generator>
1425 // <home-out-dir> <start-out-dir>
1428 // Just pretend the source directories are the same as the
1429 // binary directories so at least scanning will work.
1433 homeOutDir
= args
[3];
1434 startOutDir
= args
[3];
1438 // Create a local generator configured for the directory in
1439 // which dependencies will be scanned.
1440 homeDir
= cmSystemTools::CollapseFullPath(homeDir
.c_str());
1441 startDir
= cmSystemTools::CollapseFullPath(startDir
.c_str());
1442 homeOutDir
= cmSystemTools::CollapseFullPath(homeOutDir
.c_str());
1443 startOutDir
= cmSystemTools::CollapseFullPath(startOutDir
.c_str());
1444 cm
.SetHomeDirectory(homeDir
.c_str());
1445 cm
.SetStartDirectory(startDir
.c_str());
1446 cm
.SetHomeOutputDirectory(homeOutDir
.c_str());
1447 cm
.SetStartOutputDirectory(startOutDir
.c_str());
1448 if(cmGlobalGenerator
* ggd
= cm
.CreateGlobalGenerator(gen
.c_str()))
1450 cm
.SetGlobalGenerator(ggd
);
1451 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
1452 lgd
->SetGlobalGenerator(ggd
);
1453 lgd
->GetMakefile()->SetStartDirectory(startDir
.c_str());
1454 lgd
->GetMakefile()->SetStartOutputDirectory(startOutDir
.c_str());
1455 lgd
->GetMakefile()->MakeStartDirectoriesCurrent();
1457 // Actually scan dependencies.
1458 return lgd
->UpdateDependencies(depInfo
.c_str(),
1459 verbose
, color
)? 0 : 2;
1464 // Internal CMake link script support.
1465 else if (args
[1] == "cmake_link_script" && args
.size() >= 3)
1467 return cmake::ExecuteLinkScript(args
);
1470 // Internal CMake unimplemented feature notification.
1471 else if (args
[1] == "cmake_unimplemented_variable")
1473 std::cerr
<< "Feature not implemented for this platform.";
1474 if(args
.size() == 3)
1476 std::cerr
<< " Variable " << args
[2] << " is not set.";
1478 std::cerr
<< std::endl
;
1481 else if (args
[1] == "vs_link_exe")
1483 return cmake::VisualStudioLink(args
, 1);
1485 else if (args
[1] == "vs_link_dll")
1487 return cmake::VisualStudioLink(args
, 2);
1489 #ifdef CMAKE_BUILD_WITH_CMAKE
1490 // Internal CMake color makefile support.
1491 else if (args
[1] == "cmake_echo_color")
1493 return cmake::ExecuteEchoColor(args
);
1498 else if (args
[1] == "tar" && args
.size() > 3)
1500 std::string flags
= args
[2];
1501 std::string outFile
= args
[3];
1502 std::vector
<cmStdString
> files
;
1503 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1505 files
.push_back(args
[cc
]);
1508 bool verbose
= false;
1509 if ( flags
.find_first_of('z') != flags
.npos
)
1513 if ( flags
.find_first_of('v') != flags
.npos
)
1518 if ( flags
.find_first_of('t') != flags
.npos
)
1520 if ( !cmSystemTools::ListTar(outFile
.c_str(), files
, gzip
, verbose
) )
1522 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1526 else if ( flags
.find_first_of('c') != flags
.npos
)
1528 if ( !cmSystemTools::CreateTar(
1529 outFile
.c_str(), files
, gzip
, verbose
) )
1531 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1535 else if ( flags
.find_first_of('x') != flags
.npos
)
1537 if ( !cmSystemTools::ExtractTar(
1538 outFile
.c_str(), files
, gzip
, verbose
) )
1540 cmSystemTools::Error("Problem extracting tar: ", outFile
.c_str());
1547 #if defined(CMAKE_BUILD_WITH_CMAKE)
1548 // Internal CMake Fortran module support.
1549 else if (args
[1] == "cmake_copy_f90_mod" && args
.size() >= 4)
1551 return cmDependsFortran::CopyModule(args
)? 0 : 1;
1555 #if defined(_WIN32) && !defined(__CYGWIN__)
1556 // Write registry value
1557 else if (args
[1] == "write_regv" && args
.size() > 3)
1559 return cmSystemTools::WriteRegistryValue(args
[2].c_str(),
1560 args
[3].c_str()) ? 0 : 1;
1563 // Delete registry value
1564 else if (args
[1] == "delete_regv" && args
.size() > 2)
1566 return cmSystemTools::DeleteRegistryValue(args
[2].c_str()) ? 0 : 1;
1569 else if (args
[1] == "comspec" && args
.size() > 2)
1572 std::string command
= args
[2];
1573 for ( cc
= 3; cc
< args
.size(); cc
++ )
1575 command
+= " " + args
[cc
];
1577 return cmWin32ProcessExecution::Windows9xHack(command
.c_str());
1582 ::CMakeCommandUsage(args
[0].c_str());
1586 void cmake::AddExtraGenerator(const char* name
,
1587 CreateExtraGeneratorFunctionType newFunction
)
1589 cmExternalMakefileProjectGenerator
* extraGenerator
= newFunction();
1590 const std::vector
<std::string
>& supportedGlobalGenerators
=
1591 extraGenerator
->GetSupportedGlobalGenerators();
1593 for(std::vector
<std::string
>::const_iterator
1594 it
= supportedGlobalGenerators
.begin();
1595 it
!= supportedGlobalGenerators
.end();
1598 std::string fullName
= cmExternalMakefileProjectGenerator::
1599 CreateFullGeneratorName(it
->c_str(), name
);
1600 this->ExtraGenerators
[fullName
.c_str()] = newFunction
;
1602 delete extraGenerator
;
1605 void cmake::AddDefaultExtraGenerators()
1607 #if defined(CMAKE_BUILD_WITH_CMAKE)
1608 #if defined(_WIN32) && !defined(__CYGWIN__)
1612 #if !defined(__CYGWIN__)
1613 this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
1614 &cmExtraCodeBlocksGenerator::New
);
1617 #ifdef CMAKE_USE_ECLIPSE
1618 this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
1619 &cmExtraEclipseCDT4Generator::New
);
1622 #ifdef CMAKE_USE_KDEVELOP
1623 this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
1624 &cmGlobalKdevelopGenerator::New
);
1625 // for kdevelop also add the generator with just the name of the
1626 // extra generator, since it was this way since cmake 2.2
1627 this->ExtraGenerators
[cmGlobalKdevelopGenerator::GetActualName()]
1628 = &cmGlobalKdevelopGenerator::New
;
1635 //----------------------------------------------------------------------------
1636 void cmake::GetRegisteredGenerators(std::vector
<std::string
>& names
)
1638 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
1639 i
!= this->Generators
.end(); ++i
)
1641 names
.push_back(i
->first
);
1643 for(RegisteredExtraGeneratorsMap::const_iterator
1644 i
= this->ExtraGenerators
.begin();
1645 i
!= this->ExtraGenerators
.end(); ++i
)
1647 names
.push_back(i
->first
);
1651 cmGlobalGenerator
* cmake::CreateGlobalGenerator(const char* name
)
1653 cmGlobalGenerator
* generator
= 0;
1654 cmExternalMakefileProjectGenerator
* extraGenerator
= 0;
1655 RegisteredGeneratorsMap::const_iterator genIt
= this->Generators
.find(name
);
1656 if(genIt
== this->Generators
.end())
1658 RegisteredExtraGeneratorsMap::const_iterator extraGenIt
=
1659 this->ExtraGenerators
.find(name
);
1660 if (extraGenIt
== this->ExtraGenerators
.end())
1664 extraGenerator
= (extraGenIt
->second
)();
1665 genIt
=this->Generators
.find(extraGenerator
->GetGlobalGeneratorName(name
));
1666 if(genIt
== this->Generators
.end())
1668 delete extraGenerator
;
1673 generator
= (genIt
->second
)();
1674 generator
->SetCMakeInstance(this);
1675 generator
->SetExternalMakefileProjectGenerator(extraGenerator
);
1679 void cmake::SetHomeDirectory(const char* dir
)
1681 this->cmHomeDirectory
= dir
;
1682 cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory
);
1685 void cmake::SetHomeOutputDirectory(const char* lib
)
1687 this->HomeOutputDirectory
= lib
;
1688 cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory
);
1691 void cmake::SetGlobalGenerator(cmGlobalGenerator
*gg
)
1695 cmSystemTools::Error("Error SetGlobalGenerator called with null");
1698 // delete the old generator
1699 if (this->GlobalGenerator
)
1701 delete this->GlobalGenerator
;
1702 // restore the original environment variables CXX and CC
1704 std::string env
= "CC=";
1705 if(this->CCEnvironment
.size())
1707 env
+= this->CCEnvironment
;
1709 cmSystemTools::PutEnv(env
.c_str());
1711 if(this->CXXEnvironment
.size())
1713 env
+= this->CXXEnvironment
;
1715 cmSystemTools::PutEnv(env
.c_str());
1719 this->GlobalGenerator
= gg
;
1721 // set the global flag for unix style paths on cmSystemTools as soon as
1722 // the generator is set. This allows gmake to be used on windows.
1723 cmSystemTools::SetForceUnixPaths
1724 (this->GlobalGenerator
->GetForceUnixPaths());
1726 // Save the environment variables CXX and CC
1727 const char* cxx
= getenv("CXX");
1728 const char* cc
= getenv("CC");
1731 this->CXXEnvironment
= cxx
;
1735 this->CXXEnvironment
= "";
1739 this->CCEnvironment
= cc
;
1743 this->CCEnvironment
= "";
1745 // set the cmake instance just to be sure
1746 gg
->SetCMakeInstance(this);
1749 int cmake::DoPreConfigureChecks()
1751 // Make sure the Start directory contains a CMakeLists.txt file.
1752 std::string srcList
= this->GetHomeDirectory();
1753 srcList
+= "/CMakeLists.txt";
1754 if(!cmSystemTools::FileExists(srcList
.c_str()))
1756 cmOStringStream err
;
1757 if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
1759 err
<< "The source directory \"" << this->GetHomeDirectory()
1760 << "\" does not appear to contain CMakeLists.txt.\n";
1762 else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
1764 err
<< "The source directory \"" << this->GetHomeDirectory()
1765 << "\" is a file, not a directory.\n";
1769 err
<< "The source directory \"" << this->GetHomeDirectory()
1770 << "\" does not exist.\n";
1772 err
<< "Specify --help for usage, or press the help button on the CMake "
1774 cmSystemTools::Error(err
.str().c_str());
1778 // do a sanity check on some values
1779 if(this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY"))
1781 std::string cacheStart
=
1782 this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY");
1783 cacheStart
+= "/CMakeLists.txt";
1784 std::string currentStart
= this->GetHomeDirectory();
1785 currentStart
+= "/CMakeLists.txt";
1786 if(!cmSystemTools::SameFile(cacheStart
.c_str(), currentStart
.c_str()))
1788 std::string message
= "The source \"";
1789 message
+= currentStart
;
1790 message
+= "\" does not match the source \"";
1791 message
+= cacheStart
;
1792 message
+= "\" used to generate cache. ";
1793 message
+= "Re-run cmake with a different source directory.";
1794 cmSystemTools::Error(message
.c_str());
1804 struct SaveCacheEntry
1809 cmCacheManager::CacheEntryType type
;
1812 int cmake::HandleDeleteCacheVariables(const char* var
)
1814 std::vector
<std::string
> argsSplit
;
1815 cmSystemTools::ExpandListArgument(std::string(var
), argsSplit
);
1816 // erase the property to avoid infinite recursion
1817 this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
1819 cmCacheManager::CacheIterator ci
= this->CacheManager
->NewIterator();
1820 std::vector
<SaveCacheEntry
> saved
;
1821 cmOStringStream warning
;
1823 << "You have changed variables that require your cache to be deleted.\n"
1824 << "Configure will be re-run and you may have to reset some variables.\n"
1825 << "The following variables have changed:\n";
1826 for(std::vector
<std::string
>::iterator i
= argsSplit
.begin();
1827 i
!= argsSplit
.end(); ++i
)
1829 SaveCacheEntry save
;
1831 warning
<< *i
<< "= ";
1834 warning
<< *i
<< "\n";
1835 if(ci
.Find(save
.key
.c_str()))
1837 save
.type
= ci
.GetType();
1838 save
.help
= ci
.GetProperty("HELPSTRING");
1840 saved
.push_back(save
);
1844 this->CacheManager
->DeleteCache(this->GetStartOutputDirectory());
1845 // load the empty cache
1847 // restore the changed compilers
1848 for(std::vector
<SaveCacheEntry
>::iterator i
= saved
.begin();
1849 i
!= saved
.end(); ++i
)
1851 this->AddCacheEntry(i
->key
.c_str(), i
->value
.c_str(),
1852 i
->help
.c_str(), i
->type
);
1854 cmSystemTools::Message(warning
.str().c_str());
1855 // avoid reconfigure if there were errors
1856 if(!cmSystemTools::GetErrorOccuredFlag())
1859 return this->Configure();
1864 int cmake::Configure()
1866 int ret
= this->ActualConfigure();
1867 const char* delCacheVars
=
1868 this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
1869 if(delCacheVars
&& delCacheVars
[0] != 0)
1871 return this->HandleDeleteCacheVariables(delCacheVars
);
1877 int cmake::ActualConfigure()
1879 // Construct right now our path conversion table before it's too late:
1880 this->UpdateConversionPathTable();
1881 this->CleanupCommandsAndMacros();
1884 if ( !this->ScriptMode
)
1886 res
= this->DoPreConfigureChecks();
1894 this->CacheManager
->AddCacheEntry
1895 ("CMAKE_HOME_DIRECTORY",
1896 this->GetHomeDirectory(),
1897 "Start directory with the top level CMakeLists.txt file for this "
1899 cmCacheManager::INTERNAL
);
1902 // set the default BACKWARDS compatibility to the current version
1903 if(!this->CacheManager
->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
1906 sprintf(ver
,"%i.%i",cmVersion::GetMajorVersion(),
1907 cmVersion::GetMinorVersion());
1908 this->CacheManager
->AddCacheEntry
1909 ("CMAKE_BACKWARDS_COMPATIBILITY",ver
,
1910 "For backwards compatibility, what version of CMake commands and "
1911 "syntax should this version of CMake allow.",
1912 cmCacheManager::STRING
);
1915 // no generator specified on the command line
1916 if(!this->GlobalGenerator
)
1918 const char* genName
=
1919 this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
1920 const char* extraGenName
=
1921 this->CacheManager
->GetCacheValue("CMAKE_EXTRA_GENERATOR");
1924 std::string fullName
= cmExternalMakefileProjectGenerator::
1925 CreateFullGeneratorName(genName
, extraGenName
);
1926 this->GlobalGenerator
= this->CreateGlobalGenerator(fullName
.c_str());
1928 if(this->GlobalGenerator
)
1930 // set the global flag for unix style paths on cmSystemTools as
1931 // soon as the generator is set. This allows gmake to be used
1933 cmSystemTools::SetForceUnixPaths
1934 (this->GlobalGenerator
->GetForceUnixPaths());
1938 #if defined(__BORLANDC__) && defined(_WIN32)
1939 this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator
);
1940 #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
1941 std::string installedCompiler
;
1942 std::string mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1943 "\\VisualStudio\\8.0\\Setup;Dbghelp_path]";
1944 cmSystemTools::ExpandRegistryValues(mp
);
1945 if (!(mp
== "/registry"))
1947 installedCompiler
= "Visual Studio 8 2005";
1951 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1952 "\\VisualStudio\\7.1;InstallDir]";
1953 cmSystemTools::ExpandRegistryValues(mp
);
1954 if (!(mp
== "/registry"))
1956 installedCompiler
= "Visual Studio 7 .NET 2003";
1960 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
1961 "\\VisualStudio\\7.0;InstallDir]";
1962 cmSystemTools::ExpandRegistryValues(mp
);
1963 if (!(mp
== "/registry"))
1965 installedCompiler
= "Visual Studio 7";
1969 installedCompiler
= "Visual Studio 6";
1973 cmGlobalGenerator
* gen
1974 = this->CreateGlobalGenerator(installedCompiler
.c_str());
1977 gen
= new cmGlobalNMakeMakefileGenerator
;
1979 this->SetGlobalGenerator(gen
);
1981 this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3
);
1984 if(!this->GlobalGenerator
)
1986 cmSystemTools::Error("Could not create generator");
1991 const char* genName
= this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
1994 if(strcmp(this->GlobalGenerator
->GetName(), genName
) != 0)
1996 std::string message
= "Error: generator : ";
1997 message
+= this->GlobalGenerator
->GetName();
1998 message
+= "\nDoes not match the generator used previously: ";
2001 "\nEither remove the CMakeCache.txt file or choose a different"
2002 " binary directory.";
2003 cmSystemTools::Error(message
.c_str());
2007 if(!this->CacheManager
->GetCacheValue("CMAKE_GENERATOR"))
2009 this->CacheManager
->AddCacheEntry("CMAKE_GENERATOR",
2010 this->GlobalGenerator
->GetName(),
2011 "Name of generator.",
2012 cmCacheManager::INTERNAL
);
2013 this->CacheManager
->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
2014 this->GlobalGenerator
->GetExtraGeneratorName(),
2015 "Name of external makefile project generator.",
2016 cmCacheManager::INTERNAL
);
2019 // reset any system configuration information, except for when we are
2020 // InTryCompile. With TryCompile the system info is taken from the parent's
2021 // info to save time
2022 if (!this->InTryCompile
)
2024 this->GlobalGenerator
->ClearEnabledLanguages();
2027 this->CleanupWrittenFiles();
2029 // Truncate log files
2030 if (!this->InTryCompile
)
2032 this->TruncateOutputLog("CMakeOutput.log");
2033 this->TruncateOutputLog("CMakeError.log");
2036 // actually do the configure
2037 this->GlobalGenerator
->Configure();
2038 // Before saving the cache
2039 // if the project did not define one of the entries below, add them now
2040 // so users can edit the values in the cache:
2041 // LIBRARY_OUTPUT_PATH
2042 // EXECUTABLE_OUTPUT_PATH
2043 if(!this->CacheManager
->GetCacheValue("LIBRARY_OUTPUT_PATH"))
2045 this->CacheManager
->AddCacheEntry
2046 ("LIBRARY_OUTPUT_PATH", "",
2047 "Single output directory for building all libraries.",
2048 cmCacheManager::PATH
);
2050 if(!this->CacheManager
->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
2052 this->CacheManager
->AddCacheEntry
2053 ("EXECUTABLE_OUTPUT_PATH", "",
2054 "Single output directory for building all executables.",
2055 cmCacheManager::PATH
);
2057 if(!this->CacheManager
->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
2059 this->CacheManager
->AddCacheEntry
2060 ("CMAKE_USE_RELATIVE_PATHS", false,
2061 "If true, cmake will use relative paths in makefiles and projects.");
2062 cmCacheManager::CacheIterator it
=
2063 this->CacheManager
->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
2064 if ( !it
.PropertyExists("ADVANCED") )
2066 it
.SetProperty("ADVANCED", "1");
2070 if(cmSystemTools::GetFatalErrorOccured() &&
2071 (!this->CacheManager
->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
2072 cmSystemTools::IsOff(this->CacheManager
->
2073 GetCacheValue("CMAKE_MAKE_PROGRAM"))))
2075 // We must have a bad generator selection. Wipe the cache entry so the
2076 // user can select another.
2077 this->CacheManager
->RemoveCacheEntry("CMAKE_GENERATOR");
2078 this->CacheManager
->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
2080 // only save the cache if there were no fatal errors
2081 if ( !this->ScriptMode
)
2083 this->CacheManager
->SaveCache(this->GetHomeOutputDirectory());
2085 if ( !this->GraphVizFile
.empty() )
2087 std::cout
<< "Generate graphviz: " << this->GraphVizFile
<< std::endl
;
2088 this->GenerateGraphViz(this->GraphVizFile
.c_str());
2090 if(cmSystemTools::GetErrorOccuredFlag())
2097 bool cmake::CacheVersionMatches()
2100 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION");
2102 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MINOR_VERSION");
2104 this->CacheManager
->GetCacheValue("CMAKE_CACHE_RELEASE_VERSION");
2105 bool cacheSameCMake
= false;
2107 atoi(majv
) == static_cast<int>(cmVersion::GetMajorVersion())
2109 atoi(minv
) == static_cast<int>(cmVersion::GetMinorVersion())
2110 && relv
&& (strcmp(relv
, cmVersion::GetReleaseVersion().c_str()) == 0))
2112 cacheSameCMake
= true;
2114 return cacheSameCMake
;
2117 void cmake::PreLoadCMakeFiles()
2119 std::string pre_load
= this->GetHomeDirectory();
2120 if ( pre_load
.size() > 0 )
2122 pre_load
+= "/PreLoad.cmake";
2123 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2125 this->ReadListFile(pre_load
.c_str());
2128 pre_load
= this->GetHomeOutputDirectory();
2129 if ( pre_load
.size() > 0 )
2131 pre_load
+= "/PreLoad.cmake";
2132 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2134 this->ReadListFile(pre_load
.c_str());
2139 // handle a command line invocation
2140 int cmake::Run(const std::vector
<std::string
>& args
, bool noconfigure
)
2142 // Process the arguments
2143 this->SetArgs(args
);
2144 if(cmSystemTools::GetErrorOccuredFlag())
2149 // If we are given a stamp file check if it is really out of date.
2150 if(!this->CheckStampFile
.empty() &&
2151 cmakeCheckStampFile(this->CheckStampFile
.c_str()))
2156 // set the cmake command
2157 this->CMakeCommand
= args
[0];
2159 if ( !this->ScriptMode
)
2162 if(this->LoadCache() < 0)
2164 cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
2170 this->AddCMakePaths();
2173 // Add any cache args
2174 if ( !this->SetCacheArgs(args
) )
2176 cmSystemTools::Error("Problem processing arguments. Aborting.\n");
2180 // In script mode we terminate after running the script.
2181 if(this->ScriptMode
)
2183 if(cmSystemTools::GetErrorOccuredFlag())
2193 this->PreLoadCMakeFiles();
2195 std::string systemFile
= this->GetHomeOutputDirectory();
2196 systemFile
+= "/CMakeSystem.cmake";
2203 // now run the global generate
2204 // Check the state of the build system to see if we need to regenerate.
2205 if(!this->CheckBuildSystem())
2210 // If we are doing global generate, we better set start and start
2211 // output directory to the root of the project.
2212 std::string oldstartdir
= this->GetStartDirectory();
2213 std::string oldstartoutputdir
= this->GetStartOutputDirectory();
2214 this->SetStartDirectory(this->GetHomeDirectory());
2215 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
2216 int ret
= this->Configure();
2217 if (ret
|| this->ScriptMode
)
2219 #if defined(CMAKE_HAVE_VS_GENERATORS)
2220 if(!this->VSSolutionFile
.empty() && this->GlobalGenerator
)
2222 // CMake is running to regenerate a Visual Studio build tree
2223 // during a build from the VS IDE. The build files cannot be
2224 // regenerated, so we should stop the build.
2225 cmSystemTools::Message(
2226 "CMake Configure step failed. "
2227 "Build files cannot be regenerated correctly. "
2228 "Attempting to stop IDE build.");
2229 cmGlobalVisualStudioGenerator
* gg
=
2230 static_cast<cmGlobalVisualStudioGenerator
*>(this->GlobalGenerator
);
2231 gg
->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop
,
2232 this->VSSolutionFile
.c_str());
2237 ret
= this->Generate();
2238 std::string message
= "Build files have been written to: ";
2239 message
+= this->GetHomeOutputDirectory();
2240 this->UpdateProgress(message
.c_str(), -1);
2245 this->SetStartDirectory(oldstartdir
.c_str());
2246 this->SetStartOutputDirectory(oldstartoutputdir
.c_str());
2251 int cmake::Generate()
2253 if(!this->GlobalGenerator
)
2257 this->GlobalGenerator
->Generate();
2258 if(cmSystemTools::GetErrorOccuredFlag())
2262 if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
2264 this->ReportUndefinedPropertyAccesses
2265 (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
2270 void cmake::AddCacheEntry(const char* key
, const char* value
,
2271 const char* helpString
,
2274 this->CacheManager
->AddCacheEntry(key
, value
,
2276 cmCacheManager::CacheEntryType(type
));
2279 const char* cmake::GetCacheDefinition(const char* name
) const
2281 return this->CacheManager
->GetCacheValue(name
);
2284 int cmake::DumpDocumentationToFile(std::ostream
& f
)
2286 #ifdef CMAKE_BUILD_WITH_CMAKE
2287 // Loop over all registered commands and print out documentation
2292 sprintf(tmp
,"Version %d.%d (%s)", cmVersion::GetMajorVersion(),
2293 cmVersion::GetMinorVersion(),
2294 cmVersion::GetReleaseVersion().c_str());
2296 f
<< "<h1>Documentation for commands of CMake " << tmp
<< "</h1>\n";
2298 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
2299 j
!= this->Commands
.end(); ++j
)
2301 name
= (*j
).second
->GetName();
2302 terse
= (*j
).second
->GetTerseDocumentation();
2303 full
= (*j
).second
->GetFullDocumentation();
2304 f
<< "<li><b>" << name
<< "</b> - " << terse
<< std::endl
2305 << "<br><i>Usage:</i> " << full
<< "</li>" << std::endl
<< std::endl
;
2307 f
<< "</ul></html>\n";
2314 void cmake::AddDefaultCommands()
2316 std::list
<cmCommand
*> commands
;
2317 GetBootstrapCommands(commands
);
2318 GetPredefinedCommands(commands
);
2319 for(std::list
<cmCommand
*>::iterator i
= commands
.begin();
2320 i
!= commands
.end(); ++i
)
2322 this->AddCommand(*i
);
2326 void cmake::AddDefaultGenerators()
2328 #if defined(_WIN32) && !defined(__CYGWIN__)
2329 # if !defined(CMAKE_BOOT_MINGW)
2330 this->Generators
[cmGlobalVisualStudio6Generator::GetActualName()] =
2331 &cmGlobalVisualStudio6Generator::New
;
2332 this->Generators
[cmGlobalVisualStudio7Generator::GetActualName()] =
2333 &cmGlobalVisualStudio7Generator::New
;
2334 this->Generators
[cmGlobalVisualStudio71Generator::GetActualName()] =
2335 &cmGlobalVisualStudio71Generator::New
;
2336 this->Generators
[cmGlobalVisualStudio8Generator::GetActualName()] =
2337 &cmGlobalVisualStudio8Generator::New
;
2338 this->Generators
[cmGlobalVisualStudio9Generator::GetActualName()] =
2339 &cmGlobalVisualStudio9Generator::New
;
2340 this->Generators
[cmGlobalVisualStudio9Win64Generator::GetActualName()] =
2341 &cmGlobalVisualStudio9Win64Generator::New
;
2342 this->Generators
[cmGlobalVisualStudio8Win64Generator::GetActualName()] =
2343 &cmGlobalVisualStudio8Win64Generator::New
;
2344 this->Generators
[cmGlobalBorlandMakefileGenerator::GetActualName()] =
2345 &cmGlobalBorlandMakefileGenerator::New
;
2346 this->Generators
[cmGlobalNMakeMakefileGenerator::GetActualName()] =
2347 &cmGlobalNMakeMakefileGenerator::New
;
2348 this->Generators
[cmGlobalWatcomWMakeGenerator::GetActualName()] =
2349 &cmGlobalWatcomWMakeGenerator::New
;
2351 this->Generators
[cmGlobalMSYSMakefileGenerator::GetActualName()] =
2352 &cmGlobalMSYSMakefileGenerator::New
;
2353 this->Generators
[cmGlobalMinGWMakefileGenerator::GetActualName()] =
2354 &cmGlobalMinGWMakefileGenerator::New
;
2356 this->Generators
[cmGlobalUnixMakefileGenerator3::GetActualName()] =
2357 &cmGlobalUnixMakefileGenerator3::New
;
2358 #ifdef CMAKE_USE_XCODE
2359 this->Generators
[cmGlobalXCodeGenerator::GetActualName()] =
2360 &cmGlobalXCodeGenerator::New
;
2364 int cmake::LoadCache()
2366 // could we not read the cache
2367 if (!this->CacheManager
->LoadCache(this->GetHomeOutputDirectory()))
2369 // if it does exist, but isn;t readable then warn the user
2370 std::string cacheFile
= this->GetHomeOutputDirectory();
2371 cacheFile
+= "/CMakeCache.txt";
2372 if(cmSystemTools::FileExists(cacheFile
.c_str()))
2374 cmSystemTools::Error(
2375 "There is a CMakeCache.txt file for the current binary tree but "
2376 "cmake does not have permission to read it. Please check the "
2377 "permissions of the directory you are trying to run CMake on.");
2382 if (this->CMakeCommand
.size() < 2)
2384 cmSystemTools::Error(
2385 "cmake command was not specified prior to loading the cache in "
2390 // setup CMAKE_ROOT and CMAKE_COMMAND
2391 if(!this->AddCMakePaths())
2396 // set the default BACKWARDS compatibility to the current version
2397 if(!this->CacheManager
->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
2400 sprintf(ver
,"%i.%i",cmVersion::GetMajorVersion(),
2401 cmVersion::GetMinorVersion());
2402 this->CacheManager
->AddCacheEntry
2403 ("CMAKE_BACKWARDS_COMPATIBILITY",ver
,
2404 "For backwards compatibility, what version of CMake commands and "
2405 "syntax should this version of CMake allow.",
2406 cmCacheManager::STRING
);
2412 void cmake::SetProgressCallback(ProgressCallbackType f
, void *cd
)
2414 this->ProgressCallback
= f
;
2415 this->ProgressCallbackClientData
= cd
;
2418 void cmake::UpdateProgress(const char *msg
, float prog
)
2420 if(this->ProgressCallback
&& !this->InTryCompile
)
2422 (*this->ProgressCallback
)(msg
, prog
, this->ProgressCallbackClientData
);
2427 void cmake::GetCommandDocumentation(std::vector
<cmDocumentationEntry
>& v
,
2428 bool withCurrentCommands
,
2429 bool withCompatCommands
) const
2431 for(RegisteredCommandsMap::const_iterator j
= this->Commands
.begin();
2432 j
!= this->Commands
.end(); ++j
)
2434 if ((( withCompatCommands
== false) && ( (*j
).second
->IsDiscouraged()))
2435 || ((withCurrentCommands
== false) && (!(*j
).second
->IsDiscouraged())))
2440 cmDocumentationEntry
e((*j
).second
->GetName(),
2441 (*j
).second
->GetTerseDocumentation(),
2442 (*j
).second
->GetFullDocumentation());
2447 void cmake::GetPropertiesDocumentation(std::map
<std::string
,
2448 cmDocumentationSection
*>& v
)
2450 // loop over the properties and put them into the doc structure
2451 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
2452 i
= this->PropertyDefinitions
.begin();
2453 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
2455 i
->second
.GetPropertiesDocumentation(v
);
2459 void cmake::GetGeneratorDocumentation(std::vector
<cmDocumentationEntry
>& v
)
2461 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
2462 i
!= this->Generators
.end(); ++i
)
2464 cmDocumentationEntry e
;
2465 cmGlobalGenerator
* generator
= (i
->second
)();
2466 generator
->GetDocumentation(e
);
2470 for(RegisteredExtraGeneratorsMap::const_iterator
2471 i
= this->ExtraGenerators
.begin(); i
!= this->ExtraGenerators
.end(); ++i
)
2473 cmDocumentationEntry e
;
2474 cmExternalMakefileProjectGenerator
* generator
= (i
->second
)();
2475 generator
->GetDocumentation(e
, i
->first
.c_str());
2482 void cmake::AddWrittenFile(const char* file
)
2484 this->WrittenFiles
.insert(file
);
2487 bool cmake::HasWrittenFile(const char* file
)
2489 return this->WrittenFiles
.find(file
) != this->WrittenFiles
.end();
2492 void cmake::CleanupWrittenFiles()
2494 this->WrittenFiles
.clear();
2497 void cmake::UpdateConversionPathTable()
2499 // Update the path conversion table with any specified file:
2500 const char* tablepath
=
2501 this->CacheManager
->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
2505 std::ifstream
table( tablepath
);
2508 cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath
,
2509 ". CMake can not open file.");
2510 cmSystemTools::ReportLastSystemError("CMake can not open file.");
2517 // two entries per line
2518 table
>> a
; table
>> b
;
2519 cmSystemTools::AddTranslationPath( a
.c_str(), b
.c_str());
2525 //----------------------------------------------------------------------------
2526 int cmake::CheckBuildSystem()
2528 // We do not need to rerun CMake. Check dependency integrity. Use
2529 // the make system's VERBOSE environment variable to enable verbose
2531 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
2533 // This method will check the integrity of the build system if the
2534 // option was given on the command line. It reads the given file to
2535 // determine whether CMake should rerun.
2537 // If no file is provided for the check, we have to rerun.
2538 if(this->CheckBuildSystemArgument
.size() == 0)
2542 cmOStringStream msg
;
2543 msg
<< "Re-run cmake no build system arguments\n";
2544 cmSystemTools::Stdout(msg
.str().c_str());
2549 // If the file provided does not exist, we have to rerun.
2550 if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument
.c_str()))
2554 cmOStringStream msg
;
2555 msg
<< "Re-run cmake missing file: "
2556 << this->CheckBuildSystemArgument
.c_str() << "\n";
2557 cmSystemTools::Stdout(msg
.str().c_str());
2562 // Read the rerun check file and use it to decide whether to do the
2565 cmGlobalGenerator gg
;
2566 gg
.SetCMakeInstance(&cm
);
2567 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
2568 lg
->SetGlobalGenerator(&gg
);
2569 cmMakefile
* mf
= lg
->GetMakefile();
2570 if(!mf
->ReadListFile(0, this->CheckBuildSystemArgument
.c_str()) ||
2571 cmSystemTools::GetErrorOccuredFlag())
2575 cmOStringStream msg
;
2576 msg
<< "Re-run cmake error reading : "
2577 << this->CheckBuildSystemArgument
.c_str() << "\n";
2578 cmSystemTools::Stdout(msg
.str().c_str());
2580 // There was an error reading the file. Just rerun.
2584 if(this->ClearBuildSystem
)
2586 // Get the generator used for this build system.
2587 const char* genName
= mf
->GetDefinition("CMAKE_DEPENDS_GENERATOR");
2588 if(!genName
|| genName
[0] == '\0')
2590 genName
= "Unix Makefiles";
2593 // Create the generator and use it to clear the dependencies.
2594 std::auto_ptr
<cmGlobalGenerator
>
2595 ggd(this->CreateGlobalGenerator(genName
));
2598 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
2599 lgd
->SetGlobalGenerator(ggd
.get());
2600 lgd
->ClearDependencies(mf
, verbose
);
2604 // Get the set of dependencies and outputs.
2605 std::vector
<std::string
> depends
;
2606 std::vector
<std::string
> outputs
;
2607 const char* dependsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
2608 const char* outputsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
2609 if(dependsStr
&& outputsStr
)
2611 cmSystemTools::ExpandListArgument(dependsStr
, depends
);
2612 cmSystemTools::ExpandListArgument(outputsStr
, outputs
);
2614 if(depends
.empty() || outputs
.empty())
2616 // Not enough information was provided to do the test. Just rerun.
2619 cmOStringStream msg
;
2620 msg
<< "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
2621 "or CMAKE_MAKEFILE_OUTPUTS :\n";
2622 cmSystemTools::Stdout(msg
.str().c_str());
2627 // Find find the newest dependency.
2628 std::vector
<std::string
>::iterator dep
= depends
.begin();
2629 std::string dep_newest
= *dep
++;
2630 for(;dep
!= depends
.end(); ++dep
)
2633 if(this->FileComparison
->FileTimeCompare(dep_newest
.c_str(),
2634 dep
->c_str(), &result
))
2645 cmOStringStream msg
;
2646 msg
<< "Re-run cmake: build system dependency is missing\n";
2647 cmSystemTools::Stdout(msg
.str().c_str());
2653 // Find find the oldest output.
2654 std::vector
<std::string
>::iterator out
= outputs
.begin();
2655 std::string out_oldest
= *out
++;
2656 for(;out
!= outputs
.end(); ++out
)
2659 if(this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2660 out
->c_str(), &result
))
2671 cmOStringStream msg
;
2672 msg
<< "Re-run cmake: build system output is missing\n";
2673 cmSystemTools::Stdout(msg
.str().c_str());
2679 // If any output is older than any dependency then rerun.
2682 if(!this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2689 cmOStringStream msg
;
2690 msg
<< "Re-run cmake file: " << out_oldest
.c_str()
2691 << " older than: " << dep_newest
.c_str() << "\n";
2692 cmSystemTools::Stdout(msg
.str().c_str());
2698 // No need to rerun.
2702 //----------------------------------------------------------------------------
2703 void cmake::TruncateOutputLog(const char* fname
)
2705 std::string fullPath
= this->GetHomeOutputDirectory();
2709 if ( ::stat(fullPath
.c_str(), &st
) )
2713 if ( !this->CacheManager
->GetCacheValue("CMAKE_CACHEFILE_DIR") )
2715 cmSystemTools::RemoveFile(fullPath
.c_str());
2718 off_t fsize
= st
.st_size
;
2719 const off_t maxFileSize
= 50 * 1024;
2720 if ( fsize
< maxFileSize
)
2722 //TODO: truncate file
2727 inline std::string
removeQuotes(const std::string
& s
)
2729 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
2731 return s
.substr(1, s
.size()-2);
2736 std::string
cmake::FindCMakeProgram(const char* name
) const
2739 if ((name
) && (*name
))
2741 const cmMakefile
* mf
2742 = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
2743 #ifdef CMAKE_BUILD_WITH_CMAKE
2744 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2745 path
= removeQuotes(path
);
2746 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2749 path
+= cmSystemTools::GetExecutableExtension();
2750 if(!cmSystemTools::FileExists(path
.c_str()))
2752 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2753 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2756 path
+= cmSystemTools::GetExecutableExtension();
2758 if(!cmSystemTools::FileExists(path
.c_str()))
2760 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2761 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2762 path
+= "/Release/";
2764 path
+= cmSystemTools::GetExecutableExtension();
2767 // Only for bootstrap
2768 path
+= mf
->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
2771 path
+= cmSystemTools::GetExecutableExtension();
2777 const char* cmake::GetCTestCommand()
2779 if ( this->CTestCommand
.empty() )
2781 this->CTestCommand
= this->FindCMakeProgram("ctest");
2783 if ( this->CTestCommand
.empty() )
2785 cmSystemTools::Error("Cannot find the CTest executable");
2786 this->CTestCommand
= "CTEST-COMMAND-NOT-FOUND";
2788 return this->CTestCommand
.c_str();
2791 const char* cmake::GetCPackCommand()
2793 if ( this->CPackCommand
.empty() )
2795 this->CPackCommand
= this->FindCMakeProgram("cpack");
2797 if ( this->CPackCommand
.empty() )
2799 cmSystemTools::Error("Cannot find the CPack executable");
2800 this->CPackCommand
= "CPACK-COMMAND-NOT-FOUND";
2802 return this->CPackCommand
.c_str();
2805 void cmake::GenerateGraphViz(const char* fileName
) const
2807 cmGeneratedFileStream
str(fileName
);
2813 cmGlobalGenerator ggi
;
2814 ggi
.SetCMakeInstance(&cm
);
2815 std::auto_ptr
<cmLocalGenerator
> lg(ggi
.CreateLocalGenerator());
2816 lg
->SetGlobalGenerator(&ggi
);
2817 cmMakefile
*mf
= lg
->GetMakefile();
2819 std::string infile
= this->GetHomeOutputDirectory();
2820 infile
+= "/CMakeGraphVizOptions.cmake";
2821 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2823 infile
= this->GetHomeDirectory();
2824 infile
+= "/CMakeGraphVizOptions.cmake";
2825 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2831 if ( !infile
.empty() )
2833 if ( !mf
->ReadListFile(0, infile
.c_str()) )
2835 cmSystemTools::Error("Problem opening GraphViz options file: ",
2839 std::cout
<< "Read GraphViz options file: " << infile
.c_str()
2843 #define __set_if_not_set(var, value, cmakeDefinition) \
2844 const char* var = mf->GetDefinition(cmakeDefinition); \
2849 __set_if_not_set(graphType
, "digraph", "GRAPHVIZ_GRAPH_TYPE");
2850 __set_if_not_set(graphName
, "GG", "GRAPHVIZ_GRAPH_NAME");
2851 __set_if_not_set(graphHeader
, "node [\n fontsize = \"12\"\n];",
2852 "GRAPHVIZ_GRAPH_HEADER");
2853 __set_if_not_set(graphNodePrefix
, "node", "GRAPHVIZ_NODE_PREFIX");
2854 const char* ignoreTargets
= mf
->GetDefinition("GRAPHVIZ_IGNORE_TARGETS");
2855 std::set
<cmStdString
> ignoreTargetsSet
;
2856 if ( ignoreTargets
)
2858 std::vector
<std::string
> ignoreTargetsVector
;
2859 cmSystemTools::ExpandListArgument(ignoreTargets
,ignoreTargetsVector
);
2860 std::vector
<std::string
>::iterator itvIt
;
2861 for ( itvIt
= ignoreTargetsVector
.begin();
2862 itvIt
!= ignoreTargetsVector
.end();
2865 ignoreTargetsSet
.insert(itvIt
->c_str());
2869 str
<< graphType
<< " " << graphName
<< " {" << std::endl
;
2870 str
<< graphHeader
<< std::endl
;
2872 const cmGlobalGenerator
* gg
= this->GetGlobalGenerator();
2873 const std::vector
<cmLocalGenerator
*>& localGenerators
=
2874 gg
->GetLocalGenerators();
2875 std::vector
<cmLocalGenerator
*>::const_iterator lit
;
2878 // 2 - external target
2880 std::map
<cmStdString
, int> targetDeps
;
2881 std::map
<cmStdString
, const cmTarget
*> targetPtrs
;
2882 std::map
<cmStdString
, cmStdString
> targetNamesNodes
;
2884 // First pass get the list of all cmake targets
2885 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2887 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2888 cmTargets::const_iterator tit
;
2889 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2891 const char* realTargetName
= tit
->first
.c_str();
2892 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2894 // Skip ignored targets
2897 //std::cout << "Found target: " << tit->first.c_str() << std::endl;
2898 cmOStringStream ostr
;
2899 ostr
<< graphNodePrefix
<< cnt
++;
2900 targetNamesNodes
[realTargetName
] = ostr
.str();
2901 targetPtrs
[realTargetName
] = &tit
->second
;
2904 // Ok, now find all the stuff we link to that is not in cmake
2905 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2907 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2908 cmTargets::const_iterator tit
;
2909 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2911 const cmTarget::LinkLibraryVectorType
* ll
2912 = &(tit
->second
.GetOriginalLinkLibraries());
2913 cmTarget::LinkLibraryVectorType::const_iterator llit
;
2914 const char* realTargetName
= tit
->first
.c_str();
2915 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2917 // Skip ignored targets
2920 if ( ll
->size() > 0 )
2922 targetDeps
[realTargetName
] = 1;
2924 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
2926 const char* libName
= llit
->first
.c_str();
2927 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
2928 = targetNamesNodes
.find(libName
);
2929 if ( ignoreTargetsSet
.find(libName
) != ignoreTargetsSet
.end() )
2931 // Skip ignored targets
2934 if ( tarIt
== targetNamesNodes
.end() )
2936 cmOStringStream ostr
;
2937 ostr
<< graphNodePrefix
<< cnt
++;
2938 targetDeps
[libName
] = 2;
2939 targetNamesNodes
[libName
] = ostr
.str();
2940 //str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
2941 //<< "\" shape=\"ellipse\"];" << std::endl;
2945 std::map
<cmStdString
, int>::const_iterator depIt
2946 = targetDeps
.find(libName
);
2947 if ( depIt
== targetDeps
.end() )
2949 targetDeps
[libName
] = 1;
2957 std::map
<cmStdString
, int>::const_iterator depIt
;
2958 for ( depIt
= targetDeps
.begin(); depIt
!= targetDeps
.end(); ++ depIt
)
2960 const char* newTargetName
= depIt
->first
.c_str();
2961 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
2962 = targetNamesNodes
.find(newTargetName
);
2963 if ( tarIt
== targetNamesNodes
.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
;
2971 str
<< " \"" << tarIt
->second
.c_str() << "\" [ label=\""
2972 << newTargetName
<< "\" shape=\"";
2973 if ( depIt
->second
== 1 )
2975 std::map
<cmStdString
, const cmTarget
*>::const_iterator tarTypeIt
=
2976 targetPtrs
.find(newTargetName
);
2977 if ( tarTypeIt
== targetPtrs
.end() )
2979 // We should not be here.
2980 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
2981 << " even though it was added in the previous pass" << std::endl
;
2984 const cmTarget
* tg
= tarTypeIt
->second
;
2985 switch ( tg
->GetType() )
2987 case cmTarget::EXECUTABLE
:
2990 case cmTarget::STATIC_LIBRARY
:
2993 case cmTarget::SHARED_LIBRARY
:
2996 case cmTarget::MODULE_LIBRARY
:
3007 str
<< "\"];" << std::endl
;
3010 // Now generate the connectivity
3011 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
3013 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
3014 cmTargets::const_iterator tit
;
3015 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
3017 std::map
<cmStdString
, int>::iterator dependIt
3018 = targetDeps
.find(tit
->first
.c_str());
3019 if ( dependIt
== targetDeps
.end() )
3023 std::map
<cmStdString
, cmStdString
>::iterator cmakeTarIt
3024 = targetNamesNodes
.find(tit
->first
.c_str());
3025 const cmTarget::LinkLibraryVectorType
* ll
3026 = &(tit
->second
.GetOriginalLinkLibraries());
3027 cmTarget::LinkLibraryVectorType::const_iterator llit
;
3028 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
3030 const char* libName
= llit
->first
.c_str();
3031 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3032 = targetNamesNodes
.find(libName
);
3033 if ( tarIt
== targetNamesNodes
.end() )
3035 // We should not be here.
3036 std::cout
<< __LINE__
<< " Cannot find library: " << libName
3037 << " even though it was added in the previous pass" << std::endl
;
3040 str
<< " \"" << cmakeTarIt
->second
.c_str() << "\" -> \""
3041 << tarIt
->second
.c_str() << "\"" << std::endl
;
3046 // TODO: Use dotted or something for external libraries
3047 //str << " \"node0\":f4 -> \"node12\"[color=\"#0000ff\" style=dotted]"
3050 str
<< "}" << std::endl
;
3053 //----------------------------------------------------------------------------
3054 #ifdef CMAKE_BUILD_WITH_CMAKE
3055 int cmake::ExecuteEchoColor(std::vector
<std::string
>& args
)
3057 // The arguments are
3058 // argv[0] == <cmake-executable>
3059 // argv[1] == cmake_echo_color
3061 bool enabled
= true;
3062 int color
= cmsysTerminal_Color_Normal
;
3063 bool newline
= true;
3064 for(unsigned int i
=2; i
< args
.size(); ++i
)
3066 if(args
[i
].find("--switch=") == 0)
3068 // Enable or disable color based on the switch value.
3069 std::string value
= args
[i
].substr(9);
3072 if(cmSystemTools::IsOn(value
.c_str()))
3082 else if(args
[i
] == "--normal")
3084 color
= cmsysTerminal_Color_Normal
;
3086 else if(args
[i
] == "--black")
3088 color
= cmsysTerminal_Color_ForegroundBlack
;
3090 else if(args
[i
] == "--red")
3092 color
= cmsysTerminal_Color_ForegroundRed
;
3094 else if(args
[i
] == "--green")
3096 color
= cmsysTerminal_Color_ForegroundGreen
;
3098 else if(args
[i
] == "--yellow")
3100 color
= cmsysTerminal_Color_ForegroundYellow
;
3102 else if(args
[i
] == "--blue")
3104 color
= cmsysTerminal_Color_ForegroundBlue
;
3106 else if(args
[i
] == "--magenta")
3108 color
= cmsysTerminal_Color_ForegroundMagenta
;
3110 else if(args
[i
] == "--cyan")
3112 color
= cmsysTerminal_Color_ForegroundCyan
;
3114 else if(args
[i
] == "--white")
3116 color
= cmsysTerminal_Color_ForegroundWhite
;
3118 else if(args
[i
] == "--bold")
3120 color
|= cmsysTerminal_Color_ForegroundBold
;
3122 else if(args
[i
] == "--no-newline")
3126 else if(args
[i
] == "--newline")
3132 // Color is enabled. Print with the current color.
3133 cmSystemTools::MakefileColorEcho(color
, args
[i
].c_str(),
3141 int cmake::ExecuteEchoColor(std::vector
<std::string
>&)
3147 //----------------------------------------------------------------------------
3148 int cmake::ExecuteLinkScript(std::vector
<std::string
>& args
)
3150 // The arguments are
3151 // argv[0] == <cmake-executable>
3152 // argv[1] == cmake_link_script
3153 // argv[2] == <link-script-name>
3154 // argv[3] == --verbose=?
3155 bool verbose
= false;
3156 if(args
.size() >= 4)
3158 if(args
[3].find("--verbose=") == 0)
3160 if(!cmSystemTools::IsOff(args
[3].substr(10).c_str()))
3167 // Allocate a process instance.
3168 cmsysProcess
* cp
= cmsysProcess_New();
3171 std::cerr
<< "Error allocating process instance in link script."
3176 // Children should share stdout and stderr with this process.
3177 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDOUT
, 1);
3178 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDERR
, 1);
3180 // Run the command lines verbatim.
3181 cmsysProcess_SetOption(cp
, cmsysProcess_Option_Verbatim
, 1);
3183 // Read command lines from the script.
3184 std::ifstream
fin(args
[2].c_str());
3187 std::cerr
<< "Error opening link script \""
3188 << args
[2] << "\"" << std::endl
;
3192 // Run one command at a time.
3193 std::string command
;
3195 while(result
== 0 && cmSystemTools::GetLineFromStream(fin
, command
))
3197 // Setup this command line.
3198 const char* cmd
[2] = {command
.c_str(), 0};
3199 cmsysProcess_SetCommand(cp
, cmd
);
3201 // Report the command if verbose output is enabled.
3204 std::cout
<< command
<< std::endl
;
3207 // Run the command and wait for it to exit.
3208 cmsysProcess_Execute(cp
);
3209 cmsysProcess_WaitForExit(cp
, 0);
3211 // Report failure if any.
3212 switch(cmsysProcess_GetState(cp
))
3214 case cmsysProcess_State_Exited
:
3216 int value
= cmsysProcess_GetExitValue(cp
);
3223 case cmsysProcess_State_Exception
:
3224 std::cerr
<< "Error running link command: "
3225 << cmsysProcess_GetExceptionString(cp
) << std::endl
;
3228 case cmsysProcess_State_Error
:
3229 std::cerr
<< "Error running link command: "
3230 << cmsysProcess_GetErrorString(cp
) << std::endl
;
3238 // Free the process instance.
3239 cmsysProcess_Delete(cp
);
3241 // Return the final resulting return value.
3245 void cmake::DefineProperties(cmake
*cm
)
3248 ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL
,
3249 "If set, report any undefined properties to this file.",
3250 "If this property is set to a filename then when CMake runs "
3251 "it will report any properties or variables that were accessed "
3252 "but not defined into the filename specified in this property."
3256 ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL
,
3257 "Does the target platform support shared libraries.",
3258 "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
3259 "platform supports shared libraries. Basically all current general "
3260 "general purpose OS do so, the exception are usually embedded systems "
3261 "with no or special OSs.");
3264 ("TARGET_ARCHIVES_MAY_BE_SHARED_LIBS", cmProperty::GLOBAL
,
3265 "Set if shared libraries may be named like archives.",
3266 "On AIX shared libraries may be named \"lib<name>.a\". "
3267 "This property is set to true on such platforms.");
3270 ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL
,
3271 "Whether FIND_LIBRARY should automatically search lib64 directories.",
3272 "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
3273 "FIND_LIBRARY command should automatically search the lib64 variant of "
3274 "directories called lib in the search path when building 64-bit "
3277 ("ENABLED_FEATURES", cmProperty::GLOBAL
,
3278 "List of features which are enabled during the CMake run.",
3279 "List of features which are enabled during the CMake run. Be default "
3280 "it contains the names of all packages which were found. This is "
3281 "determined using the <NAME>_FOUND variables. Packages which are "
3282 "searched QUIET are not listed. A project can add its own features to "
3283 "this list.This property is used by the macros in FeatureSummary.cmake.");
3285 ("DISABLED_FEATURES", cmProperty::GLOBAL
,
3286 "List of features which are disabled during the CMake run.",
3287 "List of features which are disabled during the CMake run. Be default "
3288 "it contains the names of all packages which were not found. This is "
3289 "determined using the <NAME>_FOUND variables. Packages which are "
3290 "searched QUIET are not listed. A project can add its own features to "
3291 "this list.This property is used by the macros in FeatureSummary.cmake.");
3293 ("PACKAGES_FOUND", cmProperty::GLOBAL
,
3294 "List of packages which were found during the CMake run.",
3295 "List of packages which were found during the CMake run. Whether a "
3296 "package has been found is determined using the <NAME>_FOUND variables.");
3298 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3299 "List of packages which were not found during the CMake run.",
3300 "List of packages which were not found during the CMake run. Whether a "
3301 "package has been found is determined using the <NAME>_FOUND variables.");
3304 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3305 "List of packages which were not found during the CMake run.",
3306 "List of packages which were not found during the CMake run. Whether a "
3307 "package has been found is determined using the <NAME>_FOUND variables.");
3309 "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL
,
3310 "Internal property",
3311 "Used to detect compiler changes, Do not set.");
3314 "GLOBAL_DEPENDS_DEBUG_MODE", cmProperty::GLOBAL
,
3315 "Enable global target dependency graph debug mode.",
3316 "CMake automatically analyzes the global inter-target dependency graph "
3317 "at the beginning of native build system generation. "
3318 "This property causes it to display details of its analysis to stderr.");
3321 "ALLOW_DUPLICATE_CUSTOM_TARGETS", cmProperty::GLOBAL
,
3322 "Allow duplicate custom targets to be created.",
3323 "Normally CMake requires that all targets built in a project have "
3324 "globally unique names. "
3325 "This is necessary to generate meaningful project file names in "
3326 "Xcode and VS IDE generators. "
3327 "It also allows the target names to be referenced unambiguously.\n"
3328 "Makefile generators are capable of supporting duplicate custom target "
3330 "For projects that care only about Makefile generators and do "
3331 "not wish to support Xcode or VS IDE generators, one may set this "
3332 "property to true to allow duplicate custom targets. "
3333 "The property allows multiple add_custom_target command calls in "
3334 "*different directories* to specify the same target name. "
3335 "However, setting this property will cause non-Makefile generators "
3336 "to produce an error and refuse to generate the project."
3340 ("IN_TRY_COMPILE", cmProperty::GLOBAL
,
3341 "Read-only property that is true during a try-compile configuration.",
3342 "True when building a project inside a TRY_COMPILE or TRY_RUN command.");
3344 // ================================================================
3345 // define variables as well
3346 // ================================================================
3347 cmDocumentVariables::DefineVariables(cm
);
3351 void cmake::DefineProperty(const char *name
, cmProperty::ScopeType scope
,
3352 const char *ShortDescription
,
3353 const char *FullDescription
,
3354 bool chained
, const char *docSection
)
3356 this->PropertyDefinitions
[scope
].DefineProperty(name
,scope
,ShortDescription
,
3362 cmPropertyDefinition
*cmake
3363 ::GetPropertyDefinition(const char *name
,
3364 cmProperty::ScopeType scope
)
3366 if (this->IsPropertyDefined(name
,scope
))
3368 return &(this->PropertyDefinitions
[scope
][name
]);
3373 void cmake::RecordPropertyAccess(const char *name
,
3374 cmProperty::ScopeType scope
)
3376 this->AccessedProperties
.insert
3377 (std::pair
<cmStdString
,cmProperty::ScopeType
>(name
,scope
));
3380 void cmake::ReportUndefinedPropertyAccesses(const char *filename
)
3382 FILE *progFile
= fopen(filename
,"w");
3383 if (!progFile
|| !this->GlobalGenerator
)
3388 // what are the enabled languages?
3389 std::vector
<std::string
> enLangs
;
3390 this->GlobalGenerator
->GetEnabledLanguages(enLangs
);
3392 // Common configuration names.
3393 // TODO: Compute current configuration(s).
3394 std::vector
<std::string
> enConfigs
;
3395 enConfigs
.push_back("");
3396 enConfigs
.push_back("DEBUG");
3397 enConfigs
.push_back("RELEASE");
3398 enConfigs
.push_back("MINSIZEREL");
3399 enConfigs
.push_back("RELWITHDEBINFO");
3401 // take all the defined properties and add definitions for all the enabled
3403 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> > aliasedProperties
;
3404 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
3405 i
= this->PropertyDefinitions
.begin();
3406 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
3408 cmPropertyDefinitionMap::iterator j
;
3409 for (j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
3411 // TODO: What if both <LANG> and <CONFIG> appear?
3412 if (j
->first
.find("<CONFIG>") != std::string::npos
)
3414 std::vector
<std::string
>::const_iterator k
;
3415 for (k
= enConfigs
.begin(); k
!= enConfigs
.end(); ++k
)
3417 std::string tmp
= j
->first
;
3418 cmSystemTools::ReplaceString(tmp
, "<CONFIG>", k
->c_str());
3420 aliasedProperties
.insert
3421 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3424 if (j
->first
.find("<LANG>") != std::string::npos
)
3426 std::vector
<std::string
>::const_iterator k
;
3427 for (k
= enLangs
.begin(); k
!= enLangs
.end(); ++k
)
3429 std::string tmp
= j
->first
;
3430 cmSystemTools::ReplaceString(tmp
, "<LANG>", k
->c_str());
3432 aliasedProperties
.insert
3433 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3439 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> >::const_iterator ap
;
3440 ap
= this->AccessedProperties
.begin();
3441 for (;ap
!= this->AccessedProperties
.end(); ++ap
)
3443 if (!this->IsPropertyDefined(ap
->first
.c_str(),ap
->second
) &&
3444 aliasedProperties
.find(std::pair
<cmStdString
,cmProperty::ScopeType
>
3445 (ap
->first
,ap
->second
)) ==
3446 aliasedProperties
.end())
3448 const char *scopeStr
= "";
3451 case cmProperty::TARGET
:
3452 scopeStr
= "TARGET";
3454 case cmProperty::SOURCE_FILE
:
3455 scopeStr
= "SOURCE_FILE";
3457 case cmProperty::DIRECTORY
:
3458 scopeStr
= "DIRECTORY";
3460 case cmProperty::TEST
:
3463 case cmProperty::VARIABLE
:
3464 scopeStr
= "VARIABLE";
3466 case cmProperty::CACHED_VARIABLE
:
3467 scopeStr
= "CACHED_VARIABLE";
3470 scopeStr
= "unknown";
3473 fprintf(progFile
,"%s with scope %s\n",ap
->first
.c_str(),scopeStr
);
3479 bool cmake::IsPropertyDefined(const char *name
, cmProperty::ScopeType scope
)
3481 return this->PropertyDefinitions
[scope
].IsPropertyDefined(name
);
3484 bool cmake::IsPropertyChained(const char *name
, cmProperty::ScopeType scope
)
3486 return this->PropertyDefinitions
[scope
].IsPropertyChained(name
);
3489 void cmake::SetProperty(const char* prop
, const char* value
)
3500 this->Properties
.SetProperty(prop
, value
, cmProperty::GLOBAL
);
3503 void cmake::AppendProperty(const char* prop
, const char* value
)
3509 this->Properties
.AppendProperty(prop
, value
, cmProperty::GLOBAL
);
3512 const char *cmake::GetProperty(const char* prop
)
3514 return this->GetProperty(prop
, cmProperty::GLOBAL
);
3517 const char *cmake::GetProperty(const char* prop
, cmProperty::ScopeType scope
)
3521 // watch for special properties
3522 std::string propname
= prop
;
3523 std::string output
= "";
3524 if ( propname
== "CACHE_VARIABLES" )
3526 cmCacheManager::CacheIterator cit
=
3527 this->GetCacheManager()->GetCacheIterator();
3528 for ( cit
.Begin(); !cit
.IsAtEnd(); cit
.Next() )
3530 if ( output
.size() )
3534 output
+= cit
.GetName();
3536 this->SetProperty("CACHE_VARIABLES", output
.c_str());
3538 else if ( propname
== "COMMANDS" )
3540 cmake::RegisteredCommandsMap::iterator cmds
3541 = this->GetCommands()->begin();
3542 for (unsigned int cc
=0 ; cmds
!= this->GetCommands()->end(); ++ cmds
)
3548 output
+= cmds
->first
.c_str();
3551 this->SetProperty("COMMANDS",output
.c_str());
3553 else if ( propname
== "IN_TRY_COMPILE" )
3555 this->SetProperty("IN_TRY_COMPILE",
3556 this->GetIsInTryCompile()? "1":"0");
3558 return this->Properties
.GetPropertyValue(prop
, scope
, chain
);
3561 bool cmake::GetPropertyAsBool(const char* prop
)
3563 return cmSystemTools::IsOn(this->GetProperty(prop
));
3566 int cmake::GetSystemInformation(std::vector
<std::string
>& args
)
3568 // so create the directory
3569 std::string resultFile
;
3570 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
3571 std::string destPath
= cwd
+ "/__cmake_systeminformation";
3572 cmSystemTools::RemoveADirectory(destPath
.c_str());
3573 if (!cmSystemTools::MakeDirectory(destPath
.c_str()))
3575 std::cerr
<< "Error: --system-information must be run from a "
3576 "writable directory!\n";
3580 // process the arguments
3581 bool writeToStdout
= true;
3582 for(unsigned int i
=1; i
< args
.size(); ++i
)
3584 std::string arg
= args
[i
];
3585 if(arg
.find("-V",0) == 0)
3587 this->Verbose
= true;
3589 else if(arg
.find("-G",0) == 0)
3591 std::string value
= arg
.substr(2);
3592 if(value
.size() == 0)
3595 if(i
>= args
.size())
3597 cmSystemTools::Error("No generator specified for -G");
3602 cmGlobalGenerator
* gen
=
3603 this->CreateGlobalGenerator(value
.c_str());
3606 cmSystemTools::Error("Could not create named generator ",
3611 this->SetGlobalGenerator(gen
);
3614 // no option assume it is the output file
3617 if (!cmSystemTools::FileIsFullPath(arg
.c_str()))
3623 writeToStdout
= false;
3628 // we have to find the module directory, so we can copy the files
3629 this->AddCMakePaths();
3630 std::string modulesPath
=
3631 this->CacheManager
->GetCacheValue("CMAKE_ROOT");
3632 modulesPath
+= "/Modules";
3633 std::string inFile
= modulesPath
;
3634 inFile
+= "/SystemInformation.cmake";
3635 std::string outFile
= destPath
;
3636 outFile
+= "/CMakeLists.txt";
3639 if(!cmSystemTools::cmCopyFile(inFile
.c_str(), outFile
.c_str()))
3641 std::cerr
<< "Error copying file \"" << inFile
.c_str()
3642 << "\" to \"" << outFile
.c_str() << "\".\n";
3646 // do we write to a file or to stdout?
3647 if (resultFile
.size() == 0)
3650 resultFile
+= "/__cmake_systeminformation/results.txt";
3653 // now run cmake on the CMakeLists file
3654 cmSystemTools::ChangeDirectory(destPath
.c_str());
3655 std::vector
<std::string
> args2
;
3656 args2
.push_back(args
[0]);
3657 args2
.push_back(destPath
);
3658 std::string resultArg
= "-DRESULT_FILE=";
3659 resultArg
+= resultFile
;
3660 args2
.push_back(resultArg
);
3661 int res
= this->Run(args2
, false);
3665 std::cerr
<< "Error: --system-information failed on internal CMake!\n";
3669 // change back to the original directory
3670 cmSystemTools::ChangeDirectory(cwd
.c_str());
3672 // echo results to stdout if needed
3675 FILE* fin
= fopen(resultFile
.c_str(), "r");
3678 const int bufferSize
= 4096;
3679 char buffer
[bufferSize
];
3681 while((n
= fread(buffer
, 1, bufferSize
, fin
)) > 0)
3683 for(char* c
= buffer
; c
< buffer
+n
; ++c
)
3693 // clean up the directory
3694 cmSystemTools::RemoveADirectory(destPath
.c_str());
3698 //----------------------------------------------------------------------------
3699 static bool cmakeCheckStampFile(const char* stampName
)
3701 // If the stamp file still exists then it must really be out of
3703 if(cmSystemTools::FileExists(stampName
))
3708 // The stamp file does not exist. Use the stamp dependencies to
3709 // determine whether it is really out of date. This works in
3710 // conjunction with cmLocalVisualStudio7Generator to avoid
3711 // repeatedly re-running CMake when the user rebuilds the entire
3713 std::string stampDepends
= stampName
;
3714 stampDepends
+= ".depend";
3715 #if defined(_WIN32) || defined(__CYGWIN__)
3716 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
| std::ios::binary
);
3718 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
);
3722 // The stamp dependencies file cannot be read. Just assume the
3723 // build system is really out of date.
3727 // Compare the stamp dependencies against the dependency file itself.
3728 cmFileTimeComparison ftc
;
3730 while(cmSystemTools::GetLineFromStream(fin
, dep
))
3733 if(dep
.length() >= 1 && dep
[0] != '#' &&
3734 (!ftc
.FileTimeCompare(stampDepends
.c_str(), dep
.c_str(), &result
)
3737 // The stamp depends file is older than this dependency. The
3738 // build system is really out of date.
3743 // The build system is up to date. The stamp file has been removed
3744 // by the VS IDE due to a "rebuild" request. Just restore it.
3745 std::ofstream
stamp(stampName
);
3746 stamp
<< "# CMake generation timestamp file this directory.\n";
3749 // Notify the user why CMake is not re-running. It is safe to
3750 // just print to stdout here because this code is only reachable
3751 // through an undocumented flag used by the VS generator.
3752 std::cout
<< "CMake does not need to re-run because the "
3753 << "generation timestamp is up-to-date.\n";
3758 cmSystemTools::Error("Cannot restore timestamp ", stampName
);
3763 // For visual studio 2005 and newer manifest files need to be embeded into
3764 // exe and dll's. This code does that in such a way that incremental linking
3766 int cmake::VisualStudioLink(std::vector
<std::string
>& args
, int type
)
3772 bool verbose
= false;
3773 if(cmSystemTools::GetEnv("VERBOSE"))
3777 std::vector
<std::string
> expandedArgs
;
3778 for(std::vector
<std::string
>::iterator i
= args
.begin();
3779 i
!= args
.end(); ++i
)
3781 // check for nmake temporary files
3784 std::ifstream
fin(i
->substr(1).c_str());
3786 while(cmSystemTools::GetLineFromStream(fin
,
3789 cmSystemTools::ParseWindowsCommandLine(line
.c_str(), expandedArgs
);
3794 expandedArgs
.push_back(*i
);
3797 // figure out if this is an incremental link or not and run the correct
3799 for(std::vector
<std::string
>::iterator i
= expandedArgs
.begin();
3800 i
!= expandedArgs
.end(); ++i
)
3802 if(cmSystemTools::Strucmp(i
->c_str(), "/INCREMENTAL:YES") == 0)
3806 std::cout
<< "Visual Studio Incremental Link\n";
3808 return cmake::VisualStudioLinkIncremental(expandedArgs
, type
, verbose
);
3813 std::cout
<< "Visual Studio Non-Incremental Link\n";
3815 return cmake::VisualStudioLinkNonIncremental(expandedArgs
, type
, verbose
);
3818 int cmake::ParseVisualStudioLinkCommand(std::vector
<std::string
>& args
,
3819 std::vector
<cmStdString
>& command
,
3820 std::string
& targetName
)
3822 std::vector
<std::string
>::iterator i
= args
.begin();
3824 i
++; // skip vs_link_dll or vs_link_exe
3825 command
.push_back(*i
);
3826 i
++; // move past link command
3827 for(; i
!= args
.end(); ++i
)
3829 command
.push_back(*i
);
3830 if(i
->find("/Fe") == 0)
3832 targetName
= i
->substr(3);
3834 if(i
->find("/out:") == 0)
3836 targetName
= i
->substr(5);
3839 if(targetName
.size() == 0 || command
.size() == 0)
3846 bool cmake::RunCommand(const char* comment
,
3847 std::vector
<cmStdString
>& command
,
3853 std::cout
<< comment
<< ":\n";
3854 for(std::vector
<cmStdString
>::iterator i
= command
.begin();
3855 i
!= command
.end(); ++i
)
3857 std::cout
<< i
->c_str() << " ";
3863 // use rc command to create .res file
3864 cmSystemTools::RunSingleCommand(command
,
3869 std::cout
<< output
<< "\n";
3871 // if retCodeOut is requested then always return true
3872 // and set the retCodeOut to retCode
3875 *retCodeOut
= retCode
;
3880 std::cout
<< comment
<< " failed. with " << retCode
<< "\n";
3882 return retCode
== 0;
3885 int cmake::VisualStudioLinkIncremental(std::vector
<std::string
>& args
,
3886 int type
, bool verbose
)
3888 // This follows the steps listed here:
3889 // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
3891 // 1. Compiler compiles the application and generates the *.obj files.
3892 // 2. An empty manifest file is generated if this is a clean build and if
3893 // not the previous one is reused.
3894 // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
3896 // 4. Linker generates the binary (EXE or DLL) with the /incremental
3897 // switch and embeds the dummy manifest file. The linker also generates
3898 // the real manifest file based on the binaries that your binary depends
3900 // 5. The manifest tool (mt.exe) is then used to generate the final
3903 // If the final manifest is changed, then 6 and 7 are run, if not
3904 // they are skipped, and it is done.
3906 // 6. The resource compiler is invoked one more time.
3907 // 7. Finally, the Linker does another incremental link, but since the
3908 // only thing that has changed is the *.res file that contains the
3909 // manifest it is a short link.
3910 std::vector
<cmStdString
> linkCommand
;
3911 std::string targetName
;
3912 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
3916 std::string manifestArg
= "/MANIFESTFILE:";
3917 std::vector
<cmStdString
> rcCommand
;
3918 rcCommand
.push_back(cmSystemTools::FindProgram("rc.exe"));
3919 std::vector
<cmStdString
> mtCommand
;
3920 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
3921 std::string tempManifest
;
3922 tempManifest
= targetName
;
3923 tempManifest
+= ".intermediate.manifest";
3924 std::string resourceInputFile
= targetName
;
3925 resourceInputFile
+= ".resource.txt";
3928 std::cout
<< "Create " << resourceInputFile
.c_str() << "\n";
3930 // Create input file for rc command
3931 std::ofstream
fout(resourceInputFile
.c_str());
3936 std::string manifestFile
= targetName
;
3937 manifestFile
+= ".embed.manifest";
3938 std::string fullPath
= cmSystemTools::CollapseFullPath(manifestFile
.c_str());
3939 fout
<< type
<< " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
3940 "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath
.c_str() << "\"";
3942 manifestArg
+= tempManifest
;
3943 // add the manifest arg to the linkCommand
3944 linkCommand
.push_back(manifestArg
);
3945 // if manifestFile is not yet created, create an
3947 if(!cmSystemTools::FileExists(manifestFile
.c_str()))
3951 std::cout
<< "Create empty: " << manifestFile
.c_str() << "\n";
3953 std::ofstream
foutTmp(manifestFile
.c_str());
3955 std::string resourceFile
= manifestFile
;
3956 resourceFile
+= ".res";
3957 // add the resource file to the end of the link command
3958 linkCommand
.push_back(resourceFile
);
3959 std::string outputOpt
= "/fo";
3960 outputOpt
+= resourceFile
;
3961 rcCommand
.push_back(outputOpt
);
3962 rcCommand
.push_back(resourceInputFile
);
3963 // Run rc command to create resource
3964 if(!cmake::RunCommand("RC Pass 1", rcCommand
, verbose
))
3968 // Now run the link command to link and create manifest
3969 if(!cmake::RunCommand("LINK Pass 1", linkCommand
, verbose
))
3973 // create mt command
3974 std::string
outArg("/out:");
3975 outArg
+= manifestFile
;
3976 mtCommand
.push_back("/nologo");
3977 mtCommand
.push_back(outArg
);
3978 mtCommand
.push_back("/notify_update");
3979 mtCommand
.push_back("/manifest");
3980 mtCommand
.push_back(tempManifest
);
3981 // now run mt.exe to create the final manifest file
3983 cmake::RunCommand("MT", mtCommand
, verbose
, &mtRet
);
3984 // if mt returns 0, then the manifest was not changed and
3985 // we do not need to do another link step
3990 // check for magic mt return value if mt returns the magic number
3991 // 1090650113 then it means that it updated the manifest file and we need
3992 // to do the final link. If mt has any value other than 0 or 1090650113
3993 // then there was some problem with the command itself and there was an
3994 // error so return the error code back out of cmake so make can report it.
3995 if(mtRet
!= 1090650113)
3999 // update the resource file with the new manifest from the mt command.
4000 if(!cmake::RunCommand("RC Pass 2", rcCommand
, verbose
))
4004 // Run the final incremental link that will put the new manifest resource
4005 // into the file incrementally.
4006 if(!cmake::RunCommand("FINAL LINK", linkCommand
, verbose
))
4013 int cmake::VisualStudioLinkNonIncremental(std::vector
<std::string
>& args
,
4017 std::vector
<cmStdString
> linkCommand
;
4018 std::string targetName
;
4019 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
4023 // Run the link command as given
4024 if(!cmake::RunCommand("LINK", linkCommand
, verbose
))
4028 std::vector
<cmStdString
> mtCommand
;
4029 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
4030 mtCommand
.push_back("/nologo");
4031 mtCommand
.push_back("/manifest");
4032 std::string manifestFile
= targetName
;
4033 manifestFile
+= ".manifest";
4034 mtCommand
.push_back(manifestFile
);
4035 std::string outresource
= "/outputresource:";
4036 outresource
+= targetName
;
4037 outresource
+= ";#";
4046 mtCommand
.push_back(outresource
);
4047 // Now use the mt tool to embed the manifest into the exe or dll
4048 if(!cmake::RunCommand("MT", mtCommand
, verbose
))