cmCPackIFWInstaller.cxx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmCPackIFWInstaller.h"
  4. #include "CPack/cmCPackGenerator.h"
  5. #include "CPack/cmCPackLog.h"
  6. #include "cmCPackIFWGenerator.h"
  7. #include "cmCPackIFWPackage.h"
  8. #include "cmCPackIFWRepository.h"
  9. #include "cmGeneratedFileStream.h"
  10. #include "cmSystemTools.h"
  11. #include "cmXMLParser.h"
  12. #include "cmXMLWriter.h"
  13. #include <cmConfigure.h>
  14. #include <utility>
  15. #ifdef cmCPackLogger
  16. #undef cmCPackLogger
  17. #endif
  18. #define cmCPackLogger(logType, msg) \
  19. do { \
  20. std::ostringstream cmCPackLog_msg; \
  21. cmCPackLog_msg << msg; \
  22. if (Generator) { \
  23. Generator->Logger->Log(logType, __FILE__, __LINE__, \
  24. cmCPackLog_msg.str().c_str()); \
  25. } \
  26. } while (0)
  27. cmCPackIFWInstaller::cmCPackIFWInstaller()
  28. : Generator(CM_NULLPTR)
  29. {
  30. }
  31. const char* cmCPackIFWInstaller::GetOption(const std::string& op) const
  32. {
  33. return Generator ? Generator->GetOption(op) : CM_NULLPTR;
  34. }
  35. bool cmCPackIFWInstaller::IsOn(const std::string& op) const
  36. {
  37. return Generator ? Generator->IsOn(op) : false;
  38. }
  39. bool cmCPackIFWInstaller::IsVersionLess(const char* version)
  40. {
  41. return Generator ? Generator->IsVersionLess(version) : false;
  42. }
  43. bool cmCPackIFWInstaller::IsVersionGreater(const char* version)
  44. {
  45. return Generator ? Generator->IsVersionGreater(version) : false;
  46. }
  47. bool cmCPackIFWInstaller::IsVersionEqual(const char* version)
  48. {
  49. return Generator ? Generator->IsVersionEqual(version) : false;
  50. }
  51. void cmCPackIFWInstaller::ConfigureFromOptions()
  52. {
  53. // Name;
  54. if (const char* optIFW_PACKAGE_NAME =
  55. this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
  56. Name = optIFW_PACKAGE_NAME;
  57. } else if (const char* optPACKAGE_NAME =
  58. this->GetOption("CPACK_PACKAGE_NAME")) {
  59. Name = optPACKAGE_NAME;
  60. } else {
  61. Name = "Your package";
  62. }
  63. // Title;
  64. if (const char* optIFW_PACKAGE_TITLE =
  65. GetOption("CPACK_IFW_PACKAGE_TITLE")) {
  66. Title = optIFW_PACKAGE_TITLE;
  67. } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY =
  68. GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
  69. Title = optPACKAGE_DESCRIPTION_SUMMARY;
  70. } else {
  71. Title = "Your package description";
  72. }
  73. // Version;
  74. if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) {
  75. Version = option;
  76. } else {
  77. Version = "1.0.0";
  78. }
  79. // Publisher
  80. if (const char* optIFW_PACKAGE_PUBLISHER =
  81. GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
  82. Publisher = optIFW_PACKAGE_PUBLISHER;
  83. } else if (const char* optPACKAGE_VENDOR =
  84. GetOption("CPACK_PACKAGE_VENDOR")) {
  85. Publisher = optPACKAGE_VENDOR;
  86. }
  87. // ProductUrl
  88. if (const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) {
  89. ProductUrl = option;
  90. }
  91. // ApplicationIcon
  92. if (const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) {
  93. if (cmSystemTools::FileExists(option)) {
  94. InstallerApplicationIcon = option;
  95. } else {
  96. // TODO: implement warning
  97. }
  98. }
  99. // WindowIcon
  100. if (const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
  101. if (cmSystemTools::FileExists(option)) {
  102. InstallerWindowIcon = option;
  103. } else {
  104. // TODO: implement warning
  105. }
  106. }
  107. // Logo
  108. if (const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) {
  109. if (cmSystemTools::FileExists(option)) {
  110. Logo = option;
  111. } else {
  112. // TODO: implement warning
  113. }
  114. }
  115. // Start menu
  116. if (const char* optIFW_START_MENU_DIR =
  117. this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
  118. StartMenuDir = optIFW_START_MENU_DIR;
  119. } else {
  120. StartMenuDir = Name;
  121. }
  122. // Default target directory for installation
  123. if (const char* optIFW_TARGET_DIRECTORY =
  124. GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
  125. TargetDir = optIFW_TARGET_DIRECTORY;
  126. } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
  127. GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
  128. TargetDir = "@ApplicationsDir@/";
  129. TargetDir += optPACKAGE_INSTALL_DIRECTORY;
  130. } else {
  131. TargetDir = "@RootDir@/usr/local";
  132. }
  133. // Default target directory for installation with administrator rights
  134. if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
  135. AdminTargetDir = option;
  136. }
  137. // Maintenance tool
  138. if (const char* optIFW_MAINTENANCE_TOOL =
  139. this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) {
  140. MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
  141. }
  142. // Maintenance tool ini file
  143. if (const char* optIFW_MAINTENANCE_TOOL_INI =
  144. this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) {
  145. MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
  146. }
  147. // Allow non-ASCII characters
  148. if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
  149. if (IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
  150. AllowNonAsciiCharacters = "true";
  151. } else {
  152. AllowNonAsciiCharacters = "false";
  153. }
  154. }
  155. // Space in path
  156. if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
  157. if (IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
  158. AllowSpaceInPath = "true";
  159. } else {
  160. AllowSpaceInPath = "false";
  161. }
  162. }
  163. // Control script
  164. if (const char* optIFW_CONTROL_SCRIPT =
  165. this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
  166. ControlScript = optIFW_CONTROL_SCRIPT;
  167. }
  168. // Resources
  169. if (const char* optIFW_PACKAGE_RESOURCES =
  170. this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
  171. Resources.clear();
  172. cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, Resources);
  173. }
  174. }
  175. /** \class cmCPackIFWResourcesParser
  176. * \brief Helper class that parse resources form .qrc (Qt)
  177. */
  178. class cmCPackIFWResourcesParser : public cmXMLParser
  179. {
  180. public:
  181. cmCPackIFWResourcesParser(cmCPackIFWInstaller* i)
  182. : installer(i)
  183. , file(false)
  184. {
  185. path = i->Directory + "/resources";
  186. }
  187. bool ParseResource(size_t r)
  188. {
  189. hasFiles = false;
  190. hasErrors = false;
  191. basePath = cmSystemTools::GetFilenamePath(installer->Resources[r].data());
  192. ParseFile(installer->Resources[r].data());
  193. return hasFiles && !hasErrors;
  194. }
  195. cmCPackIFWInstaller* installer;
  196. bool file, hasFiles, hasErrors;
  197. std::string path, basePath;
  198. protected:
  199. void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
  200. {
  201. file = name == "file";
  202. if (file) {
  203. hasFiles = true;
  204. }
  205. }
  206. void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
  207. {
  208. if (file) {
  209. std::string content(data, data + length);
  210. content = cmSystemTools::TrimWhitespace(content);
  211. std::string source = basePath + "/" + content;
  212. std::string destination = path + "/" + content;
  213. if (!cmSystemTools::CopyFileIfDifferent(source.data(),
  214. destination.data())) {
  215. hasErrors = true;
  216. }
  217. }
  218. }
  219. void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
  220. };
  221. void cmCPackIFWInstaller::GenerateInstallerFile()
  222. {
  223. // Lazy directory initialization
  224. if (Directory.empty() && Generator) {
  225. Directory = Generator->toplevel;
  226. }
  227. // Output stream
  228. cmGeneratedFileStream fout((Directory + "/config/config.xml").data());
  229. cmXMLWriter xout(fout);
  230. xout.StartDocument();
  231. WriteGeneratedByToStrim(xout);
  232. xout.StartElement("Installer");
  233. xout.Element("Name", Name);
  234. xout.Element("Version", Version);
  235. xout.Element("Title", Title);
  236. if (!Publisher.empty()) {
  237. xout.Element("Publisher", Publisher);
  238. }
  239. if (!ProductUrl.empty()) {
  240. xout.Element("ProductUrl", ProductUrl);
  241. }
  242. // ApplicationIcon
  243. if (!InstallerApplicationIcon.empty()) {
  244. std::string name =
  245. cmSystemTools::GetFilenameName(InstallerApplicationIcon);
  246. std::string path = Directory + "/config/" + name;
  247. name = cmSystemTools::GetFilenameWithoutExtension(name);
  248. cmsys::SystemTools::CopyFileIfDifferent(InstallerApplicationIcon.data(),
  249. path.data());
  250. xout.Element("InstallerApplicationIcon", name);
  251. }
  252. // WindowIcon
  253. if (!InstallerWindowIcon.empty()) {
  254. std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon);
  255. std::string path = Directory + "/config/" + name;
  256. cmsys::SystemTools::CopyFileIfDifferent(InstallerWindowIcon.data(),
  257. path.data());
  258. xout.Element("InstallerWindowIcon", name);
  259. }
  260. // Logo
  261. if (!Logo.empty()) {
  262. std::string name = cmSystemTools::GetFilenameName(Logo);
  263. std::string path = Directory + "/config/" + name;
  264. cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data());
  265. xout.Element("Logo", name);
  266. }
  267. // Start menu
  268. if (!IsVersionLess("2.0")) {
  269. xout.Element("StartMenuDir", StartMenuDir);
  270. }
  271. // Target dir
  272. if (!TargetDir.empty()) {
  273. xout.Element("TargetDir", TargetDir);
  274. }
  275. // Admin target dir
  276. if (!AdminTargetDir.empty()) {
  277. xout.Element("AdminTargetDir", AdminTargetDir);
  278. }
  279. // Remote repositories
  280. if (!RemoteRepositories.empty()) {
  281. xout.StartElement("RemoteRepositories");
  282. for (RepositoriesVector::iterator rit = RemoteRepositories.begin();
  283. rit != RemoteRepositories.end(); ++rit) {
  284. (*rit)->WriteRepositoryConfig(xout);
  285. }
  286. xout.EndElement();
  287. }
  288. // Maintenance tool
  289. if (!IsVersionLess("2.0") && !MaintenanceToolName.empty()) {
  290. xout.Element("MaintenanceToolName", MaintenanceToolName);
  291. }
  292. // Maintenance tool ini file
  293. if (!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) {
  294. xout.Element("MaintenanceToolIniFile", MaintenanceToolIniFile);
  295. }
  296. // Different allows
  297. if (IsVersionLess("2.0")) {
  298. // CPack IFW default policy
  299. xout.Comment("CPack IFW default policy for QtIFW less 2.0");
  300. xout.Element("AllowNonAsciiCharacters", "true");
  301. xout.Element("AllowSpaceInPath", "true");
  302. } else {
  303. if (!AllowNonAsciiCharacters.empty()) {
  304. xout.Element("AllowNonAsciiCharacters", AllowNonAsciiCharacters);
  305. }
  306. if (!AllowSpaceInPath.empty()) {
  307. xout.Element("AllowSpaceInPath", AllowSpaceInPath);
  308. }
  309. }
  310. // Control script (copy to config dir)
  311. if (!IsVersionLess("2.0") && !ControlScript.empty()) {
  312. std::string name = cmSystemTools::GetFilenameName(ControlScript);
  313. std::string path = Directory + "/config/" + name;
  314. cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data());
  315. xout.Element("ControlScript", name);
  316. }
  317. // Resources (copy to resources dir)
  318. if (!Resources.empty()) {
  319. std::vector<std::string> resources;
  320. cmCPackIFWResourcesParser parser(this);
  321. for (size_t i = 0; i < Resources.size(); i++) {
  322. if (parser.ParseResource(i)) {
  323. std::string name = cmSystemTools::GetFilenameName(Resources[i]);
  324. std::string path = Directory + "/resources/" + name;
  325. cmsys::SystemTools::CopyFileIfDifferent(Resources[i].data(),
  326. path.data());
  327. resources.push_back(name);
  328. } else {
  329. cmCPackLogger(cmCPackLog::LOG_WARNING, "Can't copy resources from \""
  330. << Resources[i] << "\". Resource will be skipped."
  331. << std::endl);
  332. }
  333. }
  334. Resources = resources;
  335. }
  336. xout.EndElement();
  337. xout.EndDocument();
  338. }
  339. void cmCPackIFWInstaller::GeneratePackageFiles()
  340. {
  341. if (Packages.empty() || Generator->IsOnePackage()) {
  342. // Generate default package
  343. cmCPackIFWPackage package;
  344. package.Generator = Generator;
  345. package.Installer = this;
  346. // Check package group
  347. if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) {
  348. package.ConfigureFromGroup(option);
  349. std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
  350. cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
  351. if (!GetOption(forcedOption)) {
  352. package.ForcedInstallation = "true";
  353. }
  354. } else {
  355. package.ConfigureFromOptions();
  356. }
  357. package.GeneratePackageFile();
  358. return;
  359. }
  360. // Generate packages meta information
  361. for (PackagesMap::iterator pit = Packages.begin(); pit != Packages.end();
  362. ++pit) {
  363. cmCPackIFWPackage* package = pit->second;
  364. package->GeneratePackageFile();
  365. }
  366. }
  367. void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmXMLWriter& xout)
  368. {
  369. if (Generator) {
  370. Generator->WriteGeneratedByToStrim(xout);
  371. }
  372. }