| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmExportPackageInfoGenerator.h"
 
- #include <memory>
 
- #include <set>
 
- #include <utility>
 
- #include <vector>
 
- #include <cm/string_view>
 
- #include <cmext/algorithm>
 
- #include <cmext/string_view>
 
- #include <cm3p/json/value.h>
 
- #include <cm3p/json/writer.h>
 
- #include "cmExportSet.h"
 
- #include "cmFindPackageStack.h"
 
- #include "cmGeneratorExpression.h"
 
- #include "cmGeneratorTarget.h"
 
- #include "cmList.h"
 
- #include "cmMakefile.h"
 
- #include "cmMessageType.h"
 
- #include "cmStringAlgorithms.h"
 
- #include "cmSystemTools.h"
 
- #include "cmTarget.h"
 
- #include "cmValue.h"
 
- static const std::string kCPS_VERSION_STR = "0.12.0";
 
- cmExportPackageInfoGenerator::cmExportPackageInfoGenerator(
 
-   std::string packageName, std::string version, std::string versionCompat,
 
-   std::string versionSchema, std::vector<std::string> defaultTargets,
 
-   std::vector<std::string> defaultConfigurations)
 
-   : PackageName(std::move(packageName))
 
-   , PackageVersion(std::move(version))
 
-   , PackageVersionCompat(std::move(versionCompat))
 
-   , PackageVersionSchema(std::move(versionSchema))
 
-   , DefaultTargets(std::move(defaultTargets))
 
-   , DefaultConfigurations(std::move(defaultConfigurations))
 
- {
 
- }
 
- cm::string_view cmExportPackageInfoGenerator::GetImportPrefixWithSlash() const
 
- {
 
-   return "@prefix@/"_s;
 
- }
 
- bool cmExportPackageInfoGenerator::GenerateImportFile(std::ostream& os)
 
- {
 
-   return this->GenerateMainFile(os);
 
- }
 
- void cmExportPackageInfoGenerator::WritePackageInfo(
 
-   Json::Value const& packageInfo, std::ostream& os) const
 
- {
 
-   Json::StreamWriterBuilder builder;
 
-   builder["indentation"] = "  ";
 
-   builder["commentStyle"] = "None";
 
-   std::unique_ptr<Json::StreamWriter> const writer(builder.newStreamWriter());
 
-   writer->write(packageInfo, &os);
 
- }
 
- namespace {
 
- template <typename T>
 
- void buildArray(Json::Value& object, std::string const& property,
 
-                 T const& values)
 
- {
 
-   if (!values.empty()) {
 
-     Json::Value& array = object[property];
 
-     for (auto const& item : values) {
 
-       array.append(item);
 
-     }
 
-   }
 
- }
 
- }
 
- bool cmExportPackageInfoGenerator::CheckDefaultTargets() const
 
- {
 
-   bool result = true;
 
-   std::set<std::string> exportedTargetNames;
 
-   for (auto const* te : this->ExportedTargets) {
 
-     exportedTargetNames.emplace(te->GetExportName());
 
-   }
 
-   for (auto const& name : this->DefaultTargets) {
 
-     if (!cm::contains(exportedTargetNames, name)) {
 
-       this->ReportError(
 
-         cmStrCat("Package \"", this->GetPackageName(),
 
-                  "\" specifies DEFAULT_TARGETS \"", name,
 
-                  "\", which is not a target in the export set \"",
 
-                  this->GetExportSet()->GetName(), "\"."));
 
-       result = false;
 
-     }
 
-   }
 
-   return result;
 
- }
 
- Json::Value cmExportPackageInfoGenerator::GeneratePackageInfo() const
 
- {
 
-   Json::Value package;
 
-   package["name"] = this->GetPackageName();
 
-   package["cps_version"] = std::string(kCPS_VERSION_STR);
 
-   if (!this->PackageVersion.empty()) {
 
-     package["version"] = this->PackageVersion;
 
-     if (!this->PackageVersionCompat.empty()) {
 
-       package["compat_version"] = this->PackageVersionCompat;
 
-     }
 
-     if (!this->PackageVersionSchema.empty()) {
 
-       package["version_schema"] = this->PackageVersionSchema;
 
-     }
 
-   }
 
-   buildArray(package, "default_components", this->DefaultTargets);
 
-   buildArray(package, "configurations", this->DefaultConfigurations);
 
-   // TODO: description, website, license
 
-   return package;
 
- }
 
