You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1121 lines
38 KiB

20 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
20 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
  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. #include "cmSourceFile.h"
  19. #include "cmTarget.h"
  20. cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
  21. {
  22. // This type of makefile always requires unix style paths
  23. this->ForceUnixPaths = true;
  24. this->FindMakeProgramFile = "CMakeUnixFindMake.cmake";
  25. this->ToolSupportsColor = true;
  26. this->ForceVerboseMakefiles = false;
  27. #ifdef _WIN32
  28. this->UseLinkScript = false;
  29. #else
  30. this->UseLinkScript = true;
  31. #endif
  32. }
  33. void cmGlobalUnixMakefileGenerator3
  34. ::EnableLanguage(std::vector<std::string>const& languages,
  35. cmMakefile *mf,
  36. bool optional)
  37. {
  38. this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
  39. std::string path;
  40. for(std::vector<std::string>::const_iterator l = languages.begin();
  41. l != languages.end(); ++l)
  42. {
  43. if(*l == "NONE")
  44. {
  45. continue;
  46. }
  47. const char* lang = l->c_str();
  48. std::string langComp = "CMAKE_";
  49. langComp += lang;
  50. langComp += "_COMPILER";
  51. if(!mf->GetDefinition(langComp.c_str()))
  52. {
  53. cmSystemTools::Error(langComp.c_str(),
  54. " not set, after EnableLanguage");
  55. continue;
  56. }
  57. const char* name = mf->GetRequiredDefinition(langComp.c_str());
  58. if(!cmSystemTools::FileIsFullPath(name))
  59. {
  60. path = cmSystemTools::FindProgram(name);
  61. }
  62. else
  63. {
  64. path = name;
  65. }
  66. if((path.size() == 0 || !cmSystemTools::FileExists(path.c_str()))
  67. && (optional==false))
  68. {
  69. std::string message = "your ";
  70. message += lang;
  71. message += " compiler: \"";
  72. message += name;
  73. message += "\" was not found. Please set ";
  74. message += langComp;
  75. message += " to a valid compiler path or name.";
  76. cmSystemTools::Error(message.c_str());
  77. path = name;
  78. }
  79. std::string doc = lang;
  80. doc += " compiler.";
  81. mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
  82. doc.c_str(), cmCacheManager::FILEPATH);
  83. }
  84. }
  85. ///! Create a local generator appropriate to this Global Generator
  86. cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
  87. {
  88. cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3;
  89. lg->SetGlobalGenerator(this);
  90. return lg;
  91. }
  92. //----------------------------------------------------------------------------
  93. void cmGlobalUnixMakefileGenerator3
  94. ::GetDocumentation(cmDocumentationEntry& entry) const
  95. {
  96. entry.Name = this->GetName();
  97. entry.Brief = "Generates standard UNIX makefiles.";
  98. entry.Full =
  99. "A hierarchy of UNIX makefiles is generated into the build tree. Any "
  100. "standard UNIX-style make program can build the project through the "
  101. "default make target. A \"make install\" target is also provided.";
  102. }
  103. //----------------------------------------------------------------------------
  104. void
  105. cmGlobalUnixMakefileGenerator3
  106. ::AddMultipleOutputPair(const char* depender, const char* dependee)
  107. {
  108. MultipleOutputPairsType::value_type p(depender, dependee);
  109. this->MultipleOutputPairs.insert(p);
  110. }
  111. //----------------------------------------------------------------------------
  112. void cmGlobalUnixMakefileGenerator3::Generate()
  113. {
  114. // first do superclass method
  115. this->cmGlobalGenerator::Generate();
  116. // initialize progress
  117. unsigned int i;
  118. unsigned long total = 0;
  119. for (i = 0; i < this->LocalGenerators.size(); ++i)
  120. {
  121. cmLocalUnixMakefileGenerator3 *lg =
  122. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
  123. total += lg->GetNumberOfProgressActions();
  124. }
  125. // write each target's progress.make this loop is done twice. Bascially the
  126. // Generate pass counts all the actions, the first loop below determines
  127. // how many actions have progress updates for each target and writes to
  128. // corrrect variable values for everything except the all targets. The
  129. // second loop actually writes out correct values for the all targets as
  130. // well. This is because the all targets require more information that is
  131. // computed in the first loop.
  132. unsigned long current = 0;
  133. for (i = 0; i < this->LocalGenerators.size(); ++i)
  134. {
  135. cmLocalUnixMakefileGenerator3 *lg =
  136. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
  137. lg->WriteProgressVariables(total,current);
  138. }
  139. for (i = 0; i < this->LocalGenerators.size(); ++i)
  140. {
  141. cmLocalUnixMakefileGenerator3 *lg =
  142. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
  143. lg->WriteAllProgressVariable();
  144. }
  145. // write the main makefile
  146. this->WriteMainMakefile2();
  147. this->WriteMainCMakefile();
  148. }
  149. void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
  150. {
  151. // Open the output file. This should not be copy-if-different
  152. // because the check-build-system step compares the makefile time to
  153. // see if the build system must be regenerated.
  154. std::string makefileName =
  155. this->GetCMakeInstance()->GetHomeOutputDirectory();
  156. makefileName += cmake::GetCMakeFilesDirectory();
  157. makefileName += "/Makefile2";
  158. cmGeneratedFileStream makefileStream(makefileName.c_str());
  159. if(!makefileStream)
  160. {
  161. return;
  162. }
  163. // get a local generator for some useful methods
  164. cmLocalUnixMakefileGenerator3 *lg =
  165. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
  166. // Write the do not edit header.
  167. lg->WriteDisclaimer(makefileStream);
  168. // Write the main entry point target. This must be the VERY first
  169. // target so that make with no arguments will run it.
  170. // Just depend on the all target to drive the build.
  171. std::vector<std::string> depends;
  172. std::vector<std::string> no_commands;
  173. depends.push_back("all");
  174. // Write the rule.
  175. lg->WriteMakeRule(makefileStream,
  176. "Default target executed when no arguments are "
  177. "given to make.",
  178. "default_target",
  179. depends,
  180. no_commands, true);
  181. depends.clear();
  182. // The all and preinstall rules might never have any dependencies
  183. // added to them.
  184. if(this->EmptyRuleHackDepends != "")
  185. {
  186. depends.push_back(this->EmptyRuleHackDepends);
  187. }
  188. // Write and empty all:
  189. lg->WriteMakeRule(makefileStream,
  190. "The main recursive all target", "all",
  191. depends, no_commands, true);
  192. // Write an empty preinstall:
  193. lg->WriteMakeRule(makefileStream,
  194. "The main recursive preinstall target", "preinstall",
  195. depends, no_commands, true);
  196. // Write out the "special" stuff
  197. lg->WriteSpecialTargetsTop(makefileStream);
  198. // write the target convenience rules
  199. unsigned int i;
  200. for (i = 0; i < this->LocalGenerators.size(); ++i)
  201. {
  202. lg =
  203. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
  204. this->WriteConvenienceRules2(makefileStream,lg);
  205. }
  206. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
  207. lg->WriteSpecialTargetsBottom(makefileStream);
  208. }
  209. //----------------------------------------------------------------------------
  210. void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
  211. {
  212. // Open the output file. This should not be copy-if-different
  213. // because the check-build-system step compares the makefile time to
  214. // see if the build system must be regenerated.
  215. std::string cmakefileName =
  216. this->GetCMakeInstance()->GetHomeOutputDirectory();
  217. cmakefileName += cmake::GetCMakeFilesDirectory();
  218. cmakefileName += "/Makefile.cmake";
  219. cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
  220. if(!cmakefileStream)
  221. {
  222. return;
  223. }
  224. std::string makefileName =
  225. this->GetCMakeInstance()->GetHomeOutputDirectory();
  226. makefileName += "/Makefile";
  227. // get a local generator for some useful methods
  228. cmLocalUnixMakefileGenerator3 *lg =
  229. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
  230. // Write the do not edit header.
  231. lg->WriteDisclaimer(cmakefileStream);
  232. // Save the generator name
  233. cmakefileStream
  234. << "# The generator used is:\n"
  235. << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";
  236. // for each cmMakefile get its list of dependencies
  237. std::vector<std::string> lfiles;
  238. for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
  239. {
  240. lg =
  241. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
  242. // Get the list of files contributing to this generation step.
  243. lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
  244. lg->GetMakefile()->GetListFiles().end());
  245. }
  246. // Sort the list and remove duplicates.
  247. std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
  248. std::vector<std::string>::iterator new_end =
  249. std::unique(lfiles.begin(),lfiles.end());
  250. lfiles.erase(new_end, lfiles.end());
  251. // reset lg to the first makefile
  252. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
  253. // Build the path to the cache file.
  254. std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
  255. cache += "/CMakeCache.txt";
  256. // Save the list to the cmake file.
  257. cmakefileStream
  258. << "# The top level Makefile was generated from the following files:\n"
  259. << "SET(CMAKE_MAKEFILE_DEPENDS\n"
  260. << " \""
  261. << lg->Convert(cache.c_str(),
  262. cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
  263. for(std::vector<std::string>::const_iterator i = lfiles.begin();
  264. i != lfiles.end(); ++i)
  265. {
  266. cmakefileStream
  267. << " \""
  268. << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
  269. << "\"\n";
  270. }
  271. cmakefileStream
  272. << " )\n\n";
  273. // Build the path to the cache check file.
  274. std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
  275. check += cmake::GetCMakeFilesDirectory();
  276. check += "/cmake.check_cache";
  277. // Set the corresponding makefile in the cmake file.
  278. cmakefileStream
  279. << "# The corresponding makefile is:\n"
  280. << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
  281. << " \""
  282. << lg->Convert(makefileName.c_str(),
  283. cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
  284. << " \""
  285. << lg->Convert(check.c_str(),
  286. cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
  287. // add in all the directory information files
  288. std::string tmpStr;
  289. for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
  290. {
  291. lg =
  292. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
  293. tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
  294. tmpStr += cmake::GetCMakeFilesDirectory();
  295. tmpStr += "/CMakeDirectoryInformation.cmake";
  296. cmakefileStream << " \"" <<
  297. lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
  298. << "\"\n";
  299. const std::vector<std::string>& outfiles =
  300. lg->GetMakefile()->GetOutputFiles();
  301. for(std::vector<std::string>::const_iterator k= outfiles.begin();
  302. k != outfiles.end(); ++k)
  303. {
  304. cmakefileStream << " \"" <<
  305. lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str()
  306. << "\"\n";
  307. }
  308. }
  309. cmakefileStream << " )\n\n";
  310. this->WriteMainCMakefileLanguageRules(cmakefileStream,
  311. this->LocalGenerators);
  312. if(!this->MultipleOutputPairs.empty())
  313. {
  314. cmakefileStream
  315. << "\n"
  316. << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
  317. for(MultipleOutputPairsType::const_iterator pi =
  318. this->MultipleOutputPairs.begin();
  319. pi != this->MultipleOutputPairs.end(); ++pi)
  320. {
  321. cmakefileStream << " \"" << pi->first << "\" \""
  322. << pi->second << "\"\n";
  323. }
  324. cmakefileStream << " )\n\n";
  325. }
  326. }
  327. //----------------------------------------------------------------------------
  328. void cmGlobalUnixMakefileGenerator3::CheckMultipleOutputs(cmMakefile* mf,
  329. bool verbose)
  330. {
  331. // Get the string listing the multiple output pairs.
  332. const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
  333. if(!pairs_string)
  334. {
  335. return;
  336. }
  337. // Convert the string to a list and preserve empty entries.
  338. std::vector<std::string> pairs;
  339. cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
  340. for(std::vector<std::string>::const_iterator i = pairs.begin();
  341. i != pairs.end(); ++i)
  342. {
  343. const std::string& depender = *i;
  344. if(++i != pairs.end())
  345. {
  346. const std::string& dependee = *i;
  347. // If the depender is missing then delete the dependee to make
  348. // sure both will be regenerated.
  349. if(cmSystemTools::FileExists(dependee.c_str()) &&
  350. !cmSystemTools::FileExists(depender.c_str()))
  351. {
  352. if(verbose)
  353. {
  354. cmOStringStream msg;
  355. msg << "Deleting primary custom command output \"" << dependee
  356. << "\" because another output \""
  357. << depender << "\" does not exist." << std::endl;
  358. cmSystemTools::Stdout(msg.str().c_str());
  359. }
  360. cmSystemTools::RemoveFile(dependee.c_str());
  361. }
  362. }
  363. }
  364. }
  365. void cmGlobalUnixMakefileGenerator3
  366. ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
  367. std::vector<cmLocalGenerator *> &lGenerators
  368. )
  369. {
  370. cmLocalUnixMakefileGenerator3 *lg;
  371. // now list all the target info files
  372. cmakefileStream
  373. << "# The set of files whose dependency integrity should be checked:\n";
  374. cmakefileStream
  375. << "SET(CMAKE_DEPEND_INFO_FILES\n";
  376. for (unsigned int i = 0; i < lGenerators.size(); ++i)
  377. {
  378. lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
  379. // for all of out targets
  380. for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
  381. l != lg->GetMakefile()->GetTargets().end(); l++)
  382. {
  383. if((l->second.GetType() == cmTarget::EXECUTABLE) ||
  384. (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  385. (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  386. (l->second.GetType() == cmTarget::MODULE_LIBRARY) )
  387. {
  388. std::string tname = lg->GetRelativeTargetDirectory(l->second);
  389. tname += "/DependInfo.cmake";
  390. cmSystemTools::ConvertToUnixSlashes(tname);
  391. cmakefileStream << " \"" << tname.c_str() << "\"\n";
  392. }
  393. }
  394. }
  395. cmakefileStream << " )\n";
  396. }
  397. //----------------------------------------------------------------------------
  398. void
  399. cmGlobalUnixMakefileGenerator3
  400. ::WriteDirectoryRule2(std::ostream& ruleFileStream,
  401. cmLocalUnixMakefileGenerator3* lg,
  402. const char* pass, bool check_all,
  403. bool check_relink)
  404. {
  405. // Get the relative path to the subdirectory from the top.
  406. std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
  407. makeTarget += "/";
  408. makeTarget += pass;
  409. // The directory-level rule should depend on the target-level rules
  410. // for all targets in the directory.
  411. std::vector<std::string> depends;
  412. for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
  413. l != lg->GetMakefile()->GetTargets().end(); ++l)
  414. {
  415. if((l->second.GetType() == cmTarget::EXECUTABLE) ||
  416. (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  417. (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  418. (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  419. (l->second.GetType() == cmTarget::UTILITY))
  420. {
  421. // Add this to the list of depends rules in this directory.
  422. if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
  423. (!check_relink || l->second.NeedRelinkBeforeInstall()))
  424. {
  425. std::string tname = lg->GetRelativeTargetDirectory(l->second);
  426. tname += "/";
  427. tname += pass;
  428. depends.push_back(tname);
  429. }
  430. }
  431. }
  432. // The directory-level rule should depend on the directory-level
  433. // rules of the subdirectories.
  434. for(std::vector<cmLocalGenerator*>::iterator sdi =
  435. lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
  436. {
  437. cmLocalUnixMakefileGenerator3* slg =
  438. static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
  439. std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
  440. subdir += "/";
  441. subdir += pass;
  442. depends.push_back(subdir);
  443. }
  444. // Work-around for makes that drop rules that have no dependencies
  445. // or commands.
  446. if(depends.empty() && this->EmptyRuleHackDepends != "")
  447. {
  448. depends.push_back(this->EmptyRuleHackDepends);
  449. }
  450. // Write the rule.
  451. std::string doc = "Convenience name for \"";
  452. doc += pass;
  453. doc += "\" pass in the directory.";
  454. std::vector<std::string> no_commands;
  455. lg->WriteMakeRule(ruleFileStream, doc.c_str(),
  456. makeTarget.c_str(), depends, no_commands, true);
  457. }
  458. //----------------------------------------------------------------------------
  459. void
  460. cmGlobalUnixMakefileGenerator3
  461. ::WriteDirectoryRules2(std::ostream& ruleFileStream,
  462. cmLocalUnixMakefileGenerator3* lg)
  463. {
  464. // Only subdirectories need these rules.
  465. if(!lg->GetParent())
  466. {
  467. return;
  468. }
  469. // Begin the directory-level rules section.
  470. std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  471. dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
  472. cmLocalGenerator::MAKEFILE);
  473. lg->WriteDivider(ruleFileStream);
  474. ruleFileStream
  475. << "# Directory level rules for directory "
  476. << dir << "\n\n";
  477. // Write directory-level rules for "all".
  478. this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
  479. // Write directory-level rules for "clean".
  480. this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
  481. // Write directory-level rules for "preinstall".
  482. this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
  483. }
  484. std::string cmGlobalUnixMakefileGenerator3
  485. ::GenerateBuildCommand(const char* makeProgram, const char *projectName,
  486. const char* additionalOptions, const char *targetName,
  487. const char* config, bool ignoreErrors, bool fast)
  488. {
  489. // Project name and config are not used yet.
  490. (void)projectName;
  491. (void)config;
  492. std::string makeCommand =
  493. cmSystemTools::ConvertToUnixOutputPath(makeProgram);
  494. // Since we have full control over the invocation of nmake, let us
  495. // make it quiet.
  496. if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
  497. {
  498. makeCommand += " /NOLOGO ";
  499. }
  500. if ( ignoreErrors )
  501. {
  502. makeCommand += " -i";
  503. }
  504. if ( additionalOptions )
  505. {
  506. makeCommand += " ";
  507. makeCommand += additionalOptions;
  508. }
  509. if ( targetName && strlen(targetName))
  510. {
  511. cmLocalUnixMakefileGenerator3 *lg;
  512. if (this->LocalGenerators.size())
  513. {
  514. lg = static_cast<cmLocalUnixMakefileGenerator3 *>
  515. (this->LocalGenerators[0]);
  516. }
  517. else
  518. {
  519. lg = static_cast<cmLocalUnixMakefileGenerator3 *>
  520. (this->CreateLocalGenerator());
  521. // set the Start directories
  522. lg->GetMakefile()->SetStartDirectory
  523. (this->CMakeInstance->GetStartDirectory());
  524. lg->GetMakefile()->SetStartOutputDirectory
  525. (this->CMakeInstance->GetStartOutputDirectory());
  526. lg->GetMakefile()->MakeStartDirectoriesCurrent();
  527. }
  528. makeCommand += " \"";
  529. std::string tname = targetName;
  530. if(fast)
  531. {
  532. tname += "/fast";
  533. }
  534. tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
  535. cmLocalGenerator::MAKEFILE);
  536. makeCommand += tname.c_str();
  537. makeCommand += "\"";
  538. if (!this->LocalGenerators.size())
  539. {
  540. delete lg;
  541. }
  542. }
  543. return makeCommand;
  544. }
  545. //----------------------------------------------------------------------------
  546. void
  547. cmGlobalUnixMakefileGenerator3
  548. ::WriteConvenienceRules(std::ostream& ruleFileStream,
  549. std::set<cmStdString> &emitted)
  550. {
  551. std::vector<std::string> depends;
  552. std::vector<std::string> commands;
  553. depends.push_back("cmake_check_build_system");
  554. // write the target convenience rules
  555. unsigned int i;
  556. cmLocalUnixMakefileGenerator3 *lg;
  557. for (i = 0; i < this->LocalGenerators.size(); ++i)
  558. {
  559. lg = static_cast<cmLocalUnixMakefileGenerator3 *>
  560. (this->LocalGenerators[i]);
  561. // for each target Generate the rule files for each target.
  562. cmTargets& targets = lg->GetMakefile()->GetTargets();
  563. for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
  564. {
  565. // Don't emit the same rule twice (e.g. two targets with the same
  566. // simple name)
  567. if(t->second.GetName() &&
  568. strlen(t->second.GetName()) &&
  569. emitted.insert(t->second.GetName()).second &&
  570. // Handle user targets here. Global targets are handled in
  571. // the local generator on a per-directory basis.
  572. ((t->second.GetType() == cmTarget::EXECUTABLE) ||
  573. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  574. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  575. (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  576. (t->second.GetType() == cmTarget::UTILITY)))
  577. {
  578. // Add a rule to build the target by name.
  579. lg->WriteDivider(ruleFileStream);
  580. ruleFileStream
  581. << "# Target rules for targets named "
  582. << t->second.GetName() << "\n\n";
  583. // Write the rule.
  584. commands.clear();
  585. std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
  586. tmp += "Makefile2";
  587. commands.push_back(lg->GetRecursiveMakeCall
  588. (tmp.c_str(),t->second.GetName()));
  589. depends.clear();
  590. depends.push_back("cmake_check_build_system");
  591. lg->WriteMakeRule(ruleFileStream,
  592. "Build rule for target.",
  593. t->second.GetName(), depends, commands,
  594. true);
  595. // Add a fast rule to build the target
  596. std::string localName = lg->GetRelativeTargetDirectory(t->second);
  597. std::string makefileName;
  598. makefileName = localName;
  599. makefileName += "/build.make";
  600. depends.clear();
  601. commands.clear();
  602. std::string makeTargetName = localName;
  603. makeTargetName += "/build";
  604. localName = t->second.GetName();
  605. localName += "/fast";
  606. commands.push_back(lg->GetRecursiveMakeCall
  607. (makefileName.c_str(), makeTargetName.c_str()));
  608. lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
  609. localName.c_str(), depends, commands, true);
  610. // Add a local name for the rule to relink the target before
  611. // installation.
  612. if(t->second.NeedRelinkBeforeInstall())
  613. {
  614. makeTargetName = lg->GetRelativeTargetDirectory(t->second);
  615. makeTargetName += "/preinstall";
  616. localName = t->second.GetName();
  617. localName += "/preinstall";
  618. depends.clear();
  619. commands.clear();
  620. commands.push_back(lg->GetRecursiveMakeCall
  621. (makefileName.c_str(), makeTargetName.c_str()));
  622. lg->WriteMakeRule(ruleFileStream,
  623. "Manual pre-install relink rule for target.",
  624. localName.c_str(), depends, commands, true);
  625. }
  626. }
  627. }
  628. }
  629. }
  630. //----------------------------------------------------------------------------
  631. void
  632. cmGlobalUnixMakefileGenerator3
  633. ::WriteConvenienceRules2(std::ostream& ruleFileStream,
  634. cmLocalUnixMakefileGenerator3 *lg)
  635. {
  636. std::vector<std::string> depends;
  637. std::vector<std::string> commands;
  638. std::string localName;
  639. std::string makeTargetName;
  640. // write the directory level rules for this local gen
  641. this->WriteDirectoryRules2(ruleFileStream,lg);
  642. depends.push_back("cmake_check_build_system");
  643. // for each target Generate the rule files for each target.
  644. cmTargets& targets = lg->GetMakefile()->GetTargets();
  645. for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
  646. {
  647. if (t->second.GetName()
  648. && strlen(t->second.GetName())
  649. && ((t->second.GetType() == cmTarget::EXECUTABLE)
  650. || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
  651. || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
  652. || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
  653. || (t->second.GetType() == cmTarget::UTILITY)))
  654. {
  655. std::string makefileName;
  656. // Add a rule to build the target by name.
  657. localName = lg->GetRelativeTargetDirectory(t->second);
  658. makefileName = localName;
  659. makefileName += "/build.make";
  660. bool needRequiresStep = this->NeedRequiresStep(t->second);
  661. lg->WriteDivider(ruleFileStream);
  662. ruleFileStream
  663. << "# Target rules for target "
  664. << localName << "\n\n";
  665. commands.clear();
  666. if (t->second.GetType() != cmTarget::UTILITY)
  667. {
  668. makeTargetName = localName;
  669. makeTargetName += "/depend";
  670. commands.push_back(lg->GetRecursiveMakeCall
  671. (makefileName.c_str(),makeTargetName.c_str()));
  672. // add requires if we need it for this generator
  673. if (needRequiresStep)
  674. {
  675. makeTargetName = localName;
  676. makeTargetName += "/requires";
  677. commands.push_back(lg->GetRecursiveMakeCall
  678. (makefileName.c_str(),makeTargetName.c_str()));
  679. }
  680. }
  681. makeTargetName = localName;
  682. makeTargetName += "/build";
  683. commands.push_back(lg->GetRecursiveMakeCall
  684. (makefileName.c_str(),makeTargetName.c_str()));
  685. // Write the rule.
  686. localName += "/all";
  687. depends.clear();
  688. std::string progressDir =
  689. lg->GetMakefile()->GetHomeOutputDirectory();
  690. progressDir += cmake::GetCMakeFilesDirectory();
  691. {
  692. cmOStringStream progCmd;
  693. progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
  694. // all target counts
  695. progCmd << lg->Convert(progressDir.c_str(),
  696. cmLocalGenerator::FULL,
  697. cmLocalGenerator::SHELL);
  698. progCmd << " ";
  699. std::vector<int> &progFiles = lg->ProgressFiles[t->first];
  700. for (std::vector<int>::iterator i = progFiles.begin();
  701. i != progFiles.end(); ++i)
  702. {
  703. progCmd << " " << *i;
  704. }
  705. commands.push_back(progCmd.str());
  706. }
  707. progressDir = "Built target ";
  708. progressDir += t->first;
  709. lg->AppendEcho(commands,progressDir.c_str());
  710. this->AppendGlobalTargetDepends(depends,t->second);
  711. lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
  712. localName.c_str(), depends, commands, true);
  713. // add the all/all dependency
  714. if(!this->IsExcluded(this->LocalGenerators[0], t->second))
  715. {
  716. depends.clear();
  717. depends.push_back(localName);
  718. commands.clear();
  719. lg->WriteMakeRule(ruleFileStream, "Include target in all.",
  720. "all", depends, commands, true);
  721. }
  722. // Write the rule.
  723. commands.clear();
  724. progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
  725. progressDir += cmake::GetCMakeFilesDirectory();
  726. {
  727. // TODO: Convert the total progress count to a make variable.
  728. cmOStringStream progCmd;
  729. progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
  730. // # in target
  731. progCmd << lg->Convert(progressDir.c_str(),
  732. cmLocalGenerator::FULL,
  733. cmLocalGenerator::SHELL);
  734. //
  735. std::set<cmStdString> emitted;
  736. progCmd << " "
  737. << this->GetTargetTotalNumberOfActions(t->second,
  738. emitted);
  739. commands.push_back(progCmd.str());
  740. }
  741. std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
  742. tmp += "Makefile2";
  743. commands.push_back(lg->GetRecursiveMakeCall
  744. (tmp.c_str(),localName.c_str()));
  745. {
  746. cmOStringStream progCmd;
  747. progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
  748. progCmd << lg->Convert(progressDir.c_str(),
  749. cmLocalGenerator::FULL,
  750. cmLocalGenerator::SHELL);
  751. progCmd << " 0";
  752. commands.push_back(progCmd.str());
  753. }
  754. depends.clear();
  755. depends.push_back("cmake_check_build_system");
  756. localName = lg->GetRelativeTargetDirectory(t->second);
  757. localName += "/rule";
  758. lg->WriteMakeRule(ruleFileStream,
  759. "Build rule for subdir invocation for target.",
  760. localName.c_str(), depends, commands, true);
  761. // Add a target with the canonical name (no prefix, suffix or path).
  762. commands.clear();
  763. depends.clear();
  764. depends.push_back(localName);
  765. lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
  766. t->second.GetName(), depends, commands, true);
  767. // Add rules to prepare the target for installation.
  768. if(t->second.NeedRelinkBeforeInstall())
  769. {
  770. localName = lg->GetRelativeTargetDirectory(t->second);
  771. localName += "/preinstall";
  772. depends.clear();
  773. commands.clear();
  774. commands.push_back(lg->GetRecursiveMakeCall
  775. (makefileName.c_str(), localName.c_str()));
  776. lg->WriteMakeRule(ruleFileStream,
  777. "Pre-install relink rule for target.",
  778. localName.c_str(), depends, commands, true);
  779. if(!this->IsExcluded(this->LocalGenerators[0], t->second))
  780. {
  781. depends.clear();
  782. depends.push_back(localName);
  783. commands.clear();
  784. lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
  785. "preinstall", depends, commands, true);
  786. }
  787. }
  788. // add the clean rule
  789. localName = lg->GetRelativeTargetDirectory(t->second);
  790. makeTargetName = localName;
  791. makeTargetName += "/clean";
  792. depends.clear();
  793. commands.clear();
  794. commands.push_back(lg->GetRecursiveMakeCall
  795. (makefileName.c_str(), makeTargetName.c_str()));
  796. lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
  797. makeTargetName.c_str(), depends, commands, true);
  798. commands.clear();
  799. depends.push_back(makeTargetName);
  800. lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
  801. "clean", depends, commands, true);
  802. }
  803. }
  804. }
  805. //----------------------------------------------------------------------------
  806. int cmGlobalUnixMakefileGenerator3
  807. ::GetTargetTotalNumberOfActions(cmTarget& target,
  808. std::set<cmStdString> &emitted)
  809. {
  810. // do not double count
  811. int result = 0;
  812. if(emitted.insert(target.GetName()).second)
  813. {
  814. cmLocalUnixMakefileGenerator3 *lg =
  815. static_cast<cmLocalUnixMakefileGenerator3 *>
  816. (target.GetMakefile()->GetLocalGenerator());
  817. result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
  818. std::vector<cmTarget *>& depends = this->GetTargetDepends(target);
  819. std::vector<cmTarget *>::iterator i;
  820. for (i = depends.begin(); i != depends.end(); ++i)
  821. {
  822. result += this->GetTargetTotalNumberOfActions(**i, emitted);
  823. }
  824. }
  825. return result;
  826. }
  827. unsigned long cmGlobalUnixMakefileGenerator3
  828. ::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3 *lg)
  829. {
  830. unsigned long result = 0;
  831. std::set<cmTarget*>& targets = this->LocalGeneratorToTargetMap[lg];
  832. for(std::set<cmTarget*>::iterator t = targets.begin();
  833. t != targets.end(); ++t)
  834. {
  835. cmTarget* target = *t;
  836. cmLocalUnixMakefileGenerator3 *lg3 =
  837. static_cast<cmLocalUnixMakefileGenerator3 *>
  838. (target->GetMakefile()->GetLocalGenerator());
  839. std::vector<int> &progFiles = lg3->ProgressFiles[target->GetName()];
  840. result += static_cast<unsigned long>(progFiles.size());
  841. }
  842. return result;
  843. }
  844. //----------------------------------------------------------------------------
  845. void
  846. cmGlobalUnixMakefileGenerator3
  847. ::AppendGlobalTargetDepends(std::vector<std::string>& depends,
  848. cmTarget& target)
  849. {
  850. // Keep track of dependencies already listed.
  851. std::set<cmStdString> emitted;
  852. // A target should not depend on itself.
  853. emitted.insert(target.GetName());
  854. // Loop over all library dependencies but not for static libs
  855. if (target.GetType() != cmTarget::STATIC_LIBRARY)
  856. {
  857. const cmTarget::LinkLibraryVectorType& tlibs = target.GetLinkLibraries();
  858. for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
  859. lib != tlibs.end(); ++lib)
  860. {
  861. // Don't emit the same library twice for this target.
  862. if(emitted.insert(lib->first).second)
  863. {
  864. // Add this dependency.
  865. this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
  866. emitted, target);
  867. }
  868. }
  869. }
  870. // Loop over all utility dependencies.
  871. const std::set<cmStdString>& tutils = target.GetUtilities();
  872. for(std::set<cmStdString>::const_iterator util = tutils.begin();
  873. util != tutils.end(); ++util)
  874. {
  875. // Don't emit the same utility twice for this target.
  876. if(emitted.insert(*util).second)
  877. {
  878. // Add this dependency.
  879. this->AppendAnyGlobalDepend(depends, util->c_str(), emitted, target);
  880. }
  881. }
  882. }
  883. //----------------------------------------------------------------------------
  884. void
  885. cmGlobalUnixMakefileGenerator3
  886. ::AppendAnyGlobalDepend(std::vector<std::string>& depends, const char* name,
  887. std::set<cmStdString>& emitted, cmTarget &target)
  888. {
  889. cmTarget *result;
  890. cmLocalUnixMakefileGenerator3 *lg3;
  891. // first check the same dir as the current target
  892. lg3 = static_cast<cmLocalUnixMakefileGenerator3 *>
  893. (target.GetMakefile()->GetLocalGenerator());
  894. result = target.GetMakefile()->FindTarget(name, false);
  895. // search each local generator until a match is found
  896. if (!result)
  897. {
  898. result = this->FindTarget(0, name, false);
  899. if (result)
  900. {
  901. lg3 = static_cast<cmLocalUnixMakefileGenerator3 *>
  902. (result->GetMakefile()->GetLocalGenerator());
  903. }
  904. }
  905. // if a match was found then ...
  906. if (result)
  907. {
  908. std::string tgtName = lg3->GetRelativeTargetDirectory(*result);
  909. tgtName += "/all";
  910. depends.push_back(tgtName);
  911. if(result->GetType() == cmTarget::STATIC_LIBRARY)
  912. {
  913. // Since the static library itself does not list dependencies we
  914. // need to chain its dependencies here.
  915. const cmTarget::LinkLibraryVectorType& tlibs
  916. = result->GetLinkLibraries();
  917. for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
  918. lib != tlibs.end(); ++lib)
  919. {
  920. // Don't emit the same library twice for this target.
  921. if(emitted.insert(lib->first).second)
  922. {
  923. // Add this dependency.
  924. this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
  925. emitted, *result);
  926. }
  927. }
  928. }
  929. return;
  930. }
  931. }
  932. //----------------------------------------------------------------------------
  933. void cmGlobalUnixMakefileGenerator3::WriteHelpRule
  934. (std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
  935. {
  936. // add the help target
  937. std::string path;
  938. std::vector<std::string> no_depends;
  939. std::vector<std::string> commands;
  940. lg->AppendEcho(commands,"The following are some of the valid targets "
  941. "for this Makefile:");
  942. lg->AppendEcho(commands,"... all (the default if no target is provided)");
  943. lg->AppendEcho(commands,"... clean");
  944. lg->AppendEcho(commands,"... depend");
  945. // Keep track of targets already listed.
  946. std::set<cmStdString> emittedTargets;
  947. // for each local generator
  948. unsigned int i;
  949. cmLocalUnixMakefileGenerator3 *lg2;
  950. for (i = 0; i < this->LocalGenerators.size(); ++i)
  951. {
  952. lg2 =
  953. static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
  954. // for the passed in makefile or if this is the top Makefile wripte out
  955. // the targets
  956. if (lg2 == lg || !lg->GetParent())
  957. {
  958. // for each target Generate the rule files for each target.
  959. cmTargets& targets = lg2->GetMakefile()->GetTargets();
  960. for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
  961. {
  962. if((t->second.GetType() == cmTarget::EXECUTABLE) ||
  963. (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
  964. (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
  965. (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
  966. (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
  967. (t->second.GetType() == cmTarget::UTILITY))
  968. {
  969. if(emittedTargets.insert(t->second.GetName()).second)
  970. {
  971. path = "... ";
  972. path += t->second.GetName();
  973. lg->AppendEcho(commands,path.c_str());
  974. }
  975. }
  976. }
  977. std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
  978. for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
  979. o != localHelp.end(); ++o)
  980. {
  981. path = "... ";
  982. path += *o;
  983. lg->AppendEcho(commands, path.c_str());
  984. }
  985. }
  986. }
  987. lg->WriteMakeRule(ruleFileStream, "Help Target",
  988. "help:",
  989. no_depends, commands, true);
  990. ruleFileStream << "\n\n";
  991. }
  992. bool cmGlobalUnixMakefileGenerator3
  993. ::NeedRequiresStep(cmTarget const& target)
  994. {
  995. std::set<cmStdString> languages;
  996. target.GetLanguages(languages);
  997. for(std::set<cmStdString>::const_iterator l = languages.begin();
  998. l != languages.end(); ++l)
  999. {
  1000. std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
  1001. var += *l;
  1002. var += "_FLAG";
  1003. if(target.GetMakefile()->GetDefinition(var.c_str()))
  1004. {
  1005. return true;
  1006. }
  1007. }
  1008. return false;
  1009. }