cmCPackIFWInstaller.cxx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  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 <cmConfigure.h>
  5. #include <sstream>
  6. #include <stddef.h>
  7. #include <utility>
  8. #include "CPack/cmCPackGenerator.h"
  9. #include "CPack/cmCPackLog.h"
  10. #include "cmCPackIFWGenerator.h"
  11. #include "cmCPackIFWPackage.h"
  12. #include "cmCPackIFWRepository.h"
  13. #include "cmGeneratedFileStream.h"
  14. #include "cmSystemTools.h"
  15. #include "cmXMLParser.h"
  16. #include "cmXMLWriter.h"
  17. #ifdef cmCPackLogger
  18. #undef cmCPackLogger
  19. #endif
  20. #define cmCPackLogger(logType, msg) \
  21. do { \
  22. std::ostringstream cmCPackLog_msg; \
  23. cmCPackLog_msg << msg; \
  24. if (Generator) { \
  25. Generator->Logger->Log(logType, __FILE__, __LINE__, \
  26. cmCPackLog_msg.str().c_str()); \
  27. } \
  28. } while (false)
  29. cmCPackIFWInstaller::cmCPackIFWInstaller()
  30. : Generator(CM_NULLPTR)
  31. {
  32. }
  33. const char* cmCPackIFWInstaller::GetOption(const std::string& op) const
  34. {
  35. return Generator ? Generator->GetOption(op) : CM_NULLPTR;
  36. }
  37. bool cmCPackIFWInstaller::IsOn(const std::string& op) const
  38. {
  39. return Generator ? Generator->IsOn(op) : false;
  40. }
  41. bool cmCPackIFWInstaller::IsVersionLess(const char* version)
  42. {
  43. return Generator ? Generator->IsVersionLess(version) : false;
  44. }
  45. bool cmCPackIFWInstaller::IsVersionGreater(const char* version)
  46. {
  47. return Generator ? Generator->IsVersionGreater(version) : false;
  48. }
  49. bool cmCPackIFWInstaller::IsVersionEqual(const char* version)
  50. {
  51. return Generator ? Generator->IsVersionEqual(version) : false;
  52. }
  53. void cmCPackIFWInstaller::printSkippedOptionWarning(
  54. const std::string& optionName, const std::string& optionValue)
  55. {
  56. cmCPackLogger(
  57. cmCPackLog::LOG_WARNING, "Option "
  58. << optionName << " is set to \"" << optionValue
  59. << "\" but will be skipped because the specified file does not exist."
  60. << std::endl);
  61. }
  62. void cmCPackIFWInstaller::ConfigureFromOptions()
  63. {
  64. // Name;
  65. if (const char* optIFW_PACKAGE_NAME =
  66. this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
  67. Name = optIFW_PACKAGE_NAME;
  68. } else if (const char* optPACKAGE_NAME =
  69. this->GetOption("CPACK_PACKAGE_NAME")) {
  70. Name = optPACKAGE_NAME;
  71. } else {
  72. Name = "Your package";
  73. }
  74. // Title;
  75. if (const char* optIFW_PACKAGE_TITLE =
  76. GetOption("CPACK_IFW_PACKAGE_TITLE")) {
  77. Title = optIFW_PACKAGE_TITLE;
  78. } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY =
  79. GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
  80. Title = optPACKAGE_DESCRIPTION_SUMMARY;
  81. } else {
  82. Title = "Your package description";
  83. }
  84. // Version;
  85. if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) {
  86. Version = option;
  87. } else {
  88. Version = "1.0.0";
  89. }
  90. // Publisher
  91. if (const char* optIFW_PACKAGE_PUBLISHER =
  92. GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
  93. Publisher = optIFW_PACKAGE_PUBLISHER;
  94. } else if (const char* optPACKAGE_VENDOR =
  95. GetOption("CPACK_PACKAGE_VENDOR")) {
  96. Publisher = optPACKAGE_VENDOR;
  97. }
  98. // ProductUrl
  99. if (const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) {
  100. ProductUrl = option;
  101. }
  102. // ApplicationIcon
  103. if (const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) {
  104. if (cmSystemTools::FileExists(option)) {
  105. InstallerApplicationIcon = option;
  106. } else {
  107. printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option);
  108. }
  109. }
  110. // WindowIcon
  111. if (const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
  112. if (cmSystemTools::FileExists(option)) {
  113. InstallerWindowIcon = option;
  114. } else {
  115. printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option);
  116. }
  117. }
  118. // Logo
  119. if (const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) {
  120. if (cmSystemTools::FileExists(option)) {
  121. Logo = option;
  122. } else {
  123. printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option);
  124. }
  125. }
  126. // Watermark
  127. if (const char* option = GetOption("CPACK_IFW_PACKAGE_WATERMARK")) {
  128. if (cmSystemTools::FileExists(option)) {
  129. Watermark = option;
  130. } else {
  131. printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option);
  132. }
  133. }
  134. // Banner
  135. if (const char* option = GetOption("CPACK_IFW_PACKAGE_BANNER")) {
  136. if (cmSystemTools::FileExists(option)) {
  137. Banner = option;
  138. } else {
  139. printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option);
  140. }
  141. }
  142. // Background
  143. if (const char* option = GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) {
  144. if (cmSystemTools::FileExists(option)) {
  145. Background = option;
  146. } else {
  147. printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option);
  148. }
  149. }
  150. // WizardStyle
  151. if (const char* option = GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) {
  152. if (WizardStyle.compare("Modern") == 0 &&
  153. WizardStyle.compare("Aero") == 0 && WizardStyle.compare("Mac") == 0 &&
  154. WizardStyle.compare("Classic") == 0) {
  155. cmCPackLogger(
  156. cmCPackLog::LOG_WARNING,
  157. "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
  158. << option << "\". Expected values are: Modern, Aero, Mac, Classic."
  159. << std::endl);
  160. }
  161. WizardStyle = option;
  162. }
  163. // WizardDefaultWidth
  164. if (const char* option =
  165. GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
  166. WizardDefaultWidth = option;
  167. }
  168. // WizardDefaultHeight
  169. if (const char* option =
  170. GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) {
  171. WizardDefaultHeight = option;
  172. }
  173. // TitleColor
  174. if (const char* option = GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
  175. TitleColor = option;
  176. }
  177. // Start menu
  178. if (const char* optIFW_START_MENU_DIR =
  179. this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
  180. StartMenuDir = optIFW_START_MENU_DIR;
  181. } else {
  182. StartMenuDir = Name;
  183. }
  184. // Default target directory for installation
  185. if (const char* optIFW_TARGET_DIRECTORY =
  186. GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
  187. TargetDir = optIFW_TARGET_DIRECTORY;
  188. } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
  189. GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
  190. TargetDir = "@ApplicationsDir@/";
  191. TargetDir += optPACKAGE_INSTALL_DIRECTORY;
  192. } else {
  193. TargetDir = "@RootDir@/usr/local";
  194. }
  195. // Default target directory for installation with administrator rights
  196. if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
  197. AdminTargetDir = option;
  198. }
  199. // Maintenance tool
  200. if (const char* optIFW_MAINTENANCE_TOOL =
  201. this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) {
  202. MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
  203. }
  204. // Maintenance tool ini file
  205. if (const char* optIFW_MAINTENANCE_TOOL_INI =
  206. this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) {
  207. MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
  208. }
  209. // Allow non-ASCII characters
  210. if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
  211. if (IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
  212. AllowNonAsciiCharacters = "true";
  213. } else {
  214. AllowNonAsciiCharacters = "false";
  215. }
  216. }
  217. // Space in path
  218. if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
  219. if (IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
  220. AllowSpaceInPath = "true";
  221. } else {
  222. AllowSpaceInPath = "false";
  223. }
  224. }
  225. // Control script
  226. if (const char* optIFW_CONTROL_SCRIPT =
  227. this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
  228. ControlScript = optIFW_CONTROL_SCRIPT;
  229. }
  230. // Resources
  231. if (const char* optIFW_PACKAGE_RESOURCES =
  232. this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
  233. Resources.clear();
  234. cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, Resources);
  235. }
  236. }
  237. /** \class cmCPackIFWResourcesParser
  238. * \brief Helper class that parse resources form .qrc (Qt)
  239. */
  240. class cmCPackIFWResourcesParser : public cmXMLParser
  241. {
  242. public:
  243. cmCPackIFWResourcesParser(cmCPackIFWInstaller* i)
  244. : installer(i)
  245. , file(false)
  246. {
  247. path = i->Directory + "/resources";
  248. }
  249. bool ParseResource(size_t r)
  250. {
  251. hasFiles = false;
  252. hasErrors = false;
  253. basePath = cmSystemTools::GetFilenamePath(installer->Resources[r].data());
  254. ParseFile(installer->Resources[r].data());
  255. return hasFiles && !hasErrors;
  256. }
  257. cmCPackIFWInstaller* installer;
  258. bool file, hasFiles, hasErrors;
  259. std::string path, basePath;
  260. protected:
  261. void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
  262. {
  263. file = name == "file";
  264. if (file) {
  265. hasFiles = true;
  266. }
  267. }
  268. void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
  269. {
  270. if (file) {
  271. std::string content(data, data + length);
  272. content = cmSystemTools::TrimWhitespace(content);
  273. std::string source = basePath + "/" + content;
  274. std::string destination = path + "/" + content;
  275. if (!cmSystemTools::CopyFileIfDifferent(source.data(),
  276. destination.data())) {
  277. hasErrors = true;
  278. }
  279. }
  280. }
  281. void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
  282. };
  283. void cmCPackIFWInstaller::GenerateInstallerFile()
  284. {
  285. // Lazy directory initialization
  286. if (Directory.empty() && Generator) {
  287. Directory = Generator->toplevel;
  288. }
  289. // Output stream
  290. cmGeneratedFileStream fout((Directory + "/config/config.xml").data());
  291. cmXMLWriter xout(fout);
  292. xout.StartDocument();
  293. WriteGeneratedByToStrim(xout);
  294. xout.StartElement("Installer");
  295. xout.Element("Name", Name);
  296. xout.Element("Version", Version);
  297. xout.Element("Title", Title);
  298. if (!Publisher.empty()) {
  299. xout.Element("Publisher", Publisher);
  300. }
  301. if (!ProductUrl.empty()) {
  302. xout.Element("ProductUrl", ProductUrl);
  303. }
  304. // ApplicationIcon
  305. if (!InstallerApplicationIcon.empty()) {
  306. std::string name =
  307. cmSystemTools::GetFilenameName(InstallerApplicationIcon);
  308. std::string path = Directory + "/config/" + name;
  309. name = cmSystemTools::GetFilenameWithoutExtension(name);
  310. cmsys::SystemTools::CopyFileIfDifferent(InstallerApplicationIcon.data(),
  311. path.data());
  312. xout.Element("InstallerApplicationIcon", name);
  313. }
  314. // WindowIcon
  315. if (!InstallerWindowIcon.empty()) {
  316. std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon);
  317. std::string path = Directory + "/config/" + name;
  318. cmsys::SystemTools::CopyFileIfDifferent(InstallerWindowIcon.data(),
  319. path.data());
  320. xout.Element("InstallerWindowIcon", name);
  321. }
  322. // Logo
  323. if (!Logo.empty()) {
  324. std::string name = cmSystemTools::GetFilenameName(Logo);
  325. std::string path = Directory + "/config/" + name;
  326. cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data());
  327. xout.Element("Logo", name);
  328. }
  329. // Banner
  330. if (!Banner.empty()) {
  331. std::string name = cmSystemTools::GetFilenameName(Banner);
  332. std::string path = Directory + "/config/" + name;
  333. cmsys::SystemTools::CopyFileIfDifferent(Banner.data(), path.data());
  334. xout.Element("Banner", name);
  335. }
  336. // Watermark
  337. if (!Watermark.empty()) {
  338. std::string name = cmSystemTools::GetFilenameName(Watermark);
  339. std::string path = Directory + "/config/" + name;
  340. cmsys::SystemTools::CopyFileIfDifferent(Watermark.data(), path.data());
  341. xout.Element("Watermark", name);
  342. }
  343. // Background
  344. if (!Background.empty()) {
  345. std::string name = cmSystemTools::GetFilenameName(Background);
  346. std::string path = Directory + "/config/" + name;
  347. cmsys::SystemTools::CopyFileIfDifferent(Background.data(), path.data());
  348. xout.Element("Background", name);
  349. }
  350. // WizardStyle
  351. if (!WizardStyle.empty()) {
  352. xout.Element("WizardStyle", WizardStyle);
  353. }
  354. // WizardDefaultWidth
  355. if (!WizardDefaultWidth.empty()) {
  356. xout.Element("WizardDefaultWidth", WizardDefaultWidth);
  357. }
  358. // WizardDefaultHeight
  359. if (!WizardDefaultHeight.empty()) {
  360. xout.Element("WizardDefaultHeight", WizardDefaultHeight);
  361. }
  362. // TitleColor
  363. if (!TitleColor.empty()) {
  364. xout.Element("TitleColor", TitleColor);
  365. }
  366. // Start menu
  367. if (!IsVersionLess("2.0")) {
  368. xout.Element("StartMenuDir", StartMenuDir);
  369. }
  370. // Target dir
  371. if (!TargetDir.empty()) {
  372. xout.Element("TargetDir", TargetDir);
  373. }
  374. // Admin target dir
  375. if (!AdminTargetDir.empty()) {
  376. xout.Element("AdminTargetDir", AdminTargetDir);
  377. }
  378. // Remote repositories
  379. if (!RemoteRepositories.empty()) {
  380. xout.StartElement("RemoteRepositories");
  381. for (RepositoriesVector::iterator rit = RemoteRepositories.begin();
  382. rit != RemoteRepositories.end(); ++rit) {
  383. (*rit)->WriteRepositoryConfig(xout);
  384. }
  385. xout.EndElement();
  386. }
  387. // Maintenance tool
  388. if (!IsVersionLess("2.0") && !MaintenanceToolName.empty()) {
  389. xout.Element("MaintenanceToolName", MaintenanceToolName);
  390. }
  391. // Maintenance tool ini file
  392. if (!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) {
  393. xout.Element("MaintenanceToolIniFile", MaintenanceToolIniFile);
  394. }
  395. // Different allows
  396. if (IsVersionLess("2.0")) {
  397. // CPack IFW default policy
  398. xout.Comment("CPack IFW default policy for QtIFW less 2.0");
  399. xout.Element("AllowNonAsciiCharacters", "true");
  400. xout.Element("AllowSpaceInPath", "true");
  401. } else {
  402. if (!AllowNonAsciiCharacters.empty()) {
  403. xout.Element("AllowNonAsciiCharacters", AllowNonAsciiCharacters);
  404. }
  405. if (!AllowSpaceInPath.empty()) {
  406. xout.Element("AllowSpaceInPath", AllowSpaceInPath);
  407. }
  408. }
  409. // Control script (copy to config dir)
  410. if (!IsVersionLess("2.0") && !ControlScript.empty()) {
  411. std::string name = cmSystemTools::GetFilenameName(ControlScript);
  412. std::string path = Directory + "/config/" + name;
  413. cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data());
  414. xout.Element("ControlScript", name);
  415. }
  416. // Resources (copy to resources dir)
  417. if (!Resources.empty()) {
  418. std::vector<std::string> resources;
  419. cmCPackIFWResourcesParser parser(this);
  420. for (size_t i = 0; i < Resources.size(); i++) {
  421. if (parser.ParseResource(i)) {
  422. std::string name = cmSystemTools::GetFilenameName(Resources[i]);
  423. std::string path = Directory + "/resources/" + name;
  424. cmsys::SystemTools::CopyFileIfDifferent(Resources[i].data(),
  425. path.data());
  426. resources.push_back(name);
  427. } else {
  428. cmCPackLogger(cmCPackLog::LOG_WARNING, "Can't copy resources from \""
  429. << Resources[i] << "\". Resource will be skipped."
  430. << std::endl);
  431. }
  432. }
  433. Resources = resources;
  434. }
  435. xout.EndElement();
  436. xout.EndDocument();
  437. }
  438. void cmCPackIFWInstaller::GeneratePackageFiles()
  439. {
  440. if (Packages.empty() || Generator->IsOnePackage()) {
  441. // Generate default package
  442. cmCPackIFWPackage package;
  443. package.Generator = Generator;
  444. package.Installer = this;
  445. // Check package group
  446. if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) {
  447. package.ConfigureFromGroup(option);
  448. std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
  449. cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
  450. if (!GetOption(forcedOption)) {
  451. package.ForcedInstallation = "true";
  452. }
  453. } else {
  454. package.ConfigureFromOptions();
  455. }
  456. package.GeneratePackageFile();
  457. return;
  458. }
  459. // Generate packages meta information
  460. for (PackagesMap::iterator pit = Packages.begin(); pit != Packages.end();
  461. ++pit) {
  462. cmCPackIFWPackage* package = pit->second;
  463. package->GeneratePackageFile();
  464. }
  465. }
  466. void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmXMLWriter& xout)
  467. {
  468. if (Generator) {
  469. Generator->WriteGeneratedByToStrim(xout);
  470. }
  471. }