- void cmExportPackageInfoGenerator::GeneratePackageRequires(
 
-   Json::Value& package) const
 
- {
 
-   if (!this->Requirements.empty()) {
 
-     Json::Value& requirements = package["requires"];
 
-     for (auto const& requirement : this->Requirements) {
 
-       // TODO: version, hint
 
-       requirements[requirement] = Json::Value{};
 
-     }
 
-   }
 
- }
 
- Json::Value* cmExportPackageInfoGenerator::GenerateImportTarget(
 
-   Json::Value& components, cmGeneratorTarget const* target,
 
-   cmStateEnums::TargetType targetType) const
 
- {
 
-   auto const& name = target->GetExportName();
 
-   if (name.empty()) {
 
-     return nullptr;
 
-   }
 
-   Json::Value& component = components[name];
 
-   Json::Value& type = component["type"];
 
-   switch (targetType) {
 
-     case cmStateEnums::EXECUTABLE:
 
-       type = "executable";
 
-       break;
 
-     case cmStateEnums::STATIC_LIBRARY:
 
-       type = "archive";
 
-       break;
 
-     case cmStateEnums::SHARED_LIBRARY:
 
-       type = "dylib";
 
-       break;
 
-     case cmStateEnums::MODULE_LIBRARY:
 
-       type = "module";
 
-       break;
 
-     case cmStateEnums::INTERFACE_LIBRARY:
 
-       type = "interface";
 
-       break;
 
-     default:
 
-       type = "unknown";
 
-       break;
 
-   }
 
-   return &component;
 
- }
 
- bool cmExportPackageInfoGenerator::GenerateInterfaceProperties(
 
-   Json::Value& component, cmGeneratorTarget const* target,
 
-   ImportPropertyMap const& properties) const
 
- {
 
-   bool result = true;
 
-   this->GenerateInterfaceLinkProperties(result, component, target, properties);
 
-   this->GenerateInterfaceCompileFeatures(result, component, target,
 
-                                          properties);
 
-   this->GenerateInterfaceCompileDefines(result, component, target, properties);
 
-   this->GenerateInterfaceListProperty(result, component, target,
 
-                                       "compile_flags", "COMPILE_OPTIONS"_s,
 
-                                       properties);
 
-   this->GenerateInterfaceListProperty(result, component, target, "link_flags",
 
-                                       "LINK_OPTIONS"_s, properties);
 
-   this->GenerateInterfaceListProperty(result, component, target,
 
-                                       "link_directories", "LINK_DIRECTORIES"_s,
 
-                                       properties);
 
-   this->GenerateInterfaceListProperty(result, component, target, "includes",
 
-                                       "INCLUDE_DIRECTORIES"_s, properties);
 
-   // TODO: description, license
 
-   return result;
 
- }
 
- namespace {
 
- bool forbidGeneratorExpressions(std::string const& propertyName,
 
-                                 std::string const& propertyValue,
 
-                                 cmGeneratorTarget const* target)
 
- {
 
-   std::string const& evaluatedValue = cmGeneratorExpression::Preprocess(
 
-     propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions);
 
-   if (evaluatedValue != propertyValue) {
 
-     target->Makefile->IssueMessage(
 
-       MessageType::FATAL_ERROR,
 
-       cmStrCat("Property \"", propertyName, "\" of target \"",
 
-                target->GetName(),
 
-                "\" contains a generator expression. This is not allowed."));
 
-     return false;
 
-   }
 
-   return true;
 
- }
 
- }
 
- bool cmExportPackageInfoGenerator::NoteLinkedTarget(
 
-   cmGeneratorTarget const* target, std::string const& linkedName,
 
-   cmGeneratorTarget const* linkedTarget)
 
