cmMakefileTargetGenerator.cxx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  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 "cmMakefileTargetGenerator.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include "cmGlobalGenerator.h"
  16. #include "cmGlobalUnixMakefileGenerator3.h"
  17. #include "cmLocalUnixMakefileGenerator3.h"
  18. #include "cmMakefile.h"
  19. #include "cmSourceFile.h"
  20. #include "cmTarget.h"
  21. #include "cmake.h"
  22. #include "cmMakefileExecutableTargetGenerator.h"
  23. #include "cmMakefileLibraryTargetGenerator.h"
  24. #include "cmMakefileUtilityTargetGenerator.h"
  25. cmMakefileTargetGenerator::cmMakefileTargetGenerator()
  26. {
  27. this->BuildFileStream = 0;
  28. this->InfoFileStream = 0;
  29. this->FlagFileStream = 0;
  30. }
  31. cmMakefileTargetGenerator *
  32. cmMakefileTargetGenerator::New(cmLocalUnixMakefileGenerator3 *lg,
  33. cmStdString tgtName, cmTarget *tgt)
  34. {
  35. cmMakefileTargetGenerator *result = 0;
  36. switch (tgt->GetType())
  37. {
  38. case cmTarget::EXECUTABLE:
  39. result = new cmMakefileExecutableTargetGenerator;
  40. break;
  41. case cmTarget::STATIC_LIBRARY:
  42. case cmTarget::SHARED_LIBRARY:
  43. case cmTarget::MODULE_LIBRARY:
  44. result = new cmMakefileLibraryTargetGenerator;
  45. break;
  46. case cmTarget::UTILITY:
  47. result = new cmMakefileUtilityTargetGenerator;
  48. break;
  49. default:
  50. return result;
  51. break;
  52. }
  53. result->TargetName = tgtName;
  54. result->Target = tgt;
  55. result->LocalGenerator = lg;
  56. result->GlobalGenerator = lg->GetGlobalGenerator();
  57. result->Makefile = lg->GetMakefile();
  58. return result;
  59. }
  60. //----------------------------------------------------------------------------
  61. void cmMakefileTargetGenerator::CreateRuleFile()
  62. {
  63. // Create a directory for this target.
  64. this->TargetBuildDirectory =
  65. this->LocalGenerator->GetTargetDirectory(*this->Target);
  66. this->TargetBuildDirectoryFull =
  67. this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
  68. cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
  69. // Construct the rule file name.
  70. this->BuildFileName = this->TargetBuildDirectory;
  71. this->BuildFileName += "/build.make";
  72. this->BuildFileNameFull = this->TargetBuildDirectoryFull;
  73. this->BuildFileNameFull += "/build.make";
  74. // Open the rule file. This should be copy-if-different because the
  75. // rules may depend on this file itself.
  76. this->BuildFileStream =
  77. new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
  78. this->BuildFileStream->SetCopyIfDifferent(true);
  79. if(!this->BuildFileStream)
  80. {
  81. return;
  82. }
  83. this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
  84. this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
  85. this->LocalGenerator->WriteMakeVariables(*this->BuildFileStream);
  86. }
  87. //----------------------------------------------------------------------------
  88. void cmMakefileTargetGenerator::WriteTargetBuildRules()
  89. {
  90. // write the custom commands for this target
  91. // Look for files registered for cleaning in this directory.
  92. if(const char* additional_clean_files =
  93. this->Makefile->GetProperty
  94. ("ADDITIONAL_MAKE_CLEAN_FILES"))
  95. {
  96. cmSystemTools::ExpandListArgument(additional_clean_files,
  97. this->CleanFiles);
  98. }
  99. // add custom commands to the clean rules?
  100. const char* clean_no_custom =
  101. this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
  102. bool clean = cmSystemTools::IsOff(clean_no_custom);
  103. // First generate the object rule files. Save a list of all object
  104. // files for this target.
  105. const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
  106. for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
  107. source != sources.end(); ++source)
  108. {
  109. if(cmCustomCommand* cc = (*source)->GetCustomCommand())
  110. {
  111. this->GenerateCustomRuleFile(*cc);
  112. if (clean)
  113. {
  114. const std::vector<std::string>& outputs = cc->GetOutputs();
  115. for(std::vector<std::string>::const_iterator o = outputs.begin();
  116. o != outputs.end(); ++o)
  117. {
  118. this->CleanFiles.push_back
  119. (this->Convert(o->c_str(),
  120. cmLocalGenerator::START_OUTPUT,
  121. cmLocalGenerator::UNCHANGED));
  122. }
  123. }
  124. }
  125. else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
  126. {
  127. if(!this->GlobalGenerator->IgnoreFile
  128. ((*source)->GetSourceExtension().c_str()))
  129. {
  130. // Generate this object file's rule file.
  131. this->WriteObjectRuleFiles(*(*source));
  132. }
  133. else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
  134. {
  135. // This is an external object file. Just add it.
  136. this->ExternalObjects.push_back((*source)->GetFullPath());
  137. }
  138. else
  139. {
  140. // We only get here if a source file is not an external object
  141. // and has an extension that is listed as an ignored file type
  142. // for this language. No message or diagnosis should be
  143. // given.
  144. }
  145. }
  146. }
  147. }
  148. //----------------------------------------------------------------------------
  149. void cmMakefileTargetGenerator::WriteCommonCodeRules()
  150. {
  151. // Include the dependencies for the target.
  152. std::string dependFileNameFull = this->TargetBuildDirectoryFull;
  153. dependFileNameFull += "/depend.make";
  154. *this->BuildFileStream
  155. << "# Include any dependencies generated for this target.\n"
  156. << this->LocalGenerator->IncludeDirective << " "
  157. << this->Convert(dependFileNameFull.c_str(),
  158. cmLocalGenerator::HOME_OUTPUT,
  159. cmLocalGenerator::MAKEFILE)
  160. << "\n\n";
  161. // make sure the depend file exists
  162. if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
  163. {
  164. // Write an empty dependency file.
  165. cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
  166. depFileStream
  167. << "# Empty dependencies file for " << this->Target->GetName() << ".\n"
  168. << "# This may be replaced when dependencies are built." << std::endl;
  169. }
  170. // Open the flags file. This should be copy-if-different because the
  171. // rules may depend on this file itself.
  172. this->FlagFileNameFull = this->TargetBuildDirectoryFull;
  173. this->FlagFileNameFull += "/flags.make";
  174. this->FlagFileStream =
  175. new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
  176. this->FlagFileStream->SetCopyIfDifferent(true);
  177. if(!this->FlagFileStream)
  178. {
  179. return;
  180. }
  181. this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
  182. // Include the flags for the target.
  183. *this->BuildFileStream
  184. << "# Include the compile flags for this target's objects.\n"
  185. << this->LocalGenerator->IncludeDirective << " "
  186. << this->Convert(this->FlagFileNameFull.c_str(),
  187. cmLocalGenerator::HOME_OUTPUT,
  188. cmLocalGenerator::MAKEFILE)
  189. << "\n\n";
  190. }
  191. //----------------------------------------------------------------------------
  192. void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
  193. {
  194. // write language flags for target
  195. std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
  196. checkSet =
  197. this->LocalGenerator->GetIntegrityCheckSet()[this->Target->GetName()];
  198. for(std::map<cmStdString,
  199. cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
  200. l = checkSet.begin(); l != checkSet.end(); ++l)
  201. {
  202. const char *lang = l->first.c_str();
  203. std::string flags;
  204. // Add the export symbol definition for shared library objects.
  205. bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
  206. (this->Target->GetType() == cmTarget::MODULE_LIBRARY));
  207. if(shared)
  208. {
  209. flags += "-D";
  210. if(const char* custom_export_name =
  211. this->Target->GetProperty("DEFINE_SYMBOL"))
  212. {
  213. flags += custom_export_name;
  214. }
  215. else
  216. {
  217. std::string in = this->Target->GetName();
  218. in += "_EXPORTS";
  219. flags += cmSystemTools::MakeCindentifier(in.c_str());
  220. }
  221. }
  222. // Add language-specific flags.
  223. this->LocalGenerator
  224. ->AddLanguageFlags(flags, lang,
  225. this->LocalGenerator->ConfigurationName.c_str());
  226. // Add shared-library flags if needed.
  227. this->LocalGenerator->AddSharedFlags(flags, lang, shared);
  228. // Add include directory flags.
  229. this->LocalGenerator->
  230. AppendFlags(flags, this->LocalGenerator->GetIncludeFlags(lang));
  231. // Add include directory flags.
  232. this->LocalGenerator->
  233. AppendFlags(flags,this->GetFrameworkFlags().c_str());
  234. *this->FlagFileStream << lang << "_FLAGS = " << flags << "\n\n";
  235. }
  236. }
  237. //----------------------------------------------------------------------------
  238. void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
  239. {
  240. // Identify the language of the source file.
  241. const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
  242. if(!lang)
  243. {
  244. // don't know anything about this file so skip it
  245. return;
  246. }
  247. // Get the full path name of the object file.
  248. std::string objNoTargetDir;
  249. std::string obj =
  250. this->LocalGenerator->GetObjectFileName(*this->Target, source,
  251. &objNoTargetDir);
  252. // Avoid generating duplicate rules.
  253. if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
  254. {
  255. this->ObjectFiles.insert(obj);
  256. }
  257. else
  258. {
  259. cmOStringStream err;
  260. err << "Warning: Source file \""
  261. << source.GetSourceName().c_str() << "."
  262. << source.GetSourceExtension().c_str()
  263. << "\" is listed multiple times for target \""
  264. << this->Target->GetName()
  265. << "\".";
  266. cmSystemTools::Message(err.str().c_str(), "Warning");
  267. return;
  268. }
  269. // Create the directory containing the object file. This may be a
  270. // subdirectory under the target's directory.
  271. std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
  272. cmSystemTools::MakeDirectory
  273. (this->LocalGenerator->ConvertToFullPath(dir).c_str());
  274. // Save this in the target's list of object files.
  275. if ( source.GetPropertyAsBool("EXTRA_CONTENT") )
  276. {
  277. this->ExtraContent.insert(obj);
  278. }
  279. this->Objects.push_back(obj);
  280. std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
  281. relativeObj += obj;
  282. // we compute some depends when writing the depend.make that we will also
  283. // use in the build.make, same with depMakeFile
  284. std::vector<std::string> depends;
  285. std::string depMakeFile;
  286. // generate the build rule file
  287. this->WriteObjectBuildFile(obj, lang, source, depends);
  288. // The object file should be checked for dependency integrity.
  289. this->LocalGenerator->
  290. CheckDependFiles[this->Target->GetName()][lang].insert(&source);
  291. // add this to the list of objects for this local generator
  292. if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
  293. {
  294. objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
  295. }
  296. this->LocalGenerator->LocalObjectFiles[objNoTargetDir].
  297. push_back(this->Target);
  298. }
  299. //----------------------------------------------------------------------------
  300. void
  301. cmMakefileTargetGenerator
  302. ::WriteObjectBuildFile(std::string &obj,
  303. const char *lang,
  304. cmSourceFile& source,
  305. std::vector<std::string>& depends)
  306. {
  307. this->LocalGenerator->AppendRuleDepend(depends,
  308. this->FlagFileNameFull.c_str());
  309. // generate the depend scanning rule
  310. this->WriteObjectDependRules(source, depends);
  311. std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
  312. relativeObj += obj;
  313. if(this->Makefile->GetDefinition("CMAKE_WINDOWS_OBJECT_PATH"))
  314. {
  315. relativeObj = cmSystemTools::ConvertToOutputPath(relativeObj.c_str());
  316. }
  317. // Write the build rule.
  318. // Build the set of compiler flags.
  319. std::string flags;
  320. // Add language-specific flags.
  321. std::string langFlags = "$(";
  322. langFlags += lang;
  323. langFlags += "_FLAGS)";
  324. this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
  325. // Add target-specific flags.
  326. if(this->Target->GetProperty("COMPILE_FLAGS"))
  327. {
  328. this->LocalGenerator->AppendFlags
  329. (flags, this->Target->GetProperty("COMPILE_FLAGS"));
  330. }
  331. // Add flags from source file properties.
  332. if (source.GetProperty("COMPILE_FLAGS"))
  333. {
  334. this->LocalGenerator->AppendFlags
  335. (flags, source.GetProperty("COMPILE_FLAGS"));
  336. *this->FlagFileStream << "# Custom flags: "
  337. << relativeObj << "_FLAGS = "
  338. << source.GetProperty("COMPILE_FLAGS")
  339. << "\n"
  340. << "\n";
  341. }
  342. // Get the output paths for source and object files.
  343. std::string sourceFile = source.GetFullPath();
  344. if(this->LocalGenerator->UseRelativePaths)
  345. {
  346. sourceFile = this->Convert(sourceFile.c_str(),
  347. cmLocalGenerator::HOME_OUTPUT);
  348. }
  349. sourceFile = this->Convert(sourceFile.c_str(),
  350. cmLocalGenerator::NONE,
  351. cmLocalGenerator::SHELL);
  352. std::string objectFile = this->Convert(obj.c_str(),
  353. cmLocalGenerator::START_OUTPUT,
  354. cmLocalGenerator::SHELL);
  355. // Construct the build message.
  356. std::vector<std::string> no_commands;
  357. std::vector<std::string> commands;
  358. // add in a progress call if needed
  359. cmGlobalUnixMakefileGenerator3* gg =
  360. static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  361. int prog = gg->ShouldAddProgressRule();
  362. std::string progressDir = this->Makefile->GetHomeOutputDirectory();
  363. progressDir += cmake::GetCMakeFilesDirectory();
  364. cmOStringStream progCmd;
  365. progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
  366. progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
  367. cmLocalGenerator::FULL,
  368. cmLocalGenerator::SHELL);
  369. if (prog)
  370. {
  371. progCmd << " " << prog;
  372. this->LocalGenerator->ProgressFiles[this->Target->GetName()].
  373. push_back(prog);
  374. }
  375. commands.push_back(progCmd.str());
  376. std::string buildEcho = "Building ";
  377. buildEcho += lang;
  378. buildEcho += " object ";
  379. buildEcho += relativeObj;
  380. this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
  381. cmLocalUnixMakefileGenerator3::EchoBuild);
  382. // Construct the compile rules.
  383. std::string compileRuleVar = "CMAKE_";
  384. compileRuleVar += lang;
  385. compileRuleVar += "_COMPILE_OBJECT";
  386. std::string compileRule =
  387. this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
  388. cmSystemTools::ExpandListArgument(compileRule, commands);
  389. std::string outpath = this->Makefile->GetStartOutputDirectory();
  390. outpath += "/";
  391. outpath += this->Target->GetName();
  392. outpath += ".pdb";
  393. outpath = this->Convert(outpath.c_str(), cmLocalGenerator::FULL,
  394. cmLocalGenerator::MAKEFILE);
  395. cmLocalGenerator::RuleVariables vars;
  396. vars.Language = lang;
  397. vars.TargetPDB = outpath.c_str();
  398. vars.Source = sourceFile.c_str();
  399. vars.Object = relativeObj.c_str();
  400. std::string objdir = this->LocalGenerator->GetHomeRelativeOutputPath();
  401. objdir = this->Convert(objdir.c_str(),
  402. cmLocalGenerator::START_OUTPUT,
  403. cmLocalGenerator::SHELL);
  404. std::string objectDir = cmSystemTools::GetFilenamePath(obj);
  405. vars.ObjectDir = objectDir.c_str();
  406. vars.Flags = flags.c_str();
  407. // Expand placeholders in the commands.
  408. for(std::vector<std::string>::iterator i = commands.begin();
  409. i != commands.end(); ++i)
  410. {
  411. this->LocalGenerator->ExpandRuleVariables(*i, vars);
  412. }
  413. // Make the target dependency scanning rule include cmake-time-known
  414. // dependencies. The others are handled by the check-build-system
  415. // path.
  416. std::string depMark =
  417. this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
  418. depMark += "/depend.make.mark";
  419. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  420. depMark.c_str(),
  421. depends, no_commands, false);
  422. // Write the rule.
  423. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  424. relativeObj.c_str(),
  425. depends, commands, false);
  426. // If the language needs provides-requires mode, create the
  427. // corresponding targets.
  428. std::string objectRequires = relativeObj;
  429. objectRequires += ".requires";
  430. std::vector<std::string> p_depends;
  431. // always provide an empty requires target
  432. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  433. objectRequires.c_str(), p_depends,
  434. no_commands, true);
  435. // write a build rule to recursively build what this obj provides
  436. std::string objectProvides = relativeObj;
  437. objectProvides += ".provides";
  438. std::string temp = relativeObj;
  439. temp += ".provides.build";
  440. std::vector<std::string> r_commands;
  441. std::string tgtMakefileName =
  442. this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
  443. tgtMakefileName += "/build.make";
  444. r_commands.push_back
  445. (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
  446. temp.c_str()));
  447. p_depends.clear();
  448. p_depends.push_back(objectRequires);
  449. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  450. objectProvides.c_str(), p_depends,
  451. r_commands, true);
  452. // write the provides.build rule dependency on the obj file
  453. p_depends.clear();
  454. p_depends.push_back(relativeObj);
  455. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  456. temp.c_str(), p_depends, no_commands,
  457. true);
  458. }
  459. //----------------------------------------------------------------------------
  460. void cmMakefileTargetGenerator::WriteTargetRequiresRules()
  461. {
  462. std::vector<std::string> depends;
  463. std::vector<std::string> no_commands;
  464. // Construct the name of the dependency generation target.
  465. std::string depTarget =
  466. this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
  467. depTarget += "/requires";
  468. // This target drives dependency generation for all object files.
  469. std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
  470. std::string objTarget;
  471. for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
  472. obj != this->Objects.end(); ++obj)
  473. {
  474. objTarget = relPath;
  475. objTarget += *obj;
  476. objTarget += ".requires";
  477. depends.push_back(objTarget);
  478. }
  479. // Write the rule.
  480. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  481. depTarget.c_str(),
  482. depends, no_commands, true);
  483. }
  484. //----------------------------------------------------------------------------
  485. void cmMakefileTargetGenerator::WriteTargetCleanRules()
  486. {
  487. std::vector<std::string> depends;
  488. std::vector<std::string> commands;
  489. // Construct the clean target name.
  490. std::string cleanTarget =
  491. this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
  492. cleanTarget += "/clean";
  493. // Construct the clean command.
  494. this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
  495. *this->Target);
  496. this->LocalGenerator->CreateCDCommand
  497. (commands,
  498. this->Makefile->GetStartOutputDirectory(),
  499. this->Makefile->GetHomeOutputDirectory());
  500. // Write the rule.
  501. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  502. cleanTarget.c_str(),
  503. depends, commands, true);
  504. }
  505. //----------------------------------------------------------------------------
  506. void cmMakefileTargetGenerator::WriteTargetDependRules()
  507. {
  508. // must write the targets depend info file
  509. std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
  510. this->InfoFileNameFull = dir;
  511. this->InfoFileNameFull += "/DependInfo.cmake";
  512. this->InfoFileNameFull =
  513. this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
  514. this->InfoFileStream =
  515. new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
  516. this->InfoFileStream->SetCopyIfDifferent(true);
  517. if(!*this->InfoFileStream)
  518. {
  519. return;
  520. }
  521. this->LocalGenerator->
  522. WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
  523. // and now write the rule to use it
  524. std::vector<std::string> depends;
  525. std::vector<std::string> commands;
  526. // Construct the name of the dependency generation target.
  527. std::string depTarget =
  528. this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
  529. depTarget += "/depend";
  530. std::string depMark = depTarget;
  531. depMark += ".make.mark";
  532. depends.push_back(depMark);
  533. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  534. depTarget.c_str(),
  535. depends, commands, true);
  536. depends.clear();
  537. // Write the dependency generation rule.
  538. std::string depEcho = "Scanning dependencies of target ";
  539. depEcho += this->Target->GetName();
  540. this->LocalGenerator->AppendEcho(commands, depEcho.c_str(),
  541. cmLocalUnixMakefileGenerator3::EchoDepend);
  542. // Add a command to call CMake to scan dependencies. CMake will
  543. // touch the corresponding depends file after scanning dependencies.
  544. cmOStringStream depCmd;
  545. // TODO: Account for source file properties and directory-level
  546. // definitions when scanning for dependencies.
  547. #if !defined(_WIN32) || defined(__CYGWIN__)
  548. // This platform supports symlinks, so cmSystemTools will translate
  549. // paths. Make sure PWD is set to the original name of the home
  550. // output directory to help cmSystemTools to create the same
  551. // translation table for the dependency scanning process.
  552. depCmd << "cd "
  553. << (this->LocalGenerator->Convert(
  554. this->Makefile->GetHomeOutputDirectory(),
  555. cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
  556. << " && ";
  557. #endif
  558. // Generate a call this signature:
  559. //
  560. // cmake -E cmake_depends <generator>
  561. // <home-src-dir> <start-src-dir>
  562. // <home-out-dir> <start-out-dir>
  563. // <dep-info>
  564. //
  565. // This gives the dependency scanner enough information to recreate
  566. // the state of our local generator sufficiently for its needs.
  567. depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
  568. << this->GlobalGenerator->GetName() << "\" "
  569. << this->Convert(this->Makefile->GetHomeDirectory(),
  570. cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
  571. << " "
  572. << this->Convert(this->Makefile->GetStartDirectory(),
  573. cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
  574. << " "
  575. << this->Convert(this->Makefile->GetHomeOutputDirectory(),
  576. cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
  577. << " "
  578. << this->Convert(this->Makefile->GetStartOutputDirectory(),
  579. cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
  580. << " "
  581. << this->Convert(this->InfoFileNameFull.c_str(),
  582. cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
  583. commands.push_back(depCmd.str());
  584. // Write the rule.
  585. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  586. depMark.c_str(),
  587. depends, commands, false);
  588. }
  589. //----------------------------------------------------------------------------
  590. void cmMakefileTargetGenerator
  591. ::WriteObjectDependRules(cmSourceFile& source,
  592. std::vector<std::string>& depends)
  593. {
  594. // Create the list of dependencies known at cmake time. These are
  595. // shared between the object file and dependency scanning rule.
  596. depends.push_back(source.GetFullPath());
  597. if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
  598. {
  599. std::vector<std::string> deps;
  600. cmSystemTools::ExpandListArgument(objectDeps, deps);
  601. for(std::vector<std::string>::iterator i = deps.begin();
  602. i != deps.end(); ++i)
  603. {
  604. depends.push_back(i->c_str());
  605. }
  606. }
  607. }
  608. //----------------------------------------------------------------------------
  609. void cmMakefileTargetGenerator
  610. ::GenerateCustomRuleFile(const cmCustomCommand& cc)
  611. {
  612. // Collect the commands.
  613. std::vector<std::string> commands;
  614. std::string comment = this->LocalGenerator->ConstructComment(cc);
  615. if(!comment.empty())
  616. {
  617. this->LocalGenerator
  618. ->AppendEcho(commands, comment.c_str(),
  619. cmLocalUnixMakefileGenerator3::EchoGenerate);
  620. }
  621. this->LocalGenerator->AppendCustomCommand(commands, cc);
  622. // Collect the dependencies.
  623. std::vector<std::string> depends;
  624. this->LocalGenerator->AppendCustomDepend(depends, cc);
  625. // Write the rule.
  626. const std::vector<std::string>& outputs = cc.GetOutputs();
  627. std::vector<std::string>::const_iterator o = outputs.begin();
  628. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  629. o->c_str(), depends, commands,
  630. false);
  631. // If the rule has multiple outputs, add a rule for the extra
  632. // outputs to just depend on the first output with no command. Also
  633. // register the extra outputs as paired with the first output so
  634. // that the check-build-system step will remove the primary output
  635. // if any extra outputs are missing, forcing the rule to regenerate
  636. // all outputs.
  637. depends.clear();
  638. depends.push_back(*o);
  639. commands.clear();
  640. cmGlobalUnixMakefileGenerator3* gg =
  641. static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  642. std::string emptyCommand = gg->GetEmptyCommandHack();
  643. if(!emptyCommand.empty())
  644. {
  645. commands.push_back(emptyCommand);
  646. }
  647. for(++o; o != outputs.end(); ++o)
  648. {
  649. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  650. o->c_str(), depends, commands,
  651. false);
  652. gg->AddMultipleOutputPair(o->c_str(), depends[0].c_str());
  653. }
  654. }
  655. //----------------------------------------------------------------------------
  656. void
  657. cmMakefileTargetGenerator
  658. ::WriteObjectsVariable(std::string& variableName,
  659. std::string& variableNameExternal)
  660. {
  661. // Write a make variable assignment that lists all objects for the
  662. // target.
  663. variableName =
  664. this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
  665. "_OBJECTS");
  666. *this->BuildFileStream
  667. << "# Object files for target " << this->Target->GetName() << "\n"
  668. << variableName.c_str() << " =";
  669. std::string object;
  670. const char* objName =
  671. this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
  672. const char* lineContinue =
  673. this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
  674. if(!lineContinue)
  675. {
  676. lineContinue = "\\";
  677. }
  678. for(std::vector<std::string>::const_iterator i = this->Objects.begin();
  679. i != this->Objects.end(); ++i)
  680. {
  681. if ( this->ExtraContent.find(i->c_str()) != this->ExtraContent.end() )
  682. {
  683. continue;
  684. }
  685. *this->BuildFileStream << " " << lineContinue << "\n";
  686. if(objName)
  687. {
  688. *this->BuildFileStream <<
  689. this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
  690. cmLocalGenerator::MAKEFILE);
  691. }
  692. else
  693. {
  694. *this->BuildFileStream <<
  695. this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
  696. }
  697. }
  698. *this->BuildFileStream << "\n";
  699. // Write a make variable assignment that lists all external objects
  700. // for the target.
  701. variableNameExternal =
  702. this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
  703. "_EXTERNAL_OBJECTS");
  704. *this->BuildFileStream
  705. << "\n"
  706. << "# External object files for target "
  707. << this->Target->GetName() << "\n"
  708. << variableNameExternal.c_str() << " =";
  709. for(std::vector<std::string>::const_iterator i =
  710. this->ExternalObjects.begin();
  711. i != this->ExternalObjects.end(); ++i)
  712. {
  713. object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
  714. *this->BuildFileStream
  715. << " " << lineContinue << "\n"
  716. << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
  717. if(objName)
  718. {
  719. *this->BuildFileStream <<
  720. this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
  721. cmLocalGenerator::MAKEFILE);
  722. }
  723. else
  724. {
  725. *this->BuildFileStream <<
  726. this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
  727. }
  728. }
  729. *this->BuildFileStream << "\n" << "\n";
  730. }
  731. //----------------------------------------------------------------------------
  732. void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
  733. bool relink)
  734. {
  735. // Compute the name of the driver target.
  736. std::string dir = this->Makefile->GetStartOutputDirectory();
  737. dir += "/";
  738. dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
  739. std::string buildTargetRuleName = dir;
  740. buildTargetRuleName += relink?"/preinstall":"/build";
  741. buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
  742. cmLocalGenerator::HOME_OUTPUT,
  743. cmLocalGenerator::MAKEFILE);
  744. // Build the list of target outputs to drive.
  745. std::vector<std::string> depends;
  746. if(main_output)
  747. {
  748. depends.push_back(main_output);
  749. }
  750. const char* comment = 0;
  751. if(relink)
  752. {
  753. // Setup the comment for the preinstall driver.
  754. comment = "Rule to relink during preinstall.";
  755. }
  756. else
  757. {
  758. // Setup the comment for the main build driver.
  759. comment = "Rule to build all files generated by this target.";
  760. // Make sure all custom command outputs in this target are built.
  761. const std::vector<cmSourceFile*>& sources =
  762. this->Target->GetSourceFiles();
  763. for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
  764. source != sources.end(); ++source)
  765. {
  766. if(cmCustomCommand* cc = (*source)->GetCustomCommand())
  767. {
  768. const std::vector<std::string>& outputs = cc->GetOutputs();
  769. for(std::vector<std::string>::const_iterator o = outputs.begin();
  770. o != outputs.end(); ++o)
  771. {
  772. depends.push_back(*o);
  773. }
  774. }
  775. }
  776. }
  777. // Write the driver rule.
  778. std::vector<std::string> no_commands;
  779. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
  780. buildTargetRuleName.c_str(),
  781. depends, no_commands, true);
  782. }
  783. //----------------------------------------------------------------------------
  784. std::string cmMakefileTargetGenerator::GetFrameworkFlags()
  785. {
  786. #ifndef __APPLE__
  787. return std::string();
  788. #else
  789. std::set<cmStdString> emitted;
  790. std::vector<std::string> includes;
  791. this->LocalGenerator->GetIncludeDirectories(includes);
  792. std::vector<std::string>::iterator i;
  793. // check all include directories for frameworks as this
  794. // will already have added a -F for the framework
  795. for(i = includes.begin(); i != includes.end(); ++i)
  796. {
  797. if(cmSystemTools::IsPathToFramework(i->c_str()))
  798. {
  799. std::string frameworkDir = *i;
  800. frameworkDir += "/../";
  801. frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
  802. emitted.insert(frameworkDir);
  803. }
  804. }
  805. std::string flags;
  806. std::vector<std::string>& frameworks = this->Target->GetFrameworks();
  807. for(i = frameworks.begin();
  808. i != frameworks.end(); ++i)
  809. {
  810. if(emitted.insert(*i).second)
  811. {
  812. flags += "-F";
  813. flags += this->LocalGenerator->ConvertToOutputForExisting(i->c_str());
  814. flags += " ";
  815. }
  816. }
  817. return flags;
  818. #endif
  819. }
  820. //----------------------------------------------------------------------------
  821. void cmMakefileTargetGenerator
  822. ::AppendTargetDepends(std::vector<std::string>& depends)
  823. {
  824. // Static libraries never depend on anything for linking.
  825. if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
  826. {
  827. return;
  828. }
  829. // Keep track of dependencies already listed.
  830. std::set<cmStdString> emitted;
  831. // A target should not depend on itself.
  832. emitted.insert(this->Target->GetName());
  833. // Loop over all library dependencies.
  834. const cmTarget::LinkLibraryVectorType& tlibs =
  835. this->Target->GetLinkLibraries();
  836. for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
  837. lib != tlibs.end(); ++lib)
  838. {
  839. // Don't emit the same library twice for this target.
  840. if(emitted.insert(lib->first).second)
  841. {
  842. // Depend only on other CMake targets.
  843. if(cmTarget* tgt =
  844. this->GlobalGenerator->FindTarget(0, lib->first.c_str()))
  845. {
  846. if(const char* location =
  847. tgt->GetLocation(this->LocalGenerator->ConfigurationName.c_str()))
  848. {
  849. depends.push_back(location);
  850. }
  851. }
  852. }
  853. }
  854. }
  855. //----------------------------------------------------------------------------
  856. void cmMakefileTargetGenerator
  857. ::CloseFileStreams()
  858. {
  859. delete this->BuildFileStream;
  860. delete this->InfoFileStream;
  861. delete this->FlagFileStream;
  862. }
  863. void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
  864. const char* linkLang,
  865. std::string& linkFlags)
  866. {
  867. // check for language flags that are not allowed at link time, and
  868. // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
  869. // which fails, there may be more]
  870. std::string removeFlags = "CMAKE_";
  871. removeFlags += linkLang;
  872. removeFlags += flagVar;
  873. std::string removeflags =
  874. this->Makefile->GetSafeDefinition(removeFlags.c_str());
  875. std::vector<std::string> removeList;
  876. cmSystemTools::ExpandListArgument(removeflags, removeList);
  877. for(std::vector<std::string>::iterator i = removeList.begin();
  878. i != removeList.end(); ++i)
  879. {
  880. cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
  881. }
  882. }