cmGlobalUnixMakefileGenerator3.cxx 36 KB

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