- {
 
-   if (cm::contains(this->ExportedTargets, linkedTarget)) {
 
-     // Target is internal to this package.
 
-     this->LinkTargets.emplace(linkedName,
 
-                               cmStrCat(':', linkedTarget->GetExportName()));
 
-     return true;
 
-   }
 
-   if (linkedTarget->IsImported()) {
 
-     // Target is imported from a found package.
 
-     auto pkgName = [linkedTarget]() -> std::string {
 
-       auto const& pkgStack = linkedTarget->Target->GetFindPackageStack();
 
-       if (!pkgStack.Empty()) {
 
-         return pkgStack.Top().Name;
 
-       }
 
-       return linkedTarget->Target->GetProperty("EXPORT_FIND_PACKAGE_NAME");
 
-     }();
 
-     if (pkgName.empty()) {
 
-       target->Makefile->IssueMessage(
 
-         MessageType::FATAL_ERROR,
 
-         cmStrCat("Target \"", target->GetName(),
 
-                  "\" references imported target \"", linkedName,
 
-                  "\" which does not come from any known package."));
 
-       return false;
 
-     }
 
-     auto const& prefix = cmStrCat(pkgName, "::");
 
-     if (!cmHasPrefix(linkedName, prefix)) {
 
-       target->Makefile->IssueMessage(
 
-         MessageType::FATAL_ERROR,
 
-         cmStrCat("Target \"", target->GetName(), "\" references target \"",
 
-                  linkedName, "\", which comes from the \"", pkgName,
 
-                  "\" package, but does not belong to the package's "
 
-                  "canonical namespace. This is not allowed."));
 
-       return false;
 
-     }
 
-     // TODO: Record package version, hint.
 
-     this->Requirements.emplace(pkgName);
 
-     this->LinkTargets.emplace(
 
-       linkedName, cmStrCat(pkgName, ':', linkedName.substr(prefix.length())));
 
-     return true;
 
-   }
 
-   // Target belongs to another export from this build.
 
-   auto const& exportInfo = this->FindExportInfo(linkedTarget);
 
-   if (exportInfo.Files.size() == 1) {
 
-     auto const& linkNamespace = exportInfo.Namespace;
 
-     if (!cmHasSuffix(linkNamespace, "::")) {
 
-       target->Makefile->IssueMessage(
 
-         MessageType::FATAL_ERROR,
 
-         cmStrCat("Target \"", target->GetName(), "\" references target \"",
 
-                  linkedName,
 
-                  "\", which does not use the standard namespace separator. "
 
-                  "This is not allowed."));
 
-       return false;
 
-     }
 
-     auto pkgName =
 
-       cm::string_view{ linkNamespace.data(), linkNamespace.size() - 2 };
 
-     if (pkgName == this->GetPackageName()) {
 
-       this->LinkTargets.emplace(linkedName,
 
-                                 cmStrCat(':', linkedTarget->GetExportName()));
 
-     } else {
 
-       this->Requirements.emplace(pkgName);
 
-       this->LinkTargets.emplace(
 
-         linkedName, cmStrCat(pkgName, ':', linkedTarget->GetExportName()));
 
-     }
 
-     return true;
 
-   }
 
-   // cmExportFileGenerator::HandleMissingTarget should have complained about
 
-   // this already. (In fact, we probably shouldn't ever get here.)
 
-   return false;
 
- }
 
- void cmExportPackageInfoGenerator::GenerateInterfaceLinkProperties(
 
-   bool& result, Json::Value& component, cmGeneratorTarget const* target,
 
-   ImportPropertyMap const& properties) const
 
- {
 
-   auto const& iter = properties.find("INTERFACE_LINK_LIBRARIES");
 
-   if (iter == properties.end()) {
 
-     return;
 
-   }
 
-   // TODO: Support $<LINK_ONLY>.
 
-   if (!forbidGeneratorExpressions(iter->first, iter->second, target)) {
 
-     result = false;
 
-     return;
 
-   }
 
-   std::vector<std::string> buildRequires;
 
-   // std::vector<std::string> linkRequires; TODO
 
-   std::vector<std::string> linkLibraries;
 
-   for (auto const& name : cmList{ iter->second }) {
 
-     auto const& ti = this->LinkTargets.find(name);
 
-     if (ti != this->LinkTargets.end()) {
 
-       if (ti->second.empty()) {
 
-         result = false;
 
-       } else {
 
-         buildRequires.emplace_back(ti->second);
 
-       }
 
-     } else {
 
-       linkLibraries.emplace_back(name);
 
-     }
 
-   }
 
-   buildArray(component, "requires", buildRequires);
 
-   // buildArray(component, "link_requires", linkRequires); TODO
 
-   buildArray(component, "link_libraries", linkLibraries);
 
- }
 
- void cmExportPackageInfoGenerator::GenerateInterfaceCompileFeatures(
 
-   bool& result, Json::Value& component, cmGeneratorTarget const* target,
 
-   ImportPropertyMap const& properties) const
 
