cmCPackArchiveGenerator.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  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 "cmCPackArchiveGenerator.h"
  11. #include "cmake.h"
  12. #include "cmGlobalGenerator.h"
  13. #include "cmLocalGenerator.h"
  14. #include "cmSystemTools.h"
  15. #include "cmMakefile.h"
  16. #include "cmGeneratedFileStream.h"
  17. #include "cmCPackLog.h"
  18. #include <errno.h>
  19. #include <cmsys/SystemTools.hxx>
  20. #include <cmsys/Directory.hxx>
  21. #include <cm_libarchive.h>
  22. //----------------------------------------------------------------------
  23. cmCPackArchiveGenerator::cmCPackArchiveGenerator(cmArchiveWrite::Compress t,
  24. cmArchiveWrite::Type at)
  25. {
  26. this->Compress = t;
  27. this->Archive = at;
  28. }
  29. //----------------------------------------------------------------------
  30. cmCPackArchiveGenerator::~cmCPackArchiveGenerator()
  31. {
  32. }
  33. //----------------------------------------------------------------------
  34. int cmCPackArchiveGenerator::InitializeInternal()
  35. {
  36. this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
  37. return this->Superclass::InitializeInternal();
  38. }
  39. //----------------------------------------------------------------------
  40. int cmCPackArchiveGenerator::addOneComponentToArchive(cmArchiveWrite& archive,
  41. cmCPackComponent* component)
  42. {
  43. cmCPackLogger(cmCPackLog::LOG_VERBOSE, " - packaging component: "
  44. << component->Name
  45. << std::endl);
  46. // Add the files of this component to the archive
  47. std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
  48. localToplevel += "/"+ component->Name;
  49. std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
  50. // Change to local toplevel
  51. cmSystemTools::ChangeDirectory(localToplevel.c_str());
  52. std::string filePrefix;
  53. if (this->IsOn("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))
  54. {
  55. filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
  56. filePrefix += "/";
  57. }
  58. std::vector<std::string>::const_iterator fileIt;
  59. for (fileIt = component->Files.begin(); fileIt != component->Files.end();
  60. ++fileIt )
  61. {
  62. std::string rp = filePrefix + *fileIt;
  63. cmCPackLogger(cmCPackLog::LOG_DEBUG,"Adding file: "
  64. << rp << std::endl);
  65. archive.Add(rp);
  66. if (!archive)
  67. {
  68. cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging files: "
  69. << archive.GetError()
  70. << std::endl);
  71. return 0;
  72. }
  73. }
  74. // Go back to previous dir
  75. cmSystemTools::ChangeDirectory(dir.c_str());
  76. return 1;
  77. }
  78. /*
  79. * The macro will open/create a file 'filename'
  80. * an declare and open the associated
  81. * cmArchiveWrite 'archive' object.
  82. */
  83. #define DECLARE_AND_OPEN_ARCHIVE(filename,archive) \
  84. cmGeneratedFileStream gf; \
  85. gf.Open(filename.c_str(), false, true); \
  86. if (!GenerateHeader(&gf)) \
  87. { \
  88. cmCPackLogger(cmCPackLog::LOG_ERROR, \
  89. "Problem to generate Header for archive < " \
  90. << filename \
  91. << ">." << std::endl); \
  92. return 0; \
  93. } \
  94. cmArchiveWrite archive(gf,this->Compress, this->Archive); \
  95. if (!archive) \
  96. { \
  97. cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem to create archive < " \
  98. << filename \
  99. << ">. ERROR =" \
  100. << archive.GetError() \
  101. << std::endl); \
  102. return 0; \
  103. }
  104. //----------------------------------------------------------------------
  105. int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
  106. {
  107. packageFileNames.clear();
  108. // The default behavior is to have one package by component group
  109. // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
  110. if (!ignoreGroup)
  111. {
  112. std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
  113. for (compGIt=this->ComponentGroups.begin();
  114. compGIt!=this->ComponentGroups.end(); ++compGIt)
  115. {
  116. cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
  117. << compGIt->first
  118. << std::endl);
  119. // Begin the archive for this group
  120. std::string packageFileName= std::string(toplevel);
  121. packageFileName += "/"+
  122. GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
  123. compGIt->first,
  124. true)
  125. + this->GetOutputExtension();
  126. // open a block in order to automatically close archive
  127. // at the end of the block
  128. {
  129. DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive);
  130. // now iterate over the component of this group
  131. std::vector<cmCPackComponent*>::iterator compIt;
  132. for (compIt=(compGIt->second).Components.begin();
  133. compIt!=(compGIt->second).Components.end();
  134. ++compIt)
  135. {
  136. // Add the files of this component to the archive
  137. addOneComponentToArchive(archive,*compIt);
  138. }
  139. }
  140. // add the generated package to package file names list
  141. packageFileNames.push_back(packageFileName);
  142. }
  143. // Handle Orphan components (components not belonging to any groups)
  144. std::map<std::string, cmCPackComponent>::iterator compIt;
  145. for (compIt=this->Components.begin();
  146. compIt!=this->Components.end(); ++compIt )
  147. {
  148. // Does the component belong to a group?
  149. if (compIt->second.Group==NULL)
  150. {
  151. cmCPackLogger(cmCPackLog::LOG_VERBOSE,
  152. "Component <"
  153. << compIt->second.Name
  154. << "> does not belong to any group, package it separately."
  155. << std::endl);
  156. std::string localToplevel(
  157. this->GetOption("CPACK_TEMPORARY_DIRECTORY")
  158. );
  159. std::string packageFileName = std::string(toplevel);
  160. localToplevel += "/"+ compIt->first;
  161. packageFileName += "/"+
  162. GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
  163. compIt->first,
  164. false)
  165. + this->GetOutputExtension();
  166. {
  167. DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive);
  168. // Add the files of this component to the archive
  169. addOneComponentToArchive(archive,&(compIt->second));
  170. }
  171. // add the generated package to package file names list
  172. packageFileNames.push_back(packageFileName);
  173. }
  174. }
  175. }
  176. // CPACK_COMPONENTS_IGNORE_GROUPS is set
  177. // We build 1 package per component
  178. else
  179. {
  180. std::map<std::string, cmCPackComponent>::iterator compIt;
  181. for (compIt=this->Components.begin();
  182. compIt!=this->Components.end(); ++compIt )
  183. {
  184. std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
  185. std::string packageFileName = std::string(toplevel);
  186. localToplevel += "/"+ compIt->first;
  187. packageFileName += "/"+
  188. GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
  189. compIt->first,
  190. false)
  191. + this->GetOutputExtension();
  192. {
  193. DECLARE_AND_OPEN_ARCHIVE(packageFileName,archive);
  194. // Add the files of this component to the archive
  195. addOneComponentToArchive(archive,&(compIt->second));
  196. }
  197. // add the generated package to package file names list
  198. packageFileNames.push_back(packageFileName);
  199. }
  200. }
  201. return 1;
  202. }
  203. //----------------------------------------------------------------------
  204. int cmCPackArchiveGenerator::PackageComponentsAllInOne()
  205. {
  206. // reset the package file names
  207. packageFileNames.clear();
  208. packageFileNames.push_back(std::string(toplevel));
  209. packageFileNames[0] += "/"
  210. +std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME"))
  211. + this->GetOutputExtension();
  212. cmCPackLogger(cmCPackLog::LOG_VERBOSE,
  213. "Packaging all groups in one package..."
  214. "(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE is set)"
  215. << std::endl);
  216. DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive);
  217. // The ALL COMPONENTS in ONE package case
  218. std::map<std::string, cmCPackComponent>::iterator compIt;
  219. for (compIt=this->Components.begin();compIt!=this->Components.end();
  220. ++compIt )
  221. {
  222. // Add the files of this component to the archive
  223. addOneComponentToArchive(archive,&(compIt->second));
  224. }
  225. // archive goes out of scope so it will finalized and closed.
  226. return 1;
  227. }
  228. //----------------------------------------------------------------------
  229. int cmCPackArchiveGenerator::PackageFiles()
  230. {
  231. cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
  232. << toplevel << std::endl);
  233. if (SupportsComponentInstallation()) {
  234. // CASE 1 : COMPONENT ALL-IN-ONE package
  235. // If ALL COMPONENTS in ONE package has been requested
  236. // then the package file is unique and should be open here.
  237. if (componentPackageMethod == ONE_PACKAGE)
  238. {
  239. return PackageComponentsAllInOne();
  240. }
  241. // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
  242. // There will be 1 package for each component group
  243. // however one may require to ignore component group and
  244. // in this case you'll get 1 package for each component.
  245. else
  246. {
  247. return PackageComponents(componentPackageMethod ==
  248. ONE_PACKAGE_PER_COMPONENT);
  249. }
  250. }
  251. // CASE 3 : NON COMPONENT package.
  252. DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0],archive);
  253. std::vector<std::string>::const_iterator fileIt;
  254. std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
  255. cmSystemTools::ChangeDirectory(toplevel.c_str());
  256. for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt )
  257. {
  258. // Get the relative path to the file
  259. std::string rp = cmSystemTools::RelativePath(toplevel.c_str(),
  260. fileIt->c_str());
  261. archive.Add(rp);
  262. if(!archive)
  263. {
  264. cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem while adding file< "
  265. << *fileIt
  266. << "> to archive <"
  267. << packageFileNames[0] << "> .ERROR ="
  268. << archive.GetError()
  269. << std::endl);
  270. return 0;
  271. }
  272. }
  273. cmSystemTools::ChangeDirectory(dir.c_str());
  274. // The destructor of cmArchiveWrite will close and finish the write
  275. return 1;
  276. }
  277. //----------------------------------------------------------------------
  278. int cmCPackArchiveGenerator::GenerateHeader(std::ostream*)
  279. {
  280. return 1;
  281. }
  282. bool cmCPackArchiveGenerator::SupportsComponentInstallation() const {
  283. // The Component installation support should only
  284. // be activated if explicitly requested by the user
  285. // (for backward compatibility reason)
  286. if (IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL"))
  287. {
  288. return true;
  289. }
  290. else
  291. {
  292. return false;
  293. }
  294. }