cmake.cxx 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmake.h"
  14. #include "time.h"
  15. #include "cmCacheManager.h"
  16. #include "cmMakefile.h"
  17. #include "cmLocalGenerator.h"
  18. #include "cmCommands.h"
  19. #include "cmCommand.h"
  20. // include the generator
  21. #if defined(_WIN32) && !defined(__CYGWIN__)
  22. #include "cmGlobalVisualStudio6Generator.h"
  23. #include "cmGlobalVisualStudio7Generator.h"
  24. #include "cmGlobalBorlandMakefileGenerator.h"
  25. #include "cmGlobalNMakeMakefileGenerator.h"
  26. #include "cmWin32ProcessExecution.h"
  27. #else
  28. #include "cmGlobalCodeWarriorGenerator.h"
  29. #include "cmGlobalUnixMakefileGenerator.h"
  30. #endif
  31. #include <stdio.h>
  32. #ifdef __APPLE__
  33. #include <sys/types.h>
  34. #include <sys/time.h>
  35. #include <sys/resource.h>
  36. #endif
  37. cmake::cmake()
  38. {
  39. #ifdef __APPLE__
  40. struct rlimit rlp;
  41. if(!getrlimit(RLIMIT_STACK, &rlp))
  42. {
  43. if(rlp.rlim_cur != rlp.rlim_max)
  44. {
  45. rlp.rlim_cur = rlp.rlim_max;
  46. setrlimit(RLIMIT_STACK, &rlp);
  47. }
  48. }
  49. #endif
  50. m_Local = false;
  51. m_Verbose = false;
  52. m_InTryCompile = false;
  53. m_CacheManager = new cmCacheManager;
  54. m_GlobalGenerator = 0;
  55. m_ProgressCallback = 0;
  56. m_ProgressCallbackClientData = 0;
  57. this->AddDefaultCommands();
  58. }
  59. cmake::~cmake()
  60. {
  61. delete m_CacheManager;
  62. if (m_GlobalGenerator)
  63. {
  64. delete m_GlobalGenerator;
  65. m_GlobalGenerator = 0;
  66. }
  67. for(RegisteredCommandsMap::iterator j = m_Commands.begin();
  68. j != m_Commands.end(); ++j)
  69. {
  70. delete (*j).second;
  71. }
  72. }
  73. bool cmake::CommandExists(const char* name) const
  74. {
  75. return (m_Commands.find(name) != m_Commands.end());
  76. }
  77. cmCommand *cmake::GetCommand(const char *name)
  78. {
  79. cmCommand* rm = 0;
  80. RegisteredCommandsMap::iterator pos = m_Commands.find(name);
  81. if (pos != m_Commands.end())
  82. {
  83. rm = (*pos).second;
  84. }
  85. return rm;
  86. }
  87. void cmake::AddCommand(cmCommand* wg)
  88. {
  89. std::string name = wg->GetName();
  90. // if the command already exists, free the old one
  91. RegisteredCommandsMap::iterator pos = m_Commands.find(name);
  92. if (pos != m_Commands.end())
  93. {
  94. delete pos->second;
  95. m_Commands.erase(pos);
  96. }
  97. m_Commands.insert( RegisteredCommandsMap::value_type(name, wg));
  98. }
  99. void cmake::Usage(const char* program)
  100. {
  101. cmOStringStream errorStream;
  102. errorStream << "cmake version " << cmMakefile::GetMajorVersion()
  103. << "." << cmMakefile::GetMinorVersion() << "\n";
  104. errorStream << "Usage: " << program << " [srcdir] [options]\n"
  105. << "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";
  106. errorStream << "Options are:\n";
  107. errorStream << "\n-i (puts cmake in wizard mode, not available for ccmake)\n";
  108. errorStream << "\n-DVAR:TYPE=VALUE (create a cache file entry)\n";
  109. errorStream << "\n-Cpath_to_initial_cache (a cmake list file that is used to pre-load the cache with values.)\n";
  110. errorStream << "\n[-GgeneratorName] (where generator name can be one of these: ";
  111. std::vector<std::string> names;
  112. this->GetRegisteredGenerators(names);
  113. for(std::vector<std::string>::iterator i =names.begin();
  114. i != names.end(); ++i)
  115. {
  116. errorStream << "\"" << i->c_str() << "\" ";
  117. }
  118. errorStream << ")\n";
  119. cmSystemTools::Error(errorStream.str().c_str());
  120. }
  121. // Parse the args
  122. void cmake::SetCacheArgs(const std::vector<std::string>& args)
  123. {
  124. for(unsigned int i=1; i < args.size(); ++i)
  125. {
  126. std::string arg = args[i];
  127. if(arg.find("-D",0) == 0)
  128. {
  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))
  133. {
  134. this->m_CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
  135. "No help, variable specified on the command line.",
  136. type);
  137. }
  138. else
  139. {
  140. std::cerr << "Parse error in command line argument: " << arg << "\n"
  141. << "Should be: VAR:type=value\n";
  142. }
  143. }
  144. else if(arg.find("-C",0) == 0)
  145. {
  146. std::string path = arg.substr(2);
  147. std::cerr << "loading initial cache file " << path.c_str() << "\n";
  148. this->ReadListFile(path.c_str());
  149. }
  150. }
  151. }
  152. void cmake::ReadListFile(const char *path)
  153. {
  154. // if a generator was not yet created, temporarily create one
  155. cmGlobalGenerator *gg = this->GetGlobalGenerator();
  156. bool created = false;
  157. // if a generator was not specified use a generic one
  158. if (!gg)
  159. {
  160. gg = new cmGlobalGenerator;
  161. gg->SetCMakeInstance(this);
  162. created = true;
  163. }
  164. // read in the list file to fill the cache
  165. if(path)
  166. {
  167. cmLocalGenerator *lg = gg->CreateLocalGenerator();
  168. lg->SetGlobalGenerator(gg);
  169. if (!lg->GetMakefile()->ReadListFile(path))
  170. {
  171. std::cerr << "Error in reading cmake initial cache file:"
  172. << path << "\n";
  173. }
  174. }
  175. // free generic one if generated
  176. if (created)
  177. {
  178. delete gg;
  179. }
  180. }
  181. // Parse the args
  182. void cmake::SetArgs(const std::vector<std::string>& args)
  183. {
  184. m_Local = false;
  185. bool directoriesSet = false;
  186. // watch for cmake and cmake srcdir invocations
  187. if (args.size() <= 2)
  188. {
  189. directoriesSet = true;
  190. this->SetHomeOutputDirectory
  191. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  192. this->SetStartOutputDirectory
  193. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  194. if (args.size() == 2)
  195. {
  196. this->SetHomeDirectory
  197. (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
  198. this->SetStartDirectory
  199. (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
  200. }
  201. else
  202. {
  203. this->SetHomeDirectory
  204. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  205. this->SetStartDirectory
  206. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  207. }
  208. }
  209. for(unsigned int i=1; i < args.size(); ++i)
  210. {
  211. std::string arg = args[i];
  212. if(arg.find("-H",0) == 0)
  213. {
  214. directoriesSet = true;
  215. std::string path = arg.substr(2);
  216. this->SetHomeDirectory(path.c_str());
  217. }
  218. else if(arg.find("-S",0) == 0)
  219. {
  220. directoriesSet = true;
  221. m_Local = true;
  222. std::string path = arg.substr(2);
  223. this->SetStartDirectory(path.c_str());
  224. }
  225. else if(arg.find("-O",0) == 0)
  226. {
  227. directoriesSet = true;
  228. std::string path = arg.substr(2);
  229. this->SetStartOutputDirectory(path.c_str());
  230. }
  231. else if(arg.find("-B",0) == 0)
  232. {
  233. directoriesSet = true;
  234. std::string path = arg.substr(2);
  235. this->SetHomeOutputDirectory(path.c_str());
  236. }
  237. else if(arg.find("-V",0) == 0)
  238. {
  239. m_Verbose = true;
  240. }
  241. else if(arg.find("-D",0) == 0)
  242. {
  243. // skip for now
  244. }
  245. else if(arg.find("-C",0) == 0)
  246. {
  247. // skip for now
  248. }
  249. else if(arg.find("-G",0) == 0)
  250. {
  251. std::string value = arg.substr(2);
  252. cmGlobalGenerator* gen =
  253. this->CreateGlobalGenerator(value.c_str());
  254. if(!gen)
  255. {
  256. cmSystemTools::Error("Could not create named generator ",
  257. value.c_str());
  258. }
  259. else
  260. {
  261. this->SetGlobalGenerator(gen);
  262. }
  263. }
  264. // no option assume it is the path to the source
  265. else
  266. {
  267. directoriesSet = true;
  268. this->SetHomeOutputDirectory
  269. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  270. this->SetStartOutputDirectory
  271. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  272. this->SetHomeDirectory
  273. (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
  274. this->SetStartDirectory
  275. (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
  276. }
  277. }
  278. if(!directoriesSet)
  279. {
  280. this->SetHomeOutputDirectory
  281. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  282. this->SetStartOutputDirectory
  283. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  284. this->SetHomeDirectory
  285. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  286. this->SetStartDirectory
  287. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  288. }
  289. if (!m_Local)
  290. {
  291. this->SetStartDirectory(this->GetHomeDirectory());
  292. this->SetStartOutputDirectory(this->GetHomeOutputDirectory());
  293. }
  294. }
  295. // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the cache
  296. int cmake::AddCMakePaths(const char *arg0)
  297. {
  298. // Find our own executable.
  299. std::vector<cmStdString> failures;
  300. std::string cMakeSelf = arg0;
  301. cmSystemTools::ConvertToUnixSlashes(cMakeSelf);
  302. failures.push_back(cMakeSelf);
  303. cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str());
  304. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  305. {
  306. #ifdef CMAKE_BUILD_DIR
  307. std::string intdir = ".";
  308. #ifdef CMAKE_INTDIR
  309. intdir = CMAKE_INTDIR;
  310. #endif
  311. cMakeSelf = CMAKE_BUILD_DIR;
  312. cMakeSelf += "/Source/";
  313. cMakeSelf += intdir;
  314. cMakeSelf += "/cmake";
  315. cMakeSelf += cmSystemTools::GetExecutableExtension();
  316. #endif
  317. }
  318. #ifdef CMAKE_PREFIX
  319. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  320. {
  321. failures.push_back(cMakeSelf);
  322. cMakeSelf = CMAKE_PREFIX "/bin/cmake";
  323. }
  324. #endif
  325. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  326. {
  327. failures.push_back(cMakeSelf);
  328. cmOStringStream msg;
  329. msg << "CMAKE can not find the command line program cmake.\n";
  330. msg << " argv[0] = \"" << arg0 << "\"\n";
  331. msg << " Attempted paths:\n";
  332. std::vector<cmStdString>::iterator i;
  333. for(i=failures.begin(); i != failures.end(); ++i)
  334. {
  335. msg << " \"" << i->c_str() << "\"\n";
  336. }
  337. cmSystemTools::Error(msg.str().c_str());
  338. return 0;
  339. }
  340. // Save the value in the cache
  341. this->m_CacheManager->AddCacheEntry
  342. ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
  343. cmCacheManager::INTERNAL);
  344. // Find and save the command to edit the cache
  345. std::string editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
  346. "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  347. if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
  348. {
  349. editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
  350. "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  351. }
  352. if(cmSystemTools::FileExists(editCacheCommand.c_str()))
  353. {
  354. this->m_CacheManager->AddCacheEntry
  355. ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
  356. "Path to cache edit program executable.", cmCacheManager::INTERNAL);
  357. }
  358. // do CMAKE_ROOT, look for the environment variable first
  359. std::string cMakeRoot;
  360. std::string modules;
  361. if (getenv("CMAKE_ROOT"))
  362. {
  363. cMakeRoot = getenv("CMAKE_ROOT");
  364. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  365. }
  366. if(!cmSystemTools::FileExists(modules.c_str()))
  367. {
  368. // next try exe/..
  369. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  370. std::string::size_type slashPos = cMakeRoot.rfind("/");
  371. if(slashPos != std::string::npos)
  372. {
  373. cMakeRoot = cMakeRoot.substr(0, slashPos);
  374. }
  375. // is there no Modules direcory there?
  376. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  377. }
  378. if (!cmSystemTools::FileExists(modules.c_str()))
  379. {
  380. // try exe/../share/cmake
  381. cMakeRoot += "/share/CMake";
  382. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  383. }
  384. #ifdef CMAKE_ROOT_DIR
  385. if (!cmSystemTools::FileExists(modules.c_str()))
  386. {
  387. // try compiled in root directory
  388. cMakeRoot = CMAKE_ROOT_DIR;
  389. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  390. }
  391. #endif
  392. #ifdef CMAKE_PREFIX
  393. if (!cmSystemTools::FileExists(modules.c_str()))
  394. {
  395. // try compiled in install prefix
  396. cMakeRoot = CMAKE_PREFIX "/share/CMake";
  397. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  398. }
  399. #endif
  400. if (!cmSystemTools::FileExists(modules.c_str()))
  401. {
  402. // try
  403. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  404. cMakeRoot += "/share/CMake";
  405. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  406. }
  407. if(!cmSystemTools::FileExists(modules.c_str()))
  408. {
  409. // next try exe
  410. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  411. // is there no Modules direcory there?
  412. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  413. }
  414. if (!cmSystemTools::FileExists(modules.c_str()))
  415. {
  416. // couldn't find modules
  417. cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n",
  418. "Modules directory not in directory:\n",
  419. modules.c_str());
  420. return 0;
  421. }
  422. this->m_CacheManager->AddCacheEntry
  423. ("CMAKE_ROOT", cMakeRoot.c_str(),
  424. "Path to CMake installation.", cmCacheManager::INTERNAL);
  425. #ifdef _WIN32
  426. std::string comspec = "cmw9xcom.exe";
  427. cmSystemTools::SetWindows9xComspecSubstitute(comspec.c_str());
  428. #endif
  429. return 1;
  430. }
  431. void CMakeCommandUsage(const char* program)
  432. {
  433. cmOStringStream errorStream;
  434. errorStream
  435. << "cmake version " << cmMakefile::GetMajorVersion()
  436. << "." << cmMakefile::GetMinorVersion() << "\n";
  437. errorStream
  438. << "Usage: " << program << " -E [command] [arguments ...]\n"
  439. << "Available commands: \n"
  440. << " chdir dir cmd [args]... - run command in a given directory\n"
  441. << " copy file destination - copy file to destination (either file or directory)\n"
  442. << " echo [string]... - displays arguments as text\n"
  443. << " remove file1 file2 ... - remove the file(s)\n"
  444. << " time command [args] ... - run command and return elapsed time\n";
  445. #if defined(_WIN32) && !defined(__CYGWIN__)
  446. errorStream
  447. << " write_regv key value - write registry value\n"
  448. << " delete_regv key - delete registry value\n"
  449. << " comspec - on windows 9x use this for RunCommand\n";
  450. #endif
  451. cmSystemTools::Error(errorStream.str().c_str());
  452. }
  453. int cmake::CMakeCommand(std::vector<std::string>& args)
  454. {
  455. if (args.size() > 1)
  456. {
  457. // Copy file
  458. if (args[1] == "copy" && args.size() == 4)
  459. {
  460. cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str());
  461. return cmSystemTools::GetErrorOccuredFlag();
  462. }
  463. // Echo string
  464. else if (args[1] == "echo" )
  465. {
  466. unsigned int cc;
  467. for ( cc = 2; cc < args.size(); cc ++ )
  468. {
  469. std::cout << args[cc] << " ";
  470. }
  471. std::cout << std::endl;
  472. return 0;
  473. }
  474. // Remove file
  475. else if (args[1] == "remove" && args.size() > 2)
  476. {
  477. for (std::string::size_type cc = 2; cc < args.size(); cc ++)
  478. {
  479. if(args[cc] != "-f")
  480. {
  481. if(args[cc] == "\\-f")
  482. {
  483. args[cc] = "-f";
  484. }
  485. cmSystemTools::RemoveFile(args[cc].c_str());
  486. }
  487. }
  488. return 0;
  489. }
  490. // Clock command
  491. else if (args[1] == "time" && args.size() > 2)
  492. {
  493. std::string command = args[2];
  494. std::string output;
  495. for (std::string::size_type cc = 3; cc < args.size(); cc ++)
  496. {
  497. command += " ";
  498. command += args[cc];
  499. }
  500. clock_t clock_start, clock_finish;
  501. time_t time_start, time_finish;
  502. time(&time_start);
  503. clock_start = clock();
  504. cmSystemTools::RunCommand(command.c_str(), output, 0, true);
  505. clock_finish = clock();
  506. time(&time_finish);
  507. std::cout << output.c_str();
  508. double clocks_per_sec = (double)CLOCKS_PER_SEC;
  509. std::cout << "Elapsed time: "
  510. << (long)(time_finish - time_start) << " s. (time)"
  511. << ", "
  512. << (double)(clock_finish - clock_start) / clocks_per_sec
  513. << " s. (clock)"
  514. << "\n";
  515. return 0;
  516. }
  517. // Clock command
  518. else if (args[1] == "chdir" && args.size() >= 4)
  519. {
  520. std::string directory = args[2];
  521. std::string command = args[3];
  522. std::string output;
  523. for (std::string::size_type cc = 4; cc < args.size(); cc ++)
  524. {
  525. command += " ";
  526. command += args[cc];
  527. }
  528. int retval = 0;
  529. if ( cmSystemTools::RunCommand(command.c_str(), output, retval,
  530. directory.c_str(), false) )
  531. {
  532. std::cout << output.c_str();
  533. return retval;
  534. }
  535. return 1;
  536. }
  537. #if defined(_WIN32) && !defined(__CYGWIN__)
  538. // Write registry value
  539. else if (args[1] == "write_regv" && args.size() > 3)
  540. {
  541. return cmSystemTools::WriteRegistryValue(args[2].c_str(),
  542. args[3].c_str()) ? 0 : 1;
  543. }
  544. // Delete registry value
  545. else if (args[1] == "delete_regv" && args.size() > 2)
  546. {
  547. return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
  548. }
  549. // Remove file
  550. else if (args[1] == "comspec" && args.size() > 2)
  551. {
  552. unsigned int cc;
  553. std::string command = args[2];
  554. for ( cc = 3; cc < args.size(); cc ++ )
  555. {
  556. command += " " + args[cc];
  557. }
  558. return cmWin32ProcessExecution::Windows9xHack(command.c_str());
  559. }
  560. #endif
  561. }
  562. ::CMakeCommandUsage(args[0].c_str());
  563. return 1;
  564. }
  565. void cmake::GetRegisteredGenerators(std::vector<std::string>& names)
  566. {
  567. #if defined(_WIN32) && !defined(__CYGWIN__)
  568. names.push_back(cmGlobalVisualStudio6Generator::GetActualName());
  569. names.push_back(cmGlobalVisualStudio7Generator::GetActualName());
  570. names.push_back(cmGlobalBorlandMakefileGenerator::GetActualName());
  571. names.push_back(cmGlobalNMakeMakefileGenerator::GetActualName());
  572. #else
  573. names.push_back(cmGlobalCodeWarriorGenerator::GetActualName());
  574. names.push_back(cmGlobalUnixMakefileGenerator::GetActualName());
  575. #endif
  576. }
  577. cmGlobalGenerator* cmake::CreateGlobalGenerator(const char* name)
  578. {
  579. cmGlobalGenerator *ret = 0;
  580. #if defined(_WIN32) && !defined(__CYGWIN__)
  581. if (!strcmp(name,cmGlobalNMakeMakefileGenerator::GetActualName()))
  582. {
  583. ret = new cmGlobalNMakeMakefileGenerator;
  584. ret->SetCMakeInstance(this);
  585. }
  586. if (!strcmp(name,cmGlobalVisualStudio6Generator::GetActualName()))
  587. {
  588. ret = new cmGlobalVisualStudio6Generator;
  589. ret->SetCMakeInstance(this);
  590. }
  591. if (!strcmp(name,cmGlobalVisualStudio7Generator::GetActualName()))
  592. {
  593. ret = new cmGlobalVisualStudio7Generator;
  594. ret->SetCMakeInstance(this);
  595. }
  596. if (!strcmp(name,cmGlobalBorlandMakefileGenerator::GetActualName()))
  597. {
  598. ret = new cmGlobalBorlandMakefileGenerator;
  599. ret->SetCMakeInstance(this);
  600. }
  601. #else
  602. if (!strcmp(name,cmGlobalCodeWarriorGenerator::GetActualName()))
  603. {
  604. ret = new cmGlobalCodeWarriorGenerator;
  605. ret->SetCMakeInstance(this);
  606. }
  607. if (!strcmp(name,cmGlobalUnixMakefileGenerator::GetActualName()))
  608. {
  609. ret = new cmGlobalUnixMakefileGenerator;
  610. ret->SetCMakeInstance(this);
  611. }
  612. #endif
  613. return ret;
  614. }
  615. void cmake::SetHomeDirectory(const char* dir)
  616. {
  617. m_cmHomeDirectory = dir;
  618. cmSystemTools::ConvertToUnixSlashes(m_cmHomeDirectory);
  619. }
  620. void cmake::SetHomeOutputDirectory(const char* lib)
  621. {
  622. m_HomeOutputDirectory = lib;
  623. cmSystemTools::ConvertToUnixSlashes(m_HomeOutputDirectory);
  624. }
  625. void cmake::SetGlobalGenerator(cmGlobalGenerator *gg)
  626. {
  627. // delete the old generator
  628. if (m_GlobalGenerator)
  629. {
  630. delete m_GlobalGenerator;
  631. }
  632. // set the new
  633. m_GlobalGenerator = gg;
  634. // set the cmake instance just to be sure
  635. gg->SetCMakeInstance(this);
  636. }
  637. int cmake::Configure()
  638. {
  639. // do a sanity check on some values
  640. if(m_CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY"))
  641. {
  642. std::string cacheStart =
  643. m_CacheManager->GetCacheValue("CMAKE_HOME_DIRECTORY");
  644. cacheStart += "/CMakeLists.txt";
  645. std::string currentStart = this->GetHomeDirectory();
  646. currentStart += "/CMakeLists.txt";
  647. if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
  648. {
  649. std::string message = "Error: source : ";
  650. message += currentStart;
  651. message += "\nDoes not match source used to generate cache: ";
  652. message += cacheStart;
  653. message += "\nRe-run cmake with a different source directory.";
  654. cmSystemTools::Error(message.c_str());
  655. return -2;
  656. }
  657. }
  658. else
  659. {
  660. m_CacheManager->AddCacheEntry("CMAKE_HOME_DIRECTORY",
  661. this->GetHomeDirectory(),
  662. "Start directory with the top level CMakeLists.txt file for this project",
  663. cmCacheManager::INTERNAL);
  664. }
  665. // no generator specified on the command line
  666. if(!m_GlobalGenerator)
  667. {
  668. const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR");
  669. if(genName)
  670. {
  671. m_GlobalGenerator = this->CreateGlobalGenerator(genName);
  672. }
  673. else
  674. {
  675. #if defined(__BORLANDC__) && defined(_WIN32)
  676. this->SetGlobalGenerator(new cmGlobalBorlandMakefileGenerator);
  677. #elif defined(_WIN32) && !defined(__CYGWIN__)
  678. this->SetGlobalGenerator(new cmGlobalVisualStudio6Generator);
  679. #else
  680. this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator);
  681. #endif
  682. }
  683. if(!m_GlobalGenerator)
  684. {
  685. cmSystemTools::Error("Could not create generator");
  686. return -1;
  687. }
  688. }
  689. const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR");
  690. if(genName)
  691. {
  692. if(strcmp(m_GlobalGenerator->GetName(), genName) != 0)
  693. {
  694. std::string message = "Error: generator : ";
  695. message += m_GlobalGenerator->GetName();
  696. message += "\nDoes not match the generator used previously: ";
  697. message += genName;
  698. message +=
  699. "\nEither remove the CMakeCache.txt file or choose a different"
  700. " binary directory.";
  701. cmSystemTools::Error(message.c_str());
  702. return -2;
  703. }
  704. }
  705. if(!m_CacheManager->GetCacheValue("CMAKE_GENERATOR"))
  706. {
  707. m_CacheManager->AddCacheEntry("CMAKE_GENERATOR", m_GlobalGenerator->GetName(),
  708. "Name of generator.",
  709. cmCacheManager::INTERNAL);
  710. }
  711. // reset any system configuration information, except for when we are
  712. // InTryCompile. With TryCompile the system info is taken from the parent's
  713. // info to save time
  714. if (!m_InTryCompile)
  715. {
  716. m_GlobalGenerator->ClearEnabledLanguages();
  717. }
  718. // actually do the configure
  719. m_GlobalGenerator->Configure();
  720. // Before saving the cache
  721. // if the project did not define one of the entries below, add them now
  722. // so users can edit the values in the cache:
  723. // LIBRARY_OUTPUT_PATH
  724. // EXECUTABLE_OUTPUT_PATH
  725. if(!m_CacheManager->GetCacheValue("LIBRARY_OUTPUT_PATH"))
  726. {
  727. m_CacheManager->AddCacheEntry("LIBRARY_OUTPUT_PATH", "",
  728. "Single output directory for building all libraries.",
  729. cmCacheManager::PATH);
  730. }
  731. if(!m_CacheManager->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
  732. {
  733. m_CacheManager->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "",
  734. "Single output directory for building all executables.",
  735. cmCacheManager::PATH);
  736. }
  737. this->m_CacheManager->SaveCache(this->GetHomeOutputDirectory());
  738. if(cmSystemTools::GetErrorOccuredFlag())
  739. {
  740. return -1;
  741. }
  742. return 0;
  743. }
  744. // handle a command line invocation
  745. int cmake::Run(const std::vector<std::string>& args)
  746. {
  747. // a quick check for args
  748. if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
  749. {
  750. this->Usage(args[0].c_str());
  751. return -1;
  752. }
  753. // look for obvious request for help
  754. for(unsigned int i=1; i < args.size(); ++i)
  755. {
  756. std::string arg = args[i];
  757. if(arg.find("-help",0) != std::string::npos ||
  758. arg.find("--help",0) != std::string::npos ||
  759. arg.find("/?",0) != std::string::npos ||
  760. arg.find("-usage",0) != std::string::npos)
  761. {
  762. this->Usage(args[0].c_str());
  763. return -1;
  764. }
  765. }
  766. // Process the arguments
  767. this->SetArgs(args);
  768. // set the cmake command
  769. m_CMakeCommand = args[0];
  770. // load the cache
  771. this->LoadCache();
  772. // Add any cache args
  773. this->SetCacheArgs(args);
  774. // if we are local do the local thing, otherwise do global
  775. if (m_Local)
  776. {
  777. return this->LocalGenerate();
  778. }
  779. // otherwise global
  780. int ret = this->Configure();
  781. if (ret)
  782. {
  783. return ret;
  784. }
  785. return this->Generate();
  786. }
  787. int cmake::Generate()
  788. {
  789. m_GlobalGenerator->Generate();
  790. if(cmSystemTools::GetErrorOccuredFlag())
  791. {
  792. return -1;
  793. }
  794. return 0;
  795. }
  796. int cmake::LocalGenerate()
  797. {
  798. // Read in the cache
  799. m_CacheManager->LoadCache(this->GetHomeOutputDirectory());
  800. // create the generator based on the cache if it isn't already there
  801. const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR");
  802. if(genName)
  803. {
  804. m_GlobalGenerator = this->CreateGlobalGenerator(genName);
  805. }
  806. else
  807. {
  808. cmSystemTools::Error("Could local Generate called without the GENERATOR being specified in the CMakeCache");
  809. return -1;
  810. }
  811. // do the local generate
  812. m_GlobalGenerator->LocalGenerate();
  813. if(cmSystemTools::GetErrorOccuredFlag())
  814. {
  815. return -1;
  816. }
  817. return 0;
  818. }
  819. unsigned int cmake::GetMajorVersion()
  820. {
  821. return cmMakefile::GetMajorVersion();
  822. }
  823. unsigned int cmake::GetMinorVersion()
  824. {
  825. return cmMakefile::GetMinorVersion();
  826. }
  827. const char *cmake::GetReleaseVersion()
  828. {
  829. return cmMakefile::GetReleaseVersion();
  830. }
  831. const char* cmake::GetCacheDefinition(const char* name) const
  832. {
  833. return m_CacheManager->GetCacheValue(name);
  834. }
  835. int cmake::DumpDocumentationToFile(std::ostream& f)
  836. {
  837. // Loop over all registered commands and print out documentation
  838. const char *name;
  839. const char *terse;
  840. const char *full;
  841. char tmp[1024];
  842. sprintf(tmp,"Version %d.%d", cmake::GetMajorVersion(),
  843. cmake::GetMinorVersion());
  844. f << "<html>\n";
  845. f << "<h1>Documentation for commands of CMake " << tmp << "</h1>\n";
  846. f << "<ul>\n";
  847. for(RegisteredCommandsMap::iterator j = m_Commands.begin();
  848. j != m_Commands.end(); ++j)
  849. {
  850. name = (*j).second->GetName();
  851. terse = (*j).second->GetTerseDocumentation();
  852. full = (*j).second->GetFullDocumentation();
  853. f << "<li><b>" << name << "</b> - " << terse << std::endl
  854. << "<br><i>Usage:</i> " << full << "</li>" << std::endl << std::endl;
  855. }
  856. f << "</ul></html>\n";
  857. return 1;
  858. }
  859. void cmake::AddDefaultCommands()
  860. {
  861. std::list<cmCommand*> commands;
  862. GetPredefinedCommands(commands);
  863. for(std::list<cmCommand*>::iterator i = commands.begin();
  864. i != commands.end(); ++i)
  865. {
  866. this->AddCommand(*i);
  867. }
  868. }
  869. int cmake::LoadCache()
  870. {
  871. m_CacheManager->LoadCache(this->GetHomeOutputDirectory());
  872. if (m_CMakeCommand.size() < 2)
  873. {
  874. cmSystemTools::Error("cmake command was not specified prior to loading the cache in cmake.cxx");
  875. return -1;
  876. }
  877. // setup CMAKE_ROOT and CMAKE_COMMAND
  878. if(!this->AddCMakePaths(m_CMakeCommand.c_str()))
  879. {
  880. return -3;
  881. }
  882. return 0;
  883. }
  884. void cmake::SetProgressCallback(ProgressCallback f, void *cd)
  885. {
  886. m_ProgressCallback = f;
  887. m_ProgressCallbackClientData = cd;
  888. }
  889. void cmake::UpdateProgress(const char *msg, float prog)
  890. {
  891. if(m_ProgressCallback && !m_InTryCompile)
  892. {
  893. (*m_ProgressCallback)(msg, prog, m_ProgressCallbackClientData);
  894. return;
  895. }
  896. }