cmCPackIFWPackage.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  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 "cmCPackIFWPackage.h"
  4. #include "cmCPackComponentGroup.h"
  5. #include "cmCPackIFWCommon.h"
  6. #include "cmCPackIFWGenerator.h"
  7. #include "cmCPackIFWInstaller.h"
  8. #include "cmCPackLog.h" // IWYU pragma: keep
  9. #include "cmGeneratedFileStream.h"
  10. #include "cmSystemTools.h"
  11. #include "cmTimestamp.h"
  12. #include "cmXMLWriter.h"
  13. #include <map>
  14. #include <sstream>
  15. #include <stddef.h>
  16. #include <utility>
  17. //---------------------------------------------------------- CompareStruct ---
  18. cmCPackIFWPackage::CompareStruct::CompareStruct()
  19. : Type(cmCPackIFWPackage::CompareNone)
  20. {
  21. }
  22. //------------------------------------------------------- DependenceStruct ---
  23. cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default;
  24. cmCPackIFWPackage::DependenceStruct::DependenceStruct(
  25. const std::string& dependence)
  26. {
  27. // Search compare section
  28. size_t pos = std::string::npos;
  29. if ((pos = dependence.find("<=")) != std::string::npos) {
  30. this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
  31. this->Compare.Value = dependence.substr(pos + 2);
  32. } else if ((pos = dependence.find(">=")) != std::string::npos) {
  33. this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
  34. this->Compare.Value = dependence.substr(pos + 2);
  35. } else if ((pos = dependence.find('<')) != std::string::npos) {
  36. this->Compare.Type = cmCPackIFWPackage::CompareLess;
  37. this->Compare.Value = dependence.substr(pos + 1);
  38. } else if ((pos = dependence.find('=')) != std::string::npos) {
  39. this->Compare.Type = cmCPackIFWPackage::CompareEqual;
  40. this->Compare.Value = dependence.substr(pos + 1);
  41. } else if ((pos = dependence.find('>')) != std::string::npos) {
  42. this->Compare.Type = cmCPackIFWPackage::CompareGreater;
  43. this->Compare.Value = dependence.substr(pos + 1);
  44. } else if ((pos = dependence.find('-')) != std::string::npos) {
  45. this->Compare.Type = cmCPackIFWPackage::CompareNone;
  46. this->Compare.Value = dependence.substr(pos + 1);
  47. }
  48. size_t dashPos = dependence.find('-');
  49. if (dashPos != std::string::npos) {
  50. pos = dashPos;
  51. }
  52. this->Name =
  53. pos == std::string::npos ? dependence : dependence.substr(0, pos);
  54. }
  55. std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
  56. {
  57. if (this->Compare.Type == cmCPackIFWPackage::CompareNone) {
  58. return this->Name;
  59. }
  60. std::string result = this->Name;
  61. if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
  62. !this->Compare.Value.empty()) {
  63. result += "-";
  64. }
  65. if (this->Compare.Type == cmCPackIFWPackage::CompareLessOrEqual) {
  66. result += "<=";
  67. } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreaterOrEqual) {
  68. result += ">=";
  69. } else if (this->Compare.Type == cmCPackIFWPackage::CompareLess) {
  70. result += "<";
  71. } else if (this->Compare.Type == cmCPackIFWPackage::CompareEqual) {
  72. result += "=";
  73. } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreater) {
  74. result += ">";
  75. }
  76. result += this->Compare.Value;
  77. return result;
  78. }
  79. //------------------------------------------------------ cmCPackIFWPackage ---
  80. cmCPackIFWPackage::cmCPackIFWPackage()
  81. : Installer(nullptr)
  82. {
  83. }
  84. std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component)
  85. {
  86. if (!component) {
  87. return "";
  88. }
  89. const char* option =
  90. this->GetOption("CPACK_IFW_COMPONENT_" +
  91. cmsys::SystemTools::UpperCase(component->Name) + "_NAME");
  92. return option ? option : component->Name;
  93. }
  94. void cmCPackIFWPackage::DefaultConfiguration()
  95. {
  96. this->DisplayName.clear();
  97. this->Description.clear();
  98. this->Version.clear();
  99. this->ReleaseDate.clear();
  100. this->Script.clear();
  101. this->Licenses.clear();
  102. this->UserInterfaces.clear();
  103. this->Translations.clear();
  104. this->SortingPriority.clear();
  105. this->UpdateText.clear();
  106. this->Default.clear();
  107. this->Essential.clear();
  108. this->Virtual.clear();
  109. this->ForcedInstallation.clear();
  110. this->RequiresAdminRights.clear();
  111. }
  112. // Default configuration (all in one package)
  113. int cmCPackIFWPackage::ConfigureFromOptions()
  114. {
  115. // Restore default configuration
  116. this->DefaultConfiguration();
  117. // Name
  118. this->Name = this->Generator->GetRootPackageName();
  119. // Display name
  120. if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) {
  121. this->DisplayName[""] = option;
  122. } else {
  123. this->DisplayName[""] = "Your package";
  124. }
  125. // Description
  126. if (const char* option =
  127. this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
  128. this->Description[""] = option;
  129. } else {
  130. this->Description[""] = "Your package description";
  131. }
  132. // Version
  133. if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) {
  134. this->Version = option;
  135. } else {
  136. this->Version = "1.0.0";
  137. }
  138. this->ForcedInstallation = "true";
  139. return 1;
  140. }
  141. int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
  142. {
  143. if (!component) {
  144. return 0;
  145. }
  146. // Restore default configuration
  147. this->DefaultConfiguration();
  148. std::string prefix = "CPACK_IFW_COMPONENT_" +
  149. cmsys::SystemTools::UpperCase(component->Name) + "_";
  150. // Display name
  151. this->DisplayName[""] = component->DisplayName;
  152. // Description
  153. this->Description[""] = component->Description;
  154. // Version
  155. if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
  156. this->Version = optVERSION;
  157. } else if (const char* optPACKAGE_VERSION =
  158. this->GetOption("CPACK_PACKAGE_VERSION")) {
  159. this->Version = optPACKAGE_VERSION;
  160. } else {
  161. this->Version = "1.0.0";
  162. }
  163. // Script
  164. if (const char* option = this->GetOption(prefix + "SCRIPT")) {
  165. this->Script = option;
  166. }
  167. // User interfaces
  168. if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
  169. this->UserInterfaces.clear();
  170. cmSystemTools::ExpandListArgument(option, this->UserInterfaces);
  171. }
  172. // CMake dependencies
  173. if (!component->Dependencies.empty()) {
  174. for (cmCPackComponent* dep : component->Dependencies) {
  175. this->Dependencies.insert(this->Generator->ComponentPackages[dep]);
  176. }
  177. }
  178. // Licenses
  179. if (const char* option = this->GetOption(prefix + "LICENSES")) {
  180. this->Licenses.clear();
  181. cmSystemTools::ExpandListArgument(option, this->Licenses);
  182. if (this->Licenses.size() % 2 != 0) {
  183. cmCPackIFWLogger(
  184. WARNING,
  185. prefix << "LICENSES"
  186. << " should contain pairs of <display_name> and <file_path>."
  187. << std::endl);
  188. this->Licenses.clear();
  189. }
  190. }
  191. // Priority
  192. if (const char* option = this->GetOption(prefix + "PRIORITY")) {
  193. this->SortingPriority = option;
  194. cmCPackIFWLogger(
  195. WARNING,
  196. "The \"PRIORITY\" option is set "
  197. << "for component \"" << component->Name << "\", but there option is "
  198. << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
  199. << std::endl);
  200. }
  201. // Default
  202. this->Default = component->IsDisabledByDefault ? "false" : "true";
  203. // Essential
  204. if (this->IsOn(prefix + "ESSENTIAL")) {
  205. this->Essential = "true";
  206. }
  207. // Virtual
  208. this->Virtual = component->IsHidden ? "true" : "";
  209. // ForcedInstallation
  210. this->ForcedInstallation = component->IsRequired ? "true" : "false";
  211. return this->ConfigureFromPrefix(prefix);
  212. }
  213. int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
  214. {
  215. if (!group) {
  216. return 0;
  217. }
  218. // Restore default configuration
  219. this->DefaultConfiguration();
  220. std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" +
  221. cmsys::SystemTools::UpperCase(group->Name) + "_";
  222. this->DisplayName[""] = group->DisplayName;
  223. this->Description[""] = group->Description;
  224. // Version
  225. if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
  226. this->Version = optVERSION;
  227. } else if (const char* optPACKAGE_VERSION =
  228. this->GetOption("CPACK_PACKAGE_VERSION")) {
  229. this->Version = optPACKAGE_VERSION;
  230. } else {
  231. this->Version = "1.0.0";
  232. }
  233. // Script
  234. if (const char* option = this->GetOption(prefix + "SCRIPT")) {
  235. this->Script = option;
  236. }
  237. // User interfaces
  238. if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
  239. this->UserInterfaces.clear();
  240. cmSystemTools::ExpandListArgument(option, this->UserInterfaces);
  241. }
  242. // Licenses
  243. if (const char* option = this->GetOption(prefix + "LICENSES")) {
  244. this->Licenses.clear();
  245. cmSystemTools::ExpandListArgument(option, this->Licenses);
  246. if (this->Licenses.size() % 2 != 0) {
  247. cmCPackIFWLogger(
  248. WARNING,
  249. prefix << "LICENSES"
  250. << " should contain pairs of <display_name> and <file_path>."
  251. << std::endl);
  252. this->Licenses.clear();
  253. }
  254. }
  255. // Priority
  256. if (const char* option = this->GetOption(prefix + "PRIORITY")) {
  257. this->SortingPriority = option;
  258. cmCPackIFWLogger(
  259. WARNING,
  260. "The \"PRIORITY\" option is set "
  261. << "for component group \"" << group->Name
  262. << "\", but there option is "
  263. << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
  264. << std::endl);
  265. }
  266. return this->ConfigureFromPrefix(prefix);
  267. }
  268. int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName)
  269. {
  270. // Group configuration
  271. cmCPackComponentGroup group;
  272. std::string prefix =
  273. "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_";
  274. if (const char* option = this->GetOption(prefix + "DISPLAY_NAME")) {
  275. group.DisplayName = option;
  276. } else {
  277. group.DisplayName = group.Name;
  278. }
  279. if (const char* option = this->GetOption(prefix + "DESCRIPTION")) {
  280. group.Description = option;
  281. }
  282. group.IsBold = this->IsOn(prefix + "BOLD_TITLE");
  283. group.IsExpandedByDefault = this->IsOn(prefix + "EXPANDED");
  284. // Package configuration
  285. group.Name = groupName;
  286. if (Generator) {
  287. this->Name = this->Generator->GetGroupPackageName(&group);
  288. } else {
  289. this->Name = group.Name;
  290. }
  291. return this->ConfigureFromGroup(&group);
  292. }
  293. // Common options for components and groups
  294. int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
  295. {
  296. // Temporary variable for full option name
  297. std::string option;
  298. // Display name
  299. option = prefix + "DISPLAY_NAME";
  300. if (this->IsSetToEmpty(option)) {
  301. this->DisplayName.clear();
  302. } else if (const char* value = this->GetOption(option)) {
  303. cmCPackIFWPackage::ExpandListArgument(value, this->DisplayName);
  304. }
  305. // Description
  306. option = prefix + "DESCRIPTION";
  307. if (this->IsSetToEmpty(option)) {
  308. this->Description.clear();
  309. } else if (const char* value = this->GetOption(option)) {
  310. cmCPackIFWPackage::ExpandListArgument(value, this->Description);
  311. }
  312. // Release date
  313. option = prefix + "RELEASE_DATE";
  314. if (this->IsSetToEmpty(option)) {
  315. this->ReleaseDate.clear();
  316. } else if (const char* value = this->GetOption(option)) {
  317. this->ReleaseDate = value;
  318. }
  319. // Sorting priority
  320. option = prefix + "SORTING_PRIORITY";
  321. if (this->IsSetToEmpty(option)) {
  322. this->SortingPriority.clear();
  323. } else if (const char* value = this->GetOption(option)) {
  324. this->SortingPriority = value;
  325. }
  326. // Update text
  327. option = prefix + "UPDATE_TEXT";
  328. if (this->IsSetToEmpty(option)) {
  329. this->UpdateText.clear();
  330. } else if (const char* value = this->GetOption(option)) {
  331. this->UpdateText = value;
  332. }
  333. // Translations
  334. option = prefix + "TRANSLATIONS";
  335. if (this->IsSetToEmpty(option)) {
  336. this->Translations.clear();
  337. } else if (const char* value = this->GetOption(option)) {
  338. this->Translations.clear();
  339. cmSystemTools::ExpandListArgument(value, this->Translations);
  340. }
  341. // QtIFW dependencies
  342. std::vector<std::string> deps;
  343. option = prefix + "DEPENDS";
  344. if (const char* value = this->GetOption(option)) {
  345. cmSystemTools::ExpandListArgument(value, deps);
  346. }
  347. option = prefix + "DEPENDENCIES";
  348. if (const char* value = this->GetOption(option)) {
  349. cmSystemTools::ExpandListArgument(value, deps);
  350. }
  351. for (std::string const& d : deps) {
  352. DependenceStruct dep(d);
  353. if (this->Generator->Packages.count(dep.Name)) {
  354. cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
  355. dep.Name = depPkg.Name;
  356. }
  357. bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0;
  358. DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name];
  359. if (!hasDep) {
  360. depRef = dep;
  361. }
  362. this->AlienDependencies.insert(&depRef);
  363. }
  364. // Automatic dependency on
  365. option = prefix + "AUTO_DEPEND_ON";
  366. if (this->IsSetToEmpty(option)) {
  367. this->AlienAutoDependOn.clear();
  368. } else if (const char* value = this->GetOption(option)) {
  369. std::vector<std::string> depsOn;
  370. cmSystemTools::ExpandListArgument(value, depsOn);
  371. for (std::string const& d : depsOn) {
  372. DependenceStruct dep(d);
  373. if (this->Generator->Packages.count(dep.Name)) {
  374. cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
  375. dep.Name = depPkg.Name;
  376. }
  377. bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0;
  378. DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name];
  379. if (!hasDep) {
  380. depRef = dep;
  381. }
  382. this->AlienAutoDependOn.insert(&depRef);
  383. }
  384. }
  385. // Visibility
  386. option = prefix + "VIRTUAL";
  387. if (this->IsSetToEmpty(option)) {
  388. this->Virtual.clear();
  389. } else if (this->IsOn(option)) {
  390. this->Virtual = "true";
  391. }
  392. // Default selection
  393. option = prefix + "DEFAULT";
  394. if (this->IsSetToEmpty(option)) {
  395. this->Default.clear();
  396. } else if (const char* value = this->GetOption(option)) {
  397. std::string lowerValue = cmsys::SystemTools::LowerCase(value);
  398. if (lowerValue == "true") {
  399. this->Default = "true";
  400. } else if (lowerValue == "false") {
  401. this->Default = "false";
  402. } else if (lowerValue == "script") {
  403. this->Default = "script";
  404. } else {
  405. this->Default = value;
  406. }
  407. }
  408. // Forsed installation
  409. option = prefix + "FORCED_INSTALLATION";
  410. if (this->IsSetToEmpty(option)) {
  411. this->ForcedInstallation.clear();
  412. } else if (this->IsOn(option)) {
  413. this->ForcedInstallation = "true";
  414. } else if (this->IsSetToOff(option)) {
  415. this->ForcedInstallation = "false";
  416. }
  417. // Replaces
  418. option = prefix + "REPLACES";
  419. if (this->IsSetToEmpty(option)) {
  420. this->Replaces.clear();
  421. } else if (const char* value = this->GetOption(option)) {
  422. this->Replaces.clear();
  423. cmSystemTools::ExpandListArgument(value, this->Replaces);
  424. }
  425. // Requires admin rights
  426. option = prefix + "REQUIRES_ADMIN_RIGHTS";
  427. if (this->IsSetToEmpty(option)) {
  428. this->RequiresAdminRights.clear();
  429. } else if (this->IsOn(option)) {
  430. this->RequiresAdminRights = "true";
  431. } else if (this->IsSetToOff(option)) {
  432. this->RequiresAdminRights = "false";
  433. }
  434. // Checkable
  435. option = prefix + "CHECKABLE";
  436. if (this->IsSetToEmpty(option)) {
  437. this->Checkable.clear();
  438. } else if (this->IsOn(option)) {
  439. this->Checkable = "true";
  440. } else if (this->IsSetToOff(option)) {
  441. this->Checkable = "false";
  442. }
  443. return 1;
  444. }
  445. void cmCPackIFWPackage::GeneratePackageFile()
  446. {
  447. // Lazy directory initialization
  448. if (this->Directory.empty()) {
  449. if (this->Installer) {
  450. this->Directory = this->Installer->Directory + "/packages/" + this->Name;
  451. } else if (this->Generator) {
  452. this->Directory = this->Generator->toplevel + "/packages/" + this->Name;
  453. }
  454. }
  455. // Output stream
  456. cmGeneratedFileStream fout(this->Directory + "/meta/package.xml");
  457. cmXMLWriter xout(fout);
  458. xout.StartDocument();
  459. WriteGeneratedByToStrim(xout);
  460. xout.StartElement("Package");
  461. // DisplayName (with translations)
  462. for (auto const& dn : this->DisplayName) {
  463. xout.StartElement("DisplayName");
  464. if (!dn.first.empty()) {
  465. xout.Attribute("xml:lang", dn.first);
  466. }
  467. xout.Content(dn.second);
  468. xout.EndElement();
  469. }
  470. // Description (with translations)
  471. for (auto const& d : this->Description) {
  472. xout.StartElement("Description");
  473. if (!d.first.empty()) {
  474. xout.Attribute("xml:lang", d.first);
  475. }
  476. xout.Content(d.second);
  477. xout.EndElement();
  478. }
  479. // Update text
  480. if (!this->UpdateText.empty()) {
  481. xout.Element("UpdateText", this->UpdateText);
  482. }
  483. xout.Element("Name", this->Name);
  484. xout.Element("Version", this->Version);
  485. if (!this->ReleaseDate.empty()) {
  486. xout.Element("ReleaseDate", this->ReleaseDate);
  487. } else {
  488. xout.Element("ReleaseDate", cmTimestamp().CurrentTime("%Y-%m-%d", true));
  489. }
  490. // Script (copy to meta dir)
  491. if (!this->Script.empty()) {
  492. std::string name = cmSystemTools::GetFilenameName(this->Script);
  493. std::string path = this->Directory + "/meta/" + name;
  494. cmsys::SystemTools::CopyFileIfDifferent(this->Script, path);
  495. xout.Element("Script", name);
  496. }
  497. // User Interfaces (copy to meta dir)
  498. std::vector<std::string> userInterfaces = UserInterfaces;
  499. for (std::string& userInterface : userInterfaces) {
  500. std::string name = cmSystemTools::GetFilenameName(userInterface);
  501. std::string path = this->Directory + "/meta/" + name;
  502. cmsys::SystemTools::CopyFileIfDifferent(userInterface, path);
  503. userInterface = name;
  504. }
  505. if (!userInterfaces.empty()) {
  506. xout.StartElement("UserInterfaces");
  507. for (std::string const& userInterface : userInterfaces) {
  508. xout.Element("UserInterface", userInterface);
  509. }
  510. xout.EndElement();
  511. }
  512. // Translations (copy to meta dir)
  513. std::vector<std::string> translations = Translations;
  514. for (std::string& translation : translations) {
  515. std::string name = cmSystemTools::GetFilenameName(translation);
  516. std::string path = this->Directory + "/meta/" + name;
  517. cmsys::SystemTools::CopyFileIfDifferent(translation, path);
  518. translation = name;
  519. }
  520. if (!translations.empty()) {
  521. xout.StartElement("Translations");
  522. for (std::string const& translation : translations) {
  523. xout.Element("Translation", translation);
  524. }
  525. xout.EndElement();
  526. }
  527. // Dependencies
  528. std::set<DependenceStruct> compDepSet;
  529. for (DependenceStruct* ad : this->AlienDependencies) {
  530. compDepSet.insert(*ad);
  531. }
  532. for (cmCPackIFWPackage* d : this->Dependencies) {
  533. compDepSet.insert(DependenceStruct(d->Name));
  534. }
  535. // Write dependencies
  536. if (!compDepSet.empty()) {
  537. std::ostringstream dependencies;
  538. std::set<DependenceStruct>::iterator it = compDepSet.begin();
  539. dependencies << it->NameWithCompare();
  540. ++it;
  541. while (it != compDepSet.end()) {
  542. dependencies << "," << it->NameWithCompare();
  543. ++it;
  544. }
  545. xout.Element("Dependencies", dependencies.str());
  546. }
  547. // Automatic dependency on
  548. std::set<DependenceStruct> compAutoDepSet;
  549. for (DependenceStruct* aad : this->AlienAutoDependOn) {
  550. compAutoDepSet.insert(*aad);
  551. }
  552. // Write automatic dependency on
  553. if (!compAutoDepSet.empty()) {
  554. std::ostringstream dependencies;
  555. std::set<DependenceStruct>::iterator it = compAutoDepSet.begin();
  556. dependencies << it->NameWithCompare();
  557. ++it;
  558. while (it != compAutoDepSet.end()) {
  559. dependencies << "," << it->NameWithCompare();
  560. ++it;
  561. }
  562. xout.Element("AutoDependOn", dependencies.str());
  563. }
  564. // Licenses (copy to meta dir)
  565. std::vector<std::string> licenses = this->Licenses;
  566. for (size_t i = 1; i < licenses.size(); i += 2) {
  567. std::string name = cmSystemTools::GetFilenameName(licenses[i]);
  568. std::string path = this->Directory + "/meta/" + name;
  569. cmsys::SystemTools::CopyFileIfDifferent(licenses[i], path);
  570. licenses[i] = name;
  571. }
  572. if (!licenses.empty()) {
  573. xout.StartElement("Licenses");
  574. for (size_t i = 0; i < licenses.size(); i += 2) {
  575. xout.StartElement("License");
  576. xout.Attribute("name", licenses[i]);
  577. xout.Attribute("file", licenses[i + 1]);
  578. xout.EndElement();
  579. }
  580. xout.EndElement();
  581. }
  582. if (!this->ForcedInstallation.empty()) {
  583. xout.Element("ForcedInstallation", this->ForcedInstallation);
  584. }
  585. // Replaces
  586. if (!this->Replaces.empty()) {
  587. std::ostringstream replaces;
  588. std::vector<std::string>::iterator it = this->Replaces.begin();
  589. replaces << *it;
  590. ++it;
  591. while (it != this->Replaces.end()) {
  592. replaces << "," << *it;
  593. ++it;
  594. }
  595. xout.Element("Replaces", replaces.str());
  596. }
  597. if (!this->RequiresAdminRights.empty()) {
  598. xout.Element("RequiresAdminRights", this->RequiresAdminRights);
  599. }
  600. if (!this->Virtual.empty()) {
  601. xout.Element("Virtual", this->Virtual);
  602. } else if (!this->Default.empty()) {
  603. xout.Element("Default", this->Default);
  604. }
  605. // Essential
  606. if (!this->Essential.empty()) {
  607. xout.Element("Essential", this->Essential);
  608. }
  609. // Priority
  610. if (!this->SortingPriority.empty()) {
  611. xout.Element("SortingPriority", this->SortingPriority);
  612. }
  613. // Checkable
  614. if (!this->Checkable.empty()) {
  615. xout.Element("Checkable", this->Checkable);
  616. }
  617. xout.EndElement();
  618. xout.EndDocument();
  619. }