cmake.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Insight Consortium. All rights reserved.
  8. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 the generator
  17. #if defined(_WIN32) && !defined(__CYGWIN__)
  18. #include "cmMSProjectGenerator.h"
  19. #include "cmMSDotNETGenerator.h"
  20. #include "cmBorlandMakefileGenerator.h"
  21. #include "cmNMakeMakefileGenerator.h"
  22. #else
  23. #include "cmUnixMakefileGenerator.h"
  24. #endif
  25. cmake::cmake()
  26. {
  27. m_Verbose = false;
  28. #if defined(_WIN32) && !defined(__CYGWIN__)
  29. cmMakefileGenerator::RegisterGenerator(new cmMSProjectGenerator);
  30. cmMakefileGenerator::RegisterGenerator(new cmMSDotNETGenerator);
  31. cmMakefileGenerator::RegisterGenerator(new cmNMakeMakefileGenerator);
  32. cmMakefileGenerator::RegisterGenerator(new cmBorlandMakefileGenerator);
  33. #else
  34. cmMakefileGenerator::RegisterGenerator(new cmUnixMakefileGenerator);
  35. #endif
  36. }
  37. cmake::~cmake()
  38. {
  39. }
  40. void cmake::Usage(const char* program)
  41. {
  42. cmStringStream errorStream;
  43. errorStream << "cmake version " << cmMakefile::GetMajorVersion()
  44. << "." << cmMakefile::GetMinorVersion() << "\n";
  45. errorStream << "Usage: " << program << " [srcdir] [options]\n"
  46. << "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";
  47. errorStream << "Options are:\n";
  48. errorStream << "\n-i (puts cmake in wizard mode, not available for ccmake)\n";
  49. errorStream << "\n-DVAR:TYPE=VALUE (create a cache file entry)\n";
  50. errorStream << "\n-Cpath_to_initial_cache (a cmake list file that is used to pre-load the cache with values.)\n";
  51. errorStream << "\n[-GgeneratorName] (where generator name can be one of these: ";
  52. std::vector<std::string> names;
  53. cmMakefileGenerator::GetRegisteredGenerators(names);
  54. for(std::vector<std::string>::iterator i =names.begin();
  55. i != names.end(); ++i)
  56. {
  57. errorStream << "\"" << i->c_str() << "\" ";
  58. }
  59. errorStream << ")\n";
  60. cmSystemTools::Error(errorStream.str().c_str());
  61. }
  62. // Parse the args
  63. void cmake::SetCacheArgs(cmMakefile& builder,
  64. const std::vector<std::string>& args)
  65. {
  66. for(unsigned int i=1; i < args.size(); ++i)
  67. {
  68. std::string arg = args[i];
  69. if(arg.find("-D",0) == 0)
  70. {
  71. std::string entry = arg.substr(2);
  72. std::string var, value;
  73. cmCacheManager::CacheEntryType type;
  74. if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
  75. {
  76. cmCacheManager::GetInstance()->AddCacheEntry(
  77. var.c_str(),
  78. value.c_str(),
  79. "No help, variable specified on the command line.",
  80. type);
  81. }
  82. else
  83. {
  84. std::cerr << "Parse error in command line argument: " << arg << "\n"
  85. << "Should be: VAR:type=value\n";
  86. }
  87. }
  88. else if(arg.find("-C",0) == 0)
  89. {
  90. std::string path = arg.substr(2);
  91. std::cerr << "loading initial cache file " << path.c_str() << "\n";
  92. if(!builder.ReadListFile(path.c_str()))
  93. {
  94. std::cerr << "Error in reading cmake initial cache file:"
  95. << path.c_str() << "\n";
  96. }
  97. }
  98. }
  99. }
  100. // Parse the args
  101. void cmake::SetArgs(cmMakefile& builder, const std::vector<std::string>& args)
  102. {
  103. m_Local = false;
  104. bool directoriesSet = false;
  105. // watch for cmake and cmake srcdir invocations
  106. if (args.size() <= 2)
  107. {
  108. directoriesSet = true;
  109. builder.SetHomeOutputDirectory
  110. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  111. builder.SetStartOutputDirectory
  112. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  113. if (args.size() == 2)
  114. {
  115. builder.SetHomeDirectory
  116. (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
  117. builder.SetStartDirectory
  118. (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
  119. }
  120. else
  121. {
  122. builder.SetHomeDirectory
  123. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  124. builder.SetStartDirectory
  125. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  126. }
  127. }
  128. for(unsigned int i=1; i < args.size(); ++i)
  129. {
  130. std::string arg = args[i];
  131. if(arg.find("-H",0) == 0)
  132. {
  133. directoriesSet = true;
  134. std::string path = arg.substr(2);
  135. builder.SetHomeDirectory(path.c_str());
  136. }
  137. else if(arg.find("-S",0) == 0)
  138. {
  139. directoriesSet = true;
  140. m_Local = true;
  141. std::string path = arg.substr(2);
  142. builder.SetStartDirectory(path.c_str());
  143. }
  144. else if(arg.find("-O",0) == 0)
  145. {
  146. directoriesSet = true;
  147. std::string path = arg.substr(2);
  148. builder.SetStartOutputDirectory(path.c_str());
  149. }
  150. else if(arg.find("-B",0) == 0)
  151. {
  152. directoriesSet = true;
  153. std::string path = arg.substr(2);
  154. builder.SetHomeOutputDirectory(path.c_str());
  155. }
  156. else if(arg.find("-V",0) == 0)
  157. {
  158. m_Verbose = true;
  159. }
  160. else if(arg.find("-D",0) == 0)
  161. {
  162. // skip for now
  163. }
  164. else if(arg.find("-C",0) == 0)
  165. {
  166. // skip for now
  167. }
  168. else if(arg.find("-G",0) == 0)
  169. {
  170. std::string value = arg.substr(2);
  171. cmMakefileGenerator* gen =
  172. cmMakefileGenerator::CreateGenerator(value.c_str());
  173. if(!gen)
  174. {
  175. cmSystemTools::Error("Could not create named generator ",
  176. value.c_str());
  177. }
  178. else
  179. {
  180. builder.SetMakefileGenerator(gen);
  181. }
  182. }
  183. // no option assume it is the path to the source
  184. else
  185. {
  186. directoriesSet = true;
  187. builder.SetHomeOutputDirectory
  188. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  189. builder.SetStartOutputDirectory
  190. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  191. builder.SetHomeDirectory
  192. (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
  193. builder.SetStartDirectory
  194. (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
  195. }
  196. }
  197. if(!directoriesSet)
  198. {
  199. builder.SetHomeOutputDirectory
  200. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  201. builder.SetStartOutputDirectory
  202. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  203. builder.SetHomeDirectory
  204. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  205. builder.SetStartDirectory
  206. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  207. }
  208. if (!m_Local)
  209. {
  210. builder.SetStartDirectory(builder.GetHomeDirectory());
  211. builder.SetStartOutputDirectory(builder.GetHomeOutputDirectory());
  212. }
  213. }
  214. // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the cache
  215. int cmake::AddCMakePaths(const std::vector<std::string>& args)
  216. {
  217. // Find our own executable.
  218. std::vector<cmStdString> failures;
  219. std::string cMakeSelf = args[0];
  220. cmSystemTools::ConvertToUnixSlashes(cMakeSelf);
  221. failures.push_back(cMakeSelf);
  222. cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str());
  223. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  224. {
  225. #ifdef CMAKE_BUILD_DIR
  226. std::string intdir = ".";
  227. #ifdef CMAKE_INTDIR
  228. intdir = CMAKE_INTDIR;
  229. #endif
  230. cMakeSelf = CMAKE_BUILD_DIR;
  231. cMakeSelf += "/Source/";
  232. cMakeSelf += intdir;
  233. cMakeSelf += "/cmake";
  234. cMakeSelf += cmSystemTools::GetExecutableExtension();
  235. #endif
  236. }
  237. #ifdef CMAKE_PREFIX
  238. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  239. {
  240. failures.push_back(cMakeSelf);
  241. cMakeSelf = CMAKE_PREFIX "/bin/cmake";
  242. }
  243. #endif
  244. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  245. {
  246. failures.push_back(cMakeSelf);
  247. cmStringStream msg;
  248. msg << "CMAKE can not find the command line program cmake.\n";
  249. msg << " argv[0] = \"" << args[0].c_str() << "\"\n";
  250. msg << " Attempted paths:\n";
  251. std::vector<cmStdString>::iterator i;
  252. for(i=failures.begin(); i != failures.end(); ++i)
  253. {
  254. msg << " \"" << i->c_str() << "\"\n";
  255. }
  256. cmSystemTools::Error(msg.str().c_str());
  257. return 0;
  258. }
  259. // Save the value in the cache
  260. cmCacheManager::GetInstance()->AddCacheEntry
  261. ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
  262. cmCacheManager::INTERNAL);
  263. // Find and save the command to edit the cache
  264. std::string editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
  265. "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  266. if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
  267. {
  268. editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
  269. "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  270. }
  271. if(cmSystemTools::FileExists(editCacheCommand.c_str()))
  272. {
  273. cmCacheManager::GetInstance()->AddCacheEntry
  274. ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
  275. "Path to cache edit program executable.", cmCacheManager::INTERNAL);
  276. }
  277. // do CMAKE_ROOT, look for the environment variable first
  278. std::string cMakeRoot;
  279. std::string modules;
  280. if (getenv("CMAKE_ROOT"))
  281. {
  282. cMakeRoot = getenv("CMAKE_ROOT");
  283. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  284. }
  285. if(!cmSystemTools::FileExists(modules.c_str()))
  286. {
  287. // next try exe/..
  288. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  289. std::string::size_type slashPos = cMakeRoot.rfind("/");
  290. if(slashPos != std::string::npos)
  291. {
  292. cMakeRoot = cMakeRoot.substr(0, slashPos);
  293. }
  294. // is there no Modules direcory there?
  295. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  296. }
  297. if (!cmSystemTools::FileExists(modules.c_str()))
  298. {
  299. // try exe/../share/cmake
  300. cMakeRoot += "/share/CMake";
  301. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  302. }
  303. #ifdef CMAKE_ROOT_DIR
  304. if (!cmSystemTools::FileExists(modules.c_str()))
  305. {
  306. // try compiled in root directory
  307. cMakeRoot = CMAKE_ROOT_DIR;
  308. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  309. }
  310. #endif
  311. #ifdef CMAKE_PREFIX
  312. if (!cmSystemTools::FileExists(modules.c_str()))
  313. {
  314. // try compiled in install prefix
  315. cMakeRoot = CMAKE_PREFIX "/share/CMake";
  316. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  317. }
  318. #endif
  319. if (!cmSystemTools::FileExists(modules.c_str()))
  320. {
  321. // try
  322. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  323. cMakeRoot += "/share/CMake";
  324. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  325. }
  326. if(!cmSystemTools::FileExists(modules.c_str()))
  327. {
  328. // next try exe
  329. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  330. // is there no Modules direcory there?
  331. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  332. }
  333. if (!cmSystemTools::FileExists(modules.c_str()))
  334. {
  335. // couldn't find modules
  336. cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n",
  337. "Modules directory not in directory:\n",
  338. modules.c_str());
  339. return 0;
  340. }
  341. cmCacheManager::GetInstance()->AddCacheEntry
  342. ("CMAKE_ROOT", cMakeRoot.c_str(),
  343. "Path to CMake installation.", cmCacheManager::INTERNAL);
  344. return 1;
  345. }
  346. int cmake::Generate(const std::vector<std::string>& args, bool buildMakefiles)
  347. {
  348. if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
  349. {
  350. this->Usage(args[0].c_str());
  351. return -1;
  352. }
  353. // look for obvious request for help
  354. for(unsigned int i=1; i < args.size(); ++i)
  355. {
  356. std::string arg = args[i];
  357. if(arg.find("-help",0) != std::string::npos ||
  358. arg.find("--help",0) != std::string::npos ||
  359. arg.find("/?",0) != std::string::npos ||
  360. arg.find("-usage",0) != std::string::npos)
  361. {
  362. this->Usage(args[0].c_str());
  363. return -1;
  364. }
  365. }
  366. // Create a makefile
  367. cmMakefile mf;
  368. // extract the directory arguments, could create a Generator
  369. this->SetArgs(mf, args);
  370. // Read and parse the input makefile
  371. mf.MakeStartDirectoriesCurrent();
  372. cmCacheManager::GetInstance()->LoadCache(&mf);
  373. if(mf.GetDefinition("CMAKE_HOME_DIRECTORY"))
  374. {
  375. std::string cacheStart = mf.GetDefinition("CMAKE_HOME_DIRECTORY");
  376. cacheStart += "/CMakeLists.txt";
  377. std::string currentStart = mf.GetHomeDirectory();
  378. currentStart += "/CMakeLists.txt";
  379. if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
  380. {
  381. std::string message = "Error: source : ";
  382. message += currentStart;
  383. message += "\nDoes not match source used to generate cache: ";
  384. message += cacheStart;
  385. message += "\nRe-run cmake with a different source directory.";
  386. cmSystemTools::Error(message.c_str());
  387. return -2;
  388. }
  389. }
  390. mf.AddCacheDefinition("CMAKE_HOME_DIRECTORY", mf.GetHomeDirectory(),
  391. "Start directory with the top level CMakeLists.txt file for this project",
  392. cmCacheManager::INTERNAL);
  393. // extract command line arguments that might add cache entries
  394. this->SetCacheArgs(mf, args);
  395. // no generator specified on the command line
  396. if(!mf.GetMakefileGenerator())
  397. {
  398. cmMakefileGenerator* gen;
  399. const char* genName = mf.GetDefinition("CMAKE_GENERATOR");
  400. if(genName)
  401. {
  402. gen = cmMakefileGenerator::CreateGenerator(genName);
  403. }
  404. else
  405. {
  406. #if defined(__BORLANDC__)
  407. gen = new cmBorlandMakefileGenerator;
  408. #elif defined(_WIN32) && !defined(__CYGWIN__)
  409. gen = new cmMSProjectGenerator;
  410. #else
  411. gen = new cmUnixMakefileGenerator;
  412. #endif
  413. }
  414. if(!gen)
  415. {
  416. cmSystemTools::Error("Could not create generator");
  417. return -1;
  418. }
  419. mf.SetMakefileGenerator(gen);
  420. // add the
  421. }
  422. cmMakefileGenerator* gen = mf.GetMakefileGenerator();
  423. gen->SetLocal(m_Local);
  424. const char* genName = mf.GetDefinition("CMAKE_GENERATOR");
  425. if(genName)
  426. {
  427. if(strcmp(gen->GetName(), genName) != 0)
  428. {
  429. std::string message = "Error: generator : ";
  430. message += gen->GetName();
  431. message += "\nDoes not match the generator used previously: ";
  432. message += genName;
  433. message +=
  434. "\nEither remove the CMakeCache.txt file or choose a different"
  435. " binary directory.";
  436. cmSystemTools::Error(message.c_str());
  437. return -2;
  438. }
  439. }
  440. if(!mf.GetDefinition("CMAKE_GENERATOR"))
  441. {
  442. mf.AddCacheDefinition("CMAKE_GENERATOR",
  443. gen->GetName(),
  444. "Name of generator.",
  445. cmCacheManager::INTERNAL);
  446. }
  447. // setup CMAKE_ROOT and CMAKE_COMMAND
  448. if(!this->AddCMakePaths(args))
  449. {
  450. return -3;
  451. }
  452. // reset any system configuration information
  453. cmMakefileGenerator::ClearEnabledLanguages();
  454. std::string lf = mf.GetStartDirectory();
  455. lf += "/CMakeLists.txt";
  456. if(!mf.ReadListFile(lf.c_str()))
  457. {
  458. this->Usage(args[0].c_str());
  459. return -1;
  460. }
  461. // if buildMakefiles, then call GenerateMakefile
  462. if(buildMakefiles)
  463. {
  464. mf.GenerateMakefile();
  465. }
  466. else // do not build, but let the commands finalize
  467. {
  468. std::vector<cmMakefile*> makefiles;
  469. mf.FindSubDirectoryCMakeListsFiles(makefiles);
  470. for(std::vector<cmMakefile*>::iterator i = makefiles.begin();
  471. i != makefiles.end(); ++i)
  472. {
  473. cmMakefile* mf = *i;
  474. mf->FinalPass();
  475. delete mf;
  476. }
  477. mf.FinalPass();
  478. }
  479. // Before saving the cache
  480. // if the project did not define one of the entries below, add them now
  481. // so users can edit the values in the cache:
  482. // LIBRARY_OUTPUT_PATH
  483. // EXECUTABLE_OUTPUT_PATH
  484. if(!cmCacheManager::GetInstance()->GetCacheValue("LIBRARY_OUTPUT_PATH"))
  485. {
  486. cmCacheManager::GetInstance()->AddCacheEntry("LIBRARY_OUTPUT_PATH", "",
  487. "Single output directory for building all libraries.",
  488. cmCacheManager::PATH);
  489. }
  490. if(!cmCacheManager::GetInstance()->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
  491. {
  492. cmCacheManager::GetInstance()->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "",
  493. "Single output directory for building all executables.",
  494. cmCacheManager::PATH);
  495. }
  496. cmCacheManager::GetInstance()->SaveCache(&mf);
  497. if(m_Verbose)
  498. {
  499. cmCacheManager::GetInstance()->PrintCache(std::cout);
  500. }
  501. if(cmSystemTools::GetErrorOccuredFlag())
  502. {
  503. return -1;
  504. }
  505. return 0;
  506. }
  507. void CMakeCommandUsage(const char* program)
  508. {
  509. cmStringStream errorStream;
  510. errorStream
  511. << "cmake version " << cmMakefile::GetMajorVersion()
  512. << "." << cmMakefile::GetMinorVersion() << "\n";
  513. errorStream
  514. << "Usage: " << program << " -E [command] [arguments ...]\n"
  515. << "Available commands: \n"
  516. << " chdir dir cmd [args]... - run command in a given directory\n"
  517. << " copy file destination - copy file to destination (either file or directory)\n"
  518. << " remove file1 file2 ... - remove the file(s)\n"
  519. << " time command [args] ... - run command and return elapsed time\n";
  520. #if defined(_WIN32) && !defined(__CYGWIN__)
  521. errorStream
  522. << " write_regv key value - write registry value\n"
  523. << " delete_regv key - delete registry value\n";
  524. #endif
  525. cmSystemTools::Error(errorStream.str().c_str());
  526. }
  527. int cmake::CMakeCommand(std::vector<std::string>& args)
  528. {
  529. if (args.size() > 1)
  530. {
  531. // Copy file
  532. if (args[1] == "copy" && args.size() == 4)
  533. {
  534. cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str());
  535. return cmSystemTools::GetErrorOccuredFlag();
  536. }
  537. // Remove file
  538. else if (args[1] == "remove" && args.size() > 2)
  539. {
  540. for (std::string::size_type cc = 2; cc < args.size(); cc ++)
  541. {
  542. if(args[cc] != "-f")
  543. {
  544. if(args[cc] == "\\-f")
  545. {
  546. args[cc] = "-f";
  547. }
  548. cmSystemTools::RemoveFile(args[cc].c_str());
  549. }
  550. }
  551. return 0;
  552. }
  553. // Clock command
  554. else if (args[1] == "time" && args.size() > 2)
  555. {
  556. std::string command = args[2];
  557. std::string output;
  558. for (std::string::size_type cc = 3; cc < args.size(); cc ++)
  559. {
  560. command += " ";
  561. command += args[cc];
  562. }
  563. clock_t clock_start, clock_finish;
  564. time_t time_start, time_finish;
  565. time(&time_start);
  566. clock_start = clock();
  567. cmSystemTools::RunCommand(command.c_str(), output, 0, true);
  568. clock_finish = clock();
  569. time(&time_finish);
  570. std::cout << output.c_str();
  571. double clocks_per_sec = (double)CLOCKS_PER_SEC;
  572. std::cout << "Elapsed time: "
  573. << (long)(time_finish - time_start) << " s. (time)"
  574. << ", "
  575. << (double)(clock_finish - clock_start) / clocks_per_sec
  576. << " s. (clock)"
  577. << "\n";
  578. return 0;
  579. }
  580. // Clock command
  581. else if (args[1] == "chdir" && args.size() > 2)
  582. {
  583. std::string directory = args[2];
  584. std::string command = args[3];
  585. std::string output;
  586. for (std::string::size_type cc = 4; cc < args.size(); cc ++)
  587. {
  588. command += " ";
  589. command += args[cc];
  590. }
  591. int retval = 0;
  592. if ( cmSystemTools::RunCommand(command.c_str(), output, retval,
  593. directory.c_str(), true) )
  594. {
  595. std::cout << output.c_str();
  596. return retval;
  597. }
  598. return 1;
  599. }
  600. #if defined(_WIN32) && !defined(__CYGWIN__)
  601. // Write registry value
  602. else if (args[1] == "write_regv" && args.size() > 3)
  603. {
  604. return cmSystemTools::WriteRegistryValue(args[2].c_str(),
  605. args[3].c_str()) ? 0 : 1;
  606. }
  607. // Delete registry value
  608. else if (args[1] == "delete_regv" && args.size() > 2)
  609. {
  610. return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
  611. }
  612. #endif
  613. }
  614. ::CMakeCommandUsage(args[0].c_str());
  615. return 1;
  616. }