cmOSXBundleGenerator.cxx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmOSXBundleGenerator.h"
  4. #include "cmGeneratorTarget.h"
  5. #include "cmLocalGenerator.h"
  6. #include "cmMakefile.h"
  7. #include "cmStateTypes.h"
  8. #include "cmSystemTools.h"
  9. #include "cmTarget.h"
  10. #include <cassert>
  11. #include <utility>
  12. class cmSourceFile;
  13. cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target,
  14. std::string configName)
  15. : GT(target)
  16. , Makefile(target->Target->GetMakefile())
  17. , LocalGenerator(target->GetLocalGenerator())
  18. , ConfigName(std::move(configName))
  19. , MacContentFolders(nullptr)
  20. {
  21. if (this->MustSkip()) {
  22. return;
  23. }
  24. }
  25. bool cmOSXBundleGenerator::MustSkip()
  26. {
  27. return !this->GT->HaveWellDefinedOutputFiles();
  28. }
  29. void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
  30. std::string& outpath)
  31. {
  32. if (this->MustSkip()) {
  33. return;
  34. }
  35. // Compute bundle directory names.
  36. std::string out = outpath;
  37. out += "/";
  38. out += this->GT->GetAppBundleDirectory(this->ConfigName,
  39. cmGeneratorTarget::FullLevel);
  40. cmSystemTools::MakeDirectory(out);
  41. this->Makefile->AddCMakeOutputFile(out);
  42. // Configure the Info.plist file. Note that it needs the executable name
  43. // to be set.
  44. std::string plist = outpath;
  45. plist += "/";
  46. plist += this->GT->GetAppBundleDirectory(this->ConfigName,
  47. cmGeneratorTarget::ContentLevel);
  48. plist += "/Info.plist";
  49. this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist);
  50. this->Makefile->AddCMakeOutputFile(plist);
  51. outpath = out;
  52. }
  53. void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
  54. const std::string& outpath)
  55. {
  56. if (this->MustSkip()) {
  57. return;
  58. }
  59. assert(this->MacContentFolders);
  60. // Compute the location of the top-level foo.framework directory.
  61. std::string contentdir = outpath + "/" +
  62. this->GT->GetFrameworkDirectory(this->ConfigName,
  63. cmGeneratorTarget::ContentLevel);
  64. contentdir += "/";
  65. std::string newoutpath = outpath + "/" +
  66. this->GT->GetFrameworkDirectory(this->ConfigName,
  67. cmGeneratorTarget::FullLevel);
  68. std::string frameworkVersion = this->GT->GetFrameworkVersion();
  69. // Configure the Info.plist file
  70. std::string plist = newoutpath;
  71. if (!this->Makefile->PlatformIsAppleEmbedded()) {
  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, plist);
  79. // Generate Versions directory only for MacOSX frameworks
  80. if (this->Makefile->PlatformIsAppleEmbedded()) {
  81. return;
  82. }
  83. // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
  84. // drive rules to create these files at build time.
  85. std::string oldName;
  86. std::string newName;
  87. // Make foo.framework/Versions
  88. std::string versions = contentdir;
  89. versions += "Versions";
  90. cmSystemTools::MakeDirectory(versions);
  91. // Make foo.framework/Versions/version
  92. cmSystemTools::MakeDirectory(newoutpath);
  93. // Current -> version
  94. oldName = frameworkVersion;
  95. newName = versions;
  96. newName += "/Current";
  97. cmSystemTools::RemoveFile(newName);
  98. cmSystemTools::CreateSymlink(oldName, newName);
  99. this->Makefile->AddCMakeOutputFile(newName);
  100. // foo -> Versions/Current/foo
  101. oldName = "Versions/Current/";
  102. oldName += name;
  103. newName = contentdir;
  104. newName += name;
  105. cmSystemTools::RemoveFile(newName);
  106. cmSystemTools::CreateSymlink(oldName, newName);
  107. this->Makefile->AddCMakeOutputFile(newName);
  108. // Resources -> Versions/Current/Resources
  109. if (this->MacContentFolders->find("Resources") !=
  110. this->MacContentFolders->end()) {
  111. oldName = "Versions/Current/Resources";
  112. newName = contentdir;
  113. newName += "Resources";
  114. cmSystemTools::RemoveFile(newName);
  115. cmSystemTools::CreateSymlink(oldName, newName);
  116. this->Makefile->AddCMakeOutputFile(newName);
  117. }
  118. // Headers -> Versions/Current/Headers
  119. if (this->MacContentFolders->find("Headers") !=
  120. this->MacContentFolders->end()) {
  121. oldName = "Versions/Current/Headers";
  122. newName = contentdir;
  123. newName += "Headers";
  124. cmSystemTools::RemoveFile(newName);
  125. cmSystemTools::CreateSymlink(oldName, newName);
  126. this->Makefile->AddCMakeOutputFile(newName);
  127. }
  128. // PrivateHeaders -> Versions/Current/PrivateHeaders
  129. if (this->MacContentFolders->find("PrivateHeaders") !=
  130. this->MacContentFolders->end()) {
  131. oldName = "Versions/Current/PrivateHeaders";
  132. newName = contentdir;
  133. newName += "PrivateHeaders";
  134. cmSystemTools::RemoveFile(newName);
  135. cmSystemTools::CreateSymlink(oldName, newName);
  136. this->Makefile->AddCMakeOutputFile(newName);
  137. }
  138. }
  139. void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
  140. const std::string& root)
  141. {
  142. if (this->MustSkip()) {
  143. return;
  144. }
  145. // Compute bundle directory names.
  146. std::string out = root;
  147. out += "/";
  148. out += this->GT->GetCFBundleDirectory(this->ConfigName,
  149. cmGeneratorTarget::FullLevel);
  150. cmSystemTools::MakeDirectory(out);
  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 = root + "/" +
  155. this->GT->GetCFBundleDirectory(this->ConfigName,
  156. cmGeneratorTarget::ContentLevel);
  157. plist += "/Info.plist";
  158. std::string name = cmSystemTools::GetFilenameName(targetName);
  159. this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
  160. this->Makefile->AddCMakeOutputFile(plist);
  161. }
  162. void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
  163. std::vector<cmSourceFile const*> const& sources,
  164. MacOSXContentGeneratorType* generator)
  165. {
  166. if (this->MustSkip()) {
  167. return;
  168. }
  169. for (cmSourceFile const* source : sources) {
  170. cmGeneratorTarget::SourceFileFlags tsFlags =
  171. this->GT->GetTargetSourceFileFlags(source);
  172. if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
  173. (*generator)(*source, 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(
  182. this->ConfigName, cmStateEnums::RuntimeBinaryArtifact);
  183. macdir += "/";
  184. macdir += pkgloc;
  185. cmSystemTools::MakeDirectory(macdir);
  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. }