cmOSXBundleGenerator.cxx 7.2 KB

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