- {
 
-   auto const& iter = properties.find("INTERFACE_COMPILE_FEATURES");
 
-   if (iter == properties.end()) {
 
-     return;
 
-   }
 
-   if (!forbidGeneratorExpressions(iter->first, iter->second, target)) {
 
-     result = false;
 
-     return;
 
-   }
 
-   std::set<std::string> features;
 
-   for (auto const& value : cmList{ iter->second }) {
 
-     if (cmHasLiteralPrefix(value, "c_std_")) {
 
-       auto suffix = cm::string_view{ value }.substr(6, 2);
 
-       features.emplace(cmStrCat("cxx", suffix));
 
-     } else if (cmHasLiteralPrefix(value, "cxx_std_")) {
 
-       auto suffix = cm::string_view{ value }.substr(8, 2);
 
-       features.emplace(cmStrCat("c++", suffix));
 
-     }
 
-   }
 
-   buildArray(component, "compile_features", features);
 
- }
 
- void cmExportPackageInfoGenerator::GenerateInterfaceCompileDefines(
 
-   bool& result, Json::Value& component, cmGeneratorTarget const* target,
 
-   ImportPropertyMap const& properties) const
 
- {
 
-   auto const& iter = properties.find("INTERFACE_COMPILE_DEFINITIONS");
 
-   if (iter == properties.end()) {
 
-     return;
 
-   }
 
-   // TODO: Support language-specific defines.
 
-   if (!forbidGeneratorExpressions(iter->first, iter->second, target)) {
 
-     result = false;
 
-     return;
 
-   }
 
-   Json::Value defines;
 
-   for (auto const& def : cmList{ iter->second }) {
 
-     auto const n = def.find('=');
 
-     if (n == std::string::npos) {
 
-       defines[def] = Json::Value{};
 
-     } else {
 
-       defines[def.substr(0, n)] = def.substr(n + 1);
 
-     }
 
-   }
 
-   if (!defines.empty()) {
 
-     component["compile_definitions"]["*"] = std::move(defines);
 
-   }
 
- }
 
- void cmExportPackageInfoGenerator::GenerateInterfaceListProperty(
 
-   bool& result, Json::Value& component, cmGeneratorTarget const* target,
 
-   std::string const& outName, cm::string_view inName,
 
-   ImportPropertyMap const& properties) const
 
- {
 
-   auto const& prop = cmStrCat("INTERFACE_", inName);
 
-   auto const& iter = properties.find(prop);
 
-   if (iter == properties.end()) {
 
-     return;
 
-   }
 
-   if (!forbidGeneratorExpressions(prop, iter->second, target)) {
 
-     result = false;
 
-     return;
 
-   }
 
-   Json::Value& array = component[outName];
 
-   for (auto const& value : cmList{ iter->second }) {
 
-     array.append(value);
 
-   }
 
- }
 
- void cmExportPackageInfoGenerator::GenerateInterfaceConfigProperties(
 
-   Json::Value& components, cmGeneratorTarget const* target,
 
-   std::string const& suffix, ImportPropertyMap const& properties) const
 
- {
 
-   Json::Value component;
 
-   auto const suffixLength = suffix.length();
 
-   for (auto const& p : properties) {
 
-     if (!cmHasSuffix(p.first, suffix)) {
 
-       continue;
 
-     }
 
-     auto const n = p.first.length() - suffixLength - 9;
 
-     auto const prop = cm::string_view{ p.first }.substr(9, n);
 
-     if (prop == "LOCATION") {
 
-       component["location"] = p.second;
 
-     } else if (prop == "IMPLIB") {
 
-       component["link_location"] = p.second;
 
-     } else if (prop == "LINK_INTERFACE_LANGUAGES") {
 
-       std::vector<std::string> languages;
 
-       for (auto const& lang : cmList{ p.second }) {
 
-         auto ll = cmSystemTools::LowerCase(lang);
 
-         if (ll == "cxx") {
 
-           languages.emplace_back("cpp");
 
-         } else {
 
-           languages.emplace_back(std::move(ll));
 
-         }
 
-       }
 
-       buildArray(component, "link_languages", languages);
 
-     }
 
-   }
 
-   if (!component.empty()) {
 
-     components[target->GetExportName()] = component;
 
-   }
 
- }
 
 
  |