cmCPackIFWInstaller.cxx 12 KB

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