ENH: mark some vars as advanced (and resort the list)
[cmake.git] / Source / cmake.cxx
blob7aa0a387a91cc1c3e15bea49a053ee4bb065f92a
1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmake.cxx,v $
5 Language: C++
6 Date: $Date: 2002-10-10 14:43:59 $
7 Version: $Revision: 1.91 $
9 Copyright (c) 2002 Insight Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmake.h"
18 #include "time.h"
19 #include "cmCacheManager.h"
20 #include "cmMakefile.h"
21 #include "cmLocalGenerator.h"
22 #include "cmCommands.h"
23 #include "cmCommand.h"
25 // include the generator
26 #if defined(_WIN32) && !defined(__CYGWIN__)
27 #include "cmGlobalVisualStudio6Generator.h"
28 #include "cmGlobalVisualStudio7Generator.h"
29 #include "cmGlobalBorlandMakefileGenerator.h"
30 #include "cmGlobalNMakeMakefileGenerator.h"
31 #include "cmWin32ProcessExecution.h"
32 #else
33 #include "cmGlobalCodeWarriorGenerator.h"
34 #include "cmGlobalUnixMakefileGenerator.h"
35 #endif
37 #include <stdio.h>
39 cmake::cmake()
41 m_Local = false;
42 m_Verbose = false;
43 m_InTryCompile = false;
44 m_CacheManager = new cmCacheManager;
45 m_GlobalGenerator = 0;
46 m_ProgressCallback = 0;
47 m_ProgressCallbackClientData = 0;
49 this->AddDefaultCommands();
52 cmake::~cmake()
54 delete m_CacheManager;
55 if (m_GlobalGenerator)
57 delete m_GlobalGenerator;
58 m_GlobalGenerator = 0;
60 for(RegisteredCommandsMap::iterator j = m_Commands.begin();
61 j != m_Commands.end(); ++j)
63 delete (*j).second;
67 bool cmake::CommandExists(const char* name) const
69 return (m_Commands.find(name) != m_Commands.end());
72 cmCommand *cmake::GetCommand(const char *name)
74 cmCommand* rm = 0;
75 RegisteredCommandsMap::iterator pos = m_Commands.find(name);
76 if (pos != m_Commands.end())
78 rm = (*pos).second;
80 return rm;
83 void cmake::AddCommand(cmCommand* wg)
85 std::string name = wg->GetName();
86 // if the command already exists, free the old one
87 RegisteredCommandsMap::iterator pos = m_Commands.find(name);
88 if (pos != m_Commands.end())
90 delete pos->second;
91 m_Commands.erase(pos);
93 m_Commands.insert( RegisteredCommandsMap::value_type(name, wg));
96 void cmake::Usage(const char* program)
98 cmOStringStream errorStream;
100 errorStream << "cmake version " << cmMakefile::GetMajorVersion()
101 << "." << cmMakefile::GetMinorVersion() << "\n";
102 errorStream << "Usage: " << program << " [srcdir] [options]\n"
103 << "Where cmake is run from the directory where you want the object files written. If srcdir is not specified, the current directory is used for both source and object files.\n";
104 errorStream << "Options are:\n";
105 errorStream << "\n-i (puts cmake in wizard mode, not available for ccmake)\n";
106 errorStream << "\n-DVAR:TYPE=VALUE (create a cache file entry)\n";
107 errorStream << "\n-Cpath_to_initial_cache (a cmake list file that is used to pre-load the cache with values.)\n";
108 errorStream << "\n[-GgeneratorName] (where generator name can be one of these: ";
109 std::vector<std::string> names;
110 this->GetRegisteredGenerators(names);
111 for(std::vector<std::string>::iterator i =names.begin();
112 i != names.end(); ++i)
114 errorStream << "\"" << i->c_str() << "\" ";
116 errorStream << ")\n";
118 cmSystemTools::Error(errorStream.str().c_str());
121 // Parse the args
122 void cmake::SetCacheArgs(const std::vector<std::string>& args)
124 for(unsigned int i=1; i < args.size(); ++i)
126 std::string arg = args[i];
127 if(arg.find("-D",0) == 0)
129 std::string entry = arg.substr(2);
130 std::string var, value;
131 cmCacheManager::CacheEntryType type;
132 if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
134 this->m_CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
135 "No help, variable specified on the command line.",
136 type);
138 else
140 std::cerr << "Parse error in command line argument: " << arg << "\n"
141 << "Should be: VAR:type=value\n";
144 else if(arg.find("-C",0) == 0)
146 std::string path = arg.substr(2);
147 std::cerr << "loading initial cache file " << path.c_str() << "\n";
148 this->ReadListFile(path.c_str());
153 void cmake::ReadListFile(const char *path)
155 // if a generator was not yet created, temporarily create one
156 cmGlobalGenerator *gg = this->GetGlobalGenerator();
157 bool created = false;
159 // if a generator was not specified use a generic one
160 if (!gg)
162 gg = new cmGlobalGenerator;
163 gg->SetCMakeInstance(this);
164 created = true;
167 // read in the list file to fill the cache
168 if(path)
170 cmLocalGenerator *lg = gg->CreateLocalGenerator();
171 lg->SetGlobalGenerator(gg);
172 if (!lg->GetMakefile()->ReadListFile(path))
174 std::cerr << "Error in reading cmake initial cache file:"
175 << path << "\n";
179 // free generic one if generated
180 if (created)
182 delete gg;
186 // Parse the args
187 void cmake::SetArgs(const std::vector<std::string>& args)
189 m_Local = false;
190 bool directoriesSet = false;
191 // watch for cmake and cmake srcdir invocations
192 if (args.size() <= 2)
194 directoriesSet = true;
195 this->SetHomeOutputDirectory
196 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
197 this->SetStartOutputDirectory
198 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
199 if (args.size() == 2)
201 this->SetHomeDirectory
202 (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
203 this->SetStartDirectory
204 (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
206 else
208 this->SetHomeDirectory
209 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
210 this->SetStartDirectory
211 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
215 for(unsigned int i=1; i < args.size(); ++i)
217 std::string arg = args[i];
218 if(arg.find("-H",0) == 0)
220 directoriesSet = true;
221 std::string path = arg.substr(2);
222 this->SetHomeDirectory(path.c_str());
224 else if(arg.find("-S",0) == 0)
226 directoriesSet = true;
227 m_Local = true;
228 std::string path = arg.substr(2);
229 this->SetStartDirectory(path.c_str());
231 else if(arg.find("-O",0) == 0)
233 directoriesSet = true;
234 std::string path = arg.substr(2);
235 this->SetStartOutputDirectory(path.c_str());
237 else if(arg.find("-B",0) == 0)
239 directoriesSet = true;
240 std::string path = arg.substr(2);
241 this->SetHomeOutputDirectory(path.c_str());
243 else if(arg.find("-V",0) == 0)
245 m_Verbose = true;
247 else if(arg.find("-D",0) == 0)
249 // skip for now
251 else if(arg.find("-C",0) == 0)
253 // skip for now
255 else if(arg.find("-G",0) == 0)
257 std::string value = arg.substr(2);
258 cmGlobalGenerator* gen =
259 this->CreateGlobalGenerator(value.c_str());
260 if(!gen)
262 cmSystemTools::Error("Could not create named generator ",
263 value.c_str());
265 else
267 this->SetGlobalGenerator(gen);
270 // no option assume it is the path to the source
271 else
273 directoriesSet = true;
274 this->SetHomeOutputDirectory
275 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
276 this->SetStartOutputDirectory
277 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
278 this->SetHomeDirectory
279 (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
280 this->SetStartDirectory
281 (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
284 if(!directoriesSet)
286 this->SetHomeOutputDirectory
287 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
288 this->SetStartOutputDirectory
289 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
290 this->SetHomeDirectory
291 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
292 this->SetStartDirectory
293 (cmSystemTools::GetCurrentWorkingDirectory().c_str());
295 if (!m_Local)
297 this->SetStartDirectory(this->GetHomeDirectory());
298 this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
302 // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the cache
303 int cmake::AddCMakePaths(const char *arg0)
305 // Find our own executable.
306 std::vector<cmStdString> failures;
307 std::string cMakeSelf = arg0;
308 cmSystemTools::ConvertToUnixSlashes(cMakeSelf);
309 failures.push_back(cMakeSelf);
310 cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str());
311 if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
313 #ifdef CMAKE_BUILD_DIR
314 std::string intdir = ".";
315 #ifdef CMAKE_INTDIR
316 intdir = CMAKE_INTDIR;
317 #endif
318 cMakeSelf = CMAKE_BUILD_DIR;
319 cMakeSelf += "/Source/";
320 cMakeSelf += intdir;
321 cMakeSelf += "/cmake";
322 cMakeSelf += cmSystemTools::GetExecutableExtension();
323 #endif
325 #ifdef CMAKE_PREFIX
326 if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
328 failures.push_back(cMakeSelf);
329 cMakeSelf = CMAKE_PREFIX "/bin/cmake";
331 #endif
332 if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
334 failures.push_back(cMakeSelf);
335 cmOStringStream msg;
336 msg << "CMAKE can not find the command line program cmake.\n";
337 msg << " argv[0] = \"" << arg0 << "\"\n";
338 msg << " Attempted paths:\n";
339 std::vector<cmStdString>::iterator i;
340 for(i=failures.begin(); i != failures.end(); ++i)
342 msg << " \"" << i->c_str() << "\"\n";
344 cmSystemTools::Error(msg.str().c_str());
345 return 0;
347 // Save the value in the cache
348 this->m_CacheManager->AddCacheEntry
349 ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
350 cmCacheManager::INTERNAL);
352 // Find and save the command to edit the cache
353 std::string editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
354 "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
355 if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
357 editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
358 "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf);
360 if(cmSystemTools::FileExists(editCacheCommand.c_str()))
362 this->m_CacheManager->AddCacheEntry
363 ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
364 "Path to cache edit program executable.", cmCacheManager::INTERNAL);
367 // do CMAKE_ROOT, look for the environment variable first
368 std::string cMakeRoot;
369 std::string modules;
370 if (getenv("CMAKE_ROOT"))
372 cMakeRoot = getenv("CMAKE_ROOT");
373 modules = cMakeRoot + "/Modules/FindVTK.cmake";
375 if(!cmSystemTools::FileExists(modules.c_str()))
377 // next try exe/..
378 cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
379 std::string::size_type slashPos = cMakeRoot.rfind("/");
380 if(slashPos != std::string::npos)
382 cMakeRoot = cMakeRoot.substr(0, slashPos);
384 // is there no Modules direcory there?
385 modules = cMakeRoot + "/Modules/FindVTK.cmake";
388 if (!cmSystemTools::FileExists(modules.c_str()))
390 // try exe/../share/cmake
391 cMakeRoot += "/share/CMake";
392 modules = cMakeRoot + "/Modules/FindVTK.cmake";
394 #ifdef CMAKE_ROOT_DIR
395 if (!cmSystemTools::FileExists(modules.c_str()))
397 // try compiled in root directory
398 cMakeRoot = CMAKE_ROOT_DIR;
399 modules = cMakeRoot + "/Modules/FindVTK.cmake";
401 #endif
402 #ifdef CMAKE_PREFIX
403 if (!cmSystemTools::FileExists(modules.c_str()))
405 // try compiled in install prefix
406 cMakeRoot = CMAKE_PREFIX "/share/CMake";
407 modules = cMakeRoot + "/Modules/FindVTK.cmake";
409 #endif
410 if (!cmSystemTools::FileExists(modules.c_str()))
412 // try
413 cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
414 cMakeRoot += "/share/CMake";
415 modules = cMakeRoot + "/Modules/FindVTK.cmake";
417 if(!cmSystemTools::FileExists(modules.c_str()))
419 // next try exe
420 cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
421 // is there no Modules direcory there?
422 modules = cMakeRoot + "/Modules/FindVTK.cmake";
424 if (!cmSystemTools::FileExists(modules.c_str()))
426 // couldn't find modules
427 cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n",
428 "Modules directory not in directory:\n",
429 modules.c_str());
430 return 0;
432 this->m_CacheManager->AddCacheEntry
433 ("CMAKE_ROOT", cMakeRoot.c_str(),
434 "Path to CMake installation.", cmCacheManager::INTERNAL);
436 #ifdef _WIN32
437 std::string comspec = "cmw9xcom.exe";
438 cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
439 #endif
440 return 1;
445 void CMakeCommandUsage(const char* program)
447 cmOStringStream errorStream;
449 errorStream
450 << "cmake version " << cmMakefile::GetMajorVersion()
451 << "." << cmMakefile::GetMinorVersion() << "\n";
453 errorStream
454 << "Usage: " << program << " -E [command] [arguments ...]\n"
455 << "Available commands: \n"
456 << " chdir dir cmd [args]... - run command in a given directory\n"
457 << " copy file destination - copy file to destination (either file or directory)\n"
458 << " echo [string]... - displays arguments as text\n"
459 << " remove file1 file2 ... - remove the file(s)\n"
460 << " time command [args] ... - run command and return elapsed time\n";
461 #if defined(_WIN32) && !defined(__CYGWIN__)
462 errorStream
463 << " write_regv key value - write registry value\n"
464 << " delete_regv key - delete registry value\n"
465 << " comspec - on windows 9x use this for RunCommand\n";
466 #endif
468 cmSystemTools::Error(errorStream.str().c_str());
471 int cmake::CMakeCommand(std::vector<std::string>& args)
473 if (args.size() > 1)
475 // Copy file
476 if (args[1] == "copy" && args.size() == 4)
478 cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str());
479 return cmSystemTools::GetErrorOccuredFlag();
482 // Echo string
483 else if (args[1] == "echo" )
485 unsigned int cc;
486 for ( cc = 2; cc < args.size(); cc ++ )
488 std::cout << args[cc] << " ";
490 std::cout << std::endl;
491 return 0;
494 // Remove file
495 else if (args[1] == "remove" && args.size() > 2)
497 for (std::string::size_type cc = 2; cc < args.size(); cc ++)
499 if(args[cc] != "-f")
501 if(args[cc] == "\\-f")
503 args[cc] = "-f";
505 cmSystemTools::RemoveFile(args[cc].c_str());
508 return 0;
511 // Clock command
512 else if (args[1] == "time" && args.size() > 2)
514 std::string command = args[2];
515 std::string output;
516 for (std::string::size_type cc = 3; cc < args.size(); cc ++)
518 command += " ";
519 command += args[cc];
522 clock_t clock_start, clock_finish;
523 time_t time_start, time_finish;
525 time(&time_start);
526 clock_start = clock();
528 cmSystemTools::RunCommand(command.c_str(), output, 0, true);
530 clock_finish = clock();
531 time(&time_finish);
533 std::cout << output.c_str();
535 double clocks_per_sec = (double)CLOCKS_PER_SEC;
536 std::cout << "Elapsed time: "
537 << (long)(time_finish - time_start) << " s. (time)"
538 << ", "
539 << (double)(clock_finish - clock_start) / clocks_per_sec
540 << " s. (clock)"
541 << "\n";
542 return 0;
545 // Clock command
546 else if (args[1] == "chdir" && args.size() >= 4)
548 std::string directory = args[2];
549 std::string command = args[3];
550 std::string output;
551 for (std::string::size_type cc = 4; cc < args.size(); cc ++)
553 command += " ";
554 command += args[cc];
557 int retval = 0;
558 if ( cmSystemTools::RunCommand(command.c_str(), output, retval,
559 directory.c_str(), false) )
561 std::cout << output.c_str();
562 return retval;
565 return 1;
568 #if defined(_WIN32) && !defined(__CYGWIN__)
569 // Write registry value
570 else if (args[1] == "write_regv" && args.size() > 3)
572 return cmSystemTools::WriteRegistryValue(args[2].c_str(),
573 args[3].c_str()) ? 0 : 1;
576 // Delete registry value
577 else if (args[1] == "delete_regv" && args.size() > 2)
579 return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
581 // Remove file
582 else if (args[1] == "comspec" && args.size() > 2)
584 unsigned int cc;
585 std::string command = args[2];
586 for ( cc = 3; cc < args.size(); cc ++ )
588 command += " " + args[cc];
590 return cmWin32ProcessExecution::Windows9xHack(command.c_str());
592 #endif
595 ::CMakeCommandUsage(args[0].c_str());
596 return 1;
599 void cmake::GetRegisteredGenerators(std::vector<std::string>& names)
601 #if defined(_WIN32) && !defined(__CYGWIN__)
602 names.push_back(cmGlobalVisualStudio6Generator::GetActualName());
603 names.push_back(cmGlobalVisualStudio7Generator::GetActualName());
604 names.push_back(cmGlobalBorlandMakefileGenerator::GetActualName());
605 names.push_back(cmGlobalNMakeMakefileGenerator::GetActualName());
606 #else
607 names.push_back(cmGlobalCodeWarriorGenerator::GetActualName());
608 names.push_back(cmGlobalUnixMakefileGenerator::GetActualName());
609 #endif
612 cmGlobalGenerator* cmake::CreateGlobalGenerator(const char* name)
614 cmGlobalGenerator *ret = 0;
615 #if defined(_WIN32) && !defined(__CYGWIN__)
616 if (!strcmp(name,cmGlobalNMakeMakefileGenerator::GetActualName()))
618 ret = new cmGlobalNMakeMakefileGenerator;
619 ret->SetCMakeInstance(this);
621 if (!strcmp(name,cmGlobalVisualStudio6Generator::GetActualName()))
623 ret = new cmGlobalVisualStudio6Generator;
624 ret->SetCMakeInstance(this);
626 if (!strcmp(name,cmGlobalVisualStudio7Generator::GetActualName()))
628 ret = new cmGlobalVisualStudio7Generator;
629 ret->SetCMakeInstance(this);
631 if (!strcmp(name,cmGlobalBorlandMakefileGenerator::GetActualName()))
633 ret = new cmGlobalBorlandMakefileGenerator;
634 ret->SetCMakeInstance(this);
636 #else
637 if (!strcmp(name,cmGlobalCodeWarriorGenerator::GetActualName()))
639 ret = new cmGlobalCodeWarriorGenerator;
640 ret->SetCMakeInstance(this);
642 if (!strcmp(name,cmGlobalUnixMakefileGenerator::GetActualName()))
644 ret = new cmGlobalUnixMakefileGenerator;
645 ret->SetCMakeInstance(this);
647 #endif
648 return ret;
651 void cmake::SetHomeDirectory(const char* dir)
653 m_cmHomeDirectory = dir;
654 cmSystemTools::ConvertToUnixSlashes(m_cmHomeDirectory);
657 void cmake::SetHomeOutputDirectory(const char* lib)
659 m_HomeOutputDirectory = lib;
660 cmSystemTools::ConvertToUnixSlashes(m_HomeOutputDirectory);
663 void cmake::SetGlobalGenerator(cmGlobalGenerator *gg)
665 // delete the old generator
666 if (m_GlobalGenerator)
668 delete m_GlobalGenerator;
670 // set the new
671 m_GlobalGenerator = gg;
672 // set the cmake instance just to be sure
673 gg->SetCMakeInstance(this);
676 int cmake::Configure()
678 // do a sanity check on some values
679 if(m_CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY"))
681 std::string cacheStart =
682 m_CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY");
683 cacheStart += "/CMakeLists.txt";
684 std::string currentStart = this->GetHomeDirectory();
685 currentStart += "/CMakeLists.txt";
686 if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
688 std::string message = "Error: source : ";
689 message += currentStart;
690 message += "\nDoes not match source used to generate cache: ";
691 message += cacheStart;
692 message += "\nRe-run cmake with a different source directory.";
693 cmSystemTools::Error(message.c_str());
694 return -2;
697 else
699 m_CacheManager->AddCacheEntry("CMAKE_HOME_DIRECTORY",
700 this->GetHomeDirectory(),
701 "Start directory with the top level CMakeLists.txt file for this project",
702 cmCacheManager::INTERNAL);
705 // no generator specified on the command line
706 if(!m_GlobalGenerator)
708 const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR");
709 if(genName)
711 m_GlobalGenerator = this->CreateGlobalGenerator(genName);
713 else
715 #if defined(__BORLANDC__) && defined(_WIN32)
716 this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator);
717 #elif defined(_WIN32) && !defined(__CYGWIN__)
718 this->SetGlobalGenerator(new cmGlobalVisualStudio6Generator);
719 #else
720 this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator);
721 #endif
723 if(!m_GlobalGenerator)
725 cmSystemTools::Error("Could not create generator");
726 return -1;
730 const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR");
731 if(genName)
733 if(strcmp(m_GlobalGenerator->GetName(), genName) != 0)
735 std::string message = "Error: generator : ";
736 message += m_GlobalGenerator->GetName();
737 message += "\nDoes not match the generator used previously: ";
738 message += genName;
739 message +=
740 "\nEither remove the CMakeCache.txt file or choose a different"
741 " binary directory.";
742 cmSystemTools::Error(message.c_str());
743 return -2;
746 if(!m_CacheManager->GetCacheValue("CMAKE_GENERATOR"))
748 m_CacheManager->AddCacheEntry("CMAKE_GENERATOR", m_GlobalGenerator->GetName(),
749 "Name of generator.",
750 cmCacheManager::INTERNAL);
753 // reset any system configuration information, except for when we are
754 // InTryCompile. With TryCompile the system info is taken from the parent's
755 // info to save time
756 if (!m_InTryCompile)
758 m_GlobalGenerator->ClearEnabledLanguages();
761 // actually do the configure
762 m_GlobalGenerator->Configure();
764 // Before saving the cache
765 // if the project did not define one of the entries below, add them now
766 // so users can edit the values in the cache:
767 // LIBRARY_OUTPUT_PATH
768 // EXECUTABLE_OUTPUT_PATH
769 if(!m_CacheManager->GetCacheValue("LIBRARY_OUTPUT_PATH"))
771 m_CacheManager->AddCacheEntry("LIBRARY_OUTPUT_PATH", "",
772 "Single output directory for building all libraries.",
773 cmCacheManager::PATH);
775 if(!m_CacheManager->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
777 m_CacheManager->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "",
778 "Single output directory for building all executables.",
779 cmCacheManager::PATH);
782 this->m_CacheManager->SaveCache(this->GetHomeOutputDirectory());
783 if(cmSystemTools::GetErrorOccuredFlag())
785 return -1;
787 return 0;
790 // handle a command line invocation
791 int cmake::Run(const std::vector<std::string>& args)
793 // a quick check for args
794 if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
796 this->Usage(args[0].c_str());
797 return -1;
800 // look for obvious request for help
801 for(unsigned int i=1; i < args.size(); ++i)
803 std::string arg = args[i];
804 if(arg.find("-help",0) != std::string::npos ||
805 arg.find("--help",0) != std::string::npos ||
806 arg.find("/?",0) != std::string::npos ||
807 arg.find("-usage",0) != std::string::npos)
809 this->Usage(args[0].c_str());
810 return -1;
814 // Process the arguments
815 this->SetArgs(args);
817 // set the cmake command
818 m_CMakeCommand = args[0];
820 // load the cache
821 this->LoadCache();
823 // Add any cache args
824 this->SetCacheArgs(args);
826 // if we are local do the local thing, otherwise do global
827 if (m_Local)
829 return this->LocalGenerate();
832 // otherwise global
833 int ret = this->Configure();
834 if (ret)
836 return ret;
838 return this->Generate();
841 int cmake::Generate()
843 m_GlobalGenerator->Generate();
844 if(cmSystemTools::GetErrorOccuredFlag())
846 return -1;
848 return 0;
851 int cmake::LocalGenerate()
853 // Read in the cache
854 m_CacheManager->LoadCache(this->GetHomeOutputDirectory());
856 // create the generator based on the cache if it isn't already there
857 const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR");
858 if(genName)
860 m_GlobalGenerator = this->CreateGlobalGenerator(genName);
862 else
864 cmSystemTools::Error("Could local Generate called without the GENERATOR being specified in the CMakeCache");
865 return -1;
868 // do the local generate
869 m_GlobalGenerator->LocalGenerate();
870 if(cmSystemTools::GetErrorOccuredFlag())
872 return -1;
874 return 0;
877 unsigned int cmake::GetMajorVersion()
879 return cmMakefile::GetMajorVersion();
882 unsigned int cmake::GetMinorVersion()
884 return cmMakefile::GetMinorVersion();
887 const char *cmake::GetReleaseVersion()
889 return cmMakefile::GetReleaseVersion();
892 const char* cmake::GetCacheDefinition(const char* name) const
894 return m_CacheManager->GetCacheValue(name);
897 int cmake::DumpDocumentationToFile(std::ostream& f)
899 // Loop over all registered commands and print out documentation
900 const char *name;
901 const char *terse;
902 const char *full;
903 char tmp[1024];
904 sprintf(tmp,"Version %d.%d", cmake::GetMajorVersion(),
905 cmake::GetMinorVersion());
906 f << "<html>\n";
907 f << "<h1>Documentation for commands of CMake " << tmp << "</h1>\n";
908 f << "<ul>\n";
909 for(RegisteredCommandsMap::iterator j = m_Commands.begin();
910 j != m_Commands.end(); ++j)
912 name = (*j).second->GetName();
913 terse = (*j).second->GetTerseDocumentation();
914 full = (*j).second->GetFullDocumentation();
915 f << "<li><b>" << name << "</b> - " << terse << std::endl
916 << "<br><i>Usage:</i> " << full << "</li>" << std::endl << std::endl;
918 f << "</ul></html>\n";
919 return 1;
922 void cmake::AddDefaultCommands()
924 std::list<cmCommand*> commands;
925 GetPredefinedCommands(commands);
926 for(std::list<cmCommand*>::iterator i = commands.begin();
927 i != commands.end(); ++i)
929 this->AddCommand(*i);
933 int cmake::LoadCache()
935 m_CacheManager->LoadCache(this->GetHomeOutputDirectory());
937 if (m_CMakeCommand.size() < 2)
939 cmSystemTools::Error("cmake command was not specified prior to loading the cache in cmake.cxx");
940 return -1;
943 // setup CMAKE_ROOT and CMAKE_COMMAND
944 if(!this->AddCMakePaths(m_CMakeCommand.c_str()))
946 return -3;
948 return 0;
951 void cmake::SetProgressCallback(ProgressCallback f, void *cd)
953 m_ProgressCallback = f;
954 m_ProgressCallbackClientData = cd;
957 void cmake::UpdateProgress(const char *msg, float prog)
959 if(m_ProgressCallback && !m_InTryCompile)
961 (*m_ProgressCallback)(msg, prog, m_ProgressCallbackClientData);
962 return;