cmMakefileLibraryTargetGenerator.cxx 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  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 "cmMakefileLibraryTargetGenerator.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include "cmGlobalUnixMakefileGenerator3.h"
  16. #include "cmLocalUnixMakefileGenerator3.h"
  17. #include "cmMakefile.h"
  18. #include "cmSourceFile.h"
  19. #include "cmTarget.h"
  20. #include "cmake.h"
  21. #include <memory> // auto_ptr
  22. //----------------------------------------------------------------------------
  23. cmMakefileLibraryTargetGenerator
  24. ::cmMakefileLibraryTargetGenerator(cmTarget* target):
  25. cmMakefileTargetGenerator(target)
  26. {
  27. this->CustomCommandDriver = OnDepends;
  28. this->Target->GetLibraryNames(
  29. this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
  30. this->TargetNameImport, this->TargetNamePDB,
  31. this->LocalGenerator->ConfigurationName.c_str());
  32. if(this->Target->IsFrameworkOnApple())
  33. {
  34. this->FrameworkVersion = this->Target->GetFrameworkVersion();
  35. this->MacContentDirectory = this->Target->GetDirectory();
  36. this->MacContentDirectory += "/";
  37. this->MacContentDirectory += this->TargetNameOut;
  38. this->MacContentDirectory += ".framework/Versions/";
  39. this->MacContentDirectory += this->FrameworkVersion;
  40. this->MacContentDirectory += "/";
  41. }
  42. }
  43. //----------------------------------------------------------------------------
  44. void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
  45. {
  46. // create the build.make file and directory, put in the common blocks
  47. this->CreateRuleFile();
  48. // write rules used to help build object files
  49. this->WriteCommonCodeRules();
  50. // write in rules for object files and custom commands
  51. this->WriteTargetBuildRules();
  52. // write the per-target per-language flags
  53. this->WriteTargetLanguageFlags();
  54. // write the link rules
  55. // Write the rule for this target type.
  56. switch(this->Target->GetType())
  57. {
  58. case cmTarget::STATIC_LIBRARY:
  59. this->WriteStaticLibraryRules();
  60. break;
  61. case cmTarget::SHARED_LIBRARY:
  62. this->WriteSharedLibraryRules(false);
  63. if(this->Target->NeedRelinkBeforeInstall())
  64. {
  65. // Write rules to link an installable version of the target.
  66. this->WriteSharedLibraryRules(true);
  67. }
  68. break;
  69. case cmTarget::MODULE_LIBRARY:
  70. this->WriteModuleLibraryRules(false);
  71. if(this->Target->NeedRelinkBeforeInstall())
  72. {
  73. // Write rules to link an installable version of the target.
  74. this->WriteModuleLibraryRules(true);
  75. }
  76. break;
  77. default:
  78. // If language is not known, this is an error.
  79. cmSystemTools::Error("Unknown Library Type");
  80. break;
  81. }
  82. // Write the requires target.
  83. this->WriteTargetRequiresRules();
  84. // Write clean target
  85. this->WriteTargetCleanRules();
  86. // Write the dependency generation rule. This must be done last so
  87. // that multiple output pair information is available.
  88. this->WriteTargetDependRules();
  89. // close the streams
  90. this->CloseFileStreams();
  91. }
  92. //----------------------------------------------------------------------------
  93. void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
  94. {
  95. const char* linkLanguage =
  96. this->Target->GetLinkerLanguage(this->GlobalGenerator);
  97. std::string linkRuleVar = "CMAKE_";
  98. if (linkLanguage)
  99. {
  100. linkRuleVar += linkLanguage;
  101. }
  102. linkRuleVar += "_CREATE_STATIC_LIBRARY";
  103. std::string extraFlags;
  104. this->LocalGenerator->AppendFlags
  105. (extraFlags,this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
  106. this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
  107. }
  108. //----------------------------------------------------------------------------
  109. void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
  110. {
  111. if(this->Target->IsFrameworkOnApple())
  112. {
  113. this->WriteFrameworkRules(relink);
  114. return;
  115. }
  116. const char* linkLanguage =
  117. this->Target->GetLinkerLanguage(this->GlobalGenerator);
  118. std::string linkRuleVar = "CMAKE_";
  119. if (linkLanguage)
  120. {
  121. linkRuleVar += linkLanguage;
  122. }
  123. linkRuleVar += "_CREATE_SHARED_LIBRARY";
  124. std::string extraFlags;
  125. this->LocalGenerator->AppendFlags
  126. (extraFlags, this->Target->GetProperty("LINK_FLAGS"));
  127. std::string linkFlagsConfig = "LINK_FLAGS_";
  128. linkFlagsConfig +=
  129. cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName.c_str());
  130. this->LocalGenerator->AppendFlags
  131. (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
  132. this->LocalGenerator->AddConfigVariableFlags
  133. (extraFlags, "CMAKE_SHARED_LINKER_FLAGS",
  134. this->LocalGenerator->ConfigurationName.c_str());
  135. if(this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN")
  136. || this->Makefile->IsOn("MINGW")))
  137. {
  138. const std::vector<cmSourceFile*>& sources =
  139. this->Target->GetSourceFiles();
  140. for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
  141. i != sources.end(); ++i)
  142. {
  143. cmSourceFile* sf = *i;
  144. if(sf->GetExtension() == "def")
  145. {
  146. extraFlags += " ";
  147. extraFlags +=
  148. this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
  149. extraFlags +=
  150. this->Convert(sf->GetFullPath().c_str(),
  151. cmLocalGenerator::START_OUTPUT,
  152. cmLocalGenerator::SHELL);
  153. }
  154. }
  155. }
  156. this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
  157. }
  158. //----------------------------------------------------------------------------
  159. void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
  160. {
  161. const char* linkLanguage =
  162. this->Target->GetLinkerLanguage(this->GlobalGenerator);
  163. std::string linkRuleVar = "CMAKE_";
  164. if (linkLanguage)
  165. {
  166. linkRuleVar += linkLanguage;
  167. }
  168. linkRuleVar += "_CREATE_SHARED_MODULE";
  169. std::string extraFlags;
  170. this->LocalGenerator->AppendFlags(extraFlags,
  171. this->Target->GetProperty("LINK_FLAGS"));
  172. std::string linkFlagsConfig = "LINK_FLAGS_";
  173. linkFlagsConfig +=
  174. cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName.c_str());
  175. this->LocalGenerator->AppendFlags
  176. (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
  177. this->LocalGenerator->AddConfigVariableFlags
  178. (extraFlags, "CMAKE_MODULE_LINKER_FLAGS",
  179. this->LocalGenerator->ConfigurationName.c_str());
  180. // TODO: .def files should be supported here also.
  181. this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
  182. }
  183. //----------------------------------------------------------------------------
  184. void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
  185. {
  186. const char* linkLanguage =
  187. this->Target->GetLinkerLanguage(this->GlobalGenerator);
  188. std::string linkRuleVar = "CMAKE_";
  189. if (linkLanguage)
  190. {
  191. linkRuleVar += linkLanguage;
  192. }
  193. linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
  194. std::string extraFlags;
  195. this->LocalGenerator->AppendFlags(extraFlags,
  196. this->Target->GetProperty("LINK_FLAGS"));
  197. std::string linkFlagsConfig = "LINK_FLAGS_";
  198. linkFlagsConfig +=
  199. cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName.c_str());
  200. this->LocalGenerator->AppendFlags
  201. (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
  202. this->LocalGenerator->AddConfigVariableFlags
  203. (extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS",
  204. this->LocalGenerator->ConfigurationName.c_str());
  205. // TODO: .def files should be supported here also.
  206. this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
  207. }
  208. //----------------------------------------------------------------------------
  209. void cmMakefileLibraryTargetGenerator::CreateFramework()
  210. {
  211. // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
  212. // drive rules to create these files at build time.
  213. std::string oldName;
  214. std::string newName;
  215. // Compute the location of the top-level foo.framework directory.
  216. std::string top = this->Target->GetDirectory();
  217. top += "/";
  218. top += this->TargetNameOut;
  219. top += ".framework/";
  220. // Make foo.framework/Versions
  221. std::string versions = top;
  222. versions += "Versions";
  223. cmSystemTools::MakeDirectory(versions.c_str());
  224. // Make foo.framework/Versions/version
  225. std::string version = versions;
  226. version += "/";
  227. version += this->FrameworkVersion;
  228. cmSystemTools::MakeDirectory(version.c_str());
  229. // Current -> version
  230. oldName = this->FrameworkVersion;
  231. newName = versions;
  232. newName += "/Current";
  233. cmSystemTools::RemoveFile(newName.c_str());
  234. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  235. this->Makefile->AddCMakeOutputFile(newName.c_str());
  236. // foo -> Versions/Current/foo
  237. oldName = "Versions/Current/";
  238. oldName += this->TargetNameOut;
  239. newName = top;
  240. newName += this->TargetNameOut;
  241. cmSystemTools::RemoveFile(newName.c_str());
  242. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  243. this->Makefile->AddCMakeOutputFile(newName.c_str());
  244. // Resources -> Versions/Current/Resources
  245. if(this->MacContentFolders.find("Resources") !=
  246. this->MacContentFolders.end())
  247. {
  248. oldName = "Versions/Current/Resources";
  249. newName = top;
  250. newName += "Resources";
  251. cmSystemTools::RemoveFile(newName.c_str());
  252. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  253. this->Makefile->AddCMakeOutputFile(newName.c_str());
  254. }
  255. // Headers -> Versions/Current/Headers
  256. if(this->MacContentFolders.find("Headers") !=
  257. this->MacContentFolders.end())
  258. {
  259. oldName = "Versions/Current/Headers";
  260. newName = top;
  261. newName += "Headers";
  262. cmSystemTools::RemoveFile(newName.c_str());
  263. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  264. this->Makefile->AddCMakeOutputFile(newName.c_str());
  265. }
  266. // PrivateHeaders -> Versions/Current/PrivateHeaders
  267. if(this->MacContentFolders.find("PrivateHeaders") !=
  268. this->MacContentFolders.end())
  269. {
  270. oldName = "Versions/Current/PrivateHeaders";
  271. newName = top;
  272. newName += "PrivateHeaders";
  273. cmSystemTools::RemoveFile(newName.c_str());
  274. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  275. this->Makefile->AddCMakeOutputFile(newName.c_str());
  276. }
  277. }
  278. //----------------------------------------------------------------------------
  279. void cmMakefileLibraryTargetGenerator::WriteLibraryRules
  280. (const char* linkRuleVar, const char* extraFlags, bool relink)
  281. {
  282. // TODO: Merge the methods that call this method to avoid
  283. // code duplication.
  284. std::vector<std::string> commands;
  285. std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
  286. std::string objTarget;
  287. // Build list of dependencies.
  288. std::vector<std::string> depends;
  289. for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
  290. obj != this->Objects.end(); ++obj)
  291. {
  292. objTarget = relPath;
  293. objTarget += *obj;
  294. depends.push_back(objTarget);
  295. }
  296. // Add dependencies on targets that must be built first.
  297. this->AppendTargetDepends(depends);
  298. // Add a dependency on the rule file itself.
  299. this->LocalGenerator->AppendRuleDepend(depends,
  300. this->BuildFileNameFull.c_str());
  301. for(std::vector<std::string>::const_iterator obj
  302. = this->ExternalObjects.begin();
  303. obj != this->ExternalObjects.end(); ++obj)
  304. {
  305. depends.push_back(*obj);
  306. }
  307. // Get the language to use for linking this library.
  308. const char* linkLanguage =
  309. this->Target->GetLinkerLanguage(this->GlobalGenerator);
  310. // Make sure we have a link language.
  311. if(!linkLanguage)
  312. {
  313. cmSystemTools::Error("Cannot determine link language for target \"",
  314. this->Target->GetName(), "\".");
  315. return;
  316. }
  317. // Create set of linking flags.
  318. std::string linkFlags;
  319. this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
  320. // Add OSX version flags, if any.
  321. if(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
  322. this->Target->GetType() == cmTarget::MODULE_LIBRARY)
  323. {
  324. this->AppendOSXVerFlag(linkFlags, linkLanguage, "COMPATIBILITY", true);
  325. this->AppendOSXVerFlag(linkFlags, linkLanguage, "CURRENT", false);
  326. }
  327. // Construct the name of the library.
  328. std::string targetName;
  329. std::string targetNameSO;
  330. std::string targetNameReal;
  331. std::string targetNameImport;
  332. std::string targetNamePDB;
  333. this->Target->GetLibraryNames(
  334. targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB,
  335. this->LocalGenerator->ConfigurationName.c_str());
  336. // Construct the full path version of the names.
  337. std::string outpath;
  338. std::string outpathImp;
  339. if(this->Target->IsFrameworkOnApple())
  340. {
  341. outpath = this->MacContentDirectory;
  342. this->CreateFramework();
  343. }
  344. else if(relink)
  345. {
  346. outpath = this->Makefile->GetStartOutputDirectory();
  347. outpath += cmake::GetCMakeFilesDirectory();
  348. outpath += "/CMakeRelink.dir";
  349. cmSystemTools::MakeDirectory(outpath.c_str());
  350. outpath += "/";
  351. if(!targetNameImport.empty())
  352. {
  353. outpathImp = outpath;
  354. }
  355. }
  356. else
  357. {
  358. outpath = this->Target->GetDirectory();
  359. cmSystemTools::MakeDirectory(outpath.c_str());
  360. outpath += "/";
  361. if(!targetNameImport.empty())
  362. {
  363. outpathImp = this->Target->GetDirectory(0, true);
  364. cmSystemTools::MakeDirectory(outpathImp.c_str());
  365. outpathImp += "/";
  366. }
  367. }
  368. std::string targetFullPath = outpath + targetName;
  369. std::string targetFullPathPDB = outpath + targetNamePDB;
  370. std::string targetFullPathSO = outpath + targetNameSO;
  371. std::string targetFullPathReal = outpath + targetNameReal;
  372. std::string targetFullPathImport = outpathImp + targetNameImport;
  373. // Construct the output path version of the names for use in command
  374. // arguments.
  375. std::string targetOutPathPDB =
  376. this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::FULL,
  377. cmLocalGenerator::SHELL);
  378. std::string targetOutPath =
  379. this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
  380. cmLocalGenerator::SHELL);
  381. std::string targetOutPathSO =
  382. this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
  383. cmLocalGenerator::SHELL);
  384. std::string targetOutPathReal =
  385. this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
  386. cmLocalGenerator::SHELL);
  387. std::string targetOutPathImport =
  388. this->Convert(targetFullPathImport.c_str(),cmLocalGenerator::START_OUTPUT,
  389. cmLocalGenerator::SHELL);
  390. // Add the link message.
  391. std::string buildEcho = "Linking ";
  392. buildEcho += linkLanguage;
  393. const char* forbiddenFlagVar = 0;
  394. switch(this->Target->GetType())
  395. {
  396. case cmTarget::STATIC_LIBRARY:
  397. buildEcho += " static library ";
  398. break;
  399. case cmTarget::SHARED_LIBRARY:
  400. forbiddenFlagVar = "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
  401. buildEcho += " shared library ";
  402. break;
  403. case cmTarget::MODULE_LIBRARY:
  404. forbiddenFlagVar = "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
  405. buildEcho += " shared module ";
  406. break;
  407. default:
  408. buildEcho += " library ";
  409. break;
  410. }
  411. buildEcho += targetOutPath.c_str();
  412. this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
  413. cmLocalUnixMakefileGenerator3::EchoLink);
  414. // Construct a list of files associated with this library that may
  415. // need to be cleaned.
  416. std::vector<std::string> libCleanFiles;
  417. if(this->Target->GetPropertyAsBool("CLEAN_DIRECT_OUTPUT"))
  418. {
  419. // The user has requested that only the files directly built
  420. // by this target be cleaned instead of all possible names.
  421. libCleanFiles.push_back(this->Convert(targetFullPath.c_str(),
  422. cmLocalGenerator::START_OUTPUT,
  423. cmLocalGenerator::UNCHANGED));
  424. if(targetNameReal != targetName)
  425. {
  426. libCleanFiles.push_back(this->Convert(targetFullPathReal.c_str(),
  427. cmLocalGenerator::START_OUTPUT,
  428. cmLocalGenerator::UNCHANGED));
  429. }
  430. if(targetNameSO != targetName &&
  431. targetNameSO != targetNameReal)
  432. {
  433. libCleanFiles.push_back(this->Convert(targetFullPathSO.c_str(),
  434. cmLocalGenerator::START_OUTPUT,
  435. cmLocalGenerator::UNCHANGED));
  436. }
  437. if(!targetNameImport.empty())
  438. {
  439. libCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
  440. cmLocalGenerator::START_OUTPUT,
  441. cmLocalGenerator::UNCHANGED));
  442. }
  443. }
  444. else
  445. {
  446. // This target may switch between static and shared based
  447. // on a user option or the BUILD_SHARED_LIBS switch. Clean
  448. // all possible names.
  449. std::string cleanStaticName;
  450. std::string cleanSharedName;
  451. std::string cleanSharedSOName;
  452. std::string cleanSharedRealName;
  453. std::string cleanImportName;
  454. std::string cleanPDBName;
  455. this->Target->GetLibraryCleanNames(
  456. cleanStaticName,
  457. cleanSharedName,
  458. cleanSharedSOName,
  459. cleanSharedRealName,
  460. cleanImportName,
  461. cleanPDBName,
  462. this->LocalGenerator->ConfigurationName.c_str());
  463. std::string cleanFullStaticName = outpath + cleanStaticName;
  464. std::string cleanFullSharedName = outpath + cleanSharedName;
  465. std::string cleanFullSharedSOName = outpath + cleanSharedSOName;
  466. std::string cleanFullSharedRealName = outpath + cleanSharedRealName;
  467. std::string cleanFullImportName = outpathImp + cleanImportName;
  468. std::string cleanFullPDBName = outpath + cleanPDBName;
  469. libCleanFiles.push_back
  470. (this->Convert(cleanFullStaticName.c_str(),
  471. cmLocalGenerator::START_OUTPUT,
  472. cmLocalGenerator::UNCHANGED));
  473. if(cleanSharedRealName != cleanStaticName)
  474. {
  475. libCleanFiles.push_back(this->Convert(cleanFullSharedRealName.c_str(),
  476. cmLocalGenerator::START_OUTPUT,
  477. cmLocalGenerator::UNCHANGED));
  478. }
  479. if(cleanSharedSOName != cleanStaticName &&
  480. cleanSharedSOName != cleanSharedRealName)
  481. {
  482. libCleanFiles.push_back(this->Convert(cleanFullSharedSOName.c_str(),
  483. cmLocalGenerator::START_OUTPUT,
  484. cmLocalGenerator::UNCHANGED));
  485. }
  486. if(cleanSharedName != cleanStaticName &&
  487. cleanSharedName != cleanSharedSOName &&
  488. cleanSharedName != cleanSharedRealName)
  489. {
  490. libCleanFiles.push_back(this->Convert(cleanFullSharedName.c_str(),
  491. cmLocalGenerator::START_OUTPUT,
  492. cmLocalGenerator::UNCHANGED));
  493. }
  494. if(!cleanImportName.empty())
  495. {
  496. libCleanFiles.push_back(this->Convert(cleanFullImportName.c_str(),
  497. cmLocalGenerator::START_OUTPUT,
  498. cmLocalGenerator::UNCHANGED));
  499. }
  500. // List the PDB for cleaning only when the whole target is
  501. // cleaned. We do not want to delete the .pdb file just before
  502. // linking the target.
  503. this->CleanFiles.push_back
  504. (this->Convert(cleanFullPDBName.c_str(),
  505. cmLocalGenerator::START_OUTPUT,
  506. cmLocalGenerator::UNCHANGED));
  507. }
  508. #ifdef _WIN32
  509. // There may be a manifest file for this target. Add it to the
  510. // clean set just in case.
  511. if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
  512. {
  513. libCleanFiles.push_back(
  514. this->Convert((targetFullPath+".manifest").c_str(),
  515. cmLocalGenerator::START_OUTPUT,
  516. cmLocalGenerator::UNCHANGED));
  517. }
  518. #endif
  519. std::vector<std::string> commands1;
  520. // Add a command to remove any existing files for this library.
  521. // for static libs only
  522. if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
  523. {
  524. this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles,
  525. *this->Target, "target");
  526. this->LocalGenerator->CreateCDCommand
  527. (commands1,
  528. this->Makefile->GetStartOutputDirectory(),
  529. this->Makefile->GetHomeOutputDirectory());
  530. commands.insert(commands.end(), commands1.begin(), commands1.end());
  531. commands1.clear();
  532. }
  533. // Add the pre-build and pre-link rules building but not when relinking.
  534. if(!relink)
  535. {
  536. this->LocalGenerator
  537. ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
  538. this->LocalGenerator
  539. ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
  540. }
  541. // Determine whether a link script will be used.
  542. bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
  543. // Select whether to use a response file for objects.
  544. bool useResponseFile = false;
  545. {
  546. std::string responseVar = "CMAKE_";
  547. responseVar += linkLanguage;
  548. responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
  549. if(this->Makefile->IsOn(responseVar.c_str()))
  550. {
  551. useResponseFile = true;
  552. }
  553. }
  554. // For static libraries there might be archiving rules.
  555. std::vector<std::string> archiveCreateCommands;
  556. std::vector<std::string> archiveAppendCommands;
  557. std::vector<std::string> archiveFinishCommands;
  558. std::string::size_type archiveCommandLimit = std::string::npos;
  559. if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
  560. {
  561. std::string arCreateVar = "CMAKE_";
  562. arCreateVar += linkLanguage;
  563. arCreateVar += "_ARCHIVE_CREATE";
  564. if(const char* rule = this->Makefile->GetDefinition(arCreateVar.c_str()))
  565. {
  566. cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
  567. }
  568. std::string arAppendVar = "CMAKE_";
  569. arAppendVar += linkLanguage;
  570. arAppendVar += "_ARCHIVE_APPEND";
  571. if(const char* rule = this->Makefile->GetDefinition(arAppendVar.c_str()))
  572. {
  573. cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
  574. }
  575. std::string arFinishVar = "CMAKE_";
  576. arFinishVar += linkLanguage;
  577. arFinishVar += "_ARCHIVE_FINISH";
  578. if(const char* rule = this->Makefile->GetDefinition(arFinishVar.c_str()))
  579. {
  580. cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
  581. }
  582. }
  583. // Decide whether to use archiving rules.
  584. bool useArchiveRules =
  585. !archiveCreateCommands.empty() && !archiveAppendCommands.empty();
  586. if(useArchiveRules)
  587. {
  588. // Archiving rules are always run with a link script.
  589. useLinkScript = true;
  590. // Archiving rules never use a response file.
  591. useResponseFile = false;
  592. // Limit the length of individual object lists to less than the
  593. // 32K command line length limit on Windows. We could make this a
  594. // platform file variable but this should work everywhere.
  595. archiveCommandLimit = 30000;
  596. }
  597. // Expand the rule variables.
  598. std::vector<std::string> real_link_commands;
  599. {
  600. // Set path conversion for link script shells.
  601. this->LocalGenerator->SetLinkScriptShell(useLinkScript);
  602. // Collect up flags to link in needed libraries.
  603. cmOStringStream linklibs;
  604. if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
  605. {
  606. this->LocalGenerator
  607. ->OutputLinkLibraries(linklibs, *this->Target, relink);
  608. }
  609. // Construct object file lists that may be needed to expand the
  610. // rule.
  611. std::string variableName;
  612. std::string variableNameExternal;
  613. this->WriteObjectsVariable(variableName, variableNameExternal);
  614. std::string buildObjs;
  615. if(useResponseFile)
  616. {
  617. std::string objects;
  618. this->WriteObjectsString(objects);
  619. std::string objects_rsp =
  620. this->CreateResponseFile("objects.rsp", objects, depends);
  621. buildObjs = "@";
  622. buildObjs += this->Convert(objects_rsp.c_str(),
  623. cmLocalGenerator::NONE,
  624. cmLocalGenerator::SHELL);
  625. }
  626. else if(useLinkScript)
  627. {
  628. if(!useArchiveRules)
  629. {
  630. this->WriteObjectsString(buildObjs);
  631. }
  632. }
  633. else
  634. {
  635. buildObjs = "$(";
  636. buildObjs += variableName;
  637. buildObjs += ") $(";
  638. buildObjs += variableNameExternal;
  639. buildObjs += ")";
  640. }
  641. std::string cleanObjs = "$(";
  642. cleanObjs += variableName;
  643. cleanObjs += ")";
  644. cmLocalGenerator::RuleVariables vars;
  645. vars.TargetPDB = targetOutPathPDB.c_str();
  646. // Setup the target version.
  647. std::string targetVersionMajor;
  648. std::string targetVersionMinor;
  649. {
  650. cmOStringStream majorStream;
  651. cmOStringStream minorStream;
  652. int major;
  653. int minor;
  654. this->Target->GetTargetVersion(major, minor);
  655. majorStream << major;
  656. minorStream << minor;
  657. targetVersionMajor = majorStream.str();
  658. targetVersionMinor = minorStream.str();
  659. }
  660. vars.TargetVersionMajor = targetVersionMajor.c_str();
  661. vars.TargetVersionMinor = targetVersionMinor.c_str();
  662. vars.Language = linkLanguage;
  663. vars.Objects = buildObjs.c_str();
  664. std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash();
  665. objdir += this->Target->GetName();
  666. objdir += ".dir";
  667. objdir = this->Convert(objdir.c_str(),
  668. cmLocalGenerator::START_OUTPUT,
  669. cmLocalGenerator::SHELL);
  670. vars.ObjectDir = objdir.c_str();
  671. vars.Target = targetOutPathReal.c_str();
  672. std::string linkString = linklibs.str();
  673. vars.LinkLibraries = linkString.c_str();
  674. vars.ObjectsQuoted = buildObjs.c_str();
  675. vars.TargetSOName= targetNameSO.c_str();
  676. vars.LinkFlags = linkFlags.c_str();
  677. // Compute the directory portion of the install_name setting.
  678. std::string install_name_dir;
  679. if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
  680. {
  681. // Get the install_name directory for the build tree.
  682. const char* config = this->LocalGenerator->ConfigurationName.c_str();
  683. install_name_dir = this->Target->GetInstallNameDirForBuildTree(config);
  684. // Set the rule variable replacement value.
  685. if(install_name_dir.empty())
  686. {
  687. vars.TargetInstallNameDir = "";
  688. }
  689. else
  690. {
  691. // Convert to a path for the native build tool.
  692. install_name_dir =
  693. this->LocalGenerator->Convert(install_name_dir.c_str(),
  694. cmLocalGenerator::NONE,
  695. cmLocalGenerator::SHELL, false);
  696. vars.TargetInstallNameDir = install_name_dir.c_str();
  697. }
  698. }
  699. std::string langFlags;
  700. this->LocalGenerator
  701. ->AddLanguageFlags(langFlags, linkLanguage,
  702. this->LocalGenerator->ConfigurationName.c_str());
  703. // remove any language flags that might not work with the
  704. // particular os
  705. if(forbiddenFlagVar)
  706. {
  707. this->RemoveForbiddenFlags(forbiddenFlagVar,
  708. linkLanguage, langFlags);
  709. }
  710. vars.LanguageCompileFlags = langFlags.c_str();
  711. // Construct the main link rule and expand placeholders.
  712. this->LocalGenerator->TargetImplib = targetOutPathImport;
  713. if(useArchiveRules)
  714. {
  715. // Construct the individual object list strings.
  716. std::vector<std::string> object_strings;
  717. this->WriteObjectsStrings(object_strings, archiveCommandLimit);
  718. // Create the archive with the first set of objects.
  719. std::vector<std::string>::iterator osi = object_strings.begin();
  720. {
  721. vars.Objects = osi->c_str();
  722. for(std::vector<std::string>::const_iterator
  723. i = archiveCreateCommands.begin();
  724. i != archiveCreateCommands.end(); ++i)
  725. {
  726. std::string cmd = *i;
  727. this->LocalGenerator->ExpandRuleVariables(cmd, vars);
  728. real_link_commands.push_back(cmd);
  729. }
  730. }
  731. // Append to the archive with the other object sets.
  732. for(++osi; osi != object_strings.end(); ++osi)
  733. {
  734. vars.Objects = osi->c_str();
  735. for(std::vector<std::string>::const_iterator
  736. i = archiveAppendCommands.begin();
  737. i != archiveAppendCommands.end(); ++i)
  738. {
  739. std::string cmd = *i;
  740. this->LocalGenerator->ExpandRuleVariables(cmd, vars);
  741. real_link_commands.push_back(cmd);
  742. }
  743. }
  744. // Finish the archive.
  745. vars.Objects = "";
  746. for(std::vector<std::string>::const_iterator
  747. i = archiveFinishCommands.begin();
  748. i != archiveFinishCommands.end(); ++i)
  749. {
  750. std::string cmd = *i;
  751. this->LocalGenerator->ExpandRuleVariables(cmd, vars);
  752. real_link_commands.push_back(cmd);
  753. }
  754. }
  755. else
  756. {
  757. // Get the set of commands.
  758. std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
  759. cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
  760. // Expand placeholders.
  761. for(std::vector<std::string>::iterator i = real_link_commands.begin();
  762. i != real_link_commands.end(); ++i)
  763. {
  764. this->LocalGenerator->ExpandRuleVariables(*i, vars);
  765. }
  766. }
  767. this->LocalGenerator->TargetImplib = "";
  768. // Restore path conversion to normal shells.
  769. this->LocalGenerator->SetLinkScriptShell(false);
  770. }
  771. // Optionally convert the build rule to use a script to avoid long
  772. // command lines in the make shell.
  773. if(useLinkScript)
  774. {
  775. // Use a link script.
  776. const char* name = (relink? "relink.txt" : "link.txt");
  777. this->CreateLinkScript(name, real_link_commands, commands1, depends);
  778. }
  779. else
  780. {
  781. // No link script. Just use the link rule directly.
  782. commands1 = real_link_commands;
  783. }
  784. this->LocalGenerator->CreateCDCommand
  785. (commands1,
  786. this->Makefile->GetStartOutputDirectory(),
  787. this->Makefile->GetHomeOutputDirectory());
  788. commands.insert(commands.end(), commands1.begin(), commands1.end());
  789. commands1.clear();
  790. // Add a rule to create necessary symlinks for the library.
  791. if(targetOutPath != targetOutPathReal)
  792. {
  793. std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
  794. symlink += targetOutPathReal;
  795. symlink += " ";
  796. symlink += targetOutPathSO;
  797. symlink += " ";
  798. symlink += targetOutPath;
  799. commands1.push_back(symlink);
  800. this->LocalGenerator->CreateCDCommand(commands1,
  801. this->Makefile->GetStartOutputDirectory(),
  802. this->Makefile->GetHomeOutputDirectory());
  803. commands.insert(commands.end(), commands1.begin(), commands1.end());
  804. commands1.clear();
  805. }
  806. // Add the post-build rules when building but not when relinking.
  807. if(!relink)
  808. {
  809. this->LocalGenerator->
  810. AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
  811. }
  812. // Write the build rule.
  813. this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
  814. targetFullPathReal.c_str(),
  815. depends, commands, false);
  816. // Some targets have more than one output file. Create rules to
  817. // drive the build if any extra outputs are missing.
  818. std::vector<std::string> extraOutputs;
  819. if(targetNameSO != targetNameReal)
  820. {
  821. this->GenerateExtraOutput(targetFullPathSO.c_str(),
  822. targetFullPathReal.c_str());
  823. }
  824. if(targetName != targetNameSO &&
  825. targetName != targetNameReal)
  826. {
  827. this->GenerateExtraOutput(targetFullPath.c_str(),
  828. targetFullPathReal.c_str());
  829. }
  830. // Write the main driver rule to build everything in this target.
  831. this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
  832. // Clean all the possible library names and symlinks.
  833. this->CleanFiles.insert(this->CleanFiles.end(),
  834. libCleanFiles.begin(),libCleanFiles.end());
  835. }
  836. //----------------------------------------------------------------------------
  837. void
  838. cmMakefileLibraryTargetGenerator
  839. ::AppendOSXVerFlag(std::string& flags, const char* lang,
  840. const char* name, bool so)
  841. {
  842. // Lookup the flag to specify the version.
  843. std::string fvar = "CMAKE_";
  844. fvar += lang;
  845. fvar += "_OSX_";
  846. fvar += name;
  847. fvar += "_VERSION_FLAG";
  848. const char* flag = this->Makefile->GetDefinition(fvar.c_str());
  849. // Skip if no such flag.
  850. if(!flag)
  851. {
  852. return;
  853. }
  854. // Lookup the target version information.
  855. int major;
  856. int minor;
  857. int patch;
  858. this->Target->GetTargetVersion(so, major, minor, patch);
  859. if(major > 0 || minor > 0 || patch > 0)
  860. {
  861. // Append the flag since a non-zero version is specified.
  862. cmOStringStream vflag;
  863. vflag << flag << major << "." << minor << "." << patch;
  864. this->LocalGenerator->AppendFlags(flags, vflag.str().c_str());
  865. }
  866. }