cmake.cxx 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  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. bool cmake::CacheVersionMatches()
  745. {
  746. const char* majv = m_CacheManager->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION");
  747. const char* minv = m_CacheManager->GetCacheValue("CMAKE_CACHE_MINOR_VERSION");
  748. const char* relv = m_CacheManager->GetCacheValue("CMAKE_CACHE_RELEASE_VERSION");
  749. bool cacheSameCMake = false;
  750. if(majv &&
  751. atoi(majv) == static_cast<int>(cmMakefile::GetMajorVersion())
  752. && minv &&
  753. atoi(minv) == static_cast<int>(cmMakefile::GetMinorVersion())
  754. && relv && (strcmp(relv, cmMakefile::GetReleaseVersion()) == 0))
  755. {
  756. cacheSameCMake = true;
  757. }
  758. return cacheSameCMake;
  759. }
  760. // handle a command line invocation
  761. int cmake::Run(const std::vector<std::string>& args)
  762. {
  763. // a quick check for args
  764. if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
  765. {
  766. this->Usage(args[0].c_str());
  767. return -1;
  768. }
  769. // look for obvious request for help
  770. for(unsigned int i=1; i < args.size(); ++i)
  771. {
  772. std::string arg = args[i];
  773. if(arg.find("-help",0) != std::string::npos ||
  774. arg.find("--help",0) != std::string::npos ||
  775. arg.find("/?",0) != std::string::npos ||
  776. arg.find("-usage",0) != std::string::npos)
  777. {
  778. this->Usage(args[0].c_str());
  779. return -1;
  780. }
  781. }
  782. // Process the arguments
  783. this->SetArgs(args);
  784. // make sure rthe Start directory contains a CMakeLists.txt file
  785. std::string srcList = this->GetHomeDirectory();
  786. srcList += "/CMakeLists.txt";
  787. if(!cmSystemTools::FileExists(srcList.c_str()))
  788. {
  789. cmSystemTools::Error("The source directory does not appear to contain CMakeLists.txt\n");
  790. this->Usage(args[0].c_str());
  791. return -1;
  792. }
  793. // set the cmake command
  794. m_CMakeCommand = args[0];
  795. // load the cache
  796. this->LoadCache();
  797. // Add any cache args
  798. this->SetCacheArgs(args);
  799. int ret = 0;
  800. // if not local or the cmake version has changed
  801. // since the last run of cmake, run a global generate
  802. if(!m_Local || !this->CacheVersionMatches())
  803. {
  804. bool saveLocalFlag = m_Local;
  805. m_Local = false;
  806. ret = this->Configure();
  807. if (ret)
  808. {
  809. return ret;
  810. }
  811. ret = this->Generate();
  812. if(ret)
  813. {
  814. return ret;
  815. }
  816. m_Local = saveLocalFlag;
  817. }
  818. // if we are local do the local thing
  819. if (m_Local)
  820. {
  821. ret = this->LocalGenerate();
  822. }
  823. return ret;
  824. }
  825. int cmake::Generate()
  826. {
  827. m_GlobalGenerator->Generate();
  828. if(cmSystemTools::GetErrorOccuredFlag())
  829. {
  830. return -1;
  831. }
  832. return 0;
  833. }
  834. int cmake::LocalGenerate()
  835. {
  836. // Read in the cache
  837. m_CacheManager->LoadCache(this->GetHomeOutputDirectory());
  838. // create the generator based on the cache if it isn't already there
  839. const char* genName = m_CacheManager->GetCacheValue("CMAKE_GENERATOR");
  840. if(genName)
  841. {
  842. m_GlobalGenerator = this->CreateGlobalGenerator(genName);
  843. }
  844. else
  845. {
  846. cmSystemTools::Error("Could local Generate called without the GENERATOR being specified in the CMakeCache");
  847. return -1;
  848. }
  849. // do the local generate
  850. m_GlobalGenerator->LocalGenerate();
  851. if(cmSystemTools::GetErrorOccuredFlag())
  852. {
  853. return -1;
  854. }
  855. return 0;
  856. }
  857. unsigned int cmake::GetMajorVersion()
  858. {
  859. return cmMakefile::GetMajorVersion();
  860. }
  861. unsigned int cmake::GetMinorVersion()
  862. {
  863. return cmMakefile::GetMinorVersion();
  864. }
  865. const char *cmake::GetReleaseVersion()
  866. {
  867. return cmMakefile::GetReleaseVersion();
  868. }
  869. const char* cmake::GetCacheDefinition(const char* name) const
  870. {
  871. return m_CacheManager->GetCacheValue(name);
  872. }
  873. int cmake::DumpDocumentationToFile(std::ostream& f)
  874. {
  875. // Loop over all registered commands and print out documentation
  876. const char *name;
  877. const char *terse;
  878. const char *full;
  879. char tmp[1024];
  880. sprintf(tmp,"Version %d.%d", cmake::GetMajorVersion(),
  881. cmake::GetMinorVersion());
  882. f << "<html>\n";
  883. f << "<h1>Documentation for commands of CMake " << tmp << "</h1>\n";
  884. f << "<ul>\n";
  885. for(RegisteredCommandsMap::iterator j = m_Commands.begin();
  886. j != m_Commands.end(); ++j)
  887. {
  888. name = (*j).second->GetName();
  889. terse = (*j).second->GetTerseDocumentation();
  890. full = (*j).second->GetFullDocumentation();
  891. f << "<li><b>" << name << "</b> - " << terse << std::endl
  892. << "<br><i>Usage:</i> " << full << "</li>" << std::endl << std::endl;
  893. }
  894. f << "</ul></html>\n";
  895. return 1;
  896. }
  897. void cmake::AddDefaultCommands()
  898. {
  899. std::list<cmCommand*> commands;
  900. GetPredefinedCommands(commands);
  901. for(std::list<cmCommand*>::iterator i = commands.begin();
  902. i != commands.end(); ++i)
  903. {
  904. this->AddCommand(*i);
  905. }
  906. }
  907. int cmake::LoadCache()
  908. {
  909. m_CacheManager->LoadCache(this->GetHomeOutputDirectory());
  910. if (m_CMakeCommand.size() < 2)
  911. {
  912. cmSystemTools::Error("cmake command was not specified prior to loading the cache in cmake.cxx");
  913. return -1;
  914. }
  915. // setup CMAKE_ROOT and CMAKE_COMMAND
  916. if(!this->AddCMakePaths(m_CMakeCommand.c_str()))
  917. {
  918. return -3;
  919. }
  920. return 0;
  921. }
  922. void cmake::SetProgressCallback(ProgressCallback f, void *cd)
  923. {
  924. m_ProgressCallback = f;
  925. m_ProgressCallbackClientData = cd;
  926. }
  927. void cmake::UpdateProgress(const char *msg, float prog)
  928. {
  929. if(m_ProgressCallback && !m_InTryCompile)
  930. {
  931. (*m_ProgressCallback)(msg, prog, m_ProgressCallbackClientData);
  932. return;
  933. }
  934. }