cmExportInstallPackageInfoGenerator.cxx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 "cmExportInstallPackageInfoGenerator.h"
  4. #include <memory>
  5. #include <set>
  6. #include <utility>
  7. #include <vector>
  8. #include <cm3p/json/value.h>
  9. #include "cmExportSet.h"
  10. #include "cmGeneratorExpression.h"
  11. #include "cmGeneratorTarget.h"
  12. #include "cmInstallExportGenerator.h"
  13. #include "cmLocalGenerator.h"
  14. #include "cmMakefile.h"
  15. #include "cmStateTypes.h"
  16. #include "cmStringAlgorithms.h"
  17. #include "cmSystemTools.h"
  18. #include "cmTarget.h"
  19. #include "cmTargetExport.h"
  20. cmExportInstallPackageInfoGenerator::cmExportInstallPackageInfoGenerator(
  21. cmInstallExportGenerator* iegen, std::string packageName,
  22. std::string version, std::string versionCompat, std::string versionSchema,
  23. std::vector<std::string> defaultTargets,
  24. std::vector<std::string> defaultConfigurations)
  25. : cmExportPackageInfoGenerator(
  26. std::move(packageName), std::move(version), std::move(versionCompat),
  27. std::move(versionSchema), std::move(defaultTargets),
  28. std::move(defaultConfigurations))
  29. , cmExportInstallFileGenerator(iegen)
  30. {
  31. }
  32. std::string cmExportInstallPackageInfoGenerator::GetConfigImportFileGlob()
  33. const
  34. {
  35. std::string glob = cmStrCat(this->FileBase, "@*", this->FileExt);
  36. return glob;
  37. }
  38. std::string const& cmExportInstallPackageInfoGenerator::GetExportName() const
  39. {
  40. return this->GetPackageName();
  41. }
  42. bool cmExportInstallPackageInfoGenerator::GenerateMainFile(std::ostream& os)
  43. {
  44. std::vector<cmTargetExport const*> allTargets;
  45. {
  46. auto visitor = [&](cmTargetExport const* te) { allTargets.push_back(te); };
  47. if (!this->CollectExports(visitor)) {
  48. return false;
  49. }
  50. }
  51. if (!this->CheckDefaultTargets()) {
  52. return false;
  53. }
  54. Json::Value root = this->GeneratePackageInfo();
  55. Json::Value& components = root["components"];
  56. // Compute the relative import prefix for the file
  57. std::string const& packagePath = this->GenerateImportPrefix();
  58. if (packagePath.empty()) {
  59. return false;
  60. }
  61. root["cps_path"] = packagePath;
  62. // Create all the imported targets.
  63. bool requiresConfigFiles = false;
  64. for (cmTargetExport const* te : allTargets) {
  65. cmGeneratorTarget* gt = te->Target;
  66. cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
  67. Json::Value* const component =
  68. this->GenerateImportTarget(components, gt, targetType);
  69. if (!component) {
  70. return false;
  71. }
  72. ImportPropertyMap properties;
  73. if (!this->PopulateInterfaceProperties(te, properties)) {
  74. return false;
  75. }
  76. this->PopulateInterfaceLinkLibrariesProperty(
  77. gt, cmGeneratorExpression::InstallInterface, properties);
  78. if (targetType != cmStateEnums::INTERFACE_LIBRARY) {
  79. requiresConfigFiles = true;
  80. }
  81. // Set configuration-agnostic properties for component.
  82. this->GenerateInterfaceProperties(*component, gt, properties);
  83. }
  84. this->GeneratePackageRequires(root);
  85. // Write the primary packing information file.
  86. this->WritePackageInfo(root, os);
  87. bool result = true;
  88. // Generate an import file for each configuration.
  89. if (requiresConfigFiles) {
  90. for (std::string const& c : this->Configurations) {
  91. if (!this->GenerateImportFileConfig(c)) {
  92. result = false;
  93. }
  94. }
  95. }
  96. return result;
  97. }
  98. void cmExportInstallPackageInfoGenerator::GenerateImportTargetsConfig(
  99. std::ostream& os, std::string const& config, std::string const& suffix)
  100. {
  101. Json::Value root;
  102. root["name"] = this->GetPackageName();
  103. root["configuration"] = config;
  104. Json::Value& components = root["components"];
  105. for (auto const& te : this->GetExportSet()->GetTargetExports()) {
  106. // Collect import properties for this target.
  107. if (this->GetExportTargetType(te.get()) ==
  108. cmStateEnums::INTERFACE_LIBRARY) {
  109. continue;
  110. }
  111. ImportPropertyMap properties;
  112. std::set<std::string> importedLocations;
  113. this->PopulateImportProperties(config, suffix, te.get(), properties,
  114. importedLocations);
  115. Json::Value component =
  116. this->GenerateInterfaceConfigProperties(suffix, properties);
  117. if (!component.empty()) {
  118. components[te->Target->GetExportName()] = std::move(component);
  119. }
  120. }
  121. this->WritePackageInfo(root, os);
  122. }
  123. std::string cmExportInstallPackageInfoGenerator::GenerateImportPrefix() const
  124. {
  125. std::string expDest = this->IEGen->GetDestination();
  126. if (cmSystemTools::FileIsFullPath(expDest)) {
  127. std::string const& installPrefix =
  128. this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
  129. "CMAKE_INSTALL_PREFIX");
  130. if (cmHasPrefix(expDest, installPrefix)) {
  131. auto n = installPrefix.length();
  132. while (n < expDest.length() && expDest[n] == '/') {
  133. ++n;
  134. }
  135. expDest = expDest.substr(n);
  136. } else {
  137. this->ReportError(
  138. cmStrCat("install(PACKAGE_INFO \"", this->GetExportName(),
  139. "\" ...) specifies DESTINATION \"", expDest,
  140. "\" which is not a subdirectory of the install prefix."));
  141. return {};
  142. }
  143. }
  144. if (expDest.empty()) {
  145. return this->GetInstallPrefix();
  146. }
  147. return cmStrCat(this->GetImportPrefixWithSlash(), expDest);
  148. }
  149. std::string cmExportInstallPackageInfoGenerator::InstallNameDir(
  150. cmGeneratorTarget const* target, std::string const& config)
  151. {
  152. std::string install_name_dir;
  153. cmMakefile* mf = target->Target->GetMakefile();
  154. if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
  155. install_name_dir =
  156. target->GetInstallNameDirForInstallTree(config, "@prefix@");
  157. }
  158. return install_name_dir;
  159. }
  160. std::string cmExportInstallPackageInfoGenerator::GetCxxModulesDirectory() const
  161. {
  162. // TODO: Implement a not-CMake-specific mechanism for providing module
  163. // information.
  164. // return IEGen->GetCxxModuleDirectory();
  165. return {};
  166. }