cmOSXBundleGenerator.cxx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. class cmSourceFile;
  12. cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target,
  13. const std::string& configName)
  14. : GT(target)
  15. , Makefile(target->Target->GetMakefile())
  16. , LocalGenerator(target->GetLocalGenerator())
  17. , ConfigName(configName)
  18. , MacContentFolders(nullptr)
  19. {
  20. if (this->MustSkip()) {
  21. return;
  22. }
  23. }
  24. bool cmOSXBundleGenerator::MustSkip()
  25. {
  26. return !this->GT->HaveWellDefinedOutputFiles();
  27. }
  28. void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
  29. std::string& outpath)
  30. {
  31. if (this->MustSkip()) {
  32. return;
  33. }
  34. // Compute bundle directory names.
  35. std::string out = outpath;
  36. out += "/";
  37. out += this->GT->GetAppBundleDirectory(this->ConfigName,
  38. cmGeneratorTarget::FullLevel);
  39. cmSystemTools::MakeDirectory(out);
  40. this->Makefile->AddCMakeOutputFile(out);
  41. // Configure the Info.plist file. Note that it needs the executable name
  42. // to be set.
  43. std::string plist = outpath;
  44. plist += "/";
  45. plist += this->GT->GetAppBundleDirectory(this->ConfigName,
  46. cmGeneratorTarget::ContentLevel);
  47. plist += "/Info.plist";
  48. this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName,
  49. plist.c_str());
  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,
  79. plist.c_str());
  80. // Generate Versions directory only for MacOSX frameworks
  81. if (this->Makefile->PlatformIsAppleEmbedded()) {
  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);
  92. // Make foo.framework/Versions/version
  93. cmSystemTools::MakeDirectory(newoutpath);
  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,
  150. cmGeneratorTarget::FullLevel);
  151. cmSystemTools::MakeDirectory(out);
  152. this->Makefile->AddCMakeOutputFile(out);
  153. // Configure the Info.plist file. Note that it needs the executable name
  154. // to be set.
  155. std::string plist = root + "/" +
  156. this->GT->GetCFBundleDirectory(this->ConfigName,
  157. cmGeneratorTarget::ContentLevel);
  158. plist += "/Info.plist";
  159. std::string name = cmSystemTools::GetFilenameName(targetName);
  160. this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist.c_str());
  161. this->Makefile->AddCMakeOutputFile(plist);
  162. }
  163. void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
  164. std::vector<cmSourceFile const*> const& sources,
  165. MacOSXContentGeneratorType* generator)
  166. {
  167. if (this->MustSkip()) {
  168. return;
  169. }
  170. for (cmSourceFile const* source : sources) {
  171. cmGeneratorTarget::SourceFileFlags tsFlags =
  172. this->GT->GetTargetSourceFileFlags(source);
  173. if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
  174. (*generator)(*source, tsFlags.MacFolder);
  175. }
  176. }
  177. }
  178. std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
  179. const char* pkgloc)
  180. {
  181. // Construct the full path to the content subdirectory.
  182. std::string macdir = this->GT->GetMacContentDirectory(
  183. this->ConfigName, cmStateEnums::RuntimeBinaryArtifact);
  184. macdir += "/";
  185. macdir += pkgloc;
  186. cmSystemTools::MakeDirectory(macdir);
  187. // Record use of this content location. Only the first level
  188. // directory is needed.
  189. {
  190. std::string loc = pkgloc;
  191. loc = loc.substr(0, loc.find('/'));
  192. this->MacContentFolders->insert(loc);
  193. }
  194. return macdir;
  195. }