cmGlobalNinjaGenerator.cxx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2011 Peter Collingbourne <[email protected]>
  4. Copyright 2011 Nicolas Despres <[email protected]>
  5. Distributed under the OSI-approved BSD License (the "License");
  6. see accompanying file Copyright.txt for details.
  7. This software is distributed WITHOUT ANY WARRANTY; without even the
  8. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. See the License for more information.
  10. ============================================================================*/
  11. #include "cmGlobalNinjaGenerator.h"
  12. #include "cmLocalNinjaGenerator.h"
  13. #include "cmMakefile.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include "cmVersion.h"
  16. const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
  17. const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
  18. const char* cmGlobalNinjaGenerator::INDENT = " ";
  19. void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count)
  20. {
  21. for(int i = 0; i < count; ++i)
  22. os << cmGlobalNinjaGenerator::INDENT;
  23. }
  24. void cmGlobalNinjaGenerator::WriteDivider(std::ostream& os)
  25. {
  26. os
  27. << "# ======================================"
  28. << "=======================================\n";
  29. }
  30. void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
  31. const std::string& comment)
  32. {
  33. if (comment.empty())
  34. return;
  35. std::string replace = comment;
  36. std::string::size_type lpos = 0;
  37. std::string::size_type rpos;
  38. while((rpos = replace.find('\n', lpos)) != std::string::npos)
  39. {
  40. os << "# " << replace.substr(lpos, rpos - lpos) << "\n";
  41. lpos = rpos + 1;
  42. }
  43. os << "# " << replace.substr(lpos) << "\n";
  44. }
  45. static bool IsIdentChar(char c)
  46. {
  47. return
  48. ('a' <= c && c <= 'z') ||
  49. ('+' <= c && c <= '9') || // +,-./ and numbers
  50. ('A' <= c && c <= 'Z') ||
  51. (c == '_') || (c == '$') || (c == '\\');
  52. }
  53. std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
  54. std::ostream &vars) {
  55. if (std::find_if(ident.begin(), ident.end(),
  56. std::not1(std::ptr_fun(IsIdentChar))) != ident.end()) {
  57. static unsigned VarNum = 0;
  58. std::ostringstream names;
  59. names << "ident" << VarNum++;
  60. vars << names.str() << " = " << ident << "\n";
  61. return "$" + names.str();
  62. } else {
  63. return ident;
  64. }
  65. }
  66. std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
  67. {
  68. std::string result = lit;
  69. cmSystemTools::ReplaceString(result, "$", "$$");
  70. return result;
  71. }
  72. void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
  73. const std::string& comment,
  74. const std::string& rule,
  75. const cmNinjaDeps& outputs,
  76. const cmNinjaDeps& explicitDeps,
  77. const cmNinjaDeps& implicitDeps,
  78. const cmNinjaDeps& orderOnlyDeps,
  79. const cmNinjaVars& variables)
  80. {
  81. // Make sure there is a rule.
  82. if(rule.empty())
  83. {
  84. cmSystemTools::Error("No rule for WriteBuildStatement! called "
  85. "with comment: ",
  86. comment.c_str());
  87. return;
  88. }
  89. // Make sure there is at least one output file.
  90. if(outputs.empty())
  91. {
  92. cmSystemTools::Error("No output files for WriteBuildStatement! called "
  93. "with comment: ",
  94. comment.c_str());
  95. return;
  96. }
  97. cmGlobalNinjaGenerator::WriteComment(os, comment);
  98. std::ostringstream builds;
  99. // TODO: Better formatting for when there are multiple input/output files.
  100. // Write outputs files.
  101. builds << "build";
  102. for(cmNinjaDeps::const_iterator i = outputs.begin();
  103. i != outputs.end();
  104. ++i)
  105. builds << " " << EncodeIdent(*i, os);
  106. builds << ":";
  107. // Write the rule.
  108. builds << " " << rule;
  109. // Write explicit dependencies.
  110. for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
  111. i != explicitDeps.end();
  112. ++i)
  113. builds << " " << EncodeIdent(*i, os);
  114. // Write implicit dependencies.
  115. if(!implicitDeps.empty())
  116. {
  117. builds << " |";
  118. for(cmNinjaDeps::const_iterator i = implicitDeps.begin();
  119. i != implicitDeps.end();
  120. ++i)
  121. builds << " " << EncodeIdent(*i, os);
  122. }
  123. // Write order-only dependencies.
  124. if(!orderOnlyDeps.empty())
  125. {
  126. builds << " ||";
  127. for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
  128. i != orderOnlyDeps.end();
  129. ++i)
  130. builds << " " << EncodeIdent(*i, os);
  131. }
  132. builds << "\n";
  133. os << builds.str();
  134. // Write the variables bound to this build statement.
  135. for(cmNinjaVars::const_iterator i = variables.begin();
  136. i != variables.end();
  137. ++i)
  138. cmGlobalNinjaGenerator::WriteVariable(os, i->first, i->second, "", 1);
  139. }
  140. void cmGlobalNinjaGenerator::WritePhonyBuild(std::ostream& os,
  141. const std::string& comment,
  142. const cmNinjaDeps& outputs,
  143. const cmNinjaDeps& explicitDeps,
  144. const cmNinjaDeps& implicitDeps,
  145. const cmNinjaDeps& orderOnlyDeps,
  146. const cmNinjaVars& variables)
  147. {
  148. cmGlobalNinjaGenerator::WriteBuild(os,
  149. comment,
  150. "phony",
  151. outputs,
  152. explicitDeps,
  153. implicitDeps,
  154. orderOnlyDeps,
  155. variables);
  156. }
  157. void cmGlobalNinjaGenerator::AddCustomCommandRule()
  158. {
  159. this->AddRule("CUSTOM_COMMAND",
  160. "$COMMAND",
  161. "$DESC",
  162. "Rule for running custom commands.",
  163. /*depfile*/ "",
  164. /*restat*/ true);
  165. }
  166. void
  167. cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
  168. const std::string& description,
  169. const std::string& comment,
  170. const cmNinjaDeps& outputs,
  171. const cmNinjaDeps& deps,
  172. const cmNinjaDeps& orderOnlyDeps)
  173. {
  174. this->AddCustomCommandRule();
  175. cmNinjaVars vars;
  176. vars["COMMAND"] = command;
  177. vars["DESC"] = EncodeLiteral(description);
  178. cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,
  179. comment,
  180. "CUSTOM_COMMAND",
  181. outputs,
  182. deps,
  183. cmNinjaDeps(),
  184. orderOnlyDeps,
  185. vars);
  186. }
  187. void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
  188. const std::string& name,
  189. const std::string& command,
  190. const std::string& description,
  191. const std::string& comment,
  192. const std::string& depfile,
  193. bool restat,
  194. bool generator)
  195. {
  196. // Make sure the rule has a name.
  197. if(name.empty())
  198. {
  199. cmSystemTools::Error("No name given for WriteRuleStatement! called "
  200. "with comment: ",
  201. comment.c_str());
  202. return;
  203. }
  204. // Make sure a command is given.
  205. if(command.empty())
  206. {
  207. cmSystemTools::Error("No command given for WriteRuleStatement! called "
  208. "with comment: ",
  209. comment.c_str());
  210. return;
  211. }
  212. cmGlobalNinjaGenerator::WriteComment(os, comment);
  213. // Write the rule.
  214. os << "rule " << name << "\n";
  215. // Write the depfile if any.
  216. if(!depfile.empty())
  217. {
  218. cmGlobalNinjaGenerator::Indent(os, 1);
  219. os << "depfile = " << depfile << "\n";
  220. }
  221. // Write the command.
  222. cmGlobalNinjaGenerator::Indent(os, 1);
  223. os << "command = " << command << "\n";
  224. // Write the description if any.
  225. if(!description.empty())
  226. {
  227. cmGlobalNinjaGenerator::Indent(os, 1);
  228. os << "description = " << description << "\n";
  229. }
  230. if(restat)
  231. {
  232. cmGlobalNinjaGenerator::Indent(os, 1);
  233. os << "restat = 1\n";
  234. }
  235. if(generator)
  236. {
  237. cmGlobalNinjaGenerator::Indent(os, 1);
  238. os << "generator = 1\n";
  239. }
  240. }
  241. void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
  242. const std::string& name,
  243. const std::string& value,
  244. const std::string& comment,
  245. int indent)
  246. {
  247. // Make sure we have a name.
  248. if(name.empty())
  249. {
  250. cmSystemTools::Error("No name given for WriteVariable! called "
  251. "with comment: ",
  252. comment.c_str());
  253. return;
  254. }
  255. // Do not add a variable if the value is empty.
  256. std::string val = cmSystemTools::TrimWhitespace(value);
  257. if(val.empty())
  258. {
  259. return;
  260. }
  261. cmGlobalNinjaGenerator::WriteComment(os, comment);
  262. cmGlobalNinjaGenerator::Indent(os, indent);
  263. os << name << " = " << val << "\n";
  264. }
  265. void cmGlobalNinjaGenerator::WriteInclude(std::ostream& os,
  266. const std::string& filename,
  267. const std::string& comment)
  268. {
  269. cmGlobalNinjaGenerator::WriteComment(os, comment);
  270. os << "include " << filename << "\n";
  271. }
  272. void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os,
  273. const cmNinjaDeps& targets,
  274. const std::string& comment)
  275. {
  276. cmGlobalNinjaGenerator::WriteComment(os, comment);
  277. os << "default";
  278. for(cmNinjaDeps::const_iterator i = targets.begin(); i != targets.end(); ++i)
  279. os << " " << *i;
  280. os << "\n";
  281. }
  282. cmGlobalNinjaGenerator::cmGlobalNinjaGenerator()
  283. : cmGlobalGenerator()
  284. , BuildFileStream(0)
  285. , RulesFileStream(0)
  286. , Rules()
  287. , AllDependencies()
  288. {
  289. // // Ninja is not ported to non-Unix OS yet.
  290. // this->ForceUnixPaths = true;
  291. this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
  292. }
  293. //----------------------------------------------------------------------------
  294. // Virtual public methods.
  295. cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator()
  296. {
  297. cmLocalGenerator* lg = new cmLocalNinjaGenerator;
  298. lg->SetGlobalGenerator(this);
  299. return lg;
  300. }
  301. void cmGlobalNinjaGenerator
  302. ::GetDocumentation(cmDocumentationEntry& entry) const
  303. {
  304. entry.Name = this->GetName();
  305. entry.Brief = "Generates build.ninja files (experimental).";
  306. entry.Full =
  307. "A build.ninja file is generated into the build tree. Recent "
  308. "versions of the ninja program can build the project through the "
  309. "\"all\" target. An \"install\" target is also provided.";
  310. }
  311. // Implemented in all cmGlobaleGenerator sub-classes.
  312. // Used in:
  313. // Source/cmLocalGenerator.cxx
  314. // Source/cmake.cxx
  315. void cmGlobalNinjaGenerator::Generate()
  316. {
  317. this->OpenBuildFileStream();
  318. this->OpenRulesFileStream();
  319. this->cmGlobalGenerator::Generate();
  320. this->WriteAssumedSourceDependencies();
  321. this->WriteTargetAliases(*this->BuildFileStream);
  322. this->WriteBuiltinTargets(*this->BuildFileStream);
  323. this->CloseRulesFileStream();
  324. this->CloseBuildFileStream();
  325. }
  326. // Implemented in all cmGlobaleGenerator sub-classes.
  327. // Used in:
  328. // Source/cmMakefile.cxx:
  329. void cmGlobalNinjaGenerator
  330. ::EnableLanguage(std::vector<std::string>const& languages,
  331. cmMakefile *mf,
  332. bool optional)
  333. {
  334. this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
  335. std::string path;
  336. for(std::vector<std::string>::const_iterator l = languages.begin();
  337. l != languages.end(); ++l)
  338. {
  339. if(*l == "NONE")
  340. {
  341. continue;
  342. }
  343. if(*l == "Fortran")
  344. {
  345. std::string message = "The \"";
  346. message += this->GetName();
  347. message += "\" generator does not support the language \"";
  348. message += *l;
  349. message += "\" yet.";
  350. cmSystemTools::Error(message.c_str());
  351. }
  352. this->ResolveLanguageCompiler(*l, mf, optional);
  353. }
  354. }
  355. // Implemented by:
  356. // cmGlobalUnixMakefileGenerator3
  357. // cmGlobalVisualStudio10Generator
  358. // cmGlobalVisualStudio6Generator
  359. // cmGlobalVisualStudio7Generator
  360. // cmGlobalXCodeGenerator
  361. // Called by:
  362. // cmGlobalGenerator::Build()
  363. std::string cmGlobalNinjaGenerator
  364. ::GenerateBuildCommand(const char* makeProgram,
  365. const char* projectName,
  366. const char* additionalOptions,
  367. const char* targetName,
  368. const char* config,
  369. bool ignoreErrors,
  370. bool fast)
  371. {
  372. // Project name and config are not used yet.
  373. (void)projectName;
  374. (void)config;
  375. // Ninja does not have -i equivalent option yet.
  376. (void)ignoreErrors;
  377. // We do not handle fast build yet.
  378. (void)fast;
  379. std::string makeCommand =
  380. cmSystemTools::ConvertToUnixOutputPath(makeProgram);
  381. if(additionalOptions)
  382. {
  383. makeCommand += " ";
  384. makeCommand += additionalOptions;
  385. }
  386. if(targetName)
  387. {
  388. if(strcmp(targetName, "clean") == 0)
  389. {
  390. makeCommand += " -t clean";
  391. }
  392. else
  393. {
  394. makeCommand += " ";
  395. makeCommand += targetName;
  396. }
  397. }
  398. return makeCommand;
  399. }
  400. //----------------------------------------------------------------------------
  401. // Non-virtual public methods.
  402. void cmGlobalNinjaGenerator::AddRule(const std::string& name,
  403. const std::string& command,
  404. const std::string& description,
  405. const std::string& comment,
  406. const std::string& depfile,
  407. bool restat,
  408. bool generator)
  409. {
  410. // Do not add the same rule twice.
  411. if (this->HasRule(name))
  412. return;
  413. this->Rules.insert(name);
  414. cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream,
  415. name,
  416. command,
  417. description,
  418. comment,
  419. depfile,
  420. restat,
  421. generator);
  422. }
  423. bool cmGlobalNinjaGenerator::HasRule(const std::string &name)
  424. {
  425. RulesSetType::const_iterator rule = this->Rules.find(name);
  426. return (rule != this->Rules.end());
  427. }
  428. //----------------------------------------------------------------------------
  429. // Private methods
  430. void cmGlobalNinjaGenerator::OpenBuildFileStream()
  431. {
  432. // Compute Ninja's build file path.
  433. std::string buildFilePath =
  434. this->GetCMakeInstance()->GetHomeOutputDirectory();
  435. buildFilePath += "/";
  436. buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE;
  437. // Get a stream where to generate things.
  438. if (!this->BuildFileStream)
  439. {
  440. this->BuildFileStream = new cmGeneratedFileStream(buildFilePath.c_str());
  441. if (!this->BuildFileStream)
  442. {
  443. // An error message is generated by the constructor if it cannot
  444. // open the file.
  445. return;
  446. }
  447. }
  448. // Write the do not edit header.
  449. this->WriteDisclaimer(*this->BuildFileStream);
  450. // Write a comment about this file.
  451. *this->BuildFileStream
  452. << "# This file contains all the build statements describing the\n"
  453. << "# compilation DAG.\n\n"
  454. ;
  455. }
  456. void cmGlobalNinjaGenerator::CloseBuildFileStream()
  457. {
  458. if (this->BuildFileStream)
  459. {
  460. delete this->BuildFileStream;
  461. this->BuildFileStream = 0;
  462. }
  463. else
  464. {
  465. cmSystemTools::Error("Build file stream was not open.");
  466. }
  467. }
  468. void cmGlobalNinjaGenerator::OpenRulesFileStream()
  469. {
  470. // Compute Ninja's build file path.
  471. std::string rulesFilePath =
  472. this->GetCMakeInstance()->GetHomeOutputDirectory();
  473. rulesFilePath += "/";
  474. rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE;
  475. // Get a stream where to generate things.
  476. if (!this->RulesFileStream)
  477. {
  478. this->RulesFileStream = new cmGeneratedFileStream(rulesFilePath.c_str());
  479. if (!this->RulesFileStream)
  480. {
  481. // An error message is generated by the constructor if it cannot
  482. // open the file.
  483. return;
  484. }
  485. }
  486. // Write the do not edit header.
  487. this->WriteDisclaimer(*this->RulesFileStream);
  488. // Write comment about this file.
  489. *this->RulesFileStream
  490. << "# This file contains all the rules used to get the outputs files\n"
  491. << "# built from the input files.\n"
  492. << "# It is included in the main '" << NINJA_BUILD_FILE << "'.\n\n"
  493. ;
  494. }
  495. void cmGlobalNinjaGenerator::CloseRulesFileStream()
  496. {
  497. if (this->RulesFileStream)
  498. {
  499. delete this->RulesFileStream;
  500. this->RulesFileStream = 0;
  501. }
  502. else
  503. {
  504. cmSystemTools::Error("Rules file stream was not open.");
  505. }
  506. }
  507. void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
  508. {
  509. os
  510. << "# CMAKE generated file: DO NOT EDIT!\n"
  511. << "# Generated by \"" << this->GetName() << "\""
  512. << " Generator, CMake Version "
  513. << cmVersion::GetMajorVersion() << "."
  514. << cmVersion::GetMinorVersion() << "\n\n";
  515. }
  516. void cmGlobalNinjaGenerator::AddDependencyToAll(cmTarget* target)
  517. {
  518. this->AppendTargetOutputs(target, this->AllDependencies);
  519. }
  520. void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
  521. {
  522. for (std::map<std::string, std::set<std::string> >::iterator
  523. i = this->AssumedSourceDependencies.begin();
  524. i != this->AssumedSourceDependencies.end(); ++i) {
  525. cmNinjaDeps deps;
  526. std::copy(i->second.begin(), i->second.end(), std::back_inserter(deps));
  527. WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
  528. "Assume dependencies for generated source file.",
  529. cmNinjaDeps(1, i->first), deps);
  530. }
  531. }
  532. void
  533. cmGlobalNinjaGenerator
  534. ::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs)
  535. {
  536. const char* configName =
  537. target->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE");
  538. cmLocalNinjaGenerator *ng =
  539. static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
  540. switch (target->GetType()) {
  541. case cmTarget::EXECUTABLE:
  542. case cmTarget::SHARED_LIBRARY:
  543. case cmTarget::STATIC_LIBRARY:
  544. case cmTarget::MODULE_LIBRARY:
  545. outputs.push_back(ng->ConvertToNinjaPath(
  546. target->GetFullPath(configName).c_str()));
  547. break;
  548. case cmTarget::UTILITY: {
  549. std::string path = ng->ConvertToNinjaPath(
  550. target->GetMakefile()->GetStartOutputDirectory());
  551. if (path.empty() || path == ".")
  552. outputs.push_back(target->GetName());
  553. else {
  554. path += "/";
  555. path += target->GetName();
  556. outputs.push_back(path);
  557. }
  558. break;
  559. }
  560. case cmTarget::GLOBAL_TARGET:
  561. // Always use the target in HOME instead of an unused duplicate in a
  562. // subdirectory.
  563. outputs.push_back(target->GetName());
  564. break;
  565. default:
  566. return;
  567. }
  568. }
  569. void
  570. cmGlobalNinjaGenerator
  571. ::AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs)
  572. {
  573. if (target->GetType() == cmTarget::GLOBAL_TARGET) {
  574. // Global targets only depend on other utilities, which may not appear in
  575. // the TargetDepends set (e.g. "all").
  576. std::set<cmStdString> const& utils = target->GetUtilities();
  577. std::copy(utils.begin(), utils.end(), std::back_inserter(outputs));
  578. } else {
  579. cmTargetDependSet const& targetDeps =
  580. this->GetTargetDirectDepends(*target);
  581. for (cmTargetDependSet::const_iterator i = targetDeps.begin();
  582. i != targetDeps.end(); ++i) {
  583. this->AppendTargetOutputs(*i, outputs);
  584. }
  585. }
  586. }
  587. void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
  588. cmTarget* target) {
  589. cmNinjaDeps outputs;
  590. this->AppendTargetOutputs(target, outputs);
  591. // Mark the target's outputs as ambiguous to ensure that no other target uses
  592. // the output as an alias.
  593. for (cmNinjaDeps::iterator i = outputs.begin(); i != outputs.end(); ++i)
  594. TargetAliases[*i] = 0;
  595. // Insert the alias into the map. If the alias was already present in the
  596. // map and referred to another target, mark it as ambiguous.
  597. std::pair<TargetAliasMap::iterator, bool> newAlias =
  598. TargetAliases.insert(make_pair(alias, target));
  599. if (newAlias.second && newAlias.first->second != target)
  600. newAlias.first->second = 0;
  601. }
  602. void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
  603. {
  604. cmGlobalNinjaGenerator::WriteDivider(os);
  605. os << "# Target aliases.\n\n";
  606. for (TargetAliasMap::iterator i = TargetAliases.begin();
  607. i != TargetAliases.end(); ++i) {
  608. // Don't write ambiguous aliases.
  609. if (!i->second)
  610. continue;
  611. cmNinjaDeps deps;
  612. this->AppendTargetOutputs(i->second, deps);
  613. cmGlobalNinjaGenerator::WritePhonyBuild(os,
  614. "",
  615. cmNinjaDeps(1, i->first),
  616. deps);
  617. }
  618. }
  619. void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
  620. {
  621. // Write headers.
  622. cmGlobalNinjaGenerator::WriteDivider(os);
  623. os << "# Built-in targets\n\n";
  624. this->WriteTargetAll(os);
  625. this->WriteTargetRebuildManifest(os);
  626. }
  627. void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
  628. {
  629. cmNinjaDeps outputs;
  630. outputs.push_back("all");
  631. cmGlobalNinjaGenerator::WritePhonyBuild(os,
  632. "The main all target.",
  633. outputs,
  634. this->AllDependencies);
  635. cmGlobalNinjaGenerator::WriteDefault(os,
  636. outputs,
  637. "Make the all target the default.");
  638. }
  639. void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
  640. {
  641. cmMakefile* mfRoot = this->LocalGenerators[0]->GetMakefile();
  642. std::ostringstream cmd;
  643. cmd << mfRoot->GetRequiredDefinition("CMAKE_COMMAND")
  644. << " -H" << mfRoot->GetHomeDirectory()
  645. << " -B" << mfRoot->GetHomeOutputDirectory();
  646. WriteRule(*this->RulesFileStream,
  647. "RERUN_CMAKE",
  648. cmd.str(),
  649. "Re-running CMake...",
  650. "Rule for re-running cmake.",
  651. /*depfile=*/ "",
  652. /*restat=*/ false,
  653. /*generator=*/ true);
  654. cmNinjaDeps implicitDeps;
  655. for (std::vector<cmLocalGenerator *>::const_iterator i =
  656. this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i) {
  657. const std::vector<std::string>& lf = (*i)->GetMakefile()->GetListFiles();
  658. implicitDeps.insert(implicitDeps.end(), lf.begin(), lf.end());
  659. }
  660. std::sort(implicitDeps.begin(), implicitDeps.end());
  661. implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
  662. implicitDeps.end());
  663. implicitDeps.push_back("CMakeCache.txt");
  664. WriteBuild(os,
  665. "Re-run CMake if any of its inputs changed.",
  666. "RERUN_CMAKE",
  667. /*outputs=*/ cmNinjaDeps(1, NINJA_BUILD_FILE),
  668. /*explicitDeps=*/ cmNinjaDeps(),
  669. implicitDeps,
  670. /*orderOnlyDeps=*/ cmNinjaDeps(),
  671. /*variables=*/ cmNinjaVars());
  672. WritePhonyBuild(os,
  673. "A missing CMake input file is not an error.",
  674. implicitDeps,
  675. cmNinjaDeps());
  676. }