cmOSXBundleGenerator.cxx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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(cmTarget* target,
  18. const char* configName)
  19. : Target(target)
  20. , Makefile(target->GetMakefile())
  21. , LocalGenerator(Makefile->GetLocalGenerator())
  22. , ConfigName(configName)
  23. , MacContentFolders(0)
  24. {
  25. if (this->MustSkip())
  26. return;
  27. }
  28. //----------------------------------------------------------------------------
  29. bool cmOSXBundleGenerator::MustSkip()
  30. {
  31. return !this->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->Target->GetAppBundleDirectory(this->ConfigName, false);
  43. cmSystemTools::MakeDirectory(out.c_str());
  44. this->Makefile->AddCMakeOutputFile(out.c_str());
  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->Target->GetAppBundleDirectory(this->ConfigName, true);
  51. plist += "/Info.plist";
  52. this->LocalGenerator->GenerateAppleInfoPList(this->Target,
  53. targetName.c_str(),
  54. plist.c_str());
  55. this->Makefile->AddCMakeOutputFile(plist.c_str());
  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->Target->GetFrameworkDirectory(this->ConfigName, true);
  68. contentdir += "/";
  69. std::string newoutpath = outpath + "/" +
  70. this->Target->GetFrameworkDirectory(this->ConfigName, false);
  71. std::string frameworkVersion = this->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->Target,
  78. name.c_str(),
  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.c_str());
  95. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  96. this->Makefile->AddCMakeOutputFile(newName.c_str());
  97. // foo -> Versions/Current/foo
  98. oldName = "Versions/Current/";
  99. oldName += name;
  100. newName = contentdir;
  101. newName += name;
  102. cmSystemTools::RemoveFile(newName.c_str());
  103. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  104. this->Makefile->AddCMakeOutputFile(newName.c_str());
  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.c_str());
  113. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  114. this->Makefile->AddCMakeOutputFile(newName.c_str());
  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.c_str());
  124. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  125. this->Makefile->AddCMakeOutputFile(newName.c_str());
  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.c_str());
  135. cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
  136. this->Makefile->AddCMakeOutputFile(newName.c_str());
  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->Target->GetCFBundleDirectory(this->ConfigName, false);
  149. cmSystemTools::MakeDirectory(out.c_str());
  150. this->Makefile->AddCMakeOutputFile(out.c_str());
  151. // Configure the Info.plist file. Note that it needs the executable name
  152. // to be set.
  153. std::string plist =
  154. this->Target->GetCFBundleDirectory(this->ConfigName, true);
  155. plist += "/Info.plist";
  156. this->LocalGenerator->GenerateAppleInfoPList(this->Target,
  157. targetName.c_str(),
  158. plist.c_str());
  159. this->Makefile->AddCMakeOutputFile(plist.c_str());
  160. }
  161. //----------------------------------------------------------------------------
  162. void
  163. cmOSXBundleGenerator::
  164. GenerateMacOSXContentStatements(std::vector<cmSourceFile*> const& sources,
  165. MacOSXContentGeneratorType* generator)
  166. {
  167. if (this->MustSkip())
  168. return;
  169. for(std::vector<cmSourceFile*>::const_iterator
  170. si = sources.begin(); si != sources.end(); ++si)
  171. {
  172. cmTarget::SourceFileFlags tsFlags =
  173. this->Target->GetTargetSourceFileFlags(*si);
  174. if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
  175. {
  176. (*generator)(**si, tsFlags.MacFolder);
  177. }
  178. }
  179. }
  180. //----------------------------------------------------------------------------
  181. std::string
  182. cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
  183. {
  184. // Construct the full path to the content subdirectory.
  185. std::string macdir =
  186. this->Target->GetMacContentDirectory(this->ConfigName,
  187. /*implib*/ false);
  188. macdir += "/";
  189. macdir += pkgloc;
  190. cmSystemTools::MakeDirectory(macdir.c_str());
  191. // Record use of this content location. Only the first level
  192. // directory is needed.
  193. {
  194. std::string loc = pkgloc;
  195. loc = loc.substr(0, loc.find('/'));
  196. this->MacContentFolders->insert(loc);
  197. }
  198. return macdir;
  199. }