cmake.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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",
  239. cmSystemTools::EscapeSpaces(cMakeSelf.c_str()).c_str(),
  240. "Path to CMake executable.",
  241. cmCacheManager::INTERNAL);
  242. // do CMAKE_ROOT, look for the environment variable first
  243. std::string cMakeRoot;
  244. std::string modules;
  245. if (getenv("CMAKE_ROOT"))
  246. {
  247. cMakeRoot = getenv("CMAKE_ROOT");
  248. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  249. }
  250. if(!cmSystemTools::FileExists(modules.c_str()))
  251. {
  252. // next try exe/..
  253. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  254. std::string::size_type slashPos = cMakeRoot.rfind("/");
  255. if(slashPos != std::string::npos)
  256. {
  257. cMakeRoot = cMakeRoot.substr(0, slashPos);
  258. }
  259. // is there no Modules direcory there?
  260. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  261. }
  262. if (!cmSystemTools::FileExists(modules.c_str()))
  263. {
  264. // try exe/../share/cmake
  265. cMakeRoot += "/share/CMake";
  266. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  267. }
  268. #ifdef CMAKE_ROOT_DIR
  269. if (!cmSystemTools::FileExists(modules.c_str()))
  270. {
  271. // try compiled in root directory
  272. cMakeRoot = CMAKE_ROOT_DIR;
  273. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  274. }
  275. #endif
  276. #ifdef CMAKE_PREFIX
  277. if (!cmSystemTools::FileExists(modules.c_str()))
  278. {
  279. // try compiled in install prefix
  280. cMakeRoot = CMAKE_PREFIX "/share/CMake";
  281. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  282. }
  283. #endif
  284. if (!cmSystemTools::FileExists(modules.c_str()))
  285. {
  286. // try
  287. cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str());
  288. cMakeRoot += "/share/CMake";
  289. modules = cMakeRoot + "/Modules/FindVTK.cmake";
  290. }
  291. if (!cmSystemTools::FileExists(modules.c_str()))
  292. {
  293. // couldn't find modules
  294. cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n",
  295. "Modules directory not in directory:\n",
  296. modules.c_str());
  297. return;
  298. }
  299. cmCacheManager::GetInstance()->AddCacheEntry
  300. ("CMAKE_ROOT", cMakeRoot.c_str(),
  301. "Path to CMake installation.", cmCacheManager::INTERNAL);
  302. }
  303. int cmake::Generate(const std::vector<std::string>& args, bool buildMakefiles)
  304. {
  305. if(args.size() == 1 && !cmSystemTools::FileExists("CMakeLists.txt"))
  306. {
  307. this->Usage(args[0].c_str());
  308. return -1;
  309. }
  310. // look for obvious request for help
  311. for(unsigned int i=1; i < args.size(); ++i)
  312. {
  313. std::string arg = args[i];
  314. if(arg.find("-help",0) != std::string::npos ||
  315. arg.find("--help",0) != std::string::npos ||
  316. arg.find("/?",0) != std::string::npos ||
  317. arg.find("-usage",0) != std::string::npos)
  318. {
  319. this->Usage(args[0].c_str());
  320. return -1;
  321. }
  322. }
  323. // Create a makefile
  324. cmMakefile mf;
  325. // extract the directory arguments, could create a Generator
  326. this->SetArgs(mf, args);
  327. // Read and parse the input makefile
  328. mf.MakeStartDirectoriesCurrent();
  329. cmCacheManager::GetInstance()->LoadCache(&mf);
  330. // extract command line arguments that might add cache entries
  331. this->SetCacheArgs(mf, args);
  332. // no generator specified on the command line
  333. if(!mf.GetMakefileGenerator())
  334. {
  335. cmMakefileGenerator* gen;
  336. const char* genName = mf.GetDefinition("CMAKE_GENERATOR");
  337. if(genName)
  338. {
  339. gen = cmMakefileGenerator::CreateGenerator(genName);
  340. }
  341. else
  342. {
  343. #if defined(__BORLANDC__)
  344. gen = new cmBorlandMakefileGenerator;
  345. #elif defined(_WIN32) && !defined(__CYGWIN__)
  346. gen = new cmMSProjectGenerator;
  347. #else
  348. gen = new cmUnixMakefileGenerator;
  349. #endif
  350. }
  351. if(!gen)
  352. {
  353. cmSystemTools::Error("Could not create generator");
  354. return -1;
  355. }
  356. mf.SetMakefileGenerator(gen);
  357. // add the
  358. }
  359. cmMakefileGenerator* gen = mf.GetMakefileGenerator();
  360. gen->SetLocal(m_Local);
  361. if(!mf.GetDefinition("CMAKE_GENERATOR"))
  362. {
  363. mf.AddCacheDefinition("CMAKE_GENERATOR",
  364. gen->GetName(),
  365. "Name of generator.",
  366. cmCacheManager::INTERNAL);
  367. }
  368. // setup CMAKE_ROOT and CMAKE_COMMAND
  369. this->AddCMakePaths(args);
  370. // compute system info
  371. gen->ComputeSystemInfo();
  372. std::string lf = mf.GetStartDirectory();
  373. lf += "/CMakeLists.txt";
  374. if(!mf.ReadListFile(lf.c_str()))
  375. {
  376. this->Usage(args[0].c_str());
  377. return -1;
  378. }
  379. // if buildMakefiles, then call GenerateMakefile
  380. if(buildMakefiles)
  381. {
  382. mf.GenerateMakefile();
  383. }
  384. else // do not build, but let the commands finalize
  385. {
  386. std::vector<cmMakefile*> makefiles;
  387. mf.FindSubDirectoryCMakeListsFiles(makefiles);
  388. for(std::vector<cmMakefile*>::iterator i = makefiles.begin();
  389. i != makefiles.end(); ++i)
  390. {
  391. cmMakefile* mf = *i;
  392. mf->FinalPass();
  393. delete mf;
  394. }
  395. mf.FinalPass();
  396. }
  397. // Before saving the cache
  398. // if the project did not define one of the entries below, add them now
  399. // so users can edit the values in the cache:
  400. // LIBRARY_OUTPUT_PATH
  401. // EXECUTABLE_OUTPUT_PATH
  402. if(!cmCacheManager::GetInstance()->GetCacheValue("LIBRARY_OUTPUT_PATH"))
  403. {
  404. cmCacheManager::GetInstance()->AddCacheEntry("LIBRARY_OUTPUT_PATH", "",
  405. "Single output directory for building all libraries.",
  406. cmCacheManager::PATH);
  407. }
  408. if(!cmCacheManager::GetInstance()->GetCacheValue("EXECUTABLE_OUTPUT_PATH"))
  409. {
  410. cmCacheManager::GetInstance()->AddCacheEntry("EXECUTABLE_OUTPUT_PATH", "",
  411. "Single output directory for building all executables.",
  412. cmCacheManager::PATH);
  413. }
  414. cmCacheManager::GetInstance()->SaveCache(&mf);
  415. if(m_Verbose)
  416. {
  417. cmCacheManager::GetInstance()->PrintCache(std::cout);
  418. }
  419. if(cmSystemTools::GetErrorOccuredFlag())
  420. {
  421. return -1;
  422. }
  423. return 0;
  424. }