cmGlobalUnixMakefileGenerator3.cxx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  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->WriteMainMakefile2();
  90. this->WriteMainCMakefile();
  91. }
  92. void cmGlobalUnixMakefileGenerator3::WriteMainMakefile()
  93. {
  94. // Open the output file. This should not be copy-if-different
  95. // because the check-build-system step compares the makefile time to
  96. // see if the build system must be regenerated.
  97. std::string makefileName =
  98. this->GetCMakeInstance()->GetHomeOutputDirectory();
  99. makefileName += "/Makefile";
  100. cmGeneratedFileStream makefileStream(makefileName.c_str());
  101. if(!makefileStream)
  102. {
  103. return;
  104. }
  105. // get a local generator for some useful methods
  106. cmLocalUnixMakefileGenerator3 *lg =
  107. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  108. // Write the do not edit header.
  109. lg->WriteDisclaimer(makefileStream);
  110. // Write the main entry point target. This must be the VERY first
  111. // target so that make with no arguments will run it.
  112. // Just depend on the all target to drive the build.
  113. std::vector<std::string> depends;
  114. std::vector<std::string> no_commands;
  115. depends.push_back("all");
  116. // Write the rule.
  117. lg->WriteMakeRule(makefileStream,
  118. "Default target executed when no arguments are "
  119. "given to make.",
  120. "default_target",
  121. depends,
  122. no_commands);
  123. lg->WriteMakeVariables(makefileStream);
  124. lg->WriteSpecialTargetsTop(makefileStream);
  125. this->WriteAllRules(lg,makefileStream);
  126. // Keep track of targets already listed.
  127. std::set<cmStdString> emittedTargets;
  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. this->WriteConvenienceRules(makefileStream,lg,emittedTargets);
  134. }
  135. // add a help target as long as there isn;t a real target named help
  136. if(emittedTargets.insert("help").second)
  137. {
  138. this->WriteHelpRule(makefileStream);
  139. }
  140. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  141. lg->WriteSpecialTargetsBottom(makefileStream);
  142. }
  143. void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
  144. {
  145. // Open the output file. This should not be copy-if-different
  146. // because the check-build-system step compares the makefile time to
  147. // see if the build system must be regenerated.
  148. std::string makefileName =
  149. this->GetCMakeInstance()->GetHomeOutputDirectory();
  150. makefileName += "/Makefile2";
  151. cmGeneratedFileStream makefileStream(makefileName.c_str());
  152. if(!makefileStream)
  153. {
  154. return;
  155. }
  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(makefileStream);
  161. // Write the main entry point target. This must be the VERY first
  162. // target so that make with no arguments will run it.
  163. // Just depend on the all target to drive the build.
  164. std::vector<std::string> depends;
  165. std::vector<std::string> no_commands;
  166. depends.push_back("all");
  167. // Write the rule.
  168. lg->WriteMakeRule(makefileStream,
  169. "Default target executed when no arguments are "
  170. "given to make.",
  171. "default_target",
  172. depends,
  173. no_commands);
  174. // Write and empty all:
  175. lg->WriteMakeRule(makefileStream,
  176. "The main recursive all target", "all",
  177. no_commands, no_commands);
  178. lg->WriteMakeVariables(makefileStream);
  179. // write the target convenience rules
  180. unsigned int i;
  181. for (i = 0; i < m_LocalGenerators.size(); ++i)
  182. {
  183. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  184. // are any parents excluded
  185. bool exclude = false;
  186. cmLocalGenerator *lg3 = lg;
  187. while (lg3)
  188. {
  189. if (lg3->GetExcludeAll())
  190. {
  191. exclude = true;
  192. break;
  193. }
  194. lg3 = lg3->GetParent();
  195. }
  196. this->WriteConvenienceRules2(makefileStream,lg,exclude);
  197. }
  198. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  199. lg->WriteSpecialTargetsBottom(makefileStream);
  200. }
  201. //----------------------------------------------------------------------------
  202. void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
  203. {
  204. // Open the output file. This should not be copy-if-different
  205. // because the check-build-system step compares the makefile time to
  206. // see if the build system must be regenerated.
  207. std::string cmakefileName =
  208. this->GetCMakeInstance()->GetHomeOutputDirectory();
  209. cmakefileName += "/Makefile.cmake";
  210. cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
  211. if(!cmakefileStream)
  212. {
  213. return;
  214. }
  215. std::string makefileName =
  216. this->GetCMakeInstance()->GetHomeOutputDirectory();
  217. makefileName += "/Makefile";
  218. // get a local generator for some useful methods
  219. cmLocalUnixMakefileGenerator3 *lg =
  220. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  221. // Write the do not edit header.
  222. lg->WriteDisclaimer(cmakefileStream);
  223. // Save the generator name
  224. cmakefileStream
  225. << "# The generator used is:\n"
  226. << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
  227. // for each cmMakefile get its list of dependencies
  228. std::vector<std::string> lfiles;
  229. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  230. {
  231. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  232. // Get the list of files contributing to this generation step.
  233. lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
  234. lg->GetMakefile()->GetListFiles().end());
  235. }
  236. // Sort the list and remove duplicates.
  237. std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
  238. std::vector<std::string>::iterator new_end =
  239. std::unique(lfiles.begin(),lfiles.end());
  240. lfiles.erase(new_end, lfiles.end());
  241. // reset lg to the first makefile
  242. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  243. // Build the path to the cache file.
  244. std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
  245. cache += "/CMakeCache.txt";
  246. // Save the list to the cmake file.
  247. cmakefileStream
  248. << "# The top level Makefile was generated from the following files:\n"
  249. << "SET(CMAKE_MAKEFILE_DEPENDS\n"
  250. << " \"" << lg->ConvertToRelativePath(cache.c_str()).c_str() << "\"\n";
  251. for(std::vector<std::string>::const_iterator i = lfiles.begin();
  252. i != lfiles.end(); ++i)
  253. {
  254. cmakefileStream
  255. << " \"" << lg->ConvertToRelativePath(i->c_str()).c_str()
  256. << "\"\n";
  257. }
  258. cmakefileStream
  259. << " )\n\n";
  260. // Build the path to the cache check file.
  261. std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
  262. check += "/cmake.check_cache";
  263. // Set the corresponding makefile in the cmake file.
  264. cmakefileStream
  265. << "# The corresponding makefile is:\n"
  266. << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
  267. << " \"" << lg->ConvertToRelativePath(makefileName.c_str()).c_str() << "\"\n"
  268. << " \"" << lg->ConvertToRelativePath(check.c_str()).c_str() << "\"\n";
  269. // add in all the directory information files
  270. std::string tmpStr;
  271. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  272. {
  273. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  274. tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
  275. tmpStr += "/CMakeDirectoryInformation.cmake";
  276. cmakefileStream << " \"" <<
  277. lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() << "\"\n";
  278. }
  279. cmakefileStream << " )\n\n";
  280. this->WriteMainCMakefileLanguageRules(cmakefileStream);
  281. }
  282. void cmGlobalUnixMakefileGenerator3
  283. ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream)
  284. {
  285. cmLocalUnixMakefileGenerator3 *lg;
  286. // now write all the language stuff
  287. // Set the set of files to check for dependency integrity.
  288. // loop over all of the local generators to collect this
  289. std::set<cmStdString> checkSetLangs;
  290. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  291. {
  292. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  293. std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet =
  294. lg->GetIntegrityCheckSet();
  295. for(std::map<cmStdString,
  296. cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
  297. l = checkSet.begin(); l != checkSet.end(); ++l)
  298. {
  299. checkSetLangs.insert(l->first);
  300. }
  301. }
  302. // list the languages
  303. cmakefileStream
  304. << "# The set of files whose dependency integrity should be checked:\n";
  305. cmakefileStream
  306. << "SET(CMAKE_DEPENDS_LANGUAGES\n";
  307. for(std::set<cmStdString>::iterator
  308. l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
  309. {
  310. cmakefileStream << " \"" << l->c_str() << "\"\n";
  311. }
  312. cmakefileStream << " )\n";
  313. // now list the files for each language
  314. for(std::set<cmStdString>::iterator
  315. l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
  316. {
  317. cmakefileStream
  318. << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n";
  319. // now for each local gen get the checkset
  320. for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
  321. {
  322. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  323. // get the check set for this local gen and language
  324. cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet =
  325. lg->GetIntegrityCheckSet()[*l];
  326. // for each file
  327. for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator csIter =
  328. iCheckSet.begin();
  329. csIter != iCheckSet.end(); ++csIter)
  330. {
  331. cmakefileStream << " \"" <<
  332. lg->Convert(csIter->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() << "\"\n";
  333. }
  334. }
  335. cmakefileStream << " )\n";
  336. }
  337. }
  338. //----------------------------------------------------------------------------
  339. void cmGlobalUnixMakefileGenerator3
  340. ::WriteAllRules(cmLocalUnixMakefileGenerator3 *lg,
  341. std::ostream& makefileStream)
  342. {
  343. // Write section header.
  344. lg->WriteDivider(makefileStream);
  345. makefileStream
  346. << "# Rules to build dependencies and targets.\n"
  347. << "\n";
  348. std::vector<std::string> depends;
  349. std::vector<std::string> commands;
  350. // Check the build system in this directory.
  351. depends.push_back("cmake_check_build_system");
  352. commands.push_back(lg->GetRecursiveMakeCall("Makefile2","all"));
  353. // Write the rule.
  354. lg->WriteMakeRule(makefileStream, "The main all target", "all", depends, commands);
  355. // write the clean
  356. depends.clear();
  357. commands.clear();
  358. commands.push_back(lg->GetRecursiveMakeCall("Makefile2","clean"));
  359. lg->WriteMakeRule(makefileStream, "The main clean target", "clean",
  360. depends, commands);
  361. }
  362. //----------------------------------------------------------------------------
  363. void
  364. cmGlobalUnixMakefileGenerator3
  365. ::WriteDirectoryRules(std::ostream& ruleFileStream,
  366. cmLocalUnixMakefileGenerator3 *lg)
  367. {
  368. std::vector<std::string> depends;
  369. std::vector<std::string> commands;
  370. std::string localName;
  371. std::string makeTargetName;
  372. depends.push_back("cmake_check_build_system");
  373. if (lg->GetParent())
  374. {
  375. std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  376. dir = lg->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
  377. lg->WriteDivider(ruleFileStream);
  378. ruleFileStream
  379. << "# Directory level rules for directory "
  380. << dir << "\n\n";
  381. localName = dir;
  382. localName += "/directorystart";
  383. makeTargetName = dir;
  384. makeTargetName += "/directory";
  385. std::vector<std::string> all_tgts;
  386. // for all of out targets
  387. for (cmTargets::const_iterator l = lg->GetMakefile()->GetTargets().begin();
  388. l != lg->GetMakefile()->GetTargets().end(); l++)
  389. {
  390. if((l->second.GetType() == cmTarget::EXECUTABLE) ||
  391. (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  392. (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  393. (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  394. (l->second.GetType() == cmTarget::UTILITY))
  395. {
  396. // Add this to the list of depends rules in this directory.
  397. if(l->second.IsInAll())
  398. {
  399. std::string tname = lg->GetRelativeTargetDirectory(l->second);
  400. tname += "/all";
  401. all_tgts.push_back(tname);
  402. }
  403. }
  404. }
  405. // write the directory rule add in the subdirs
  406. std::vector<cmLocalGenerator *> subdirs = lg->GetChildren();
  407. // for each subdir add the directory depend
  408. std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
  409. for (; sdi != subdirs.end(); ++sdi)
  410. {
  411. cmLocalUnixMakefileGenerator3 * lg2 =
  412. static_cast<cmLocalUnixMakefileGenerator3 *>(*sdi);
  413. dir = lg2->GetMakefile()->GetStartOutputDirectory();
  414. dir += "/directory";
  415. dir = lg2->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,
  416. cmLocalGenerator::MAKEFILE);
  417. all_tgts.push_back(dir);
  418. }
  419. // write the directory rule
  420. commands.clear();
  421. commands.push_back
  422. (lg->GetRecursiveMakeCall("Makefile2",makeTargetName.c_str()));
  423. // Write the rule.
  424. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
  425. localName.c_str(), depends, commands);
  426. // Write the rule.
  427. commands.clear();
  428. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
  429. makeTargetName.c_str(), all_tgts, commands);
  430. }
  431. // now do the clean targets
  432. if (lg->GetParent())
  433. {
  434. std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  435. dir = lg->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
  436. makeTargetName = dir;
  437. makeTargetName += "/clean";
  438. std::vector<std::string> all_tgts;
  439. // for all of out targets
  440. for (cmTargets::const_iterator l = lg->GetMakefile()->GetTargets().begin();
  441. l != lg->GetMakefile()->GetTargets().end(); l++)
  442. {
  443. if((l->second.GetType() == cmTarget::EXECUTABLE) ||
  444. (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  445. (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  446. (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  447. (l->second.GetType() == cmTarget::UTILITY))
  448. {
  449. // Add this to the list of depends rules in this directory.
  450. std::string tname = lg->GetRelativeTargetDirectory(l->second);
  451. tname += "/clean";
  452. all_tgts.push_back(tname);
  453. }
  454. }
  455. // write the directory rule add in the subdirs
  456. std::vector<cmLocalGenerator *> subdirs = lg->GetChildren();
  457. // for each subdir add the directory depend
  458. std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
  459. for (; sdi != subdirs.end(); ++sdi)
  460. {
  461. cmLocalUnixMakefileGenerator3 * lg2 =
  462. static_cast<cmLocalUnixMakefileGenerator3 *>(*sdi);
  463. dir = lg2->GetMakefile()->GetStartOutputDirectory();
  464. dir += "/clean";
  465. dir = lg2->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,
  466. cmLocalGenerator::MAKEFILE);
  467. all_tgts.push_back(dir);
  468. }
  469. // write the directory clean rule
  470. commands.clear();
  471. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory clean.",
  472. makeTargetName.c_str(), all_tgts, commands);
  473. }
  474. }
  475. //----------------------------------------------------------------------------
  476. void
  477. cmGlobalUnixMakefileGenerator3
  478. ::WriteDirectoryRules2(std::ostream& ruleFileStream,
  479. cmLocalUnixMakefileGenerator3 *lg)
  480. {
  481. std::vector<std::string> depends;
  482. std::vector<std::string> commands;
  483. std::string localName;
  484. std::string makeTargetName;
  485. depends.push_back("cmake_check_build_system");
  486. if (lg->GetParent())
  487. {
  488. std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  489. dir = lg->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
  490. lg->WriteDivider(ruleFileStream);
  491. ruleFileStream
  492. << "# Directory level rules for directory "
  493. << dir << "\n\n";
  494. localName = dir;
  495. localName += "/directorystart";
  496. makeTargetName = dir;
  497. makeTargetName += "/directory";
  498. std::vector<std::string> all_tgts;
  499. // for all of out targets
  500. for (cmTargets::const_iterator l = lg->GetMakefile()->GetTargets().begin();
  501. l != lg->GetMakefile()->GetTargets().end(); l++)
  502. {
  503. if((l->second.GetType() == cmTarget::EXECUTABLE) ||
  504. (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  505. (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  506. (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  507. (l->second.GetType() == cmTarget::UTILITY))
  508. {
  509. // Add this to the list of depends rules in this directory.
  510. if(l->second.IsInAll())
  511. {
  512. std::string tname = lg->GetRelativeTargetDirectory(l->second);
  513. tname += "/all";
  514. all_tgts.push_back(tname);
  515. }
  516. }
  517. }
  518. // write the directory rule add in the subdirs
  519. std::vector<cmLocalGenerator *> subdirs = lg->GetChildren();
  520. // for each subdir add the directory depend
  521. std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
  522. for (; sdi != subdirs.end(); ++sdi)
  523. {
  524. cmLocalUnixMakefileGenerator3 * lg2 =
  525. static_cast<cmLocalUnixMakefileGenerator3 *>(*sdi);
  526. dir = lg2->GetMakefile()->GetStartOutputDirectory();
  527. dir += "/directory";
  528. dir = lg2->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,
  529. cmLocalGenerator::MAKEFILE);
  530. all_tgts.push_back(dir);
  531. }
  532. // write the directory rule
  533. commands.clear();
  534. commands.push_back
  535. (lg->GetRecursiveMakeCall("Makefile2",makeTargetName.c_str()));
  536. // Write the rule.
  537. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
  538. localName.c_str(), depends, commands);
  539. // Write the rule.
  540. commands.clear();
  541. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
  542. makeTargetName.c_str(), all_tgts, commands);
  543. }
  544. // now do the clean targets
  545. if (lg->GetParent())
  546. {
  547. std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  548. dir = lg->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
  549. makeTargetName = dir;
  550. makeTargetName += "/clean";
  551. std::vector<std::string> all_tgts;
  552. // for all of out targets
  553. for (cmTargets::const_iterator l = lg->GetMakefile()->GetTargets().begin();
  554. l != lg->GetMakefile()->GetTargets().end(); l++)
  555. {
  556. if((l->second.GetType() == cmTarget::EXECUTABLE) ||
  557. (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  558. (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  559. (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  560. (l->second.GetType() == cmTarget::UTILITY))
  561. {
  562. // Add this to the list of depends rules in this directory.
  563. std::string tname = lg->GetRelativeTargetDirectory(l->second);
  564. tname += "/clean";
  565. all_tgts.push_back(tname);
  566. }
  567. }
  568. // write the directory rule add in the subdirs
  569. std::vector<cmLocalGenerator *> subdirs = lg->GetChildren();
  570. // for each subdir add the directory depend
  571. std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
  572. for (; sdi != subdirs.end(); ++sdi)
  573. {
  574. cmLocalUnixMakefileGenerator3 * lg2 =
  575. static_cast<cmLocalUnixMakefileGenerator3 *>(*sdi);
  576. dir = lg2->GetMakefile()->GetStartOutputDirectory();
  577. dir += "/clean";
  578. dir = lg2->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,
  579. cmLocalGenerator::MAKEFILE);
  580. all_tgts.push_back(dir);
  581. }
  582. // write the directory clean rule
  583. commands.clear();
  584. lg->WriteMakeRule(ruleFileStream, "Convenience name for directory clean.",
  585. makeTargetName.c_str(), all_tgts, commands);
  586. }
  587. }
  588. //----------------------------------------------------------------------------
  589. void
  590. cmGlobalUnixMakefileGenerator3
  591. ::WriteConvenienceRules(std::ostream& ruleFileStream,
  592. cmLocalUnixMakefileGenerator3 *lg,
  593. std::set<cmStdString> &emitted)
  594. {
  595. std::vector<std::string> depends;
  596. std::vector<std::string> commands;
  597. // write the directory level rules for this local gen
  598. //this->WriteDirectoryRules(ruleFileStream,lg);
  599. depends.push_back("cmake_check_build_system");
  600. // for each target Generate the rule files for each target.
  601. const cmTargets& targets = lg->GetMakefile()->GetTargets();
  602. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  603. {
  604. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  605. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  606. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  607. (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  608. (t->second.GetType() == cmTarget::UTILITY))
  609. {
  610. // Don't emit the same rule twice (e.g. two targets with the same
  611. // simple name)
  612. if(t->second.GetName() &&
  613. strlen(t->second.GetName()) &&
  614. emitted.insert(t->second.GetName()).second)
  615. {
  616. // Add a rule to build the target by name.
  617. lg->WriteDivider(ruleFileStream);
  618. ruleFileStream
  619. << "# Target rules for targets named "
  620. << t->second.GetName() << "\n\n";
  621. // Write the rule.
  622. commands.clear();
  623. commands.push_back(lg->GetRecursiveMakeCall("Makefile2",
  624. t->second.GetName()));
  625. depends.clear();
  626. depends.push_back("cmake_check_build_system");
  627. lg->WriteMakeRule(ruleFileStream,
  628. "Build rule for target.",
  629. t->second.GetName(), depends, commands);
  630. }
  631. }
  632. }
  633. }
  634. //----------------------------------------------------------------------------
  635. void
  636. cmGlobalUnixMakefileGenerator3
  637. ::WriteConvenienceRules2(std::ostream& ruleFileStream,
  638. cmLocalUnixMakefileGenerator3 *lg,
  639. bool exclude)
  640. {
  641. std::vector<std::string> depends;
  642. std::vector<std::string> commands;
  643. std::string localName;
  644. std::string makeTargetName;
  645. // write the directory level rules for this local gen
  646. this->WriteDirectoryRules2(ruleFileStream,lg);
  647. depends.push_back("cmake_check_build_system");
  648. // for each target Generate the rule files for each target.
  649. const cmTargets& targets = lg->GetMakefile()->GetTargets();
  650. bool needRequiresStep = this->NeedRequiresStep(lg);
  651. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  652. {
  653. if (((t->second.GetType() == cmTarget::EXECUTABLE) ||
  654. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  655. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  656. (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  657. (t->second.GetType() == cmTarget::UTILITY)) &&
  658. t->second.GetName() &&
  659. strlen(t->second.GetName()))
  660. {
  661. // Add a rule to build the target by name.
  662. localName = lg->GetRelativeTargetDirectory(t->second);
  663. std::string makefileName = localName;
  664. makefileName += "/build.make";
  665. lg->WriteDivider(ruleFileStream);
  666. ruleFileStream
  667. << "# Target rules for target "
  668. << localName << "\n\n";
  669. commands.clear();
  670. if (t->second.GetType() != cmTarget::UTILITY)
  671. {
  672. makeTargetName = localName;
  673. makeTargetName += "/depend";
  674. commands.push_back(lg->GetRecursiveMakeCall(makefileName.c_str(),
  675. makeTargetName.c_str()));
  676. // add requires if we need it for this generator
  677. if (needRequiresStep)
  678. {
  679. makeTargetName = localName;
  680. makeTargetName += "/requires";
  681. commands.push_back(lg->GetRecursiveMakeCall(makefileName.c_str(),
  682. makeTargetName.c_str()));
  683. }
  684. }
  685. makeTargetName = localName;
  686. makeTargetName += "/build";
  687. commands.push_back(lg->GetRecursiveMakeCall(makefileName.c_str(),
  688. makeTargetName.c_str()));
  689. // Write the rule.
  690. localName += "/all";
  691. depends.clear();
  692. this->AppendGlobalTargetDepends(depends,t->second);
  693. lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
  694. localName.c_str(), depends, commands);
  695. // add the all/all dependency
  696. if (!exclude && t->second.IsInAll())
  697. {
  698. depends.clear();
  699. depends.push_back(localName);
  700. commands.clear();
  701. lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
  702. "all", depends, commands);
  703. }
  704. // Write the rule.
  705. commands.clear();
  706. commands.push_back(lg->GetRecursiveMakeCall("Makefile2",
  707. localName.c_str()));
  708. depends.clear();
  709. depends.push_back("cmake_check_build_system");
  710. localName = lg->GetRelativeTargetDirectory(t->second);
  711. lg->WriteMakeRule(ruleFileStream,
  712. "Build rule for subdir invocation for target.",
  713. localName.c_str(), depends, commands);
  714. // Add a target with the canonical name (no prefix, suffix or path).
  715. commands.clear();
  716. depends.clear();
  717. depends.push_back(localName);
  718. lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
  719. t->second.GetName(), depends, commands);
  720. // add the clean rule
  721. makeTargetName = localName;
  722. makeTargetName += "/clean";
  723. depends.clear();
  724. commands.clear();
  725. commands.push_back(lg->GetRecursiveMakeCall(makefileName.c_str(),
  726. makeTargetName.c_str()));
  727. lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
  728. makeTargetName.c_str(), depends, commands);
  729. commands.clear();
  730. depends.push_back(makeTargetName);
  731. lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
  732. "clean", depends, commands);
  733. }
  734. }
  735. }
  736. //----------------------------------------------------------------------------
  737. void
  738. cmGlobalUnixMakefileGenerator3
  739. ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
  740. const cmTarget& target)
  741. {
  742. // Keep track of dependencies already listed.
  743. std::set<cmStdString> emitted;
  744. // A target should not depend on itself.
  745. emitted.insert(target.GetName());
  746. // Loop over all library dependencies but not for static libs
  747. if (target.GetType() != cmTarget::STATIC_LIBRARY)
  748. {
  749. const cmTarget::LinkLibraries& tlibs = target.GetLinkLibraries();
  750. for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
  751. lib != tlibs.end(); ++lib)
  752. {
  753. // Don't emit the same library twice for this target.
  754. if(emitted.insert(lib->first).second)
  755. {
  756. // Add this dependency.
  757. this->AppendAnyGlobalDepend(depends, lib->first.c_str());
  758. }
  759. }
  760. }
  761. // Loop over all utility dependencies.
  762. const std::set<cmStdString>& tutils = target.GetUtilities();
  763. for(std::set<cmStdString>::const_iterator util = tutils.begin();
  764. util != tutils.end(); ++util)
  765. {
  766. // Don't emit the same utility twice for this target.
  767. if(emitted.insert(*util).second)
  768. {
  769. // Add this dependency.
  770. this->AppendAnyGlobalDepend(depends, util->c_str());
  771. }
  772. }
  773. }
  774. //----------------------------------------------------------------------------
  775. void
  776. cmGlobalUnixMakefileGenerator3
  777. ::AppendAnyGlobalDepend(std::vector<std::string>& depends, const char* name)
  778. {
  779. cmTarget *result;
  780. // search each local generator until a match is found
  781. unsigned int i;
  782. for (i = 0; i < m_LocalGenerators.size(); ++i)
  783. {
  784. // search all targets
  785. result = m_LocalGenerators[i]->GetMakefile()->FindTarget(name);
  786. // if a match was found then ...
  787. if (result)
  788. {
  789. cmLocalUnixMakefileGenerator3 *lg3 =
  790. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  791. std::string tgtName = lg3->GetRelativeTargetDirectory(*result);
  792. tgtName += "/all";
  793. depends.push_back(tgtName);
  794. return;
  795. }
  796. }
  797. }
  798. //----------------------------------------------------------------------------
  799. void
  800. cmGlobalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream)
  801. {
  802. cmLocalUnixMakefileGenerator3 *lg =
  803. static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
  804. // add the help target
  805. std::string path;
  806. std::vector<std::string> no_depends;
  807. std::vector<std::string> commands;
  808. lg->AppendEcho(commands,
  809. "The following are some of the valid targets for this Makefile:");
  810. lg->AppendEcho(commands,"... all (the default if no target is provided)");
  811. lg->AppendEcho(commands,"... clean");
  812. lg->AppendEcho(commands,"... depend");
  813. lg->AppendEcho(commands,"... install");
  814. lg->AppendEcho(commands,"... rebuild_cache");
  815. // Keep track of targets already listed.
  816. std::set<cmStdString> emittedTargets;
  817. // for each local generator
  818. unsigned int i;
  819. for (i = 0; i < m_LocalGenerators.size(); ++i)
  820. {
  821. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
  822. // for each target Generate the rule files for each target.
  823. const cmTargets& targets = lg->GetMakefile()->GetTargets();
  824. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  825. {
  826. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  827. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  828. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  829. (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  830. (t->second.GetType() == cmTarget::UTILITY))
  831. {
  832. if(emittedTargets.insert(t->second.GetName()).second)
  833. {
  834. path = "... ";
  835. path += t->second.GetName();
  836. lg->AppendEcho(commands,path.c_str());
  837. }
  838. }
  839. }
  840. }
  841. lg->WriteMakeRule(ruleFileStream, "Help Target",
  842. "help:",
  843. no_depends, commands);
  844. ruleFileStream << "\n\n";
  845. }
  846. bool cmGlobalUnixMakefileGenerator3
  847. ::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg)
  848. {
  849. std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
  850. checkSet = lg->GetIntegrityCheckSet();
  851. for(std::map<cmStdString,
  852. cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
  853. l = checkSet.begin(); l != checkSet.end(); ++l)
  854. {
  855. std::string name = "CMAKE_NEEDS_REQUIRES_STEP_";
  856. name += l->first;
  857. name += "_FLAG";
  858. if(lg->GetMakefile()->GetDefinition(name.c_str()))
  859. {
  860. return true;
  861. }
  862. }
  863. return false;
  864. }