cmGlobalUnixMakefileGenerator3.cxx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator3
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html 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 "cmGlobalUnixMakefileGenerator3.h"
  14. #include "cmLocalUnixMakefileGenerator3.h"
  15. #include "cmMakefile.h"
  16. #include "cmake.h"
  17. #include "cmGeneratedFileStream.h"
  18. cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
  19. {
  20. // This type of makefile always requires unix style paths
  21. m_ForceUnixPaths = true;
  22. m_FindMakeProgramFile = "CMakeUnixFindMake.cmake";
  23. }
  24. void cmGlobalUnixMakefileGenerator3
  25. ::EnableLanguage(std::vector<std::string>const& languages, cmMakefile *mf)
  26. {
  27. mf->AddDefinition("CMAKE_CFG_INTDIR",".");
  28. this->cmGlobalGenerator::EnableLanguage(languages, mf);
  29. std::string path;
  30. for(std::vector<std::string>::const_iterator l = languages.begin();
  31. l != languages.end(); ++l)
  32. {
  33. const char* lang = l->c_str();
  34. std::string langComp = "CMAKE_";
  35. langComp += lang;
  36. langComp += "_COMPILER";
  37. if(!mf->GetDefinition(langComp.c_str()))
  38. {
  39. cmSystemTools::Error(langComp.c_str(), " not set, after EnableLanguage");
  40. continue;
  41. }
  42. const char* cc = mf->GetRequiredDefinition(langComp.c_str());
  43. path = cmSystemTools::FindProgram(cc);
  44. if(path.size() == 0)
  45. {
  46. std::string message = "your ";
  47. message += lang;
  48. message += " compiler: ";
  49. if(cc)
  50. {
  51. message += cc;
  52. }
  53. else
  54. {
  55. message += "(NULL)";
  56. }
  57. message += " was not found in your path. "
  58. "For CMake to correctly use try compile commands, the compiler must "
  59. "be in your path. Please add the compiler to your PATH environment,"
  60. " and re-run CMake.";
  61. cmSystemTools::Error(message.c_str());
  62. }
  63. }
  64. }
  65. ///! Create a local generator appropriate to this Global Generator
  66. cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
  67. {
  68. cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
  69. lg->SetGlobalGenerator(this);
  70. return lg;
  71. }
  72. //----------------------------------------------------------------------------
  73. void cmGlobalUnixMakefileGenerator3::GetDocumentation(cmDocumentationEntry& entry) const
  74. {
  75. entry.name = this->GetName();
  76. entry.brief = "Generates standard UNIX makefiles.";
  77. entry.full =
  78. "A hierarchy of UNIX makefiles is generated into the build tree. Any "
  79. "standard UNIX-style make program can build the project through the "
  80. "default make target. A \"make install\" target is also provided.";
  81. }
  82. //----------------------------------------------------------------------------
  83. void cmGlobalUnixMakefileGenerator3::Generate()
  84. {
  85. // first do superclass method
  86. this->cmGlobalGenerator::Generate();
  87. // write the main makefile
  88. this->WriteMainMakefile();
  89. this->WriteMainCMakefile();
  90. // now write the support Makefiles
  91. this->WriteDependMakefile();
  92. this->WriteBuildMakefile();
  93. this->WriteCleanMakefile();
  94. }
  95. void cmGlobalUnixMakefileGenerator3::WriteMainMakefile()
  96. {
  97. // Open the output file. This should not be copy-if-different
  98. // because the check-build-system step compares the makefile time to
  99. // see if the build system must be regenerated.
  100. std::string makefileName =
  101. this->GetCMakeInstance()->GetHomeOutputDirectory();
  102. makefileName += "/Makefile";
  103. cmGeneratedFileStream makefileStream(makefileName.c_str());
  104. if(!makefileStream)
  105. {
  106. return;
  107. }
  108. // get a local generator for some useful methods
  109. cmLocalUnixMakefileGenerator3 *lg =
  110. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  111. // Write the do not edit header.
  112. lg->WriteDisclaimer(makefileStream);
  113. // Write the main entry point target. This must be the VERY first
  114. // target so that make with no arguments will run it.
  115. // Just depend on the all target to drive the build.
  116. std::vector<std::string> depends;
  117. std::vector<std::string> no_commands;
  118. depends.push_back("all");
  119. // Write the rule.
  120. lg->WriteMakeRule(makefileStream,
  121. "Default target executed when no arguments are "
  122. "given to make.",
  123. "default_target",
  124. depends,
  125. no_commands);
  126. lg->WriteMakeVariables(makefileStream);
  127. lg->WriteSpecialTargetsTop(makefileStream);
  128. this->WriteAllRules(lg,makefileStream);
  129. // write the target convenience rules
  130. unsigned int i;
  131. for (i = 0; i < m_LocalGenerators.size(); ++i)
  132. {
  133. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  134. this->WriteConvenienceRules(makefileStream,lg);
  135. }
  136. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  137. lg->WriteSpecialTargetsBottom(makefileStream);
  138. }
  139. //----------------------------------------------------------------------------
  140. void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
  141. {
  142. // Open the output file. This should not be copy-if-different
  143. // because the check-build-system step compares the makefile time to
  144. // see if the build system must be regenerated.
  145. std::string cmakefileName =
  146. this->GetCMakeInstance()->GetHomeOutputDirectory();
  147. cmakefileName += "/Makefile.cmake";
  148. cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
  149. if(!cmakefileStream)
  150. {
  151. return;
  152. }
  153. std::string makefileName =
  154. this->GetCMakeInstance()->GetHomeOutputDirectory();
  155. makefileName += "/Makefile";
  156. // get a local generator for some useful methods
  157. cmLocalUnixMakefileGenerator3 *lg =
  158. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  159. // Write the do not edit header.
  160. lg->WriteDisclaimer(cmakefileStream);
  161. // Save the generator name
  162. cmakefileStream
  163. << "# The generator used is:\n"
  164. << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
  165. // for each cmMakefile get its list of dependencies
  166. unsigned int i;
  167. std::vector<std::string> lfiles;
  168. for (i = 0; i < m_LocalGenerators.size(); ++i)
  169. {
  170. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  171. // Get the list of files contributing to this generation step.
  172. lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
  173. lg->GetMakefile()->GetListFiles().end());
  174. }
  175. // Sort the list and remove duplicates.
  176. std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
  177. std::vector<std::string>::iterator new_end =
  178. std::unique(lfiles.begin(),lfiles.end());
  179. lfiles.erase(new_end, lfiles.end());
  180. // reset lg to the first makefile
  181. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  182. // Build the path to the cache file.
  183. std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
  184. cache += "/CMakeCache.txt";
  185. // Save the list to the cmake file.
  186. cmakefileStream
  187. << "# The top level Makefile was generated from the following files:\n"
  188. << "SET(CMAKE_MAKEFILE_DEPENDS\n"
  189. << " \"" << lg->ConvertToRelativePath(cache.c_str()).c_str() << "\"\n";
  190. for(std::vector<std::string>::const_iterator i = lfiles.begin();
  191. i != lfiles.end(); ++i)
  192. {
  193. cmakefileStream
  194. << " \"" << lg->ConvertToRelativePath(i->c_str()).c_str()
  195. << "\"\n";
  196. }
  197. cmakefileStream
  198. << " )\n\n";
  199. // Build the path to the cache check file.
  200. std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
  201. check += "/cmake.check_cache";
  202. // Set the corresponding makefile in the cmake file.
  203. cmakefileStream
  204. << "# The corresponding makefile is:\n"
  205. << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
  206. << " \"" << lg->ConvertToRelativePath(makefileName.c_str()).c_str() << "\"\n"
  207. << " \"" << lg->ConvertToRelativePath(check.c_str()).c_str() << "\"\n";
  208. // add in all the directory information files
  209. std::string tmpStr;
  210. for (i = 0; i < m_LocalGenerators.size(); ++i)
  211. {
  212. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  213. tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
  214. tmpStr += "/CMakeDirectoryInformation.cmake";
  215. cmakefileStream
  216. << " \"" << this->ConvertToHomeRelativePath(tmpStr.c_str()).c_str() << "\"\n";
  217. }
  218. cmakefileStream << " )\n\n";
  219. this->WriteMainCMakefileLanguageRules(cmakefileStream);
  220. }
  221. void cmGlobalUnixMakefileGenerator3
  222. ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream)
  223. {
  224. cmLocalUnixMakefileGenerator3 *lg;
  225. // now write all the language stuff
  226. // Set the set of files to check for dependency integrity.
  227. // loop over all of the local generators to collect this
  228. std::set<cmStdString> checkSetLangs;
  229. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  230. {
  231. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  232. std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet =
  233. lg->GetIntegrityCheckSet();
  234. for(std::map<cmStdString,
  235. cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
  236. l = checkSet.begin(); l != checkSet.end(); ++l)
  237. {
  238. checkSetLangs.insert(l->first);
  239. }
  240. }
  241. // list the languages
  242. cmakefileStream
  243. << "# The set of files whose dependency integrity should be checked:\n";
  244. cmakefileStream
  245. << "SET(CMAKE_DEPENDS_LANGUAGES\n";
  246. for(std::set<cmStdString>::iterator
  247. l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
  248. {
  249. cmakefileStream << " \"" << l->c_str() << "\"\n";
  250. }
  251. cmakefileStream << " )\n";
  252. // now list the files for each language
  253. for(std::set<cmStdString>::iterator
  254. l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
  255. {
  256. cmakefileStream
  257. << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n";
  258. // now for each local gen get the checkset
  259. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  260. {
  261. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  262. // get the check set for this local gen and language
  263. cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet =
  264. lg->GetIntegrityCheckSet()[*l];
  265. // for each file
  266. for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator csIter =
  267. iCheckSet.begin();
  268. csIter != iCheckSet.end(); ++csIter)
  269. {
  270. cmakefileStream
  271. << " \"" << this->ConvertToHomeRelativePath(csIter->c_str()).c_str() << "\"\n";
  272. }
  273. }
  274. cmakefileStream << " )\n";
  275. }
  276. }
  277. void cmGlobalUnixMakefileGenerator3::WriteDependMakefile()
  278. {
  279. unsigned int i;
  280. // Open the output file. This should not be copy-if-different
  281. // because the check-build-system step compares the makefile time to
  282. // see if the build system must be regenerated.
  283. std::string makefileName = this->GetCMakeInstance()->GetHomeOutputDirectory();
  284. makefileName += "/depend.make";
  285. cmGeneratedFileStream makefileStream(makefileName.c_str());
  286. if(!makefileStream)
  287. {
  288. return;
  289. }
  290. // get a local generator for some useful methods
  291. cmLocalUnixMakefileGenerator3 *lg =
  292. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  293. // Write the do not edit header.
  294. lg->WriteDisclaimer(makefileStream);
  295. //lg->WriteMakeVariables(makefileStream);
  296. // add the generic dependency
  297. std::vector<std::string> depends;
  298. std::vector<std::string> no_commands;
  299. lg->WriteMakeRule(makefileStream, 0, "depend", depends, no_commands);
  300. // include the build rules
  301. makefileStream
  302. << "# Include make rules for build targets\n";
  303. makefileStream
  304. << lg->GetIncludeDirective() << " "
  305. << lg->ConvertToOutputForExisting("build.make").c_str()
  306. << "\n\n";
  307. // include all the target depends
  308. for (i = 0; i < m_LocalGenerators.size(); ++i)
  309. {
  310. cmLocalUnixMakefileGenerator3 *lg2 =
  311. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  312. // are any parents excluded
  313. bool exclude = false;
  314. cmLocalGenerator *lg3 = lg2;
  315. while (lg3)
  316. {
  317. if (lg3->GetExcludeAll())
  318. {
  319. exclude = true;
  320. break;
  321. }
  322. lg3 = lg3->GetParent();
  323. }
  324. lg2->WriteMainTargetIncludes(makefileStream,"depend.make","depend");
  325. lg2->WriteMainTargetRules(makefileStream,"depend.make","depend",!exclude);
  326. }
  327. }
  328. void cmGlobalUnixMakefileGenerator3::WriteBuildMakefile()
  329. {
  330. unsigned int i;
  331. // Open the output file. This should not be copy-if-different
  332. // because the check-build-system step compares the makefile time to
  333. // see if the build system must be regenerated.
  334. std::string makefileName = this->GetCMakeInstance()->GetHomeOutputDirectory();
  335. makefileName += "/build.make";
  336. cmGeneratedFileStream makefileStream(makefileName.c_str());
  337. if(!makefileStream)
  338. {
  339. return;
  340. }
  341. // get a local generator for some useful methods
  342. cmLocalUnixMakefileGenerator3 *lg =
  343. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  344. // Write the do not edit header.
  345. lg->WriteDisclaimer(makefileStream);
  346. lg->WriteMakeVariables(makefileStream);
  347. // add the generic dependency
  348. std::vector<std::string> depends;
  349. std::vector<std::string> no_commands;
  350. lg->WriteMakeRule(makefileStream, 0, "build", depends, no_commands);
  351. // include all the target depends
  352. for (i = 0; i < m_LocalGenerators.size(); ++i)
  353. {
  354. cmLocalUnixMakefileGenerator3 *lg2 =
  355. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  356. // are any parents excluded
  357. bool exclude = false;
  358. cmLocalGenerator *lg3 = lg2;
  359. while (lg3)
  360. {
  361. if (lg3->GetExcludeAll())
  362. {
  363. exclude = true;
  364. break;
  365. }
  366. lg3 = lg3->GetParent();
  367. }
  368. lg2->WriteMainTargetIncludes(makefileStream,"build.make","build");
  369. lg2->WriteMainTargetRules(makefileStream,"build.make","build",!exclude);
  370. lg2->WriteMainTargetRules(makefileStream,"build.make","requires",!exclude);
  371. }
  372. }
  373. void cmGlobalUnixMakefileGenerator3::WriteCleanMakefile()
  374. {
  375. unsigned int i;
  376. // Open the output file. This should not be copy-if-different
  377. // because the check-build-system step compares the makefile time to
  378. // see if the build system must be regenerated.
  379. std::string makefileName = this->GetCMakeInstance()->GetHomeOutputDirectory();
  380. makefileName += "/clean.make";
  381. cmGeneratedFileStream makefileStream(makefileName.c_str());
  382. if(!makefileStream)
  383. {
  384. return;
  385. }
  386. // get a local generator for some useful methods
  387. cmLocalUnixMakefileGenerator3 *lg =
  388. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  389. // Write the do not edit header.
  390. lg->WriteDisclaimer(makefileStream);
  391. lg->WriteMakeVariables(makefileStream);
  392. // add the generic dependency
  393. std::vector<std::string> depends;
  394. std::vector<std::string> no_commands;
  395. lg->WriteMakeRule(makefileStream, 0, "clean", depends, no_commands);
  396. // include all the target depends
  397. for (i = 0; i < m_LocalGenerators.size(); ++i)
  398. {
  399. cmLocalUnixMakefileGenerator3 *lg2 =
  400. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  401. lg2->WriteMainTargetIncludes(makefileStream,"clean.make","clean");
  402. lg2->WriteMainTargetRules(makefileStream,"clean.make","clean",true);
  403. // add the directory based rules
  404. lg2->WriteLocalCleanRule(makefileStream);
  405. }
  406. }
  407. //----------------------------------------------------------------------------
  408. void cmGlobalUnixMakefileGenerator3
  409. ::WriteAllRules(cmLocalUnixMakefileGenerator3 *lg,
  410. std::ostream& makefileStream)
  411. {
  412. // Write section header.
  413. lg->WriteDivider(makefileStream);
  414. makefileStream
  415. << "# Rules to build dependencies and targets.\n"
  416. << "\n";
  417. std::vector<std::string> depends;
  418. std::vector<std::string> commands;
  419. // Check the build system in this directory.
  420. depends.push_back("cmake_check_build_system");
  421. commands.push_back(lg->GetRecursiveMakeCall("depend.make",0));
  422. commands.push_back(lg->GetRecursiveMakeCall("depend.make","requires"));
  423. commands.push_back(lg->GetRecursiveMakeCall("build.make",0));
  424. // Write the rule.
  425. lg->WriteMakeRule(makefileStream, "The main all target", "all", depends, commands);
  426. // write the clean
  427. commands.clear();
  428. commands.push_back(lg->GetRecursiveMakeCall("clean.make",0));
  429. lg->WriteMakeRule(makefileStream, "default clean target", "clean", depends, commands);
  430. }
  431. //----------------------------------------------------------------------------
  432. void
  433. cmGlobalUnixMakefileGenerator3
  434. ::WriteConvenienceRules(std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
  435. {
  436. std::vector<std::string> depends;
  437. std::vector<std::string> tgt_depends;
  438. std::vector<std::string> commands;
  439. std::string localName;
  440. std::string makeTargetName;
  441. depends.push_back("cmake_check_build_system");
  442. std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  443. dir = this->ConvertToHomeRelativeOutputPath(dir.c_str());
  444. localName = dir;
  445. localName += "/directory";
  446. // write the directory rule
  447. commands.clear();
  448. makeTargetName = dir;
  449. makeTargetName += "/depend";
  450. commands.push_back(lg->GetRecursiveMakeCall("depend.make",makeTargetName.c_str()));
  451. makeTargetName = dir;
  452. makeTargetName += "/requires";
  453. commands.push_back(lg->GetRecursiveMakeCall("depend.make",makeTargetName.c_str()));
  454. makeTargetName = dir;
  455. makeTargetName += "/build";
  456. commands.push_back(lg->GetRecursiveMakeCall("build.make",makeTargetName.c_str()));
  457. // Write the rule.
  458. lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
  459. localName.c_str(), depends, commands);
  460. // for each target Generate the rule files for each target.
  461. const cmTargets& targets = lg->GetMakefile()->GetTargets();
  462. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  463. {
  464. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  465. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  466. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  467. (t->second.GetType() == cmTarget::MODULE_LIBRARY))
  468. {
  469. // Add a rule to build the target by name.
  470. localName = lg->GetRelativeTargetDirectory(t->second);
  471. commands.clear();
  472. makeTargetName = localName;
  473. makeTargetName += "/depend";
  474. commands.push_back(lg->GetRecursiveMakeCall("depend.make",makeTargetName.c_str()));
  475. makeTargetName = localName;
  476. makeTargetName += "/requires";
  477. commands.push_back(lg->GetRecursiveMakeCall("depend.make",makeTargetName.c_str()));
  478. makeTargetName = localName;
  479. makeTargetName += "/build";
  480. commands.push_back(lg->GetRecursiveMakeCall("build.make",makeTargetName.c_str()));
  481. // Write the rule.
  482. lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
  483. localName.c_str(), depends, commands);
  484. // Add a target with the canonical name (no prefix, suffix or path).
  485. if(localName != t->second.GetName())
  486. {
  487. commands.clear();
  488. tgt_depends.clear();
  489. tgt_depends.push_back(localName);
  490. lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
  491. t->second.GetName(), tgt_depends, commands);
  492. }
  493. }
  494. }
  495. }