cmake.cxx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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 "cmCacheManager.h"
  15. // include the generator
  16. #if defined(_WIN32) && !defined(__CYGWIN__)
  17. #include "cmMSProjectGenerator.h"
  18. #include "cmMSDotNETGenerator.h"
  19. #include "cmBorlandMakefileGenerator.h"
  20. #include "cmNMakeMakefileGenerator.h"
  21. #else
  22. #include "cmUnixMakefileGenerator.h"
  23. #endif
  24. cmake::cmake()
  25. {
  26. m_Verbose = false;
  27. #if defined(_WIN32) && !defined(__CYGWIN__)
  28. cmMakefileGenerator::RegisterGenerator(new cmMSProjectGenerator);
  29. cmMakefileGenerator::RegisterGenerator(new cmMSDotNETGenerator);
  30. cmMakefileGenerator::RegisterGenerator(new cmNMakeMakefileGenerator);
  31. cmMakefileGenerator::RegisterGenerator(new cmBorlandMakefileGenerator);
  32. #else
  33. cmMakefileGenerator::RegisterGenerator(new cmUnixMakefileGenerator);
  34. #endif
  35. }
  36. void cmake::Usage(const char* program)
  37. {
  38. std::strstream errorStream;
  39. errorStream << "cmake version " << cmMakefile::GetMajorVersion()
  40. << "." << cmMakefile::GetMinorVersion() << "\n";
  41. errorStream << "Usage: " << program << " [srcdir] [options]\n"
  42. << "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";
  43. errorStream << "Options are:\n";
  44. errorStream << "\n-i (puts cmake in wizard mode, not available for ccmake)\n";
  45. errorStream << "\n-DVAR:TYPE=VALUE (create a cache file entry)\n";
  46. errorStream << "\n-Cpath_to_initial_cache (a cmake list file that is used to pre-load the cache with values.)\n";
  47. errorStream << "\n[-GgeneratorName] (where generator name can be one of these: ";
  48. std::vector<std::string> names;
  49. cmMakefileGenerator::GetRegisteredGenerators(names);
  50. for(std::vector<std::string>::iterator i =names.begin();
  51. i != names.end(); ++i)
  52. {
  53. errorStream << "\"" << i->c_str() << "\" ";
  54. }
  55. errorStream << ")\n" << std::ends;
  56. cmSystemTools::Error(errorStream.str());
  57. }
  58. // Parse the args
  59. void cmake::SetCacheArgs(cmMakefile& builder,
  60. const std::vector<std::string>& args)
  61. {
  62. for(unsigned int i=1; i < args.size(); ++i)
  63. {
  64. std::string arg = args[i];
  65. if(arg.find("-D",0) == 0)
  66. {
  67. std::string entry = arg.substr(2);
  68. std::string var, value;
  69. cmCacheManager::CacheEntryType type;
  70. if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
  71. {
  72. cmCacheManager::GetInstance()->AddCacheEntry(
  73. var.c_str(),
  74. value.c_str(),
  75. "No help, variable specified on the command line.",
  76. type);
  77. }
  78. else
  79. {
  80. std::cerr << "Parse error in command line argument: " << arg << "\n"
  81. << "Should be: VAR:type=value\n";
  82. }
  83. }
  84. else if(arg.find("-C",0) == 0)
  85. {
  86. std::string path = arg.substr(2);
  87. std::cerr << "loading initial cache file " << path.c_str() << "\n";
  88. if(!builder.ReadListFile(path.c_str()))
  89. {
  90. std::cerr << "Error in reading cmake initial cache file:"
  91. << path.c_str() << "\n";
  92. }
  93. }
  94. }
  95. }
  96. // Parse the args
  97. void cmake::SetArgs(cmMakefile& builder, const std::vector<std::string>& args)
  98. {
  99. m_Local = false;
  100. bool directoriesSet = false;
  101. // watch for cmake and cmake srcdir invocations
  102. if (args.size() <= 2)
  103. {
  104. directoriesSet = true;
  105. builder.SetHomeOutputDirectory
  106. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  107. builder.SetStartOutputDirectory
  108. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  109. if (args.size() == 2)
  110. {
  111. builder.SetHomeDirectory
  112. (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
  113. builder.SetStartDirectory
  114. (cmSystemTools::CollapseFullPath(args[1].c_str()).c_str());
  115. }
  116. else
  117. {
  118. builder.SetHomeDirectory
  119. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  120. builder.SetStartDirectory
  121. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  122. }
  123. }
  124. for(unsigned int i=1; i < args.size(); ++i)
  125. {
  126. std::string arg = args[i];
  127. if(arg.find("-H",0) == 0)
  128. {
  129. directoriesSet = true;
  130. std::string path = arg.substr(2);
  131. builder.SetHomeDirectory(path.c_str());
  132. }
  133. else if(arg.find("-S",0) == 0)
  134. {
  135. directoriesSet = true;
  136. m_Local = true;
  137. std::string path = arg.substr(2);
  138. builder.SetStartDirectory(path.c_str());
  139. }
  140. else if(arg.find("-O",0) == 0)
  141. {
  142. directoriesSet = true;
  143. std::string path = arg.substr(2);
  144. builder.SetStartOutputDirectory(path.c_str());
  145. }
  146. else if(arg.find("-B",0) == 0)
  147. {
  148. directoriesSet = true;
  149. std::string path = arg.substr(2);
  150. builder.SetHomeOutputDirectory(path.c_str());
  151. }
  152. else if(arg.find("-V",0) == 0)
  153. {
  154. m_Verbose = true;
  155. }
  156. else if(arg.find("-D",0) == 0)
  157. {
  158. // skip for now
  159. }
  160. else if(arg.find("-C",0) == 0)
  161. {
  162. // skip for now
  163. }
  164. else if(arg.find("-G",0) == 0)
  165. {
  166. std::string value = arg.substr(2);
  167. cmMakefileGenerator* gen =
  168. cmMakefileGenerator::CreateGenerator(value.c_str());
  169. if(!gen)
  170. {
  171. cmSystemTools::Error("Could not create named generator ",
  172. value.c_str());
  173. }
  174. else
  175. {
  176. builder.SetMakefileGenerator(gen);
  177. }
  178. }
  179. // no option assume it is the path to the source
  180. else
  181. {
  182. directoriesSet = true;
  183. builder.SetHomeOutputDirectory
  184. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  185. builder.SetStartOutputDirectory
  186. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  187. builder.SetHomeDirectory
  188. (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
  189. builder.SetStartDirectory
  190. (cmSystemTools::CollapseFullPath(arg.c_str()).c_str());
  191. }
  192. }
  193. if(!directoriesSet)
  194. {
  195. builder.SetHomeOutputDirectory
  196. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  197. builder.SetStartOutputDirectory
  198. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  199. builder.SetHomeDirectory
  200. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  201. builder.SetStartDirectory
  202. (cmSystemTools::GetCurrentWorkingDirectory().c_str());
  203. }
  204. if (!m_Local)
  205. {
  206. builder.SetStartDirectory(builder.GetHomeDirectory());
  207. builder.SetStartOutputDirectory(builder.GetHomeOutputDirectory());
  208. }
  209. }
  210. // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the cache
  211. void cmake::AddCMakePaths(const std::vector<std::string>& args)
  212. {
  213. // Find our own executable.
  214. std::string cMakeSelf = args[0];
  215. cmSystemTools::ConvertToUnixSlashes(cMakeSelf);
  216. cMakeSelf = cmSystemTools::FindProgram(cMakeSelf.c_str());
  217. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  218. {
  219. #ifdef CMAKE_BUILD_DIR
  220. cMakeSelf = CMAKE_BUILD_DIR;
  221. cMakeSelf += "/Source/cmake";
  222. #endif
  223. }
  224. #ifdef CMAKE_PREFIX
  225. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  226. {
  227. cMakeSelf = CMAKE_PREFIX "/bin/cmake";
  228. }
  229. #endif
  230. if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
  231. {
  232. cmSystemTools::Error("CMAKE can not find the command line program cmake. "
  233. "Attempted path: ", cMakeSelf.c_str());
  234. return;
  235. }
  236. // Save the value in the cache
  237. cmCacheManager::GetInstance()->AddCacheEntry
  238. ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.",
  239. cmCacheManager::INTERNAL);
  240. // Find ccommand
  241. std::string cCommand = cmSystemTools::GetFilenamePath(cMakeSelf) +
  242. "/ccommand" + cmSystemTools::GetFilenameExtension(cMakeSelf);
  243. if( !cmSystemTools::FileExists(cMakeSelf.c_str()))
  244. {
  245. cmSystemTools::Error("CMAKE can not find the command line program "
  246. "ccommand. Attempted path: ", cMakeSelf.c_str());
  247. return;
  248. }
  249. // Save the value in the cache
  250. cmCacheManager::GetInstance()->AddCacheEntry
  251. ("CCOMMAND_COMMAND",cCommand.c_str(),
  252. "Path to CMakeCommand executable.", cmCacheManager::INTERNAL);
  253. // do CMAKE_ROOT, look for the environment variable first
  254. std::string cMakeRoot;
  255. std::string modules;
  256. if (getenv("CMAKE_ROOT"))
  257. {
  258. cMakeRoot = getenv("CMAKE_ROOT");
  259. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  260. }
  261. if(!cmSystemTools::FileExists(modules.c_str()))
  262. {
  263. // next try exe/..
  264. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  265. std::string::size_type slashPos = cMakeRoot.rfind("/");
  266. if(slashPos != std::string::npos)
  267. {
  268. cMakeRoot = cMakeRoot.substr(0, slashPos);
  269. }
  270. // is there no Modules direcory there?
  271. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  272. }
  273. if (!cmSystemTools::FileExists(modules.c_str()))
  274. {
  275. // try exe/../share/cmake
  276. cMakeRoot += "/share/CMake";
  277. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  278. }
  279. #ifdef CMAKE_ROOT_DIR
  280. if (!cmSystemTools::FileExists(modules.c_str()))
  281. {
  282. // try compiled in root directory
  283. cMakeRoot = CMAKE_ROOT_DIR;
  284. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  285. }
  286. #endif
  287. #ifdef CMAKE_PREFIX
  288. if (!cmSystemTools::FileExists(modules.c_str()))
  289. {
  290. // try compiled in install prefix
  291. cMakeRoot = CMAKE_PREFIX "/share/CMake";
  292. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  293. }
  294. #endif
  295. if (!cmSystemTools::FileExists(modules.c_str()))
  296. {
  297. // try
  298. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  299. cMakeRoot += "/share/CMake";
  300. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  301. }
  302. if (!cmSystemTools::FileExists(modules.c_str()))
  303. {
  304. // couldn't find modules
  305. cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n",
  306. "Modules directory not in directory:\n",
  307. modules.c_str());
  308. return;
  309. }
  310. cmCacheManager::GetInstance()->AddCacheEntry
  311. ("CMAKE_ROOT", cMakeRoot.c_str(),
  312. "Path to CMake installation.", cmCacheManager::INTERNAL);
  313. }
  314. int cmake::Generate(const std::vector<std::string>& args, bool buildMakefiles)
  315. {
  316. if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
  317. {
  318. this->Usage(args[0].c_str());
  319. return -1;
  320. }
  321. // look for obvious request for help
  322. for(unsigned int i=1; i < args.size(); ++i)
  323. {
  324. std::string arg = args[i];
  325. if(arg.find("-help",0) != std::string::npos ||
  326. arg.find("--help",0) != std::string::npos ||
  327. arg.find("/?",0) != std::string::npos ||
  328. arg.find("-usage",0) != std::string::npos)
  329. {
  330. this->Usage(args[0].c_str());
  331. return -1;
  332. }
  333. }
  334. // Create a makefile
  335. cmMakefile mf;
  336. // extract the directory arguments, could create a Generator
  337. this->SetArgs(mf, args);
  338. // Read and parse the input makefile
  339. mf.MakeStartDirectoriesCurrent();
  340. cmCacheManager::GetInstance()->LoadCache(&mf);
  341. if(mf.GetDefinition("CMAKE_HOME_DIRECTORY"))
  342. {
  343. std::string cacheStart = mf.GetDefinition("CMAKE_HOME_DIRECTORY");
  344. cacheStart += "/CMakeLists.txt";
  345. std::string currentStart = mf.GetHomeDirectory();
  346. currentStart += "/CMakeLists.txt";
  347. if(!cmSystemTools::SameFile(cacheStart.c_str(), currentStart.c_str()))
  348. {
  349. std::string message = "Error: source : ";
  350. message += currentStart;
  351. message += "\nDoes not match source used to generate cache: ";
  352. message += cacheStart;
  353. message += "\nRe-run cmake with a different source directory.";
  354. cmSystemTools::Error(message.c_str());
  355. return -2;
  356. }
  357. }
  358. mf.AddCacheDefinition("CMAKE_HOME_DIRECTORY", mf.GetHomeDirectory(),
  359. "Start directory with the top level CMakeLists.txt file for this project",
  360. cmCacheManager::INTERNAL);
  361. // extract command line arguments that might add cache entries
  362. this->SetCacheArgs(mf, args);
  363. // no generator specified on the command line
  364. if(!mf.GetMakefileGenerator())
  365. {
  366. cmMakefileGenerator* gen;
  367. const char* genName = mf.GetDefinition("CMAKE_GENERATOR");
  368. if(genName)
  369. {
  370. gen = cmMakefileGenerator::CreateGenerator(genName);
  371. }
  372. else
  373. {
  374. #if defined(__BORLANDC__)
  375. gen = new cmBorlandMakefileGenerator;
  376. #elif defined(_WIN32) && !defined(__CYGWIN__)
  377. gen = new cmMSProjectGenerator;
  378. #else
  379. gen = new cmUnixMakefileGenerator;
  380. #endif
  381. }
  382. if(!gen)
  383. {
  384. cmSystemTools::Error("Could not create generator");
  385. return -1;
  386. }
  387. mf.SetMakefileGenerator(gen);
  388. // add the
  389. }
  390. cmMakefileGenerator* gen = mf.GetMakefileGenerator();
  391. gen->SetLocal(m_Local);
  392. if(!mf.GetDefinition("CMAKE_GENERATOR"))
  393. {
  394. mf.AddCacheDefinition("CMAKE_GENERATOR",
  395. gen->GetName(),
  396. "Name of generator.",
  397. cmCacheManager::INTERNAL);
  398. }
  399. // setup CMAKE_ROOT and CMAKE_COMMAND
  400. this->AddCMakePaths(args);
  401. // reset any system configuration information
  402. cmMakefileGenerator::ClearEnabledLanguages();
  403. std::string lf = mf.GetStartDirectory();
  404. lf += "/CMakeLists.txt";
  405. if(!mf.ReadListFile(lf.c_str()))
  406. {
  407. this->Usage(args[0].c_str());
  408. return -1;
  409. }
  410. // if buildMakefiles, then call GenerateMakefile
  411. if(buildMakefiles)
  412. {
  413. mf.GenerateMakefile();
  414. }
  415. else // do not build, but let the commands finalize
  416. {
  417. std::vector<cmMakefile*> makefiles;
  418. mf.FindSubDirectoryCMakeListsFiles(makefiles);
  419. for(std::vector<cmMakefile*>::iterator i = makefiles.begin();
  420. i != makefiles.end(); ++i)
  421. {
  422. cmMakefile* mf = *i;
  423. mf->FinalPass();
  424. delete mf;
  425. }
  426. mf.FinalPass();
  427. }
  428. // Before saving the cache
  429. // if the project did not define one of the entries below, add them now
  430. // so users can edit the values in the cache:
  431. // LIBRARY_OUTPUT_PATH
  432. // EXECUTABLE_OUTPUT_PATH
  433. if(!cmCacheManager::GetInstance()->GetCacheValue("LIBRARY_OUTPUT_PATH"))
  434. {
  435. cmCacheManager::GetInstance()->AddCacheEntry("LIBRARY_OUTPUT_PATH", "",
  436. "Single output directory for building all libraries.",
  437. cmCacheManager::PATH);
  438. }
  439. if(!cmCacheManager::GetInstance()->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
  440. {
  441. cmCacheManager::GetInstance()->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "",
  442. "Single output directory for building all executables.",
  443. cmCacheManager::PATH);
  444. }
  445. cmCacheManager::GetInstance()->SaveCache(&mf);
  446. if(m_Verbose)
  447. {
  448. cmCacheManager::GetInstance()->PrintCache(std::cout);
  449. }
  450. if(cmSystemTools::GetErrorOccuredFlag())
  451. {
  452. return -1;
  453. }
  454. return 0;
  455. }