cmake.cxx 20 KB

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