cmOSXBundleGenerator.cxx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2012 Nicolas Despres <[email protected]>
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmOSXBundleGenerator.h"
  11. #include "cmLocalGenerator.h"
  12. #include "cmMakefile.h"
  13. #include "cmTarget.h"
  14. #include <cassert>
  15. cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target,
  16. const std::string& configName)
  17. : GT(target)
  18. , Makefile(target->Target->GetMakefile())
  19. , LocalGenerator(target->GetLocalGenerator())
  20. , ConfigName(configName)
  21. , MacContentFolders(0)
  22. {
  23. if (this->MustSkip()) {
  24. return;
  25. }
  26. }
  27. bool cmOSXBundleGenerator::MustSkip()
  28. {
  29. return !this->GT->HaveWellDefinedOutputFiles();
  30. }
  31. void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
  32. std::string& outpath)
  33. {
  34. if (this->MustSkip()) {
  35. return;
  36. }
  37. // Compute bundle directory names.
  38. std::string out = outpath;
  39. out += "/";
  40. out += this->GT->GetAppBundleDirectory(this->ConfigName, false);
  41. cmSystemTools::MakeDirectory(out.c_str());
  42. this->Makefile->AddCMakeOutputFile(out);
  43. std::string newoutpath = out;
  44. // Configure the Info.plist file. Note that it needs the executable name
  45. // to be set.
  46. std::string plist = outpath;
  47. plist += "/";
  48. plist += this->GT->GetAppBundleDirectory(this->ConfigName, true);
  49. plist += "/Info.plist";
  50. this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName,
  51. plist.c_str());
  52. this->Makefile->AddCMakeOutputFile(plist);
  53. outpath = newoutpath;
  54. }
  55. void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
  56. const std::string& outpath)
  57. {
  58. if (this->MustSkip()) {
  59. return;
  60. }
  61. assert(this->MacContentFolders);
  62. // Compute the location of the top-level foo.framework directory.
  63. std::string contentdir =
  64. outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, true);
  65. contentdir += "/";
  66. std::string newoutpath =
  67. outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, false);
  68. std::string frameworkVersion = this->GT->GetFrameworkVersion();
  69. // Configure the Info.plist file
  70. std::string plist = newoutpath;
  71. if (!this->Makefile->PlatformIsAppleIos()) {
  72. // Put the Info.plist file into the Resources directory.
  73. this->MacContentFolders->insert("Resources");
  74. plist += "/Resources";
  75. }
  76. plist += "/Info.plist";
  77. std::string name = cmSystemTools::GetFilenameName(targetName);
  78. this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name,
  79. plist.c_str());
  80. // Generate Versions directory only for MacOSX frameworks
  81. if (this->Makefile->PlatformIsAppleIos()) {
  82. return;
  83. }
  84. // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
  85. // drive rules to create these files at build time.
  86. std::string oldName;
  87. std::string newName;
  88. // Make foo.framework/Versions
  89. std::string versions = contentdir;
  90. versions += "Versions";
  91. cmSystemTools::MakeDirectory(versions.c_str());
  92. // Make foo.framework/Versions/version
  93. cmSystemTools::MakeDirectory(newoutpath.c_str());
  94. // Current -> version
  95. oldName = frameworkVersion;
  96. newName = versions;
  97. newName += "/Current";
  98. cmSystemTools::RemoveFile(newName);
  99. cmSystemTools::CreateSymlink(oldName, newName);
  100. this->Makefile->AddCMakeOutputFile(newName);
  101. // foo -> Versions/Current/foo
  102. oldName = "Versions/Current/";
  103. oldName += name;
  104. newName = contentdir;
  105. newName += name;
  106. cmSystemTools::RemoveFile(newName);
  107. cmSystemTools::CreateSymlink(oldName, newName);
  108. this->Makefile->AddCMakeOutputFile(newName);
  109. // Resources -> Versions/Current/Resources
  110. if (this->MacContentFolders->find("Resources") !=
  111. this->MacContentFolders->end()) {
  112. oldName = "Versions/Current/Resources";
  113. newName = contentdir;
  114. newName += "Resources";
  115. cmSystemTools::RemoveFile(newName);
  116. cmSystemTools::CreateSymlink(oldName, newName);
  117. this->Makefile->AddCMakeOutputFile(newName);
  118. }
  119. // Headers -> Versions/Current/Headers
  120. if (this->MacContentFolders->find("Headers") !=
  121. this->MacContentFolders->end()) {
  122. oldName = "Versions/Current/Headers";
  123. newName = contentdir;
  124. newName += "Headers";
  125. cmSystemTools::RemoveFile(newName);
  126. cmSystemTools::CreateSymlink(oldName, newName);
  127. this->Makefile->AddCMakeOutputFile(newName);
  128. }
  129. // PrivateHeaders -> Versions/Current/PrivateHeaders
  130. if (this->MacContentFolders->find("PrivateHeaders") !=
  131. this->MacContentFolders->end()) {
  132. oldName = "Versions/Current/PrivateHeaders";
  133. newName = contentdir;
  134. newName += "PrivateHeaders";
  135. cmSystemTools::RemoveFile(newName);
  136. cmSystemTools::CreateSymlink(oldName, newName);
  137. this->Makefile->AddCMakeOutputFile(newName);
  138. }
  139. }
  140. void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
  141. const std::string& root)
  142. {
  143. if (this->MustSkip()) {
  144. return;
  145. }
  146. // Compute bundle directory names.
  147. std::string out = root;
  148. out += "/";
  149. out += this->GT->GetCFBundleDirectory(this->ConfigName, false);
  150. cmSystemTools::MakeDirectory(out.c_str());
  151. this->Makefile->AddCMakeOutputFile(out);
  152. // Configure the Info.plist file. Note that it needs the executable name
  153. // to be set.
  154. std::string plist =
  155. root + "/" + this->GT->GetCFBundleDirectory(this->ConfigName, true);
  156. plist += "/Info.plist";
  157. std::string name = cmSystemTools::GetFilenameName(targetName);
  158. this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist.c_str());
  159. this->Makefile->AddCMakeOutputFile(plist);
  160. }
  161. void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
  162. std::vector<cmSourceFile const*> const& sources,
  163. MacOSXContentGeneratorType* generator)
  164. {
  165. if (this->MustSkip()) {
  166. return;
  167. }
  168. for (std::vector<cmSourceFile const*>::const_iterator si = sources.begin();
  169. si != sources.end(); ++si) {
  170. cmGeneratorTarget::SourceFileFlags tsFlags =
  171. this->GT->GetTargetSourceFileFlags(*si);
  172. if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
  173. (*generator)(**si, tsFlags.MacFolder);
  174. }
  175. }
  176. }
  177. std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
  178. const char* pkgloc)
  179. {
  180. // Construct the full path to the content subdirectory.
  181. std::string macdir = this->GT->GetMacContentDirectory(this->ConfigName,
  182. /*implib*/ false);
  183. macdir += "/";
  184. macdir += pkgloc;
  185. cmSystemTools::MakeDirectory(macdir.c_str());
  186. // Record use of this content location. Only the first level
  187. // directory is needed.
  188. {
  189. std::string loc = pkgloc;
  190. loc = loc.substr(0, loc.find('/'));
  191. this->MacContentFolders->insert(loc);
  192. }
  193. return macdir;
  194. }