cmGlobalUnixMakefileGenerator3.cxx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  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->WriteBuildMakefile();
  92. this->WriteCleanMakefile();
  93. }
  94. void cmGlobalUnixMakefileGenerator3::WriteMainMakefile()
  95. {
  96. // Open the output file. This should not be copy-if-different
  97. // because the check-build-system step compares the makefile time to
  98. // see if the build system must be regenerated.
  99. std::string makefileName =
  100. this->GetCMakeInstance()->GetHomeOutputDirectory();
  101. makefileName += "/Makefile";
  102. cmGeneratedFileStream makefileStream(makefileName.c_str());
  103. if(!makefileStream)
  104. {
  105. return;
  106. }
  107. // get a local generator for some useful methods
  108. cmLocalUnixMakefileGenerator3 *lg =
  109. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  110. // Write the do not edit header.
  111. lg->WriteDisclaimer(makefileStream);
  112. // Write the main entry point target. This must be the VERY first
  113. // target so that make with no arguments will run it.
  114. // Just depend on the all target to drive the build.
  115. std::vector<std::string> depends;
  116. std::vector<std::string> no_commands;
  117. depends.push_back("all");
  118. // Write the rule.
  119. lg->WriteMakeRule(makefileStream,
  120. "Default target executed when no arguments are "
  121. "given to make.",
  122. "default_target",
  123. depends,
  124. no_commands);
  125. lg->WriteMakeVariables(makefileStream);
  126. lg->WriteSpecialTargetsTop(makefileStream);
  127. this->WriteAllRules(lg,makefileStream);
  128. // write the target convenience rules
  129. unsigned int i;
  130. for (i = 0; i < m_LocalGenerators.size(); ++i)
  131. {
  132. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  133. // are any parents excluded
  134. bool exclude = false;
  135. cmLocalGenerator *lg3 = lg;
  136. while (lg3)
  137. {
  138. if (lg3->GetExcludeAll())
  139. {
  140. exclude = true;
  141. break;
  142. }
  143. lg3 = lg3->GetParent();
  144. }
  145. this->WriteConvenienceRules(makefileStream,lg,exclude);
  146. }
  147. this->WriteHelpRule(makefileStream);
  148. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  149. lg->WriteSpecialTargetsBottom(makefileStream);
  150. }
  151. //----------------------------------------------------------------------------
  152. void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
  153. {
  154. // Open the output file. This should not be copy-if-different
  155. // because the check-build-system step compares the makefile time to
  156. // see if the build system must be regenerated.
  157. std::string cmakefileName =
  158. this->GetCMakeInstance()->GetHomeOutputDirectory();
  159. cmakefileName += "/Makefile.cmake";
  160. cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
  161. if(!cmakefileStream)
  162. {
  163. return;
  164. }
  165. std::string makefileName =
  166. this->GetCMakeInstance()->GetHomeOutputDirectory();
  167. makefileName += "/Makefile";
  168. // get a local generator for some useful methods
  169. cmLocalUnixMakefileGenerator3 *lg =
  170. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  171. // Write the do not edit header.
  172. lg->WriteDisclaimer(cmakefileStream);
  173. // Save the generator name
  174. cmakefileStream
  175. << "# The generator used is:\n"
  176. << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
  177. // for each cmMakefile get its list of dependencies
  178. std::vector<std::string> lfiles;
  179. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  180. {
  181. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  182. // Get the list of files contributing to this generation step.
  183. lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
  184. lg->GetMakefile()->GetListFiles().end());
  185. }
  186. // Sort the list and remove duplicates.
  187. std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
  188. std::vector<std::string>::iterator new_end =
  189. std::unique(lfiles.begin(),lfiles.end());
  190. lfiles.erase(new_end, lfiles.end());
  191. // reset lg to the first makefile
  192. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  193. // Build the path to the cache file.
  194. std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
  195. cache += "/CMakeCache.txt";
  196. // Save the list to the cmake file.
  197. cmakefileStream
  198. << "# The top level Makefile was generated from the following files:\n"
  199. << "SET(CMAKE_MAKEFILE_DEPENDS\n"
  200. << " \"" << lg->ConvertToRelativePath(cache.c_str()).c_str() << "\"\n";
  201. for(std::vector<std::string>::const_iterator i = lfiles.begin();
  202. i != lfiles.end(); ++i)
  203. {
  204. cmakefileStream
  205. << " \"" << lg->ConvertToRelativePath(i->c_str()).c_str()
  206. << "\"\n";
  207. }
  208. cmakefileStream
  209. << " )\n\n";
  210. // Build the path to the cache check file.
  211. std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
  212. check += "/cmake.check_cache";
  213. // Set the corresponding makefile in the cmake file.
  214. cmakefileStream
  215. << "# The corresponding makefile is:\n"
  216. << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
  217. << " \"" << lg->ConvertToRelativePath(makefileName.c_str()).c_str() << "\"\n"
  218. << " \"" << lg->ConvertToRelativePath(check.c_str()).c_str() << "\"\n";
  219. // add in all the directory information files
  220. std::string tmpStr;
  221. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  222. {
  223. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  224. tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
  225. tmpStr += "/CMakeDirectoryInformation.cmake";
  226. cmakefileStream << " \"" <<
  227. lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() << "\"\n";
  228. }
  229. cmakefileStream << " )\n\n";
  230. this->WriteMainCMakefileLanguageRules(cmakefileStream);
  231. }
  232. void cmGlobalUnixMakefileGenerator3
  233. ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream)
  234. {
  235. cmLocalUnixMakefileGenerator3 *lg;
  236. // now write all the language stuff
  237. // Set the set of files to check for dependency integrity.
  238. // loop over all of the local generators to collect this
  239. std::set<cmStdString> checkSetLangs;
  240. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  241. {
  242. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  243. std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet =
  244. lg->GetIntegrityCheckSet();
  245. for(std::map<cmStdString,
  246. cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
  247. l = checkSet.begin(); l != checkSet.end(); ++l)
  248. {
  249. checkSetLangs.insert(l->first);
  250. }
  251. }
  252. // list the languages
  253. cmakefileStream
  254. << "# The set of files whose dependency integrity should be checked:\n";
  255. cmakefileStream
  256. << "SET(CMAKE_DEPENDS_LANGUAGES\n";
  257. for(std::set<cmStdString>::iterator
  258. l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
  259. {
  260. cmakefileStream << " \"" << l->c_str() << "\"\n";
  261. }
  262. cmakefileStream << " )\n";
  263. // now list the files for each language
  264. for(std::set<cmStdString>::iterator
  265. l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
  266. {
  267. cmakefileStream
  268. << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n";
  269. // now for each local gen get the checkset
  270. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  271. {
  272. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  273. // get the check set for this local gen and language
  274. cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet =
  275. lg->GetIntegrityCheckSet()[*l];
  276. // for each file
  277. for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator csIter =
  278. iCheckSet.begin();
  279. csIter != iCheckSet.end(); ++csIter)
  280. {
  281. cmakefileStream << " \"" <<
  282. lg->Convert(csIter->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() << "\"\n";
  283. }
  284. }
  285. cmakefileStream << " )\n";
  286. }
  287. }
  288. void cmGlobalUnixMakefileGenerator3::WriteBuildMakefile()
  289. {
  290. unsigned int i;
  291. // Open the output file. This should not be copy-if-different
  292. // because the check-build-system step compares the makefile time to
  293. // see if the build system must be regenerated.
  294. std::string makefileName = this->GetCMakeInstance()->GetHomeOutputDirectory();
  295. makefileName += "/build.make";
  296. cmGeneratedFileStream makefileStream(makefileName.c_str());
  297. if(!makefileStream)
  298. {
  299. return;
  300. }
  301. // get a local generator for some useful methods
  302. cmLocalUnixMakefileGenerator3 *lg =
  303. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  304. // Write the do not edit header.
  305. lg->WriteDisclaimer(makefileStream);
  306. lg->WriteMakeVariables(makefileStream);
  307. // add the generic dependency
  308. std::vector<std::string> depends;
  309. std::vector<std::string> no_commands;
  310. lg->WriteMakeRule(makefileStream, 0, "build", depends, no_commands);
  311. lg->WriteMakeRule(makefileStream, 0, "depend", depends, no_commands);
  312. lg->WriteMakeRule(makefileStream, 0, "requires", depends, no_commands);
  313. // include all the target depends
  314. for (i = 0; i < m_LocalGenerators.size(); ++i)
  315. {
  316. cmLocalUnixMakefileGenerator3 *lg2 =
  317. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  318. // are any parents excluded
  319. bool exclude = false;
  320. cmLocalGenerator *lg3 = lg2;
  321. while (lg3)
  322. {
  323. if (lg3->GetExcludeAll())
  324. {
  325. exclude = true;
  326. break;
  327. }
  328. lg3 = lg3->GetParent();
  329. }
  330. lg2->WriteMainTargetIncludes(makefileStream,"build.make","build");
  331. lg2->WriteMainTargetRules(makefileStream,"build.make","depend",!exclude);
  332. lg2->WriteMainTargetRules(makefileStream,"build.make","requires",!exclude);
  333. lg2->WriteMainTargetRules(makefileStream,"build.make","build",!exclude);
  334. }
  335. }
  336. void cmGlobalUnixMakefileGenerator3::WriteCleanMakefile()
  337. {
  338. unsigned int i;
  339. // Open the output file. This should not be copy-if-different
  340. // because the check-build-system step compares the makefile time to
  341. // see if the build system must be regenerated.
  342. std::string makefileName = this->GetCMakeInstance()->GetHomeOutputDirectory();
  343. makefileName += "/clean.make";
  344. cmGeneratedFileStream makefileStream(makefileName.c_str());
  345. if(!makefileStream)
  346. {
  347. return;
  348. }
  349. // get a local generator for some useful methods
  350. cmLocalUnixMakefileGenerator3 *lg =
  351. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  352. // Write the do not edit header.
  353. lg->WriteDisclaimer(makefileStream);
  354. lg->WriteMakeVariables(makefileStream);
  355. // add the generic dependency
  356. std::vector<std::string> depends;
  357. std::vector<std::string> no_commands;
  358. lg->WriteMakeRule(makefileStream, 0, "clean", depends, no_commands);
  359. // include all the target depends
  360. for (i = 0; i < m_LocalGenerators.size(); ++i)
  361. {
  362. cmLocalUnixMakefileGenerator3 *lg2 =
  363. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  364. lg2->WriteMainTargetIncludes(makefileStream,"clean.make","clean");
  365. lg2->WriteMainTargetRules(makefileStream,"clean.make","clean",true);
  366. // add the directory based rules
  367. lg2->WriteLocalCleanRule(makefileStream);
  368. }
  369. }
  370. //----------------------------------------------------------------------------
  371. void cmGlobalUnixMakefileGenerator3
  372. ::WriteAllRules(cmLocalUnixMakefileGenerator3 *lg,
  373. std::ostream& makefileStream)
  374. {
  375. // Write section header.
  376. lg->WriteDivider(makefileStream);
  377. makefileStream
  378. << "# Rules to build dependencies and targets.\n"
  379. << "\n";
  380. std::vector<std::string> depends;
  381. std::vector<std::string> commands;
  382. // Check the build system in this directory.
  383. depends.push_back("cmake_check_build_system");
  384. commands.push_back(lg->GetRecursiveMakeCall("Makefile","all/all"));
  385. // Write the rule.
  386. lg->WriteMakeRule(makefileStream, "The main all target", "all", depends, commands);
  387. // Write and empty all/all:
  388. commands.clear();
  389. lg->WriteMakeRule(makefileStream, "The main recursive all target", "all/all",
  390. commands, commands);
  391. // write the clean
  392. commands.push_back(lg->GetRecursiveMakeCall("clean.make",0));
  393. lg->WriteMakeRule(makefileStream, "default clean target", "clean", depends, commands);
  394. }
  395. //----------------------------------------------------------------------------
  396. void
  397. cmGlobalUnixMakefileGenerator3
  398. ::WriteConvenienceRules(std::ostream& ruleFileStream,
  399. cmLocalUnixMakefileGenerator3 *lg,
  400. bool exclude)
  401. {
  402. std::vector<std::string> depends;
  403. std::vector<std::string> commands;
  404. std::string localName;
  405. std::string makeTargetName;
  406. depends.push_back("cmake_check_build_system");
  407. if (lg->GetParent())
  408. {
  409. std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  410. dir = lg->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
  411. localName = dir;
  412. localName += "/directorystart";
  413. makeTargetName = dir;
  414. makeTargetName += "/directory";
  415. std::vector<std::string> all_tgts;
  416. // for all of out targets
  417. for (cmTargets::const_iterator l = lg->GetMakefile()->GetTargets().begin();
  418. l != lg->GetMakefile()->GetTargets().end(); l++)
  419. {
  420. if((l->second.GetType() == cmTarget::EXECUTABLE) ||
  421. (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  422. (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  423. (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  424. (l->second.GetType() == cmTarget::UTILITY))
  425. {
  426. // Add this to the list of depends rules in this directory.
  427. if(l->second.IsInAll())
  428. {
  429. std::string tname = lg->GetRelativeTargetDirectory(l->second);
  430. tname += "/all";
  431. all_tgts.push_back(tname);
  432. }
  433. }
  434. }
  435. // write the directory rule add in the subdirs
  436. std::vector<cmLocalGenerator *> subdirs = lg->GetChildren();
  437. // for each subdir add the directory depend
  438. std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
  439. for (; sdi != subdirs.end(); ++sdi)
  440. {
  441. cmLocalUnixMakefileGenerator3 * lg2 =
  442. static_cast<cmLocalUnixMakefileGenerator3 *>(*sdi);
  443. dir = lg2->GetMakefile()->GetStartOutputDirectory();
  444. dir += "/directory";
  445. dir = lg2->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,
  446. cmLocalGenerator::MAKEFILE);
  447. all_tgts.push_back(dir);
  448. }
  449. // write the directory rule
  450. commands.clear();
  451. commands.push_back(lg->GetRecursiveMakeCall("Makefile",makeTargetName.c_str()));
  452. // Write the rule.
  453. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
  454. localName.c_str(), depends, commands);
  455. // Write the rule.
  456. commands.clear();
  457. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
  458. makeTargetName.c_str(), all_tgts, commands);
  459. }
  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. (t->second.GetType() == cmTarget::UTILITY))
  469. {
  470. // Add a rule to build the target by name.
  471. localName = lg->GetRelativeTargetDirectory(t->second);
  472. std::string makefileName = localName;
  473. makefileName += "/build.make";
  474. commands.clear();
  475. if (t->second.GetType() != cmTarget::UTILITY)
  476. {
  477. makeTargetName = localName;
  478. makeTargetName += "/depend";
  479. commands.push_back(lg->GetRecursiveMakeCall(makefileName.c_str(),
  480. makeTargetName.c_str()));
  481. makeTargetName = localName;
  482. makeTargetName += "/requires";
  483. commands.push_back(lg->GetRecursiveMakeCall(makefileName.c_str(),
  484. makeTargetName.c_str()));
  485. }
  486. makeTargetName = localName;
  487. makeTargetName += "/build";
  488. commands.push_back(lg->GetRecursiveMakeCall(makefileName.c_str(),
  489. makeTargetName.c_str()));
  490. // Write the rule.
  491. localName += "/all";
  492. depends.clear();
  493. this->AppendGlobalTargetDepends(depends,t->second);
  494. lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
  495. localName.c_str(), depends, commands);
  496. // add the all/all dependency
  497. if (!exclude && t->second.IsInAll())
  498. {
  499. depends.clear();
  500. depends.push_back(localName);
  501. commands.clear();
  502. lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
  503. "all/all", depends, commands);
  504. }
  505. // Write the rule.
  506. commands.clear();
  507. commands.push_back(lg->GetRecursiveMakeCall("Makefile",localName.c_str()));
  508. depends.clear();
  509. depends.push_back("cmake_check_build_system");
  510. localName = lg->GetRelativeTargetDirectory(t->second);
  511. lg->WriteMakeRule(ruleFileStream, "Build rule for subir invocation for target.",
  512. localName.c_str(), depends, commands);
  513. // Add a target with the canonical name (no prefix, suffix or path).
  514. commands.clear();
  515. depends.clear();
  516. depends.push_back(localName);
  517. lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
  518. t->second.GetName(), depends, commands);
  519. }
  520. }
  521. }
  522. //----------------------------------------------------------------------------
  523. void
  524. cmGlobalUnixMakefileGenerator3
  525. ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
  526. const cmTarget& target)
  527. {
  528. // Keep track of dependencies already listed.
  529. std::set<cmStdString> emitted;
  530. // A target should not depend on itself.
  531. emitted.insert(target.GetName());
  532. // Loop over all library dependencies but not for static libs
  533. if (target.GetType() != cmTarget::STATIC_LIBRARY)
  534. {
  535. const cmTarget::LinkLibraries& tlibs = target.GetLinkLibraries();
  536. for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
  537. lib != tlibs.end(); ++lib)
  538. {
  539. // Don't emit the same library twice for this target.
  540. if(emitted.insert(lib->first).second)
  541. {
  542. // Add this dependency.
  543. this->AppendAnyGlobalDepend(depends, lib->first.c_str());
  544. }
  545. }
  546. }
  547. // Loop over all utility dependencies.
  548. const std::set<cmStdString>& tutils = target.GetUtilities();
  549. for(std::set<cmStdString>::const_iterator util = tutils.begin();
  550. util != tutils.end(); ++util)
  551. {
  552. // Don't emit the same utility twice for this target.
  553. if(emitted.insert(*util).second)
  554. {
  555. // Add this dependency.
  556. this->AppendAnyGlobalDepend(depends, util->c_str());
  557. }
  558. }
  559. }
  560. //----------------------------------------------------------------------------
  561. void
  562. cmGlobalUnixMakefileGenerator3
  563. ::AppendAnyGlobalDepend(std::vector<std::string>& depends, const char* name)
  564. {
  565. cmTarget *result;
  566. // search each local generator until a match is found
  567. unsigned int i;
  568. for (i = 0; i < m_LocalGenerators.size(); ++i)
  569. {
  570. // search all targets
  571. result = m_LocalGenerators[i]->GetMakefile()->FindTarget(name);
  572. // if a match was found then ...
  573. if (result)
  574. {
  575. cmLocalUnixMakefileGenerator3 *lg3 =
  576. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  577. std::string tgtName = lg3->GetRelativeTargetDirectory(*result);
  578. tgtName += "/all";
  579. depends.push_back(tgtName);
  580. return;
  581. }
  582. }
  583. }
  584. //----------------------------------------------------------------------------
  585. void
  586. cmGlobalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream)
  587. {
  588. cmLocalUnixMakefileGenerator3 *lg =
  589. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  590. // add the help target
  591. std::string path;
  592. std::vector<std::string> no_depends;
  593. std::vector<std::string> commands;
  594. lg->AppendEcho(commands,
  595. "The following are some of the valid targets for this Makefile:");
  596. lg->AppendEcho(commands,"... all (the default if no target is provided)");
  597. lg->AppendEcho(commands,"... clean");
  598. lg->AppendEcho(commands,"... depend");
  599. lg->AppendEcho(commands,"... install");
  600. lg->AppendEcho(commands,"... rebuild_cache");
  601. // for each local generator
  602. unsigned int i;
  603. for (i = 0; i < m_LocalGenerators.size(); ++i)
  604. {
  605. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  606. // for each target Generate the rule files for each target.
  607. const cmTargets& targets = lg->GetMakefile()->GetTargets();
  608. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  609. {
  610. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  611. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  612. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  613. (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  614. (t->second.GetType() == cmTarget::UTILITY))
  615. {
  616. path = "... ";
  617. path += t->second.GetName();
  618. lg->AppendEcho(commands,path.c_str());
  619. }
  620. }
  621. }
  622. lg->WriteMakeRule(ruleFileStream, "Help Target",
  623. "help:",
  624. no_depends, commands);
  625. ruleFileStream << "\n\n";
  626. }