cmOSXBundleGenerator.cxx 7.8 KB

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