1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
13 #include "cmDocumentVariables.h"
15 #include "cmCacheManager.h"
16 #include "cmMakefile.h"
17 #include "cmLocalGenerator.h"
18 #include "cmExternalMakefileProjectGenerator.h"
19 #include "cmCommands.h"
20 #include "cmCommand.h"
21 #include "cmFileTimeComparison.h"
22 #include "cmGeneratedFileStream.h"
23 #include "cmQtAutomoc.h"
24 #include "cmSourceFile.h"
25 #include "cmVersion.h"
27 #include "cmDocumentationFormatterText.h"
29 #if defined(CMAKE_BUILD_WITH_CMAKE)
30 # include "cmGraphVizWriter.h"
31 # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
32 # include "cmVariableWatch.h"
33 # include <cmsys/Terminal.h>
34 # include <cmsys/CommandLineArguments.hxx>
37 #include <cmsys/Directory.hxx>
38 #include <cmsys/Process.h>
39 #include <cmsys/Glob.hxx>
40 #include <cmsys/RegularExpression.hxx>
42 // only build kdevelop generator on non-windows platforms
43 // when not bootstrapping cmake
45 # if defined(CMAKE_BUILD_WITH_CMAKE)
46 # define CMAKE_USE_KDEVELOP
50 #if defined(CMAKE_BUILD_WITH_CMAKE)
51 # define CMAKE_USE_ECLIPSE
54 #if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
55 # define CMAKE_BOOT_MINGW
58 // include the generator
59 #if defined(_WIN32) && !defined(__CYGWIN__)
60 # if !defined(CMAKE_BOOT_MINGW)
61 # include "cmGlobalVisualStudio6Generator.h"
62 # include "cmGlobalVisualStudio7Generator.h"
63 # include "cmGlobalVisualStudio71Generator.h"
64 # include "cmGlobalVisualStudio8Generator.h"
65 # include "cmGlobalVisualStudio9Generator.h"
66 # include "cmGlobalVisualStudio10Generator.h"
67 # include "cmGlobalVisualStudio11Generator.h"
68 # include "cmGlobalVisualStudio12Generator.h"
69 # include "cmGlobalBorlandMakefileGenerator.h"
70 # include "cmGlobalNMakeMakefileGenerator.h"
71 # include "cmGlobalJOMMakefileGenerator.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"
81 #include "cmGlobalNinjaGenerator.h"
84 #if defined(CMAKE_HAVE_VS_GENERATORS)
85 #include "cmCallVisualStudioMacro.h"
86 #include "cmVisualStudioWCEPlatformParser.h"
89 #if !defined(CMAKE_BOOT_MINGW)
90 # include "cmExtraCodeBlocksGenerator.h"
92 #include "cmExtraSublimeTextGenerator.h"
94 #ifdef CMAKE_USE_KDEVELOP
95 # include "cmGlobalKdevelopGenerator.h"
98 #ifdef CMAKE_USE_ECLIPSE
99 # include "cmExtraEclipseCDT4Generator.h"
102 #include <stdlib.h> // required for atoi
104 #if defined( __APPLE__ )
105 # if defined(CMAKE_BUILD_WITH_CMAKE)
106 # include "cmGlobalXCodeGenerator.h"
107 # define CMAKE_USE_XCODE 1
109 # include <sys/types.h>
110 # include <sys/time.h>
111 # include <sys/resource.h>
114 #include <sys/stat.h> // struct stat
116 static bool cmakeCheckStampFile(const char* stampName);
117 static bool cmakeCheckStampList(const char* stampName);
119 void cmNeedBackwardsCompatibility(const std::string& variable,
120 int access_type, void*, const char*, const cmMakefile*)
122 #ifdef CMAKE_BUILD_WITH_CMAKE
123 if (access_type == cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS)
125 std::string message = "An attempt was made to access a variable: ";
128 " that has not been defined. Some variables were always defined "
129 "by CMake in versions prior to 1.6. To fix this you might need to set "
130 "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
131 "you are writing a CMakeLists file, (or have already set "
132 "CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less) then you probably need "
133 "to include a CMake module to test for the feature this variable "
135 cmSystemTools::Error(message.c_str());
143 void cmWarnUnusedCliWarning(const std::string& variable,
144 int, void* ctx, const char*, const cmMakefile*)
146 cmake* cm = reinterpret_cast<cmake*>(ctx);
147 cm->MarkCliAsUsed(variable);
153 this->WarnUninitialized = false;
154 this->WarnUnused = false;
155 this->WarnUnusedCli = true;
156 this->CheckSystemVars = false;
157 this->SuppressDevWarnings = false;
158 this->DoSuppressDevWarnings = false;
159 this->DebugOutput = false;
160 this->DebugTryCompile = false;
161 this->ClearBuildSystem = false;
162 this->FileComparison = new cmFileTimeComparison;
164 this->Policies = new cmPolicies();
165 this->InitializeProperties();
169 if(!getrlimit(RLIMIT_STACK, &rlp))
171 if(rlp.rlim_cur != rlp.rlim_max)
173 rlp.rlim_cur = rlp.rlim_max;
174 setrlimit(RLIMIT_STACK, &rlp);
179 this->Verbose = false;
180 this->InTryCompile = false;
181 this->CacheManager = new cmCacheManager(this);
182 this->GlobalGenerator = 0;
183 this->ProgressCallback = 0;
184 this->ProgressCallbackClientData = 0;
185 this->CurrentWorkingMode = NORMAL_MODE;
187 #ifdef CMAKE_BUILD_WITH_CMAKE
188 this->VariableWatch = new cmVariableWatch;
189 this->VariableWatch->AddWatch("CMAKE_WORDS_BIGENDIAN",
190 cmNeedBackwardsCompatibility);
191 this->VariableWatch->AddWatch("CMAKE_SIZEOF_INT",
192 cmNeedBackwardsCompatibility);
193 this->VariableWatch->AddWatch("CMAKE_X_LIBS",
194 cmNeedBackwardsCompatibility);
197 this->AddDefaultGenerators();
198 this->AddDefaultExtraGenerators();
199 this->AddDefaultCommands();
201 // Make sure we can capture the build tool output.
202 cmSystemTools::EnableVSConsoleOutput();
207 delete this->CacheManager;
208 delete this->Policies;
209 if (this->GlobalGenerator)
211 delete this->GlobalGenerator;
212 this->GlobalGenerator = 0;
214 for(RegisteredCommandsMap::iterator j = this->Commands.begin();
215 j != this->Commands.end(); ++j)
219 for(RegisteredGeneratorsVector::iterator j = this->Generators.begin();
220 j != this->Generators.end(); ++j)
224 #ifdef CMAKE_BUILD_WITH_CMAKE
225 delete this->VariableWatch;
227 delete this->FileComparison;
230 void cmake::InitializeProperties()
232 this->Properties.clear();
233 this->Properties.SetCMakeInstance(this);
234 this->AccessedProperties.clear();
235 this->PropertyDefinitions.clear();
237 // initialize properties
238 cmCacheManager::DefineProperties(this);
239 cmSourceFile::DefineProperties(this);
240 cmTarget::DefineProperties(this);
241 cmMakefile::DefineProperties(this);
242 cmTest::DefineProperties(this);
243 cmake::DefineProperties(this);
246 void cmake::CleanupCommandsAndMacros()
248 this->InitializeProperties();
249 std::vector<cmCommand*> commands;
250 for(RegisteredCommandsMap::iterator j = this->Commands.begin();
251 j != this->Commands.end(); ++j)
253 if ( !j->second->IsA("cmMacroHelperCommand") &&
254 !j->second->IsA("cmFunctionHelperCommand"))
256 commands.push_back(j->second);
263 this->Commands.erase(this->Commands.begin(), this->Commands.end());
264 std::vector<cmCommand*>::iterator it;
265 for ( it = commands.begin(); it != commands.end();
268 this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
272 bool cmake::CommandExists(const char* name) const
274 std::string sName = cmSystemTools::LowerCase(name);
275 return (this->Commands.find(sName) != this->Commands.end());
278 cmCommand *cmake::GetCommand(const char *name)
281 std::string sName = cmSystemTools::LowerCase(name);
282 RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
283 if (pos != this->Commands.end())
290 void cmake::RenameCommand(const char*oldName, const char* newName)
292 // if the command already exists, free the old one
293 std::string sOldName = cmSystemTools::LowerCase(oldName);
294 std::string sNewName = cmSystemTools::LowerCase(newName);
295 RegisteredCommandsMap::iterator pos = this->Commands.find(sOldName);
296 if ( pos == this->Commands.end() )
300 cmCommand* cmd = pos->second;
302 pos = this->Commands.find(sNewName);
303 if (pos != this->Commands.end())
306 this->Commands.erase(pos);
308 this->Commands.insert(RegisteredCommandsMap::value_type(sNewName, cmd));
309 pos = this->Commands.find(sOldName);
310 this->Commands.erase(pos);
313 void cmake::RemoveCommand(const char* name)
315 std::string sName = cmSystemTools::LowerCase(name);
316 RegisteredCommandsMap::iterator pos = this->Commands.find(sName);
317 if ( pos != this->Commands.end() )
320 this->Commands.erase(pos);
324 void cmake::AddCommand(cmCommand* wg)
326 std::string name = cmSystemTools::LowerCase(wg->GetName());
327 // if the command already exists, free the old one
328 RegisteredCommandsMap::iterator pos = this->Commands.find(name);
329 if (pos != this->Commands.end())
332 this->Commands.erase(pos);
334 this->Commands.insert( RegisteredCommandsMap::value_type(name, wg));
338 void cmake::RemoveUnscriptableCommands()
340 std::vector<std::string> unscriptableCommands;
341 cmake::RegisteredCommandsMap* commands = this->GetCommands();
342 for (cmake::RegisteredCommandsMap::const_iterator pos = commands->begin();
343 pos != commands->end();
346 if (!pos->second->IsScriptable())
348 unscriptableCommands.push_back(pos->first);
352 for(std::vector<std::string>::const_iterator it=unscriptableCommands.begin();
353 it != unscriptableCommands.end();
356 this->RemoveCommand(it->c_str());
361 bool cmake::SetCacheArgs(const std::vector<std::string>& args)
363 bool findPackageMode = false;
364 for(unsigned int i=1; i < args.size(); ++i)
366 std::string arg = args[i];
367 if(arg.find("-D",0) == 0)
369 std::string entry = arg.substr(2);
370 if(entry.size() == 0)
379 cmSystemTools::Error("-D must be followed with VAR=VALUE.");
383 std::string var, value;
384 cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
385 if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
387 // The value is transformed if it is a filepath for example, so
388 // we can't compare whether the value is already in the cache until
389 // after we call AddCacheEntry.
390 const char *cachedValue =
391 this->CacheManager->GetCacheValue(var.c_str());
393 this->CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
394 "No help, variable specified on the command line.", type);
395 if(this->WarnUnusedCli)
398 || strcmp(this->CacheManager->GetCacheValue(var.c_str()),
401 this->WatchUnusedCli(var.c_str());
407 std::cerr << "Parse error in command line argument: " << arg << "\n"
408 << "Should be: VAR:type=value\n";
409 cmSystemTools::Error("No cmake script provided.");
413 else if(arg.find("-Wno-dev",0) == 0)
415 this->SuppressDevWarnings = true;
416 this->DoSuppressDevWarnings = true;
418 else if(arg.find("-Wdev",0) == 0)
420 this->SuppressDevWarnings = false;
421 this->DoSuppressDevWarnings = true;
423 else if(arg.find("-U",0) == 0)
425 std::string entryPattern = arg.substr(2);
426 if(entryPattern.size() == 0)
431 entryPattern = args[i];
435 cmSystemTools::Error("-U must be followed with VAR.");
439 cmsys::RegularExpression regex(
440 cmsys::Glob::PatternToRegex(entryPattern.c_str(), true, true).c_str());
441 //go through all cache entries and collect the vars which will be removed
442 std::vector<std::string> entriesToDelete;
443 cmCacheManager::CacheIterator it =
444 this->CacheManager->GetCacheIterator();
445 for ( it.Begin(); !it.IsAtEnd(); it.Next() )
447 cmCacheManager::CacheEntryType t = it.GetType();
448 if(t != cmCacheManager::STATIC)
450 std::string entryName = it.GetName();
451 if (regex.find(entryName.c_str()))
453 entriesToDelete.push_back(entryName);
458 // now remove them from the cache
459 for(std::vector<std::string>::const_iterator currentEntry =
460 entriesToDelete.begin();
461 currentEntry != entriesToDelete.end();
464 this->CacheManager->RemoveCacheEntry(currentEntry->c_str());
467 else if(arg.find("-C",0) == 0)
469 std::string path = arg.substr(2);
470 if ( path.size() == 0 )
479 cmSystemTools::Error("-C must be followed by a file name.");
483 std::cerr << "loading initial cache file " << path.c_str() << "\n";
484 this->ReadListFile(args, path.c_str());
486 else if(arg.find("-P",0) == 0)
491 cmSystemTools::Error("-P must be followed by a file name.");
494 std::string path = args[i];
495 if ( path.size() == 0 )
497 cmSystemTools::Error("No cmake script provided.");
500 this->ReadListFile(args, path.c_str());
502 else if (arg.find("--find-package",0) == 0)
504 findPackageMode = true;
510 return this->FindPackage(args);
516 void cmake::ReadListFile(const std::vector<std::string>& args,
519 // if a generator was not yet created, temporarily create one
520 cmGlobalGenerator *gg = this->GetGlobalGenerator();
521 bool created = false;
523 // if a generator was not specified use a generic one
526 gg = new cmGlobalGenerator;
527 gg->SetCMakeInstance(this);
531 // read in the list file to fill the cache
534 cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
535 lg->GetMakefile()->SetHomeOutputDirectory
536 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
537 lg->GetMakefile()->SetStartOutputDirectory
538 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
539 lg->GetMakefile()->SetHomeDirectory
540 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
541 lg->GetMakefile()->SetStartDirectory
542 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
543 if (this->GetWorkingMode() != NORMAL_MODE)
545 std::string file(cmSystemTools::CollapseFullPath(path));
546 cmSystemTools::ConvertToUnixSlashes(file);
547 lg->GetMakefile()->SetScriptModeFile(file.c_str());
549 lg->GetMakefile()->SetArgcArgv(args);
551 if (!lg->GetMakefile()->ReadListFile(0, path))
553 cmSystemTools::Error("Error processing file: ", path);
557 // free generic one if generated
565 bool cmake::FindPackage(const std::vector<std::string>& args)
567 // if a generator was not yet created, temporarily create one
568 cmGlobalGenerator *gg = new cmGlobalGenerator;
569 gg->SetCMakeInstance(this);
570 this->SetGlobalGenerator(gg);
572 // read in the list file to fill the cache
573 cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
574 cmMakefile* mf = lg->GetMakefile();
575 mf->SetHomeOutputDirectory
576 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
577 mf->SetStartOutputDirectory
578 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
580 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
581 mf->SetStartDirectory
582 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
584 mf->SetArgcArgv(args);
586 std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake");
587 mf->ReadListFile(0, systemFile.c_str());
589 std::string language = mf->GetSafeDefinition("LANGUAGE");
590 std::string mode = mf->GetSafeDefinition("MODE");
591 std::string packageName = mf->GetSafeDefinition("NAME");
592 bool packageFound = mf->IsOn("PACKAGE_FOUND");
593 bool quiet = mf->IsOn("PACKAGE_QUIET");
599 printf("%s not found.\n", packageName.c_str());
602 else if (mode == "EXIST")
606 printf("%s found.\n", packageName.c_str());
609 else if (mode == "COMPILE")
611 std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS");
612 std::vector<std::string> includeDirs;
613 cmSystemTools::ExpandListArgument(includes, includeDirs);
615 std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0,
616 language.c_str(), false);
618 std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
619 printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
621 else if (mode == "LINK")
623 const char* targetName = "dummy";
624 std::vector<std::string> srcs;
625 cmTarget* tgt = mf->AddExecutable(targetName, srcs, true);
626 tgt->SetProperty("LINKER_LANGUAGE", language.c_str());
628 std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES");
629 std::vector<std::string> libList;
630 cmSystemTools::ExpandListArgument(libs, libList);
631 for(std::vector<std::string>::const_iterator libIt=libList.begin();
632 libIt != libList.end();
635 mf->AddLinkLibraryForTarget(targetName, libIt->c_str(),
640 std::string linkLibs;
641 std::string frameworkPath;
642 std::string linkPath;
644 std::string linkFlags;
645 cmGeneratorTarget gtgt(tgt);
646 lg->GetTargetFlags(linkLibs, frameworkPath, linkPath, flags, linkFlags,
648 linkLibs = frameworkPath + linkPath + linkLibs;
650 printf("%s\n", linkLibs.c_str() );
654 tgt->SetProperty("WIN32_EXECUTABLE", "ON");
658 tgt->SetProperty("MACOSX_BUNDLE", "ON");
662 // free generic one if generated
663 // this->SetGlobalGenerator(0); // setting 0-pointer is not possible
664 // delete gg; // this crashes inside the cmake instance
671 void cmake::SetArgs(const std::vector<std::string>& args,
672 bool directoriesSetBefore)
674 bool directoriesSet = directoriesSetBefore;
675 bool haveToolset = false;
676 for(unsigned int i=1; i < args.size(); ++i)
678 std::string arg = args[i];
679 if(arg.find("-H",0) == 0)
681 directoriesSet = true;
682 std::string path = arg.substr(2);
683 path = cmSystemTools::CollapseFullPath(path.c_str());
684 cmSystemTools::ConvertToUnixSlashes(path);
685 this->SetHomeDirectory(path.c_str());
687 else if(arg.find("-S",0) == 0)
689 // There is no local generate anymore. Ignore -S option.
691 else if(arg.find("-O",0) == 0)
693 // There is no local generate anymore. Ignore -O option.
695 else if(arg.find("-B",0) == 0)
697 directoriesSet = true;
698 std::string path = arg.substr(2);
699 path = cmSystemTools::CollapseFullPath(path.c_str());
700 cmSystemTools::ConvertToUnixSlashes(path);
701 this->SetHomeOutputDirectory(path.c_str());
703 else if((i < args.size()-1) && (arg.find("--check-build-system",0) == 0))
705 this->CheckBuildSystemArgument = args[++i];
706 this->ClearBuildSystem = (atoi(args[++i].c_str()) > 0);
708 else if((i < args.size()-1) && (arg.find("--check-stamp-file",0) == 0))
710 this->CheckStampFile = args[++i];
712 else if((i < args.size()-1) && (arg.find("--check-stamp-list",0) == 0))
714 this->CheckStampList = args[++i];
716 #if defined(CMAKE_HAVE_VS_GENERATORS)
717 else if((i < args.size()-1) && (arg.find("--vs-solution-file",0) == 0))
719 this->VSSolutionFile = args[++i];
722 else if(arg.find("-V",0) == 0)
724 this->Verbose = true;
726 else if(arg.find("-D",0) == 0)
730 else if(arg.find("-U",0) == 0)
734 else if(arg.find("-C",0) == 0)
738 else if(arg.find("-P",0) == 0)
743 else if(arg.find("--find-package",0) == 0)
748 else if(arg.find("-Wno-dev",0) == 0)
752 else if(arg.find("-Wdev",0) == 0)
756 else if(arg.find("--graphviz=",0) == 0)
758 std::string path = arg.substr(strlen("--graphviz="));
759 path = cmSystemTools::CollapseFullPath(path.c_str());
760 cmSystemTools::ConvertToUnixSlashes(path);
761 this->GraphVizFile = path;
762 if ( this->GraphVizFile.empty() )
764 cmSystemTools::Error("No file specified for --graphviz");
767 else if(arg.find("--debug-trycompile",0) == 0)
769 std::cout << "debug trycompile on\n";
770 this->DebugTryCompileOn();
772 else if(arg.find("--debug-output",0) == 0)
774 std::cout << "Running with debug output on.\n";
775 this->SetDebugOutputOn(true);
777 else if(arg.find("--trace",0) == 0)
779 std::cout << "Running with trace output on.\n";
780 this->SetTrace(true);
782 else if(arg.find("--warn-uninitialized",0) == 0)
784 std::cout << "Warn about uninitialized values.\n";
785 this->SetWarnUninitialized(true);
787 else if(arg.find("--warn-unused-vars",0) == 0)
789 std::cout << "Finding unused variables.\n";
790 this->SetWarnUnused(true);
792 else if(arg.find("--no-warn-unused-cli",0) == 0)
794 std::cout << "Not searching for unused variables given on the " <<
796 this->SetWarnUnusedCli(false);
798 else if(arg.find("--check-system-vars",0) == 0)
800 std::cout << "Also check system files when warning about unused and " <<
801 "uninitialized variables.\n";
802 this->SetCheckSystemVars(true);
804 else if(arg.find("-T",0) == 0)
806 std::string value = arg.substr(2);
807 if(value.size() == 0)
812 cmSystemTools::Error("No toolset specified for -T");
819 cmSystemTools::Error("Multiple -T options not allowed");
822 this->GeneratorToolset = value;
825 else if(arg.find("-G",0) == 0)
827 std::string value = arg.substr(2);
828 if(value.size() == 0)
833 cmSystemTools::Error("No generator specified for -G");
838 cmGlobalGenerator* gen =
839 this->CreateGlobalGenerator(value.c_str());
842 cmSystemTools::Error("Could not create named generator ",
847 this->SetGlobalGenerator(gen);
850 // no option assume it is the path to the source
853 directoriesSet = true;
854 this->SetDirectoriesFromFile(arg.c_str());
859 this->SetHomeOutputDirectory
860 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
861 this->SetStartOutputDirectory
862 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
863 this->SetHomeDirectory
864 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
865 this->SetStartDirectory
866 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
869 this->SetStartDirectory(this->GetHomeDirectory());
870 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
873 //----------------------------------------------------------------------------
874 void cmake::SetDirectoriesFromFile(const char* arg)
876 // Check if the argument refers to a CMakeCache.txt or
877 // CMakeLists.txt file.
878 std::string listPath;
879 std::string cachePath;
880 bool argIsFile = false;
881 if(cmSystemTools::FileIsDirectory(arg))
883 std::string path = cmSystemTools::CollapseFullPath(arg);
884 cmSystemTools::ConvertToUnixSlashes(path);
885 std::string cacheFile = path;
886 cacheFile += "/CMakeCache.txt";
887 std::string listFile = path;
888 listFile += "/CMakeLists.txt";
889 if(cmSystemTools::FileExists(cacheFile.c_str()))
893 if(cmSystemTools::FileExists(listFile.c_str()))
898 else if(cmSystemTools::FileExists(arg))
901 std::string fullPath = cmSystemTools::CollapseFullPath(arg);
902 std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
903 name = cmSystemTools::LowerCase(name);
904 if(name == "cmakecache.txt")
906 cachePath = cmSystemTools::GetFilenamePath(fullPath.c_str());
908 else if(name == "cmakelists.txt")
910 listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
915 // Specified file or directory does not exist. Try to set things
916 // up to produce a meaningful error message.
917 std::string fullPath = cmSystemTools::CollapseFullPath(arg);
918 std::string name = cmSystemTools::GetFilenameName(fullPath.c_str());
919 name = cmSystemTools::LowerCase(name);
920 if(name == "cmakecache.txt" || name == "cmakelists.txt")
923 listPath = cmSystemTools::GetFilenamePath(fullPath.c_str());
931 // If there is a CMakeCache.txt file, use its settings.
932 if(cachePath.length() > 0)
934 cmCacheManager* cachem = this->GetCacheManager();
935 cmCacheManager::CacheIterator it = cachem->NewIterator();
936 if(cachem->LoadCache(cachePath.c_str()) &&
937 it.Find("CMAKE_HOME_DIRECTORY"))
939 this->SetHomeOutputDirectory(cachePath.c_str());
940 this->SetStartOutputDirectory(cachePath.c_str());
941 this->SetHomeDirectory(it.GetValue());
942 this->SetStartDirectory(it.GetValue());
947 // If there is a CMakeLists.txt file, use it as the source tree.
948 if(listPath.length() > 0)
950 this->SetHomeDirectory(listPath.c_str());
951 this->SetStartDirectory(listPath.c_str());
955 // Source CMakeLists.txt file given. It was probably dropped
956 // onto the executable in a GUI. Default to an in-source build.
957 this->SetHomeOutputDirectory(listPath.c_str());
958 this->SetStartOutputDirectory(listPath.c_str());
962 // Source directory given on command line. Use current working
963 // directory as build tree.
964 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
965 this->SetHomeOutputDirectory(cwd.c_str());
966 this->SetStartOutputDirectory(cwd.c_str());
971 // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
972 // argument. Assume it is the path to the source tree, and use the
973 // current working directory as the build tree.
974 std::string full = cmSystemTools::CollapseFullPath(arg);
975 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
976 this->SetHomeDirectory(full.c_str());
977 this->SetStartDirectory(full.c_str());
978 this->SetHomeOutputDirectory(cwd.c_str());
979 this->SetStartOutputDirectory(cwd.c_str());
982 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
984 int cmake::AddCMakePaths()
986 // Find the cmake executable
987 std::string cMakeSelf = cmSystemTools::GetExecutableDirectory();
988 cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
989 cMakeSelf += "/cmake";
990 cMakeSelf += cmSystemTools::GetExecutableExtension();
992 // on the apple this might be the gui bundle
993 if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
995 cMakeSelf = cmSystemTools::GetExecutableDirectory();
996 cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
997 cMakeSelf += "../../../..";
998 cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
999 cMakeSelf = cmSystemTools::CollapseFullPath(cMakeSelf.c_str());
1000 cMakeSelf += "/cmake";
1001 std::cerr << cMakeSelf.c_str() << "\n";
1004 if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
1006 cmSystemTools::Error("CMake executable cannot be found at ",
1010 // Save the value in the cache
1011 this->CacheManager->AddCacheEntry
1012 ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
1013 cmCacheManager::INTERNAL);
1014 // if the edit command is not yet in the cache,
1015 // or if CMakeEditCommand has been set on this object,
1016 // then set the CMAKE_EDIT_COMMAND in the cache
1017 // This will mean that the last gui to edit the cache
1018 // will be the one that make edit_cache uses.
1019 if(!this->GetCacheDefinition("CMAKE_EDIT_COMMAND")
1020 || !this->CMakeEditCommand.empty())
1022 // Find and save the command to edit the cache
1023 std::string editCacheCommand;
1024 if(!this->CMakeEditCommand.empty())
1026 editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf)
1028 + this->CMakeEditCommand
1029 + cmSystemTools::GetFilenameExtension(cMakeSelf);
1031 if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
1033 editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1034 "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1036 if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
1038 editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1039 "/cmake-gui" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1041 if(cmSystemTools::FileExists(editCacheCommand.c_str()))
1043 this->CacheManager->AddCacheEntry
1044 ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
1045 "Path to cache edit program executable.", cmCacheManager::INTERNAL);
1048 std::string ctestCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1049 "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1050 if(cmSystemTools::FileExists(ctestCommand.c_str()))
1052 this->CacheManager->AddCacheEntry
1053 ("CMAKE_CTEST_COMMAND", ctestCommand.c_str(),
1054 "Path to ctest program executable.", cmCacheManager::INTERNAL);
1056 std::string cpackCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
1057 "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf);
1058 if(cmSystemTools::FileExists(cpackCommand.c_str()))
1060 this->CacheManager->AddCacheEntry
1061 ("CMAKE_CPACK_COMMAND", cpackCommand.c_str(),
1062 "Path to cpack program executable.", cmCacheManager::INTERNAL);
1065 // do CMAKE_ROOT, look for the environment variable first
1066 std::string cMakeRoot;
1067 std::string modules;
1068 if (getenv("CMAKE_ROOT"))
1070 cMakeRoot = getenv("CMAKE_ROOT");
1071 modules = cMakeRoot + "/Modules/CMake.cmake";
1073 if(!cmSystemTools::FileExists(modules.c_str()))
1076 cMakeRoot = cmSystemTools::GetRealPath(cMakeSelf.c_str());
1077 cMakeRoot = cmSystemTools::GetProgramPath(cMakeRoot.c_str());
1078 std::string::size_type slashPos = cMakeRoot.rfind("/");
1079 if(slashPos != std::string::npos)
1081 cMakeRoot = cMakeRoot.substr(0, slashPos);
1083 // is there no Modules directory there?
1084 modules = cMakeRoot + "/Modules/CMake.cmake";
1087 if (!cmSystemTools::FileExists(modules.c_str()))
1089 // try exe/../share/cmake
1090 cMakeRoot += CMAKE_DATA_DIR;
1091 modules = cMakeRoot + "/Modules/CMake.cmake";
1093 #ifdef CMAKE_ROOT_DIR
1094 if (!cmSystemTools::FileExists(modules.c_str()))
1096 // try compiled in root directory
1097 cMakeRoot = CMAKE_ROOT_DIR;
1098 modules = cMakeRoot + "/Modules/CMake.cmake";
1101 if (!cmSystemTools::FileExists(modules.c_str()))
1104 cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
1105 cMakeRoot += CMAKE_DATA_DIR;
1106 modules = cMakeRoot + "/Modules/CMake.cmake";
1108 if(!cmSystemTools::FileExists(modules.c_str()))
1111 cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
1112 // is there no Modules directory there?
1113 modules = cMakeRoot + "/Modules/CMake.cmake";
1115 if (!cmSystemTools::FileExists(modules.c_str()))
1117 // couldn't find modules
1118 cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n"
1119 "CMake has most likely not been installed correctly.\n"
1120 "Modules directory not found in\n",
1124 this->CacheManager->AddCacheEntry
1125 ("CMAKE_ROOT", cMakeRoot.c_str(),
1126 "Path to CMake installation.", cmCacheManager::INTERNAL);
1129 std::string comspec = "cmw9xcom.exe";
1130 cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
1137 void CMakeCommandUsage(const char* program)
1139 cmOStringStream errorStream;
1141 #ifdef CMAKE_BUILD_WITH_CMAKE
1143 << "cmake version " << cmVersion::GetCMakeVersion() << "\n";
1146 << "cmake bootstrap\n";
1148 // If you add new commands, change here,
1149 // and in cmakemain.cxx in the options table
1151 << "Usage: " << program << " -E [command] [arguments ...]\n"
1152 << "Available commands: \n"
1153 << " chdir dir cmd [args]... - run command in a given directory\n"
1154 << " compare_files file1 file2 - check if file1 is same as file2\n"
1155 << " copy file destination - copy file to destination (either file "
1157 << " copy_directory source destination - copy directory 'source' "
1158 "content to directory 'destination'\n"
1159 << " copy_if_different in-file out-file - copy file if input has "
1161 << " echo [string]... - displays arguments as text\n"
1162 << " echo_append [string]... - displays arguments as text but no new "
1164 << " environment - display the current environment\n"
1165 << " make_directory dir - create a directory\n"
1166 << " md5sum file1 [...] - compute md5sum of files\n"
1167 << " remove [-f] file1 file2 ... - remove the file(s), use -f to force "
1169 << " remove_directory dir - remove a directory and its contents\n"
1170 << " rename oldname newname - rename a file or directory "
1172 << " tar [cxt][vfz][cvfj] file.tar [file/dir1 file/dir2 ...]\n"
1173 << " - create or extract a tar or zip archive\n"
1174 << " time command [args] ... - run command and return elapsed time\n"
1175 << " touch file - touch a file.\n"
1176 << " touch_nocreate file - touch a file but do not create it.\n"
1177 #if defined(_WIN32) && !defined(__CYGWIN__)
1178 << "Available on Windows only:\n"
1179 << " comspec - on windows 9x use this for RunCommand\n"
1180 << " delete_regv key - delete registry value\n"
1181 << " env_vs8_wince sdkname - displays a batch file which sets the "
1182 "environment for the provided Windows CE SDK installed in VS2005\n"
1183 << " env_vs9_wince sdkname - displays a batch file which sets the "
1184 "environment for the provided Windows CE SDK installed in VS2008\n"
1185 << " write_regv key value - write registry value\n"
1187 << "Available on UNIX only:\n"
1188 << " create_symlink old new - create a symbolic link new -> old\n"
1192 cmSystemTools::Error(errorStream.str().c_str());
1195 int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
1197 // IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
1198 if (args.size() > 1)
1201 if (args[1] == "copy" && args.size() == 4)
1203 if(!cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str()))
1205 std::cerr << "Error copying file \"" << args[2].c_str()
1206 << "\" to \"" << args[3].c_str() << "\".\n";
1212 // Copy file if different.
1213 if (args[1] == "copy_if_different" && args.size() == 4)
1215 if(!cmSystemTools::CopyFileIfDifferent(args[2].c_str(),
1218 std::cerr << "Error copying file (if different) from \""
1219 << args[2].c_str() << "\" to \"" << args[3].c_str()
1226 // Copy directory content
1227 if (args[1] == "copy_directory" && args.size() == 4)
1229 if(!cmSystemTools::CopyADirectory(args[2].c_str(), args[3].c_str()))
1231 std::cerr << "Error copying directory from \""
1232 << args[2].c_str() << "\" to \"" << args[3].c_str()
1239 // Rename a file or directory
1240 if (args[1] == "rename" && args.size() == 4)
1242 if(!cmSystemTools::RenameFile(args[2].c_str(), args[3].c_str()))
1244 std::string e = cmSystemTools::GetLastSystemError();
1245 std::cerr << "Error renaming from \""
1246 << args[2].c_str() << "\" to \"" << args[3].c_str()
1247 << "\": " << e << "\n";
1254 if (args[1] == "compare_files" && args.size() == 4)
1256 if(cmSystemTools::FilesDiffer(args[2].c_str(), args[3].c_str()))
1258 std::cerr << "Files \""
1259 << args[2].c_str() << "\" to \"" << args[3].c_str()
1260 << "\" are different.\n";
1267 else if (args[1] == "echo" )
1270 const char* space = "";
1271 for ( cc = 2; cc < args.size(); cc ++ )
1273 std::cout << space << args[cc];
1276 std::cout << std::endl;
1280 // Echo string no new line
1281 else if (args[1] == "echo_append" )
1284 const char* space = "";
1285 for ( cc = 2; cc < args.size(); cc ++ )
1287 std::cout << space << args[cc];
1293 #if defined(CMAKE_BUILD_WITH_CMAKE)
1294 // Command to create a symbolic link. Fails on platforms not
1296 else if (args[1] == "environment" )
1298 std::vector<std::string> env = cmSystemTools::GetEnvironmentVariables();
1299 std::vector<std::string>::iterator it;
1300 for ( it = env.begin(); it != env.end(); ++ it )
1302 std::cout << it->c_str() << std::endl;
1308 else if (args[1] == "make_directory" && args.size() == 3)
1310 if(!cmSystemTools::MakeDirectory(args[2].c_str()))
1312 std::cerr << "Error making directory \"" << args[2].c_str()
1319 else if (args[1] == "remove_directory" && args.size() == 3)
1321 if(cmSystemTools::FileIsDirectory(args[2].c_str()) &&
1322 !cmSystemTools::RemoveADirectory(args[2].c_str()))
1324 std::cerr << "Error removing directory \"" << args[2].c_str()
1332 else if (args[1] == "remove" && args.size() > 2)
1335 for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1337 if(args[cc] == "\\-f" || args[cc] == "-f")
1343 // Complain if the file could not be removed, still exists,
1344 // and the -f option was not given.
1345 if(!cmSystemTools::RemoveFile(args[cc].c_str()) && !force &&
1346 cmSystemTools::FileExists(args[cc].c_str()))
1355 else if (args[1] == "touch" && args.size() > 2)
1357 for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1359 // Complain if the file could not be removed, still exists,
1360 // and the -f option was not given.
1361 if(!cmSystemTools::Touch(args[cc].c_str(), true))
1369 else if (args[1] == "touch_nocreate" && args.size() > 2)
1371 for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1373 // Complain if the file could not be removed, still exists,
1374 // and the -f option was not given.
1375 if(!cmSystemTools::Touch(args[cc].c_str(), false))
1384 else if (args[1] == "time" && args.size() > 2)
1386 std::string command = args[2];
1387 for (std::string::size_type cc = 3; cc < args.size(); cc ++)
1390 command += args[cc];
1393 clock_t clock_start, clock_finish;
1394 time_t time_start, time_finish;
1397 clock_start = clock();
1399 cmSystemTools::RunSingleCommand(command.c_str(), 0, &ret);
1401 clock_finish = clock();
1404 double clocks_per_sec = static_cast<double>(CLOCKS_PER_SEC);
1405 std::cout << "Elapsed time: "
1406 << static_cast<long>(time_finish - time_start) << " s. (time)"
1408 << static_cast<double>(clock_finish - clock_start) / clocks_per_sec
1413 // Command to calculate the md5sum of a file
1414 else if (args[1] == "md5sum" && args.size() >= 3)
1418 for (std::string::size_type cc = 2; cc < args.size(); cc ++)
1420 const char *filename = args[cc].c_str();
1421 // Cannot compute md5sum of a directory
1422 if(cmSystemTools::FileIsDirectory(filename))
1424 std::cerr << "Error: " << filename << " is a directory" << std::endl;
1427 else if(!cmSystemTools::ComputeFileMD5(filename, md5out))
1429 // To mimic md5sum behavior in a shell:
1430 std::cerr << filename << ": No such file or directory" << std::endl;
1435 std::cout << std::string(md5out,32) << " " << filename << std::endl;
1441 // Command to change directory and run a program.
1442 else if (args[1] == "chdir" && args.size() >= 4)
1444 std::string directory = args[2];
1445 if(!cmSystemTools::FileExists(directory.c_str()))
1447 cmSystemTools::Error("Directory does not exist for chdir command: ",
1452 std::string command = "\"";
1455 for (std::string::size_type cc = 4; cc < args.size(); cc ++)
1458 command += args[cc];
1463 if ( cmSystemTools::RunSingleCommand(command.c_str(), 0, &retval,
1464 directory.c_str(), cmSystemTools::OUTPUT_NORMAL, timeout) )
1472 // Command to start progress for a build
1473 else if (args[1] == "cmake_progress_start" && args.size() == 4)
1475 // basically remove the directory
1476 std::string dirName = args[2];
1477 dirName += "/Progress";
1478 cmSystemTools::RemoveADirectory(dirName.c_str());
1480 // is the last argument a filename that exists?
1481 FILE *countFile = fopen(args[3].c_str(),"r");
1485 if (1!=fscanf(countFile,"%i",&count))
1487 cmSystemTools::Message("Could not read from count file.");
1493 count = atoi(args[3].c_str());
1497 cmSystemTools::MakeDirectory(dirName.c_str());
1498 // write the count into the directory
1499 std::string fName = dirName;
1500 fName += "/count.txt";
1501 FILE *progFile = fopen(fName.c_str(),"w");
1504 fprintf(progFile,"%i\n",count);
1511 // Command to report progress for a build
1512 else if (args[1] == "cmake_progress_report" && args.size() >= 3)
1514 std::string dirName = args[2];
1515 dirName += "/Progress";
1521 fName += "/count.txt";
1522 progFile = fopen(fName.c_str(),"r");
1530 if (1!=fscanf(progFile,"%i",&count))
1532 cmSystemTools::Message("Could not read from progress file.");
1537 for (i = 3; i < args.size(); ++i)
1542 progFile = fopen(fName.c_str(),"w");
1545 fprintf(progFile,"empty");
1549 int fileNum = static_cast<int>
1550 (cmsys::Directory::GetNumberOfFilesInDirectory(dirName.c_str()));
1553 // print the progress
1554 fprintf(stdout,"[%3i%%] ",((fileNum-3)*100)/count);
1559 // Command to create a symbolic link. Fails on platforms not
1561 else if (args[1] == "create_symlink" && args.size() == 4)
1563 const char* destinationFileName = args[3].c_str();
1564 if ( cmSystemTools::FileExists(destinationFileName) )
1566 if ( cmSystemTools::FileIsSymlink(destinationFileName) )
1568 if ( !cmSystemTools::RemoveFile(destinationFileName) ||
1569 cmSystemTools::FileExists(destinationFileName) )
1579 return cmSystemTools::CreateSymlink(args[2].c_str(),
1580 args[3].c_str())? 0:1;
1583 // Internal CMake shared library support.
1584 else if (args[1] == "cmake_symlink_library" && args.size() == 5)
1586 return cmake::SymlinkLibrary(args);
1588 // Internal CMake versioned executable support.
1589 else if (args[1] == "cmake_symlink_executable" && args.size() == 4)
1591 return cmake::SymlinkExecutable(args);
1594 #if defined(CMAKE_HAVE_VS_GENERATORS)
1595 // Internal CMake support for calling Visual Studio macros.
1596 else if (args[1] == "cmake_call_visual_studio_macro" && args.size() >= 4)
1598 // args[2] = full path to .sln file or "ALL"
1599 // args[3] = name of Visual Studio macro to call
1600 // args[4..args.size()-1] = [optional] args for Visual Studio macro
1602 std::string macroArgs;
1604 if (args.size() > 4)
1606 macroArgs = args[4];
1608 for (size_t i = 5; i < args.size(); ++i)
1611 macroArgs += args[i];
1615 return cmCallVisualStudioMacro::CallMacro(args[2], args[3],
1620 // Internal CMake dependency scanning support.
1621 else if (args[1] == "cmake_depends" && args.size() >= 6)
1623 // Use the make system's VERBOSE environment variable to enable
1624 // verbose output. This can be skipped by also setting CMAKE_NO_VERBOSE
1625 // (which is set by the Eclipse and KDevelop generators).
1626 bool verbose = ((cmSystemTools::GetEnv("VERBOSE") != 0)
1627 && (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == 0));
1629 // Create a cmake object instance to process dependencies.
1632 std::string homeDir;
1633 std::string startDir;
1634 std::string homeOutDir;
1635 std::string startOutDir;
1636 std::string depInfo;
1638 if(args.size() >= 8)
1642 // -E cmake_depends <generator>
1643 // <home-src-dir> <start-src-dir>
1644 // <home-out-dir> <start-out-dir>
1645 // <dep-info> [--color=$(COLOR)]
1647 // All paths are provided.
1651 homeOutDir = args[5];
1652 startOutDir = args[6];
1654 if(args.size() >= 9 &&
1655 args[8].length() >= 8 &&
1656 args[8].substr(0, 8) == "--color=")
1658 // Enable or disable color based on the switch value.
1659 color = (args[8].size() == 8 ||
1660 cmSystemTools::IsOn(args[8].substr(8).c_str()));
1665 // Support older signature for existing makefiles:
1667 // -E cmake_depends <generator>
1668 // <home-out-dir> <start-out-dir>
1671 // Just pretend the source directories are the same as the
1672 // binary directories so at least scanning will work.
1676 homeOutDir = args[3];
1677 startOutDir = args[3];
1681 // Create a local generator configured for the directory in
1682 // which dependencies will be scanned.
1683 homeDir = cmSystemTools::CollapseFullPath(homeDir.c_str());
1684 startDir = cmSystemTools::CollapseFullPath(startDir.c_str());
1685 homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir.c_str());
1686 startOutDir = cmSystemTools::CollapseFullPath(startOutDir.c_str());
1687 cm.SetHomeDirectory(homeDir.c_str());
1688 cm.SetStartDirectory(startDir.c_str());
1689 cm.SetHomeOutputDirectory(homeOutDir.c_str());
1690 cm.SetStartOutputDirectory(startOutDir.c_str());
1691 if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str()))
1693 cm.SetGlobalGenerator(ggd);
1694 cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
1695 lgd->GetMakefile()->SetStartDirectory(startDir.c_str());
1696 lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
1697 lgd->GetMakefile()->MakeStartDirectoriesCurrent();
1699 // Actually scan dependencies.
1700 return lgd->UpdateDependencies(depInfo.c_str(),
1701 verbose, color)? 0 : 2;
1706 // Internal CMake link script support.
1707 else if (args[1] == "cmake_link_script" && args.size() >= 3)
1709 return cmake::ExecuteLinkScript(args);
1712 // Internal CMake unimplemented feature notification.
1713 else if (args[1] == "cmake_unimplemented_variable")
1715 std::cerr << "Feature not implemented for this platform.";
1716 if(args.size() == 3)
1718 std::cerr << " Variable " << args[2] << " is not set.";
1720 std::cerr << std::endl;
1723 else if (args[1] == "vs_link_exe")
1725 return cmake::VisualStudioLink(args, 1);
1727 else if (args[1] == "vs_link_dll")
1729 return cmake::VisualStudioLink(args, 2);
1731 #ifdef CMAKE_BUILD_WITH_CMAKE
1732 // Internal CMake color makefile support.
1733 else if (args[1] == "cmake_echo_color")
1735 return cmake::ExecuteEchoColor(args);
1737 else if (args[1] == "cmake_automoc" && args.size() >= 4)
1739 cmQtAutomoc automoc;
1740 const char *config = args[3].empty() ? 0 : args[3].c_str();
1741 bool automocSuccess = automoc.Run(args[2].c_str(), config);
1742 return automocSuccess ? 0 : 1;
1747 else if (args[1] == "tar" && args.size() > 3)
1749 std::string flags = args[2];
1750 std::string outFile = args[3];
1751 std::vector<cmStdString> files;
1752 for (std::string::size_type cc = 4; cc < args.size(); cc ++)
1754 files.push_back(args[cc]);
1758 bool verbose = false;
1759 if ( flags.find_first_of('j') != flags.npos )
1763 if ( flags.find_first_of('z') != flags.npos )
1767 if ( flags.find_first_of('v') != flags.npos )
1772 if ( flags.find_first_of('t') != flags.npos )
1774 if ( !cmSystemTools::ListTar(outFile.c_str(), gzip, verbose) )
1776 cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
1780 else if ( flags.find_first_of('c') != flags.npos )
1782 if ( !cmSystemTools::CreateTar(
1783 outFile.c_str(), files, gzip, bzip2, verbose) )
1785 cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
1789 else if ( flags.find_first_of('x') != flags.npos )
1791 if ( !cmSystemTools::ExtractTar(
1792 outFile.c_str(), gzip, verbose) )
1794 cmSystemTools::Error("Problem extracting tar: ", outFile.c_str());
1798 // OK, on windows 7 after we untar some files,
1799 // sometimes we can not rename the directory after
1800 // the untar is done. This breaks the external project
1801 // untar and rename code. So, by default we will wait
1802 // 1/10th of a second after the untar. If CMAKE_UNTAR_DELAY
1803 // is set in the env, its value will be used instead of 100.
1805 const char* delayVar = cmSystemTools::GetEnv("CMAKE_UNTAR_DELAY");
1808 delay = atoi(delayVar);
1812 cmSystemTools::Delay(delay);
1819 #if defined(CMAKE_BUILD_WITH_CMAKE)
1820 // Internal CMake Fortran module support.
1821 else if (args[1] == "cmake_copy_f90_mod" && args.size() >= 4)
1823 return cmDependsFortran::CopyModule(args)? 0 : 1;
1827 #if defined(_WIN32) && !defined(__CYGWIN__)
1828 // Write registry value
1829 else if (args[1] == "write_regv" && args.size() > 3)
1831 return cmSystemTools::WriteRegistryValue(args[2].c_str(),
1832 args[3].c_str()) ? 0 : 1;
1835 // Delete registry value
1836 else if (args[1] == "delete_regv" && args.size() > 2)
1838 return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
1841 else if (args[1] == "comspec" && args.size() > 2)
1844 std::string command = args[2];
1845 for ( cc = 3; cc < args.size(); cc ++ )
1847 command += " " + args[cc];
1849 return cmWin32ProcessExecution::Windows9xHack(command.c_str());
1851 else if (args[1] == "env_vs8_wince" && args.size() == 3)
1853 return cmake::WindowsCEEnvironment("8.0", args[2]);
1855 else if (args[1] == "env_vs9_wince" && args.size() == 3)
1857 return cmake::WindowsCEEnvironment("9.0", args[2]);
1862 ::CMakeCommandUsage(args[0].c_str());
1866 void cmake::AddExtraGenerator(const char* name,
1867 CreateExtraGeneratorFunctionType newFunction)
1869 cmExternalMakefileProjectGenerator* extraGenerator = newFunction();
1870 const std::vector<std::string>& supportedGlobalGenerators =
1871 extraGenerator->GetSupportedGlobalGenerators();
1873 for(std::vector<std::string>::const_iterator
1874 it = supportedGlobalGenerators.begin();
1875 it != supportedGlobalGenerators.end();
1878 std::string fullName = cmExternalMakefileProjectGenerator::
1879 CreateFullGeneratorName(it->c_str(), name);
1880 this->ExtraGenerators[fullName.c_str()] = newFunction;
1882 delete extraGenerator;
1885 void cmake::AddDefaultExtraGenerators()
1887 #if defined(CMAKE_BUILD_WITH_CMAKE)
1888 #if defined(_WIN32) && !defined(__CYGWIN__)
1892 this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
1893 &cmExtraCodeBlocksGenerator::New);
1894 this->AddExtraGenerator(cmExtraSublimeTextGenerator::GetActualName(),
1895 &cmExtraSublimeTextGenerator::New);
1897 #ifdef CMAKE_USE_ECLIPSE
1898 this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
1899 &cmExtraEclipseCDT4Generator::New);
1902 #ifdef CMAKE_USE_KDEVELOP
1903 this->AddExtraGenerator(cmGlobalKdevelopGenerator::GetActualName(),
1904 &cmGlobalKdevelopGenerator::New);
1905 // for kdevelop also add the generator with just the name of the
1906 // extra generator, since it was this way since cmake 2.2
1907 this->ExtraGenerators[cmGlobalKdevelopGenerator::GetActualName()]
1908 = &cmGlobalKdevelopGenerator::New;
1915 //----------------------------------------------------------------------------
1916 void cmake::GetRegisteredGenerators(std::vector<std::string>& names)
1918 for(RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
1919 i != this->Generators.end(); ++i)
1921 (*i)->GetGenerators(names);
1923 for(RegisteredExtraGeneratorsMap::const_iterator
1924 i = this->ExtraGenerators.begin();
1925 i != this->ExtraGenerators.end(); ++i)
1927 names.push_back(i->first);
1931 cmGlobalGenerator* cmake::CreateGlobalGenerator(const char* name)
1933 cmExternalMakefileProjectGenerator* extraGenerator = 0;
1934 RegisteredExtraGeneratorsMap::const_iterator extraGenIt =
1935 this->ExtraGenerators.find(name);
1936 if (extraGenIt != this->ExtraGenerators.end())
1938 extraGenerator = (extraGenIt->second)();
1939 name = extraGenerator->GetGlobalGeneratorName(name);
1942 cmGlobalGenerator* generator = 0;
1943 for (RegisteredGeneratorsVector::const_iterator i =
1944 this->Generators.begin(); i != this->Generators.end(); ++i)
1946 generator = (*i)->CreateGlobalGenerator(name);
1955 generator->SetCMakeInstance(this);
1956 generator->SetExternalMakefileProjectGenerator(extraGenerator);
1960 delete extraGenerator;
1966 void cmake::SetHomeDirectory(const char* dir)
1968 this->cmHomeDirectory = dir;
1969 cmSystemTools::ConvertToUnixSlashes(this->cmHomeDirectory);
1972 void cmake::SetHomeOutputDirectory(const char* lib)
1974 this->HomeOutputDirectory = lib;
1975 cmSystemTools::ConvertToUnixSlashes(this->HomeOutputDirectory);
1978 void cmake::SetGlobalGenerator(cmGlobalGenerator *gg)
1982 cmSystemTools::Error("Error SetGlobalGenerator called with null");
1985 // delete the old generator
1986 if (this->GlobalGenerator)
1988 delete this->GlobalGenerator;
1989 // restore the original environment variables CXX and CC
1991 std::string env = "CC=";
1992 if(this->CCEnvironment.size())
1994 env += this->CCEnvironment;
1996 cmSystemTools::PutEnv(env.c_str());
1998 if(this->CXXEnvironment.size())
2000 env += this->CXXEnvironment;
2002 cmSystemTools::PutEnv(env.c_str());
2006 this->GlobalGenerator = gg;
2008 // set the global flag for unix style paths on cmSystemTools as soon as
2009 // the generator is set. This allows gmake to be used on windows.
2010 cmSystemTools::SetForceUnixPaths
2011 (this->GlobalGenerator->GetForceUnixPaths());
2013 // Save the environment variables CXX and CC
2014 const char* cxx = getenv("CXX");
2015 const char* cc = getenv("CC");
2018 this->CXXEnvironment = cxx;
2022 this->CXXEnvironment = "";
2026 this->CCEnvironment = cc;
2030 this->CCEnvironment = "";
2032 // set the cmake instance just to be sure
2033 gg->SetCMakeInstance(this);
2036 int cmake::DoPreConfigureChecks()
2038 // Make sure the Start directory contains a CMakeLists.txt file.
2039 std::string srcList = this->GetHomeDirectory();
2040 srcList += "/CMakeLists.txt";
2041 if(!cmSystemTools::FileExists(srcList.c_str()))
2043 cmOStringStream err;
2044 if(cmSystemTools::FileIsDirectory(this->GetHomeDirectory()))
2046 err << "The source directory \"" << this->GetHomeDirectory()
2047 << "\" does not appear to contain CMakeLists.txt.\n";
2049 else if(cmSystemTools::FileExists(this->GetHomeDirectory()))
2051 err << "The source directory \"" << this->GetHomeDirectory()
2052 << "\" is a file, not a directory.\n";
2056 err << "The source directory \"" << this->GetHomeDirectory()
2057 << "\" does not exist.\n";
2059 err << "Specify --help for usage, or press the help button on the CMake "
2061 cmSystemTools::Error(err.str().c_str());
2065 // do a sanity check on some values
2066 if(this->CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY"))
2068 std::string cacheStart =
2069 this->CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY");
2070 cacheStart += "/CMakeLists.txt";
2071 std::string currentStart = this->GetHomeDirectory();
2072 currentStart += "/CMakeLists.txt";
2073 if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
2075 std::string message = "The source \"";
2076 message += currentStart;
2077 message += "\" does not match the source \"";
2078 message += cacheStart;
2079 message += "\" used to generate cache. ";
2080 message += "Re-run cmake with a different source directory.";
2081 cmSystemTools::Error(message.c_str());
2091 struct SaveCacheEntry
2096 cmCacheManager::CacheEntryType type;
2099 int cmake::HandleDeleteCacheVariables(const char* var)
2101 std::vector<std::string> argsSplit;
2102 cmSystemTools::ExpandListArgument(std::string(var), argsSplit, true);
2103 // erase the property to avoid infinite recursion
2104 this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
2105 if(this->GetIsInTryCompile())
2109 cmCacheManager::CacheIterator ci = this->CacheManager->NewIterator();
2110 std::vector<SaveCacheEntry> saved;
2111 cmOStringStream warning;
2113 << "You have changed variables that require your cache to be deleted.\n"
2114 << "Configure will be re-run and you may have to reset some variables.\n"
2115 << "The following variables have changed:\n";
2116 for(std::vector<std::string>::iterator i = argsSplit.begin();
2117 i != argsSplit.end(); ++i)
2119 SaveCacheEntry save;
2121 warning << *i << "= ";
2124 warning << *i << "\n";
2125 if(ci.Find(save.key.c_str()))
2127 save.type = ci.GetType();
2128 save.help = ci.GetProperty("HELPSTRING");
2130 saved.push_back(save);
2134 this->CacheManager->DeleteCache(this->GetStartOutputDirectory());
2135 // load the empty cache
2137 // restore the changed compilers
2138 for(std::vector<SaveCacheEntry>::iterator i = saved.begin();
2139 i != saved.end(); ++i)
2141 this->AddCacheEntry(i->key.c_str(), i->value.c_str(),
2142 i->help.c_str(), i->type);
2144 cmSystemTools::Message(warning.str().c_str());
2145 // avoid reconfigure if there were errors
2146 if(!cmSystemTools::GetErrorOccuredFlag())
2149 return this->Configure();
2154 int cmake::Configure()
2156 if(this->DoSuppressDevWarnings)
2158 if(this->SuppressDevWarnings)
2160 this->CacheManager->
2161 AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE",
2162 "Suppress Warnings that are meant for"
2163 " the author of the CMakeLists.txt files.",
2164 cmCacheManager::INTERNAL);
2168 this->CacheManager->
2169 AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE",
2170 "Suppress Warnings that are meant for"
2171 " the author of the CMakeLists.txt files.",
2172 cmCacheManager::INTERNAL);
2175 int ret = this->ActualConfigure();
2176 const char* delCacheVars =
2177 this->GetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
2178 if(delCacheVars && delCacheVars[0] != 0)
2180 return this->HandleDeleteCacheVariables(delCacheVars);
2186 int cmake::ActualConfigure()
2188 // Construct right now our path conversion table before it's too late:
2189 this->UpdateConversionPathTable();
2190 this->CleanupCommandsAndMacros();
2193 if ( this->GetWorkingMode() == NORMAL_MODE )
2195 res = this->DoPreConfigureChecks();
2203 this->CacheManager->AddCacheEntry
2204 ("CMAKE_HOME_DIRECTORY",
2205 this->GetHomeDirectory(),
2206 "Start directory with the top level CMakeLists.txt file for this "
2208 cmCacheManager::INTERNAL);
2211 // no generator specified on the command line
2212 if(!this->GlobalGenerator)
2214 const char* genName =
2215 this->CacheManager->GetCacheValue("CMAKE_GENERATOR");
2216 const char* extraGenName =
2217 this->CacheManager->GetCacheValue("CMAKE_EXTRA_GENERATOR");
2220 std::string fullName = cmExternalMakefileProjectGenerator::
2221 CreateFullGeneratorName(genName, extraGenName);
2222 this->GlobalGenerator = this->CreateGlobalGenerator(fullName.c_str());
2224 if(this->GlobalGenerator)
2226 // set the global flag for unix style paths on cmSystemTools as
2227 // soon as the generator is set. This allows gmake to be used
2229 cmSystemTools::SetForceUnixPaths
2230 (this->GlobalGenerator->GetForceUnixPaths());
2234 #if defined(__BORLANDC__) && defined(_WIN32)
2235 this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator);
2236 #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
2237 std::string installedCompiler;
2238 // Try to find the newest VS installed on the computer and
2239 // use that as a default if -G is not specified
2240 const std::string vsregBase =
2241 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\";
2242 std::vector<std::string> vsVerions;
2243 vsVerions.push_back("VisualStudio\\");
2244 vsVerions.push_back("VCExpress\\");
2245 vsVerions.push_back("WDExpress\\");
2246 struct VSRegistryEntryName
2248 const char* MSVersion;
2249 const char* GeneratorName;
2251 VSRegistryEntryName version[] = {
2252 {"6.0", "Visual Studio 6"},
2253 {"7.0", "Visual Studio 7"},
2254 {"7.1", "Visual Studio 7 .NET 2003"},
2255 {"8.0", "Visual Studio 8 2005"},
2256 {"9.0", "Visual Studio 9 2008"},
2257 {"10.0", "Visual Studio 10"},
2258 {"11.0", "Visual Studio 11"},
2259 {"12.0", "Visual Studio 12"},
2261 for(int i=0; version[i].MSVersion != 0; i++)
2263 for(size_t b=0; b < vsVerions.size(); b++)
2265 std::string reg = vsregBase + vsVerions[b] + version[i].MSVersion;
2266 reg += ";InstallDir]";
2267 cmSystemTools::ExpandRegistryValues(reg,
2268 cmSystemTools::KeyWOW64_32);
2269 if (!(reg == "/registry"))
2271 installedCompiler = version[i].GeneratorName;
2276 cmGlobalGenerator* gen
2277 = this->CreateGlobalGenerator(installedCompiler.c_str());
2280 gen = new cmGlobalNMakeMakefileGenerator;
2282 this->SetGlobalGenerator(gen);
2283 std::cout << "-- Building for: " << gen->GetName() << "\n";
2285 this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3);
2288 if(!this->GlobalGenerator)
2290 cmSystemTools::Error("Could not create generator");
2295 const char* genName = this->CacheManager->GetCacheValue("CMAKE_GENERATOR");
2298 if(strcmp(this->GlobalGenerator->GetName(), genName) != 0)
2300 std::string message = "Error: generator : ";
2301 message += this->GlobalGenerator->GetName();
2302 message += "\nDoes not match the generator used previously: ";
2305 "\nEither remove the CMakeCache.txt file or choose a different"
2306 " binary directory.";
2307 cmSystemTools::Error(message.c_str());
2311 if(!this->CacheManager->GetCacheValue("CMAKE_GENERATOR"))
2313 this->CacheManager->AddCacheEntry("CMAKE_GENERATOR",
2314 this->GlobalGenerator->GetName(),
2315 "Name of generator.",
2316 cmCacheManager::INTERNAL);
2317 this->CacheManager->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
2318 this->GlobalGenerator->GetExtraGeneratorName(),
2319 "Name of external makefile project generator.",
2320 cmCacheManager::INTERNAL);
2323 if(const char* tsName =
2324 this->CacheManager->GetCacheValue("CMAKE_GENERATOR_TOOLSET"))
2326 if(this->GeneratorToolset.empty())
2328 this->GeneratorToolset = tsName;
2330 else if(this->GeneratorToolset != tsName)
2332 std::string message = "Error: generator toolset: ";
2333 message += this->GeneratorToolset;
2334 message += "\nDoes not match the toolset used previously: ";
2337 "\nEither remove the CMakeCache.txt file or choose a different"
2338 " binary directory.";
2339 cmSystemTools::Error(message.c_str());
2345 this->CacheManager->AddCacheEntry("CMAKE_GENERATOR_TOOLSET",
2346 this->GeneratorToolset.c_str(),
2347 "Name of generator toolset.",
2348 cmCacheManager::INTERNAL);
2350 if(!this->GeneratorToolset.empty() &&
2351 !this->GlobalGenerator->SetGeneratorToolset(this->GeneratorToolset))
2356 // reset any system configuration information, except for when we are
2357 // InTryCompile. With TryCompile the system info is taken from the parent's
2358 // info to save time
2359 if (!this->InTryCompile)
2361 this->GlobalGenerator->ClearEnabledLanguages();
2364 // Truncate log files
2365 if (!this->InTryCompile)
2367 this->TruncateOutputLog("CMakeOutput.log");
2368 this->TruncateOutputLog("CMakeError.log");
2371 // actually do the configure
2372 this->GlobalGenerator->Configure();
2373 // Before saving the cache
2374 // if the project did not define one of the entries below, add them now
2375 // so users can edit the values in the cache:
2377 // We used to always present LIBRARY_OUTPUT_PATH and
2378 // EXECUTABLE_OUTPUT_PATH. They are now documented as old-style and
2379 // should no longer be used. Therefore we present them only if the
2380 // project requires compatibility with CMake 2.4. We detect this
2381 // here by looking for the old CMAKE_BACKWARDS_COMPATIBILITY
2382 // variable created when CMP0001 is not set to NEW.
2383 if(this->GetCacheManager()->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
2385 if(!this->CacheManager->GetCacheValue("LIBRARY_OUTPUT_PATH"))
2387 this->CacheManager->AddCacheEntry
2388 ("LIBRARY_OUTPUT_PATH", "",
2389 "Single output directory for building all libraries.",
2390 cmCacheManager::PATH);
2392 if(!this->CacheManager->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
2394 this->CacheManager->AddCacheEntry
2395 ("EXECUTABLE_OUTPUT_PATH", "",
2396 "Single output directory for building all executables.",
2397 cmCacheManager::PATH);
2400 if(!this->CacheManager->GetCacheValue("CMAKE_USE_RELATIVE_PATHS"))
2402 this->CacheManager->AddCacheEntry
2403 ("CMAKE_USE_RELATIVE_PATHS", "OFF",
2404 "If true, cmake will use relative paths in makefiles and projects.",
2405 cmCacheManager::BOOL);
2406 cmCacheManager::CacheIterator it =
2407 this->CacheManager->GetCacheIterator("CMAKE_USE_RELATIVE_PATHS");
2408 if ( !it.PropertyExists("ADVANCED") )
2410 it.SetProperty("ADVANCED", "1");
2414 if(cmSystemTools::GetFatalErrorOccured() &&
2415 (!this->CacheManager->GetCacheValue("CMAKE_MAKE_PROGRAM") ||
2416 cmSystemTools::IsOff(this->CacheManager->
2417 GetCacheValue("CMAKE_MAKE_PROGRAM"))))
2419 // We must have a bad generator selection. Wipe the cache entry so the
2420 // user can select another.
2421 this->CacheManager->RemoveCacheEntry("CMAKE_GENERATOR");
2422 this->CacheManager->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR");
2425 cmMakefile* mf=this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
2426 if (mf->IsOn("CTEST_USE_LAUNCHERS")
2427 && !this->GetProperty("RULE_LAUNCH_COMPILE", cmProperty::GLOBAL))
2429 cmSystemTools::Error("CTEST_USE_LAUNCHERS is enabled, but the "
2430 "RULE_LAUNCH_COMPILE global property is not defined.\n"
2431 "Did you forget to include(CTest) in the toplevel "
2432 "CMakeLists.txt ?");
2435 // only save the cache if there were no fatal errors
2436 if ( this->GetWorkingMode() == NORMAL_MODE )
2438 this->CacheManager->SaveCache(this->GetHomeOutputDirectory());
2440 if ( !this->GraphVizFile.empty() )
2442 std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl;
2443 this->GenerateGraphViz(this->GraphVizFile.c_str());
2445 if(cmSystemTools::GetErrorOccuredFlag())
2452 void cmake::PreLoadCMakeFiles()
2454 std::vector<std::string> args;
2455 std::string pre_load = this->GetHomeDirectory();
2456 if ( pre_load.size() > 0 )
2458 pre_load += "/PreLoad.cmake";
2459 if ( cmSystemTools::FileExists(pre_load.c_str()) )
2461 this->ReadListFile(args, pre_load.c_str());
2464 pre_load = this->GetHomeOutputDirectory();
2465 if ( pre_load.size() > 0 )
2467 pre_load += "/PreLoad.cmake";
2468 if ( cmSystemTools::FileExists(pre_load.c_str()) )
2470 this->ReadListFile(args, pre_load.c_str());
2475 // handle a command line invocation
2476 int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
2478 // Process the arguments
2479 this->SetArgs(args);
2480 if(cmSystemTools::GetErrorOccuredFlag())
2485 // If we are given a stamp list file check if it is really out of date.
2486 if(!this->CheckStampList.empty() &&
2487 cmakeCheckStampList(this->CheckStampList.c_str()))
2492 // If we are given a stamp file check if it is really out of date.
2493 if(!this->CheckStampFile.empty() &&
2494 cmakeCheckStampFile(this->CheckStampFile.c_str()))
2499 // set the cmake command
2500 this->CMakeCommand = args[0];
2502 if ( this->GetWorkingMode() == NORMAL_MODE )
2505 if(this->LoadCache() < 0)
2507 cmSystemTools::Error("Error executing cmake::LoadCache(). Aborting.\n");
2513 this->AddCMakePaths();
2515 // Add any cache args
2516 if ( !this->SetCacheArgs(args) )
2518 cmSystemTools::Error("Problem processing arguments. Aborting.\n");
2522 // In script mode we terminate after running the script.
2523 if(this->GetWorkingMode() != NORMAL_MODE)
2525 if(cmSystemTools::GetErrorOccuredFlag())
2535 // If MAKEFLAGS are given in the environment, remove the environment
2536 // variable. This will prevent try-compile from succeeding when it
2537 // should fail (if "-i" is an option). We cannot simply test
2538 // whether "-i" is given and remove it because some make programs
2539 // encode the MAKEFLAGS variable in a strange way.
2540 if(getenv("MAKEFLAGS"))
2542 cmSystemTools::PutEnv("MAKEFLAGS=");
2545 this->PreLoadCMakeFiles();
2552 // now run the global generate
2553 // Check the state of the build system to see if we need to regenerate.
2554 if(!this->CheckBuildSystem())
2559 // If we are doing global generate, we better set start and start
2560 // output directory to the root of the project.
2561 std::string oldstartdir = this->GetStartDirectory();
2562 std::string oldstartoutputdir = this->GetStartOutputDirectory();
2563 this->SetStartDirectory(this->GetHomeDirectory());
2564 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
2565 int ret = this->Configure();
2566 if (ret || this->GetWorkingMode() != NORMAL_MODE)
2568 #if defined(CMAKE_HAVE_VS_GENERATORS)
2569 if(!this->VSSolutionFile.empty() && this->GlobalGenerator)
2571 // CMake is running to regenerate a Visual Studio build tree
2572 // during a build from the VS IDE. The build files cannot be
2573 // regenerated, so we should stop the build.
2574 cmSystemTools::Message(
2575 "CMake Configure step failed. "
2576 "Build files cannot be regenerated correctly. "
2577 "Attempting to stop IDE build.");
2578 cmGlobalVisualStudioGenerator* gg =
2579 static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
2580 gg->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop,
2581 this->VSSolutionFile.c_str());
2586 ret = this->Generate();
2587 std::string message = "Build files have been written to: ";
2588 message += this->GetHomeOutputDirectory();
2589 this->UpdateProgress(message.c_str(), -1);
2594 this->SetStartDirectory(oldstartdir.c_str());
2595 this->SetStartOutputDirectory(oldstartoutputdir.c_str());
2600 int cmake::Generate()
2602 if(!this->GlobalGenerator)
2606 this->GlobalGenerator->Generate();
2607 if(this->WarnUnusedCli)
2609 this->RunCheckForUnusedVariables();
2611 if(cmSystemTools::GetErrorOccuredFlag())
2615 if (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"))
2617 this->ReportUndefinedPropertyAccesses
2618 (this->GetProperty("REPORT_UNDEFINED_PROPERTIES"));
2620 // Save the cache again after a successful Generate so that any internal
2621 // variables created during Generate are saved. (Specifically target GUIDs
2622 // for the Visual Studio and Xcode generators.)
2623 if ( this->GetWorkingMode() == NORMAL_MODE )
2625 this->CacheManager->SaveCache(this->GetHomeOutputDirectory());
2630 void cmake::AddCacheEntry(const char* key, const char* value,
2631 const char* helpString,
2634 this->CacheManager->AddCacheEntry(key, value,
2636 cmCacheManager::CacheEntryType(type));
2639 const char* cmake::GetCacheDefinition(const char* name) const
2641 return this->CacheManager->GetCacheValue(name);
2644 void cmake::AddDefaultCommands()
2646 std::list<cmCommand*> commands;
2647 GetBootstrapCommands1(commands);
2648 GetBootstrapCommands2(commands);
2649 GetPredefinedCommands(commands);
2650 for(std::list<cmCommand*>::iterator i = commands.begin();
2651 i != commands.end(); ++i)
2653 this->AddCommand(*i);
2657 void cmake::AddDefaultGenerators()
2659 #if defined(_WIN32) && !defined(__CYGWIN__)
2660 # if !defined(CMAKE_BOOT_MINGW)
2661 this->Generators.push_back(
2662 cmGlobalVisualStudio6Generator::NewFactory());
2663 this->Generators.push_back(
2664 cmGlobalVisualStudio7Generator::NewFactory());
2665 this->Generators.push_back(
2666 cmGlobalVisualStudio10Generator::NewFactory());
2667 this->Generators.push_back(
2668 cmGlobalVisualStudio11Generator::NewFactory());
2669 this->Generators.push_back(
2670 cmGlobalVisualStudio12Generator::NewFactory());
2671 this->Generators.push_back(
2672 cmGlobalVisualStudio71Generator::NewFactory());
2673 this->Generators.push_back(
2674 cmGlobalVisualStudio8Generator::NewFactory());
2675 this->Generators.push_back(
2676 cmGlobalVisualStudio9Generator::NewFactory());
2677 this->Generators.push_back(
2678 cmGlobalBorlandMakefileGenerator::NewFactory());
2679 this->Generators.push_back(
2680 cmGlobalNMakeMakefileGenerator::NewFactory());
2681 this->Generators.push_back(
2682 cmGlobalJOMMakefileGenerator::NewFactory());
2683 this->Generators.push_back(
2684 cmGlobalWatcomWMakeGenerator::NewFactory());
2686 this->Generators.push_back(
2687 cmGlobalMSYSMakefileGenerator::NewFactory());
2688 this->Generators.push_back(
2689 cmGlobalMinGWMakefileGenerator::NewFactory());
2691 this->Generators.push_back(
2692 cmGlobalUnixMakefileGenerator3::NewFactory());
2693 this->Generators.push_back(
2694 cmGlobalNinjaGenerator::NewFactory());
2695 #ifdef CMAKE_USE_XCODE
2696 this->Generators.push_back(
2697 cmGlobalXCodeGenerator::NewFactory());
2701 int cmake::LoadCache()
2703 // could we not read the cache
2704 if (!this->CacheManager->LoadCache(this->GetHomeOutputDirectory()))
2706 // if it does exist, but isn't readable then warn the user
2707 std::string cacheFile = this->GetHomeOutputDirectory();
2708 cacheFile += "/CMakeCache.txt";
2709 if(cmSystemTools::FileExists(cacheFile.c_str()))
2711 cmSystemTools::Error(
2712 "There is a CMakeCache.txt file for the current binary tree but "
2713 "cmake does not have permission to read it. Please check the "
2714 "permissions of the directory you are trying to run CMake on.");
2719 if (this->CMakeCommand.size() < 2)
2721 cmSystemTools::Error(
2722 "cmake command was not specified prior to loading the cache in "
2727 // setup CMAKE_ROOT and CMAKE_COMMAND
2728 if(!this->AddCMakePaths())
2735 void cmake::SetProgressCallback(ProgressCallbackType f, void *cd)
2737 this->ProgressCallback = f;
2738 this->ProgressCallbackClientData = cd;
2741 void cmake::UpdateProgress(const char *msg, float prog)
2743 if(this->ProgressCallback && !this->InTryCompile)
2745 (*this->ProgressCallback)(msg, prog, this->ProgressCallbackClientData);
2750 void cmake::GetCommandDocumentation(std::vector<cmDocumentationEntry>& v,
2751 bool withCurrentCommands,
2752 bool withCompatCommands) const
2754 for(RegisteredCommandsMap::const_iterator j = this->Commands.begin();
2755 j != this->Commands.end(); ++j)
2757 if ((( withCompatCommands == false) && ( (*j).second->IsDiscouraged()))
2758 || ((withCurrentCommands == false) && (!(*j).second->IsDiscouraged()))
2759 || (!((*j).second->ShouldAppearInDocumentation()))
2765 cmDocumentationEntry e((*j).second->GetName(),
2766 (*j).second->GetTerseDocumentation(),
2767 (*j).second->GetFullDocumentation());
2772 void cmake::GetPolicyDocumentation(std::vector<cmDocumentationEntry>& v)
2774 this->Policies->GetDocumentation(v);
2777 void cmake::GetPropertiesDocumentation(std::map<std::string,
2778 cmDocumentationSection *>& v)
2780 // loop over the properties and put them into the doc structure
2781 std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::iterator i;
2782 i = this->PropertyDefinitions.begin();
2783 for (;i != this->PropertyDefinitions.end(); ++i)
2785 i->second.GetPropertiesDocumentation(v);
2789 void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
2791 for(RegisteredGeneratorsVector::const_iterator i =
2792 this->Generators.begin(); i != this->Generators.end(); ++i)
2794 cmDocumentationEntry e;
2795 (*i)->GetDocumentation(e);
2798 for(RegisteredExtraGeneratorsMap::const_iterator i =
2799 this->ExtraGenerators.begin(); i != this->ExtraGenerators.end(); ++i)
2801 cmDocumentationEntry e;
2802 cmExternalMakefileProjectGenerator* generator = (i->second)();
2803 generator->GetDocumentation(e, i->first.c_str());
2810 void cmake::UpdateConversionPathTable()
2812 // Update the path conversion table with any specified file:
2813 const char* tablepath =
2814 this->CacheManager->GetCacheValue("CMAKE_PATH_TRANSLATION_FILE");
2818 std::ifstream table( tablepath );
2821 cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath,
2822 ". CMake can not open file.");
2823 cmSystemTools::ReportLastSystemError("CMake can not open file.");
2830 // two entries per line
2831 table >> a; table >> b;
2832 cmSystemTools::AddTranslationPath( a.c_str(), b.c_str());
2838 //----------------------------------------------------------------------------
2839 int cmake::CheckBuildSystem()
2841 // We do not need to rerun CMake. Check dependency integrity. Use
2842 // the make system's VERBOSE environment variable to enable verbose
2843 // output. This can be skipped by setting CMAKE_NO_VERBOSE (which is set
2844 // by the Eclipse and KDevelop generators).
2845 bool verbose = ((cmSystemTools::GetEnv("VERBOSE") != 0)
2846 && (cmSystemTools::GetEnv("CMAKE_NO_VERBOSE") == 0));
2848 // This method will check the integrity of the build system if the
2849 // option was given on the command line. It reads the given file to
2850 // determine whether CMake should rerun.
2852 // If no file is provided for the check, we have to rerun.
2853 if(this->CheckBuildSystemArgument.size() == 0)
2857 cmOStringStream msg;
2858 msg << "Re-run cmake no build system arguments\n";
2859 cmSystemTools::Stdout(msg.str().c_str());
2864 // If the file provided does not exist, we have to rerun.
2865 if(!cmSystemTools::FileExists(this->CheckBuildSystemArgument.c_str()))
2869 cmOStringStream msg;
2870 msg << "Re-run cmake missing file: "
2871 << this->CheckBuildSystemArgument.c_str() << "\n";
2872 cmSystemTools::Stdout(msg.str().c_str());
2877 // Read the rerun check file and use it to decide whether to do the
2880 cmGlobalGenerator gg;
2881 gg.SetCMakeInstance(&cm);
2882 cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
2883 cmMakefile* mf = lg->GetMakefile();
2884 if(!mf->ReadListFile(0, this->CheckBuildSystemArgument.c_str()) ||
2885 cmSystemTools::GetErrorOccuredFlag())
2889 cmOStringStream msg;
2890 msg << "Re-run cmake error reading : "
2891 << this->CheckBuildSystemArgument.c_str() << "\n";
2892 cmSystemTools::Stdout(msg.str().c_str());
2894 // There was an error reading the file. Just rerun.
2898 if(this->ClearBuildSystem)
2900 // Get the generator used for this build system.
2901 const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
2902 if(!genName || genName[0] == '\0')
2904 genName = "Unix Makefiles";
2907 // Create the generator and use it to clear the dependencies.
2908 cmsys::auto_ptr<cmGlobalGenerator>
2909 ggd(this->CreateGlobalGenerator(genName));
2912 cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
2913 lgd->ClearDependencies(mf, verbose);
2917 // If any byproduct of makefile generation is missing we must re-run.
2918 std::vector<std::string> products;
2919 if(const char* productStr = mf->GetDefinition("CMAKE_MAKEFILE_PRODUCTS"))
2921 cmSystemTools::ExpandListArgument(productStr, products);
2923 for(std::vector<std::string>::const_iterator pi = products.begin();
2924 pi != products.end(); ++pi)
2926 if(!(cmSystemTools::FileExists(pi->c_str()) ||
2927 cmSystemTools::FileIsSymlink(pi->c_str())))
2931 cmOStringStream msg;
2932 msg << "Re-run cmake, missing byproduct: " << *pi << "\n";
2933 cmSystemTools::Stdout(msg.str().c_str());
2939 // Get the set of dependencies and outputs.
2940 std::vector<std::string> depends;
2941 std::vector<std::string> outputs;
2942 const char* dependsStr = mf->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
2943 const char* outputsStr = mf->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
2944 if(dependsStr && outputsStr)
2946 cmSystemTools::ExpandListArgument(dependsStr, depends);
2947 cmSystemTools::ExpandListArgument(outputsStr, outputs);
2949 if(depends.empty() || outputs.empty())
2951 // Not enough information was provided to do the test. Just rerun.
2954 cmOStringStream msg;
2955 msg << "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
2956 "or CMAKE_MAKEFILE_OUTPUTS :\n";
2957 cmSystemTools::Stdout(msg.str().c_str());
2962 // Find the newest dependency.
2963 std::vector<std::string>::iterator dep = depends.begin();
2964 std::string dep_newest = *dep++;
2965 for(;dep != depends.end(); ++dep)
2968 if(this->FileComparison->FileTimeCompare(dep_newest.c_str(),
2969 dep->c_str(), &result))
2980 cmOStringStream msg;
2981 msg << "Re-run cmake: build system dependency is missing\n";
2982 cmSystemTools::Stdout(msg.str().c_str());
2988 // Find the oldest output.
2989 std::vector<std::string>::iterator out = outputs.begin();
2990 std::string out_oldest = *out++;
2991 for(;out != outputs.end(); ++out)
2994 if(this->FileComparison->FileTimeCompare(out_oldest.c_str(),
2995 out->c_str(), &result))
3006 cmOStringStream msg;
3007 msg << "Re-run cmake: build system output is missing\n";
3008 cmSystemTools::Stdout(msg.str().c_str());
3014 // If any output is older than any dependency then rerun.
3017 if(!this->FileComparison->FileTimeCompare(out_oldest.c_str(),
3024 cmOStringStream msg;
3025 msg << "Re-run cmake file: " << out_oldest.c_str()
3026 << " older than: " << dep_newest.c_str() << "\n";
3027 cmSystemTools::Stdout(msg.str().c_str());
3033 // No need to rerun.
3037 //----------------------------------------------------------------------------
3038 void cmake::TruncateOutputLog(const char* fname)
3040 std::string fullPath = this->GetHomeOutputDirectory();
3044 if ( ::stat(fullPath.c_str(), &st) )
3048 if ( !this->CacheManager->GetCacheValue("CMAKE_CACHEFILE_DIR") )
3050 cmSystemTools::RemoveFile(fullPath.c_str());
3053 off_t fsize = st.st_size;
3054 const off_t maxFileSize = 50 * 1024;
3055 if ( fsize < maxFileSize )
3057 //TODO: truncate file
3062 inline std::string removeQuotes(const std::string& s)
3064 if(s[0] == '\"' && s[s.size()-1] == '\"')
3066 return s.substr(1, s.size()-2);
3071 std::string cmake::FindCMakeProgram(const char* name) const
3074 if ((name) && (*name))
3076 const cmMakefile* mf
3077 = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile();
3078 #ifdef CMAKE_BUILD_WITH_CMAKE
3079 path = mf->GetRequiredDefinition("CMAKE_COMMAND");
3080 path = removeQuotes(path);
3081 path = cmSystemTools::GetFilenamePath(path.c_str());
3084 path += cmSystemTools::GetExecutableExtension();
3085 if(!cmSystemTools::FileExists(path.c_str()))
3087 path = mf->GetRequiredDefinition("CMAKE_COMMAND");
3088 path = cmSystemTools::GetFilenamePath(path.c_str());
3091 path += cmSystemTools::GetExecutableExtension();
3093 if(!cmSystemTools::FileExists(path.c_str()))
3095 path = mf->GetRequiredDefinition("CMAKE_COMMAND");
3096 path = cmSystemTools::GetFilenamePath(path.c_str());
3097 path += "/Release/";
3099 path += cmSystemTools::GetExecutableExtension();
3102 // Only for bootstrap
3103 path += mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
3106 path += cmSystemTools::GetExecutableExtension();
3112 const char* cmake::GetCTestCommand()
3114 if ( this->CTestCommand.empty() )
3116 this->CTestCommand = this->FindCMakeProgram("ctest");
3118 if ( this->CTestCommand.empty() )
3120 cmSystemTools::Error("Cannot find the CTest executable");
3121 this->CTestCommand = "CTEST-COMMAND-NOT-FOUND";
3123 return this->CTestCommand.c_str();
3126 const char* cmake::GetCPackCommand()
3128 if ( this->CPackCommand.empty() )
3130 this->CPackCommand = this->FindCMakeProgram("cpack");
3132 if ( this->CPackCommand.empty() )
3134 cmSystemTools::Error("Cannot find the CPack executable");
3135 this->CPackCommand = "CPACK-COMMAND-NOT-FOUND";
3137 return this->CPackCommand.c_str();
3141 const char* cmake::GetCMakeCommand()
3143 return this->CMakeCommand.c_str();
3147 void cmake::MarkCliAsUsed(const std::string& variable)
3149 this->UsedCliVariables[variable] = true;
3152 void cmake::GenerateGraphViz(const char* fileName) const
3154 #ifdef CMAKE_BUILD_WITH_CMAKE
3155 cmsys::auto_ptr<cmGraphVizWriter> gvWriter(
3156 new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
3158 std::string settingsFile = this->GetHomeOutputDirectory();
3159 settingsFile += "/CMakeGraphVizOptions.cmake";
3160 std::string fallbackSettingsFile = this->GetHomeDirectory();
3161 fallbackSettingsFile += "/CMakeGraphVizOptions.cmake";
3163 gvWriter->ReadSettings(settingsFile.c_str(), fallbackSettingsFile.c_str());
3165 gvWriter->WritePerTargetFiles(fileName);
3166 gvWriter->WriteTargetDependersFiles(fileName);
3167 gvWriter->WriteGlobalFile(fileName);
3173 //----------------------------------------------------------------------------
3174 int cmake::SymlinkLibrary(std::vector<std::string>& args)
3177 std::string realName = args[2];
3178 std::string soName = args[3];
3179 std::string name = args[4];
3180 if(soName != realName)
3182 if(!cmake::SymlinkInternal(realName, soName))
3184 cmSystemTools::ReportLastSystemError("cmake_symlink_library");
3190 if(!cmake::SymlinkInternal(soName, name))
3192 cmSystemTools::ReportLastSystemError("cmake_symlink_library");
3199 //----------------------------------------------------------------------------
3200 int cmake::SymlinkExecutable(std::vector<std::string>& args)
3203 std::string realName = args[2];
3204 std::string name = args[3];
3205 if(name != realName)
3207 if(!cmake::SymlinkInternal(realName, name))
3209 cmSystemTools::ReportLastSystemError("cmake_symlink_executable");
3216 //----------------------------------------------------------------------------
3217 bool cmake::SymlinkInternal(std::string const& file, std::string const& link)
3219 if(cmSystemTools::FileExists(link.c_str()) ||
3220 cmSystemTools::FileIsSymlink(link.c_str()))
3222 cmSystemTools::RemoveFile(link.c_str());
3224 #if defined(_WIN32) && !defined(__CYGWIN__)
3225 return cmSystemTools::CopyFileAlways(file.c_str(), link.c_str());
3227 std::string linktext = cmSystemTools::GetFilenameName(file);
3228 return cmSystemTools::CreateSymlink(linktext.c_str(), link.c_str());
3232 //----------------------------------------------------------------------------
3233 #ifdef CMAKE_BUILD_WITH_CMAKE
3234 int cmake::ExecuteEchoColor(std::vector<std::string>& args)
3236 // The arguments are
3237 // argv[0] == <cmake-executable>
3238 // argv[1] == cmake_echo_color
3240 bool enabled = true;
3241 int color = cmsysTerminal_Color_Normal;
3242 bool newline = true;
3243 for(unsigned int i=2; i < args.size(); ++i)
3245 if(args[i].find("--switch=") == 0)
3247 // Enable or disable color based on the switch value.
3248 std::string value = args[i].substr(9);
3251 if(cmSystemTools::IsOn(value.c_str()))
3261 else if(args[i] == "--normal")
3263 color = cmsysTerminal_Color_Normal;
3265 else if(args[i] == "--black")
3267 color = cmsysTerminal_Color_ForegroundBlack;
3269 else if(args[i] == "--red")
3271 color = cmsysTerminal_Color_ForegroundRed;
3273 else if(args[i] == "--green")
3275 color = cmsysTerminal_Color_ForegroundGreen;
3277 else if(args[i] == "--yellow")
3279 color = cmsysTerminal_Color_ForegroundYellow;
3281 else if(args[i] == "--blue")
3283 color = cmsysTerminal_Color_ForegroundBlue;
3285 else if(args[i] == "--magenta")
3287 color = cmsysTerminal_Color_ForegroundMagenta;
3289 else if(args[i] == "--cyan")
3291 color = cmsysTerminal_Color_ForegroundCyan;
3293 else if(args[i] == "--white")
3295 color = cmsysTerminal_Color_ForegroundWhite;
3297 else if(args[i] == "--bold")
3299 color |= cmsysTerminal_Color_ForegroundBold;
3301 else if(args[i] == "--no-newline")
3305 else if(args[i] == "--newline")
3311 // Color is enabled. Print with the current color.
3312 cmSystemTools::MakefileColorEcho(color, args[i].c_str(),
3320 int cmake::ExecuteEchoColor(std::vector<std::string>&)
3326 //----------------------------------------------------------------------------
3327 int cmake::ExecuteLinkScript(std::vector<std::string>& args)
3329 // The arguments are
3330 // argv[0] == <cmake-executable>
3331 // argv[1] == cmake_link_script
3332 // argv[2] == <link-script-name>
3333 // argv[3] == --verbose=?
3334 bool verbose = false;
3335 if(args.size() >= 4)
3337 if(args[3].find("--verbose=") == 0)
3339 if(!cmSystemTools::IsOff(args[3].substr(10).c_str()))
3346 // Allocate a process instance.
3347 cmsysProcess* cp = cmsysProcess_New();
3350 std::cerr << "Error allocating process instance in link script."
3355 // Children should share stdout and stderr with this process.
3356 cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
3357 cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
3359 // Run the command lines verbatim.
3360 cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
3362 // Read command lines from the script.
3363 std::ifstream fin(args[2].c_str());
3366 std::cerr << "Error opening link script \""
3367 << args[2] << "\"" << std::endl;
3371 // Run one command at a time.
3372 std::string command;
3374 while(result == 0 && cmSystemTools::GetLineFromStream(fin, command))
3376 // Skip empty command lines.
3377 if(command.find_first_not_of(" \t") == command.npos)
3382 // Setup this command line.
3383 const char* cmd[2] = {command.c_str(), 0};
3384 cmsysProcess_SetCommand(cp, cmd);
3386 // Report the command if verbose output is enabled.
3389 std::cout << command << std::endl;
3392 // Run the command and wait for it to exit.
3393 cmsysProcess_Execute(cp);
3394 cmsysProcess_WaitForExit(cp, 0);
3396 // Report failure if any.
3397 switch(cmsysProcess_GetState(cp))
3399 case cmsysProcess_State_Exited:
3401 int value = cmsysProcess_GetExitValue(cp);
3408 case cmsysProcess_State_Exception:
3409 std::cerr << "Error running link command: "
3410 << cmsysProcess_GetExceptionString(cp) << std::endl;
3413 case cmsysProcess_State_Error:
3414 std::cerr << "Error running link command: "
3415 << cmsysProcess_GetErrorString(cp) << std::endl;
3423 // Free the process instance.
3424 cmsysProcess_Delete(cp);
3426 // Return the final resulting return value.
3430 void cmake::DefineProperties(cmake *cm)
3433 ("REPORT_UNDEFINED_PROPERTIES", cmProperty::GLOBAL,
3434 "If set, report any undefined properties to this file.",
3435 "If this property is set to a filename then when CMake runs "
3436 "it will report any properties or variables that were accessed "
3437 "but not defined into the filename specified in this property."
3441 ("TARGET_SUPPORTS_SHARED_LIBS", cmProperty::GLOBAL,
3442 "Does the target platform support shared libraries.",
3443 "TARGET_SUPPORTS_SHARED_LIBS is a boolean specifying whether the target "
3444 "platform supports shared libraries. Basically all current general "
3445 "general purpose OS do so, the exception are usually embedded systems "
3446 "with no or special OSs.");
3449 ("TARGET_ARCHIVES_MAY_BE_SHARED_LIBS", cmProperty::GLOBAL,
3450 "Set if shared libraries may be named like archives.",
3451 "On AIX shared libraries may be named \"lib<name>.a\". "
3452 "This property is set to true on such platforms.");
3455 ("FIND_LIBRARY_USE_LIB64_PATHS", cmProperty::GLOBAL,
3456 "Whether FIND_LIBRARY should automatically search lib64 directories.",
3457 "FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the "
3458 "FIND_LIBRARY command should automatically search the lib64 variant of "
3459 "directories called lib in the search path when building 64-bit "
3462 ("FIND_LIBRARY_USE_OPENBSD_VERSIONING", cmProperty::GLOBAL,
3463 "Whether FIND_LIBRARY should find OpenBSD-style shared libraries.",
3464 "This property is a boolean specifying whether the FIND_LIBRARY "
3465 "command should find shared libraries with OpenBSD-style versioned "
3466 "extension: \".so.<major>.<minor>\". "
3467 "The property is set to true on OpenBSD and false on other platforms.");
3469 ("ENABLED_FEATURES", cmProperty::GLOBAL,
3470 "List of features which are enabled during the CMake run.",
3471 "List of features which are enabled during the CMake run. By default "
3472 "it contains the names of all packages which were found. This is "
3473 "determined using the <NAME>_FOUND variables. Packages which are "
3474 "searched QUIET are not listed. A project can add its own features to "
3476 "This property is used by the macros in FeatureSummary.cmake.");
3478 ("DISABLED_FEATURES", cmProperty::GLOBAL,
3479 "List of features which are disabled during the CMake run.",
3480 "List of features which are disabled during the CMake run. By default "
3481 "it contains the names of all packages which were not found. This is "
3482 "determined using the <NAME>_FOUND variables. Packages which are "
3483 "searched QUIET are not listed. A project can add its own features to "
3485 "This property is used by the macros in FeatureSummary.cmake.");
3487 ("PACKAGES_FOUND", cmProperty::GLOBAL,
3488 "List of packages which were found during the CMake run.",
3489 "List of packages which were found during the CMake run. Whether a "
3490 "package has been found is determined using the <NAME>_FOUND variables.");
3492 ("PACKAGES_NOT_FOUND", cmProperty::GLOBAL,
3493 "List of packages which were not found during the CMake run.",
3494 "List of packages which were not found during the CMake run. Whether a "
3495 "package has been found is determined using the <NAME>_FOUND variables.");
3498 "__CMAKE_DELETE_CACHE_CHANGE_VARS_", cmProperty::GLOBAL,
3499 "Internal property",
3500 "Used to detect compiler changes, Do not set.");
3503 "DEBUG_CONFIGURATIONS", cmProperty::GLOBAL,
3504 "Specify which configurations are for debugging.",
3505 "The value must be a semi-colon separated list of configuration names. "
3506 "Currently this property is used only by the target_link_libraries "
3507 "command (see its documentation for details). "
3508 "Additional uses may be defined in the future. "
3510 "This property must be set at the top level of the project and before "
3511 "the first target_link_libraries command invocation. "
3512 "If any entry in the list does not match a valid configuration for "
3513 "the project the behavior is undefined.");
3516 "GLOBAL_DEPENDS_DEBUG_MODE", cmProperty::GLOBAL,
3517 "Enable global target dependency graph debug mode.",
3518 "CMake automatically analyzes the global inter-target dependency graph "
3519 "at the beginning of native build system generation. "
3520 "This property causes it to display details of its analysis to stderr.");
3523 "GLOBAL_DEPENDS_NO_CYCLES", cmProperty::GLOBAL,
3524 "Disallow global target dependency graph cycles.",
3525 "CMake automatically analyzes the global inter-target dependency graph "
3526 "at the beginning of native build system generation. "
3527 "It reports an error if the dependency graph contains a cycle that "
3528 "does not consist of all STATIC library targets. "
3529 "This property tells CMake to disallow all cycles completely, even "
3530 "among static libraries.");
3533 "ALLOW_DUPLICATE_CUSTOM_TARGETS", cmProperty::GLOBAL,
3534 "Allow duplicate custom targets to be created.",
3535 "Normally CMake requires that all targets built in a project have "
3536 "globally unique logical names (see policy CMP0002). "
3537 "This is necessary to generate meaningful project file names in "
3538 "Xcode and VS IDE generators. "
3539 "It also allows the target names to be referenced unambiguously.\n"
3540 "Makefile generators are capable of supporting duplicate custom target "
3542 "For projects that care only about Makefile generators and do "
3543 "not wish to support Xcode or VS IDE generators, one may set this "
3544 "property to true to allow duplicate custom targets. "
3545 "The property allows multiple add_custom_target command calls in "
3546 "different directories to specify the same target name. "
3547 "However, setting this property will cause non-Makefile generators "
3548 "to produce an error and refuse to generate the project."
3552 ("IN_TRY_COMPILE", cmProperty::GLOBAL,
3553 "Read-only property that is true during a try-compile configuration.",
3554 "True when building a project inside a TRY_COMPILE or TRY_RUN command.");
3556 ("ENABLED_LANGUAGES", cmProperty::GLOBAL,
3557 "Read-only property that contains the list of currently "
3558 "enabled languages",
3559 "Set to list of currently enabled languages.");
3562 ("RULE_LAUNCH_COMPILE", cmProperty::GLOBAL,
3563 "Specify a launcher for compile rules.",
3564 "Makefile generators prefix compiler commands with the given "
3565 "launcher command line. "
3566 "This is intended to allow launchers to intercept build problems "
3567 "with high granularity. "
3568 "Non-Makefile generators currently ignore this property.");
3570 ("RULE_LAUNCH_LINK", cmProperty::GLOBAL,
3571 "Specify a launcher for link rules.",
3572 "Makefile generators prefix link and archive commands with the given "
3573 "launcher command line. "
3574 "This is intended to allow launchers to intercept build problems "
3575 "with high granularity. "
3576 "Non-Makefile generators currently ignore this property.");
3578 ("RULE_LAUNCH_CUSTOM", cmProperty::GLOBAL,
3579 "Specify a launcher for custom rules.",
3580 "Makefile generators prefix custom commands with the given "
3581 "launcher command line. "
3582 "This is intended to allow launchers to intercept build problems "
3583 "with high granularity. "
3584 "Non-Makefile generators currently ignore this property.");
3587 ("RULE_MESSAGES", cmProperty::GLOBAL,
3588 "Specify whether to report a message for each make rule.",
3589 "This property specifies whether Makefile generators should add a "
3590 "progress message describing what each build rule does. "
3591 "If the property is not set the default is ON. "
3592 "Set the property to OFF to disable granular messages and report only "
3593 "as each target completes. "
3594 "This is intended to allow scripted builds to avoid the build time "
3595 "cost of detailed reports. "
3596 "If a CMAKE_RULE_MESSAGES cache entry exists its value initializes "
3597 "the value of this property. "
3598 "Non-Makefile generators currently ignore this property.");
3601 ("USE_FOLDERS", cmProperty::GLOBAL,
3602 "Use the FOLDER target property to organize targets into folders.",
3603 "If not set, CMake treats this property as OFF by default. "
3604 "CMake generators that are capable of organizing into a "
3605 "hierarchy of folders use the values of the FOLDER target "
3606 "property to name those folders. See also the documentation "
3607 "for the FOLDER target property.");
3610 ("AUTOMOC_TARGETS_FOLDER", cmProperty::GLOBAL,
3611 "Name of FOLDER for *_automoc targets that are added automatically by "
3612 "CMake for targets for which AUTOMOC is enabled.",
3613 "If not set, CMake uses the FOLDER property of the parent target as a "
3614 "default value for this property. See also the documentation for the "
3615 "FOLDER target property and the AUTOMOC target property.");
3618 ("PREDEFINED_TARGETS_FOLDER", cmProperty::GLOBAL,
3619 "Name of FOLDER for targets that are added automatically by CMake.",
3620 "If not set, CMake uses \"CMakePredefinedTargets\" as a default "
3621 "value for this property. Targets such as INSTALL, PACKAGE and "
3622 "RUN_TESTS will be organized into this FOLDER. See also the "
3623 "documentation for the FOLDER target property.");
3625 // ================================================================
3626 // define variables as well
3627 // ================================================================
3628 cmDocumentVariables::DefineVariables(cm);
3632 void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope,
3633 const char *ShortDescription,
3634 const char *FullDescription,
3635 bool chained, const char *docSection)
3637 this->PropertyDefinitions[scope].DefineProperty(name,scope,ShortDescription,
3643 bool cmake::GetIsPropertyDefined(const char *name,
3644 cmProperty::ScopeType scope)
3646 return this->PropertyDefinitions[scope].find(name) !=
3647 this->PropertyDefinitions[scope].end();
3650 cmPropertyDefinition *cmake
3651 ::GetPropertyDefinition(const char *name,
3652 cmProperty::ScopeType scope)
3654 if (this->IsPropertyDefined(name,scope))
3656 return &(this->PropertyDefinitions[scope][name]);
3661 void cmake::RecordPropertyAccess(const char *name,
3662 cmProperty::ScopeType scope)
3664 this->AccessedProperties.insert
3665 (std::pair<cmStdString,cmProperty::ScopeType>(name,scope));
3668 void cmake::ReportUndefinedPropertyAccesses(const char *filename)
3670 if(!this->GlobalGenerator)
3672 FILE *progFile = fopen(filename,"w");
3676 // what are the enabled languages?
3677 std::vector<std::string> enLangs;
3678 this->GlobalGenerator->GetEnabledLanguages(enLangs);
3680 // Common configuration names.
3681 // TODO: Compute current configuration(s).
3682 std::vector<std::string> enConfigs;
3683 enConfigs.push_back("");
3684 enConfigs.push_back("DEBUG");
3685 enConfigs.push_back("RELEASE");
3686 enConfigs.push_back("MINSIZEREL");
3687 enConfigs.push_back("RELWITHDEBINFO");
3689 // take all the defined properties and add definitions for all the enabled
3691 std::set<std::pair<cmStdString,cmProperty::ScopeType> > aliasedProperties;
3692 std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::iterator i;
3693 i = this->PropertyDefinitions.begin();
3694 for (;i != this->PropertyDefinitions.end(); ++i)
3696 cmPropertyDefinitionMap::iterator j;
3697 for (j = i->second.begin(); j != i->second.end(); ++j)
3699 // TODO: What if both <LANG> and <CONFIG> appear?
3700 if (j->first.find("<CONFIG>") != std::string::npos)
3702 std::vector<std::string>::const_iterator k;
3703 for (k = enConfigs.begin(); k != enConfigs.end(); ++k)
3705 std::string tmp = j->first;
3706 cmSystemTools::ReplaceString(tmp, "<CONFIG>", k->c_str());
3708 aliasedProperties.insert
3709 (std::pair<cmStdString,cmProperty::ScopeType>(tmp,i->first));
3712 if (j->first.find("<LANG>") != std::string::npos)
3714 std::vector<std::string>::const_iterator k;
3715 for (k = enLangs.begin(); k != enLangs.end(); ++k)
3717 std::string tmp = j->first;
3718 cmSystemTools::ReplaceString(tmp, "<LANG>", k->c_str());
3720 aliasedProperties.insert
3721 (std::pair<cmStdString,cmProperty::ScopeType>(tmp,i->first));
3727 std::set<std::pair<cmStdString,cmProperty::ScopeType> >::const_iterator ap;
3728 ap = this->AccessedProperties.begin();
3729 for (;ap != this->AccessedProperties.end(); ++ap)
3731 if (!this->IsPropertyDefined(ap->first.c_str(),ap->second) &&
3732 aliasedProperties.find(std::pair<cmStdString,cmProperty::ScopeType>
3733 (ap->first,ap->second)) ==
3734 aliasedProperties.end())
3736 const char *scopeStr = "";
3739 case cmProperty::TARGET:
3740 scopeStr = "TARGET";
3742 case cmProperty::SOURCE_FILE:
3743 scopeStr = "SOURCE_FILE";
3745 case cmProperty::DIRECTORY:
3746 scopeStr = "DIRECTORY";
3748 case cmProperty::TEST:
3751 case cmProperty::VARIABLE:
3752 scopeStr = "VARIABLE";
3754 case cmProperty::CACHED_VARIABLE:
3755 scopeStr = "CACHED_VARIABLE";
3758 scopeStr = "unknown";
3761 fprintf(progFile, "%s with scope %s\n", ap->first.c_str(), scopeStr);
3767 bool cmake::IsPropertyDefined(const char *name, cmProperty::ScopeType scope)
3769 return this->PropertyDefinitions[scope].IsPropertyDefined(name);
3772 bool cmake::IsPropertyChained(const char *name, cmProperty::ScopeType scope)
3774 return this->PropertyDefinitions[scope].IsPropertyChained(name);
3777 void cmake::SetProperty(const char* prop, const char* value)
3784 // Special hook to invalidate cached value.
3785 if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0)
3787 this->DebugConfigs.clear();
3790 this->Properties.SetProperty(prop, value, cmProperty::GLOBAL);
3793 void cmake::AppendProperty(const char* prop, const char* value, bool asString)
3800 // Special hook to invalidate cached value.
3801 if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0)
3803 this->DebugConfigs.clear();
3806 this->Properties.AppendProperty(prop, value, cmProperty::GLOBAL, asString);
3809 const char *cmake::GetProperty(const char* prop)
3811 return this->GetProperty(prop, cmProperty::GLOBAL);
3814 const char *cmake::GetProperty(const char* prop, cmProperty::ScopeType scope)
3822 // watch for special properties
3823 std::string propname = prop;
3824 std::string output = "";
3825 if ( propname == "CACHE_VARIABLES" )
3827 cmCacheManager::CacheIterator cit =
3828 this->GetCacheManager()->GetCacheIterator();
3829 for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
3831 if ( output.size() )
3835 output += cit.GetName();
3837 this->SetProperty("CACHE_VARIABLES", output.c_str());
3839 else if ( propname == "COMMANDS" )
3841 cmake::RegisteredCommandsMap::iterator cmds
3842 = this->GetCommands()->begin();
3843 for (unsigned int cc=0 ; cmds != this->GetCommands()->end(); ++ cmds )
3849 output += cmds->first.c_str();
3852 this->SetProperty("COMMANDS",output.c_str());
3854 else if ( propname == "IN_TRY_COMPILE" )
3856 this->SetProperty("IN_TRY_COMPILE",
3857 this->GetIsInTryCompile()? "1":"0");
3859 else if ( propname == "ENABLED_LANGUAGES" )
3862 if(this->GlobalGenerator)
3864 std::vector<std::string> enLangs;
3865 this->GlobalGenerator->GetEnabledLanguages(enLangs);
3866 const char* sep = "";
3867 for(std::vector<std::string>::iterator i = enLangs.begin();
3868 i != enLangs.end(); ++i)
3875 this->SetProperty("ENABLED_LANGUAGES", lang.c_str());
3877 return this->Properties.GetPropertyValue(prop, scope, chain);
3880 bool cmake::GetPropertyAsBool(const char* prop)
3882 return cmSystemTools::IsOn(this->GetProperty(prop));
3885 int cmake::GetSystemInformation(std::vector<std::string>& args)
3887 // so create the directory
3888 std::string resultFile;
3889 std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
3890 std::string destPath = cwd + "/__cmake_systeminformation";
3891 cmSystemTools::RemoveADirectory(destPath.c_str());
3892 if (!cmSystemTools::MakeDirectory(destPath.c_str()))
3894 std::cerr << "Error: --system-information must be run from a "
3895 "writable directory!\n";
3899 // process the arguments
3900 bool writeToStdout = true;
3901 for(unsigned int i=1; i < args.size(); ++i)
3903 std::string arg = args[i];
3904 if(arg.find("-V",0) == 0)
3906 this->Verbose = true;
3908 else if(arg.find("-G",0) == 0)
3910 std::string value = arg.substr(2);
3911 if(value.size() == 0)
3914 if(i >= args.size())
3916 cmSystemTools::Error("No generator specified for -G");
3921 cmGlobalGenerator* gen =
3922 this->CreateGlobalGenerator(value.c_str());
3925 cmSystemTools::Error("Could not create named generator ",
3930 this->SetGlobalGenerator(gen);
3933 // no option assume it is the output file
3936 if (!cmSystemTools::FileIsFullPath(arg.c_str()))
3942 writeToStdout = false;
3947 // we have to find the module directory, so we can copy the files
3948 this->AddCMakePaths();
3949 std::string modulesPath =
3950 this->CacheManager->GetCacheValue("CMAKE_ROOT");
3951 modulesPath += "/Modules";
3952 std::string inFile = modulesPath;
3953 inFile += "/SystemInformation.cmake";
3954 std::string outFile = destPath;
3955 outFile += "/CMakeLists.txt";
3958 if(!cmSystemTools::cmCopyFile(inFile.c_str(), outFile.c_str()))
3960 std::cerr << "Error copying file \"" << inFile.c_str()
3961 << "\" to \"" << outFile.c_str() << "\".\n";
3965 // do we write to a file or to stdout?
3966 if (resultFile.size() == 0)
3969 resultFile += "/__cmake_systeminformation/results.txt";
3972 // now run cmake on the CMakeLists file
3973 cmSystemTools::ChangeDirectory(destPath.c_str());
3974 std::vector<std::string> args2;
3975 args2.push_back(args[0]);
3976 args2.push_back(destPath);
3977 std::string resultArg = "-DRESULT_FILE=";
3978 resultArg += resultFile;
3979 args2.push_back(resultArg);
3980 int res = this->Run(args2, false);
3984 std::cerr << "Error: --system-information failed on internal CMake!\n";
3988 // change back to the original directory
3989 cmSystemTools::ChangeDirectory(cwd.c_str());
3991 // echo results to stdout if needed
3994 FILE* fin = fopen(resultFile.c_str(), "r");
3997 const int bufferSize = 4096;
3998 char buffer[bufferSize];
4000 while((n = fread(buffer, 1, bufferSize, fin)) > 0)
4002 for(char* c = buffer; c < buffer+n; ++c)
4012 // clean up the directory
4013 cmSystemTools::RemoveADirectory(destPath.c_str());
4017 //----------------------------------------------------------------------------
4018 static bool cmakeCheckStampFile(const char* stampName)
4020 // The stamp file does not exist. Use the stamp dependencies to
4021 // determine whether it is really out of date. This works in
4022 // conjunction with cmLocalVisualStudio7Generator to avoid
4023 // repeatedly re-running CMake when the user rebuilds the entire
4025 std::string stampDepends = stampName;
4026 stampDepends += ".depend";
4027 #if defined(_WIN32) || defined(__CYGWIN__)
4028 std::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
4030 std::ifstream fin(stampDepends.c_str(), std::ios::in);
4034 // The stamp dependencies file cannot be read. Just assume the
4035 // build system is really out of date.
4036 std::cout << "CMake is re-running because " << stampName
4037 << " dependency file is missing.\n";
4041 // Compare the stamp dependencies against the dependency file itself.
4042 cmFileTimeComparison ftc;
4044 while(cmSystemTools::GetLineFromStream(fin, dep))
4047 if(dep.length() >= 1 && dep[0] != '#' &&
4048 (!ftc.FileTimeCompare(stampDepends.c_str(), dep.c_str(), &result)
4051 // The stamp depends file is older than this dependency. The
4052 // build system is really out of date.
4053 std::cout << "CMake is re-running because " << stampName
4054 << " is out-of-date.\n";
4055 std::cout << " the file '" << dep << "'\n";
4056 std::cout << " is newer than '" << stampDepends << "'\n";
4057 std::cout << " result='" << result << "'\n";
4062 // The build system is up to date. The stamp file has been removed
4063 // by the VS IDE due to a "rebuild" request. Restore it atomically.
4064 cmOStringStream stampTempStream;
4065 stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
4066 std::string stampTempString = stampTempStream.str();
4067 const char* stampTemp = stampTempString.c_str();
4069 // TODO: Teach cmGeneratedFileStream to use a random temp file (with
4070 // multiple tries in unlikely case of conflict) and use that here.
4071 std::ofstream stamp(stampTemp);
4072 stamp << "# CMake generation timestamp file for this directory.\n";
4074 if(cmSystemTools::RenameFile(stampTemp, stampName))
4076 // Notify the user why CMake is not re-running. It is safe to
4077 // just print to stdout here because this code is only reachable
4078 // through an undocumented flag used by the VS generator.
4079 std::cout << "CMake does not need to re-run because "
4080 << stampName << " is up-to-date.\n";
4085 cmSystemTools::RemoveFile(stampTemp);
4086 cmSystemTools::Error("Cannot restore timestamp ", stampName);
4091 //----------------------------------------------------------------------------
4092 static bool cmakeCheckStampList(const char* stampList)
4094 // If the stamp list does not exist CMake must rerun to generate it.
4095 if(!cmSystemTools::FileExists(stampList))
4097 std::cout << "CMake is re-running because generate.stamp.list "
4101 std::ifstream fin(stampList);
4104 std::cout << "CMake is re-running because generate.stamp.list "
4105 << "could not be read.\n";
4109 // Check each stamp.
4110 std::string stampName;
4111 while(cmSystemTools::GetLineFromStream(fin, stampName))
4113 if(!cmakeCheckStampFile(stampName.c_str()))
4121 //----------------------------------------------------------------------------
4122 int cmake::WindowsCEEnvironment(const char* version, const std::string& name)
4124 #if defined(CMAKE_HAVE_VS_GENERATORS)
4125 cmVisualStudioWCEPlatformParser parser(name.c_str());
4126 parser.ParseVersion(version);
4129 std::cout << "@echo off" << std::endl;
4130 std::cout << "echo Environment Selection: " << name << std::endl;
4131 std::cout << "set PATH=" << parser.GetPathDirectories() << std::endl;
4132 std::cout << "set INCLUDE=" << parser.GetIncludeDirectories() <<std::endl;
4133 std::cout << "set LIB=" << parser.GetLibraryDirectories() <<std::endl;
4140 std::cerr << "Could not find " << name;
4144 // For visual studio 2005 and newer manifest files need to be embedded into
4145 // exe and dll's. This code does that in such a way that incremental linking
4147 int cmake::VisualStudioLink(std::vector<std::string>& args, int type)
4153 bool verbose = false;
4154 if(cmSystemTools::GetEnv("VERBOSE"))
4158 std::vector<std::string> expandedArgs;
4159 for(std::vector<std::string>::iterator i = args.begin();
4160 i != args.end(); ++i)
4162 // check for nmake temporary files
4163 if((*i)[0] == '@' && i->find("@CMakeFiles") != 0 )
4165 std::ifstream fin(i->substr(1).c_str());
4167 while(cmSystemTools::GetLineFromStream(fin,
4170 cmSystemTools::ParseWindowsCommandLine(line.c_str(), expandedArgs);
4175 expandedArgs.push_back(*i);
4178 bool hasIncremental = false;
4179 bool hasManifest = true;
4180 for(std::vector<std::string>::iterator i = expandedArgs.begin();
4181 i != expandedArgs.end(); ++i)
4183 if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL:YES") == 0)
4185 hasIncremental = true;
4187 if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL") == 0)
4189 hasIncremental = true;
4191 if(cmSystemTools::Strucmp(i->c_str(), "/MANIFEST:NO") == 0)
4193 hasManifest = false;
4196 if(hasIncremental && hasManifest)
4200 std::cout << "Visual Studio Incremental Link with embedded manifests\n";
4202 return cmake::VisualStudioLinkIncremental(expandedArgs, type, verbose);
4208 std::cout << "Visual Studio Non-Incremental Link\n";
4212 std::cout << "Visual Studio Incremental Link without manifests\n";
4215 return cmake::VisualStudioLinkNonIncremental(expandedArgs,
4216 type, hasManifest, verbose);
4219 int cmake::ParseVisualStudioLinkCommand(std::vector<std::string>& args,
4220 std::vector<cmStdString>& command,
4221 std::string& targetName)
4223 std::vector<std::string>::iterator i = args.begin();
4225 i++; // skip vs_link_dll or vs_link_exe
4226 command.push_back(*i);
4227 i++; // move past link command
4228 for(; i != args.end(); ++i)
4230 command.push_back(*i);
4231 if(i->find("/Fe") == 0)
4233 targetName = i->substr(3);
4235 if(i->find("/out:") == 0)
4237 targetName = i->substr(5);
4240 if(targetName.size() == 0 || command.size() == 0)
4247 bool cmake::RunCommand(const char* comment,
4248 std::vector<cmStdString>& command,
4254 std::cout << comment << ":\n";
4255 for(std::vector<cmStdString>::iterator i = command.begin();
4256 i != command.end(); ++i)
4258 std::cout << i->c_str() << " ";
4264 // use rc command to create .res file
4265 cmSystemTools::RunSingleCommand(command,
4267 &retCode, 0, cmSystemTools::OUTPUT_NONE);
4268 // always print the output of the command, unless
4269 // it is the dumb rc command banner, but if the command
4270 // returned an error code then print the output anyway as
4271 // the banner may be mixed with some other important information.
4272 if(output.find("Resource Compiler Version") == output.npos
4275 std::cout << output;
4277 // if retCodeOut is requested then always return true
4278 // and set the retCodeOut to retCode
4281 *retCodeOut = retCode;
4286 std::cout << comment << " failed. with " << retCode << "\n";
4288 return retCode == 0;
4291 int cmake::VisualStudioLinkIncremental(std::vector<std::string>& args,
4292 int type, bool verbose)
4294 // This follows the steps listed here:
4295 // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
4297 // 1. Compiler compiles the application and generates the *.obj files.
4298 // 2. An empty manifest file is generated if this is a clean build and if
4299 // not the previous one is reused.
4300 // 3. The resource compiler (rc.exe) compiles the *.manifest file to a
4302 // 4. Linker generates the binary (EXE or DLL) with the /incremental
4303 // switch and embeds the dummy manifest file. The linker also generates
4304 // the real manifest file based on the binaries that your binary depends
4306 // 5. The manifest tool (mt.exe) is then used to generate the final
4309 // If the final manifest is changed, then 6 and 7 are run, if not
4310 // they are skipped, and it is done.
4312 // 6. The resource compiler is invoked one more time.
4313 // 7. Finally, the Linker does another incremental link, but since the
4314 // only thing that has changed is the *.res file that contains the
4315 // manifest it is a short link.
4316 std::vector<cmStdString> linkCommand;
4317 std::string targetName;
4318 if(cmake::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
4322 std::string manifestArg = "/MANIFESTFILE:";
4323 std::vector<cmStdString> rcCommand;
4324 rcCommand.push_back(cmSystemTools::FindProgram("rc.exe"));
4325 std::vector<cmStdString> mtCommand;
4326 mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
4327 std::string tempManifest;
4328 tempManifest = targetName;
4329 tempManifest += ".intermediate.manifest";
4330 std::string resourceInputFile = targetName;
4331 resourceInputFile += ".resource.txt";
4334 std::cout << "Create " << resourceInputFile.c_str() << "\n";
4336 // Create input file for rc command
4337 std::ofstream fout(resourceInputFile.c_str());
4342 std::string manifestFile = targetName;
4343 manifestFile += ".embed.manifest";
4344 std::string fullPath= cmSystemTools::CollapseFullPath(manifestFile.c_str());
4345 fout << type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID "
4346 "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath.c_str() << "\"";
4348 manifestArg += tempManifest;
4349 // add the manifest arg to the linkCommand
4350 linkCommand.push_back("/MANIFEST");
4351 linkCommand.push_back(manifestArg);
4352 // if manifestFile is not yet created, create an
4354 if(!cmSystemTools::FileExists(manifestFile.c_str()))
4358 std::cout << "Create empty: " << manifestFile.c_str() << "\n";
4360 std::ofstream foutTmp(manifestFile.c_str());
4362 std::string resourceFile = manifestFile;
4363 resourceFile += ".res";
4364 // add the resource file to the end of the link command
4365 linkCommand.push_back(resourceFile);
4366 std::string outputOpt = "/fo";
4367 outputOpt += resourceFile;
4368 rcCommand.push_back(outputOpt);
4369 rcCommand.push_back(resourceInputFile);
4370 // Run rc command to create resource
4371 if(!cmake::RunCommand("RC Pass 1", rcCommand, verbose))
4375 // Now run the link command to link and create manifest
4376 if(!cmake::RunCommand("LINK Pass 1", linkCommand, verbose))
4380 // create mt command
4381 std::string outArg("/out:");
4382 outArg+= manifestFile;
4383 mtCommand.push_back("/nologo");
4384 mtCommand.push_back(outArg);
4385 mtCommand.push_back("/notify_update");
4386 mtCommand.push_back("/manifest");
4387 mtCommand.push_back(tempManifest);
4388 // now run mt.exe to create the final manifest file
4390 cmake::RunCommand("MT", mtCommand, verbose, &mtRet);
4391 // if mt returns 0, then the manifest was not changed and
4392 // we do not need to do another link step
4397 // check for magic mt return value if mt returns the magic number
4398 // 1090650113 then it means that it updated the manifest file and we need
4399 // to do the final link. If mt has any value other than 0 or 1090650113
4400 // then there was some problem with the command itself and there was an
4401 // error so return the error code back out of cmake so make can report it.
4402 if(mtRet != 1090650113)
4406 // update the resource file with the new manifest from the mt command.
4407 if(!cmake::RunCommand("RC Pass 2", rcCommand, verbose))
4411 // Run the final incremental link that will put the new manifest resource
4412 // into the file incrementally.
4413 if(!cmake::RunCommand("FINAL LINK", linkCommand, verbose))
4420 int cmake::VisualStudioLinkNonIncremental(std::vector<std::string>& args,
4425 std::vector<cmStdString> linkCommand;
4426 std::string targetName;
4427 if(cmake::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1)
4431 // Run the link command as given
4434 linkCommand.push_back("/MANIFEST");
4436 if(!cmake::RunCommand("LINK", linkCommand, verbose))
4444 std::vector<cmStdString> mtCommand;
4445 mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
4446 mtCommand.push_back("/nologo");
4447 mtCommand.push_back("/manifest");
4448 std::string manifestFile = targetName;
4449 manifestFile += ".manifest";
4450 mtCommand.push_back(manifestFile);
4451 std::string outresource = "/outputresource:";
4452 outresource += targetName;
4453 outresource += ";#";
4462 mtCommand.push_back(outresource);
4463 // Now use the mt tool to embed the manifest into the exe or dll
4464 if(!cmake::RunCommand("MT", mtCommand, verbose))
4471 //----------------------------------------------------------------------------
4472 void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
4473 cmListFileBacktrace const& backtrace)
4475 cmOStringStream msg;
4476 bool isError = false;
4477 // Construct the message header.
4478 if(t == cmake::FATAL_ERROR)
4481 msg << "CMake Error";
4483 else if(t == cmake::INTERNAL_ERROR)
4486 msg << "CMake Internal Error (please report a bug)";
4488 else if(t == cmake::LOG)
4490 msg << "CMake Debug Log";
4494 msg << "CMake Warning";
4495 if(t == cmake::AUTHOR_WARNING)
4497 // Allow suppression of these warnings.
4498 cmCacheManager::CacheIterator it = this->CacheManager
4499 ->GetCacheIterator("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
4500 if(!it.IsAtEnd() && it.GetValueAsBool())
4508 // Add the immediate context.
4509 cmListFileBacktrace::const_iterator i = backtrace.begin();
4510 if(i != backtrace.end())
4512 cmListFileContext const& lfc = *i;
4513 msg << (lfc.Line? " at ": " in ") << lfc;
4517 // Add the message text.
4520 cmDocumentationFormatterText formatter;
4521 formatter.SetIndent(" ");
4522 formatter.PrintFormatted(msg, text.c_str());
4525 // Add the rest of the context.
4526 if(i != backtrace.end())
4528 msg << "Call Stack (most recent call first):\n";
4529 while(i != backtrace.end())
4531 cmListFileContext const& lfc = *i;
4532 msg << " " << lfc << "\n";
4537 // Add a note about warning suppression.
4538 if(t == cmake::AUTHOR_WARNING)
4541 "This warning is for project developers. Use -Wno-dev to suppress it.";
4544 // Add a terminating blank line.
4547 // Output the message.
4550 cmSystemTools::SetErrorOccured();
4551 cmSystemTools::Message(msg.str().c_str(), "Error");
4555 cmSystemTools::Message(msg.str().c_str(), "Warning");
4559 //----------------------------------------------------------------------------
4560 std::vector<std::string> const& cmake::GetDebugConfigs()
4562 // Compute on-demand.
4563 if(this->DebugConfigs.empty())
4565 if(const char* config_list = this->GetProperty("DEBUG_CONFIGURATIONS"))
4567 // Expand the specified list and convert to upper-case.
4568 cmSystemTools::ExpandListArgument(config_list, this->DebugConfigs);
4569 for(std::vector<std::string>::iterator i = this->DebugConfigs.begin();
4570 i != this->DebugConfigs.end(); ++i)
4572 *i = cmSystemTools::UpperCase(*i);
4575 // If no configurations were specified, use a default list.
4576 if(this->DebugConfigs.empty())
4578 this->DebugConfigs.push_back("DEBUG");
4581 return this->DebugConfigs;
4585 int cmake::Build(const std::string& dir,
4586 const std::string& target,
4587 const std::string& config,
4588 const std::vector<std::string>& nativeOptions,
4590 cmSystemTools::OutputOption outputflag)
4592 if(!cmSystemTools::FileIsDirectory(dir.c_str()))
4594 std::cerr << "Error: " << dir << " is not a directory\n";
4597 std::string cachePath = dir;
4598 cmSystemTools::ConvertToUnixSlashes(cachePath);
4599 cmCacheManager* cachem = this->GetCacheManager();
4600 cmCacheManager::CacheIterator it = cachem->NewIterator();
4601 if(!cachem->LoadCache(cachePath.c_str()))
4603 std::cerr << "Error: could not load cache\n";
4606 if(!it.Find("CMAKE_GENERATOR"))
4608 std::cerr << "Error: could find generator in Cache\n";
4611 cmsys::auto_ptr<cmGlobalGenerator> gen(
4612 this->CreateGlobalGenerator(it.GetValue()));
4614 std::string projName;
4615 std::string makeProgram;
4616 if(!it.Find("CMAKE_PROJECT_NAME"))
4618 std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
4621 projName = it.GetValue();
4622 if(!it.Find("CMAKE_MAKE_PROGRAM"))
4624 std::cerr << "Error: could not find CMAKE_MAKE_PROGRAM in Cache\n";
4627 makeProgram = it.GetValue();
4628 return gen->Build(0, dir.c_str(),
4629 projName.c_str(), target.c_str(),
4631 makeProgram.c_str(),
4632 config.c_str(), clean, false, 0, outputflag,
4636 void cmake::WatchUnusedCli(const char* var)
4638 #ifdef CMAKE_BUILD_WITH_CMAKE
4639 this->VariableWatch->AddWatch(var, cmWarnUnusedCliWarning, this);
4640 if(this->UsedCliVariables.find(var) == this->UsedCliVariables.end())
4642 this->UsedCliVariables[var] = false;
4647 void cmake::UnwatchUnusedCli(const char* var)
4649 #ifdef CMAKE_BUILD_WITH_CMAKE
4650 this->VariableWatch->RemoveWatch(var, cmWarnUnusedCliWarning);
4651 this->UsedCliVariables.erase(var);
4655 void cmake::RunCheckForUnusedVariables()
4657 #ifdef CMAKE_BUILD_WITH_CMAKE
4658 bool haveUnused = false;
4659 cmOStringStream msg;
4660 msg << "Manually-specified variables were not used by the project:";
4661 for(std::map<cmStdString, bool>::const_iterator
4662 it = this->UsedCliVariables.begin();
4663 it != this->UsedCliVariables.end(); ++it)
4668 msg << "\n " << it->first;
4673 this->IssueMessage(cmake::WARNING, msg.str(), cmListFileBacktrace());