cmake.cxx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  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. std::strstream 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" << std::ends;
  57. cmSystemTools::Error(errorStream.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. void cmake::AddCMakePaths(const std::vector<std::string>& args)
  213. {
  214. // Find our own executable.
  215. std::string cMakeSelf = args[0];
  216. cmSystemTools::ConvertToUnixSlashes(cMakeSelf);
  217. cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str());
  218. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  219. {
  220. #ifdef CMAKE_BUILD_DIR
  221. std::string intdir = ".";
  222. #ifdef CMAKE_INTDIR
  223. intdir = CMAKE_INTDIR;
  224. #endif
  225. cMakeSelf = CMAKE_BUILD_DIR;
  226. cMakeSelf += "/Source/";
  227. cMakeSelf += intdir;
  228. cMakeSelf += "/cmake";
  229. cMakeSelf += cmSystemTools::GetExecutableExtension();
  230. #endif
  231. }
  232. #ifdef CMAKE_PREFIX
  233. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  234. {
  235. cMakeSelf = CMAKE_PREFIX "/bin/cmake";
  236. }
  237. #endif
  238. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  239. {
  240. cmSystemTools::Error("CMAKE can not find the command line program cmake. "
  241. "Attempted path: ", cMakeSelf.c_str());
  242. return;
  243. }
  244. // Save the value in the cache
  245. cmCacheManager::GetInstance()->AddCacheEntry
  246. ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
  247. cmCacheManager::INTERNAL);
  248. // Find and save the command to edit the cache
  249. std::string editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
  250. "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  251. if( !cmSystemTools::FileExists(editCacheCommand.c_str()))
  252. {
  253. editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
  254. "/CMakeSetup" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  255. }
  256. if(cmSystemTools::FileExists(editCacheCommand.c_str()))
  257. {
  258. cmCacheManager::GetInstance()->AddCacheEntry
  259. ("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
  260. "Path to cache edit program executable.", cmCacheManager::INTERNAL);
  261. }
  262. // do CMAKE_ROOT, look for the environment variable first
  263. std::string cMakeRoot;
  264. std::string modules;
  265. if (getenv("CMAKE_ROOT"))
  266. {
  267. cMakeRoot = getenv("CMAKE_ROOT");
  268. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  269. }
  270. if(!cmSystemTools::FileExists(modules.c_str()))
  271. {
  272. // next try exe/..
  273. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  274. std::string::size_type slashPos = cMakeRoot.rfind("/");
  275. if(slashPos != std::string::npos)
  276. {
  277. cMakeRoot = cMakeRoot.substr(0, slashPos);
  278. }
  279. // is there no Modules direcory there?
  280. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  281. }
  282. if (!cmSystemTools::FileExists(modules.c_str()))
  283. {
  284. // try exe/../share/cmake
  285. cMakeRoot += "/share/CMake";
  286. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  287. }
  288. #ifdef CMAKE_ROOT_DIR
  289. if (!cmSystemTools::FileExists(modules.c_str()))
  290. {
  291. // try compiled in root directory
  292. cMakeRoot = CMAKE_ROOT_DIR;
  293. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  294. }
  295. #endif
  296. #ifdef CMAKE_PREFIX
  297. if (!cmSystemTools::FileExists(modules.c_str()))
  298. {
  299. // try compiled in install prefix
  300. cMakeRoot = CMAKE_PREFIX "/share/CMake";
  301. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  302. }
  303. #endif
  304. if (!cmSystemTools::FileExists(modules.c_str()))
  305. {
  306. // try
  307. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  308. cMakeRoot += "/share/CMake";
  309. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  310. }
  311. if(!cmSystemTools::FileExists(modules.c_str()))
  312. {
  313. // next try exe
  314. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  315. // is there no Modules direcory there?
  316. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  317. }
  318. if (!cmSystemTools::FileExists(modules.c_str()))
  319. {
  320. // couldn't find modules
  321. cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n",
  322. "Modules directory not in directory:\n",
  323. modules.c_str());
  324. return;
  325. }
  326. cmCacheManager::GetInstance()->AddCacheEntry
  327. ("CMAKE_ROOT", cMakeRoot.c_str(),
  328. "Path to CMake installation.", cmCacheManager::INTERNAL);
  329. }
  330. int cmake::Generate(const std::vector<std::string>& args, bool buildMakefiles)
  331. {
  332. if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
  333. {
  334. this->Usage(args[0].c_str());
  335. return -1;
  336. }
  337. // look for obvious request for help
  338. for(unsigned int i=1; i < args.size(); ++i)
  339. {
  340. std::string arg = args[i];
  341. if(arg.find("-help",0) != std::string::npos ||
  342. arg.find("--help",0) != std::string::npos ||
  343. arg.find("/?",0) != std::string::npos ||
  344. arg.find("-usage",0) != std::string::npos)
  345. {
  346. this->Usage(args[0].c_str());
  347. return -1;
  348. }
  349. }
  350. // Create a makefile
  351. cmMakefile mf;
  352. // extract the directory arguments, could create a Generator
  353. this->SetArgs(mf, args);
  354. // Read and parse the input makefile
  355. mf.MakeStartDirectoriesCurrent();
  356. cmCacheManager::GetInstance()->LoadCache(&mf);
  357. if(mf.GetDefinition("CMAKE_HOME_DIRECTORY"))
  358. {
  359. std::string cacheStart = mf.GetDefinition("CMAKE_HOME_DIRECTORY");
  360. cacheStart += "/CMakeLists.txt";
  361. std::string currentStart = mf.GetHomeDirectory();
  362. currentStart += "/CMakeLists.txt";
  363. if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
  364. {
  365. std::string message = "Error: source : ";
  366. message += currentStart;
  367. message += "\nDoes not match source used to generate cache: ";
  368. message += cacheStart;
  369. message += "\nRe-run cmake with a different source directory.";
  370. cmSystemTools::Error(message.c_str());
  371. return -2;
  372. }
  373. }
  374. mf.AddCacheDefinition("CMAKE_HOME_DIRECTORY", mf.GetHomeDirectory(),
  375. "Start directory with the top level CMakeLists.txt file for this project",
  376. cmCacheManager::INTERNAL);
  377. // extract command line arguments that might add cache entries
  378. this->SetCacheArgs(mf, args);
  379. // no generator specified on the command line
  380. if(!mf.GetMakefileGenerator())
  381. {
  382. cmMakefileGenerator* gen;
  383. const char* genName = mf.GetDefinition("CMAKE_GENERATOR");
  384. if(genName)
  385. {
  386. gen = cmMakefileGenerator::CreateGenerator(genName);
  387. }
  388. else
  389. {
  390. #if defined(__BORLANDC__)
  391. gen = new cmBorlandMakefileGenerator;
  392. #elif defined(_WIN32) && !defined(__CYGWIN__)
  393. gen = new cmMSProjectGenerator;
  394. #else
  395. gen = new cmUnixMakefileGenerator;
  396. #endif
  397. }
  398. if(!gen)
  399. {
  400. cmSystemTools::Error("Could not create generator");
  401. return -1;
  402. }
  403. mf.SetMakefileGenerator(gen);
  404. // add the
  405. }
  406. cmMakefileGenerator* gen = mf.GetMakefileGenerator();
  407. gen->SetLocal(m_Local);
  408. const char* genName = mf.GetDefinition("CMAKE_GENERATOR");
  409. if(genName)
  410. {
  411. if(strcmp(gen->GetName(), genName) != 0)
  412. {
  413. std::string message = "Error: generator : ";
  414. message += gen->GetName();
  415. message += "\nDoes not match the generator used previously: ";
  416. message += genName;
  417. message +=
  418. "\nEither remove the CMakeCache.txt file or choose a different"
  419. " binary directory.";
  420. cmSystemTools::Error(message.c_str());
  421. return -2;
  422. }
  423. }
  424. if(!mf.GetDefinition("CMAKE_GENERATOR"))
  425. {
  426. mf.AddCacheDefinition("CMAKE_GENERATOR",
  427. gen->GetName(),
  428. "Name of generator.",
  429. cmCacheManager::INTERNAL);
  430. }
  431. // setup CMAKE_ROOT and CMAKE_COMMAND
  432. this->AddCMakePaths(args);
  433. // reset any system configuration information
  434. cmMakefileGenerator::ClearEnabledLanguages();
  435. std::string lf = mf.GetStartDirectory();
  436. lf += "/CMakeLists.txt";
  437. if(!mf.ReadListFile(lf.c_str()))
  438. {
  439. this->Usage(args[0].c_str());
  440. return -1;
  441. }
  442. // if buildMakefiles, then call GenerateMakefile
  443. if(buildMakefiles)
  444. {
  445. mf.GenerateMakefile();
  446. }
  447. else // do not build, but let the commands finalize
  448. {
  449. std::vector<cmMakefile*> makefiles;
  450. mf.FindSubDirectoryCMakeListsFiles(makefiles);
  451. for(std::vector<cmMakefile*>::iterator i = makefiles.begin();
  452. i != makefiles.end(); ++i)
  453. {
  454. cmMakefile* mf = *i;
  455. mf->FinalPass();
  456. delete mf;
  457. }
  458. mf.FinalPass();
  459. }
  460. // Before saving the cache
  461. // if the project did not define one of the entries below, add them now
  462. // so users can edit the values in the cache:
  463. // LIBRARY_OUTPUT_PATH
  464. // EXECUTABLE_OUTPUT_PATH
  465. if(!cmCacheManager::GetInstance()->GetCacheValue("LIBRARY_OUTPUT_PATH"))
  466. {
  467. cmCacheManager::GetInstance()->AddCacheEntry("LIBRARY_OUTPUT_PATH", "",
  468. "Single output directory for building all libraries.",
  469. cmCacheManager::PATH);
  470. }
  471. if(!cmCacheManager::GetInstance()->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
  472. {
  473. cmCacheManager::GetInstance()->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "",
  474. "Single output directory for building all executables.",
  475. cmCacheManager::PATH);
  476. }
  477. cmCacheManager::GetInstance()->SaveCache(&mf);
  478. if(m_Verbose)
  479. {
  480. cmCacheManager::GetInstance()->PrintCache(std::cout);
  481. }
  482. if(cmSystemTools::GetErrorOccuredFlag())
  483. {
  484. return -1;
  485. }
  486. return 0;
  487. }
  488. void CMakeCommandUsage(const char* program)
  489. {
  490. std::strstream errorStream;
  491. errorStream
  492. << "cmake version " << cmMakefile::GetMajorVersion()
  493. << "." << cmMakefile::GetMinorVersion() << "\n";
  494. errorStream
  495. << "Usage: " << program << " -E [command] [arguments ...]\n"
  496. << "Available commands: \n"
  497. << " copy file destination - copy file to destination (either file or directory)\n"
  498. << " remove file1 file2 ... - remove the file(s)\n"
  499. << " time command [args] ... - run command and return elapsed time\n"
  500. #if defined(_WIN32) && !defined(__CYGWIN__)
  501. << " write_regv key value - write registry value\n"
  502. << " delete_regv key - delete registry value\n"
  503. #endif
  504. << std::ends;
  505. cmSystemTools::Error(errorStream.str());
  506. }
  507. int cmake::CMakeCommand(std::vector<std::string>& args)
  508. {
  509. if (args.size() > 1)
  510. {
  511. // Copy file
  512. if (args[1] == "copy" && args.size() == 4)
  513. {
  514. cmSystemTools::cmCopyFile(args[2].c_str(), args[3].c_str());
  515. return cmSystemTools::GetErrorOccuredFlag();
  516. }
  517. // Remove file
  518. else if (args[1] == "remove" && args.size() > 2)
  519. {
  520. for (std::string::size_type cc = 2; cc < args.size(); cc ++)
  521. {
  522. if(args[cc] != "-f")
  523. {
  524. if(args[cc] == "\\-f")
  525. {
  526. args[cc] = "-f";
  527. }
  528. cmSystemTools::RemoveFile(args[cc].c_str());
  529. }
  530. }
  531. return 0;
  532. }
  533. // Clock command
  534. else if (args[1] == "time" && args.size() > 2)
  535. {
  536. std::string command = args[2];
  537. std::string output;
  538. for (std::string::size_type cc = 3; cc < args.size(); cc ++)
  539. {
  540. command += " ";
  541. command += args[cc];
  542. }
  543. clock_t clock_start, clock_finish;
  544. time_t time_start, time_finish;
  545. time(&time_start);
  546. clock_start = clock();
  547. cmSystemTools::RunCommand(command.c_str(), output, 0, true);
  548. clock_finish = clock();
  549. time(&time_finish);
  550. std::cout << output.c_str();
  551. double clocks_per_sec = (double)CLOCKS_PER_SEC;
  552. std::cout << "Elapsed time: "
  553. << (long)(time_finish - time_start) << " s. (time)"
  554. << ", "
  555. << (double)(clock_finish - clock_start) / clocks_per_sec
  556. << " s. (clock)"
  557. << "\n";
  558. return 0;
  559. }
  560. #if defined(_WIN32) && !defined(__CYGWIN__)
  561. // Write registry value
  562. else if (args[1] == "write_regv" && args.size() > 3)
  563. {
  564. return cmSystemTools::WriteRegistryValue(args[2].c_str(),
  565. args[3].c_str()) ? 0 : 1;
  566. }
  567. // Delete registry value
  568. else if (args[1] == "delete_regv" && args.size() > 2)
  569. {
  570. return cmSystemTools::DeleteRegistryValue(args[2].c_str()) ? 0 : 1;
  571. }
  572. #endif
  573. }
  574. ::CMakeCommandUsage(args[0].c_str());
  575. return 1;
  576. }