1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmake.cxx,v $
6 Date: $Date: 2008-04-04 20:02:50 $
7 Version: $Revision: 1.382 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmDocumentVariables.h"
20 #include "cmCacheManager.h"
21 #include "cmMakefile.h"
22 #include "cmLocalGenerator.h"
23 #include "cmExternalMakefileProjectGenerator.h"
24 #include "cmCommands.h"
25 #include "cmCommand.h"
26 #include "cmFileTimeComparison.h"
27 #include "cmGeneratedFileStream.h"
28 #include "cmSourceFile.h"
29 #include "cmVersion.h"
31 #include "cmDocumentationFormatterText.h"
33 #if defined(CMAKE_BUILD_WITH_CMAKE)
34 # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
35 # include "cmVariableWatch.h"
36 # include <cmsys/Terminal.h>
39 #include <cmsys/Directory.hxx>
40 #include <cmsys/Process.h>
41 #include <cmsys/Glob.hxx>
42 #include <cmsys/RegularExpression.hxx>
44 // only build kdevelop generator on non-windows platforms
45 // when not bootstrapping cmake
47 # if defined(CMAKE_BUILD_WITH_CMAKE)
48 # define CMAKE_USE_KDEVELOP
52 #if defined(CMAKE_BUILD_WITH_CMAKE)
53 # define CMAKE_USE_ECLIPSE
56 #if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
57 # define CMAKE_BOOT_MINGW
60 // include the generator
61 #if defined(_WIN32) && !defined(__CYGWIN__)
62 # if !defined(CMAKE_BOOT_MINGW)
63 # include "cmGlobalVisualStudio6Generator.h"
64 # include "cmGlobalVisualStudio7Generator.h"
65 # include "cmGlobalVisualStudio71Generator.h"
66 # include "cmGlobalVisualStudio8Generator.h"
67 # include "cmGlobalVisualStudio9Generator.h"
68 # include "cmGlobalVisualStudio9Win64Generator.h"
69 # include "cmGlobalVisualStudio8Win64Generator.h"
70 # include "cmGlobalBorlandMakefileGenerator.h"
71 # include "cmGlobalNMakeMakefileGenerator.h"
72 # include "cmGlobalWatcomWMakeGenerator.h"
73 # define CMAKE_HAVE_VS_GENERATORS
75 # include "cmGlobalMSYSMakefileGenerator.h"
76 # include "cmGlobalMinGWMakefileGenerator.h"
77 # include "cmWin32ProcessExecution.h"
80 #include "cmGlobalUnixMakefileGenerator3.h"
82 #if defined(CMAKE_HAVE_VS_GENERATORS)
83 #include "cmCallVisualStudioMacro.h"
86 #if !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
87 # include "cmExtraCodeBlocksGenerator.h"
90 #ifdef CMAKE_USE_KDEVELOP
91 # include "cmGlobalKdevelopGenerator.h"
94 #ifdef CMAKE_USE_ECLIPSE
95 # include "cmExtraEclipseCDT4Generator.h"
98 #include <stdlib.h> // required for atoi
100 #if defined( __APPLE__ )
101 # if defined(CMAKE_BUILD_WITH_CMAKE)
102 # include "cmGlobalXCodeGenerator.h"
103 # define CMAKE_USE_XCODE 1
105 # include <sys/types.h>
106 # include <sys/time.h>
107 # include <sys/resource.h>
110 #include <sys/stat.h> // struct stat
112 #include <memory> // auto_ptr
114 static bool cmakeCheckStampFile(const char* stampName
);
115 static bool cmakeCheckStampList(const char* stampName
);
117 void cmNeedBackwardsCompatibility(const std::string
& variable
,
118 int access_type
, void*, const char*, const cmMakefile
*)
120 #ifdef CMAKE_BUILD_WITH_CMAKE
121 if (access_type
== cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS
)
123 std::string message
= "An attempt was made to access a variable: ";
126 " that has not been defined. Some variables were always defined "
127 "by CMake in versions prior to 1.6. To fix this you might need to set "
128 "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
129 "you are writing a CMakeList file, (or have already set "
130 "CMAKE_BACKWARDS_COMPATABILITY to 1.4 or less) then you probably need "
131 "to include a CMake module to test for the feature this variable "
133 cmSystemTools::Error(message
.c_str());
143 this->SuppressDevWarnings
= false;
144 this->DoSuppressDevWarnings
= false;
145 this->DebugOutput
= false;
146 this->DebugTryCompile
= false;
147 this->ClearBuildSystem
= false;
148 this->FileComparison
= new cmFileTimeComparison
;
150 this->Policies
= new cmPolicies();
151 this->InitializeProperties();
155 if(!getrlimit(RLIMIT_STACK
, &rlp
))
157 if(rlp
.rlim_cur
!= rlp
.rlim_max
)
159 rlp
.rlim_cur
= rlp
.rlim_max
;
160 setrlimit(RLIMIT_STACK
, &rlp
);
165 // If MAKEFLAGS are given in the environment, remove the environment
166 // variable. This will prevent try-compile from succeeding when it
167 // should fail (if "-i" is an option). We cannot simply test
168 // whether "-i" is given and remove it because some make programs
169 // encode the MAKEFLAGS variable in a strange way.
170 if(getenv("MAKEFLAGS"))
172 cmSystemTools::PutEnv("MAKEFLAGS=");
175 this->Verbose
= false;
176 this->InTryCompile
= false;
177 this->CacheManager
= new cmCacheManager
;
178 this->GlobalGenerator
= 0;
179 this->ProgressCallback
= 0;
180 this->ProgressCallbackClientData
= 0;
181 this->ScriptMode
= false;
183 #ifdef CMAKE_BUILD_WITH_CMAKE
184 this->VariableWatch
= new cmVariableWatch
;
185 this->VariableWatch
->AddWatch("CMAKE_WORDS_BIGENDIAN",
186 cmNeedBackwardsCompatibility
);
187 this->VariableWatch
->AddWatch("CMAKE_SIZEOF_INT",
188 cmNeedBackwardsCompatibility
);
189 this->VariableWatch
->AddWatch("CMAKE_X_LIBS",
190 cmNeedBackwardsCompatibility
);
193 this->AddDefaultGenerators();
194 this->AddDefaultExtraGenerators();
195 this->AddDefaultCommands();
197 // Make sure we can capture the build tool output.
198 cmSystemTools::EnableVSConsoleOutput();
203 delete this->CacheManager
;
204 delete this->Policies
;
205 if (this->GlobalGenerator
)
207 delete this->GlobalGenerator
;
208 this->GlobalGenerator
= 0;
210 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
211 j
!= this->Commands
.end(); ++j
)
215 #ifdef CMAKE_BUILD_WITH_CMAKE
216 delete this->VariableWatch
;
218 delete this->FileComparison
;
221 void cmake::InitializeProperties()
223 this->Properties
.clear();
224 this->Properties
.SetCMakeInstance(this);
225 this->AccessedProperties
.clear();
226 this->PropertyDefinitions
.clear();
228 // initialize properties
229 cmSourceFile::DefineProperties(this);
230 cmTarget::DefineProperties(this);
231 cmMakefile::DefineProperties(this);
232 cmTest::DefineProperties(this);
233 cmake::DefineProperties(this);
236 void cmake::CleanupCommandsAndMacros()
238 this->InitializeProperties();
239 std::vector
<cmCommand
*> commands
;
240 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
241 j
!= this->Commands
.end(); ++j
)
243 if ( !j
->second
->IsA("cmMacroHelperCommand") &&
244 !j
->second
->IsA("cmFunctionHelperCommand"))
246 commands
.push_back(j
->second
);
253 this->Commands
.erase(this->Commands
.begin(), this->Commands
.end());
254 std::vector
<cmCommand
*>::iterator it
;
255 for ( it
= commands
.begin(); it
!= commands
.end();
258 this->Commands
[cmSystemTools::LowerCase((*it
)->GetName())] = *it
;
262 bool cmake::CommandExists(const char* name
) const
264 std::string sName
= cmSystemTools::LowerCase(name
);
265 return (this->Commands
.find(sName
) != this->Commands
.end());
268 cmCommand
*cmake::GetCommand(const char *name
)
271 std::string sName
= cmSystemTools::LowerCase(name
);
272 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
273 if (pos
!= this->Commands
.end())
280 void cmake::RenameCommand(const char*oldName
, const char* newName
)
282 // if the command already exists, free the old one
283 std::string sOldName
= cmSystemTools::LowerCase(oldName
);
284 std::string sNewName
= cmSystemTools::LowerCase(newName
);
285 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sOldName
);
286 if ( pos
== this->Commands
.end() )
290 cmCommand
* cmd
= pos
->second
;
292 pos
= this->Commands
.find(sNewName
);
293 if (pos
!= this->Commands
.end())
296 this->Commands
.erase(pos
);
298 this->Commands
.insert(RegisteredCommandsMap::value_type(sNewName
, cmd
));
299 pos
= this->Commands
.find(sOldName
);
300 this->Commands
.erase(pos
);
303 void cmake::RemoveCommand(const char* name
)
305 std::string sName
= cmSystemTools::LowerCase(name
);
306 RegisteredCommandsMap::iterator pos
= this->Commands
.find(sName
);
307 if ( pos
!= this->Commands
.end() )
310 this->Commands
.erase(pos
);
314 void cmake::AddCommand(cmCommand
* wg
)
316 std::string name
= cmSystemTools::LowerCase(wg
->GetName());
317 // if the command already exists, free the old one
318 RegisteredCommandsMap::iterator pos
= this->Commands
.find(name
);
319 if (pos
!= this->Commands
.end())
322 this->Commands
.erase(pos
);
324 this->Commands
.insert( RegisteredCommandsMap::value_type(name
, wg
));
328 void cmake::RemoveUnscriptableCommands()
330 std::vector
<std::string
> unscriptableCommands
;
331 cmake::RegisteredCommandsMap
* commands
= this->GetCommands();
332 for (cmake::RegisteredCommandsMap::const_iterator pos
= commands
->begin();
333 pos
!= commands
->end();
336 if (!pos
->second
->IsScriptable())
338 unscriptableCommands
.push_back(pos
->first
);
342 for(std::vector
<std::string
>::const_iterator it
=unscriptableCommands
.begin();
343 it
!= unscriptableCommands
.end();
346 this->RemoveCommand(it
->c_str());
351 bool cmake::SetCacheArgs(const std::vector
<std::string
>& args
)
353 for(unsigned int i
=1; i
< args
.size(); ++i
)
355 std::string arg
= args
[i
];
356 if(arg
.find("-D",0) == 0)
358 std::string entry
= arg
.substr(2);
359 if(entry
.size() == 0)
368 cmSystemTools::Error("-D must be followed with VAR=VALUE.");
372 std::string var
, value
;
373 cmCacheManager::CacheEntryType type
= cmCacheManager::UNINITIALIZED
;
374 if(cmCacheManager::ParseEntry(entry
.c_str(), var
, value
, type
) ||
375 cmCacheManager::ParseEntry(entry
.c_str(), var
, value
))
377 this->CacheManager
->AddCacheEntry(var
.c_str(), value
.c_str(),
378 "No help, variable specified on the command line.", type
);
382 std::cerr
<< "Parse error in command line argument: " << arg
<< "\n"
383 << "Should be: VAR:type=value\n";
384 cmSystemTools::Error("No cmake scrpt provided.");
388 else if(arg
.find("-Wno-dev",0) == 0)
390 this->SuppressDevWarnings
= true;
391 this->DoSuppressDevWarnings
= true;
393 else if(arg
.find("-Wdev",0) == 0)
395 this->SuppressDevWarnings
= false;
396 this->DoSuppressDevWarnings
= true;
398 else if(arg
.find("-U",0) == 0)
400 std::string entryPattern
= arg
.substr(2);
401 if(entryPattern
.size() == 0)
406 entryPattern
= args
[i
];
410 cmSystemTools::Error("-U must be followed with VAR.");
414 cmsys::RegularExpression
regex(
415 cmsys::Glob::PatternToRegex(entryPattern
.c_str(), true).c_str());
416 //go through all cache entries and collect the vars which will be removed
417 std::vector
<std::string
> entriesToDelete
;
418 cmCacheManager::CacheIterator it
=
419 this->CacheManager
->GetCacheIterator();
420 for ( it
.Begin(); !it
.IsAtEnd(); it
.Next() )
422 cmCacheManager::CacheEntryType t
= it
.GetType();
423 if(t
!= cmCacheManager::STATIC
)
425 std::string entryName
= it
.GetName();
426 if (regex
.find(entryName
.c_str()))
428 entriesToDelete
.push_back(entryName
);
433 // now remove them from the cache
434 for(std::vector
<std::string
>::const_iterator currentEntry
=
435 entriesToDelete
.begin();
436 currentEntry
!= entriesToDelete
.end();
439 this->CacheManager
->RemoveCacheEntry(currentEntry
->c_str());
442 else if(arg
.find("-C",0) == 0)
444 std::string path
= arg
.substr(2);
445 if ( path
.size() == 0 )
454 cmSystemTools::Error("-C must be followed by a file name.");
458 std::cerr
<< "loading initial cache file " << path
.c_str() << "\n";
459 this->ReadListFile(path
.c_str());
461 else if(arg
.find("-P",0) == 0)
466 cmSystemTools::Error("-P must be followed by a file name.");
469 std::string path
= args
[i
];
470 if ( path
.size() == 0 )
472 cmSystemTools::Error("No cmake script provided.");
475 this->ReadListFile(path
.c_str());
481 void cmake::ReadListFile(const char *path
)
483 // if a generator was not yet created, temporarily create one
484 cmGlobalGenerator
*gg
= this->GetGlobalGenerator();
485 bool created
= false;
487 // if a generator was not specified use a generic one
490 gg
= new cmGlobalGenerator
;
491 gg
->SetCMakeInstance(this);
495 // read in the list file to fill the cache
498 std::auto_ptr
<cmLocalGenerator
> lg(gg
->CreateLocalGenerator());
499 lg
->SetGlobalGenerator(gg
);
500 lg
->GetMakefile()->SetHomeOutputDirectory
501 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
502 lg
->GetMakefile()->SetStartOutputDirectory
503 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
504 lg
->GetMakefile()->SetHomeDirectory
505 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
506 lg
->GetMakefile()->SetStartDirectory
507 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
508 if (!lg
->GetMakefile()->ReadListFile(0, path
))
510 cmSystemTools::Error("Error processing file:", path
);
514 // free generic one if generated
522 void cmake::SetArgs(const std::vector
<std::string
>& args
)
524 bool directoriesSet
= false;
525 for(unsigned int i
=1; i
< args
.size(); ++i
)
527 std::string arg
= args
[i
];
528 if(arg
.find("-H",0) == 0)
530 directoriesSet
= true;
531 std::string path
= arg
.substr(2);
532 path
= cmSystemTools::CollapseFullPath(path
.c_str());
533 cmSystemTools::ConvertToUnixSlashes(path
);
534 this->SetHomeDirectory(path
.c_str());
536 else if(arg
.find("-S",0) == 0)
538 // There is no local generate anymore. Ignore -S option.
540 else if(arg
.find("-O",0) == 0)
542 // There is no local generate anymore. Ignore -O option.
544 else if(arg
.find("-B",0) == 0)
546 directoriesSet
= true;
547 std::string path
= arg
.substr(2);
548 path
= cmSystemTools::CollapseFullPath(path
.c_str());
549 cmSystemTools::ConvertToUnixSlashes(path
);
550 this->SetHomeOutputDirectory(path
.c_str());
552 else if((i
< args
.size()-1) && (arg
.find("--check-build-system",0) == 0))
554 this->CheckBuildSystemArgument
= args
[++i
];
555 this->ClearBuildSystem
= (atoi(args
[++i
].c_str()) > 0);
557 else if((i
< args
.size()-1) && (arg
.find("--check-stamp-file",0) == 0))
559 this->CheckStampFile
= args
[++i
];
561 else if((i
< args
.size()-1) && (arg
.find("--check-stamp-list",0) == 0))
563 this->CheckStampList
= args
[++i
];
565 #if defined(CMAKE_HAVE_VS_GENERATORS)
566 else if((i
< args
.size()-1) && (arg
.find("--vs-solution-file",0) == 0))
568 this->VSSolutionFile
= args
[++i
];
571 else if(arg
.find("-V",0) == 0)
573 this->Verbose
= true;
575 else if(arg
.find("-D",0) == 0)
579 else if(arg
.find("-U",0) == 0)
583 else if(arg
.find("-C",0) == 0)
587 else if(arg
.find("-P",0) == 0)
592 else if(arg
.find("-Wno-dev",0) == 0)
597 else if(arg
.find("-Wdev",0) == 0)
602 else if(arg
.find("--graphviz=",0) == 0)
604 std::string path
= arg
.substr(strlen("--graphviz="));
605 path
= cmSystemTools::CollapseFullPath(path
.c_str());
606 cmSystemTools::ConvertToUnixSlashes(path
);
607 this->GraphVizFile
= path
;
608 if ( this->GraphVizFile
.empty() )
610 cmSystemTools::Error("No file specified for --graphviz");
613 else if(arg
.find("--debug-trycompile",0) == 0)
615 std::cout
<< "debug trycompile on\n";
616 this->DebugTryCompileOn();
618 else if(arg
.find("--debug-output",0) == 0)
620 std::cout
<< "Running with debug output on.\n";
621 this->SetDebugOutputOn(true);
623 else if(arg
.find("-G",0) == 0)
625 std::string value
= arg
.substr(2);
626 if(value
.size() == 0)
631 cmSystemTools::Error("No generator specified for -G");
636 cmGlobalGenerator
* gen
=
637 this->CreateGlobalGenerator(value
.c_str());
640 cmSystemTools::Error("Could not create named generator ",
645 this->SetGlobalGenerator(gen
);
648 // no option assume it is the path to the source
651 directoriesSet
= true;
652 this->SetDirectoriesFromFile(arg
.c_str());
657 this->SetHomeOutputDirectory
658 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
659 this->SetStartOutputDirectory
660 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
661 this->SetHomeDirectory
662 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
663 this->SetStartDirectory
664 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
667 this->SetStartDirectory(this->GetHomeDirectory());
668 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
671 //----------------------------------------------------------------------------
672 void cmake::SetDirectoriesFromFile(const char* arg
)
674 // Check if the argument refers to a CMakeCache.txt or
675 // CMakeLists.txt file.
676 std::string listPath
;
677 std::string cachePath
;
678 bool argIsFile
= false;
679 if(cmSystemTools::FileIsDirectory(arg
))
681 std::string path
= cmSystemTools::CollapseFullPath(arg
);
682 cmSystemTools::ConvertToUnixSlashes(path
);
683 std::string cacheFile
= path
;
684 cacheFile
+= "/CMakeCache.txt";
685 std::string listFile
= path
;
686 listFile
+= "/CMakeLists.txt";
687 if(cmSystemTools::FileExists(cacheFile
.c_str()))
691 if(cmSystemTools::FileExists(listFile
.c_str()))
696 else if(cmSystemTools::FileExists(arg
))
699 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
700 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
701 name
= cmSystemTools::LowerCase(name
);
702 if(name
== "cmakecache.txt")
704 cachePath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
706 else if(name
== "cmakelists.txt")
708 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
713 // Specified file or directory does not exist. Try to set things
714 // up to produce a meaningful error message.
715 std::string fullPath
= cmSystemTools::CollapseFullPath(arg
);
716 std::string name
= cmSystemTools::GetFilenameName(fullPath
.c_str());
717 name
= cmSystemTools::LowerCase(name
);
718 if(name
== "cmakecache.txt" || name
== "cmakelists.txt")
721 listPath
= cmSystemTools::GetFilenamePath(fullPath
.c_str());
729 // If there is a CMakeCache.txt file, use its settings.
730 if(cachePath
.length() > 0)
732 cmCacheManager
* cachem
= this->GetCacheManager();
733 cmCacheManager::CacheIterator it
= cachem
->NewIterator();
734 if(cachem
->LoadCache(cachePath
.c_str()) &&
735 it
.Find("CMAKE_HOME_DIRECTORY"))
737 this->SetHomeOutputDirectory(cachePath
.c_str());
738 this->SetStartOutputDirectory(cachePath
.c_str());
739 this->SetHomeDirectory(it
.GetValue());
740 this->SetStartDirectory(it
.GetValue());
745 // If there is a CMakeLists.txt file, use it as the source tree.
746 if(listPath
.length() > 0)
748 this->SetHomeDirectory(listPath
.c_str());
749 this->SetStartDirectory(listPath
.c_str());
753 // Source CMakeLists.txt file given. It was probably dropped
754 // onto the executable in a GUI. Default to an in-source build.
755 this->SetHomeOutputDirectory(listPath
.c_str());
756 this->SetStartOutputDirectory(listPath
.c_str());
760 // Source directory given on command line. Use current working
761 // directory as build tree.
762 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
763 this->SetHomeOutputDirectory(cwd
.c_str());
764 this->SetStartOutputDirectory(cwd
.c_str());
769 // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
770 // argument. Assume it is the path to the source tree, and use the
771 // current working directory as the build tree.
772 std::string full
= cmSystemTools::CollapseFullPath(arg
);
773 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
774 this->SetHomeDirectory(full
.c_str());
775 this->SetStartDirectory(full
.c_str());
776 this->SetHomeOutputDirectory(cwd
.c_str());
777 this->SetStartOutputDirectory(cwd
.c_str());
780 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
782 int cmake::AddCMakePaths()
784 // Find the cmake executable
785 std::string cMakeSelf
= cmSystemTools::GetExecutableDirectory();
786 cMakeSelf
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
787 cMakeSelf
+= "/cmake";
788 cMakeSelf
+= cmSystemTools::GetExecutableExtension();
790 // on the apple this might be the gui bundle
791 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
793 cMakeSelf
= cmSystemTools::GetExecutableDirectory();
794 cMakeSelf
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
795 cMakeSelf
+= "../../../..";
796 cMakeSelf
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
797 cMakeSelf
= cmSystemTools::CollapseFullPath(cMakeSelf
.c_str());
798 cMakeSelf
+= "/cmake";
799 std::cerr
<< cMakeSelf
.c_str() << "\n";
802 if(!cmSystemTools::FileExists(cMakeSelf
.c_str()))
804 cmSystemTools::Error("CMake executable cannot be found at ",
808 // Save the value in the cache
809 this->CacheManager
->AddCacheEntry
810 ("CMAKE_COMMAND",cMakeSelf
.c_str(), "Path to CMake executable.",
811 cmCacheManager::INTERNAL
);
812 // if the edit command is not yet in the cache,
813 // or if CMakeEditCommand has been set on this object,
814 // then set the CMAKE_EDIT_COMMAND in the cache
815 // This will mean that the last gui to edit the cache
816 // will be the one that make edit_cache uses.
817 if(!this->GetCacheDefinition("CMAKE_EDIT_COMMAND")
818 || !this->CMakeEditCommand
.empty())
820 // Find and save the command to edit the cache
821 std::string editCacheCommand
;
822 if(!this->CMakeEditCommand
.empty())
824 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
)
826 + this->CMakeEditCommand
827 + cmSystemTools::GetFilenameExtension(cMakeSelf
);
829 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
831 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
832 "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
834 if( !cmSystemTools::FileExists(editCacheCommand
.c_str()))
836 editCacheCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
837 "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
839 if(cmSystemTools::FileExists(editCacheCommand
.c_str()))
841 this->CacheManager
->AddCacheEntry
842 ("CMAKE_EDIT_COMMAND", editCacheCommand
.c_str(),
843 "Path to cache edit program executable.", cmCacheManager::INTERNAL
);
846 std::string ctestCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
847 "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
848 if(cmSystemTools::FileExists(ctestCommand
.c_str()))
850 this->CacheManager
->AddCacheEntry
851 ("CMAKE_CTEST_COMMAND", ctestCommand
.c_str(),
852 "Path to ctest program executable.", cmCacheManager::INTERNAL
);
854 std::string cpackCommand
= cmSystemTools::GetFilenamePath(cMakeSelf
) +
855 "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf
);
856 if(cmSystemTools::FileExists(ctestCommand
.c_str()))
858 this->CacheManager
->AddCacheEntry
859 ("CMAKE_CPACK_COMMAND", cpackCommand
.c_str(),
860 "Path to cpack program executable.", cmCacheManager::INTERNAL
);
863 // do CMAKE_ROOT, look for the environment variable first
864 std::string cMakeRoot
;
866 if (getenv("CMAKE_ROOT"))
868 cMakeRoot
= getenv("CMAKE_ROOT");
869 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
871 if(!cmSystemTools::FileExists(modules
.c_str()))
874 cMakeRoot
= cmSystemTools::GetRealPath(cMakeSelf
.c_str());
875 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeRoot
.c_str());
876 std::string::size_type slashPos
= cMakeRoot
.rfind("/");
877 if(slashPos
!= std::string::npos
)
879 cMakeRoot
= cMakeRoot
.substr(0, slashPos
);
881 // is there no Modules direcory there?
882 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
885 if (!cmSystemTools::FileExists(modules
.c_str()))
887 // try exe/../share/cmake
888 cMakeRoot
+= CMAKE_DATA_DIR
;
889 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
891 #ifdef CMAKE_ROOT_DIR
892 if (!cmSystemTools::FileExists(modules
.c_str()))
894 // try compiled in root directory
895 cMakeRoot
= CMAKE_ROOT_DIR
;
896 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
899 if (!cmSystemTools::FileExists(modules
.c_str()))
902 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
903 cMakeRoot
+= CMAKE_DATA_DIR
;
904 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
906 if(!cmSystemTools::FileExists(modules
.c_str()))
909 cMakeRoot
= cmSystemTools::GetProgramPath(cMakeSelf
.c_str());
910 // is there no Modules direcory there?
911 modules
= cMakeRoot
+ "/Modules/CMake.cmake";
913 if (!cmSystemTools::FileExists(modules
.c_str()))
915 // couldn't find modules
916 cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n"
917 "CMake has most likely not been installed correctly.\n"
918 "Modules directory not found in\n",
922 this->CacheManager
->AddCacheEntry
923 ("CMAKE_ROOT", cMakeRoot
.c_str(),
924 "Path to CMake installation.", cmCacheManager::INTERNAL
);
927 std::string comspec
= "cmw9xcom.exe";
928 cmSystemTools::SetWindows9xComspecSubstitute(comspec
.c_str());
935 void CMakeCommandUsage(const char* program
)
937 cmOStringStream errorStream
;
939 #ifdef CMAKE_BUILD_WITH_CMAKE
941 << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
944 << "cmake bootstrap\n";
948 << "Usage: " << program
<< " -E [command] [arguments ...]\n"
949 << "Available commands: \n"
950 << " chdir dir cmd [args]... - run command in a given directory\n"
951 << " copy file destination - copy file to destination (either file "
953 << " copy_if_different in-file out-file - copy file if input has "
955 << " copy_directory source destination - copy directory 'source' "
956 "content to directory 'destination'\n"
957 << " compare_files file1 file2 - check if file1 is same as file2\n"
958 << " echo [string]... - displays arguments as text\n"
959 << " echo_append [string]... - displays arguments as text but no new "
961 << " environment - display the current enviroment\n"
962 << " make_directory dir - create a directory\n"
963 << " md5sum file1 [...] - compute md5sum of files\n"
964 << " remove_directory dir - remove a directory and its contents\n"
965 << " remove [-f] file1 file2 ... - remove the file(s), use -f to force "
967 << " tar [cxt][vfz] file.tar file/dir1 file/dir2 ... - create a tar "
969 << " time command [args] ... - run command and return elapsed time\n"
970 << " touch file - touch a file.\n"
971 << " touch_nocreate file - touch a file but do not create it.\n"
972 #if defined(_WIN32) && !defined(__CYGWIN__)
973 << " write_regv key value - write registry value\n"
974 << " delete_regv key - delete registry value\n"
975 << " comspec - on windows 9x use this for RunCommand\n"
977 << " create_symlink old new - create a symbolic link new -> old\n"
981 cmSystemTools::Error(errorStream
.str().c_str());
984 int cmake::ExecuteCMakeCommand(std::vector
<std::string
>& args
)
989 if (args
[1] == "copy" && args
.size() == 4)
991 if(!cmSystemTools::cmCopyFile(args
[2].c_str(), args
[3].c_str()))
993 std::cerr
<< "Error copying file \"" << args
[2].c_str()
994 << "\" to \"" << args
[3].c_str() << "\".\n";
1000 // Copy file if different.
1001 if (args
[1] == "copy_if_different" && args
.size() == 4)
1003 if(!cmSystemTools::CopyFileIfDifferent(args
[2].c_str(),
1006 std::cerr
<< "Error copying file (if different) from \""
1007 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
1014 // Copy directory content
1015 if (args
[1] == "copy_directory" && args
.size() == 4)
1017 if(!cmSystemTools::CopyADirectory(args
[2].c_str(), args
[3].c_str()))
1019 std::cerr
<< "Error copying directory from \""
1020 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
1028 if (args
[1] == "compare_files" && args
.size() == 4)
1030 if(cmSystemTools::FilesDiffer(args
[2].c_str(), args
[3].c_str()))
1032 std::cerr
<< "Files \""
1033 << args
[2].c_str() << "\" to \"" << args
[3].c_str()
1034 << "\" are different.\n";
1041 else if (args
[1] == "echo" )
1044 const char* space
= "";
1045 for ( cc
= 2; cc
< args
.size(); cc
++ )
1047 std::cout
<< space
<< args
[cc
];
1050 std::cout
<< std::endl
;
1054 // Echo string no new line
1055 else if (args
[1] == "echo_append" )
1058 const char* space
= "";
1059 for ( cc
= 2; cc
< args
.size(); cc
++ )
1061 std::cout
<< space
<< args
[cc
];
1067 #if defined(CMAKE_BUILD_WITH_CMAKE)
1068 // Command to create a symbolic link. Fails on platforms not
1070 else if (args
[1] == "environment" )
1072 std::vector
<std::string
> env
= cmSystemTools::GetEnvironmentVariables();
1073 std::vector
<std::string
>::iterator it
;
1074 for ( it
= env
.begin(); it
!= env
.end(); ++ it
)
1076 std::cout
<< it
->c_str() << std::endl
;
1082 else if (args
[1] == "make_directory" && args
.size() == 3)
1084 if(!cmSystemTools::MakeDirectory(args
[2].c_str()))
1086 std::cerr
<< "Error making directory \"" << args
[2].c_str()
1093 else if (args
[1] == "remove_directory" && args
.size() == 3)
1095 if(cmSystemTools::FileIsDirectory(args
[2].c_str()) &&
1096 !cmSystemTools::RemoveADirectory(args
[2].c_str()))
1098 std::cerr
<< "Error removing directory \"" << args
[2].c_str()
1106 else if (args
[1] == "remove" && args
.size() > 2)
1109 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1111 if(args
[cc
] == "\\-f" || args
[cc
] == "-f")
1117 // Complain if the file could not be removed, still exists,
1118 // and the -f option was not given.
1119 if(!cmSystemTools::RemoveFile(args
[cc
].c_str()) && !force
&&
1120 cmSystemTools::FileExists(args
[cc
].c_str()))
1129 else if (args
[1] == "touch" && args
.size() > 2)
1131 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1133 // Complain if the file could not be removed, still exists,
1134 // and the -f option was not given.
1135 if(!cmSystemTools::Touch(args
[cc
].c_str(), true))
1143 else if (args
[1] == "touch_nocreate" && args
.size() > 2)
1145 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1147 // Complain if the file could not be removed, still exists,
1148 // and the -f option was not given.
1149 if(!cmSystemTools::Touch(args
[cc
].c_str(), false))
1158 else if (args
[1] == "time" && args
.size() > 2)
1160 std::string command
= args
[2];
1161 for (std::string::size_type cc
= 3; cc
< args
.size(); cc
++)
1164 command
+= args
[cc
];
1167 clock_t clock_start
, clock_finish
;
1168 time_t time_start
, time_finish
;
1171 clock_start
= clock();
1173 cmSystemTools::RunSingleCommand(command
.c_str());
1175 clock_finish
= clock();
1178 double clocks_per_sec
= static_cast<double>(CLOCKS_PER_SEC
);
1179 std::cout
<< "Elapsed time: "
1180 << static_cast<long>(time_finish
- time_start
) << " s. (time)"
1182 << static_cast<double>(clock_finish
- clock_start
) / clocks_per_sec
1188 // Command to calculate the md5sum of a file
1189 else if (args
[1] == "md5sum" && args
.size() >= 3)
1193 for (std::string::size_type cc
= 2; cc
< args
.size(); cc
++)
1195 const char *filename
= args
[cc
].c_str();
1196 // Cannot compute md5sum of a directory
1197 if(cmSystemTools::FileIsDirectory(filename
))
1199 std::cerr
<< "Error: " << filename
<< " is a directory" << std::endl
;
1202 else if(!cmSystemTools::ComputeFileMD5(filename
, md5out
))
1204 // To mimic md5sum behavior in a shell:
1205 std::cerr
<< filename
<< ": No such file or directory" << std::endl
;
1210 std::cout
<< std::string(md5out
,32) << " " << filename
<< std::endl
;
1216 // Command to change directory and run a program.
1217 else if (args
[1] == "chdir" && args
.size() >= 4)
1219 std::string directory
= args
[2];
1220 if(!cmSystemTools::FileExists(directory
.c_str()))
1222 cmSystemTools::Error("Directory does not exist for chdir command: ",
1227 std::string command
= "\"";
1230 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1233 command
+= args
[cc
];
1238 if ( cmSystemTools::RunSingleCommand(command
.c_str(), 0, &retval
,
1239 directory
.c_str(), true, timeout
) )
1247 // Command to start progress for a build
1248 else if (args
[1] == "cmake_progress_start" && args
.size() == 4)
1250 // bascially remove the directory
1251 std::string dirName
= args
[2];
1252 dirName
+= "/Progress";
1253 cmSystemTools::RemoveADirectory(dirName
.c_str());
1255 // is the last argument a filename that exists?
1256 FILE *countFile
= fopen(args
[3].c_str(),"r");
1260 fscanf(countFile
,"%i",&count
);
1265 count
= atoi(args
[3].c_str());
1269 cmSystemTools::MakeDirectory(dirName
.c_str());
1270 // write the count into the directory
1271 std::string fName
= dirName
;
1272 fName
+= "/count.txt";
1273 FILE *progFile
= fopen(fName
.c_str(),"w");
1276 fprintf(progFile
,"%i\n",count
);
1283 // Command to report progress for a build
1284 else if (args
[1] == "cmake_progress_report" && args
.size() >= 3)
1286 std::string dirName
= args
[2];
1287 dirName
+= "/Progress";
1293 fName
+= "/count.txt";
1294 progFile
= fopen(fName
.c_str(),"r");
1302 fscanf(progFile
,"%i",&count
);
1306 for (i
= 3; i
< args
.size(); ++i
)
1311 progFile
= fopen(fName
.c_str(),"w");
1314 fprintf(progFile
,"empty");
1318 int fileNum
= static_cast<int>
1319 (cmsys::Directory::GetNumberOfFilesInDirectory(dirName
.c_str()));
1322 // print the progress
1323 fprintf(stdout
,"[%3i%%] ",((fileNum
-3)*100)/count
);
1328 // Command to create a symbolic link. Fails on platforms not
1330 else if (args
[1] == "create_symlink" && args
.size() == 4)
1332 const char* destinationFileName
= args
[3].c_str();
1333 if ( cmSystemTools::FileExists(destinationFileName
) )
1335 if ( cmSystemTools::FileIsSymlink(destinationFileName
) )
1337 if ( !cmSystemTools::RemoveFile(destinationFileName
) ||
1338 cmSystemTools::FileExists(destinationFileName
) )
1348 return cmSystemTools::CreateSymlink(args
[2].c_str(),
1349 args
[3].c_str())? 0:1;
1352 // Internal CMake shared library support.
1353 else if (args
[1] == "cmake_symlink_library" && args
.size() == 5)
1356 std::string realName
= args
[2];
1357 std::string soName
= args
[3];
1358 std::string name
= args
[4];
1359 if(soName
!= realName
)
1361 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1362 if(cmSystemTools::FileExists(soName
.c_str()))
1364 cmSystemTools::RemoveFile(soName
.c_str());
1366 if(!cmSystemTools::CreateSymlink(fname
.c_str(), soName
.c_str()))
1373 std::string fname
= cmSystemTools::GetFilenameName(soName
);
1374 if(cmSystemTools::FileExists(soName
.c_str()))
1376 cmSystemTools::RemoveFile(name
.c_str());
1378 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1385 // Internal CMake versioned executable support.
1386 else if (args
[1] == "cmake_symlink_executable" && args
.size() == 4)
1389 std::string realName
= args
[2];
1390 std::string name
= args
[3];
1391 if(name
!= realName
)
1393 std::string fname
= cmSystemTools::GetFilenameName(realName
);
1394 if(cmSystemTools::FileExists(realName
.c_str()))
1396 cmSystemTools::RemoveFile(name
.c_str());
1398 if(!cmSystemTools::CreateSymlink(fname
.c_str(), name
.c_str()))
1406 #if defined(CMAKE_HAVE_VS_GENERATORS)
1407 // Internal CMake support for calling Visual Studio macros.
1408 else if (args
[1] == "cmake_call_visual_studio_macro" && args
.size() >= 4)
1410 // args[2] = full path to .sln file or "ALL"
1411 // args[3] = name of Visual Studio macro to call
1412 // args[4..args.size()-1] = [optional] args for Visual Studio macro
1414 std::string macroArgs
;
1416 if (args
.size() > 4)
1418 macroArgs
= args
[4];
1420 for (size_t i
= 5; i
< args
.size(); ++i
)
1423 macroArgs
+= args
[i
];
1427 return cmCallVisualStudioMacro::CallMacro(args
[2], args
[3], macroArgs
);
1431 // Internal CMake dependency scanning support.
1432 else if (args
[1] == "cmake_depends" && args
.size() >= 6)
1434 // Use the make system's VERBOSE environment variable to enable
1436 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
1438 // Create a cmake object instance to process dependencies.
1441 std::string homeDir
;
1442 std::string startDir
;
1443 std::string homeOutDir
;
1444 std::string startOutDir
;
1445 std::string depInfo
;
1447 if(args
.size() >= 8)
1451 // -E cmake_depends <generator>
1452 // <home-src-dir> <start-src-dir>
1453 // <home-out-dir> <start-out-dir>
1454 // <dep-info> [--color=$(COLOR)]
1456 // All paths are provided.
1460 homeOutDir
= args
[5];
1461 startOutDir
= args
[6];
1463 if(args
.size() >= 9 &&
1464 args
[8].length() > 8 &&
1465 args
[8].substr(0, 8) == "--color=")
1467 // Enable or disable color based on the switch value.
1468 color
= cmSystemTools::IsOn(args
[8].substr(8).c_str());
1473 // Support older signature for existing makefiles:
1475 // -E cmake_depends <generator>
1476 // <home-out-dir> <start-out-dir>
1479 // Just pretend the source directories are the same as the
1480 // binary directories so at least scanning will work.
1484 homeOutDir
= args
[3];
1485 startOutDir
= args
[3];
1489 // Create a local generator configured for the directory in
1490 // which dependencies will be scanned.
1491 homeDir
= cmSystemTools::CollapseFullPath(homeDir
.c_str());
1492 startDir
= cmSystemTools::CollapseFullPath(startDir
.c_str());
1493 homeOutDir
= cmSystemTools::CollapseFullPath(homeOutDir
.c_str());
1494 startOutDir
= cmSystemTools::CollapseFullPath(startOutDir
.c_str());
1495 cm
.SetHomeDirectory(homeDir
.c_str());
1496 cm
.SetStartDirectory(startDir
.c_str());
1497 cm
.SetHomeOutputDirectory(homeOutDir
.c_str());
1498 cm
.SetStartOutputDirectory(startOutDir
.c_str());
1499 if(cmGlobalGenerator
* ggd
= cm
.CreateGlobalGenerator(gen
.c_str()))
1501 cm
.SetGlobalGenerator(ggd
);
1502 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
1503 lgd
->SetGlobalGenerator(ggd
);
1504 lgd
->GetMakefile()->SetStartDirectory(startDir
.c_str());
1505 lgd
->GetMakefile()->SetStartOutputDirectory(startOutDir
.c_str());
1506 lgd
->GetMakefile()->MakeStartDirectoriesCurrent();
1508 // Actually scan dependencies.
1509 return lgd
->UpdateDependencies(depInfo
.c_str(),
1510 verbose
, color
)? 0 : 2;
1515 // Internal CMake link script support.
1516 else if (args
[1] == "cmake_link_script" && args
.size() >= 3)
1518 return cmake::ExecuteLinkScript(args
);
1521 // Internal CMake unimplemented feature notification.
1522 else if (args
[1] == "cmake_unimplemented_variable")
1524 std::cerr
<< "Feature not implemented for this platform.";
1525 if(args
.size() == 3)
1527 std::cerr
<< " Variable " << args
[2] << " is not set.";
1529 std::cerr
<< std::endl
;
1532 else if (args
[1] == "vs_link_exe")
1534 return cmake::VisualStudioLink(args
, 1);
1536 else if (args
[1] == "vs_link_dll")
1538 return cmake::VisualStudioLink(args
, 2);
1540 #ifdef CMAKE_BUILD_WITH_CMAKE
1541 // Internal CMake color makefile support.
1542 else if (args
[1] == "cmake_echo_color")
1544 return cmake::ExecuteEchoColor(args
);
1549 else if (args
[1] == "tar" && args
.size() > 3)
1551 std::string flags
= args
[2];
1552 std::string outFile
= args
[3];
1553 std::vector
<cmStdString
> files
;
1554 for (std::string::size_type cc
= 4; cc
< args
.size(); cc
++)
1556 files
.push_back(args
[cc
]);
1559 bool verbose
= false;
1560 if ( flags
.find_first_of('z') != flags
.npos
)
1564 if ( flags
.find_first_of('v') != flags
.npos
)
1569 if ( flags
.find_first_of('t') != flags
.npos
)
1571 if ( !cmSystemTools::ListTar(outFile
.c_str(), files
, gzip
, verbose
) )
1573 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1577 else if ( flags
.find_first_of('c') != flags
.npos
)
1579 if ( !cmSystemTools::CreateTar(
1580 outFile
.c_str(), files
, gzip
, verbose
) )
1582 cmSystemTools::Error("Problem creating tar: ", outFile
.c_str());
1586 else if ( flags
.find_first_of('x') != flags
.npos
)
1588 if ( !cmSystemTools::ExtractTar(
1589 outFile
.c_str(), files
, gzip
, verbose
) )
1591 cmSystemTools::Error("Problem extracting tar: ", outFile
.c_str());
1598 #if defined(CMAKE_BUILD_WITH_CMAKE)
1599 // Internal CMake Fortran module support.
1600 else if (args
[1] == "cmake_copy_f90_mod" && args
.size() >= 4)
1602 return cmDependsFortran::CopyModule(args
)? 0 : 1;
1606 #if defined(_WIN32) && !defined(__CYGWIN__)
1607 // Write registry value
1608 else if (args
[1] == "write_regv" && args
.size() > 3)
1610 return cmSystemTools::WriteRegistryValue(args
[2].c_str(),
1611 args
[3].c_str()) ? 0 : 1;
1614 // Delete registry value
1615 else if (args
[1] == "delete_regv" && args
.size() > 2)
1617 return cmSystemTools::DeleteRegistryValue(args
[2].c_str()) ? 0 : 1;
1620 else if (args
[1] == "comspec" && args
.size() > 2)
1623 std::string command
= args
[2];
1624 for ( cc
= 3; cc
< args
.size(); cc
++ )
1626 command
+= " " + args
[cc
];
1628 return cmWin32ProcessExecution::Windows9xHack(command
.c_str());
1633 ::CMakeCommandUsage(args
[0].c_str());
1637 void cmake::AddExtraGenerator(const char* name
,
1638 CreateExtraGeneratorFunctionType newFunction
)
1640 cmExternalMakefileProjectGenerator
* extraGenerator
= newFunction();
1641 const std::vector
<std::string
>& supportedGlobalGenerators
=
1642 extraGenerator
->GetSupportedGlobalGenerators();
1644 for(std::vector
<std::string
>::const_iterator
1645 it
= supportedGlobalGenerators
.begin();
1646 it
!= supportedGlobalGenerators
.end();
1649 std::string fullName
= cmExternalMakefileProjectGenerator::
1650 CreateFullGeneratorName(it
->c_str(), name
);
1651 this->ExtraGenerators
[fullName
.c_str()] = newFunction
;
1653 delete extraGenerator
;
1656 void cmake::AddDefaultExtraGenerators()
1658 #if defined(CMAKE_BUILD_WITH_CMAKE)
1659 #if defined(_WIN32) && !defined(__CYGWIN__)
1663 #if !defined(__CYGWIN__)
1664 this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
1665 &cmExtraCodeBlocksGenerator::New
);
1668 #ifdef CMAKE_USE_ECLIPSE
1669 this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
1670 &cmExtraEclipseCDT4Generator::New
);
1673 #ifdef CMAKE_USE_KDEVELOP
1674 this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
1675 &cmGlobalKdevelopGenerator::New
);
1676 // for kdevelop also add the generator with just the name of the
1677 // extra generator, since it was this way since cmake 2.2
1678 this->ExtraGenerators
[cmGlobalKdevelopGenerator::GetActualName()]
1679 = &cmGlobalKdevelopGenerator::New
;
1686 //----------------------------------------------------------------------------
1687 void cmake::GetRegisteredGenerators(std::vector
<std::string
>& names
)
1689 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
1690 i
!= this->Generators
.end(); ++i
)
1692 names
.push_back(i
->first
);
1694 for(RegisteredExtraGeneratorsMap::const_iterator
1695 i
= this->ExtraGenerators
.begin();
1696 i
!= this->ExtraGenerators
.end(); ++i
)
1698 names
.push_back(i
->first
);
1702 cmGlobalGenerator
* cmake::CreateGlobalGenerator(const char* name
)
1704 cmGlobalGenerator
* generator
= 0;
1705 cmExternalMakefileProjectGenerator
* extraGenerator
= 0;
1706 RegisteredGeneratorsMap::const_iterator genIt
= this->Generators
.find(name
);
1707 if(genIt
== this->Generators
.end())
1709 RegisteredExtraGeneratorsMap::const_iterator extraGenIt
=
1710 this->ExtraGenerators
.find(name
);
1711 if (extraGenIt
== this->ExtraGenerators
.end())
1715 extraGenerator
= (extraGenIt
->second
)();
1716 genIt
=this->Generators
.find(extraGenerator
->GetGlobalGeneratorName(name
));
1717 if(genIt
== this->Generators
.end())
1719 delete extraGenerator
;
1724 generator
= (genIt
->second
)();
1725 generator
->SetCMakeInstance(this);
1726 generator
->SetExternalMakefileProjectGenerator(extraGenerator
);
1730 void cmake::SetHomeDirectory(const char* dir
)
1732 this->cmHomeDirectory
= dir
;
1733 cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory
);
1736 void cmake::SetHomeOutputDirectory(const char* lib
)
1738 this->HomeOutputDirectory
= lib
;
1739 cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory
);
1742 void cmake::SetGlobalGenerator(cmGlobalGenerator
*gg
)
1746 cmSystemTools::Error("Error SetGlobalGenerator called with null");
1749 // delete the old generator
1750 if (this->GlobalGenerator
)
1752 delete this->GlobalGenerator
;
1753 // restore the original environment variables CXX and CC
1755 std::string env
= "CC=";
1756 if(this->CCEnvironment
.size())
1758 env
+= this->CCEnvironment
;
1760 cmSystemTools::PutEnv(env
.c_str());
1762 if(this->CXXEnvironment
.size())
1764 env
+= this->CXXEnvironment
;
1766 cmSystemTools::PutEnv(env
.c_str());
1770 this->GlobalGenerator
= gg
;
1772 // set the global flag for unix style paths on cmSystemTools as soon as
1773 // the generator is set. This allows gmake to be used on windows.
1774 cmSystemTools::SetForceUnixPaths
1775 (this->GlobalGenerator
->GetForceUnixPaths());
1777 // Save the environment variables CXX and CC
1778 const char* cxx
= getenv("CXX");
1779 const char* cc
= getenv("CC");
1782 this->CXXEnvironment
= cxx
;
1786 this->CXXEnvironment
= "";
1790 this->CCEnvironment
= cc
;
1794 this->CCEnvironment
= "";
1796 // set the cmake instance just to be sure
1797 gg
->SetCMakeInstance(this);
1800 int cmake::DoPreConfigureChecks()
1802 // Make sure the Start directory contains a CMakeLists.txt file.
1803 std::string srcList
= this->GetHomeDirectory();
1804 srcList
+= "/CMakeLists.txt";
1805 if(!cmSystemTools::FileExists(srcList
.c_str()))
1807 cmOStringStream err
;
1808 if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
1810 err
<< "The source directory \"" << this->GetHomeDirectory()
1811 << "\" does not appear to contain CMakeLists.txt.\n";
1813 else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
1815 err
<< "The source directory \"" << this->GetHomeDirectory()
1816 << "\" is a file, not a directory.\n";
1820 err
<< "The source directory \"" << this->GetHomeDirectory()
1821 << "\" does not exist.\n";
1823 err
<< "Specify --help for usage, or press the help button on the CMake "
1825 cmSystemTools::Error(err
.str().c_str());
1829 // do a sanity check on some values
1830 if(this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY"))
1832 std::string cacheStart
=
1833 this->CacheManager
->GetCacheValue("CMAKE_HOME_DIRECTORY");
1834 cacheStart
+= "/CMakeLists.txt";
1835 std::string currentStart
= this->GetHomeDirectory();
1836 currentStart
+= "/CMakeLists.txt";
1837 if(!cmSystemTools::SameFile(cacheStart
.c_str(), currentStart
.c_str()))
1839 std::string message
= "The source \"";
1840 message
+= currentStart
;
1841 message
+= "\" does not match the source \"";
1842 message
+= cacheStart
;
1843 message
+= "\" used to generate cache. ";
1844 message
+= "Re-run cmake with a different source directory.";
1845 cmSystemTools::Error(message
.c_str());
1855 struct SaveCacheEntry
1860 cmCacheManager::CacheEntryType type
;
1863 int cmake::HandleDeleteCacheVariables(const char* var
)
1865 std::vector
<std::string
> argsSplit
;
1866 cmSystemTools::ExpandListArgument(std::string(var
), argsSplit
);
1867 // erase the property to avoid infinite recursion
1868 this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
1870 cmCacheManager::CacheIterator ci
= this->CacheManager
->NewIterator();
1871 std::vector
<SaveCacheEntry
> saved
;
1872 cmOStringStream warning
;
1874 << "You have changed variables that require your cache to be deleted.\n"
1875 << "Configure will be re-run and you may have to reset some variables.\n"
1876 << "The following variables have changed:\n";
1877 for(std::vector
<std::string
>::iterator i
= argsSplit
.begin();
1878 i
!= argsSplit
.end(); ++i
)
1880 SaveCacheEntry save
;
1882 warning
<< *i
<< "= ";
1885 warning
<< *i
<< "\n";
1886 if(ci
.Find(save
.key
.c_str()))
1888 save
.type
= ci
.GetType();
1889 save
.help
= ci
.GetProperty("HELPSTRING");
1891 saved
.push_back(save
);
1895 this->CacheManager
->DeleteCache(this->GetStartOutputDirectory());
1896 // load the empty cache
1898 // restore the changed compilers
1899 for(std::vector
<SaveCacheEntry
>::iterator i
= saved
.begin();
1900 i
!= saved
.end(); ++i
)
1902 this->AddCacheEntry(i
->key
.c_str(), i
->value
.c_str(),
1903 i
->help
.c_str(), i
->type
);
1905 cmSystemTools::Message(warning
.str().c_str());
1906 // avoid reconfigure if there were errors
1907 if(!cmSystemTools::GetErrorOccuredFlag())
1910 return this->Configure();
1915 int cmake::Configure()
1917 if(this->DoSuppressDevWarnings
)
1919 if(this->SuppressDevWarnings
)
1921 this->CacheManager
->
1922 AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE",
1923 "Suppress Warnings that are meant for"
1924 " the author of the CMakeLists.txt files.",
1925 cmCacheManager::INTERNAL
);
1929 this->CacheManager
->
1930 AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE",
1931 "Suppress Warnings that are meant for"
1932 " the author of the CMakeLists.txt files.",
1933 cmCacheManager::INTERNAL
);
1936 int ret
= this->ActualConfigure();
1937 const char* delCacheVars
=
1938 this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
1939 if(delCacheVars
&& delCacheVars
[0] != 0)
1941 return this->HandleDeleteCacheVariables(delCacheVars
);
1947 int cmake::ActualConfigure()
1949 // Construct right now our path conversion table before it's too late:
1950 this->UpdateConversionPathTable();
1951 this->CleanupCommandsAndMacros();
1954 if ( !this->ScriptMode
)
1956 res
= this->DoPreConfigureChecks();
1964 this->CacheManager
->AddCacheEntry
1965 ("CMAKE_HOME_DIRECTORY",
1966 this->GetHomeDirectory(),
1967 "Start directory with the top level CMakeLists.txt file for this "
1969 cmCacheManager::INTERNAL
);
1972 // no generator specified on the command line
1973 if(!this->GlobalGenerator
)
1975 const char* genName
=
1976 this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
1977 const char* extraGenName
=
1978 this->CacheManager
->GetCacheValue("CMAKE_EXTRA_GENERATOR");
1981 std::string fullName
= cmExternalMakefileProjectGenerator::
1982 CreateFullGeneratorName(genName
, extraGenName
);
1983 this->GlobalGenerator
= this->CreateGlobalGenerator(fullName
.c_str());
1985 if(this->GlobalGenerator
)
1987 // set the global flag for unix style paths on cmSystemTools as
1988 // soon as the generator is set. This allows gmake to be used
1990 cmSystemTools::SetForceUnixPaths
1991 (this->GlobalGenerator
->GetForceUnixPaths());
1995 #if defined(__BORLANDC__) && defined(_WIN32)
1996 this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator
);
1997 #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
1998 std::string installedCompiler
;
1999 std::string mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
2000 "\\VisualStudio\\8.0\\Setup;Dbghelp_path]";
2001 cmSystemTools::ExpandRegistryValues(mp
);
2002 if (!(mp
== "/registry"))
2004 installedCompiler
= "Visual Studio 8 2005";
2008 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
2009 "\\VisualStudio\\7.1;InstallDir]";
2010 cmSystemTools::ExpandRegistryValues(mp
);
2011 if (!(mp
== "/registry"))
2013 installedCompiler
= "Visual Studio 7 .NET 2003";
2017 mp
= "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft"
2018 "\\VisualStudio\\7.0;InstallDir]";
2019 cmSystemTools::ExpandRegistryValues(mp
);
2020 if (!(mp
== "/registry"))
2022 installedCompiler
= "Visual Studio 7";
2026 installedCompiler
= "Visual Studio 6";
2030 cmGlobalGenerator
* gen
2031 = this->CreateGlobalGenerator(installedCompiler
.c_str());
2034 gen
= new cmGlobalNMakeMakefileGenerator
;
2036 this->SetGlobalGenerator(gen
);
2038 this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3
);
2041 if(!this->GlobalGenerator
)
2043 cmSystemTools::Error("Could not create generator");
2048 const char* genName
= this->CacheManager
->GetCacheValue("CMAKE_GENERATOR");
2051 if(strcmp(this->GlobalGenerator
->GetName(), genName
) != 0)
2053 std::string message
= "Error: generator : ";
2054 message
+= this->GlobalGenerator
->GetName();
2055 message
+= "\nDoes not match the generator used previously: ";
2058 "\nEither remove the CMakeCache.txt file or choose a different"
2059 " binary directory.";
2060 cmSystemTools::Error(message
.c_str());
2064 if(!this->CacheManager
->GetCacheValue("CMAKE_GENERATOR"))
2066 this->CacheManager
->AddCacheEntry("CMAKE_GENERATOR",
2067 this->GlobalGenerator
->GetName(),
2068 "Name of generator.",
2069 cmCacheManager::INTERNAL
);
2070 this->CacheManager
->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
2071 this->GlobalGenerator
->GetExtraGeneratorName(),
2072 "Name of external makefile project generator.",
2073 cmCacheManager::INTERNAL
);
2076 // reset any system configuration information, except for when we are
2077 // InTryCompile. With TryCompile the system info is taken from the parent's
2078 // info to save time
2079 if (!this->InTryCompile
)
2081 this->GlobalGenerator
->ClearEnabledLanguages();
2084 this->CleanupWrittenFiles();
2086 // Truncate log files
2087 if (!this->InTryCompile
)
2089 this->TruncateOutputLog("CMakeOutput.log");
2090 this->TruncateOutputLog("CMakeError.log");
2093 // actually do the configure
2094 this->GlobalGenerator
->Configure();
2095 // Before saving the cache
2096 // if the project did not define one of the entries below, add them now
2097 // so users can edit the values in the cache:
2098 // LIBRARY_OUTPUT_PATH
2099 // EXECUTABLE_OUTPUT_PATH
2100 if(!this->CacheManager
->GetCacheValue("LIBRARY_OUTPUT_PATH"))
2102 this->CacheManager
->AddCacheEntry
2103 ("LIBRARY_OUTPUT_PATH", "",
2104 "Single output directory for building all libraries.",
2105 cmCacheManager::PATH
);
2107 if(!this->CacheManager
->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
2109 this->CacheManager
->AddCacheEntry
2110 ("EXECUTABLE_OUTPUT_PATH", "",
2111 "Single output directory for building all executables.",
2112 cmCacheManager::PATH
);
2114 if(!this->CacheManager
->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
2116 this->CacheManager
->AddCacheEntry
2117 ("CMAKE_USE_RELATIVE_PATHS", false,
2118 "If true, cmake will use relative paths in makefiles and projects.");
2119 cmCacheManager::CacheIterator it
=
2120 this->CacheManager
->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
2121 if ( !it
.PropertyExists("ADVANCED") )
2123 it
.SetProperty("ADVANCED", "1");
2127 if(cmSystemTools::GetFatalErrorOccured() &&
2128 (!this->CacheManager
->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
2129 cmSystemTools::IsOff(this->CacheManager
->
2130 GetCacheValue("CMAKE_MAKE_PROGRAM"))))
2132 // We must have a bad generator selection. Wipe the cache entry so the
2133 // user can select another.
2134 this->CacheManager
->RemoveCacheEntry("CMAKE_GENERATOR");
2135 this->CacheManager
->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
2137 // only save the cache if there were no fatal errors
2138 if ( !this->ScriptMode
)
2140 this->CacheManager
->SaveCache(this->GetHomeOutputDirectory());
2142 if ( !this->GraphVizFile
.empty() )
2144 std::cout
<< "Generate graphviz: " << this->GraphVizFile
<< std::endl
;
2145 this->GenerateGraphViz(this->GraphVizFile
.c_str());
2147 if(cmSystemTools::GetErrorOccuredFlag())
2154 bool cmake::CacheVersionMatches()
2157 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION");
2159 this->CacheManager
->GetCacheValue("CMAKE_CACHE_MINOR_VERSION");
2161 this->CacheManager
->GetCacheValue("CMAKE_CACHE_RELEASE_VERSION");
2162 bool cacheSameCMake
= false;
2164 atoi(majv
) == static_cast<int>(cmVersion::GetMajorVersion())
2166 atoi(minv
) == static_cast<int>(cmVersion::GetMinorVersion())
2167 && relv
&& (strcmp(relv
, cmVersion::GetReleaseVersion().c_str()) == 0))
2169 cacheSameCMake
= true;
2171 return cacheSameCMake
;
2174 void cmake::PreLoadCMakeFiles()
2176 std::string pre_load
= this->GetHomeDirectory();
2177 if ( pre_load
.size() > 0 )
2179 pre_load
+= "/PreLoad.cmake";
2180 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2182 this->ReadListFile(pre_load
.c_str());
2185 pre_load
= this->GetHomeOutputDirectory();
2186 if ( pre_load
.size() > 0 )
2188 pre_load
+= "/PreLoad.cmake";
2189 if ( cmSystemTools::FileExists(pre_load
.c_str()) )
2191 this->ReadListFile(pre_load
.c_str());
2196 // handle a command line invocation
2197 int cmake::Run(const std::vector
<std::string
>& args
, bool noconfigure
)
2199 // Process the arguments
2200 this->SetArgs(args
);
2201 if(cmSystemTools::GetErrorOccuredFlag())
2206 // If we are given a stamp list file check if it is really out of date.
2207 if(!this->CheckStampList
.empty() &&
2208 cmakeCheckStampList(this->CheckStampList
.c_str()))
2213 // If we are given a stamp file check if it is really out of date.
2214 if(!this->CheckStampFile
.empty() &&
2215 cmakeCheckStampFile(this->CheckStampFile
.c_str()))
2220 // set the cmake command
2221 this->CMakeCommand
= args
[0];
2223 if ( !this->ScriptMode
)
2226 if(this->LoadCache() < 0)
2228 cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
2234 this->AddCMakePaths();
2236 // Add any cache args
2237 if ( !this->SetCacheArgs(args
) )
2239 cmSystemTools::Error("Problem processing arguments. Aborting.\n");
2243 // In script mode we terminate after running the script.
2244 if(this->ScriptMode
)
2246 if(cmSystemTools::GetErrorOccuredFlag())
2256 this->PreLoadCMakeFiles();
2258 std::string systemFile
= this->GetHomeOutputDirectory();
2259 systemFile
+= "/CMakeSystem.cmake";
2266 // now run the global generate
2267 // Check the state of the build system to see if we need to regenerate.
2268 if(!this->CheckBuildSystem())
2273 // If we are doing global generate, we better set start and start
2274 // output directory to the root of the project.
2275 std::string oldstartdir
= this->GetStartDirectory();
2276 std::string oldstartoutputdir
= this->GetStartOutputDirectory();
2277 this->SetStartDirectory(this->GetHomeDirectory());
2278 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
2279 int ret
= this->Configure();
2280 if (ret
|| this->ScriptMode
)
2282 #if defined(CMAKE_HAVE_VS_GENERATORS)
2283 if(!this->VSSolutionFile
.empty() && this->GlobalGenerator
)
2285 // CMake is running to regenerate a Visual Studio build tree
2286 // during a build from the VS IDE. The build files cannot be
2287 // regenerated, so we should stop the build.
2288 cmSystemTools::Message(
2289 "CMake Configure step failed. "
2290 "Build files cannot be regenerated correctly. "
2291 "Attempting to stop IDE build.");
2292 cmGlobalVisualStudioGenerator
* gg
=
2293 static_cast<cmGlobalVisualStudioGenerator
*>(this->GlobalGenerator
);
2294 gg
->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop
,
2295 this->VSSolutionFile
.c_str());
2300 ret
= this->Generate();
2301 std::string message
= "Build files have been written to: ";
2302 message
+= this->GetHomeOutputDirectory();
2303 this->UpdateProgress(message
.c_str(), -1);
2308 this->SetStartDirectory(oldstartdir
.c_str());
2309 this->SetStartOutputDirectory(oldstartoutputdir
.c_str());
2314 int cmake::Generate()
2316 if(!this->GlobalGenerator
)
2320 this->GlobalGenerator
->Generate();
2321 if(cmSystemTools::GetErrorOccuredFlag())
2325 if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
2327 this->ReportUndefinedPropertyAccesses
2328 (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
2333 void cmake::AddCacheEntry(const char* key
, const char* value
,
2334 const char* helpString
,
2337 this->CacheManager
->AddCacheEntry(key
, value
,
2339 cmCacheManager::CacheEntryType(type
));
2342 const char* cmake::GetCacheDefinition(const char* name
) const
2344 return this->CacheManager
->GetCacheValue(name
);
2347 int cmake::DumpDocumentationToFile(std::ostream
& f
)
2349 #ifdef CMAKE_BUILD_WITH_CMAKE
2350 // Loop over all registered commands and print out documentation
2355 sprintf(tmp
,"Version %d.%d (%s)", cmVersion::GetMajorVersion(),
2356 cmVersion::GetMinorVersion(),
2357 cmVersion::GetReleaseVersion().c_str());
2359 f
<< "<h1>Documentation for commands of CMake " << tmp
<< "</h1>\n";
2361 for(RegisteredCommandsMap::iterator j
= this->Commands
.begin();
2362 j
!= this->Commands
.end(); ++j
)
2364 name
= (*j
).second
->GetName();
2365 terse
= (*j
).second
->GetTerseDocumentation();
2366 full
= (*j
).second
->GetFullDocumentation();
2367 f
<< "<li><b>" << name
<< "</b> - " << terse
<< std::endl
2368 << "<br><i>Usage:</i> " << full
<< "</li>" << std::endl
<< std::endl
;
2370 f
<< "</ul></html>\n";
2377 void cmake::AddDefaultCommands()
2379 std::list
<cmCommand
*> commands
;
2380 GetBootstrapCommands(commands
);
2381 GetPredefinedCommands(commands
);
2382 for(std::list
<cmCommand
*>::iterator i
= commands
.begin();
2383 i
!= commands
.end(); ++i
)
2385 this->AddCommand(*i
);
2389 void cmake::AddDefaultGenerators()
2391 #if defined(_WIN32) && !defined(__CYGWIN__)
2392 # if !defined(CMAKE_BOOT_MINGW)
2393 this->Generators
[cmGlobalVisualStudio6Generator::GetActualName()] =
2394 &cmGlobalVisualStudio6Generator::New
;
2395 this->Generators
[cmGlobalVisualStudio7Generator::GetActualName()] =
2396 &cmGlobalVisualStudio7Generator::New
;
2397 this->Generators
[cmGlobalVisualStudio71Generator::GetActualName()] =
2398 &cmGlobalVisualStudio71Generator::New
;
2399 this->Generators
[cmGlobalVisualStudio8Generator::GetActualName()] =
2400 &cmGlobalVisualStudio8Generator::New
;
2401 this->Generators
[cmGlobalVisualStudio9Generator::GetActualName()] =
2402 &cmGlobalVisualStudio9Generator::New
;
2403 this->Generators
[cmGlobalVisualStudio9Win64Generator::GetActualName()] =
2404 &cmGlobalVisualStudio9Win64Generator::New
;
2405 this->Generators
[cmGlobalVisualStudio8Win64Generator::GetActualName()] =
2406 &cmGlobalVisualStudio8Win64Generator::New
;
2407 this->Generators
[cmGlobalBorlandMakefileGenerator::GetActualName()] =
2408 &cmGlobalBorlandMakefileGenerator::New
;
2409 this->Generators
[cmGlobalNMakeMakefileGenerator::GetActualName()] =
2410 &cmGlobalNMakeMakefileGenerator::New
;
2411 this->Generators
[cmGlobalWatcomWMakeGenerator::GetActualName()] =
2412 &cmGlobalWatcomWMakeGenerator::New
;
2414 this->Generators
[cmGlobalMSYSMakefileGenerator::GetActualName()] =
2415 &cmGlobalMSYSMakefileGenerator::New
;
2416 this->Generators
[cmGlobalMinGWMakefileGenerator::GetActualName()] =
2417 &cmGlobalMinGWMakefileGenerator::New
;
2419 this->Generators
[cmGlobalUnixMakefileGenerator3::GetActualName()] =
2420 &cmGlobalUnixMakefileGenerator3::New
;
2421 #ifdef CMAKE_USE_XCODE
2422 this->Generators
[cmGlobalXCodeGenerator::GetActualName()] =
2423 &cmGlobalXCodeGenerator::New
;
2427 int cmake::LoadCache()
2429 // could we not read the cache
2430 if (!this->CacheManager
->LoadCache(this->GetHomeOutputDirectory()))
2432 // if it does exist, but isn;t readable then warn the user
2433 std::string cacheFile
= this->GetHomeOutputDirectory();
2434 cacheFile
+= "/CMakeCache.txt";
2435 if(cmSystemTools::FileExists(cacheFile
.c_str()))
2437 cmSystemTools::Error(
2438 "There is a CMakeCache.txt file for the current binary tree but "
2439 "cmake does not have permission to read it. Please check the "
2440 "permissions of the directory you are trying to run CMake on.");
2445 if (this->CMakeCommand
.size() < 2)
2447 cmSystemTools::Error(
2448 "cmake command was not specified prior to loading the cache in "
2453 // setup CMAKE_ROOT and CMAKE_COMMAND
2454 if(!this->AddCMakePaths())
2461 void cmake::SetProgressCallback(ProgressCallbackType f
, void *cd
)
2463 this->ProgressCallback
= f
;
2464 this->ProgressCallbackClientData
= cd
;
2467 void cmake::UpdateProgress(const char *msg
, float prog
)
2469 if(this->ProgressCallback
&& !this->InTryCompile
)
2471 (*this->ProgressCallback
)(msg
, prog
, this->ProgressCallbackClientData
);
2476 void cmake::GetCommandDocumentation(std::vector
<cmDocumentationEntry
>& v
,
2477 bool withCurrentCommands
,
2478 bool withCompatCommands
) const
2480 for(RegisteredCommandsMap::const_iterator j
= this->Commands
.begin();
2481 j
!= this->Commands
.end(); ++j
)
2483 if ((( withCompatCommands
== false) && ( (*j
).second
->IsDiscouraged()))
2484 || ((withCurrentCommands
== false) && (!(*j
).second
->IsDiscouraged())))
2489 cmDocumentationEntry
e((*j
).second
->GetName(),
2490 (*j
).second
->GetTerseDocumentation(),
2491 (*j
).second
->GetFullDocumentation());
2496 void cmake::GetPolicyDocumentation(std::vector
<cmDocumentationEntry
>& v
)
2498 this->Policies
->GetDocumentation(v
);
2501 void cmake::GetPropertiesDocumentation(std::map
<std::string
,
2502 cmDocumentationSection
*>& v
)
2504 // loop over the properties and put them into the doc structure
2505 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
2506 i
= this->PropertyDefinitions
.begin();
2507 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
2509 i
->second
.GetPropertiesDocumentation(v
);
2513 void cmake::GetGeneratorDocumentation(std::vector
<cmDocumentationEntry
>& v
)
2515 for(RegisteredGeneratorsMap::const_iterator i
= this->Generators
.begin();
2516 i
!= this->Generators
.end(); ++i
)
2518 cmDocumentationEntry e
;
2519 cmGlobalGenerator
* generator
= (i
->second
)();
2520 generator
->GetDocumentation(e
);
2524 for(RegisteredExtraGeneratorsMap::const_iterator
2525 i
= this->ExtraGenerators
.begin(); i
!= this->ExtraGenerators
.end(); ++i
)
2527 cmDocumentationEntry e
;
2528 cmExternalMakefileProjectGenerator
* generator
= (i
->second
)();
2529 generator
->GetDocumentation(e
, i
->first
.c_str());
2536 void cmake::AddWrittenFile(const char* file
)
2538 this->WrittenFiles
.insert(file
);
2541 bool cmake::HasWrittenFile(const char* file
)
2543 return this->WrittenFiles
.find(file
) != this->WrittenFiles
.end();
2546 void cmake::CleanupWrittenFiles()
2548 this->WrittenFiles
.clear();
2551 void cmake::UpdateConversionPathTable()
2553 // Update the path conversion table with any specified file:
2554 const char* tablepath
=
2555 this->CacheManager
->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
2559 std::ifstream
table( tablepath
);
2562 cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath
,
2563 ". CMake can not open file.");
2564 cmSystemTools::ReportLastSystemError("CMake can not open file.");
2571 // two entries per line
2572 table
>> a
; table
>> b
;
2573 cmSystemTools::AddTranslationPath( a
.c_str(), b
.c_str());
2579 //----------------------------------------------------------------------------
2580 int cmake::CheckBuildSystem()
2582 // We do not need to rerun CMake. Check dependency integrity. Use
2583 // the make system's VERBOSE environment variable to enable verbose
2585 bool verbose
= cmSystemTools::GetEnv("VERBOSE") != 0;
2587 // This method will check the integrity of the build system if the
2588 // option was given on the command line. It reads the given file to
2589 // determine whether CMake should rerun.
2591 // If no file is provided for the check, we have to rerun.
2592 if(this->CheckBuildSystemArgument
.size() == 0)
2596 cmOStringStream msg
;
2597 msg
<< "Re-run cmake no build system arguments\n";
2598 cmSystemTools::Stdout(msg
.str().c_str());
2603 // If the file provided does not exist, we have to rerun.
2604 if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument
.c_str()))
2608 cmOStringStream msg
;
2609 msg
<< "Re-run cmake missing file: "
2610 << this->CheckBuildSystemArgument
.c_str() << "\n";
2611 cmSystemTools::Stdout(msg
.str().c_str());
2616 // Read the rerun check file and use it to decide whether to do the
2619 cmGlobalGenerator gg
;
2620 gg
.SetCMakeInstance(&cm
);
2621 std::auto_ptr
<cmLocalGenerator
> lg(gg
.CreateLocalGenerator());
2622 lg
->SetGlobalGenerator(&gg
);
2623 cmMakefile
* mf
= lg
->GetMakefile();
2624 if(!mf
->ReadListFile(0, this->CheckBuildSystemArgument
.c_str()) ||
2625 cmSystemTools::GetErrorOccuredFlag())
2629 cmOStringStream msg
;
2630 msg
<< "Re-run cmake error reading : "
2631 << this->CheckBuildSystemArgument
.c_str() << "\n";
2632 cmSystemTools::Stdout(msg
.str().c_str());
2634 // There was an error reading the file. Just rerun.
2638 if(this->ClearBuildSystem
)
2640 // Get the generator used for this build system.
2641 const char* genName
= mf
->GetDefinition("CMAKE_DEPENDS_GENERATOR");
2642 if(!genName
|| genName
[0] == '\0')
2644 genName
= "Unix Makefiles";
2647 // Create the generator and use it to clear the dependencies.
2648 std::auto_ptr
<cmGlobalGenerator
>
2649 ggd(this->CreateGlobalGenerator(genName
));
2652 std::auto_ptr
<cmLocalGenerator
> lgd(ggd
->CreateLocalGenerator());
2653 lgd
->SetGlobalGenerator(ggd
.get());
2654 lgd
->ClearDependencies(mf
, verbose
);
2658 // Get the set of dependencies and outputs.
2659 std::vector
<std::string
> depends
;
2660 std::vector
<std::string
> outputs
;
2661 const char* dependsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
2662 const char* outputsStr
= mf
->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
2663 if(dependsStr
&& outputsStr
)
2665 cmSystemTools::ExpandListArgument(dependsStr
, depends
);
2666 cmSystemTools::ExpandListArgument(outputsStr
, outputs
);
2668 if(depends
.empty() || outputs
.empty())
2670 // Not enough information was provided to do the test. Just rerun.
2673 cmOStringStream msg
;
2674 msg
<< "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
2675 "or CMAKE_MAKEFILE_OUTPUTS :\n";
2676 cmSystemTools::Stdout(msg
.str().c_str());
2681 // Find find the newest dependency.
2682 std::vector
<std::string
>::iterator dep
= depends
.begin();
2683 std::string dep_newest
= *dep
++;
2684 for(;dep
!= depends
.end(); ++dep
)
2687 if(this->FileComparison
->FileTimeCompare(dep_newest
.c_str(),
2688 dep
->c_str(), &result
))
2699 cmOStringStream msg
;
2700 msg
<< "Re-run cmake: build system dependency is missing\n";
2701 cmSystemTools::Stdout(msg
.str().c_str());
2707 // Find find the oldest output.
2708 std::vector
<std::string
>::iterator out
= outputs
.begin();
2709 std::string out_oldest
= *out
++;
2710 for(;out
!= outputs
.end(); ++out
)
2713 if(this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2714 out
->c_str(), &result
))
2725 cmOStringStream msg
;
2726 msg
<< "Re-run cmake: build system output is missing\n";
2727 cmSystemTools::Stdout(msg
.str().c_str());
2733 // If any output is older than any dependency then rerun.
2736 if(!this->FileComparison
->FileTimeCompare(out_oldest
.c_str(),
2743 cmOStringStream msg
;
2744 msg
<< "Re-run cmake file: " << out_oldest
.c_str()
2745 << " older than: " << dep_newest
.c_str() << "\n";
2746 cmSystemTools::Stdout(msg
.str().c_str());
2752 // No need to rerun.
2756 //----------------------------------------------------------------------------
2757 void cmake::TruncateOutputLog(const char* fname
)
2759 std::string fullPath
= this->GetHomeOutputDirectory();
2763 if ( ::stat(fullPath
.c_str(), &st
) )
2767 if ( !this->CacheManager
->GetCacheValue("CMAKE_CACHEFILE_DIR") )
2769 cmSystemTools::RemoveFile(fullPath
.c_str());
2772 off_t fsize
= st
.st_size
;
2773 const off_t maxFileSize
= 50 * 1024;
2774 if ( fsize
< maxFileSize
)
2776 //TODO: truncate file
2781 inline std::string
removeQuotes(const std::string
& s
)
2783 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
2785 return s
.substr(1, s
.size()-2);
2790 std::string
cmake::FindCMakeProgram(const char* name
) const
2793 if ((name
) && (*name
))
2795 const cmMakefile
* mf
2796 = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
2797 #ifdef CMAKE_BUILD_WITH_CMAKE
2798 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2799 path
= removeQuotes(path
);
2800 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2803 path
+= cmSystemTools::GetExecutableExtension();
2804 if(!cmSystemTools::FileExists(path
.c_str()))
2806 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2807 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2810 path
+= cmSystemTools::GetExecutableExtension();
2812 if(!cmSystemTools::FileExists(path
.c_str()))
2814 path
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
2815 path
= cmSystemTools::GetFilenamePath(path
.c_str());
2816 path
+= "/Release/";
2818 path
+= cmSystemTools::GetExecutableExtension();
2821 // Only for bootstrap
2822 path
+= mf
->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
2825 path
+= cmSystemTools::GetExecutableExtension();
2831 const char* cmake::GetCTestCommand()
2833 if ( this->CTestCommand
.empty() )
2835 this->CTestCommand
= this->FindCMakeProgram("ctest");
2837 if ( this->CTestCommand
.empty() )
2839 cmSystemTools::Error("Cannot find the CTest executable");
2840 this->CTestCommand
= "CTEST-COMMAND-NOT-FOUND";
2842 return this->CTestCommand
.c_str();
2845 const char* cmake::GetCPackCommand()
2847 if ( this->CPackCommand
.empty() )
2849 this->CPackCommand
= this->FindCMakeProgram("cpack");
2851 if ( this->CPackCommand
.empty() )
2853 cmSystemTools::Error("Cannot find the CPack executable");
2854 this->CPackCommand
= "CPACK-COMMAND-NOT-FOUND";
2856 return this->CPackCommand
.c_str();
2859 void cmake::GenerateGraphViz(const char* fileName
) const
2861 cmGeneratedFileStream
str(fileName
);
2867 cmGlobalGenerator ggi
;
2868 ggi
.SetCMakeInstance(&cm
);
2869 std::auto_ptr
<cmLocalGenerator
> lg(ggi
.CreateLocalGenerator());
2870 lg
->SetGlobalGenerator(&ggi
);
2871 cmMakefile
*mf
= lg
->GetMakefile();
2873 std::string infile
= this->GetHomeOutputDirectory();
2874 infile
+= "/CMakeGraphVizOptions.cmake";
2875 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2877 infile
= this->GetHomeDirectory();
2878 infile
+= "/CMakeGraphVizOptions.cmake";
2879 if ( !cmSystemTools::FileExists(infile
.c_str()) )
2885 if ( !infile
.empty() )
2887 if ( !mf
->ReadListFile(0, infile
.c_str()) )
2889 cmSystemTools::Error("Problem opening GraphViz options file: ",
2893 std::cout
<< "Read GraphViz options file: " << infile
.c_str()
2897 #define __set_if_not_set(var, value, cmakeDefinition) \
2898 const char* var = mf->GetDefinition(cmakeDefinition); \
2903 __set_if_not_set(graphType
, "digraph", "GRAPHVIZ_GRAPH_TYPE");
2904 __set_if_not_set(graphName
, "GG", "GRAPHVIZ_GRAPH_NAME");
2905 __set_if_not_set(graphHeader
, "node [\n fontsize = \"12\"\n];",
2906 "GRAPHVIZ_GRAPH_HEADER");
2907 __set_if_not_set(graphNodePrefix
, "node", "GRAPHVIZ_NODE_PREFIX");
2908 const char* ignoreTargets
= mf
->GetDefinition("GRAPHVIZ_IGNORE_TARGETS");
2909 std::set
<cmStdString
> ignoreTargetsSet
;
2910 if ( ignoreTargets
)
2912 std::vector
<std::string
> ignoreTargetsVector
;
2913 cmSystemTools::ExpandListArgument(ignoreTargets
,ignoreTargetsVector
);
2914 std::vector
<std::string
>::iterator itvIt
;
2915 for ( itvIt
= ignoreTargetsVector
.begin();
2916 itvIt
!= ignoreTargetsVector
.end();
2919 ignoreTargetsSet
.insert(itvIt
->c_str());
2923 str
<< graphType
<< " " << graphName
<< " {" << std::endl
;
2924 str
<< graphHeader
<< std::endl
;
2926 const cmGlobalGenerator
* gg
= this->GetGlobalGenerator();
2927 const std::vector
<cmLocalGenerator
*>& localGenerators
=
2928 gg
->GetLocalGenerators();
2929 std::vector
<cmLocalGenerator
*>::const_iterator lit
;
2932 // 2 - external target
2934 std::map
<cmStdString
, int> targetDeps
;
2935 std::map
<cmStdString
, const cmTarget
*> targetPtrs
;
2936 std::map
<cmStdString
, cmStdString
> targetNamesNodes
;
2938 // First pass get the list of all cmake targets
2939 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2941 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2942 cmTargets::const_iterator tit
;
2943 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2945 const char* realTargetName
= tit
->first
.c_str();
2946 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2948 // Skip ignored targets
2951 //std::cout << "Found target: " << tit->first.c_str() << std::endl;
2952 cmOStringStream ostr
;
2953 ostr
<< graphNodePrefix
<< cnt
++;
2954 targetNamesNodes
[realTargetName
] = ostr
.str();
2955 targetPtrs
[realTargetName
] = &tit
->second
;
2958 // Ok, now find all the stuff we link to that is not in cmake
2959 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
2961 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
2962 cmTargets::const_iterator tit
;
2963 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
2965 const cmTarget::LinkLibraryVectorType
* ll
2966 = &(tit
->second
.GetOriginalLinkLibraries());
2967 cmTarget::LinkLibraryVectorType::const_iterator llit
;
2968 const char* realTargetName
= tit
->first
.c_str();
2969 if ( ignoreTargetsSet
.find(realTargetName
) != ignoreTargetsSet
.end() )
2971 // Skip ignored targets
2974 if ( ll
->size() > 0 )
2976 targetDeps
[realTargetName
] = 1;
2978 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
2980 const char* libName
= llit
->first
.c_str();
2981 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
2982 = targetNamesNodes
.find(libName
);
2983 if ( ignoreTargetsSet
.find(libName
) != ignoreTargetsSet
.end() )
2985 // Skip ignored targets
2988 if ( tarIt
== targetNamesNodes
.end() )
2990 cmOStringStream ostr
;
2991 ostr
<< graphNodePrefix
<< cnt
++;
2992 targetDeps
[libName
] = 2;
2993 targetNamesNodes
[libName
] = ostr
.str();
2994 //str << " \"" << ostr.c_str() << "\" [ label=\"" << libName
2995 //<< "\" shape=\"ellipse\"];" << std::endl;
2999 std::map
<cmStdString
, int>::const_iterator depIt
3000 = targetDeps
.find(libName
);
3001 if ( depIt
== targetDeps
.end() )
3003 targetDeps
[libName
] = 1;
3011 std::map
<cmStdString
, int>::const_iterator depIt
;
3012 for ( depIt
= targetDeps
.begin(); depIt
!= targetDeps
.end(); ++ depIt
)
3014 const char* newTargetName
= depIt
->first
.c_str();
3015 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3016 = targetNamesNodes
.find(newTargetName
);
3017 if ( tarIt
== targetNamesNodes
.end() )
3019 // We should not be here.
3020 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
3021 << " even though it was added in the previous pass" << std::endl
;
3025 str
<< " \"" << tarIt
->second
.c_str() << "\" [ label=\""
3026 << newTargetName
<< "\" shape=\"";
3027 if ( depIt
->second
== 1 )
3029 std::map
<cmStdString
, const cmTarget
*>::const_iterator tarTypeIt
=
3030 targetPtrs
.find(newTargetName
);
3031 if ( tarTypeIt
== targetPtrs
.end() )
3033 // We should not be here.
3034 std::cout
<< __LINE__
<< " Cannot find library: " << newTargetName
3035 << " even though it was added in the previous pass" << std::endl
;
3038 const cmTarget
* tg
= tarTypeIt
->second
;
3039 switch ( tg
->GetType() )
3041 case cmTarget::EXECUTABLE
:
3044 case cmTarget::STATIC_LIBRARY
:
3047 case cmTarget::SHARED_LIBRARY
:
3050 case cmTarget::MODULE_LIBRARY
:
3061 str
<< "\"];" << std::endl
;
3064 // Now generate the connectivity
3065 for ( lit
= localGenerators
.begin(); lit
!= localGenerators
.end(); ++ lit
)
3067 const cmTargets
* targets
= &((*lit
)->GetMakefile()->GetTargets());
3068 cmTargets::const_iterator tit
;
3069 for ( tit
= targets
->begin(); tit
!= targets
->end(); ++ tit
)
3071 std::map
<cmStdString
, int>::iterator dependIt
3072 = targetDeps
.find(tit
->first
.c_str());
3073 if ( dependIt
== targetDeps
.end() )
3077 std::map
<cmStdString
, cmStdString
>::iterator cmakeTarIt
3078 = targetNamesNodes
.find(tit
->first
.c_str());
3079 const cmTarget::LinkLibraryVectorType
* ll
3080 = &(tit
->second
.GetOriginalLinkLibraries());
3081 cmTarget::LinkLibraryVectorType::const_iterator llit
;
3082 for ( llit
= ll
->begin(); llit
!= ll
->end(); ++ llit
)
3084 const char* libName
= llit
->first
.c_str();
3085 std::map
<cmStdString
, cmStdString
>::const_iterator tarIt
3086 = targetNamesNodes
.find(libName
);
3087 if ( tarIt
== targetNamesNodes
.end() )
3089 // We should not be here.
3090 std::cout
<< __LINE__
<< " Cannot find library: " << libName
3091 << " even though it was added in the previous pass" << std::endl
;
3094 str
<< " \"" << cmakeTarIt
->second
.c_str() << "\" -> \""
3095 << tarIt
->second
.c_str() << "\"" << std::endl
;
3100 // TODO: Use dotted or something for external libraries
3101 //str << " \"node0\":f4 -> \"node12\"[color=\"#0000ff\" style=dotted]"
3104 str
<< "}" << std::endl
;
3107 //----------------------------------------------------------------------------
3108 #ifdef CMAKE_BUILD_WITH_CMAKE
3109 int cmake::ExecuteEchoColor(std::vector
<std::string
>& args
)
3111 // The arguments are
3112 // argv[0] == <cmake-executable>
3113 // argv[1] == cmake_echo_color
3115 bool enabled
= true;
3116 int color
= cmsysTerminal_Color_Normal
;
3117 bool newline
= true;
3118 for(unsigned int i
=2; i
< args
.size(); ++i
)
3120 if(args
[i
].find("--switch=") == 0)
3122 // Enable or disable color based on the switch value.
3123 std::string value
= args
[i
].substr(9);
3126 if(cmSystemTools::IsOn(value
.c_str()))
3136 else if(args
[i
] == "--normal")
3138 color
= cmsysTerminal_Color_Normal
;
3140 else if(args
[i
] == "--black")
3142 color
= cmsysTerminal_Color_ForegroundBlack
;
3144 else if(args
[i
] == "--red")
3146 color
= cmsysTerminal_Color_ForegroundRed
;
3148 else if(args
[i
] == "--green")
3150 color
= cmsysTerminal_Color_ForegroundGreen
;
3152 else if(args
[i
] == "--yellow")
3154 color
= cmsysTerminal_Color_ForegroundYellow
;
3156 else if(args
[i
] == "--blue")
3158 color
= cmsysTerminal_Color_ForegroundBlue
;
3160 else if(args
[i
] == "--magenta")
3162 color
= cmsysTerminal_Color_ForegroundMagenta
;
3164 else if(args
[i
] == "--cyan")
3166 color
= cmsysTerminal_Color_ForegroundCyan
;
3168 else if(args
[i
] == "--white")
3170 color
= cmsysTerminal_Color_ForegroundWhite
;
3172 else if(args
[i
] == "--bold")
3174 color
|= cmsysTerminal_Color_ForegroundBold
;
3176 else if(args
[i
] == "--no-newline")
3180 else if(args
[i
] == "--newline")
3186 // Color is enabled. Print with the current color.
3187 cmSystemTools::MakefileColorEcho(color
, args
[i
].c_str(),
3195 int cmake::ExecuteEchoColor(std::vector
<std::string
>&)
3201 //----------------------------------------------------------------------------
3202 int cmake::ExecuteLinkScript(std::vector
<std::string
>& args
)
3204 // The arguments are
3205 // argv[0] == <cmake-executable>
3206 // argv[1] == cmake_link_script
3207 // argv[2] == <link-script-name>
3208 // argv[3] == --verbose=?
3209 bool verbose
= false;
3210 if(args
.size() >= 4)
3212 if(args
[3].find("--verbose=") == 0)
3214 if(!cmSystemTools::IsOff(args
[3].substr(10).c_str()))
3221 // Allocate a process instance.
3222 cmsysProcess
* cp
= cmsysProcess_New();
3225 std::cerr
<< "Error allocating process instance in link script."
3230 // Children should share stdout and stderr with this process.
3231 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDOUT
, 1);
3232 cmsysProcess_SetPipeShared(cp
, cmsysProcess_Pipe_STDERR
, 1);
3234 // Run the command lines verbatim.
3235 cmsysProcess_SetOption(cp
, cmsysProcess_Option_Verbatim
, 1);
3237 // Read command lines from the script.
3238 std::ifstream
fin(args
[2].c_str());
3241 std::cerr
<< "Error opening link script \""
3242 << args
[2] << "\"" << std::endl
;
3246 // Run one command at a time.
3247 std::string command
;
3249 while(result
== 0 && cmSystemTools::GetLineFromStream(fin
, command
))
3251 // Setup this command line.
3252 const char* cmd
[2] = {command
.c_str(), 0};
3253 cmsysProcess_SetCommand(cp
, cmd
);
3255 // Report the command if verbose output is enabled.
3258 std::cout
<< command
<< std::endl
;
3261 // Run the command and wait for it to exit.
3262 cmsysProcess_Execute(cp
);
3263 cmsysProcess_WaitForExit(cp
, 0);
3265 // Report failure if any.
3266 switch(cmsysProcess_GetState(cp
))
3268 case cmsysProcess_State_Exited
:
3270 int value
= cmsysProcess_GetExitValue(cp
);
3277 case cmsysProcess_State_Exception
:
3278 std::cerr
<< "Error running link command: "
3279 << cmsysProcess_GetExceptionString(cp
) << std::endl
;
3282 case cmsysProcess_State_Error
:
3283 std::cerr
<< "Error running link command: "
3284 << cmsysProcess_GetErrorString(cp
) << std::endl
;
3292 // Free the process instance.
3293 cmsysProcess_Delete(cp
);
3295 // Return the final resulting return value.
3299 void cmake::DefineProperties(cmake
*cm
)
3302 ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL
,
3303 "If set, report any undefined properties to this file.",
3304 "If this property is set to a filename then when CMake runs "
3305 "it will report any properties or variables that were accessed "
3306 "but not defined into the filename specified in this property."
3310 ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL
,
3311 "Does the target platform support shared libraries.",
3312 "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
3313 "platform supports shared libraries. Basically all current general "
3314 "general purpose OS do so, the exception are usually embedded systems "
3315 "with no or special OSs.");
3318 ("TARGET_ARCHIVES_MAY_BE_SHARED_LIBS", cmProperty::GLOBAL
,
3319 "Set if shared libraries may be named like archives.",
3320 "On AIX shared libraries may be named \"lib<name>.a\". "
3321 "This property is set to true on such platforms.");
3324 ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL
,
3325 "Whether FIND_LIBRARY should automatically search lib64 directories.",
3326 "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
3327 "FIND_LIBRARY command should automatically search the lib64 variant of "
3328 "directories called lib in the search path when building 64-bit "
3331 ("ENABLED_FEATURES", cmProperty::GLOBAL
,
3332 "List of features which are enabled during the CMake run.",
3333 "List of features which are enabled during the CMake run. Be default "
3334 "it contains the names of all packages which were found. This is "
3335 "determined using the <NAME>_FOUND variables. Packages which are "
3336 "searched QUIET are not listed. A project can add its own features to "
3337 "this list.This property is used by the macros in FeatureSummary.cmake.");
3339 ("DISABLED_FEATURES", cmProperty::GLOBAL
,
3340 "List of features which are disabled during the CMake run.",
3341 "List of features which are disabled during the CMake run. Be default "
3342 "it contains the names of all packages which were not found. This is "
3343 "determined using the <NAME>_FOUND variables. Packages which are "
3344 "searched QUIET are not listed. A project can add its own features to "
3345 "this list.This property is used by the macros in FeatureSummary.cmake.");
3347 ("PACKAGES_FOUND", cmProperty::GLOBAL
,
3348 "List of packages which were found during the CMake run.",
3349 "List of packages which were found during the CMake run. Whether a "
3350 "package has been found is determined using the <NAME>_FOUND variables.");
3352 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3353 "List of packages which were not found during the CMake run.",
3354 "List of packages which were not found during the CMake run. Whether a "
3355 "package has been found is determined using the <NAME>_FOUND variables.");
3358 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL
,
3359 "List of packages which were not found during the CMake run.",
3360 "List of packages which were not found during the CMake run. Whether a "
3361 "package has been found is determined using the <NAME>_FOUND variables.");
3363 "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL
,
3364 "Internal property",
3365 "Used to detect compiler changes, Do not set.");
3368 "GLOBAL_DEPENDS_DEBUG_MODE", cmProperty::GLOBAL
,
3369 "Enable global target dependency graph debug mode.",
3370 "CMake automatically analyzes the global inter-target dependency graph "
3371 "at the beginning of native build system generation. "
3372 "This property causes it to display details of its analysis to stderr.");
3375 "ALLOW_DUPLICATE_CUSTOM_TARGETS", cmProperty::GLOBAL
,
3376 "Allow duplicate custom targets to be created.",
3377 "Normally CMake requires that all targets built in a project have "
3378 "globally unique logical names (see policy CMP0002). "
3379 "This is necessary to generate meaningful project file names in "
3380 "Xcode and VS IDE generators. "
3381 "It also allows the target names to be referenced unambiguously.\n"
3382 "Makefile generators are capable of supporting duplicate custom target "
3384 "For projects that care only about Makefile generators and do "
3385 "not wish to support Xcode or VS IDE generators, one may set this "
3386 "property to true to allow duplicate custom targets. "
3387 "The property allows multiple add_custom_target command calls in "
3388 "different directories to specify the same target name. "
3389 "However, setting this property will cause non-Makefile generators "
3390 "to produce an error and refuse to generate the project."
3394 ("IN_TRY_COMPILE", cmProperty::GLOBAL
,
3395 "Read-only property that is true during a try-compile configuration.",
3396 "True when building a project inside a TRY_COMPILE or TRY_RUN command.");
3398 // ================================================================
3399 // define variables as well
3400 // ================================================================
3401 cmDocumentVariables::DefineVariables(cm
);
3405 void cmake::DefineProperty(const char *name
, cmProperty::ScopeType scope
,
3406 const char *ShortDescription
,
3407 const char *FullDescription
,
3408 bool chained
, const char *docSection
)
3410 this->PropertyDefinitions
[scope
].DefineProperty(name
,scope
,ShortDescription
,
3416 cmPropertyDefinition
*cmake
3417 ::GetPropertyDefinition(const char *name
,
3418 cmProperty::ScopeType scope
)
3420 if (this->IsPropertyDefined(name
,scope
))
3422 return &(this->PropertyDefinitions
[scope
][name
]);
3427 void cmake::RecordPropertyAccess(const char *name
,
3428 cmProperty::ScopeType scope
)
3430 this->AccessedProperties
.insert
3431 (std::pair
<cmStdString
,cmProperty::ScopeType
>(name
,scope
));
3434 void cmake::ReportUndefinedPropertyAccesses(const char *filename
)
3436 FILE *progFile
= fopen(filename
,"w");
3437 if (!progFile
|| !this->GlobalGenerator
)
3442 // what are the enabled languages?
3443 std::vector
<std::string
> enLangs
;
3444 this->GlobalGenerator
->GetEnabledLanguages(enLangs
);
3446 // Common configuration names.
3447 // TODO: Compute current configuration(s).
3448 std::vector
<std::string
> enConfigs
;
3449 enConfigs
.push_back("");
3450 enConfigs
.push_back("DEBUG");
3451 enConfigs
.push_back("RELEASE");
3452 enConfigs
.push_back("MINSIZEREL");
3453 enConfigs
.push_back("RELWITHDEBINFO");
3455 // take all the defined properties and add definitions for all the enabled
3457 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> > aliasedProperties
;
3458 std::map
<cmProperty::ScopeType
, cmPropertyDefinitionMap
>::iterator i
;
3459 i
= this->PropertyDefinitions
.begin();
3460 for (;i
!= this->PropertyDefinitions
.end(); ++i
)
3462 cmPropertyDefinitionMap::iterator j
;
3463 for (j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
)
3465 // TODO: What if both <LANG> and <CONFIG> appear?
3466 if (j
->first
.find("<CONFIG>") != std::string::npos
)
3468 std::vector
<std::string
>::const_iterator k
;
3469 for (k
= enConfigs
.begin(); k
!= enConfigs
.end(); ++k
)
3471 std::string tmp
= j
->first
;
3472 cmSystemTools::ReplaceString(tmp
, "<CONFIG>", k
->c_str());
3474 aliasedProperties
.insert
3475 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3478 if (j
->first
.find("<LANG>") != std::string::npos
)
3480 std::vector
<std::string
>::const_iterator k
;
3481 for (k
= enLangs
.begin(); k
!= enLangs
.end(); ++k
)
3483 std::string tmp
= j
->first
;
3484 cmSystemTools::ReplaceString(tmp
, "<LANG>", k
->c_str());
3486 aliasedProperties
.insert
3487 (std::pair
<cmStdString
,cmProperty::ScopeType
>(tmp
,i
->first
));
3493 std::set
<std::pair
<cmStdString
,cmProperty::ScopeType
> >::const_iterator ap
;
3494 ap
= this->AccessedProperties
.begin();
3495 for (;ap
!= this->AccessedProperties
.end(); ++ap
)
3497 if (!this->IsPropertyDefined(ap
->first
.c_str(),ap
->second
) &&
3498 aliasedProperties
.find(std::pair
<cmStdString
,cmProperty::ScopeType
>
3499 (ap
->first
,ap
->second
)) ==
3500 aliasedProperties
.end())
3502 const char *scopeStr
= "";
3505 case cmProperty::TARGET
:
3506 scopeStr
= "TARGET";
3508 case cmProperty::SOURCE_FILE
:
3509 scopeStr
= "SOURCE_FILE";
3511 case cmProperty::DIRECTORY
:
3512 scopeStr
= "DIRECTORY";
3514 case cmProperty::TEST
:
3517 case cmProperty::VARIABLE
:
3518 scopeStr
= "VARIABLE";
3520 case cmProperty::CACHED_VARIABLE
:
3521 scopeStr
= "CACHED_VARIABLE";
3524 scopeStr
= "unknown";
3527 fprintf(progFile
,"%s with scope %s\n",ap
->first
.c_str(),scopeStr
);
3533 bool cmake::IsPropertyDefined(const char *name
, cmProperty::ScopeType scope
)
3535 return this->PropertyDefinitions
[scope
].IsPropertyDefined(name
);
3538 bool cmake::IsPropertyChained(const char *name
, cmProperty::ScopeType scope
)
3540 return this->PropertyDefinitions
[scope
].IsPropertyChained(name
);
3543 void cmake::SetProperty(const char* prop
, const char* value
)
3554 this->Properties
.SetProperty(prop
, value
, cmProperty::GLOBAL
);
3557 void cmake::AppendProperty(const char* prop
, const char* value
)
3563 this->Properties
.AppendProperty(prop
, value
, cmProperty::GLOBAL
);
3566 const char *cmake::GetProperty(const char* prop
)
3568 return this->GetProperty(prop
, cmProperty::GLOBAL
);
3571 const char *cmake::GetProperty(const char* prop
, cmProperty::ScopeType scope
)
3575 // watch for special properties
3576 std::string propname
= prop
;
3577 std::string output
= "";
3578 if ( propname
== "CACHE_VARIABLES" )
3580 cmCacheManager::CacheIterator cit
=
3581 this->GetCacheManager()->GetCacheIterator();
3582 for ( cit
.Begin(); !cit
.IsAtEnd(); cit
.Next() )
3584 if ( output
.size() )
3588 output
+= cit
.GetName();
3590 this->SetProperty("CACHE_VARIABLES", output
.c_str());
3592 else if ( propname
== "COMMANDS" )
3594 cmake::RegisteredCommandsMap::iterator cmds
3595 = this->GetCommands()->begin();
3596 for (unsigned int cc
=0 ; cmds
!= this->GetCommands()->end(); ++ cmds
)
3602 output
+= cmds
->first
.c_str();
3605 this->SetProperty("COMMANDS",output
.c_str());
3607 else if ( propname
== "IN_TRY_COMPILE" )
3609 this->SetProperty("IN_TRY_COMPILE",
3610 this->GetIsInTryCompile()? "1":"0");
3612 return this->Properties
.GetPropertyValue(prop
, scope
, chain
);
3615 bool cmake::GetPropertyAsBool(const char* prop
)
3617 return cmSystemTools::IsOn(this->GetProperty(prop
));
3620 int cmake::GetSystemInformation(std::vector
<std::string
>& args
)
3622 // so create the directory
3623 std::string resultFile
;
3624 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
3625 std::string destPath
= cwd
+ "/__cmake_systeminformation";
3626 cmSystemTools::RemoveADirectory(destPath
.c_str());
3627 if (!cmSystemTools::MakeDirectory(destPath
.c_str()))
3629 std::cerr
<< "Error: --system-information must be run from a "
3630 "writable directory!\n";
3634 // process the arguments
3635 bool writeToStdout
= true;
3636 for(unsigned int i
=1; i
< args
.size(); ++i
)
3638 std::string arg
= args
[i
];
3639 if(arg
.find("-V",0) == 0)
3641 this->Verbose
= true;
3643 else if(arg
.find("-G",0) == 0)
3645 std::string value
= arg
.substr(2);
3646 if(value
.size() == 0)
3649 if(i
>= args
.size())
3651 cmSystemTools::Error("No generator specified for -G");
3656 cmGlobalGenerator
* gen
=
3657 this->CreateGlobalGenerator(value
.c_str());
3660 cmSystemTools::Error("Could not create named generator ",
3665 this->SetGlobalGenerator(gen
);
3668 // no option assume it is the output file
3671 if (!cmSystemTools::FileIsFullPath(arg
.c_str()))
3677 writeToStdout
= false;
3682 // we have to find the module directory, so we can copy the files
3683 this->AddCMakePaths();
3684 std::string modulesPath
=
3685 this->CacheManager
->GetCacheValue("CMAKE_ROOT");
3686 modulesPath
+= "/Modules";
3687 std::string inFile
= modulesPath
;
3688 inFile
+= "/SystemInformation.cmake";
3689 std::string outFile
= destPath
;
3690 outFile
+= "/CMakeLists.txt";
3693 if(!cmSystemTools::cmCopyFile(inFile
.c_str(), outFile
.c_str()))
3695 std::cerr
<< "Error copying file \"" << inFile
.c_str()
3696 << "\" to \"" << outFile
.c_str() << "\".\n";
3700 // do we write to a file or to stdout?
3701 if (resultFile
.size() == 0)
3704 resultFile
+= "/__cmake_systeminformation/results.txt";
3707 // now run cmake on the CMakeLists file
3708 cmSystemTools::ChangeDirectory(destPath
.c_str());
3709 std::vector
<std::string
> args2
;
3710 args2
.push_back(args
[0]);
3711 args2
.push_back(destPath
);
3712 std::string resultArg
= "-DRESULT_FILE=";
3713 resultArg
+= resultFile
;
3714 args2
.push_back(resultArg
);
3715 int res
= this->Run(args2
, false);
3719 std::cerr
<< "Error: --system-information failed on internal CMake!\n";
3723 // change back to the original directory
3724 cmSystemTools::ChangeDirectory(cwd
.c_str());
3726 // echo results to stdout if needed
3729 FILE* fin
= fopen(resultFile
.c_str(), "r");
3732 const int bufferSize
= 4096;
3733 char buffer
[bufferSize
];
3735 while((n
= fread(buffer
, 1, bufferSize
, fin
)) > 0)
3737 for(char* c
= buffer
; c
< buffer
+n
; ++c
)
3747 // clean up the directory
3748 cmSystemTools::RemoveADirectory(destPath
.c_str());
3752 //----------------------------------------------------------------------------
3753 static bool cmakeCheckStampFile(const char* stampName
)
3755 // If the stamp file still exists then it must really be out of
3757 if(cmSystemTools::FileExists(stampName
))
3759 // Notify the user why CMake is re-running. It is safe to
3760 // just print to stdout here because this code is only reachable
3761 // through an undocumented flag used by the VS generator.
3762 std::cout
<< "CMake is re-running due to explicit user request.\n";
3766 // The stamp file does not exist. Use the stamp dependencies to
3767 // determine whether it is really out of date. This works in
3768 // conjunction with cmLocalVisualStudio7Generator to avoid
3769 // repeatedly re-running CMake when the user rebuilds the entire
3771 std::string stampDepends
= stampName
;
3772 stampDepends
+= ".depend";
3773 #if defined(_WIN32) || defined(__CYGWIN__)
3774 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
| std::ios::binary
);
3776 std::ifstream
fin(stampDepends
.c_str(), std::ios::in
);
3780 // The stamp dependencies file cannot be read. Just assume the
3781 // build system is really out of date.
3785 // Compare the stamp dependencies against the dependency file itself.
3786 cmFileTimeComparison ftc
;
3788 while(cmSystemTools::GetLineFromStream(fin
, dep
))
3791 if(dep
.length() >= 1 && dep
[0] != '#' &&
3792 (!ftc
.FileTimeCompare(stampDepends
.c_str(), dep
.c_str(), &result
)
3795 // The stamp depends file is older than this dependency. The
3796 // build system is really out of date.
3801 // The build system is up to date. The stamp file has been removed
3802 // by the VS IDE due to a "rebuild" request. Just restore it.
3803 std::ofstream
stamp(stampName
);
3804 stamp
<< "# CMake generation timestamp file this directory.\n";
3807 // Notify the user why CMake is not re-running. It is safe to
3808 // just print to stdout here because this code is only reachable
3809 // through an undocumented flag used by the VS generator.
3810 std::cout
<< "CMake does not need to re-run because "
3811 << stampName
<< " is up-to-date.\n";
3816 cmSystemTools::Error("Cannot restore timestamp ", stampName
);
3821 //----------------------------------------------------------------------------
3822 static bool cmakeCheckStampList(const char* stampList
)
3824 // If the stamp list does not exist CMake must rerun to generate it.
3825 if(!cmSystemTools::FileExists(stampList
))
3827 std::cout
<< "CMake is re-running because generate.stamp.list "
3831 std::ifstream
fin(stampList
);
3834 std::cout
<< "CMake is re-running because generate.stamp.list "
3835 << "could not be read.\n";
3839 // Check each stamp.
3840 std::string stampName
;
3841 while(cmSystemTools::GetLineFromStream(fin
, stampName
))
3843 if(!cmakeCheckStampFile(stampName
.c_str()))
3851 // For visual studio 2005 and newer manifest files need to be embeded into
3852 // exe and dll's. This code does that in such a way that incremental linking
3854 int cmake::VisualStudioLink(std::vector
<std::string
>& args
, int type
)
3860 bool verbose
= false;
3861 if(cmSystemTools::GetEnv("VERBOSE"))
3865 std::vector
<std::string
> expandedArgs
;
3866 for(std::vector
<std::string
>::iterator i
= args
.begin();
3867 i
!= args
.end(); ++i
)
3869 // check for nmake temporary files
3872 std::ifstream
fin(i
->substr(1).c_str());
3874 while(cmSystemTools::GetLineFromStream(fin
,
3877 cmSystemTools::ParseWindowsCommandLine(line
.c_str(), expandedArgs
);
3882 expandedArgs
.push_back(*i
);
3885 // figure out if this is an incremental link or not and run the correct
3887 for(std::vector
<std::string
>::iterator i
= expandedArgs
.begin();
3888 i
!= expandedArgs
.end(); ++i
)
3890 if(cmSystemTools::Strucmp(i
->c_str(), "/INCREMENTAL:YES") == 0)
3894 std::cout
<< "Visual Studio Incremental Link\n";
3896 return cmake::VisualStudioLinkIncremental(expandedArgs
, type
, verbose
);
3901 std::cout
<< "Visual Studio Non-Incremental Link\n";
3903 return cmake::VisualStudioLinkNonIncremental(expandedArgs
, type
, verbose
);
3906 int cmake::ParseVisualStudioLinkCommand(std::vector
<std::string
>& args
,
3907 std::vector
<cmStdString
>& command
,
3908 std::string
& targetName
)
3910 std::vector
<std::string
>::iterator i
= args
.begin();
3912 i
++; // skip vs_link_dll or vs_link_exe
3913 command
.push_back(*i
);
3914 i
++; // move past link command
3915 for(; i
!= args
.end(); ++i
)
3917 command
.push_back(*i
);
3918 if(i
->find("/Fe") == 0)
3920 targetName
= i
->substr(3);
3922 if(i
->find("/out:") == 0)
3924 targetName
= i
->substr(5);
3927 if(targetName
.size() == 0 || command
.size() == 0)
3934 bool cmake::RunCommand(const char* comment
,
3935 std::vector
<cmStdString
>& command
,
3941 std::cout
<< comment
<< ":\n";
3942 for(std::vector
<cmStdString
>::iterator i
= command
.begin();
3943 i
!= command
.end(); ++i
)
3945 std::cout
<< i
->c_str() << " ";
3951 // use rc command to create .res file
3952 cmSystemTools::RunSingleCommand(command
,
3954 &retCode
, 0, false);
3955 // always print the output of the command, unless
3956 // it is the dumb rc command banner, but if the command
3957 // returned an error code then print the output anyway as
3958 // the banner may be mixed with some other important information.
3959 if(output
.find("Resource Compiler Version") == output
.npos
3962 std::cout
<< output
;
3964 // if retCodeOut is requested then always return true
3965 // and set the retCodeOut to retCode
3968 *retCodeOut
= retCode
;
3973 std::cout
<< comment
<< " failed. with " << retCode
<< "\n";
3975 return retCode
== 0;
3978 int cmake::VisualStudioLinkIncremental(std::vector
<std::string
>& args
,
3979 int type
, bool verbose
)
3981 // This follows the steps listed here:
3982 // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
3984 // 1. Compiler compiles the application and generates the *.obj files.
3985 // 2. An empty manifest file is generated if this is a clean build and if
3986 // not the previous one is reused.
3987 // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
3989 // 4. Linker generates the binary (EXE or DLL) with the /incremental
3990 // switch and embeds the dummy manifest file. The linker also generates
3991 // the real manifest file based on the binaries that your binary depends
3993 // 5. The manifest tool (mt.exe) is then used to generate the final
3996 // If the final manifest is changed, then 6 and 7 are run, if not
3997 // they are skipped, and it is done.
3999 // 6. The resource compiler is invoked one more time.
4000 // 7. Finally, the Linker does another incremental link, but since the
4001 // only thing that has changed is the *.res file that contains the
4002 // manifest it is a short link.
4003 std::vector
<cmStdString
> linkCommand
;
4004 std::string targetName
;
4005 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
4009 std::string manifestArg
= "/MANIFESTFILE:";
4010 std::vector
<cmStdString
> rcCommand
;
4011 rcCommand
.push_back(cmSystemTools::FindProgram("rc.exe"));
4012 std::vector
<cmStdString
> mtCommand
;
4013 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
4014 std::string tempManifest
;
4015 tempManifest
= targetName
;
4016 tempManifest
+= ".intermediate.manifest";
4017 std::string resourceInputFile
= targetName
;
4018 resourceInputFile
+= ".resource.txt";
4021 std::cout
<< "Create " << resourceInputFile
.c_str() << "\n";
4023 // Create input file for rc command
4024 std::ofstream
fout(resourceInputFile
.c_str());
4029 std::string manifestFile
= targetName
;
4030 manifestFile
+= ".embed.manifest";
4031 std::string fullPath
= cmSystemTools::CollapseFullPath(manifestFile
.c_str());
4032 fout
<< type
<< " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
4033 "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath
.c_str() << "\"";
4035 manifestArg
+= tempManifest
;
4036 // add the manifest arg to the linkCommand
4037 linkCommand
.push_back(manifestArg
);
4038 // if manifestFile is not yet created, create an
4040 if(!cmSystemTools::FileExists(manifestFile
.c_str()))
4044 std::cout
<< "Create empty: " << manifestFile
.c_str() << "\n";
4046 std::ofstream
foutTmp(manifestFile
.c_str());
4048 std::string resourceFile
= manifestFile
;
4049 resourceFile
+= ".res";
4050 // add the resource file to the end of the link command
4051 linkCommand
.push_back(resourceFile
);
4052 std::string outputOpt
= "/fo";
4053 outputOpt
+= resourceFile
;
4054 rcCommand
.push_back(outputOpt
);
4055 rcCommand
.push_back(resourceInputFile
);
4056 // Run rc command to create resource
4057 if(!cmake::RunCommand("RC Pass 1", rcCommand
, verbose
))
4061 // Now run the link command to link and create manifest
4062 if(!cmake::RunCommand("LINK Pass 1", linkCommand
, verbose
))
4066 // create mt command
4067 std::string
outArg("/out:");
4068 outArg
+= manifestFile
;
4069 mtCommand
.push_back("/nologo");
4070 mtCommand
.push_back(outArg
);
4071 mtCommand
.push_back("/notify_update");
4072 mtCommand
.push_back("/manifest");
4073 mtCommand
.push_back(tempManifest
);
4074 // now run mt.exe to create the final manifest file
4076 cmake::RunCommand("MT", mtCommand
, verbose
, &mtRet
);
4077 // if mt returns 0, then the manifest was not changed and
4078 // we do not need to do another link step
4083 // check for magic mt return value if mt returns the magic number
4084 // 1090650113 then it means that it updated the manifest file and we need
4085 // to do the final link. If mt has any value other than 0 or 1090650113
4086 // then there was some problem with the command itself and there was an
4087 // error so return the error code back out of cmake so make can report it.
4088 if(mtRet
!= 1090650113)
4092 // update the resource file with the new manifest from the mt command.
4093 if(!cmake::RunCommand("RC Pass 2", rcCommand
, verbose
))
4097 // Run the final incremental link that will put the new manifest resource
4098 // into the file incrementally.
4099 if(!cmake::RunCommand("FINAL LINK", linkCommand
, verbose
))
4106 int cmake::VisualStudioLinkNonIncremental(std::vector
<std::string
>& args
,
4110 std::vector
<cmStdString
> linkCommand
;
4111 std::string targetName
;
4112 if(cmake::ParseVisualStudioLinkCommand(args
, linkCommand
, targetName
) == -1)
4116 // Run the link command as given
4117 if(!cmake::RunCommand("LINK", linkCommand
, verbose
))
4121 std::vector
<cmStdString
> mtCommand
;
4122 mtCommand
.push_back(cmSystemTools::FindProgram("mt.exe"));
4123 mtCommand
.push_back("/nologo");
4124 mtCommand
.push_back("/manifest");
4125 std::string manifestFile
= targetName
;
4126 manifestFile
+= ".manifest";
4127 mtCommand
.push_back(manifestFile
);
4128 std::string outresource
= "/outputresource:";
4129 outresource
+= targetName
;
4130 outresource
+= ";#";
4139 mtCommand
.push_back(outresource
);
4140 // Now use the mt tool to embed the manifest into the exe or dll
4141 if(!cmake::RunCommand("MT", mtCommand
, verbose
))
4148 //----------------------------------------------------------------------------
4149 void cmake::IssueMessage(cmake::MessageType t
, std::string
const& text
,
4150 cmListFileBacktrace
const& backtrace
)
4152 cmOStringStream msg
;
4153 bool isError
= false;
4154 // Construct the message header.
4155 if(t
== cmake::FATAL_ERROR
)
4158 msg
<< "CMake Error";
4160 else if(t
== cmake::INTERNAL_ERROR
)
4163 msg
<< "CMake Internal Error (please report a bug)";
4167 msg
<< "CMake Warning";
4168 if(t
== cmake::AUTHOR_WARNING
)
4170 // Allow suppression of these warnings.
4171 cmCacheManager::CacheIterator it
= this->CacheManager
4172 ->GetCacheIterator("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
4173 if(!it
.IsAtEnd() && it
.GetValueAsBool())
4181 // Add the immediate context.
4182 cmListFileBacktrace::const_iterator i
= backtrace
.begin();
4183 if(i
!= backtrace
.end())
4185 cmListFileContext
const& lfc
= *i
;
4186 msg
<< (lfc
.Line
? " at ": " in ") << lfc
;
4190 // Add the message text.
4193 cmDocumentationFormatterText formatter
;
4194 formatter
.SetIndent(" ");
4195 formatter
.PrintFormatted(msg
, text
.c_str());
4198 // Add the rest of the context.
4199 if(i
!= backtrace
.end())
4201 msg
<< "Call Stack (most recent call first):\n";
4202 while(i
!= backtrace
.end())
4204 cmListFileContext
const& lfc
= *i
;
4205 msg
<< " " << lfc
<< "\n";
4210 // Add a note about warning suppression.
4211 if(t
== cmake::AUTHOR_WARNING
)
4214 "This warning is for project developers. Use -Wno-dev to suppress it.";
4217 // Add a terminating blank line.
4220 // Output the message.
4223 cmSystemTools::SetErrorOccured();
4224 cmSystemTools::Message(msg
.str().c_str(), "Error");
4228 cmSystemTools::Message(msg
.str().c_str(), "Warning");