cmOSXBundleGenerator.cxx 7.6 KB

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